/**********************************************************************
 
	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	<sys/types.h>
#include	<winsock2.h>
#include	<stdlib.h>

#include	<task.h>

#include	"memory_debug.h"
#include	"server.h"
#include	"stream.h"

/* extern int max_fid,now_open_files; */

int s_close_accept();
int s_error();
STREAM * s_error_stream();
extern SEM stream_lock;
S_TABLE s_accept_table = {
	'a',
	0,
	{0,0},
	0,
	s_error_stream,
	s_error,
	s_close_accept,
	s_error,
	s_error,
	s_error,
	s_error_stream
};

STREAM *
init_server(int * open_port,int base_port,int limit)
{
struct sockaddr_in server;
int len;
int on;
int sd;
int p;
STREAM * ret;
extern void _s_open(STREAM * s,int mode);

/*
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD( 2, 2 );

	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		exit(1);
	}
*/
	if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		printf("Error(server): can't open socket\n");
		perror("error");
		exit(1);
	}
	on = 1;
	if (setsockopt(sd,
			SOL_SOCKET,
			SO_REUSEADDR, (char *)&on, sizeof(int)) < 0) {
	        perror("setsockopt");
        	exit(1);
	}
	for ( p = base_port ; p < base_port + limit ; p ++ ) {
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons((u_short)p);
		len = sizeof(server);
		if (bind(sd, (struct sockaddr*)&server, len) == -1) {
			continue;
		}
		break;
	}
	if ( p == base_port + limit ) {
		printf("Error(server): can't bind");
		exit(1);
	}

	if (listen(sd, 5) == -1) {
		printf("Error(server): can't listen\n");
		exit(1);
	}
	*open_port = p;
	ret = d_alloc(sizeof(S_ACCEPT));
	ret->h.tbl = &s_accept_table;
	ret->accept.fid = sd;
	lock_task(stream_lock);
	_s_open(ret,O_RDONLY);
	unlock_task(stream_lock,"init_server");
	return ret;
}

int
s_close_accept(STREAM * s)
{
	closesocket(s->accept.fid);
	return 0;
}
