From 7295fcfa86aafdca76ac0210ca59ad9a70a2d67a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 27 Oct 2015 12:50:23 -0700 Subject: Merge Phy<> from netcon. --- osdep/Http.cpp | 8 ++++ osdep/Phy.hpp | 123 ++++++++++++++++++++++--------------------------- selftest.cpp | 4 +- service/OneService.cpp | 4 +- 4 files changed, 65 insertions(+), 74 deletions(-) diff --git a/osdep/Http.cpp b/osdep/Http.cpp index 0eb7c4c6..6d812a14 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -100,6 +100,14 @@ struct HttpPhyHandler phy->setNotifyWritable(sock,false); } + inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {} +#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__ + http_parser parser; std::string currentHeaderField; std::string currentHeaderValue; diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index 6737034e..94130faf 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -78,11 +78,6 @@ #define ZT_PHY_MAX_INTERCEPTS ZT_PHY_MAX_SOCKETS #define ZT_PHY_SOCKADDR_STORAGE_TYPE struct sockaddr_storage -#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux) -#define ZT_PHY_HAVE_EVENTFD 1 -#include -#endif - #endif // Windows or not namespace ZeroTier { @@ -109,6 +104,7 @@ typedef void PhySocket; * phyOnTcpClose(PhySocket *sock,void **uptr) * phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) * phyOnTcpWritable(PhySocket *sock,void **uptr) + * phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) * * On Linux/OSX/Unix only (not required/used on Windows or elsewhere): * @@ -116,9 +112,6 @@ typedef void PhySocket; * phyOnUnixClose(PhySocket *sock,void **uptr) * phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) * phyOnUnixWritable(PhySocket *sock,void **uptr) - * phyOnSocketPairEndpointClose(PhySocket *sock,void **uptr) - * phyOnSocketPairEndpointData(PhySocket *sock,void **uptr,void *data,unsigned long len) - * phyOnSocketPairEndpointWritable(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 @@ -154,11 +147,10 @@ private: ZT_PHY_SOCKET_TCP_OUT_CONNECTED = 0x02, 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 = 0x05, + ZT_PHY_SOCKET_FD = 0x06, ZT_PHY_SOCKET_UNIX_IN = 0x07, - ZT_PHY_SOCKET_UNIX_LISTEN = 0x08, - ZT_PHY_SOCKET_PAIR_ENDPOINT = 0x09 + ZT_PHY_SOCKET_UNIX_LISTEN = 0x08 }; struct PhySocketImpl @@ -277,57 +269,47 @@ public: */ inline unsigned long maxCount() const throw() { return ZT_PHY_MAX_SOCKETS; } -#ifdef __UNIX_LIKE__ /** - * Create a two-way socket pair + * Wrap a raw file descriptor in a PhySocket structure * - * This uses socketpair() to create a local domain pair. The returned - * PhySocket holds the local side of the socket pair, while the - * supplied fd variable is set to the descriptor for the remote side. + * This can be used to select/poll on a raw file descriptor as part of this + * class's I/O loop. By default the fd is set for read notification but + * this can be controlled with setNotifyReadable(). When any detected + * condition is present, the phyOnFileDescriptorActivity() callback is + * called with one or both of its arguments 'true'. * - * The local side is set to O_NONBLOCK to work with our poll loop, but - * the remote descriptor is left untouched. It's up to the caller to - * set any required fcntl(), ioctl(), or setsockopt() settings there. - * It's also up to the caller to close the remote descriptor when - * done, if necessary. + * The Phy<>::close() method *must* be called when you're done with this + * file descriptor to remove it from the select/poll set, but unlike other + * types of sockets Phy<> does not actually close the underlying fd or + * otherwise manage its life cycle. There is also no close notification + * callback for this fd, since Phy<> doesn't actually perform reading or + * writing or detect error conditions. This is only useful for adding a + * file descriptor to Phy<> to select/poll on it. * - * @param remoteSocketDescriptor Result parameter set to remote end of socket pair's socket FD - * @param uptr Pointer to associate with local side of socket pair - * @return PhySocket for local side of socket pair + * @param fd Raw file descriptor + * @param uptr User pointer to supply to callbacks + * @return PhySocket wrapping fd or NULL on failure (out of memory or too many sockets) */ - inline PhySocket *createSocketPair(ZT_PHY_SOCKFD_TYPE &remoteSocketDescriptor,void *uptr = (void *)0) + inline PhySocket *wrapSocket(ZT_PHY_SOCKFD_TYPE fd,void *uptr = (void *)0) { if (_socks.size() >= ZT_PHY_MAX_SOCKETS) return (PhySocket *)0; - - int fd[2]; fd[0] = -1; fd[1] = -1; - if ((::socketpair(PF_LOCAL,SOCK_STREAM,0,fd) != 0)||(fd[0] <= 0)||(fd[1] <= 0)) - return (PhySocket *)0; - fcntl(fd[0],F_SETFL,O_NONBLOCK); - try { _socks.push_back(PhySocketImpl()); } catch ( ... ) { - ZT_PHY_CLOSE_SOCKET(fd[0]); - ZT_PHY_CLOSE_SOCKET(fd[1]); return (PhySocket *)0; } PhySocketImpl &sws = _socks.back(); - - if ((long)fd[0] > _nfds) - _nfds = (long)fd[0]; - FD_SET(fd[0],&_readfds); - sws.type = ZT_PHY_SOCKET_PAIR_ENDPOINT; - sws.sock = fd[0]; + if ((long)fd > _nfds) + _nfds = (long)fd; + FD_SET(fd,&_readfds); + sws.type = ZT_PHY_SOCKET_FD; + sws.sock = fd; sws.uptr = uptr; memset(&(sws.saddr),0,sizeof(struct sockaddr_storage)); // no sockaddr for this socket type, leave saddr null - - remoteSocketDescriptor = fd[1]; - return (PhySocket *)&sws; } -#endif // __UNIX_LIKE__ /** * Bind a UDP socket @@ -787,6 +769,26 @@ public: } } + /** + * Set whether we want to be notified that a socket is readable + * + * This is primarily for raw sockets added with wrapSocket(). It could be + * used with others, but doing so would essentially lock them and prevent + * data from being read from them until this is set to 'true' again. + * + * @param sock Socket to modify + * @param notifyReadable True if socket should be monitored for readability + */ + inline const void setNotifyReadable(PhySocket *sock,bool notifyReadable) + { + PhySocketImpl &sws = *(reinterpret_cast(sock)); + if (notifyReadable) { + FD_SET(sws.sock,&_readfds); + } else { + FD_CLR(sws.sock,&_readfds); + } + } + /** * Wait for activity and handle one or more events * @@ -936,7 +938,7 @@ public: } if ((FD_ISSET(sock,&wfds))&&(FD_ISSET(sock,&_writefds))) { try { - _handler->phyOnUnixWritable((PhySocket *)&(*s),&(s->uptr)); + //_handler->phyOnUnixWritable((PhySocket *)&(*s),&(s->uptr)); } catch ( ... ) {} } #endif // __UNIX_LIKE__ @@ -971,25 +973,15 @@ public: #endif // __UNIX_LIKE__ break; - case ZT_PHY_SOCKET_PAIR_ENDPOINT: { -#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->phyOnSocketPairEndpointData((PhySocket *)&(*s),&(s->uptr),(void *)buf,(unsigned long)n); - } catch ( ... ) {} - } - } - if ((FD_ISSET(sock,&wfds))&&(FD_ISSET(sock,&_writefds))) { + case ZT_PHY_SOCKET_FD: { + ZT_PHY_SOCKFD_TYPE sock = s->sock; + const bool readable = ((FD_ISSET(sock,&rfds))&&(FD_ISSET(sock,&_readfds))); + const bool writable = ((FD_ISSET(sock,&wfds))&&(FD_ISSET(sock,&_writefds))); + if ((readable)||(writable)) { try { - _handler->phyOnSocketPairEndpointWritable((PhySocket *)&(*s),&(s->uptr)); + _handler->phyOnFileDescriptorActivity((PhySocket *)&(*s),&(s->uptr),readable,writable); } catch ( ... ) {} } -#endif // __UNIX_LIKE__ } break; default: @@ -1021,7 +1013,8 @@ public: FD_CLR(sws.sock,&_exceptfds); #endif - ZT_PHY_CLOSE_SOCKET(sws.sock); + if (sws.type != ZT_PHY_SOCKET_FD) + ZT_PHY_CLOSE_SOCKET(sws.sock); #ifdef __UNIX_LIKE__ if (sws.type == ZT_PHY_SOCKET_UNIX_LISTEN) @@ -1048,12 +1041,6 @@ public: } catch ( ... ) {} #endif // __UNIX_LIKE__ break; - case ZT_PHY_SOCKET_PAIR_ENDPOINT: -#ifdef __UNIX_LIKE__ - try { - _handler->phyOnSocketPairEndpointClose(sock,&(sws.uptr)); - } catch ( ... ) {} -#endif // __UNIX_LIKE__ default: break; } diff --git a/selftest.cpp b/selftest.cpp index 9c357dc4..fa5eec0f 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -837,9 +837,7 @@ struct TestPhyHandlers 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 void phyOnSocketPairEndpointClose(PhySocket *sock,void **uptr) {} - inline void phyOnSocketPairEndpointData(PhySocket *sock,void **uptr,void *data,unsigned long len) {} - inline void phyOnSocketPairEndpointWritable(PhySocket *sock,void **uptr) {} + inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {} #endif // __UNIX_LIKE__ }; static int testPhy() diff --git a/service/OneService.cpp b/service/OneService.cpp index 7a473b67..1765b5c4 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -1085,9 +1085,7 @@ public: 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 void phyOnSocketPairEndpointClose(PhySocket *sock,void **uptr) {} - inline void phyOnSocketPairEndpointData(PhySocket *sock,void **uptr,void *data,unsigned long len) {} - inline void phyOnSocketPairEndpointWritable(PhySocket *sock,void **uptr) {} + inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {} inline int nodeVirtualNetworkConfigFunction(uint64_t nwid,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwc) { -- cgit v1.2.3