#include "includes.h"
#include "lwip/timers.h"
#include "lwip/tcp.h"
#include "lwip/sockets.h"
#include "string.h"


//socket编程示例 需要操作系统
//socket 客户端编程

#define SERVER_PORT  30000
#define SERVER_IP    "192.168.0.104"

void socket_client(void)
{
	int sock = -1;
	struct sockaddr_in serverAddr;
	uint8_t send_buf[] = "This is a TCP client test ... \n";
	
	
	while(1)
	{
		sock = socket(AF_INET, SOCK_STREAM, 0);
		if(sock < 0) 
		{
			OSTimeDly(100);
			continue;
		}
	
		serverAddr.sin_family = AF_INET;
		serverAddr.sin_port = htons(SERVER_PORT);
		serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
		memset(&(serverAddr.sin_zero), 0, sizeof(serverAddr.sin_zero));
		
		if( connect(sock, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr) )!= ERR_OK)
		{
			closesocket(sock);
			OSTimeDly(1000);
			continue;
		}
		
		while(1)
		{
			if(write(sock, send_buf, sizeof(send_buf)) < 0) break;
			OSTimeDly(2000);
		}
		
		closesocket(sock);
	}
}

//server 编程

uint8_t recvdata[256];

void sock_tcpServer(void)
{
	int sock = -1;
	int connected = -1;
	
	struct sockaddr_in server_addr, client_addr;
	socklen_t sin_size;
	int recv_data_len;
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock < 0) goto __exit;
	
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = INADDR_ANY;
	server_addr.sin_port = htons(SERVER_PORT);
	memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
	if(bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) goto __exit;
	
	if(listen(sock, 5) == -1) goto __exit;
	
	while(1)
	{
		sin_size = sizeof(struct sockaddr_in);
		connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
		printf("new client connected from(%s, %d) \n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
		
		while(1)
		{
			memset(recvdata, 0, 256);
			recv_data_len = recv(connected, recvdata, 256, 0);
			if(recv_data_len <= 0) break;
			printf("recv a data: %s \n", (char *)recvdata);
			write(connected, recvdata, recv_data_len);
		}
		if(connected > 0) closesocket(connected);
		connected = -1;
	}
	
__exit:
	if(sock >= 0) closesocket(sock);
}




/*RAW 编程示例, 只可以在无操作系统的情况下使用*/
/*
static err_t tcpecho_newrecv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
	if(p != NULL)
	{
		tcp_recved(tpcb, p->tot_len);
		tcp_write(tpcb, p->payload, p->len, TCP_WRITE_FLAG_COPY);
		printf("receive a data: %s \n", (char *)p->payload);
		memset(p->payload, 0, p->len);	
		pbuf_free(p);
	}
	else if(err == ERR_OK)
	{
		printf("client close \n");
		return tcp_close(tpcb);
	}
	return ERR_OK;
}

static err_t tcpecho_newtcp(void *arg, struct tcp_pcb *newpcb, err_t err)
{
	tcp_recv(newpcb, tcpecho_newrecv);

	printf("connect new client \n");
	return ERR_OK;
}

void tcp_serverInit(void)
{
	struct tcp_pcb *pcb = NULL;
	ip_addr_t local_ip;
	
	IP4_ADDR(&local_ip, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
	
	pcb = tcp_new();
	
	tcp_bind(pcb, &local_ip, 2000);
	
	pcb = tcp_listen(pcb);

	tcp_accept(pcb, tcpecho_newtcp);
}*/



/*   RAW  TCP CLIENT
#define  TCP_CLIENT_PORT  40000
#define  TCP_SERVER_PORT  40001

static err_t TCPClientConnected(void *arg, struct tcp_pcb *pcb, err_t err);
static void TCPClientConnectError(void *arg, err_t err);
static err_t TCPClientCallback(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err);


 void Tcp_Client_Initialization(void)
 {
   struct tcp_pcb *tcp_client_pcb;
   ip_addr_t ipaddr;
  
   IP4_ADDR(&ipaddr, 192,168,0,187);
  
   tcp_client_pcb = tcp_new();
  
   tcp_bind(tcp_client_pcb, IP_ADDR_ANY, TCP_CLIENT_PORT);
  
   if (tcp_client_pcb != NULL)
   {
     tcp_err(tcp_client_pcb, TCPClientConnectError);
     tcp_connect(tcp_client_pcb, &ipaddr, TCP_SERVER_PORT, TCPClientConnected);
   }
 }


 static err_t TCPClientConnected(void *arg, struct tcp_pcb *pcb, err_t err)
 {
   char clientString[]="This is a new client connection.\r\n";
  
   tcp_recv(pcb, TCPClientCallback);
  
   tcp_write(pcb,clientString, strlen(clientString),0);
  
   return ERR_OK;
 }
 
 static void TCPClientConnectError(void *arg, err_t err)
 {

   Tcp_Client_Initialization();
 }


 static err_t TCPClientCallback(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err)
 {
   struct pbuf *tcp_send_pbuf;
   char echoString[]="This is the server content echo:\r\n";
  
   if (tcp_recv_pbuf != NULL)
   {

     tcp_recved(pcb, tcp_recv_pbuf->tot_len);
  

     tcp_write(pcb,echoString, strlen(echoString), 1);
		 
     tcp_send_pbuf = tcp_recv_pbuf;
		 
     tcp_write(pcb, tcp_send_pbuf->payload, tcp_send_pbuf->len, 1);
  
     pbuf_free(tcp_recv_pbuf);
   }
   else if (err == ERR_OK)
   {
     tcp_close(pcb);
     Tcp_Client_Initialization();
  
     return ERR_OK;
   }
  
   return ERR_OK;
 }*/