1 // 2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net> 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 // === 17 /// 18 /// \file gsimpleclient.h 19 /// 20 21 #ifndef G_SIMPLE_CLIENT_H 22 #define G_SIMPLE_CLIENT_H 23 24 #include "gdef.h" 25 #include "gnet.h" 26 #include "gaddress.h" 27 #include "gmemory.h" 28 #include "gconnection.h" 29 #include "gexception.h" 30 #include "geventhandler.h" 31 #include "gresolver.h" 32 #include "gresolverinfo.h" 33 #include "gsocket.h" 34 #include "gsocketprotocol.h" 35 #include "gevent.h" 36 #include <string> 37 38 /// \namespace GNet 39 namespace GNet 40 { 41 class SimpleClient ; 42 class ClientResolver ; 43 } 44 45 /// \class GNet::ClientResolver 46 /// A resolver class which calls SimpleClient::resolveCon() when done. 47 /// 48 class GNet::ClientResolver : public GNet::Resolver 49 { 50 private: 51 SimpleClient & m_client ; 52 53 public: 54 explicit ClientResolver( SimpleClient & ) ; 55 ///< Constructor. 56 57 void resolveCon( bool success , const Address &address , std::string reason ) ; 58 ///< From Resolver. 59 60 private: 61 ClientResolver( const ClientResolver & ) ; 62 void operator=( const ClientResolver & ) ; 63 } ; 64 65 /// \class GNet::SimpleClient 66 /// A class for making an outgoing connection to a remote server, with 67 /// support for socket-level protocols such as TLS/SSL and SOCKS 4a. 68 /// 69 /// The class handles name-to-address resolution, deals with connection issues, 70 /// reads incoming data, and manages flow-control when sending. The implementation 71 /// uses the SocketProtocol class in order to do TLS/SSL; see sslConnect(). 72 /// 73 /// Name-to-address lookup is performed if the supplied ResolverInfo object 74 /// does not contain an address. This can be done synchronously or asynchronously. 75 /// The results of the lookup can be obtained via the resolverInfo() method 76 /// and possibly fed back to the next SimpleClient that connects to the same 77 /// host/service in order to implement name lookup cacheing (see GNet::ClientPtr). 78 /// However, most operating systems implement their own name lookup cacheing, 79 /// so this is not terribly useful in practice. 80 /// 81 class GNet::SimpleClient : public GNet::EventHandler , public GNet::Connection , public GNet::SocketProtocolSink 82 { 83 public: 84 enum ConnectStatus { Success , Failure , Retry , ImmediateSuccess } ; 85 enum State { Idle , Resolving , Connecting , Connected , Socksing } ; 86 G_EXCEPTION( DnsError , "dns error" ) ; 87 G_EXCEPTION( ConnectError , "connect failure" ) ; 88 G_EXCEPTION( SocksError , "socks error" ) ; 89 G_EXCEPTION( NotConnected , "socket not connected" ) ; 90 typedef std::string::size_type size_type ; 91 92 SimpleClient( const ResolverInfo & remote_info , 93 const Address & local_address = Address(0U) , 94 bool privileged = false , 95 bool sync_dns = synchronousDnsDefault() , 96 unsigned int secure_connection_timeout = 0U ) ; 97 ///< Constructor. 98 ///< 99 ///< If the 'privileged' parameter is true then the 100 ///< given 'local_address' is used to bind the local 101 ///< socket once its port number has been overwritten 102 ///< with a privileged port number (ie. < 1024) 103 ///< selected at random. 104 ///< 105 ///< Otherwise, if the given 'local_address' is 106 ///< not the default value then it is used to bind 107 ///< the local socket. 108 109 void connect() ; 110 ///< Initates a connection to the remote server. 111 ///< 112 ///< This default implementation throws on error, and may 113 ///< call onConnect() synchronously before returning. To 114 ///< ensure onConnect() is always called asynchronously 115 ///< it can be a good idea to call connect() from a 116 ///< zero-length timer (as HeapClient does). 117 118 bool connected() const ; 119 ///< Returns true if connected to the peer. 120 121 virtual std::pair<bool,Address> localAddress() const ; 122 ///< Override from Connection. Returns the local 123 ///< address. Pair.first is false on error. 124 ///< Final override from GNet::Connection. 125 126 virtual std::pair<bool,Address> peerAddress() const ; 127 ///< Override from Connection. Returns the peer 128 ///< address. Pair.first is false on error. 129 ///< Final override from GNet::Connection. 130 131 virtual std::string peerCertificate() const ; 132 ///< Returns the peer's TLS certificate. 133 ///< Final override from GNet::Connection. 134 135 ResolverInfo resolverInfo() const ; 136 ///< Returns a ResolverInfo structure containing the 137 ///< result of host() and service() name lookup if 138 ///< available. 139 140 static bool synchronousDnsDefault() ; 141 ///< Returns true if DNS queries should normally be 142 ///< synchronous on this platform. Used to default the 143 ///< relevant constructor parameter. 144 145 void updateResolverInfo( const ResolverInfo & ) ; 146 ///< Updates the constructor's ResolverInfo object with 147 ///< the given one as long as both objects have the 148 ///< same host and service name. This is only useful 149 ///< immediately after construction and before 150 ///< re-entering the event loop. 151 152 virtual void readEvent() ; 153 ///< Final override from GNet::EventHandler. 154 155 virtual void writeEvent() ; 156 ///< Final override from GNet::EventHandler. 157 158 bool send( const std::string & data , std::string::size_type offset = 0 ) ; 159 ///< Returns true if all sent, or false if flow 160 ///< control was asserted. Throws on error. 161 162 protected: 163 virtual ~SimpleClient() ; 164 ///< Destructor. 165 166 StreamSocket & socket() ; 167 ///< Returns a reference to the socket. Throws if not connected. 168 169 const StreamSocket & socket() const ; 170 ///< Returns a const reference to the socket. Throws if not connected. 171 172 virtual void onConnect() = 0 ; 173 ///< Called once connected. May (unfortunately) be 174 ///< called from within connect(). 175 176 virtual void onConnectImp() ; 177 ///< An alternative to onConnect() for private implementation 178 ///< classes. The default implementation does nothing. 179 180 virtual void onSendComplete() = 0 ; 181 ///< Called when all residual data from send() has been sent. 182 183 virtual void onSendImp() ; 184 ///< Called from within send(). 185 186 void sslConnect() ; 187 ///< Starts TLS/SSL client-side negotiation. 188 189 static bool canRetry( const std::string & reason ) ; 190 ///< Parses the given failure reason and returns 191 ///< true if the client can reasonably retry 192 ///< at some later time. (Not used?) 193 194 std::string logId() const ; 195 ///< Returns a identification string for logging purposes. 196 ///< Not guaranteed to stay the same during the lifetime 197 ///< of the object. 198 199 private: 200 friend class ClientResolver ; 201 void resolveCon( bool , const Address & , std::string ) ; 202 203 private: 204 SimpleClient( const SimpleClient& ) ; // not implemented 205 void operator=( const SimpleClient& ) ; // not implemented 206 void close() ; 207 static unsigned int getRandomPort() ; 208 bool startConnecting() ; 209 bool localBind( Address ) ; 210 ConnectStatus connectCore( Address remote_address , std::string *error_p ) ; 211 void setState( State ) ; 212 void immediateConnection() ; 213 void sendSocksRequest() ; 214 bool readSocksResponse() ; 215 void logFlowControlAsserted() const ; 216 void logFlowControlReleased() const ; 217 218 private: 219 std::auto_ptr<ClientResolver> m_resolver ; 220 std::auto_ptr<StreamSocket> m_s ; 221 std::auto_ptr<SocketProtocol> m_sp ; 222 ResolverInfo m_remote ; 223 Address m_local_address ; 224 bool m_privileged ; 225 State m_state ; 226 bool m_sync_dns ; 227 unsigned int m_secure_connection_timeout ; 228 } ; 229 230 #endif 231