| 639 | */ |
| 640 | |
| 641 | int |
| 642 | lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) |
| 643 | { |
| 644 | struct lwip_sock *sock, *nsock; |
| 645 | struct netconn *newconn; |
| 646 | ip_addr_t naddr; |
| 647 | u16_t port = 0; |
| 648 | int newsock; |
| 649 | err_t err; |
| 650 | int recvevent; |
| 651 | SYS_ARCH_DECL_PROTECT(lev); |
| 652 | |
| 653 | LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); |
| 654 | sock = get_socket(s); |
| 655 | if (!sock) { |
| 656 | return -1; |
| 657 | } |
| 658 | |
| 659 | /* wait for a new connection */ |
| 660 | err = netconn_accept(sock->conn, &newconn); |
| 661 | if (err != ERR_OK) { |
| 662 | LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); |
| 663 | if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { |
| 664 | sock_set_errno(sock, EOPNOTSUPP); |
| 665 | } else if (err == ERR_CLSD) { |
| 666 | sock_set_errno(sock, EINVAL); |
| 667 | } else { |
| 668 | sock_set_errno(sock, err_to_errno(err)); |
| 669 | } |
| 670 | done_socket(sock); |
| 671 | return -1; |
| 672 | } |
| 673 | LWIP_ASSERT("newconn != NULL", newconn != NULL); |
| 674 | |
| 675 | newsock = alloc_socket(newconn, 1); |
| 676 | if (newsock == -1) { |
| 677 | netconn_delete(newconn); |
| 678 | sock_set_errno(sock, ENFILE); |
| 679 | done_socket(sock); |
| 680 | return -1; |
| 681 | } |
| 682 | LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); |
| 683 | nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; |
| 684 | |
| 685 | /* See event_callback: If data comes in right away after an accept, even |
| 686 | * though the server task might not have created a new socket yet. |
| 687 | * In that case, newconn->socket is counted down (newconn->socket--), |
| 688 | * so nsock->rcvevent is >= 1 here! |
| 689 | */ |
| 690 | SYS_ARCH_PROTECT(lev); |
| 691 | recvevent = (s16_t)(-1 - newconn->socket); |
| 692 | newconn->socket = newsock; |
| 693 | SYS_ARCH_UNPROTECT(lev); |
| 694 | |
| 695 | if (newconn->callback) { |
| 696 | LOCK_TCPIP_CORE(); |
| 697 | while (recvevent > 0) { |
| 698 | recvevent--; |