PageRenderTime 57ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/api/test_sockets.c

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