fixed connect/accept behaviour, added to selftest, renamed BSD makefile

This commit is contained in:
Joseph Henry
2017-06-11 20:24:11 -07:00
parent 8ea81f5fbb
commit 3793b23229
10 changed files with 75 additions and 49 deletions

View File

@@ -60,7 +60,7 @@ namespace ZeroTier {
struct sockaddr_storage *peer_addr; // Address of connection call to remote host
// RX/TX buffers
int txsz, rxsz;
int txsz = 0, rxsz = 0;
unsigned char txbuf[ZT_TCP_TX_BUF_SZ];
unsigned char rxbuf[ZT_TCP_RX_BUF_SZ];
@@ -89,6 +89,7 @@ namespace ZeroTier {
}
sdk_fd = fdpair[0];
app_fd = fdpair[1];
if(ZT_SOCK_BEHAVIOR_LINGER) {
struct linger so_linger;
so_linger.l_onoff = true;

View File

@@ -289,7 +289,7 @@ namespace ZeroTier {
}
picostack->pico_Close(conn);
if(!conn->sock) {
DEBUG_EXTRA("invalid PhySocket");
// DEBUG_EXTRA("invalid PhySocket");
return;
}
// Here we assume _tcpconns_m is already locked by caller

View File

@@ -429,10 +429,11 @@ Darwin:
[ ] [ECONNRESET] Remote host reset the connection request.
*/
int zts_connect(ZT_CONNECT_SIG) {
DEBUG_INFO("fd = %d", fd);
// DEBUG_INFO("fd = %d", fd);
int err = 0;
if(fd < 0) {
errno = EBADF;
DEBUG_ERROR("EBADF");
err = -1;
}
if(!zt1Service) {
@@ -460,8 +461,8 @@ int zts_connect(ZT_CONNECT_SIG) {
// TODO: This is a hack, determine a proper way to do this
iaddr.fromString(ipstr + std::string("/88"));
}
DEBUG_INFO("ipstr= %s", ipstr);
DEBUG_INFO("iaddr= %s", iaddr.toString().c_str());
//DEBUG_INFO("ipstr= %s", ipstr);
//DEBUG_INFO("iaddr= %s", iaddr.toString().c_str());
tap = zt1Service->getTap(iaddr);
if(!tap) {
DEBUG_ERROR("no route to host");
@@ -471,7 +472,7 @@ int zts_connect(ZT_CONNECT_SIG) {
else {
// pointer to tap we use in callbacks from the stack
conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn);
DEBUG_INFO("found appropriate SocketTap");
//DEBUG_INFO("found appropriate SocketTap");
// Semantically: tap->stack->connect
err = tap->Connect(conn, fd, addr, addrlen);
if(err == 0) {
@@ -500,12 +501,18 @@ int zts_connect(ZT_CONNECT_SIG) {
// to the multiplexer logic that this connection is complete and a success value can be sent to the
// user application
socklen_t optlen;
socklen_t blocking;
zts_getsockopt(fd, SOL_SOCKET, O_NONBLOCK, &blocking, &optlen);
int f_err, blocking = 1;
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
err = -1;
}
else {
blocking = !(f_err & O_NONBLOCK);
}
// non-blocking
if(err == 0 && !blocking) {
DEBUG_EXTRA("EINPROGRESS, not a real error, assuming non-blocking mode");
errno = EINPROGRESS;
err = -1;
}
@@ -524,6 +531,7 @@ int zts_connect(ZT_CONNECT_SIG) {
{
if(tap->_Connections[i]->state == PICO_ERR_ECONNRESET) {
errno = ECONNRESET;
DEBUG_ERROR("ECONNRESET");
err = -1;
}
if(tap->_Connections[i]->state == ZT_SOCK_STATE_UNHANDLED_CONNECTED) {
@@ -666,7 +674,7 @@ Darwin:
[ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM.
[ ] [EFAULT] The addr parameter is not in a writable part of the
user address space.
[ ] [EWOULDBLOCK] The socket is marked non-blocking and no connections
[--] [EWOULDBLOCK] The socket is marked non-blocking and no connections
are present to be accepted.
[--] [EMFILE] The per-process descriptor table is full.
[ ] [ENFILE] The system file table is full.
@@ -697,19 +705,31 @@ int zts_accept(ZT_ACCEPT_SIG) {
ZeroTier::Connection *conn = p->first;
ZeroTier::SocketTap *tap = p->second;
ZeroTier::Connection *accepted_conn;
// BLOCKING: loop and keep checking until we find a newly accepted connection
if(true) {
int f_err, blocking = 1;
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
err = -1;
}
else {
blocking = !(f_err & O_NONBLOCK);
}
if(!err && !blocking) { // non-blocking
DEBUG_EXTRA("EWOULDBLOCK, not a real error, assuming non-blocking mode");
errno = EWOULDBLOCK;
err = -1;
accepted_conn = tap->Accept(conn);
}
else if (!err && blocking) { // blocking
while(true) {
DEBUG_EXTRA("checking...");
usleep(ZT_ACCEPT_RECHECK_DELAY * 1000);
accepted_conn = tap->Accept(conn);
if(accepted_conn)
break; // accepted fd = err
}
}
// NON-BLOCKING: only check for a new connection once
else
accepted_conn = tap->Accept(conn);
if(accepted_conn) {
ZeroTier::fdmap[accepted_conn->app_fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(accepted_conn, tap);
err = accepted_conn->app_fd;

View File

@@ -143,7 +143,7 @@ namespace ZeroTier {
void picoTCP::pico_cb_tcp_read(ZeroTier::SocketTap *tap, struct pico_socket *s)
{
//DEBUG_INFO();
DEBUG_INFO();
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
if(conn) {
int r;
@@ -227,7 +227,7 @@ namespace ZeroTier {
void picoTCP::pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s)
{
//DEBUG_INFO();
DEBUG_INFO();
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
if(!conn) {
DEBUG_ERROR("invalid connection");
@@ -259,7 +259,7 @@ namespace ZeroTier {
void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s)
{
//DEBUG_INFO();
DEBUG_INFO();
if(!(SocketTap*)((ConnectionPair*)(s->priv)))
return;
SocketTap *tap = (SocketTap*)((ConnectionPair*)(s->priv))->tap;
@@ -312,7 +312,7 @@ namespace ZeroTier {
}
}
if (ev & PICO_SOCK_EV_FIN) {
DEBUG_INFO("PICO_SOCK_EV_FIN (socket closed), picosock=%p, conn=%p", s, conn);
// DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p, conn=%p", s, conn);
conn->closure_ts = std::time(nullptr);
}
if (ev & PICO_SOCK_EV_ERR) {
@@ -488,7 +488,7 @@ namespace ZeroTier {
inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN);
// TODO: This isn't proper
pico_string_to_ipv6("::", pip6.addr);
DEBUG_ATTN("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port));
DEBUG_INFO("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port));
err = pico_socket_bind(conn->picosock, &pip6, (uint16_t *)&(in6->sin6_port));
}
if(err < 0) {
@@ -635,6 +635,7 @@ namespace ZeroTier {
void picoTCP::pico_Write(Connection *conn, void *data, ssize_t len)
{
DEBUG_INFO();
if(conn->picosock->state & PICO_SOCKET_STATE_CLOSED){
DEBUG_ERROR("socket is CLOSED, this write() will fail");
return;
@@ -677,7 +678,7 @@ namespace ZeroTier {
int picoTCP::pico_Close(Connection *conn)
{
//DEBUG_INFO("conn = %p, picosock=%p, fd = %d", conn, conn->picosock, conn->app_fd);
DEBUG_INFO("conn = %p, picosock=%p, fd = %d", conn, conn->picosock, conn->app_fd);
if(!conn || !conn->picosock)
return ZT_ERR_GENERAL_FAILURE;
int err;