* @ingroup netconn_tcp * Accept a new connection on a TCP listening netconn. * * @param conn the TCP listen netconn * @param new_conn pointer where the new connection is stored * @return ERR_OK if a new connection has been received or an error * code otherwise */
| 468 | * code otherwise |
| 469 | */ |
| 470 | err_t |
| 471 | netconn_accept(struct netconn *conn, struct netconn **new_conn) |
| 472 | { |
| 473 | #if LWIP_TCP |
| 474 | err_t err; |
| 475 | void *accept_ptr; |
| 476 | struct netconn *newconn; |
| 477 | #if TCP_LISTEN_BACKLOG |
| 478 | API_MSG_VAR_DECLARE(msg); |
| 479 | #endif /* TCP_LISTEN_BACKLOG */ |
| 480 | |
| 481 | LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); |
| 482 | *new_conn = NULL; |
| 483 | LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); |
| 484 | |
| 485 | /* NOTE: Although the opengroup spec says a pending error shall be returned to |
| 486 | send/recv/getsockopt(SO_ERROR) only, we return it for listening |
| 487 | connections also, to handle embedded-system errors */ |
| 488 | err = netconn_err(conn); |
| 489 | if (err != ERR_OK) { |
| 490 | /* return pending error */ |
| 491 | return err; |
| 492 | } |
| 493 | if (!NETCONN_ACCEPTMBOX_WAITABLE(conn)) { |
| 494 | /* don't accept if closed: this might block the application task |
| 495 | waiting on acceptmbox forever! */ |
| 496 | return ERR_CLSD; |
| 497 | } |
| 498 | |
| 499 | API_MSG_VAR_ALLOC_ACCEPT(msg); |
| 500 | |
| 501 | NETCONN_MBOX_WAITING_INC(conn); |
| 502 | if (netconn_is_nonblocking(conn)) { |
| 503 | if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_ARCH_TIMEOUT) { |
| 504 | API_MSG_VAR_FREE_ACCEPT(msg); |
| 505 | NETCONN_MBOX_WAITING_DEC(conn); |
| 506 | return ERR_WOULDBLOCK; |
| 507 | } |
| 508 | } else { |
| 509 | #if LWIP_SO_RCVTIMEO |
| 510 | if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { |
| 511 | API_MSG_VAR_FREE_ACCEPT(msg); |
| 512 | NETCONN_MBOX_WAITING_DEC(conn); |
| 513 | return ERR_TIMEOUT; |
| 514 | } |
| 515 | #else |
| 516 | sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); |
| 517 | #endif /* LWIP_SO_RCVTIMEO*/ |
| 518 | } |
| 519 | NETCONN_MBOX_WAITING_DEC(conn); |
| 520 | #if LWIP_NETCONN_FULLDUPLEX |
| 521 | if (conn->flags & NETCONN_FLAG_MBOXINVALID) { |
| 522 | if (lwip_netconn_is_deallocated_msg(accept_ptr)) { |
| 523 | /* the netconn has been closed from another thread */ |
| 524 | API_MSG_VAR_FREE_ACCEPT(msg); |
| 525 | return ERR_CONN; |
| 526 | } |
| 527 | } |