1 2#include "socket_examples.h" 3 4#include "lwip/opt.h" 5 6#if LWIP_SOCKET && (LWIP_IPV4 || LWIP_IPV6) 7 8#include "lwip/sockets.h" 9#include "lwip/sys.h" 10 11#include <string.h> 12#include <stdio.h> 13 14#ifndef SOCK_TARGET_HOST4 15#define SOCK_TARGET_HOST4 "192.168.1.1" 16#endif 17 18#ifndef SOCK_TARGET_HOST6 19#define SOCK_TARGET_HOST6 "FE80::12:34FF:FE56:78AB" 20#endif 21 22#ifndef SOCK_TARGET_PORT 23#define SOCK_TARGET_PORT 80 24#endif 25 26#ifndef SOCK_TARGET_MAXHTTPPAGESIZE 27#define SOCK_TARGET_MAXHTTPPAGESIZE 1024 28#endif 29 30#ifndef SOCKET_EXAMPLES_RUN_PARALLEL 31#define SOCKET_EXAMPLES_RUN_PARALLEL 0 32#endif 33 34const u8_t cmpbuf[8] = {0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab}; 35 36/* a helper struct to ensure memory before/after fd_set is not touched */ 37typedef struct _xx 38{ 39 u8_t buf1[8]; 40 fd_set readset; 41 u8_t buf2[8]; 42 fd_set writeset; 43 u8_t buf3[8]; 44 fd_set errset; 45 u8_t buf4[8]; 46} fdsets; 47 48#define INIT_FDSETS(sets) do { \ 49 memset((sets)->buf1, 0xab, 8); \ 50 memset((sets)->buf2, 0xab, 8); \ 51 memset((sets)->buf3, 0xab, 8); \ 52 memset((sets)->buf4, 0xab, 8); \ 53}while(0) 54 55#define CHECK_FDSETS(sets) do { \ 56 LWIP_ASSERT("buf1 fail", !memcmp((sets)->buf1, cmpbuf, 8)); \ 57 LWIP_ASSERT("buf2 fail", !memcmp((sets)->buf2, cmpbuf, 8)); \ 58 LWIP_ASSERT("buf3 fail", !memcmp((sets)->buf3, cmpbuf, 8)); \ 59 LWIP_ASSERT("buf4 fail", !memcmp((sets)->buf4, cmpbuf, 8)); \ 60}while(0) 61 62static ip_addr_t dstaddr; 63 64/** This is an example function that tests 65 blocking- and nonblocking connect. */ 66static void 67sockex_nonblocking_connect(void *arg) 68{ 69 int s; 70 int ret; 71 u32_t opt; 72#if LWIP_IPV6 73 struct sockaddr_in6 addr; 74#else /* LWIP_IPV6 */ 75 struct sockaddr_in addr; 76#endif /* LWIP_IPV6 */ 77 fdsets sets; 78 struct timeval tv; 79 u32_t ticks_a, ticks_b; 80 int err; 81 const ip_addr_t *ipaddr = (const ip_addr_t*)arg; 82 INIT_FDSETS(&sets); 83 84 /* set up address to connect to */ 85 memset(&addr, 0, sizeof(addr)); 86#if LWIP_IPV6 87 addr.sin6_len = sizeof(addr); 88 addr.sin6_family = AF_INET6; 89 addr.sin6_port = PP_HTONS(SOCK_TARGET_PORT); 90 inet6_addr_from_ip6addr(&addr.sin6_addr, ip_2_ip6(ipaddr)); 91#else /* LWIP_IPV6 */ 92 addr.sin_len = sizeof(addr); 93 addr.sin_family = AF_INET; 94 addr.sin_port = PP_HTONS(SOCK_TARGET_PORT); 95 inet_addr_from_ip4addr(&addr.sin_addr, ip_2_ip4(ipaddr)); 96#endif /* LWIP_IPV6 */ 97 98 /* first try blocking: */ 99 100 /* create the socket */ 101#if LWIP_IPV6 102 s = lwip_socket(AF_INET6, SOCK_STREAM, 0); 103#else /* LWIP_IPV6 */ 104 s = lwip_socket(AF_INET, SOCK_STREAM, 0); 105#endif /* LWIP_IPV6 */ 106 LWIP_ASSERT("s >= 0", s >= 0); 107 108 /* connect */ 109 ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); 110 /* should succeed */ 111 LWIP_ASSERT("ret == 0", ret == 0); 112 113 /* write something */ 114 ret = lwip_write(s, "test", 4); 115 LWIP_ASSERT("ret == 4", ret == 4); 116 117 /* close */ 118 ret = lwip_close(s); 119 LWIP_ASSERT("ret == 0", ret == 0); 120 121 /* now try nonblocking and close before being connected */ 122 123 /* create the socket */ 124#if LWIP_IPV6 125 s = lwip_socket(AF_INET6, SOCK_STREAM, 0); 126#else /* LWIP_IPV6 */ 127 s = lwip_socket(AF_INET, SOCK_STREAM, 0); 128#endif /* LWIP_IPV6 */ 129 LWIP_ASSERT("s >= 0", s >= 0); 130 /* nonblocking */ 131 opt = lwip_fcntl(s, F_GETFL, 0); 132 LWIP_ASSERT("ret != -1", ret != -1); 133 opt |= O_NONBLOCK; 134 ret = lwip_fcntl(s, F_SETFL, opt); 135 LWIP_ASSERT("ret != -1", ret != -1); 136 /* connect */ 137 ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); 138 /* should have an error: "inprogress" */ 139 LWIP_ASSERT("ret == -1", ret == -1); 140 err = errno; 141 LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); 142 /* close */ 143 ret = lwip_close(s); 144 LWIP_ASSERT("ret == 0", ret == 0); 145 /* try to close again, should fail with EBADF */ 146 ret = lwip_close(s); 147 LWIP_ASSERT("ret == -1", ret == -1); 148 err = errno; 149 LWIP_ASSERT("errno == EBADF", err == EBADF); 150 printf("closing socket in nonblocking connect succeeded\n"); 151 152 /* now try nonblocking, connect should succeed: 153 this test only works if it is fast enough, i.e. no breakpoints, please! */ 154 155 /* create the socket */ 156#if LWIP_IPV6 157 s = lwip_socket(AF_INET6, SOCK_STREAM, 0); 158#else /* LWIP_IPV6 */ 159 s = lwip_socket(AF_INET, SOCK_STREAM, 0); 160#endif /* LWIP_IPV6 */ 161 LWIP_ASSERT("s >= 0", s >= 0); 162 163 /* nonblocking */ 164 opt = 1; 165 ret = lwip_ioctl(s, FIONBIO, &opt); 166 LWIP_ASSERT("ret == 0", ret == 0); 167 168 /* connect */ 169 ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); 170 /* should have an error: "inprogress" */ 171 LWIP_ASSERT("ret == -1", ret == -1); 172 err = errno; 173 LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); 174 175 /* write should fail, too */ 176 ret = lwip_write(s, "test", 4); 177 LWIP_ASSERT("ret == -1", ret == -1); 178 err = errno; 179 LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); 180 181 CHECK_FDSETS(&sets); 182 FD_ZERO(&sets.readset); 183 CHECK_FDSETS(&sets); 184 FD_SET(s, &sets.readset); 185 CHECK_FDSETS(&sets); 186 FD_ZERO(&sets.writeset); 187 CHECK_FDSETS(&sets); 188 FD_SET(s, &sets.writeset); 189 CHECK_FDSETS(&sets); 190 FD_ZERO(&sets.errset); 191 CHECK_FDSETS(&sets); 192 FD_SET(s, &sets.errset); 193 CHECK_FDSETS(&sets); 194 tv.tv_sec = 0; 195 tv.tv_usec = 0; 196 /* select without waiting should fail */ 197 ret = lwip_select(s + 1, &sets.readset, &sets.writeset, &sets.errset, &tv); 198 CHECK_FDSETS(&sets); 199 LWIP_ASSERT("ret == 0", ret == 0); 200 LWIP_ASSERT("!FD_ISSET(s, &writeset)", !FD_ISSET(s, &sets.writeset)); 201 LWIP_ASSERT("!FD_ISSET(s, &readset)", !FD_ISSET(s, &sets.readset)); 202 LWIP_ASSERT("!FD_ISSET(s, &errset)", !FD_ISSET(s, &sets.errset)); 203 204 FD_ZERO(&sets.readset); 205 FD_SET(s, &sets.readset); 206 FD_ZERO(&sets.writeset); 207 FD_SET(s, &sets.writeset); 208 FD_ZERO(&sets.errset); 209 FD_SET(s, &sets.errset); 210 ticks_a = sys_now(); 211 /* select with waiting should succeed */ 212 ret = lwip_select(s + 1, &sets.readset, &sets.writeset, &sets.errset, NULL); 213 ticks_b = sys_now(); 214 LWIP_ASSERT("ret == 1", ret == 1); 215 LWIP_ASSERT("FD_ISSET(s, &writeset)", FD_ISSET(s, &sets.writeset)); 216 LWIP_ASSERT("!FD_ISSET(s, &readset)", !FD_ISSET(s, &sets.readset)); 217 LWIP_ASSERT("!FD_ISSET(s, &errset)", !FD_ISSET(s, &sets.errset)); 218 219 /* now write should succeed */ 220 ret = lwip_write(s, "test", 4); 221 LWIP_ASSERT("ret == 4", ret == 4); 222 223 /* close */ 224 ret = lwip_close(s); 225 LWIP_ASSERT("ret == 0", ret == 0); 226 227 printf("select() needed %d ticks to return writable\n", (int)(ticks_b - ticks_a)); 228 229 230 /* now try nonblocking to invalid address: 231 this test only works if it is fast enough, i.e. no breakpoints, please! */ 232 233 /* create the socket */ 234#if LWIP_IPV6 235 s = lwip_socket(AF_INET6, SOCK_STREAM, 0); 236#else /* LWIP_IPV6 */ 237 s = lwip_socket(AF_INET, SOCK_STREAM, 0); 238#endif /* LWIP_IPV6 */ 239 LWIP_ASSERT("s >= 0", s >= 0); 240 241 /* nonblocking */ 242 opt = 1; 243 ret = lwip_ioctl(s, FIONBIO, &opt); 244 LWIP_ASSERT("ret == 0", ret == 0); 245 246#if LWIP_IPV6 247 addr.sin6_addr.un.u8_addr[0]++; /* this should result in an invalid address */ 248#else /* LWIP_IPV6 */ 249 addr.sin_addr.s_addr++; /* this should result in an invalid address */ 250#endif /* LWIP_IPV6 */ 251 252 /* connect */ 253 ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); 254 /* should have an error: "inprogress" */ 255 LWIP_ASSERT("ret == -1", ret == -1); 256 err = errno; 257 LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); 258 259 /* write should fail, too */ 260 ret = lwip_write(s, "test", 4); 261 LWIP_ASSERT("ret == -1", ret == -1); 262 err = errno; 263 LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); 264 LWIP_UNUSED_ARG(err); 265 266 FD_ZERO(&sets.readset); 267 FD_SET(s, &sets.readset); 268 FD_ZERO(&sets.writeset); 269 FD_SET(s, &sets.writeset); 270 FD_ZERO(&sets.errset); 271 FD_SET(s, &sets.errset); 272 tv.tv_sec = 0; 273 tv.tv_usec = 0; 274 /* select without waiting should fail */ 275 ret = lwip_select(s + 1, &sets.readset, &sets.writeset, &sets.errset, &tv); 276 LWIP_ASSERT("ret == 0", ret == 0); 277 278 FD_ZERO(&sets.readset); 279 FD_SET(s, &sets.readset); 280 FD_ZERO(&sets.writeset); 281 FD_SET(s, &sets.writeset); 282 FD_ZERO(&sets.errset); 283 FD_SET(s, &sets.errset); 284 ticks_a = sys_now(); 285 /* select with waiting should eventually succeed and return errset! */ 286 ret = lwip_select(s + 1, &sets.readset, &sets.writeset, &sets.errset, NULL); 287 ticks_b = sys_now(); 288 LWIP_ASSERT("ret > 0", ret > 0); 289 LWIP_ASSERT("FD_ISSET(s, &errset)", FD_ISSET(s, &sets.errset)); 290 /*LWIP_ASSERT("!FD_ISSET(s, &readset)", !FD_ISSET(s, &sets.readset)); 291 LWIP_ASSERT("!FD_ISSET(s, &writeset)", !FD_ISSET(s, &sets.writeset));*/ 292 293 /* close */ 294 ret = lwip_close(s); 295 LWIP_ASSERT("ret == 0", ret == 0); 296 LWIP_UNUSED_ARG(ret); 297 298 printf("select() needed %d ticks to return error\n", (int)(ticks_b - ticks_a)); 299 printf("all tests done, thread ending\n"); 300} 301 302/** This is an example function that tests 303 the recv function (timeout etc.). */ 304static void 305sockex_testrecv(void *arg) 306{ 307 int s; 308 int ret; 309 int err; 310 int opt, opt2; 311 socklen_t opt2size; 312#if LWIP_IPV6 313 struct sockaddr_in6 addr; 314#else /* LWIP_IPV6 */ 315 struct sockaddr_in addr; 316#endif /* LWIP_IPV6 */ 317 size_t len; 318 char rxbuf[SOCK_TARGET_MAXHTTPPAGESIZE]; 319 fd_set readset; 320 fd_set errset; 321 struct timeval tv; 322 const ip_addr_t *ipaddr = (const ip_addr_t*)arg; 323 324 /* set up address to connect to */ 325 memset(&addr, 0, sizeof(addr)); 326#if LWIP_IPV6 327 addr.sin6_len = sizeof(addr); 328 addr.sin6_family = AF_INET6; 329 addr.sin6_port = PP_HTONS(SOCK_TARGET_PORT); 330 inet6_addr_from_ip6addr(&addr.sin6_addr, ip_2_ip6(ipaddr)); 331#else /* LWIP_IPV6 */ 332 addr.sin_len = sizeof(addr); 333 addr.sin_family = AF_INET; 334 addr.sin_port = PP_HTONS(SOCK_TARGET_PORT); 335 inet_addr_from_ip4addr(&addr.sin_addr, ip_2_ip4(ipaddr)); 336#endif /* LWIP_IPV6 */ 337 338 /* first try blocking: */ 339 340 /* create the socket */ 341#if LWIP_IPV6 342 s = lwip_socket(AF_INET6, SOCK_STREAM, 0); 343#else /* LWIP_IPV6 */ 344 s = lwip_socket(AF_INET, SOCK_STREAM, 0); 345#endif /* LWIP_IPV6 */ 346 LWIP_ASSERT("s >= 0", s >= 0); 347 348 /* connect */ 349 ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); 350 /* should succeed */ 351 LWIP_ASSERT("ret == 0", ret == 0); 352 353 /* set recv timeout (100 ms) */ 354 opt = 100; 355 ret = lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &opt, sizeof(int)); 356 LWIP_ASSERT("ret == 0", ret == 0); 357 opt2 = 0; 358 opt2size = sizeof(opt2); 359 ret = lwip_getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &opt2, &opt2size); 360 LWIP_ASSERT("ret == 0", ret == 0); 361 LWIP_ASSERT("opt2size == sizeof(opt2)", opt2size == sizeof(opt2)); 362 LWIP_ASSERT("opt == opt2", opt == opt2); 363 364 /* write the start of a GET request */ 365#define SNDSTR1 "G" 366 len = strlen(SNDSTR1); 367 ret = lwip_write(s, SNDSTR1, len); 368 LWIP_ASSERT("ret == len", ret == (int)len); 369 370 /* should time out if the other side is a good HTTP server */ 371 ret = lwip_read(s, rxbuf, 1); 372 LWIP_ASSERT("ret == -1", ret == -1); 373 err = errno; 374 LWIP_ASSERT("errno == EAGAIN", err == EAGAIN); 375 LWIP_UNUSED_ARG(err); 376 377 /* write the rest of a GET request */ 378#define SNDSTR2 "ET / HTTP_1.1\r\n\r\n" 379 len = strlen(SNDSTR2); 380 ret = lwip_write(s, SNDSTR2, len); 381 LWIP_ASSERT("ret == len", ret == (int)len); 382 383 /* wait a while: should be enough for the server to send a response */ 384 sys_msleep(1000); 385 386 /* should not time out but receive a response */ 387 ret = lwip_read(s, rxbuf, SOCK_TARGET_MAXHTTPPAGESIZE); 388 LWIP_ASSERT("ret > 0", ret > 0); 389 390 /* now select should directly return because the socket is readable */ 391 FD_ZERO(&readset); 392 FD_ZERO(&errset); 393 FD_SET(s, &readset); 394 FD_SET(s, &errset); 395 tv.tv_sec = 10; 396 tv.tv_usec = 0; 397 ret = lwip_select(s + 1, &readset, NULL, &errset, &tv); 398 LWIP_ASSERT("ret == 1", ret == 1); 399 LWIP_ASSERT("!FD_ISSET(s, &errset)", !FD_ISSET(s, &errset)); 400 LWIP_ASSERT("FD_ISSET(s, &readset)", FD_ISSET(s, &readset)); 401 402 /* should not time out but receive a response */ 403 ret = lwip_read(s, rxbuf, SOCK_TARGET_MAXHTTPPAGESIZE); 404 /* might receive a second packet for HTTP/1.1 servers */ 405 if (ret > 0) { 406 /* should return 0: closed */ 407 ret = lwip_read(s, rxbuf, SOCK_TARGET_MAXHTTPPAGESIZE); 408 LWIP_ASSERT("ret == 0", ret == 0); 409 } 410 411 /* close */ 412 ret = lwip_close(s); 413 LWIP_ASSERT("ret == 0", ret == 0); 414 LWIP_UNUSED_ARG(ret); 415 416 printf("sockex_testrecv finished successfully\n"); 417} 418 419/** helper struct for the 2 functions below (multithreaded: thread-argument) */ 420struct sockex_select_helper { 421 int socket; 422 int wait_read; 423 int expect_read; 424 int wait_write; 425 int expect_write; 426 int wait_err; 427 int expect_err; 428 int wait_ms; 429 sys_sem_t sem; 430}; 431 432/** helper thread to wait for socket events using select */ 433static void 434sockex_select_waiter(void *arg) 435{ 436 struct sockex_select_helper *helper = (struct sockex_select_helper *)arg; 437 int ret; 438 fd_set readset; 439 fd_set writeset; 440 fd_set errset; 441 struct timeval tv; 442 443 LWIP_ASSERT("helper != NULL", helper != NULL); 444 445 FD_ZERO(&readset); 446 FD_ZERO(&writeset); 447 FD_ZERO(&errset); 448 if (helper->wait_read) { 449 FD_SET(helper->socket, &readset); 450 } 451 if (helper->wait_write) { 452 FD_SET(helper->socket, &writeset); 453 } 454 if (helper->wait_err) { 455 FD_SET(helper->socket, &errset); 456 } 457 458 tv.tv_sec = helper->wait_ms / 1000; 459 tv.tv_usec = (helper->wait_ms % 1000) * 1000; 460 461 ret = lwip_select(helper->socket, &readset, &writeset, &errset, &tv); 462 if (helper->expect_read || helper->expect_write || helper->expect_err) { 463 LWIP_ASSERT("ret > 0", ret > 0); 464 } else { 465 LWIP_ASSERT("ret == 0", ret == 0); 466 } 467 LWIP_UNUSED_ARG(ret); 468 if (helper->expect_read) { 469 LWIP_ASSERT("FD_ISSET(helper->socket, &readset)", FD_ISSET(helper->socket, &readset)); 470 } else { 471 LWIP_ASSERT("!FD_ISSET(helper->socket, &readset)", !FD_ISSET(helper->socket, &readset)); 472 } 473 if (helper->expect_write) { 474 LWIP_ASSERT("FD_ISSET(helper->socket, &writeset)", FD_ISSET(helper->socket, &writeset)); 475 } else { 476 LWIP_ASSERT("!FD_ISSET(helper->socket, &writeset)", !FD_ISSET(helper->socket, &writeset)); 477 } 478 if (helper->expect_err) { 479 LWIP_ASSERT("FD_ISSET(helper->socket, &errset)", FD_ISSET(helper->socket, &errset)); 480 } else { 481 LWIP_ASSERT("!FD_ISSET(helper->socket, &errset)", !FD_ISSET(helper->socket, &errset)); 482 } 483 sys_sem_signal(&helper->sem); 484} 485 486/** This is an example function that tests 487 more than one thread being active in select. */ 488static void 489sockex_testtwoselects(void *arg) 490{ 491 int s1; 492 int s2; 493 int ret; 494#if LWIP_IPV6 495 struct sockaddr_in6 addr; 496#else /* LWIP_IPV6 */ 497 struct sockaddr_in addr; 498#endif /* LWIP_IPV6 */ 499 size_t len; 500 err_t lwiperr; 501 struct sockex_select_helper h1, h2, h3, h4; 502 const ip_addr_t *ipaddr = (const ip_addr_t*)arg; 503 504 /* set up address to connect to */ 505 memset(&addr, 0, sizeof(addr)); 506#if LWIP_IPV6 507 addr.sin6_len = sizeof(addr); 508 addr.sin6_family = AF_INET6; 509 addr.sin6_port = PP_HTONS(SOCK_TARGET_PORT); 510 inet6_addr_from_ip6addr(&addr.sin6_addr, ip_2_ip6(ipaddr)); 511#else /* LWIP_IPV6 */ 512 addr.sin_len = sizeof(addr); 513 addr.sin_family = AF_INET; 514 addr.sin_port = PP_HTONS(SOCK_TARGET_PORT); 515 inet_addr_from_ip4addr(&addr.sin_addr, ip_2_ip4(ipaddr)); 516#endif /* LWIP_IPV6 */ 517 518 /* create the sockets */ 519#if LWIP_IPV6 520 s1 = lwip_socket(AF_INET6, SOCK_STREAM, 0); 521 s2 = lwip_socket(AF_INET6, SOCK_STREAM, 0); 522#else /* LWIP_IPV6 */ 523 s1 = lwip_socket(AF_INET, SOCK_STREAM, 0); 524 s2 = lwip_socket(AF_INET, SOCK_STREAM, 0); 525#endif /* LWIP_IPV6 */ 526 LWIP_ASSERT("s1 >= 0", s1 >= 0); 527 LWIP_ASSERT("s2 >= 0", s2 >= 0); 528 529 /* connect, should succeed */ 530 ret = lwip_connect(s1, (struct sockaddr*)&addr, sizeof(addr)); 531 LWIP_ASSERT("ret == 0", ret == 0); 532 ret = lwip_connect(s2, (struct sockaddr*)&addr, sizeof(addr)); 533 LWIP_ASSERT("ret == 0", ret == 0); 534 535 /* write the start of a GET request */ 536#define SNDSTR1 "G" 537 len = strlen(SNDSTR1); 538 ret = lwip_write(s1, SNDSTR1, len); 539 LWIP_ASSERT("ret == len", ret == (int)len); 540 ret = lwip_write(s2, SNDSTR1, len); 541 LWIP_ASSERT("ret == len", ret == (int)len); 542 LWIP_UNUSED_ARG(ret); 543 544 h1.wait_read = 1; 545 h1.wait_write = 1; 546 h1.wait_err = 1; 547 h1.expect_read = 0; 548 h1.expect_write = 0; 549 h1.expect_err = 0; 550 lwiperr = sys_sem_new(&h1.sem, 0); 551 LWIP_ASSERT("lwiperr == ERR_OK", lwiperr == ERR_OK); 552 h1.socket = s1; 553 h1.wait_ms = 500; 554 555 h2 = h1; 556 lwiperr = sys_sem_new(&h2.sem, 0); 557 LWIP_ASSERT("lwiperr == ERR_OK", lwiperr == ERR_OK); 558 h2.socket = s2; 559 h2.wait_ms = 1000; 560 561 h3 = h1; 562 lwiperr = sys_sem_new(&h3.sem, 0); 563 LWIP_ASSERT("lwiperr == ERR_OK", lwiperr == ERR_OK); 564 h3.socket = s2; 565 h3.wait_ms = 1500; 566 567 h4 = h1; 568 lwiperr = sys_sem_new(&h4.sem, 0); 569 LWIP_ASSERT("lwiperr == ERR_OK", lwiperr == ERR_OK); 570 LWIP_UNUSED_ARG(lwiperr); 571 h4.socket = s2; 572 h4.wait_ms = 2000; 573 574 /* select: all sockets should time out if the other side is a good HTTP server */ 575 576 sys_thread_new("sockex_select_waiter1", sockex_select_waiter, &h2, 0, 0); 577 sys_msleep(100); 578 sys_thread_new("sockex_select_waiter2", sockex_select_waiter, &h1, 0, 0); 579 sys_msleep(100); 580 sys_thread_new("sockex_select_waiter2", sockex_select_waiter, &h4, 0, 0); 581 sys_msleep(100); 582 sys_thread_new("sockex_select_waiter2", sockex_select_waiter, &h3, 0, 0); 583 584 sys_sem_wait(&h1.sem); 585 sys_sem_wait(&h2.sem); 586 sys_sem_wait(&h3.sem); 587 sys_sem_wait(&h4.sem); 588 589 /* close */ 590 ret = lwip_close(s1); 591 LWIP_ASSERT("ret == 0", ret == 0); 592 ret = lwip_close(s2); 593 LWIP_ASSERT("ret == 0", ret == 0); 594 595 printf("sockex_testtwoselects finished successfully\n"); 596} 597 598#if !SOCKET_EXAMPLES_RUN_PARALLEL 599static void 600socket_example_test(void* arg) 601{ 602 sockex_nonblocking_connect(arg); 603 sockex_testrecv(arg); 604 sockex_testtwoselects(arg); 605} 606#endif 607 608void socket_examples_init(void) 609{ 610 611#if LWIP_IPV6 612 IP_SET_TYPE_VAL(dstaddr, IPADDR_TYPE_V6); 613 ip6addr_aton(SOCK_TARGET_HOST6, ip_2_ip6(&dstaddr)); 614#else /* LWIP_IPV6 */ 615 IP_SET_TYPE_VAL(dstaddr, IPADDR_TYPE_V4); 616 ip4addr_aton(SOCK_TARGET_HOST4, ip_2_ip4(&dstaddr)); 617#endif /* LWIP_IPV6 */ 618 619#if SOCKET_EXAMPLES_RUN_PARALLEL 620 sys_thread_new("sockex_nonblocking_connect", sockex_nonblocking_connect, &dstaddr, 0, 0); 621 sys_thread_new("sockex_testrecv", sockex_testrecv, &dstaddr, 0, 0); 622 sys_thread_new("sockex_testtwoselects", sockex_testtwoselects, &dstaddr, 0, 0); 623#else 624 sys_thread_new("socket_example_test", socket_example_test, &dstaddr, 0, 0); 625#endif 626} 627 628#endif /* LWIP_SOCKET */ 629