1195972f6Sopenharmony_ci#include "test_sockets.h" 2195972f6Sopenharmony_ci 3195972f6Sopenharmony_ci#include "lwip/mem.h" 4195972f6Sopenharmony_ci#include "lwip/opt.h" 5195972f6Sopenharmony_ci#include "lwip/sockets.h" 6195972f6Sopenharmony_ci#include "lwip/priv/sockets_priv.h" 7195972f6Sopenharmony_ci#include "lwip/stats.h" 8195972f6Sopenharmony_ci 9195972f6Sopenharmony_ci#include "lwip/tcpip.h" 10195972f6Sopenharmony_ci#include "lwip/priv/tcp_priv.h" 11195972f6Sopenharmony_ci#include "lwip/api.h" 12195972f6Sopenharmony_ci 13195972f6Sopenharmony_ci 14195972f6Sopenharmony_cistatic int 15195972f6Sopenharmony_citest_sockets_get_used_count(void) 16195972f6Sopenharmony_ci{ 17195972f6Sopenharmony_ci int used = 0; 18195972f6Sopenharmony_ci int i; 19195972f6Sopenharmony_ci 20195972f6Sopenharmony_ci for (i = 0; i < NUM_SOCKETS; i++) { 21195972f6Sopenharmony_ci struct lwip_sock* s = lwip_socket_dbg_get_socket(i); 22195972f6Sopenharmony_ci if (s != NULL) { 23195972f6Sopenharmony_ci if (s->fd_used) { 24195972f6Sopenharmony_ci used++; 25195972f6Sopenharmony_ci } 26195972f6Sopenharmony_ci } 27195972f6Sopenharmony_ci } 28195972f6Sopenharmony_ci return used; 29195972f6Sopenharmony_ci} 30195972f6Sopenharmony_ci 31195972f6Sopenharmony_ci 32195972f6Sopenharmony_ci/* Setups/teardown functions */ 33195972f6Sopenharmony_ci 34195972f6Sopenharmony_cistatic void 35195972f6Sopenharmony_cisockets_setup(void) 36195972f6Sopenharmony_ci{ 37195972f6Sopenharmony_ci /* expect full free heap */ 38195972f6Sopenharmony_ci lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 39195972f6Sopenharmony_ci} 40195972f6Sopenharmony_ci 41195972f6Sopenharmony_cistatic void 42195972f6Sopenharmony_cisockets_teardown(void) 43195972f6Sopenharmony_ci{ 44195972f6Sopenharmony_ci fail_unless(test_sockets_get_used_count() == 0); 45195972f6Sopenharmony_ci /* poll until all memory is released... */ 46195972f6Sopenharmony_ci tcpip_thread_poll_one(); 47195972f6Sopenharmony_ci while (tcp_tw_pcbs) { 48195972f6Sopenharmony_ci tcp_abort(tcp_tw_pcbs); 49195972f6Sopenharmony_ci tcpip_thread_poll_one(); 50195972f6Sopenharmony_ci } 51195972f6Sopenharmony_ci tcpip_thread_poll_one(); 52195972f6Sopenharmony_ci /* ensure full free heap */ 53195972f6Sopenharmony_ci lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); 54195972f6Sopenharmony_ci} 55195972f6Sopenharmony_ci 56195972f6Sopenharmony_ci#ifndef NUM_SOCKETS 57195972f6Sopenharmony_ci#define NUM_SOCKETS MEMP_NUM_NETCONN 58195972f6Sopenharmony_ci#endif 59195972f6Sopenharmony_ci 60195972f6Sopenharmony_ci#if LWIP_SOCKET 61195972f6Sopenharmony_cistatic int 62195972f6Sopenharmony_citest_sockets_alloc_socket_nonblocking(int domain, int type) 63195972f6Sopenharmony_ci{ 64195972f6Sopenharmony_ci int s = lwip_socket(domain, type, 0); 65195972f6Sopenharmony_ci if (s >= 0) { 66195972f6Sopenharmony_ci int ret = lwip_fcntl(s, F_SETFL, O_NONBLOCK); 67195972f6Sopenharmony_ci fail_unless(ret == 0); 68195972f6Sopenharmony_ci } 69195972f6Sopenharmony_ci return s; 70195972f6Sopenharmony_ci} 71195972f6Sopenharmony_ci 72195972f6Sopenharmony_ci/* Verify basic sockets functionality 73195972f6Sopenharmony_ci */ 74195972f6Sopenharmony_ciSTART_TEST(test_sockets_basics) 75195972f6Sopenharmony_ci{ 76195972f6Sopenharmony_ci int s, i, ret; 77195972f6Sopenharmony_ci int s2[NUM_SOCKETS]; 78195972f6Sopenharmony_ci LWIP_UNUSED_ARG(_i); 79195972f6Sopenharmony_ci 80195972f6Sopenharmony_ci s = lwip_socket(AF_INET, SOCK_STREAM, 0); 81195972f6Sopenharmony_ci fail_unless(s >= 0); 82195972f6Sopenharmony_ci lwip_close(s); 83195972f6Sopenharmony_ci 84195972f6Sopenharmony_ci for (i = 0; i < NUM_SOCKETS; i++) { 85195972f6Sopenharmony_ci s2[i] = lwip_socket(AF_INET, SOCK_STREAM, 0); 86195972f6Sopenharmony_ci fail_unless(s2[i] >= 0); 87195972f6Sopenharmony_ci } 88195972f6Sopenharmony_ci 89195972f6Sopenharmony_ci /* all sockets used, now it should fail */ 90195972f6Sopenharmony_ci s = lwip_socket(AF_INET, SOCK_STREAM, 0); 91195972f6Sopenharmony_ci fail_unless(s == -1); 92195972f6Sopenharmony_ci /* close one socket */ 93195972f6Sopenharmony_ci ret = lwip_close(s2[0]); 94195972f6Sopenharmony_ci fail_unless(ret == 0); 95195972f6Sopenharmony_ci /* now it should succeed */ 96195972f6Sopenharmony_ci s2[0] = lwip_socket(AF_INET, SOCK_STREAM, 0); 97195972f6Sopenharmony_ci fail_unless(s2[0] >= 0); 98195972f6Sopenharmony_ci 99195972f6Sopenharmony_ci /* close all sockets */ 100195972f6Sopenharmony_ci for (i = 0; i < NUM_SOCKETS; i++) { 101195972f6Sopenharmony_ci ret = lwip_close(s2[i]); 102195972f6Sopenharmony_ci fail_unless(ret == 0); 103195972f6Sopenharmony_ci } 104195972f6Sopenharmony_ci} 105195972f6Sopenharmony_ciEND_TEST 106195972f6Sopenharmony_ci 107195972f6Sopenharmony_cistatic void test_sockets_allfunctions_basic_domain(int domain) 108195972f6Sopenharmony_ci{ 109195972f6Sopenharmony_ci int s, s2, s3, ret; 110195972f6Sopenharmony_ci struct sockaddr_storage addr, addr2; 111195972f6Sopenharmony_ci socklen_t addrlen, addr2len; 112195972f6Sopenharmony_ci char buf[4]; 113195972f6Sopenharmony_ci /* listen socket */ 114195972f6Sopenharmony_ci s = lwip_socket(domain, SOCK_STREAM, 0); 115195972f6Sopenharmony_ci fail_unless(s >= 0); 116195972f6Sopenharmony_ci 117195972f6Sopenharmony_ci ret = lwip_listen(s, 0); 118195972f6Sopenharmony_ci fail_unless(ret == 0); 119195972f6Sopenharmony_ci 120195972f6Sopenharmony_ci addrlen = sizeof(addr); 121195972f6Sopenharmony_ci ret = lwip_getsockname(s, (struct sockaddr*)&addr, &addrlen); 122195972f6Sopenharmony_ci fail_unless(ret == 0); 123195972f6Sopenharmony_ci 124195972f6Sopenharmony_ci s2 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM); 125195972f6Sopenharmony_ci fail_unless(s2 >= 0); 126195972f6Sopenharmony_ci /* nonblocking connect s2 to s (but use loopback address) */ 127195972f6Sopenharmony_ci if (domain == AF_INET) { 128195972f6Sopenharmony_ci#if LWIP_IPV4 129195972f6Sopenharmony_ci struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; 130195972f6Sopenharmony_ci addr4->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); 131195972f6Sopenharmony_ci#endif 132195972f6Sopenharmony_ci } else { 133195972f6Sopenharmony_ci#if LWIP_IPV6 134195972f6Sopenharmony_ci struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 135195972f6Sopenharmony_ci struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; 136195972f6Sopenharmony_ci addr6->sin6_addr = lo6; 137195972f6Sopenharmony_ci#endif 138195972f6Sopenharmony_ci } 139195972f6Sopenharmony_ci ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); 140195972f6Sopenharmony_ci fail_unless(ret == -1); 141195972f6Sopenharmony_ci fail_unless(errno == EINPROGRESS); 142195972f6Sopenharmony_ci ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); 143195972f6Sopenharmony_ci fail_unless(ret == -1); 144195972f6Sopenharmony_ci fail_unless(errno == EALREADY); 145195972f6Sopenharmony_ci 146195972f6Sopenharmony_ci while(tcpip_thread_poll_one()); 147195972f6Sopenharmony_ci 148195972f6Sopenharmony_ci s3 = lwip_accept(s, (struct sockaddr*)&addr2, &addr2len); 149195972f6Sopenharmony_ci fail_unless(s3 >= 0); 150195972f6Sopenharmony_ci 151195972f6Sopenharmony_ci ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); 152195972f6Sopenharmony_ci fail_unless(ret == -1); 153195972f6Sopenharmony_ci fail_unless(errno == EISCONN); 154195972f6Sopenharmony_ci 155195972f6Sopenharmony_ci /* write from server to client */ 156195972f6Sopenharmony_ci ret = write(s3, "test", 4); 157195972f6Sopenharmony_ci fail_unless(ret == 4); 158195972f6Sopenharmony_ci 159195972f6Sopenharmony_ci ret = lwip_shutdown(s3, SHUT_WR); 160195972f6Sopenharmony_ci fail_unless(ret == 0); 161195972f6Sopenharmony_ci 162195972f6Sopenharmony_ci while(tcpip_thread_poll_one()); 163195972f6Sopenharmony_ci 164195972f6Sopenharmony_ci ret = lwip_recv(s2, buf, 3, MSG_PEEK); 165195972f6Sopenharmony_ci fail_unless(ret == 3); 166195972f6Sopenharmony_ci 167195972f6Sopenharmony_ci ret = lwip_recv(s2, buf, 3, MSG_PEEK); 168195972f6Sopenharmony_ci fail_unless(ret == 3); 169195972f6Sopenharmony_ci 170195972f6Sopenharmony_ci ret = lwip_read(s2, buf, 4); 171195972f6Sopenharmony_ci fail_unless(ret == 4); 172195972f6Sopenharmony_ci 173195972f6Sopenharmony_ci ret = lwip_read(s2, buf, 1); 174195972f6Sopenharmony_ci fail_unless(ret == 0); 175195972f6Sopenharmony_ci 176195972f6Sopenharmony_ci ret = lwip_read(s2, buf, 1); 177195972f6Sopenharmony_ci fail_unless(ret == -1); 178195972f6Sopenharmony_ci 179195972f6Sopenharmony_ci ret = lwip_write(s2, "foo", 3); 180195972f6Sopenharmony_ci fail_unless(ret == 3); 181195972f6Sopenharmony_ci 182195972f6Sopenharmony_ci ret = lwip_close(s2); 183195972f6Sopenharmony_ci fail_unless(ret == 0); 184195972f6Sopenharmony_ci 185195972f6Sopenharmony_ci while(tcpip_thread_poll_one()); 186195972f6Sopenharmony_ci 187195972f6Sopenharmony_ci /* read one byte more than available to check handling FIN */ 188195972f6Sopenharmony_ci ret = lwip_read(s3, buf, 4); 189195972f6Sopenharmony_ci fail_unless(ret == 3); 190195972f6Sopenharmony_ci 191195972f6Sopenharmony_ci ret = lwip_read(s3, buf, 1); 192195972f6Sopenharmony_ci fail_unless(ret == 0); 193195972f6Sopenharmony_ci 194195972f6Sopenharmony_ci ret = lwip_read(s3, buf, 1); 195195972f6Sopenharmony_ci fail_unless(ret == -1); 196195972f6Sopenharmony_ci 197195972f6Sopenharmony_ci while(tcpip_thread_poll_one()); 198195972f6Sopenharmony_ci 199195972f6Sopenharmony_ci ret = lwip_close(s); 200195972f6Sopenharmony_ci fail_unless(ret == 0); 201195972f6Sopenharmony_ci ret = lwip_close(s3); 202195972f6Sopenharmony_ci fail_unless(ret == 0); 203195972f6Sopenharmony_ci} 204195972f6Sopenharmony_ci 205195972f6Sopenharmony_ci/* Try to step through all sockets functions once... 206195972f6Sopenharmony_ci */ 207195972f6Sopenharmony_ciSTART_TEST(test_sockets_allfunctions_basic) 208195972f6Sopenharmony_ci{ 209195972f6Sopenharmony_ci LWIP_UNUSED_ARG(_i); 210195972f6Sopenharmony_ci#if LWIP_IPV4 211195972f6Sopenharmony_ci test_sockets_allfunctions_basic_domain(AF_INET); 212195972f6Sopenharmony_ci#endif 213195972f6Sopenharmony_ci#if LWIP_IPV6 214195972f6Sopenharmony_ci test_sockets_allfunctions_basic_domain(AF_INET6); 215195972f6Sopenharmony_ci#endif 216195972f6Sopenharmony_ci} 217195972f6Sopenharmony_ciEND_TEST 218195972f6Sopenharmony_ci 219195972f6Sopenharmony_cistatic void test_sockets_init_loopback_addr(int domain, struct sockaddr_storage *addr_st, socklen_t *sz) 220195972f6Sopenharmony_ci{ 221195972f6Sopenharmony_ci memset(addr_st, 0, sizeof(*addr_st)); 222195972f6Sopenharmony_ci switch(domain) { 223195972f6Sopenharmony_ci#if LWIP_IPV6 224195972f6Sopenharmony_ci case AF_INET6: { 225195972f6Sopenharmony_ci struct sockaddr_in6 *addr = (struct sockaddr_in6*)addr_st; 226195972f6Sopenharmony_ci struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; 227195972f6Sopenharmony_ci addr->sin6_family = AF_INET6; 228195972f6Sopenharmony_ci addr->sin6_port = 0; /* use ephemeral port */ 229195972f6Sopenharmony_ci addr->sin6_addr = lo6; 230195972f6Sopenharmony_ci *sz = sizeof(*addr); 231195972f6Sopenharmony_ci } 232195972f6Sopenharmony_ci break; 233195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 234195972f6Sopenharmony_ci#if LWIP_IPV4 235195972f6Sopenharmony_ci case AF_INET: { 236195972f6Sopenharmony_ci struct sockaddr_in *addr = (struct sockaddr_in*)addr_st; 237195972f6Sopenharmony_ci addr->sin_family = AF_INET; 238195972f6Sopenharmony_ci addr->sin_port = 0; /* use ephemeral port */ 239195972f6Sopenharmony_ci addr->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); 240195972f6Sopenharmony_ci *sz = sizeof(*addr); 241195972f6Sopenharmony_ci } 242195972f6Sopenharmony_ci break; 243195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 244195972f6Sopenharmony_ci default: 245195972f6Sopenharmony_ci *sz = 0; 246195972f6Sopenharmony_ci fail(); 247195972f6Sopenharmony_ci break; 248195972f6Sopenharmony_ci } 249195972f6Sopenharmony_ci} 250195972f6Sopenharmony_ci 251195972f6Sopenharmony_cistatic void test_sockets_msgapi_update_iovs(struct msghdr *msg, size_t bytes) 252195972f6Sopenharmony_ci{ 253195972f6Sopenharmony_ci int i; 254195972f6Sopenharmony_ci 255195972f6Sopenharmony_ci /* note: this modifies the underyling iov_base and iov_len for a partial 256195972f6Sopenharmony_ci read for an individual vector. This updates the msg->msg_iov pointer 257195972f6Sopenharmony_ci to skip fully consumed vecotrs */ 258195972f6Sopenharmony_ci 259195972f6Sopenharmony_ci /* process fully consumed vectors */ 260195972f6Sopenharmony_ci for (i = 0; i < msg->msg_iovlen; i++) { 261195972f6Sopenharmony_ci if (msg->msg_iov[i].iov_len <= bytes) { 262195972f6Sopenharmony_ci /* reduce bytes by amount of this vector */ 263195972f6Sopenharmony_ci bytes -= msg->msg_iov[i].iov_len; 264195972f6Sopenharmony_ci } else { 265195972f6Sopenharmony_ci break; /* iov not fully consumed */ 266195972f6Sopenharmony_ci } 267195972f6Sopenharmony_ci } 268195972f6Sopenharmony_ci 269195972f6Sopenharmony_ci /* slide down over fully consumed vectors */ 270195972f6Sopenharmony_ci msg->msg_iov = &msg->msg_iov[i]; 271195972f6Sopenharmony_ci msg->msg_iovlen -= i; 272195972f6Sopenharmony_ci 273195972f6Sopenharmony_ci /* update new first vector with any remaining amount */ 274195972f6Sopenharmony_ci msg->msg_iov[0].iov_base = ((u8_t *)msg->msg_iov[0].iov_base + bytes); 275195972f6Sopenharmony_ci msg->msg_iov[0].iov_len -= bytes; 276195972f6Sopenharmony_ci} 277195972f6Sopenharmony_ci 278195972f6Sopenharmony_cistatic void test_sockets_msgapi_tcp(int domain) 279195972f6Sopenharmony_ci{ 280195972f6Sopenharmony_ci #define BUF_SZ (TCP_SND_BUF/4) 281195972f6Sopenharmony_ci #define TOTAL_DATA_SZ (BUF_SZ*8) /* ~(TCP_SND_BUF*2) that accounts for integer rounding */ 282195972f6Sopenharmony_ci #define NEED_TRAILER (BUF_SZ % 4 != 0) 283195972f6Sopenharmony_ci int listnr, s1, s2, i, ret, opt; 284195972f6Sopenharmony_ci int bytes_written, bytes_read; 285195972f6Sopenharmony_ci struct sockaddr_storage addr_storage; 286195972f6Sopenharmony_ci socklen_t addr_size; 287195972f6Sopenharmony_ci struct iovec siovs[8]; 288195972f6Sopenharmony_ci struct msghdr smsg; 289195972f6Sopenharmony_ci u8_t * snd_buf; 290195972f6Sopenharmony_ci struct iovec riovs[5]; 291195972f6Sopenharmony_ci struct iovec riovs_tmp[5]; 292195972f6Sopenharmony_ci struct msghdr rmsg; 293195972f6Sopenharmony_ci u8_t * rcv_buf; 294195972f6Sopenharmony_ci int rcv_off; 295195972f6Sopenharmony_ci int rcv_trailer = 0; 296195972f6Sopenharmony_ci u8_t val; 297195972f6Sopenharmony_ci 298195972f6Sopenharmony_ci test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size); 299195972f6Sopenharmony_ci 300195972f6Sopenharmony_ci listnr = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM); 301195972f6Sopenharmony_ci fail_unless(listnr >= 0); 302195972f6Sopenharmony_ci s1 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM); 303195972f6Sopenharmony_ci fail_unless(s1 >= 0); 304195972f6Sopenharmony_ci 305195972f6Sopenharmony_ci /* setup a listener socket on loopback with ephemeral port */ 306195972f6Sopenharmony_ci ret = lwip_bind(listnr, (struct sockaddr*)&addr_storage, addr_size); 307195972f6Sopenharmony_ci fail_unless(ret == 0); 308195972f6Sopenharmony_ci ret = lwip_listen(listnr, 0); 309195972f6Sopenharmony_ci fail_unless(ret == 0); 310195972f6Sopenharmony_ci 311195972f6Sopenharmony_ci /* update address with ephemeral port */ 312195972f6Sopenharmony_ci ret = lwip_getsockname(listnr, (struct sockaddr*)&addr_storage, &addr_size); 313195972f6Sopenharmony_ci fail_unless(ret == 0); 314195972f6Sopenharmony_ci 315195972f6Sopenharmony_ci /* connect, won't complete until we accept it */ 316195972f6Sopenharmony_ci ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size); 317195972f6Sopenharmony_ci fail_unless(ret == -1); 318195972f6Sopenharmony_ci fail_unless(errno == EINPROGRESS); 319195972f6Sopenharmony_ci 320195972f6Sopenharmony_ci while (tcpip_thread_poll_one()); 321195972f6Sopenharmony_ci 322195972f6Sopenharmony_ci /* accept, creating the other side of the connection */ 323195972f6Sopenharmony_ci s2 = lwip_accept(listnr, NULL, NULL); 324195972f6Sopenharmony_ci fail_unless(s2 >= 0); 325195972f6Sopenharmony_ci 326195972f6Sopenharmony_ci /* double check s1 is connected */ 327195972f6Sopenharmony_ci ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size); 328195972f6Sopenharmony_ci fail_unless(ret == -1); 329195972f6Sopenharmony_ci fail_unless(errno == EISCONN); 330195972f6Sopenharmony_ci 331195972f6Sopenharmony_ci /* set s2 to non-blocking, not inherited from listener */ 332195972f6Sopenharmony_ci opt = lwip_fcntl(s2, F_GETFL, 0); 333195972f6Sopenharmony_ci fail_unless(opt == 6); 334195972f6Sopenharmony_ci opt = O_NONBLOCK; 335195972f6Sopenharmony_ci ret = lwip_fcntl(s2, F_SETFL, opt); 336195972f6Sopenharmony_ci fail_unless(ret == 0); 337195972f6Sopenharmony_ci 338195972f6Sopenharmony_ci /* we are done with listener, close it */ 339195972f6Sopenharmony_ci ret = lwip_close(listnr); 340195972f6Sopenharmony_ci fail_unless(ret == 0); 341195972f6Sopenharmony_ci 342195972f6Sopenharmony_ci /* allocate a buffer for a stream of incrementing hex (0x00..0xFF) which we will use 343195972f6Sopenharmony_ci to create an input vector set that is larger than the TCP's send buffer. This will 344195972f6Sopenharmony_ci force execution of the partial IO vector send case */ 345195972f6Sopenharmony_ci snd_buf = (u8_t*)mem_malloc(BUF_SZ); 346195972f6Sopenharmony_ci val = 0x00; 347195972f6Sopenharmony_ci fail_unless(snd_buf != NULL); 348195972f6Sopenharmony_ci for (i = 0; i < BUF_SZ; i++,val++) { 349195972f6Sopenharmony_ci snd_buf[i] = val; 350195972f6Sopenharmony_ci } 351195972f6Sopenharmony_ci 352195972f6Sopenharmony_ci /* send the buffer 8 times in one message, equating to TOTAL_DATA_SZ */ 353195972f6Sopenharmony_ci for (i = 0; i < 8; i++) { 354195972f6Sopenharmony_ci siovs[i].iov_base = snd_buf; 355195972f6Sopenharmony_ci siovs[i].iov_len = BUF_SZ; 356195972f6Sopenharmony_ci } 357195972f6Sopenharmony_ci 358195972f6Sopenharmony_ci /* allocate a receive buffer, same size as snd_buf for easy verification */ 359195972f6Sopenharmony_ci rcv_buf = (u8_t*)mem_calloc(1, BUF_SZ); 360195972f6Sopenharmony_ci fail_unless(rcv_buf != NULL); 361195972f6Sopenharmony_ci /* split across iovs */ 362195972f6Sopenharmony_ci for (i = 0; i < 4; i++) { 363195972f6Sopenharmony_ci riovs[i].iov_base = &rcv_buf[i*(BUF_SZ/4)]; 364195972f6Sopenharmony_ci riovs[i].iov_len = BUF_SZ/4; 365195972f6Sopenharmony_ci } 366195972f6Sopenharmony_ci /* handling trailing bytes if buffer doesn't evenly divide by 4 */ 367195972f6Sopenharmony_ci#if NEED_TRAILER 368195972f6Sopenharmony_ci if ((BUF_SZ % 4) != 0) { 369195972f6Sopenharmony_ci riovs[5].iov_base = &rcv_buf[4*(BUF_SZ/4)]; 370195972f6Sopenharmony_ci riovs[5].iov_len = BUF_SZ - (4*(BUF_SZ/4)); 371195972f6Sopenharmony_ci rcv_trailer = 1; 372195972f6Sopenharmony_ci } 373195972f6Sopenharmony_ci#endif /* NEED_TRAILER */ 374195972f6Sopenharmony_ci 375195972f6Sopenharmony_ci /* we use a copy of riovs since we'll be modifying base and len during 376195972f6Sopenharmony_ci receiving. This gives us an easy way to reset the iovs for next recvmsg */ 377195972f6Sopenharmony_ci memcpy(riovs_tmp, riovs, sizeof(riovs)); 378195972f6Sopenharmony_ci 379195972f6Sopenharmony_ci memset(&smsg, 0, sizeof(smsg)); 380195972f6Sopenharmony_ci smsg.msg_iov = siovs; 381195972f6Sopenharmony_ci smsg.msg_iovlen = 8; 382195972f6Sopenharmony_ci 383195972f6Sopenharmony_ci memset(&rmsg, 0, sizeof(rmsg)); 384195972f6Sopenharmony_ci rmsg.msg_iov = riovs_tmp; 385195972f6Sopenharmony_ci rmsg.msg_iovlen = (rcv_trailer ? 5 : 4); 386195972f6Sopenharmony_ci 387195972f6Sopenharmony_ci bytes_written = 0; 388195972f6Sopenharmony_ci bytes_read = 0; 389195972f6Sopenharmony_ci rcv_off = 0; 390195972f6Sopenharmony_ci 391195972f6Sopenharmony_ci while (bytes_written < TOTAL_DATA_SZ && (bytes_read < TOTAL_DATA_SZ)) { 392195972f6Sopenharmony_ci /* send data */ 393195972f6Sopenharmony_ci if (bytes_written < TOTAL_DATA_SZ) { 394195972f6Sopenharmony_ci ret = lwip_sendmsg(s1, &smsg, 0); 395195972f6Sopenharmony_ci /* note: since we always receive after sending, there will be open 396195972f6Sopenharmony_ci space in the send buffer */ 397195972f6Sopenharmony_ci fail_unless(ret > 0); 398195972f6Sopenharmony_ci 399195972f6Sopenharmony_ci bytes_written += ret; 400195972f6Sopenharmony_ci if (bytes_written < TOTAL_DATA_SZ) { 401195972f6Sopenharmony_ci test_sockets_msgapi_update_iovs(&smsg, (size_t)ret); 402195972f6Sopenharmony_ci } 403195972f6Sopenharmony_ci } 404195972f6Sopenharmony_ci 405195972f6Sopenharmony_ci while (tcpip_thread_poll_one()); 406195972f6Sopenharmony_ci 407195972f6Sopenharmony_ci /* receive and verify data */ 408195972f6Sopenharmony_ci do { 409195972f6Sopenharmony_ci if (bytes_read < TOTAL_DATA_SZ) { 410195972f6Sopenharmony_ci ret = lwip_recvmsg(s2, &rmsg, 0); 411195972f6Sopenharmony_ci fail_unless(ret > 0 || (ret == -1 && errno == EWOULDBLOCK)); 412195972f6Sopenharmony_ci 413195972f6Sopenharmony_ci if (ret > 0) { 414195972f6Sopenharmony_ci rcv_off += ret; 415195972f6Sopenharmony_ci /* we have received a full buffer */ 416195972f6Sopenharmony_ci if (rcv_off == BUF_SZ) { 417195972f6Sopenharmony_ci /* note: since iovs are just pointers, compare underlying buf */ 418195972f6Sopenharmony_ci fail_unless(!memcmp(snd_buf, rcv_buf, BUF_SZ)); 419195972f6Sopenharmony_ci bytes_read += BUF_SZ; 420195972f6Sopenharmony_ci /* reset receive state for next buffer */ 421195972f6Sopenharmony_ci rcv_off = 0; 422195972f6Sopenharmony_ci memset(rcv_buf, 0, BUF_SZ); 423195972f6Sopenharmony_ci memcpy(riovs_tmp, riovs, sizeof(riovs)); 424195972f6Sopenharmony_ci rmsg.msg_iov = riovs_tmp; 425195972f6Sopenharmony_ci rmsg.msg_iovlen = (rcv_trailer ? 5 : 4); 426195972f6Sopenharmony_ci } else { /* partial read */ 427195972f6Sopenharmony_ci test_sockets_msgapi_update_iovs(&rmsg, (size_t)ret); 428195972f6Sopenharmony_ci } 429195972f6Sopenharmony_ci } 430195972f6Sopenharmony_ci } else { 431195972f6Sopenharmony_ci break; 432195972f6Sopenharmony_ci } 433195972f6Sopenharmony_ci } while(ret > 0); 434195972f6Sopenharmony_ci } 435195972f6Sopenharmony_ci 436195972f6Sopenharmony_ci ret = lwip_close(s1); 437195972f6Sopenharmony_ci fail_unless(ret == 0); 438195972f6Sopenharmony_ci ret = lwip_close(s2); 439195972f6Sopenharmony_ci fail_unless(ret == 0); 440195972f6Sopenharmony_ci mem_free(snd_buf); 441195972f6Sopenharmony_ci mem_free(rcv_buf); 442195972f6Sopenharmony_ci} 443195972f6Sopenharmony_ci 444195972f6Sopenharmony_cistatic void test_sockets_msgapi_udp_send_recv_loop(int s, struct msghdr *smsg, struct msghdr *rmsg) 445195972f6Sopenharmony_ci{ 446195972f6Sopenharmony_ci int i, ret; 447195972f6Sopenharmony_ci 448195972f6Sopenharmony_ci /* send/receive our datagram of IO vectors 10 times */ 449195972f6Sopenharmony_ci for (i = 0; i < 10; i++) { 450195972f6Sopenharmony_ci ret = lwip_sendmsg(s, smsg, 0); 451195972f6Sopenharmony_ci fail_unless(ret == 4); 452195972f6Sopenharmony_ci 453195972f6Sopenharmony_ci while (tcpip_thread_poll_one()); 454195972f6Sopenharmony_ci 455195972f6Sopenharmony_ci /* receive the datagram split across 4 buffers */ 456195972f6Sopenharmony_ci ret = lwip_recvmsg(s, rmsg, 0); 457195972f6Sopenharmony_ci fail_unless(ret == 4); 458195972f6Sopenharmony_ci 459195972f6Sopenharmony_ci /* verify data */ 460195972f6Sopenharmony_ci fail_unless(*((u8_t*)rmsg->msg_iov[0].iov_base) == 0xDE); 461195972f6Sopenharmony_ci fail_unless(*((u8_t*)rmsg->msg_iov[1].iov_base) == 0xAD); 462195972f6Sopenharmony_ci fail_unless(*((u8_t*)rmsg->msg_iov[2].iov_base) == 0xBE); 463195972f6Sopenharmony_ci fail_unless(*((u8_t*)rmsg->msg_iov[3].iov_base) == 0xEF); 464195972f6Sopenharmony_ci 465195972f6Sopenharmony_ci /* clear rcv_buf to ensure no data is being skipped */ 466195972f6Sopenharmony_ci *((u8_t*)rmsg->msg_iov[0].iov_base) = 0x00; 467195972f6Sopenharmony_ci *((u8_t*)rmsg->msg_iov[1].iov_base) = 0x00; 468195972f6Sopenharmony_ci *((u8_t*)rmsg->msg_iov[2].iov_base) = 0x00; 469195972f6Sopenharmony_ci *((u8_t*)rmsg->msg_iov[3].iov_base) = 0x00; 470195972f6Sopenharmony_ci } 471195972f6Sopenharmony_ci} 472195972f6Sopenharmony_ci 473195972f6Sopenharmony_cistatic void test_sockets_msgapi_udp(int domain) 474195972f6Sopenharmony_ci{ 475195972f6Sopenharmony_ci int s, i, ret; 476195972f6Sopenharmony_ci struct sockaddr_storage addr_storage; 477195972f6Sopenharmony_ci socklen_t addr_size; 478195972f6Sopenharmony_ci struct iovec riovs[4]; 479195972f6Sopenharmony_ci struct msghdr rmsg; 480195972f6Sopenharmony_ci u8_t rcv_buf[4]; 481195972f6Sopenharmony_ci struct iovec siovs[4]; 482195972f6Sopenharmony_ci struct msghdr smsg; 483195972f6Sopenharmony_ci u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF}; 484195972f6Sopenharmony_ci 485195972f6Sopenharmony_ci /* initialize IO vectors with data */ 486195972f6Sopenharmony_ci for (i = 0; i < 4; i++) { 487195972f6Sopenharmony_ci siovs[i].iov_base = &snd_buf[i]; 488195972f6Sopenharmony_ci siovs[i].iov_len = sizeof(u8_t); 489195972f6Sopenharmony_ci riovs[i].iov_base = &rcv_buf[i]; 490195972f6Sopenharmony_ci riovs[i].iov_len = sizeof(u8_t); 491195972f6Sopenharmony_ci } 492195972f6Sopenharmony_ci 493195972f6Sopenharmony_ci test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size); 494195972f6Sopenharmony_ci 495195972f6Sopenharmony_ci s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM); 496195972f6Sopenharmony_ci fail_unless(s >= 0); 497195972f6Sopenharmony_ci 498195972f6Sopenharmony_ci ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size); 499195972f6Sopenharmony_ci fail_unless(ret == 0); 500195972f6Sopenharmony_ci 501195972f6Sopenharmony_ci /* Update addr with epehermal port */ 502195972f6Sopenharmony_ci ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size); 503195972f6Sopenharmony_ci fail_unless(ret == 0); 504195972f6Sopenharmony_ci switch(domain) { 505195972f6Sopenharmony_ci#if LWIP_IPV6 506195972f6Sopenharmony_ci case AF_INET6: 507195972f6Sopenharmony_ci fail_unless(addr_size == sizeof(struct sockaddr_in6)); 508195972f6Sopenharmony_ci break; 509195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 510195972f6Sopenharmony_ci#if LWIP_IPV4 511195972f6Sopenharmony_ci case AF_INET: 512195972f6Sopenharmony_ci fail_unless(addr_size == sizeof(struct sockaddr_in)); 513195972f6Sopenharmony_ci break; 514195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 515195972f6Sopenharmony_ci default: 516195972f6Sopenharmony_ci fail(); 517195972f6Sopenharmony_ci break; 518195972f6Sopenharmony_ci } 519195972f6Sopenharmony_ci 520195972f6Sopenharmony_ci /* send and receive the datagram in 4 pieces */ 521195972f6Sopenharmony_ci memset(&smsg, 0, sizeof(smsg)); 522195972f6Sopenharmony_ci smsg.msg_iov = siovs; 523195972f6Sopenharmony_ci smsg.msg_iovlen = 4; 524195972f6Sopenharmony_ci memset(&rmsg, 0, sizeof(rmsg)); 525195972f6Sopenharmony_ci rmsg.msg_iov = riovs; 526195972f6Sopenharmony_ci rmsg.msg_iovlen = 4; 527195972f6Sopenharmony_ci 528195972f6Sopenharmony_ci /* perform a sendmsg with remote host (self) */ 529195972f6Sopenharmony_ci smsg.msg_name = &addr_storage; 530195972f6Sopenharmony_ci smsg.msg_namelen = addr_size; 531195972f6Sopenharmony_ci 532195972f6Sopenharmony_ci test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg); 533195972f6Sopenharmony_ci 534195972f6Sopenharmony_ci /* Connect to self, allowing us to not pass message name */ 535195972f6Sopenharmony_ci ret = lwip_connect(s, (struct sockaddr*)&addr_storage, addr_size); 536195972f6Sopenharmony_ci fail_unless(ret == 0); 537195972f6Sopenharmony_ci 538195972f6Sopenharmony_ci smsg.msg_name = NULL; 539195972f6Sopenharmony_ci smsg.msg_namelen = 0; 540195972f6Sopenharmony_ci 541195972f6Sopenharmony_ci test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg); 542195972f6Sopenharmony_ci 543195972f6Sopenharmony_ci ret = lwip_close(s); 544195972f6Sopenharmony_ci fail_unless(ret == 0); 545195972f6Sopenharmony_ci} 546195972f6Sopenharmony_ci 547195972f6Sopenharmony_ci#if LWIP_IPV4 548195972f6Sopenharmony_cistatic void test_sockets_msgapi_cmsg(int domain) 549195972f6Sopenharmony_ci{ 550195972f6Sopenharmony_ci int s, ret, enable; 551195972f6Sopenharmony_ci struct sockaddr_storage addr_storage; 552195972f6Sopenharmony_ci socklen_t addr_size; 553195972f6Sopenharmony_ci struct iovec iov; 554195972f6Sopenharmony_ci struct msghdr msg; 555195972f6Sopenharmony_ci struct cmsghdr *cmsg; 556195972f6Sopenharmony_ci struct in_pktinfo *pktinfo; 557195972f6Sopenharmony_ci u8_t rcv_buf[4]; 558195972f6Sopenharmony_ci u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF}; 559195972f6Sopenharmony_ci u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; 560195972f6Sopenharmony_ci 561195972f6Sopenharmony_ci test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size); 562195972f6Sopenharmony_ci 563195972f6Sopenharmony_ci s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM); 564195972f6Sopenharmony_ci fail_unless(s >= 0); 565195972f6Sopenharmony_ci 566195972f6Sopenharmony_ci ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size); 567195972f6Sopenharmony_ci fail_unless(ret == 0); 568195972f6Sopenharmony_ci 569195972f6Sopenharmony_ci /* Update addr with epehermal port */ 570195972f6Sopenharmony_ci ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size); 571195972f6Sopenharmony_ci fail_unless(ret == 0); 572195972f6Sopenharmony_ci 573195972f6Sopenharmony_ci enable = 1; 574195972f6Sopenharmony_ci ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable)); 575195972f6Sopenharmony_ci fail_unless(ret == 0); 576195972f6Sopenharmony_ci 577195972f6Sopenharmony_ci /* Receive full message, including control message */ 578195972f6Sopenharmony_ci iov.iov_base = rcv_buf; 579195972f6Sopenharmony_ci iov.iov_len = sizeof(rcv_buf); 580195972f6Sopenharmony_ci msg.msg_control = cmsg_buf; 581195972f6Sopenharmony_ci msg.msg_controllen = sizeof(cmsg_buf); 582195972f6Sopenharmony_ci msg.msg_flags = 0; 583195972f6Sopenharmony_ci msg.msg_iov = &iov; 584195972f6Sopenharmony_ci msg.msg_iovlen = 1; 585195972f6Sopenharmony_ci msg.msg_name = NULL; 586195972f6Sopenharmony_ci msg.msg_namelen = 0; 587195972f6Sopenharmony_ci 588195972f6Sopenharmony_ci memset(rcv_buf, 0, sizeof(rcv_buf)); 589195972f6Sopenharmony_ci ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size); 590195972f6Sopenharmony_ci fail_unless(ret == sizeof(snd_buf)); 591195972f6Sopenharmony_ci 592195972f6Sopenharmony_ci tcpip_thread_poll_one(); 593195972f6Sopenharmony_ci 594195972f6Sopenharmony_ci ret = lwip_recvmsg(s, &msg, 0); 595195972f6Sopenharmony_ci fail_unless(ret == sizeof(rcv_buf)); 596195972f6Sopenharmony_ci fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf))); 597195972f6Sopenharmony_ci 598195972f6Sopenharmony_ci /* Verify message header */ 599195972f6Sopenharmony_ci cmsg = CMSG_FIRSTHDR(&msg); 600195972f6Sopenharmony_ci fail_unless(cmsg != NULL); 601195972f6Sopenharmony_ci fail_unless(cmsg->cmsg_len > 0); 602195972f6Sopenharmony_ci fail_unless(cmsg->cmsg_level == IPPROTO_IP); 603195972f6Sopenharmony_ci fail_unless(cmsg->cmsg_type == IP_PKTINFO); 604195972f6Sopenharmony_ci 605195972f6Sopenharmony_ci /* Verify message data */ 606195972f6Sopenharmony_ci pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg); 607195972f6Sopenharmony_ci /* We only have loopback interface enabled */ 608195972f6Sopenharmony_ci fail_unless(pktinfo->ipi_ifindex == 1); 609195972f6Sopenharmony_ci fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK)); 610195972f6Sopenharmony_ci 611195972f6Sopenharmony_ci /* Verify there are no additional messages */ 612195972f6Sopenharmony_ci cmsg = CMSG_NXTHDR(&msg, cmsg); 613195972f6Sopenharmony_ci fail_unless(cmsg == NULL); 614195972f6Sopenharmony_ci 615195972f6Sopenharmony_ci /* Send datagram again, testing truncation */ 616195972f6Sopenharmony_ci memset(rcv_buf, 0, sizeof(rcv_buf)); 617195972f6Sopenharmony_ci ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size); 618195972f6Sopenharmony_ci fail_unless(ret == sizeof(snd_buf)); 619195972f6Sopenharmony_ci 620195972f6Sopenharmony_ci tcpip_thread_poll_one(); 621195972f6Sopenharmony_ci 622195972f6Sopenharmony_ci msg.msg_controllen = 1; 623195972f6Sopenharmony_ci msg.msg_flags = 0; 624195972f6Sopenharmony_ci ret = lwip_recvmsg(s, &msg, 0); 625195972f6Sopenharmony_ci fail_unless(ret == sizeof(rcv_buf)); 626195972f6Sopenharmony_ci fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf))); 627195972f6Sopenharmony_ci /* Ensure truncation was returned */ 628195972f6Sopenharmony_ci fail_unless(msg.msg_flags & MSG_CTRUNC); 629195972f6Sopenharmony_ci /* Ensure no control messages were returned */ 630195972f6Sopenharmony_ci fail_unless(msg.msg_controllen == 0); 631195972f6Sopenharmony_ci 632195972f6Sopenharmony_ci ret = lwip_close(s); 633195972f6Sopenharmony_ci fail_unless(ret == 0); 634195972f6Sopenharmony_ci} 635195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 636195972f6Sopenharmony_ci 637195972f6Sopenharmony_ciSTART_TEST(test_sockets_msgapis) 638195972f6Sopenharmony_ci{ 639195972f6Sopenharmony_ci LWIP_UNUSED_ARG(_i); 640195972f6Sopenharmony_ci#if LWIP_IPV4 641195972f6Sopenharmony_ci test_sockets_msgapi_udp(AF_INET); 642195972f6Sopenharmony_ci test_sockets_msgapi_tcp(AF_INET); 643195972f6Sopenharmony_ci test_sockets_msgapi_cmsg(AF_INET); 644195972f6Sopenharmony_ci#endif 645195972f6Sopenharmony_ci#if LWIP_IPV6 646195972f6Sopenharmony_ci test_sockets_msgapi_udp(AF_INET6); 647195972f6Sopenharmony_ci test_sockets_msgapi_tcp(AF_INET6); 648195972f6Sopenharmony_ci#endif 649195972f6Sopenharmony_ci} 650195972f6Sopenharmony_ciEND_TEST 651195972f6Sopenharmony_ci 652195972f6Sopenharmony_ciSTART_TEST(test_sockets_select) 653195972f6Sopenharmony_ci{ 654195972f6Sopenharmony_ci#if LWIP_SOCKET_SELECT 655195972f6Sopenharmony_ci int s; 656195972f6Sopenharmony_ci int ret; 657195972f6Sopenharmony_ci fd_set readset; 658195972f6Sopenharmony_ci fd_set writeset; 659195972f6Sopenharmony_ci fd_set errset; 660195972f6Sopenharmony_ci struct timeval tv; 661195972f6Sopenharmony_ci 662195972f6Sopenharmony_ci fail_unless(test_sockets_get_used_count() == 0); 663195972f6Sopenharmony_ci 664195972f6Sopenharmony_ci s = lwip_socket(AF_INET, SOCK_STREAM, 0); 665195972f6Sopenharmony_ci fail_unless(s >= 0); 666195972f6Sopenharmony_ci fail_unless(test_sockets_get_used_count() == 0); 667195972f6Sopenharmony_ci 668195972f6Sopenharmony_ci FD_ZERO(&readset); 669195972f6Sopenharmony_ci FD_SET(s, &readset); 670195972f6Sopenharmony_ci FD_ZERO(&writeset); 671195972f6Sopenharmony_ci FD_SET(s, &writeset); 672195972f6Sopenharmony_ci FD_ZERO(&errset); 673195972f6Sopenharmony_ci FD_SET(s, &errset); 674195972f6Sopenharmony_ci 675195972f6Sopenharmony_ci tv.tv_sec = tv.tv_usec = 0; 676195972f6Sopenharmony_ci ret = lwip_select(s + 1, &readset, &writeset, &errset, &tv); 677195972f6Sopenharmony_ci fail_unless(ret == 0); 678195972f6Sopenharmony_ci fail_unless(test_sockets_get_used_count() == 0); 679195972f6Sopenharmony_ci 680195972f6Sopenharmony_ci ret = lwip_close(s); 681195972f6Sopenharmony_ci fail_unless(ret == 0); 682195972f6Sopenharmony_ci 683195972f6Sopenharmony_ci#endif 684195972f6Sopenharmony_ci LWIP_UNUSED_ARG(_i); 685195972f6Sopenharmony_ci} 686195972f6Sopenharmony_ciEND_TEST 687195972f6Sopenharmony_ci 688195972f6Sopenharmony_ciSTART_TEST(test_sockets_recv_after_rst) 689195972f6Sopenharmony_ci{ 690195972f6Sopenharmony_ci int sl, sact; 691195972f6Sopenharmony_ci int spass = -1; 692195972f6Sopenharmony_ci int ret; 693195972f6Sopenharmony_ci struct sockaddr_in sa_listen; 694195972f6Sopenharmony_ci const u16_t port = 1234; 695195972f6Sopenharmony_ci int arg; 696195972f6Sopenharmony_ci const char txbuf[] = "something"; 697195972f6Sopenharmony_ci char rxbuf[16]; 698195972f6Sopenharmony_ci struct lwip_sock *sact_sock; 699195972f6Sopenharmony_ci int err; 700195972f6Sopenharmony_ci LWIP_UNUSED_ARG(_i); 701195972f6Sopenharmony_ci 702195972f6Sopenharmony_ci fail_unless(test_sockets_get_used_count() == 0); 703195972f6Sopenharmony_ci 704195972f6Sopenharmony_ci memset(&sa_listen, 0, sizeof(sa_listen)); 705195972f6Sopenharmony_ci sa_listen.sin_family = AF_INET; 706195972f6Sopenharmony_ci sa_listen.sin_port = PP_HTONS(port); 707195972f6Sopenharmony_ci sa_listen.sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); 708195972f6Sopenharmony_ci 709195972f6Sopenharmony_ci /* set up the listener */ 710195972f6Sopenharmony_ci sl = lwip_socket(AF_INET, SOCK_STREAM, 0); 711195972f6Sopenharmony_ci fail_unless(sl >= 0); 712195972f6Sopenharmony_ci fail_unless(test_sockets_get_used_count() == 0); 713195972f6Sopenharmony_ci 714195972f6Sopenharmony_ci ret = lwip_bind(sl, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); 715195972f6Sopenharmony_ci fail_unless(ret == 0); 716195972f6Sopenharmony_ci ret = lwip_listen(sl, 0); 717195972f6Sopenharmony_ci fail_unless(ret == 0); 718195972f6Sopenharmony_ci 719195972f6Sopenharmony_ci /* set up the client */ 720195972f6Sopenharmony_ci sact = lwip_socket(AF_INET, SOCK_STREAM, 0); 721195972f6Sopenharmony_ci fail_unless(sact >= 0); 722195972f6Sopenharmony_ci fail_unless(test_sockets_get_used_count() == 0); 723195972f6Sopenharmony_ci /* set the client to nonblocking to simplify this test */ 724195972f6Sopenharmony_ci arg = 1; 725195972f6Sopenharmony_ci ret = lwip_ioctl(sact, FIONBIO, &arg); 726195972f6Sopenharmony_ci fail_unless(ret == 0); 727195972f6Sopenharmony_ci /* connect */ 728195972f6Sopenharmony_ci do { 729195972f6Sopenharmony_ci ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); 730195972f6Sopenharmony_ci err = errno; 731195972f6Sopenharmony_ci fail_unless((ret == 0) || (ret == -1)); 732195972f6Sopenharmony_ci if (ret != 0) { 733195972f6Sopenharmony_ci if (err == EISCONN) { 734195972f6Sopenharmony_ci /* Although this is not valid, use EISCONN as an indicator for successful connection. 735195972f6Sopenharmony_ci This marks us as "connect phase is done". On error, we would either have a different 736195972f6Sopenharmony_ci errno code or "send" fails later... -> good enough for this test. */ 737195972f6Sopenharmony_ci ret = 0; 738195972f6Sopenharmony_ci } else { 739195972f6Sopenharmony_ci fail_unless(err == EINPROGRESS); 740195972f6Sopenharmony_ci if (err != EINPROGRESS) { 741195972f6Sopenharmony_ci goto cleanup; 742195972f6Sopenharmony_ci } 743195972f6Sopenharmony_ci /* we're in progress: little side check: test for EALREADY */ 744195972f6Sopenharmony_ci ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); 745195972f6Sopenharmony_ci err = errno; 746195972f6Sopenharmony_ci fail_unless(ret == -1); 747195972f6Sopenharmony_ci fail_unless(err == EALREADY); 748195972f6Sopenharmony_ci if ((ret != -1) || (err != EALREADY)) { 749195972f6Sopenharmony_ci goto cleanup; 750195972f6Sopenharmony_ci } 751195972f6Sopenharmony_ci } 752195972f6Sopenharmony_ci tcpip_thread_poll_one(); 753195972f6Sopenharmony_ci tcpip_thread_poll_one(); 754195972f6Sopenharmony_ci tcpip_thread_poll_one(); 755195972f6Sopenharmony_ci tcpip_thread_poll_one(); 756195972f6Sopenharmony_ci } 757195972f6Sopenharmony_ci } while (ret != 0); 758195972f6Sopenharmony_ci fail_unless(ret == 0); 759195972f6Sopenharmony_ci 760195972f6Sopenharmony_ci /* accept the server connection part */ 761195972f6Sopenharmony_ci spass = lwip_accept(sl, NULL, NULL); 762195972f6Sopenharmony_ci fail_unless(spass >= 0); 763195972f6Sopenharmony_ci 764195972f6Sopenharmony_ci /* write data from client */ 765195972f6Sopenharmony_ci ret = lwip_send(sact, txbuf, sizeof(txbuf), 0); 766195972f6Sopenharmony_ci fail_unless(ret == sizeof(txbuf)); 767195972f6Sopenharmony_ci 768195972f6Sopenharmony_ci tcpip_thread_poll_one(); 769195972f6Sopenharmony_ci tcpip_thread_poll_one(); 770195972f6Sopenharmony_ci 771195972f6Sopenharmony_ci /* issue RST (This is a HACK, don't try this in your own app!) */ 772195972f6Sopenharmony_ci sact_sock = lwip_socket_dbg_get_socket(sact); 773195972f6Sopenharmony_ci fail_unless(sact_sock != NULL); 774195972f6Sopenharmony_ci if (sact_sock != NULL) { 775195972f6Sopenharmony_ci struct netconn *sact_conn = sact_sock->conn; 776195972f6Sopenharmony_ci fail_unless(sact_conn != NULL); 777195972f6Sopenharmony_ci if (sact_conn != NULL) { 778195972f6Sopenharmony_ci struct tcp_pcb *pcb = sact_conn->pcb.tcp; 779195972f6Sopenharmony_ci fail_unless(pcb != NULL); 780195972f6Sopenharmony_ci if (pcb != NULL) { 781195972f6Sopenharmony_ci tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, 782195972f6Sopenharmony_ci pcb->local_port, pcb->remote_port); 783195972f6Sopenharmony_ci } 784195972f6Sopenharmony_ci } 785195972f6Sopenharmony_ci } 786195972f6Sopenharmony_ci tcpip_thread_poll_one(); 787195972f6Sopenharmony_ci tcpip_thread_poll_one(); 788195972f6Sopenharmony_ci 789195972f6Sopenharmony_ci /* expect to receive data first */ 790195972f6Sopenharmony_ci ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); 791195972f6Sopenharmony_ci fail_unless(ret > 0); 792195972f6Sopenharmony_ci tcpip_thread_poll_one(); 793195972f6Sopenharmony_ci tcpip_thread_poll_one(); 794195972f6Sopenharmony_ci 795195972f6Sopenharmony_ci /* expect to receive RST indication */ 796195972f6Sopenharmony_ci ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); 797195972f6Sopenharmony_ci fail_unless(ret == -1); 798195972f6Sopenharmony_ci err = errno; 799195972f6Sopenharmony_ci fail_unless(err == ECONNRESET); 800195972f6Sopenharmony_ci tcpip_thread_poll_one(); 801195972f6Sopenharmony_ci tcpip_thread_poll_one(); 802195972f6Sopenharmony_ci 803195972f6Sopenharmony_ci /* expect to receive ENOTCONN indication */ 804195972f6Sopenharmony_ci ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); 805195972f6Sopenharmony_ci fail_unless(ret == -1); 806195972f6Sopenharmony_ci err = errno; 807195972f6Sopenharmony_ci fail_unless(err == ENOTCONN); 808195972f6Sopenharmony_ci tcpip_thread_poll_one(); 809195972f6Sopenharmony_ci tcpip_thread_poll_one(); 810195972f6Sopenharmony_ci 811195972f6Sopenharmony_ci /* expect to receive ENOTCONN indication */ 812195972f6Sopenharmony_ci ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); 813195972f6Sopenharmony_ci fail_unless(ret == -1); 814195972f6Sopenharmony_ci err = errno; 815195972f6Sopenharmony_ci fail_unless(err == ENOTCONN); 816195972f6Sopenharmony_ci tcpip_thread_poll_one(); 817195972f6Sopenharmony_ci tcpip_thread_poll_one(); 818195972f6Sopenharmony_ci 819195972f6Sopenharmony_cicleanup: 820195972f6Sopenharmony_ci ret = lwip_close(sl); 821195972f6Sopenharmony_ci fail_unless(ret == 0); 822195972f6Sopenharmony_ci ret = lwip_close(sact); 823195972f6Sopenharmony_ci fail_unless(ret == 0); 824195972f6Sopenharmony_ci if (spass >= 0) { 825195972f6Sopenharmony_ci ret = lwip_close(spass); 826195972f6Sopenharmony_ci fail_unless(ret == 0); 827195972f6Sopenharmony_ci } 828195972f6Sopenharmony_ci} 829195972f6Sopenharmony_ciEND_TEST 830195972f6Sopenharmony_ci 831195972f6Sopenharmony_ci/** Create the suite including all tests for this module */ 832195972f6Sopenharmony_ciSuite * 833195972f6Sopenharmony_cisockets_suite(void) 834195972f6Sopenharmony_ci{ 835195972f6Sopenharmony_ci testfunc tests[] = { 836195972f6Sopenharmony_ci TESTFUNC(test_sockets_basics), 837195972f6Sopenharmony_ci TESTFUNC(test_sockets_allfunctions_basic), 838195972f6Sopenharmony_ci TESTFUNC(test_sockets_msgapis), 839195972f6Sopenharmony_ci TESTFUNC(test_sockets_select), 840195972f6Sopenharmony_ci TESTFUNC(test_sockets_recv_after_rst), 841195972f6Sopenharmony_ci }; 842195972f6Sopenharmony_ci return create_suite("SOCKETS", tests, sizeof(tests)/sizeof(testfunc), sockets_setup, sockets_teardown); 843195972f6Sopenharmony_ci} 844195972f6Sopenharmony_ci 845195972f6Sopenharmony_ci#else /* LWIP_SOCKET */ 846195972f6Sopenharmony_ci 847195972f6Sopenharmony_ciSuite * 848195972f6Sopenharmony_cisockets_suite(void) 849195972f6Sopenharmony_ci{ 850195972f6Sopenharmony_ci return create_suite("SOCKETS", NULL, 0, NULL, NULL); 851195972f6Sopenharmony_ci} 852195972f6Sopenharmony_ci#endif /* LWIP_SOCKET */ 853