/* * TCP code. For TCP, a socket is created and listens. * A callback occurs when the packet is received. The callback handles the different types of TCP events, * including the handshake protocol. * Based off the sample tcpecho app provided in the picotcp library. */ void cb_tcpecho(uint16_t ev, struct pico_socket *s) { int r = 0; ZF_LOGD("tcpecho> wakeup ev=%u\n", ev); if (ev & PICO_SOCK_EV_RD) { char buf[100]; r = pico_socket_read(s, buf, 100); pico_socket_write(s, buf, r); // Immediately echo back a response } if (ev & PICO_SOCK_EV_CONN) { uint32_t ka_val = 0; struct pico_socket *sock_peer; struct pico_ip4 orig = {0}; uint16_t port = 0; char peer[30] = {0}; int yes = 1; sock_peer = pico_socket_accept(s, &orig, &port); pico_ipv4_to_string(peer, orig.addr); ZF_LOGD("Connection established with %s:%d.\n", peer, short_be(port)); pico_socket_setoption(sock_peer, PICO_TCP_NODELAY, &yes); /* Set keepalive options - from picoTCP documentation */ ka_val = 5; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPCNT, &ka_val); ka_val = 30000; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPIDLE, &ka_val); ka_val = 5000; pico_socket_setoption(sock_peer, PICO_SOCKET_OPT_KEEPINTVL, &ka_val); } if (ev & PICO_SOCK_EV_FIN) { ZF_LOGD("Socket closed. Exit normally. \n"); } if (ev & PICO_SOCK_EV_ERR) { ZF_LOGD("Socket error received: %s. Bailing out.\n", strerror(pico_err)); } if (ev & PICO_SOCK_EV_CLOSE) { ZF_LOGD("Socket received close from peer.\n"); pico_socket_shutdown(s, PICO_SHUT_WR); } if (ev & PICO_SOCK_EV_WR) { ZF_LOGD("TCP Write ack\n"); } }
void cb_tcpecho(uint16_t ev, struct pico_socket *s) { int r = 0; picoapp_dbg("tcpecho> wakeup ev=%u\n", ev); if (ev & PICO_SOCK_EV_RD) { if (flag & PICO_SOCK_EV_CLOSE) printf("SOCKET> EV_RD, FIN RECEIVED\n"); while (len < BSIZE) { r = pico_socket_read(s, recvbuf + len, BSIZE - len); if (r > 0) { len += r; flag &= ~(PICO_SOCK_EV_RD); } else { flag |= PICO_SOCK_EV_RD; break; } } if (flag & PICO_SOCK_EV_WR) { flag &= ~PICO_SOCK_EV_WR; send_tcpecho(s); } } if (ev & PICO_SOCK_EV_CONN) { uint32_t ka_val = 0; struct pico_socket *sock_a = { 0 }; struct pico_ip4 orig = { 0 }; uint16_t port = 0; char peer[30] = { 0 }; int yes = 1; sock_a = pico_socket_accept(s, &orig, &port); pico_ipv4_to_string(peer, orig.addr); printf("Connection established with %s:%d.\n", peer, short_be(port)); pico_socket_setoption(sock_a, PICO_TCP_NODELAY, &yes); /* Set keepalive options */ ka_val = 5; pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPCNT, &ka_val); ka_val = 30000; pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPIDLE, &ka_val); ka_val = 5000; pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPINTVL, &ka_val); } if (ev & PICO_SOCK_EV_FIN) { printf("Socket closed. Exit normally. \n"); if (!pico_timer_add(2000, deferred_exit, NULL)) { printf("Failed to start exit timer, exiting now\n"); exit(1); } } if (ev & PICO_SOCK_EV_ERR) { printf("Socket error received: %s. Bailing out.\n", strerror(pico_err)); exit(1); } if (ev & PICO_SOCK_EV_CLOSE) { printf("Socket received close from peer.\n"); if (flag & PICO_SOCK_EV_RD) { pico_socket_shutdown(s, PICO_SHUT_WR); printf("SOCKET> Called shutdown write, ev = %d\n", ev); } } if (ev & PICO_SOCK_EV_WR) { r = send_tcpecho(s); if (r == 0) flag |= PICO_SOCK_EV_WR; else flag &= (~PICO_SOCK_EV_WR); } }