📄 api_msg.c
字号:
#if LWIP_RAW case NETCONN_RAW: msg->conn->pcb.raw = raw_new(msg->msg.n.proto); if(msg->conn->pcb.raw == NULL) { msg->conn->err = ERR_MEM; break; } raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); break;#endif /* LWIP_RAW */#if LWIP_UDP case NETCONN_UDP: msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; break; }#if LWIP_UDPLITE if (msg->conn->type==NETCONN_UDPLITE) { udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); }#endif /* LWIP_UDPLITE */ if (msg->conn->type==NETCONN_UDPNOCHKSUM) { udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); } udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break;#endif /* LWIP_UDP */#if LWIP_TCP case NETCONN_TCP: msg->conn->pcb.tcp = tcp_new(); if(msg->conn->pcb.tcp == NULL) { msg->conn->err = ERR_MEM; break; } setup_tcp(msg->conn); break;#endif /* LWIP_TCP */ default: /* Unsupported netconn type, e.g. protocol disabled */ msg->conn->err = ERR_VAL; break; } return msg->conn->err;}/** * Create a new pcb of a specific type inside a netconn. * Called from netconn_new_with_proto_and_callback. * * @param msg the api_msg_msg describing the connection type */voiddo_newconn(struct api_msg_msg *msg){ if(msg->conn->pcb.tcp == NULL) { pcb_new(msg); } /* Else? This "new" connection already has a PCB allocated. */ /* Is this an error condition? Should it be deleted? */ /* We currently just are happy and return. */ TCPIP_APIMSG_ACK(msg);}/** * Create a new netconn (of a specific type) that has a callback function. * The corresponding pcb is NOT created! * * @param t the type of 'connection' to create (@see enum netconn_type) * @param proto the IP protocol for RAW IP pcbs * @param callback a function to call on status changes (RX available, TX'ed) * @return a newly allocated struct netconn or * NULL on memory error */struct netconn*netconn_alloc(enum netconn_type t, netconn_callback callback){ struct netconn *conn; int size; conn = memp_malloc(MEMP_NETCONN); if (conn == NULL) { return NULL; } conn->err = ERR_OK; conn->type = t; conn->pcb.tcp = NULL;#if (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_UDP_RECVMBOX_SIZE) && \ (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_TCP_RECVMBOX_SIZE) size = DEFAULT_RAW_RECVMBOX_SIZE;#else switch(NETCONNTYPE_GROUP(t)) {#if LWIP_RAW case NETCONN_RAW: size = DEFAULT_RAW_RECVMBOX_SIZE; break;#endif /* LWIP_RAW */#if LWIP_UDP case NETCONN_UDP: size = DEFAULT_UDP_RECVMBOX_SIZE; break;#endif /* LWIP_UDP */#if LWIP_TCP case NETCONN_TCP: size = DEFAULT_TCP_RECVMBOX_SIZE; break;#endif /* LWIP_TCP */ default: LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); break; }#endif if ((conn->op_completed = sys_sem_new(0)) == SYS_SEM_NULL) { memp_free(MEMP_NETCONN, conn); return NULL; } if ((conn->recvmbox = sys_mbox_new(size)) == SYS_MBOX_NULL) { sys_sem_free(conn->op_completed); memp_free(MEMP_NETCONN, conn); return NULL; } conn->acceptmbox = SYS_MBOX_NULL; conn->state = NETCONN_NONE; /* initialize socket to -1 since 0 is a valid socket */ conn->socket = -1; conn->callback = callback; conn->recv_avail = 0;#if LWIP_TCP conn->write_msg = NULL; conn->write_offset = 0;#if LWIP_TCPIP_CORE_LOCKING conn->write_delayed = 0;#endif /* LWIP_TCPIP_CORE_LOCKING */#endif /* LWIP_TCP */#if LWIP_SO_RCVTIMEO conn->recv_timeout = 0;#endif /* LWIP_SO_RCVTIMEO */#if LWIP_SO_RCVBUF conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;#endif /* LWIP_SO_RCVBUF */ return conn;}/** * Delete a netconn and all its resources. * The pcb is NOT freed (since we might not be in the right thread context do this). * * @param conn the netconn to free */voidnetconn_free(struct netconn *conn){ void *mem; LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); /* Drain the recvmbox. */ if (conn->recvmbox != SYS_MBOX_NULL) { while (sys_mbox_tryfetch(conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { if (conn->type == NETCONN_TCP) { if(mem != NULL) { pbuf_free((struct pbuf *)mem); } } else { netbuf_delete((struct netbuf *)mem); } } sys_mbox_free(conn->recvmbox); conn->recvmbox = SYS_MBOX_NULL; } /* Drain the acceptmbox. */ if (conn->acceptmbox != SYS_MBOX_NULL) { while (sys_mbox_tryfetch(conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { netconn_delete((struct netconn *)mem); } sys_mbox_free(conn->acceptmbox); conn->acceptmbox = SYS_MBOX_NULL; } sys_sem_free(conn->op_completed); conn->op_completed = SYS_SEM_NULL; memp_free(MEMP_NETCONN, conn);}#if LWIP_TCP/** * Internal helper function to close a TCP netconn: since this sometimes * doesn't work at the first attempt, this function is called from multiple * places. * * @param conn the TCP netconn to close */static voiddo_close_internal(struct netconn *conn){ err_t err; LWIP_ASSERT("invalid conn", (conn != NULL)); LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP)); LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); /* Set back some callback pointers */ tcp_arg(conn->pcb.tcp, NULL); if (conn->pcb.tcp->state == LISTEN) { tcp_accept(conn->pcb.tcp, NULL); } else { tcp_recv(conn->pcb.tcp, NULL); tcp_accept(conn->pcb.tcp, NULL); /* some callbacks have to be reset if tcp_close is not successful */ tcp_sent(conn->pcb.tcp, NULL); tcp_poll(conn->pcb.tcp, NULL, 4); tcp_err(conn->pcb.tcp, NULL); } /* Try to close the connection */ err = tcp_close(conn->pcb.tcp); if (err == ERR_OK) { /* Closing succeeded */ conn->state = NETCONN_NONE; /* Set back some callback pointers as conn is going away */ conn->pcb.tcp = NULL; conn->err = ERR_OK; /* Trigger select() in socket layer. This send should something else so the errorfd is set, not the read and write fd! */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); /* wake up the application task */ sys_sem_signal(conn->op_completed); } else { /* Closing failed, restore some of the callbacks */ /* Closing of listen pcb will never fail! */ LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); 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); } /* If closing didn't succeed, we get called again either from poll_tcp or from sent_tcp */}#endif /* LWIP_TCP *//** * Delete the pcb inside a netconn. * Called from netconn_delete. * * @param msg the api_msg_msg pointing to the connection */voiddo_delconn(struct api_msg_msg *msg){ if (msg->conn->pcb.tcp != NULL) { switch (NETCONNTYPE_GROUP(msg->conn->type)) {#if LWIP_RAW case NETCONN_RAW: raw_remove(msg->conn->pcb.raw); break;#endif /* LWIP_RAW */#if LWIP_UDP case NETCONN_UDP: msg->conn->pcb.udp->recv_arg = NULL; udp_remove(msg->conn->pcb.udp); break;#endif /* LWIP_UDP */#if LWIP_TCP case NETCONN_TCP: msg->conn->state = NETCONN_CLOSE; do_close_internal(msg->conn); /* API_EVENT is called inside do_close_internal, before releasing the application thread, so we can return at this point! */ return;#endif /* LWIP_TCP */ default: break; } } /* tcp netconns don't come here! */ /* Trigger select() in socket layer. This send should something else so the errorfd is set, not the read and write fd! */ API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); if (msg->conn->op_completed != SYS_SEM_NULL) { sys_sem_signal(msg->conn->op_completed); }}/** * Bind a pcb contained in a netconn * Called from netconn_bind. * * @param msg the api_msg_msg pointing to the connection and containing * the IP address and port to bind to */voiddo_bind(struct api_msg_msg *msg){ if (!ERR_IS_FATAL(msg->conn->err)) { if (msg->conn->pcb.tcp != NULL) { switch (NETCONNTYPE_GROUP(msg->conn->type)) {#if LWIP_RAW case NETCONN_RAW: msg->conn->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr); break;#endif /* LWIP_RAW */#if LWIP_UDP case NETCONN_UDP: msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); break;#endif /* LWIP_UDP */#if LWIP_TCP case NETCONN_TCP: msg->conn->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port); break;#endif /* LWIP_TCP */ default: break; } } else { /* msg->conn->pcb is NULL */ msg->conn->err = ERR_VAL; } } TCPIP_APIMSG_ACK(msg);}#if LWIP_TCP/** * TCP callback function if a connection (opened by tcp_connect/do_connect) has * been established (or reset by the remote host). * * @see tcp.h (struct tcp_pcb.connected) for parameters and return values */static err_tdo_connected(void *arg, struct tcp_pcb *pcb, err_t err){ struct netconn *conn; LWIP_UNUSED_ARG(pcb); conn = arg; if (conn == NULL) { return ERR_VAL; } conn->err = err; if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) { setup_tcp(conn); } conn->state = NETCONN_NONE; sys_sem_signal(conn->op_completed); return ERR_OK;}#endif /* LWIP_TCP *//** * Connect a pcb contained inside a netconn * Called from netconn_connect. * * @param msg the api_msg_msg pointing to the connection and containing * the IP address and port to connect to */voiddo_connect(struct api_msg_msg *msg){ if (msg->conn->pcb.tcp == NULL) { sys_sem_signal(msg->conn->op_completed); return; } switch (NETCONNTYPE_GROUP(msg->conn->type)) {#if LWIP_RAW case NETCONN_RAW: msg->conn->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr); sys_sem_signal(msg->conn->op_completed); break;#endif /* LWIP_RAW */#if LWIP_UDP case NETCONN_UDP: msg->conn->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); sys_sem_signal(msg->conn->op_completed); break;#endif /* LWIP_UDP */#if LWIP_TCP case NETCONN_TCP: msg->conn->state = NETCONN_CONNECT; setup_tcp(msg->conn); msg->conn->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port, do_connected); /* sys_sem_signal() is called from do_connected (or err_tcp()), * when the connection is established! */ break;#endif /* LWIP_TCP */ default: LWIP_ERROR("Invalid netconn type", 0, do{ msg->conn->err = ERR_VAL; sys_sem_signal(msg->conn->op_completed); }while(0)); break; }}/** * Connect a pcb contained inside a netconn * Only used for UDP netconns. * Called from netconn_disconnect. * * @param msg the api_msg_msg pointing to the connection to disconnect
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -