Renamed SocketTap to VirtualTap and Connection to VirtualSocket to prevent confusion
This commit is contained in:
@@ -90,7 +90,7 @@ struct zts_ifreq {
|
|||||||
|
|
||||||
#define LWIP_APPLICATION_POLL_FREQ 2
|
#define LWIP_APPLICATION_POLL_FREQ 2
|
||||||
#define LWIP_TCP_TIMER_INTERVAL 50
|
#define LWIP_TCP_TIMER_INTERVAL 50
|
||||||
#define LWIP_STATUS_TMR_INTERVAL 500 // How often we check connection statuses (in ms)
|
#define LWIP_STATUS_TMR_INTERVAL 500 // How often we check VirtualSocket statuses (in ms)
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* Defines */
|
/* Defines */
|
||||||
@@ -155,11 +155,11 @@ struct zts_ifreq {
|
|||||||
#define ZT_SDK_CLTIME 60
|
#define ZT_SDK_CLTIME 60
|
||||||
|
|
||||||
// After closing a pico_socket, other threads might still try to use the
|
// After closing a pico_socket, other threads might still try to use the
|
||||||
// Connection object for remaining data I/O, as a safety measure we will wait to
|
// VirtualSocket object for remaining data I/O, as a safety measure we will wait to
|
||||||
// delete this Connection object until the socket has been closed for some arbitrary
|
// delete this VirtualSocket object until the socket has been closed for some arbitrary
|
||||||
// amount of time and it is safe to assume any clients interacting with this
|
// amount of time and it is safe to assume any clients interacting with this
|
||||||
// socket have read some sort of error code from the API.
|
// socket have read some sort of error code from the API.
|
||||||
#define ZT_CONNECTION_DELETE_WAIT_TIME 30 // s
|
#define ZT_VirtualSocket_DELETE_WAIT_TIME 30 // s
|
||||||
|
|
||||||
// Interval for performing cleanup tasks on Tap/Stack objects
|
// Interval for performing cleanup tasks on Tap/Stack objects
|
||||||
#define ZT_HOUSEKEEPING_INTERVAL 10 // s
|
#define ZT_HOUSEKEEPING_INTERVAL 10 // s
|
||||||
@@ -351,30 +351,30 @@ int zts_connect(ZT_CONNECT_SIG);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds a socket to a specific address
|
* Binds a socket to a specific address
|
||||||
* - To accept connections on a specific ZeroTier network you must
|
* - To accept VirtualSockets on a specific ZeroTier network you must
|
||||||
* use this bind call with an address which is associated with that network
|
* use this bind call with an address which is associated with that network
|
||||||
*
|
*
|
||||||
* For instance, given the following networks:
|
* For instance, given the following networks:
|
||||||
* - nwid = 97afaf1963cc6a90 (10.9.0.0/24)
|
* - nwid = 97afaf1963cc6a90 (10.9.0.0/24)
|
||||||
* - nwid = 23bfae5663c8b188 (192.168.0.0/24)
|
* - nwid = 23bfae5663c8b188 (192.168.0.0/24)
|
||||||
*
|
*
|
||||||
* In order to accept a connection on 97afaf1963cc6a90, you
|
* In order to accept a VirtualSocket on 97afaf1963cc6a90, you
|
||||||
* should bind to 10.9.0.0
|
* should bind to 10.9.0.0
|
||||||
*/
|
*/
|
||||||
int zts_bind(ZT_BIND_SIG);
|
int zts_bind(ZT_BIND_SIG);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for incoming connections
|
* Listen for incoming VirtualSockets
|
||||||
*/
|
*/
|
||||||
int zts_listen(ZT_LISTEN_SIG);
|
int zts_listen(ZT_LISTEN_SIG);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept a connection
|
* Accept a VirtualSocket
|
||||||
*/
|
*/
|
||||||
int zts_accept(ZT_ACCEPT_SIG);
|
int zts_accept(ZT_ACCEPT_SIG);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept a connection
|
* Accept a VirtualSocket
|
||||||
*/
|
*/
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
int zts_accept4(ZT_ACCEPT4_SIG);
|
int zts_accept4(ZT_ACCEPT4_SIG);
|
||||||
@@ -485,7 +485,7 @@ namespace ZeroTier
|
|||||||
class lwIP;
|
class lwIP;
|
||||||
extern ZeroTier::lwIP *lwipstack;
|
extern ZeroTier::lwIP *lwipstack;
|
||||||
|
|
||||||
class SocketTap;
|
class VirtualTap;
|
||||||
struct InetAddress;
|
struct InetAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,10 +521,10 @@ int pico_ntimers();
|
|||||||
/* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */
|
/* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
ZeroTier::SocketTap *getTapByNWID(uint64_t nwid);
|
ZeroTier::VirtualTap *getTapByNWID(uint64_t nwid);
|
||||||
ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr);
|
ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress &addr);
|
||||||
ZeroTier::SocketTap *getTapByName(char *ifname);
|
ZeroTier::VirtualTap *getTapByName(char *ifname);
|
||||||
ZeroTier::SocketTap *getTapByIndex(int index);
|
ZeroTier::VirtualTap *getTapByIndex(int index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Destroys all virtual tap devices
|
* Destroys all virtual tap devices
|
||||||
|
|||||||
@@ -136,11 +136,11 @@ CXXFLAGS+=-DSDK_IPV6
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
STACK_DRIVER_FILES:=src/picoTCP.cpp
|
STACK_DRIVER_FILES:=src/picoTCP.cpp
|
||||||
TAP_FILES:=src/SocketTap.cpp \
|
TAP_FILES:=src/VirtualTap.cpp \
|
||||||
src/libzt.cpp \
|
src/libzt.cpp \
|
||||||
src/Utilities.cpp
|
src/Utilities.cpp
|
||||||
|
|
||||||
SDK_OBJS+= SocketTap.o \
|
SDK_OBJS+= VirtualTap.o \
|
||||||
picoTCP.o \
|
picoTCP.o \
|
||||||
libzt.o \
|
libzt.o \
|
||||||
Utilities.o
|
Utilities.o
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ STACK_FLAGS+=LIBZT_IPV4=1
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LIBZT_FILES:=src/SocketTap.cpp src/libzt.cpp src/Utilities.cpp
|
LIBZT_FILES:=src/VirtualTap.cpp src/libzt.cpp src/Utilities.cpp
|
||||||
|
|
||||||
ifeq ($(STACK_PICO),1)
|
ifeq ($(STACK_PICO),1)
|
||||||
CXXFLAGS+=-DSTACK_PICO
|
CXXFLAGS+=-DSTACK_PICO
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ STACK_FLAGS+=LIBZT_IPV4=1
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LIBZT_FILES:=src/SocketTap.cpp src/libzt.cpp src/Utilities.cpp
|
LIBZT_FILES:=src/VirtualTap.cpp src/libzt.cpp src/Utilities.cpp
|
||||||
|
|
||||||
ifeq ($(STACK_PICO),1)
|
ifeq ($(STACK_PICO),1)
|
||||||
CXXFLAGS+=-DSTACK_PICO
|
CXXFLAGS+=-DSTACK_PICO
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
* of your own application.
|
* of your own application.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// General connection object used by SocketTap and network stack drivers
|
// General connection object used by VirtualTap and network stack drivers
|
||||||
|
|
||||||
#ifndef ZT_CONNECTION_HPP
|
#ifndef ZT_CONNECTION_HPP
|
||||||
#define ZT_CONNECTION_HPP
|
#define ZT_CONNECTION_HPP
|
||||||
@@ -39,19 +39,24 @@
|
|||||||
#include "Phy.hpp"
|
#include "Phy.hpp"
|
||||||
|
|
||||||
#include "libzt.h"
|
#include "libzt.h"
|
||||||
#include "SocketTap.hpp"
|
#include "VirtualTap.hpp"
|
||||||
#include "RingBuffer.hpp"
|
#include "RingBuffer.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class SocketTap;
|
class VirtualTap;
|
||||||
|
|
||||||
struct Connection
|
/*
|
||||||
|
* Something analogous to a socket. This is a common object used by the
|
||||||
|
* libzt API, VirtualTap, and the userspace network stack driver implementations.
|
||||||
|
* In some situations the word 'Connection' would capture the meaning and
|
||||||
|
* function of this object, however I'd like to discourage this since this
|
||||||
|
* object also handles non-connection-based traffic as well.
|
||||||
|
*/
|
||||||
|
struct VirtualSocket
|
||||||
{
|
{
|
||||||
int tot = 0;
|
|
||||||
RingBuffer<unsigned char> *TXbuf;
|
RingBuffer<unsigned char> *TXbuf;
|
||||||
RingBuffer<unsigned char> *RXbuf;
|
RingBuffer<unsigned char> *RXbuf;
|
||||||
|
|
||||||
Mutex _tx_m, _rx_m;
|
Mutex _tx_m, _rx_m;
|
||||||
|
|
||||||
PhySocket *sock;
|
PhySocket *sock;
|
||||||
@@ -62,6 +67,7 @@ namespace ZeroTier {
|
|||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
void *pcb;
|
void *pcb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: For getsockname, etc
|
// TODO: For getsockname, etc
|
||||||
struct sockaddr_storage *local_addr; // Address we've bound to locally
|
struct sockaddr_storage *local_addr; // Address we've bound to locally
|
||||||
struct sockaddr_storage *peer_addr; // Address of connection call to remote host
|
struct sockaddr_storage *peer_addr; // Address of connection call to remote host
|
||||||
@@ -71,14 +77,14 @@ namespace ZeroTier {
|
|||||||
int app_fd; // used by app for I/O
|
int app_fd; // used by app for I/O
|
||||||
int sdk_fd; // used by lib for I/O
|
int sdk_fd; // used by lib for I/O
|
||||||
|
|
||||||
std::queue<Connection*> _AcceptedConnections;
|
std::queue<VirtualSocket*> _AcceptedConnections;
|
||||||
SocketTap *tap;
|
VirtualTap *tap;
|
||||||
int state; // See libzt.h for (ZT_SOCK_STATE_*)
|
int state; // See libzt.h for (ZT_SOCK_STATE_*)
|
||||||
|
|
||||||
// timestamp for closure event
|
// timestamp for closure event
|
||||||
std::time_t closure_ts;
|
std::time_t closure_ts;
|
||||||
|
|
||||||
Connection() {
|
VirtualSocket() {
|
||||||
TXbuf = new RingBuffer<unsigned char>(ZT_TCP_TX_BUF_SZ);
|
TXbuf = new RingBuffer<unsigned char>(ZT_TCP_TX_BUF_SZ);
|
||||||
RXbuf = new RingBuffer<unsigned char>(ZT_TCP_RX_BUF_SZ);
|
RXbuf = new RingBuffer<unsigned char>(ZT_TCP_RX_BUF_SZ);
|
||||||
|
|
||||||
@@ -93,17 +99,17 @@ namespace ZeroTier {
|
|||||||
sdk_fd = fdpair[0];
|
sdk_fd = fdpair[0];
|
||||||
app_fd = fdpair[1];
|
app_fd = fdpair[1];
|
||||||
}
|
}
|
||||||
~Connection() { }
|
~VirtualSocket() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A helper object for passing SocketTap(s) and Connection(s) through the stack
|
* A helper object for passing VirtualTap(s) and VirtualSocket(s) through the stack
|
||||||
*/
|
*/
|
||||||
struct ConnectionPair
|
struct VirtualBindingPair
|
||||||
{
|
{
|
||||||
SocketTap *tap;
|
VirtualTap *tap;
|
||||||
Connection *conn;
|
VirtualSocket *vs;
|
||||||
ConnectionPair(SocketTap *_tap, Connection *conn) : tap(_tap), conn(conn) {}
|
VirtualBindingPair(VirtualTap *_tap, VirtualSocket *_vs) : tap(_tap), vs(_vs) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "SocketTap.hpp"
|
#include "VirtualTap.hpp"
|
||||||
#include "libzt.h"
|
#include "libzt.h"
|
||||||
|
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
@@ -58,23 +58,21 @@
|
|||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "Phy.hpp"
|
#include "Phy.hpp"
|
||||||
|
|
||||||
class SocketTap;
|
class VirtualTap;
|
||||||
|
|
||||||
|
|
||||||
extern std::vector<void*> vtaps;
|
extern std::vector<void*> vtaps;
|
||||||
//extern ZeroTier::OneService *zt1Service;
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
int SocketTap::devno = 0;
|
int VirtualTap::devno = 0;
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* SocketTap Service */
|
/* VirtualTap Service */
|
||||||
/* - For each joined network a SocketTap will be created to administer I/O */
|
/* - For each joined network a VirtualTap will be created to administer I/O */
|
||||||
/* calls to the stack and the ZT virtual wire */
|
/* calls to the stack and the ZT virtual wire */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
SocketTap::SocketTap(
|
VirtualTap::VirtualTap(
|
||||||
const char *homePath,
|
const char *homePath,
|
||||||
const MAC &mac,
|
const MAC &mac,
|
||||||
unsigned int mtu,
|
unsigned int mtu,
|
||||||
@@ -107,26 +105,26 @@ namespace ZeroTier {
|
|||||||
_thread = Thread::start(this);
|
_thread = Thread::start(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketTap::~SocketTap()
|
VirtualTap::~VirtualTap()
|
||||||
{
|
{
|
||||||
_run = false;
|
_run = false;
|
||||||
_phy.whack();
|
_phy.whack();
|
||||||
Thread::join(_thread);
|
Thread::join(_thread);
|
||||||
_phy.close(_unixListenSocket,false);
|
_phy.close(_unixListenSocket,false);
|
||||||
for(int i=0; i<_Connections.size(); i++) delete _Connections[i];
|
for(int i=0; i<_VirtualSockets.size(); i++) delete _VirtualSockets[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::setEnabled(bool en)
|
void VirtualTap::setEnabled(bool en)
|
||||||
{
|
{
|
||||||
_enabled = en;
|
_enabled = en;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SocketTap::enabled() const
|
bool VirtualTap::enabled() const
|
||||||
{
|
{
|
||||||
return _enabled;
|
return _enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SocketTap::registerIpWithStack(const InetAddress &ip)
|
bool VirtualTap::registerIpWithStack(const InetAddress &ip)
|
||||||
{
|
{
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack){
|
if(picostack){
|
||||||
@@ -143,7 +141,7 @@ namespace ZeroTier {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SocketTap::addIp(const InetAddress &ip)
|
bool VirtualTap::addIp(const InetAddress &ip)
|
||||||
{
|
{
|
||||||
#if defined(NO_STACK)
|
#if defined(NO_STACK)
|
||||||
char ipbuf[64];
|
char ipbuf[64];
|
||||||
@@ -163,7 +161,7 @@ namespace ZeroTier {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SocketTap::removeIp(const InetAddress &ip)
|
bool VirtualTap::removeIp(const InetAddress &ip)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_ips_m);
|
Mutex::Lock _l(_ips_m);
|
||||||
std::vector<InetAddress>::iterator i(std::find(_ips.begin(),_ips.end(),ip));
|
std::vector<InetAddress>::iterator i(std::find(_ips.begin(),_ips.end(),ip));
|
||||||
@@ -179,13 +177,13 @@ namespace ZeroTier {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<InetAddress> SocketTap::ips() const
|
std::vector<InetAddress> VirtualTap::ips() const
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_ips_m);
|
Mutex::Lock _l(_ips_m);
|
||||||
return _ips;
|
return _ips;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::put(const MAC &from,const MAC &to,unsigned int etherType,
|
void VirtualTap::put(const MAC &from,const MAC &to,unsigned int etherType,
|
||||||
const void *data,unsigned int len)
|
const void *data,unsigned int len)
|
||||||
{
|
{
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
@@ -198,18 +196,18 @@ namespace ZeroTier {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SocketTap::deviceName() const
|
std::string VirtualTap::deviceName() const
|
||||||
{
|
{
|
||||||
return _dev;
|
return _dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::setFriendlyName(const char *friendlyName)
|
void VirtualTap::setFriendlyName(const char *friendlyName)
|
||||||
{
|
{
|
||||||
DEBUG_INFO("%s", friendlyName);
|
DEBUG_INFO("%s", friendlyName);
|
||||||
// Someday
|
// Someday
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
void VirtualTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
||||||
std::vector<MulticastGroup> &removed)
|
std::vector<MulticastGroup> &removed)
|
||||||
{
|
{
|
||||||
std::vector<MulticastGroup> newGroups;
|
std::vector<MulticastGroup> newGroups;
|
||||||
@@ -233,14 +231,14 @@ namespace ZeroTier {
|
|||||||
_multicastGroups.swap(newGroups);
|
_multicastGroups.swap(newGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::setMtu(unsigned int mtu)
|
void VirtualTap::setMtu(unsigned int mtu)
|
||||||
{
|
{
|
||||||
if (_mtu != mtu) {
|
if (_mtu != mtu) {
|
||||||
_mtu = mtu;
|
_mtu = mtu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::threadMain()
|
void VirtualTap::threadMain()
|
||||||
throw()
|
throw()
|
||||||
{
|
{
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
@@ -253,35 +251,35 @@ namespace ZeroTier {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::phyOnUnixClose(PhySocket *sock,void **uptr)
|
void VirtualTap::phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||||
{
|
{
|
||||||
if(sock) {
|
if(sock) {
|
||||||
Connection *conn = (Connection*)uptr;
|
VirtualSocket *vs = (VirtualSocket*)uptr;
|
||||||
if(conn)
|
if(vs)
|
||||||
Close(conn);
|
Close(vs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len)
|
void VirtualTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len)
|
||||||
{
|
{
|
||||||
DEBUG_ATTN("sock->fd=%d", _phy.getDescriptor(sock));
|
DEBUG_ATTN("sock->fd=%d", _phy.getDescriptor(sock));
|
||||||
Connection *conn = (Connection*)*uptr;
|
VirtualSocket *vs = (VirtualSocket*)*uptr;
|
||||||
if(!conn)
|
if(!vs)
|
||||||
return;
|
return;
|
||||||
if(len){
|
if(len){
|
||||||
Write(conn, data, len);
|
Write(vs, data, len);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::phyOnUnixWritable(PhySocket *sock, void **uptr, bool stack_invoked)
|
void VirtualTap::phyOnUnixWritable(PhySocket *sock, void **uptr, bool stack_invoked)
|
||||||
{
|
{
|
||||||
if(sock)
|
if(sock)
|
||||||
Read(sock,uptr,stack_invoked);
|
Read(sock,uptr,stack_invoked);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a route to the virtual tap
|
// Adds a route to the virtual tap
|
||||||
bool SocketTap::routeAdd(const InetAddress &addr, const InetAddress &nm, const InetAddress &gw)
|
bool VirtualTap::routeAdd(const InetAddress &addr, const InetAddress &nm, const InetAddress &gw)
|
||||||
{
|
{
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack)
|
if(picostack)
|
||||||
@@ -294,7 +292,7 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deletes a route from the virtual tap
|
// Deletes a route from the virtual tap
|
||||||
bool SocketTap::routeDelete(const InetAddress &addr, const InetAddress &nm)
|
bool VirtualTap::routeDelete(const InetAddress &addr, const InetAddress &nm)
|
||||||
{
|
{
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack)
|
if(picostack)
|
||||||
@@ -311,94 +309,94 @@ namespace ZeroTier {
|
|||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
// Connect
|
// Connect
|
||||||
int SocketTap::Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen) {
|
int VirtualTap::Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
#if defined(NO_STACK)
|
#if defined(NO_STACK)
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack)
|
if(picostack)
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
return picostack->pico_Connect(conn, addr, addrlen);
|
return picostack->pico_Connect(vs, addr, addrlen);
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
if(lwipstack)
|
if(lwipstack)
|
||||||
return lwipstack->lwip_Connect(conn, addr, addrlen);
|
return lwipstack->lwip_Connect(vs, addr, addrlen);
|
||||||
#endif
|
#endif
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind VirtualSocket to a network stack's interface
|
// Bind VirtualSocket to a network stack's interface
|
||||||
int SocketTap::Bind(Connection *conn, const struct sockaddr *addr, socklen_t addrlen) {
|
int VirtualTap::Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) {
|
||||||
#if defined(NO_STACK)
|
#if defined(NO_STACK)
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack)
|
if(picostack)
|
||||||
return picostack->pico_Bind(conn, addr, addrlen);
|
return picostack->pico_Bind(vs, addr, addrlen);
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
if(lwipstack)
|
if(lwipstack)
|
||||||
return lwipstack->lwip_Bind(this, conn, addr, addrlen);
|
return lwipstack->lwip_Bind(this, vs, addr, addrlen);
|
||||||
#endif
|
#endif
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen for an incoming connection
|
// Listen for an incoming VirtualSocket
|
||||||
int SocketTap::Listen(Connection *conn, int backlog) {
|
int VirtualTap::Listen(VirtualSocket *vs, int backlog) {
|
||||||
#if defined(NO_STACK)
|
#if defined(NO_STACK)
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack)
|
if(picostack)
|
||||||
return picostack->pico_Listen(conn, backlog);
|
return picostack->pico_Listen(vs, backlog);
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
if(lwipstack)
|
if(lwipstack)
|
||||||
return lwipstack->lwip_Listen(conn, backlog);
|
return lwipstack->lwip_Listen(vs, backlog);
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
#endif
|
#endif
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept a connection
|
// Accept a VirtualSocket
|
||||||
Connection* SocketTap::Accept(Connection *conn) {
|
VirtualSocket* VirtualTap::Accept(VirtualSocket *vs) {
|
||||||
#if defined(NO_STACK)
|
#if defined(NO_STACK)
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack)
|
if(picostack)
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
return picostack->pico_Accept(conn);
|
return picostack->pico_Accept(vs);
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
if(lwipstack)
|
if(lwipstack)
|
||||||
return lwipstack->lwip_Accept(conn);
|
return lwipstack->lwip_Accept(vs);
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read from stack/buffers into the app's socket
|
// Read from stack/buffers into the app's socket
|
||||||
int SocketTap::Read(PhySocket *sock,void **uptr,bool stack_invoked) {
|
int VirtualTap::Read(PhySocket *sock,void **uptr,bool stack_invoked) {
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack)
|
if(picostack)
|
||||||
return picostack->pico_Read(this, sock, (Connection*)uptr, stack_invoked);
|
return picostack->pico_Read(this, sock, (VirtualSocket*)uptr, stack_invoked);
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
if(lwipstack)
|
if(lwipstack)
|
||||||
return lwipstack->lwip_Read((Connection*)*(_phy.getuptr(sock)), stack_invoked);
|
return lwipstack->lwip_Read((VirtualSocket*)*(_phy.getuptr(sock)), stack_invoked);
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write data from app socket to the virtual wire, either raw over VL2, or via network stack
|
// Write data from app socket to the virtual wire, either raw over VL2, or via network stack
|
||||||
int SocketTap::Write(Connection *conn, void *data, ssize_t len) {
|
int VirtualTap::Write(VirtualSocket *vs, void *data, ssize_t len) {
|
||||||
// VL2, SOCK_RAW, no network stack
|
// VL2, SOCK_RAW, no network stack
|
||||||
if(conn->socket_type == SOCK_RAW) {
|
if(vs->socket_type == SOCK_RAW) {
|
||||||
struct ether_header *eh = (struct ether_header *) data;
|
struct ether_header *eh = (struct ether_header *) data;
|
||||||
MAC src_mac;
|
MAC src_mac;
|
||||||
MAC dest_mac;
|
MAC dest_mac;
|
||||||
@@ -409,49 +407,49 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack)
|
if(picostack)
|
||||||
return picostack->pico_Write(conn, data, len);
|
return picostack->pico_Write(vs, data, len);
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
if(lwipstack)
|
if(lwipstack)
|
||||||
return lwipstack->lwip_Write(conn, data, len);
|
return lwipstack->lwip_Write(vs, data, len);
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send data to a specified host
|
// Send data to a specified host
|
||||||
int SocketTap::SendTo(Connection *conn, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen)
|
int VirtualTap::SendTo(VirtualSocket *vs, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
// TODO: flags
|
// TODO: flags
|
||||||
int err = 0;
|
int err = 0;
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(picostack) {
|
if(picostack) {
|
||||||
err = picostack->pico_Connect(conn, addr, addrlen); // implicit
|
err = picostack->pico_Connect(vs, addr, addrlen); // implicit
|
||||||
err = picostack->pico_Write(conn, (void*)buf, len);
|
err = picostack->pico_Write(vs, (void*)buf, len);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
if(lwipstack)
|
if(lwipstack)
|
||||||
err = lwipstack->lwip_Connect(conn, addr, addrlen); // implicit
|
err = lwipstack->lwip_Connect(vs, addr, addrlen); // implicit
|
||||||
err = lwipstack->lwip_Write(conn, (void*)buf, len);
|
err = lwipstack->lwip_Write(vs, (void*)buf, len);
|
||||||
#endif
|
#endif
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SocketTap::Close(Connection *conn) {
|
int VirtualTap::Close(VirtualSocket *vs) {
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("invalid connection");
|
DEBUG_ERROR("invalid VirtualSocket");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
picostack->pico_Close(conn);
|
picostack->pico_Close(vs);
|
||||||
if(!conn->sock) {
|
if(!vs->sock) {
|
||||||
// DEBUG_EXTRA("invalid PhySocket");
|
// DEBUG_EXTRA("invalid PhySocket");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Here we assume _tcpconns_m is already locked by caller
|
// Here we assume _tcpconns_m is already locked by caller
|
||||||
// FIXME: is this assumption still valid
|
// FIXME: is this assumption still valid
|
||||||
if(conn->state==ZT_SOCK_STATE_LISTENING)
|
if(vs->state==ZT_SOCK_STATE_LISTENING)
|
||||||
{
|
{
|
||||||
// since we never wrapped this socket
|
// since we never wrapped this socket
|
||||||
DEBUG_INFO("in LISTENING state, no need to close in PhyIO");
|
DEBUG_INFO("in LISTENING state, no need to close in PhyIO");
|
||||||
@@ -459,14 +457,14 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(conn->sock)
|
if(vs->sock)
|
||||||
_phy.close(conn->sock, false);
|
_phy.close(vs->sock, false);
|
||||||
}
|
}
|
||||||
close(_phy.getDescriptor(conn->sock));
|
close(_phy.getDescriptor(vs->sock));
|
||||||
for(size_t i=0;i<_Connections.size();++i) {
|
for(size_t i=0;i<_VirtualSockets.size();++i) {
|
||||||
if(_Connections[i] == conn){
|
if(_VirtualSockets[i] == vs){
|
||||||
// FIXME: double free issue exists here (potentially)
|
// FIXME: double free issue exists here (potentially)
|
||||||
// _Connections.erase(_Connections.begin() + i);
|
// _VirtualSockets.erase(_VirtualSockets.begin() + i);
|
||||||
//delete conn;
|
//delete conn;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -474,12 +472,12 @@ namespace ZeroTier {
|
|||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
if(lwipstack)
|
if(lwipstack)
|
||||||
lwipstack->lwip_Close(conn);
|
lwipstack->lwip_Close(vs);
|
||||||
#endif
|
#endif
|
||||||
return 0; // TODO
|
return 0; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
void SocketTap::Housekeeping()
|
void VirtualTap::Housekeeping()
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(_tcpconns_m);
|
Mutex::Lock _l(_tcpconns_m);
|
||||||
std::time_t current_ts = std::time(nullptr);
|
std::time_t current_ts = std::time(nullptr);
|
||||||
@@ -537,7 +535,7 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Clean up Connection objects
|
// TODO: Clean up VirtualSocket objects
|
||||||
|
|
||||||
last_housekeeping_ts = std::time(nullptr);
|
last_housekeeping_ts = std::time(nullptr);
|
||||||
}
|
}
|
||||||
@@ -547,14 +545,14 @@ namespace ZeroTier {
|
|||||||
/* Not used in this implementation */
|
/* Not used in this implementation */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
void SocketTap::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address,
|
void VirtualTap::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address,
|
||||||
const struct sockaddr *from,void *data,unsigned long len) {}
|
const struct sockaddr *from,void *data,unsigned long len) {}
|
||||||
void SocketTap::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) {}
|
void VirtualTap::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) {}
|
||||||
void SocketTap::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,
|
void VirtualTap::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,
|
||||||
const struct sockaddr *from) {}
|
const struct sockaddr *from) {}
|
||||||
void SocketTap::phyOnTcpClose(PhySocket *sock,void **uptr) {}
|
void VirtualTap::phyOnTcpClose(PhySocket *sock,void **uptr) {}
|
||||||
void SocketTap::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
void VirtualTap::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
||||||
void SocketTap::phyOnTcpWritable(PhySocket *sock,void **uptr) {}
|
void VirtualTap::phyOnTcpWritable(PhySocket *sock,void **uptr) {}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
* of your own application.
|
* of your own application.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZT_SOCKETTAP_HPP
|
#ifndef ZT_VIRTUALTAP_HPP
|
||||||
#define ZT_SOCKETTAP_HPP
|
#define ZT_VIRTUALTAP_HPP
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
#include "Phy.hpp"
|
#include "Phy.hpp"
|
||||||
|
|
||||||
#include "libzt.h"
|
#include "libzt.h"
|
||||||
#include "Connection.hpp"
|
#include "VirtualSocket.hpp"
|
||||||
|
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
#include "picoTCP.hpp"
|
#include "picoTCP.hpp"
|
||||||
@@ -66,12 +66,12 @@ namespace ZeroTier {
|
|||||||
/*
|
/*
|
||||||
* Socket Tap -- emulates an Ethernet tap device
|
* Socket Tap -- emulates an Ethernet tap device
|
||||||
*/
|
*/
|
||||||
class SocketTap
|
class VirtualTap
|
||||||
{
|
{
|
||||||
friend class Phy<SocketTap *>;
|
friend class Phy<VirtualTap *>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SocketTap(
|
VirtualTap(
|
||||||
const char *homePath,
|
const char *homePath,
|
||||||
const MAC &mac,
|
const MAC &mac,
|
||||||
unsigned int mtu,
|
unsigned int mtu,
|
||||||
@@ -81,7 +81,7 @@ namespace ZeroTier {
|
|||||||
void (*handler)(void *, void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
void (*handler)(void *, void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int),
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
~SocketTap();
|
~VirtualTap();
|
||||||
|
|
||||||
void setEnabled(bool en);
|
void setEnabled(bool en);
|
||||||
bool enabled() const;
|
bool enabled() const;
|
||||||
@@ -92,13 +92,13 @@ namespace ZeroTier {
|
|||||||
bool registerIpWithStack(const InetAddress &ip);
|
bool registerIpWithStack(const InetAddress &ip);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds an address to the userspace stack interface associated with this SocketTap
|
* Adds an address to the userspace stack interface associated with this VirtualTap
|
||||||
* - Starts SocketTap main thread ONLY if successful
|
* - Starts VirtualTap main thread ONLY if successful
|
||||||
*/
|
*/
|
||||||
bool addIp(const InetAddress &ip);
|
bool addIp(const InetAddress &ip);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Removes an address from the userspace stack interface associated with this SocketTap
|
* Removes an address from the userspace stack interface associated with this VirtualTap
|
||||||
*/
|
*/
|
||||||
bool removeIp(const InetAddress &ip);
|
bool removeIp(const InetAddress &ip);
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ namespace ZeroTier {
|
|||||||
const void *, unsigned int);
|
const void *, unsigned int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signals us to close the TcpConnection associated with this PhySocket
|
* Signals us to close the TcpVirtualSocket associated with this PhySocket
|
||||||
*/
|
*/
|
||||||
void phyOnUnixClose(PhySocket *sock, void **uptr);
|
void phyOnUnixClose(PhySocket *sock, void **uptr);
|
||||||
|
|
||||||
@@ -210,9 +210,9 @@ namespace ZeroTier {
|
|||||||
unsigned int _mtu;
|
unsigned int _mtu;
|
||||||
uint64_t _nwid;
|
uint64_t _nwid;
|
||||||
PhySocket *_unixListenSocket;
|
PhySocket *_unixListenSocket;
|
||||||
Phy<SocketTap *> _phy;
|
Phy<VirtualTap *> _phy;
|
||||||
|
|
||||||
std::vector<Connection*> _Connections;
|
std::vector<VirtualSocket*> _VirtualSockets;
|
||||||
|
|
||||||
Thread _thread;
|
Thread _thread;
|
||||||
std::string _dev; // path to Unix domain socket
|
std::string _dev; // path to Unix domain socket
|
||||||
@@ -233,24 +233,24 @@ namespace ZeroTier {
|
|||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connect to a remote host via the userspace stack interface associated with this SocketTap
|
* Connect to a remote host via the userspace stack interface associated with this VirtualTap
|
||||||
*/
|
*/
|
||||||
int Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
|
int Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bind to the userspace stack interface associated with this SocketTap
|
* Bind to the userspace stack interface associated with this VirtualTap
|
||||||
*/
|
*/
|
||||||
int Bind(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
|
int Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Listen for a Connection
|
* Listen for a VirtualSocket
|
||||||
*/
|
*/
|
||||||
int Listen(Connection *conn, int backlog);
|
int Listen(VirtualSocket *vs, int backlog);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accepts an incoming Connection
|
* Accepts an incoming VirtualSocket
|
||||||
*/
|
*/
|
||||||
Connection* Accept(Connection *conn);
|
VirtualSocket* Accept(VirtualSocket *vs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move data from RX buffer to application's "socket"
|
* Move data from RX buffer to application's "socket"
|
||||||
@@ -260,20 +260,20 @@ namespace ZeroTier {
|
|||||||
/*
|
/*
|
||||||
* Move data from application's "socket" into network stack
|
* Move data from application's "socket" into network stack
|
||||||
*/
|
*/
|
||||||
int Write(Connection *conn, void *data, ssize_t len);
|
int Write(VirtualSocket *vs, void *data, ssize_t len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send data to specified host
|
* Send data to specified host
|
||||||
*/
|
*/
|
||||||
int SendTo(Connection *conn, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
|
int SendTo(VirtualSocket *vs, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Closes a Connection
|
* Closes a VirtualSocket
|
||||||
*/
|
*/
|
||||||
int Close(Connection *conn);
|
int Close(VirtualSocket *vs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disposes of previously-closed Connections
|
* Disposes of previously-closed VirtualSockets
|
||||||
*/
|
*/
|
||||||
void Housekeeping();
|
void Housekeeping();
|
||||||
|
|
||||||
336
src/libzt.cpp
336
src/libzt.cpp
@@ -67,7 +67,7 @@ for applications to use. See also: include/libzt.h */
|
|||||||
#include "InetAddress.hpp"
|
#include "InetAddress.hpp"
|
||||||
#include "ZeroTierOne.h"
|
#include "ZeroTierOne.h"
|
||||||
|
|
||||||
#include "SocketTap.hpp"
|
#include "VirtualTap.hpp"
|
||||||
#include "libzt.h"
|
#include "libzt.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -89,14 +89,14 @@ namespace ZeroTier {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "sockets" that have been created but not bound to a SocketTap interface yet
|
* "sockets" that have been created but not bound to a VirtualTap interface yet
|
||||||
*/
|
*/
|
||||||
std::map<int, Connection*> unmap;
|
std::map<int, VirtualSocket*> unmap;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For fast lookup of Connections and SocketTaps via given file descriptor
|
* For fast lookup of VirtualSockets and VirtualTaps via given file descriptor
|
||||||
*/
|
*/
|
||||||
std::map<int, std::pair<Connection*,SocketTap*>*> fdmap;
|
std::map<int, std::pair<VirtualSocket*,VirtualTap*>*> fdmap;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Virtual tap interfaces, one per virtual network
|
* Virtual tap interfaces, one per virtual network
|
||||||
@@ -105,7 +105,7 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
ZeroTier::Mutex _vtaps_lock;
|
ZeroTier::Mutex _vtaps_lock;
|
||||||
ZeroTier::Mutex _multiplexer_lock;
|
ZeroTier::Mutex _multiplexer_lock;
|
||||||
ZeroTier::Mutex _accepted_connection_lock;
|
ZeroTier::Mutex _accepted_VirtualSocket_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@@ -165,7 +165,7 @@ void zts_join(const char * nwid) {
|
|||||||
// provide ZTO service reference to virtual taps
|
// provide ZTO service reference to virtual taps
|
||||||
// TODO: This might prove to be unreliable, but it works for now
|
// TODO: This might prove to be unreliable, but it works for now
|
||||||
for(int i=0;i<ZeroTier::vtaps.size(); i++) {
|
for(int i=0;i<ZeroTier::vtaps.size(); i++) {
|
||||||
ZeroTier::SocketTap *s = (ZeroTier::SocketTap*)ZeroTier::vtaps[i];
|
ZeroTier::VirtualTap *s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||||
s->zt1ServiceRef=(void*)ZeroTier::zt1Service;
|
s->zt1ServiceRef=(void*)ZeroTier::zt1Service;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,7 +263,7 @@ void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen)
|
|||||||
{
|
{
|
||||||
if(ZeroTier::zt1Service) {
|
if(ZeroTier::zt1Service) {
|
||||||
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
||||||
ZeroTier::SocketTap *tap = getTapByNWID(nwid_int);
|
ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int);
|
||||||
if(tap && tap->_ips.size()){
|
if(tap && tap->_ips.size()){
|
||||||
for(int i=0; i<tap->_ips.size(); i++) {
|
for(int i=0; i<tap->_ips.size(); i++) {
|
||||||
if(tap->_ips[i].isV4()) {
|
if(tap->_ips[i].isV4()) {
|
||||||
@@ -285,7 +285,7 @@ void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen)
|
|||||||
{
|
{
|
||||||
if(ZeroTier::zt1Service) {
|
if(ZeroTier::zt1Service) {
|
||||||
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
||||||
ZeroTier::SocketTap *tap = getTapByNWID(nwid_int);
|
ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int);
|
||||||
if(tap && tap->_ips.size()){
|
if(tap && tap->_ips.size()){
|
||||||
for(int i=0; i<tap->_ips.size(); i++) {
|
for(int i=0; i<tap->_ips.size(); i++) {
|
||||||
if(tap->_ips[i].isV6()) {
|
if(tap->_ips[i].isV6()) {
|
||||||
@@ -351,11 +351,11 @@ void zts_disable_http_control_plane()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* SocketTap Multiplexer Functionality */
|
/* VirtualTap Multiplexer Functionality */
|
||||||
/* - This section of the API is used to implement the general socket */
|
/* - This section of the API is used to implement the general socket */
|
||||||
/* controls. Basically this is designed to handle socket provisioning */
|
/* controls. Basically this is designed to handle socket provisioning */
|
||||||
/* requests when no SocketTap is yet initialized, and as a way to */
|
/* requests when no VirtualTap is yet initialized, and as a way to */
|
||||||
/* determine which SocketTap is to be used for a particular connect() or */
|
/* determine which VirtualTap is to be used for a particular connect() or */
|
||||||
/* bind() call. This enables multi-network support */
|
/* bind() call. This enables multi-network support */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
@@ -396,25 +396,25 @@ int zts_socket(ZT_SOCKET_SIG) {
|
|||||||
|
|
||||||
if(socket_type == SOCK_RAW)
|
if(socket_type == SOCK_RAW)
|
||||||
{
|
{
|
||||||
// Connection is only used to associate a socket with a SocketTap, it has no other implication
|
// VirtualSocket is only used to associate a socket with a VirtualTap, it has no other implication
|
||||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket();
|
||||||
conn->socket_family = socket_family;
|
vs->socket_family = socket_family;
|
||||||
conn->socket_type = socket_type;
|
vs->socket_type = socket_type;
|
||||||
conn->protocol = protocol;
|
vs->protocol = protocol;
|
||||||
ZeroTier::unmap[conn->app_fd] = conn;
|
ZeroTier::unmap[vs->app_fd] = vs;
|
||||||
return conn->app_fd;
|
return vs->app_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
struct pico_socket *p;
|
struct pico_socket *p;
|
||||||
err = ZeroTier::picostack->pico_Socket(&p, socket_family, socket_type, protocol);
|
err = ZeroTier::picostack->pico_Socket(&p, socket_family, socket_type, protocol);
|
||||||
if(p) {
|
if(p) {
|
||||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket();
|
||||||
conn->socket_family = socket_family;
|
vs->socket_family = socket_family;
|
||||||
conn->socket_type = socket_type;
|
vs->socket_type = socket_type;
|
||||||
conn->picosock = p;
|
vs->picosock = p;
|
||||||
ZeroTier::unmap[conn->app_fd] = conn;
|
ZeroTier::unmap[vs->app_fd] = vs;
|
||||||
err = conn->app_fd; // return one end of the socketpair
|
err = vs->app_fd; // return one end of the socketpair
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_ERROR("failed to create pico_socket");
|
DEBUG_ERROR("failed to create pico_socket");
|
||||||
@@ -427,12 +427,12 @@ int zts_socket(ZT_SOCKET_SIG) {
|
|||||||
void *pcb;
|
void *pcb;
|
||||||
err = ZeroTier::lwipstack->lwip_Socket(&pcb, socket_family, socket_type, protocol);
|
err = ZeroTier::lwipstack->lwip_Socket(&pcb, socket_family, socket_type, protocol);
|
||||||
if(pcb) {
|
if(pcb) {
|
||||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket();
|
||||||
conn->socket_family = socket_family;
|
vs->socket_family = socket_family;
|
||||||
conn->socket_type = socket_type;
|
vs->socket_type = socket_type;
|
||||||
conn->pcb = pcb;
|
vs->pcb = pcb;
|
||||||
ZeroTier::unmap[conn->app_fd] = conn;
|
ZeroTier::unmap[vs->app_fd] = vs;
|
||||||
err = conn->app_fd; // return one end of the socketpair
|
err = vs->app_fd; // return one end of the socketpair
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_ERROR("failed to create lwip pcb");
|
DEBUG_ERROR("failed to create lwip pcb");
|
||||||
@@ -453,12 +453,12 @@ Darwin:
|
|||||||
[ ] [EADDRINUSE] The address is already in use.
|
[ ] [EADDRINUSE] The address is already in use.
|
||||||
[ ] [EADDRNOTAVAIL] The specified address is not available on this machine.
|
[ ] [EADDRNOTAVAIL] The specified address is not available on this machine.
|
||||||
[ ] [EAFNOSUPPORT] Addresses in the specified address family cannot be used with this socket.
|
[ ] [EAFNOSUPPORT] Addresses in the specified address family cannot be used with this socket.
|
||||||
[ ] [EALREADY] The socket is non-blocking and a previous connection attempt has not yet been completed.
|
[ ] [EALREADY] The socket is non-blocking and a previous VirtualSocket attempt has not yet been completed.
|
||||||
[--] [EBADF] socket is not a valid descriptor.
|
[--] [EBADF] socket is not a valid descriptor.
|
||||||
[ ] [ECONNREFUSED] The attempt to connect was ignored (because the target is not listening for connections) or explicitly rejected.
|
[ ] [ECONNREFUSED] The attempt to connect was ignored (because the target is not listening for VirtualSockets) or explicitly rejected.
|
||||||
[ ] [EFAULT] The address parameter specifies an area outside the process address space.
|
[ ] [EFAULT] The address parameter specifies an area outside the process address space.
|
||||||
[ ] [EHOSTUNREACH] The target host cannot be reached (e.g., down, disconnected).
|
[ ] [EHOSTUNREACH] The target host cannot be reached (e.g., down, disconnected).
|
||||||
[--] [EINPROGRESS] The socket is non-blocking and the connection cannot be completed immediately.
|
[--] [EINPROGRESS] The socket is non-blocking and the VirtualSocket cannot be completed immediately.
|
||||||
It is possible to select(2) for completion by selecting the socket for writing.
|
It is possible to select(2) for completion by selecting the socket for writing.
|
||||||
[NA] [EINTR] Its execution was interrupted by a signal.
|
[NA] [EINTR] Its execution was interrupted by a signal.
|
||||||
[ ] [EINVAL] An invalid argument was detected (e.g., address_len is not valid for the address family, the specified address family is invalid).
|
[ ] [EINVAL] An invalid argument was detected (e.g., address_len is not valid for the address family, the specified address family is invalid).
|
||||||
@@ -467,26 +467,26 @@ Darwin:
|
|||||||
[--] [ENETUNREACH] The network isn't reachable from this host.
|
[--] [ENETUNREACH] The network isn't reachable from this host.
|
||||||
[ ] [ENOBUFS] The system call was unable to allocate a needed memory buffer.
|
[ ] [ENOBUFS] The system call was unable to allocate a needed memory buffer.
|
||||||
[ ] [ENOTSOCK] socket is not a file descriptor for a socket.
|
[ ] [ENOTSOCK] socket is not a file descriptor for a socket.
|
||||||
[ ] [EOPNOTSUPP] Because socket is listening, no connection is allowed.
|
[ ] [EOPNOTSUPP] Because socket is listening, no VirtualSocket is allowed.
|
||||||
[ ] [EPROTOTYPE] address has a different type than the socket that is bound to the specified peer address.
|
[ ] [EPROTOTYPE] address has a different type than the socket that is bound to the specified peer address.
|
||||||
[ ] [ETIMEDOUT] Connection establishment timed out without establishing a connection.
|
[ ] [ETIMEDOUT] VirtualSocket establishment timed out without establishing a VirtualSocket.
|
||||||
[ ] [ECONNRESET] Remote host reset the connection request.
|
[ ] [ECONNRESET] Remote host reset the VirtualSocket request.
|
||||||
|
|
||||||
Linux:
|
Linux:
|
||||||
|
|
||||||
[ ] [EACCES] For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket file,
|
[ ] [EACCES] For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket file,
|
||||||
or search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).)
|
or search permission is denied for one of the directories in the path prefix. (See also path_resolution(7).)
|
||||||
[ ] [EACCES, EPERM] The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the
|
[ ] [EACCES, EPERM] The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the
|
||||||
connection request failed because of a local firewall rule.
|
VirtualSocket request failed because of a local firewall rule.
|
||||||
[ ] [EADDRINUSE] Local address is already in use.
|
[ ] [EADDRINUSE] Local address is already in use.
|
||||||
[ ] [EAFNOSUPPORT] The passed address didn't have the correct address family in its sa_family field.
|
[ ] [EAFNOSUPPORT] The passed address didn't have the correct address family in its sa_family field.
|
||||||
[ ] [EAGAIN] No more free local ports or insufficient entries in the routing cache. For AF_INET see the description
|
[ ] [EAGAIN] No more free local ports or insufficient entries in the routing cache. For AF_INET see the description
|
||||||
of /proc/sys/net/ipv4/ip_local_port_range ip(7) for information on how to increase the number of local ports.
|
of /proc/sys/net/ipv4/ip_local_port_range ip(7) for information on how to increase the number of local ports.
|
||||||
[ ] [EALREADY] The socket is nonblocking and a previous connection attempt has not yet been completed.
|
[ ] [EALREADY] The socket is nonblocking and a previous VirtualSocket attempt has not yet been completed.
|
||||||
[ ] [EBADF] The file descriptor is not a valid index in the descriptor table.
|
[ ] [EBADF] The file descriptor is not a valid index in the descriptor table.
|
||||||
[ ] [ECONNREFUSED] No-one listening on the remote address.
|
[ ] [ECONNREFUSED] No-one listening on the remote address.
|
||||||
[ ] [EFAULT] The socket structure address is outside the user's address space.
|
[ ] [EFAULT] The socket structure address is outside the user's address space.
|
||||||
[ ] [EINPROGRESS] The socket is nonblocking and the connection cannot be completed immediately. It is possible to select(2) or
|
[ ] [EINPROGRESS] The socket is nonblocking and the VirtualSocket cannot be completed immediately. It is possible to select(2) or
|
||||||
poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsockopt(2)
|
poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsockopt(2)
|
||||||
to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero)
|
to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero)
|
||||||
or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure).
|
or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure).
|
||||||
@@ -494,7 +494,7 @@ Linux:
|
|||||||
[ ] [EISCONN] The socket is already connected.
|
[ ] [EISCONN] The socket is already connected.
|
||||||
[ ] [ENETUNREACH] Network is unreachable.
|
[ ] [ENETUNREACH] Network is unreachable.
|
||||||
[ ] [ENOTSOCK] The file descriptor is not associated with a socket.
|
[ ] [ENOTSOCK] The file descriptor is not associated with a socket.
|
||||||
[ ] [ETIMEDOUT] Timeout while attempting connection. The server may be too busy to accept new connections. Note that for
|
[ ] [ETIMEDOUT] Timeout while attempting VirtualSocket. The server may be too busy to accept new VirtualSockets. Note that for
|
||||||
IP sockets the timeout may be very long when syncookies are enabled on the server.
|
IP sockets the timeout may be very long when syncookies are enabled on the server.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -512,22 +512,22 @@ int zts_connect(ZT_CONNECT_SIG) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ZeroTier::_multiplexer_lock.lock();
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||||
ZeroTier::SocketTap *tap;
|
ZeroTier::VirtualTap *tap;
|
||||||
|
|
||||||
if(conn) {
|
if(vs) {
|
||||||
char ipstr[INET6_ADDRSTRLEN];
|
char ipstr[INET6_ADDRSTRLEN];
|
||||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||||
ZeroTier::InetAddress iaddr;
|
ZeroTier::InetAddress iaddr;
|
||||||
int port = 0;
|
int port = 0;
|
||||||
|
|
||||||
if(conn->socket_family == AF_INET) {
|
if(vs->socket_family == AF_INET) {
|
||||||
inet_ntop(AF_INET,
|
inet_ntop(AF_INET,
|
||||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||||
iaddr.fromString(ipstr);
|
iaddr.fromString(ipstr);
|
||||||
port = ((struct sockaddr_in*)addr)->sin_port;
|
port = ((struct sockaddr_in*)addr)->sin_port;
|
||||||
}
|
}
|
||||||
if(conn->socket_family == AF_INET6) {
|
if(vs->socket_family == AF_INET6) {
|
||||||
inet_ntop(AF_INET6,
|
inet_ntop(AF_INET6,
|
||||||
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
||||||
// TODO: This is a hack, determine a proper way to do this
|
// TODO: This is a hack, determine a proper way to do this
|
||||||
@@ -546,33 +546,33 @@ int zts_connect(ZT_CONNECT_SIG) {
|
|||||||
else {
|
else {
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
// pointer to tap we use in callbacks from the stack
|
// pointer to tap we use in callbacks from the stack
|
||||||
conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn);
|
vs->picosock->priv = new ZeroTier::VirtualBindingPair(tap, vs);
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
#endif
|
#endif
|
||||||
err = tap->Connect(conn, addr, addrlen);
|
err = tap->Connect(vs, addr, addrlen);
|
||||||
if(err == 0) {
|
if(err == 0) {
|
||||||
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
|
tap->_VirtualSockets.push_back(vs); // Give this VirtualSocket to the tap we decided on
|
||||||
conn->tap = tap;
|
vs->tap = tap;
|
||||||
}
|
}
|
||||||
// Wrap the socketpair we created earlier
|
// Wrap the socketpair we created earlier
|
||||||
// For I/O loop participation and referencing the PhySocket's parent Connection in callbacks
|
// For I/O loop participation and referencing the PhySocket's parent VirtualSocket in callbacks
|
||||||
conn->sock = tap->_phy.wrapSocket(conn->sdk_fd, conn);
|
vs->sock = tap->_phy.wrapSocket(vs->sdk_fd, vs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_ERROR("unable to locate connection");
|
DEBUG_ERROR("unable to locate VirtualSocket");
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
ZeroTier::unmap.erase(fd);
|
ZeroTier::unmap.erase(fd);
|
||||||
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap);
|
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>(vs, tap);
|
||||||
ZeroTier::_multiplexer_lock.unlock();
|
ZeroTier::_multiplexer_lock.unlock();
|
||||||
|
|
||||||
// NOTE: pico_socket_connect() will return 0 if no error happens immediately, but that doesn't indicate
|
// NOTE: pico_socket_connect() will return 0 if no error happens immediately, but that doesn't indicate
|
||||||
// the connection was completed, for that we must wait for a callback from the stack. During that
|
// the VirtualSocket was completed, for that we must wait for a callback from the stack. During that
|
||||||
// callback we will place the Connection in a ZT_SOCK_STATE_UNHANDLED_CONNECTED state to signal
|
// callback we will place the VirtualSocket in a ZT_SOCK_STATE_UNHANDLED_CONNECTED state to signal
|
||||||
// to the multiplexer logic that this connection is complete and a success value can be sent to the
|
// to the multiplexer logic that this VirtualSocket is complete and a success value can be sent to the
|
||||||
// user application
|
// user application
|
||||||
|
|
||||||
int f_err, blocking = 1;
|
int f_err, blocking = 1;
|
||||||
@@ -596,15 +596,15 @@ int zts_connect(ZT_CONNECT_SIG) {
|
|||||||
bool complete = false;
|
bool complete = false;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
// FIXME: locking and unlocking so often might cause a performance bottleneck while outgoing connections
|
// FIXME: locking and unlocking so often might cause a performance bottleneck while outgoing VirtualSockets
|
||||||
// are being established (also applies to accept())
|
// are being established (also applies to accept())
|
||||||
usleep(ZT_CONNECT_RECHECK_DELAY * 1000);
|
usleep(ZT_CONNECT_RECHECK_DELAY * 1000);
|
||||||
//DEBUG_ERROR("waiting to connect...\n");
|
//DEBUG_ERROR("waiting to connect...\n");
|
||||||
tap->_tcpconns_m.lock();
|
tap->_tcpconns_m.lock();
|
||||||
for(int i=0; i<tap->_Connections.size(); i++)
|
for(int i=0; i<tap->_VirtualSockets.size(); i++)
|
||||||
{
|
{
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
if(tap->_Connections[i]->state == PICO_ERR_ECONNRESET) {
|
if(tap->_VirtualSockets[i]->state == PICO_ERR_ECONNRESET) {
|
||||||
errno = ECONNRESET;
|
errno = ECONNRESET;
|
||||||
DEBUG_ERROR("ECONNRESET");
|
DEBUG_ERROR("ECONNRESET");
|
||||||
err = -1;
|
err = -1;
|
||||||
@@ -612,8 +612,8 @@ int zts_connect(ZT_CONNECT_SIG) {
|
|||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
#endif
|
#endif
|
||||||
if(tap->_Connections[i]->state == ZT_SOCK_STATE_UNHANDLED_CONNECTED) {
|
if(tap->_VirtualSockets[i]->state == ZT_SOCK_STATE_UNHANDLED_CONNECTED) {
|
||||||
tap->_Connections[i]->state = ZT_SOCK_STATE_CONNECTED;
|
tap->_VirtualSockets[i]->state = ZT_SOCK_STATE_CONNECTED;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
err = 0; // complete
|
err = 0; // complete
|
||||||
complete = true;
|
complete = true;
|
||||||
@@ -655,20 +655,20 @@ int zts_bind(ZT_BIND_SIG) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ZeroTier::_multiplexer_lock.lock();
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||||
ZeroTier::SocketTap *tap;
|
ZeroTier::VirtualTap *tap;
|
||||||
|
|
||||||
if(conn) {
|
if(vs) {
|
||||||
char ipstr[INET6_ADDRSTRLEN];
|
char ipstr[INET6_ADDRSTRLEN];
|
||||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||||
ZeroTier::InetAddress iaddr;
|
ZeroTier::InetAddress iaddr;
|
||||||
int port = 0;
|
int port = 0;
|
||||||
if(conn->socket_family == AF_INET) {
|
if(vs->socket_family == AF_INET) {
|
||||||
inet_ntop(AF_INET,
|
inet_ntop(AF_INET,
|
||||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||||
port = ((struct sockaddr_in*)addr)->sin_port;
|
port = ((struct sockaddr_in*)addr)->sin_port;
|
||||||
}
|
}
|
||||||
if(conn->socket_family == AF_INET6) {
|
if(vs->socket_family == AF_INET6) {
|
||||||
inet_ntop(AF_INET6,
|
inet_ntop(AF_INET6,
|
||||||
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
||||||
port = ((struct sockaddr_in6*)addr)->sin6_port;
|
port = ((struct sockaddr_in6*)addr)->sin6_port;
|
||||||
@@ -684,30 +684,30 @@ int zts_bind(ZT_BIND_SIG) {
|
|||||||
}
|
}
|
||||||
#if defined(STACK_PICO)
|
#if defined(STACK_PICO)
|
||||||
else {
|
else {
|
||||||
conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn);
|
vs->picosock->priv = new ZeroTier::VirtualBindingPair(tap, vs);
|
||||||
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
|
tap->_VirtualSockets.push_back(vs); // Give this VirtualSocket to the tap we decided on
|
||||||
err = tap->Bind(conn, addr, addrlen);
|
err = tap->Bind(vs, addr, addrlen);
|
||||||
conn->tap = tap;
|
vs->tap = tap;
|
||||||
if(err == 0) { // success
|
if(err == 0) { // success
|
||||||
ZeroTier::unmap.erase(fd);
|
ZeroTier::unmap.erase(fd);
|
||||||
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap);
|
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>(vs, tap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(STACK_LWIP)
|
#if defined(STACK_LWIP)
|
||||||
else {
|
else {
|
||||||
tap->_Connections.push_back(conn);
|
tap->_VirtualSockets.push_back(vs);
|
||||||
err = tap->Bind(conn, addr, addrlen);
|
err = tap->Bind(vs, addr, addrlen);
|
||||||
conn->tap = tap;
|
vs->tap = tap;
|
||||||
if(err == 0) { // success
|
if(err == 0) { // success
|
||||||
ZeroTier::unmap.erase(fd);
|
ZeroTier::unmap.erase(fd);
|
||||||
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap);
|
ZeroTier::fdmap[fd] = new std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>(vs, tap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_ERROR("unable to locate connection");
|
DEBUG_ERROR("unable to locate VirtualSocket");
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
@@ -746,23 +746,23 @@ int zts_listen(ZT_LISTEN_SIG) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ZeroTier::_multiplexer_lock.lock();
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||||
if(!p) {
|
if(!p) {
|
||||||
DEBUG_ERROR("unable to locate connection pair. did you bind?");
|
DEBUG_ERROR("unable to locate VirtualSocket pair. did you bind?");
|
||||||
errno = EDESTADDRREQ;
|
errno = EDESTADDRREQ;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ZeroTier::Connection *conn = p->first;
|
ZeroTier::VirtualSocket *vs = p->first;
|
||||||
ZeroTier::SocketTap *tap = p->second;
|
ZeroTier::VirtualTap *tap = p->second;
|
||||||
if(!tap || !conn) {
|
if(!tap || !vs) {
|
||||||
DEBUG_ERROR("unable to locate tap interface for file descriptor");
|
DEBUG_ERROR("unable to locate tap interface for file descriptor");
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(!err) {
|
if(!err) {
|
||||||
backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn
|
backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn
|
||||||
err = tap->Listen(conn, backlog);
|
err = tap->Listen(vs, backlog);
|
||||||
conn->state = ZT_SOCK_STATE_LISTENING;
|
vs->state = ZT_SOCK_STATE_LISTENING;
|
||||||
ZeroTier::_multiplexer_lock.unlock();
|
ZeroTier::_multiplexer_lock.unlock();
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
@@ -777,7 +777,7 @@ Darwin:
|
|||||||
[ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM.
|
[ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM.
|
||||||
[ ] [EFAULT] The addr parameter is not in a writable part of the
|
[ ] [EFAULT] The addr parameter is not in a writable part of the
|
||||||
user address space.
|
user address space.
|
||||||
[--] [EWOULDBLOCK] The socket is marked non-blocking and no connections
|
[--] [EWOULDBLOCK] The socket is marked non-blocking and no VirtualSockets
|
||||||
are present to be accepted.
|
are present to be accepted.
|
||||||
[--] [EMFILE] The per-process descriptor table is full.
|
[--] [EMFILE] The per-process descriptor table is full.
|
||||||
[ ] [ENFILE] The system file table is full.
|
[ ] [ENFILE] The system file table is full.
|
||||||
@@ -789,24 +789,24 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
|||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// +1 since we'll be creating a new pico_socket when we accept the connection
|
// +1 since we'll be creating a new pico_socket when we accept the VirtualSocket
|
||||||
if(!can_provision_new_socket()) {
|
if(!can_provision_new_socket()) {
|
||||||
DEBUG_ERROR("cannot provision additional socket due to limitation of network stack");
|
DEBUG_ERROR("cannot provision additional socket due to limitation of network stack");
|
||||||
errno = EMFILE;
|
errno = EMFILE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ZeroTier::_multiplexer_lock.lock();
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||||
if(!p) {
|
if(!p) {
|
||||||
DEBUG_ERROR("unable to locate connection pair (did you zts_bind())?");
|
DEBUG_ERROR("unable to locate VirtualSocket pair (did you zts_bind())?");
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ZeroTier::Connection *conn = p->first;
|
ZeroTier::VirtualSocket *vs = p->first;
|
||||||
ZeroTier::SocketTap *tap = p->second;
|
ZeroTier::VirtualTap *tap = p->second;
|
||||||
|
|
||||||
// BLOCKING: loop and keep checking until we find a newly accepted connection
|
// BLOCKING: loop and keep checking until we find a newly accepted VirtualSocket
|
||||||
int f_err, blocking = 1;
|
int f_err, blocking = 1;
|
||||||
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
|
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
|
||||||
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
|
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
|
||||||
@@ -817,24 +817,24 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!err) {
|
if(!err) {
|
||||||
ZeroTier::Connection *accepted_conn;
|
ZeroTier::VirtualSocket *accepted_vs;
|
||||||
if(!blocking) { // non-blocking
|
if(!blocking) { // non-blocking
|
||||||
DEBUG_EXTRA("EWOULDBLOCK, not a real error, assuming non-blocking mode");
|
DEBUG_EXTRA("EWOULDBLOCK, not a real error, assuming non-blocking mode");
|
||||||
errno = EWOULDBLOCK;
|
errno = EWOULDBLOCK;
|
||||||
err = -1;
|
err = -1;
|
||||||
accepted_conn = tap->Accept(conn);
|
accepted_vs = tap->Accept(vs);
|
||||||
}
|
}
|
||||||
else { // blocking
|
else { // blocking
|
||||||
while(true) {
|
while(true) {
|
||||||
usleep(ZT_ACCEPT_RECHECK_DELAY * 1000);
|
usleep(ZT_ACCEPT_RECHECK_DELAY * 1000);
|
||||||
accepted_conn = tap->Accept(conn);
|
accepted_vs = tap->Accept(vs);
|
||||||
if(accepted_conn)
|
if(accepted_vs)
|
||||||
break; // accepted fd = err
|
break; // accepted fd = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(accepted_conn) {
|
if(accepted_vs) {
|
||||||
ZeroTier::fdmap[accepted_conn->app_fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(accepted_conn, tap);
|
ZeroTier::fdmap[accepted_vs->app_fd] = new std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>(accepted_vs, tap);
|
||||||
err = accepted_conn->app_fd;
|
err = accepted_vs->app_fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -847,12 +847,12 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
|||||||
Linux accept() (and accept4()) passes already-pending network errors on the new socket as an error code from accept(). This behavior differs from other BSD socket implementations. For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying. In the case of TCP/IP, these are ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH.
|
Linux accept() (and accept4()) passes already-pending network errors on the new socket as an error code from accept(). This behavior differs from other BSD socket implementations. For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying. In the case of TCP/IP, these are ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH.
|
||||||
Errors
|
Errors
|
||||||
|
|
||||||
[ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.
|
[ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and no VirtualSockets are present to be accepted. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.
|
||||||
[--] [EBADF] The descriptor is invalid.
|
[--] [EBADF] The descriptor is invalid.
|
||||||
[ ] [ECONNABORTED] A connection has been aborted.
|
[ ] [ECONNABORTED] A VirtualSocket has been aborted.
|
||||||
[ ] [EFAULT] The addr argument is not in a writable part of the user address space.
|
[ ] [EFAULT] The addr argument is not in a writable part of the user address space.
|
||||||
[NA] [EINTR] The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).
|
[NA] [EINTR] The system call was interrupted by a signal that was caught before a valid VirtualSocket arrived; see signal(7).
|
||||||
[ ] [EINVAL] Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
|
[ ] [EINVAL] Socket is not listening for VirtualSockets, or addrlen is invalid (e.g., is negative).
|
||||||
[ ] [EINVAL] (accept4()) invalid value in flags.
|
[ ] [EINVAL] (accept4()) invalid value in flags.
|
||||||
[ ] [EMFILE] The per-process limit of open file descriptors has been reached.
|
[ ] [EMFILE] The per-process limit of open file descriptors has been reached.
|
||||||
[ ] [ENFILE] The system limit on the total number of open files has been reached.
|
[ ] [ENFILE] The system limit on the total number of open files has been reached.
|
||||||
@@ -863,7 +863,7 @@ Errors
|
|||||||
|
|
||||||
In addition, Linux accept() may fail if:
|
In addition, Linux accept() may fail if:
|
||||||
|
|
||||||
EPERM Firewall rules forbid connection.
|
EPERM Firewall rules forbid VirtualSocket.
|
||||||
*/
|
*/
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
int zts_accept4(ZT_ACCEPT4_SIG)
|
int zts_accept4(ZT_ACCEPT4_SIG)
|
||||||
@@ -1016,36 +1016,36 @@ int zts_close(ZT_CLOSE_SIG)
|
|||||||
{
|
{
|
||||||
ZeroTier::_multiplexer_lock.lock();
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
//DEBUG_INFO("unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size());
|
//DEBUG_INFO("unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size());
|
||||||
// First, look for for unassigned connections
|
// First, look for for unassigned VirtualSockets
|
||||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||||
|
|
||||||
// Since we found an unassigned connection, we don't need to consult the stack or tap
|
// Since we found an unassigned VirtualSocket, we don't need to consult the stack or tap
|
||||||
// during closure - it isn't yet stitched into the clockwork
|
// during closure - it isn't yet stitched into the clockwork
|
||||||
if(conn) // unassigned
|
if(vs) // unassigned
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("unassigned closure");
|
DEBUG_ERROR("unassigned closure");
|
||||||
if((err = pico_socket_close(conn->picosock)) < 0)
|
if((err = pico_socket_close(vs->picosock)) < 0)
|
||||||
DEBUG_ERROR("error calling pico_socket_close()");
|
DEBUG_ERROR("error calling pico_socket_close()");
|
||||||
if((err = close(conn->app_fd)) < 0)
|
if((err = close(vs->app_fd)) < 0)
|
||||||
DEBUG_ERROR("error closing app_fd");
|
DEBUG_ERROR("error closing app_fd");
|
||||||
if((err = close(conn->sdk_fd)) < 0)
|
if((err = close(vs->sdk_fd)) < 0)
|
||||||
DEBUG_ERROR("error closing sdk_fd");
|
DEBUG_ERROR("error closing sdk_fd");
|
||||||
delete conn;
|
delete vs;
|
||||||
ZeroTier::unmap.erase(fd);
|
ZeroTier::unmap.erase(fd);
|
||||||
}
|
}
|
||||||
else // assigned
|
else // assigned
|
||||||
{
|
{
|
||||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||||
if(!p)
|
if(!p)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("unable to locate connection pair.");
|
DEBUG_ERROR("unable to locate VirtualSocket pair.");
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
else // found everything, begin closure
|
else // found everything, begin closure
|
||||||
{
|
{
|
||||||
conn = p->first;
|
vs = p->first;
|
||||||
ZeroTier::SocketTap *tap = p->second;
|
ZeroTier::VirtualTap *tap = p->second;
|
||||||
|
|
||||||
// check if socket is blocking
|
// check if socket is blocking
|
||||||
int f_err, blocking = 1;
|
int f_err, blocking = 1;
|
||||||
@@ -1060,7 +1060,7 @@ int zts_close(ZT_CLOSE_SIG)
|
|||||||
if(blocking) {
|
if(blocking) {
|
||||||
DEBUG_INFO("blocking, waiting for write operations before closure...");
|
DEBUG_INFO("blocking, waiting for write operations before closure...");
|
||||||
for(int i=0; i<ZT_SDK_CLTIME; i++) {
|
for(int i=0; i<ZT_SDK_CLTIME; i++) {
|
||||||
if(conn->TXbuf->count() == 0)
|
if(vs->TXbuf->count() == 0)
|
||||||
break;
|
break;
|
||||||
usleep(ZT_API_CHECK_INTERVAL * 1000);
|
usleep(ZT_API_CHECK_INTERVAL * 1000);
|
||||||
}
|
}
|
||||||
@@ -1087,8 +1087,8 @@ int zts_close(ZT_CLOSE_SIG)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//DEBUG_INFO("s->state = %s", ZeroTier::picoTCP::beautify_pico_state(conn->picosock->state));
|
//DEBUG_INFO("s->state = %s", ZeroTier::picoTCP::beautify_pico_state(vs->picosock->state));
|
||||||
tap->Close(conn);
|
tap->Close(vs);
|
||||||
ZeroTier::fdmap.erase(fd);
|
ZeroTier::fdmap.erase(fd);
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
@@ -1165,23 +1165,23 @@ int zts_ioctl(ZT_IOCTL_SIG)
|
|||||||
if(argp)
|
if(argp)
|
||||||
{
|
{
|
||||||
struct ifreq *ifr = (struct ifreq *)argp;
|
struct ifreq *ifr = (struct ifreq *)argp;
|
||||||
ZeroTier::SocketTap *tap = getTapByName(ifr->ifr_name);
|
ZeroTier::VirtualTap *tap = getTapByName(ifr->ifr_name);
|
||||||
if(!tap) {
|
if(!tap) {
|
||||||
DEBUG_ERROR("unable to locate tap interface with that name");
|
DEBUG_ERROR("unable to locate tap interface with that name");
|
||||||
err = -1;
|
err = -1;
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
}
|
}
|
||||||
// index of SocketTap interface
|
// index of VirtualTap interface
|
||||||
if(request == SIOCGIFINDEX) {
|
if(request == SIOCGIFINDEX) {
|
||||||
ifr->ifr_ifindex = tap->ifindex;
|
ifr->ifr_ifindex = tap->ifindex;
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
// MAC addres or SocketTap
|
// MAC addres or VirtualTap
|
||||||
if(request == SIOCGIFHWADDR) {
|
if(request == SIOCGIFHWADDR) {
|
||||||
tap->_mac.copyTo(&(ifr->ifr_hwaddr.sa_data), sizeof(ifr->ifr_hwaddr.sa_data));
|
tap->_mac.copyTo(&(ifr->ifr_hwaddr.sa_data), sizeof(ifr->ifr_hwaddr.sa_data));
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
// IP address of SocketTap
|
// IP address of VirtualTap
|
||||||
if(request == SIOCGIFADDR) {
|
if(request == SIOCGIFADDR) {
|
||||||
struct sockaddr_in *in4 = (struct sockaddr_in *)&(ifr->ifr_addr);
|
struct sockaddr_in *in4 = (struct sockaddr_in *)&(ifr->ifr_addr);
|
||||||
memcpy(&(in4->sin_addr.s_addr), tap->_ips[0].rawIpData(), sizeof(ifr->ifr_addr));
|
memcpy(&(in4->sin_addr.s_addr), tap->_ips[0].rawIpData(), sizeof(ifr->ifr_addr));
|
||||||
@@ -1206,19 +1206,19 @@ Linux:
|
|||||||
|
|
||||||
[ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and the requested operation would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.
|
[ ] [EAGAIN or EWOULDBLOCK] The socket is marked nonblocking and the requested operation would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.
|
||||||
[ ] [EBADF] An invalid descriptor was specified.
|
[ ] [EBADF] An invalid descriptor was specified.
|
||||||
[ ] [ECONNRESET] Connection reset by peer.
|
[ ] [ECONNRESET] VirtualSocket reset by peer.
|
||||||
[ ] [EDESTADDRREQ] The socket is not connection-mode, and no peer address is set.
|
[ ] [EDESTADDRREQ] The socket is not VirtualSocket-mode, and no peer address is set.
|
||||||
[ ] [EFAULT] An invalid user space address was specified for an argument.
|
[ ] [EFAULT] An invalid user space address was specified for an argument.
|
||||||
[ ] [EINTR] A signal occurred before any data was transmitted; see signal(7).
|
[ ] [EINTR] A signal occurred before any data was transmitted; see signal(7).
|
||||||
[ ] [EINVAL] Invalid argument passed.
|
[ ] [EINVAL] Invalid argument passed.
|
||||||
[ ] [EISCONN] The connection-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.)
|
[ ] [EISCONN] The VirtualSocket-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.)
|
||||||
[ ] [EMSGSIZE] The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible.
|
[ ] [EMSGSIZE] The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible.
|
||||||
[ ] [ENOBUFS] The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)
|
[ ] [ENOBUFS] The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)
|
||||||
[ ] [ENOMEM] No memory available.
|
[ ] [ENOMEM] No memory available.
|
||||||
[ ] [ENOTCONN] The socket is not connected, and no target has been given.
|
[ ] [ENOTCONN] The socket is not connected, and no target has been given.
|
||||||
[ ] [ENOTSOCK] The argument sockfd is not a socket.
|
[ ] [ENOTSOCK] The argument sockfd is not a socket.
|
||||||
[ ] [EOPNOTSUPP] Some bit in the flags argument is inappropriate for the socket type.
|
[ ] [EOPNOTSUPP] Some bit in the flags argument is inappropriate for the socket type.
|
||||||
[ ] [EPIPE] The local end has been shut down on a connection oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.
|
[ ] [EPIPE] The local end has been shut down on a VirtualSocket oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
ssize_t zts_sendto(ZT_SENDTO_SIG)
|
ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||||
@@ -1230,21 +1230,21 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
|||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||||
ZeroTier::InetAddress iaddr;
|
ZeroTier::InetAddress iaddr;
|
||||||
ZeroTier::SocketTap *tap;
|
ZeroTier::VirtualTap *tap;
|
||||||
char ipstr[INET6_ADDRSTRLEN];
|
char ipstr[INET6_ADDRSTRLEN];
|
||||||
int port;
|
int port;
|
||||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||||
|
|
||||||
if(conn->socket_type == SOCK_DGRAM) {
|
if(vs->socket_type == SOCK_DGRAM) {
|
||||||
if(conn->socket_family == AF_INET) {
|
if(vs->socket_family == AF_INET) {
|
||||||
inet_ntop(AF_INET,
|
inet_ntop(AF_INET,
|
||||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||||
iaddr.fromString(ipstr);
|
iaddr.fromString(ipstr);
|
||||||
port = ((struct sockaddr_in*)addr)->sin_port;
|
port = ((struct sockaddr_in*)addr)->sin_port;
|
||||||
}
|
}
|
||||||
if(conn->socket_family == AF_INET6) {
|
if(vs->socket_family == AF_INET6) {
|
||||||
inet_ntop(AF_INET6,
|
inet_ntop(AF_INET6,
|
||||||
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
||||||
// TODO: This is a hack, determine a proper way to do this
|
// TODO: This is a hack, determine a proper way to do this
|
||||||
@@ -1255,7 +1255,7 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
|||||||
}
|
}
|
||||||
tap = getTapByAddr(iaddr);
|
tap = getTapByAddr(iaddr);
|
||||||
if(tap) {
|
if(tap) {
|
||||||
tap->SendTo(conn, buf, len, flags, addr, addrlen);
|
tap->SendTo(vs, buf, len, flags, addr, addrlen);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_INFO("SOCK_DGRAM, tap not found");
|
DEBUG_INFO("SOCK_DGRAM, tap not found");
|
||||||
@@ -1263,19 +1263,19 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conn->socket_type == SOCK_RAW)
|
if(vs->socket_type == SOCK_RAW)
|
||||||
{
|
{
|
||||||
struct sockaddr_ll *socket_address = (struct sockaddr_ll *)addr;
|
struct sockaddr_ll *socket_address = (struct sockaddr_ll *)addr;
|
||||||
ZeroTier::SocketTap *tap = getTapByIndex(socket_address->sll_ifindex);
|
ZeroTier::VirtualTap *tap = getTapByIndex(socket_address->sll_ifindex);
|
||||||
if(tap)
|
if(tap)
|
||||||
{
|
{
|
||||||
DEBUG_INFO("found interface of ifindex=%d", tap->ifindex);
|
DEBUG_INFO("found interface of ifindex=%d", tap->ifindex);
|
||||||
if(conn) {
|
if(vs) {
|
||||||
DEBUG_INFO("located connection object for fd=%d", fd);
|
DEBUG_INFO("located VirtualSocket object for fd=%d", fd);
|
||||||
err = tap->Write(conn, (void*)buf, len);
|
err = tap->Write(vs, (void*)buf, len);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_ERROR("unable to locate connection object for fd=%d", fd);
|
DEBUG_ERROR("unable to locate VirtualSocket object for fd=%d", fd);
|
||||||
err = -1;
|
err = -1;
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
}
|
}
|
||||||
@@ -1371,11 +1371,11 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ZeroTier::_multiplexer_lock.lock();
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
// First, look for for unassigned connections
|
// First, look for for unassigned VirtualSockets
|
||||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||||
// Since we found an unassigned connection, we don't need to consult the stack or tap
|
// Since we found an unassigned VirtualSocket, we don't need to consult the stack or tap
|
||||||
// during closure - it isn't yet stitched into the clockwork
|
// during closure - it isn't yet stitched into the clockwork
|
||||||
if(conn) // unassigned
|
if(vs) // unassigned
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("unassigned shutdown");
|
DEBUG_ERROR("unassigned shutdown");
|
||||||
/*
|
/*
|
||||||
@@ -1383,24 +1383,24 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
|||||||
PICO_SHUT_WR
|
PICO_SHUT_WR
|
||||||
PICO_SHUT_RDWR
|
PICO_SHUT_RDWR
|
||||||
*/
|
*/
|
||||||
if((err = pico_socket_shutdown(conn->picosock, mode)) < 0)
|
if((err = pico_socket_shutdown(vs->picosock, mode)) < 0)
|
||||||
DEBUG_ERROR("error calling pico_socket_shutdown()");
|
DEBUG_ERROR("error calling pico_socket_shutdown()");
|
||||||
delete conn;
|
delete vs;
|
||||||
ZeroTier::unmap.erase(fd);
|
ZeroTier::unmap.erase(fd);
|
||||||
// FIXME: Is deleting this correct behaviour?
|
// FIXME: Is deleting this correct behaviour?
|
||||||
}
|
}
|
||||||
else // assigned
|
else // assigned
|
||||||
{
|
{
|
||||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||||
if(!p)
|
if(!p)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("unable to locate connection pair.");
|
DEBUG_ERROR("unable to locate VirtualSocket pair.");
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
else // found everything, begin closure
|
else // found everything, begin closure
|
||||||
{
|
{
|
||||||
conn = p->first;
|
vs = p->first;
|
||||||
int f_err, blocking = 1;
|
int f_err, blocking = 1;
|
||||||
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
|
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
|
||||||
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
|
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
|
||||||
@@ -1412,13 +1412,13 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
|||||||
if(blocking) {
|
if(blocking) {
|
||||||
DEBUG_INFO("blocking, waiting for write operations before shutdown...");
|
DEBUG_INFO("blocking, waiting for write operations before shutdown...");
|
||||||
for(int i=0; i<ZT_SDK_CLTIME; i++) {
|
for(int i=0; i<ZT_SDK_CLTIME; i++) {
|
||||||
if(conn->TXbuf->count() == 0)
|
if(vs->TXbuf->count() == 0)
|
||||||
break;
|
break;
|
||||||
usleep(ZT_API_CHECK_INTERVAL * 1000);
|
usleep(ZT_API_CHECK_INTERVAL * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((err = pico_socket_shutdown(conn->picosock, mode)) < 0)
|
if((err = pico_socket_shutdown(vs->picosock, mode)) < 0)
|
||||||
DEBUG_ERROR("error calling pico_socket_shutdown()");
|
DEBUG_ERROR("error calling pico_socket_shutdown()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1704,19 +1704,19 @@ int zts_get_pico_socket(int fd, struct pico_socket **s)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ZeroTier::_multiplexer_lock.lock();
|
ZeroTier::_multiplexer_lock.lock();
|
||||||
// First, look for for unassigned connections
|
// First, look for for unassigned VirtualSockets
|
||||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||||
if(conn)
|
if(vs)
|
||||||
{
|
{
|
||||||
*s = conn->picosock;
|
*s = vs->picosock;
|
||||||
err = 1; // unassigned
|
err = 1; // unassigned
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||||
if(!p)
|
if(!p)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("unable to locate connection pair.");
|
DEBUG_ERROR("unable to locate VirtualSocket pair.");
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
@@ -1774,25 +1774,25 @@ std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(char *nwid)
|
|||||||
return ZeroTier::zt1Service->getRoutes(nwid_int);
|
return ZeroTier::zt1Service->getRoutes(nwid_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroTier::SocketTap *getTapByNWID(uint64_t nwid)
|
ZeroTier::VirtualTap *getTapByNWID(uint64_t nwid)
|
||||||
{
|
{
|
||||||
ZeroTier::_vtaps_lock.lock();
|
ZeroTier::_vtaps_lock.lock();
|
||||||
ZeroTier::SocketTap *s, *tap = nullptr;
|
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||||
s = (ZeroTier::SocketTap*)ZeroTier::vtaps[i];
|
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||||
if(s->_nwid == nwid) { tap = s; }
|
if(s->_nwid == nwid) { tap = s; }
|
||||||
}
|
}
|
||||||
ZeroTier::_vtaps_lock.unlock();
|
ZeroTier::_vtaps_lock.unlock();
|
||||||
return tap;
|
return tap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr)
|
ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress &addr)
|
||||||
{
|
{
|
||||||
ZeroTier::_vtaps_lock.lock();
|
ZeroTier::_vtaps_lock.lock();
|
||||||
ZeroTier::SocketTap *s, *tap = nullptr;
|
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||||
char ipbuf[64], ipbuf2[64], ipbuf3[64];
|
char ipbuf[64], ipbuf2[64], ipbuf3[64];
|
||||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||||
s = (ZeroTier::SocketTap*)ZeroTier::vtaps[i];
|
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||||
// check address schemes
|
// check address schemes
|
||||||
for(int j=0; j<s->_ips.size(); j++) {
|
for(int j=0; j<s->_ips.size(); j++) {
|
||||||
if(s->_ips[j].isEqualPrefix(addr)
|
if(s->_ips[j].isEqualPrefix(addr)
|
||||||
@@ -1824,12 +1824,12 @@ ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr)
|
|||||||
return tap;
|
return tap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroTier::SocketTap *getTapByName(char *ifname)
|
ZeroTier::VirtualTap *getTapByName(char *ifname)
|
||||||
{
|
{
|
||||||
ZeroTier::_vtaps_lock.lock();
|
ZeroTier::_vtaps_lock.lock();
|
||||||
ZeroTier::SocketTap *s, *tap = nullptr;
|
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||||
s = (ZeroTier::SocketTap*)ZeroTier::vtaps[i];
|
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||||
if(!strcmp(s->_dev.c_str(), ifname)) {
|
if(!strcmp(s->_dev.c_str(), ifname)) {
|
||||||
tap = s;
|
tap = s;
|
||||||
}
|
}
|
||||||
@@ -1838,12 +1838,12 @@ ZeroTier::SocketTap *getTapByName(char *ifname)
|
|||||||
return tap;
|
return tap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZeroTier::SocketTap *getTapByIndex(int index)
|
ZeroTier::VirtualTap *getTapByIndex(int index)
|
||||||
{
|
{
|
||||||
ZeroTier::_vtaps_lock.lock();
|
ZeroTier::_vtaps_lock.lock();
|
||||||
ZeroTier::SocketTap *s, *tap = nullptr;
|
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||||
s = (ZeroTier::SocketTap*)ZeroTier::vtaps[i];
|
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||||
if(s->ifindex == index) {
|
if(s->ifindex == index) {
|
||||||
tap = s;
|
tap = s;
|
||||||
}
|
}
|
||||||
@@ -1855,7 +1855,7 @@ ZeroTier::SocketTap *getTapByIndex(int index)
|
|||||||
void dismantleTaps()
|
void dismantleTaps()
|
||||||
{
|
{
|
||||||
ZeroTier::_vtaps_lock.lock();
|
ZeroTier::_vtaps_lock.lock();
|
||||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) { delete (ZeroTier::SocketTap*)ZeroTier::vtaps[i]; }
|
for(int i=0; i<ZeroTier::vtaps.size(); i++) { delete (ZeroTier::VirtualTap*)ZeroTier::vtaps[i]; }
|
||||||
ZeroTier::vtaps.clear();
|
ZeroTier::vtaps.clear();
|
||||||
ZeroTier::_vtaps_lock.unlock();
|
ZeroTier::_vtaps_lock.unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
280
src/lwIP.cpp
280
src/lwIP.cpp
@@ -29,7 +29,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "libzt.h"
|
#include "libzt.h"
|
||||||
#include "SocketTap.hpp"
|
#include "VirtualTap.hpp"
|
||||||
#include "Utilities.hpp"
|
#include "Utilities.hpp"
|
||||||
#include "lwIP.hpp"
|
#include "lwIP.hpp"
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ err_t low_level_output(struct netif *netif, struct pbuf *p)
|
|||||||
char *bufptr;
|
char *bufptr;
|
||||||
int totalLength = 0;
|
int totalLength = 0;
|
||||||
|
|
||||||
ZeroTier::SocketTap *tap = (ZeroTier::SocketTap*)netif->state;
|
ZeroTier::VirtualTap *tap = (ZeroTier::VirtualTap*)netif->state;
|
||||||
bufptr = buf;
|
bufptr = buf;
|
||||||
// Copy data from each pbuf, one at a time
|
// Copy data from each pbuf, one at a time
|
||||||
for(q = p; q != NULL; q = q->next) {
|
for(q = p; q != NULL; q = q->next) {
|
||||||
@@ -81,7 +81,7 @@ err_t low_level_output(struct netif *netif, struct pbuf *p)
|
|||||||
|
|
||||||
namespace ZeroTier
|
namespace ZeroTier
|
||||||
{
|
{
|
||||||
void lwIP::lwip_init_interface(SocketTap *tap, const InetAddress &ip)
|
void lwIP::lwip_init_interface(VirtualTap *tap, const InetAddress &ip)
|
||||||
{
|
{
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
Mutex::Lock _l(tap->_ips_m);
|
Mutex::Lock _l(tap->_ips_m);
|
||||||
@@ -140,7 +140,7 @@ namespace ZeroTier
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lwIP::lwip_loop(SocketTap *tap)
|
void lwIP::lwip_loop(VirtualTap *tap)
|
||||||
{
|
{
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
uint64_t prev_tcp_time = 0, prev_discovery_time = 0;
|
uint64_t prev_tcp_time = 0, prev_discovery_time = 0;
|
||||||
@@ -181,7 +181,7 @@ namespace ZeroTier
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lwIP::lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
void lwIP::lwip_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||||
{
|
{
|
||||||
DEBUG_INFO("etherType=%x, len=%d", etherType, len);
|
DEBUG_INFO("etherType=%x, len=%d", etherType, len);
|
||||||
struct pbuf *p,*q;
|
struct pbuf *p,*q;
|
||||||
@@ -249,7 +249,7 @@ namespace ZeroTier
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lwIP::lwip_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen)
|
int lwIP::lwip_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
ip_addr_t ba;
|
ip_addr_t ba;
|
||||||
@@ -269,7 +269,7 @@ namespace ZeroTier
|
|||||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr;
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr;
|
||||||
in6_to_ip6((ip6_addr *)&ba, in6);
|
in6_to_ip6((ip6_addr *)&ba, in6);
|
||||||
if(addr->sa_family == AF_INET6) {
|
if(addr->sa_family == AF_INET6) {
|
||||||
struct sockaddr_in6 *connaddr6 = (struct sockaddr_in6 *)addr;
|
struct sockaddr_in6 *vsaddr6 = (struct sockaddr_in6 *)addr;
|
||||||
inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN);
|
inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN);
|
||||||
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port));
|
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port));
|
||||||
}
|
}
|
||||||
@@ -277,25 +277,25 @@ namespace ZeroTier
|
|||||||
|
|
||||||
DEBUG_INFO("addr=%s", addrstr);
|
DEBUG_INFO("addr=%s", addrstr);
|
||||||
|
|
||||||
if(conn->socket_type == SOCK_DGRAM) {
|
if(vs->socket_type == SOCK_DGRAM) {
|
||||||
// Generates no network traffic
|
// Generates no network traffic
|
||||||
if((err = udp_connect((struct udp_pcb*)conn->pcb,(ip_addr_t *)&ba,port)) < 0) {
|
if((err = udp_connect((struct udp_pcb*)vs->pcb,(ip_addr_t *)&ba,port)) < 0) {
|
||||||
DEBUG_ERROR("error while connecting to with UDP");
|
DEBUG_ERROR("error while connecting to with UDP");
|
||||||
}
|
}
|
||||||
udp_recv((struct udp_pcb*)conn->pcb, nc_udp_recved, conn);
|
udp_recv((struct udp_pcb*)vs->pcb, nc_udp_recved, vs);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(conn->socket_type == SOCK_STREAM) {
|
if(vs->socket_type == SOCK_STREAM) {
|
||||||
struct tcp_pcb *tpcb = (struct tcp_pcb*)conn->pcb;
|
struct tcp_pcb *tpcb = (struct tcp_pcb*)vs->pcb;
|
||||||
tcp_sent(tpcb, nc_sent);
|
tcp_sent(tpcb, nc_sent);
|
||||||
tcp_recv(tpcb, nc_recved);
|
tcp_recv(tpcb, nc_recved);
|
||||||
tcp_err(tpcb, nc_err);
|
tcp_err(tpcb, nc_err);
|
||||||
tcp_poll(tpcb, nc_poll, LWIP_APPLICATION_POLL_FREQ);
|
tcp_poll(tpcb, nc_poll, LWIP_APPLICATION_POLL_FREQ);
|
||||||
tcp_arg(tpcb, conn);
|
tcp_arg(tpcb, vs);
|
||||||
|
|
||||||
//DEBUG_EXTRA(" pcb->state=%x", conn->TCP_pcb->state);
|
//DEBUG_EXTRA(" pcb->state=%x", vs->TCP_pcb->state);
|
||||||
//if(conn->TCP_pcb->state != CLOSED) {
|
//if(vs->TCP_pcb->state != CLOSED) {
|
||||||
// DEBUG_INFO(" cannot connect using this PCB, PCB!=CLOSED");
|
// DEBUG_INFO(" cannot connect using this PCB, PCB!=CLOSED");
|
||||||
// tap->sendReturnValue(tap->_phy.getDescriptor(rpcSock), -1, EAGAIN);
|
// tap->sendReturnValue(tap->_phy.getDescriptor(rpcSock), -1, EAGAIN);
|
||||||
// return;
|
// return;
|
||||||
@@ -343,7 +343,7 @@ namespace ZeroTier
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lwIP::lwip_Bind(SocketTap *tap, Connection *conn, const struct sockaddr *addr, socklen_t addrlen)
|
int lwIP::lwip_Bind(VirtualTap *tap, VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
ip_addr_t ba;
|
ip_addr_t ba;
|
||||||
@@ -363,26 +363,26 @@ namespace ZeroTier
|
|||||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr;
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr;
|
||||||
in6_to_ip6((ip6_addr *)&ba, in6);
|
in6_to_ip6((ip6_addr *)&ba, in6);
|
||||||
if(addr->sa_family == AF_INET6) {
|
if(addr->sa_family == AF_INET6) {
|
||||||
struct sockaddr_in6 *connaddr6 = (struct sockaddr_in6 *)addr;
|
struct sockaddr_in6 *vsaddr6 = (struct sockaddr_in6 *)addr;
|
||||||
inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN);
|
inet_ntop(AF_INET6, &(connaddr6->sin6_addr), addrstr, INET6_ADDRSTRLEN);
|
||||||
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port));
|
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(conn->socket_type == SOCK_DGRAM) {
|
if(vs->socket_type == SOCK_DGRAM) {
|
||||||
err = udp_bind((struct udp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port);
|
err = udp_bind((struct udp_pcb*)vs->pcb, (const ip_addr_t *)&ba, port);
|
||||||
if(err == ERR_USE) {
|
if(err == ERR_USE) {
|
||||||
err = -1;
|
err = -1;
|
||||||
errno = EADDRINUSE; // port in use
|
errno = EADDRINUSE; // port in use
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// set the recv callback
|
// set the recv callback
|
||||||
udp_recv((struct udp_pcb*)conn->pcb, nc_udp_recved, new ConnectionPair(tap, conn));
|
udp_recv((struct udp_pcb*)vs->pcb, nc_udp_recved, new VirtualBindingPair(tap, vs));
|
||||||
err = ERR_OK;
|
err = ERR_OK;
|
||||||
errno = ERR_OK; // success
|
errno = ERR_OK; // success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (conn->socket_type == SOCK_STREAM) {
|
else if (vs->socket_type == SOCK_STREAM) {
|
||||||
err = tcp_bind((struct tcp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port);
|
err = tcp_bind((struct tcp_pcb*)vs->pcb, (const ip_addr_t *)&ba, port);
|
||||||
if(err != ERR_OK) {
|
if(err != ERR_OK) {
|
||||||
DEBUG_ERROR("err=%d", err);
|
DEBUG_ERROR("err=%d", err);
|
||||||
if(err == ERR_USE){
|
if(err == ERR_USE){
|
||||||
@@ -406,103 +406,103 @@ namespace ZeroTier
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lwIP::lwip_Listen(Connection *conn, int backlog)
|
int lwIP::lwip_Listen(VirtualSocket *vs, int backlog)
|
||||||
{
|
{
|
||||||
DEBUG_INFO("conn=%p", conn);
|
DEBUG_INFO("vs=%p", vs);
|
||||||
struct tcp_pcb* listeningPCB;
|
struct tcp_pcb* listeningPCB;
|
||||||
#ifdef TCP_LISTEN_BACKLOG
|
#ifdef TCP_LISTEN_BACKLOG
|
||||||
listeningPCB = tcp_listen_with_backlog((struct tcp_pcb*)conn->pcb, backlog);
|
listeningPCB = tcp_listen_with_backlog((struct tcp_pcb*)vs->pcb, backlog);
|
||||||
#else
|
#else
|
||||||
listeningPCB = tcp_listen((struct tcp_pcb*)conn->pcb);
|
listeningPCB = tcp_listen((struct tcp_pcb*)vs->pcb);
|
||||||
#endif
|
#endif
|
||||||
if(listeningPCB != NULL) {
|
if(listeningPCB != NULL) {
|
||||||
conn->pcb = listeningPCB;
|
vs->pcb = listeningPCB;
|
||||||
tcp_accept(listeningPCB, nc_accept); // set callback
|
tcp_accept(listeningPCB, nc_accept); // set callback
|
||||||
tcp_arg(listeningPCB, conn);
|
tcp_arg(listeningPCB, vs);
|
||||||
//fcntl(tap->_phy.getDescriptor(conn->sock), F_SETFL, O_NONBLOCK);
|
//fcntl(tap->_phy.getDescriptor(vs->sock), F_SETFL, O_NONBLOCK);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection* lwIP::lwip_Accept(Connection *conn)
|
VirtualSocket* lwIP::lwip_Accept(VirtualSocket *vs)
|
||||||
{
|
{
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("invalid conn");
|
DEBUG_ERROR("invalid virtual socket");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Retreive first of queued Connections from parent connection
|
// Retreive first of queued VirtualSockets from parent VirtualSocket
|
||||||
Connection *new_conn = NULL;
|
VirtualSocket *new_vs = NULL;
|
||||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||||
if(conn->_AcceptedConnections.size()) {
|
if(vs->_AcceptedConnections.size()) {
|
||||||
new_conn = conn->_AcceptedConnections.front();
|
new_vs = vs->_AcceptedConnections.front();
|
||||||
conn->_AcceptedConnections.pop();
|
vs->_AcceptedConnections.pop();
|
||||||
}
|
}
|
||||||
return new_conn;
|
return new_vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lwIP::lwip_Read(Connection *conn, bool lwip_invoked)
|
int lwIP::lwip_Read(VirtualSocket *vs, bool lwip_invoked)
|
||||||
{
|
{
|
||||||
DEBUG_EXTRA("conn=%p", conn);
|
DEBUG_EXTRA("vs=%p", vs);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("no connection");
|
DEBUG_ERROR("no VirtualSocket");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(!lwip_invoked) {
|
if(!lwip_invoked) {
|
||||||
DEBUG_INFO("!lwip_invoked");
|
DEBUG_INFO("!lwip_invoked");
|
||||||
conn->tap->_tcpconns_m.lock();
|
vs->tap->_tcpconns_m.lock();
|
||||||
conn->_rx_m.lock();
|
vs->_rx_m.lock();
|
||||||
}
|
}
|
||||||
if(conn->RXbuf->count()) {
|
if(vs->RXbuf->count()) {
|
||||||
int max = conn->socket_type == SOCK_STREAM ? ZT_STACK_TCP_SOCKET_RX_SZ : ZT_STACK_TCP_SOCKET_RX_SZ;
|
int max = vs->socket_type == SOCK_STREAM ? ZT_STACK_TCP_SOCKET_RX_SZ : ZT_STACK_TCP_SOCKET_RX_SZ;
|
||||||
int wr = std::min((ssize_t)max, (ssize_t)conn->RXbuf->count());
|
int wr = std::min((ssize_t)max, (ssize_t)vs->RXbuf->count());
|
||||||
int n = conn->tap->_phy.streamSend(conn->sock, conn->RXbuf->get_buf(), wr);
|
int n = vs->tap->_phy.streamSend(vs->sock, vs->RXbuf->get_buf(), wr);
|
||||||
char str[22];
|
char str[22];
|
||||||
memcpy(str, conn->RXbuf->get_buf(), 22);
|
memcpy(str, vs->RXbuf->get_buf(), 22);
|
||||||
conn->RXbuf->consume(n);
|
vs->RXbuf->consume(n);
|
||||||
|
|
||||||
if(conn->socket_type == SOCK_DGRAM)
|
if(vs->socket_type == SOCK_DGRAM)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
if(conn->socket_type == SOCK_STREAM) { // Only acknolwedge receipt of TCP packets
|
if(vs->socket_type == SOCK_STREAM) { // Only acknolwedge receipt of TCP packets
|
||||||
tcp_recved((struct tcp_pcb*)conn->pcb, n);
|
tcp_recved((struct tcp_pcb*)vs->pcb, n);
|
||||||
DEBUG_TRANS("TCP RX %d bytes", n);
|
DEBUG_TRANS("TCP RX %d bytes", n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conn->RXbuf->count() == 0) {
|
if(vs->RXbuf->count() == 0) {
|
||||||
DEBUG_INFO("wrote everything");
|
DEBUG_INFO("wrote everything");
|
||||||
conn->tap->_phy.setNotifyWritable(conn->sock, false); // nothing else to send to the app
|
vs->tap->_phy.setNotifyWritable(vs->sock, false); // nothing else to send to the app
|
||||||
}
|
}
|
||||||
if(!lwip_invoked) {
|
if(!lwip_invoked) {
|
||||||
conn->tap->_tcpconns_m.unlock();
|
vs->tap->_tcpconns_m.unlock();
|
||||||
conn->_rx_m.unlock();
|
vs->_rx_m.unlock();
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lwIP::lwip_Write(Connection *conn, void *data, ssize_t len)
|
int lwIP::lwip_Write(VirtualSocket *vs, void *data, ssize_t len)
|
||||||
{
|
{
|
||||||
DEBUG_EXTRA("conn=%p, len=%d", (void*)&conn, len);
|
DEBUG_EXTRA("vs=%p, len=%d", (void*)&vs, len);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("no connection");
|
DEBUG_ERROR("no VirtualSocket");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(conn->socket_type == SOCK_DGRAM)
|
if(vs->socket_type == SOCK_DGRAM)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("socket_type==SOCK_DGRAM");
|
DEBUG_ERROR("socket_type==SOCK_DGRAM");
|
||||||
// TODO: Packet re-assembly hasn't yet been tested with lwIP so UDP packets are limited to MTU-sized chunks
|
// TODO: Packet re-assembly hasn't yet been tested with lwIP so UDP packets are limited to MTU-sized chunks
|
||||||
int udp_trans_len = std::min((ssize_t)conn->TXbuf->count(), (ssize_t)ZT_MAX_MTU);
|
int udp_trans_len = std::min((ssize_t)vs->TXbuf->count(), (ssize_t)ZT_MAX_MTU);
|
||||||
DEBUG_EXTRA("allocating pbuf chain of size=%d for UDP packet, txsz=%d", udp_trans_len, conn->TXbuf->count());
|
DEBUG_EXTRA("allocating pbuf chain of size=%d for UDP packet, txsz=%d", udp_trans_len, vs->TXbuf->count());
|
||||||
struct pbuf * pb = pbuf_alloc(PBUF_TRANSPORT, udp_trans_len, PBUF_POOL);
|
struct pbuf * pb = pbuf_alloc(PBUF_TRANSPORT, udp_trans_len, PBUF_POOL);
|
||||||
if(!pb){
|
if(!pb){
|
||||||
DEBUG_ERROR("unable to allocate new pbuf of size=%d", conn->TXbuf->count());
|
DEBUG_ERROR("unable to allocate new pbuf of size=%d", vs->TXbuf->count());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(pb->payload, conn->TXbuf->get_buf(), udp_trans_len);
|
memcpy(pb->payload, vs->TXbuf->get_buf(), udp_trans_len);
|
||||||
int err = udp_send((struct udp_pcb*)conn->pcb, pb);
|
int err = udp_send((struct udp_pcb*)vs->pcb, pb);
|
||||||
|
|
||||||
if(err == ERR_MEM) {
|
if(err == ERR_MEM) {
|
||||||
DEBUG_ERROR("error sending packet. out of memory");
|
DEBUG_ERROR("error sending packet. out of memory");
|
||||||
@@ -511,48 +511,48 @@ namespace ZeroTier
|
|||||||
} else if(err != ERR_OK) {
|
} else if(err != ERR_OK) {
|
||||||
DEBUG_ERROR("error sending packet - %d", err);
|
DEBUG_ERROR("error sending packet - %d", err);
|
||||||
} else {
|
} else {
|
||||||
conn->TXbuf->consume(udp_trans_len); // success
|
vs->TXbuf->consume(udp_trans_len); // success
|
||||||
}
|
}
|
||||||
pbuf_free(pb);
|
pbuf_free(pb);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
if(conn->socket_type == SOCK_STREAM)
|
if(vs->socket_type == SOCK_STREAM)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("socket_type==SOCK_STREAM");
|
DEBUG_ERROR("socket_type==SOCK_STREAM");
|
||||||
// How much we are currently allowed to write to the connection
|
// How much we are currently allowed to write to the VirtualSocket
|
||||||
ssize_t sndbuf = ((struct tcp_pcb*)conn->pcb)->snd_buf;
|
ssize_t sndbuf = ((struct tcp_pcb*)vs->pcb)->snd_buf;
|
||||||
int err, r;
|
int err, r;
|
||||||
if(!sndbuf) {
|
if(!sndbuf) {
|
||||||
// PCB send buffer is full, turn off readability notifications for the
|
// PCB send buffer is full, turn off readability notifications for the
|
||||||
// corresponding PhySocket until nc_sent() is called and confirms that there is
|
// corresponding PhySocket until nc_sent() is called and confirms that there is
|
||||||
// now space on the buffer
|
// now space on the buffer
|
||||||
DEBUG_ERROR("lwIP stack is full, sndbuf == 0");
|
DEBUG_ERROR("lwIP stack is full, sndbuf == 0");
|
||||||
conn->tap->_phy.setNotifyReadable(conn->sock, false);
|
vs->tap->_phy.setNotifyReadable(vs->sock, false);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int buf_w = conn->TXbuf->write((const unsigned char*)data, len);
|
int buf_w = vs->TXbuf->write((const unsigned char*)data, len);
|
||||||
if (buf_w != len) {
|
if (buf_w != len) {
|
||||||
// because we checked ZT_TCP_TX_BUF_SZ above, this should not happen
|
// because we checked ZT_TCP_TX_BUF_SZ above, this should not happen
|
||||||
DEBUG_ERROR("TX wrote only %d but expected to write %d", buf_w, len);
|
DEBUG_ERROR("TX wrote only %d but expected to write %d", buf_w, len);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
if(conn->TXbuf->count() <= 0) {
|
if(vs->TXbuf->count() <= 0) {
|
||||||
return -1; // nothing to write
|
return -1; // nothing to write
|
||||||
}
|
}
|
||||||
if(conn->sock) {
|
if(vs->sock) {
|
||||||
r = std::min((ssize_t)conn->TXbuf->count(), sndbuf);
|
r = std::min((ssize_t)vs->TXbuf->count(), sndbuf);
|
||||||
// Writes data pulled from the client's socket buffer to LWIP. This merely sends the
|
// Writes data pulled from the client's socket buffer to LWIP. This merely sends the
|
||||||
// data to LWIP to be enqueued and eventually sent to the network.
|
// data to LWIP to be enqueued and eventually sent to the network.
|
||||||
if(r > 0) {
|
if(r > 0) {
|
||||||
err = tcp_write((struct tcp_pcb*)conn->pcb, conn->TXbuf->get_buf(), r, TCP_WRITE_FLAG_COPY);
|
err = tcp_write((struct tcp_pcb*)vs->pcb, vs->TXbuf->get_buf(), r, TCP_WRITE_FLAG_COPY);
|
||||||
tcp_output((struct tcp_pcb*)conn->pcb);
|
tcp_output((struct tcp_pcb*)vs->pcb);
|
||||||
if(err != ERR_OK) {
|
if(err != ERR_OK) {
|
||||||
DEBUG_ERROR("error while writing to lwIP tcp_pcb, err=%d", err);
|
DEBUG_ERROR("error while writing to lwIP tcp_pcb, err=%d", err);
|
||||||
if(err == -1)
|
if(err == -1)
|
||||||
DEBUG_ERROR("lwIP out of memory");
|
DEBUG_ERROR("lwIP out of memory");
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
conn->TXbuf->consume(r); // success
|
vs->TXbuf->consume(r); // success
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -561,22 +561,22 @@ namespace ZeroTier
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lwIP::lwip_Close(Connection *conn)
|
int lwIP::lwip_Close(VirtualSocket *vs)
|
||||||
{
|
{
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
|
|
||||||
if(conn->socket_type == SOCK_DGRAM) {
|
if(vs->socket_type == SOCK_DGRAM) {
|
||||||
udp_remove((struct udp_pcb*)conn->pcb);
|
udp_remove((struct udp_pcb*)vs->pcb);
|
||||||
}
|
}
|
||||||
// FIXME: check if already closed? conn->TCP_pcb->state != CLOSED
|
// FIXME: check if already closed? vs->TCP_pcb->state != CLOSED
|
||||||
if(conn->pcb) {
|
if(vs->pcb) {
|
||||||
//DEBUG_EXTRA("conn=%p, sock=%p, PCB->state = %d",
|
//DEBUG_EXTRA("vs=%p, sock=%p, PCB->state = %d",
|
||||||
// (void*)&conn, (void*)&sock, conn->TCP_pcb->state);
|
// (void*)&conn, (void*)&sock, vs->TCP_pcb->state);
|
||||||
if(((struct tcp_pcb*)conn->pcb)->state == SYN_SENT /*|| conn->TCP_pcb->state == CLOSE_WAIT*/) {
|
if(((struct tcp_pcb*)vs->pcb)->state == SYN_SENT /*|| vs->TCP_pcb->state == CLOSE_WAIT*/) {
|
||||||
DEBUG_EXTRA("ignoring close request. invalid PCB state for this operation. sock=%p", conn->sock);
|
DEBUG_EXTRA("ignoring close request. invalid PCB state for this operation. sock=%p", vs->sock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
struct tcp_pcb* tpcb = (struct tcp_pcb*)conn->pcb;
|
struct tcp_pcb* tpcb = (struct tcp_pcb*)vs->pcb;
|
||||||
if(tcp_close(tpcb) == ERR_OK) {
|
if(tcp_close(tpcb) == ERR_OK) {
|
||||||
// Unregister callbacks for this PCB
|
// Unregister callbacks for this PCB
|
||||||
tcp_arg(tpcb, NULL);
|
tcp_arg(tpcb, NULL);
|
||||||
@@ -586,7 +586,7 @@ namespace ZeroTier
|
|||||||
tcp_poll(tpcb, NULL, 1);
|
tcp_poll(tpcb, NULL, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG_EXTRA("error while calling tcp_close() sock=%p", conn->sock);
|
DEBUG_EXTRA("error while calling tcp_close() sock=%p", vs->sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -599,22 +599,22 @@ namespace ZeroTier
|
|||||||
err_t lwIP::nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err)
|
err_t lwIP::nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err)
|
||||||
{
|
{
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
Connection *conn = (Connection *)arg;
|
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||||
int tot = 0;
|
int tot = 0;
|
||||||
|
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("no connection");
|
DEBUG_ERROR("no VirtualSocket");
|
||||||
return ERR_OK; // FIXME: Determine if this is correct behaviour expected by the stack
|
return ERR_OK; // FIXME: Determine if this is correct behaviour expected by the stack
|
||||||
}
|
}
|
||||||
|
|
||||||
//Mutex::Lock _l(conn->tap->_tcpconns_m);
|
//Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||||
//Mutex::Lock _l2(conn->_rx_m);
|
//Mutex::Lock _l2(vs->_rx_m);
|
||||||
conn->tap->_tcpconns_m.lock();
|
vs->tap->_tcpconns_m.lock();
|
||||||
conn->_rx_m.lock();
|
vs->_rx_m.lock();
|
||||||
|
|
||||||
struct pbuf* q = p;
|
struct pbuf* q = p;
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
if(((struct tcp_pcb*)conn->pcb)->state == CLOSE_WAIT) {
|
if(((struct tcp_pcb*)vs->pcb)->state == CLOSE_WAIT) {
|
||||||
// FIXME: Implement?
|
// FIXME: Implement?
|
||||||
}
|
}
|
||||||
DEBUG_INFO("p == NULL");
|
DEBUG_INFO("p == NULL");
|
||||||
@@ -626,24 +626,24 @@ namespace ZeroTier
|
|||||||
while(p != NULL) {
|
while(p != NULL) {
|
||||||
if(p->len <= 0)
|
if(p->len <= 0)
|
||||||
break;
|
break;
|
||||||
int avail = ZT_TCP_RX_BUF_SZ - conn->RXbuf->count();
|
int avail = ZT_TCP_RX_BUF_SZ - vs->RXbuf->count();
|
||||||
int len = p->len;
|
int len = p->len;
|
||||||
if(avail < len) {
|
if(avail < len) {
|
||||||
DEBUG_ERROR("not enough room (%d bytes) on RX buffer", avail);
|
DEBUG_ERROR("not enough room (%d bytes) on RX buffer", avail);
|
||||||
}
|
}
|
||||||
memcpy(conn->RXbuf->get_buf(), p->payload, len);
|
memcpy(vs->RXbuf->get_buf(), p->payload, len);
|
||||||
conn->RXbuf->produce(len);
|
vs->RXbuf->produce(len);
|
||||||
p = p->next;
|
p = p->next;
|
||||||
tot += len;
|
tot += len;
|
||||||
}
|
}
|
||||||
DEBUG_INFO("tot=%d", tot);
|
DEBUG_INFO("tot=%d", tot);
|
||||||
|
|
||||||
conn->tap->_tcpconns_m.unlock();
|
vs->tap->_tcpconns_m.unlock();
|
||||||
conn->_rx_m.unlock();
|
vs->_rx_m.unlock();
|
||||||
|
|
||||||
if(tot) {
|
if(tot) {
|
||||||
conn->tap->_phy.setNotifyWritable(conn->sock, true);
|
vs->tap->_phy.setNotifyWritable(vs->sock, true);
|
||||||
//conn->tap->phyOnUnixWritable(conn->sock, NULL, true); // to app
|
//vs->tap->phyOnUnixWritable(vs->sock, NULL, true); // to app
|
||||||
}
|
}
|
||||||
pbuf_free(q);
|
pbuf_free(q);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
@@ -651,27 +651,27 @@ namespace ZeroTier
|
|||||||
|
|
||||||
err_t lwIP::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err)
|
err_t lwIP::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err)
|
||||||
{
|
{
|
||||||
Connection *conn = (Connection*)arg;
|
VirtualSocket *vs = (VirtualSocket*)arg;
|
||||||
DEBUG_INFO("conn=%p", conn);
|
DEBUG_INFO("vs=%p", vs);
|
||||||
//Mutex::Lock _l(conn->tap->_tcpconns_m);
|
//Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||||
// create and populate new Connection object
|
// create and populate new VirtualSocket object
|
||||||
Connection *new_conn = new Connection();
|
VirtualSocket *new_vs = new VirtualSocket();
|
||||||
new_conn->socket_type = SOCK_STREAM;
|
new_vs->socket_type = SOCK_STREAM;
|
||||||
new_conn->pcb = newPCB;
|
new_vs->pcb = newPCB;
|
||||||
new_conn->tap = conn->tap;
|
new_vs->tap = vs->tap;
|
||||||
new_conn->sock = conn->tap->_phy.wrapSocket(new_conn->sdk_fd, new_conn);
|
new_vs->sock = vs->tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs);
|
||||||
//memcpy(new_conn->tap->_phy.getuptr(new_conn->sock), new_conn, sizeof(conn));
|
//memcpy(new_vs->tap->_phy.getuptr(new_vs->sock), new_vs, sizeof(vs));
|
||||||
DEBUG_INFO("new_conn=%p", new_conn);
|
DEBUG_INFO("new_vs=%p", new_vs);
|
||||||
// add new Connection object to parent connection so that we can find it via lwip_Accept()
|
// add new VirtualSocket object to parent VirtualSocket so that we can find it via lwip_Accept()
|
||||||
conn->_AcceptedConnections.push(new_conn);
|
vs->_AcceptedConnections.push(new_vs);
|
||||||
// set callbacks
|
// set callbacks
|
||||||
tcp_arg(newPCB, new_conn);
|
tcp_arg(newPCB, new_vs);
|
||||||
tcp_recv(newPCB, nc_recved);
|
tcp_recv(newPCB, nc_recved);
|
||||||
tcp_err(newPCB, nc_err);
|
tcp_err(newPCB, nc_err);
|
||||||
tcp_sent(newPCB, nc_sent);
|
tcp_sent(newPCB, nc_sent);
|
||||||
tcp_poll(newPCB, nc_poll, 1);
|
tcp_poll(newPCB, nc_poll, 1);
|
||||||
// let lwIP know that it can queue additional incoming connections
|
// let lwIP know that it can queue additional incoming VirtualSockets
|
||||||
tcp_accepted((struct tcp_pcb*)conn->pcb);
|
tcp_accepted((struct tcp_pcb*)vs->pcb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -684,13 +684,13 @@ namespace ZeroTier
|
|||||||
err_t lwIP::nc_sent(void* arg, struct tcp_pcb *PCB, u16_t len)
|
err_t lwIP::nc_sent(void* arg, struct tcp_pcb *PCB, u16_t len)
|
||||||
{
|
{
|
||||||
DEBUG_EXTRA("pcb=%p", (void*)&PCB);
|
DEBUG_EXTRA("pcb=%p", (void*)&PCB);
|
||||||
Connection *conn = (Connection *)arg;
|
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||||
if(conn && len) {
|
if(vs && len) {
|
||||||
int softmax = conn->socket_type == SOCK_STREAM ? ZT_TCP_TX_BUF_SZ : ZT_UDP_TX_BUF_SZ;
|
int softmax = vs->socket_type == SOCK_STREAM ? ZT_TCP_TX_BUF_SZ : ZT_UDP_TX_BUF_SZ;
|
||||||
if(conn->TXbuf->count() < softmax) {
|
if(vs->TXbuf->count() < softmax) {
|
||||||
conn->tap->_phy.setNotifyReadable(conn->sock, true);
|
vs->tap->_phy.setNotifyReadable(vs->sock, true);
|
||||||
conn->tap->_phy.whack();
|
vs->tap->_phy.whack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
@@ -699,8 +699,8 @@ namespace ZeroTier
|
|||||||
err_t lwIP::nc_connected(void *arg, struct tcp_pcb *PCB, err_t err)
|
err_t lwIP::nc_connected(void *arg, struct tcp_pcb *PCB, err_t err)
|
||||||
{
|
{
|
||||||
DEBUG_ATTN("pcb=%p", (void*)&PCB);
|
DEBUG_ATTN("pcb=%p", (void*)&PCB);
|
||||||
Connection *conn = (Connection *)arg;
|
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||||
if(conn)
|
if(vs)
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
return -1;
|
return -1;
|
||||||
// FIXME: check stack for expected return values
|
// FIXME: check stack for expected return values
|
||||||
@@ -714,16 +714,16 @@ namespace ZeroTier
|
|||||||
void lwIP::nc_err(void *arg, err_t err)
|
void lwIP::nc_err(void *arg, err_t err)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("err=%d", err);
|
DEBUG_ERROR("err=%d", err);
|
||||||
Connection *conn = (Connection *)arg;
|
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||||
if(!conn){
|
if(!vs){
|
||||||
DEBUG_ERROR("conn==NULL");
|
DEBUG_ERROR("vs==NULL");
|
||||||
errno = -1; // FIXME: Find more appropriate value
|
errno = -1; // FIXME: Find more appropriate value
|
||||||
}
|
}
|
||||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||||
int fd = conn->tap->_phy.getDescriptor(conn->sock);
|
int fd = vs->tap->_phy.getDescriptor(vs->sock);
|
||||||
DEBUG_ERROR("conn=%p, pcb=%p, fd=%d, err=%d", conn, conn->pcb, fd, err);
|
DEBUG_ERROR("vs=%p, pcb=%p, fd=%d, err=%d", vs, vs->pcb, fd, err);
|
||||||
DEBUG_ERROR("closing connection");
|
DEBUG_ERROR("closing VirtualSocket");
|
||||||
conn->tap->Close(conn);
|
vs->tap->Close(vs);
|
||||||
switch(err)
|
switch(err)
|
||||||
{
|
{
|
||||||
case ERR_MEM:
|
case ERR_MEM:
|
||||||
@@ -759,7 +759,7 @@ namespace ZeroTier
|
|||||||
errno = EADDRINUSE;
|
errno = EADDRINUSE;
|
||||||
break;
|
break;
|
||||||
case ERR_ISCONN:
|
case ERR_ISCONN:
|
||||||
DEBUG_ERROR("ERR_ISCONN->EISCONN");
|
DEBUG_ERROR("ERR_ISvs->EISCONN");
|
||||||
errno = EISCONN;
|
errno = EISCONN;
|
||||||
break;
|
break;
|
||||||
case ERR_ABRT:
|
case ERR_ABRT:
|
||||||
|
|||||||
28
src/lwIP.hpp
28
src/lwIP.hpp
@@ -45,7 +45,7 @@
|
|||||||
#include "OSUtils.hpp"
|
#include "OSUtils.hpp"
|
||||||
|
|
||||||
#include "libzt.h"
|
#include "libzt.h"
|
||||||
#include "SocketTap.hpp"
|
#include "VirtualTap.hpp"
|
||||||
|
|
||||||
struct tcp_pcb;
|
struct tcp_pcb;
|
||||||
struct netif;
|
struct netif;
|
||||||
@@ -162,36 +162,36 @@ extern "C" err_t ip_input(LWIP_IP_INPUT_SIG);
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class SocketTap;
|
class VirtualTap;
|
||||||
struct Connection;
|
struct VirtualSocket;
|
||||||
|
|
||||||
class lwIP
|
class lwIP
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up an interface in the network stack for the SocketTap
|
* Set up an interface in the network stack for the VirtualTap
|
||||||
*/
|
*/
|
||||||
void lwip_init_interface(SocketTap *tap, const InetAddress &ip);
|
void lwip_init_interface(VirtualTap *tap, const InetAddress &ip);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main stack loop
|
* Main stack loop
|
||||||
*/
|
*/
|
||||||
void lwip_loop(SocketTap *tap);
|
void lwip_loop(VirtualTap *tap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Packets from the ZeroTier virtual wire enter the stack here
|
* Packets from the ZeroTier virtual wire enter the stack here
|
||||||
*/
|
*/
|
||||||
void lwip_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
void lwip_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||||
|
|
||||||
int lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol);
|
int lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol);
|
||||||
int lwip_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
|
int lwip_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
int lwip_Bind(SocketTap *tap, Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
|
int lwip_Bind(VirtualTap *tap, VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
int lwip_Listen(Connection *conn, int backlog);
|
int lwip_Listen(VirtualSocket *vs, int backlog);
|
||||||
Connection* lwip_Accept(Connection *conn);
|
VirtualSocket* lwip_Accept(VirtualSocket *vs);
|
||||||
int lwip_Read(Connection *conn, bool lwip_invoked);
|
int lwip_Read(VirtualSocket *vs, bool lwip_invoked);
|
||||||
int lwip_Write(Connection *conn, void *data, ssize_t len);
|
int lwip_Write(VirtualSocket *vs, void *data, ssize_t len);
|
||||||
int lwip_Close(Connection *conn);
|
int lwip_Close(VirtualSocket *vs);
|
||||||
|
|
||||||
static err_t nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err);
|
static err_t nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err);
|
||||||
static err_t nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err);
|
static err_t nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err);
|
||||||
|
|||||||
349
src/picoTCP.cpp
349
src/picoTCP.cpp
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
#include "libzt.h"
|
#include "libzt.h"
|
||||||
#include "Utilities.hpp"
|
#include "Utilities.hpp"
|
||||||
#include "SocketTap.hpp"
|
#include "VirtualTap.hpp"
|
||||||
#include "picoTCP.hpp"
|
#include "picoTCP.hpp"
|
||||||
#include "RingBuffer.hpp"
|
#include "RingBuffer.hpp"
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
struct pico_device picodev;
|
struct pico_device picodev;
|
||||||
|
|
||||||
bool picoTCP::pico_init_interface(SocketTap *tap, const InetAddress &ip)
|
bool picoTCP::pico_init_interface(VirtualTap *tap, const InetAddress &ip)
|
||||||
{
|
{
|
||||||
char ipbuf[64];
|
char ipbuf[64];
|
||||||
if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) {
|
if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) {
|
||||||
@@ -136,7 +136,7 @@ namespace ZeroTier {
|
|||||||
// pico_ipv6_route_add
|
// pico_ipv6_route_add
|
||||||
// pico_ipv6_route_del
|
// pico_ipv6_route_del
|
||||||
|
|
||||||
bool picoTCP::pico_route_add(SocketTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric)
|
bool picoTCP::pico_route_add(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric)
|
||||||
{
|
{
|
||||||
struct pico_ipv4_link *link = NULL;
|
struct pico_ipv4_link *link = NULL;
|
||||||
struct pico_ip4 address;
|
struct pico_ip4 address;
|
||||||
@@ -152,7 +152,7 @@ namespace ZeroTier {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool picoTCP::pico_route_del(SocketTap *tap, const InetAddress &addr, const InetAddress &nm, int metric)
|
bool picoTCP::pico_route_del(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, int metric)
|
||||||
{
|
{
|
||||||
struct pico_ip4 address;
|
struct pico_ip4 address;
|
||||||
address.addr = *((uint32_t *)addr.rawIpData());
|
address.addr = *((uint32_t *)addr.rawIpData());
|
||||||
@@ -165,7 +165,7 @@ namespace ZeroTier {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void picoTCP::pico_loop(SocketTap *tap)
|
void picoTCP::pico_loop(VirtualTap *tap)
|
||||||
{
|
{
|
||||||
while(tap->_run)
|
while(tap->_run)
|
||||||
{
|
{
|
||||||
@@ -176,13 +176,13 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// from stack socket to app socket
|
// from stack socket to app socket
|
||||||
void picoTCP::pico_cb_tcp_read(ZeroTier::SocketTap *tap, struct pico_socket *s)
|
void picoTCP::pico_cb_tcp_read(ZeroTier::VirtualTap *tap, struct pico_socket *s)
|
||||||
{
|
{
|
||||||
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
|
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||||
Mutex::Lock _l(conn->_rx_m);
|
Mutex::Lock _l(vs->_rx_m);
|
||||||
|
|
||||||
if(!conn || !tap) {
|
if(!vs || !tap) {
|
||||||
DEBUG_ERROR("invalid tap or conn");
|
DEBUG_ERROR("invalid tap or vs");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -196,37 +196,32 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
n = 0;
|
n = 0;
|
||||||
//DEBUG_INFO("RXbuf->count() = %d", conn->RXbuf->count());
|
//DEBUG_INFO("RXbuf->count() = %d", vs->RXbuf->count());
|
||||||
int avail = ZT_TCP_RX_BUF_SZ - conn->RXbuf->count();
|
int avail = ZT_TCP_RX_BUF_SZ - vs->RXbuf->count();
|
||||||
if(avail) {
|
if(avail) {
|
||||||
|
r = pico_socket_recvfrom(s, vs->RXbuf->get_buf(), ZT_STACK_SOCKET_RD_MAX,
|
||||||
r = pico_socket_recvfrom(s, conn->RXbuf->get_buf(), ZT_STACK_SOCKET_RD_MAX,
|
|
||||||
(void *)&peer.ip4.addr, &port);
|
(void *)&peer.ip4.addr, &port);
|
||||||
|
|
||||||
conn->tot += r;
|
|
||||||
|
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
{
|
{
|
||||||
conn->RXbuf->produce(r);
|
vs->RXbuf->produce(r);
|
||||||
//DEBUG_INFO("RXbuf->count() = %d", conn->RXbuf->count());
|
//DEBUG_INFO("RXbuf->count() = %d", vs->RXbuf->count());
|
||||||
n = tap->_phy.streamSend(conn->sock, conn->RXbuf->get_buf(), r);
|
n = tap->_phy.streamSend(vs->sock, vs->RXbuf->get_buf(), r);
|
||||||
|
|
||||||
if(n>0)
|
if(n>0)
|
||||||
conn->RXbuf->consume(n);
|
vs->RXbuf->consume(n);
|
||||||
//DEBUG_INFO("pico_recv = %d, streamSend = %d, rxsz = %d, tot = %d", r, n, conn->RXbuf->count(), conn->tot);
|
//DEBUG_INFO("pico_recv = %d, streamSend = %d, rxsz = %d, tot = %d", r, n, vs->RXbuf->count(), vs->tot);
|
||||||
|
|
||||||
//DEBUG_TRANS("[ TCP RX <- STACK] :: conn = %p, len = %d", conn, n);
|
//DEBUG_TRANS("[ TCP RX <- STACK] :: vs = %p, len = %d", vs, n);
|
||||||
}
|
}
|
||||||
|
if(vs->RXbuf->count() == 0) {
|
||||||
if(conn->RXbuf->count() == 0) {
|
tap->_phy.setNotifyWritable(vs->sock, false);
|
||||||
tap->_phy.setNotifyWritable(conn->sock, false);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tap->_phy.setNotifyWritable(conn->sock, true);
|
tap->_phy.setNotifyWritable(vs->sock, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//tap->_phy.setNotifyWritable(conn->sock, false);
|
//tap->_phy.setNotifyWritable(vs->sock, false);
|
||||||
DEBUG_ERROR("not enough space left on I/O RX buffer for pico_socket(%p)", s);
|
DEBUG_ERROR("not enough space left on I/O RX buffer for pico_socket(%p)", s);
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
}
|
}
|
||||||
@@ -235,13 +230,13 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// from stack socket to app socket
|
// from stack socket to app socket
|
||||||
void picoTCP::pico_cb_udp_read(SocketTap *tap, struct pico_socket *s)
|
void picoTCP::pico_cb_udp_read(VirtualTap *tap, struct pico_socket *s)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
|
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||||
Mutex::Lock _l(conn->_rx_m);
|
Mutex::Lock _l(vs->_rx_m);
|
||||||
if(conn) {
|
if(vs) {
|
||||||
|
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
union {
|
union {
|
||||||
@@ -259,15 +254,15 @@ namespace ZeroTier {
|
|||||||
int r = pico_socket_recvfrom(s, tmpbuf, ZT_SDK_MTU, (void *)&peer.ip4.addr, &port);
|
int r = pico_socket_recvfrom(s, tmpbuf, ZT_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);
|
||||||
|
|
||||||
if(conn->rxsz == ZT_UDP_RX_BUF_SZ) { // if UDP buffer full
|
if(vs->rxsz == ZT_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 + ZT_SDK_MTU, ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU);
|
memmove(vs->rxbuf, vs->rxbuf + ZT_SDK_MTU, ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU);
|
||||||
addr_pos = conn->rxbuf + (ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); // TODO:
|
addr_pos = vs->rxbuf + (ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); // TODO:
|
||||||
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
||||||
conn->rxsz -= ZT_SDK_MTU;
|
vs->rxsz -= ZT_SDK_MTU;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addr_pos = conn->rxbuf + conn->rxsz; // where we'll prepend the size of the address
|
addr_pos = vs->rxbuf + vs->rxsz; // where we'll prepend the size of the address
|
||||||
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
||||||
}
|
}
|
||||||
payload_pos = addr_pos + sizeof(struct sockaddr_storage) + sizeof(r);
|
payload_pos = addr_pos + sizeof(struct sockaddr_storage) + sizeof(r);
|
||||||
@@ -276,7 +271,7 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
// Adjust buffer size
|
// Adjust buffer size
|
||||||
if(r) {
|
if(r) {
|
||||||
conn->rxsz += ZT_SDK_MTU;
|
vs->rxsz += ZT_SDK_MTU;
|
||||||
memcpy(sz_pos, &r, sizeof(r));
|
memcpy(sz_pos, &r, sizeof(r));
|
||||||
}
|
}
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@@ -286,38 +281,38 @@ namespace ZeroTier {
|
|||||||
tap->_rx_buf_m.unlock();
|
tap->_rx_buf_m.unlock();
|
||||||
|
|
||||||
if(r)
|
if(r)
|
||||||
tap->phyOnUnixWritable(conn->sock, NULL, true);
|
tap->phyOnUnixWritable(vs->sock, NULL, true);
|
||||||
//DEBUG_EXTRA(" Copied onto rxbuf (%d) from stack socket", r);
|
//DEBUG_EXTRA(" Copied onto rxbuf (%d) from stack socket", r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void picoTCP::pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s)
|
void picoTCP::pico_cb_tcp_write(VirtualTap *tap, struct pico_socket *s)
|
||||||
{
|
{
|
||||||
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
|
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||||
Mutex::Lock _l(conn->_tx_m);
|
Mutex::Lock _l(vs->_tx_m);
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("invalid connection");
|
DEBUG_ERROR("invalid VirtualSocket");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int txsz = conn->TXbuf->count();
|
int txsz = vs->TXbuf->count();
|
||||||
if(txsz <= 0)
|
if(txsz <= 0)
|
||||||
return;
|
return;
|
||||||
//DEBUG_INFO("TXbuf->count() = %d", conn->TXbuf->count());
|
//DEBUG_INFO("TXbuf->count() = %d", vs->TXbuf->count());
|
||||||
|
|
||||||
int r, max_write_len = std::min(std::min(txsz, ZT_SDK_MTU),ZT_STACK_SOCKET_WR_MAX);
|
int r, max_write_len = std::min(std::min(txsz, ZT_SDK_MTU),ZT_STACK_SOCKET_WR_MAX);
|
||||||
if((r = pico_socket_write(conn->picosock, conn->TXbuf->get_buf(), max_write_len)) < 0) {
|
if((r = pico_socket_write(vs->picosock, vs->TXbuf->get_buf(), max_write_len)) < 0) {
|
||||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r);
|
DEBUG_ERROR("unable to write to picosock=%p, r=%d", vs->picosock, r);
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(conn->socket_type == SOCK_STREAM) {
|
if(vs->socket_type == SOCK_STREAM) {
|
||||||
//DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r);
|
//DEBUG_TRANS("[ TCP TX -> STACK] :: vs = %p, len = %d", vs, r);
|
||||||
}
|
}
|
||||||
if(conn->socket_type == SOCK_DGRAM) {
|
if(vs->socket_type == SOCK_DGRAM) {
|
||||||
//DEBUG_TRANS("[ UDP TX -> STACK] :: conn = %p, len = %d", conn, r);
|
//DEBUG_TRANS("[ UDP TX -> STACK] :: vs = %p, len = %d", vs, r);
|
||||||
}
|
}
|
||||||
if(r == 0) {
|
if(r == 0) {
|
||||||
// This is a peciliarity of the picoTCP network stack, if we receive no error code, and the size of
|
// This is a peciliarity of the picoTCP network stack, if we receive no error code, and the size of
|
||||||
@@ -326,32 +321,32 @@ namespace ZeroTier {
|
|||||||
// handle_general_failure();
|
// handle_general_failure();
|
||||||
}
|
}
|
||||||
if(r>0)
|
if(r>0)
|
||||||
conn->TXbuf->consume(r);
|
vs->TXbuf->consume(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s)
|
void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s)
|
||||||
{
|
{
|
||||||
if(!(SocketTap*)((ConnectionPair*)(s->priv)))
|
if(!(VirtualTap*)((VirtualBindingPair*)(s->priv)))
|
||||||
return;
|
return;
|
||||||
SocketTap *tap = (SocketTap*)((ConnectionPair*)(s->priv))->tap;
|
VirtualTap *tap = (VirtualTap*)((VirtualBindingPair*)(s->priv))->tap;
|
||||||
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
|
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||||
if(!tap || !conn) {
|
if(!tap || !vs) {
|
||||||
DEBUG_ERROR("invalid tap or conn");
|
DEBUG_ERROR("invalid tap or vs");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("invalid connection");
|
DEBUG_ERROR("invalid VirtualSocket");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// PICO_SOCK_EV_CONN - triggered when connection is established (TCP only). This event is
|
// PICO_SOCK_EV_vs - triggered when VirtualSocket is established (TCP only). This event is
|
||||||
// received either after a successful call to pico socket connect to indicate that the connection
|
// received either after a successful call to pico socket vsect to indicate that the VirtualSocket
|
||||||
// has been established, or on a listening socket, indicating that a call to pico socket accept
|
// has been established, or on a listening socket, indicating that a call to pico socket accept
|
||||||
// may now be issued in order to accept the incoming connection from a remote host.
|
// may now be issued in order to accept the incoming VirtualSocket from a remote host.
|
||||||
if (ev & PICO_SOCK_EV_CONN) {
|
if (ev & PICO_SOCK_EV_CONN) {
|
||||||
if(conn->state == ZT_SOCK_STATE_LISTENING)
|
if(vs->state == ZT_SOCK_STATE_LISTENING)
|
||||||
{
|
{
|
||||||
Mutex::Lock _l(tap->_tcpconns_m);
|
Mutex::Lock _l(tap->_tcpconns_m);
|
||||||
uint32_t peer;
|
uint32_t peer;
|
||||||
@@ -362,78 +357,78 @@ namespace ZeroTier {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Connection and add it to the queue,
|
// Create a new VirtualSocket and add it to the queue,
|
||||||
// some time in the future a call to zts_multiplex_accept() will pick up
|
// some time in the future a call to zts_multiplex_accept() will pick up
|
||||||
// this new connection, add it to the connection list and return its
|
// this new VirtualSocket, add it to the VirtualSocket list and return its
|
||||||
// Connection->sock to the application
|
// VirtualSocket->sock to the application
|
||||||
|
|
||||||
Connection *newConn = new Connection();
|
VirtualSocket *new_vs = new VirtualSocket();
|
||||||
newConn->socket_type = SOCK_STREAM;
|
new_vs->socket_type = SOCK_STREAM;
|
||||||
newConn->picosock = client_psock;
|
new_vs->picosock = client_psock;
|
||||||
newConn->tap = tap;
|
new_vs->tap = tap;
|
||||||
newConn->picosock->priv = new ConnectionPair(tap,newConn);
|
new_vs->picosock->priv = new VirtualBindingPair(tap,new_vs);
|
||||||
tap->_Connections.push_back(newConn);
|
tap->_VirtualSockets.push_back(new_vs);
|
||||||
conn->_AcceptedConnections.push(newConn);
|
vs->_AcceptedConnections.push(new_vs);
|
||||||
|
|
||||||
|
|
||||||
int value = 1;
|
int value = 1;
|
||||||
pico_socket_setoption(newConn->picosock, PICO_TCP_NODELAY, &value);
|
pico_socket_setoption(new_vs->picosock, PICO_TCP_NODELAY, &value);
|
||||||
|
|
||||||
if(ZT_SOCK_BEHAVIOR_LINGER) {
|
if(ZT_SOCK_BEHAVIOR_LINGER) {
|
||||||
int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME;
|
int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME;
|
||||||
int t_err = 0;
|
int t_err = 0;
|
||||||
if((t_err = pico_socket_setoption(newConn->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0)
|
if((t_err = pico_socket_setoption(new_vs->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0)
|
||||||
DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d, app_fd=%d, sdk_fd=%d", t_err, pico_err, conn->app_fd, conn->sdk_fd);
|
DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d, app_fd=%d, sdk_fd=%d", t_err, pico_err, vs->app_fd, vs->sdk_fd);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
linger_time_ms = 0;
|
linger_time_ms = 0;
|
||||||
if((t_err = pico_socket_getoption(newConn->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0)
|
if((t_err = pico_socket_getoption(new_vs->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0)
|
||||||
DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d", t_err, pico_err);
|
DEBUG_ERROR("unable to set LINGER size, err = %d, pico_err = %d", t_err, pico_err);
|
||||||
DEBUG_TEST("getting linger = %d", linger_time_ms);
|
DEBUG_TEST("getting linger = %d", linger_time_ms);
|
||||||
*/
|
*/
|
||||||
// For I/O loop participation and referencing the PhySocket's parent Connection in callbacks
|
// For I/O loop participation and referencing the PhySocket's parent VirtualSocket in callbacks
|
||||||
newConn->sock = tap->_phy.wrapSocket(newConn->sdk_fd, newConn);
|
new_vs->sock = tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs);
|
||||||
//DEBUG_ERROR("sock->fd = %d", tap->_phy.getDescriptor(newConn->sock));
|
//DEBUG_ERROR("sock->fd = %d", tap->_phy.getDescriptor(new_vs->sock));
|
||||||
|
|
||||||
}
|
}
|
||||||
if(conn->state != ZT_SOCK_STATE_LISTENING) {
|
if(vs->state != ZT_SOCK_STATE_LISTENING) {
|
||||||
// set state so socket multiplexer logic will pick this up
|
// set state so socket multiplexer logic will pick this up
|
||||||
conn->state = ZT_SOCK_STATE_UNHANDLED_CONNECTED;
|
vs->state = ZT_SOCK_STATE_UNHANDLED_CONNECTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PICO_SOCK_EV_FIN - triggered when the socket is closed. No further communication is
|
// PICO_SOCK_EV_FIN - triggered when the socket is closed. No further communication is
|
||||||
// possible from this point on the socket.
|
// possible from this point on the socket.
|
||||||
if (ev & PICO_SOCK_EV_FIN) {
|
if (ev & PICO_SOCK_EV_FIN) {
|
||||||
//DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p, conn=%p, app_fd=%d, sdk_fd=%d", s, conn, conn->app_fd, conn->sdk_fd);
|
//DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p, vs=%p, app_fd=%d, sdk_fd=%d", s, vs, vs->app_fd, vs->sdk_fd);
|
||||||
conn->closure_ts = std::time(nullptr);
|
vs->closure_ts = std::time(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PICO_SOCK_EV_ERR - triggered when an error occurs.
|
// PICO_SOCK_EV_ERR - triggered when an error occurs.
|
||||||
if (ev & PICO_SOCK_EV_ERR) {
|
if (ev & PICO_SOCK_EV_ERR) {
|
||||||
if(pico_err == PICO_ERR_ECONNRESET) {
|
if(pico_err == PICO_ERR_ECONNRESET) {
|
||||||
DEBUG_ERROR("PICO_ERR_ECONNRESET");
|
DEBUG_ERROR("PICO_ERR_ECONNRESET");
|
||||||
conn->state = PICO_ERR_ECONNRESET;
|
vs->state = PICO_ERR_ECONNRESET;
|
||||||
}
|
}
|
||||||
DEBUG_ERROR("PICO_SOCK_EV_ERR, err=%s, picosock=%p, app_fd=%d, sdk_fd=%d", beautify_pico_error(pico_err), s, conn->app_fd, conn->sdk_fd);
|
DEBUG_ERROR("PICO_SOCK_EV_ERR, err=%s, picosock=%p, app_fd=%d, sdk_fd=%d", beautify_pico_error(pico_err), s, vs->app_fd, vs->sdk_fd);
|
||||||
}
|
}
|
||||||
// PICO_SOCK_EV_CLOSE - triggered when a FIN segment is received (TCP only). This event
|
// PICO_SOCK_EV_CLOSE - triggered when a FIN segment is received (TCP only). This event
|
||||||
// indicates that the oher endpont has closed the connection, so the local TCP layer is only
|
// indicates that the oher endpont has closed the VirtualSocket, so the local TCP layer is only
|
||||||
// allowed to send new data until a local shutdown or close is initiated. PicoTCP is able to
|
// allowed to send new data until a local shutdown or close is initiated. PicoTCP is able to
|
||||||
// keep the connection half-open (only for sending) after the FIN packet has been received,
|
// keep the VirtualSocket half-open (only for sending) after the FIN packet has been received,
|
||||||
// allowing new data to be sent in the TCP CLOSE WAIT state.
|
// allowing new data to be sent in the TCP CLOSE WAIT state.
|
||||||
if (ev & PICO_SOCK_EV_CLOSE) {
|
if (ev & PICO_SOCK_EV_CLOSE) {
|
||||||
err = pico_socket_close(s);
|
err = pico_socket_close(s);
|
||||||
//DEBUG_INFO("PICO_SOCK_EV_CLOSE (socket closure) err = %d, picosock=%p, conn=%p, app_fd=%d, sdk_fd=%d", err, s, conn, conn->app_fd, conn->sdk_fd);
|
//DEBUG_INFO("PICO_SOCK_EV_CLOSE (socket closure) err = %d, picosock=%p, vs=%p, app_fd=%d, sdk_fd=%d", err, s, vs, vs->app_fd, vs->sdk_fd);
|
||||||
conn->closure_ts = std::time(nullptr);
|
vs->closure_ts = std::time(nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// PICO_SOCK_EV_RD - triggered when new data arrives on the socket. A new receive action
|
// PICO_SOCK_EV_RD - triggered when new data arrives on the socket. A new receive action
|
||||||
// can be taken by the socket owner because this event indicates there is new data to receive.
|
// can be taken by the socket owner because this event indicates there is new data to receive.
|
||||||
if (ev & PICO_SOCK_EV_RD) {
|
if (ev & PICO_SOCK_EV_RD) {
|
||||||
if(conn->socket_type==SOCK_STREAM)
|
if(vs->socket_type==SOCK_STREAM)
|
||||||
pico_cb_tcp_read(tap, s);
|
pico_cb_tcp_read(tap, s);
|
||||||
if(conn->socket_type==SOCK_DGRAM)
|
if(vs->socket_type==SOCK_DGRAM)
|
||||||
pico_cb_udp_read(tap, s);
|
pico_cb_udp_read(tap, s);
|
||||||
}
|
}
|
||||||
// PICO_SOCK_EV_WR - triggered when ready to write to the socket. Issuing a write/send call
|
// PICO_SOCK_EV_WR - triggered when ready to write to the socket. Issuing a write/send call
|
||||||
@@ -446,7 +441,7 @@ 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);
|
//DEBUG_INFO("len = %d", len);
|
||||||
SocketTap *tap = (SocketTap*)(dev->tap);
|
VirtualTap *tap = (VirtualTap*)(dev->tap);
|
||||||
if(!tap) {
|
if(!tap) {
|
||||||
DEBUG_ERROR("invalid dev->tap");
|
DEBUG_ERROR("invalid dev->tap");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
@@ -464,7 +459,7 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// receive frames from zerotier virtual wire and copy them to a guarded buffer awaiting placement into network stack
|
// receive frames from zerotier virtual wire and copy them to a guarded buffer awaiting placement into network stack
|
||||||
void picoTCP::pico_rx(SocketTap *tap, const MAC &from,const MAC &to,unsigned int etherType,
|
void picoTCP::pico_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType,
|
||||||
const void *data,unsigned int len)
|
const void *data,unsigned int len)
|
||||||
{
|
{
|
||||||
DEBUG_INFO("len = %d", len);
|
DEBUG_INFO("len = %d", len);
|
||||||
@@ -502,14 +497,14 @@ namespace ZeroTier {
|
|||||||
// feed frames on the guarded RX buffer (from zerotier virtual wire) into the network stack
|
// feed frames on the guarded RX buffer (from zerotier virtual wire) into the network stack
|
||||||
int pico_eth_poll(struct pico_device *dev, int loop_score)
|
int pico_eth_poll(struct pico_device *dev, int loop_score)
|
||||||
{
|
{
|
||||||
SocketTap *tap = (SocketTap*)(dev->tap);
|
VirtualTap *tap = (VirtualTap*)(dev->tap);
|
||||||
if(!tap) {
|
if(!tap) {
|
||||||
DEBUG_ERROR("invalid dev->tap");
|
DEBUG_ERROR("invalid dev->tap");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
// FIXME: The copy logic and/or buffer structure should be reworked for better performance after the BETA
|
// FIXME: The copy logic and/or buffer structure should be reworked for better performance after the BETA
|
||||||
// SocketTap *tap = (SocketTap*)netif->state;
|
// VirtualTap *tap = (VirtualTap*)netif->state;
|
||||||
Mutex::Lock _l(tap->_pico_frame_rxbuf_m);
|
Mutex::Lock _l(tap->_pico_frame_rxbuf_m);
|
||||||
unsigned char frame[ZT_SDK_MTU];
|
unsigned char frame[ZT_SDK_MTU];
|
||||||
int len;
|
int len;
|
||||||
@@ -588,15 +583,15 @@ namespace ZeroTier {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int picoTCP::pico_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen)
|
int picoTCP::pico_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
if(!conn || !conn->picosock) {
|
if(!vs || !vs->picosock) {
|
||||||
DEBUG_ERROR("invalid conn or conn->picosock");
|
DEBUG_ERROR("invalid vs or vs->picosock");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if(conn->socket_family == AF_INET) {
|
if(vs->socket_family == AF_INET) {
|
||||||
struct pico_ip4 zaddr;
|
struct pico_ip4 zaddr;
|
||||||
memset(&zaddr, 0, sizeof (struct pico_ip4));
|
memset(&zaddr, 0, sizeof (struct pico_ip4));
|
||||||
struct sockaddr_in *in4 = (struct sockaddr_in*)addr;
|
struct sockaddr_in *in4 = (struct sockaddr_in*)addr;
|
||||||
@@ -605,20 +600,20 @@ namespace ZeroTier {
|
|||||||
uint32_t ipval = 0;
|
uint32_t ipval = 0;
|
||||||
pico_string_to_ipv4(ipv4_str, &ipval);
|
pico_string_to_ipv4(ipv4_str, &ipval);
|
||||||
zaddr.addr = ipval;
|
zaddr.addr = ipval;
|
||||||
err = pico_socket_connect(conn->picosock, &zaddr, in4->sin_port);
|
err = pico_socket_connect(vs->picosock, &zaddr, in4->sin_port);
|
||||||
}
|
}
|
||||||
if(conn->socket_family == AF_INET6) {
|
if(vs->socket_family == AF_INET6) {
|
||||||
struct pico_ip6 zaddr;
|
struct pico_ip6 zaddr;
|
||||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
||||||
char ipv6_str[INET6_ADDRSTRLEN];
|
char ipv6_str[INET6_ADDRSTRLEN];
|
||||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN);
|
inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN);
|
||||||
pico_string_to_ipv6(ipv6_str, zaddr.addr);
|
pico_string_to_ipv6(ipv6_str, zaddr.addr);
|
||||||
err = pico_socket_connect(conn->picosock, &zaddr, in6->sin6_port);
|
err = pico_socket_connect(vs->picosock, &zaddr, in6->sin6_port);
|
||||||
}
|
}
|
||||||
if(err) {
|
if(err) {
|
||||||
DEBUG_ERROR("err=%d, %s", err, beautify_pico_error(pico_err));
|
DEBUG_ERROR("err=%d, %s", err, beautify_pico_error(pico_err));
|
||||||
}
|
}
|
||||||
memcpy(&(conn->peer_addr), &addr, sizeof(struct sockaddr_storage));
|
memcpy(&(vs->peer_addr), &addr, sizeof(struct sockaddr_storage));
|
||||||
|
|
||||||
if(err == PICO_ERR_EPROTONOSUPPORT)
|
if(err == PICO_ERR_EPROTONOSUPPORT)
|
||||||
DEBUG_ERROR("PICO_ERR_EPROTONOSUPPORT");
|
DEBUG_ERROR("PICO_ERR_EPROTONOSUPPORT");
|
||||||
@@ -629,16 +624,16 @@ namespace ZeroTier {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int picoTCP::pico_Bind(Connection *conn, const struct sockaddr *addr, socklen_t addrlen)
|
int picoTCP::pico_Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
//DEBUG_INFO();
|
//DEBUG_INFO();
|
||||||
if(!conn || !conn->picosock) {
|
if(!vs || !vs->picosock) {
|
||||||
DEBUG_ERROR("invalid conn or conn->picosock");
|
DEBUG_ERROR("invalid vs or vs->picosock");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if(conn->socket_family == AF_INET) {
|
if(vs->socket_family == AF_INET) {
|
||||||
struct pico_ip4 zaddr;
|
struct pico_ip4 zaddr;
|
||||||
uint32_t tempaddr;
|
uint32_t tempaddr;
|
||||||
memset(&zaddr, 0, sizeof (struct pico_ip4));
|
memset(&zaddr, 0, sizeof (struct pico_ip4));
|
||||||
@@ -648,9 +643,9 @@ namespace ZeroTier {
|
|||||||
pico_string_to_ipv4(ipv4_str, &tempaddr);
|
pico_string_to_ipv4(ipv4_str, &tempaddr);
|
||||||
zaddr.addr = tempaddr;
|
zaddr.addr = tempaddr;
|
||||||
//DEBUG_EXTRA("addr=%s:%d", ipv4_str, Utils::ntoh(in4->sin_port));
|
//DEBUG_EXTRA("addr=%s:%d", ipv4_str, Utils::ntoh(in4->sin_port));
|
||||||
err = pico_socket_bind(conn->picosock, &zaddr, (uint16_t *)&(in4->sin_port));
|
err = pico_socket_bind(vs->picosock, &zaddr, (uint16_t *)&(in4->sin_port));
|
||||||
}
|
}
|
||||||
if(conn->socket_family == AF_INET6) {
|
if(vs->socket_family == AF_INET6) {
|
||||||
struct pico_ip6 pip6;
|
struct pico_ip6 pip6;
|
||||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
||||||
char ipv6_str[INET6_ADDRSTRLEN];
|
char ipv6_str[INET6_ADDRSTRLEN];
|
||||||
@@ -658,12 +653,12 @@ namespace ZeroTier {
|
|||||||
// TODO: This isn't proper
|
// TODO: This isn't proper
|
||||||
pico_string_to_ipv6("::", pip6.addr);
|
pico_string_to_ipv6("::", pip6.addr);
|
||||||
//DEBUG_EXTRA("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port));
|
//DEBUG_EXTRA("addr=%s:%d", ipv6_str, Utils::ntoh(in6->sin6_port));
|
||||||
err = pico_socket_bind(conn->picosock, &pip6, (uint16_t *)&(in6->sin6_port));
|
err = pico_socket_bind(vs->picosock, &pip6, (uint16_t *)&(in6->sin6_port));
|
||||||
}
|
}
|
||||||
if(err < 0) {
|
if(err < 0) {
|
||||||
if(pico_err < 0)
|
if(pico_err < 0)
|
||||||
DEBUG_ERROR("pico_err = %d", pico_err);
|
DEBUG_ERROR("pico_err = %d", pico_err);
|
||||||
DEBUG_ERROR("unable to bind pico_socket(%p), err=%d", (conn->picosock), err);
|
DEBUG_ERROR("unable to bind pico_socket(%p), err=%d", (vs->picosock), err);
|
||||||
if(err == PICO_ERR_EINVAL) {
|
if(err == PICO_ERR_EINVAL) {
|
||||||
DEBUG_ERROR("PICO_ERR_EINVAL - invalid argument");
|
DEBUG_ERROR("PICO_ERR_EINVAL - invalid argument");
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
@@ -683,16 +678,16 @@ namespace ZeroTier {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int picoTCP::pico_Listen(Connection *conn, int backlog)
|
int picoTCP::pico_Listen(VirtualSocket *vs, int backlog)
|
||||||
{
|
{
|
||||||
//DEBUG_INFO();
|
//DEBUG_INFO();
|
||||||
if(!conn || !conn->picosock) {
|
if(!vs || !vs->picosock) {
|
||||||
DEBUG_ERROR("invalid conn or conn->picosock");
|
DEBUG_ERROR("invalid vs or vs->picosock");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if((err = pico_socket_listen(conn->picosock, backlog)) < 0)
|
if((err = pico_socket_listen(vs->picosock, backlog)) < 0)
|
||||||
{
|
{
|
||||||
if(err == PICO_ERR_EINVAL) {
|
if(err == PICO_ERR_EINVAL) {
|
||||||
DEBUG_ERROR("PICO_ERR_EINVAL");
|
DEBUG_ERROR("PICO_ERR_EINVAL");
|
||||||
@@ -705,33 +700,33 @@ namespace ZeroTier {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn->state = ZT_SOCK_STATE_LISTENING;
|
vs->state = ZT_SOCK_STATE_LISTENING;
|
||||||
return ZT_ERR_OK;
|
return ZT_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection* picoTCP::pico_Accept(Connection *conn)
|
VirtualSocket* picoTCP::pico_Accept(VirtualSocket *vs)
|
||||||
{
|
{
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("invalid conn");
|
DEBUG_ERROR("invalid vs");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Retreive first of queued Connections from parent connection
|
// Retreive first of queued VirtualSockets from parent VirtualSocket
|
||||||
Connection *new_conn = NULL;
|
VirtualSocket *new_vs = NULL;
|
||||||
if(conn->_AcceptedConnections.size()) {
|
if(vs->_AcceptedConnections.size()) {
|
||||||
new_conn = conn->_AcceptedConnections.front();
|
new_vs = vs->_AcceptedConnections.front();
|
||||||
conn->_AcceptedConnections.pop();
|
vs->_AcceptedConnections.pop();
|
||||||
}
|
}
|
||||||
return new_conn;
|
return new_vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
int picoTCP::pico_Read(SocketTap *tap, PhySocket *sock, Connection* conn, bool stack_invoked)
|
int picoTCP::pico_Read(VirtualTap *tap, PhySocket *sock, VirtualSocket* vs, bool stack_invoked)
|
||||||
{
|
{
|
||||||
DEBUG_INFO();
|
DEBUG_INFO();
|
||||||
//exit(0);
|
//exit(0);
|
||||||
/*
|
/*
|
||||||
if(!conn || !tap || !conn) {
|
if(!vs || !tap || !vs) {
|
||||||
DEBUG_ERROR("invalid tap, sock, or conn");
|
DEBUG_ERROR("invalid tap, sock, or vs");
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -743,14 +738,14 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
int tot = 0, n = -1, write_attempts = 0;
|
int tot = 0, n = -1, write_attempts = 0;
|
||||||
|
|
||||||
if(conn && conn->rxsz) {
|
if(vs && vs->rxsz) {
|
||||||
//DEBUG_INFO("conn = %p", conn);
|
//DEBUG_INFO("vs = %p", vs);
|
||||||
//
|
//
|
||||||
if(conn->socket_type==SOCK_DGRAM) {
|
if(vs->socket_type==SOCK_DGRAM) {
|
||||||
// Try to write ZT_SDK_MTU-sized chunk to app socket
|
// Try to write ZT_SDK_MTU-sized chunk to app socket
|
||||||
while(tot < ZT_SDK_MTU) {
|
while(tot < ZT_SDK_MTU) {
|
||||||
write_attempts++;
|
write_attempts++;
|
||||||
n = tap->_phy.streamSend(conn->sock, (conn->rxbuf)+tot, ZT_SDK_MTU);
|
n = tap->_phy.streamSend(vs->sock, (vs->rxbuf)+tot, ZT_SDK_MTU);
|
||||||
tot += n;
|
tot += n;
|
||||||
//DEBUG_FLOW("[ ZTSOCK <- RXBUF] wrote = %d, errno=%d", n, errno);
|
//DEBUG_FLOW("[ ZTSOCK <- RXBUF] wrote = %d, errno=%d", n, errno);
|
||||||
// If socket is unavailable, attempt to write N times before giving up
|
// If socket is unavailable, attempt to write N times before giving up
|
||||||
@@ -762,33 +757,33 @@ namespace ZeroTier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int payload_sz, addr_sz_offset = sizeof(struct sockaddr_storage);
|
int payload_sz, addr_sz_offset = sizeof(struct sockaddr_storage);
|
||||||
memcpy(&payload_sz, conn->rxbuf + addr_sz_offset, sizeof(int));
|
memcpy(&payload_sz, vs->rxbuf + addr_sz_offset, sizeof(int));
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
memcpy(&addr, conn->rxbuf, addr_sz_offset);
|
memcpy(&addr, vs->rxbuf, addr_sz_offset);
|
||||||
// adjust buffer
|
// adjust buffer
|
||||||
if(conn->rxsz-n > 0) { // If more remains on buffer
|
if(vs->rxsz-n > 0) { // If more remains on buffer
|
||||||
memcpy(conn->rxbuf, conn->rxbuf+ZT_SDK_MTU, conn->rxsz - ZT_SDK_MTU);
|
memcpy(vs->rxbuf, vs->rxbuf+ZT_SDK_MTU, vs->rxsz - ZT_SDK_MTU);
|
||||||
}
|
}
|
||||||
conn->rxsz -= ZT_SDK_MTU;
|
vs->rxsz -= ZT_SDK_MTU;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if(conn->socket_type==SOCK_STREAM) {
|
if(vs->socket_type==SOCK_STREAM) {
|
||||||
//DEBUG_INFO("writing to conn->sock = %p, conn->sdk_fd=%d, conn->app_fd=%d", conn->sock, conn->sdk_fd, conn->app_fd);
|
//DEBUG_INFO("writing to vs->sock = %p, vs->sdk_fd=%d, vs->app_fd=%d", vs->sock, vs->sdk_fd, vs->app_fd);
|
||||||
n = tap->_phy.streamSend(conn->sock, conn->rxbuf, conn->rxsz);
|
n = tap->_phy.streamSend(vs->sock, vs->rxbuf, vs->rxsz);
|
||||||
// FIXME: Revisit the idea of writing directly to the app socketpair instead of using Phy I/O
|
// FIXME: Revisit the idea of writing directly to the app socketpair instead of using Phy I/O
|
||||||
// n = write(conn->sdk_fd, conn->rxbuf, conn->rxsz);
|
// n = write(vs->sdk_fd, vs->rxbuf, vs->rxsz);
|
||||||
if(conn->rxsz-n > 0) // If more remains on buffer
|
if(vs->rxsz-n > 0) // If more remains on buffer
|
||||||
memcpy(conn->rxbuf, conn->rxbuf+n, conn->rxsz - n);
|
memcpy(vs->rxbuf, vs->rxbuf+n, vs->rxsz - n);
|
||||||
conn->rxsz -= n;
|
vs->rxsz -= n;
|
||||||
}
|
}
|
||||||
// Notify ZT I/O loop that it has new buffer contents
|
// Notify ZT I/O loop that it has new buffer contents
|
||||||
if(n) {
|
if(n) {
|
||||||
if(conn->socket_type==SOCK_STREAM) {
|
if(vs->socket_type==SOCK_STREAM) {
|
||||||
//#if DEBUG_LEVEL >= MSG_TRANSFER
|
//#if DEBUG_LEVEL >= MSG_TRANSFER
|
||||||
// DEBUG_TRANS("[ TCP RX <- STACK] :: conn = %p, len = %d", conn, n);
|
// DEBUG_TRANS("[ TCP RX <- STACK] :: vs = %p, len = %d", vs, n);
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
if(conn->rxsz == 0) {
|
if(vs->rxsz == 0) {
|
||||||
tap->_phy.setNotifyWritable(sock, false);
|
tap->_phy.setNotifyWritable(sock, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -803,91 +798,91 @@ namespace ZeroTier {
|
|||||||
tap->_tcpconns_m.unlock();
|
tap->_tcpconns_m.unlock();
|
||||||
tap->_rx_buf_m.unlock();
|
tap->_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, vs->rxsz);
|
||||||
*/
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int picoTCP::pico_Write(Connection *conn, void *data, ssize_t len)
|
int picoTCP::pico_Write(VirtualSocket *vs, void *data, ssize_t len)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
// TODO: Add RingBuffer overflow checks
|
// TODO: Add RingBuffer overflow checks
|
||||||
DEBUG_INFO("conn=%p, len=%d", conn, len);
|
DEBUG_INFO("vs=%p, len=%d", vs, len);
|
||||||
Mutex::Lock _l(conn->_tx_m);
|
Mutex::Lock _l(vs->_tx_m);
|
||||||
if(len <= 0) {
|
if(len <= 0) {
|
||||||
DEBUG_ERROR("invalid write length (len=%d)", len);
|
DEBUG_ERROR("invalid write length (len=%d)", len);
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(conn->picosock->state & PICO_SOCKET_STATE_CLOSED){
|
if(vs->picosock->state & PICO_SOCKET_STATE_CLOSED){
|
||||||
DEBUG_ERROR("socket is CLOSED, this write() will fail");
|
DEBUG_ERROR("socket is CLOSED, this write() will fail");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(!conn) {
|
if(!vs) {
|
||||||
DEBUG_ERROR("invalid connection (len=%d)", len);
|
DEBUG_ERROR("invalid VirtualSocket (len=%d)", len);
|
||||||
handle_general_failure();
|
handle_general_failure();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(conn->socket_type == SOCK_DGRAM)
|
if(vs->socket_type == SOCK_DGRAM)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
if((r = pico_socket_write(conn->picosock, data, len)) < 0) {
|
if((r = pico_socket_write(vs->picosock, data, len)) < 0) {
|
||||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r);
|
DEBUG_ERROR("unable to write to picosock=%p, r=%d", vs->picosock, r);
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
err = r; // successful write
|
err = r; // successful write
|
||||||
}
|
}
|
||||||
DEBUG_TRANS("[ UDP TX -> STACK] :: conn=%p, len=%d, err=%s", conn, r, beautify_pico_error(pico_err));
|
DEBUG_TRANS("[ UDP TX -> STACK] :: vs=%p, len=%d, err=%s", vs, r, beautify_pico_error(pico_err));
|
||||||
}
|
}
|
||||||
if(conn->socket_type == SOCK_STREAM)
|
if(vs->socket_type == SOCK_STREAM)
|
||||||
{
|
{
|
||||||
int original_txsz = conn->TXbuf->count();
|
int original_txsz = vs->TXbuf->count();
|
||||||
if(original_txsz + len >= ZT_TCP_TX_BUF_SZ) {
|
if(original_txsz + len >= ZT_TCP_TX_BUF_SZ) {
|
||||||
DEBUG_ERROR("txsz=%d, len=%d", original_txsz, len);
|
DEBUG_ERROR("txsz=%d, len=%d", original_txsz, len);
|
||||||
DEBUG_ERROR("TX buffer is too small, try increasing ZT_TCP_TX_BUF_SZ in libzt.h");
|
DEBUG_ERROR("TX buffer is too small, try increasing ZT_TCP_TX_BUF_SZ in libzt.h");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
int buf_w = conn->TXbuf->write((const unsigned char*)data, len);
|
int buf_w = vs->TXbuf->write((const unsigned char*)data, len);
|
||||||
if (buf_w != len) {
|
if (buf_w != len) {
|
||||||
// because we checked ZT_TCP_TX_BUF_SZ above, this should not happen
|
// because we checked ZT_TCP_TX_BUF_SZ above, this should not happen
|
||||||
DEBUG_ERROR("TX wrote only %d but expected to write %d", buf_w, len);
|
DEBUG_ERROR("TX wrote only %d but expected to write %d", buf_w, len);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
//DEBUG_INFO("TXbuf->count() = %d", conn->TXbuf->count());
|
//DEBUG_INFO("TXbuf->count() = %d", vs->TXbuf->count());
|
||||||
int txsz = conn->TXbuf->count();
|
int txsz = vs->TXbuf->count();
|
||||||
|
|
||||||
int r, max_write_len = std::min(std::min(txsz, ZT_SDK_MTU),ZT_STACK_SOCKET_WR_MAX);
|
int r, max_write_len = std::min(std::min(txsz, ZT_SDK_MTU),ZT_STACK_SOCKET_WR_MAX);
|
||||||
//int buf_r = conn->TXbuf->read(conn->tmptxbuf, max_write_len);
|
//int buf_r = vs->TXbuf->read(vs->tmptxbuf, max_write_len);
|
||||||
|
|
||||||
if((r = pico_socket_write(conn->picosock, conn->TXbuf->get_buf(), max_write_len)) < 0) {
|
if((r = pico_socket_write(vs->picosock, vs->TXbuf->get_buf(), max_write_len)) < 0) {
|
||||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r);
|
DEBUG_ERROR("unable to write to picosock=%p, r=%d", vs->picosock, r);
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
err = r; // successful write
|
err = r; // successful write
|
||||||
}
|
}
|
||||||
if(r>0){
|
if(r>0){
|
||||||
conn->TXbuf->consume(r);
|
vs->TXbuf->consume(r);
|
||||||
}
|
}
|
||||||
DEBUG_TRANS("[ TCP TX -> STACK] :: conn=%p, len=%d", conn, r);
|
DEBUG_TRANS("[ TCP TX -> STACK] :: vs=%p, len=%d", vs, r);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int picoTCP::pico_Close(Connection *conn)
|
int picoTCP::pico_Close(VirtualSocket *vs)
|
||||||
{
|
{
|
||||||
DEBUG_INFO("conn=%p, picosock=%p, fd=%d", conn, conn->picosock, conn->app_fd);
|
DEBUG_INFO("vs=%p, picosock=%p, fd=%d", vs, vs->picosock, vs->app_fd);
|
||||||
if(!conn || !conn->picosock)
|
if(!vs || !vs->picosock)
|
||||||
return ZT_ERR_GENERAL_FAILURE;
|
return ZT_ERR_GENERAL_FAILURE;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||||
if(conn->closure_ts != -1) // it was closed at some point in the past, it'll work itself out
|
if(vs->closure_ts != -1) // it was closed at some point in the past, it'll work itself out
|
||||||
return ZT_ERR_OK;
|
return ZT_ERR_OK;
|
||||||
if((err = pico_socket_close(conn->picosock)) < 0) {
|
if((err = pico_socket_close(vs->picosock)) < 0) {
|
||||||
errno = pico_err;
|
errno = pico_err;
|
||||||
DEBUG_ERROR("error closing pico_socket(%p)", (void*)(conn->picosock));
|
DEBUG_ERROR("error closing pico_socket(%p)", (void*)(vs->picosock));
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
#include "pico_device.h"
|
#include "pico_device.h"
|
||||||
#include "pico_ipv6.h"
|
#include "pico_ipv6.h"
|
||||||
|
|
||||||
#include "SocketTap.hpp"
|
#include "VirtualTap.hpp"
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* PicoTCP API Signatures (See libzt.h for the API an app should use) */
|
/* PicoTCP API Signatures (See libzt.h for the API an app should use) */
|
||||||
@@ -84,47 +84,47 @@ namespace ZeroTier
|
|||||||
*/
|
*/
|
||||||
int pico_eth_poll(struct pico_device *dev, int loop_score);
|
int pico_eth_poll(struct pico_device *dev, int loop_score);
|
||||||
|
|
||||||
class SocketTap;
|
class VirtualTap;
|
||||||
struct Connection;
|
struct VirtualSocket;
|
||||||
|
|
||||||
class picoTCP
|
class picoTCP
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up an interface in the network stack for the SocketTap
|
* Set up an interface in the network stack for the VirtualTap
|
||||||
*/
|
*/
|
||||||
bool pico_init_interface(ZeroTier::SocketTap *tap, const ZeroTier::InetAddress &ip);
|
bool pico_init_interface(ZeroTier::VirtualTap *tap, const ZeroTier::InetAddress &ip);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds a route to the picoTCP device
|
* Adds a route to the picoTCP device
|
||||||
*/
|
*/
|
||||||
bool pico_route_add(SocketTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric);
|
bool pico_route_add(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deletes a route from the picoTCP device
|
* Deletes a route from the picoTCP device
|
||||||
*/
|
*/
|
||||||
bool pico_route_del(SocketTap *tap, const InetAddress &addr, const InetAddress &nm, int metric);
|
bool pico_route_del(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, int metric);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main stack loop
|
* Main stack loop
|
||||||
*/
|
*/
|
||||||
void pico_loop(SocketTap *tap);
|
void pico_loop(VirtualTap *tap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read bytes from the stack to the RX buffer (prepare to be read by app)
|
* Read bytes from the stack to the RX buffer (prepare to be read by app)
|
||||||
*/
|
*/
|
||||||
static void pico_cb_tcp_read(SocketTap *tap, struct pico_socket *s);
|
static void pico_cb_tcp_read(VirtualTap *tap, struct pico_socket *s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read bytes from the stack to the RX buffer (prepare to be read by app)
|
* Read bytes from the stack to the RX buffer (prepare to be read by app)
|
||||||
*/
|
*/
|
||||||
static void pico_cb_udp_read(SocketTap *tap, struct pico_socket *s);
|
static void pico_cb_udp_read(VirtualTap *tap, struct pico_socket *s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire)
|
* Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire)
|
||||||
*/
|
*/
|
||||||
static void pico_cb_tcp_write(SocketTap *tap, struct pico_socket *s);
|
static void pico_cb_tcp_write(VirtualTap *tap, struct pico_socket *s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire)
|
* Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire)
|
||||||
@@ -134,47 +134,47 @@ namespace ZeroTier
|
|||||||
/*
|
/*
|
||||||
* Packets from the ZeroTier virtual wire enter the stack here
|
* Packets from the ZeroTier virtual wire enter the stack here
|
||||||
*/
|
*/
|
||||||
void pico_rx(SocketTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
void pico_rx(VirtualTap *tap, const ZeroTier::MAC &from,const ZeroTier::MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates a stack-specific "socket" or "connection object"
|
* Creates a stack-specific "socket" or "VirtualSocket object"
|
||||||
*/
|
*/
|
||||||
int pico_Socket(struct pico_socket **p, int socket_family, int socket_type, int protocol);
|
int pico_Socket(struct pico_socket **p, int socket_family, int socket_type, int protocol);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connect to remote host via userspace network stack interface - Called from SocketTap
|
* Connect to remote host via userspace network stack interface - Called from VirtualTap
|
||||||
*/
|
*/
|
||||||
int pico_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
|
int pico_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bind to a userspace network stack interface - Called from SocketTap
|
* Bind to a userspace network stack interface - Called from VirtualTap
|
||||||
*/
|
*/
|
||||||
int pico_Bind(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
|
int pico_Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Listen for incoming connections - Called from SocketTap
|
* Listen for incoming VirtualSockets - Called from VirtualTap
|
||||||
*/
|
*/
|
||||||
int pico_Listen(Connection *conn, int backlog);
|
int pico_Listen(VirtualSocket *vs, int backlog);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accept an incoming connection - Called from SocketTap
|
* Accept an incoming VirtualSocket - Called from VirtualTap
|
||||||
*/
|
*/
|
||||||
Connection* pico_Accept(Connection *conn);
|
VirtualSocket* pico_Accept(VirtualSocket *vs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read from RX buffer to application - Called from SocketTap
|
* Read from RX buffer to application - Called from VirtualTap
|
||||||
*/
|
*/
|
||||||
int pico_Read(SocketTap *tap, ZeroTier::PhySocket *sock,Connection *conn,bool stack_invoked);
|
int pico_Read(VirtualTap *tap, ZeroTier::PhySocket *sock,VirtualSocket *vs,bool stack_invoked);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write to userspace network stack - Called from SocketTap
|
* Write to userspace network stack - Called from VirtualTap
|
||||||
*/
|
*/
|
||||||
int pico_Write(Connection *conn, void *data, ssize_t len);
|
int pico_Write(VirtualSocket *vs, void *data, ssize_t len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close a Connection - Called from SocketTap
|
* Close a VirtualSocket - Called from VirtualTap
|
||||||
*/
|
*/
|
||||||
int pico_Close(Connection *conn);
|
int pico_Close(VirtualSocket *vs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Converts picoTCP error codes to pretty string
|
* Converts picoTCP error codes to pretty string
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ int main(int argc , char *argv[])
|
|||||||
fprintf(stderr, "Send failed\n");
|
fprintf(stderr, "Send failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// dismantle all zt virtual taps (SocketTaps)
|
// dismantle all zt virtual taps
|
||||||
zts_stop();
|
zts_stop();
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -220,31 +220,31 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
void ZTProxy::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len)
|
void ZTProxy::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len)
|
||||||
{
|
{
|
||||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
// Not used, connections are handled via user space network stack and VirtualTap
|
||||||
DEBUG_INFO("phyOnDatagram");
|
DEBUG_INFO("phyOnDatagram");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
void ZTProxy::phyOnTcpWritable(PhySocket *sock,void **uptr)
|
void ZTProxy::phyOnTcpWritable(PhySocket *sock,void **uptr)
|
||||||
{
|
{
|
||||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
// Not used, connections are handled via user space network stack and VirtualTap
|
||||||
DEBUG_INFO("phyOnTcpWritable");
|
DEBUG_INFO("phyOnTcpWritable");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
void ZTProxy::phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable)
|
void ZTProxy::phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable)
|
||||||
{
|
{
|
||||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
// Not used, connections are handled via user space network stack and VirtualTap
|
||||||
DEBUG_INFO("phyOnFileDescriptorActivity, sock=%p", sock);
|
DEBUG_INFO("phyOnFileDescriptorActivity, sock=%p", sock);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
void ZTProxy::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success)
|
void ZTProxy::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success)
|
||||||
{
|
{
|
||||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
// Not used, connections are handled via user space network stack and VirtualTap
|
||||||
DEBUG_INFO("phyOnTcpConnect, sock=%p", sock);
|
DEBUG_INFO("phyOnTcpConnect, sock=%p", sock);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
void ZTProxy::phyOnUnixClose(PhySocket *sock,void **uptr)
|
void ZTProxy::phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||||
{
|
{
|
||||||
// Not used, connections are handled via user space network stack and SocketTap subsystem
|
// Not used, connections are handled via user space network stack and VirtualTap
|
||||||
DEBUG_INFO("phyOnUnixClose, sock=%p", sock);
|
DEBUG_INFO("phyOnUnixClose, sock=%p", sock);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
2
zto
2
zto
Submodule zto updated: ee1dc16e8f...59b7cbb591
Reference in New Issue
Block a user