//
// 
//	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
// 
//	This program is free software; you can redistribute it 
//	and/or modify it under the terms of the GLOBALBASE 
//	Library General Public License (G-LGPL) as published by 
//
//	http://www.globalbase.org/
// 
//	This program is distributed in the hope that it will be 
//	useful, but WITHOUT ANY WARRANTY; without even the 
//	implied warranty of MERCHANTABILITY or FITNESS FOR A 
//	PARTICULAR PURPOSE.
//
//

extern "C" {

#define STREAM_LIB
#define LIBRARY

#include	"machine/err.h"
#include	"task.h"
#include	"stream.h"
#include	"net_msg.h"
#include	"memory_debug.h"
#include	"client.h"
#include	"log.h"
#include	<LInternetAddress.h>
#include	<LTCPEndpoint.h>
#include	<UNetworkFactory.h>
#include	"CServerMaster.h"
//void _s_open(STREAM * s,int mode);

int con_err;
extern SEM stream_lock;

STREAM *
new_connection(
	int * cerr,
	char * hostname,
	int ip,
	short port,
	int (*func)(),
	void * work)
{
STREAM *	ret = 0;
//Str255 name;
HOST_ENTRY * hp;
	
	*cerr = 0;
	_ExStop();
	try
	{
		ret = (STREAM *)d_alloc(sizeof(STREAM));
		ret->socket.ep = UNetworkFactory::CreateTCPEndpoint();
		ret->socket.ep->QueueSends();
		LInternetAddress localAddress(0,0);
		if (func)
			(*(int(*)(int,void*))func)(0,work);
		ret->socket.ep->Bind(localAddress);
		LInternetAddress remoteAddress;
		if (hostname) {
/*
			NET_MSG("---Resolving Host Name '%s'...\n", hostname);
			c2pstrcpy(name, hostname);
			remoteAddress.SetDNSAddress(name);
*/
			hp = r_gethostbyname(hostname);
			if ( hp == 0 ) {
				*cerr = ESYS_NOENT;
				return 0;
			}
			ip = hp->ips[0].d.v4;
		}
		remoteAddress.SetIPAddress(ip);
		remoteAddress.SetHostPort(port);
		//NET_MSG("---Connecting...\n");
		ret->socket.ep->Connect(remoteAddress, 3*60);
		NET_MSG("---Connected.[%x]\n", ret->socket.ep);
		ret->socket.state = S_STATE_OK;
	}
	catch(LException exc)
	{
		*cerr = exc.GetErrorCode();
		if ( hostname )
			log_printf(LOG_ERROR,LOG_LAYER_STREAM,0, "# Error in connecting to \"%s\".(ID : %d)\n", hostname, *cerr);
		else
			log_printf(LOG_ERROR,LOG_LAYER_STREAM,0, "# Error in connecting to IP \"%x\".(ID : %d)\n", ip, *cerr);
		if (ret)
		{
			if (ret->socket.ep)
				delete ret->socket.ep;
			d_f_ree(ret);
		}
		_ExRevert();
		if (func)
			(*(int(*)(int,void*))func)(1,work);
		switch(*cerr) {
		  case kOTCanceledErr:
		  case kOTNoDataErr:
		  case kENETUNREACHErr:
		  case kETIMEDOUTErr:
		  case kEHOSTDOWNErr:
		  case kEHOSTUNREACHErr:
		  case kETIMEErr:
		  case Timeout_Error:
			*cerr = ESYS_CTIMEOUT;
			break;
		  case kECONNREFUSEDErr:
		  	*cerr = ESYS_CREFUSED;
		}
		return 0;
	}
	catch(...)
	{
		*cerr = -1;
		_ExRevert();
		if (func)
			(*(int(*)(int,void*))func)(1,work);
		return 0;
	}
	_ExRevert();
	if (func)
		(*(int(*)(int,void*))func)(1,work);

	ret->h.tbl = &s_socket_table;
	ret->h.thread = 0;
	lock_task(stream_lock);
	_s_open(ret,0);
	unlock_task(stream_lock,"new_connection");
//void newLogWindow(void*);
//newLogWindow(ret);
	return ret;
}


} // extern "C"