#include "lwip/tcp.h"
#include "lwip/err.h"
#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
extern struct netif *enc28j60;
enum tcp_client_state{
CLIENT_CONNECTED = 0x00U,
CLIENT_WAITING_FOR_CMD,
CLIENT_BUSY,
CLIENT_SENT,
CLIENT_ERROR,
CLIENT_CLOSE,
CLIENT_WAITING_FOR_CONNECTION
};
struct tcp_client_app_arg{
uint8_t app_state;
uint8_t textlen;
uint8_t* dataptr;
};
static struct ip_addr destip;
void tcp_client_errf(void *arg, err_t err)
{
struct tcp_client_app_arg* pro_arg = (struct tcp_client_app_arg*)arg;
printf("tcp client err\n");
pro_arg->app_state = CLIENT_ERROR;
switch(err){
case ERR_MEM: printf("Out of memory error\n"); break;
case ERR_BUF: printf("Buffer error\n"); break;
case ERR_TIMEOUT: printf("Timeout\n"); break;
case ERR_RTE: printf("Routing problem\n"); break;
case ERR_ABRT: printf("Connection aborted\n"); break;
case ERR_RST: printf("Connection reset\n"); break;
case ERR_CLSD: printf("Connection closed\n"); break;
case ERR_CONN: printf("Not connected\n"); break;
case ERR_VAL: printf("Illegal value\n"); break;
case ERR_ARG: printf("Illegal argument\n"); break;
case ERR_USE: printf("Address in use\n"); break;
case ERR_IF: printf("Low-level netif error\n"); break;
case ERR_ISCONN: printf("Already connected\n"); break;
case ERR_INPROGRESS: printf("Operation in progress\n"); break;
default: printf("Unknown error\n");
}
}
err_t tcp_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct pbuf *q;
struct tcp_client_app_arg *appcmd = (struct tcp_client_app_arg *)arg;
uint16_t i = 0;
uint8_t ip[4];
uint8_t* str;
const char* cmd1 = "hello";
const char* cmd2 = "LEDON";
const char* cmd3 = "LEDOFF";
const char* cmd4 = "echo IP";
const char* cmd5 = "bye";
printf("tcp client recieve\n");
/* We perform here any necessary processing on the pbuf */
if (p != NULL)
{
/* We call this function to tell the LwIp that we have processed the data */
/* This lets the stack advertise a larger window, so more data can be received*/
tcp_recved(pcb, p->tot_len);
/* Check the name if NULL, no data passed, return withh illegal argument error */
if(appcmd == NULL)
{
pbuf_free(p);
return ERR_ARG;
}
appcmd->dataptr = (uint8_t*)mem_calloc(sizeof(uint8_t), p->tot_len);
if(appcmd->dataptr == NULL){
printf("Memory error\n");
return ERR_MEM;
}
appcmd->textlen = p->tot_len;
for(q=p; q!=NULL; q=q->next){
memcpy((uint8_t*)&appcmd->dataptr[i], q->payload, q->len); //同一个数据包会存在一个pbuf链表中
i = i + q->len;
}
//应用层代码
switch(appcmd->app_state){
case CLIENT_CONNECTED:
case CLIENT_WAITING_FOR_CMD: {
if(memcmp(appcmd->dataptr, cmd1, strlen(cmd1)) == 0)
{
str = "hello\n";
// tcp_write(pcb, (uint8_t*)str, strlen(str), 1);
}
else if(memcmp(appcmd->dataptr, cmd2, strlen(cmd2)) == 0)
{
GPIO_ResetBits(GPIOF,GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9);
str="LEDON\n";
//还可以加上这样
/*if(GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_6) == RESET)str="LEDON\n";*/
}
else if(memcmp(appcmd->dataptr, cmd3, strlen(cmd3)) == 0)
{
GPIO_SetBits(GPIOF,GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9);
str="LEDOFF\n";
}
else if(memcmp(appcmd->dataptr, cmd4, strlen(cmd4)) == 0)
{
ip[0] = 192;
ip[1] = 168;
ip[2] = 0;
ip[3] = 16;
// ip[0] = enc28j60->ip_addr.addr>>24; //打出来有点不对
// ip[1] = enc28j60->ip_addr.addr>>16;
// ip[2] = enc28j60->ip_addr.addr>>8;
// ip[3] = enc28j60->ip_addr.addr;
// ip[0] = pcb->remote_ip.addr>>24;
// ip[1] = pcb->remote_ip.addr>>16;
// ip[2] = pcb->remote_ip.addr>>8;
// ip[3] = pcb->remote_ip.addr;
str = mem_calloc(sizeof(uint8_t), 30);
sprintf((char*)str, "ipaddr:%d,%d,%d,%d\n", ip[3], ip[2], ip[1], ip[0]);
tcp_write(pcb, (const char *)str, strlen(str), 1);
mem_free(str);
break;
}
else if(memcmp(appcmd->dataptr, cmd5, strlen(cmd5)) == 0)
{
appcmd->app_state = CLIENT_CLOSE;
break;
}
else
{
str = "unknown cmd\n";
// tcp_write(pcb, (uint8_t*)str, strlen(str), 1);
}
tcp_write(pcb, (const char *)str, strlen(str), 1);
break;
}
default:
{
str = "lwip down\n";
tcp_write(pcb, (const char *)str, strlen(str), 1);
break;
}
}
mem_free(appcmd->dataptr);
//取得应用层数据后,先释放pbuf队列相应数据链,再对数据进行解析与执行操作
/* End of processing, we free the pbuf */
pbuf_free(p);
}
else if (err == ERR_OK)
{
/* When the pbuf is NULL and the err is ERR_OK, the remote end
is closing the connection. */
/* We free the allocated memory and we close the connection */
mem_free(appcmd);
return tcp_close(pcb);
}
return ERR_OK;
}
err_t tcp_client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct tcp_client_app_arg* pro_arg = (struct tcp_client_app_arg*)arg;
printf("tcp client sent\n");
switch(pro_arg->app_state){
case CLIENT_WAITING_FOR_CMD:{
printf("acked!\n");
break;
}
case CLIENT_CLOSE:{
mem_free(pro_arg);
return tcp_close(pcb);
}
default:{}
}
return ERR_OK;
}
err_t tcp_client_poll(void *arg, struct tcp_pcb *pcb)
{
const char* str = "The data come from the stm32 client\n";
printf("tcp client poll\n");
tcp_write(pcb, (const char*)str, strlen(str), 1);
return ERR_OK;
}
err_t tcp_client_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct tcp_client_app_arg* app_arg = (struct tcp_client_app_arg*)arg;
uint8_t* str = "Welcome to the client\n";
printf("tcp client connected\n");
tcp_err(pcb, tcp_client_errf); //指定出错时的回调函数
tcp_recv(pcb, tcp_client_recv); //指定接收到新数据时的回调函数
tcp_sent(pcb, tcp_client_sent); //指定远程主机成功接收到数据的回调函数
tcp_poll(pcb, tcp_client_poll, 4); //指定轮询的时间间隔和回调函数(*250ms)
tcp_write(pcb, (const char *)str, strlen(str), 1);
app_arg->app_state = CLIENT_WAITING_FOR_CMD;
return ERR_OK;
}
void tcp_client_init(void)
{
struct tcp_pcb* client_pcb;
struct tcp_client_app_arg* app_arg;
printf("tcp client inti\n");
destip.addr = (uint32_t)192+(168<<8)+(0<<16)+(105<<24);
client_pcb = tcp_new();
if(client_pcb != NULL)
{
// tcp_bind(client_pcb,IP_ADDR_ANY,2200);
tcp_arg(client_pcb, mem_calloc(sizeof(struct tcp_client_app_arg), 1));
app_arg = client_pcb->callback_arg;
app_arg->app_state = CLIENT_WAITING_FOR_CONNECTION;
tcp_connect(client_pcb, &destip, 2200, tcp_client_connected); //按需求连接,加上条件
}
else
{
printf("tcp alloc failed\n");
}
}