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 */ 853