先了解應用層和協議棧是怎麼交互消息的
先看內核消息數據結構
/* tcp/ip內核消息類型 */
enum tcpip_msg_type
{
TCPIP_MSG_API, //調用API
TCPIP_MSG_INPKT, //底層數據包輸入
TCPIP_MSG_TIMEOUT, //註冊一個定時事件
TCPIP_MSG_UNTIMEOUT, //刪除一個定時事件
TCPIP_MSG_CALLBACK, //上層回調函數
TCPIP_MSG_CALLBACK_STATIC //上層回調函數(消息爲靜態)
};
/* tcp/ip內核消息 */
struct tcpip_msg
{
enum tcpip_msg_type type; //消息類型
sys_sem_t *sem; //信號量指針
union
{
/* API消息 */
struct api_msg *apimsg;
/* 底層數據包輸入消息 */
struct
{
struct pbuf *p; //數據包pbuf指針
struct netif *netif; //網絡接口指針
}inp;
/* 上層回調函數消息 */
struct
{
tcpip_callback_fn function; //回調函數
void *ctx; //回調函數參數
}cb;
/* 定時事件 */
struct
{
u32_t msecs; //時間
sys_timeout_handler h; //回調函數
void *arg; //回調函數參數
}tmo;
}msg;
};
在看一下,內核是怎麼分類處理應用層消息的
static tcpip_init_done_fn tcpip_init_done;
static void *tcpip_init_done_arg;
static sys_mbox_t mbox;
/* tcp/ip線程 */
static void tcpip_thread(void *arg)
{
struct tcpip_msg *msg;
/* 用戶自定義初始化函數 */
if(tcpip_init_done != NULL)
{
tcpip_init_done(tcpip_init_done_arg);
}
while(1)
{
/* 所有的超時事件和郵箱消息都在這裏處理 */
sys_timeouts_mbox_fetch(&mbox, (void **)&msg);
/* 接收到消息 */
switch(msg->type)
{
/* API消息 */
case TCPIP_MSG_API:
/* 調用API */
msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
break;
/* 底層數據包輸入 */
case TCPIP_MSG_INPKT:
/* 以太網設備 */
/* 支持ARP協議 */
if(msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET))
{
/* 以太網數據包輸入處理 */
ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
}
/* 不支持ARP協議 */
else
{
/* IP數據包輸入處理 */
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
}
/* 釋放該消息內存空間 */
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
break;
/* 註冊一個定時事件 */
case TCPIP_MSG_TIMEOUT:
/* 啓動定時事件 */
sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
/* 釋放該消息內存空間 */
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
/* 刪除一個定時事件 */
case TCPIP_MSG_UNTIMEOUT:
/* 取消定時事件 */
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
/* 釋放該消息內存空間 */
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
/* 上層回調函數 */
case TCPIP_MSG_CALLBACK:
/* 調用回調函數 */
msg->msg.cb.function(msg->msg.cb.ctx);
/* 釋放該消息內存空間 */
memp_free(MEMP_TCPIP_MSG_API, msg);
break;
/* 上層回調函數(消息爲靜態) */
case TCPIP_MSG_CALLBACK_STATIC:
/* 調用回調函數 */
msg->msg.cb.function(msg->msg.cb.ctx);
break;
default:
break;
}
}
}
/* 底層數據包輸入處理函數 */
err_t tcpip_input(struct pbuf *p, struct netif *inp)
{
struct tcpip_msg *msg;
/* 郵箱無效 */
if(!sys_mbox_valid(&mbox))
{
return ERR_VAL;
}
/* 爲底層數據包輸入消息從內存池申請內存 */
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
if(msg == NULL)
{
return ERR_MEM;
}
/* 底層數據包輸入消息 */
msg->type = TCPIP_MSG_INPKT;
/* 數據包內容 */
msg->msg.inp.p = p;
/* 網絡接口指針 */
msg->msg.inp.netif = inp;
/* 發送消息 */
if(sys_mbox_trypost(&mbox, msg) != ERR_OK)
{
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
return ERR_MEM;
}
return ERR_OK;
}
/* 上層回調函數 */
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
{
struct tcpip_msg *msg;
/* 郵箱有效 */
if(sys_mbox_valid(&mbox))
{
/* 爲上層回調函數消息從內存池申請內存 */
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if(msg == NULL)
{
return ERR_MEM;
}
/* 上層回調函數 */
msg->type = TCPIP_MSG_CALLBACK;
/* 回調函數 */
msg->msg.cb.function = function;
/* 回調函數參數 */
msg->msg.cb.ctx = ctx;
/* 發送消息(阻塞) */
if(block)
{
sys_mbox_post(&mbox, msg);
}
/* 發送消息(非阻塞) */
else
{
if(sys_mbox_trypost(&mbox, msg) != ERR_OK)
{
memp_free(MEMP_TCPIP_MSG_API, msg);
return ERR_MEM;
}
}
return ERR_OK;
}
return ERR_VAL;
}
/* 註冊一個定時事件 */
err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
/* 郵箱爲有效 */
if(sys_mbox_valid(&mbox))
{
/* 爲註冊一個定時事件消息從內存池申請內存 */
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if(msg == NULL)
{
return ERR_MEM;
}
/* 註冊一個定時事件 */
msg->type = TCPIP_MSG_TIMEOUT;
/* 定時事件 */
msg->msg.tmo.msecs = msecs;
/* 回調函數 */
msg->msg.tmo.h = h;
/* 回調函數參數 */
msg->msg.tmo.arg = arg;
/* 發送消息 */
sys_mbox_post(&mbox, msg);
return ERR_OK;
}
return ERR_VAL;
}
/* 刪除一個定時事件 */
err_t tcpip_untimeout(sys_timeout_handler h, void *arg)
{
struct tcpip_msg *msg;
/* 郵箱爲有效 */
if(sys_mbox_valid(&mbox))
{
/* 爲刪除一個定時事件消息從內存池申請內存 */
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if(msg == NULL)
{
return ERR_MEM;
}
/* 刪除一個定時事件 */
msg->type = TCPIP_MSG_UNTIMEOUT;
/* 回調函數 */
msg->msg.tmo.h = h;
/* 回調函數參數 */
msg->msg.tmo.arg = arg;
/* 發送消息 */
sys_mbox_post(&mbox, msg);
return ERR_OK;
}
return ERR_VAL;
}
/* API調用 */
err_t tcpip_apimsg(struct api_msg *apimsg)
{
struct tcpip_msg msg;
/* 郵箱爲有效 */
if(sys_mbox_valid(&mbox))
{
/* 調用API */
msg.type = TCPIP_MSG_API;
/* API消息 */
msg.msg.apimsg = apimsg;
/* 發送消息 */
sys_mbox_post(&mbox, &msg);
/* 等待API調用完成 */
sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0);
return apimsg->msg.err;
}
return ERR_VAL;
}
/* 創建上層回調函數消息 */
struct tcpip_callback_msg *tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
{
/* 爲上層回調函數消息從內存池申請內存 */
struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if(msg == NULL)
{
return NULL;
}
/* 上層回調函數 */
msg->type = TCPIP_MSG_CALLBACK_STATIC;
/* 回調函數 */
msg->msg.cb.function = function;
/* 回調函數參數 */
msg->msg.cb.ctx = ctx;
/* 返回消息指針 */
return (struct tcpip_callback_msg *)msg;
}
/* 釋放上層回調函數消息 */
void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg)
{
memp_free(MEMP_TCPIP_MSG_API, msg);
}
/* 發送上層回調函數消息 */
err_t tcpip_trycallback(struct tcpip_callback_msg* msg)
{
if(!sys_mbox_valid(&mbox))
{
return ERR_VAL;
}
return sys_mbox_trypost(&mbox, msg);
}
/* tcp/ip初始化 */
void tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{
/* 初始化協議棧 */
lwip_init();
/* 自定義初始化函數 */
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
/* 創建郵箱 */
if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK)
{
}
/* 創建線程 */
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
}
/* 釋放pbuf上層回調函數 */
static void pbuf_free_int(void *p)
{
struct pbuf *q = (struct pbuf *)p;
pbuf_free(q);
}
/* 使用上層回調函數消息釋放pbuf */
err_t pbuf_free_callback(struct pbuf *p)
{
/* 使用上層回調函數消息釋放pbuf */
return tcpip_callback_with_block(pbuf_free_int, p, 0);
}
/* 使用上層回調函數消息釋放到內存堆 */
err_t mem_free_callback(void *m)
{
/* 使用上層回調函數消息釋放到內存堆 */
return tcpip_callback_with_block(mem_free, m, 0);
}
接下來看一下內核收到消息後具體是怎麼工作的
/* API消息 */
struct api_msg_msg
{
/* 連接結構 */
struct netconn *conn;
/* 錯誤 */
err_t err;
union
{
/* do_send時需要的參數 */
struct netbuf *b;
/* do_newconn時需要的參數 */
struct
{
u8_t proto; //協議類型
}n;
/* do_bind和do_connect時需要的參數 */
struct
{
ip_addr_t *ipaddr; //IP地址
u16_t port; //端口號
}bc;
/* do_getaddr時需要的參數 */
struct
{
ip_addr_t *ipaddr; //IP地址
u16_t *port; //端口號
u8_t local; //1本地IP、0遠程IP
}ad;
/* do_write時需要的參數 */
struct
{
const void *dataptr; //數據
size_t len; //長度
u8_t apiflags; //標誌位
}w;
/* do_recv時需要的參數 */
struct
{
u32_t len; //長度
}r;
/* do_close時需要的參數 */
struct
{
u8_t shut; //關閉方向
}sd;
}msg;
};
/* API消息 */
struct api_msg
{
void (*function)(struct api_msg_msg *msg); //回調函數
struct api_msg_msg msg; //回調函數參數
};
/* 設置是否爲阻塞態 */
#define SET_NONBLOCKING_CONNECT(conn, val) do { if(val) { \
(conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \
} else { \
(conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0)
/* 非阻塞態 */
#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0)
static err_t do_writemore(struct netconn *conn);
static void do_close_internal(struct netconn *conn);
/* 原始IP接口接收回調函數 */
static u8_t recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr)
{
struct pbuf *q;
struct netbuf *buf;
struct netconn *conn;
/* 參數 */
conn = (struct netconn *)arg;
/* 接收郵箱有效 */
if((conn != NULL) && sys_mbox_valid(&conn->recvmbox))
{
/* 將數據放到netbuf中 */
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
if(q != NULL)
{
if(pbuf_copy(q, p) != ERR_OK)
{
pbuf_free(q);
q = NULL;
}
}
if(q != NULL)
{
u16_t len;
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if(buf == NULL)
{
pbuf_free(q);
return 0;
}
buf->p = q;
buf->ptr = q;
ip_addr_copy(buf->addr, *ip_current_src_addr());
buf->port = pcb->protocol;
len = q->tot_len;
/* 發送接收郵箱消息 */
if(sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK)
{
netbuf_delete(buf);
return 0;
}
else
{
/* 調用連接回調函數 */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
}
}
}
return 0;
}
/* UDP接口接收回調函數 */
static void recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
{
struct netbuf *buf;
struct netconn *conn;
u16_t len;
conn = (struct netconn *)arg;
/* 郵箱無效 */
if((conn == NULL) || !sys_mbox_valid(&conn->recvmbox))
{
pbuf_free(p);
return;
}
/* 將數據放到netbuf中 */
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if(buf == NULL)
{
pbuf_free(p);
return;
}
else
{
buf->p = p;
buf->ptr = p;
ip_addr_set(&buf->addr, addr);
buf->port = port;
}
len = p->tot_len;
/* 發送接收郵箱消息 */
if(sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK)
{
netbuf_delete(buf);
return;
}
else
{
/* 調用連接回調函數 */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
}
}
/* 接收回調函數 */
static err_t recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct netconn *conn;
u16_t len;
conn = (struct netconn *)arg;
if(conn == NULL)
{
return ERR_VAL;
}
/* 郵箱無效 */
if(!sys_mbox_valid(&conn->recvmbox))
{
if(p != NULL)
{
tcp_recved(pcb, p->tot_len);
pbuf_free(p);
}
return ERR_OK;
}
/* 設置致命錯誤 */
NETCONN_SET_SAFE_ERR(conn, err);
if(p != NULL)
{
len = p->tot_len;
}
else
{
len = 0;
}
/* 發送接收郵箱消息 */
if(sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK)
{
return ERR_MEM;
}
else
{
/* 調用連接回調函數 */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
}
return ERR_OK;
}
/* poll回調函數 */
static err_t poll_tcp(void *arg, struct tcp_pcb *pcb)
{
struct netconn *conn = (struct netconn *)arg;
/* 正在發送數據 */
if(conn->state == NETCONN_WRITE)
{
do_writemore(conn);
}
/* 關閉狀態 */
else if(conn->state == NETCONN_CLOSE)
{
do_close_internal(conn);
}
/* 需要再次檢查是否可寫 */
if(conn->flags & NETCONN_FLAG_CHECK_WRITESPACE)
{
/* 判斷是否可寫 */
if((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
(tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT))
{
conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
/* 調用連接回調函數 */
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
}
}
return ERR_OK;
}
/* 發送回調函數 */
static err_t sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct netconn *conn = (struct netconn *)arg;
/* 正在發送數據 */
if(conn->state == NETCONN_WRITE)
{
do_writemore(conn);
}
/* 關閉狀態 */
else if(conn->state == NETCONN_CLOSE)
{
do_close_internal(conn);
}
if(conn)
{
/* 需要再次檢查是否可寫 */
if((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
(tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT))
{
conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
/* 調用連接回調函數 */
API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
}
}
return ERR_OK;
}
/* 錯誤回調函數 */
static void err_tcp(void *arg, err_t err)
{
struct netconn *conn;
enum netconn_state old_state;
conn = (struct netconn *)arg;
conn->pcb.tcp = NULL;
/* 記錄錯誤 */
conn->last_err = err;
/* 復位連接 */
old_state = conn->state;
conn->state = NETCONN_NONE;
/* 調用連接回調函數 */
API_EVENT(conn, NETCONN_EVT_ERROR, 0);
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
/* 發送接收郵箱消息 */
if(sys_mbox_valid(&conn->recvmbox))
{
sys_mbox_trypost(&conn->recvmbox, NULL);
}
/* 發送接受連接郵箱消息 */
if(sys_mbox_valid(&conn->acceptmbox))
{
sys_mbox_trypost(&conn->acceptmbox, NULL);
}
if((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
(old_state == NETCONN_CONNECT))
{
/* 清空阻塞態 */
int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn);
SET_NONBLOCKING_CONNECT(conn, 0);
/* 阻塞態 */
if(!was_nonblocking_connect)
{
conn->current_msg->err = err;
conn->current_msg = NULL;
/* 釋放操作完成信號量 */
sys_sem_signal(&conn->op_completed);
}
}
}
/* 設置TCP回調函數 */
static void setup_tcp(struct netconn *conn)
{
struct tcp_pcb *pcb;
pcb = conn->pcb.tcp;
/* 設置用戶自定義參數 */
tcp_arg(pcb, conn);
/* 設置接收回調函數 */
tcp_recv(pcb, recv_tcp);
/* 設置發送成功回調函數 */
tcp_sent(pcb, sent_tcp);
/* 設置poll回調函數和週期 */
tcp_poll(pcb, poll_tcp, 4);
/* 設置連接錯誤回調函數 */
tcp_err(pcb, err_tcp);
}
/* 接受連接回調函數 */
static err_t accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
struct netconn *newconn;
struct netconn *conn = (struct netconn *)arg;
if(!sys_mbox_valid(&conn->acceptmbox))
{
return ERR_VAL;
}
/* 爲新連接創建一個連接結構體,設置TCP回調函數 */
newconn = netconn_alloc(conn->type, conn->callback);
if(newconn == NULL)
{
return ERR_MEM;
}
newconn->pcb.tcp = newpcb;
setup_tcp(newconn);
newconn->last_err = err;
/* 發送接受連接消息 */
if(sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK)
{
struct tcp_pcb* pcb = newconn->pcb.tcp;
tcp_arg(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_poll(pcb, NULL, 4);
tcp_err(pcb, NULL);
newconn->pcb.tcp = NULL;
sys_mbox_free(&newconn->recvmbox);
sys_mbox_set_invalid(&newconn->recvmbox);
netconn_free(newconn);
return ERR_MEM;
}
else
{
/* 調用連接事件回調函數 */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
}
return ERR_OK;
}
/* 創建控制塊 */
static void pcb_new(struct api_msg_msg *msg)
{
LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
/* 判斷協議類型 */
switch(NETCONNTYPE_GROUP(msg->conn->type))
{
/* 原始IP連接 */
case NETCONN_RAW:
/* 創建IP原始接口控制塊 */
msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
if(msg->conn->pcb.raw == NULL)
{
msg->err = ERR_MEM;
break;
}
/* IP原始接口設置接收回調函數 */
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
break;
/* UDP */
case NETCONN_UDP:
/* 創建一個UDP控制塊 */
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL)
{
msg->err = ERR_MEM;
break;
}
/* 無校驗UDP */
if(msg->conn->type == NETCONN_UDPNOCHKSUM)
{
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
}
/* 設置UDP控制塊回調函數 */
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
/* TCP */
case NETCONN_TCP:
/* 新建TCP控制塊 */
msg->conn->pcb.tcp = tcp_new();
if(msg->conn->pcb.tcp == NULL)
{
msg->err = ERR_MEM;
break;
}
/* 設置TCP回調函數 */
setup_tcp(msg->conn);
break;
/* 不支持 */
default:
msg->err = ERR_VAL;
break;
}
}
/* 創建一個連接PCB */
void do_newconn(struct api_msg_msg *msg)
{
msg->err = ERR_OK;
/* 控制塊還未創建 */
if(msg->conn->pcb.tcp == NULL)
{
/* 創建控制塊 */
pcb_new(msg);
}
/* 釋放API調用完成信號量 */
TCPIP_APIMSG_ACK(msg);
}
/* 創建一個連接結構體 */
struct netconn *netconn_alloc(enum netconn_type t, netconn_callback callback)
{
struct netconn *conn;
int size;
/* 爲連接申請內存空間 */
conn = (struct netconn *)memp_malloc(MEMP_NETCONN);
if(conn == NULL)
{
return NULL;
}
/* 清空最近一個錯誤 */
conn->last_err = ERR_OK;
/* 連接類型 */
conn->type = t;
/* 清空控制塊指針 */
conn->pcb.tcp = NULL;
size = DEFAULT_RAW_RECVMBOX_SIZE;
/* 創建API調用完成信號量 */
if(sys_sem_new(&conn->op_completed, 0) != ERR_OK)
{
goto free_and_return;
}
/* 創建接收郵箱 */
if(sys_mbox_new(&conn->recvmbox, size) != ERR_OK)
{
sys_sem_free(&conn->op_completed);
goto free_and_return;
}
/* 接受連接郵箱設置爲無效 */
sys_mbox_set_invalid(&conn->acceptmbox);
/* 不處於任何連接狀態 */
conn->state = NETCONN_NONE;
/* 套接字描述符 */
conn->socket = -1;
/* 回調函數 */
conn->callback = callback;
/* 寫數據緩存不足時,數據暫時封裝在current_msg中,
write_offset是下一次發送的索引 */
conn->current_msg = NULL;
conn->write_offset = 0;
/* 清空標誌位 */
conn->flags = 0;
return conn;
free_and_return:
memp_free(MEMP_NETCONN, conn);
return NULL;
}
/* 釋放連接結構體 */
void netconn_free(struct netconn *conn)
{
/* 刪除API調用完成信號量 */
sys_sem_free(&conn->op_completed);
/* API信號量設置爲無效 */
sys_sem_set_invalid(&conn->op_completed);
/* 釋放連接內存空間 */
memp_free(MEMP_NETCONN, conn);
}
/* 刪除接收郵箱和接受連接郵箱 */
static void netconn_drain(struct netconn *conn)
{
void *mem;
struct pbuf *p;
/* 接收郵箱有效 */
if(sys_mbox_valid(&conn->recvmbox))
{
/* 接收消息並處理 */
while(sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY)
{
/* TCP連接 */
if(conn->type == NETCONN_TCP)
{
/* pbuf處理 */
if(mem != NULL)
{
p = (struct pbuf *)mem;
if(conn->pcb.tcp != NULL)
{
/* 應用層接收對方傳來的數據 */
tcp_recved(conn->pcb.tcp, p->tot_len);
}
/* 釋放數據pbuf */
pbuf_free(p);
}
}
else
{
/* 刪除netbuf */
netbuf_delete((struct netbuf *)mem);
}
}
/* 刪除接收郵箱 */
sys_mbox_free(&conn->recvmbox);
sys_mbox_set_invalid(&conn->recvmbox);
}
/* 接受連接郵箱有效 */
if(sys_mbox_valid(&conn->acceptmbox))
{
/* 接收消息並處理 */
while(sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY)
{
/* 新連接處理 */
struct netconn *newconn = (struct netconn *)mem;
if(conn->pcb.tcp != NULL)
{
/* 接受新連接 */
tcp_accepted(conn->pcb.tcp);
}
/* 刪除每一個新連接接收郵箱 */
netconn_drain(newconn);
/* 刪除TCP控制塊,併發送TCP復位報文 */
if(newconn->pcb.tcp != NULL)
{
tcp_abort(newconn->pcb.tcp);
newconn->pcb.tcp = NULL;
}
/* 釋放連接結構體 */
netconn_free(newconn);
}
/* 刪除接受連接郵箱 */
sys_mbox_free(&conn->acceptmbox);
sys_mbox_set_invalid(&conn->acceptmbox);
}
}
/* 關閉連接 */
static void do_close_internal(struct netconn *conn)
{
err_t err;
u8_t shut, shut_rx, shut_tx, close;
/* 關閉方向 */
shut = conn->current_msg->msg.sd.shut;
shut_rx = shut & NETCONN_SHUT_RD;
shut_tx = shut & NETCONN_SHUT_WR;
/* 關閉 */
close = shut == NETCONN_SHUT_RDWR;
/* 清空用戶自定義參數 */
if(close)
{
tcp_arg(conn->pcb.tcp, NULL);
}
/* 偵聽狀態,清空接受連接回調函數 */
if(conn->pcb.tcp->state == LISTEN)
{
tcp_accept(conn->pcb.tcp, NULL);
}
/* 非偵聽狀態 */
else
{
/* 關閉接收方向,清空接收和接受連接回調函數 */
if(shut_rx)
{
tcp_recv(conn->pcb.tcp, NULL);
tcp_accept(conn->pcb.tcp, NULL);
}
/* 關閉發送方向,清空發送回調函數 */
if(shut_tx)
{
tcp_sent(conn->pcb.tcp, NULL);
}
/* 清空poll和錯誤回調函數 */
if(close)
{
tcp_poll(conn->pcb.tcp, NULL, 4);
tcp_err(conn->pcb.tcp, NULL);
}
}
/* 關閉連接 */
if(close)
{
err = tcp_close(conn->pcb.tcp);
}
else
{
err = tcp_shutdown(conn->pcb.tcp, shut_rx, shut_tx);
}
/* 調用連接API回調函數 */
if(err == ERR_OK)
{
conn->current_msg->err = ERR_OK;
conn->current_msg = NULL;
conn->state = NETCONN_NONE;
if(close)
{
conn->pcb.tcp = NULL;
API_EVENT(conn, NETCONN_EVT_ERROR, 0);
}
if(shut_rx)
{
API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
}
if(shut_tx)
{
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
}
sys_sem_signal(&conn->op_completed);
}
/* 關閉失敗 */
else
{
tcp_sent(conn->pcb.tcp, sent_tcp);
tcp_poll(conn->pcb.tcp, poll_tcp, 4);
tcp_err(conn->pcb.tcp, err_tcp);
tcp_arg(conn->pcb.tcp, conn);
}
}
/* 刪除控制塊 */
void do_delconn(struct api_msg_msg *msg)
{
if((msg->conn->state != NETCONN_NONE) &&
(msg->conn->state != NETCONN_LISTEN) &&
(msg->conn->state != NETCONN_CONNECT))
{
msg->err = ERR_INPROGRESS;
}
else
{
/* 刪除接收郵箱和接受連接郵箱 */
netconn_drain(msg->conn);
/* 判斷連接類型 */
if(msg->conn->pcb.tcp != NULL)
{
switch(NETCONNTYPE_GROUP(msg->conn->type))
{
/* 原始IP連接 */
case NETCONN_RAW:
/* 移除IP原始接口控制塊 */
raw_remove(msg->conn->pcb.raw);
break;
/* UDP */
case NETCONN_UDP:
/* 刪除UDP控制塊 */
msg->conn->pcb.udp->recv_arg = NULL;
udp_remove(msg->conn->pcb.udp);
break;
/* TCP */
case NETCONN_TCP:
msg->conn->state = NETCONN_CLOSE;
msg->msg.sd.shut = NETCONN_SHUT_RDWR;
msg->conn->current_msg = msg;
/* 關閉連接 */
do_close_internal(msg->conn);
return;
default:
break;
}
msg->conn->pcb.tcp = NULL;
}
/* 調用連接API回調函數 */
API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
}
/* 釋放操作完成信號量 */
if(sys_sem_valid(&msg->conn->op_completed))
{
sys_sem_signal(&msg->conn->op_completed);
}
}
/* 綁定本地端口 */
void do_bind(struct api_msg_msg *msg)
{
/* 根據連接類型調用綁定 */
if(ERR_IS_FATAL(msg->conn->last_err))
{
msg->err = msg->conn->last_err;
}
else
{
msg->err = ERR_VAL;
if(msg->conn->pcb.tcp != NULL)
{
switch(NETCONNTYPE_GROUP(msg->conn->type))
{
case NETCONN_RAW:
msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
break;
case NETCONN_UDP:
msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
case NETCONN_TCP:
msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
default:
break;
}
}
}
/* 釋放API調用完成信號量 */
TCPIP_APIMSG_ACK(msg);
}
/* 連接完成 */
static err_t do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct netconn *conn;
int was_blocking;
conn = (struct netconn *)arg;
if(conn == NULL)
{
return ERR_VAL;
}
if(conn->current_msg != NULL)
{
conn->current_msg->err = err;
}
/* 設置TCP回調函數 */
if((conn->type == NETCONN_TCP) && (err == ERR_OK))
{
setup_tcp(conn);
}
/* 是否爲阻塞態 */
was_blocking = !IN_NONBLOCKING_CONNECT(conn);
/* 清空非阻塞態 */
SET_NONBLOCKING_CONNECT(conn, 0);
/* 清空消息 */
conn->current_msg = NULL;
/* 清空狀態 */
conn->state = NETCONN_NONE;
if(!was_blocking)
{
NETCONN_SET_SAFE_ERR(conn, ERR_OK);
}
/* 調用連接API回調函數 */
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
/* 阻塞態,釋放操作完成信號量 */
if(was_blocking)
{
sys_sem_signal(&conn->op_completed);
}
return ERR_OK;
}
/* 連接遠程端口 */
void do_connect(struct api_msg_msg *msg)
{
/* 根據連接類型調用連接 */
if(msg->conn->pcb.tcp == NULL)
{
msg->err = ERR_CLSD;
}
else
{
switch(NETCONNTYPE_GROUP(msg->conn->type))
{
case NETCONN_RAW:
msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
break;
case NETCONN_UDP:
msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
case NETCONN_TCP:
if(msg->conn->state != NETCONN_NONE)
{
msg->err = ERR_ISCONN;
}
else
{
setup_tcp(msg->conn);
msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port, do_connected);
if(msg->err == ERR_OK)
{
u8_t non_blocking = netconn_is_nonblocking(msg->conn);
msg->conn->state = NETCONN_CONNECT;
SET_NONBLOCKING_CONNECT(msg->conn, non_blocking);
if(non_blocking)
{
msg->err = ERR_INPROGRESS;
}
else
{
msg->conn->current_msg = msg;
return;
}
}
}
break;
default:
break;
}
}
/* 釋放操作完成信號量 */
sys_sem_signal(&msg->conn->op_completed);
}
/* 斷開連接 */
void do_disconnect(struct api_msg_msg *msg)
{
if(NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP)
{
udp_disconnect(msg->conn->pcb.udp);
msg->err = ERR_OK;
}
else
{
msg->err = ERR_VAL;
}
/* 釋放操作完成信號量 */
TCPIP_APIMSG_ACK(msg);
}
/* 偵聽 */
void do_listen(struct api_msg_msg *msg)
{
if(ERR_IS_FATAL(msg->conn->last_err))
{
msg->err = msg->conn->last_err;
}
else
{
msg->err = ERR_CONN;
if(msg->conn->pcb.tcp != NULL)
{
if(msg->conn->type == NETCONN_TCP)
{
if(msg->conn->state == NETCONN_NONE)
{
struct tcp_pcb *lpcb = tcp_listen(msg->conn->pcb.tcp);
/* 刪除接收郵箱,創建接受連接郵箱 */
if(lpcb == NULL)
{
msg->err = ERR_MEM;
}
else
{
if(sys_mbox_valid(&msg->conn->recvmbox))
{
sys_mbox_free(&msg->conn->recvmbox);
sys_mbox_set_invalid(&msg->conn->recvmbox);
}
msg->err = ERR_OK;
if(!sys_mbox_valid(&msg->conn->acceptmbox))
{
msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE);
}
if(msg->err == ERR_OK)
{
msg->conn->state = NETCONN_LISTEN;
msg->conn->pcb.tcp = lpcb;
tcp_arg(msg->conn->pcb.tcp, msg->conn);
tcp_accept(msg->conn->pcb.tcp, accept_function);
}
else
{
tcp_close(lpcb);
msg->conn->pcb.tcp = NULL;
}
}
}
}
else
{
msg->err = ERR_ARG;
}
}
}
/* 釋放操作完成信號量 */
TCPIP_APIMSG_ACK(msg);
}
/* 非TCP發送數據 */
void do_send(struct api_msg_msg *msg)
{
if(ERR_IS_FATAL(msg->conn->last_err))
{
msg->err = msg->conn->last_err;
}
else
{
msg->err = ERR_CONN;
if(msg->conn->pcb.tcp != NULL)
{
switch(NETCONNTYPE_GROUP(msg->conn->type))
{
case NETCONN_RAW:
if(ip_addr_isany(&msg->msg.b->addr))
{
msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
}
else
{
msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
}
break;
case NETCONN_UDP:
if(ip_addr_isany(&msg->msg.b->addr))
{
msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
}
else
{
msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port);
}
break;
default:
break;
}
}
}
/* 釋放操作完成信號量 */
TCPIP_APIMSG_ACK(msg);
}
#if LWIP_TCP
/* TCP接收數據 */
void do_recv(struct api_msg_msg *msg)
{
msg->err = ERR_OK;
if(msg->conn->pcb.tcp != NULL)
{
if(msg->conn->type == NETCONN_TCP)
{
u32_t remaining = msg->msg.r.len;
do
{
u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
tcp_recved(msg->conn->pcb.tcp, recved);
remaining -= recved;
}while(remaining != 0);
}
}
/* 釋放操作完成信號量 */
TCPIP_APIMSG_ACK(msg);
}
/* TCP發送沒發完的數據 */
static err_t do_writemore(struct netconn *conn)
{
err_t err;
void *dataptr;
u16_t len, available;
u8_t write_finished = 0;
size_t diff;
u8_t dontblock = netconn_is_nonblocking(conn) || (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK);
u8_t apiflags = conn->current_msg->msg.w.apiflags;
{
/* 判斷一次能不能寫完 */
dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset;
diff = conn->current_msg->msg.w.len - conn->write_offset;
if(diff > 0xffffUL)
{
len = 0xffff;
apiflags |= TCP_WRITE_FLAG_MORE;
}
else
{
len = (u16_t)diff;
}
available = tcp_sndbuf(conn->pcb.tcp);
/* 寫不完 */
if(available < len)
{
len = available;
/* 非阻塞,報錯 */
if(dontblock)
{
if(!len)
{
err = ERR_WOULDBLOCK;
goto err_mem;
}
}
/* 阻塞,還有剩餘數據 */
else
{
apiflags |= TCP_WRITE_FLAG_MORE;
}
}
/* 組建發送數據 */
err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
if((err == ERR_OK) || (err == ERR_MEM))
{
err_mem:
/* 非阻塞態,並且沒寫完 */
if(dontblock && (len < conn->current_msg->msg.w.len))
{
/* 調用連接API回調函數 */
API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
/* 需要再次檢查是否可寫 */
conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE;
}
/* 發送數據成功 */
else if((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT))
{
/* 調用連接API回調函數 */
API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
}
}
/* 將數據發送出去 */
if(err == ERR_OK)
{
conn->write_offset += len;
if((conn->write_offset == conn->current_msg->msg.w.len) || dontblock)
{
conn->current_msg->msg.w.len = conn->write_offset;
write_finished = 1;
conn->write_offset = 0;
}
tcp_output(conn->pcb.tcp);
}
else if((err == ERR_MEM) && !dontblock)
{
tcp_output(conn->pcb.tcp);
}
else
{
write_finished = 1;
conn->current_msg->msg.w.len = 0;
}
}
/* 發送完成 */
if(write_finished)
{
conn->current_msg->err = err;
conn->current_msg = NULL;
conn->state = NETCONN_NONE;
{
/* 釋放操作完成信號量 */
sys_sem_signal(&conn->op_completed);
}
}
return ERR_OK;
}
/* TCP發送數據 */
void do_write(struct api_msg_msg *msg)
{
if(ERR_IS_FATAL(msg->conn->last_err))
{
msg->err = msg->conn->last_err;
}
else
{
/* TCP連接 */
if(msg->conn->type == NETCONN_TCP)
{
if(msg->conn->state != NETCONN_NONE)
{
msg->err = ERR_INPROGRESS;
}
else if(msg->conn->pcb.tcp != NULL)
{
msg->conn->state = NETCONN_WRITE;
msg->conn->current_msg = msg;
msg->conn->write_offset = 0;
do_writemore(msg->conn);
return;
}
else
{
msg->err = ERR_CONN;
}
}
/* 非TCP連接 */
else
{
msg->err = ERR_VAL;
}
}
/* 釋放操作完成信號量 */
TCPIP_APIMSG_ACK(msg);
}
/* 獲取本地或者遠程IP和端口號 */
void do_getaddr(struct api_msg_msg *msg)
{
if(msg->conn->pcb.ip != NULL)
{
*(msg->msg.ad.ipaddr) = (msg->msg.ad.local ? msg->conn->pcb.ip->local_ip : msg->conn->pcb.ip->remote_ip);
msg->err = ERR_OK;
switch(NETCONNTYPE_GROUP(msg->conn->type))
{
case NETCONN_RAW:
if(msg->msg.ad.local)
{
*(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
}
else
{
msg->err = ERR_CONN;
}
break;
case NETCONN_UDP:
if(msg->msg.ad.local)
{
*(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
}
else
{
if((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0)
{
msg->err = ERR_CONN;
}
else
{
*(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
}
}
break;
case NETCONN_TCP:
*(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port);
break;
default:
break;
}
}
else
{
msg->err = ERR_CONN;
}
/* 釋放操作完成信號量 */
TCPIP_APIMSG_ACK(msg);
}
/* 關閉連接 */
void do_close(struct api_msg_msg *msg)
{
if((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN))
{
msg->err = ERR_INPROGRESS;
}
/* TCP連接 */
else if((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP))
{
if((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN))
{
msg->err = ERR_CONN;
}
else
{
/* 關閉接收方向 */
if(msg->msg.sd.shut & NETCONN_SHUT_RD)
{
/* 刪除接收郵箱和接受連接郵箱 */
netconn_drain(msg->conn);
}
msg->conn->state = NETCONN_CLOSE;
msg->conn->current_msg = msg;
/* 關閉連接 */
do_close_internal(msg->conn);
return;
}
}
else
{
msg->err = ERR_VAL;
}
/* 釋放操作完成信號量 */
sys_sem_signal(&msg->conn->op_completed);
}
最後,看一下應用程序接口
/* 創建一個新的連接並且設置回調函數 */
struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
{
struct netconn *conn;
struct api_msg msg;
/* 創建一個連接結構體 */
conn = netconn_alloc(t, callback);
if(conn != NULL)
{
/* 請求創建一個連接PCB */
msg.function = do_newconn;
msg.msg.msg.n.proto = proto;
msg.msg.conn = conn;
if(TCPIP_APIMSG(&msg) != ERR_OK)
{
sys_sem_free(&conn->op_completed);
sys_mbox_free(&conn->recvmbox);
memp_free(MEMP_NETCONN, conn);
return NULL;
}
}
return conn;
}
/* 刪除連接 */
err_t netconn_delete(struct netconn *conn)
{
struct api_msg msg;
if(conn == NULL)
{
return ERR_OK;
}
/* 請求刪除控制塊 */
msg.function = do_delconn;
msg.msg.conn = conn;
tcpip_apimsg(&msg);
/* 釋放連接結構體 */
netconn_free(conn);
return ERR_OK;
}
/* 獲取本地或者遠程IP和端口號 */
err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
{
struct api_msg msg;
err_t err;
/* 請求獲取本地或者遠程IP和端口號 */
msg.function = do_getaddr;
msg.msg.conn = conn;
msg.msg.msg.ad.ipaddr = addr;
msg.msg.msg.ad.port = port;
msg.msg.msg.ad.local = local;
err = TCPIP_APIMSG(&msg);
NETCONN_SET_SAFE_ERR(conn, err);
return err;
}
/* 綁定本地端口 */
err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port)
{
struct api_msg msg;
err_t err;
/* 請求綁定本地端口 */
msg.function = do_bind;
msg.msg.conn = conn;
msg.msg.msg.bc.ipaddr = addr;
msg.msg.msg.bc.port = port;
err = TCPIP_APIMSG(&msg);
NETCONN_SET_SAFE_ERR(conn, err);
return err;
}
/* 連接遠程端口 */
err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
{
struct api_msg msg;
err_t err;
/* 請求連接遠程端口 */
msg.function = do_connect;
msg.msg.conn = conn;
msg.msg.msg.bc.ipaddr = addr;
msg.msg.msg.bc.port = port;
err = tcpip_apimsg(&msg);
NETCONN_SET_SAFE_ERR(conn, err);
return err;
}
/* 斷開連接 */
err_t netconn_disconnect(struct netconn *conn)
{
struct api_msg msg;
err_t err;
/* 請求斷開連接 */
msg.function = do_disconnect;
msg.msg.conn = conn;
err = TCPIP_APIMSG(&msg);
NETCONN_SET_SAFE_ERR(conn, err);
return err;
}
/* 開始偵聽 */
err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
{
struct api_msg msg;
err_t err;
/* 請求偵聽 */
msg.function = do_listen;
msg.msg.conn = conn;
err = TCPIP_APIMSG(&msg);
NETCONN_SET_SAFE_ERR(conn, err);
return err;
}
/* 接受連接 */
err_t netconn_accept(struct netconn *conn, struct netconn **new_conn)
{
struct netconn *newconn;
err_t err;
*new_conn = NULL;
err = conn->last_err;
if (ERR_IS_FATAL(err))
{
return err;
}
/* 等待連接 */
sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
/* 調用連接API回調函數 */
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
if(newconn == NULL)
{
NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
return ERR_ABRT;
}
*new_conn = newconn;
return ERR_OK;
}
/* 接收數據 */
static err_t netconn_recv_data(struct netconn *conn, void **new_buf)
{
void *buf = NULL;
u16_t len;
err_t err;
struct api_msg msg;
*new_buf = NULL;
err = conn->last_err;
if(ERR_IS_FATAL(err))
{
return err;
}
/* 等待數據 */
sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
/* TCP */
if(conn->type == NETCONN_TCP)
{
/* 自動接收 */
if(!netconn_get_noautorecved(conn) || (buf == NULL))
{
/* 請求接收,更新窗口 */
msg.function = do_recv;
msg.msg.conn = conn;
if(buf != NULL)
{
msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
}
else
{
msg.msg.msg.r.len = 1;
}
TCPIP_APIMSG(&msg);
}
if(buf == NULL)
{
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
return ERR_CLSD;
}
len = ((struct pbuf *)buf)->tot_len;
}
/* 非TCP */
else
{
len = netbuf_len((struct netbuf *)buf);
}
/* 調用連接API回調函數 */
API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
*new_buf = buf;
return ERR_OK;
}
/* 接收數據 */
err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
{
return netconn_recv_data(conn, (void **)new_buf);
}
/* 接收數據並將數據封裝到netbuf */
err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf)
{
struct netbuf *buf = NULL;
err_t err;
*new_buf = NULL;
if (conn->type == NETCONN_TCP)
{
struct pbuf *p = NULL;
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
if(buf == NULL)
{
NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
return ERR_MEM;
}
err = netconn_recv_data(conn, (void **)&p);
if(err != ERR_OK)
{
memp_free(MEMP_NETBUF, buf);
return err;
}
buf->p = p;
buf->ptr = p;
buf->port = 0;
ip_addr_set_any(&buf->addr);
*new_buf = buf;
return ERR_OK;
}
else
{
return netconn_recv_data(conn, (void **)new_buf);
}
}
/* 更新接收窗口 */
void netconn_recved(struct netconn *conn, u32_t length)
{
if((conn != NULL) && (conn->type == NETCONN_TCP) && (netconn_get_noautorecved(conn)))
{
struct api_msg msg;
/* 請求接收,更新窗口 */
msg.function = do_recv;
msg.msg.conn = conn;
msg.msg.msg.r.len = length;
TCPIP_APIMSG(&msg);
}
}
/* UDP或RAW發送數據 */
err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
{
if(buf != NULL)
{
ip_addr_set(&buf->addr, addr);
buf->port = port;
return netconn_send(conn, buf);
}
return ERR_VAL;
}
/* UDP或RAW發送數據 */
err_t netconn_send(struct netconn *conn, struct netbuf *buf)
{
struct api_msg msg;
err_t err;
/* 請求發送數據 */
msg.function = do_send;
msg.msg.conn = conn;
msg.msg.msg.b = buf;
err = TCPIP_APIMSG(&msg);
NETCONN_SET_SAFE_ERR(conn, err);
return err;
}
/* TCP發送數據 */
err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags, size_t *bytes_written)
{
struct api_msg msg;
err_t err;
u8_t dontblock;
if(size == 0)
{
return ERR_OK;
}
dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
if(dontblock && !bytes_written)
{
return ERR_VAL;
}
/* 請求TCP發送數據 */
msg.function = do_write;
msg.msg.conn = conn;
msg.msg.msg.w.dataptr = dataptr;
msg.msg.msg.w.apiflags = apiflags;
msg.msg.msg.w.len = size;
err = TCPIP_APIMSG(&msg);
if((err == ERR_OK) && (bytes_written != NULL))
{
/* 非阻塞 */
if(dontblock)
{
*bytes_written = msg.msg.msg.w.len;
}
/* 阻塞型 */
else
{
*bytes_written = size;
}
}
NETCONN_SET_SAFE_ERR(conn, err);
return err;
}
/* 關閉連接 */
static err_t netconn_close_shutdown(struct netconn *conn, u8_t how)
{
struct api_msg msg;
err_t err;
/* 請求關閉連接 */
msg.function = do_close;
msg.msg.conn = conn;
msg.msg.msg.sd.shut = how;
err = tcpip_apimsg(&msg);
NETCONN_SET_SAFE_ERR(conn, err);
return err;
}
/* 完全關閉連接 */
err_t netconn_close(struct netconn *conn)
{
return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
}
/* 關閉連接方向 */
err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
{
return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
}