Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
test_sockets.c
00001 #include "test_sockets.h" 00002 00003 #include "lwip/mem.h" 00004 #include "lwip/opt.h" 00005 #include "lwip/sockets.h" 00006 #include "lwip/priv/sockets_priv.h" 00007 #include "lwip/stats.h" 00008 00009 #include "lwip/tcpip.h" 00010 #include "lwip/priv/tcp_priv.h" 00011 #include "lwip/api.h" 00012 00013 00014 static int 00015 test_sockets_get_used_count(void) 00016 { 00017 int used = 0; 00018 int i; 00019 00020 for (i = 0; i < NUM_SOCKETS; i++) { 00021 struct lwip_sock* s = lwip_socket_dbg_get_socket(i); 00022 if (s != NULL) { 00023 if (s->fd_used) { 00024 used++; 00025 } 00026 } 00027 } 00028 return used; 00029 } 00030 00031 00032 /* Setups/teardown functions */ 00033 00034 static void 00035 sockets_setup(void) 00036 { 00037 /* expect full free heap */ 00038 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 00039 } 00040 00041 static void 00042 sockets_teardown(void) 00043 { 00044 fail_unless(test_sockets_get_used_count() == 0); 00045 /* poll until all memory is released... */ 00046 tcpip_thread_poll_one(); 00047 while (tcp_tw_pcbs) { 00048 tcp_abort(tcp_tw_pcbs); 00049 tcpip_thread_poll_one(); 00050 } 00051 tcpip_thread_poll_one(); 00052 /* ensure full free heap */ 00053 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 00054 } 00055 00056 #ifndef NUM_SOCKETS 00057 #define NUM_SOCKETS MEMP_NUM_NETCONN 00058 #endif 00059 00060 #if LWIP_SOCKET 00061 static int 00062 test_sockets_alloc_socket_nonblocking(int domain, int type) 00063 { 00064 int s = lwip_socket(domain, type, 0); 00065 if (s >= 0) { 00066 int ret = lwip_fcntl(s, F_SETFL, O_NONBLOCK); 00067 fail_unless(ret == 0); 00068 } 00069 return s; 00070 } 00071 00072 /* Verify basic sockets functionality 00073 */ 00074 START_TEST(test_sockets_basics) 00075 { 00076 int s, i, ret; 00077 int s2[NUM_SOCKETS]; 00078 LWIP_UNUSED_ARG(_i); 00079 00080 s = lwip_socket(AF_INET, SOCK_STREAM, 0); 00081 fail_unless(s >= 0); 00082 lwip_close(s); 00083 00084 for (i = 0; i < NUM_SOCKETS; i++) { 00085 s2[i] = lwip_socket(AF_INET, SOCK_STREAM, 0); 00086 fail_unless(s2[i] >= 0); 00087 } 00088 00089 /* all sockets used, now it should fail */ 00090 s = lwip_socket(AF_INET, SOCK_STREAM, 0); 00091 fail_unless(s == -1); 00092 /* close one socket */ 00093 ret = lwip_close(s2[0]); 00094 fail_unless(ret == 0); 00095 /* now it should succeed */ 00096 s2[0] = lwip_socket(AF_INET, SOCK_STREAM, 0); 00097 fail_unless(s2[0] >= 0); 00098 00099 /* close all sockets */ 00100 for (i = 0; i < NUM_SOCKETS; i++) { 00101 ret = lwip_close(s2[i]); 00102 fail_unless(ret == 0); 00103 } 00104 } 00105 END_TEST 00106 00107 static void test_sockets_allfunctions_basic_domain(int domain) 00108 { 00109 int s, s2, s3, ret; 00110 struct sockaddr_storage addr, addr2; 00111 socklen_t addrlen, addr2len; 00112 char buf[4]; 00113 /* listen socket */ 00114 s = lwip_socket(domain, SOCK_STREAM, 0); 00115 fail_unless(s >= 0); 00116 00117 ret = lwip_listen(s, 0); 00118 fail_unless(ret == 0); 00119 00120 addrlen = sizeof(addr); 00121 ret = lwip_getsockname(s, (struct sockaddr*)&addr, &addrlen); 00122 fail_unless(ret == 0); 00123 00124 s2 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM); 00125 fail_unless(s2 >= 0); 00126 /* nonblocking connect s2 to s (but use loopback address) */ 00127 if (domain == AF_INET) { 00128 #if LWIP_IPV4 00129 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; 00130 addr4->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); 00131 #endif 00132 } else { 00133 #if LWIP_IPV6 00134 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 00135 struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; 00136 addr6->sin6_addr = lo6; 00137 #endif 00138 } 00139 ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); 00140 fail_unless(ret == -1); 00141 fail_unless(errno == EINPROGRESS); 00142 ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); 00143 fail_unless(ret == -1); 00144 fail_unless(errno == EALREADY); 00145 00146 while(tcpip_thread_poll_one()); 00147 00148 s3 = lwip_accept(s, (struct sockaddr*)&addr2, &addr2len); 00149 fail_unless(s3 >= 0); 00150 00151 ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); 00152 fail_unless(ret == -1); 00153 fail_unless(errno == EISCONN); 00154 00155 /* write from server to client */ 00156 ret = write(s3, "test", 4); 00157 fail_unless(ret == 4); 00158 00159 ret = lwip_shutdown(s3, SHUT_WR); 00160 fail_unless(ret == 0); 00161 00162 while(tcpip_thread_poll_one()); 00163 00164 ret = lwip_recv(s2, buf, 3, MSG_PEEK); 00165 fail_unless(ret == 3); 00166 00167 ret = lwip_recv(s2, buf, 3, MSG_PEEK); 00168 fail_unless(ret == 3); 00169 00170 ret = lwip_read(s2, buf, 4); 00171 fail_unless(ret == 4); 00172 00173 ret = lwip_read(s2, buf, 1); 00174 fail_unless(ret == 0); 00175 00176 ret = lwip_read(s2, buf, 1); 00177 fail_unless(ret == -1); 00178 00179 ret = lwip_write(s2, "foo", 3); 00180 fail_unless(ret == 3); 00181 00182 ret = lwip_close(s2); 00183 fail_unless(ret == 0); 00184 00185 while(tcpip_thread_poll_one()); 00186 00187 /* read one byte more than available to check handling FIN */ 00188 ret = lwip_read(s3, buf, 4); 00189 fail_unless(ret == 3); 00190 00191 ret = lwip_read(s3, buf, 1); 00192 fail_unless(ret == 0); 00193 00194 ret = lwip_read(s3, buf, 1); 00195 fail_unless(ret == -1); 00196 00197 while(tcpip_thread_poll_one()); 00198 00199 ret = lwip_close(s); 00200 fail_unless(ret == 0); 00201 ret = lwip_close(s3); 00202 fail_unless(ret == 0); 00203 } 00204 00205 /* Try to step through all sockets functions once... 00206 */ 00207 START_TEST(test_sockets_allfunctions_basic) 00208 { 00209 LWIP_UNUSED_ARG(_i); 00210 #if LWIP_IPV4 00211 test_sockets_allfunctions_basic_domain(AF_INET); 00212 #endif 00213 #if LWIP_IPV6 00214 test_sockets_allfunctions_basic_domain(AF_INET6); 00215 #endif 00216 } 00217 END_TEST 00218 00219 static void test_sockets_init_loopback_addr(int domain, struct sockaddr_storage *addr_st, socklen_t *sz) 00220 { 00221 memset(addr_st, 0, sizeof(*addr_st)); 00222 switch(domain) { 00223 #if LWIP_IPV6 00224 case AF_INET6: { 00225 struct sockaddr_in6 *addr = (struct sockaddr_in6*)addr_st; 00226 struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; 00227 addr->sin6_family = AF_INET6; 00228 addr->sin6_port = 0; /* use ephemeral port */ 00229 addr->sin6_addr = lo6; 00230 *sz = sizeof(*addr); 00231 } 00232 break; 00233 #endif /* LWIP_IPV6 */ 00234 #if LWIP_IPV4 00235 case AF_INET: { 00236 struct sockaddr_in *addr = (struct sockaddr_in*)addr_st; 00237 addr->sin_family = AF_INET; 00238 addr->sin_port = 0; /* use ephemeral port */ 00239 addr->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); 00240 *sz = sizeof(*addr); 00241 } 00242 break; 00243 #endif /* LWIP_IPV4 */ 00244 default: 00245 *sz = 0; 00246 fail(); 00247 break; 00248 } 00249 } 00250 00251 static void test_sockets_msgapi_update_iovs(struct msghdr *msg, size_t bytes) 00252 { 00253 int i; 00254 00255 /* note: this modifies the underyling iov_base and iov_len for a partial 00256 read for an individual vector. This updates the msg->msg_iov pointer 00257 to skip fully consumed vecotrs */ 00258 00259 /* process fully consumed vectors */ 00260 for (i = 0; i < msg->msg_iovlen; i++) { 00261 if (msg->msg_iov[i].iov_len <= bytes) { 00262 /* reduce bytes by amount of this vector */ 00263 bytes -= msg->msg_iov[i].iov_len; 00264 } else { 00265 break; /* iov not fully consumed */ 00266 } 00267 } 00268 00269 /* slide down over fully consumed vectors */ 00270 msg->msg_iov = &msg->msg_iov[i]; 00271 msg->msg_iovlen -= i; 00272 00273 /* update new first vector with any remaining amount */ 00274 msg->msg_iov[0].iov_base = ((u8_t *)msg->msg_iov[0].iov_base + bytes); 00275 msg->msg_iov[0].iov_len -= bytes; 00276 } 00277 00278 static void test_sockets_msgapi_tcp(int domain) 00279 { 00280 #define BUF_SZ (TCP_SND_BUF/4) 00281 #define TOTAL_DATA_SZ (BUF_SZ*8) /* ~(TCP_SND_BUF*2) that accounts for integer rounding */ 00282 #define NEED_TRAILER (BUF_SZ % 4 != 0) 00283 int listnr, s1, s2, i, ret, opt; 00284 int bytes_written, bytes_read; 00285 struct sockaddr_storage addr_storage; 00286 socklen_t addr_size; 00287 struct iovec siovs[8]; 00288 struct msghdr smsg; 00289 u8_t * snd_buf; 00290 struct iovec riovs[5]; 00291 struct iovec riovs_tmp[5]; 00292 struct msghdr rmsg; 00293 u8_t * rcv_buf; 00294 int rcv_off; 00295 int rcv_trailer = 0; 00296 u8_t val; 00297 00298 test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size); 00299 00300 listnr = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM); 00301 fail_unless(listnr >= 0); 00302 s1 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM); 00303 fail_unless(s1 >= 0); 00304 00305 /* setup a listener socket on loopback with ephemeral port */ 00306 ret = lwip_bind(listnr, (struct sockaddr*)&addr_storage, addr_size); 00307 fail_unless(ret == 0); 00308 ret = lwip_listen(listnr, 0); 00309 fail_unless(ret == 0); 00310 00311 /* update address with ephemeral port */ 00312 ret = lwip_getsockname(listnr, (struct sockaddr*)&addr_storage, &addr_size); 00313 fail_unless(ret == 0); 00314 00315 /* connect, won't complete until we accept it */ 00316 ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size); 00317 fail_unless(ret == -1); 00318 fail_unless(errno == EINPROGRESS); 00319 00320 while (tcpip_thread_poll_one()); 00321 00322 /* accept, creating the other side of the connection */ 00323 s2 = lwip_accept(listnr, NULL, NULL); 00324 fail_unless(s2 >= 0); 00325 00326 /* double check s1 is connected */ 00327 ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size); 00328 fail_unless(ret == -1); 00329 fail_unless(errno == EISCONN); 00330 00331 /* set s2 to non-blocking, not inherited from listener */ 00332 opt = lwip_fcntl(s2, F_GETFL, 0); 00333 fail_unless(opt == 6); 00334 opt = O_NONBLOCK; 00335 ret = lwip_fcntl(s2, F_SETFL, opt); 00336 fail_unless(ret == 0); 00337 00338 /* we are done with listener, close it */ 00339 ret = lwip_close(listnr); 00340 fail_unless(ret == 0); 00341 00342 /* allocate a buffer for a stream of incrementing hex (0x00..0xFF) which we will use 00343 to create an input vector set that is larger than the TCP's send buffer. This will 00344 force execution of the partial IO vector send case */ 00345 snd_buf = (u8_t*)mem_malloc(BUF_SZ); 00346 val = 0x00; 00347 fail_unless(snd_buf != NULL); 00348 for (i = 0; i < BUF_SZ; i++,val++) { 00349 snd_buf[i] = val; 00350 } 00351 00352 /* send the buffer 8 times in one message, equating to TOTAL_DATA_SZ */ 00353 for (i = 0; i < 8; i++) { 00354 siovs[i].iov_base = snd_buf; 00355 siovs[i].iov_len = BUF_SZ; 00356 } 00357 00358 /* allocate a receive buffer, same size as snd_buf for easy verification */ 00359 rcv_buf = (u8_t*)mem_calloc(1, BUF_SZ); 00360 fail_unless(rcv_buf != NULL); 00361 /* split across iovs */ 00362 for (i = 0; i < 4; i++) { 00363 riovs[i].iov_base = &rcv_buf[i*(BUF_SZ/4)]; 00364 riovs[i].iov_len = BUF_SZ/4; 00365 } 00366 /* handling trailing bytes if buffer doesn't evenly divide by 4 */ 00367 #if NEED_TRAILER 00368 if ((BUF_SZ % 4) != 0) { 00369 riovs[5].iov_base = &rcv_buf[4*(BUF_SZ/4)]; 00370 riovs[5].iov_len = BUF_SZ - (4*(BUF_SZ/4)); 00371 rcv_trailer = 1; 00372 } 00373 #endif /* NEED_TRAILER */ 00374 00375 /* we use a copy of riovs since we'll be modifying base and len during 00376 receiving. This gives us an easy way to reset the iovs for next recvmsg */ 00377 memcpy(riovs_tmp, riovs, sizeof(riovs)); 00378 00379 memset(&smsg, 0, sizeof(smsg)); 00380 smsg.msg_iov = siovs; 00381 smsg.msg_iovlen = 8; 00382 00383 memset(&rmsg, 0, sizeof(rmsg)); 00384 rmsg.msg_iov = riovs_tmp; 00385 rmsg.msg_iovlen = (rcv_trailer ? 5 : 4); 00386 00387 bytes_written = 0; 00388 bytes_read = 0; 00389 rcv_off = 0; 00390 00391 while (bytes_written < TOTAL_DATA_SZ && (bytes_read < TOTAL_DATA_SZ)) { 00392 /* send data */ 00393 if (bytes_written < TOTAL_DATA_SZ) { 00394 ret = lwip_sendmsg(s1, &smsg, 0); 00395 /* note: since we always receive after sending, there will be open 00396 space in the send buffer */ 00397 fail_unless(ret > 0); 00398 00399 bytes_written += ret; 00400 if (bytes_written < TOTAL_DATA_SZ) { 00401 test_sockets_msgapi_update_iovs(&smsg, (size_t)ret); 00402 } 00403 } 00404 00405 while (tcpip_thread_poll_one()); 00406 00407 /* receive and verify data */ 00408 do { 00409 if (bytes_read < TOTAL_DATA_SZ) { 00410 ret = lwip_recvmsg(s2, &rmsg, 0); 00411 fail_unless(ret > 0 || (ret == -1 && errno == EWOULDBLOCK)); 00412 00413 if (ret > 0) { 00414 rcv_off += ret; 00415 /* we have received a full buffer */ 00416 if (rcv_off == BUF_SZ) { 00417 /* note: since iovs are just pointers, compare underlying buf */ 00418 fail_unless(!memcmp(snd_buf, rcv_buf, BUF_SZ)); 00419 bytes_read += BUF_SZ; 00420 /* reset receive state for next buffer */ 00421 rcv_off = 0; 00422 memset(rcv_buf, 0, BUF_SZ); 00423 memcpy(riovs_tmp, riovs, sizeof(riovs)); 00424 rmsg.msg_iov = riovs_tmp; 00425 rmsg.msg_iovlen = (rcv_trailer ? 5 : 4); 00426 } else { /* partial read */ 00427 test_sockets_msgapi_update_iovs(&rmsg, (size_t)ret); 00428 } 00429 } 00430 } else { 00431 break; 00432 } 00433 } while(ret > 0); 00434 } 00435 00436 ret = lwip_close(s1); 00437 fail_unless(ret == 0); 00438 ret = lwip_close(s2); 00439 fail_unless(ret == 0); 00440 mem_free(snd_buf); 00441 mem_free(rcv_buf); 00442 } 00443 00444 static void test_sockets_msgapi_udp_send_recv_loop(int s, struct msghdr *smsg, struct msghdr *rmsg) 00445 { 00446 int i, ret; 00447 00448 /* send/receive our datagram of IO vectors 10 times */ 00449 for (i = 0; i < 10; i++) { 00450 ret = lwip_sendmsg(s, smsg, 0); 00451 fail_unless(ret == 4); 00452 00453 while (tcpip_thread_poll_one()); 00454 00455 /* receive the datagram split across 4 buffers */ 00456 ret = lwip_recvmsg(s, rmsg, 0); 00457 fail_unless(ret == 4); 00458 00459 /* verify data */ 00460 fail_unless(*((u8_t*)rmsg->msg_iov[0].iov_base) == 0xDE); 00461 fail_unless(*((u8_t*)rmsg->msg_iov[1].iov_base) == 0xAD); 00462 fail_unless(*((u8_t*)rmsg->msg_iov[2].iov_base) == 0xBE); 00463 fail_unless(*((u8_t*)rmsg->msg_iov[3].iov_base) == 0xEF); 00464 00465 /* clear rcv_buf to ensure no data is being skipped */ 00466 *((u8_t*)rmsg->msg_iov[0].iov_base) = 0x00; 00467 *((u8_t*)rmsg->msg_iov[1].iov_base) = 0x00; 00468 *((u8_t*)rmsg->msg_iov[2].iov_base) = 0x00; 00469 *((u8_t*)rmsg->msg_iov[3].iov_base) = 0x00; 00470 } 00471 } 00472 00473 static void test_sockets_msgapi_udp(int domain) 00474 { 00475 int s, i, ret; 00476 struct sockaddr_storage addr_storage; 00477 socklen_t addr_size; 00478 struct iovec riovs[4]; 00479 struct msghdr rmsg; 00480 u8_t rcv_buf[4]; 00481 struct iovec siovs[4]; 00482 struct msghdr smsg; 00483 u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF}; 00484 00485 /* initialize IO vectors with data */ 00486 for (i = 0; i < 4; i++) { 00487 siovs[i].iov_base = &snd_buf[i]; 00488 siovs[i].iov_len = sizeof(u8_t); 00489 riovs[i].iov_base = &rcv_buf[i]; 00490 riovs[i].iov_len = sizeof(u8_t); 00491 } 00492 00493 test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size); 00494 00495 s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM); 00496 fail_unless(s >= 0); 00497 00498 ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size); 00499 fail_unless(ret == 0); 00500 00501 /* Update addr with epehermal port */ 00502 ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size); 00503 fail_unless(ret == 0); 00504 switch(domain) { 00505 #if LWIP_IPV6 00506 case AF_INET6: 00507 fail_unless(addr_size == sizeof(struct sockaddr_in6)); 00508 break; 00509 #endif /* LWIP_IPV6 */ 00510 #if LWIP_IPV4 00511 case AF_INET: 00512 fail_unless(addr_size == sizeof(struct sockaddr_in)); 00513 break; 00514 #endif /* LWIP_IPV6 */ 00515 default: 00516 fail(); 00517 break; 00518 } 00519 00520 /* send and receive the datagram in 4 pieces */ 00521 memset(&smsg, 0, sizeof(smsg)); 00522 smsg.msg_iov = siovs; 00523 smsg.msg_iovlen = 4; 00524 memset(&rmsg, 0, sizeof(rmsg)); 00525 rmsg.msg_iov = riovs; 00526 rmsg.msg_iovlen = 4; 00527 00528 /* perform a sendmsg with remote host (self) */ 00529 smsg.msg_name = &addr_storage; 00530 smsg.msg_namelen = addr_size; 00531 00532 test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg); 00533 00534 /* Connect to self, allowing us to not pass message name */ 00535 ret = lwip_connect(s, (struct sockaddr*)&addr_storage, addr_size); 00536 fail_unless(ret == 0); 00537 00538 smsg.msg_name = NULL; 00539 smsg.msg_namelen = 0; 00540 00541 test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg); 00542 00543 ret = lwip_close(s); 00544 fail_unless(ret == 0); 00545 } 00546 00547 #if LWIP_IPV4 00548 static void test_sockets_msgapi_cmsg(int domain) 00549 { 00550 int s, ret, enable; 00551 struct sockaddr_storage addr_storage; 00552 socklen_t addr_size; 00553 struct iovec iov; 00554 struct msghdr msg; 00555 struct cmsghdr *cmsg; 00556 struct in_pktinfo *pktinfo; 00557 u8_t rcv_buf[4]; 00558 u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF}; 00559 u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; 00560 00561 test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size); 00562 00563 s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM); 00564 fail_unless(s >= 0); 00565 00566 ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size); 00567 fail_unless(ret == 0); 00568 00569 /* Update addr with epehermal port */ 00570 ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size); 00571 fail_unless(ret == 0); 00572 00573 enable = 1; 00574 ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable)); 00575 fail_unless(ret == 0); 00576 00577 /* Receive full message, including control message */ 00578 iov.iov_base = rcv_buf; 00579 iov.iov_len = sizeof(rcv_buf); 00580 msg.msg_control = cmsg_buf; 00581 msg.msg_controllen = sizeof(cmsg_buf); 00582 msg.msg_flags = 0; 00583 msg.msg_iov = &iov; 00584 msg.msg_iovlen = 1; 00585 msg.msg_name = NULL; 00586 msg.msg_namelen = 0; 00587 00588 memset(rcv_buf, 0, sizeof(rcv_buf)); 00589 ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size); 00590 fail_unless(ret == sizeof(snd_buf)); 00591 00592 tcpip_thread_poll_one(); 00593 00594 ret = lwip_recvmsg(s, &msg, 0); 00595 fail_unless(ret == sizeof(rcv_buf)); 00596 fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf))); 00597 00598 /* Verify message header */ 00599 cmsg = CMSG_FIRSTHDR(&msg); 00600 fail_unless(cmsg != NULL); 00601 fail_unless(cmsg->cmsg_len > 0); 00602 fail_unless(cmsg->cmsg_level == IPPROTO_IP); 00603 fail_unless(cmsg->cmsg_type == IP_PKTINFO); 00604 00605 /* Verify message data */ 00606 pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg); 00607 /* We only have loopback interface enabled */ 00608 fail_unless(pktinfo->ipi_ifindex == 1); 00609 fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK)); 00610 00611 /* Verify there are no additional messages */ 00612 cmsg = CMSG_NXTHDR(&msg, cmsg); 00613 fail_unless(cmsg == NULL); 00614 00615 /* Send datagram again, testing truncation */ 00616 memset(rcv_buf, 0, sizeof(rcv_buf)); 00617 ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size); 00618 fail_unless(ret == sizeof(snd_buf)); 00619 00620 tcpip_thread_poll_one(); 00621 00622 msg.msg_controllen = 1; 00623 msg.msg_flags = 0; 00624 ret = lwip_recvmsg(s, &msg, 0); 00625 fail_unless(ret == sizeof(rcv_buf)); 00626 fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf))); 00627 /* Ensure truncation was returned */ 00628 fail_unless(msg.msg_flags & MSG_CTRUNC); 00629 /* Ensure no control messages were returned */ 00630 fail_unless(msg.msg_controllen == 0); 00631 00632 ret = lwip_close(s); 00633 fail_unless(ret == 0); 00634 } 00635 #endif /* LWIP_IPV4 */ 00636 00637 START_TEST(test_sockets_msgapis) 00638 { 00639 LWIP_UNUSED_ARG(_i); 00640 #if LWIP_IPV4 00641 test_sockets_msgapi_udp(AF_INET); 00642 test_sockets_msgapi_tcp(AF_INET); 00643 test_sockets_msgapi_cmsg(AF_INET); 00644 #endif 00645 #if LWIP_IPV6 00646 test_sockets_msgapi_udp(AF_INET6); 00647 test_sockets_msgapi_tcp(AF_INET6); 00648 #endif 00649 } 00650 END_TEST 00651 00652 START_TEST(test_sockets_select) 00653 { 00654 #if LWIP_SOCKET_SELECT 00655 int s; 00656 int ret; 00657 fd_set readset; 00658 fd_set writeset; 00659 fd_set errset; 00660 struct timeval tv; 00661 00662 fail_unless(test_sockets_get_used_count() == 0); 00663 00664 s = lwip_socket(AF_INET, SOCK_STREAM, 0); 00665 fail_unless(s >= 0); 00666 fail_unless(test_sockets_get_used_count() == 0); 00667 00668 FD_ZERO(&readset); 00669 FD_SET(s, &readset); 00670 FD_ZERO(&writeset); 00671 FD_SET(s, &writeset); 00672 FD_ZERO(&errset); 00673 FD_SET(s, &errset); 00674 00675 tv.tv_sec = tv.tv_usec = 0; 00676 ret = lwip_select(s + 1, &readset, &writeset, &errset, &tv); 00677 fail_unless(ret == 0); 00678 fail_unless(test_sockets_get_used_count() == 0); 00679 00680 ret = lwip_close(s); 00681 fail_unless(ret == 0); 00682 00683 #endif 00684 LWIP_UNUSED_ARG(_i); 00685 } 00686 END_TEST 00687 00688 START_TEST(test_sockets_recv_after_rst) 00689 { 00690 int sl, sact; 00691 int spass = -1; 00692 int ret; 00693 struct sockaddr_in sa_listen; 00694 const u16_t port = 1234; 00695 int arg; 00696 const char txbuf[] = "something"; 00697 char rxbuf[16]; 00698 struct lwip_sock *sact_sock; 00699 int err; 00700 LWIP_UNUSED_ARG(_i); 00701 00702 fail_unless(test_sockets_get_used_count() == 0); 00703 00704 memset(&sa_listen, 0, sizeof(sa_listen)); 00705 sa_listen.sin_family = AF_INET; 00706 sa_listen.sin_port = PP_HTONS(port); 00707 sa_listen.sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); 00708 00709 /* set up the listener */ 00710 sl = lwip_socket(AF_INET, SOCK_STREAM, 0); 00711 fail_unless(sl >= 0); 00712 fail_unless(test_sockets_get_used_count() == 0); 00713 00714 ret = lwip_bind(sl, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); 00715 fail_unless(ret == 0); 00716 ret = lwip_listen(sl, 0); 00717 fail_unless(ret == 0); 00718 00719 /* set up the client */ 00720 sact = lwip_socket(AF_INET, SOCK_STREAM, 0); 00721 fail_unless(sact >= 0); 00722 fail_unless(test_sockets_get_used_count() == 0); 00723 /* set the client to nonblocking to simplify this test */ 00724 arg = 1; 00725 ret = lwip_ioctl(sact, FIONBIO, &arg); 00726 fail_unless(ret == 0); 00727 /* connect */ 00728 do { 00729 ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); 00730 err = errno; 00731 fail_unless((ret == 0) || (ret == -1)); 00732 if (ret != 0) { 00733 if (err == EISCONN) { 00734 /* Although this is not valid, use EISCONN as an indicator for successful connection. 00735 This marks us as "connect phase is done". On error, we would either have a different 00736 errno code or "send" fails later... -> good enough for this test. */ 00737 ret = 0; 00738 } else { 00739 fail_unless(err == EINPROGRESS); 00740 if (err != EINPROGRESS) { 00741 goto cleanup; 00742 } 00743 /* we're in progress: little side check: test for EALREADY */ 00744 ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); 00745 err = errno; 00746 fail_unless(ret == -1); 00747 fail_unless(err == EALREADY); 00748 if ((ret != -1) || (err != EALREADY)) { 00749 goto cleanup; 00750 } 00751 } 00752 tcpip_thread_poll_one(); 00753 tcpip_thread_poll_one(); 00754 tcpip_thread_poll_one(); 00755 tcpip_thread_poll_one(); 00756 } 00757 } while (ret != 0); 00758 fail_unless(ret == 0); 00759 00760 /* accept the server connection part */ 00761 spass = lwip_accept(sl, NULL, NULL); 00762 fail_unless(spass >= 0); 00763 00764 /* write data from client */ 00765 ret = lwip_send(sact, txbuf, sizeof(txbuf), 0); 00766 fail_unless(ret == sizeof(txbuf)); 00767 00768 tcpip_thread_poll_one(); 00769 tcpip_thread_poll_one(); 00770 00771 /* issue RST (This is a HACK, don't try this in your own app!) */ 00772 sact_sock = lwip_socket_dbg_get_socket(sact); 00773 fail_unless(sact_sock != NULL); 00774 if (sact_sock != NULL) { 00775 struct netconn *sact_conn = sact_sock->conn; 00776 fail_unless(sact_conn != NULL); 00777 if (sact_conn != NULL) { 00778 struct tcp_pcb *pcb = sact_conn->pcb.tcp; 00779 fail_unless(pcb != NULL); 00780 if (pcb != NULL) { 00781 tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, 00782 pcb->local_port, pcb->remote_port); 00783 } 00784 } 00785 } 00786 tcpip_thread_poll_one(); 00787 tcpip_thread_poll_one(); 00788 00789 /* expect to receive data first */ 00790 ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); 00791 fail_unless(ret > 0); 00792 tcpip_thread_poll_one(); 00793 tcpip_thread_poll_one(); 00794 00795 /* expect to receive RST indication */ 00796 ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); 00797 fail_unless(ret == -1); 00798 err = errno; 00799 fail_unless(err == ECONNRESET); 00800 tcpip_thread_poll_one(); 00801 tcpip_thread_poll_one(); 00802 00803 /* expect to receive ENOTCONN indication */ 00804 ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); 00805 fail_unless(ret == -1); 00806 err = errno; 00807 fail_unless(err == ENOTCONN); 00808 tcpip_thread_poll_one(); 00809 tcpip_thread_poll_one(); 00810 00811 /* expect to receive ENOTCONN indication */ 00812 ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); 00813 fail_unless(ret == -1); 00814 err = errno; 00815 fail_unless(err == ENOTCONN); 00816 tcpip_thread_poll_one(); 00817 tcpip_thread_poll_one(); 00818 00819 cleanup: 00820 ret = lwip_close(sl); 00821 fail_unless(ret == 0); 00822 ret = lwip_close(sact); 00823 fail_unless(ret == 0); 00824 if (spass >= 0) { 00825 ret = lwip_close(spass); 00826 fail_unless(ret == 0); 00827 } 00828 } 00829 END_TEST 00830 00831 /** Create the suite including all tests for this module */ 00832 Suite * 00833 sockets_suite(void) 00834 { 00835 testfunc tests[] = { 00836 TESTFUNC(test_sockets_basics), 00837 TESTFUNC(test_sockets_allfunctions_basic), 00838 TESTFUNC(test_sockets_msgapis), 00839 TESTFUNC(test_sockets_select), 00840 TESTFUNC(test_sockets_recv_after_rst), 00841 }; 00842 return create_suite("SOCKETS", tests, sizeof(tests)/sizeof(testfunc), sockets_setup, sockets_teardown); 00843 } 00844 00845 #else /* LWIP_SOCKET */ 00846 00847 Suite * 00848 sockets_suite(void) 00849 { 00850 return create_suite("SOCKETS", NULL, 0, NULL, NULL); 00851 } 00852 #endif /* LWIP_SOCKET */
Generated on Tue Jul 12 2022 13:54:56 by
