63 #if LWIP_CHECKSUM_ON_COPY
73 #define LWIP_NETCONN 1
78 #define LWIP_NETCONN 0
82 #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
83 (sin)->sin_len = sizeof(struct sockaddr_in); \
84 (sin)->sin_family = AF_INET; \
85 (sin)->sin_port = lwip_htons((port)); \
86 inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
87 memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
88 #define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
89 inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
90 (port) = lwip_ntohs((sin)->sin_port); }while(0)
94 #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \
95 (sin6)->sin6_len = sizeof(struct sockaddr_in6); \
96 (sin6)->sin6_family = AF_INET6; \
97 (sin6)->sin6_port = lwip_htons((port)); \
98 (sin6)->sin6_flowinfo = 0; \
99 inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \
100 (sin6)->sin6_scope_id = 0; }while(0)
101 #define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \
102 inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \
103 (port) = lwip_ntohs((sin6)->sin6_port); }while(0)
106 #if LWIP_IPV4 && LWIP_IPV6
107 static void sockaddr_to_ipaddr_port(
const struct sockaddr* sockaddr,
ip_addr_t* ipaddr,
u16_t* port);
109 #define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \
110 ((namelen) == sizeof(struct sockaddr_in6)))
111 #define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \
112 ((name)->sa_family == AF_INET6))
113 #define SOCK_ADDR_TYPE_MATCH(name, sock) \
114 ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \
115 (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type))))
116 #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \
117 if (IP_IS_V6(ipaddr)) { \
118 IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \
120 IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \
122 #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port))
123 #define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \
124 (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6))
126 #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6))
127 #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6)
128 #define SOCK_ADDR_TYPE_MATCH(name, sock) 1
129 #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
130 IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port)
131 #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
132 SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port)
133 #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
135 #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in))
136 #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET)
137 #define SOCK_ADDR_TYPE_MATCH(name, sock) 1
138 #define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \
139 IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port)
140 #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \
141 SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port)
142 #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type)
145 #define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \
146 IS_SOCK_ADDR_TYPE_VALID(name))
147 #define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \
148 SOCK_ADDR_TYPE_MATCH(name, sock))
149 #define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0)
152 #define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0)
153 #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \
154 LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \
155 if ((sock)->conn == NULL) { return EINVAL; } }while(0)
156 #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \
157 LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \
158 if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0)
159 #define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \
160 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \
161 if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0)
164 #define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name)
165 #define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name)
166 #define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name)
167 #if LWIP_MPU_COMPATIBLE
168 #define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \
169 name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \
170 if (name == NULL) { \
171 sock_set_errno(sock, ENOMEM); \
175 #define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock)
178 #if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
179 #define LWIP_SO_SNDRCVTIMEO_OPTTYPE int
180 #define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val))
181 #define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval))
183 #define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval
184 #define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \
186 ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \
187 ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0)
188 #define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U))
191 #define NUM_SOCKETS MEMP_NUM_NETCONN
197 #define SELWAIT_T u8_t
203 struct netconn *conn;
219 SELWAIT_T select_waiting;
222 #if LWIP_NETCONN_SEM_PER_THREAD
223 #define SELECT_SEM_T sys_sem_t*
224 #define SELECT_SEM_PTR(sem) (sem)
226 #define SELECT_SEM_T sys_sem_t
227 #define SELECT_SEM_PTR(sem) (&(sem))
231 struct lwip_select_cb {
233 struct lwip_select_cb *next;
235 struct lwip_select_cb *prev;
251 union sockaddr_aligned {
254 struct sockaddr_in6 sin6;
257 struct sockaddr_in sin;
263 #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS
264 #define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS
269 struct lwip_socket_multicast_pair {
271 struct lwip_sock* sock;
275 ip4_addr_t multi_addr;
278 struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS];
280 static int lwip_socket_register_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr);
281 static void lwip_socket_unregister_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr);
282 static void lwip_socket_drop_registered_memberships(
int s);
286 static struct lwip_sock sockets[NUM_SOCKETS];
288 static struct lwip_select_cb *select_cb_list;
291 static volatile int select_cb_ctr;
293 #if LWIP_SOCKET_SET_ERRNO
295 #define set_errno(err) do { if (err) { errno = (err); } } while(0)
298 #define set_errno(err)
301 #define sock_set_errno(sk, e) do { \
302 const int sockerr = (e); \
303 sk->err = (u8_t)sockerr; \
304 set_errno(sockerr); \
308 static void event_callback(
struct netconn *conn,
enum netconn_evt evt,
u16_t len);
309 #if !LWIP_TCPIP_CORE_LOCKING
310 static void lwip_getsockopt_callback(
void *arg);
311 static void lwip_setsockopt_callback(
void *arg);
313 static u8_t lwip_getsockopt_impl(
int s,
int level,
int optname,
void *optval, socklen_t *optlen);
314 static u8_t lwip_setsockopt_impl(
int s,
int level,
int optname,
const void *optval, socklen_t optlen);
316 #if LWIP_IPV4 && LWIP_IPV6
318 sockaddr_to_ipaddr_port(
const struct sockaddr* sockaddr,
ip_addr_t* ipaddr,
u16_t* port)
320 if ((sockaddr->sa_family) == AF_INET6) {
321 SOCKADDR6_TO_IP6ADDR_PORT((
const struct sockaddr_in6*)(
const void*)(sockaddr), ipaddr, *port);
324 SOCKADDR4_TO_IP4ADDR_PORT((
const struct sockaddr_in*)(
const void*)(sockaddr), ipaddr, *port);
332 lwip_socket_thread_init(
void)
334 netconn_thread_init();
339 lwip_socket_thread_cleanup(
void)
341 netconn_thread_cleanup();
350 static struct lwip_sock *
353 struct lwip_sock *sock;
357 if ((s < 0) || (s >= NUM_SOCKETS)) {
380 static struct lwip_sock *
384 if ((s < 0) || (s >= NUM_SOCKETS)) {
387 if (!sockets[s].conn) {
402 alloc_socket(
struct netconn *newconn,
int accepted)
408 for (i = 0; i < NUM_SOCKETS; ++i) {
411 if (!sockets[i].conn && (sockets[i].select_waiting == 0)) {
412 sockets[i].conn = newconn;
416 sockets[i].lastdata =
NULL;
417 sockets[i].lastoffset = 0;
418 sockets[i].rcvevent = 0;
421 sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
422 sockets[i].errevent = 0;
438 free_socket(
struct lwip_sock *sock,
int is_tcp)
442 lastdata = sock->lastdata;
443 sock->lastdata =
NULL;
444 sock->lastoffset = 0;
451 if (lastdata !=
NULL) {
455 netbuf_delete((
struct netbuf *)lastdata);
467 lwip_accept(
int s,
struct sockaddr *addr, socklen_t *addrlen)
469 struct lwip_sock *sock, *nsock;
470 struct netconn *newconn;
478 sock = get_socket(s);
483 if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
490 err = netconn_accept(sock->conn, &newconn);
493 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
496 sock_set_errno(sock,
EINVAL);
504 newsock = alloc_socket(newconn, 1);
506 netconn_delete(newconn);
507 sock_set_errno(sock,
ENFILE);
511 LWIP_ASSERT(
"newconn->callback == event_callback", newconn->callback == event_callback);
520 nsock->rcvevent += (
s16_t)(-1 - newconn->socket);
521 newconn->socket = newsock;
528 union sockaddr_aligned tempaddr;
530 err = netconn_peer(newconn, &naddr, &port);
533 netconn_delete(newconn);
534 free_socket(nsock, 1);
540 IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port);
541 if (*addrlen > tempaddr.sa.sa_len) {
542 *addrlen = tempaddr.sa.sa_len;
544 MEMCPY(addr, &tempaddr, *addrlen);
553 sock_set_errno(sock, 0);
558 lwip_bind(
int s,
const struct sockaddr *
name, socklen_t namelen)
560 struct lwip_sock *sock;
565 sock = get_socket(s);
570 if (!SOCK_ADDR_TYPE_MATCH(
name, sock)) {
577 LWIP_ERROR(
"lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) &&
578 IS_SOCK_ADDR_TYPE_VALID(
name) && IS_SOCK_ADDR_ALIGNED(
name)),
582 SOCKADDR_TO_IPADDR_PORT(
name, &local_addr, local_port);
587 #if LWIP_IPV4 && LWIP_IPV6
590 unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr),
ip_2_ip6(&local_addr));
595 err = netconn_bind(sock->conn, &local_addr, local_port);
604 sock_set_errno(sock, 0);
611 struct lwip_sock *sock;
617 sock = get_socket(s);
622 if (sock->conn !=
NULL) {
623 is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
630 lwip_socket_drop_registered_memberships(s);
633 err = netconn_delete(sock->conn);
639 free_socket(sock, is_tcp);
645 lwip_connect(
int s,
const struct sockaddr *
name, socklen_t namelen)
647 struct lwip_sock *sock;
650 sock = get_socket(s);
655 if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(
name, sock)) {
662 if (
name->sa_family == AF_UNSPEC) {
664 err = netconn_disconnect(sock->conn);
670 LWIP_ERROR(
"lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) &&
671 IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(
name) && IS_SOCK_ADDR_ALIGNED(
name),
674 SOCKADDR_TO_IPADDR_PORT(
name, &remote_addr, remote_port);
679 #if LWIP_IPV4 && LWIP_IPV6
682 unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr),
ip_2_ip6(&remote_addr));
687 err = netconn_connect(sock->conn, &remote_addr, remote_port);
697 sock_set_errno(sock, 0);
710 lwip_listen(
int s,
int backlog)
712 struct lwip_sock *sock;
717 sock = get_socket(s);
725 err = netconn_listen_with_backlog(sock->conn, (
u8_t)backlog);
729 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
737 sock_set_errno(sock, 0);
742 lwip_recvfrom(
int s,
void *
mem,
size_t len,
int flags,
743 struct sockaddr *from, socklen_t *fromlen)
745 struct lwip_sock *sock;
748 u16_t buflen, copylen;
754 sock = get_socket(s);
762 if (sock->lastdata) {
763 buf = sock->lastdata;
766 if (((
flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
767 (sock->rcvevent <= 0)) {
770 sock_set_errno(sock, 0);
780 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
781 err = netconn_recv_tcp_pbuf(sock->conn, (
struct pbuf **)&
buf);
783 err = netconn_recv(sock->conn, (
struct netbuf **)&
buf);
792 event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0);
795 sock_set_errno(sock, 0);
809 sock->lastdata =
buf;
812 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
815 p = ((
struct netbuf *)
buf)->p;
819 buflen, len, off, sock->lastoffset));
821 buflen -= sock->lastoffset;
826 copylen = (
u16_t)len;
835 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
836 LWIP_ASSERT(
"invalid copylen, len would underflow", len >= copylen);
840 (sock->rcvevent <= 0) ||
841 ((flags & MSG_PEEK) != 0)) {
857 union sockaddr_aligned saddr;
859 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
861 netconn_getaddr(sock->conn, fromaddr, &port, 0);
863 port = netbuf_fromport((
struct netbuf *)
buf);
864 fromaddr = netbuf_fromaddr((
struct netbuf *)
buf);
867 #if LWIP_IPV4 && LWIP_IPV6
869 if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
IP_IS_V4(fromaddr)) {
870 ip4_2_ipv4_mapped_ipv6(
ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
875 IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
882 if (*fromlen > saddr.sa.sa_len) {
883 *fromlen = saddr.sa.sa_len;
885 MEMCPY(from, &saddr, *fromlen);
891 if ((flags & MSG_PEEK) == 0) {
895 if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) {
896 sock->lastdata =
buf;
897 sock->lastoffset += copylen;
900 sock->lastdata =
NULL;
901 sock->lastoffset = 0;
903 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
906 netbuf_delete((
struct netbuf *)
buf);
913 sock_set_errno(sock, 0);
918 lwip_read(
int s,
void *
mem,
size_t len)
924 lwip_recv(
int s,
void *
mem,
size_t len,
int flags)
926 return lwip_recvfrom(s,
mem, len, flags,
NULL,
NULL);
930 lwip_send(
int s,
const void *data,
size_t size,
int flags)
932 struct lwip_sock *sock;
938 s, data, size, flags));
940 sock = get_socket(s);
945 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
946 #if (LWIP_UDP || LWIP_RAW)
947 return lwip_sendto(s, data, size, flags,
NULL, 0);
954 write_flags = NETCONN_COPY |
955 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
956 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
958 err = netconn_write_partly(sock->conn, data, size, write_flags, &written);
962 return (err ==
ERR_OK ? (
int)written : -1);
966 lwip_sendmsg(
int s,
const struct msghdr *msg,
int flags)
968 struct lwip_sock *sock;
977 sock = get_socket(s);
988 LWIP_ERROR(
"lwip_sendmsg: invalid msghdr iov", (msg->msg_iov !=
NULL && msg->msg_iovlen != 0),
991 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
993 write_flags = NETCONN_COPY |
994 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
995 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
997 for (i = 0; i < msg->msg_iovlen; i++) {
998 u8_t apiflags = write_flags;
999 if (i + 1 < msg->msg_iovlen) {
1000 apiflags |= NETCONN_MORE;
1003 err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written);
1007 if (written != msg->msg_iov[i].iov_len)
1028 #if LWIP_UDP || LWIP_RAW
1030 struct netbuf *chain_buf;
1033 LWIP_ERROR(
"lwip_sendmsg: invalid msghdr name", (((msg->msg_name ==
NULL) && (msg->msg_namelen == 0)) ||
1034 IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) ,
1038 chain_buf = netbuf_new();
1043 if (msg->msg_name) {
1045 SOCKADDR_TO_IPADDR_PORT((
const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port);
1046 netbuf_fromport(chain_buf) = remote_port;
1048 #if LWIP_NETIF_TX_SINGLE_PBUF
1049 for (i = 0; i < msg->msg_iovlen; i++) {
1050 size += msg->msg_iov[i].iov_len;
1053 if (netbuf_alloc(chain_buf, (
u16_t)size) ==
NULL) {
1058 for (i = 0; i < msg->msg_iovlen; i++) {
1059 MEMCPY(&((
u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
1060 offset += msg->msg_iov[i].iov_len;
1062 #if LWIP_CHECKSUM_ON_COPY
1066 netbuf_set_chksum(chain_buf, chksum);
1074 for (i = 0; i < msg->msg_iovlen; i++) {
1080 p->
payload = msg->msg_iov[i].iov_base;
1081 LWIP_ASSERT(
"iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF);
1084 if (chain_buf->p ==
NULL) {
1085 chain_buf->p = chain_buf->ptr = p;
1093 size = netbuf_len(chain_buf);
1098 #if LWIP_IPV4 && LWIP_IPV6
1101 unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr),
ip_2_ip6(&chain_buf->addr));
1107 err = netconn_send(sock->conn, chain_buf);
1111 netbuf_delete(chain_buf);
1114 return (err ==
ERR_OK ? size : -1);
1123 lwip_sendto(
int s,
const void *data,
size_t size,
int flags,
1124 const struct sockaddr *to, socklen_t tolen)
1126 struct lwip_sock *sock;
1132 sock = get_socket(s);
1137 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
1139 return lwip_send(s, data, size, flags);
1148 LWIP_ASSERT(
"lwip_sendto: size must fit in u16_t", size <= 0xffff);
1149 short_size = (
u16_t)size;
1150 LWIP_ERROR(
"lwip_sendto: invalid address", (((to ==
NULL) && (tolen == 0)) ||
1151 (IS_SOCK_ADDR_LEN_VALID(tolen) &&
1152 IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))),
1158 #if LWIP_CHECKSUM_ON_COPY
1162 SOCKADDR_TO_IPADDR_PORT(to, &
buf.addr, remote_port);
1167 netbuf_fromport(&
buf) = remote_port;
1171 s, data, short_size, flags));
1176 #if LWIP_NETIF_TX_SINGLE_PBUF
1178 if (netbuf_alloc(&
buf, short_size) ==
NULL) {
1181 #if LWIP_CHECKSUM_ON_COPY
1182 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) {
1183 u16_t chksum = LWIP_CHKSUM_COPY(
buf.p->payload, data, short_size);
1184 netbuf_set_chksum(&
buf, chksum);
1188 MEMCPY(
buf.p->payload, data, short_size);
1193 err = netbuf_ref(&
buf, data, short_size);
1196 #if LWIP_IPV4 && LWIP_IPV6
1199 unmap_ipv4_mapped_ipv6(ip_2_ip4(&
buf.addr),
ip_2_ip6(&
buf.addr));
1205 err = netconn_send(sock->conn, &
buf);
1212 return (err ==
ERR_OK ? short_size : -1);
1216 lwip_socket(
int domain,
int type,
int protocol)
1218 struct netconn *conn;
1226 conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW),
1227 (
u8_t)protocol, event_callback);
1229 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1232 conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain,
1233 ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) ,
1236 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1239 conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback);
1241 domain == PF_INET ?
"PF_INET" :
"UNKNOWN", protocol));
1245 domain, type, protocol));
1256 i = alloc_socket(conn, 0);
1259 netconn_delete(conn);
1270 lwip_write(
int s,
const void *data,
size_t size)
1272 return lwip_send(s, data, size, 0);
1276 lwip_writev(
int s,
const struct iovec *iov,
int iovcnt)
1280 msg.msg_name =
NULL;
1281 msg.msg_namelen = 0;
1285 msg.msg_iovlen = iovcnt;
1286 msg.msg_control =
NULL;
1287 msg.msg_controllen = 0;
1289 return lwip_sendmsg(s, &msg, 0);
1307 lwip_selscan(
int maxfdp1,
fd_set *readset_in,
fd_set *writeset_in,
fd_set *exceptset_in,
1311 fd_set lreadset, lwriteset, lexceptset;
1312 struct lwip_sock *sock;
1323 if (!(readset_in &&
FD_ISSET(i, readset_in)) &&
1324 !(writeset_in &&
FD_ISSET(i, writeset_in)) &&
1325 !(exceptset_in &&
FD_ISSET(i, exceptset_in))) {
1330 sock = tryget_socket(i);
1332 void* lastdata = sock->lastdata;
1333 s16_t rcvevent = sock->rcvevent;
1334 u16_t sendevent = sock->sendevent;
1335 u16_t errevent = sock->errevent;
1340 if (readset_in &&
FD_ISSET(i, readset_in) && ((lastdata !=
NULL) || (rcvevent > 0))) {
1346 if (writeset_in &&
FD_ISSET(i, writeset_in) && (sendevent != 0)) {
1352 if (exceptset_in &&
FD_ISSET(i, exceptset_in) && (errevent != 0)) {
1363 *readset_out = lreadset;
1364 *writeset_out = lwriteset;
1365 *exceptset_out = lexceptset;
1374 fd_set lreadset, lwriteset, lexceptset;
1376 struct lwip_select_cb select_cb;
1379 #if LWIP_NETCONN_SEM_PER_THREAD
1385 maxfdp1, (
void *)readset, (
void *) writeset, (
void *) exceptset,
1391 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1395 if (timeout && timeout->
tv_sec == 0 && timeout->
tv_usec == 0) {
1399 goto return_copy_fdsets;
1407 select_cb.next =
NULL;
1408 select_cb.prev =
NULL;
1409 select_cb.readset = readset;
1410 select_cb.writeset = writeset;
1411 select_cb.exceptset = exceptset;
1412 select_cb.sem_signalled = 0;
1413 #if LWIP_NETCONN_SEM_PER_THREAD
1414 select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET();
1427 select_cb.next = select_cb_list;
1428 if (select_cb_list !=
NULL) {
1429 select_cb_list->prev = &select_cb;
1431 select_cb_list = &select_cb;
1441 if ((readset &&
FD_ISSET(i, readset)) ||
1442 (writeset &&
FD_ISSET(i, writeset)) ||
1443 (exceptset &&
FD_ISSET(i, exceptset))) {
1444 struct lwip_sock *sock;
1446 sock = tryget_socket(i);
1448 sock->select_waiting++;
1449 LWIP_ASSERT(
"sock->select_waiting > 0", sock->select_waiting > 0);
1464 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1471 msectimeout = ((timeout->
tv_sec * 1000) + ((timeout->
tv_usec + 500)/1000));
1472 if (msectimeout == 0) {
1479 #if LWIP_NETCONN_SEM_PER_THREAD
1487 if ((readset &&
FD_ISSET(i, readset)) ||
1488 (writeset &&
FD_ISSET(i, writeset)) ||
1489 (exceptset &&
FD_ISSET(i, exceptset))) {
1490 struct lwip_sock *sock;
1492 sock = tryget_socket(i);
1495 LWIP_ASSERT(
"sock->select_waiting > 0", sock->select_waiting > 0);
1496 if (sock->select_waiting > 0) {
1497 sock->select_waiting--;
1508 if (select_cb.next !=
NULL) {
1509 select_cb.next->prev = select_cb.prev;
1511 if (select_cb_list == &select_cb) {
1513 select_cb_list = select_cb.next;
1516 select_cb.prev->next = select_cb.next;
1522 #if LWIP_NETCONN_SEM_PER_THREAD
1523 if (select_cb.sem_signalled && (!waited || (waitres ==
SYS_ARCH_TIMEOUT))) {
1542 goto return_copy_fdsets;
1546 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1553 *readset = lreadset;
1556 *writeset = lwriteset;
1559 *exceptset = lexceptset;
1569 event_callback(
struct netconn *conn,
enum netconn_evt evt,
u16_t len)
1572 struct lwip_sock *sock;
1573 struct lwip_select_cb *scb;
1574 int last_select_cb_ctr;
1589 if (conn->socket < 0) {
1590 if (evt == NETCONN_EVT_RCVPLUS) {
1600 sock = get_socket(s);
1611 case NETCONN_EVT_RCVPLUS:
1614 case NETCONN_EVT_RCVMINUS:
1617 case NETCONN_EVT_SENDPLUS:
1618 sock->sendevent = 1;
1620 case NETCONN_EVT_SENDMINUS:
1621 sock->sendevent = 0;
1623 case NETCONN_EVT_ERROR:
1631 if (sock->select_waiting == 0) {
1644 for (scb = select_cb_list; scb !=
NULL; scb = scb->next) {
1646 last_select_cb_ctr = select_cb_ctr;
1647 if (scb->sem_signalled == 0) {
1651 if (sock->rcvevent > 0) {
1652 if (scb->readset &&
FD_ISSET(s, scb->readset)) {
1656 if (sock->sendevent != 0) {
1657 if (!do_signal && scb->writeset &&
FD_ISSET(s, scb->writeset)) {
1661 if (sock->errevent != 0) {
1662 if (!do_signal && scb->exceptset &&
FD_ISSET(s, scb->exceptset)) {
1667 scb->sem_signalled = 1;
1677 if (last_select_cb_ctr != select_cb_ctr) {
1689 lwip_shutdown(
int s,
int how)
1691 struct lwip_sock *sock;
1693 u8_t shut_rx = 0, shut_tx = 0;
1697 sock = get_socket(s);
1702 if (sock->conn !=
NULL) {
1703 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
1712 if (how == SHUT_RD) {
1714 }
else if (how == SHUT_WR) {
1716 }
else if (how == SHUT_RDWR) {
1720 sock_set_errno(sock,
EINVAL);
1723 err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
1726 return (err ==
ERR_OK ? 0 : -1);
1730 lwip_getaddrname(
int s,
struct sockaddr *
name, socklen_t *namelen,
u8_t local)
1732 struct lwip_sock *sock;
1733 union sockaddr_aligned saddr;
1738 sock = get_socket(s);
1744 err = netconn_getaddr(sock->conn, &naddr, &port, local);
1750 #if LWIP_IPV4 && LWIP_IPV6
1752 if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) &&
1754 ip4_2_ipv4_mapped_ipv6(
ip_2_ip6(&naddr), ip_2_ip4(&naddr));
1759 IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port);
1765 if (*namelen > saddr.sa.sa_len) {
1766 *namelen = saddr.sa.sa_len;
1770 sock_set_errno(sock, 0);
1775 lwip_getpeername(
int s,
struct sockaddr *
name, socklen_t *namelen)
1777 return lwip_getaddrname(s,
name, namelen, 0);
1781 lwip_getsockname(
int s,
struct sockaddr *
name, socklen_t *namelen)
1783 return lwip_getaddrname(s,
name, namelen, 1);
1787 lwip_getsockopt(
int s,
int level,
int optname,
void *optval, socklen_t *optlen)
1790 struct lwip_sock *sock = get_socket(s);
1791 #if !LWIP_TCPIP_CORE_LOCKING
1792 LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
1799 if ((
NULL == optval) || (
NULL == optlen)) {
1800 sock_set_errno(sock,
EFAULT);
1804 #if LWIP_TCPIP_CORE_LOCKING
1807 err = lwip_getsockopt_impl(s, level, optname, optval, optlen);
1812 #if LWIP_MPU_COMPATIBLE
1814 if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
1815 sock_set_errno(sock,
ENOBUFS);
1820 LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
1821 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
1822 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
1823 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
1824 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen;
1825 #if !LWIP_MPU_COMPATIBLE
1826 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval;
1828 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
1829 #if LWIP_NETCONN_SEM_PER_THREAD
1830 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
1832 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
1834 err =
tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
1836 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
1843 *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen;
1844 #if LWIP_MPU_COMPATIBLE
1845 MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval,
1846 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen);
1850 err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
1851 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
1854 sock_set_errno(sock, err);
1855 return err ? -1 : 0;
1858 #if !LWIP_TCPIP_CORE_LOCKING
1863 lwip_getsockopt_callback(
void *arg)
1865 struct lwip_setgetsockopt_data *data;
1867 data = (
struct lwip_setgetsockopt_data*)arg;
1869 data->err = lwip_getsockopt_impl(data->s, data->level, data->optname,
1885 lwip_getsockopt_impl(
int s,
int level,
int optname,
void *optval, socklen_t *optlen)
1888 struct lwip_sock *sock = tryget_socket(s);
1901 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
1902 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) {
1905 if ((sock->conn->pcb.tcp !=
NULL) && (sock->conn->pcb.tcp->state == LISTEN)) {
1919 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
1922 s, optname, (*(
int*)optval?
"on":
"off")));
1926 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
1927 switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) {
1929 *(
int*)optval = SOCK_RAW;
1932 *(
int*)optval = SOCK_STREAM;
1935 *(
int*)optval = SOCK_DGRAM;
1938 *(
int*)optval = netconn_type(sock->conn);
1940 (
"lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
1941 s, *(
int *)optval));
1944 s, *(
int *)optval));
1948 LWIP_SOCKOPT_CHECK_OPTLEN(*optlen,
int);
1950 if (((sock->err == 0) || (sock->err ==
EINPROGRESS)) && (sock->conn !=
NULL)) {
1951 sock_set_errno(sock,
err_to_errno(sock->conn->last_err));
1953 *(
int *)optval = (sock->err == 0xFF ? (
int)-1 : (int)sock->err);
1956 s, *(
int *)optval));
1959 #if LWIP_SO_SNDTIMEO
1961 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
1962 LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn));
1965 #if LWIP_SO_RCVTIMEO
1967 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
1968 LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn));
1973 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
1974 *(
int *)optval = netconn_get_recvbufsize(sock->conn);
1981 struct linger* linger = (
struct linger*)optval;
1982 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
struct linger);
1983 conn_linger = sock->conn->linger;
1984 if (conn_linger >= 0) {
1985 linger->l_onoff = 1;
1986 linger->l_linger = (int)conn_linger;
1988 linger->l_onoff = 0;
1989 linger->l_linger = 0;
1996 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_UDP);
1998 if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
2003 *(
int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
2018 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
2019 *(
int*)optval = sock->conn->pcb.ip->ttl;
2021 s, *(
int *)optval));
2024 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
2025 *(
int*)optval = sock->conn->pcb.ip->tos;
2027 s, *(
int *)optval));
2029 #if LWIP_MULTICAST_TX_OPTIONS
2030 case IP_MULTICAST_TTL:
2031 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
u8_t);
2032 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
2035 *(
u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp);
2037 s, *(
int *)optval));
2039 case IP_MULTICAST_IF:
2040 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
struct in_addr);
2041 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) {
2044 inet_addr_from_ip4addr((
struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp));
2046 s, *(
u32_t *)optval));
2048 case IP_MULTICAST_LOOP:
2049 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
u8_t);
2050 if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
2056 s, *(
int *)optval));
2071 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_TCP);
2072 if (sock->conn->pcb.tcp->state == LISTEN) {
2077 *(
int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
2079 s, (*(
int*)optval)?
"on":
"off") );
2082 *(
int*)optval = (
int)sock->conn->pcb.tcp->keep_idle;
2084 s, *(
int *)optval));
2087 #if LWIP_TCP_KEEPALIVE
2089 *(
int*)optval = (
int)(sock->conn->pcb.tcp->keep_idle/1000);
2091 s, *(
int *)optval));
2094 *(
int*)optval = (
int)(sock->conn->pcb.tcp->keep_intvl/1000);
2096 s, *(
int *)optval));
2099 *(
int*)optval = (
int)sock->conn->pcb.tcp->keep_cnt;
2101 s, *(
int *)optval));
2118 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen,
int);
2119 *(
int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0);
2121 s, *(
int *)optval));
2132 #if LWIP_UDP && LWIP_UDPLITE
2134 case IPPROTO_UDPLITE:
2136 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen,
int);
2138 if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
2142 case UDPLITE_SEND_CSCOV:
2143 *(
int*)optval = sock->conn->pcb.udp->chksum_len_tx;
2145 s, (*(
int*)optval)) );
2147 case UDPLITE_RECV_CSCOV:
2148 *(
int*)optval = sock->conn->pcb.udp->chksum_len_rx;
2150 s, (*(
int*)optval)) );
2163 #if LWIP_IPV6 && LWIP_RAW
2165 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen,
int, NETCONN_RAW);
2166 if (sock->conn->pcb.raw->chksum_reqd == 0) {
2167 *(
int *)optval = -1;
2169 *(
int *)optval = sock->conn->pcb.raw->chksum_offset;
2172 s, (*(
int*)optval)) );
2184 s, level, optname));
2193 lwip_setsockopt(
int s,
int level,
int optname,
const void *optval, socklen_t optlen)
2196 struct lwip_sock *sock = get_socket(s);
2197 #if !LWIP_TCPIP_CORE_LOCKING
2198 kprintf(
"%s:%i: %i", __FILE__, __LINE__, err);
2199 LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
2206 if (
NULL == optval) {
2207 sock_set_errno(sock,
EFAULT);
2211 #if LWIP_TCPIP_CORE_LOCKING
2212 kprintf(
"%s:%i: %i", __FILE__, __LINE__, err);
2215 err = lwip_setsockopt_impl(s, level, optname, optval, optlen);
2218 kprintf(
"%s:%i: %i", __FILE__, __LINE__, err);
2221 #if LWIP_MPU_COMPATIBLE
2222 kprintf(
"%s:%i: %i", __FILE__, __LINE__, err);
2224 if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) {
2225 sock_set_errno(sock,
ENOBUFS);
2226 kprintf(
"%s:%i: %i", __FILE__, __LINE__, err);
2229 kprintf(
"%s:%i: %i", __FILE__, __LINE__, err);
2232 LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock);
2233 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s;
2234 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level;
2235 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname;
2236 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen;
2237 #if LWIP_MPU_COMPATIBLE
2238 MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen);
2240 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (
const void*)optval;
2242 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0;
2243 #if LWIP_NETCONN_SEM_PER_THREAD
2244 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
2246 LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed;
2248 err =
tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data));
2250 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
2257 err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err;
2258 LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data);
2261 kprintf(
"%s:%i: %i", __FILE__, __LINE__, err);
2263 sock_set_errno(sock, err);
2264 return err ? -1 : 0;
2267 #if !LWIP_TCPIP_CORE_LOCKING
2272 lwip_setsockopt_callback(
void *arg)
2274 struct lwip_setgetsockopt_data *data;
2276 data = (
struct lwip_setgetsockopt_data*)arg;
2278 data->err = lwip_setsockopt_impl(data->s, data->level, data->optname,
2294 lwip_setsockopt_impl(
int s,
int level,
int optname,
const void *optval, socklen_t optlen)
2297 struct lwip_sock *sock = tryget_socket(s);
2316 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
2317 if (*(
const int*)optval) {
2323 s, optname, (*(
const int*)optval?
"on":
"off")));
2329 #if LWIP_SO_SNDTIMEO
2331 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
2332 netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
2335 #if LWIP_SO_RCVTIMEO
2337 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE);
2338 netconn_set_recvtimeout(sock->conn, (
int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval));
2343 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen,
int);
2344 netconn_set_recvbufsize(sock->conn, *(
const int*)optval);
2350 const struct linger* linger = (
const struct linger*)optval;
2351 LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen,
struct linger);
2352 if (linger->l_onoff) {
2353 int lingersec = linger->l_linger;
2354 if (lingersec < 0) {
2357 if (lingersec > 0xFFFF) {
2360 sock->conn->linger = (
s16_t)lingersec;
2362 sock->conn->linger = -1;
2369 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_UDP);
2371 if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) {
2376 if (*(
const int*)optval) {
2377 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
2379 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
2395 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
2396 sock->conn->pcb.ip->ttl = (
u8_t)(*(
const int*)optval);
2398 s, sock->conn->pcb.ip->ttl));
2401 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
2402 sock->conn->pcb.ip->tos = (
u8_t)(*(
const int*)optval);
2404 s, sock->conn->pcb.ip->tos));
2406 #if LWIP_MULTICAST_TX_OPTIONS
2407 case IP_MULTICAST_TTL:
2408 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
u8_t, NETCONN_UDP);
2409 udp_set_multicast_ttl(sock->conn->pcb.udp, (
u8_t)(*(
const u8_t*)optval));
2411 case IP_MULTICAST_IF:
2414 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
struct in_addr, NETCONN_UDP);
2415 inet_addr_to_ip4addr(&if_addr, (
const struct in_addr*)optval);
2416 udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr);
2419 case IP_MULTICAST_LOOP:
2420 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
u8_t, NETCONN_UDP);
2421 if (*(
const u8_t*)optval) {
2422 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
2424 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
2429 case IP_ADD_MEMBERSHIP:
2430 case IP_DROP_MEMBERSHIP:
2435 const struct ip_mreq *imr = (
const struct ip_mreq *)optval;
2437 ip4_addr_t multi_addr;
2438 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
struct ip_mreq, NETCONN_UDP);
2439 inet_addr_to_ip4addr(&if_addr, &imr->imr_interface);
2440 inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr);
2441 if (optname == IP_ADD_MEMBERSHIP) {
2442 if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) {
2447 igmp_err = igmp_joingroup(&if_addr, &multi_addr);
2450 igmp_err = igmp_leavegroup(&if_addr, &multi_addr);
2451 lwip_socket_unregister_membership(s, &if_addr, &multi_addr);
2453 if (igmp_err !=
ERR_OK) {
2471 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_TCP);
2472 if (sock->conn->pcb.tcp->state == LISTEN) {
2477 if (*(
const int*)optval) {
2478 tcp_nagle_disable(sock->conn->pcb.tcp);
2480 tcp_nagle_enable(sock->conn->pcb.tcp);
2483 s, (*(
const int *)optval)?
"on":
"off") );
2486 sock->conn->pcb.tcp->keep_idle = (
u32_t)(*(
const int*)optval);
2488 s, sock->conn->pcb.tcp->keep_idle));
2491 #if LWIP_TCP_KEEPALIVE
2493 sock->conn->pcb.tcp->keep_idle = 1000*(
u32_t)(*(
const int*)optval);
2495 s, sock->conn->pcb.tcp->keep_idle));
2498 sock->conn->pcb.tcp->keep_intvl = 1000*(
u32_t)(*(
const int*)optval);
2500 s, sock->conn->pcb.tcp->keep_intvl));
2503 sock->conn->pcb.tcp->keep_cnt = (
u32_t)(*(
const int*)optval);
2505 s, sock->conn->pcb.tcp->keep_cnt));
2522 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_TCP);
2523 if (*(
const int*)optval) {
2524 netconn_set_ipv6only(sock->conn, 1);
2526 netconn_set_ipv6only(sock->conn, 0);
2529 s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
2540 #if LWIP_UDP && LWIP_UDPLITE
2542 case IPPROTO_UDPLITE:
2544 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen,
int);
2546 if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) {
2550 case UDPLITE_SEND_CSCOV:
2551 if ((*(
const int*)optval != 0) && ((*(
const int*)optval < 8) || (*(
const int*)optval > 0xffff))) {
2553 sock->conn->pcb.udp->chksum_len_tx = 8;
2555 sock->conn->pcb.udp->chksum_len_tx = (
u16_t)*(
const int*)optval;
2558 s, (*(
const int*)optval)) );
2560 case UDPLITE_RECV_CSCOV:
2561 if ((*(
const int*)optval != 0) && ((*(
const int*)optval < 8) || (*(
const int*)optval > 0xffff))) {
2563 sock->conn->pcb.udp->chksum_len_rx = 8;
2565 sock->conn->pcb.udp->chksum_len_rx = (
u16_t)*(
const int*)optval;
2568 s, (*(
const int*)optval)) );
2581 #if LWIP_IPV6 && LWIP_RAW
2585 if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) {
2589 LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen,
int, NETCONN_RAW);
2590 if (*(
const int *)optval < 0) {
2591 sock->conn->pcb.raw->chksum_reqd = 0;
2592 }
else if (*(
const int *)optval & 1) {
2596 sock->conn->pcb.raw->chksum_reqd = 1;
2597 sock->conn->pcb.raw->chksum_offset = (
u16_t)*(
const int *)optval;
2600 s, sock->conn->pcb.raw->chksum_reqd));
2612 s, level, optname));
2621 lwip_ioctl(
int s,
long cmd,
void *argp)
2623 struct lwip_sock *sock = get_socket(s);
2635 #if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE
2638 sock_set_errno(sock,
EINVAL);
2641 #if LWIP_FIONREAD_LINUXMODE
2642 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
2644 if (sock->lastdata) {
2645 p = ((
struct netbuf *)sock->lastdata)->p;
2646 *((
int*)argp) = p->
tot_len - sock->lastoffset;
2648 struct netbuf *rxbuf;
2650 if (sock->rcvevent <= 0) {
2653 err = netconn_recv(sock->conn, &rxbuf);
2657 sock->lastdata = rxbuf;
2658 sock->lastoffset = 0;
2659 *((
int*)argp) = rxbuf->p->tot_len;
2670 if (recv_avail < 0) {
2673 *((
int*)argp) = recv_avail;
2676 if (sock->lastdata) {
2677 struct pbuf *p = (
struct pbuf *)sock->lastdata;
2678 if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) {
2679 p = ((
struct netbuf *)p)->p;
2682 buflen -= sock->lastoffset;
2684 *((
int*)argp) += buflen;
2688 sock_set_errno(sock, 0);
2697 if (argp && *(
u32_t*)argp) {
2700 netconn_set_nonblocking(sock->conn, val);
2702 sock_set_errno(sock, 0);
2709 sock_set_errno(sock,
ENOSYS);
2718 lwip_fcntl(
int s,
int cmd,
int val)
2720 struct lwip_sock *sock = get_socket(s);
2729 ret = netconn_is_nonblocking(sock->conn) ?
O_NONBLOCK : 0;
2730 sock_set_errno(sock, 0);
2735 netconn_set_nonblocking(sock->conn, val &
O_NONBLOCK);
2737 sock_set_errno(sock, 0);
2739 sock_set_errno(sock,
ENOSYS);
2744 sock_set_errno(sock,
ENOSYS);
2758 lwip_socket_register_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr)
2760 struct lwip_sock *sock = get_socket(s);
2767 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
2768 if (socket_ipv4_multicast_memberships[i].sock ==
NULL) {
2769 socket_ipv4_multicast_memberships[i].sock = sock;
2770 ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr);
2771 ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr);
2784 lwip_socket_unregister_membership(
int s,
const ip4_addr_t *if_addr,
const ip4_addr_t *multi_addr)
2786 struct lwip_sock *sock = get_socket(s);
2793 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
2794 if ((socket_ipv4_multicast_memberships[i].sock == sock) &&
2795 ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) &&
2796 ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) {
2797 socket_ipv4_multicast_memberships[i].sock =
NULL;
2798 ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
2799 ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
2810 lwip_socket_drop_registered_memberships(
int s)
2812 struct lwip_sock *sock = get_socket(s);
2819 for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) {
2820 if (socket_ipv4_multicast_memberships[i].sock == sock) {
2822 ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr);
2823 ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr);
2824 socket_ipv4_multicast_memberships[i].sock =
NULL;
2825 ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr);
2826 ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr);
2828 netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE);