mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-29 15:43:52 +00:00
Unix domain sockets in Phy<>
This commit is contained in:
parent
b11ffc9635
commit
4838cbc350
187
osdep/Phy.hpp
187
osdep/Phy.hpp
@ -93,6 +93,10 @@ typedef void PhySocket;
|
||||
* phyOnTcpClose(PhySocket *sock,void **uptr)
|
||||
* phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len)
|
||||
* phyOnTcpWritable(PhySocket *sock,void **uptr)
|
||||
* phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN)
|
||||
* phyOnUnixClose(PhySocket *sock,void **uptr)
|
||||
* phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len)
|
||||
* phyOnUnixWritable(PhySocket *sock,void **uptr)
|
||||
*
|
||||
* These templates typically refer to function objects. Templates are used to
|
||||
* avoid the call overhead of indirection, which is surprisingly high for high
|
||||
@ -105,6 +109,9 @@ typedef void PhySocket;
|
||||
* uptr: sockL and uptrL for the listen socket, and sockN and uptrN for
|
||||
* the new TCP connection socket that has just been created.
|
||||
*
|
||||
* Note that phyOnUnix*() are only required and will only be used on systems
|
||||
* that support Unix domain sockets.
|
||||
*
|
||||
* Handlers are always called. On outgoing TCP connection, CONNECT is always
|
||||
* called on either success or failure followed by DATA and/or WRITABLE as
|
||||
* indicated. On socket close, handlers are called unless close() is told
|
||||
@ -129,7 +136,9 @@ private:
|
||||
ZT_PHY_SOCKET_TCP_IN = 0x03,
|
||||
ZT_PHY_SOCKET_TCP_LISTEN = 0x04,
|
||||
ZT_PHY_SOCKET_RAW = 0x05,
|
||||
ZT_PHY_SOCKET_UDP = 0x06
|
||||
ZT_PHY_SOCKET_UDP = 0x06,
|
||||
ZT_PHY_SOCKET_UNIX_IN = 0x07,
|
||||
ZT_PHY_SOCKET_UNIX_LISTEN = 0x08
|
||||
};
|
||||
|
||||
struct PhySocketImpl
|
||||
@ -358,6 +367,64 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
/**
|
||||
* Listen for connections on a Unix domain socket
|
||||
*
|
||||
* @param path Path to Unix domain socket
|
||||
* @param uptr Arbitrary pointer to associate
|
||||
* @return PhySocket or NULL if cannot bind
|
||||
*/
|
||||
inline PhySocket *unixListen(const char *path,void *uptr = (void *)0)
|
||||
{
|
||||
struct sockaddr_un sun;
|
||||
|
||||
if (_socks.size() >= ZT_PHY_MAX_SOCKETS)
|
||||
return (PhySocket *)0;
|
||||
|
||||
memset(&sun,0,sizeof(sun));
|
||||
sun.sun_family = AF_UNIX;
|
||||
if (strlen(path) >= sizeof(sun.sun_path))
|
||||
return (PhySocket *)0;
|
||||
strcpy(sun.sun_path,path);
|
||||
|
||||
ZT_PHY_SOCKFD_TYPE s = ::socket(PF_UNIX,SOCK_STREAM,0);
|
||||
if (!ZT_PHY_SOCKFD_VALID(s))
|
||||
return (PhySocket *)0;
|
||||
|
||||
::fcntl(s,F_SETFL,O_NONBLOCK);
|
||||
|
||||
::unlink(path);
|
||||
if (::bind(s,(struct sockaddr *)&sun,sizeof(struct sockaddr_un)) != 0) {
|
||||
ZT_PHY_CLOSE_SOCKET(s);
|
||||
return (PhySocket *)0;
|
||||
}
|
||||
if (::listen(s,128) != 0) {
|
||||
ZT_PHY_CLOSE_SOCKET(s);
|
||||
return (PhySocket *)0;
|
||||
}
|
||||
|
||||
try {
|
||||
_socks.push_back(PhySocketImpl());
|
||||
} catch ( ... ) {
|
||||
ZT_PHY_CLOSE_SOCKET(s);
|
||||
return (PhySocket *)0;
|
||||
}
|
||||
PhySocketImpl &sws = _socks.back();
|
||||
|
||||
if ((long)s > _nfds)
|
||||
_nfds = (long)s;
|
||||
FD_SET(s,&_readfds);
|
||||
sws.type = ZT_PHY_SOCKET_UNIX_LISTEN;
|
||||
sws.sock = s;
|
||||
sws.uptr = uptr;
|
||||
memset(&(sws.saddr),0,sizeof(struct sockaddr_storage));
|
||||
memcpy(&(sws.saddr),&sun,sizeof(struct sockaddr_un));
|
||||
|
||||
return (PhySocket *)&sws;
|
||||
}
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
/**
|
||||
* Bind a local listen socket to listen for new TCP connections
|
||||
*
|
||||
@ -573,6 +640,45 @@ public:
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
/**
|
||||
* Attempt to send data to a Unix domain socket connection (non-blocking)
|
||||
*
|
||||
* If -1 is returned, the socket should no longer be used as it is now
|
||||
* destroyed. If callCloseHandler is true, the close handler will be
|
||||
* called before the function returns.
|
||||
*
|
||||
* @param sock An open Unix socket (other socket types will fail)
|
||||
* @param data Data to send
|
||||
* @param len Length of data
|
||||
* @param callCloseHandler If true, call close handler on socket closing failure condition (default: true)
|
||||
* @return Number of bytes actually sent or -1 on fatal error (socket closure)
|
||||
*/
|
||||
inline long unixSend(PhySocket *sock,const void *data,unsigned long len,bool callCloseHandler = true)
|
||||
{
|
||||
PhySocketImpl &sws = *(reinterpret_cast<PhySocketImpl *>(sock));
|
||||
long n = (long)::write(sws.sock,data,len);
|
||||
if (n < 0) {
|
||||
switch(errno) {
|
||||
#ifdef EAGAIN
|
||||
case EAGAIN:
|
||||
#endif
|
||||
#if defined(EWOULDBLOCK) && ( !defined(EAGAIN) || (EWOULDBLOCK != EAGAIN) )
|
||||
case EWOULDBLOCK:
|
||||
#endif
|
||||
#ifdef EINTR
|
||||
case EINTR:
|
||||
#endif
|
||||
return 0;
|
||||
default:
|
||||
this->close(sock,callCloseHandler);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
#endif // __UNIX_LIKE__
|
||||
|
||||
/**
|
||||
* Set whether we want to be notified via the TCP writability handler when a socket is writable
|
||||
*
|
||||
@ -727,6 +833,56 @@ public:
|
||||
}
|
||||
break;
|
||||
|
||||
case ZT_PHY_SOCKET_UNIX_IN: {
|
||||
#ifdef __UNIX_LIKE__
|
||||
ZT_PHY_SOCKFD_TYPE sock = s->sock; // if closed, s->sock becomes invalid as s is no longer dereferencable
|
||||
if (FD_ISSET(sock,&rfds)) {
|
||||
long n = (long)::read(sock,buf,sizeof(buf));
|
||||
if (n <= 0) {
|
||||
this->close((PhySocket *)&(*s),true);
|
||||
} else {
|
||||
try {
|
||||
_handler->phyOnUnixData((PhySocket *)&(*s),&(s->uptr),(void *)buf,(unsigned long)n);
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
}
|
||||
if ((FD_ISSET(sock,&wfds))&&(FD_ISSET(sock,&_writefds))) {
|
||||
try {
|
||||
_handler->phyOnUnixWritable((PhySocket *)&(*s),&(s->uptr));
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
#endif // __UNIX_LIKE__
|
||||
} break;
|
||||
|
||||
case ZT_PHY_SOCKET_UNIX_LISTEN:
|
||||
#ifdef __UNIX_LIKE__
|
||||
if (FD_ISSET(s->sock,&rfds)) {
|
||||
memset(&ss,0,sizeof(ss));
|
||||
socklen_t slen = sizeof(ss);
|
||||
ZT_PHY_SOCKFD_TYPE newSock = ::accept(s->sock,(struct sockaddr *)&ss,&slen);
|
||||
if (ZT_PHY_SOCKFD_VALID(newSock)) {
|
||||
if (_socks.size() >= ZT_PHY_MAX_SOCKETS) {
|
||||
ZT_PHY_CLOSE_SOCKET(newSock);
|
||||
} else {
|
||||
fcntl(newSock,F_SETFL,O_NONBLOCK);
|
||||
_socks.push_back(PhySocketImpl());
|
||||
PhySocketImpl &sws = _socks.back();
|
||||
FD_SET(newSock,&_readfds);
|
||||
if ((long)newSock > _nfds)
|
||||
_nfds = (long)newSock;
|
||||
sws.type = ZT_PHY_SOCKET_UNIX_IN;
|
||||
sws.sock = newSock;
|
||||
sws.uptr = (void *)0;
|
||||
memcpy(&(sws.saddr),&ss,sizeof(struct sockaddr_storage));
|
||||
try {
|
||||
_handler->phyOnUnixAccept((PhySocket *)&(*s),(PhySocket *)&(_socks.back()),&(s->uptr),&(sws.uptr));
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // __UNIX_LIKE__
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -758,24 +914,29 @@ public:
|
||||
|
||||
ZT_PHY_CLOSE_SOCKET(sws.sock);
|
||||
|
||||
switch(sws.type) {
|
||||
case ZT_PHY_SOCKET_TCP_OUT_PENDING:
|
||||
if (callHandlers) {
|
||||
if (callHandlers) {
|
||||
switch(sws.type) {
|
||||
case ZT_PHY_SOCKET_TCP_OUT_PENDING:
|
||||
try {
|
||||
_handler->phyOnTcpConnect(sock,&(sws.uptr),false);
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
break;
|
||||
case ZT_PHY_SOCKET_TCP_OUT_CONNECTED:
|
||||
case ZT_PHY_SOCKET_TCP_IN:
|
||||
if (callHandlers) {
|
||||
break;
|
||||
case ZT_PHY_SOCKET_TCP_OUT_CONNECTED:
|
||||
case ZT_PHY_SOCKET_TCP_IN:
|
||||
try {
|
||||
_handler->phyOnTcpClose(sock,&(sws.uptr));
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
case ZT_PHY_SOCKET_UNIX_IN:
|
||||
#ifdef __UNIX_LIKE__
|
||||
try {
|
||||
_handler->phyOnUnixClose(sock,&(sws.uptr));
|
||||
} catch ( ... ) {}
|
||||
#endif // __UNIX_LIKE__
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Causes entry to be deleted from list in poll(), ignored elsewhere
|
||||
|
@ -791,6 +791,13 @@ struct TestPhyHandlers
|
||||
testPhyInstance->close(sock,true);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
inline void phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN) {}
|
||||
inline void phyOnUnixClose(PhySocket *sock,void **uptr) {}
|
||||
inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
||||
inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {}
|
||||
#endif // __UNIX_LIKE__
|
||||
};
|
||||
static int testPhy()
|
||||
{
|
||||
|
@ -924,6 +924,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline void phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN) {}
|
||||
inline void phyOnUnixClose(PhySocket *sock,void **uptr) {}
|
||||
inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
|
||||
inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {}
|
||||
|
||||
inline int nodeVirtualNetworkConfigFunction(uint64_t nwid,enum ZT1_VirtualNetworkConfigOperation op,const ZT1_VirtualNetworkConfig *nwc)
|
||||
{
|
||||
Mutex::Lock _l(_taps_m);
|
||||
|
Loading…
x
Reference in New Issue
Block a user