/**********************************************************
	echo_server.c
 	Z-World, 2002

	This program is used with RCM3200 series controllers.
	
	The sample library, rcm3200.lib, contains a brdInit()
	function which initializes port pins. Modify this
	function to fit your application.

	Description
	===========
   This program demonstrates a basic server which will
   echo back any data sent from a client connect.

   Use echo_client.c to program a client controller.

   This program was adapted from \Samples\TCPIP\echo.c.
   
	Instructions
	============
   1. Modify the TCPCONFIG, INCOMING_IP, INCOMING_PORT,
      and MY_PORT to the appropriate settings for the
      network.
	2. Compile and run this program.
	
**********************************************************/
#class auto

#use rcm3200.lib    		//sample library used for this demo

//#define DCRTCP_DEBUG		// display tcp/ip debugging information
//#define DCRTCP_VERBOSE	// allow stepping through tcp/ip functions

/***********************************
 * Configuration                   *
 * -------------                   *
 * All fields in this section must *
 * be altered to match your local  *
 * network settings.               *
 ***********************************/

/*
 * Pick the predefined TCP/IP configuration for this sample.  See
 * LIB\TCPIP\TCP_CONFIG.LIB for instructions on how to set the
 * configuration.
 */
#define TCPCONFIG 1

#define MY_PORT 			1111

//************************************************************************************************
#define	ETH_MTU		 1000
#define  BUFF_SIZE	 (ETH_MTU-40)	//must be smaller than (ETH_MTU - (IP Datagram + TCP Segment))
#define  TCP_BUF_SIZE ((ETH_MTU-40)*4)	// sets up (ETH_MTU-40)*2 bytes for Tx & Rx buffers

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

#memmap xmem
#use "dcrtcp.lib"

#define INCOMING_IP		0		// accept all connections
#define INCOMING_PORT	0		// accept all ports
#define TIME_OUT			5000	// if in any state for more than X milliseconds re-initialize

#define	RED		"\x1b[31m"	// foreground colors for printf
#define	GREEN		"\x1b[32m"	// foreground colors for printf
#define	BLUE		"\x1b[34m"	// foreground colors for printf

tcp_Socket sock;
int bytes;
long statetime;
static char buff[BUFF_SIZE];

///////////////////////////////////////////////////////////////////////

int receive_packet(void)
{
	/* receive the packet */
	bytes = sock_fastread(&sock,buff,BUFF_SIZE);
	
	switch(bytes)
	{
		case -1:
			return 4; // there was an error go to state 4 (NO_WAIT_CLOSE)
		case  0:
			return 2; // connection is okay, but no data received
		default:
			statetime = MS_TIMER+TIME_OUT;	// reset time to be in the SEND state
			return 3;	//now go to state 3 (SEND)
	}
}

int send_packet(void)
{
	/* send the packet */
	memset(buff,'S',BUFF_SIZE);	// fill buffer with S's
	buff[BUFF_SIZE-1] = '\n';		// null terminate the buffer
	
	bytes = sock_fastwrite(&sock,buff,BUFF_SIZE);
	switch(bytes)
	{
		case -1:
			return 3; // there was an error stay is SEND state and retry
		default:
			statetime = MS_TIMER+TIME_OUT;	// reset time to be in the RECEIVE state
			return 2;	//now go to state 2 (RECEIVE)
	}
}

void main()
{
	int state,status;
	state = 0;
	
	sock_init();
	
	while(1)
	{
		switch(state)
		{
			case 0:/*INITIALIZATION*/					// listen for incoming connection
				if(!tcp_listen(&sock,MY_PORT,INCOMING_IP,INCOMING_PORT,NULL,0))
					printf("%sERROR OPENNING SOCKET!\n",RED);
				else
				{
					printf("%swaiting for incomming session\n",GREEN);
					statetime = MS_TIMER+TIME_OUT;		// setup the time to be in LISTEN state
					state++;										// init complete move onto next state
				}
				break;
			case 1:/*LISTEN*/
				if(sock_established(&sock))			// check for a connection
				{
					printf("%ssocket established\n",BLUE);
					statetime = MS_TIMER+TIME_OUT;	// reset time to be in the RECEIVE state
					state++;									//   we have connection so move on
				}
				else if ((long)(MS_TIMER-statetime) > 0)	// if X millisecs and still waiting
					state = 4;										//	  abort and re-init
				break;
			case 2:/*RECEIVE*/
				state = receive_packet();				// see function for details
				if ((long)(MS_TIMER-statetime) > 0)	// if X millisecs and still waiting
					state = 4;								//	  abort and re-init
				break;
			case 3:/*SEND*/
				state = send_packet();					// see function for details
				if ((long)(MS_TIMER-statetime) > 0) // if X millisecs and still waiting
					state = 4;								//	  abort and re-init
				break;
			case 4:/*NO WAIT_CLOSE*/
				printf("%sABORT SOCKET\n",RED);
				sock_abort(&sock);						// close the socket
				state = 0;									// go back to the INIT state
		}
		status = tcp_tick(&sock);
	}	
}

