diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/network/CMakeLists.txt | 9 | ||||
-rw-r--r-- | common/network/Socket.cxx | 183 | ||||
-rw-r--r-- | common/network/Socket.h | 66 | ||||
-rw-r--r-- | common/network/TcpSocket.cxx | 209 | ||||
-rw-r--r-- | common/network/TcpSocket.h | 31 | ||||
-rw-r--r-- | common/network/UnixSocket.cxx | 171 | ||||
-rw-r--r-- | common/network/UnixSocket.h | 60 | ||||
-rw-r--r-- | common/rfb/Configuration.cxx | 2 |
8 files changed, 507 insertions, 224 deletions
diff --git a/common/network/CMakeLists.txt b/common/network/CMakeLists.txt index b624c8e6..d00ca452 100644 --- a/common/network/CMakeLists.txt +++ b/common/network/CMakeLists.txt @@ -1,8 +1,15 @@ include_directories(${CMAKE_SOURCE_DIR}/common) -add_library(network STATIC +set(NETWORK_SOURCES + Socket.cxx TcpSocket.cxx) +if(NOT WIN32) + set(NETWORK_SOURCES ${NETWORK_SOURCES} UnixSocket.cxx) +endif() + +add_library(network STATIC ${NETWORK_SOURCES}) + if(WIN32) target_link_libraries(network ws2_32) endif() diff --git a/common/network/Socket.cxx b/common/network/Socket.cxx new file mode 100644 index 00000000..9dd8bfe1 --- /dev/null +++ b/common/network/Socket.cxx @@ -0,0 +1,183 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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 2 of the License, or + * (at your option) any later version. + * + * This software 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef WIN32 +//#include <io.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#define errorNumber WSAGetLastError() +#else +#define errorNumber errno +#define closesocket close +#include <sys/socket.h> +#endif + +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <errno.h> + +#include <network/Socket.h> + +using namespace network; + +// -=- Socket initialisation +static bool socketsInitialised = false; +void network::initSockets() { + if (socketsInitialised) + return; +#ifdef WIN32 + WORD requiredVersion = MAKEWORD(2,0); + WSADATA initResult; + + if (WSAStartup(requiredVersion, &initResult) != 0) + throw SocketException("unable to initialise Winsock2", errorNumber); +#else + signal(SIGPIPE, SIG_IGN); +#endif + socketsInitialised = true; +} + +bool network::isSocketListening(int sock) +{ + int listening = 0; + socklen_t listening_size = sizeof(listening); + if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN, + (char *)&listening, &listening_size) < 0) + return false; + return listening != 0; +} + +Socket::Socket(int fd) + : instream(0), outstream(0), + isShutdown_(false), queryConnection(false) +{ + initSockets(); + setFd(fd); +} + +Socket::Socket() + : instream(0), outstream(0), + isShutdown_(false), queryConnection(false) +{ + initSockets(); +} + +Socket::~Socket() +{ + if (instream && outstream) + closesocket(getFd()); + delete instream; + delete outstream; +} + +// if shutdown() is overridden then the override MUST call on to here +void Socket::shutdown() +{ + isShutdown_ = true; + ::shutdown(getFd(), 2); +} + +bool Socket::isShutdown() const +{ + return isShutdown_; +} + +// Was there a "?" in the ConnectionFilter used to accept this Socket? +void Socket::setRequiresQuery() +{ + queryConnection = true; +} + +bool Socket::requiresQuery() const +{ + return queryConnection; +} + +void Socket::setFd(int fd) +{ +#ifndef WIN32 + // - By default, close the socket on exec() + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif + + instream = new rdr::FdInStream(fd); + outstream = new rdr::FdOutStream(fd); + isShutdown_ = false; +} + +SocketListener::SocketListener(int fd) + : fd(fd), filter(0) +{ + initSockets(); +} + +SocketListener::SocketListener() + : fd(-1), filter(0) +{ + initSockets(); +} + +SocketListener::~SocketListener() +{ + if (fd != -1) + closesocket(fd); +} + +void SocketListener::shutdown() +{ +#ifdef WIN32 + closesocket(fd); + fd = -1; +#else + ::shutdown(fd, 2); +#endif +} + +Socket* SocketListener::accept() { + int new_sock = -1; + + // Accept an incoming connection + if ((new_sock = ::accept(fd, 0, 0)) < 0) + throw SocketException("unable to accept new connection", errorNumber); + + // Create the socket object & check connection is allowed + Socket* s = createSocket(new_sock); + if (filter && !filter->verifyConnection(s)) { + delete s; + return NULL; + } + + return s; +} + +void SocketListener::listen(int sock) +{ + // - Set it to be a listening socket + if (::listen(sock, 5) < 0) { + int e = errorNumber; + closesocket(sock); + throw SocketException("unable to set socket to listening mode", e); + } + + fd = sock; +} diff --git a/common/network/Socket.h b/common/network/Socket.h index 7a30cacf..bfda8a57 100644 --- a/common/network/Socket.h +++ b/common/network/Socket.h @@ -30,52 +30,40 @@ namespace network { + void initSockets(); + + bool isSocketListening(int sock); + class Socket { public: - Socket(int fd) - : instream(new rdr::FdInStream(fd)), - outstream(new rdr::FdOutStream(fd)), - ownStreams(true), isShutdown_(false), - queryConnection(false) {} - virtual ~Socket() { - if (ownStreams) { - delete instream; - delete outstream; - } - } + Socket(int fd); + virtual ~Socket(); + rdr::FdInStream &inStream() {return *instream;} rdr::FdOutStream &outStream() {return *outstream;} int getFd() {return outstream->getFd();} - // if shutdown() is overridden then the override MUST call on to here - virtual void shutdown() {isShutdown_ = true;} - bool isShutdown() const {return isShutdown_;} - virtual bool cork(bool enable) = 0; + void shutdown(); + bool isShutdown() const; - // information about this end of the socket - virtual int getMyPort() = 0; + virtual bool cork(bool enable) = 0; // information about the remote end of the socket virtual char* getPeerAddress() = 0; // a string e.g. "192.168.0.1" - virtual int getPeerPort() = 0; virtual char* getPeerEndpoint() = 0; // <address>::<port> - // Is the remote end on the same machine? - virtual bool sameMachine() = 0; - // Was there a "?" in the ConnectionFilter used to accept this Socket? - void setRequiresQuery() {queryConnection = true;} - bool requiresQuery() const {return queryConnection;} + void setRequiresQuery(); + bool requiresQuery() const; protected: - Socket() : instream(0), outstream(0), ownStreams(false), - isShutdown_(false), queryConnection(false) {} - Socket(rdr::FdInStream* i, rdr::FdOutStream* o, bool own) - : instream(i), outstream(o), ownStreams(own), - isShutdown_(false), queryConnection(false) {} + Socket(); + + void setFd(int fd); + + private: rdr::FdInStream* instream; rdr::FdOutStream* outstream; - bool ownStreams; bool isShutdown_; bool queryConnection; }; @@ -88,20 +76,32 @@ namespace network { class SocketListener { public: - SocketListener() : fd(0), filter(0) {} - virtual ~SocketListener() {} + SocketListener(int fd); + virtual ~SocketListener(); // shutdown() stops the socket from accepting further connections - virtual void shutdown() = 0; + void shutdown(); // accept() returns a new Socket object if there is a connection // attempt in progress AND if the connection passes the filter // if one is installed. Otherwise, returns 0. - virtual Socket* accept() = 0; + Socket* accept(); + + virtual int getMyPort() = 0; // setFilter() applies the specified filter to all new connections void setFilter(ConnectionFilter* f) {filter = f;} int getFd() {return fd;} + + protected: + SocketListener(); + + void listen(int fd); + + // createSocket() should create a new socket of the correct class + // for the given file descriptor + virtual Socket* createSocket(int fd) = 0; + protected: int fd; ConnectionFilter* filter; diff --git a/common/network/TcpSocket.cxx b/common/network/TcpSocket.cxx index 9603c385..51d77c76 100644 --- a/common/network/TcpSocket.cxx +++ b/common/network/TcpSocket.cxx @@ -28,21 +28,17 @@ #else #define errorNumber errno #define closesocket close -#include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/tcp.h> #include <netdb.h> #include <errno.h> -#include <string.h> -#include <signal.h> -#include <fcntl.h> #endif #include <stdlib.h> #include <unistd.h> + #include <network/TcpSocket.h> -#include <rfb/util.h> #include <rfb/LogWriter.h> #include <rfb/Configuration.h> @@ -99,40 +95,35 @@ int network::findFreeTcpPort (void) return ntohs(addr.sin_port); } +int network::getSockPort(int sock) +{ + vnc_sockaddr_t sa; + socklen_t sa_size = sizeof(sa); + if (getsockname(sock, &sa.u.sa, &sa_size) < 0) + return 0; -// -=- Socket initialisation -static bool socketsInitialised = false; -static void initSockets() { - if (socketsInitialised) - return; -#ifdef WIN32 - WORD requiredVersion = MAKEWORD(2,0); - WSADATA initResult; - - if (WSAStartup(requiredVersion, &initResult) != 0) - throw SocketException("unable to initialise Winsock2", errorNumber); -#else - signal(SIGPIPE, SIG_IGN); -#endif - socketsInitialised = true; + switch (sa.u.sa.sa_family) { + case AF_INET6: + return ntohs(sa.u.sin6.sin6_port); + default: + return ntohs(sa.u.sin.sin_port); + } } - // -=- TcpSocket -TcpSocket::TcpSocket(int sock, bool close) - : Socket(new FdInStream(sock), new FdOutStream(sock), true), closeFd(close) +TcpSocket::TcpSocket(int sock) : Socket(sock) { + // Disable Nagle's algorithm, to reduce latency + enableNagles(false); } TcpSocket::TcpSocket(const char *host, int port) - : closeFd(true) { int sock, err, result; struct addrinfo *ai, *current, hints; // - Create a socket - initSockets(); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; @@ -214,27 +205,11 @@ TcpSocket::TcpSocket(const char *host, int port) throw SocketException("unable connect to socket", err); } -#ifndef WIN32 - // - By default, close the socket on exec() - fcntl(sock, F_SETFD, FD_CLOEXEC); -#endif + // Take proper ownership of the socket + setFd(sock); // Disable Nagle's algorithm, to reduce latency - enableNagles(sock, false); - - // Create the input and output streams - instream = new FdInStream(sock); - outstream = new FdOutStream(sock); - ownStreams = true; -} - -TcpSocket::~TcpSocket() { - if (closeFd) - closesocket(getFd()); -} - -int TcpSocket::getMyPort() { - return getSockPort(getFd()); + enableNagles(false); } char* TcpSocket::getPeerAddress() { @@ -281,25 +256,20 @@ char* TcpSocket::getPeerAddress() { return rfb::strDup(""); } -int TcpSocket::getPeerPort() { +char* TcpSocket::getPeerEndpoint() { + rfb::CharArray address; address.buf = getPeerAddress(); vnc_sockaddr_t sa; socklen_t sa_size = sizeof(sa); + int port; getpeername(getFd(), &sa.u.sa, &sa_size); - switch (sa.u.sa.sa_family) { - case AF_INET6: - return ntohs(sa.u.sin6.sin6_port); - case AF_INET: - return ntohs(sa.u.sin.sin_port); - default: - return 0; - } -} - -char* TcpSocket::getPeerEndpoint() { - rfb::CharArray address; address.buf = getPeerAddress(); - int port = getPeerPort(); + if (sa.u.sa.sa_family == AF_INET6) + port = ntohs(sa.u.sin6.sin6_port); + else if (sa.u.sa.sa_family == AF_INET) + port = ntohs(sa.u.sin.sin_port); + else + port = 0; int buflen = strlen(address.buf) + 32; char* buffer = new char[buflen]; @@ -307,40 +277,9 @@ char* TcpSocket::getPeerEndpoint() { return buffer; } -bool TcpSocket::sameMachine() { - vnc_sockaddr_t peeraddr, myaddr; - socklen_t addrlen; - - addrlen = sizeof(peeraddr); - if (getpeername(getFd(), &peeraddr.u.sa, &addrlen) < 0) - throw SocketException ("unable to get peer address", errorNumber); - - addrlen = sizeof(myaddr); /* need to reset, since getpeername overwrote */ - if (getsockname(getFd(), &myaddr.u.sa, &addrlen) < 0) - throw SocketException ("unable to get my address", errorNumber); - - if (peeraddr.u.sa.sa_family != myaddr.u.sa.sa_family) - return false; - - if (peeraddr.u.sa.sa_family == AF_INET6) - return IN6_ARE_ADDR_EQUAL(&peeraddr.u.sin6.sin6_addr, - &myaddr.u.sin6.sin6_addr); - if (peeraddr.u.sa.sa_family == AF_INET) - return (peeraddr.u.sin.sin_addr.s_addr == myaddr.u.sin.sin_addr.s_addr); - - // No idea what this is. Assume we're on different machines. - return false; -} - -void TcpSocket::shutdown() -{ - Socket::shutdown(); - ::shutdown(getFd(), 2); -} - -bool TcpSocket::enableNagles(int sock, bool enable) { +bool TcpSocket::enableNagles(bool enable) { int one = enable ? 0 : 1; - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + if (setsockopt(getFd(), IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { int e = errorNumber; vlog.error("unable to setsockopt TCP_NODELAY: %d", e); @@ -360,34 +299,8 @@ bool TcpSocket::cork(bool enable) { #endif } -bool TcpSocket::isListening(int sock) +TcpListener::TcpListener(int sock) : SocketListener(sock) { - int listening = 0; - socklen_t listening_size = sizeof(listening); - if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN, - (char *)&listening, &listening_size) < 0) - return false; - return listening != 0; -} - -int TcpSocket::getSockPort(int sock) -{ - vnc_sockaddr_t sa; - socklen_t sa_size = sizeof(sa); - if (getsockname(sock, &sa.u.sa, &sa_size) < 0) - return 0; - - switch (sa.u.sa.sa_family) { - case AF_INET6: - return ntohs(sa.u.sin6.sin6_port); - default: - return ntohs(sa.u.sin.sin_port); - } -} - -TcpListener::TcpListener(int sock) -{ - fd = sock; } TcpListener::TcpListener(const struct sockaddr *listenaddr, @@ -397,8 +310,6 @@ TcpListener::TcpListener(const struct sockaddr *listenaddr, vnc_sockaddr_t sa; int sock; - initSockets(); - if ((sock = socket (listenaddr->sa_family, SOCK_STREAM, 0)) < 0) throw SocketException("unable to create listening socket", errorNumber); @@ -436,53 +347,11 @@ TcpListener::TcpListener(const struct sockaddr *listenaddr, throw SocketException("failed to bind socket", e); } - // - Set it to be a listening socket - if (listen(sock, 5) < 0) { - int e = errorNumber; - closesocket(sock); - throw SocketException("unable to set socket to listening mode", e); - } - - fd = sock; + listen(sock); } -TcpListener::~TcpListener() { - closesocket(fd); -} - -void TcpListener::shutdown() -{ -#ifdef WIN32 - closesocket(getFd()); -#else - ::shutdown(getFd(), 2); -#endif -} - - -Socket* -TcpListener::accept() { - int new_sock = -1; - - // Accept an incoming connection - if ((new_sock = ::accept(fd, 0, 0)) < 0) - throw SocketException("unable to accept new connection", errorNumber); - -#ifndef WIN32 - // - By default, close the socket on exec() - fcntl(new_sock, F_SETFD, FD_CLOEXEC); -#endif - - // Disable Nagle's algorithm, to reduce latency - TcpSocket::enableNagles(new_sock, false); - - // Create the socket object & check connection is allowed - TcpSocket* s = new TcpSocket(new_sock); - if (filter && !filter->verifyConnection(s)) { - delete s; - return 0; - } - return s; +Socket* TcpListener::createSocket(int fd) { + return new TcpSocket(fd); } void TcpListener::getMyAddresses(std::list<char*>* result) { @@ -528,11 +397,11 @@ void TcpListener::getMyAddresses(std::list<char*>* result) { } int TcpListener::getMyPort() { - return TcpSocket::getSockPort(getFd()); + return getSockPort(getFd()); } -void network::createLocalTcpListeners(std::list<TcpListener*> *listeners, +void network::createLocalTcpListeners(std::list<SocketListener*> *listeners, int port) { struct addrinfo ai[2]; @@ -562,7 +431,7 @@ void network::createLocalTcpListeners(std::list<TcpListener*> *listeners, createTcpListeners(listeners, ai); } -void network::createTcpListeners(std::list<TcpListener*> *listeners, +void network::createTcpListeners(std::list<SocketListener*> *listeners, const char *addr, int port) { @@ -594,11 +463,11 @@ void network::createTcpListeners(std::list<TcpListener*> *listeners, } } -void network::createTcpListeners(std::list<TcpListener*> *listeners, +void network::createTcpListeners(std::list<SocketListener*> *listeners, const struct addrinfo *ai) { const struct addrinfo *current; - std::list<TcpListener*> new_listeners; + std::list<SocketListener*> new_listeners; initSockets(); diff --git a/common/network/TcpSocket.h b/common/network/TcpSocket.h index c1b142ff..eb6c0958 100644 --- a/common/network/TcpSocket.h +++ b/common/network/TcpSocket.h @@ -48,48 +48,41 @@ namespace network { /* Tunnelling support. */ int findFreeTcpPort (void); + int getSockPort(int sock); + class TcpSocket : public Socket { public: - TcpSocket(int sock, bool close=true); + TcpSocket(int sock); TcpSocket(const char *name, int port); - virtual ~TcpSocket(); - - virtual int getMyPort(); virtual char* getPeerAddress(); - virtual int getPeerPort(); virtual char* getPeerEndpoint(); - virtual bool sameMachine(); - virtual void shutdown(); virtual bool cork(bool enable); - static bool enableNagles(int sock, bool enable); - static bool isListening(int sock); - static int getSockPort(int sock); - private: - bool closeFd; + protected: + bool enableNagles(bool enable); }; class TcpListener : public SocketListener { public: TcpListener(const struct sockaddr *listenaddr, socklen_t listenaddrlen); TcpListener(int sock); - virtual ~TcpListener(); - virtual void shutdown(); - virtual Socket* accept(); + virtual int getMyPort(); static void getMyAddresses(std::list<char*>* result); - int getMyPort(); + + protected: + virtual Socket* createSocket(int fd); }; - void createLocalTcpListeners(std::list<TcpListener*> *listeners, + void createLocalTcpListeners(std::list<SocketListener*> *listeners, int port); - void createTcpListeners(std::list<TcpListener*> *listeners, + void createTcpListeners(std::list<SocketListener*> *listeners, const char *addr, int port); - void createTcpListeners(std::list<TcpListener*> *listeners, + void createTcpListeners(std::list<SocketListener*> *listeners, const struct addrinfo *ai); typedef struct vnc_sockaddr { diff --git a/common/network/UnixSocket.cxx b/common/network/UnixSocket.cxx new file mode 100644 index 00000000..bfabc141 --- /dev/null +++ b/common/network/UnixSocket.cxx @@ -0,0 +1,171 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright (c) 2012 University of Oslo. All Rights Reserved. + * + * This 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 2 of the License, or + * (at your option) any later version. + * + * This software 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> +#include <stddef.h> + +#include <network/UnixSocket.h> +#include <rfb/LogWriter.h> + +using namespace network; +using namespace rdr; + +static rfb::LogWriter vlog("UnixSocket"); + +// -=- UnixSocket + +UnixSocket::UnixSocket(int sock) : Socket(sock) +{ +} + +UnixSocket::UnixSocket(const char *path) +{ + int sock, err, result; + sockaddr_un addr; + socklen_t salen; + + if (strlen(path) >= sizeof(addr.sun_path)) + throw SocketException("socket path is too long", ENAMETOOLONG); + + // - Create a socket + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock == -1) + throw SocketException("unable to create socket", errno); + + // - Attempt to connect + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, path); + salen = sizeof(addr); + while ((result = connect(sock, (sockaddr *)&addr, salen)) == -1) { + err = errno; + close(sock); + break; + } + + if (result == -1) + throw SocketException("unable connect to socket", err); + + setFd(sock); +} + +char* UnixSocket::getPeerAddress() { + struct sockaddr_un addr; + socklen_t salen; + + // AF_UNIX only has a single address (the server side). + // Unfortunately we don't know which end we are, so we'll have to + // test a bit. + + salen = sizeof(addr); + if (getpeername(getFd(), (struct sockaddr *)&addr, &salen) != 0) { + vlog.error("unable to get peer name for socket"); + return rfb::strDup(""); + } + + if (salen > offsetof(struct sockaddr_un, sun_path)) + return rfb::strDup(addr.sun_path); + + salen = sizeof(addr); + if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) != 0) { + vlog.error("unable to get local name for socket"); + return rfb::strDup(""); + } + + if (salen > offsetof(struct sockaddr_un, sun_path)) + return rfb::strDup(addr.sun_path); + + // socketpair() will create unnamed sockets + + return rfb::strDup("(unnamed UNIX socket)"); +} + +char* UnixSocket::getPeerEndpoint() { + return getPeerAddress(); +} + +bool UnixSocket::cork(bool enable) +{ + return true; +} + +UnixListener::UnixListener(const char *path, int mode) +{ + struct sockaddr_un addr; + mode_t saved_umask; + int err, result; + + if (strlen(path) >= sizeof(addr.sun_path)) + throw SocketException("socket path is too long", ENAMETOOLONG); + + // - Create a socket + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + throw SocketException("unable to create listening socket", errno); + + // - Delete existing socket (ignore result) + unlink(path); + + // - Attempt to bind to the requested path + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, path); + saved_umask = umask(0777); + result = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + err = errno; + umask(saved_umask); + if (result < 0) { + close(fd); + throw SocketException("unable to bind listening socket", err); + } + + // - Set socket mode + if (chmod(path, mode) < 0) { + err = errno; + close(fd); + throw SocketException("unable to set socket mode", err); + } + + listen(fd); +} + +UnixListener::~UnixListener() +{ + struct sockaddr_un addr; + socklen_t salen = sizeof(addr); + + if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) == 0) + unlink(addr.sun_path); +} + +Socket* UnixListener::createSocket(int fd) { + return new UnixSocket(fd); +} + +int UnixListener::getMyPort() { + return 0; +} diff --git a/common/network/UnixSocket.h b/common/network/UnixSocket.h new file mode 100644 index 00000000..1ffca456 --- /dev/null +++ b/common/network/UnixSocket.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright (c) 2012 University of Oslo. All Rights Reserved. + * + * This 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 2 of the License, or + * (at your option) any later version. + * + * This software 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// -=- UnixSocket.h - base-class for UNIX stream sockets. +// This header also defines the UnixListener class, used +// to listen for incoming socket connections over UNIX +// +// NB: Any file descriptors created by the UnixSocket or +// UnixListener classes are close-on-exec if the OS supports +// it. UnixSockets initialised with a caller-supplied fd +// are NOT set to close-on-exec. + +#ifndef __NETWORK_UNIX_SOCKET_H__ +#define __NETWORK_UNIX_SOCKET_H__ + +#include <network/Socket.h> + +namespace network { + + class UnixSocket : public Socket { + public: + UnixSocket(int sock); + UnixSocket(const char *name); + + virtual char* getPeerAddress(); + virtual char* getPeerEndpoint(); + + virtual bool cork(bool enable); + }; + + class UnixListener : public SocketListener { + public: + UnixListener(const char *listenaddr, int mode); + virtual ~UnixListener(); + + int getMyPort(); + + protected: + virtual Socket* createSocket(int fd); + }; + +} + +#endif // __NETWORK_UNIX_SOCKET_H__ diff --git a/common/rfb/Configuration.cxx b/common/rfb/Configuration.cxx index 418a0c93..619c4d5a 100644 --- a/common/rfb/Configuration.cxx +++ b/common/rfb/Configuration.cxx @@ -338,7 +338,7 @@ bool IntParameter::setParam(const char* v) { if (immutable) return true; vlog.debug("set %s(Int) to %s", getName(), v); - int i = atoi(v); + int i = strtol(v, NULL, 0); if (i < minValue || i > maxValue) return false; value = i; |