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_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 */
|
||||
@@ -155,11 +155,11 @@ struct zts_ifreq {
|
||||
#define ZT_SDK_CLTIME 60
|
||||
|
||||
// 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
|
||||
// delete this Connection object until the socket has been closed for some arbitrary
|
||||
// VirtualSocket object for remaining data I/O, as a safety measure we will wait to
|
||||
// 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
|
||||
// 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
|
||||
#define ZT_HOUSEKEEPING_INTERVAL 10 // s
|
||||
@@ -351,30 +351,30 @@ int zts_connect(ZT_CONNECT_SIG);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* For instance, given the following networks:
|
||||
* - nwid = 97afaf1963cc6a90 (10.9.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
|
||||
*/
|
||||
int zts_bind(ZT_BIND_SIG);
|
||||
|
||||
/**
|
||||
* Listen for incoming connections
|
||||
* Listen for incoming VirtualSockets
|
||||
*/
|
||||
int zts_listen(ZT_LISTEN_SIG);
|
||||
|
||||
/**
|
||||
* Accept a connection
|
||||
* Accept a VirtualSocket
|
||||
*/
|
||||
int zts_accept(ZT_ACCEPT_SIG);
|
||||
|
||||
/**
|
||||
* Accept a connection
|
||||
* Accept a VirtualSocket
|
||||
*/
|
||||
#if defined(__linux__)
|
||||
int zts_accept4(ZT_ACCEPT4_SIG);
|
||||
@@ -485,7 +485,7 @@ namespace ZeroTier
|
||||
class lwIP;
|
||||
extern ZeroTier::lwIP *lwipstack;
|
||||
|
||||
class SocketTap;
|
||||
class VirtualTap;
|
||||
struct InetAddress;
|
||||
}
|
||||
|
||||
@@ -521,10 +521,10 @@ int pico_ntimers();
|
||||
/* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */
|
||||
/****************************************************************************/
|
||||
|
||||
ZeroTier::SocketTap *getTapByNWID(uint64_t nwid);
|
||||
ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr);
|
||||
ZeroTier::SocketTap *getTapByName(char *ifname);
|
||||
ZeroTier::SocketTap *getTapByIndex(int index);
|
||||
ZeroTier::VirtualTap *getTapByNWID(uint64_t nwid);
|
||||
ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress &addr);
|
||||
ZeroTier::VirtualTap *getTapByName(char *ifname);
|
||||
ZeroTier::VirtualTap *getTapByIndex(int index);
|
||||
|
||||
/*
|
||||
* Destroys all virtual tap devices
|
||||
|
||||
@@ -136,11 +136,11 @@ CXXFLAGS+=-DSDK_IPV6
|
||||
##############################################################################
|
||||
|
||||
STACK_DRIVER_FILES:=src/picoTCP.cpp
|
||||
TAP_FILES:=src/SocketTap.cpp \
|
||||
TAP_FILES:=src/VirtualTap.cpp \
|
||||
src/libzt.cpp \
|
||||
src/Utilities.cpp
|
||||
|
||||
SDK_OBJS+= SocketTap.o \
|
||||
SDK_OBJS+= VirtualTap.o \
|
||||
picoTCP.o \
|
||||
libzt.o \
|
||||
Utilities.o
|
||||
|
||||
@@ -150,7 +150,7 @@ STACK_FLAGS+=LIBZT_IPV4=1
|
||||
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)
|
||||
CXXFLAGS+=-DSTACK_PICO
|
||||
|
||||
@@ -149,7 +149,7 @@ STACK_FLAGS+=LIBZT_IPV4=1
|
||||
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)
|
||||
CXXFLAGS+=-DSTACK_PICO
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* 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
|
||||
#define ZT_CONNECTION_HPP
|
||||
@@ -39,19 +39,24 @@
|
||||
#include "Phy.hpp"
|
||||
|
||||
#include "libzt.h"
|
||||
#include "SocketTap.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
#include "RingBuffer.hpp"
|
||||
|
||||
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> *RXbuf;
|
||||
|
||||
Mutex _tx_m, _rx_m;
|
||||
|
||||
PhySocket *sock;
|
||||
@@ -62,6 +67,7 @@ namespace ZeroTier {
|
||||
#if defined(STACK_LWIP)
|
||||
void *pcb;
|
||||
#endif
|
||||
|
||||
// TODO: For getsockname, etc
|
||||
struct sockaddr_storage *local_addr; // Address we've bound to locally
|
||||
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 sdk_fd; // used by lib for I/O
|
||||
|
||||
std::queue<Connection*> _AcceptedConnections;
|
||||
SocketTap *tap;
|
||||
std::queue<VirtualSocket*> _AcceptedConnections;
|
||||
VirtualTap *tap;
|
||||
int state; // See libzt.h for (ZT_SOCK_STATE_*)
|
||||
|
||||
// timestamp for closure event
|
||||
std::time_t closure_ts;
|
||||
|
||||
Connection() {
|
||||
VirtualSocket() {
|
||||
TXbuf = new RingBuffer<unsigned char>(ZT_TCP_TX_BUF_SZ);
|
||||
RXbuf = new RingBuffer<unsigned char>(ZT_TCP_RX_BUF_SZ);
|
||||
|
||||
@@ -93,17 +99,17 @@ namespace ZeroTier {
|
||||
sdk_fd = fdpair[0];
|
||||
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;
|
||||
Connection *conn;
|
||||
ConnectionPair(SocketTap *_tap, Connection *conn) : tap(_tap), conn(conn) {}
|
||||
VirtualTap *tap;
|
||||
VirtualSocket *vs;
|
||||
VirtualBindingPair(VirtualTap *_tap, VirtualSocket *_vs) : tap(_tap), vs(_vs) {}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
#include "SocketTap.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
#include "libzt.h"
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
@@ -58,23 +58,21 @@
|
||||
#include "Constants.hpp"
|
||||
#include "Phy.hpp"
|
||||
|
||||
class SocketTap;
|
||||
|
||||
class VirtualTap;
|
||||
|
||||
extern std::vector<void*> vtaps;
|
||||
//extern ZeroTier::OneService *zt1Service;
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
int SocketTap::devno = 0;
|
||||
int VirtualTap::devno = 0;
|
||||
|
||||
/****************************************************************************/
|
||||
/* SocketTap Service */
|
||||
/* - For each joined network a SocketTap will be created to administer I/O */
|
||||
/* VirtualTap Service */
|
||||
/* - For each joined network a VirtualTap will be created to administer I/O */
|
||||
/* calls to the stack and the ZT virtual wire */
|
||||
/****************************************************************************/
|
||||
|
||||
SocketTap::SocketTap(
|
||||
VirtualTap::VirtualTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
unsigned int mtu,
|
||||
@@ -107,26 +105,26 @@ namespace ZeroTier {
|
||||
_thread = Thread::start(this);
|
||||
}
|
||||
|
||||
SocketTap::~SocketTap()
|
||||
VirtualTap::~VirtualTap()
|
||||
{
|
||||
_run = false;
|
||||
_phy.whack();
|
||||
Thread::join(_thread);
|
||||
_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;
|
||||
}
|
||||
|
||||
bool SocketTap::enabled() const
|
||||
bool VirtualTap::enabled() const
|
||||
{
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
bool SocketTap::registerIpWithStack(const InetAddress &ip)
|
||||
bool VirtualTap::registerIpWithStack(const InetAddress &ip)
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack){
|
||||
@@ -143,7 +141,7 @@ namespace ZeroTier {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SocketTap::addIp(const InetAddress &ip)
|
||||
bool VirtualTap::addIp(const InetAddress &ip)
|
||||
{
|
||||
#if defined(NO_STACK)
|
||||
char ipbuf[64];
|
||||
@@ -163,7 +161,7 @@ namespace ZeroTier {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SocketTap::removeIp(const InetAddress &ip)
|
||||
bool VirtualTap::removeIp(const InetAddress &ip)
|
||||
{
|
||||
Mutex::Lock _l(_ips_m);
|
||||
std::vector<InetAddress>::iterator i(std::find(_ips.begin(),_ips.end(),ip));
|
||||
@@ -179,13 +177,13 @@ namespace ZeroTier {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<InetAddress> SocketTap::ips() const
|
||||
std::vector<InetAddress> VirtualTap::ips() const
|
||||
{
|
||||
Mutex::Lock _l(_ips_m);
|
||||
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)
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
@@ -198,18 +196,18 @@ namespace ZeroTier {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string SocketTap::deviceName() const
|
||||
std::string VirtualTap::deviceName() const
|
||||
{
|
||||
return _dev;
|
||||
}
|
||||
|
||||
void SocketTap::setFriendlyName(const char *friendlyName)
|
||||
void VirtualTap::setFriendlyName(const char *friendlyName)
|
||||
{
|
||||
DEBUG_INFO("%s", friendlyName);
|
||||
// Someday
|
||||
}
|
||||
|
||||
void SocketTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
||||
void VirtualTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
|
||||
std::vector<MulticastGroup> &removed)
|
||||
{
|
||||
std::vector<MulticastGroup> newGroups;
|
||||
@@ -233,14 +231,14 @@ namespace ZeroTier {
|
||||
_multicastGroups.swap(newGroups);
|
||||
}
|
||||
|
||||
void SocketTap::setMtu(unsigned int mtu)
|
||||
void VirtualTap::setMtu(unsigned int mtu)
|
||||
{
|
||||
if (_mtu != mtu) {
|
||||
_mtu = mtu;
|
||||
}
|
||||
}
|
||||
|
||||
void SocketTap::threadMain()
|
||||
void VirtualTap::threadMain()
|
||||
throw()
|
||||
{
|
||||
#if defined(STACK_PICO)
|
||||
@@ -253,35 +251,35 @@ namespace ZeroTier {
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketTap::phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||
void VirtualTap::phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||
{
|
||||
if(sock) {
|
||||
Connection *conn = (Connection*)uptr;
|
||||
if(conn)
|
||||
Close(conn);
|
||||
VirtualSocket *vs = (VirtualSocket*)uptr;
|
||||
if(vs)
|
||||
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));
|
||||
Connection *conn = (Connection*)*uptr;
|
||||
if(!conn)
|
||||
VirtualSocket *vs = (VirtualSocket*)*uptr;
|
||||
if(!vs)
|
||||
return;
|
||||
if(len){
|
||||
Write(conn, data, len);
|
||||
Write(vs, data, len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void SocketTap::phyOnUnixWritable(PhySocket *sock, void **uptr, bool stack_invoked)
|
||||
void VirtualTap::phyOnUnixWritable(PhySocket *sock, void **uptr, bool stack_invoked)
|
||||
{
|
||||
if(sock)
|
||||
Read(sock,uptr,stack_invoked);
|
||||
}
|
||||
|
||||
// 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(picostack)
|
||||
@@ -294,7 +292,7 @@ namespace ZeroTier {
|
||||
}
|
||||
|
||||
// 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(picostack)
|
||||
@@ -311,94 +309,94 @@ namespace ZeroTier {
|
||||
/****************************************************************************/
|
||||
|
||||
// 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)
|
||||
return -1;
|
||||
#endif
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return picostack->pico_Connect(conn, addr, addrlen);
|
||||
return picostack->pico_Connect(vs, addr, addrlen);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
return lwipstack->lwip_Connect(conn, addr, addrlen);
|
||||
return lwipstack->lwip_Connect(vs, addr, addrlen);
|
||||
#endif
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
// 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)
|
||||
return -1;
|
||||
#endif
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
return picostack->pico_Bind(conn, addr, addrlen);
|
||||
return picostack->pico_Bind(vs, addr, addrlen);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
return lwipstack->lwip_Bind(this, conn, addr, addrlen);
|
||||
return lwipstack->lwip_Bind(this, vs, addr, addrlen);
|
||||
#endif
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
// Listen for an incoming connection
|
||||
int SocketTap::Listen(Connection *conn, int backlog) {
|
||||
// Listen for an incoming VirtualSocket
|
||||
int VirtualTap::Listen(VirtualSocket *vs, int backlog) {
|
||||
#if defined(NO_STACK)
|
||||
return -1;
|
||||
#endif
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
return picostack->pico_Listen(conn, backlog);
|
||||
return picostack->pico_Listen(vs, backlog);
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
return lwipstack->lwip_Listen(conn, backlog);
|
||||
return lwipstack->lwip_Listen(vs, backlog);
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
#endif
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
// Accept a connection
|
||||
Connection* SocketTap::Accept(Connection *conn) {
|
||||
// Accept a VirtualSocket
|
||||
VirtualSocket* VirtualTap::Accept(VirtualSocket *vs) {
|
||||
#if defined(NO_STACK)
|
||||
return NULL;
|
||||
#endif
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
return picostack->pico_Accept(conn);
|
||||
return picostack->pico_Accept(vs);
|
||||
return NULL;
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
return lwipstack->lwip_Accept(conn);
|
||||
return lwipstack->lwip_Accept(vs);
|
||||
return NULL;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 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(picostack)
|
||||
return picostack->pico_Read(this, sock, (Connection*)uptr, stack_invoked);
|
||||
return picostack->pico_Read(this, sock, (VirtualSocket*)uptr, stack_invoked);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
return lwipstack->lwip_Read((Connection*)*(_phy.getuptr(sock)), stack_invoked);
|
||||
return lwipstack->lwip_Read((VirtualSocket*)*(_phy.getuptr(sock)), stack_invoked);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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
|
||||
if(conn->socket_type == SOCK_RAW) {
|
||||
if(vs->socket_type == SOCK_RAW) {
|
||||
struct ether_header *eh = (struct ether_header *) data;
|
||||
MAC src_mac;
|
||||
MAC dest_mac;
|
||||
@@ -409,49 +407,49 @@ namespace ZeroTier {
|
||||
}
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack)
|
||||
return picostack->pico_Write(conn, data, len);
|
||||
return picostack->pico_Write(vs, data, len);
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
return lwipstack->lwip_Write(conn, data, len);
|
||||
return lwipstack->lwip_Write(vs, data, len);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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
|
||||
int err = 0;
|
||||
DEBUG_INFO();
|
||||
#if defined(STACK_PICO)
|
||||
if(picostack) {
|
||||
err = picostack->pico_Connect(conn, addr, addrlen); // implicit
|
||||
err = picostack->pico_Write(conn, (void*)buf, len);
|
||||
err = picostack->pico_Connect(vs, addr, addrlen); // implicit
|
||||
err = picostack->pico_Write(vs, (void*)buf, len);
|
||||
}
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
err = lwipstack->lwip_Connect(conn, addr, addrlen); // implicit
|
||||
err = lwipstack->lwip_Write(conn, (void*)buf, len);
|
||||
err = lwipstack->lwip_Connect(vs, addr, addrlen); // implicit
|
||||
err = lwipstack->lwip_Write(vs, (void*)buf, len);
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
int SocketTap::Close(Connection *conn) {
|
||||
int VirtualTap::Close(VirtualSocket *vs) {
|
||||
#if defined(STACK_PICO)
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid connection");
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid VirtualSocket");
|
||||
return -1;
|
||||
}
|
||||
picostack->pico_Close(conn);
|
||||
if(!conn->sock) {
|
||||
picostack->pico_Close(vs);
|
||||
if(!vs->sock) {
|
||||
// DEBUG_EXTRA("invalid PhySocket");
|
||||
return -1;
|
||||
}
|
||||
// Here we assume _tcpconns_m is already locked by caller
|
||||
// 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
|
||||
DEBUG_INFO("in LISTENING state, no need to close in PhyIO");
|
||||
@@ -459,14 +457,14 @@ namespace ZeroTier {
|
||||
}
|
||||
else
|
||||
{
|
||||
if(conn->sock)
|
||||
_phy.close(conn->sock, false);
|
||||
if(vs->sock)
|
||||
_phy.close(vs->sock, false);
|
||||
}
|
||||
close(_phy.getDescriptor(conn->sock));
|
||||
for(size_t i=0;i<_Connections.size();++i) {
|
||||
if(_Connections[i] == conn){
|
||||
close(_phy.getDescriptor(vs->sock));
|
||||
for(size_t i=0;i<_VirtualSockets.size();++i) {
|
||||
if(_VirtualSockets[i] == vs){
|
||||
// FIXME: double free issue exists here (potentially)
|
||||
// _Connections.erase(_Connections.begin() + i);
|
||||
// _VirtualSockets.erase(_VirtualSockets.begin() + i);
|
||||
//delete conn;
|
||||
break;
|
||||
}
|
||||
@@ -474,12 +472,12 @@ namespace ZeroTier {
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
if(lwipstack)
|
||||
lwipstack->lwip_Close(conn);
|
||||
lwipstack->lwip_Close(vs);
|
||||
#endif
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
void SocketTap::Housekeeping()
|
||||
void VirtualTap::Housekeeping()
|
||||
{
|
||||
Mutex::Lock _l(_tcpconns_m);
|
||||
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);
|
||||
}
|
||||
@@ -547,14 +545,14 @@ namespace ZeroTier {
|
||||
/* 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) {}
|
||||
void SocketTap::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) {}
|
||||
void SocketTap::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,
|
||||
void VirtualTap::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) {}
|
||||
void VirtualTap::phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,
|
||||
const struct sockaddr *from) {}
|
||||
void SocketTap::phyOnTcpClose(PhySocket *sock,void **uptr) {}
|
||||
void SocketTap::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
||||
void SocketTap::phyOnTcpWritable(PhySocket *sock,void **uptr) {}
|
||||
void VirtualTap::phyOnTcpClose(PhySocket *sock,void **uptr) {}
|
||||
void VirtualTap::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
||||
void VirtualTap::phyOnTcpWritable(PhySocket *sock,void **uptr) {}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
* of your own application.
|
||||
*/
|
||||
|
||||
#ifndef ZT_SOCKETTAP_HPP
|
||||
#define ZT_SOCKETTAP_HPP
|
||||
#ifndef ZT_VIRTUALTAP_HPP
|
||||
#define ZT_VIRTUALTAP_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "Phy.hpp"
|
||||
|
||||
#include "libzt.h"
|
||||
#include "Connection.hpp"
|
||||
#include "VirtualSocket.hpp"
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
#include "picoTCP.hpp"
|
||||
@@ -66,12 +66,12 @@ namespace ZeroTier {
|
||||
/*
|
||||
* Socket Tap -- emulates an Ethernet tap device
|
||||
*/
|
||||
class SocketTap
|
||||
class VirtualTap
|
||||
{
|
||||
friend class Phy<SocketTap *>;
|
||||
friend class Phy<VirtualTap *>;
|
||||
|
||||
public:
|
||||
SocketTap(
|
||||
VirtualTap(
|
||||
const char *homePath,
|
||||
const MAC &mac,
|
||||
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 *arg);
|
||||
|
||||
~SocketTap();
|
||||
~VirtualTap();
|
||||
|
||||
void setEnabled(bool en);
|
||||
bool enabled() const;
|
||||
@@ -92,13 +92,13 @@ namespace ZeroTier {
|
||||
bool registerIpWithStack(const InetAddress &ip);
|
||||
|
||||
/*
|
||||
* Adds an address to the userspace stack interface associated with this SocketTap
|
||||
* - Starts SocketTap main thread ONLY if successful
|
||||
* Adds an address to the userspace stack interface associated with this VirtualTap
|
||||
* - Starts VirtualTap main thread ONLY if successful
|
||||
*/
|
||||
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);
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace ZeroTier {
|
||||
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);
|
||||
|
||||
@@ -210,9 +210,9 @@ namespace ZeroTier {
|
||||
unsigned int _mtu;
|
||||
uint64_t _nwid;
|
||||
PhySocket *_unixListenSocket;
|
||||
Phy<SocketTap *> _phy;
|
||||
Phy<VirtualTap *> _phy;
|
||||
|
||||
std::vector<Connection*> _Connections;
|
||||
std::vector<VirtualSocket*> _VirtualSockets;
|
||||
|
||||
Thread _thread;
|
||||
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"
|
||||
@@ -260,20 +260,20 @@ namespace ZeroTier {
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
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();
|
||||
|
||||
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 "ZeroTierOne.h"
|
||||
|
||||
#include "SocketTap.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
#include "libzt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -89,14 +89,14 @@ namespace ZeroTier {
|
||||
#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
|
||||
@@ -105,7 +105,7 @@ namespace ZeroTier {
|
||||
|
||||
ZeroTier::Mutex _vtaps_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
|
||||
// TODO: This might prove to be unreliable, but it works for now
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -263,7 +263,7 @@ void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen)
|
||||
{
|
||||
if(ZeroTier::zt1Service) {
|
||||
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()){
|
||||
for(int i=0; i<tap->_ips.size(); i++) {
|
||||
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) {
|
||||
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()){
|
||||
for(int i=0; i<tap->_ips.size(); i++) {
|
||||
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 */
|
||||
/* controls. Basically this is designed to handle socket provisioning */
|
||||
/* requests when no SocketTap is yet initialized, and as a way to */
|
||||
/* determine which SocketTap is to be used for a particular connect() or */
|
||||
/* requests when no VirtualTap is yet initialized, and as a way to */
|
||||
/* determine which VirtualTap is to be used for a particular connect() or */
|
||||
/* bind() call. This enables multi-network support */
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -396,25 +396,25 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
|
||||
if(socket_type == SOCK_RAW)
|
||||
{
|
||||
// Connection is only used to associate a socket with a SocketTap, it has no other implication
|
||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
||||
conn->socket_family = socket_family;
|
||||
conn->socket_type = socket_type;
|
||||
conn->protocol = protocol;
|
||||
ZeroTier::unmap[conn->app_fd] = conn;
|
||||
return conn->app_fd;
|
||||
// VirtualSocket is only used to associate a socket with a VirtualTap, it has no other implication
|
||||
ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket();
|
||||
vs->socket_family = socket_family;
|
||||
vs->socket_type = socket_type;
|
||||
vs->protocol = protocol;
|
||||
ZeroTier::unmap[vs->app_fd] = vs;
|
||||
return vs->app_fd;
|
||||
}
|
||||
|
||||
#if defined(STACK_PICO)
|
||||
struct pico_socket *p;
|
||||
err = ZeroTier::picostack->pico_Socket(&p, socket_family, socket_type, protocol);
|
||||
if(p) {
|
||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
||||
conn->socket_family = socket_family;
|
||||
conn->socket_type = socket_type;
|
||||
conn->picosock = p;
|
||||
ZeroTier::unmap[conn->app_fd] = conn;
|
||||
err = conn->app_fd; // return one end of the socketpair
|
||||
ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket();
|
||||
vs->socket_family = socket_family;
|
||||
vs->socket_type = socket_type;
|
||||
vs->picosock = p;
|
||||
ZeroTier::unmap[vs->app_fd] = vs;
|
||||
err = vs->app_fd; // return one end of the socketpair
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("failed to create pico_socket");
|
||||
@@ -427,12 +427,12 @@ int zts_socket(ZT_SOCKET_SIG) {
|
||||
void *pcb;
|
||||
err = ZeroTier::lwipstack->lwip_Socket(&pcb, socket_family, socket_type, protocol);
|
||||
if(pcb) {
|
||||
ZeroTier::Connection *conn = new ZeroTier::Connection();
|
||||
conn->socket_family = socket_family;
|
||||
conn->socket_type = socket_type;
|
||||
conn->pcb = pcb;
|
||||
ZeroTier::unmap[conn->app_fd] = conn;
|
||||
err = conn->app_fd; // return one end of the socketpair
|
||||
ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket();
|
||||
vs->socket_family = socket_family;
|
||||
vs->socket_type = socket_type;
|
||||
vs->pcb = pcb;
|
||||
ZeroTier::unmap[vs->app_fd] = vs;
|
||||
err = vs->app_fd; // return one end of the socketpair
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("failed to create lwip pcb");
|
||||
@@ -453,12 +453,12 @@ Darwin:
|
||||
[ ] [EADDRINUSE] The address is already in use.
|
||||
[ ] [EADDRNOTAVAIL] The specified address is not available on this machine.
|
||||
[ ] [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.
|
||||
[ ] [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.
|
||||
[ ] [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.
|
||||
[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).
|
||||
@@ -467,26 +467,26 @@ Darwin:
|
||||
[--] [ENETUNREACH] The network isn't reachable from this host.
|
||||
[ ] [ENOBUFS] The system call was unable to allocate a needed memory buffer.
|
||||
[ ] [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.
|
||||
[ ] [ETIMEDOUT] Connection establishment timed out without establishing a connection.
|
||||
[ ] [ECONNRESET] Remote host reset the connection request.
|
||||
[ ] [ETIMEDOUT] VirtualSocket establishment timed out without establishing a VirtualSocket.
|
||||
[ ] [ECONNRESET] Remote host reset the VirtualSocket request.
|
||||
|
||||
Linux:
|
||||
|
||||
[ ] [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).)
|
||||
[ ] [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.
|
||||
[ ] [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
|
||||
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.
|
||||
[ ] [ECONNREFUSED] No-one listening on the remote address.
|
||||
[ ] [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)
|
||||
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).
|
||||
@@ -494,7 +494,7 @@ Linux:
|
||||
[ ] [EISCONN] The socket is already connected.
|
||||
[ ] [ENETUNREACH] Network is unreachable.
|
||||
[ ] [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.
|
||||
|
||||
*/
|
||||
@@ -512,22 +512,22 @@ int zts_connect(ZT_CONNECT_SIG) {
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
ZeroTier::SocketTap *tap;
|
||||
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||
ZeroTier::VirtualTap *tap;
|
||||
|
||||
if(conn) {
|
||||
if(vs) {
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||
ZeroTier::InetAddress iaddr;
|
||||
int port = 0;
|
||||
|
||||
if(conn->socket_family == AF_INET) {
|
||||
if(vs->socket_family == AF_INET) {
|
||||
inet_ntop(AF_INET,
|
||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||
iaddr.fromString(ipstr);
|
||||
port = ((struct sockaddr_in*)addr)->sin_port;
|
||||
}
|
||||
if(conn->socket_family == AF_INET6) {
|
||||
if(vs->socket_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6,
|
||||
(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
|
||||
@@ -546,33 +546,33 @@ int zts_connect(ZT_CONNECT_SIG) {
|
||||
else {
|
||||
#if defined(STACK_PICO)
|
||||
// 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
|
||||
#if defined(STACK_LWIP)
|
||||
#endif
|
||||
err = tap->Connect(conn, addr, addrlen);
|
||||
err = tap->Connect(vs, addr, addrlen);
|
||||
if(err == 0) {
|
||||
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
|
||||
conn->tap = tap;
|
||||
tap->_VirtualSockets.push_back(vs); // Give this VirtualSocket to the tap we decided on
|
||||
vs->tap = tap;
|
||||
}
|
||||
// Wrap the socketpair we created earlier
|
||||
// For I/O loop participation and referencing the PhySocket's parent Connection in callbacks
|
||||
conn->sock = tap->_phy.wrapSocket(conn->sdk_fd, conn);
|
||||
// For I/O loop participation and referencing the PhySocket's parent VirtualSocket in callbacks
|
||||
vs->sock = tap->_phy.wrapSocket(vs->sdk_fd, vs);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("unable to locate connection");
|
||||
DEBUG_ERROR("unable to locate VirtualSocket");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
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();
|
||||
|
||||
// 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
|
||||
// callback we will place the Connection 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
|
||||
// the VirtualSocket was completed, for that we must wait for a callback from the stack. During that
|
||||
// callback we will place the VirtualSocket in a ZT_SOCK_STATE_UNHANDLED_CONNECTED state to signal
|
||||
// to the multiplexer logic that this VirtualSocket is complete and a success value can be sent to the
|
||||
// user application
|
||||
|
||||
int f_err, blocking = 1;
|
||||
@@ -596,15 +596,15 @@ int zts_connect(ZT_CONNECT_SIG) {
|
||||
bool complete = false;
|
||||
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())
|
||||
usleep(ZT_CONNECT_RECHECK_DELAY * 1000);
|
||||
//DEBUG_ERROR("waiting to connect...\n");
|
||||
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(tap->_Connections[i]->state == PICO_ERR_ECONNRESET) {
|
||||
if(tap->_VirtualSockets[i]->state == PICO_ERR_ECONNRESET) {
|
||||
errno = ECONNRESET;
|
||||
DEBUG_ERROR("ECONNRESET");
|
||||
err = -1;
|
||||
@@ -612,8 +612,8 @@ int zts_connect(ZT_CONNECT_SIG) {
|
||||
#endif
|
||||
#if defined(STACK_LWIP)
|
||||
#endif
|
||||
if(tap->_Connections[i]->state == ZT_SOCK_STATE_UNHANDLED_CONNECTED) {
|
||||
tap->_Connections[i]->state = ZT_SOCK_STATE_CONNECTED;
|
||||
if(tap->_VirtualSockets[i]->state == ZT_SOCK_STATE_UNHANDLED_CONNECTED) {
|
||||
tap->_VirtualSockets[i]->state = ZT_SOCK_STATE_CONNECTED;
|
||||
errno = 0;
|
||||
err = 0; // complete
|
||||
complete = true;
|
||||
@@ -655,20 +655,20 @@ int zts_bind(ZT_BIND_SIG) {
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
ZeroTier::SocketTap *tap;
|
||||
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||
ZeroTier::VirtualTap *tap;
|
||||
|
||||
if(conn) {
|
||||
if(vs) {
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||
ZeroTier::InetAddress iaddr;
|
||||
int port = 0;
|
||||
if(conn->socket_family == AF_INET) {
|
||||
if(vs->socket_family == AF_INET) {
|
||||
inet_ntop(AF_INET,
|
||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||
port = ((struct sockaddr_in*)addr)->sin_port;
|
||||
}
|
||||
if(conn->socket_family == AF_INET6) {
|
||||
if(vs->socket_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6,
|
||||
(const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN);
|
||||
port = ((struct sockaddr_in6*)addr)->sin6_port;
|
||||
@@ -684,30 +684,30 @@ int zts_bind(ZT_BIND_SIG) {
|
||||
}
|
||||
#if defined(STACK_PICO)
|
||||
else {
|
||||
conn->picosock->priv = new ZeroTier::ConnectionPair(tap, conn);
|
||||
tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on
|
||||
err = tap->Bind(conn, addr, addrlen);
|
||||
conn->tap = tap;
|
||||
vs->picosock->priv = new ZeroTier::VirtualBindingPair(tap, vs);
|
||||
tap->_VirtualSockets.push_back(vs); // Give this VirtualSocket to the tap we decided on
|
||||
err = tap->Bind(vs, addr, addrlen);
|
||||
vs->tap = tap;
|
||||
if(err == 0) { // success
|
||||
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
|
||||
#if defined(STACK_LWIP)
|
||||
else {
|
||||
tap->_Connections.push_back(conn);
|
||||
err = tap->Bind(conn, addr, addrlen);
|
||||
conn->tap = tap;
|
||||
tap->_VirtualSockets.push_back(vs);
|
||||
err = tap->Bind(vs, addr, addrlen);
|
||||
vs->tap = tap;
|
||||
if(err == 0) { // success
|
||||
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
|
||||
}
|
||||
else {
|
||||
DEBUG_ERROR("unable to locate connection");
|
||||
DEBUG_ERROR("unable to locate VirtualSocket");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
@@ -746,23 +746,23 @@ int zts_listen(ZT_LISTEN_SIG) {
|
||||
return -1;
|
||||
}
|
||||
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) {
|
||||
DEBUG_ERROR("unable to locate connection pair. did you bind?");
|
||||
DEBUG_ERROR("unable to locate VirtualSocket pair. did you bind?");
|
||||
errno = EDESTADDRREQ;
|
||||
return -1;
|
||||
}
|
||||
ZeroTier::Connection *conn = p->first;
|
||||
ZeroTier::SocketTap *tap = p->second;
|
||||
if(!tap || !conn) {
|
||||
ZeroTier::VirtualSocket *vs = p->first;
|
||||
ZeroTier::VirtualTap *tap = p->second;
|
||||
if(!tap || !vs) {
|
||||
DEBUG_ERROR("unable to locate tap interface for file descriptor");
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
if(!err) {
|
||||
backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn
|
||||
err = tap->Listen(conn, backlog);
|
||||
conn->state = ZT_SOCK_STATE_LISTENING;
|
||||
err = tap->Listen(vs, backlog);
|
||||
vs->state = ZT_SOCK_STATE_LISTENING;
|
||||
ZeroTier::_multiplexer_lock.unlock();
|
||||
}
|
||||
return err;
|
||||
@@ -777,7 +777,7 @@ Darwin:
|
||||
[ ] [EOPNOTSUPP] The referenced socket is not of type SOCK_STREAM.
|
||||
[ ] [EFAULT] The addr parameter is not in a writable part of the
|
||||
user address space.
|
||||
[--] [EWOULDBLOCK] The socket is marked non-blocking and no connections
|
||||
[--] [EWOULDBLOCK] The socket is marked non-blocking and no VirtualSockets
|
||||
are present to be accepted.
|
||||
[--] [EMFILE] The per-process descriptor table is full.
|
||||
[ ] [ENFILE] The system file table is full.
|
||||
@@ -789,24 +789,24 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
errno = EBADF;
|
||||
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()) {
|
||||
DEBUG_ERROR("cannot provision additional socket due to limitation of network stack");
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
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) {
|
||||
DEBUG_ERROR("unable to locate connection pair (did you zts_bind())?");
|
||||
DEBUG_ERROR("unable to locate VirtualSocket pair (did you zts_bind())?");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
else {
|
||||
ZeroTier::Connection *conn = p->first;
|
||||
ZeroTier::SocketTap *tap = p->second;
|
||||
ZeroTier::VirtualSocket *vs = p->first;
|
||||
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;
|
||||
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
|
||||
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
|
||||
@@ -817,24 +817,24 @@ int zts_accept(ZT_ACCEPT_SIG) {
|
||||
}
|
||||
|
||||
if(!err) {
|
||||
ZeroTier::Connection *accepted_conn;
|
||||
ZeroTier::VirtualSocket *accepted_vs;
|
||||
if(!blocking) { // non-blocking
|
||||
DEBUG_EXTRA("EWOULDBLOCK, not a real error, assuming non-blocking mode");
|
||||
errno = EWOULDBLOCK;
|
||||
err = -1;
|
||||
accepted_conn = tap->Accept(conn);
|
||||
accepted_vs = tap->Accept(vs);
|
||||
}
|
||||
else { // blocking
|
||||
while(true) {
|
||||
usleep(ZT_ACCEPT_RECHECK_DELAY * 1000);
|
||||
accepted_conn = tap->Accept(conn);
|
||||
if(accepted_conn)
|
||||
accepted_vs = tap->Accept(vs);
|
||||
if(accepted_vs)
|
||||
break; // accepted fd = err
|
||||
}
|
||||
}
|
||||
if(accepted_conn) {
|
||||
ZeroTier::fdmap[accepted_conn->app_fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(accepted_conn, tap);
|
||||
err = accepted_conn->app_fd;
|
||||
if(accepted_vs) {
|
||||
ZeroTier::fdmap[accepted_vs->app_fd] = new std::pair<ZeroTier::VirtualSocket*,ZeroTier::VirtualTap*>(accepted_vs, tap);
|
||||
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.
|
||||
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.
|
||||
[ ] [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.
|
||||
[NA] [EINTR] The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).
|
||||
[ ] [EINVAL] Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
|
||||
[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 VirtualSockets, or addrlen is invalid (e.g., is negative).
|
||||
[ ] [EINVAL] (accept4()) invalid value in flags.
|
||||
[ ] [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.
|
||||
@@ -863,7 +863,7 @@ Errors
|
||||
|
||||
In addition, Linux accept() may fail if:
|
||||
|
||||
EPERM Firewall rules forbid connection.
|
||||
EPERM Firewall rules forbid VirtualSocket.
|
||||
*/
|
||||
#if defined(__linux__)
|
||||
int zts_accept4(ZT_ACCEPT4_SIG)
|
||||
@@ -1016,36 +1016,36 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
{
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
//DEBUG_INFO("unmap=%d, fdmap=%d", ZeroTier::unmap.size(), ZeroTier::fdmap.size());
|
||||
// First, look for for unassigned connections
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
// First, look for for unassigned VirtualSockets
|
||||
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
|
||||
if(conn) // unassigned
|
||||
if(vs) // unassigned
|
||||
{
|
||||
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()");
|
||||
if((err = close(conn->app_fd)) < 0)
|
||||
if((err = close(vs->app_fd)) < 0)
|
||||
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");
|
||||
delete conn;
|
||||
delete vs;
|
||||
ZeroTier::unmap.erase(fd);
|
||||
}
|
||||
else // assigned
|
||||
{
|
||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
||||
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||
if(!p)
|
||||
{
|
||||
DEBUG_ERROR("unable to locate connection pair.");
|
||||
DEBUG_ERROR("unable to locate VirtualSocket pair.");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
else // found everything, begin closure
|
||||
{
|
||||
conn = p->first;
|
||||
ZeroTier::SocketTap *tap = p->second;
|
||||
vs = p->first;
|
||||
ZeroTier::VirtualTap *tap = p->second;
|
||||
|
||||
// check if socket is blocking
|
||||
int f_err, blocking = 1;
|
||||
@@ -1060,7 +1060,7 @@ int zts_close(ZT_CLOSE_SIG)
|
||||
if(blocking) {
|
||||
DEBUG_INFO("blocking, waiting for write operations before closure...");
|
||||
for(int i=0; i<ZT_SDK_CLTIME; i++) {
|
||||
if(conn->TXbuf->count() == 0)
|
||||
if(vs->TXbuf->count() == 0)
|
||||
break;
|
||||
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));
|
||||
tap->Close(conn);
|
||||
//DEBUG_INFO("s->state = %s", ZeroTier::picoTCP::beautify_pico_state(vs->picosock->state));
|
||||
tap->Close(vs);
|
||||
ZeroTier::fdmap.erase(fd);
|
||||
err = 0;
|
||||
}
|
||||
@@ -1165,23 +1165,23 @@ int zts_ioctl(ZT_IOCTL_SIG)
|
||||
if(argp)
|
||||
{
|
||||
struct ifreq *ifr = (struct ifreq *)argp;
|
||||
ZeroTier::SocketTap *tap = getTapByName(ifr->ifr_name);
|
||||
ZeroTier::VirtualTap *tap = getTapByName(ifr->ifr_name);
|
||||
if(!tap) {
|
||||
DEBUG_ERROR("unable to locate tap interface with that name");
|
||||
err = -1;
|
||||
errno = EINVAL;
|
||||
}
|
||||
// index of SocketTap interface
|
||||
// index of VirtualTap interface
|
||||
if(request == SIOCGIFINDEX) {
|
||||
ifr->ifr_ifindex = tap->ifindex;
|
||||
err = 0;
|
||||
}
|
||||
// MAC addres or SocketTap
|
||||
// MAC addres or VirtualTap
|
||||
if(request == SIOCGIFHWADDR) {
|
||||
tap->_mac.copyTo(&(ifr->ifr_hwaddr.sa_data), sizeof(ifr->ifr_hwaddr.sa_data));
|
||||
err = 0;
|
||||
}
|
||||
// IP address of SocketTap
|
||||
// IP address of VirtualTap
|
||||
if(request == SIOCGIFADDR) {
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in *)&(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.
|
||||
[ ] [EBADF] An invalid descriptor was specified.
|
||||
[ ] [ECONNRESET] Connection reset by peer.
|
||||
[ ] [EDESTADDRREQ] The socket is not connection-mode, and no peer address is set.
|
||||
[ ] [ECONNRESET] VirtualSocket reset by peer.
|
||||
[ ] [EDESTADDRREQ] The socket is not VirtualSocket-mode, and no peer address is set.
|
||||
[ ] [EFAULT] An invalid user space address was specified for an argument.
|
||||
[ ] [EINTR] A signal occurred before any data was transmitted; see signal(7).
|
||||
[ ] [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.
|
||||
[ ] [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.
|
||||
[ ] [ENOTCONN] The socket is not connected, and no target has been given.
|
||||
[ ] [ENOTSOCK] The argument sockfd is not a socket.
|
||||
[ ] [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)
|
||||
@@ -1230,21 +1230,21 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
err = -1;
|
||||
}
|
||||
else {
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||
ZeroTier::InetAddress iaddr;
|
||||
ZeroTier::SocketTap *tap;
|
||||
ZeroTier::VirtualTap *tap;
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
int port;
|
||||
memset(ipstr, 0, INET6_ADDRSTRLEN);
|
||||
|
||||
if(conn->socket_type == SOCK_DGRAM) {
|
||||
if(conn->socket_family == AF_INET) {
|
||||
if(vs->socket_type == SOCK_DGRAM) {
|
||||
if(vs->socket_family == AF_INET) {
|
||||
inet_ntop(AF_INET,
|
||||
(const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN);
|
||||
iaddr.fromString(ipstr);
|
||||
port = ((struct sockaddr_in*)addr)->sin_port;
|
||||
}
|
||||
if(conn->socket_family == AF_INET6) {
|
||||
if(vs->socket_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6,
|
||||
(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
|
||||
@@ -1255,7 +1255,7 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
}
|
||||
tap = getTapByAddr(iaddr);
|
||||
if(tap) {
|
||||
tap->SendTo(conn, buf, len, flags, addr, addrlen);
|
||||
tap->SendTo(vs, buf, len, flags, addr, addrlen);
|
||||
}
|
||||
else {
|
||||
DEBUG_INFO("SOCK_DGRAM, tap not found");
|
||||
@@ -1263,19 +1263,19 @@ ssize_t zts_sendto(ZT_SENDTO_SIG)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(conn->socket_type == SOCK_RAW)
|
||||
if(vs->socket_type == SOCK_RAW)
|
||||
{
|
||||
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)
|
||||
{
|
||||
DEBUG_INFO("found interface of ifindex=%d", tap->ifindex);
|
||||
if(conn) {
|
||||
DEBUG_INFO("located connection object for fd=%d", fd);
|
||||
err = tap->Write(conn, (void*)buf, len);
|
||||
if(vs) {
|
||||
DEBUG_INFO("located VirtualSocket object for fd=%d", fd);
|
||||
err = tap->Write(vs, (void*)buf, len);
|
||||
}
|
||||
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;
|
||||
errno = EINVAL;
|
||||
}
|
||||
@@ -1371,11 +1371,11 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
||||
else
|
||||
{
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
// First, look for for unassigned connections
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
// Since we found an unassigned connection, we don't need to consult the stack or tap
|
||||
// First, look for for unassigned VirtualSockets
|
||||
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||
// 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
|
||||
if(conn) // unassigned
|
||||
if(vs) // unassigned
|
||||
{
|
||||
DEBUG_ERROR("unassigned shutdown");
|
||||
/*
|
||||
@@ -1383,24 +1383,24 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
||||
PICO_SHUT_WR
|
||||
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()");
|
||||
delete conn;
|
||||
delete vs;
|
||||
ZeroTier::unmap.erase(fd);
|
||||
// FIXME: Is deleting this correct behaviour?
|
||||
}
|
||||
else // assigned
|
||||
{
|
||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
||||
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||
if(!p)
|
||||
{
|
||||
DEBUG_ERROR("unable to locate connection pair.");
|
||||
DEBUG_ERROR("unable to locate VirtualSocket pair.");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
else // found everything, begin closure
|
||||
{
|
||||
conn = p->first;
|
||||
vs = p->first;
|
||||
int f_err, blocking = 1;
|
||||
if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) {
|
||||
DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno);
|
||||
@@ -1412,13 +1412,13 @@ int zts_shutdown(ZT_SHUTDOWN_SIG)
|
||||
if(blocking) {
|
||||
DEBUG_INFO("blocking, waiting for write operations before shutdown...");
|
||||
for(int i=0; i<ZT_SDK_CLTIME; i++) {
|
||||
if(conn->TXbuf->count() == 0)
|
||||
if(vs->TXbuf->count() == 0)
|
||||
break;
|
||||
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()");
|
||||
}
|
||||
}
|
||||
@@ -1704,19 +1704,19 @@ int zts_get_pico_socket(int fd, struct pico_socket **s)
|
||||
else
|
||||
{
|
||||
ZeroTier::_multiplexer_lock.lock();
|
||||
// First, look for for unassigned connections
|
||||
ZeroTier::Connection *conn = ZeroTier::unmap[fd];
|
||||
if(conn)
|
||||
// First, look for for unassigned VirtualSockets
|
||||
ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd];
|
||||
if(vs)
|
||||
{
|
||||
*s = conn->picosock;
|
||||
*s = vs->picosock;
|
||||
err = 1; // unassigned
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<ZeroTier::Connection*, ZeroTier::SocketTap*> *p = ZeroTier::fdmap[fd];
|
||||
std::pair<ZeroTier::VirtualSocket*, ZeroTier::VirtualTap*> *p = ZeroTier::fdmap[fd];
|
||||
if(!p)
|
||||
{
|
||||
DEBUG_ERROR("unable to locate connection pair.");
|
||||
DEBUG_ERROR("unable to locate VirtualSocket pair.");
|
||||
errno = EBADF;
|
||||
err = -1;
|
||||
}
|
||||
@@ -1774,25 +1774,25 @@ std::vector<ZT_VirtualNetworkRoute> *zts_get_network_routes(char *nwid)
|
||||
return ZeroTier::zt1Service->getRoutes(nwid_int);
|
||||
}
|
||||
|
||||
ZeroTier::SocketTap *getTapByNWID(uint64_t nwid)
|
||||
ZeroTier::VirtualTap *getTapByNWID(uint64_t nwid)
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::SocketTap *s, *tap = nullptr;
|
||||
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||
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; }
|
||||
}
|
||||
ZeroTier::_vtaps_lock.unlock();
|
||||
return tap;
|
||||
}
|
||||
|
||||
ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr)
|
||||
ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress &addr)
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::SocketTap *s, *tap = nullptr;
|
||||
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||
char ipbuf[64], ipbuf2[64], ipbuf3[64];
|
||||
for(int i=0; i<ZeroTier::vtaps.size(); i++) {
|
||||
s = (ZeroTier::SocketTap*)ZeroTier::vtaps[i];
|
||||
s = (ZeroTier::VirtualTap*)ZeroTier::vtaps[i];
|
||||
// check address schemes
|
||||
for(int j=0; j<s->_ips.size(); j++) {
|
||||
if(s->_ips[j].isEqualPrefix(addr)
|
||||
@@ -1824,12 +1824,12 @@ ZeroTier::SocketTap *getTapByAddr(ZeroTier::InetAddress &addr)
|
||||
return tap;
|
||||
}
|
||||
|
||||
ZeroTier::SocketTap *getTapByName(char *ifname)
|
||||
ZeroTier::VirtualTap *getTapByName(char *ifname)
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::SocketTap *s, *tap = nullptr;
|
||||
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||
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)) {
|
||||
tap = s;
|
||||
}
|
||||
@@ -1838,12 +1838,12 @@ ZeroTier::SocketTap *getTapByName(char *ifname)
|
||||
return tap;
|
||||
}
|
||||
|
||||
ZeroTier::SocketTap *getTapByIndex(int index)
|
||||
ZeroTier::VirtualTap *getTapByIndex(int index)
|
||||
{
|
||||
ZeroTier::_vtaps_lock.lock();
|
||||
ZeroTier::SocketTap *s, *tap = nullptr;
|
||||
ZeroTier::VirtualTap *s, *tap = nullptr;
|
||||
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) {
|
||||
tap = s;
|
||||
}
|
||||
@@ -1855,7 +1855,7 @@ ZeroTier::SocketTap *getTapByIndex(int index)
|
||||
void dismantleTaps()
|
||||
{
|
||||
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_lock.unlock();
|
||||
}
|
||||
|
||||
280
src/lwIP.cpp
280
src/lwIP.cpp
@@ -29,7 +29,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "libzt.h"
|
||||
#include "SocketTap.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
#include "Utilities.hpp"
|
||||
#include "lwIP.hpp"
|
||||
|
||||
@@ -57,7 +57,7 @@ err_t low_level_output(struct netif *netif, struct pbuf *p)
|
||||
char *bufptr;
|
||||
int totalLength = 0;
|
||||
|
||||
ZeroTier::SocketTap *tap = (ZeroTier::SocketTap*)netif->state;
|
||||
ZeroTier::VirtualTap *tap = (ZeroTier::VirtualTap*)netif->state;
|
||||
bufptr = buf;
|
||||
// Copy data from each pbuf, one at a time
|
||||
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
|
||||
{
|
||||
void lwIP::lwip_init_interface(SocketTap *tap, const InetAddress &ip)
|
||||
void lwIP::lwip_init_interface(VirtualTap *tap, const InetAddress &ip)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
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();
|
||||
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);
|
||||
struct pbuf *p,*q;
|
||||
@@ -249,7 +249,7 @@ namespace ZeroTier
|
||||
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();
|
||||
ip_addr_t ba;
|
||||
@@ -269,7 +269,7 @@ namespace ZeroTier
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr;
|
||||
in6_to_ip6((ip6_addr *)&ba, in6);
|
||||
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);
|
||||
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port));
|
||||
}
|
||||
@@ -277,25 +277,25 @@ namespace ZeroTier
|
||||
|
||||
DEBUG_INFO("addr=%s", addrstr);
|
||||
|
||||
if(conn->socket_type == SOCK_DGRAM) {
|
||||
if(vs->socket_type == SOCK_DGRAM) {
|
||||
// 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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if(conn->socket_type == SOCK_STREAM) {
|
||||
struct tcp_pcb *tpcb = (struct tcp_pcb*)conn->pcb;
|
||||
if(vs->socket_type == SOCK_STREAM) {
|
||||
struct tcp_pcb *tpcb = (struct tcp_pcb*)vs->pcb;
|
||||
tcp_sent(tpcb, nc_sent);
|
||||
tcp_recv(tpcb, nc_recved);
|
||||
tcp_err(tpcb, nc_err);
|
||||
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);
|
||||
//if(conn->TCP_pcb->state != CLOSED) {
|
||||
//DEBUG_EXTRA(" pcb->state=%x", vs->TCP_pcb->state);
|
||||
//if(vs->TCP_pcb->state != CLOSED) {
|
||||
// DEBUG_INFO(" cannot connect using this PCB, PCB!=CLOSED");
|
||||
// tap->sendReturnValue(tap->_phy.getDescriptor(rpcSock), -1, EAGAIN);
|
||||
// return;
|
||||
@@ -343,7 +343,7 @@ namespace ZeroTier
|
||||
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();
|
||||
ip_addr_t ba;
|
||||
@@ -363,26 +363,26 @@ namespace ZeroTier
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr;
|
||||
in6_to_ip6((ip6_addr *)&ba, in6);
|
||||
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);
|
||||
DEBUG_INFO("%s:%d", addrstr, lwip_ntohs(connaddr6->sin6_port));
|
||||
}
|
||||
#endif
|
||||
if(conn->socket_type == SOCK_DGRAM) {
|
||||
err = udp_bind((struct udp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port);
|
||||
if(vs->socket_type == SOCK_DGRAM) {
|
||||
err = udp_bind((struct udp_pcb*)vs->pcb, (const ip_addr_t *)&ba, port);
|
||||
if(err == ERR_USE) {
|
||||
err = -1;
|
||||
errno = EADDRINUSE; // port in use
|
||||
}
|
||||
else {
|
||||
// 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;
|
||||
errno = ERR_OK; // success
|
||||
}
|
||||
}
|
||||
else if (conn->socket_type == SOCK_STREAM) {
|
||||
err = tcp_bind((struct tcp_pcb*)conn->pcb, (const ip_addr_t *)&ba, port);
|
||||
else if (vs->socket_type == SOCK_STREAM) {
|
||||
err = tcp_bind((struct tcp_pcb*)vs->pcb, (const ip_addr_t *)&ba, port);
|
||||
if(err != ERR_OK) {
|
||||
DEBUG_ERROR("err=%d", err);
|
||||
if(err == ERR_USE){
|
||||
@@ -406,103 +406,103 @@ namespace ZeroTier
|
||||
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;
|
||||
#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
|
||||
listeningPCB = tcp_listen((struct tcp_pcb*)conn->pcb);
|
||||
listeningPCB = tcp_listen((struct tcp_pcb*)vs->pcb);
|
||||
#endif
|
||||
if(listeningPCB != NULL) {
|
||||
conn->pcb = listeningPCB;
|
||||
vs->pcb = listeningPCB;
|
||||
tcp_accept(listeningPCB, nc_accept); // set callback
|
||||
tcp_arg(listeningPCB, conn);
|
||||
//fcntl(tap->_phy.getDescriptor(conn->sock), F_SETFL, O_NONBLOCK);
|
||||
tcp_arg(listeningPCB, vs);
|
||||
//fcntl(tap->_phy.getDescriptor(vs->sock), F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Connection* lwIP::lwip_Accept(Connection *conn)
|
||||
VirtualSocket* lwIP::lwip_Accept(VirtualSocket *vs)
|
||||
{
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid conn");
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid virtual socket");
|
||||
handle_general_failure();
|
||||
return NULL;
|
||||
}
|
||||
// Retreive first of queued Connections from parent connection
|
||||
Connection *new_conn = NULL;
|
||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
||||
if(conn->_AcceptedConnections.size()) {
|
||||
new_conn = conn->_AcceptedConnections.front();
|
||||
conn->_AcceptedConnections.pop();
|
||||
// Retreive first of queued VirtualSockets from parent VirtualSocket
|
||||
VirtualSocket *new_vs = NULL;
|
||||
Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||
if(vs->_AcceptedConnections.size()) {
|
||||
new_vs = vs->_AcceptedConnections.front();
|
||||
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;
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("no connection");
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("no VirtualSocket");
|
||||
return -1;
|
||||
}
|
||||
if(!lwip_invoked) {
|
||||
DEBUG_INFO("!lwip_invoked");
|
||||
conn->tap->_tcpconns_m.lock();
|
||||
conn->_rx_m.lock();
|
||||
vs->tap->_tcpconns_m.lock();
|
||||
vs->_rx_m.lock();
|
||||
}
|
||||
if(conn->RXbuf->count()) {
|
||||
int max = conn->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 n = conn->tap->_phy.streamSend(conn->sock, conn->RXbuf->get_buf(), wr);
|
||||
if(vs->RXbuf->count()) {
|
||||
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)vs->RXbuf->count());
|
||||
int n = vs->tap->_phy.streamSend(vs->sock, vs->RXbuf->get_buf(), wr);
|
||||
char str[22];
|
||||
memcpy(str, conn->RXbuf->get_buf(), 22);
|
||||
conn->RXbuf->consume(n);
|
||||
memcpy(str, vs->RXbuf->get_buf(), 22);
|
||||
vs->RXbuf->consume(n);
|
||||
|
||||
if(conn->socket_type == SOCK_DGRAM)
|
||||
if(vs->socket_type == SOCK_DGRAM)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
if(conn->socket_type == SOCK_STREAM) { // Only acknolwedge receipt of TCP packets
|
||||
tcp_recved((struct tcp_pcb*)conn->pcb, n);
|
||||
if(vs->socket_type == SOCK_STREAM) { // Only acknolwedge receipt of TCP packets
|
||||
tcp_recved((struct tcp_pcb*)vs->pcb, n);
|
||||
DEBUG_TRANS("TCP RX %d bytes", n);
|
||||
}
|
||||
}
|
||||
if(conn->RXbuf->count() == 0) {
|
||||
if(vs->RXbuf->count() == 0) {
|
||||
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) {
|
||||
conn->tap->_tcpconns_m.unlock();
|
||||
conn->_rx_m.unlock();
|
||||
vs->tap->_tcpconns_m.unlock();
|
||||
vs->_rx_m.unlock();
|
||||
}
|
||||
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;
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("no connection");
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("no VirtualSocket");
|
||||
return -1;
|
||||
}
|
||||
if(conn->socket_type == SOCK_DGRAM)
|
||||
if(vs->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
|
||||
int udp_trans_len = std::min((ssize_t)conn->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());
|
||||
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, vs->TXbuf->count());
|
||||
struct pbuf * pb = pbuf_alloc(PBUF_TRANSPORT, udp_trans_len, PBUF_POOL);
|
||||
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;
|
||||
}
|
||||
memcpy(pb->payload, conn->TXbuf->get_buf(), udp_trans_len);
|
||||
int err = udp_send((struct udp_pcb*)conn->pcb, pb);
|
||||
memcpy(pb->payload, vs->TXbuf->get_buf(), udp_trans_len);
|
||||
int err = udp_send((struct udp_pcb*)vs->pcb, pb);
|
||||
|
||||
if(err == ERR_MEM) {
|
||||
DEBUG_ERROR("error sending packet. out of memory");
|
||||
@@ -511,48 +511,48 @@ namespace ZeroTier
|
||||
} else if(err != ERR_OK) {
|
||||
DEBUG_ERROR("error sending packet - %d", err);
|
||||
} else {
|
||||
conn->TXbuf->consume(udp_trans_len); // success
|
||||
vs->TXbuf->consume(udp_trans_len); // success
|
||||
}
|
||||
pbuf_free(pb);
|
||||
return ERR_OK;
|
||||
}
|
||||
if(conn->socket_type == SOCK_STREAM)
|
||||
if(vs->socket_type == SOCK_STREAM)
|
||||
{
|
||||
DEBUG_ERROR("socket_type==SOCK_STREAM");
|
||||
// How much we are currently allowed to write to the connection
|
||||
ssize_t sndbuf = ((struct tcp_pcb*)conn->pcb)->snd_buf;
|
||||
// How much we are currently allowed to write to the VirtualSocket
|
||||
ssize_t sndbuf = ((struct tcp_pcb*)vs->pcb)->snd_buf;
|
||||
int err, r;
|
||||
if(!sndbuf) {
|
||||
// PCB send buffer is full, turn off readability notifications for the
|
||||
// corresponding PhySocket until nc_sent() is called and confirms that there is
|
||||
// now space on the buffer
|
||||
DEBUG_ERROR("lwIP stack is full, sndbuf == 0");
|
||||
conn->tap->_phy.setNotifyReadable(conn->sock, false);
|
||||
vs->tap->_phy.setNotifyReadable(vs->sock, false);
|
||||
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) {
|
||||
// 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);
|
||||
exit(0);
|
||||
}
|
||||
if(conn->TXbuf->count() <= 0) {
|
||||
if(vs->TXbuf->count() <= 0) {
|
||||
return -1; // nothing to write
|
||||
}
|
||||
if(conn->sock) {
|
||||
r = std::min((ssize_t)conn->TXbuf->count(), sndbuf);
|
||||
if(vs->sock) {
|
||||
r = std::min((ssize_t)vs->TXbuf->count(), sndbuf);
|
||||
// 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.
|
||||
if(r > 0) {
|
||||
err = tcp_write((struct tcp_pcb*)conn->pcb, conn->TXbuf->get_buf(), r, TCP_WRITE_FLAG_COPY);
|
||||
tcp_output((struct tcp_pcb*)conn->pcb);
|
||||
err = tcp_write((struct tcp_pcb*)vs->pcb, vs->TXbuf->get_buf(), r, TCP_WRITE_FLAG_COPY);
|
||||
tcp_output((struct tcp_pcb*)vs->pcb);
|
||||
if(err != ERR_OK) {
|
||||
DEBUG_ERROR("error while writing to lwIP tcp_pcb, err=%d", err);
|
||||
if(err == -1)
|
||||
DEBUG_ERROR("lwIP out of memory");
|
||||
return -1;
|
||||
} else {
|
||||
conn->TXbuf->consume(r); // success
|
||||
vs->TXbuf->consume(r); // success
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
@@ -561,22 +561,22 @@ namespace ZeroTier
|
||||
return err;
|
||||
}
|
||||
|
||||
int lwIP::lwip_Close(Connection *conn)
|
||||
int lwIP::lwip_Close(VirtualSocket *vs)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
|
||||
if(conn->socket_type == SOCK_DGRAM) {
|
||||
udp_remove((struct udp_pcb*)conn->pcb);
|
||||
if(vs->socket_type == SOCK_DGRAM) {
|
||||
udp_remove((struct udp_pcb*)vs->pcb);
|
||||
}
|
||||
// FIXME: check if already closed? conn->TCP_pcb->state != CLOSED
|
||||
if(conn->pcb) {
|
||||
//DEBUG_EXTRA("conn=%p, sock=%p, PCB->state = %d",
|
||||
// (void*)&conn, (void*)&sock, conn->TCP_pcb->state);
|
||||
if(((struct tcp_pcb*)conn->pcb)->state == SYN_SENT /*|| conn->TCP_pcb->state == CLOSE_WAIT*/) {
|
||||
DEBUG_EXTRA("ignoring close request. invalid PCB state for this operation. sock=%p", conn->sock);
|
||||
// FIXME: check if already closed? vs->TCP_pcb->state != CLOSED
|
||||
if(vs->pcb) {
|
||||
//DEBUG_EXTRA("vs=%p, sock=%p, PCB->state = %d",
|
||||
// (void*)&conn, (void*)&sock, vs->TCP_pcb->state);
|
||||
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", vs->sock);
|
||||
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) {
|
||||
// Unregister callbacks for this PCB
|
||||
tcp_arg(tpcb, NULL);
|
||||
@@ -586,7 +586,7 @@ namespace ZeroTier
|
||||
tcp_poll(tpcb, NULL, 1);
|
||||
}
|
||||
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;
|
||||
@@ -599,22 +599,22 @@ namespace ZeroTier
|
||||
err_t lwIP::nc_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err)
|
||||
{
|
||||
DEBUG_INFO();
|
||||
Connection *conn = (Connection *)arg;
|
||||
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||
int tot = 0;
|
||||
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("no connection");
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("no VirtualSocket");
|
||||
return ERR_OK; // FIXME: Determine if this is correct behaviour expected by the stack
|
||||
}
|
||||
|
||||
//Mutex::Lock _l(conn->tap->_tcpconns_m);
|
||||
//Mutex::Lock _l2(conn->_rx_m);
|
||||
conn->tap->_tcpconns_m.lock();
|
||||
conn->_rx_m.lock();
|
||||
//Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||
//Mutex::Lock _l2(vs->_rx_m);
|
||||
vs->tap->_tcpconns_m.lock();
|
||||
vs->_rx_m.lock();
|
||||
|
||||
struct pbuf* q = p;
|
||||
if(p == NULL) {
|
||||
if(((struct tcp_pcb*)conn->pcb)->state == CLOSE_WAIT) {
|
||||
if(((struct tcp_pcb*)vs->pcb)->state == CLOSE_WAIT) {
|
||||
// FIXME: Implement?
|
||||
}
|
||||
DEBUG_INFO("p == NULL");
|
||||
@@ -626,24 +626,24 @@ namespace ZeroTier
|
||||
while(p != NULL) {
|
||||
if(p->len <= 0)
|
||||
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;
|
||||
if(avail < len) {
|
||||
DEBUG_ERROR("not enough room (%d bytes) on RX buffer", avail);
|
||||
}
|
||||
memcpy(conn->RXbuf->get_buf(), p->payload, len);
|
||||
conn->RXbuf->produce(len);
|
||||
memcpy(vs->RXbuf->get_buf(), p->payload, len);
|
||||
vs->RXbuf->produce(len);
|
||||
p = p->next;
|
||||
tot += len;
|
||||
}
|
||||
DEBUG_INFO("tot=%d", tot);
|
||||
|
||||
conn->tap->_tcpconns_m.unlock();
|
||||
conn->_rx_m.unlock();
|
||||
vs->tap->_tcpconns_m.unlock();
|
||||
vs->_rx_m.unlock();
|
||||
|
||||
if(tot) {
|
||||
conn->tap->_phy.setNotifyWritable(conn->sock, true);
|
||||
//conn->tap->phyOnUnixWritable(conn->sock, NULL, true); // to app
|
||||
vs->tap->_phy.setNotifyWritable(vs->sock, true);
|
||||
//vs->tap->phyOnUnixWritable(vs->sock, NULL, true); // to app
|
||||
}
|
||||
pbuf_free(q);
|
||||
return ERR_OK;
|
||||
@@ -651,27 +651,27 @@ namespace ZeroTier
|
||||
|
||||
err_t lwIP::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err)
|
||||
{
|
||||
Connection *conn = (Connection*)arg;
|
||||
DEBUG_INFO("conn=%p", conn);
|
||||
//Mutex::Lock _l(conn->tap->_tcpconns_m);
|
||||
// create and populate new Connection object
|
||||
Connection *new_conn = new Connection();
|
||||
new_conn->socket_type = SOCK_STREAM;
|
||||
new_conn->pcb = newPCB;
|
||||
new_conn->tap = conn->tap;
|
||||
new_conn->sock = conn->tap->_phy.wrapSocket(new_conn->sdk_fd, new_conn);
|
||||
//memcpy(new_conn->tap->_phy.getuptr(new_conn->sock), new_conn, sizeof(conn));
|
||||
DEBUG_INFO("new_conn=%p", new_conn);
|
||||
// add new Connection object to parent connection so that we can find it via lwip_Accept()
|
||||
conn->_AcceptedConnections.push(new_conn);
|
||||
VirtualSocket *vs = (VirtualSocket*)arg;
|
||||
DEBUG_INFO("vs=%p", vs);
|
||||
//Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||
// create and populate new VirtualSocket object
|
||||
VirtualSocket *new_vs = new VirtualSocket();
|
||||
new_vs->socket_type = SOCK_STREAM;
|
||||
new_vs->pcb = newPCB;
|
||||
new_vs->tap = vs->tap;
|
||||
new_vs->sock = vs->tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs);
|
||||
//memcpy(new_vs->tap->_phy.getuptr(new_vs->sock), new_vs, sizeof(vs));
|
||||
DEBUG_INFO("new_vs=%p", new_vs);
|
||||
// add new VirtualSocket object to parent VirtualSocket so that we can find it via lwip_Accept()
|
||||
vs->_AcceptedConnections.push(new_vs);
|
||||
// set callbacks
|
||||
tcp_arg(newPCB, new_conn);
|
||||
tcp_arg(newPCB, new_vs);
|
||||
tcp_recv(newPCB, nc_recved);
|
||||
tcp_err(newPCB, nc_err);
|
||||
tcp_sent(newPCB, nc_sent);
|
||||
tcp_poll(newPCB, nc_poll, 1);
|
||||
// let lwIP know that it can queue additional incoming connections
|
||||
tcp_accepted((struct tcp_pcb*)conn->pcb);
|
||||
// let lwIP know that it can queue additional incoming VirtualSockets
|
||||
tcp_accepted((struct tcp_pcb*)vs->pcb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -684,13 +684,13 @@ namespace ZeroTier
|
||||
err_t lwIP::nc_sent(void* arg, struct tcp_pcb *PCB, u16_t len)
|
||||
{
|
||||
DEBUG_EXTRA("pcb=%p", (void*)&PCB);
|
||||
Connection *conn = (Connection *)arg;
|
||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
||||
if(conn && len) {
|
||||
int softmax = conn->socket_type == SOCK_STREAM ? ZT_TCP_TX_BUF_SZ : ZT_UDP_TX_BUF_SZ;
|
||||
if(conn->TXbuf->count() < softmax) {
|
||||
conn->tap->_phy.setNotifyReadable(conn->sock, true);
|
||||
conn->tap->_phy.whack();
|
||||
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||
Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||
if(vs && len) {
|
||||
int softmax = vs->socket_type == SOCK_STREAM ? ZT_TCP_TX_BUF_SZ : ZT_UDP_TX_BUF_SZ;
|
||||
if(vs->TXbuf->count() < softmax) {
|
||||
vs->tap->_phy.setNotifyReadable(vs->sock, true);
|
||||
vs->tap->_phy.whack();
|
||||
}
|
||||
}
|
||||
return ERR_OK;
|
||||
@@ -699,8 +699,8 @@ namespace ZeroTier
|
||||
err_t lwIP::nc_connected(void *arg, struct tcp_pcb *PCB, err_t err)
|
||||
{
|
||||
DEBUG_ATTN("pcb=%p", (void*)&PCB);
|
||||
Connection *conn = (Connection *)arg;
|
||||
if(conn)
|
||||
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||
if(vs)
|
||||
return ERR_OK;
|
||||
return -1;
|
||||
// FIXME: check stack for expected return values
|
||||
@@ -714,16 +714,16 @@ namespace ZeroTier
|
||||
void lwIP::nc_err(void *arg, err_t err)
|
||||
{
|
||||
DEBUG_ERROR("err=%d", err);
|
||||
Connection *conn = (Connection *)arg;
|
||||
if(!conn){
|
||||
DEBUG_ERROR("conn==NULL");
|
||||
VirtualSocket *vs = (VirtualSocket *)arg;
|
||||
if(!vs){
|
||||
DEBUG_ERROR("vs==NULL");
|
||||
errno = -1; // FIXME: Find more appropriate value
|
||||
}
|
||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
||||
int fd = conn->tap->_phy.getDescriptor(conn->sock);
|
||||
DEBUG_ERROR("conn=%p, pcb=%p, fd=%d, err=%d", conn, conn->pcb, fd, err);
|
||||
DEBUG_ERROR("closing connection");
|
||||
conn->tap->Close(conn);
|
||||
Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||
int fd = vs->tap->_phy.getDescriptor(vs->sock);
|
||||
DEBUG_ERROR("vs=%p, pcb=%p, fd=%d, err=%d", vs, vs->pcb, fd, err);
|
||||
DEBUG_ERROR("closing VirtualSocket");
|
||||
vs->tap->Close(vs);
|
||||
switch(err)
|
||||
{
|
||||
case ERR_MEM:
|
||||
@@ -759,7 +759,7 @@ namespace ZeroTier
|
||||
errno = EADDRINUSE;
|
||||
break;
|
||||
case ERR_ISCONN:
|
||||
DEBUG_ERROR("ERR_ISCONN->EISCONN");
|
||||
DEBUG_ERROR("ERR_ISvs->EISCONN");
|
||||
errno = EISCONN;
|
||||
break;
|
||||
case ERR_ABRT:
|
||||
|
||||
28
src/lwIP.hpp
28
src/lwIP.hpp
@@ -45,7 +45,7 @@
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include "libzt.h"
|
||||
#include "SocketTap.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
|
||||
struct tcp_pcb;
|
||||
struct netif;
|
||||
@@ -162,36 +162,36 @@ extern "C" err_t ip_input(LWIP_IP_INPUT_SIG);
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class SocketTap;
|
||||
struct Connection;
|
||||
class VirtualTap;
|
||||
struct VirtualSocket;
|
||||
|
||||
class lwIP
|
||||
{
|
||||
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
|
||||
*/
|
||||
void lwip_loop(SocketTap *tap);
|
||||
void lwip_loop(VirtualTap *tap);
|
||||
|
||||
/*
|
||||
* 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_Connect(Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int lwip_Bind(SocketTap *tap, Connection *conn, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int lwip_Listen(Connection *conn, int backlog);
|
||||
Connection* lwip_Accept(Connection *conn);
|
||||
int lwip_Read(Connection *conn, bool lwip_invoked);
|
||||
int lwip_Write(Connection *conn, void *data, ssize_t len);
|
||||
int lwip_Close(Connection *conn);
|
||||
int lwip_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int lwip_Bind(VirtualTap *tap, VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int lwip_Listen(VirtualSocket *vs, int backlog);
|
||||
VirtualSocket* lwip_Accept(VirtualSocket *vs);
|
||||
int lwip_Read(VirtualSocket *vs, bool lwip_invoked);
|
||||
int lwip_Write(VirtualSocket *vs, void *data, ssize_t len);
|
||||
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_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 "Utilities.hpp"
|
||||
#include "SocketTap.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
#include "picoTCP.hpp"
|
||||
#include "RingBuffer.hpp"
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace ZeroTier {
|
||||
|
||||
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];
|
||||
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_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_ip4 address;
|
||||
@@ -152,7 +152,7 @@ namespace ZeroTier {
|
||||
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;
|
||||
address.addr = *((uint32_t *)addr.rawIpData());
|
||||
@@ -165,7 +165,7 @@ namespace ZeroTier {
|
||||
return err;
|
||||
}
|
||||
|
||||
void picoTCP::pico_loop(SocketTap *tap)
|
||||
void picoTCP::pico_loop(VirtualTap *tap)
|
||||
{
|
||||
while(tap->_run)
|
||||
{
|
||||
@@ -176,13 +176,13 @@ namespace ZeroTier {
|
||||
}
|
||||
|
||||
// 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;
|
||||
Mutex::Lock _l(conn->_rx_m);
|
||||
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||
Mutex::Lock _l(vs->_rx_m);
|
||||
|
||||
if(!conn || !tap) {
|
||||
DEBUG_ERROR("invalid tap or conn");
|
||||
if(!vs || !tap) {
|
||||
DEBUG_ERROR("invalid tap or vs");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
@@ -196,37 +196,32 @@ namespace ZeroTier {
|
||||
|
||||
do {
|
||||
n = 0;
|
||||
//DEBUG_INFO("RXbuf->count() = %d", conn->RXbuf->count());
|
||||
int avail = ZT_TCP_RX_BUF_SZ - conn->RXbuf->count();
|
||||
//DEBUG_INFO("RXbuf->count() = %d", vs->RXbuf->count());
|
||||
int avail = ZT_TCP_RX_BUF_SZ - vs->RXbuf->count();
|
||||
if(avail) {
|
||||
|
||||
r = pico_socket_recvfrom(s, conn->RXbuf->get_buf(), ZT_STACK_SOCKET_RD_MAX,
|
||||
r = pico_socket_recvfrom(s, vs->RXbuf->get_buf(), ZT_STACK_SOCKET_RD_MAX,
|
||||
(void *)&peer.ip4.addr, &port);
|
||||
|
||||
conn->tot += r;
|
||||
|
||||
if (r > 0)
|
||||
{
|
||||
conn->RXbuf->produce(r);
|
||||
//DEBUG_INFO("RXbuf->count() = %d", conn->RXbuf->count());
|
||||
n = tap->_phy.streamSend(conn->sock, conn->RXbuf->get_buf(), r);
|
||||
vs->RXbuf->produce(r);
|
||||
//DEBUG_INFO("RXbuf->count() = %d", vs->RXbuf->count());
|
||||
n = tap->_phy.streamSend(vs->sock, vs->RXbuf->get_buf(), r);
|
||||
|
||||
if(n>0)
|
||||
conn->RXbuf->consume(n);
|
||||
//DEBUG_INFO("pico_recv = %d, streamSend = %d, rxsz = %d, tot = %d", r, n, conn->RXbuf->count(), conn->tot);
|
||||
vs->RXbuf->consume(n);
|
||||
//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(conn->RXbuf->count() == 0) {
|
||||
tap->_phy.setNotifyWritable(conn->sock, false);
|
||||
if(vs->RXbuf->count() == 0) {
|
||||
tap->_phy.setNotifyWritable(vs->sock, false);
|
||||
}
|
||||
else {
|
||||
tap->_phy.setNotifyWritable(conn->sock, true);
|
||||
tap->_phy.setNotifyWritable(vs->sock, true);
|
||||
}
|
||||
}
|
||||
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);
|
||||
handle_general_failure();
|
||||
}
|
||||
@@ -235,13 +230,13 @@ namespace ZeroTier {
|
||||
}
|
||||
|
||||
// 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();
|
||||
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
|
||||
Mutex::Lock _l(conn->_rx_m);
|
||||
if(conn) {
|
||||
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||
Mutex::Lock _l(vs->_rx_m);
|
||||
if(vs) {
|
||||
|
||||
uint16_t port = 0;
|
||||
union {
|
||||
@@ -259,15 +254,15 @@ namespace ZeroTier {
|
||||
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);
|
||||
|
||||
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");
|
||||
memmove(conn->rxbuf, conn->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:
|
||||
memmove(vs->rxbuf, vs->rxbuf + ZT_SDK_MTU, ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU);
|
||||
addr_pos = vs->rxbuf + (ZT_UDP_RX_BUF_SZ - ZT_SDK_MTU); // TODO:
|
||||
sz_pos = addr_pos + sizeof(struct sockaddr_storage);
|
||||
conn->rxsz -= ZT_SDK_MTU;
|
||||
vs->rxsz -= ZT_SDK_MTU;
|
||||
}
|
||||
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);
|
||||
}
|
||||
payload_pos = addr_pos + sizeof(struct sockaddr_storage) + sizeof(r);
|
||||
@@ -276,7 +271,7 @@ namespace ZeroTier {
|
||||
|
||||
// Adjust buffer size
|
||||
if(r) {
|
||||
conn->rxsz += ZT_SDK_MTU;
|
||||
vs->rxsz += ZT_SDK_MTU;
|
||||
memcpy(sz_pos, &r, sizeof(r));
|
||||
}
|
||||
if (r < 0) {
|
||||
@@ -286,38 +281,38 @@ namespace ZeroTier {
|
||||
tap->_rx_buf_m.unlock();
|
||||
|
||||
if(r)
|
||||
tap->phyOnUnixWritable(conn->sock, NULL, true);
|
||||
tap->phyOnUnixWritable(vs->sock, NULL, true);
|
||||
//DEBUG_EXTRA(" Copied onto rxbuf (%d) from stack socket", r);
|
||||
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;
|
||||
Mutex::Lock _l(conn->_tx_m);
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid connection");
|
||||
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||
Mutex::Lock _l(vs->_tx_m);
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid VirtualSocket");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
int txsz = conn->TXbuf->count();
|
||||
int txsz = vs->TXbuf->count();
|
||||
if(txsz <= 0)
|
||||
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);
|
||||
if((r = pico_socket_write(conn->picosock, conn->TXbuf->get_buf(), max_write_len)) < 0) {
|
||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r);
|
||||
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", vs->picosock, r);
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
if(conn->socket_type == SOCK_STREAM) {
|
||||
//DEBUG_TRANS("[ TCP TX -> STACK] :: conn = %p, len = %d", conn, r);
|
||||
if(vs->socket_type == SOCK_STREAM) {
|
||||
//DEBUG_TRANS("[ TCP TX -> STACK] :: vs = %p, len = %d", vs, r);
|
||||
}
|
||||
if(conn->socket_type == SOCK_DGRAM) {
|
||||
//DEBUG_TRANS("[ UDP TX -> STACK] :: conn = %p, len = %d", conn, r);
|
||||
if(vs->socket_type == SOCK_DGRAM) {
|
||||
//DEBUG_TRANS("[ UDP TX -> STACK] :: vs = %p, len = %d", vs, r);
|
||||
}
|
||||
if(r == 0) {
|
||||
// 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();
|
||||
}
|
||||
if(r>0)
|
||||
conn->TXbuf->consume(r);
|
||||
vs->TXbuf->consume(r);
|
||||
}
|
||||
|
||||
void picoTCP::pico_cb_socket_activity(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
if(!(SocketTap*)((ConnectionPair*)(s->priv)))
|
||||
if(!(VirtualTap*)((VirtualBindingPair*)(s->priv)))
|
||||
return;
|
||||
SocketTap *tap = (SocketTap*)((ConnectionPair*)(s->priv))->tap;
|
||||
Connection *conn = (Connection*)((ConnectionPair*)(s->priv))->conn;
|
||||
if(!tap || !conn) {
|
||||
DEBUG_ERROR("invalid tap or conn");
|
||||
VirtualTap *tap = (VirtualTap*)((VirtualBindingPair*)(s->priv))->tap;
|
||||
VirtualSocket *vs = (VirtualSocket*)((VirtualBindingPair*)(s->priv))->vs;
|
||||
if(!tap || !vs) {
|
||||
DEBUG_ERROR("invalid tap or vs");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
int err = 0;
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid connection");
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid VirtualSocket");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
// PICO_SOCK_EV_CONN - triggered when connection is established (TCP only). This event is
|
||||
// received either after a successful call to pico socket connect to indicate that the connection
|
||||
// PICO_SOCK_EV_vs - triggered when VirtualSocket is established (TCP only). This event is
|
||||
// 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
|
||||
// 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(conn->state == ZT_SOCK_STATE_LISTENING)
|
||||
if(vs->state == ZT_SOCK_STATE_LISTENING)
|
||||
{
|
||||
Mutex::Lock _l(tap->_tcpconns_m);
|
||||
uint32_t peer;
|
||||
@@ -362,78 +357,78 @@ namespace ZeroTier {
|
||||
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
|
||||
// this new connection, add it to the connection list and return its
|
||||
// Connection->sock to the application
|
||||
// this new VirtualSocket, add it to the VirtualSocket list and return its
|
||||
// VirtualSocket->sock to the application
|
||||
|
||||
Connection *newConn = new Connection();
|
||||
newConn->socket_type = SOCK_STREAM;
|
||||
newConn->picosock = client_psock;
|
||||
newConn->tap = tap;
|
||||
newConn->picosock->priv = new ConnectionPair(tap,newConn);
|
||||
tap->_Connections.push_back(newConn);
|
||||
conn->_AcceptedConnections.push(newConn);
|
||||
VirtualSocket *new_vs = new VirtualSocket();
|
||||
new_vs->socket_type = SOCK_STREAM;
|
||||
new_vs->picosock = client_psock;
|
||||
new_vs->tap = tap;
|
||||
new_vs->picosock->priv = new VirtualBindingPair(tap,new_vs);
|
||||
tap->_VirtualSockets.push_back(new_vs);
|
||||
vs->_AcceptedConnections.push(new_vs);
|
||||
|
||||
|
||||
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) {
|
||||
int linger_time_ms = ZT_SOCK_BEHAVIOR_LINGER_TIME;
|
||||
int t_err = 0;
|
||||
if((t_err = pico_socket_setoption(newConn->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);
|
||||
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, vs->app_fd, vs->sdk_fd);
|
||||
}
|
||||
/*
|
||||
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_TEST("getting linger = %d", linger_time_ms);
|
||||
*/
|
||||
// For I/O loop participation and referencing the PhySocket's parent Connection in callbacks
|
||||
newConn->sock = tap->_phy.wrapSocket(newConn->sdk_fd, newConn);
|
||||
//DEBUG_ERROR("sock->fd = %d", tap->_phy.getDescriptor(newConn->sock));
|
||||
// For I/O loop participation and referencing the PhySocket's parent VirtualSocket in callbacks
|
||||
new_vs->sock = tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs);
|
||||
//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
|
||||
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
|
||||
// possible from this point on the socket.
|
||||
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);
|
||||
conn->closure_ts = std::time(nullptr);
|
||||
//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);
|
||||
vs->closure_ts = std::time(nullptr);
|
||||
}
|
||||
|
||||
// PICO_SOCK_EV_ERR - triggered when an error occurs.
|
||||
if (ev & PICO_SOCK_EV_ERR) {
|
||||
if(pico_err == 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
|
||||
// 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
|
||||
// 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.
|
||||
if (ev & PICO_SOCK_EV_CLOSE) {
|
||||
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);
|
||||
conn->closure_ts = std::time(nullptr);
|
||||
//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);
|
||||
vs->closure_ts = std::time(nullptr);
|
||||
return;
|
||||
}
|
||||
// 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.
|
||||
if (ev & PICO_SOCK_EV_RD) {
|
||||
if(conn->socket_type==SOCK_STREAM)
|
||||
if(vs->socket_type==SOCK_STREAM)
|
||||
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_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)
|
||||
{
|
||||
//DEBUG_INFO("len = %d", len);
|
||||
SocketTap *tap = (SocketTap*)(dev->tap);
|
||||
VirtualTap *tap = (VirtualTap*)(dev->tap);
|
||||
if(!tap) {
|
||||
DEBUG_ERROR("invalid dev->tap");
|
||||
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
|
||||
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)
|
||||
{
|
||||
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
|
||||
int pico_eth_poll(struct pico_device *dev, int loop_score)
|
||||
{
|
||||
SocketTap *tap = (SocketTap*)(dev->tap);
|
||||
VirtualTap *tap = (VirtualTap*)(dev->tap);
|
||||
if(!tap) {
|
||||
DEBUG_ERROR("invalid dev->tap");
|
||||
handle_general_failure();
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
// 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);
|
||||
unsigned char frame[ZT_SDK_MTU];
|
||||
int len;
|
||||
@@ -588,15 +583,15 @@ namespace ZeroTier {
|
||||
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) {
|
||||
DEBUG_ERROR("invalid conn or conn->picosock");
|
||||
if(!vs || !vs->picosock) {
|
||||
DEBUG_ERROR("invalid vs or vs->picosock");
|
||||
handle_general_failure();
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
int err = 0;
|
||||
if(conn->socket_family == AF_INET) {
|
||||
if(vs->socket_family == AF_INET) {
|
||||
struct pico_ip4 zaddr;
|
||||
memset(&zaddr, 0, sizeof (struct pico_ip4));
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in*)addr;
|
||||
@@ -605,20 +600,20 @@ namespace ZeroTier {
|
||||
uint32_t ipval = 0;
|
||||
pico_string_to_ipv4(ipv4_str, &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 sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
||||
char ipv6_str[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN);
|
||||
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) {
|
||||
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)
|
||||
DEBUG_ERROR("PICO_ERR_EPROTONOSUPPORT");
|
||||
@@ -629,16 +624,16 @@ namespace ZeroTier {
|
||||
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();
|
||||
if(!conn || !conn->picosock) {
|
||||
DEBUG_ERROR("invalid conn or conn->picosock");
|
||||
if(!vs || !vs->picosock) {
|
||||
DEBUG_ERROR("invalid vs or vs->picosock");
|
||||
handle_general_failure();
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
int err = 0;
|
||||
if(conn->socket_family == AF_INET) {
|
||||
if(vs->socket_family == AF_INET) {
|
||||
struct pico_ip4 zaddr;
|
||||
uint32_t tempaddr;
|
||||
memset(&zaddr, 0, sizeof (struct pico_ip4));
|
||||
@@ -648,9 +643,9 @@ namespace ZeroTier {
|
||||
pico_string_to_ipv4(ipv4_str, &tempaddr);
|
||||
zaddr.addr = tempaddr;
|
||||
//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 sockaddr_in6 *in6 = (struct sockaddr_in6*)addr;
|
||||
char ipv6_str[INET6_ADDRSTRLEN];
|
||||
@@ -658,12 +653,12 @@ namespace ZeroTier {
|
||||
// TODO: This isn't proper
|
||||
pico_string_to_ipv6("::", pip6.addr);
|
||||
//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(pico_err < 0)
|
||||
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) {
|
||||
DEBUG_ERROR("PICO_ERR_EINVAL - invalid argument");
|
||||
errno = EINVAL;
|
||||
@@ -683,16 +678,16 @@ namespace ZeroTier {
|
||||
return err;
|
||||
}
|
||||
|
||||
int picoTCP::pico_Listen(Connection *conn, int backlog)
|
||||
int picoTCP::pico_Listen(VirtualSocket *vs, int backlog)
|
||||
{
|
||||
//DEBUG_INFO();
|
||||
if(!conn || !conn->picosock) {
|
||||
DEBUG_ERROR("invalid conn or conn->picosock");
|
||||
if(!vs || !vs->picosock) {
|
||||
DEBUG_ERROR("invalid vs or vs->picosock");
|
||||
handle_general_failure();
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
}
|
||||
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) {
|
||||
DEBUG_ERROR("PICO_ERR_EINVAL");
|
||||
@@ -705,33 +700,33 @@ namespace ZeroTier {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
conn->state = ZT_SOCK_STATE_LISTENING;
|
||||
vs->state = ZT_SOCK_STATE_LISTENING;
|
||||
return ZT_ERR_OK;
|
||||
}
|
||||
|
||||
Connection* picoTCP::pico_Accept(Connection *conn)
|
||||
VirtualSocket* picoTCP::pico_Accept(VirtualSocket *vs)
|
||||
{
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid conn");
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid vs");
|
||||
handle_general_failure();
|
||||
return NULL;
|
||||
}
|
||||
// Retreive first of queued Connections from parent connection
|
||||
Connection *new_conn = NULL;
|
||||
if(conn->_AcceptedConnections.size()) {
|
||||
new_conn = conn->_AcceptedConnections.front();
|
||||
conn->_AcceptedConnections.pop();
|
||||
// Retreive first of queued VirtualSockets from parent VirtualSocket
|
||||
VirtualSocket *new_vs = NULL;
|
||||
if(vs->_AcceptedConnections.size()) {
|
||||
new_vs = vs->_AcceptedConnections.front();
|
||||
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();
|
||||
//exit(0);
|
||||
/*
|
||||
if(!conn || !tap || !conn) {
|
||||
DEBUG_ERROR("invalid tap, sock, or conn");
|
||||
if(!vs || !tap || !vs) {
|
||||
DEBUG_ERROR("invalid tap, sock, or vs");
|
||||
handle_general_failure();
|
||||
return;
|
||||
}
|
||||
@@ -743,14 +738,14 @@ namespace ZeroTier {
|
||||
}
|
||||
int tot = 0, n = -1, write_attempts = 0;
|
||||
|
||||
if(conn && conn->rxsz) {
|
||||
//DEBUG_INFO("conn = %p", conn);
|
||||
if(vs && vs->rxsz) {
|
||||
//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
|
||||
while(tot < ZT_SDK_MTU) {
|
||||
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;
|
||||
//DEBUG_FLOW("[ ZTSOCK <- RXBUF] wrote = %d, errno=%d", n, errno);
|
||||
// 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);
|
||||
memcpy(&payload_sz, conn->rxbuf + addr_sz_offset, sizeof(int));
|
||||
memcpy(&payload_sz, vs->rxbuf + addr_sz_offset, sizeof(int));
|
||||
struct sockaddr_storage addr;
|
||||
memcpy(&addr, conn->rxbuf, addr_sz_offset);
|
||||
memcpy(&addr, vs->rxbuf, addr_sz_offset);
|
||||
// adjust buffer
|
||||
if(conn->rxsz-n > 0) { // If more remains on buffer
|
||||
memcpy(conn->rxbuf, conn->rxbuf+ZT_SDK_MTU, conn->rxsz - ZT_SDK_MTU);
|
||||
if(vs->rxsz-n > 0) { // If more remains on buffer
|
||||
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) {
|
||||
//DEBUG_INFO("writing to conn->sock = %p, conn->sdk_fd=%d, conn->app_fd=%d", conn->sock, conn->sdk_fd, conn->app_fd);
|
||||
n = tap->_phy.streamSend(conn->sock, conn->rxbuf, conn->rxsz);
|
||||
if(vs->socket_type==SOCK_STREAM) {
|
||||
//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(vs->sock, vs->rxbuf, vs->rxsz);
|
||||
// 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);
|
||||
if(conn->rxsz-n > 0) // If more remains on buffer
|
||||
memcpy(conn->rxbuf, conn->rxbuf+n, conn->rxsz - n);
|
||||
conn->rxsz -= n;
|
||||
// n = write(vs->sdk_fd, vs->rxbuf, vs->rxsz);
|
||||
if(vs->rxsz-n > 0) // If more remains on buffer
|
||||
memcpy(vs->rxbuf, vs->rxbuf+n, vs->rxsz - n);
|
||||
vs->rxsz -= n;
|
||||
}
|
||||
// Notify ZT I/O loop that it has new buffer contents
|
||||
if(n) {
|
||||
if(conn->socket_type==SOCK_STREAM) {
|
||||
if(vs->socket_type==SOCK_STREAM) {
|
||||
//#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
|
||||
}
|
||||
if(conn->rxsz == 0) {
|
||||
if(vs->rxsz == 0) {
|
||||
tap->_phy.setNotifyWritable(sock, false);
|
||||
}
|
||||
else {
|
||||
@@ -803,91 +798,91 @@ namespace ZeroTier {
|
||||
tap->_tcpconns_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;
|
||||
}
|
||||
|
||||
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;
|
||||
// TODO: Add RingBuffer overflow checks
|
||||
DEBUG_INFO("conn=%p, len=%d", conn, len);
|
||||
Mutex::Lock _l(conn->_tx_m);
|
||||
DEBUG_INFO("vs=%p, len=%d", vs, len);
|
||||
Mutex::Lock _l(vs->_tx_m);
|
||||
if(len <= 0) {
|
||||
DEBUG_ERROR("invalid write length (len=%d)", len);
|
||||
handle_general_failure();
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
if(!conn) {
|
||||
DEBUG_ERROR("invalid connection (len=%d)", len);
|
||||
if(!vs) {
|
||||
DEBUG_ERROR("invalid VirtualSocket (len=%d)", len);
|
||||
handle_general_failure();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(conn->socket_type == SOCK_DGRAM)
|
||||
if(vs->socket_type == SOCK_DGRAM)
|
||||
{
|
||||
int r;
|
||||
if((r = pico_socket_write(conn->picosock, data, len)) < 0) {
|
||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r);
|
||||
if((r = pico_socket_write(vs->picosock, data, len)) < 0) {
|
||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", vs->picosock, r);
|
||||
err = -1;
|
||||
}
|
||||
else {
|
||||
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) {
|
||||
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");
|
||||
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) {
|
||||
// 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);
|
||||
exit(0);
|
||||
}
|
||||
//DEBUG_INFO("TXbuf->count() = %d", conn->TXbuf->count());
|
||||
int txsz = conn->TXbuf->count();
|
||||
//DEBUG_INFO("TXbuf->count() = %d", vs->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 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) {
|
||||
DEBUG_ERROR("unable to write to picosock=%p, r=%d", conn->picosock, r);
|
||||
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", vs->picosock, r);
|
||||
err = -1;
|
||||
}
|
||||
else {
|
||||
err = r; // successful write
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if(!conn || !conn->picosock)
|
||||
DEBUG_INFO("vs=%p, picosock=%p, fd=%d", vs, vs->picosock, vs->app_fd);
|
||||
if(!vs || !vs->picosock)
|
||||
return ZT_ERR_GENERAL_FAILURE;
|
||||
int err = 0;
|
||||
Mutex::Lock _l(conn->tap->_tcpconns_m);
|
||||
if(conn->closure_ts != -1) // it was closed at some point in the past, it'll work itself out
|
||||
Mutex::Lock _l(vs->tap->_tcpconns_m);
|
||||
if(vs->closure_ts != -1) // it was closed at some point in the past, it'll work itself out
|
||||
return ZT_ERR_OK;
|
||||
if((err = pico_socket_close(conn->picosock)) < 0) {
|
||||
if((err = pico_socket_close(vs->picosock)) < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "pico_device.h"
|
||||
#include "pico_ipv6.h"
|
||||
|
||||
#include "SocketTap.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
|
||||
/****************************************************************************/
|
||||
/* 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);
|
||||
|
||||
class SocketTap;
|
||||
struct Connection;
|
||||
class VirtualTap;
|
||||
struct VirtualSocket;
|
||||
|
||||
class picoTCP
|
||||
{
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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)
|
||||
*/
|
||||
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)
|
||||
*/
|
||||
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)
|
||||
*/
|
||||
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)
|
||||
@@ -134,47 +134,47 @@ namespace ZeroTier
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
@@ -188,7 +188,7 @@ int main(int argc , char *argv[])
|
||||
fprintf(stderr, "Send failed\n");
|
||||
}
|
||||
|
||||
// dismantle all zt virtual taps (SocketTaps)
|
||||
// dismantle all zt virtual taps
|
||||
zts_stop();
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
// 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");
|
||||
exit(0);
|
||||
}
|
||||
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");
|
||||
exit(0);
|
||||
}
|
||||
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);
|
||||
exit(0);
|
||||
}
|
||||
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);
|
||||
exit(0);
|
||||
}
|
||||
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);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
2
zto
2
zto
Submodule zto updated: ee1dc16e8f...59b7cbb591
Reference in New Issue
Block a user