int udpSetBlocking(int socket, bool blocking) { int b = blocking ? 1 : 0; return lwip_ioctl(socket, FIONBIO, &b); }
/* The number of bytes available for reading on this socket. @param socket The socket to check. @return The number of bytes available. \b Example \code int sock = udpOpen(); // create a new socket if (udpBytesAvailable(sock) > 0) { // we have some reading to do... } \endcode */ int udpAvailable(int socket) { int bytes; return (lwip_ioctl(socket, FIONREAD, &bytes) == 0) ? bytes : -1; }
int ioctl(int s, long cmd, void *argp) { BT_HANDLE hSocket = (BT_HANDLE)s; return lwip_ioctl(hSocket->socket, cmd, argp); }
static inline int net_socket_blocking(int sock, int state) { return lwip_ioctl(sock, FIONBIO, &state); }
unsigned int UA_socket_set_nonblocking(UA_SOCKET sockfd){ int on = 1; if(lwip_ioctl(sockfd, FIONBIO, &on) < 0) return UA_STATUSCODE_BADINTERNALERROR; return UA_STATUSCODE_GOOD; }
/** This is an example function that tests blocking- and nonblocking connect. */ static void sockex_nonblocking_connect(void *arg) { int s; int ret; u32_t opt; struct sockaddr_in addr; fdsets sets; struct timeval tv; u32_t ticks_a, ticks_b; int err; INIT_FDSETS(&sets); LWIP_UNUSED_ARG(arg); /* set up address to connect to */ memset(&addr, 0, sizeof(addr)); addr.sin_len = sizeof(addr); addr.sin_family = AF_INET; addr.sin_port = PP_HTONS(SOCK_TARGET_PORT); addr.sin_addr.s_addr = inet_addr(SOCK_TARGET_HOST); /* first try blocking: */ /* create the socket */ s = lwip_socket(AF_INET, SOCK_STREAM, 0); LWIP_ASSERT("s >= 0", s >= 0); /* connect */ ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); /* should succeed */ LWIP_ASSERT("ret == 0", ret == 0); /* write something */ ret = lwip_write(s, "test", 4); LWIP_ASSERT("ret == 4", ret == 4); /* close */ ret = lwip_close(s); LWIP_ASSERT("ret == 0", ret == 0); /* now try nonblocking and close before being connected */ /* create the socket */ s = lwip_socket(AF_INET, SOCK_STREAM, 0); LWIP_ASSERT("s >= 0", s >= 0); /* nonblocking */ opt = lwip_fcntl(s, F_GETFL, 0); LWIP_ASSERT("ret != -1", ret != -1); opt |= O_NONBLOCK; ret = lwip_fcntl(s, F_SETFL, opt); LWIP_ASSERT("ret != -1", ret != -1); /* connect */ ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); /* should have an error: "inprogress" */ LWIP_ASSERT("ret == -1", ret == -1); err = errno; LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); /* close */ ret = lwip_close(s); LWIP_ASSERT("ret == 0", ret == 0); /* try to close again, should fail with EBADF */ ret = lwip_close(s); LWIP_ASSERT("ret == -1", ret == -1); err = errno; LWIP_ASSERT("errno == EBADF", err == EBADF); printf("closing socket in nonblocking connect succeeded\n"); /* now try nonblocking, connect should succeed: this test only works if it is fast enough, i.e. no breakpoints, please! */ /* create the socket */ s = lwip_socket(AF_INET, SOCK_STREAM, 0); LWIP_ASSERT("s >= 0", s >= 0); /* nonblocking */ opt = 1; ret = lwip_ioctl(s, FIONBIO, &opt); LWIP_ASSERT("ret == 0", ret == 0); /* connect */ ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); /* should have an error: "inprogress" */ LWIP_ASSERT("ret == -1", ret == -1); err = errno; LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); /* write should fail, too */ ret = lwip_write(s, "test", 4); LWIP_ASSERT("ret == -1", ret == -1); err = errno; LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); CHECK_FDSETS(&sets); FD_ZERO(&sets.readset); CHECK_FDSETS(&sets); FD_SET(s, &sets.readset); CHECK_FDSETS(&sets); FD_ZERO(&sets.writeset); CHECK_FDSETS(&sets); FD_SET(s, &sets.writeset); CHECK_FDSETS(&sets); FD_ZERO(&sets.errset); CHECK_FDSETS(&sets); FD_SET(s, &sets.errset); CHECK_FDSETS(&sets); tv.tv_sec = 0; tv.tv_usec = 0; /* select without waiting should fail */ ret = lwip_select(s + 1, &sets.readset, &sets.writeset, &sets.errset, &tv); CHECK_FDSETS(&sets); LWIP_ASSERT("ret == 0", ret == 0); LWIP_ASSERT("!FD_ISSET(s, &writeset)", !FD_ISSET(s, &sets.writeset)); LWIP_ASSERT("!FD_ISSET(s, &readset)", !FD_ISSET(s, &sets.readset)); LWIP_ASSERT("!FD_ISSET(s, &errset)", !FD_ISSET(s, &sets.errset)); FD_ZERO(&sets.readset); FD_SET(s, &sets.readset); FD_ZERO(&sets.writeset); FD_SET(s, &sets.writeset); FD_ZERO(&sets.errset); FD_SET(s, &sets.errset); ticks_a = sys_now(); /* select with waiting should succeed */ ret = lwip_select(s + 1, &sets.readset, &sets.writeset, &sets.errset, NULL); ticks_b = sys_now(); LWIP_ASSERT("ret == 1", ret == 1); LWIP_ASSERT("FD_ISSET(s, &writeset)", FD_ISSET(s, &sets.writeset)); LWIP_ASSERT("!FD_ISSET(s, &readset)", !FD_ISSET(s, &sets.readset)); LWIP_ASSERT("!FD_ISSET(s, &errset)", !FD_ISSET(s, &sets.errset)); /* now write should succeed */ ret = lwip_write(s, "test", 4); LWIP_ASSERT("ret == 4", ret == 4); /* close */ ret = lwip_close(s); LWIP_ASSERT("ret == 0", ret == 0); printf("select() needed %d ticks to return writable\n", (int)(ticks_b - ticks_a)); /* now try nonblocking to invalid address: this test only works if it is fast enough, i.e. no breakpoints, please! */ /* create the socket */ s = lwip_socket(AF_INET, SOCK_STREAM, 0); LWIP_ASSERT("s >= 0", s >= 0); /* nonblocking */ opt = 1; ret = lwip_ioctl(s, FIONBIO, &opt); LWIP_ASSERT("ret == 0", ret == 0); addr.sin_addr.s_addr++; /* this should result in an invalid address */ /* connect */ ret = lwip_connect(s, (struct sockaddr*)&addr, sizeof(addr)); /* should have an error: "inprogress" */ LWIP_ASSERT("ret == -1", ret == -1); err = errno; LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); /* write should fail, too */ ret = lwip_write(s, "test", 4); LWIP_ASSERT("ret == -1", ret == -1); err = errno; LWIP_ASSERT("errno == EINPROGRESS", err == EINPROGRESS); FD_ZERO(&sets.readset); FD_SET(s, &sets.readset); FD_ZERO(&sets.writeset); FD_SET(s, &sets.writeset); FD_ZERO(&sets.errset); FD_SET(s, &sets.errset); tv.tv_sec = 0; tv.tv_usec = 0; /* select without waiting should fail */ ret = lwip_select(s + 1, &sets.readset, &sets.writeset, &sets.errset, &tv); LWIP_ASSERT("ret == 0", ret == 0); FD_ZERO(&sets.readset); FD_SET(s, &sets.readset); FD_ZERO(&sets.writeset); FD_SET(s, &sets.writeset); FD_ZERO(&sets.errset); FD_SET(s, &sets.errset); ticks_a = sys_now(); /* select with waiting should eventually succeed and return errset! */ ret = lwip_select(s + 1, &sets.readset, &sets.writeset, &sets.errset, NULL); ticks_b = sys_now(); LWIP_ASSERT("ret > 0", ret > 0); LWIP_ASSERT("FD_ISSET(s, &errset)", FD_ISSET(s, &sets.errset)); /*LWIP_ASSERT("!FD_ISSET(s, &readset)", !FD_ISSET(s, &sets.readset)); LWIP_ASSERT("!FD_ISSET(s, &writeset)", !FD_ISSET(s, &sets.writeset));*/ /* close */ ret = lwip_close(s); LWIP_ASSERT("ret == 0", ret == 0); printf("select() needed %d ticks to return error\n", (int)(ticks_b - ticks_a)); printf("all tests done, thread ending\n"); }
END_TEST START_TEST(test_sockets_recv_after_rst) { int sl, sact; int spass = -1; int ret; struct sockaddr_in sa_listen; const u16_t port = 1234; int arg; const char txbuf[] = "something"; char rxbuf[16]; struct lwip_sock *sact_sock; int err; LWIP_UNUSED_ARG(_i); fail_unless(test_sockets_get_used_count() == 0); memset(&sa_listen, 0, sizeof(sa_listen)); sa_listen.sin_family = AF_INET; sa_listen.sin_port = PP_HTONS(port); sa_listen.sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); /* set up the listener */ sl = lwip_socket(AF_INET, SOCK_STREAM, 0); fail_unless(sl >= 0); fail_unless(test_sockets_get_used_count() == 0); ret = lwip_bind(sl, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); fail_unless(ret == 0); ret = lwip_listen(sl, 0); fail_unless(ret == 0); /* set up the client */ sact = lwip_socket(AF_INET, SOCK_STREAM, 0); fail_unless(sact >= 0); fail_unless(test_sockets_get_used_count() == 0); /* set the client to nonblocking to simplify this test */ arg = 1; ret = lwip_ioctl(sact, FIONBIO, &arg); fail_unless(ret == 0); /* connect */ do { ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); err = errno; fail_unless((ret == 0) || (ret == -1)); if (ret != 0) { if (err == EISCONN) { /* Although this is not valid, use EISCONN as an indicator for successful connection. This marks us as "connect phase is done". On error, we would either have a different errno code or "send" fails later... -> good enough for this test. */ ret = 0; } else { fail_unless(err == EINPROGRESS); if (err != EINPROGRESS) { goto cleanup; } /* we're in progress: little side check: test for EALREADY */ ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); err = errno; fail_unless(ret == -1); fail_unless(err == EALREADY); if ((ret != -1) || (err != EALREADY)) { goto cleanup; } } tcpip_thread_poll_one(); tcpip_thread_poll_one(); tcpip_thread_poll_one(); tcpip_thread_poll_one(); } } while (ret != 0); fail_unless(ret == 0); /* accept the server connection part */ spass = lwip_accept(sl, NULL, NULL); fail_unless(spass >= 0); /* write data from client */ ret = lwip_send(sact, txbuf, sizeof(txbuf), 0); fail_unless(ret == sizeof(txbuf)); tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* issue RST (This is a HACK, don't try this in your own app!) */ sact_sock = lwip_socket_dbg_get_socket(sact); fail_unless(sact_sock != NULL); if (sact_sock != NULL) { struct netconn *sact_conn = sact_sock->conn; fail_unless(sact_conn != NULL); if (sact_conn != NULL) { struct tcp_pcb *pcb = sact_conn->pcb.tcp; fail_unless(pcb != NULL); if (pcb != NULL) { tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port); } } } tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* expect to receive data first */ ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); fail_unless(ret > 0); tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* expect to receive RST indication */ ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); fail_unless(ret == -1); err = errno; fail_unless(err == ECONNRESET); tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* expect to receive ENOTCONN indication */ ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); fail_unless(ret == -1); err = errno; fail_unless(err == ENOTCONN); tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* expect to receive ENOTCONN indication */ ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); fail_unless(ret == -1); err = errno; fail_unless(err == ENOTCONN); tcpip_thread_poll_one(); tcpip_thread_poll_one(); cleanup: ret = lwip_close(sl); fail_unless(ret == 0); ret = lwip_close(sact); fail_unless(ret == 0); if (spass >= 0) { ret = lwip_close(spass); fail_unless(ret == 0); } }