1 /* 2 * Copyright (c) 2007-2019 by Jakob Schröter <js@camaya.net> 3 * This file is part of the gloox library. http://camaya.net/gloox 4 * 5 * This software is distributed under a license. The full license 6 * agreement can be found in the file LICENSE in this distribution. 7 * This software may not be copied, modified, sold or distributed 8 * other than expressed in the named license agreement. 9 * 10 * This software is distributed without any warranty. 11 */ 12 13 #ifndef CONNECTIONBOSH_H__ 14 #define CONNECTIONBOSH_H__ 15 16 #include "gloox.h" 17 #include "connectionbase.h" 18 #include "logsink.h" 19 #include "taghandler.h" 20 #include "parser.h" 21 22 #include <string> 23 #include <list> 24 #include <ctime> 25 26 namespace gloox 27 { 28 29 /** 30 * @brief This is an implementation of a BOSH (HTTP binding) connection. 31 * 32 * Usage: 33 * 34 * @code 35 * Client *c = new Client( ... ); 36 * c->setConnectionImpl( new ConnectionBOSH( c, 37 * new ConnectionTCPClient( c->logInstance(), httpServer, httpPort ), 38 * c->logInstance(), boshHost, xmpphost, xmppPort ) ); 39 * @endcode 40 * 41 * Make sure to pass the BOSH connection manager's host/port to the transport connection 42 * (ConnectionTCPClient in this case), and the XMPP server's host and port to the BOSH connection. 43 * You must also pass to BOSH the address of the BOSH server you are dealing with, this is used 44 * in the HTTP Host header. 45 * 46 * In the case of using ConnectionBOSH through a HTTP proxy, supply httpServer and httpPort as 47 * those of the proxy. In all cases, boshHost should be set to the hostname (not IP address) of 48 * the server running the BOSH connection manager. 49 * 50 * The reason why ConnectionBOSH doesn't manage its own ConnectionTCPClient is that it allows it 51 * to be used with other transports (like chained SOCKS5/HTTP proxies, or ConnectionTLS 52 * for HTTPS). 53 * 54 * @note To avoid problems, you should disable TLS in gloox by calling 55 * ClientBase::setTls( TLSDisabled ). 56 * 57 * Sample configurations for different servers can be found in the bosh_example.cpp file included 58 * with gloox in the @b src/examples/ directory. 59 * 60 * @author Matthew Wild <mwild1@gmail.com> 61 * @author Jakob Schröter <js@camaya.net> 62 * @since 1.0 63 */ 64 class GLOOX_API ConnectionBOSH : public ConnectionBase, ConnectionDataHandler, TagHandler 65 { 66 public: 67 /** 68 * Constructs a new ConnectionBOSH object. 69 * @param connection A transport connection. It should be configured to connect to 70 * the BOSH connection manager's (or a HTTP proxy's) host and port, @b not to the XMPP host. 71 * ConnectionBOSH will own the transport connection and delete it in its destructor. 72 * @param logInstance The log target. Obtain it from ClientBase::logInstance(). 73 * @param boshHost The hostname of the BOSH connection manager 74 * @param xmppServer A server to connect to. This is the XMPP server's address, @b not the 75 * connection manager's. 76 * @param xmppPort The port to connect to. This is the XMPP server's port, @b not the connection 77 * manager's. 78 * @note To properly use this object, you have to set a ConnectionDataHandler using 79 * registerConnectionDataHandler(). This is not necessary if this object is 80 * part of a 'connection chain', e.g. with ConnectionSOCKS5Proxy. 81 */ 82 ConnectionBOSH( ConnectionBase* connection, const LogSink& logInstance, const std::string& boshHost, 83 const std::string& xmppServer, int xmppPort = 5222 ); 84 85 /** 86 * Constructs a new ConnectionBOSH object. 87 * @param cdh An ConnectionDataHandler-derived object that will handle incoming data. 88 * @param connection A transport connection. It should be configured to connect to 89 * the connection manager's (or proxy's) host and port, @b not to the XMPP host. ConnectionBOSH 90 * will own the transport connection and delete it in its destructor. 91 * @param logInstance The log target. Obtain it from ClientBase::logInstance(). 92 * @param boshHost The hostname of the BOSH connection manager (not any intermediate proxy) 93 * @param xmppServer A server to connect to. This is the XMPP server's address, @b not the connection 94 * manager's. 95 * @param xmppPort The port to connect to. This is the XMPP server's port, @b not the connection 96 * manager's. 97 */ 98 ConnectionBOSH( ConnectionDataHandler* cdh, ConnectionBase* connection, 99 const LogSink& logInstance, const std::string& boshHost, 100 const std::string& xmppServer, int xmppPort = 5222 ); 101 102 /** 103 * Virtual destructor 104 */ 105 virtual ~ConnectionBOSH(); 106 107 /** 108 * The supported connection modes. Usually auto-detected. 109 */ 110 enum ConnMode 111 { 112 ModeLegacyHTTP, /**< HTTP 1.0 connections, closed after receiving a response */ 113 ModePersistentHTTP, /**< HTTP 1.1 connections, re-used after receiving a response */ 114 ModePipelining /**< HTTP Pipelining (implies HTTP 1.1) a single connection is used */ 115 }; 116 117 /** 118 * Sets the XMPP server to proxy to. 119 * @param xmppHost The XMPP server hostname (IP address). 120 * @param xmppPort The XMPP server port. 121 */ 122 void setServer( const std::string& xmppHost, unsigned short xmppPort = 5222 ) 123 { m_server = xmppHost; m_port = xmppPort; } 124 125 /** 126 * Sets the path on the connection manager to request 127 * @param path The path, the default is "/http-bind/", which is the default for 128 * many connection managers. 129 */ setPath(const std::string & path)130 void setPath( const std::string& path ) { m_path = path; } 131 132 /** 133 * Sets the connection mode 134 * @param mode The connection mode, @sa ConnMode 135 * @note In the case that a mode is selected that the connection manager 136 * or proxy does not support, gloox will fall back to using HTTP/1.0 connections, 137 * which should work with any server. 138 */ setMode(ConnMode mode)139 void setMode( ConnMode mode ) { m_connMode = mode; } 140 141 // reimplemented from ConnectionBase 142 virtual ConnectionError connect(); 143 144 // reimplemented from ConnectionBase 145 virtual ConnectionError recv( int timeout = -1 ); 146 147 // reimplemented from ConnectionBase 148 virtual bool send( const std::string& data ); 149 150 // reimplemented from ConnectionBase 151 virtual ConnectionError receive(); 152 153 // reimplemented from ConnectionBase 154 virtual void disconnect(); 155 156 // reimplemented from ConnectionBase 157 virtual void cleanup(); 158 159 // reimplemented from ConnectionBase 160 virtual void getStatistics( long int& totalIn, long int& totalOut ); 161 162 // reimplemented from ConnectionDataHandler 163 virtual void handleReceivedData( const ConnectionBase* connection, const std::string& data ); 164 165 // reimplemented from ConnectionDataHandler 166 virtual void handleConnect( const ConnectionBase* connection ); 167 168 // reimplemented from ConnectionDataHandler 169 virtual void handleDisconnect( const ConnectionBase* connection, ConnectionError reason ); 170 171 // reimplemented from ConnectionDataHandler 172 virtual ConnectionBase* newInstance() const; 173 174 // reimplemented from TagHandler 175 virtual void handleTag( Tag* tag ); 176 177 private: 178 ConnectionBOSH& operator=( const ConnectionBOSH& ); 179 void initInstance( ConnectionBase* connection, const std::string& xmppServer, const int xmppPort ); 180 bool sendRequest( const std::string& xml ); 181 bool sendXML(); 182 const std::string getHTTPField( const std::string& field ); 183 ConnectionBase* getConnection(); 184 ConnectionBase* activateConnection(); 185 void putConnection(); 186 187 //ConnectionBase *m_connection; 188 const LogSink& m_logInstance; 189 190 Parser m_parser; // Used for parsing XML section of responses 191 std::string m_boshHost; // The hostname of the BOSH connection manager 192 std::string m_boshedHost; // The hostname of the BOSH connection manager + : + port 193 std::string m_path; // The path part of the URL that we need to request 194 195 // BOSH parameters 196 unsigned long m_rid; 197 std::string m_sid; 198 199 bool m_initialStreamSent; 200 int m_openRequests; 201 int m_maxOpenRequests; 202 int m_wait; 203 int m_hold; 204 205 bool m_streamRestart; // Set to true if we are waiting for an acknowledgement of a stream restart 206 207 time_t m_lastRequestTime; 208 unsigned long m_minTimePerRequest; 209 210 std::string m_buffer; // Buffer of received data 211 std::string m_bufferHeader; // HTTP header of data currently in buffer // FIXME doens't need to be member 212 std::string::size_type m_bufferContentLength; // Length of the data in the current response 213 214 std::string m_sendBuffer; // Data waiting to be sent 215 216 typedef std::list<ConnectionBase*> ConnectionList; 217 ConnectionList m_activeConnections; 218 ConnectionList m_connectionPool; 219 ConnMode m_connMode; 220 221 }; 222 223 } 224 225 #endif // CONNECTIONBOSH_H__ 226