diff --git a/src/SDK_EthernetTap.cpp b/src/SDK_EthernetTap.cpp index 3b329fa..7fb0a9a 100644 --- a/src/SDK_EthernetTap.cpp +++ b/src/SDK_EthernetTap.cpp @@ -624,6 +624,7 @@ void NetconEthernetTap::picoTCP_loop() DEBUG_INFO(); while(_run) { + _phy.poll((unsigned long)std::min(500,1000)); //DEBUG_INFO("pico_tick"); usleep(1000); picostack->__pico_stack_tick(); @@ -1439,41 +1440,75 @@ Connection * NetconEthernetTap::handleSocketProxy(PhySocket *sock, int socket_ty return NULL; } +static void cb_tcpclient(uint16_t ev, struct pico_socket *s) +{ + DEBUG_ERROR("ACTIVITY!"); +} + Connection * NetconEthernetTap::handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc) { DEBUG_ATTN("sock=%p, sock_type=%d", (void*)&sock, socket_rpc->socket_type); - struct udp_pcb *new_udp_PCB = NULL; - struct tcp_pcb *new_tcp_PCB = NULL; + #if defined(SDK_LWIP) + struct udp_pcb *new_udp_PCB = NULL; + struct tcp_pcb *new_tcp_PCB = NULL; - if(socket_rpc->socket_type == SOCK_DGRAM) { - DEBUG_EXTRA("SOCK_DGRAM"); - Mutex::Lock _l(_tcpconns_m); - new_udp_PCB = lwipstack->__udp_new(); - } - else if(socket_rpc->socket_type == SOCK_STREAM) { - DEBUG_EXTRA("SOCK_STREAM"); - Mutex::Lock _l(_tcpconns_m); - new_tcp_PCB = lwipstack->__tcp_new(); - } - else if(socket_rpc->socket_type == SOCK_RAW) { - DEBUG_ERROR("SOCK_RAW, not currently supported."); - } - if(new_udp_PCB || new_tcp_PCB) { - Connection * newConn = new Connection(); - *uptr = newConn; - newConn->type = socket_rpc->socket_type; - newConn->sock = sock; - newConn->local_addr = NULL; - newConn->peer_addr = NULL; - if(newConn->type == SOCK_DGRAM) newConn->UDP_pcb = new_udp_PCB; - if(newConn->type == SOCK_STREAM) newConn->TCP_pcb = new_tcp_PCB; - _Connections.push_back(newConn); - return newConn; - } - DEBUG_ERROR(" memory not available for new PCB"); - sendReturnValue(_phy.getDescriptor(sock), -1, ENOMEM); - return NULL; + if(socket_rpc->socket_type == SOCK_DGRAM) { + DEBUG_EXTRA("SOCK_DGRAM"); + Mutex::Lock _l(_tcpconns_m); + new_udp_PCB = lwipstack->__udp_new(); + } + else if(socket_rpc->socket_type == SOCK_STREAM) { + DEBUG_EXTRA("SOCK_STREAM"); + Mutex::Lock _l(_tcpconns_m); + new_tcp_PCB = lwipstack->__tcp_new(); + } + else if(socket_rpc->socket_type == SOCK_RAW) { + DEBUG_ERROR("SOCK_RAW, not currently supported."); + } + if(new_udp_PCB || new_tcp_PCB) { + Connection * newConn = new Connection(); + *uptr = newConn; + newConn->type = socket_rpc->socket_type; + newConn->sock = sock; + newConn->local_addr = NULL; + newConn->peer_addr = NULL; + if(newConn->type == SOCK_DGRAM) newConn->UDP_pcb = new_udp_PCB; + if(newConn->type == SOCK_STREAM) newConn->TCP_pcb = new_tcp_PCB; + _Connections.push_back(newConn); + return newConn; + } + DEBUG_ERROR(" memory not available for new PCB"); + sendReturnValue(_phy.getDescriptor(sock), -1, ENOMEM); + return NULL; + + #elif defined(SDK_PICOTCP) + DEBUG_ERROR("opening socket"); + + struct pico_socket * psock = picostack->__pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpclient); + DEBUG_ERROR("fin"); + + if(psock) + { + DEBUG_ATTN("psock = %p", (void*)psock); + Connection * newConn = new Connection(); + *uptr = newConn; + newConn->type = socket_rpc->socket_type; + newConn->sock = sock; + newConn->local_addr = NULL; + newConn->peer_addr = NULL; + newConn->picosock = psock; + //if(newConn->type == SOCK_DGRAM) newConn->pico_UDP_sock = new_udp_PCB; + //if(newConn->type == SOCK_STREAM) newConn->pico_TCP_sock = new_tcp_PCB; + _Connections.push_back(newConn); + return newConn; + } + else + { + DEBUG_ERROR("psock == NULL"); + } + return NULL; + #endif } int NetconEthernetTap::handleConnectProxy(PhySocket *sock, struct sockaddr_in *rawAddr) @@ -1575,93 +1610,101 @@ int NetconEthernetTap::handleConnectProxy(PhySocket *sock, struct sockaddr_in *r void NetconEthernetTap::handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn, struct connect_st* connect_rpc) { DEBUG_ATTN("sock=%p", (void*)&sock); - Mutex::Lock _l(_tcpconns_m); - struct sockaddr_in *rawAddr = (struct sockaddr_in *) &connect_rpc->addr; - int port = lwipstack->__lwip_ntohs(rawAddr->sin_port); - ip_addr_t connAddr = convert_ip(rawAddr); - int err = 0, ip = rawAddr->sin_addr.s_addr; - char addrstr[INET6_ADDRSTRLEN]; - struct sockaddr *addr = (struct sockaddr*)rawAddr; - if(addr->sa_family == AF_INET) { - struct sockaddr_in *connaddr = (struct sockaddr_in *)addr; - inet_ntop(AF_INET, &(connaddr->sin_addr), addrstr, INET_ADDRSTRLEN); - sprintf(addrstr, "%s:%d", addrstr, lwipstack->__lwip_ntohs(connaddr->sin_port)); - } - if(addr->sa_family == AF_INET6) { - struct sockaddr_in6 *connaddr6 = (struct sockaddr_in6 *)addr; - inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN); - sprintf(addrstr, "%s:%d", addrstr, lwipstack->__lwip_ntohs(connaddr6->sin6_port)); - } - DEBUG_INFO("addr=%s", addrstr); + #if defined(SDK_LWIP) + Mutex::Lock _l(_tcpconns_m); + struct sockaddr_in *rawAddr = (struct sockaddr_in *) &connect_rpc->addr; + int port = lwipstack->__lwip_ntohs(rawAddr->sin_port); + ip_addr_t connAddr = convert_ip(rawAddr); + int err = 0, ip = rawAddr->sin_addr.s_addr; - if(conn->type == SOCK_DGRAM) { - // Generates no network traffic - if((err = lwipstack->__udp_connect(conn->UDP_pcb,&connAddr,port)) < 0) - DEBUG_ERROR("error while connecting to with UDP"); - lwipstack->__udp_recv(conn->UDP_pcb, nc_udp_recved, new Larg(this, conn)); + char addrstr[INET6_ADDRSTRLEN]; + struct sockaddr *addr = (struct sockaddr*)rawAddr; + if(addr->sa_family == AF_INET) { + struct sockaddr_in *connaddr = (struct sockaddr_in *)addr; + inet_ntop(AF_INET, &(connaddr->sin_addr), addrstr, INET_ADDRSTRLEN); + sprintf(addrstr, "%s:%d", addrstr, lwipstack->__lwip_ntohs(connaddr->sin_port)); + } + if(addr->sa_family == AF_INET6) { + struct sockaddr_in6 *connaddr6 = (struct sockaddr_in6 *)addr; + inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN); + sprintf(addrstr, "%s:%d", addrstr, lwipstack->__lwip_ntohs(connaddr6->sin6_port)); + } + DEBUG_INFO("addr=%s", addrstr); + + if(conn->type == SOCK_DGRAM) { + // Generates no network traffic + if((err = lwipstack->__udp_connect(conn->UDP_pcb,&connAddr,port)) < 0) + DEBUG_ERROR("error while connecting to with UDP"); + lwipstack->__udp_recv(conn->UDP_pcb, nc_udp_recved, new Larg(this, conn)); + sendReturnValue(rpcSock, 0, ERR_OK); + return; + } + if(conn != NULL) { + lwipstack->__tcp_sent(conn->TCP_pcb, nc_sent); + lwipstack->__tcp_recv(conn->TCP_pcb, nc_recved); + lwipstack->__tcp_err(conn->TCP_pcb, nc_err); + lwipstack->__tcp_poll(conn->TCP_pcb, nc_poll, APPLICATION_POLL_FREQ); + lwipstack->__tcp_arg(conn->TCP_pcb, new Larg(this, conn)); + + DEBUG_EXTRA(" pcb->state=%x", conn->TCP_pcb->state); + if(conn->TCP_pcb->state != CLOSED) { + DEBUG_INFO(" cannot connect using this PCB, PCB!=CLOSED"); + sendReturnValue(rpcSock, -1, EAGAIN); + return; + } + + static ip_addr_t ba; + + IP6_ADDR2(&ba, 0xfd56,0x5799,0xd8f6,0x1238,0x8c99,0x9322,0x30ce,0x418a); + + + if((err = lwipstack->__tcp_connect(conn->TCP_pcb,&ba,port,nc_connected)) < 0) + { + if(err == ERR_ISCONN) { + sendReturnValue(rpcSock, -1, EISCONN); // Already in connected state + return; + } if(err == ERR_USE) { + sendReturnValue(rpcSock, -1, EADDRINUSE); // Already in use + return; + } if(err == ERR_VAL) { + sendReturnValue(rpcSock, -1, EINVAL); // Invalid ipaddress parameter + return; + } if(err == ERR_RTE) { + sendReturnValue(rpcSock, -1, ENETUNREACH); // No route to host + return; + } if(err == ERR_BUF) { + sendReturnValue(rpcSock, -1, EAGAIN); // No more ports available + return; + } + if(err == ERR_MEM) { + sendReturnValue(rpcSock, -1, EAGAIN); // TODO: Doesn't describe the problem well, but closest match + return; + } + + // We should only return a value if failure happens immediately + // Otherwise, we still need to wait for a callback from lwIP. + // - This is because an ERR_OK from tcp_connect() only verifies + // that the SYN packet was enqueued onto the stack properly, + // that's it! + // - Most instances of a retval for a connect() should happen + // in the nc_connect() and nc_err() callbacks! + DEBUG_ERROR(" unable to connect"); + sendReturnValue(rpcSock, -1, EAGAIN); + } + // Everything seems to be ok, but we don't have enough info to retval + conn->listening=true; + conn->rpcSock=rpcSock; // used for return value from lwip CB + } else { + DEBUG_ERROR(" could not locate PCB based on application-provided fd"); + sendReturnValue(rpcSock, -1, EBADF); + } + #elif defined(SDK_PICOTCP) + int ret = pico_socket_connect(s, &dst.ip4, send_port); + DEBUG_ATTN("ret = %d", ret); sendReturnValue(rpcSock, 0, ERR_OK); return; - } - if(conn != NULL) { - lwipstack->__tcp_sent(conn->TCP_pcb, nc_sent); - lwipstack->__tcp_recv(conn->TCP_pcb, nc_recved); - lwipstack->__tcp_err(conn->TCP_pcb, nc_err); - lwipstack->__tcp_poll(conn->TCP_pcb, nc_poll, APPLICATION_POLL_FREQ); - lwipstack->__tcp_arg(conn->TCP_pcb, new Larg(this, conn)); - - DEBUG_EXTRA(" pcb->state=%x", conn->TCP_pcb->state); - if(conn->TCP_pcb->state != CLOSED) { - DEBUG_INFO(" cannot connect using this PCB, PCB!=CLOSED"); - sendReturnValue(rpcSock, -1, EAGAIN); - return; - } - - static ip_addr_t ba; - - IP6_ADDR2(&ba, 0xfd56,0x5799,0xd8f6,0x1238,0x8c99,0x9322,0x30ce,0x418a); - - - if((err = lwipstack->__tcp_connect(conn->TCP_pcb,&ba,port,nc_connected)) < 0) - { - if(err == ERR_ISCONN) { - sendReturnValue(rpcSock, -1, EISCONN); // Already in connected state - return; - } if(err == ERR_USE) { - sendReturnValue(rpcSock, -1, EADDRINUSE); // Already in use - return; - } if(err == ERR_VAL) { - sendReturnValue(rpcSock, -1, EINVAL); // Invalid ipaddress parameter - return; - } if(err == ERR_RTE) { - sendReturnValue(rpcSock, -1, ENETUNREACH); // No route to host - return; - } if(err == ERR_BUF) { - sendReturnValue(rpcSock, -1, EAGAIN); // No more ports available - return; - } - if(err == ERR_MEM) { - sendReturnValue(rpcSock, -1, EAGAIN); // TODO: Doesn't describe the problem well, but closest match - return; - } - - // We should only return a value if failure happens immediately - // Otherwise, we still need to wait for a callback from lwIP. - // - This is because an ERR_OK from tcp_connect() only verifies - // that the SYN packet was enqueued onto the stack properly, - // that's it! - // - Most instances of a retval for a connect() should happen - // in the nc_connect() and nc_err() callbacks! - DEBUG_ERROR(" unable to connect"); - sendReturnValue(rpcSock, -1, EAGAIN); - } - // Everything seems to be ok, but we don't have enough info to retval - conn->listening=true; - conn->rpcSock=rpcSock; // used for return value from lwip CB - } else { - DEBUG_ERROR(" could not locate PCB based on application-provided fd"); - sendReturnValue(rpcSock, -1, EBADF); - } + #endif } void NetconEthernetTap::handleWrite(Connection *conn) diff --git a/src/SDK_EthernetTap.hpp b/src/SDK_EthernetTap.hpp index ee3627f..ff732c9 100644 --- a/src/SDK_EthernetTap.hpp +++ b/src/SDK_EthernetTap.hpp @@ -86,6 +86,9 @@ namespace ZeroTier { unsigned char rxbuf[DEFAULT_TCP_RX_BUF_SZ]; // TODO: necessary still? int proxy_conn_state; + + // pico + struct pico_socket *picosock; }; /* diff --git a/src/SDK_pico.hpp b/src/SDK_pico.hpp index bd3ac15..6c81ebd 100644 --- a/src/SDK_pico.hpp +++ b/src/SDK_pico.hpp @@ -61,6 +61,21 @@ #define PICO_DEVICE_INIT_SIG struct pico_device *dev, const char *name, uint8_t *mac #define PICO_STACK_RECV_SIG struct pico_device *dev, uint8_t *buffer, uint32_t len #define PICO_ICMP4_PING_SIG char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *) +// +#define PICO_TIMER_ADD_SIG pico_time expire, void (*timer)(pico_time, void *), void *arg + +#define PICO_STRING_TO_IPV6_SIG const char *ipstr, uint8_t *ip +#define PICO_SOCKET_SETOPTION_SIG struct pico_socket *s, int option, void *value +#define PICO_SOCKET_SEND_SIG struct pico_socket *s, const void *buf, int len +#define PICO_SOCKET_SENDTO_SIG struct pico_socket *s, const void *buf, int len, void *dst, uint16_t remote_port +#define PICO_SOCKET_RECV_SIG struct pico_socket *s, void *buf, int len +#define PICO_SOCKET_OPEN_SIG uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *s) +#define PICO_SOCKET_BIND_SIG struct pico_socket *s, void *local_addr, uint16_t *port +#define PICO_SOCKET_CONNECT_SIG struct pico_socket *s, const void *srv_addr, uint16_t remote_port +#define PICO_SOCKET_READ_SIG struct pico_socket *s, void *buf, int len +#define PICO_SOCKET_WRITE_SIG struct pico_socket *s, const void *buf, int len +#define PICO_SOCKET_CLOSE_SIG struct pico_socket *s +#define PICO_SOCKET_SHUTDOWN_SIG struct pico_socket *s, int mode namespace ZeroTier { @@ -99,6 +114,20 @@ namespace ZeroTier { int32_t (*_pico_stack_recv)(PICO_STACK_RECV_SIG); int (*_pico_icmp4_ping)(PICO_ICMP4_PING_SIG); + int (*_pico_string_to_ipv6)(PICO_STRING_TO_IPV6_SIG); + int (*_pico_socket_setoption)(PICO_SOCKET_SETOPTION_SIG); + uint32_t (*_pico_timer_add)(PICO_TIMER_ADD_SIG); + int (*_pico_socket_send)(PICO_SOCKET_SEND_SIG); + int (*_pico_socket_recv)(PICO_SOCKET_RECV_SIG); + + struct pico_socket * (*_pico_socket_open)(PICO_SOCKET_OPEN_SIG); + int (*_pico_socket_bind)(PICO_SOCKET_BIND_SIG); + int (*_pico_socket_connect)(PICO_SOCKET_CONNECT_SIG); + int (*_pico_socket_read)(PICO_SOCKET_READ_SIG); + int (*_pico_socket_write)(PICO_SOCKET_WRITE_SIG); + int (*_pico_socket_close)(PICO_SOCKET_CLOSE_SIG); + int (*_pico_socket_shutdown)(PICO_SOCKET_SHUTDOWN_SIG); + Mutex _lock; Mutex _lock_mem; @@ -141,6 +170,20 @@ namespace ZeroTier { _pico_stack_recv = (int32_t(*)(PICO_STACK_RECV_SIG))&pico_stack_recv; _pico_icmp4_ping = (int(*)(PICO_ICMP4_PING_SIG))&pico_icmp4_ping; + _pico_string_to_ipv6 = (int(*)(PICO_STRING_TO_IPV6_SIG))&pico_string_to_ipv6; + _pico_socket_setoption = (int(*)(PICO_SOCKET_SETOPTION_SIG))&pico_socket_setoption; + _pico_timer_add = (uint32_t(*)(PICO_TIMER_ADD_SIG))&pico_timer_add; + _pico_socket_send = (int(*)(PICO_SOCKET_SEND_SIG))&pico_socket_send; + _pico_socket_recv = (int(*)(PICO_SOCKET_RECV_SIG))&pico_socket_recv; + + _pico_socket_open = (struct pico_socket*(*)(PICO_SOCKET_OPEN_SIG))&pico_socket_open; + _pico_socket_bind = (int(*)(PICO_SOCKET_BIND_SIG))&pico_socket_bind; + _pico_socket_connect = (int(*)(PICO_SOCKET_CONNECT_SIG))&pico_socket_connect; + _pico_socket_read = (int(*)(PICO_SOCKET_READ_SIG))&pico_socket_read; + _pico_socket_write = (int(*)(PICO_SOCKET_WRITE_SIG))&pico_socket_write; + _pico_socket_close = (int(*)(PICO_SOCKET_CLOSE_SIG))&pico_socket_close; + _pico_socket_shutdown = (int(*)(PICO_SOCKET_SHUTDOWN_SIG))&pico_socket_shutdown; + #endif @@ -160,6 +203,19 @@ namespace ZeroTier { _pico_stack_recv = (int32_t(*)(PICO_STACK_RECV_SIG))dlsym(_libref, "pico_stack_recv"); _pico_icmp4_ping = (int(*)(PICO_ICMP4_PING_SIG))dlsym(_libref, "pico_icmp4_ping"); + _pico_string_to_ipv6 = (int(*)(PICO_STRING_TO_IPV6_SIG))dlsym(_libref, "pico_string_to_ipv6"); + _pico_socket_setoption = (int(*)(PICO_SOCKET_SETOPTION_SIG))dlsym(_libref, "pico_socket_setoption"); + _pico_timer_add = (uint32_t(*)(PICO_TIMER_ADD_SIG))dlsym(_libref, "pico_timer_add"); + _pico_socket_send = (int(*)(PICO_SOCKET_SEND_SIG))dlsym(_libref, "pico_socket_send"); + _pico_socket_recv = (int(*)(PICO_SOCKET_RECV_SIG))dlsym(_libref, "pico_socket_recv"); + + _pico_socket_open = (struct pico_socket*(*)(PICO_SOCKET_OPEN_SIG))dlsym(_libref, "pico_socket_open"); + _pico_socket_bind = (int(*)(PICO_SOCKET_BIND_SIG))dlsym(_libref, "pico_socket_bind"); + _pico_socket_connect = (int(*)(PICO_SOCKET_CONNECT_SIG))dlsym(_libref, "pico_socket_connect"); + _pico_socket_read = (int(*)(PICO_SOCKET_READ_SIG))dlsym(_libref, "pico_socket_read"); + _pico_socket_write = (int(*)(PICO_SOCKET_WRITE_SIG))dlsym(_libref, "pico_socket_write"); + _pico_socket_close = (int(*)(PICO_SOCKET_CLOSE_SIG))dlsym(_libref, "pico_socket_close"); + _pico_socket_shutdown = (int(*)(PICO_SOCKET_SHUTDOWN_SIG))dlsym(_libref, "pico_socket_shutdown"); #endif } @@ -181,6 +237,19 @@ namespace ZeroTier { inline int __pico_stack_recv(PICO_STACK_RECV_SIG) throw() { /*Mutex::Lock _l(_lock);*/ return _pico_stack_recv(dev, buffer, len); } inline int __pico_icmp4_ping(PICO_ICMP4_PING_SIG) throw() { Mutex::Lock _l(_lock); return _pico_icmp4_ping(dst, count, interval, timeout, size, cb); } + inline int __pico_string_to_ipv6(PICO_STRING_TO_IPV6_SIG) throw() { Mutex::Lock _l(_lock); return _pico_string_to_ipv6(ipstr, ip); } + inline int __pico_socket_setoption(PICO_SOCKET_SETOPTION_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_setoption(s, option, value); } + inline uint32_t __pico_timer_add(PICO_TIMER_ADD_SIG) throw() { Mutex::Lock _l(_lock); return _pico_timer_add(expire, timer, arg); } + inline int __pico_socket_send(PICO_SOCKET_SEND_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_send(s, buf, len); } + inline int __pico_socket_recv(PICO_SOCKET_RECV_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_recv(s, buf, len); } + + inline struct pico_socket * __pico_socket_open(PICO_SOCKET_OPEN_SIG) throw() { return _pico_socket_open(net, proto, wakeup); } + inline int __pico_socket_bind(PICO_SOCKET_BIND_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_bind(s, local_addr, port); } + inline int __pico_socket_connect(PICO_SOCKET_CONNECT_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_connect(s, srv_addr, remote_port); } + inline int __pico_socket_read(PICO_SOCKET_READ_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_read(s, buf, len); } + inline int __pico_socket_write(PICO_SOCKET_WRITE_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_write(s, buf, len); } + inline int __pico_socket_close(PICO_SOCKET_CLOSE_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_close(s); } + inline int __pico_socket_shutdown(PICO_SOCKET_SHUTDOWN_SIG) throw() { Mutex::Lock _l(_lock); return _pico_socket_shutdown(s, mode); } }; } // namespace ZeroTier