/**********************************************************************
 
	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.

**********************************************************************/


#include	<stdio.h>
#include	<errno.h>
#include	<sys/types.h>
#include	<winsock2.h>

#include	<stdlib.h>
#include	"memory_debug.h"
#include	"stream.h"
#include	"task.h"
#include	"machine/err.h"

extern SEM netutils_lock;
extern SEM stream_lock;

int con_err;

STREAM *
new_connection(
	int * cerr,
	char * hostname,
	int ip,
	short port,
	int (*func)(),
	void * work)
{
int id;
struct sockaddr_in server;

int len;
struct hostent * hp;
STREAM * ret;
extern S_TABLE s_socket_table;

	if ( func )
		(*func)(0,work);

	WSASetLastError(0);
	if ( hostname ) {
		lock_task(netutils_lock);
		hp = gethostbyname(hostname);
		if ( hp == 0 ) {
			unlock_task(netutils_lock, "new_connection\n");
			if ( func )
				(*func)(1,work);

			*cerr = WSAGetLastError();
			if(*cerr == WSAHOST_NOT_FOUND){
				*cerr = ESYS_CTIMEOUT;
			}
			return 0;
		}
		ip = ntohl(*(int*)(hp->h_addr_list[0]));
		unlock_task(netutils_lock, "new_connection\n");
	}
	if ((id = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		printf("Error(client): can't open socket\n");
		if ( func )
			(*func)(1,work);
		*cerr = WSAGetLastError();
		return 0;
	}

	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(ip);
	server.sin_port = htons(port);
	len = sizeof(server);
	if (connect(id, (struct sockaddr*)&server, len) == SOCKET_ERROR) {
		*cerr = WSAGetLastError();
		
		printf("Error(clinet): can't connect %d \n", *cerr);
		
		closesocket(id);
		if ( func )
			(*func)(1,work);
		return 0;
	}
	if ( func )
		(*func)(1,work);
	ret = d_alloc(sizeof(S_SOCKET));
	ret->h.tbl = &s_socket_table;
	ret->h.thread = 0;
	ret->socket.sock = id;
	ret->socket.shutdown_before_close = 1;
	lock_task(stream_lock);
	_s_open(ret,O_RDWR);
	
	unlock_task(stream_lock,"new_connection");
	return ret;
}

