60#define NETCONN_TCP_POLL_INTERVAL 2
62#define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \
63 netconn_set_flags(conn, NETCONN_FLAG_IN_NONBLOCKING_CONNECT); \
65 netconn_clear_flags(conn, NETCONN_FLAG_IN_NONBLOCKING_CONNECT); }} while(0)
66#define IN_NONBLOCKING_CONNECT(conn) netconn_is_flag_set(conn, NETCONN_FLAG_IN_NONBLOCKING_CONNECT)
68#if LWIP_NETCONN_FULLDUPLEX
69#define NETCONN_MBOX_VALID(conn, mbox) (sys_mbox_valid(mbox) && ((conn->flags & NETCONN_FLAG_MBOXINVALID) == 0))
71#define NETCONN_MBOX_VALID(conn, mbox) sys_mbox_valid(mbox)
76#if LWIP_TCPIP_CORE_LOCKING
77#define WRITE_DELAYED , 1
78#define WRITE_DELAYED_PARAM , u8_t delayed
81#define WRITE_DELAYED_PARAM
83static err_t lwip_netconn_do_writemore(
struct netconn *conn WRITE_DELAYED_PARAM);
84static err_t lwip_netconn_do_close_internal(
struct netconn *conn WRITE_DELAYED_PARAM);
87static void netconn_drain(
struct netconn *conn);
89#if LWIP_TCPIP_CORE_LOCKING
90#define TCPIP_APIMSG_ACK(m)
92#define TCPIP_APIMSG_ACK(m) do { sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0)
95#if LWIP_NETCONN_FULLDUPLEX
96static const u8_t netconn_deleted = 0;
99lwip_netconn_is_deallocated_msg(
void *msg)
101 if (msg == &netconn_deleted) {
109static const u8_t netconn_aborted = 0;
110static const u8_t netconn_reset = 0;
111static const u8_t netconn_closed = 0;
115lwip_netconn_err_to_msg(err_t err)
125 LWIP_ASSERT(
"unhandled error", err ==
ERR_OK);
131lwip_netconn_is_err_msg(
void *msg, err_t *err)
133 LWIP_ASSERT(
"err != NULL", err != NULL);
135 if (msg == &netconn_aborted) {
138 }
else if (msg == &netconn_reset) {
141 }
else if (msg == &netconn_closed) {
159recv_raw(
void *arg,
struct raw_pcb *pcb,
struct pbuf *p,
160 const ip_addr_t *addr)
164 struct netconn *conn;
167 conn = (
struct netconn *)arg;
169 if ((conn != NULL) && NETCONN_MBOX_VALID(conn, &conn->recvmbox)) {
172 SYS_ARCH_GET(conn->recv_avail, recv_avail);
173 if ((recv_avail + (
int)(p->tot_len)) > conn->recv_bufsize) {
190 buf->port = pcb->protocol;
198 SYS_ARCH_INC(conn->recv_avail, len);
201 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
218recv_udp(
void *arg,
struct udp_pcb *pcb,
struct pbuf *p,
219 const ip_addr_t *addr, u16_t port)
222 struct netconn *conn;
230 LWIP_ASSERT(
"recv_udp must have a pcb argument", pcb != NULL);
231 LWIP_ASSERT(
"recv_udp must have an argument", arg != NULL);
232 conn = (
struct netconn *)arg;
239 LWIP_ASSERT(
"recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
242 SYS_ARCH_GET(conn->recv_avail, recv_avail);
243 if (!NETCONN_MBOX_VALID(conn, &conn->recvmbox) ||
244 ((recv_avail + (
int)(p->tot_len)) > conn->recv_bufsize)) {
246 if (!NETCONN_MBOX_VALID(conn, &conn->recvmbox)) {
259 ip_addr_set(&buf->addr, addr);
261#if LWIP_NETBUF_RECVINFO
262 if (conn->flags & NETCONN_FLAG_PKTINFO) {
264 const struct udp_hdr *udphdr = (
const struct udp_hdr *)ip_next_header_ptr();
265 buf->flags = NETBUF_FLAG_DESTADDR;
267 buf->toport_chksum = udphdr->dest;
276 LWIP_DEBUGF(
API_MSG_DEBUG, (
"recv_udp: sys_mbox_trypost failed, err=%d\n", err));
280 SYS_ARCH_INC(conn->recv_avail, len);
283 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
296recv_tcp(
void *arg,
struct tcp_pcb *pcb,
struct pbuf *p, err_t err)
298 struct netconn *conn;
303 LWIP_ASSERT(
"recv_tcp must have a pcb argument", pcb != NULL);
304 LWIP_ASSERT(
"recv_tcp must have an argument", arg != NULL);
305 LWIP_ASSERT(
"err != ERR_OK unhandled", err ==
ERR_OK);
307 conn = (
struct netconn *)arg;
312 LWIP_ASSERT(
"recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
314 if (!NETCONN_MBOX_VALID(conn, &conn->recvmbox)) {
317 tcp_recved(pcb, p->tot_len);
339 SYS_ARCH_INC(conn->recv_avail, len);
342 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
360poll_tcp(
void *arg,
struct tcp_pcb *pcb)
362 struct netconn *conn = (
struct netconn *)arg;
365 LWIP_ASSERT(
"conn != NULL", (conn != NULL));
367 if (conn->state == NETCONN_WRITE) {
368 lwip_netconn_do_writemore(conn WRITE_DELAYED);
369 }
else if (conn->state == NETCONN_CLOSE) {
370#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER
371 if (conn->current_msg && conn->current_msg->msg.sd.polls_left) {
372 conn->current_msg->msg.sd.polls_left--;
375 lwip_netconn_do_close_internal(conn WRITE_DELAYED);
380 if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
383 if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) >
TCP_SNDLOWAT) &&
385 netconn_clear_flags(conn, NETCONN_FLAG_CHECK_WRITESPACE);
386 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
401sent_tcp(
void *arg,
struct tcp_pcb *pcb, u16_t len)
403 struct netconn *conn = (
struct netconn *)arg;
406 LWIP_ASSERT(
"conn != NULL", (conn != NULL));
409 if (conn->state == NETCONN_WRITE) {
410 lwip_netconn_do_writemore(conn WRITE_DELAYED);
411 }
else if (conn->state == NETCONN_CLOSE) {
412 lwip_netconn_do_close_internal(conn WRITE_DELAYED);
417 if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) >
TCP_SNDLOWAT) &&
419 netconn_clear_flags(conn, NETCONN_FLAG_CHECK_WRITESPACE);
420 API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
435err_tcp(
void *arg, err_t err)
437 struct netconn *conn;
438 enum netconn_state old_state;
442 conn = (
struct netconn *)arg;
443 LWIP_ASSERT(
"conn != NULL", (conn != NULL));
445 SYS_ARCH_PROTECT(lev);
448 conn->pcb.tcp = NULL;
450 conn->pending_err = err;
452 conn->flags |= NETCONN_FLAG_MBOXCLOSED;
455 old_state = conn->state;
456 conn->state = NETCONN_NONE;
458 SYS_ARCH_UNPROTECT(lev);
461 API_EVENT(conn, NETCONN_EVT_ERROR, 0);
464 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
465 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
467 mbox_msg = lwip_netconn_err_to_msg(err);
469 if (NETCONN_MBOX_VALID(conn, &conn->recvmbox)) {
474 if (NETCONN_MBOX_VALID(conn, &conn->acceptmbox)) {
479 if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
480 (old_state == NETCONN_CONNECT)) {
483 int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn);
484 SET_NONBLOCKING_CONNECT(conn, 0);
486 if (!was_nonblocking_connect) {
487 sys_sem_t *op_completed_sem;
489 LWIP_ASSERT(
"conn->current_msg != NULL", conn->current_msg != NULL);
490 if (old_state == NETCONN_CLOSE) {
492 conn->current_msg->err =
ERR_OK;
495 conn->current_msg->err = err;
497 op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
498 LWIP_ASSERT(
"invalid op_completed_sem",
sys_sem_valid(op_completed_sem));
499 conn->current_msg = NULL;
506 LWIP_ASSERT(
"conn->current_msg == NULL", conn->current_msg == NULL);
517setup_tcp(
struct netconn *conn)
523 tcp_recv(pcb, recv_tcp);
524 tcp_sent(pcb, sent_tcp);
525 tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL);
526 tcp_err(pcb, err_tcp);
536accept_function(
void *arg,
struct tcp_pcb *newpcb, err_t err)
538 struct netconn *newconn;
539 struct netconn *conn = (
struct netconn *)arg;
544 if (!NETCONN_MBOX_VALID(conn, &conn->acceptmbox)) {
545 LWIP_DEBUGF(
API_MSG_DEBUG, (
"accept_function: acceptmbox already deleted\n"));
549 if (newpcb == NULL) {
553 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
557 LWIP_ASSERT(
"expect newpcb == NULL or err == ERR_OK", err ==
ERR_OK);
560 LWIP_DEBUGF(
API_MSG_DEBUG, (
"accept_function: newpcb->state: %s\n", tcp_debug_state_str(newpcb->state)));
564 newconn = netconn_alloc(conn->type, conn->callback);
565 if (newconn == NULL) {
569 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
573 newconn->pcb.tcp = newpcb;
577 tcp_backlog_delayed(newpcb);
583 struct tcp_pcb *pcb = newconn->pcb.tcp;
587 tcp_poll(pcb, NULL, 0);
590 newconn->pcb.tcp = NULL;
594 netconn_free(newconn);
598 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
612pcb_new(
struct api_msg *msg)
616 LWIP_ASSERT(
"pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
618#if LWIP_IPV6 && LWIP_IPV4
620 if (NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) {
626 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
629 msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto);
630 if (msg->conn->pcb.raw != NULL) {
633 if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) {
634 msg->conn->pcb.raw->chksum_reqd = 1;
635 msg->conn->pcb.raw->chksum_offset = 2;
638 raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
644 msg->conn->pcb.udp = udp_new_ip_type(iptype);
645 if (msg->conn->pcb.udp != NULL) {
647 if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) {
648 udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
651 if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) {
652 udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
654 udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
660 msg->conn->pcb.tcp = tcp_new_ip_type(iptype);
661 if (msg->conn->pcb.tcp != NULL) {
662 setup_tcp(msg->conn);
671 if (msg->conn->pcb.ip == NULL) {
683lwip_netconn_do_newconn(
void *m)
685 struct api_msg *msg = (
struct api_msg *)m;
688 if (msg->conn->pcb.tcp == NULL) {
695 TCPIP_APIMSG_ACK(msg);
708netconn_alloc(
enum netconn_type t, netconn_callback callback)
710 struct netconn *conn;
714 conn = (
struct netconn *)
memp_malloc(MEMP_NETCONN);
719 conn->pending_err =
ERR_OK;
721 conn->pcb.tcp = NULL;
722#if LWIP_NETCONN_FULLDUPLEX
723 conn->mbox_threads_waiting = 0;
727 switch (NETCONNTYPE_GROUP(t)) {
736#if LWIP_NETBUF_RECVINFO
737 init_flags |= NETCONN_FLAG_PKTINFO;
747 LWIP_ASSERT(
"netconn_alloc: undefined netconn_type", 0);
748 goto free_and_return;
752 goto free_and_return;
754#if !LWIP_NETCONN_SEM_PER_THREAD
757 goto free_and_return;
764 conn->state = NETCONN_NONE;
766 conn->callback_arg.socket = -1;
767 conn->callback = callback;
769 conn->current_msg = NULL;
772 conn->send_timeout = 0;
775 conn->recv_timeout = 0;
779 conn->recv_avail = 0;
784 conn->flags = init_flags;
798netconn_free(
struct netconn *conn)
800 LWIP_ASSERT(
"PCB must be deallocated outside this function", conn->pcb.tcp == NULL);
802#if LWIP_NETCONN_FULLDUPLEX
807 LWIP_ASSERT(
"recvmbox must be deallocated before calling this function",
810 LWIP_ASSERT(
"acceptmbox must be deallocated before calling this function",
814#if !LWIP_NETCONN_SEM_PER_THREAD
831netconn_drain(
struct netconn *conn)
837#if LWIP_NETCONN_FULLDUPLEX
838 LWIP_ASSERT(
"netconn marked closed", conn->flags & NETCONN_FLAG_MBOXINVALID);
844#if LWIP_NETCONN_FULLDUPLEX
845 if (!lwip_netconn_is_deallocated_msg(
mem))
849 if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
851 if (!lwip_netconn_is_err_msg(
mem, &err)) {
857 netbuf_delete((
struct netbuf *)
mem);
869#if LWIP_NETCONN_FULLDUPLEX
870 if (!lwip_netconn_is_deallocated_msg(
mem))
874 if (!lwip_netconn_is_err_msg(
mem, &err)) {
875 struct netconn *newconn = (
struct netconn *)
mem;
879 netconn_drain(newconn);
880 if (newconn->pcb.tcp != NULL) {
881 tcp_abort(newconn->pcb.tcp);
882 newconn->pcb.tcp = NULL;
884 netconn_free(newconn);
894#if LWIP_NETCONN_FULLDUPLEX
896netconn_mark_mbox_invalid(
struct netconn *conn)
902 conn->flags |= NETCONN_FLAG_MBOXINVALID;
904 SYS_ARCH_LOCKED(num_waiting = conn->mbox_threads_waiting);
905 for (i = 0; i < num_waiting; i++) {
924lwip_netconn_do_close_internal(
struct netconn *conn WRITE_DELAYED_PARAM)
927 u8_t shut, shut_rx, shut_tx, shut_close;
928 u8_t close_finished = 0;
929 struct tcp_pcb *tpcb;
931 u8_t linger_wait_required = 0;
934 LWIP_ASSERT(
"invalid conn", (conn != NULL));
935 LWIP_ASSERT(
"this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP));
936 LWIP_ASSERT(
"conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
937 LWIP_ASSERT(
"pcb already closed", (conn->pcb.tcp != NULL));
938 LWIP_ASSERT(
"conn->current_msg != NULL", conn->current_msg != NULL);
940 tpcb = conn->pcb.tcp;
941 shut = conn->current_msg->msg.sd.shut;
942 shut_rx = shut & NETCONN_SHUT_RD;
943 shut_tx = shut & NETCONN_SHUT_WR;
946 if (shut == NETCONN_SHUT_RDWR) {
948 }
else if (shut_rx &&
949 ((tpcb->state == FIN_WAIT_1) ||
950 (tpcb->state == FIN_WAIT_2) ||
951 (tpcb->state == CLOSING))) {
953 }
else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) {
963 if (tpcb->state == LISTEN) {
964 tcp_accept(tpcb, NULL);
968 tcp_recv(tpcb, NULL);
969 tcp_accept(tpcb, NULL);
972 tcp_sent(tpcb, NULL);
975 tcp_poll(tpcb, NULL, 0);
985 if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) {
986 if ((conn->linger == 0)) {
990 }
else if (conn->linger > 0) {
992 if (netconn_is_nonblocking(conn)) {
995 }
else if ((s32_t)(
sys_now() - conn->current_msg->msg.sd.time_started) >=
996 (conn->linger * 1000)) {
1003 linger_wait_required = 1;
1007 if ((err ==
ERR_OK) && (tpcb != NULL))
1010 err = tcp_close(tpcb);
1013 err = tcp_shutdown(tpcb, shut_rx, shut_tx);
1018 if (linger_wait_required) {
1031#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
1034 if (conn->send_timeout > 0) {
1035 close_timeout = conn->send_timeout;
1039 if (conn->linger >= 0) {
1041 close_timeout = conn->linger * 1000U;
1044 if ((s32_t)(
sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) {
1046 if (conn->current_msg->msg.sd.polls_left == 0) {
1060 if (close_finished) {
1062 sys_sem_t *op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
1063 conn->current_msg->err = err;
1064 conn->current_msg = NULL;
1065 conn->state = NETCONN_NONE;
1069 conn->pcb.tcp = NULL;
1072 API_EVENT(conn, NETCONN_EVT_ERROR, 0);
1075 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
1078 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
1081#if LWIP_TCPIP_CORE_LOCKING
1090 if (!close_finished) {
1093 LWIP_ASSERT(
"Closing a listen pcb may not fail!", (tpcb->state != LISTEN));
1095 tcp_sent(tpcb, sent_tcp);
1098 tcp_poll(tpcb, poll_tcp, 1);
1099 tcp_err(tpcb, err_tcp);
1100 tcp_arg(tpcb, conn);
1105 LWIP_ASSERT(
"err != ERR_OK", err !=
ERR_OK);
1117lwip_netconn_do_delconn(
void *m)
1119 struct api_msg *msg = (
struct api_msg *)m;
1121 enum netconn_state state = msg->conn->state;
1122 LWIP_ASSERT(
"netconn state error",
1123 (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP));
1124#if LWIP_NETCONN_FULLDUPLEX
1126 if (state != NETCONN_NONE) {
1127 if ((state == NETCONN_WRITE) ||
1128 ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) {
1130 sys_sem_t *op_completed_sem;
1131 LWIP_ASSERT(
"msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
1132 op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
1133 msg->conn->current_msg->err =
ERR_CLSD;
1134 msg->conn->current_msg = NULL;
1135 msg->conn->state = NETCONN_NONE;
1140 if (((state != NETCONN_NONE) &&
1141 (state != NETCONN_LISTEN) &&
1142 (state != NETCONN_CONNECT)) ||
1143 ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) {
1150 LWIP_ASSERT(
"blocking connect in progress",
1151 (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn));
1153#if LWIP_NETCONN_FULLDUPLEX
1155 netconn_mark_mbox_invalid(msg->conn);
1157 netconn_drain(msg->conn);
1160 if (msg->conn->pcb.tcp != NULL) {
1162 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
1165 raw_remove(msg->conn->pcb.raw);
1170 msg->conn->pcb.udp->recv_arg = NULL;
1171 udp_remove(msg->conn->pcb.udp);
1176 LWIP_ASSERT(
"already writing or closing", msg->conn->current_msg == NULL);
1177 msg->conn->state = NETCONN_CLOSE;
1178 msg->msg.sd.shut = NETCONN_SHUT_RDWR;
1179 msg->conn->current_msg = msg;
1180#if LWIP_TCPIP_CORE_LOCKING
1181 if (lwip_netconn_do_close_internal(msg->conn, 0) !=
ERR_OK) {
1182 LWIP_ASSERT(
"state!", msg->conn->state == NETCONN_CLOSE);
1183 UNLOCK_TCPIP_CORE();
1186 LWIP_ASSERT(
"state!", msg->conn->state == NETCONN_NONE);
1189 lwip_netconn_do_close_internal(msg->conn);
1198 msg->conn->pcb.tcp = NULL;
1204 API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
1205 API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
1208 TCPIP_APIMSG_ACK(msg);
1220lwip_netconn_do_bind(
void *m)
1222 struct api_msg *msg = (
struct api_msg *)m;
1225 if (msg->conn->pcb.tcp != NULL) {
1226 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
1229 err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr));
1234 err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
1239 err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
1250 TCPIP_APIMSG_ACK(msg);
1260lwip_netconn_do_bind_if(
void *m)
1263 struct api_msg *msg = (
struct api_msg *)m;
1268 if ((
netif != NULL) && (msg->conn->pcb.tcp != NULL)) {
1270 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
1273 raw_bind_netif(msg->conn->pcb.raw,
netif);
1278 udp_bind_netif(msg->conn->pcb.udp,
netif);
1283 tcp_bind_netif(msg->conn->pcb.tcp,
netif);
1294 TCPIP_APIMSG_ACK(msg);
1305lwip_netconn_do_connected(
void *arg,
struct tcp_pcb *pcb, err_t err)
1307 struct netconn *conn;
1309 sys_sem_t *op_completed_sem = NULL;
1313 conn = (
struct netconn *)arg;
1319 LWIP_ASSERT(
"conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT);
1320 LWIP_ASSERT(
"(conn->current_msg != NULL) || conn->in_non_blocking_connect",
1321 (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn));
1323 if (conn->current_msg != NULL) {
1324 conn->current_msg->err = err;
1325 op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
1327 if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err ==
ERR_OK)) {
1330 was_blocking = !IN_NONBLOCKING_CONNECT(conn);
1331 SET_NONBLOCKING_CONNECT(conn, 0);
1332 LWIP_ASSERT(
"blocking connect state error",
1333 (was_blocking && op_completed_sem != NULL) ||
1334 (!was_blocking && op_completed_sem == NULL));
1335 conn->current_msg = NULL;
1336 conn->state = NETCONN_NONE;
1337 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
1354lwip_netconn_do_connect(
void *m)
1356 struct api_msg *msg = (
struct api_msg *)m;
1359 if (msg->conn->pcb.tcp == NULL) {
1363 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
1366 err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr));
1371 err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
1377 if (msg->conn->state == NETCONN_CONNECT) {
1379 }
else if (msg->conn->state != NETCONN_NONE) {
1382 setup_tcp(msg->conn);
1383 err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr),
1384 msg->msg.bc.port, lwip_netconn_do_connected);
1386 u8_t non_blocking = netconn_is_nonblocking(msg->conn);
1387 msg->conn->state = NETCONN_CONNECT;
1388 SET_NONBLOCKING_CONNECT(msg->conn, non_blocking);
1392 msg->conn->current_msg = msg;
1395#if LWIP_TCPIP_CORE_LOCKING
1396 LWIP_ASSERT(
"state!", msg->conn->state == NETCONN_CONNECT);
1397 UNLOCK_TCPIP_CORE();
1400 LWIP_ASSERT(
"state!", msg->conn->state != NETCONN_CONNECT);
1409 LWIP_ERROR(
"Invalid netconn type", 0,
do {
1418 TCPIP_APIMSG_ACK(msg);
1429lwip_netconn_do_disconnect(
void *m)
1431 struct api_msg *msg = (
struct api_msg *)m;
1434 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
1435 udp_disconnect(msg->conn->pcb.udp);
1442 TCPIP_APIMSG_ACK(msg);
1453lwip_netconn_do_listen(
void *m)
1455 struct api_msg *msg = (
struct api_msg *)m;
1458 if (msg->conn->pcb.tcp != NULL) {
1459 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
1460 if (msg->conn->state == NETCONN_NONE) {
1461 struct tcp_pcb *lpcb;
1462 if (msg->conn->pcb.tcp->state != CLOSED) {
1467#if TCP_LISTEN_BACKLOG
1468 backlog = msg->msg.lb.backlog;
1472#if LWIP_IPV4 && LWIP_IPV6
1476 if (ip_addr_eq(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) &&
1477 (netconn_get_ipv6only(msg->conn) == 0)) {
1484 lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err);
1500 msg->conn->state = NETCONN_LISTEN;
1501 msg->conn->pcb.tcp = lpcb;
1502 tcp_arg(msg->conn->pcb.tcp, msg->conn);
1503 tcp_accept(msg->conn->pcb.tcp, accept_function);
1507 msg->conn->pcb.tcp = NULL;
1511 }
else if (msg->conn->state == NETCONN_LISTEN) {
1514 tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog);
1525 TCPIP_APIMSG_ACK(msg);
1536lwip_netconn_do_send(
void *m)
1538 struct api_msg *msg = (
struct api_msg *)m;
1540 err_t err = netconn_err(msg->conn);
1542 if (msg->conn->pcb.tcp != NULL) {
1543 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
1546 if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
1547 err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
1549 err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
1555#if LWIP_CHECKSUM_ON_COPY
1556 if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
1557 err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
1558 msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
1560 err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p,
1561 &msg->msg.b->addr, msg->msg.b->port,
1562 msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
1565 if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
1566 err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
1568 err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port);
1582 TCPIP_APIMSG_ACK(msg);
1593lwip_netconn_do_recv(
void *m)
1595 struct api_msg *msg = (
struct api_msg *)m;
1598 if (msg->conn->pcb.tcp != NULL) {
1599 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
1600 size_t remaining = msg->msg.r.len;
1602 u16_t recved = (u16_t)((remaining > 0xffff) ? 0xffff : remaining);
1603 tcp_recved(msg->conn->pcb.tcp, recved);
1604 remaining -= recved;
1605 }
while (remaining != 0);
1608 TCPIP_APIMSG_ACK(msg);
1611#if TCP_LISTEN_BACKLOG
1618lwip_netconn_do_accepted(
void *m)
1620 struct api_msg *msg = (
struct api_msg *)m;
1623 if (msg->conn->pcb.tcp != NULL) {
1624 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
1625 tcp_backlog_accepted(msg->conn->pcb.tcp);
1628 TCPIP_APIMSG_ACK(msg);
1644lwip_netconn_do_writemore(
struct netconn *conn WRITE_DELAYED_PARAM)
1647 const void *dataptr;
1648 u16_t len, available;
1649 u8_t write_finished = 0;
1655 LWIP_ASSERT(
"conn != NULL", conn != NULL);
1656 LWIP_ASSERT(
"conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
1657 LWIP_ASSERT(
"conn->current_msg != NULL", conn->current_msg != NULL);
1658 LWIP_ASSERT(
"conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
1659 LWIP_ASSERT(
"conn->current_msg->msg.w.offset < conn->current_msg->msg.w.len",
1660 conn->current_msg->msg.w.offset < conn->current_msg->msg.w.len);
1661 LWIP_ASSERT(
"conn->current_msg->msg.w.vector_cnt > 0", conn->current_msg->msg.w.vector_cnt > 0);
1663 apiflags = conn->current_msg->msg.w.apiflags;
1664 dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
1667 if ((conn->send_timeout != 0) &&
1668 ((s32_t)(
sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) {
1670 if (conn->current_msg->msg.w.offset == 0) {
1681 dataptr = (
const u8_t *)conn->current_msg->msg.w.vector->ptr + conn->current_msg->msg.w.vector_off;
1682 diff = conn->current_msg->msg.w.vector->len - conn->current_msg->msg.w.vector_off;
1683 if (diff > 0xffffUL) {
1685 apiflags |= TCP_WRITE_FLAG_MORE;
1689 available = tcp_sndbuf(conn->pcb.tcp);
1690 if (available < len) {
1700 apiflags |= TCP_WRITE_FLAG_MORE;
1703 LWIP_ASSERT(
"lwip_netconn_do_writemore: invalid length!",
1704 ((conn->current_msg->msg.w.vector_off + len) <= conn->current_msg->msg.w.vector->len));
1709 if ((len == 0xffff && diff > 0xffffUL) ||
1710 (len == (u16_t)diff && conn->current_msg->msg.w.vector_cnt > 1)) {
1712 apiflags |= TCP_WRITE_FLAG_MORE;
1716 err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
1718 conn->current_msg->msg.w.offset += len;
1719 conn->current_msg->msg.w.vector_off += len;
1721 if (conn->current_msg->msg.w.vector_off == conn->current_msg->msg.w.vector->len) {
1722 conn->current_msg->msg.w.vector_cnt--;
1724 if (conn->current_msg->msg.w.vector_cnt > 0) {
1725 conn->current_msg->msg.w.vector++;
1726 conn->current_msg->msg.w.vector_off = 0;
1730 }
while (write_more && err ==
ERR_OK);
1734 if (dontblock && (conn->current_msg->msg.w.offset < conn->current_msg->msg.w.len)) {
1737 API_EVENT(conn, NETCONN_EVT_SENDMINUS, 0);
1738 conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE;
1739 }
else if ((tcp_sndbuf(conn->pcb.tcp) <=
TCP_SNDLOWAT) ||
1743 API_EVENT(conn, NETCONN_EVT_SENDMINUS, 0);
1749 if ((conn->current_msg->msg.w.offset == conn->current_msg->msg.w.len) || dontblock) {
1753 out_err = tcp_output(conn->pcb.tcp);
1768 err_t out_err = tcp_output(conn->pcb.tcp);
1775 }
else if (dontblock) {
1787 if (write_finished) {
1790 sys_sem_t *op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
1791 conn->current_msg->err = err;
1792 conn->current_msg = NULL;
1793 conn->state = NETCONN_NONE;
1794#if LWIP_TCPIP_CORE_LOCKING
1801#if LWIP_TCPIP_CORE_LOCKING
1817lwip_netconn_do_write(
void *m)
1819 struct api_msg *msg = (
struct api_msg *)m;
1821 err_t err = netconn_err(msg->conn);
1823 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
1825 if (msg->conn->state != NETCONN_NONE) {
1828 }
else if (msg->conn->pcb.tcp != NULL) {
1829 msg->conn->state = NETCONN_WRITE;
1831 LWIP_ASSERT(
"already writing or closing", msg->conn->current_msg == NULL);
1832 LWIP_ASSERT(
"msg->msg.w.len != 0", msg->msg.w.len != 0);
1833 msg->conn->current_msg = msg;
1834#if LWIP_TCPIP_CORE_LOCKING
1835 if (lwip_netconn_do_writemore(msg->conn, 0) !=
ERR_OK) {
1836 LWIP_ASSERT(
"state!", msg->conn->state == NETCONN_WRITE);
1837 UNLOCK_TCPIP_CORE();
1840 LWIP_ASSERT(
"state!", msg->conn->state != NETCONN_WRITE);
1843 lwip_netconn_do_writemore(msg->conn);
1854#if (LWIP_UDP || LWIP_RAW)
1861 TCPIP_APIMSG_ACK(msg);
1871lwip_netconn_do_getaddr(
void *m)
1873 struct api_msg *msg = (
struct api_msg *)m;
1875 if (msg->conn->pcb.ip != NULL) {
1876 if (msg->msg.ad.local) {
1877 ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
1878 msg->conn->pcb.ip->local_ip);
1880 ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
1881 msg->conn->pcb.ip->remote_ip);
1885 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
1888 if (msg->msg.ad.local) {
1889 API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
1898 if (msg->msg.ad.local) {
1899 API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
1901 if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
1904 API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
1911 if ((msg->msg.ad.local == 0) &&
1912 ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) {
1916 API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port);
1921 LWIP_ASSERT(
"invalid netconn_type", 0);
1927 TCPIP_APIMSG_ACK(msg);
1938lwip_netconn_do_close(
void *m)
1940 struct api_msg *msg = (
struct api_msg *)m;
1943 enum netconn_state state = msg->conn->state;
1946 if ((msg->conn->pcb.tcp != NULL) &&
1947 (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) &&
1948 ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) {
1950 if (state == NETCONN_CONNECT) {
1953 }
else if (state == NETCONN_WRITE) {
1954#if LWIP_NETCONN_FULLDUPLEX
1955 if (msg->msg.sd.shut & NETCONN_SHUT_WR) {
1957 sys_sem_t *write_completed_sem;
1958 LWIP_ASSERT(
"msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
1959 write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
1960 msg->conn->current_msg->err =
ERR_CLSD;
1961 msg->conn->current_msg = NULL;
1962 msg->conn->state = NETCONN_NONE;
1963 state = NETCONN_NONE;
1966 LWIP_ASSERT(
"msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD);
1969 msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0);
1972 if (state == NETCONN_NONE) {
1977 if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
1978#if LWIP_NETCONN_FULLDUPLEX
1980 netconn_mark_mbox_invalid(msg->conn);
1982 netconn_drain(msg->conn);
1985 LWIP_ASSERT(
"already writing or closing", msg->conn->current_msg == NULL);
1986 msg->conn->state = NETCONN_CLOSE;
1987 msg->conn->current_msg = msg;
1988#if LWIP_TCPIP_CORE_LOCKING
1989 if (lwip_netconn_do_close_internal(msg->conn, 0) !=
ERR_OK) {
1990 LWIP_ASSERT(
"state!", msg->conn->state == NETCONN_CLOSE);
1991 UNLOCK_TCPIP_CORE();
1994 LWIP_ASSERT(
"state!", msg->conn->state == NETCONN_NONE);
1997 lwip_netconn_do_close_internal(msg->conn);
2007 TCPIP_APIMSG_ACK(msg);
2010#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
2018lwip_netconn_do_join_leave_group(
void *m)
2020 struct api_msg *msg = (
struct api_msg *)m;
2023 if (msg->conn->pcb.tcp != NULL) {
2024 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
2026#if LWIP_IPV6 && LWIP_IPV6_MLD
2027 if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
2028 if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
2029 msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)),
2030 ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
2032 msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)),
2033 ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
2039 if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
2040 msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)),
2041 ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr)));
2043 msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)),
2044 ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr)));
2049#if (LWIP_TCP || LWIP_RAW)
2055 TCPIP_APIMSG_ACK(msg);
2064lwip_netconn_do_join_leave_group_netif(
void *m)
2066 struct api_msg *msg = (
struct api_msg *)m;
2070 if (
netif == NULL) {
2076 if (msg->conn->pcb.tcp != NULL) {
2077 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
2079#if LWIP_IPV6 && LWIP_IPV6_MLD
2080 if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
2081 if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
2082 msg->err = mld6_joingroup_netif(
netif,
2083 ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
2085 msg->err = mld6_leavegroup_netif(
netif,
2086 ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
2092 if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
2093 msg->err = igmp_joingroup_netif(
netif,
2094 ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr)));
2096 msg->err = igmp_leavegroup_netif(
netif,
2097 ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr)));
2102#if (LWIP_TCP || LWIP_RAW)
2110 TCPIP_APIMSG_ACK(msg);
2121lwip_netconn_do_dns_found(
const char *name,
const ip_addr_t *ipaddr,
void *arg)
2123 struct dns_api_msg *msg = (
struct dns_api_msg *)arg;
2128 if (ipaddr == NULL) {
2130 API_EXPR_DEREF(msg->err) =
ERR_VAL;
2133 API_EXPR_DEREF(msg->err) =
ERR_OK;
2134 API_EXPR_DEREF(msg->addr) = *ipaddr;
2147lwip_netconn_do_gethostbyname(
void *arg)
2149 struct dns_api_msg *msg = (
struct dns_api_msg *)arg;
2151#if LWIP_IPV4 && LWIP_IPV6
2154 LWIP_DNS_ADDRTYPE_DEFAULT;
2157 API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name,
2158 API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype);
2159#if LWIP_TCPIP_CORE_LOCKING
2162 UNLOCK_TCPIP_CORE();
2165 LWIP_ASSERT(
"do_gethostbyname still in progress!!", API_EXPR_DEREF(msg->err) !=
ERR_INPROGRESS);
#define LWIP_UNUSED_ARG(x)
#define LWIP_CONST_CAST(target_type, val)
#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT
#define RECV_BUFSIZE_DEFAULT
#define TCP_SNDQUEUELOWAT
#define TCP_DEFAULT_LISTEN_BACKLOG
#define DEFAULT_UDP_RECVMBOX_SIZE
#define DEFAULT_TCP_RECVMBOX_SIZE
#define DEFAULT_RAW_RECVMBOX_SIZE
#define DEFAULT_ACCEPTMBOX_SIZE
struct netif * netif_get_by_index(u8_t idx)
u8 pbuf_free(struct pbuf *p)
struct pbuf * pbuf_clone(pbuf_layer l, pbuf_type type, struct pbuf *p)
void sys_mbox_set_invalid(sys_mbox_t *mbox)
int sys_mbox_valid(sys_mbox_t *mbox)
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
void sys_mbox_free(sys_mbox_t *mbox)
int sys_sem_valid(sys_sem_t *sem)
void sys_sem_set_invalid(sys_sem_t *sem)
void sys_sem_free(sys_sem_t *sem)
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
void sys_sem_signal(sys_sem_t *sem)
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
#define ip_current_src_addr()
#define ip_current_dest_addr()
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
#define sys_sem_wait(sem)
#define SYS_ARCH_DECL_PROTECT(lev)
#define sys_mbox_valid_val(mbox)
#define sys_mbox_tryfetch(mbox, msg)