BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 #include "test_sockets.h"
2  
3 #include "lwip/mem.h"
4 #include "lwip/opt.h"
5 #include "lwip/sockets.h"
6 #include "lwip/priv/sockets_priv.h"
7 #include "lwip/stats.h"
8  
9 #include "lwip/tcpip.h"
10 #include "lwip/priv/tcp_priv.h"
11 #include "lwip/api.h"
12  
13  
14 static int
15 test_sockets_get_used_count(void)
16 {
17 int used = 0;
18 int i;
19  
20 for (i = 0; i < NUM_SOCKETS; i++) {
21 struct lwip_sock* s = lwip_socket_dbg_get_socket(i);
22 if (s != NULL) {
23 if (s->fd_used) {
24 used++;
25 }
26 }
27 }
28 return used;
29 }
30  
31  
32 /* Setups/teardown functions */
33  
34 static void
35 sockets_setup(void)
36 {
37 /* expect full free heap */
38 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
39 }
40  
41 static void
42 sockets_teardown(void)
43 {
44 fail_unless(test_sockets_get_used_count() == 0);
45 /* poll until all memory is released... */
46 tcpip_thread_poll_one();
47 while (tcp_tw_pcbs) {
48 tcp_abort(tcp_tw_pcbs);
49 tcpip_thread_poll_one();
50 }
51 tcpip_thread_poll_one();
52 /* ensure full free heap */
53 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
54 }
55  
56 #ifndef NUM_SOCKETS
57 #define NUM_SOCKETS MEMP_NUM_NETCONN
58 #endif
59  
60 #if LWIP_SOCKET
61 static int
62 test_sockets_alloc_socket_nonblocking(int domain, int type)
63 {
64 int s = lwip_socket(domain, type, 0);
65 if (s >= 0) {
66 int ret = lwip_fcntl(s, F_SETFL, O_NONBLOCK);
67 fail_unless(ret == 0);
68 }
69 return s;
70 }
71  
72 /* Verify basic sockets functionality
73 */
74 START_TEST(test_sockets_basics)
75 {
76 int s, i, ret;
77 int s2[NUM_SOCKETS];
78 LWIP_UNUSED_ARG(_i);
79  
80 s = lwip_socket(AF_INET, SOCK_STREAM, 0);
81 fail_unless(s >= 0);
82 lwip_close(s);
83  
84 for (i = 0; i < NUM_SOCKETS; i++) {
85 s2[i] = lwip_socket(AF_INET, SOCK_STREAM, 0);
86 fail_unless(s2[i] >= 0);
87 }
88  
89 /* all sockets used, now it should fail */
90 s = lwip_socket(AF_INET, SOCK_STREAM, 0);
91 fail_unless(s == -1);
92 /* close one socket */
93 ret = lwip_close(s2[0]);
94 fail_unless(ret == 0);
95 /* now it should succeed */
96 s2[0] = lwip_socket(AF_INET, SOCK_STREAM, 0);
97 fail_unless(s2[0] >= 0);
98  
99 /* close all sockets */
100 for (i = 0; i < NUM_SOCKETS; i++) {
101 ret = lwip_close(s2[i]);
102 fail_unless(ret == 0);
103 }
104 }
105 END_TEST
106  
107 static void test_sockets_allfunctions_basic_domain(int domain)
108 {
109 int s, s2, s3, ret;
110 struct sockaddr_storage addr, addr2;
111 socklen_t addrlen, addr2len;
112 /* listen socket */
113 s = lwip_socket(domain, SOCK_STREAM, 0);
114 fail_unless(s >= 0);
115  
116 ret = lwip_listen(s, 0);
117 fail_unless(ret == 0);
118  
119 addrlen = sizeof(addr);
120 ret = lwip_getsockname(s, (struct sockaddr*)&addr, &addrlen);
121 fail_unless(ret == 0);
122  
123 s2 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
124 fail_unless(s2 >= 0);
125 /* nonblocking connect s2 to s (but use loopback address) */
126 if (domain == AF_INET) {
127 #if LWIP_IPV4
128 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
129 addr4->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
130 #endif
131 } else {
132 #if LWIP_IPV6
133 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
134 struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
135 addr6->sin6_addr = lo6;
136 #endif
137 }
138 ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
139 fail_unless(ret == -1);
140 fail_unless(errno == EINPROGRESS);
141 ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
142 fail_unless(ret == -1);
143 fail_unless(errno == EALREADY);
144  
145 while(tcpip_thread_poll_one());
146  
147 s3 = lwip_accept(s, (struct sockaddr*)&addr2, &addr2len);
148 fail_unless(s3 >= 0);
149  
150 ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
151 fail_unless(ret == -1);
152 fail_unless(errno == EISCONN);
153  
154 ret = lwip_close(s);
155 fail_unless(ret == 0);
156 ret = lwip_close(s2);
157 fail_unless(ret == 0);
158 ret = lwip_close(s3);
159 fail_unless(ret == 0);
160 }
161  
162 /* Try to step through all sockets functions once...
163 */
164 START_TEST(test_sockets_allfunctions_basic)
165 {
166 LWIP_UNUSED_ARG(_i);
167 #if LWIP_IPV4
168 test_sockets_allfunctions_basic_domain(AF_INET);
169 #endif
170 #if LWIP_IPV6
171 test_sockets_allfunctions_basic_domain(AF_INET6);
172 #endif
173 }
174 END_TEST
175  
176 static void test_sockets_init_loopback_addr(int domain, struct sockaddr_storage *addr_st, socklen_t *sz)
177 {
178 memset(addr_st, 0, sizeof(*addr_st));
179 switch(domain) {
180 #if LWIP_IPV6
181 case AF_INET6: {
182 struct sockaddr_in6 *addr = (struct sockaddr_in6*)addr_st;
183 struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
184 addr->sin6_family = AF_INET6;
185 addr->sin6_port = 0; /* use ephemeral port */
186 addr->sin6_addr = lo6;
187 *sz = sizeof(*addr);
188 }
189 break;
190 #endif /* LWIP_IPV6 */
191 #if LWIP_IPV4
192 case AF_INET: {
193 struct sockaddr_in *addr = (struct sockaddr_in*)addr_st;
194 addr->sin_family = AF_INET;
195 addr->sin_port = 0; /* use ephemeral port */
196 addr->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
197 *sz = sizeof(*addr);
198 }
199 break;
200 #endif /* LWIP_IPV4 */
201 default:
202 *sz = 0;
203 fail();
204 break;
205 }
206 }
207  
208 static void test_sockets_msgapi_update_iovs(struct msghdr *msg, size_t bytes)
209 {
210 int i;
211  
212 /* note: this modifies the underyling iov_base and iov_len for a partial
213 read for an individual vector. This updates the msg->msg_iov pointer
214 to skip fully consumed vecotrs */
215  
216 /* process fully consumed vectors */
217 for (i = 0; i < msg->msg_iovlen; i++) {
218 if (msg->msg_iov[i].iov_len <= bytes) {
219 /* reduce bytes by amount of this vector */
220 bytes -= msg->msg_iov[i].iov_len;
221 } else {
222 break; /* iov not fully consumed */
223 }
224 }
225  
226 /* slide down over fully consumed vectors */
227 msg->msg_iov = &msg->msg_iov[i];
228 msg->msg_iovlen -= i;
229  
230 /* update new first vector with any remaining amount */
231 msg->msg_iov[0].iov_base = ((u8_t *)msg->msg_iov[0].iov_base + bytes);
232 msg->msg_iov[0].iov_len -= bytes;
233 }
234  
235 static void test_sockets_msgapi_tcp(int domain)
236 {
237 #define BUF_SZ (TCP_SND_BUF/4)
238 #define TOTAL_DATA_SZ (BUF_SZ*8) /* ~(TCP_SND_BUF*2) that accounts for integer rounding */
239 #define NEED_TRAILER (BUF_SZ % 4 != 0)
240 int listnr, s1, s2, i, ret, opt;
241 int bytes_written, bytes_read;
242 struct sockaddr_storage addr_storage;
243 socklen_t addr_size;
244 struct iovec siovs[8];
245 struct msghdr smsg;
246 u8_t * snd_buf;
247 struct iovec riovs[5];
248 struct iovec riovs_tmp[5];
249 struct msghdr rmsg;
250 u8_t * rcv_buf;
251 int rcv_off;
252 int rcv_trailer = 0;
253 u8_t val;
254  
255 test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
256  
257 listnr = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
258 fail_unless(listnr >= 0);
259 s1 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
260 fail_unless(s1 >= 0);
261  
262 /* setup a listener socket on loopback with ephemeral port */
263 ret = lwip_bind(listnr, (struct sockaddr*)&addr_storage, addr_size);
264 fail_unless(ret == 0);
265 ret = lwip_listen(listnr, 0);
266 fail_unless(ret == 0);
267  
268 /* update address with ephemeral port */
269 ret = lwip_getsockname(listnr, (struct sockaddr*)&addr_storage, &addr_size);
270 fail_unless(ret == 0);
271  
272 /* connect, won't complete until we accept it */
273 ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size);
274 fail_unless(ret == -1);
275 fail_unless(errno == EINPROGRESS);
276  
277 while (tcpip_thread_poll_one());
278  
279 /* accept, creating the other side of the connection */
280 s2 = lwip_accept(listnr, NULL, NULL);
281 fail_unless(s2 >= 0);
282  
283 /* double check s1 is connected */
284 ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size);
285 fail_unless(ret == -1);
286 fail_unless(errno == EISCONN);
287  
288 /* set s2 to non-blocking, not inherited from listener */
289 opt = lwip_fcntl(s2, F_GETFL, 0);
290 fail_unless(opt == 6);
291 opt = O_NONBLOCK;
292 ret = lwip_fcntl(s2, F_SETFL, opt);
293 fail_unless(ret == 0);
294  
295 /* we are done with listener, close it */
296 ret = lwip_close(listnr);
297 fail_unless(ret == 0);
298  
299 /* allocate a buffer for a stream of incrementing hex (0x00..0xFF) which we will use
300 to create an input vector set that is larger than the TCP's send buffer. This will
301 force execution of the partial IO vector send case */
302 snd_buf = (u8_t*)mem_malloc(BUF_SZ);
303 val = 0x00;
304 fail_unless(snd_buf != NULL);
305 for (i = 0; i < BUF_SZ; i++,val++) {
306 snd_buf[i] = val;
307 }
308  
309 /* send the buffer 8 times in one message, equating to TOTAL_DATA_SZ */
310 for (i = 0; i < 8; i++) {
311 siovs[i].iov_base = snd_buf;
312 siovs[i].iov_len = BUF_SZ;
313 }
314  
315 /* allocate a receive buffer, same size as snd_buf for easy verification */
316 rcv_buf = (u8_t*)mem_calloc(1, BUF_SZ);
317 fail_unless(rcv_buf != NULL);
318 /* split across iovs */
319 for (i = 0; i < 4; i++) {
320 riovs[i].iov_base = &rcv_buf[i*(BUF_SZ/4)];
321 riovs[i].iov_len = BUF_SZ/4;
322 }
323 /* handling trailing bytes if buffer doesn't evenly divide by 4 */
324 #if NEED_TRAILER
325 if ((BUF_SZ % 4) != 0) {
326 riovs[5].iov_base = &rcv_buf[4*(BUF_SZ/4)];
327 riovs[5].iov_len = BUF_SZ - (4*(BUF_SZ/4));
328 rcv_trailer = 1;
329 }
330 #endif /* NEED_TRAILER */
331  
332 /* we use a copy of riovs since we'll be modifying base and len during
333 receiving. This gives us an easy way to reset the iovs for next recvmsg */
334 memcpy(riovs_tmp, riovs, sizeof(riovs));
335  
336 memset(&smsg, 0, sizeof(smsg));
337 smsg.msg_iov = siovs;
338 smsg.msg_iovlen = 8;
339  
340 memset(&rmsg, 0, sizeof(rmsg));
341 rmsg.msg_iov = riovs_tmp;
342 rmsg.msg_iovlen = (rcv_trailer ? 5 : 4);
343  
344 bytes_written = 0;
345 bytes_read = 0;
346 rcv_off = 0;
347  
348 while (bytes_written < TOTAL_DATA_SZ && (bytes_read < TOTAL_DATA_SZ)) {
349 /* send data */
350 if (bytes_written < TOTAL_DATA_SZ) {
351 ret = lwip_sendmsg(s1, &smsg, 0);
352 /* note: since we always receive after sending, there will be open
353 space in the send buffer */
354 fail_unless(ret > 0);
355  
356 bytes_written += ret;
357 if (bytes_written < TOTAL_DATA_SZ) {
358 test_sockets_msgapi_update_iovs(&smsg, (size_t)ret);
359 }
360 }
361  
362 while (tcpip_thread_poll_one());
363  
364 /* receive and verify data */
365 do {
366 if (bytes_read < TOTAL_DATA_SZ) {
367 ret = lwip_recvmsg(s2, &rmsg, 0);
368 fail_unless(ret > 0 || (ret == -1 && errno == EWOULDBLOCK));
369  
370 if (ret > 0) {
371 rcv_off += ret;
372 /* we have received a full buffer */
373 if (rcv_off == BUF_SZ) {
374 /* note: since iovs are just pointers, compare underlying buf */
375 fail_unless(!memcmp(snd_buf, rcv_buf, BUF_SZ));
376 bytes_read += BUF_SZ;
377 /* reset receive state for next buffer */
378 rcv_off = 0;
379 memset(rcv_buf, 0, BUF_SZ);
380 memcpy(riovs_tmp, riovs, sizeof(riovs));
381 rmsg.msg_iov = riovs_tmp;
382 rmsg.msg_iovlen = (rcv_trailer ? 5 : 4);
383 } else { /* partial read */
384 test_sockets_msgapi_update_iovs(&rmsg, (size_t)ret);
385 }
386 }
387 } else {
388 break;
389 }
390 } while(ret > 0);
391 }
392  
393 ret = lwip_close(s1);
394 fail_unless(ret == 0);
395 ret = lwip_close(s2);
396 fail_unless(ret == 0);
397 mem_free(snd_buf);
398 mem_free(rcv_buf);
399 }
400  
401 static void test_sockets_msgapi_udp_send_recv_loop(int s, struct msghdr *smsg, struct msghdr *rmsg)
402 {
403 int i, ret;
404  
405 /* send/receive our datagram of IO vectors 10 times */
406 for (i = 0; i < 10; i++) {
407 ret = lwip_sendmsg(s, smsg, 0);
408 fail_unless(ret == 4);
409  
410 while (tcpip_thread_poll_one());
411  
412 /* receive the datagram split across 4 buffers */
413 ret = lwip_recvmsg(s, rmsg, 0);
414 fail_unless(ret == 4);
415  
416 /* verify data */
417 fail_unless(*((u8_t*)rmsg->msg_iov[0].iov_base) == 0xDE);
418 fail_unless(*((u8_t*)rmsg->msg_iov[1].iov_base) == 0xAD);
419 fail_unless(*((u8_t*)rmsg->msg_iov[2].iov_base) == 0xBE);
420 fail_unless(*((u8_t*)rmsg->msg_iov[3].iov_base) == 0xEF);
421  
422 /* clear rcv_buf to ensure no data is being skipped */
423 *((u8_t*)rmsg->msg_iov[0].iov_base) = 0x00;
424 *((u8_t*)rmsg->msg_iov[1].iov_base) = 0x00;
425 *((u8_t*)rmsg->msg_iov[2].iov_base) = 0x00;
426 *((u8_t*)rmsg->msg_iov[3].iov_base) = 0x00;
427 }
428 }
429  
430 static void test_sockets_msgapi_udp(int domain)
431 {
432 int s, i, ret;
433 struct sockaddr_storage addr_storage;
434 socklen_t addr_size;
435 struct iovec riovs[4];
436 struct msghdr rmsg;
437 u8_t rcv_buf[4];
438 struct iovec siovs[4];
439 struct msghdr smsg;
440 u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF};
441  
442 /* initialize IO vectors with data */
443 for (i = 0; i < 4; i++) {
444 siovs[i].iov_base = &snd_buf[i];
445 siovs[i].iov_len = sizeof(u8_t);
446 riovs[i].iov_base = &rcv_buf[i];
447 riovs[i].iov_len = sizeof(u8_t);
448 }
449  
450 test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
451  
452 s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM);
453 fail_unless(s >= 0);
454  
455 ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size);
456 fail_unless(ret == 0);
457  
458 /* Update addr with epehermal port */
459 ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size);
460 fail_unless(ret == 0);
461 switch(domain) {
462 #if LWIP_IPV6
463 case AF_INET6:
464 fail_unless(addr_size == sizeof(struct sockaddr_in6));
465 break;
466 #endif /* LWIP_IPV6 */
467 #if LWIP_IPV4
468 case AF_INET:
469 fail_unless(addr_size == sizeof(struct sockaddr_in));
470 break;
471 #endif /* LWIP_IPV6 */
472 default:
473 fail();
474 break;
475 }
476  
477 /* send and receive the datagram in 4 pieces */
478 memset(&smsg, 0, sizeof(smsg));
479 smsg.msg_iov = siovs;
480 smsg.msg_iovlen = 4;
481 memset(&rmsg, 0, sizeof(rmsg));
482 rmsg.msg_iov = riovs;
483 rmsg.msg_iovlen = 4;
484  
485 /* perform a sendmsg with remote host (self) */
486 smsg.msg_name = &addr_storage;
487 smsg.msg_namelen = addr_size;
488  
489 test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg);
490  
491 /* Connect to self, allowing us to not pass message name */
492 ret = lwip_connect(s, (struct sockaddr*)&addr_storage, addr_size);
493 fail_unless(ret == 0);
494  
495 smsg.msg_name = NULL;
496 smsg.msg_namelen = 0;
497  
498 test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg);
499  
500 ret = lwip_close(s);
501 fail_unless(ret == 0);
502 }
503  
504 #if LWIP_IPV4
505 static void test_sockets_msgapi_cmsg(int domain)
506 {
507 int s, ret, enable;
508 struct sockaddr_storage addr_storage;
509 socklen_t addr_size;
510 struct iovec iov;
511 struct msghdr msg;
512 struct cmsghdr *cmsg;
513 struct in_pktinfo *pktinfo;
514 u8_t rcv_buf[4];
515 u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF};
516 u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
517  
518 test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
519  
520 s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM);
521 fail_unless(s >= 0);
522  
523 ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size);
524 fail_unless(ret == 0);
525  
526 /* Update addr with epehermal port */
527 ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size);
528 fail_unless(ret == 0);
529  
530 enable = 1;
531 ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable));
532 fail_unless(ret == 0);
533  
534 /* Receive full message, including control message */
535 iov.iov_base = rcv_buf;
536 iov.iov_len = sizeof(rcv_buf);
537 msg.msg_control = cmsg_buf;
538 msg.msg_controllen = sizeof(cmsg_buf);
539 msg.msg_flags = 0;
540 msg.msg_iov = &iov;
541 msg.msg_iovlen = 1;
542 msg.msg_name = NULL;
543 msg.msg_namelen = 0;
544  
545 memset(rcv_buf, 0, sizeof(rcv_buf));
546 ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size);
547 fail_unless(ret == sizeof(snd_buf));
548  
549 tcpip_thread_poll_one();
550  
551 ret = lwip_recvmsg(s, &msg, 0);
552 fail_unless(ret == sizeof(rcv_buf));
553 fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf)));
554  
555 /* Verify message header */
556 cmsg = CMSG_FIRSTHDR(&msg);
557 fail_unless(cmsg != NULL);
558 fail_unless(cmsg->cmsg_len > 0);
559 fail_unless(cmsg->cmsg_level == IPPROTO_IP);
560 fail_unless(cmsg->cmsg_type == IP_PKTINFO);
561  
562 /* Verify message data */
563 pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
564 /* We only have loopback interface enabled */
565 fail_unless(pktinfo->ipi_ifindex == 1);
566 fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK));
567  
568 /* Verify there are no additional messages */
569 cmsg = CMSG_NXTHDR(&msg, cmsg);
570 fail_unless(cmsg == NULL);
571  
572 /* Send datagram again, testing truncation */
573 memset(rcv_buf, 0, sizeof(rcv_buf));
574 ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size);
575 fail_unless(ret == sizeof(snd_buf));
576  
577 tcpip_thread_poll_one();
578  
579 msg.msg_controllen = 1;
580 msg.msg_flags = 0;
581 ret = lwip_recvmsg(s, &msg, 0);
582 fail_unless(ret == sizeof(rcv_buf));
583 fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf)));
584 /* Ensure truncation was returned */
585 fail_unless(msg.msg_flags & MSG_CTRUNC);
586 /* Ensure no control messages were returned */
587 fail_unless(msg.msg_controllen == 0);
588  
589 ret = lwip_close(s);
590 fail_unless(ret == 0);
591 }
592 #endif /* LWIP_IPV4 */
593  
594 START_TEST(test_sockets_msgapis)
595 {
596 LWIP_UNUSED_ARG(_i);
597 #if LWIP_IPV4
598 test_sockets_msgapi_udp(AF_INET);
599 test_sockets_msgapi_tcp(AF_INET);
600 test_sockets_msgapi_cmsg(AF_INET);
601 #endif
602 #if LWIP_IPV6
603 test_sockets_msgapi_udp(AF_INET6);
604 test_sockets_msgapi_tcp(AF_INET6);
605 #endif
606 }
607 END_TEST
608  
609 START_TEST(test_sockets_select)
610 {
611 #if LWIP_SOCKET_SELECT
612 int s;
613 int ret;
614 fd_set readset;
615 fd_set writeset;
616 fd_set errset;
617 struct timeval tv;
618  
619 fail_unless(test_sockets_get_used_count() == 0);
620  
621 s = lwip_socket(AF_INET, SOCK_STREAM, 0);
622 fail_unless(s >= 0);
623 fail_unless(test_sockets_get_used_count() == 0);
624  
625 FD_ZERO(&readset);
626 FD_SET(s, &readset);
627 FD_ZERO(&writeset);
628 FD_SET(s, &writeset);
629 FD_ZERO(&errset);
630 FD_SET(s, &errset);
631  
632 tv.tv_sec = tv.tv_usec = 0;
633 ret = lwip_select(s + 1, &readset, &writeset, &errset, &tv);
634 fail_unless(ret == 0);
635 fail_unless(test_sockets_get_used_count() == 0);
636  
637 ret = lwip_close(s);
638 fail_unless(ret == 0);
639  
640 #endif
641 LWIP_UNUSED_ARG(_i);
642 }
643 END_TEST
644  
645 START_TEST(test_sockets_recv_after_rst)
646 {
647 int sl, sact;
648 int spass = -1;
649 int ret;
650 struct sockaddr_in sa_listen;
651 const u16_t port = 1234;
652 int arg;
653 const char txbuf[] = "something";
654 char rxbuf[16];
655 struct lwip_sock *sact_sock;
656 int err;
657 LWIP_UNUSED_ARG(_i);
658  
659 fail_unless(test_sockets_get_used_count() == 0);
660  
661 memset(&sa_listen, 0, sizeof(sa_listen));
662 sa_listen.sin_family = AF_INET;
663 sa_listen.sin_port = PP_HTONS(port);
664 sa_listen.sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
665  
666 /* set up the listener */
667 sl = lwip_socket(AF_INET, SOCK_STREAM, 0);
668 fail_unless(sl >= 0);
669 fail_unless(test_sockets_get_used_count() == 0);
670  
671 ret = lwip_bind(sl, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
672 fail_unless(ret == 0);
673 ret = lwip_listen(sl, 0);
674 fail_unless(ret == 0);
675  
676 /* set up the client */
677 sact = lwip_socket(AF_INET, SOCK_STREAM, 0);
678 fail_unless(sact >= 0);
679 fail_unless(test_sockets_get_used_count() == 0);
680 /* set the client to nonblocking to simplify this test */
681 arg = 1;
682 ret = lwip_ioctl(sact, FIONBIO, &arg);
683 fail_unless(ret == 0);
684 /* connect */
685 do {
686 ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
687 err = errno;
688 fail_unless((ret == 0) || (ret == -1));
689 if (ret != 0) {
690 if (err == EISCONN) {
691 /* Although this is not valid, use EISCONN as an indicator for successful connection.
692 This marks us as "connect phase is done". On error, we would either have a different
693 errno code or "send" fails later... -> good enough for this test. */
694 ret = 0;
695 } else {
696 fail_unless(err == EINPROGRESS);
697 if (err != EINPROGRESS) {
698 goto cleanup;
699 }
700 /* we're in progress: little side check: test for EALREADY */
701 ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
702 err = errno;
703 fail_unless(ret == -1);
704 fail_unless(err == EALREADY);
705 if ((ret != -1) || (err != EALREADY)) {
706 goto cleanup;
707 }
708 }
709 tcpip_thread_poll_one();
710 tcpip_thread_poll_one();
711 tcpip_thread_poll_one();
712 tcpip_thread_poll_one();
713 }
714 } while (ret != 0);
715 fail_unless(ret == 0);
716  
717 /* accept the server connection part */
718 spass = lwip_accept(sl, NULL, NULL);
719 fail_unless(spass >= 0);
720  
721 /* write data from client */
722 ret = lwip_send(sact, txbuf, sizeof(txbuf), 0);
723 fail_unless(ret == sizeof(txbuf));
724  
725 tcpip_thread_poll_one();
726 tcpip_thread_poll_one();
727  
728 /* issue RST (This is a HACK, don't try this in your own app!) */
729 sact_sock = lwip_socket_dbg_get_socket(sact);
730 fail_unless(sact_sock != NULL);
731 if (sact_sock != NULL) {
732 struct netconn *sact_conn = sact_sock->conn;
733 fail_unless(sact_conn != NULL);
734 if (sact_conn != NULL) {
735 struct tcp_pcb *pcb = sact_conn->pcb.tcp;
736 fail_unless(pcb != NULL);
737 if (pcb != NULL) {
738 tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
739 pcb->local_port, pcb->remote_port);
740 }
741 }
742 }
743 tcpip_thread_poll_one();
744 tcpip_thread_poll_one();
745  
746 /* expect to receive data first */
747 ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
748 fail_unless(ret > 0);
749 tcpip_thread_poll_one();
750 tcpip_thread_poll_one();
751  
752 /* expect to receive RST indication */
753 ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
754 fail_unless(ret == -1);
755 err = errno;
756 fail_unless(err == ECONNRESET);
757 tcpip_thread_poll_one();
758 tcpip_thread_poll_one();
759  
760 /* expect to receive ENOTCONN indication */
761 ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
762 fail_unless(ret == -1);
763 err = errno;
764 fail_unless(err == ENOTCONN);
765 tcpip_thread_poll_one();
766 tcpip_thread_poll_one();
767  
768 /* expect to receive ENOTCONN indication */
769 ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
770 fail_unless(ret == -1);
771 err = errno;
772 fail_unless(err == ENOTCONN);
773 tcpip_thread_poll_one();
774 tcpip_thread_poll_one();
775  
776 cleanup:
777 ret = lwip_close(sl);
778 fail_unless(ret == 0);
779 ret = lwip_close(sact);
780 fail_unless(ret == 0);
781 if (spass >= 0) {
782 ret = lwip_close(spass);
783 fail_unless(ret == 0);
784 }
785 }
786 END_TEST
787  
788 /** Create the suite including all tests for this module */
789 Suite *
790 sockets_suite(void)
791 {
792 testfunc tests[] = {
793 TESTFUNC(test_sockets_basics),
794 TESTFUNC(test_sockets_allfunctions_basic),
795 TESTFUNC(test_sockets_msgapis),
796 TESTFUNC(test_sockets_select),
797 TESTFUNC(test_sockets_recv_after_rst),
798 };
799 return create_suite("SOCKETS", tests, sizeof(tests)/sizeof(testfunc), sockets_setup, sockets_teardown);
800 }
801  
802 #else /* LWIP_SOCKET */
803  
804 Suite *
805 sockets_suite(void)
806 {
807 return create_suite("SOCKETS", NULL, 0, NULL, NULL);
808 }
809 #endif /* LWIP_SOCKET */