//tcp server
// can work on unix or windows machines
// this program tests the time it takes to transfer a fixed file size by varying the packet size

#define WIN
//#define BSD


#ifdef WIN
	#include < windows.h>
#else
	#include < sys/types.h>
	#include < sys/socket.h>
	#include < netinet/in.h>
	#include < arpa/inet.h>
#endif



#include < stdio.h>
#include < iostream.h>

/* ipc stuff */
#define PORTNUM	18000
#define MESS_SIZE  1000000


#ifdef WIN
DWORD Tid1 ;

DWORD WINAPI MyThread1( LPVOID param )
{
	unsigned int n ;
	char	line[ MESS_SIZE ] ;
	int sockfd = *( (int *)param ) ;
int count = 0 ;
	for( ; ; )
	{
		if( ( n = recv( sockfd, line, MESS_SIZE, 0 ) ) == 0 )
			return 0 ;//connection closed by client
//cout << " count = " << count++ << endl ;
//cout << "n = " << n << endl ;

	n %= 65549 ;

		send( sockfd, line, n, 0 ) ;//acknowledge client
	}

}

#else	//bsd

void str_echo( int sockfd )
{
	ssize_t n ;
	char	line[ MESS_SIZE ] ;

	for( ; ; )
	{
		if( ( n = read( sockfd, line, MESS_SIZE ) ) == 0 )
			return ;//connection closed by client

		write( sockfd, line, n ) ;//acknowledge client
	}
}

#endif



void str_echo( int sockfd ) ;


/* main */
int main()
{
	/* ipc stuff */
	int	clilen,
			TheSocket,
			TheSocketConnection ;

	struct sockaddr_in ServerUnixSocketAddress,
							 ClientUnixSocketAddress ;

#ifdef BSD
	pid_t childpid ;
#else
	int *pTheSocketConnection = 0;//new int ;

HANDLE status ;

	WORD		wVersionRequested = MAKEWORD( 1, 1 ) ;
	WSADATA	wsaData ;
	WSAStartup( wVersionRequested, &wsaData ) ;
#endif




	TheSocket = socket( AF_INET, SOCK_STREAM, 0 ) ;
	if( TheSocket < 0 )
	{
		perror( "server error:  socket() failed" ) ;
		exit( -1 ) ;
	}
	


	
#ifdef WIN
	memset( (char *)&ServerUnixSocketAddress,
			  0,
			  sizeof( ServerUnixSocketAddress ) ) ;
#else
	bzero( ( char * )&ServerUnixSocketAddress,
				sizeof( ServerUnixSocketAddress ) ) ;
#endif

	ServerUnixSocketAddress.sin_family	= AF_INET ;
	ServerUnixSocketAddress.sin_addr.s_addr	= htonl( INADDR_ANY ) ;
	ServerUnixSocketAddress.sin_port	= htons( PORTNUM ) ;


	if( bind( TheSocket,
		  (struct sockaddr *)&ServerUnixSocketAddress,
		  sizeof( ServerUnixSocketAddress ) ) < 0 )
	{
		perror( "server error:  connect() failed" ) ;
		exit( -1 ) ;
	}
	printf("bind done\n" ) ;



	
	if( listen( TheSocket, 5 ) < 0 )
	{
		perror( "server error:  listen() failed" ) ;
		exit( -1 ) ;
	}
	printf("listen done\n" ) ;



/* the loop */
	for( ; ; )
	{
		clilen = sizeof( ClientUnixSocketAddress ) ;
		
		printf("before accept\n" ) ;
		TheSocketConnection = accept( TheSocket,
												(struct sockaddr *)&ClientUnixSocketAddress,
												&clilen ) ;
		printf("after accept\n" ) ;

		
		if( TheSocketConnection < 0 )
		{
			printf("server error:  accept() failed %d", WSAGetLastError() ) ;
			exit( -1 ) ;
		}
	
		printf( "socket connection = %d\n",TheSocketConnection ) ;


#ifdef WIN
		pTheSocketConnection = new int ;
		*pTheSocketConnection = TheSocketConnection ;
		
		status = CreateThread( NULL,
						  0,
						  (LPTHREAD_START_ROUTINE)MyThread1,
						  (LPVOID)pTheSocketConnection,
						  0,
						  &Tid1 );

		//exit( 0 ) ;
#else
		if( ( childpid = fork() ) == 0 )
		{
			close( TheSocket ) ;					//close listening socket
			str_echo( TheSocketConnection ) ;//process the request
			exit( 0 ) ;
		}
#endif


		
		

	}	


#ifdef WIN
  WSACleanup();
#endif

	return 0 ;
}