/**********************************************************************
 
	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"
extern SEM netutils_lock;
extern SEM stream_lock;
/*
extern int max_fid,now_open_files;
*/

int con_err;

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

struct sockaddr_in client;
int len;
struct hostent * hp;
STREAM * ret;
extern S_TABLE s_socket_table;
extern void _s_open(STREAM * s,int mode);

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

	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();
			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;
	}

/*
	client.sin_family = AF_INET;
	client.sin_addr.s_addr = ntohl(INADDR_ANY);
	client.sin_port = 0;
	len = sizeof(client);
	if (bind(id, (struct sockaddr *)&client, len) == -1) {
		printf("Error(client): can't bind\n");
		closesocket(id);
		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) {
		printf("Error(clinet): can't connect\n");
		/* close(id); */
		closesocket(id);
		if ( func )
			(*func)(1,work);
		*cerr = WSAGetLastError();
		return 0;
	}
	if ( func )
		(*func)(1,work);
	ret = d_alloc(sizeof(S_SOCKET),336);
	ret->h.tbl = &s_socket_table;
	ret->h.thread = 0;
	ret->_socket.fid = id;
	lock_task(stream_lock);
	_s_open(ret,O_RDWR);
	unlock_task(stream_lock,"new_connection");
	return ret;
}

