Constantin Kaplinsky | a2adc8d | 2006-05-25 05:01:55 +0000 | [diff] [blame] | 1 | /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. |
| 2 | * |
| 3 | * This is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License as published by |
| 5 | * the Free Software Foundation; either version 2 of the License, or |
| 6 | * (at your option) any later version. |
| 7 | * |
| 8 | * This software is distributed in the hope that it will be useful, |
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | * GNU General Public License for more details. |
| 12 | * |
| 13 | * You should have received a copy of the GNU General Public License |
| 14 | * along with this software; if not, write to the Free Software |
| 15 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
| 16 | * USA. |
| 17 | */ |
| 18 | |
| 19 | // -=- Socket.h - abstract base-class for any kind of network stream/socket |
| 20 | |
| 21 | #ifndef __NETWORK_SOCKET_H__ |
| 22 | #define __NETWORK_SOCKET_H__ |
| 23 | |
Pierre Ossman | 574dc64 | 2016-10-05 13:39:11 +0200 | [diff] [blame] | 24 | #include <list> |
| 25 | |
Constantin Kaplinsky | a2adc8d | 2006-05-25 05:01:55 +0000 | [diff] [blame] | 26 | #include <limits.h> |
| 27 | #include <rdr/FdInStream.h> |
| 28 | #include <rdr/FdOutStream.h> |
| 29 | #include <rdr/Exception.h> |
| 30 | |
| 31 | namespace network { |
| 32 | |
| 33 | class Socket { |
| 34 | public: |
| 35 | Socket(int fd) |
| 36 | : instream(new rdr::FdInStream(fd)), |
| 37 | outstream(new rdr::FdOutStream(fd)), |
| 38 | ownStreams(true), isShutdown_(false), |
| 39 | queryConnection(false) {} |
| 40 | virtual ~Socket() { |
| 41 | if (ownStreams) { |
| 42 | delete instream; |
| 43 | delete outstream; |
| 44 | } |
| 45 | } |
| 46 | rdr::FdInStream &inStream() {return *instream;} |
| 47 | rdr::FdOutStream &outStream() {return *outstream;} |
| 48 | int getFd() {return outstream->getFd();} |
| 49 | |
| 50 | // if shutdown() is overridden then the override MUST call on to here |
| 51 | virtual void shutdown() {isShutdown_ = true;} |
| 52 | bool isShutdown() const {return isShutdown_;} |
Peter Åstrand (astrand) | 01dc1a6 | 2017-10-10 12:56:04 +0200 | [diff] [blame^] | 53 | virtual bool cork(bool enable) = 0; |
Constantin Kaplinsky | a2adc8d | 2006-05-25 05:01:55 +0000 | [diff] [blame] | 54 | |
| 55 | // information about this end of the socket |
Constantin Kaplinsky | a2adc8d | 2006-05-25 05:01:55 +0000 | [diff] [blame] | 56 | virtual int getMyPort() = 0; |
Constantin Kaplinsky | a2adc8d | 2006-05-25 05:01:55 +0000 | [diff] [blame] | 57 | |
| 58 | // information about the remote end of the socket |
| 59 | virtual char* getPeerAddress() = 0; // a string e.g. "192.168.0.1" |
| 60 | virtual int getPeerPort() = 0; |
| 61 | virtual char* getPeerEndpoint() = 0; // <address>::<port> |
| 62 | |
| 63 | // Is the remote end on the same machine? |
| 64 | virtual bool sameMachine() = 0; |
| 65 | |
| 66 | // Was there a "?" in the ConnectionFilter used to accept this Socket? |
| 67 | void setRequiresQuery() {queryConnection = true;} |
| 68 | bool requiresQuery() const {return queryConnection;} |
| 69 | |
| 70 | protected: |
| 71 | Socket() : instream(0), outstream(0), ownStreams(false), |
| 72 | isShutdown_(false), queryConnection(false) {} |
| 73 | Socket(rdr::FdInStream* i, rdr::FdOutStream* o, bool own) |
| 74 | : instream(i), outstream(o), ownStreams(own), |
| 75 | isShutdown_(false), queryConnection(false) {} |
| 76 | rdr::FdInStream* instream; |
| 77 | rdr::FdOutStream* outstream; |
| 78 | bool ownStreams; |
| 79 | bool isShutdown_; |
| 80 | bool queryConnection; |
| 81 | }; |
| 82 | |
| 83 | class ConnectionFilter { |
| 84 | public: |
| 85 | virtual bool verifyConnection(Socket* s) = 0; |
Steve Kondik | a642462 | 2017-07-08 01:49:14 -0700 | [diff] [blame] | 86 | virtual ~ConnectionFilter() {} |
Constantin Kaplinsky | a2adc8d | 2006-05-25 05:01:55 +0000 | [diff] [blame] | 87 | }; |
| 88 | |
| 89 | class SocketListener { |
| 90 | public: |
| 91 | SocketListener() : fd(0), filter(0) {} |
| 92 | virtual ~SocketListener() {} |
| 93 | |
| 94 | // shutdown() stops the socket from accepting further connections |
| 95 | virtual void shutdown() = 0; |
| 96 | |
| 97 | // accept() returns a new Socket object if there is a connection |
| 98 | // attempt in progress AND if the connection passes the filter |
| 99 | // if one is installed. Otherwise, returns 0. |
| 100 | virtual Socket* accept() = 0; |
| 101 | |
| 102 | // setFilter() applies the specified filter to all new connections |
| 103 | void setFilter(ConnectionFilter* f) {filter = f;} |
| 104 | int getFd() {return fd;} |
| 105 | protected: |
| 106 | int fd; |
| 107 | ConnectionFilter* filter; |
| 108 | }; |
| 109 | |
| 110 | struct SocketException : public rdr::SystemException { |
| 111 | SocketException(const char* text, int err_) : rdr::SystemException(text, err_) {} |
| 112 | }; |
| 113 | |
| 114 | class SocketServer { |
| 115 | public: |
| 116 | virtual ~SocketServer() {} |
| 117 | |
| 118 | // addSocket() tells the server to serve the Socket. The caller |
| 119 | // retains ownership of the Socket - the only way for the server |
| 120 | // to discard a Socket is by calling shutdown() on it. |
| 121 | // outgoing is set to true if the socket was created by connecting out |
| 122 | // to another host, or false if the socket was created by accept()ing |
| 123 | // an incoming connection. |
| 124 | virtual void addSocket(network::Socket* sock, bool outgoing=false) = 0; |
| 125 | |
| 126 | // removeSocket() tells the server to stop serving the Socket. The |
| 127 | // caller retains ownership of the Socket - the server must NOT |
| 128 | // delete the Socket! This call is used mainly to cause per-Socket |
| 129 | // resources to be freed. |
| 130 | virtual void removeSocket(network::Socket* sock) = 0; |
| 131 | |
Pierre Ossman | 574dc64 | 2016-10-05 13:39:11 +0200 | [diff] [blame] | 132 | // getSockets() gets a list of sockets. This can be used to generate an |
| 133 | // fd_set for calling select(). |
| 134 | virtual void getSockets(std::list<network::Socket*>* sockets) = 0; |
| 135 | |
Pierre Ossman | d408ca5 | 2016-04-29 14:26:05 +0200 | [diff] [blame] | 136 | // processSocketReadEvent() tells the server there is a Socket read event. |
Constantin Kaplinsky | a2adc8d | 2006-05-25 05:01:55 +0000 | [diff] [blame] | 137 | // The implementation can indicate that the Socket is no longer active |
| 138 | // by calling shutdown() on it. The caller will then call removeSocket() |
| 139 | // soon after processSocketEvent returns, to allow any pre-Socket |
| 140 | // resources to be tidied up. |
Pierre Ossman | d408ca5 | 2016-04-29 14:26:05 +0200 | [diff] [blame] | 141 | virtual void processSocketReadEvent(network::Socket* sock) = 0; |
| 142 | |
| 143 | // processSocketReadEvent() tells the server there is a Socket write event. |
| 144 | // This is only necessary if the Socket has been put in non-blocking |
| 145 | // mode and needs this callback to flush the buffer. |
| 146 | virtual void processSocketWriteEvent(network::Socket* sock) = 0; |
Constantin Kaplinsky | a2adc8d | 2006-05-25 05:01:55 +0000 | [diff] [blame] | 147 | |
| 148 | // checkTimeouts() allows the server to check socket timeouts, etc. The |
| 149 | // return value is the number of milliseconds to wait before |
| 150 | // checkTimeouts() should be called again. If this number is zero then |
| 151 | // there is no timeout and checkTimeouts() should be called the next time |
| 152 | // an event occurs. |
| 153 | virtual int checkTimeouts() = 0; |
| 154 | |
| 155 | virtual bool getDisable() {return false;}; |
| 156 | }; |
| 157 | |
| 158 | } |
| 159 | |
| 160 | #endif // __NETWORK_SOCKET_H__ |