|
@@ -292,6 +292,9 @@ void NetconEthernetTap::threadMain()
|
|
|
{
|
|
|
uint64_t prev_tcp_time = 0, prev_status_time = 0, prev_etharp_time = 0;
|
|
|
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
+ _tcpconns_m.unlock();
|
|
|
+
|
|
|
// Main timer loop
|
|
|
while (_run) {
|
|
|
uint64_t now = OSUtils::now();
|
|
@@ -307,13 +310,16 @@ void NetconEthernetTap::threadMain()
|
|
|
prev_status_time = now;
|
|
|
status_remaining = STATUS_TMR_INTERVAL - since_status;
|
|
|
|
|
|
-
|
|
|
+ _tcpconns_m.lock();
|
|
|
for(size_t i=0;i<_TcpConnections.size();++i) {
|
|
|
if(!_TcpConnections[i]->sock)
|
|
|
continue; // Skip, this is a pending connection
|
|
|
int fd = _phy.getDescriptor(_TcpConnections[i]->sock);
|
|
|
dwr(MSG_DEBUG," tap_thread(): tcp\\jobs = {%d, %d}\n", _TcpConnections.size(), jobmap.size());
|
|
|
|
|
|
+
|
|
|
+ dwr(MSG_DEBUG," tap_thread(): sock=%x, pcb->state=%d\n", _TcpConnections[i]->sock, _TcpConnections[i]->pcb->state);
|
|
|
+
|
|
|
fcntl(fd, F_SETFL, O_NONBLOCK);
|
|
|
unsigned char tmpbuf[BUF_SZ];
|
|
|
|
|
@@ -329,12 +335,14 @@ void NetconEthernetTap::threadMain()
|
|
|
phyOnUnixData(_TcpConnections[i]->sock,_phy.getuptr(_TcpConnections[i]->sock),&tmpbuf,BUF_SZ);
|
|
|
}
|
|
|
}
|
|
|
+ _tcpconns_m.unlock();
|
|
|
}
|
|
|
// Main TCP/ETHARP timer section
|
|
|
if (since_tcp >= ZT_LWIP_TCP_TIMER_INTERVAL) {
|
|
|
prev_tcp_time = now;
|
|
|
lwipstack->tcp_tmr();
|
|
|
// Makeshift poll
|
|
|
+ _tcpconns_m.lock();
|
|
|
for(size_t i=0;i<_TcpConnections.size();++i) {
|
|
|
if(_TcpConnections[i]->txsz > 0){
|
|
|
lwipstack->_lock.lock();
|
|
@@ -342,6 +350,7 @@ void NetconEthernetTap::threadMain()
|
|
|
lwipstack->_lock.unlock();
|
|
|
}
|
|
|
}
|
|
|
+ _tcpconns_m.unlock();
|
|
|
} else {
|
|
|
tcp_remaining = ZT_LWIP_TCP_TIMER_INTERVAL - since_tcp;
|
|
|
}
|
|
@@ -367,7 +376,6 @@ void NetconEthernetTap::phyOnTcpWritable(PhySocket *sock,void **uptr) {}
|
|
|
|
|
|
TcpConnection *NetconEthernetTap::getConnection(PhySocket *sock)
|
|
|
{
|
|
|
- Mutex::Lock _l(_tcpconns_m);
|
|
|
for(size_t i=0;i<_TcpConnections.size();++i) {
|
|
|
if(_TcpConnections[i]->sock == sock)
|
|
|
return _TcpConnections[i];
|
|
@@ -375,27 +383,10 @@ TcpConnection *NetconEthernetTap::getConnection(PhySocket *sock)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-TcpConnection *NetconEthernetTap::addConnection(TcpConnection *conn)
|
|
|
-{
|
|
|
- Mutex::Lock _l(_tcpconns_m);
|
|
|
- _TcpConnections.push_back(conn);
|
|
|
- return conn;
|
|
|
-}
|
|
|
-
|
|
|
-void NetconEthernetTap::removeConnection(TcpConnection *conn)
|
|
|
-{
|
|
|
- Mutex::Lock _l(_tcpconns_m);
|
|
|
- for(size_t i=0;i<_TcpConnections.size();++i) {
|
|
|
- if(_TcpConnections[i] == conn){
|
|
|
- _TcpConnections.erase(_TcpConnections.begin() + i);
|
|
|
- delete conn;
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void NetconEthernetTap::closeConnection(PhySocket *sock)
|
|
|
{
|
|
|
+ // Here we assume _tcpconns_m is already locked by caller
|
|
|
+
|
|
|
dwr(MSG_DEBUG,"closeConnection(%x)\n",sock);
|
|
|
if(!sock) {
|
|
|
dwr(MSG_DEBUG," closeConnection(): invalid PhySocket\n");
|
|
@@ -405,16 +396,30 @@ void NetconEthernetTap::closeConnection(PhySocket *sock)
|
|
|
if(!conn)
|
|
|
return;
|
|
|
if(conn->pcb) {
|
|
|
- if(conn->pcb->state == SYN_SENT || conn->pcb->state == CLOSE_WAIT) {
|
|
|
+ dwr(MSG_DEBUG," closeConnection(): PCB->state = %d\n", conn->pcb->state);
|
|
|
+ if(conn->pcb->state == SYN_SENT) {
|
|
|
dwr(MSG_DEBUG," closeConnection(): invalid PCB state for this operation. ignoring.\n");
|
|
|
return;
|
|
|
}
|
|
|
- dwr(MSG_DEBUG," closeConnection(): PCB->state = %d\n", conn->pcb->state);
|
|
|
- if(lwipstack->_tcp_close(conn->pcb) != ERR_OK) {
|
|
|
+ if(lwipstack->_tcp_close(conn->pcb) == ERR_OK) {
|
|
|
+ // Unregister callbacks for this PCB
|
|
|
+ lwipstack->_tcp_arg(conn->pcb, NULL);
|
|
|
+ lwipstack->_tcp_recv(conn->pcb, NULL);
|
|
|
+ lwipstack->_tcp_err(conn->pcb, NULL);
|
|
|
+ lwipstack->_tcp_sent(conn->pcb, NULL);
|
|
|
+ lwipstack->_tcp_poll(conn->pcb, NULL, 1);
|
|
|
+ }
|
|
|
+ else {
|
|
|
dwr(MSG_ERROR," closeConnection(): error while calling tcp_close()\n");
|
|
|
}
|
|
|
}
|
|
|
- removeConnection(conn);
|
|
|
+ for(size_t i=0;i<_TcpConnections.size();++i) {
|
|
|
+ if(_TcpConnections[i] == conn){
|
|
|
+ _TcpConnections.erase(_TcpConnections.begin() + i);
|
|
|
+ delete conn;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
if(!sock)
|
|
|
return;
|
|
|
close(_phy.getDescriptor(sock));
|
|
@@ -422,13 +427,15 @@ void NetconEthernetTap::closeConnection(PhySocket *sock)
|
|
|
}
|
|
|
|
|
|
void NetconEthernetTap::phyOnUnixClose(PhySocket *sock,void **uptr) {
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
closeConnection(sock);
|
|
|
}
|
|
|
|
|
|
void NetconEthernetTap::phyOnUnixWritable(PhySocket *sock,void **uptr)
|
|
|
{
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
+ Mutex::Lock _l2(_rx_buf_m);
|
|
|
TcpConnection *conn = getConnection(sock);
|
|
|
- Mutex::Lock _l(_rx_buf_m);
|
|
|
int len = conn->rxsz;
|
|
|
int n = _phy.streamSend(conn->sock, conn->rxbuf, len);
|
|
|
if(n > 0) {
|
|
@@ -596,6 +603,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
closeConnection(sockdata.first); // close RPC after sending retval, no longer needed
|
|
|
jobmap.erase(CANARY_num);
|
|
|
return;
|
|
@@ -636,6 +644,8 @@ void NetconEthernetTap::unloadRPC(void *data, pid_t &pid, pid_t &tid,
|
|
|
err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err)
|
|
|
{
|
|
|
Larg *l = (Larg*)arg;
|
|
|
+ Mutex::Lock _l(l->tap->_tcpconns_m);
|
|
|
+
|
|
|
TcpConnection *conn = l->conn;
|
|
|
NetconEthernetTap *tap = l->tap;
|
|
|
|
|
@@ -655,15 +665,12 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err)
|
|
|
}
|
|
|
// create and populate new TcpConnection
|
|
|
TcpConnection *newTcpConn = new TcpConnection();
|
|
|
- tap->addConnection(newTcpConn);
|
|
|
+ l->tap->_TcpConnections.push_back(newTcpConn);
|
|
|
newTcpConn->pcb = newPCB;
|
|
|
newTcpConn->sock = tap->_phy.wrapSocket(fds[0], newTcpConn);
|
|
|
|
|
|
if(sock_fd_write(fd, fds[1]) < 0)
|
|
|
return -1;
|
|
|
- else {
|
|
|
- //close(fds[1]); // close other end of socketpair
|
|
|
- }
|
|
|
tap->lwipstack->_tcp_arg(newPCB, new Larg(tap, newTcpConn));
|
|
|
tap->lwipstack->_tcp_recv(newPCB, nc_recved);
|
|
|
tap->lwipstack->_tcp_err(newPCB, nc_err);
|
|
@@ -686,21 +693,20 @@ err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *
|
|
|
int tot = 0;
|
|
|
struct pbuf* q = p;
|
|
|
|
|
|
+ Mutex::Lock _l(l->tap->_tcpconns_m);
|
|
|
+
|
|
|
if(!l->conn) {
|
|
|
dwr(MSG_ERROR," nc_recved(): no connection\n");
|
|
|
return ERR_OK;
|
|
|
}
|
|
|
if(p == NULL) {
|
|
|
- if(l->conn && !l->conn->listening) {
|
|
|
- dwr(MSG_INFO," nc_recved(): closing connection\n");
|
|
|
- if(l->tap->lwipstack->_tcp_close(l->conn->pcb) != ERR_OK)
|
|
|
- dwr(MSG_ERROR," nc_recved(): error while calling tcp_close()\n");
|
|
|
+ if(l->conn->pcb->state == CLOSE_WAIT){
|
|
|
l->tap->closeConnection(l->conn->sock);
|
|
|
return ERR_ABRT;
|
|
|
}
|
|
|
return err;
|
|
|
}
|
|
|
- Mutex::Lock _l(l->tap->_rx_buf_m);
|
|
|
+ Mutex::Lock _l2(l->tap->_rx_buf_m);
|
|
|
// Cycle through pbufs and write them to the RX buffer
|
|
|
// The RX buffer will be emptied via phyOnUnixWritable()
|
|
|
while(p != NULL) {
|
|
@@ -721,10 +727,39 @@ err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *
|
|
|
return ERR_OK;
|
|
|
}
|
|
|
|
|
|
+err_t NetconEthernetTap::nc_sent(void* arg, struct tcp_pcb *PCB, u16_t len)
|
|
|
+{
|
|
|
+ Larg *l = (Larg*)arg;
|
|
|
+ Mutex::Lock _l(l->tap->_tcpconns_m);
|
|
|
+ if(l && l->conn && len) {
|
|
|
+ float max = (float)DEFAULT_BUF_SZ;
|
|
|
+ if(l->conn->txsz < max / 2) {
|
|
|
+ l->tap->_phy.setNotifyReadable(l->conn->sock, true);
|
|
|
+ l->tap->_phy.whack();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
+err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *PCB, err_t err)
|
|
|
+{
|
|
|
+ Larg *l = (Larg*)arg;
|
|
|
+ if(l && l->conn)
|
|
|
+ l->tap->sendReturnValue(l->tap->_phy.getDescriptor(l->conn->rpcSock), ERR_OK);
|
|
|
+ return ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
+err_t NetconEthernetTap::nc_poll(void* arg, struct tcp_pcb *PCB)
|
|
|
+{
|
|
|
+ return ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
void NetconEthernetTap::nc_err(void *arg, err_t err)
|
|
|
{
|
|
|
dwr(MSG_DEBUG,"nc_err() = %d\n", err);
|
|
|
Larg *l = (Larg*)arg;
|
|
|
+ Mutex::Lock _l(l->tap->_tcpconns_m);
|
|
|
+
|
|
|
if(!l->conn)
|
|
|
dwr(MSG_ERROR,"nc_err(): connection is NULL!\n");
|
|
|
int fd = l->tap->_phy.getDescriptor(l->conn->sock);
|
|
@@ -796,37 +831,13 @@ void NetconEthernetTap::nc_err(void *arg, err_t err)
|
|
|
l->tap->closeConnection(l->conn);
|
|
|
}
|
|
|
|
|
|
-err_t NetconEthernetTap::nc_poll(void* arg, struct tcp_pcb *PCB)
|
|
|
-{
|
|
|
- return ERR_OK;
|
|
|
-}
|
|
|
-
|
|
|
-err_t NetconEthernetTap::nc_sent(void* arg, struct tcp_pcb *PCB, u16_t len)
|
|
|
-{
|
|
|
- Larg *l = (Larg*)arg;
|
|
|
- if(l->conn && len) {
|
|
|
- float max = (float)DEFAULT_BUF_SZ;
|
|
|
- if(l->conn->txsz < max / 2) {
|
|
|
- l->tap->_phy.setNotifyReadable(l->conn->sock, true);
|
|
|
- l->tap->_phy.whack();
|
|
|
- }
|
|
|
- }
|
|
|
- return ERR_OK;
|
|
|
-}
|
|
|
-
|
|
|
-err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *PCB, err_t err)
|
|
|
-{
|
|
|
- Larg *l = (Larg*)arg;
|
|
|
- l->tap->sendReturnValue(l->tap->_phy.getDescriptor(l->conn->rpcSock), ERR_OK);
|
|
|
- return ERR_OK;
|
|
|
-}
|
|
|
-
|
|
|
/*------------------------------------------------------------------------------
|
|
|
----------------------------- RPC Handler functions ----------------------------
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
|
|
void NetconEthernetTap::handleGetsockname(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct getsockname_st *getsockname_rpc)
|
|
|
{
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
TcpConnection *conn = getConnection(sock);
|
|
|
char retmsg[sizeof(struct sockaddr_storage)];
|
|
|
memset(&retmsg, 0, sizeof(retmsg));
|
|
@@ -837,6 +848,7 @@ void NetconEthernetTap::handleGetsockname(PhySocket *sock, PhySocket *rpcSock, v
|
|
|
|
|
|
void NetconEthernetTap::handleBind(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct bind_st *bind_rpc)
|
|
|
{
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
struct sockaddr_in *rawAddr = (struct sockaddr_in *) &bind_rpc->addr;
|
|
|
int port = lwipstack->ntohs(rawAddr->sin_port);
|
|
|
ip_addr_t connAddr;
|
|
@@ -878,6 +890,7 @@ void NetconEthernetTap::handleBind(PhySocket *sock, PhySocket *rpcSock, void **u
|
|
|
|
|
|
void NetconEthernetTap::handleListen(PhySocket *sock, PhySocket *rpcSock, void **uptr, struct listen_st *listen_rpc)
|
|
|
{
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
TcpConnection *conn = getConnection(sock);
|
|
|
if(!conn){
|
|
|
dwr(MSG_ERROR," handleListen(): unable to locate TcpConnection.\n");
|
|
@@ -913,13 +926,15 @@ void NetconEthernetTap::handleListen(PhySocket *sock, PhySocket *rpcSock, void *
|
|
|
|
|
|
TcpConnection * NetconEthernetTap::handleSocket(PhySocket *sock, void **uptr, struct socket_st* socket_rpc)
|
|
|
{
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
struct tcp_pcb *newPCB = lwipstack->tcp_new();
|
|
|
if(newPCB != NULL) {
|
|
|
TcpConnection *newConn = new TcpConnection();
|
|
|
*uptr = newConn;
|
|
|
newConn->sock = sock;
|
|
|
newConn->pcb = newPCB;
|
|
|
- return addConnection(newConn);;
|
|
|
+ _TcpConnections.push_back(newConn);
|
|
|
+ return newConn;
|
|
|
}
|
|
|
dwr(MSG_ERROR," handleSocket(): Memory not available for new PCB\n");
|
|
|
sendReturnValue(_phy.getDescriptor(sock), -1, ENOMEM);
|
|
@@ -928,9 +943,10 @@ TcpConnection * NetconEthernetTap::handleSocket(PhySocket *sock, void **uptr, st
|
|
|
|
|
|
void NetconEthernetTap::handleConnect(PhySocket *sock, PhySocket *rpcSock, TcpConnection *conn, struct connect_st* connect_rpc)
|
|
|
{
|
|
|
+ Mutex::Lock _l(_tcpconns_m);
|
|
|
struct sockaddr_in *rawAddr = (struct sockaddr_in *) &connect_rpc->__addr;
|
|
|
int port = lwipstack->ntohs(rawAddr->sin_port);
|
|
|
- ip_addr_t connAddr = convert_ip((struct sockaddr_in *)&connect_rpc->__addr);
|
|
|
+ ip_addr_t connAddr = convert_ip(rawAddr);
|
|
|
|
|
|
if(conn != NULL) {
|
|
|
lwipstack->tcp_sent(conn->pcb, nc_sent);
|