fixed longstanding buffer logic bug

This commit is contained in:
Joseph Henry
2017-03-20 07:54:08 -07:00
parent 2f57ea600a
commit db3bf75b7d
6 changed files with 55 additions and 105 deletions

View File

@@ -33,7 +33,7 @@
#ifndef _SDK_DEBUG_H_ #ifndef _SDK_DEBUG_H_
#define _SDK_DEBUG_H_ #define _SDK_DEBUG_H_
#define DEBUG_LEVEL 1 // Set this to adjust what you'd like to see in the debug traces #define DEBUG_LEVEL 0 // Set this to adjust what you'd like to see in the debug traces
#define MSG_ERROR 1 // Errors #define MSG_ERROR 1 // Errors
#define MSG_TRANSFER 2 // RX/TX specific statements #define MSG_TRANSFER 2 // RX/TX specific statements

View File

@@ -167,12 +167,14 @@ int rpc_send_command(char *path, int cmd, int forfd, void *data, int len)
uint64_t canary_num; uint64_t canary_num;
// ephemeral RPC socket used only for this command // ephemeral RPC socket used only for this command
int rpc_sock = rpc_join(path); int rpc_sock = rpc_join(path);
// Generate token // Generate token
int fdrand = open("/dev/urandom", O_RDONLY); int fdrand = open("/dev/urandom", O_RDONLY);
if(read(fdrand, &CANARY, CANARY_SZ) < 0) { if(read(fdrand, &CANARY, CANARY_SZ) < 0) {
DEBUG_ERROR("unable to read from /dev/urandom for RPC canary data"); DEBUG_ERROR("unable to read from /dev/urandom for RPC canary data");
return -1; return -1;
} }
close(fdrand); close(fdrand);
memcpy(&canary_num, CANARY, CANARY_SZ); memcpy(&canary_num, CANARY, CANARY_SZ);
cmdbuf[CMD_ID_IDX] = cmd; cmdbuf[CMD_ID_IDX] = cmd;
@@ -204,6 +206,7 @@ int rpc_send_command(char *path, int cmd, int forfd, void *data, int len)
/* Combine command flag+payload with RPC metadata */ /* Combine command flag+payload with RPC metadata */
memcpy(metabuf, RPC_PHRASE, RPC_PHRASE_SZ); // Write signal phrase memcpy(metabuf, RPC_PHRASE, RPC_PHRASE_SZ); // Write signal phrase
memcpy(&metabuf[IDX_PAYLOAD], cmdbuf, len + 1 + CANARY_SZ); memcpy(&metabuf[IDX_PAYLOAD], cmdbuf, len + 1 + CANARY_SZ);
// Write RPC // Write RPC
long n_write = write(rpc_sock, &metabuf, BUF_SZ); long n_write = write(rpc_sock, &metabuf, BUF_SZ);
if(n_write < 0) { if(n_write < 0) {

View File

@@ -55,9 +55,6 @@
#endif #endif
#endif #endif
#include <sys/socket.h>
#include <stdbool.h>
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
// -------------- Socket API function signatures for convenience ---------------- // -------------- Socket API function signatures for convenience ----------------
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------

View File

@@ -320,7 +320,6 @@ int (*realclose)(CLOSE_SIG);
if(n>0) { if(n>0) {
total_read += n; total_read += n;
total_socket_rx += n;
} }
else if (n < 0) else if (n < 0)
return n; return n;
@@ -555,7 +554,6 @@ int (*realclose)(CLOSE_SIG);
JNIEXPORT jint JNICALL Java_ZeroTier_ZTSDK_zt_1connect(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) { JNIEXPORT jint JNICALL Java_ZeroTier_ZTSDK_zt_1connect(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) {
struct sockaddr_in addr; struct sockaddr_in addr;
const char *str = (*env)->GetStringUTFChars(env, addrstr, 0); const char *str = (*env)->GetStringUTFChars(env, addrstr, 0);
DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port);
addr.sin_addr.s_addr = inet_addr(str); addr.sin_addr.s_addr = inet_addr(str);
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons( port ); addr.sin_port = htons( port );
@@ -571,7 +569,6 @@ int (*realclose)(CLOSE_SIG);
#endif #endif
{ {
get_api_netpath(); get_api_netpath();
//DEBUG_INFO("fd=%d", fd);
struct connect_st rpc_st; struct connect_st rpc_st;
rpc_st.fd = fd; rpc_st.fd = fd;
memcpy(&rpc_st.addr, addr, sizeof(struct sockaddr_storage)); memcpy(&rpc_st.addr, addr, sizeof(struct sockaddr_storage));

View File

@@ -57,7 +57,6 @@ namespace ZeroTier {
void pico_init_interface(NetconEthernetTap *tap, const InetAddress &ip) void pico_init_interface(NetconEthernetTap *tap, const InetAddress &ip)
{ {
picoTCP_stack *stack = tap->picostack; picoTCP_stack *stack = tap->picostack;
DEBUG_INFO();
if (std::find(picotap->_ips.begin(),picotap->_ips.end(),ip) == picotap->_ips.end()) { if (std::find(picotap->_ips.begin(),picotap->_ips.end(),ip) == picotap->_ips.end()) {
picotap->_ips.push_back(ip); picotap->_ips.push_back(ip);
std::sort(picotap->_ips.begin(),picotap->_ips.end()); std::sort(picotap->_ips.begin(),picotap->_ips.end());
@@ -128,7 +127,6 @@ namespace ZeroTier {
// After this step, buffer will be emptied periodically by pico_handleRead() // After this step, buffer will be emptied periodically by pico_handleRead()
void pico_cb_tcp_read(NetconEthernetTap *tap, struct pico_socket *s) void pico_cb_tcp_read(NetconEthernetTap *tap, struct pico_socket *s)
{ {
DEBUG_INFO();
Connection *conn = tap->getConnection(s); Connection *conn = tap->getConnection(s);
if(conn) { if(conn) {
int r; int r;
@@ -171,8 +169,6 @@ namespace ZeroTier {
// //
void pico_cb_udp_read(NetconEthernetTap *tap, struct pico_socket *s) void pico_cb_udp_read(NetconEthernetTap *tap, struct pico_socket *s)
{ {
DEBUG_INFO();
Connection *conn = tap->getConnection(s); Connection *conn = tap->getConnection(s);
if(conn) { if(conn) {
@@ -190,16 +186,14 @@ namespace ZeroTier {
// RX // RX
int r = tap->picostack->__pico_socket_recvfrom(s, tmpbuf, SDK_MTU, (void *)&peer.ip4.addr, &port); int r = tap->picostack->__pico_socket_recvfrom(s, tmpbuf, SDK_MTU, (void *)&peer.ip4.addr, &port);
DEBUG_FLOW(" [ RXBUF <- STACK] Receiving (%d) from stack, copying to receving buffer", r); //DEBUG_FLOW(" [ RXBUF <- STACK] Receiving (%d) from stack, copying to receving buffer", r);
// Mutex::Lock _l2(tap->_rx_buf_m); // Mutex::Lock _l2(tap->_rx_buf_m);
// struct sockaddr_in6 addr_in6; // struct sockaddr_in6 addr_in6;
// addr_in6.sin6_addr.s6_addr; // addr_in6.sin6_addr.s6_addr;
// addr_in6.sin6_port = Utils::ntoh(s->remote_port); // addr_in6.sin6_port = Utils::ntoh(s->remote_port);
// DEBUG_ATTN("remote_port=%d, local_port=%d", s->remote_port, Utils::ntoh(s->local_port)); // DEBUG_ATTN("remote_port=%d, local_port=%d", s->remote_port, Utils::ntoh(s->local_port));
picotap->_rx_buf_m.lock(); picotap->_rx_buf_m.lock();
if(conn->rxsz == DEFAULT_UDP_RX_BUF_SZ) { // if UDP buffer full if(conn->rxsz == DEFAULT_UDP_RX_BUF_SZ) { // if UDP buffer full
//DEBUG_FLOW(" [ RXBUF <- STACK] UDP RX buffer full. Discarding oldest payload segment"); //DEBUG_FLOW(" [ RXBUF <- STACK] UDP RX buffer full. Discarding oldest payload segment");
memmove(conn->rxbuf, conn->rxbuf + SDK_MTU, DEFAULT_UDP_RX_BUF_SZ - SDK_MTU); memmove(conn->rxbuf, conn->rxbuf + SDK_MTU, DEFAULT_UDP_RX_BUF_SZ - SDK_MTU);
@@ -214,19 +208,22 @@ namespace ZeroTier {
payload_pos = addr_pos + sizeof(struct sockaddr_storage) + sizeof(r); payload_pos = addr_pos + sizeof(struct sockaddr_storage) + sizeof(r);
memcpy(addr_pos, &addr_in, sizeof(struct sockaddr_storage)); memcpy(addr_pos, &addr_in, sizeof(struct sockaddr_storage));
memcpy(payload_pos, tmpbuf, r); // write payload to app's socket
// Adjust buffer size // Adjust buffer size
if(r) { if(r) {
conn->rxsz += SDK_MTU; conn->rxsz += SDK_MTU;
memcpy(sz_pos, &r, sizeof(r)); memcpy(sz_pos, &r, sizeof(r));
tap->phyOnUnixWritable(conn->sock, NULL, true);
//tap->_phy.setNotifyWritable(conn->sock, false);
} }
if (r < 0) { if (r < 0) {
DEBUG_ERROR("unable to read from picosock=%p", s); DEBUG_ERROR("unable to read from picosock=%p", s);
} }
memcpy(payload_pos, tmpbuf, r); // write payload to app's socket picotap->_rx_buf_m.unlock();
// TODO: Revisit logic
if(r)
tap->phyOnUnixWritable(conn->sock, NULL, true);
//DEBUG_EXTRA(" Copied onto rxbuf (%d) from stack socket", r); //DEBUG_EXTRA(" Copied onto rxbuf (%d) from stack socket", r);
picotap->_rx_buf_m.unlock();
return; return;
} }
} }
@@ -239,8 +236,6 @@ namespace ZeroTier {
DEBUG_ERROR("invalid connection"); DEBUG_ERROR("invalid connection");
if(!conn->txsz) if(!conn->txsz)
return; return;
DEBUG_INFO("txsz=%d bytes ready to be written", conn->txsz);
// Only called from a locked context, no need to lock anything // Only called from a locked context, no need to lock anything
if(conn->txsz > 0) { if(conn->txsz > 0) {
int r, max_write_len = conn->txsz < SDK_MTU ? conn->txsz : SDK_MTU; int r, max_write_len = conn->txsz < SDK_MTU ? conn->txsz : SDK_MTU;
@@ -262,7 +257,6 @@ namespace ZeroTier {
// Main callback for TCP connections // Main callback for TCP connections
void pico_cb_socket_activity(uint16_t ev, struct pico_socket *s) void pico_cb_socket_activity(uint16_t ev, struct pico_socket *s)
{ {
DEBUG_INFO();
int err; int err;
Mutex::Lock _l(picotap->_tcpconns_m); Mutex::Lock _l(picotap->_tcpconns_m);
Connection *conn = picotap->getConnection(s); Connection *conn = picotap->getConnection(s);
@@ -313,7 +307,6 @@ namespace ZeroTier {
} }
return; return;
} }
// Read from picoTCP socket // Read from picoTCP socket
if (ev & PICO_SOCK_EV_RD) { if (ev & PICO_SOCK_EV_RD) {
if(conn->type==SOCK_STREAM) if(conn->type==SOCK_STREAM)
@@ -352,7 +345,6 @@ namespace ZeroTier {
// ----------------------------------------- // -----------------------------------------
int pico_eth_send(struct pico_device *dev, void *buf, int len) int pico_eth_send(struct pico_device *dev, void *buf, int len)
{ {
//DEBUG_INFO("len=%d", len);
struct pico_eth_hdr *ethhdr; struct pico_eth_hdr *ethhdr;
ethhdr = (struct pico_eth_hdr *)buf; ethhdr = (struct pico_eth_hdr *)buf;
@@ -376,7 +368,6 @@ namespace ZeroTier {
// It will then periodically be transfered into the network stack via pico_eth_poll() // It will then periodically be transfered into the network stack via pico_eth_poll()
void pico_rx(NetconEthernetTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) void pico_rx(NetconEthernetTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
{ {
DEBUG_INFO();
// Since picoTCP only allows the reception of frames from within the polling function, we // Since picoTCP only allows the reception of frames from within the polling function, we
// must enqueue each frame into a memory structure shared by both threads. This structure will // must enqueue each frame into a memory structure shared by both threads. This structure will
Mutex::Lock _l(tap->_pico_frame_rxbuf_m); Mutex::Lock _l(tap->_pico_frame_rxbuf_m);
@@ -392,7 +383,7 @@ namespace ZeroTier {
while(newlen > (MAX_PICO_FRAME_RX_BUF_SZ-tap->pico_frame_rxbuf_tot) && ethhdr.proto == 56710) while(newlen > (MAX_PICO_FRAME_RX_BUF_SZ-tap->pico_frame_rxbuf_tot) && ethhdr.proto == 56710)
{ {
mylen = 0; mylen = 0;
DEBUG_ERROR(" [ ZTWIRE -> FBUF ] not enough space left on RX frame buffer, dropping oldest packet in buffer"); //DEBUG_FLOW(" [ ZTWIRE -> FBUF ] not enough space left on RX frame buffer, dropping oldest packet in buffer");
/* /*
memcpy(&mylen, picotap->pico_frame_rxbuf, sizeof(len)); memcpy(&mylen, picotap->pico_frame_rxbuf, sizeof(len));
memmove(tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + mylen, MAX_PICO_FRAME_RX_BUF_SZ-mylen); // shift buffer memmove(tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + mylen, MAX_PICO_FRAME_RX_BUF_SZ-mylen); // shift buffer
@@ -406,28 +397,6 @@ namespace ZeroTier {
memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(newlen) + sizeof(ethhdr), data, len); // frame data memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(newlen) + sizeof(ethhdr), data, len); // frame data
tap->pico_frame_rxbuf_tot += newlen; tap->pico_frame_rxbuf_tot += newlen;
DEBUG_FLOW(" [ ZTWIRE -> FBUF ] Move FRAME(sz=%d) into FBUF(sz=%d), data_len=%d", newlen, picotap->pico_frame_rxbuf_tot, len); DEBUG_FLOW(" [ ZTWIRE -> FBUF ] Move FRAME(sz=%d) into FBUF(sz=%d), data_len=%d", newlen, picotap->pico_frame_rxbuf_tot, len);
/*
char graph[GRAPH_BUF_SZ];
gengraph(&graph, GRAPH_BUF_SZ, '|', 0.6);
DEBUG_FLOW(graph);
*/
//}
//else
//{
/*
if(newlen > (MAX_PICO_FRAME_RX_BUF_SZ-tap->pico_frame_rxbuf_tot)) {
DEBUG_ERROR("dropping packet (len = %d) - not enough space left on RX frame buffer", len);
return;
}
memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot, &newlen, sizeof(newlen)); // size of frame + meta
memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(newlen), &ethhdr, sizeof(ethhdr)); // new eth header
memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(newlen) + sizeof(ethhdr), data, len); // frame data
tap->pico_frame_rxbuf_tot += newlen;
DEBUG_FLOW(" [ ZTWIRE -> FBUF ] Moved FRAME(sz=%d) into FBUF(sz=%d), data_len=%d, ethhdr.proto=%d", newlen, picotap->pico_frame_rxbuf_tot, len, ethhdr.proto);
*/
//}
} }
// Called periodically by the stack, this removes data from the locked memory buffer (FBUF) and feeds it into the stack. // Called periodically by the stack, this removes data from the locked memory buffer (FBUF) and feeds it into the stack.
@@ -440,19 +409,18 @@ namespace ZeroTier {
// ----------------------------------------- // -----------------------------------------
int pico_eth_poll(struct pico_device *dev, int loop_score) int pico_eth_poll(struct pico_device *dev, int loop_score)
{ {
//DEBUG_ERROR();
// OPTIMIZATION: The copy logic and/or buffer structure should be reworked for better performance after the BETA // OPTIMIZATION: The copy logic and/or buffer structure should be reworked for better performance after the BETA
// NetconEthernetTap *tap = (NetconEthernetTap*)netif->state; // NetconEthernetTap *tap = (NetconEthernetTap*)netif->state;
Mutex::Lock _l(picotap->_pico_frame_rxbuf_m); Mutex::Lock _l(picotap->_pico_frame_rxbuf_m);
unsigned char frame[SDK_MTU]; unsigned char frame[SDK_MTU];
int len; int len;
while (picotap->pico_frame_rxbuf_tot > 0 && loop_score > 0) { while (picotap->pico_frame_rxbuf_tot > 0 && loop_score > 0) {
DEBUG_INFO(" [ FBUF -> STACK] Frame buffer SZ=%d", picotap->pico_frame_rxbuf_tot); //DEBUG_FLOW(" [ FBUF -> STACK] Frame buffer SZ=%d", picotap->pico_frame_rxbuf_tot);
memset(frame, 0, sizeof(frame)); memset(frame, 0, sizeof(frame));
len = 0; len = 0;
memcpy(&len, picotap->pico_frame_rxbuf, sizeof(len)); // get frame len memcpy(&len, picotap->pico_frame_rxbuf, sizeof(len)); // get frame len
if(len >= 0) { if(len >= 0) {
DEBUG_FLOW(" [ FBUF -> STACK] Moving FRAME of size (%d) from FBUF(sz=%d) into stack",len, picotap->pico_frame_rxbuf_tot-len); //DEBUG_FLOW(" [ FBUF -> STACK] Moving FRAME of size (%d) from FBUF(sz=%d) into stack",len, picotap->pico_frame_rxbuf_tot-len);
memcpy(frame, picotap->pico_frame_rxbuf + sizeof(len), len-(sizeof(len)) ); // get frame data memcpy(frame, picotap->pico_frame_rxbuf + sizeof(len), len-(sizeof(len)) ); // get frame data
memmove(picotap->pico_frame_rxbuf, picotap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len); // shift buffer memmove(picotap->pico_frame_rxbuf, picotap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len); // shift buffer
picotap->picostack->__pico_stack_recv(dev, (uint8_t*)frame, (len-sizeof(len))); picotap->picostack->__pico_stack_recv(dev, (uint8_t*)frame, (len-sizeof(len)));
@@ -470,7 +438,6 @@ namespace ZeroTier {
// Creates a new pico_socket and Connection object to represent a new connection to be. // Creates a new pico_socket and Connection object to represent a new connection to be.
Connection *pico_handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc) Connection *pico_handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc)
{ {
DEBUG_INFO();
struct pico_socket * psock; struct pico_socket * psock;
int protocol, protocol_version; int protocol, protocol_version;
@@ -494,33 +461,33 @@ namespace ZeroTier {
*uptr = newConn; *uptr = newConn;
newConn->type = socket_rpc->socket_type; newConn->type = socket_rpc->socket_type;
newConn->sock = sock; newConn->sock = sock;
/*
/*
int res = 0; int res = 0;
int sendbuff = UNIX_SOCK_BUF_SIZE; int sendbuff = UNIX_SOCK_BUF_SIZE;
socklen_t optlen = sizeof(sendbuff); socklen_t optlen = sizeof(sendbuff);
res = setsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_RCVBUF, &sendbuff, sizeof(sendbuff)); res = setsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_RCVBUF, &sendbuff, sizeof(sendbuff));
if(res == -1) if(res == -1)
DEBUG_ERROR("Error while setting RX buffer limits"); //DEBUG_ERROR("Error while setting RX buffer limits");
res = setsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)); res = setsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));
if(res == -1) if(res == -1)
DEBUG_ERROR("Error while setting TX buffer limits"); //DEBUG_ERROR("Error while setting TX buffer limits");
// Get buffer size // Get buffer size
// optlen = sizeof(sendbuff); // optlen = sizeof(sendbuff);
// res = getsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen); // res = getsockopt(picotap->_phy.getDescriptor(sock), SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);
// DEBUG_INFO("buflen=%d", sendbuff); // DEBUG_INFO("buflen=%d", sendbuff);
*/ */
newConn->local_addr = NULL; newConn->local_addr = NULL;
// newConn->peer_addr = NULL;
newConn->picosock = psock; newConn->picosock = psock;
picotap->_Connections.push_back(newConn); picotap->_Connections.push_back(newConn);
memset(newConn->rxbuf, 0, DEFAULT_UDP_RX_BUF_SZ); memset(newConn->rxbuf, 0, DEFAULT_UDP_RX_BUF_SZ);
return newConn; return newConn;
} }
else { else
DEBUG_ERROR("failed to create pico_socket"); DEBUG_ERROR("failed to create pico_socket");
}
return NULL; return NULL;
} }
@@ -533,7 +500,6 @@ namespace ZeroTier {
// ----------------------------------------- // -----------------------------------------
void pico_handleWrite(Connection *conn) void pico_handleWrite(Connection *conn)
{ {
//DEBUG_INFO();
if(!conn || !conn->picosock) { if(!conn || !conn->picosock) {
DEBUG_ERROR(" invalid connection"); DEBUG_ERROR(" invalid connection");
return; return;
@@ -579,15 +545,14 @@ namespace ZeroTier {
} }
if(conn->type == SOCK_DGRAM) { if(conn->type == SOCK_DGRAM) {
max = DEFAULT_UDP_TX_BUF_SZ; max = DEFAULT_UDP_TX_BUF_SZ;
//DEBUG_TRANS("[UDP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes", DEBUG_TRANS("[UDP TX] ---> :: {TX: %.3f%%, RX: %.3f%%, physock=%p} :: %d bytes",
// (float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r); (float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, r);
} }
} }
// Instructs the stack to connect to a remote host // Instructs the stack to connect to a remote host
void pico_handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn, struct connect_st* connect_rpc) void pico_handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn, struct connect_st* connect_rpc)
{ {
//DEBUG_INFO();
if(conn->picosock) { if(conn->picosock) {
struct sockaddr_in *addr = (struct sockaddr_in *) &connect_rpc->addr; struct sockaddr_in *addr = (struct sockaddr_in *) &connect_rpc->addr;
int ret; int ret;
@@ -612,15 +577,13 @@ namespace ZeroTier {
memcpy(&(conn->peer_addr), &connect_rpc->addr, sizeof(struct sockaddr_storage)); memcpy(&(conn->peer_addr), &connect_rpc->addr, sizeof(struct sockaddr_storage));
if(ret == PICO_ERR_EPROTONOSUPPORT) { if(ret == PICO_ERR_EPROTONOSUPPORT)
DEBUG_ERROR("PICO_ERR_EPROTONOSUPPORT"); DEBUG_ERROR("PICO_ERR_EPROTONOSUPPORT");
} if(ret == PICO_ERR_EINVAL)
if(ret == PICO_ERR_EINVAL) {
DEBUG_ERROR("PICO_ERR_EINVAL"); DEBUG_ERROR("PICO_ERR_EINVAL");
} if(ret == PICO_ERR_EHOSTUNREACH)
if(ret == PICO_ERR_EHOSTUNREACH) {
DEBUG_ERROR("PICO_ERR_EHOSTUNREACH"); DEBUG_ERROR("PICO_ERR_EHOSTUNREACH");
}
picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), 0, ERR_OK); picotap->sendReturnValue(picotap->_phy.getDescriptor(rpcSock), 0, ERR_OK);
} }
} }
@@ -628,7 +591,6 @@ namespace ZeroTier {
// Instructs the stack to bind to a given address // Instructs the stack to bind to a given address
void pico_handleBind(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct bind_st *bind_rpc) void pico_handleBind(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct bind_st *bind_rpc)
{ {
DEBUG_INFO();
Connection *conn = picotap->getConnection(sock); Connection *conn = picotap->getConnection(sock);
if(!sock) { if(!sock) {
DEBUG_ERROR("invalid connection"); DEBUG_ERROR("invalid connection");
@@ -706,26 +668,35 @@ namespace ZeroTier {
// ----------------------------------------- // -----------------------------------------
void pico_handleRead(PhySocket *sock,void **uptr,bool lwip_invoked) void pico_handleRead(PhySocket *sock,void **uptr,bool lwip_invoked)
{ {
DEBUG_INFO();
if(!lwip_invoked) { if(!lwip_invoked) {
// The stack thread writes to RXBUF as well // The stack thread writes to RXBUF as well
picotap->_tcpconns_m.lock(); picotap->_tcpconns_m.lock();
picotap->_rx_buf_m.lock(); picotap->_rx_buf_m.lock();
} }
int tot = 0, n = -1; int tot = 0, n = -1, write_attempts = 0;
Connection *conn = picotap->getConnection(sock); Connection *conn = picotap->getConnection(sock);
if(conn && conn->rxsz) { if(conn && conn->rxsz) {
float max = conn->type == SOCK_STREAM ? (float)DEFAULT_TCP_RX_BUF_SZ : (float)DEFAULT_UDP_RX_BUF_SZ; float max = conn->type == SOCK_STREAM ? (float)DEFAULT_TCP_RX_BUF_SZ : (float)DEFAULT_UDP_RX_BUF_SZ;
if(conn->type==SOCK_DGRAM) { if(conn->type==SOCK_DGRAM) {
//DEBUG_FLOW(" [ ZTSOCK <- RXBUF] attempting write, RXBUF(%d)", conn->rxsz); //DEBUG_ERROR(" [ ZTSOCK <- RXBUF] attempting write, RXBUF(%d)", conn->rxsz);
// Try to write SDK_MTU-sized chunk to app socket // Try to write SDK_MTU-sized chunk to app socket
while(tot < SDK_MTU) { while(tot < SDK_MTU) {
write_attempts++;
n = picotap->_phy.streamSend(conn->sock, (conn->rxbuf)+tot, SDK_MTU); n = picotap->_phy.streamSend(conn->sock, (conn->rxbuf)+tot, SDK_MTU);
tot += n; tot += n;
DEBUG_FLOW(" [ ZTSOCK <- RXBUF] wrote = %d, total = %d", n, tot); //DEBUG_ERROR(" [ ZTSOCK <- RXBUF] wrote = %d, total = %d, errno=%d", n, tot, errno);
// If socket is unavailable, attempt to write N times before giving up
if(errno==35) {
if(write_attempts == 1024) {
n = SDK_MTU; // say we wrote it, even though we didn't (drop packet)
tot = SDK_MTU;
}
}
} }
// DEBUG_EXTRA("SOCK_DGRAM, conn=%p, physock=%p", conn, sock); // DEBUG_EXTRA("SOCK_DGRAM, conn=%p, physock=%p", conn, sock);
int payload_sz, addr_sz_offset = sizeof(struct sockaddr_storage); int payload_sz, addr_sz_offset = sizeof(struct sockaddr_storage);
@@ -765,18 +736,17 @@ namespace ZeroTier {
picotap->_phy.setNotifyWritable(sock, false); picotap->_phy.setNotifyWritable(sock, false);
} }
} }
//picotap->_phy.whack();
if(!lwip_invoked) { if(!lwip_invoked) {
picotap->_tcpconns_m.unlock(); picotap->_tcpconns_m.unlock();
picotap->_rx_buf_m.unlock(); picotap->_rx_buf_m.unlock();
} }
DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Emitted (%d) from RXBUF(%d) to socket", tot, conn->rxsz); DEBUG_FLOW(" [ ZTSOCK <- RXBUF] Emitted (%d) from RXBUF(%d) to socket", tot, conn->rxsz);
} }
// Closes a pico_socket // Closes a pico_socket
void pico_handleClose(PhySocket *sock) void pico_handleClose(PhySocket *sock)
{ {
DEBUG_INFO();
/* /*
int ret; int ret;
if(conn && conn->picosock) { if(conn && conn->picosock) {

View File

@@ -62,8 +62,7 @@
namespace ZeroTier { namespace ZeroTier {
int NetconEthernetTap::sendReturnValue(int fd, int retval, int _errno) int NetconEthernetTap::sendReturnValue(int fd, int retval, int _errno)
{ {
//#if !defined(USE_SOCKS_PROXY) //DEBUG_INFO("fd=%d, retval=%d, errno=%d", fd, retval, _errno);
//DEBUG_EXTRA("fd=%d, retval=%d, errno=%d", fd, retval, _errno);
int sz = sizeof(char) + sizeof(retval) + sizeof(errno); int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
char retmsg[sz]; char retmsg[sz];
memset(&retmsg, 0, sizeof(retmsg)); memset(&retmsg, 0, sizeof(retmsg));
@@ -71,9 +70,6 @@ int NetconEthernetTap::sendReturnValue(int fd, int retval, int _errno)
memcpy(&retmsg[1], &retval, sizeof(retval)); memcpy(&retmsg[1], &retval, sizeof(retval));
memcpy(&retmsg[1]+sizeof(retval), &_errno, sizeof(_errno)); memcpy(&retmsg[1]+sizeof(retval), &_errno, sizeof(_errno));
return write(fd, &retmsg, sz); return write(fd, &retmsg, sz);
//#else
// return 1;
//#endif
} }
// Unpacks the buffer from an RPC command // Unpacks the buffer from an RPC command
void NetconEthernetTap::unloadRPC(void *data, pid_t &pid, pid_t &tid, void NetconEthernetTap::unloadRPC(void *data, pid_t &pid, pid_t &tid,
@@ -296,7 +292,6 @@ Connection *NetconEthernetTap::getConnection(struct pico_socket *sock)
void NetconEthernetTap::closeConnection(PhySocket *sock) void NetconEthernetTap::closeConnection(PhySocket *sock)
{ {
DEBUG_EXTRA("physock=%p", sock);
Mutex::Lock _l(_close_m); Mutex::Lock _l(_close_m);
// Here we assume _tcpconns_m is already locked by caller // Here we assume _tcpconns_m is already locked by caller
if(!sock) { if(!sock) {
@@ -359,10 +354,11 @@ void NetconEthernetTap::phyOnUnixWritable(PhySocket *sock,void **uptr,bool lwip_
void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len) void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len)
{ {
//DEBUG_EXTRA("physock=%p, len=%d", sock, (int)len); //DEBUG_INFO("physock=%p, len=%d", sock, (int)len);
uint64_t CANARY_num; uint64_t CANARY_num;
pid_t pid, tid; pid_t pid, tid;
ssize_t wlen = len; ssize_t wlen = len;
char tmpbuf[SDK_MTU];
char cmd, timestamp[20], CANARY[CANARY_SZ], padding[] = {PADDING}; char cmd, timestamp[20], CANARY[CANARY_SZ], padding[] = {PADDING};
void *payload; void *payload;
unsigned char *buf = (unsigned char*)data; unsigned char *buf = (unsigned char*)data;
@@ -384,7 +380,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data,
// DEBUG_EXTRA(" RPC: physock=%p, (pid=%d, tid=%d, timestamp=%s, cmd=%d)", sock, pid, tid, timestamp, cmd); // DEBUG_EXTRA(" RPC: physock=%p, (pid=%d, tid=%d, timestamp=%s, cmd=%d)", sock, pid, tid, timestamp, cmd);
if(cmd == RPC_SOCKET) { if(cmd == RPC_SOCKET) {
//DEBUG_INFO("RPC_SOCKET, physock=%p", sock); // DEBUG_INFO("RPC_SOCKET, physock=%p", sock);
// Create new lwip socket and associate it with this sock // Create new lwip socket and associate it with this sock
struct socket_st socket_rpc; struct socket_st socket_rpc;
memcpy(&socket_rpc, &buf[IDX_PAYLOAD+STRUCT_IDX], sizeof(struct socket_st)); memcpy(&socket_rpc, &buf[IDX_PAYLOAD+STRUCT_IDX], sizeof(struct socket_st));
@@ -393,9 +389,11 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data,
new_conn->pid = pid; // Merely kept to look up application path/names later, not strictly necessary new_conn->pid = pid; // Merely kept to look up application path/names later, not strictly necessary
} }
} else { } else {
jobmap[CANARY_num] = std::pair<PhySocket*, void*>(sock, data); memcpy(&tmpbuf,data,len);
jobmap[CANARY_num] = std::pair<PhySocket*, void*>(sock, tmpbuf);
} }
write(_phy.getDescriptor(sock), "z", 1); // RPC ACK byte to maintain order int nwrit = write(_phy.getDescriptor(sock), "z", 1); // RPC ACK byte to maintain order
} }
// STREAM // STREAM
else { else {
@@ -417,7 +415,6 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data,
foundJob = true; foundJob = true;
} }
} }
conn = getConnection(sock); conn = getConnection(sock);
if(!conn) if(!conn)
return; return;
@@ -451,21 +448,9 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data,
} }
} }
} }
// Write data from stream // Write data from stream
if(wlen) { if(wlen) {
/*
if(conn->type == SOCK_STREAM) { // We only disable TCP "connections"
int softmax = conn->type == SOCK_STREAM ? DEFAULT_TCP_RX_BUF_SZ : DEFAULT_UDP_RX_BUF_SZ;
if(conn->txsz > softmax) {
_phy.setNotifyReadable(sock, false);
conn->disabled = true;
}
else if (conn->disabled) {
conn->disabled = false;
_phy.setNotifyReadable(sock, true);
}
}
*/
conn->txsz += wlen; conn->txsz += wlen;
handleWrite(conn); handleWrite(conn);
} }
@@ -475,7 +460,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data,
rpcSock = sockdata.first; rpcSock = sockdata.first;
buf = (unsigned char*)sockdata.second; buf = (unsigned char*)sockdata.second;
unloadRPC(buf, pid, tid, timestamp, CANARY, cmd, payload); unloadRPC(buf, pid, tid, timestamp, CANARY, cmd, payload);
// DEBUG_EXTRA(" RPC: physock=%p, (pid=%d, tid=%d, timestamp=%s, cmd=%d)", sock, pid, tid, timestamp, cmd); //DEBUG_ERROR(" RPC: physock=%p, (pid=%d, tid=%d, timestamp=%s, cmd=%d)", sock, pid, tid, timestamp, cmd);
switch(cmd) { switch(cmd) {
case RPC_BIND: case RPC_BIND:
//DEBUG_INFO("RPC_BIND, physock=%p", sock); //DEBUG_INFO("RPC_BIND, physock=%p", sock);
@@ -509,12 +494,12 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data,
jobmap.erase(CANARY_num); jobmap.erase(CANARY_num);
return; // Keep open RPC, we'll use it once in nc_connected to send retval return; // Keep open RPC, we'll use it once in nc_connected to send retval
default: default:
return;
break; break;
} }
Mutex::Lock _l(_tcpconns_m); Mutex::Lock _l(_tcpconns_m);
closeConnection(sockdata.first); // close RPC after sending retval, no longer needed closeConnection(sockdata.first); // close RPC after sending retval, no longer needed
jobmap.erase(CANARY_num); jobmap.erase(CANARY_num);
return;
} }
} }
@@ -552,7 +537,6 @@ void NetconEthernetTap::handleGetpeername(PhySocket *sock, PhySocket *rpcSock, v
Connection * NetconEthernetTap::handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc) Connection * NetconEthernetTap::handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc)
{ {
DEBUG_ATTN("physock=%p, sock_type=%d", sock, socket_rpc->socket_type);
#if defined(SDK_PICOTCP) #if defined(SDK_PICOTCP)
return pico_handleSocket(sock, uptr, socket_rpc); return pico_handleSocket(sock, uptr, socket_rpc);
#endif #endif
@@ -574,7 +558,6 @@ int NetconEthernetTap::handleConnectProxy(PhySocket *sock, struct sockaddr_in *r
// Connect a stack's PCB/socket/Connection object to a remote host // Connect a stack's PCB/socket/Connection object to a remote host
void NetconEthernetTap::handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn, struct connect_st* connect_rpc) void NetconEthernetTap::handleConnect(PhySocket *sock, PhySocket *rpcSock, Connection *conn, struct connect_st* connect_rpc)
{ {
//DEBUG_ATTN("physock=%p", sock);
Mutex::Lock _l(_tcpconns_m); Mutex::Lock _l(_tcpconns_m);
#if defined(SDK_PICOTCP) #if defined(SDK_PICOTCP)
pico_handleConnect(sock, rpcSock, conn, connect_rpc); pico_handleConnect(sock, rpcSock, conn, connect_rpc);