source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/lwip-2.1.2/test/unit/api/test_sockets.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

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