]> source.dussan.org Git - tigervnc.git/commitdiff
Merge common socket code
authorPierre Ossman <ossman@cendio.se>
Fri, 4 May 2018 10:44:31 +0000 (12:44 +0200)
committerPierre Ossman <ossman@cendio.se>
Tue, 29 May 2018 14:44:48 +0000 (16:44 +0200)
common/network/CMakeLists.txt
common/network/Socket.cxx [new file with mode: 0644]
common/network/Socket.h
common/network/TcpSocket.cxx
common/network/TcpSocket.h
common/network/UnixSocket.cxx
common/network/UnixSocket.h
unix/xserver/hw/vnc/RFBGlue.cc
unix/xserver/hw/vnc/vncExtInit.cc

index a63df96bab75949f2d7918b20661a984f8b659f7..d00ca452f4e1167cd3cd69142ec0a44c2fb7958c 100644 (file)
@@ -1,6 +1,7 @@
 include_directories(${CMAKE_SOURCE_DIR}/common)
 
 set(NETWORK_SOURCES
+  Socket.cxx
   TcpSocket.cxx)
 
 if(NOT WIN32)
diff --git a/common/network/Socket.cxx b/common/network/Socket.cxx
new file mode 100644 (file)
index 0000000..9dd8bfe
--- /dev/null
@@ -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;
+}
index 39ac39b4402d42753a4f8c50df042c07b9cd3295..bfda8a57ad6b0909cea1362e20fce18475dc5b69 100644 (file)
 
 namespace network {
 
+  void initSockets();
+
+  bool isSocketListening(int sock);
+
   class Socket {
   public:
-    Socket(int fd)
-      : instream(new rdr::FdInStream(fd)),
-      outstream(new rdr::FdOutStream(fd)),
-      isShutdown_(false),
-      queryConnection(false) {}
-    virtual ~Socket() {
-      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_;}
+    void shutdown();
+    bool isShutdown() const;
+
     virtual bool cork(bool enable) = 0;
 
     // information about the remote end of the socket
@@ -55,15 +53,15 @@ namespace network {
     virtual char* getPeerEndpoint() = 0; // <address>::<port>
 
     // 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),
-      isShutdown_(false), queryConnection(false) {}
-    Socket(rdr::FdInStream* i, rdr::FdOutStream* o)
-      : instream(i), outstream(o),
-      isShutdown_(false), queryConnection(false) {}
+    Socket();
+
+    void setFd(int fd);
+
+  private:
     rdr::FdInStream* instream;
     rdr::FdOutStream* outstream;
     bool isShutdown_;
@@ -78,22 +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;
index 555ce21553ee7712826d0ce2545dbd818e60af8d..51d77c76ebfd209033a90097cc63397b9e1a3404 100644 (file)
@@ -33,8 +33,6 @@
 #include <netinet/tcp.h>
 #include <netdb.h>
 #include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
 #endif
 
 #include <stdlib.h>
@@ -97,30 +95,27 @@ 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)
-  : Socket(new FdInStream(sock), new FdOutStream(sock))
+TcpSocket::TcpSocket(int sock) : Socket(sock)
 {
+  // Disable Nagle's algorithm, to reduce latency
+  enableNagles(false);
 }
 
 TcpSocket::TcpSocket(const char *host, int port)
@@ -129,7 +124,6 @@ TcpSocket::TcpSocket(const char *host, int port)
   struct addrinfo *ai, *current, hints;
 
   // - Create a socket
-  initSockets();
 
   memset(&hints, 0, sizeof(struct addrinfo));
   hints.ai_family = AF_UNSPEC;
@@ -211,21 +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);
-}
-
-TcpSocket::~TcpSocket() {
-  closesocket(getFd());
+  enableNagles(false);
 }
 
 char* TcpSocket::getPeerAddress() {
@@ -293,15 +277,9 @@ char* TcpSocket::getPeerEndpoint() {
   return buffer;
 }
 
-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);
@@ -321,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,
@@ -358,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);
 
@@ -397,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;
-}
-
-TcpListener::~TcpListener() {
-  closesocket(fd);
+  listen(sock);
 }
 
-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) {
@@ -489,7 +397,7 @@ void TcpListener::getMyAddresses(std::list<char*>* result) {
 }
 
 int TcpListener::getMyPort() {
-  return TcpSocket::getSockPort(getFd());
+  return getSockPort(getFd());
 }
 
 
index 87d8e695d8093da2cc40b0e342f27d58229903ae..eb6c0958d8481de646402e1bf179baa7371b2a5a 100644 (file)
@@ -48,35 +48,33 @@ namespace network {
   /* Tunnelling support. */
   int findFreeTcpPort (void);
 
+  int getSockPort(int sock);
+
   class TcpSocket : public Socket {
   public:
     TcpSocket(int sock);
     TcpSocket(const char *name, int port);
-    virtual ~TcpSocket();
 
     virtual char* getPeerAddress();
     virtual char* getPeerEndpoint();
 
-    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);
+  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);
+
+  protected:
+    virtual Socket* createSocket(int fd);
   };
 
   void createLocalTcpListeners(std::list<SocketListener*> *listeners,
index 8a223e4049b631b4e52bf902751a4e541b937483..bfabc141d42fb4e3a22adb1f287e8272af4c1458 100644 (file)
@@ -26,8 +26,6 @@
 #include <sys/un.h>
 #include <unistd.h>
 #include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <stddef.h>
 
@@ -39,20 +37,9 @@ using namespace rdr;
 
 static rfb::LogWriter vlog("UnixSocket");
 
-// -=- Socket initialisation
-static bool socketsInitialised = false;
-static void initSockets() {
-  if (socketsInitialised)
-    return;
-  signal(SIGPIPE, SIG_IGN);
-  socketsInitialised = true;
-}
-
-
 // -=- UnixSocket
 
-UnixSocket::UnixSocket(int sock)
-  : Socket(new FdInStream(sock), new FdOutStream(sock))
+UnixSocket::UnixSocket(int sock) : Socket(sock)
 {
 }
 
@@ -66,7 +53,6 @@ UnixSocket::UnixSocket(const char *path)
     throw SocketException("socket path is too long", ENAMETOOLONG);
 
   // - Create a socket
-  initSockets();
   sock = socket(AF_UNIX, SOCK_STREAM, 0);
   if (sock == -1)
     throw SocketException("unable to create socket", errno);
@@ -85,16 +71,7 @@ UnixSocket::UnixSocket(const char *path)
   if (result == -1)
     throw SocketException("unable connect to socket", err);
 
-  // - By default, close the socket on exec()
-  fcntl(sock, F_SETFD, FD_CLOEXEC);
-
-  // Create the input and output streams
-  instream = new FdInStream(sock);
-  outstream = new FdOutStream(sock);
-}
-
-UnixSocket::~UnixSocket() {
-  close(getFd());
+  setFd(sock);
 }
 
 char* UnixSocket::getPeerAddress() {
@@ -132,12 +109,6 @@ char* UnixSocket::getPeerEndpoint() {
   return getPeerAddress();
 }
 
-void UnixSocket::shutdown()
-{
-  Socket::shutdown();
-  ::shutdown(getFd(), 2);
-}
-
 bool UnixSocket::cork(bool enable)
 {
   return true;
@@ -153,13 +124,9 @@ UnixListener::UnixListener(const char *path, int mode)
     throw SocketException("socket path is too long", ENAMETOOLONG);
 
   // - Create a socket
-  initSockets();
   if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
     throw SocketException("unable to create listening socket", errno);
 
-  // - By default, close the socket on exec()
-  fcntl(fd, F_SETFD, FD_CLOEXEC);
-
   // - Delete existing socket (ignore result)
   unlink(path);
 
@@ -183,12 +150,7 @@ UnixListener::UnixListener(const char *path, int mode)
     throw SocketException("unable to set socket mode", err);
   }
 
-  // - Set it to be a listening socket
-  if (listen(fd, 5) < 0) {
-    err = errno;
-    close(fd);
-    throw SocketException("unable to set socket to listening mode", err);
-  }
+  listen(fd);
 }
 
 UnixListener::~UnixListener()
@@ -196,31 +158,12 @@ UnixListener::~UnixListener()
   struct sockaddr_un addr;
   socklen_t salen = sizeof(addr);
 
-  close(fd);
-
   if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) == 0)
     unlink(addr.sun_path);
 }
 
-void UnixListener::shutdown()
-{
-  ::shutdown(getFd(), 2);
-}
-
-
-Socket*
-UnixListener::accept() {
-  int new_sock = -1;
-
-  // Accept an incoming connection
-  if ((new_sock = ::accept(fd, 0, 0)) < 0)
-    throw SocketException("unable to accept new connection", errno);
-
-  // - By default, close the socket on exec()
-  fcntl(new_sock, F_SETFD, FD_CLOEXEC);
-
-  // - Create the socket object
-  return new UnixSocket(new_sock);
+Socket* UnixListener::createSocket(int fd) {
+  return new UnixSocket(fd);
 }
 
 int UnixListener::getMyPort() {
index 48c5b63f48af8f7cfe94186619c6d689f0da94c2..1ffca456df8ff21e076500ab98a5ebf7fd5d3997 100644 (file)
@@ -37,12 +37,10 @@ namespace network {
   public:
     UnixSocket(int sock);
     UnixSocket(const char *name);
-    virtual ~UnixSocket();
 
     virtual char* getPeerAddress();
     virtual char* getPeerEndpoint();
 
-    virtual void shutdown();
     virtual bool cork(bool enable);
   };
 
@@ -51,10 +49,10 @@ namespace network {
     UnixListener(const char *listenaddr, int mode);
     virtual ~UnixListener();
 
-    virtual void shutdown();
-    virtual Socket* accept();
-
     int getMyPort();
+
+  protected:
+    virtual Socket* createSocket(int fd);
   };
 
 }
index c09dfe6c82da168da4d37bb918928fc1e6f276a1..160177bd0d4a16075c6d26c2d4ca4d812467666a 100644 (file)
@@ -192,7 +192,7 @@ void vncListParams(int width, int nameWidth)
 
 int vncGetSocketPort(int fd)
 {
-  return network::TcpSocket::getSockPort(fd);
+  return network::getSockPort(fd);
 }
 
 int vncIsTCPPortUsed(int port)
index 4d96ca0d6e5d45d6dc1d7053004321d93fab7743..e4135b3c8b1fe562732367836960d26e9c1610de 100644 (file)
@@ -179,7 +179,7 @@ void vncExtensionInit(void)
         std::list<network::SocketListener*> listeners;
         std::list<network::SocketListener*> httpListeners;
         if (scr == 0 && vncInetdSock != -1) {
-          if (network::TcpSocket::isListening(vncInetdSock))
+          if (network::isSocketListening(vncInetdSock))
           {
             listeners.push_back(new network::TcpListener(vncInetdSock));
             vlog.info("inetd wait");