diff --git a/node/Socket.hpp b/node/Socket.hpp index e8ebfeb73..4eef01b3d 100644 --- a/node/Socket.hpp +++ b/node/Socket.hpp @@ -102,7 +102,6 @@ protected: virtual bool notifyAvailableForRead(const SharedPtr<Socket> &self,SocketManager *sm) = 0; virtual bool notifyAvailableForWrite(const SharedPtr<Socket> &self,SocketManager *sm) = 0; -private: #ifdef __WINDOWS__ SOCKET _sock; #else diff --git a/node/SocketManager.cpp b/node/SocketManager.cpp index 36def1e17..825d107e1 100644 --- a/node/SocketManager.cpp +++ b/node/SocketManager.cpp @@ -434,10 +434,20 @@ void SocketManager::poll(unsigned long timeout) } } for(std::vector< SharedPtr<Socket> >::iterator s(ts.begin());s!=ts.end();++s) { - if (FD_ISSET((*s)->_sock,&rfds)) - (*s)->notifyAvailableForRead(*s,this); - if (FD_ISSET((*s)->_sock,&wfds)) - (*s)->notifyAvailableForWrite(*s,this); + if (FD_ISSET((*s)->_sock,&wfds)) { + if (!(*s)->notifyAvailableForWrite(*s,this)) { + Mutex::Lock _l2(_tcpSockets_m); + _tcpSockets.erase(((TcpSocket *)s->ptr())->_remote); + continue; + } + } + if (FD_ISSET((*s)->_sock,&rfds)) { + if (!(*s)->notifyAvailableForRead(*s,this)) { + Mutex::Lock _l2(_tcpSockets_m); + _tcpSockets.erase(((TcpSocket *)s->ptr())->_remote); + continue; + } + } } } diff --git a/node/UdpSocket.cpp b/node/UdpSocket.cpp new file mode 100644 index 000000000..03041cf31 --- /dev/null +++ b/node/UdpSocket.cpp @@ -0,0 +1,112 @@ +/* + * ZeroTier One - Global Peer to Peer Ethernet + * Copyright (C) 2011-2014 ZeroTier Networks LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <time.h> +#include <errno.h> +#include <sys/types.h> + +#include "Constants.hpp" +#include "UdpSocket.hpp" +#include "SocketManager.hpp" + +#ifdef __WINDOWS__ +#include <WinSock2.h> +#include <WS2tcpip.h> +#include <Windows.h> +#else +#include <unistd.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <signal.h> +#endif + +namespace ZeroTier { + +UdpSocket::~UdpSocket() +{ +#ifdef __WINDOWS__ + ::closesocket(_sock); +#else + ::close(_sock); +#endif +} + +bool UdpSocket::send(const InetAddress &to,const void *msg,unsigned int msglen) +{ + return sendWithHopLimit(to,msg,msglen,0); +} + +bool UdpSocket::sendWithHopLimit(const InetAddress &to,const void *msg,unsigned int msglen,int hopLimit) +{ + if (hopLimit <= 0) + hopLimit = 255; + if (to.isV6()) { +#ifdef __WINDOWS__ + DWORD hltmp = (DWORD)hopLimit; + setsockopt(_sock,IPPROTO_IPV6,IPV6_UNICAST_HOPS,(const char *)&hltmp,sizeof(hltmp)); + return ((int)sendto(_sock,(const char *)msg,msglen,0,to.saddr(),to.saddrLen()) == (int)msglen); +#else + setsockopt(_sock,IPPROTO_IPV6,IPV6_UNICAST_HOPS,&hopLimit,sizeof(hopLimit)); + return ((int)sendto(_sock,msg,msglen,0,to.saddr(),to.saddrLen()) == (int)msglen); +#endif + } else { +#ifdef __WINDOWS__ + DWORD hltmp = (DWORD)hopLimit; + setsockopt(_sock,IPPROTO_IP,IP_TTL,(const char *)&hltmp,sizeof(hltmp)); + return ((int)sendto(_sock,(const char *)msg,msglen,0,to.saddr(),to.saddrLen()) == (int)msglen); +#else + setsockopt(_sock,IPPROTO_IP,IP_TTL,&hopLimit,sizeof(hopLimit)); + return ((int)sendto(_sock,msg,msglen,0,to.saddr(),to.saddrLen()) == (int)msglen); +#endif + } +} + +bool UdpSocket::notifyAvailableForRead(const SharedPtr<Socket> &self,SocketManager *sm) +{ + Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> buf; + InetAddress from; + for(;;) { + socklen_t salen = from.saddrSpaceLen(); + int n = (int)recvfrom(_sock,buf.data(),ZT_SOCKET_MAX_MESSAGE_LEN,0,from.saddr(),&salen); + if (n > 0) { + buf.setSize((unsigned int)n); + sm->handleReceivedPacket(self,from,buf); + } else break; + } + return true; +} + +bool UdpSocket::notifyAvailableForWrite(const SharedPtr<Socket> &self,SocketManager *sm) +{ + return true; +} + +} // namespace ZeroTier diff --git a/node/UdpSocket.hpp b/node/UdpSocket.hpp index 5e0f961a8..9566b9ca5 100644 --- a/node/UdpSocket.hpp +++ b/node/UdpSocket.hpp @@ -28,7 +28,7 @@ #ifndef ZT_UDPSOCKET_HPP #define ZT_UDPSOCKET_HPP -//#include "Socket.hpp" +#include "Socket.hpp" namespace ZeroTier { @@ -44,7 +44,6 @@ class UdpSocket : public Socket public: virtual ~UdpSocket(); - virtual bool send(const InetAddress &to,const void *msg,unsigned int msglen); /**