#include "../iinchip/socket.h"
#include "../util/sockutil.h"
#include "../util/myprintf.h"
#include "../evb/config.h"
#include "../evb/channel.h"
#include "../evb/evb.h"
#include "../main/main.h"
#include "../iinchip/w5100.h"

#include <stdlib.h>

#include "loopback.h"

void loopback_tcps(u_char ch)
{
	uint16 len;

	u_char data_buf[TX_RX_MAX_BUF_SIZE] = {0};
	
	switch (getSn_SR(ch))
	{
	case SOCK_ESTABLISHED:						/* if connection is established */
		if(bchannel_start[ch]==1)
		{
			printf("%d : Connected by %s(%u)\r\n",ch,inet_ntoa(GetDestAddr(ch)),GetDestPort(ch));
			bchannel_start[ch] = 2;
		}
		if ((len = getSn_RX_RSR(ch)) > 0) 			/* check Rx data */
		{
			if (len > TX_RX_MAX_BUF_SIZE) len = TX_RX_MAX_BUF_SIZE;	/* if Rx data size is lager than TX_RX_MAX_BUF_SIZE */
									/* the data size to read is MAX_BUF_SIZE. */
			len = recv(ch, data_buf, len);			/* read the received data */
			send(ch, data_buf, len);				/* send the received data */
		}
		break;
	case SOCK_CLOSE_WAIT:                           		/* If the client request to close */
		DPRINTLN1("%d : CLOSE_WAIT", ch);
		disconnect(ch);
		bchannel_start[ch] = 0;
		break;
	case SOCK_CLOSED:                                               /* if a socket is closed */
		if(!bchannel_start[ch]) 
		{
			printf("%d : Loop-Back TCP Server Started.\r\n",ch);
			bchannel_start[ch] = 1;
		}
		if(socket(ch,Sn_MR_TCP,ChConf.ch[ch].port,0x00) == 0)    /* reinitialize the socket */
		{
			printf("\a%d : Fail to create socket.\r\n",ch);
			bchannel_start[ch] = 0;
		}
		else	listen(ch);
		break;
	}
}

void loopback_tcpc(u_char ch)
{
	uint16 len;							
	u_char data_buf[TX_RX_MAX_BUF_SIZE] = {0};

	switch (getSn_SR(ch))
	{
	case SOCK_ESTABLISHED:						/* if connection is established */
		if(bchannel_start[ch]==1)
		{
			printf("%d : Connected by %s(%u)\r\n",ch,inet_ntoa(GetDestAddr(ch)),GetDestPort(ch));			
			bchannel_start[ch] = 2;
		}
		if ((len = getSn_RX_RSR(ch)) > 0) 			/* check Rx data */
		{
			if (len > TX_RX_MAX_BUF_SIZE) len = TX_RX_MAX_BUF_SIZE;	/* if Rx data size is lager than TX_RX_MAX_BUF_SIZE */
									/* the data size to read is MAX_BUF_SIZE. */
			len = recv(ch, data_buf, len);			/* read the received data */
			send(ch, data_buf, len);				/* send the received data */
		}
		break;
	case SOCK_CLOSE_WAIT:                           		/* If the client request to close */
		DPRINTLN1("%d : CLOSE_WAIT", ch);
		disconnect(ch);
		bchannel_start[ch] = 0;
		break;
	case SOCK_CLOSED:                                               /* if a socket is closed */
		if(!bchannel_start[ch])
		{
			printf("%d : Loop-Back TCP Client Started.\r\n",ch);
			bchannel_start[ch] = 1;
		}
		if(socket(ch,Sn_MR_TCP,get_system_any_port(),0x00) == 0)    /* reinitialize the socket */
		{
			printf("\a%d : Fail to create socket.\r\n",ch);
			bchannel_start[ch] = 0;
		}
		else	connect(ch,(u_char*)&ChConf.ch[ch].destip,ChConf.ch[ch].port);
		break;
	}
}

void loopback_udp(u_char ch)
{
	uint16 len;
	u_char data_buf[TX_RX_MAX_BUF_SIZE] = {0};

	u_long destip = 0;
	uint16 destport;

	switch (getSn_SR(ch))
	{
	case SOCK_UDP:
		if ((len = getSn_RX_RSR(ch)) > 0) 			/* check Rx data */
		{
			if (len > TX_RX_MAX_BUF_SIZE) len = TX_RX_MAX_BUF_SIZE;	/* if Rx data size is lager than TX_RX_MAX_BUF_SIZE */
									/* the data size to read is MAX_BUF_SIZE. */
			len = recvfrom(ch, data_buf, len,(u_char*)&destip,&destport);			/* read the received data */
			if(sendto(ch, data_buf, len,(u_char*)&destip,destport) == 0)	/* send the received data */
			{
				printf("\a\a\a%d : System Fatal Error.\r\n",ch);
				evb_soft_reset();
			}
		}
		break;
	case SOCK_CLOSED:                                               /* if a socket is closed */
		printf("%d : Loop-Back UDP Started.\r\n",ch);
		if(socket(ch,Sn_MR_UDP,ChConf.ch[ch].port,0x00)== 0)    /* reinitialize the socket */
			printf("\a%d : Fail to create socket.\r\n",ch);
		break;
	}
}

