81 #if LWIP_CHECKSUM_ON_COPY 91 #define LWIP_NETCONN 1 96 #define LWIP_NETCONN 0 100 #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ 101 (sin)->sin_len = sizeof(struct sockaddr_in); \ 102 (sin)->sin_family = AF_INET; \ 103 (sin)->sin_port = lwip_htons((port)); \ 104 inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ 105 memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) 106 #define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ 107 inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ 108 (port) = lwip_ntohs((sin)->sin_port); }while(0) 112 #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ 113 (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ 114 (sin6)->sin6_family = AF_INET6; \ 115 (sin6)->sin6_port = lwip_htons((port)); \ 116 (sin6)->sin6_flowinfo = 0; \ 117 inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ 118 (sin6)->sin6_scope_id = 0; }while(0) 119 #define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ 120 inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ 121 (port) = lwip_ntohs((sin6)->sin6_port); }while(0) 124 #if LWIP_IPV4 && LWIP_IPV6 125 static void sockaddr_to_ipaddr_port(
const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port);
127 #define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ 128 ((namelen) == sizeof(struct sockaddr_in6))) 129 #define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ 130 ((name)->sa_family == AF_INET6)) 131 #define SOCK_ADDR_TYPE_MATCH(name, sock) \ 132 ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ 133 (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) 134 #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ 135 if (IP_IS_V6(ipaddr)) { \ 136 IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ 138 IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ 140 #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port)) 141 #define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ 142 (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) 144 #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6)) 145 #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6) 146 #define SOCK_ADDR_TYPE_MATCH(name, sock) 1 147 #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ 148 IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) 149 #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ 150 SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) 151 #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) 153 #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) 154 #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) 155 #define SOCK_ADDR_TYPE_MATCH(name, sock) 1 156 #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ 157 IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port) 158 #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ 159 SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port) 160 #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) 163 #define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ 164 IS_SOCK_ADDR_TYPE_VALID(name)) 165 #define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ 166 SOCK_ADDR_TYPE_MATCH(name, sock)) 167 #define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) 170 #define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) 171 #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ 172 LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ 173 if ((sock)->conn == NULL) { return EINVAL; } }while(0) 174 #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ 175 LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ 176 if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) 177 #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ 178 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ 179 if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) 182 #define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) 183 #define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) 184 #define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) 185 #if LWIP_MPU_COMPATIBLE 186 #define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ 187 name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ 188 if (name == NULL) { \ 189 sock_set_errno(sock, ENOMEM); \ 193 #define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) 196 #if LWIP_SO_SNDRCVTIMEO_NONSTANDARD 197 #define LWIP_SO_SNDRCVTIMEO_OPTTYPE int 198 #define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) 199 #define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval)) 201 #define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval 202 #define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ 204 ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ 205 ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0) 206 #define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U)) 209 #define NUM_SOCKETS MEMP_NUM_NETCONN 215 #define SELWAIT_T u8_t 221 struct netconn *conn;
237 SELWAIT_T select_waiting;
240 #if LWIP_NETCONN_SEM_PER_THREAD 241 #define SELECT_SEM_T sys_sem_t* 242 #define SELECT_SEM_PTR(sem) (sem) 244 #define SELECT_SEM_T sys_sem_t 245 #define SELECT_SEM_PTR(sem) (&(sem)) 249 struct lwip_select_cb {
251 struct lwip_select_cb *next;
253 struct lwip_select_cb *prev;
269 union sockaddr_aligned {
272 struct sockaddr_in6 sin6;
275 struct sockaddr_in sin;
281 #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS 282 #define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS 287 struct lwip_socket_multicast_pair {
289 struct lwip_sock* sock;
293 ip4_addr_t multi_addr;
296 struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
298 static int lwip_socket_register_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr);
299 static void lwip_socket_unregister_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr);
300 static void lwip_socket_drop_registered_memberships(
int s);
304 static struct lwip_sock sockets[NUM_SOCKETS];
306 static struct lwip_select_cb *select_cb_list;
309 static volatile int select_cb_ctr;
311 #if LWIP_SOCKET_SET_ERRNO 313 #define set_errno(err) do { if (err) { errno = (err); } } while(0) 316 #define set_errno(err) 319 #define sock_set_errno(sk, e) do { \ 320 const int sockerr = (e); \ 321 sk->err = (u8_t)sockerr; \ 322 set_errno(sockerr); \ 326 static void event_callback(
struct netconn *conn,
enum netconn_evt evt, u16_t len);
327 #if !LWIP_TCPIP_CORE_LOCKING 328 static void lwip_getsockopt_callback(
void *arg);
329 static void lwip_setsockopt_callback(
void *arg);
331 static u8_t lwip_getsockopt_impl(
int s,
int level,
int optname,
void *optval, socklen_t *optlen);
332 static u8_t lwip_setsockopt_impl(
int s,
int level,
int optname,
const void *optval, socklen_t optlen);
334 #if LWIP_IPV4 && LWIP_IPV6 336 sockaddr_to_ipaddr_port(
const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port)
338 if ((sockaddr->sa_family) == AF_INET6) {
339 SOCKADDR6_TO_IP6ADDR_PORT((
const struct sockaddr_in6*)(
const void*)(sockaddr), ipaddr, *port);
342 SOCKADDR4_TO_IP4ADDR_PORT((
const struct sockaddr_in*)(
const void*)(sockaddr), ipaddr, *port);
350 lwip_socket_thread_init(
void)
352 netconn_thread_init();
357 lwip_socket_thread_cleanup(
void)
359 netconn_thread_cleanup();
368 static struct lwip_sock *
371 struct lwip_sock *sock;
375 if ((s < 0) || (s >= NUM_SOCKETS)) {
398 static struct lwip_sock *
402 if ((s < 0) || (s >= NUM_SOCKETS)) {
405 if (!sockets[s].conn) {
420 alloc_socket(
struct netconn *newconn,
int accepted)
426 for (i = 0; i < NUM_SOCKETS; ++i) {
428 SYS_ARCH_PROTECT(lev);
429 if (!sockets[i].conn && (sockets[i].select_waiting == 0)) {
430 sockets[i].conn = newconn;
433 SYS_ARCH_UNPROTECT(lev);
434 sockets[i].lastdata = NULL;
435 sockets[i].lastoffset = 0;
436 sockets[i].rcvevent = 0;
439 sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
440 sockets[i].errevent = 0;
444 SYS_ARCH_UNPROTECT(lev);
456 free_socket(
struct lwip_sock *sock,
int is_tcp)
460 lastdata = sock->lastdata;
461 sock->lastdata = NULL;
462 sock->lastoffset = 0;
466 SYS_ARCH_SET(sock->conn, NULL);
469 if (lastdata != NULL) {
473 netbuf_delete((
struct netbuf *)lastdata);
485 lwip_accept(
int s,
struct sockaddr *addr, socklen_t *addrlen)
487 struct lwip_sock *sock, *nsock;
488 struct netconn *newconn;
496 sock = get_socket(s);
501 if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
503 set_errno(EWOULDBLOCK);
508 err = netconn_accept(sock->conn, &newconn);
511 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
512 sock_set_errno(sock, EOPNOTSUPP);
514 sock_set_errno(sock, EINVAL);
516 sock_set_errno(sock, err_to_errno(err));
520 LWIP_ASSERT(
"newconn != NULL", newconn != NULL);
522 newsock = alloc_socket(newconn, 1);
524 netconn_delete(newconn);
525 sock_set_errno(sock, ENFILE);
529 LWIP_ASSERT(
"newconn->callback == event_callback", newconn->callback == event_callback);
537 SYS_ARCH_PROTECT(lev);
538 nsock->rcvevent += (s16_t)(-1 - newconn->socket);
539 newconn->socket = newsock;
540 SYS_ARCH_UNPROTECT(lev);
546 union sockaddr_aligned tempaddr;
548 err = netconn_peer(newconn, &naddr, &port);
551 netconn_delete(newconn);
552 free_socket(nsock, 1);
553 sock_set_errno(sock, err_to_errno(err));
556 LWIP_ASSERT(
"addr valid but addrlen NULL", addrlen != NULL);
558 IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port);
559 if (*addrlen > tempaddr.sa.sa_len) {
560 *addrlen = tempaddr.sa.sa_len;
562 MEMCPY(addr, &tempaddr, *addrlen);
571 sock_set_errno(sock, 0);
576 lwip_bind(
int s,
const struct sockaddr *name, socklen_t namelen)
578 struct lwip_sock *sock;
579 ip_addr_t local_addr;
583 sock = get_socket(s);
588 if (!SOCK_ADDR_TYPE_MATCH(name, sock)) {
590 sock_set_errno(sock, err_to_errno(
ERR_VAL));
595 LWIP_ERROR(
"lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) &&
596 IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)),
597 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
600 SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port);
605 #if LWIP_IPV4 && LWIP_IPV6 607 if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) {
608 unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr));
613 err = netconn_bind(sock->conn, &local_addr, local_port);
617 sock_set_errno(sock, err_to_errno(err));
622 sock_set_errno(sock, 0);
629 struct lwip_sock *sock;
635 sock = get_socket(s);
640 if (sock->conn != NULL) {
641 is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
643 LWIP_ASSERT(
"sock->lastdata == NULL", sock->lastdata == NULL);
648 lwip_socket_drop_registered_memberships(s);
651 err = netconn_delete(sock->conn);
653 sock_set_errno(sock, err_to_errno(err));
657 free_socket(sock, is_tcp);
663 lwip_connect(
int s,
const struct sockaddr *name, socklen_t namelen)
665 struct lwip_sock *sock;
668 sock = get_socket(s);
673 if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) {
675 sock_set_errno(sock, err_to_errno(
ERR_VAL));
680 if (name->sa_family == AF_UNSPEC) {
682 err = netconn_disconnect(sock->conn);
684 ip_addr_t remote_addr;
688 LWIP_ERROR(
"lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) &&
689 IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name),
690 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
692 SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port);
697 #if LWIP_IPV4 && LWIP_IPV6 699 if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) {
700 unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr));
705 err = netconn_connect(sock->conn, &remote_addr, remote_port);
710 sock_set_errno(sock, err_to_errno(err));
715 sock_set_errno(sock, 0);
728 lwip_listen(
int s,
int backlog)
730 struct lwip_sock *sock;
735 sock = get_socket(s);
741 backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
743 err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
747 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
748 sock_set_errno(sock, EOPNOTSUPP);
751 sock_set_errno(sock, err_to_errno(err));
755 sock_set_errno(sock, 0);
760 lwip_recvfrom(
int s,
void *
mem,
size_t len,
int flags,
761 struct sockaddr *from, socklen_t *fromlen)
763 struct lwip_sock *sock;
766 u16_t buflen, copylen;
772 sock = get_socket(s);
780 if (sock->lastdata) {
781 buf = sock->lastdata;
784 if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
785 (sock->rcvevent <= 0)) {
788 sock_set_errno(sock, 0);
792 set_errno(EWOULDBLOCK);
798 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
799 err = netconn_recv_tcp_pbuf(sock->conn, (
struct pbuf **)&buf);
801 err = netconn_recv(sock->conn, (
struct netbuf **)&buf);
810 event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0);
813 sock_set_errno(sock, 0);
818 s, lwip_strerr(err)));
819 sock_set_errno(sock, err_to_errno(err));
826 LWIP_ASSERT(
"buf != NULL", buf != NULL);
827 sock->lastdata = buf;
830 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
831 p = (
struct pbuf *)buf;
833 p = ((
struct netbuf *)buf)->p;
837 buflen, len, off, sock->lastoffset));
839 buflen -= sock->lastoffset;
844 copylen = (u16_t)len;
853 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
854 LWIP_ASSERT(
"invalid copylen, len would underflow", len >= copylen);
858 (sock->rcvevent <= 0) ||
859 ((flags & MSG_PEEK) != 0)) {
875 union sockaddr_aligned saddr;
877 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
879 netconn_getaddr(sock->conn, fromaddr, &port, 0);
881 port = netbuf_fromport((
struct netbuf *)buf);
882 fromaddr = netbuf_fromaddr((
struct netbuf *)buf);
885 #if LWIP_IPV4 && LWIP_IPV6 887 if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) {
888 ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
893 IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
900 if (*fromlen > saddr.sa.sa_len) {
901 *fromlen = saddr.sa.sa_len;
903 MEMCPY(from, &saddr, *fromlen);
909 if ((flags & MSG_PEEK) == 0) {
913 if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) {
914 sock->lastdata = buf;
915 sock->lastoffset += copylen;
918 sock->lastdata = NULL;
919 sock->lastoffset = 0;
921 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
924 netbuf_delete((
struct netbuf *)buf);
931 sock_set_errno(sock, 0);
936 lwip_read(
int s,
void *mem,
size_t len)
938 return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
942 lwip_recv(
int s,
void *mem,
size_t len,
int flags)
944 return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
948 lwip_send(
int s,
const void *data,
size_t size,
int flags)
950 struct lwip_sock *sock;
956 s, data, size, flags));
958 sock = get_socket(s);
963 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
964 #if (LWIP_UDP || LWIP_RAW) 965 return lwip_sendto(s, data, size, flags, NULL, 0);
967 sock_set_errno(sock, err_to_errno(
ERR_ARG));
972 write_flags = NETCONN_COPY |
973 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
974 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
976 err = netconn_write_partly(sock->conn, data, size, write_flags, &written);
979 sock_set_errno(sock, err_to_errno(err));
980 return (err ==
ERR_OK ? (
int)written : -1);
984 lwip_sendmsg(
int s,
const struct msghdr *msg,
int flags)
986 struct lwip_sock *sock;
995 sock = get_socket(s);
1000 LWIP_ERROR(
"lwip_sendmsg: invalid msghdr", msg != NULL,
1001 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
1006 LWIP_ERROR(
"lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0),
1007 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
1009 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
1011 write_flags = NETCONN_COPY |
1012 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
1013 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
1015 for (i = 0; i < msg->msg_iovlen; i++) {
1016 u8_t apiflags = write_flags;
1017 if (i + 1 < msg->msg_iovlen) {
1018 apiflags |= NETCONN_MORE;
1021 err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written);
1025 if (written != msg->msg_iov[i].iov_len)
1038 sock_set_errno(sock, err_to_errno(err));
1041 sock_set_errno(sock, err_to_errno(
ERR_ARG));
1046 #if LWIP_UDP || LWIP_RAW 1048 struct netbuf *chain_buf;
1051 LWIP_ERROR(
"lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) ||
1052 IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) ,
1053 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
1056 chain_buf = netbuf_new();
1058 sock_set_errno(sock, err_to_errno(
ERR_MEM));
1061 if (msg->msg_name) {
1063 SOCKADDR_TO_IPADDR_PORT((
const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port);
1064 netbuf_fromport(chain_buf) = remote_port;
1066 #if LWIP_NETIF_TX_SINGLE_PBUF 1067 for (i = 0; i < msg->msg_iovlen; i++) {
1068 size += msg->msg_iov[i].iov_len;
1071 if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) {
1076 for (i = 0; i < msg->msg_iovlen; i++) {
1077 MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
1078 offset += msg->msg_iov[i].iov_len;
1080 #if LWIP_CHECKSUM_ON_COPY 1084 netbuf_set_chksum(chain_buf, chksum);
1092 for (i = 0; i < msg->msg_iovlen; i++) {
1098 p->
payload = msg->msg_iov[i].iov_base;
1099 LWIP_ASSERT(
"iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF);
1100 p->
len = p->
tot_len = (u16_t)msg->msg_iov[i].iov_len;
1102 if (chain_buf->p == NULL) {
1103 chain_buf->p = chain_buf->ptr = p;
1111 size = netbuf_len(chain_buf);
1116 #if LWIP_IPV4 && LWIP_IPV6 1118 if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) {
1119 unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr));
1125 err = netconn_send(sock->conn, chain_buf);
1129 netbuf_delete(chain_buf);
1131 sock_set_errno(sock, err_to_errno(err));
1132 return (err ==
ERR_OK ? size : -1);
1135 sock_set_errno(sock, err_to_errno(
ERR_ARG));
1141 lwip_sendto(
int s,
const void *data,
size_t size,
int flags,
1142 const struct sockaddr *to, socklen_t tolen)
1144 struct lwip_sock *sock;
1150 sock = get_socket(s);
1155 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
1157 return lwip_send(s, data, size, flags);
1160 sock_set_errno(sock, err_to_errno(
ERR_ARG));
1166 LWIP_ASSERT(
"lwip_sendto: size must fit in u16_t", size <= 0xffff);
1167 short_size = (u16_t)size;
1168 LWIP_ERROR(
"lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
1169 (IS_SOCK_ADDR_LEN_VALID(tolen) &&
1170 IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))),
1171 sock_set_errno(sock, err_to_errno(
ERR_ARG));
return -1;);
1175 buf.p = buf.ptr = NULL;
1176 #if LWIP_CHECKSUM_ON_COPY 1180 SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port);
1183 ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr);
1185 netbuf_fromport(&buf) = remote_port;
1189 s, data, short_size, flags));
1194 #if LWIP_NETIF_TX_SINGLE_PBUF 1196 if (netbuf_alloc(&buf, short_size) == NULL) {
1199 #if LWIP_CHECKSUM_ON_COPY 1200 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) {
1201 u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
1202 netbuf_set_chksum(&buf, chksum);
1206 MEMCPY(buf.p->payload, data, short_size);
1211 err = netbuf_ref(&buf, data, short_size);
1214 #if LWIP_IPV4 && LWIP_IPV6 1216 if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) {
1217 unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr));
1223 err = netconn_send(sock->conn, &buf);
1229 sock_set_errno(sock, err_to_errno(err));
1230 return (err ==
ERR_OK ? short_size : -1);
1234 lwip_socket(
int domain,
int type,
int protocol)
1236 struct netconn *conn;
1244 conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW),
1245 (u8_t)protocol, event_callback);
1247 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1250 conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain,
1251 ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) ,
1254 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1257 conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback);
1259 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1263 domain, type, protocol));
1274 i = alloc_socket(conn, 0);
1277 netconn_delete(conn);
1288 lwip_write(
int s,
const void *data,
size_t size)
1290 return lwip_send(s, data, size, 0);
1294 lwip_writev(
int s,
const struct iovec *iov,
int iovcnt)
1298 msg.msg_name = NULL;
1299 msg.msg_namelen = 0;
1303 msg.msg_iovlen = iovcnt;
1304 msg.msg_control = NULL;
1305 msg.msg_controllen = 0;
1307 return lwip_sendmsg(s, &msg, 0);
1325 lwip_selscan(
int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
1326 fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
1329 fd_set lreadset, lwriteset, lexceptset;
1330 struct lwip_sock *sock;
1334 FD_ZERO(&lwriteset);
1335 FD_ZERO(&lexceptset);
1341 if (!(readset_in && FD_ISSET(i, readset_in)) &&
1342 !(writeset_in && FD_ISSET(i, writeset_in)) &&
1343 !(exceptset_in && FD_ISSET(i, exceptset_in))) {
1347 SYS_ARCH_PROTECT(lev);
1348 sock = tryget_socket(i);
1350 void* lastdata = sock->lastdata;
1351 s16_t rcvevent = sock->rcvevent;
1352 u16_t sendevent = sock->sendevent;
1353 u16_t errevent = sock->errevent;
1354 SYS_ARCH_UNPROTECT(lev);
1358 if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
1359 FD_SET(i, &lreadset);
1364 if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
1365 FD_SET(i, &lwriteset);
1370 if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
1371 FD_SET(i, &lexceptset);
1376 SYS_ARCH_UNPROTECT(lev);
1381 *readset_out = lreadset;
1382 *writeset_out = lwriteset;
1383 *exceptset_out = lexceptset;
1385 LWIP_ASSERT(
"nready >= 0", nready >= 0);
1390 lwip_select(
int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
1391 struct timeval *timeout)
1395 fd_set lreadset, lwriteset, lexceptset;
1397 struct lwip_select_cb select_cb;
1400 #if LWIP_NETCONN_SEM_PER_THREAD 1406 maxfdp1, (
void *)readset, (
void *) writeset, (
void *) exceptset,
1407 timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
1408 timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
1412 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1416 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
1420 goto return_copy_fdsets;
1428 select_cb.next = NULL;
1429 select_cb.prev = NULL;
1430 select_cb.readset = readset;
1431 select_cb.writeset = writeset;
1432 select_cb.exceptset = exceptset;
1433 select_cb.sem_signalled = 0;
1434 #if LWIP_NETCONN_SEM_PER_THREAD 1435 select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET();
1445 SYS_ARCH_PROTECT(lev);
1448 select_cb.next = select_cb_list;
1449 if (select_cb_list != NULL) {
1450 select_cb_list->prev = &select_cb;
1452 select_cb_list = &select_cb;
1457 SYS_ARCH_UNPROTECT(lev);
1462 if ((readset && FD_ISSET(i, readset)) ||
1463 (writeset && FD_ISSET(i, writeset)) ||
1464 (exceptset && FD_ISSET(i, exceptset))) {
1465 struct lwip_sock *sock;
1466 SYS_ARCH_PROTECT(lev);
1467 sock = tryget_socket(i);
1469 sock->select_waiting++;
1470 LWIP_ASSERT(
"sock->select_waiting > 0", sock->select_waiting > 0);
1475 SYS_ARCH_UNPROTECT(lev);
1478 SYS_ARCH_UNPROTECT(lev);
1485 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1492 msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
1493 if (msectimeout == 0) {
1500 #if LWIP_NETCONN_SEM_PER_THREAD 1508 if ((readset && FD_ISSET(i, readset)) ||
1509 (writeset && FD_ISSET(i, writeset)) ||
1510 (exceptset && FD_ISSET(i, exceptset))) {
1511 struct lwip_sock *sock;
1512 SYS_ARCH_PROTECT(lev);
1513 sock = tryget_socket(i);
1516 LWIP_ASSERT(
"sock->select_waiting > 0", sock->select_waiting > 0);
1517 if (sock->select_waiting > 0) {
1518 sock->select_waiting--;
1524 SYS_ARCH_UNPROTECT(lev);
1528 SYS_ARCH_PROTECT(lev);
1529 if (select_cb.next != NULL) {
1530 select_cb.next->prev = select_cb.prev;
1532 if (select_cb_list == &select_cb) {
1533 LWIP_ASSERT(
"select_cb.prev == NULL", select_cb.prev == NULL);
1534 select_cb_list = select_cb.next;
1536 LWIP_ASSERT(
"select_cb.prev != NULL", select_cb.prev != NULL);
1537 select_cb.prev->next = select_cb.next;
1541 SYS_ARCH_UNPROTECT(lev);
1543 #if LWIP_NETCONN_SEM_PER_THREAD 1544 if (select_cb.sem_signalled && (!waited || (waitres ==
SYS_ARCH_TIMEOUT))) {
1563 goto return_copy_fdsets;
1567 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1574 *readset = lreadset;
1577 *writeset = lwriteset;
1580 *exceptset = lexceptset;
1590 event_callback(
struct netconn *conn,
enum netconn_evt evt, u16_t len)
1593 struct lwip_sock *sock;
1594 struct lwip_select_cb *scb;
1595 int last_select_cb_ctr;
1609 SYS_ARCH_PROTECT(lev);
1610 if (conn->socket < 0) {
1611 if (evt == NETCONN_EVT_RCVPLUS) {
1614 SYS_ARCH_UNPROTECT(lev);
1618 SYS_ARCH_UNPROTECT(lev);
1621 sock = get_socket(s);
1629 SYS_ARCH_PROTECT(lev);
1632 case NETCONN_EVT_RCVPLUS:
1635 case NETCONN_EVT_RCVMINUS:
1638 case NETCONN_EVT_SENDPLUS:
1639 sock->sendevent = 1;
1641 case NETCONN_EVT_SENDMINUS:
1642 sock->sendevent = 0;
1644 case NETCONN_EVT_ERROR:
1648 LWIP_ASSERT(
"unknown event", 0);
1652 if (sock->select_waiting == 0) {
1654 SYS_ARCH_UNPROTECT(lev);
1665 for (scb = select_cb_list; scb != NULL; scb = scb->next) {
1667 last_select_cb_ctr = select_cb_ctr;
1668 if (scb->sem_signalled == 0) {
1672 if (sock->rcvevent > 0) {
1673 if (scb->readset && FD_ISSET(s, scb->readset)) {
1677 if (sock->sendevent != 0) {
1678 if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
1682 if (sock->errevent != 0) {
1683 if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
1688 scb->sem_signalled = 1;
1695 SYS_ARCH_UNPROTECT(lev);
1697 SYS_ARCH_PROTECT(lev);
1698 if (last_select_cb_ctr != select_cb_ctr) {
1703 SYS_ARCH_UNPROTECT(lev);
1710 lwip_shutdown(
int s,
int how)
1712 struct lwip_sock *sock;
1714 u8_t shut_rx = 0, shut_tx = 0;
1718 sock = get_socket(s);
1723 if (sock->conn != NULL) {
1724 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
1725 sock_set_errno(sock, EOPNOTSUPP);
1729 sock_set_errno(sock, ENOTCONN);
1733 if (how == SHUT_RD) {
1735 }
else if (how == SHUT_WR) {
1737 }
else if (how == SHUT_RDWR) {
1741 sock_set_errno(sock, EINVAL);
1744 err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
1746 sock_set_errno(sock, err_to_errno(err));
1747 return (err ==
ERR_OK ? 0 : -1);
1751 lwip_getaddrname(
int s,
struct sockaddr *name, socklen_t *namelen, u8_t local)
1753 struct lwip_sock *sock;
1754 union sockaddr_aligned saddr;
1759 sock = get_socket(s);
1765 err = netconn_getaddr(sock->conn, &naddr, &port, local);
1767 sock_set_errno(sock, err_to_errno(err));
1771 #if LWIP_IPV4 && LWIP_IPV6 1773 if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
1774 IP_IS_V4_VAL(naddr)) {
1775 ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr));
1780 IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
1786 if (*namelen > saddr.sa.sa_len) {
1787 *namelen = saddr.sa.sa_len;
1789 MEMCPY(name, &saddr, *namelen);
1791 sock_set_errno(sock, 0);
1796 lwip_getpeername(
int s,
struct sockaddr *name, socklen_t *namelen)
1798 return lwip_getaddrname(s, name, namelen, 0);
1802 lwip_getsockname(
int s,
struct sockaddr *name, socklen_t *namelen)
1804 return lwip_getaddrname(s, name, namelen, 1);
1808 lwip_getsockopt(
int s,
int level,
int optname,
void *optval, socklen_t *optlen)
1811 struct lwip_sock *sock = get_socket(s);
1812 #if !LWIP_TCPIP_CORE_LOCKING 1813 LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
1820 if ((NULL == optval) || (NULL == optlen)) {
1821 sock_set_errno(sock, EFAULT);
1825 #if LWIP_TCPIP_CORE_LOCKING 1828 err = lwip_getsockopt_impl(s, level, optname, optval, optlen);
1829 UNLOCK_TCPIP_CORE();
1833 #if LWIP_MPU_COMPATIBLE 1835 if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
1836 sock_set_errno(sock, ENOBUFS);
1841 LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
1842 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
1843 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
1844 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
1845 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen;
1846 #if !LWIP_MPU_COMPATIBLE 1847 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval;
1849 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
1850 #if LWIP_NETCONN_SEM_PER_THREAD 1851 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
1853 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
1855 err =
tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
1857 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
1858 sock_set_errno(sock, err_to_errno(err));
1861 sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
1864 *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen;
1865 #if LWIP_MPU_COMPATIBLE 1866 MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval,
1867 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen);
1871 err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
1872 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
1875 sock_set_errno(sock, err);
1876 return err ? -1 : 0;
1879 #if !LWIP_TCPIP_CORE_LOCKING 1884 lwip_getsockopt_callback(
void *arg)
1886 struct lwip_setgetsockopt_data *data;
1887 LWIP_ASSERT(
"arg != NULL", arg != NULL);
1888 data = (
struct lwip_setgetsockopt_data*)arg;
1890 data->err = lwip_getsockopt_impl(data->s, data->level, data->optname,
1906 lwip_getsockopt_impl(
int s,
int level,
int optname,
void *optval, socklen_t *optlen)
1909 struct lwip_sock *sock = tryget_socket(s);
1922 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
1923 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) {
1926 if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) {
1940 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
1943 s, optname, (*(
int*)optval?
"on":
"off")));
1947 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
1948 switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) {
1950 *(
int*)optval = SOCK_RAW;
1953 *(
int*)optval = SOCK_STREAM;
1956 *(
int*)optval = SOCK_DGRAM;
1959 *(
int*)optval = netconn_type(sock->conn);
1961 (
"lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
1962 s, *(
int *)optval));
1965 s, *(
int *)optval));
1969 LWIP_SOCKOPT_CHECK_OPTLEN(*optlen,
int);
1971 if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) {
1972 sock_set_errno(sock, err_to_errno(sock->conn->last_err));
1974 *(
int *)optval = (sock->err == 0xFF ? (
int)-1 : (int)sock->err);
1977 s, *(
int *)optval));
1980 #if LWIP_SO_SNDTIMEO 1982 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
1983 LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn));
1986 #if LWIP_SO_RCVTIMEO 1988 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
1989 LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn));
1994 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
1995 *(
int *)optval = netconn_get_recvbufsize(sock->conn);
2002 struct linger* linger = (
struct linger*)optval;
2003 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
struct linger);
2004 conn_linger = sock->conn->linger;
2005 if (conn_linger >= 0) {
2006 linger->l_onoff = 1;
2007 linger->l_linger = (int)conn_linger;
2009 linger->l_onoff = 0;
2010 linger->l_linger = 0;
2017 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_UDP);
2019 if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
2021 return EAFNOSUPPORT;
2024 *(
int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
2039 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
2040 *(
int*)optval = sock->conn->pcb.ip->ttl;
2042 s, *(
int *)optval));
2045 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
2046 *(
int*)optval = sock->conn->pcb.ip->tos;
2048 s, *(
int *)optval));
2050 #if LWIP_MULTICAST_TX_OPTIONS 2051 case IP_MULTICAST_TTL:
2052 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
2053 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
2056 *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp);
2058 s, *(
int *)optval));
2060 case IP_MULTICAST_IF:
2061 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
struct in_addr);
2062 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
2065 inet_addr_from_ip4addr((
struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
2067 s, *(u32_t *)optval));
2069 case IP_MULTICAST_LOOP:
2070 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t);
2071 if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
2077 s, *(
int *)optval));
2092 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_TCP);
2093 if (sock->conn->pcb.tcp->state == LISTEN) {
2098 *(
int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
2100 s, (*(
int*)optval)?
"on":
"off") );
2103 *(
int*)optval = (
int)sock->conn->pcb.tcp->keep_idle;
2105 s, *(
int *)optval));
2108 #if LWIP_TCP_KEEPALIVE 2110 *(
int*)optval = (
int)(sock->conn->pcb.tcp->keep_idle/1000);
2112 s, *(
int *)optval));
2115 *(
int*)optval = (
int)(sock->conn->pcb.tcp->keep_intvl/1000);
2117 s, *(
int *)optval));
2120 *(
int*)optval = (
int)sock->conn->pcb.tcp->keep_cnt;
2122 s, *(
int *)optval));
2139 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
2140 *(
int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
2142 s, *(
int *)optval));
2153 #if LWIP_UDP && LWIP_UDPLITE 2155 case IPPROTO_UDPLITE:
2157 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
2159 if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
2163 case UDPLITE_SEND_CSCOV:
2164 *(
int*)optval = sock->conn->pcb.udp->chksum_len_tx;
2166 s, (*(
int*)optval)) );
2168 case UDPLITE_RECV_CSCOV:
2169 *(
int*)optval = sock->conn->pcb.udp->chksum_len_rx;
2171 s, (*(
int*)optval)) );
2184 #if LWIP_IPV6 && LWIP_RAW 2186 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_RAW);
2187 if (sock->conn->pcb.raw->chksum_reqd == 0) {
2188 *(
int *)optval = -1;
2190 *(
int *)optval = sock->conn->pcb.raw->chksum_offset;
2193 s, (*(
int*)optval)) );
2205 s, level, optname));
2214 lwip_setsockopt(
int s,
int level,
int optname,
const void *optval, socklen_t optlen)
2217 struct lwip_sock *sock = get_socket(s);
2218 #if !LWIP_TCPIP_CORE_LOCKING 2219 LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
2226 if (NULL == optval) {
2227 sock_set_errno(sock, EFAULT);
2231 #if LWIP_TCPIP_CORE_LOCKING 2234 err = lwip_setsockopt_impl(s, level, optname, optval, optlen);
2235 UNLOCK_TCPIP_CORE();
2239 #if LWIP_MPU_COMPATIBLE 2241 if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
2242 sock_set_errno(sock, ENOBUFS);
2247 LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
2248 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
2249 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
2250 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
2251 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen;
2252 #if LWIP_MPU_COMPATIBLE 2253 MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen);
2255 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (
const void*)optval;
2257 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
2258 #if LWIP_NETCONN_SEM_PER_THREAD 2259 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
2261 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
2263 err =
tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
2265 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
2266 sock_set_errno(sock, err_to_errno(err));
2269 sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0);
2272 err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
2273 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
2276 sock_set_errno(sock, err);
2277 return err ? -1 : 0;
2280 #if !LWIP_TCPIP_CORE_LOCKING 2285 lwip_setsockopt_callback(
void *arg)
2287 struct lwip_setgetsockopt_data *data;
2288 LWIP_ASSERT(
"arg != NULL", arg != NULL);
2289 data = (
struct lwip_setgetsockopt_data*)arg;
2291 data->err = lwip_setsockopt_impl(data->s, data->level, data->optname,
2307 lwip_setsockopt_impl(
int s,
int level,
int optname,
const void *optval, socklen_t optlen)
2310 struct lwip_sock *sock = tryget_socket(s);
2329 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
2330 if (*(
const int*)optval) {
2336 s, optname, (*(
const int*)optval?
"on":
"off")));
2342 #if LWIP_SO_SNDTIMEO 2344 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
2345 netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
2348 #if LWIP_SO_RCVTIMEO 2350 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
2351 netconn_set_recvtimeout(sock->conn, (
int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
2356 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen,
int);
2357 netconn_set_recvbufsize(sock->conn, *(
const int*)optval);
2363 const struct linger* linger = (
const struct linger*)optval;
2364 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen,
struct linger);
2365 if (linger->l_onoff) {
2366 int lingersec = linger->l_linger;
2367 if (lingersec < 0) {
2370 if (lingersec > 0xFFFF) {
2373 sock->conn->linger = (s16_t)lingersec;
2375 sock->conn->linger = -1;
2382 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_UDP);
2384 if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
2386 return EAFNOSUPPORT;
2389 if (*(
const int*)optval) {
2390 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
2392 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
2408 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
2409 sock->conn->pcb.ip->ttl = (u8_t)(*(
const int*)optval);
2411 s, sock->conn->pcb.ip->ttl));
2414 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
2415 sock->conn->pcb.ip->tos = (u8_t)(*(
const int*)optval);
2417 s, sock->conn->pcb.ip->tos));
2419 #if LWIP_MULTICAST_TX_OPTIONS 2420 case IP_MULTICAST_TTL:
2421 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
2422 udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(
const u8_t*)optval));
2424 case IP_MULTICAST_IF:
2427 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
struct in_addr, NETCONN_UDP);
2428 inet_addr_to_ip4addr(&if_addr, (
const struct in_addr*)optval);
2429 udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
2432 case IP_MULTICAST_LOOP:
2433 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP);
2434 if (*(
const u8_t*)optval) {
2435 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
2437 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
2442 case IP_ADD_MEMBERSHIP:
2443 case IP_DROP_MEMBERSHIP:
2448 const struct ip_mreq *imr = (
const struct ip_mreq *)optval;
2450 ip4_addr_t multi_addr;
2451 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
struct ip_mreq, NETCONN_UDP);
2452 inet_addr_to_ip4addr(&if_addr, &imr->imr_interface);
2453 inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr);
2454 if (optname == IP_ADD_MEMBERSHIP) {
2455 if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
2460 igmp_err = igmp_joingroup(&if_addr, &multi_addr);
2463 igmp_err = igmp_leavegroup(&if_addr, &multi_addr);
2464 lwip_socket_unregister_membership(s, &if_addr, &multi_addr);
2466 if (igmp_err !=
ERR_OK) {
2467 err = EADDRNOTAVAIL;
2484 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_TCP);
2485 if (sock->conn->pcb.tcp->state == LISTEN) {
2490 if (*(
const int*)optval) {
2491 tcp_nagle_disable(sock->conn->pcb.tcp);
2493 tcp_nagle_enable(sock->conn->pcb.tcp);
2496 s, (*(
const int *)optval)?
"on":
"off") );
2499 sock->conn->pcb.tcp->keep_idle = (u32_t)(*(
const int*)optval);
2501 s, sock->conn->pcb.tcp->keep_idle));
2504 #if LWIP_TCP_KEEPALIVE 2506 sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(
const int*)optval);
2508 s, sock->conn->pcb.tcp->keep_idle));
2511 sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(
const int*)optval);
2513 s, sock->conn->pcb.tcp->keep_intvl));
2516 sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(
const int*)optval);
2518 s, sock->conn->pcb.tcp->keep_cnt));
2535 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_TCP);
2536 if (*(
const int*)optval) {
2537 netconn_set_ipv6only(sock->conn, 1);
2539 netconn_set_ipv6only(sock->conn, 0);
2542 s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
2553 #if LWIP_UDP && LWIP_UDPLITE 2555 case IPPROTO_UDPLITE:
2557 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
2559 if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
2563 case UDPLITE_SEND_CSCOV:
2564 if ((*(
const int*)optval != 0) && ((*(
const int*)optval < 8) || (*(
const int*)optval > 0xffff))) {
2566 sock->conn->pcb.udp->chksum_len_tx = 8;
2568 sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(
const int*)optval;
2571 s, (*(
const int*)optval)) );
2573 case UDPLITE_RECV_CSCOV:
2574 if ((*(
const int*)optval != 0) && ((*(
const int*)optval < 8) || (*(
const int*)optval > 0xffff))) {
2576 sock->conn->pcb.udp->chksum_len_rx = 8;
2578 sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(
const int*)optval;
2581 s, (*(
const int*)optval)) );
2594 #if LWIP_IPV6 && LWIP_RAW 2598 if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) {
2602 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_RAW);
2603 if (*(
const int *)optval < 0) {
2604 sock->conn->pcb.raw->chksum_reqd = 0;
2605 }
else if (*(
const int *)optval & 1) {
2609 sock->conn->pcb.raw->chksum_reqd = 1;
2610 sock->conn->pcb.raw->chksum_offset = (u16_t)*(
const int *)optval;
2613 s, sock->conn->pcb.raw->chksum_reqd));
2625 s, level, optname));
2634 lwip_ioctl(
int s,
long cmd,
void *argp)
2636 struct lwip_sock *sock = get_socket(s);
2648 #if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE 2651 sock_set_errno(sock, EINVAL);
2654 #if LWIP_FIONREAD_LINUXMODE 2655 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
2657 if (sock->lastdata) {
2658 p = ((
struct netbuf *)sock->lastdata)->p;
2659 *((
int*)argp) = p->
tot_len - sock->lastoffset;
2661 struct netbuf *rxbuf;
2663 if (sock->rcvevent <= 0) {
2666 err = netconn_recv(sock->conn, &rxbuf);
2670 sock->lastdata = rxbuf;
2671 sock->lastoffset = 0;
2672 *((
int*)argp) = rxbuf->p->tot_len;
2682 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
2683 if (recv_avail < 0) {
2686 *((
int*)argp) = recv_avail;
2689 if (sock->lastdata) {
2690 struct pbuf *p = (
struct pbuf *)sock->lastdata;
2691 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
2692 p = ((
struct netbuf *)p)->p;
2695 buflen -= sock->lastoffset;
2697 *((
int*)argp) += buflen;
2701 sock_set_errno(sock, 0);
2710 if (argp && *(u32_t*)argp) {
2713 netconn_set_nonblocking(sock->conn, val);
2715 sock_set_errno(sock, 0);
2722 sock_set_errno(sock, ENOSYS);
2731 lwip_fcntl(
int s,
int cmd,
int val)
2733 struct lwip_sock *sock = get_socket(s);
2742 ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
2743 sock_set_errno(sock, 0);
2746 if ((val & ~O_NONBLOCK) == 0) {
2748 netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
2750 sock_set_errno(sock, 0);
2752 sock_set_errno(sock, ENOSYS);
2757 sock_set_errno(sock, ENOSYS);
2771 lwip_socket_register_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr)
2773 struct lwip_sock *sock = get_socket(s);
2780 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
2781 if (socket_ipv4_multicast_memberships[i].sock == NULL) {
2782 socket_ipv4_multicast_memberships[i].sock = sock;
2783 ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr);
2784 ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr);
2797 lwip_socket_unregister_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr)
2799 struct lwip_sock *sock = get_socket(s);
2806 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
2807 if ((socket_ipv4_multicast_memberships[i].sock == sock) &&
2808 ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) &&
2809 ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) {
2810 socket_ipv4_multicast_memberships[i].sock = NULL;
2811 ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
2812 ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
2823 lwip_socket_drop_registered_memberships(
int s)
2825 struct lwip_sock *sock = get_socket(s);
2832 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
2833 if (socket_ipv4_multicast_memberships[i].sock == sock) {
2834 ip_addr_t multi_addr, if_addr;
2835 ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr);
2836 ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr);
2837 socket_ipv4_multicast_memberships[i].sock = NULL;
2838 ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
2839 ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
2841 netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE);
void sys_sem_free(sys_sem_t *sem)
#define ip_reset_option(pcb, opt)
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
#define SYS_ARCH_DECL_PROTECT(lev)
#define tcpip_callback(f, ctx)
u16_t inet_chksum_pbuf(struct pbuf *p)
#define LWIP_SOCKET_OFFSET
void pbuf_cat(struct pbuf *h, struct pbuf *t)
void sys_sem_signal(sys_sem_t *sem)
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
#define LWIP_DEBUGF(debug, message)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
#define LWIP_UNUSED_ARG(x)
#define LWIP_MPU_COMPATIBLE
#define LWIP_CONST_CAST(target_type, val)
u8_t pbuf_free(struct pbuf *p)
#define ip_set_option(pcb, opt)
#define ip_get_option(pcb, opt)