81#if LWIP_CHECKSUM_ON_COPY
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
125static 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))
249struct lwip_select_cb {
251 struct lwip_select_cb *next;
253 struct lwip_select_cb *prev;
269union 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
287struct lwip_socket_multicast_pair {
289 struct lwip_sock* sock;
293 ip4_addr_t multi_addr;
296struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
298static int lwip_socket_register_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr);
299static void lwip_socket_unregister_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr);
300static void lwip_socket_drop_registered_memberships(
int s);
304static struct lwip_sock sockets[NUM_SOCKETS];
306static struct lwip_select_cb *select_cb_list;
309static 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); \
326static void event_callback(
struct netconn *conn,
enum netconn_evt evt, u16_t len);
327#if !LWIP_TCPIP_CORE_LOCKING
328static void lwip_getsockopt_callback(
void *arg);
329static void lwip_setsockopt_callback(
void *arg);
331static u8_t lwip_getsockopt_impl(
int s,
int level,
int optname,
void *optval, socklen_t *optlen);
332static u8_t lwip_setsockopt_impl(
int s,
int level,
int optname,
const void *optval, socklen_t optlen);
334#if LWIP_IPV4 && LWIP_IPV6
336sockaddr_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);
350lwip_socket_thread_init(
void)
352 netconn_thread_init();
357lwip_socket_thread_cleanup(
void)
359 netconn_thread_cleanup();
368static struct lwip_sock *
371 struct lwip_sock *sock;
375 if ((s < 0) || (s >= NUM_SOCKETS)) {
398static struct lwip_sock *
402 if ((s < 0) || (s >= NUM_SOCKETS)) {
405 if (!sockets[s].conn) {
420alloc_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);
456free_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);
485lwip_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);
576lwip_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);
663lwip_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);
728lwip_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);
760lwip_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);
936lwip_read(
int s,
void *
mem,
size_t len)
938 return lwip_recvfrom(s,
mem, len, 0, NULL, NULL);
942lwip_recv(
int s,
void *
mem,
size_t len,
int flags)
944 return lwip_recvfrom(s,
mem, len, flags, NULL, NULL);
948lwip_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);
984lwip_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
1083 u16_t chksum = ~inet_chksum_pbuf(chain_buf->p);
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));
1141lwip_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);
1234lwip_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);
1288lwip_write(
int s,
const void *data,
size_t size)
1290 return lwip_send(s, data, size, 0);
1294lwip_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);
1325lwip_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);
1390lwip_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;
1590event_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);
1710lwip_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);
1751lwip_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);
1796lwip_getpeername(
int s,
struct sockaddr *name, socklen_t *namelen)
1798 return lwip_getaddrname(s, name, namelen, 0);
1802lwip_getsockname(
int s,
struct sockaddr *name, socklen_t *namelen)
1804 return lwip_getaddrname(s, name, namelen, 1);
1808lwip_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
1884lwip_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,
1906lwip_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));
1982 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
1983 LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn));
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));
2214lwip_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
2285lwip_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,
2307lwip_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")));
2344 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
2345 netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
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));
2634lwip_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);
2731lwip_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);
2771lwip_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);
2797lwip_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);
2823lwip_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);
#define LWIP_DEBUGF(debug, message)
#define LWIP_UNUSED_ARG(x)
#define LWIP_CONST_CAST(target_type, val)
#define LWIP_MPU_COMPATIBLE
#define LWIP_SOCKET_OFFSET
void pbuf_cat(struct pbuf *h, struct pbuf *t)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
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_set_option(pcb, opt)
#define ip_get_option(pcb, opt)
#define ip_reset_option(pcb, opt)
#define SYS_ARCH_DECL_PROTECT(lev)
#define tcpip_callback(f, ctx)