226 lines
8.9 KiB
C
226 lines
8.9 KiB
C
|
/*
|
||
|
* Copyright (c) 2007-2009 by Jakob Schroeter <js@camaya.net>
|
||
|
* This file is part of the gloox library. http://camaya.net/gloox
|
||
|
*
|
||
|
* This software is distributed under a license. The full license
|
||
|
* agreement can be found in the file LICENSE in this distribution.
|
||
|
* This software may not be copied, modified, sold or distributed
|
||
|
* other than expressed in the named license agreement.
|
||
|
*
|
||
|
* This software is distributed without any warranty.
|
||
|
*/
|
||
|
|
||
|
#ifndef CONNECTIONBOSH_H__
|
||
|
#define CONNECTIONBOSH_H__
|
||
|
|
||
|
#include "gloox.h"
|
||
|
#include "connectionbase.h"
|
||
|
#include "logsink.h"
|
||
|
#include "taghandler.h"
|
||
|
#include "parser.h"
|
||
|
|
||
|
#include <string>
|
||
|
#include <list>
|
||
|
#include <ctime>
|
||
|
|
||
|
namespace gloox
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* @brief This is an implementation of a BOSH (HTTP binding) connection.
|
||
|
*
|
||
|
* Usage:
|
||
|
*
|
||
|
* @code
|
||
|
* Client *c = new Client( ... );
|
||
|
* c->setConnectionImpl( new ConnectionBOSH( c,
|
||
|
* new ConnectionTCPClient( c->logInstance(), httpServer, httpPort ),
|
||
|
* c->logInstance(), boshHost, xmpphost, xmppPort ) );
|
||
|
* @endcode
|
||
|
*
|
||
|
* Make sure to pass the BOSH connection manager's host/port to the transport connection
|
||
|
* (ConnectionTCPClient in this case), and the XMPP server's host and port to the BOSH connection.
|
||
|
* You must also pass to BOSH the address of the BOSH server you are dealing with, this is used
|
||
|
* in the HTTP Host header.
|
||
|
*
|
||
|
* In the case of using ConnectionBOSH through a HTTP proxy, supply httpServer and httpPort as
|
||
|
* those of the proxy. In all cases, boshHost should be set to the hostname (not IP address) of
|
||
|
* the server running the BOSH connection manager.
|
||
|
*
|
||
|
* The reason why ConnectionBOSH doesn't manage its own ConnectionTCPClient is that it allows it
|
||
|
* to be used with other transports (like chained SOCKS5/HTTP proxies, or ConnectionTLS
|
||
|
* for HTTPS).
|
||
|
*
|
||
|
* @note To avoid problems, you should disable TLS in gloox by calling
|
||
|
* ClientBase::setTls( TLSDisabled ).
|
||
|
*
|
||
|
* Sample configurations for different servers can be found in the bosh_example.cpp file included
|
||
|
* with gloox in the @b src/examples/ directory.
|
||
|
*
|
||
|
* @author Matthew Wild <mwild1@gmail.com>
|
||
|
* @author Jakob Schroeter <js@camaya.net>
|
||
|
* @since 1.0
|
||
|
*/
|
||
|
class GLOOX_API ConnectionBOSH : public ConnectionBase, ConnectionDataHandler, TagHandler
|
||
|
{
|
||
|
public:
|
||
|
/**
|
||
|
* Constructs a new ConnectionBOSH object.
|
||
|
* @param connection A transport connection. It should be configured to connect to
|
||
|
* the BOSH connection manager's (or a HTTP proxy's) host and port, @b not to the XMPP host.
|
||
|
* ConnectionBOSH will own the transport connection and delete it in its destructor.
|
||
|
* @param logInstance The log target. Obtain it from ClientBase::logInstance().
|
||
|
* @param boshHost The hostname of the BOSH connection manager
|
||
|
* @param xmppServer A server to connect to. This is the XMPP server's address, @b not the
|
||
|
* connection manager's.
|
||
|
* @param xmppPort The port to connect to. This is the XMPP server's port, @b not the connection
|
||
|
* manager's.
|
||
|
* @note To properly use this object, you have to set a ConnectionDataHandler using
|
||
|
* registerConnectionDataHandler(). This is not necessary if this object is
|
||
|
* part of a 'connection chain', e.g. with ConnectionSOCKS5Proxy.
|
||
|
*/
|
||
|
ConnectionBOSH( ConnectionBase* connection, const LogSink& logInstance, const std::string& boshHost,
|
||
|
const std::string& xmppServer, int xmppPort = 5222 );
|
||
|
|
||
|
/**
|
||
|
* Constructs a new ConnectionBOSH object.
|
||
|
* @param cdh An ConnectionDataHandler-derived object that will handle incoming data.
|
||
|
* @param connection A transport connection. It should be configured to connect to
|
||
|
* the connection manager's (or proxy's) host and port, @b not to the XMPP host. ConnectionBOSH
|
||
|
* will own the transport connection and delete it in its destructor.
|
||
|
* @param logInstance The log target. Obtain it from ClientBase::logInstance().
|
||
|
* @param boshHost The hostname of the BOSH connection manager (not any intermediate proxy)
|
||
|
* @param xmppServer A server to connect to. This is the XMPP server's address, @b not the connection
|
||
|
* manager's.
|
||
|
* @param xmppPort The port to connect to. This is the XMPP server's port, @b not the connection
|
||
|
* manager's.
|
||
|
*/
|
||
|
ConnectionBOSH( ConnectionDataHandler* cdh, ConnectionBase* connection,
|
||
|
const LogSink& logInstance, const std::string& boshHost,
|
||
|
const std::string& xmppServer, int xmppPort = 5222 );
|
||
|
|
||
|
/**
|
||
|
* Virtual destructor
|
||
|
*/
|
||
|
virtual ~ConnectionBOSH();
|
||
|
|
||
|
/**
|
||
|
* The supported connection modes. Usually auto-detected.
|
||
|
*/
|
||
|
enum ConnMode
|
||
|
{
|
||
|
ModeLegacyHTTP, /**< HTTP 1.0 connections, closed after receiving a response */
|
||
|
ModePersistentHTTP, /**< HTTP 1.1 connections, re-used after receiving a response */
|
||
|
ModePipelining /**< HTTP Pipelining (implies HTTP 1.1) a single connection is used */
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Sets the XMPP server to proxy to.
|
||
|
* @param xmppHost The XMPP server hostname (IP address).
|
||
|
* @param xmppPort The XMPP server port.
|
||
|
*/
|
||
|
void setServer( const std::string& xmppHost, unsigned short xmppPort = 5222 )
|
||
|
{ m_server = xmppHost; m_port = xmppPort; }
|
||
|
|
||
|
/**
|
||
|
* Sets the path on the connection manager to request
|
||
|
* @param path The path, the default is "/http-bind/", which is the default for
|
||
|
* many connection managers.
|
||
|
*/
|
||
|
void setPath( const std::string& path ) { m_path = path; }
|
||
|
|
||
|
/**
|
||
|
* Sets the connection mode
|
||
|
* @param mode The connection mode, @sa ConnMode
|
||
|
* @note In the case that a mode is selected that the connection manager
|
||
|
* or proxy does not support, gloox will fall back to using HTTP/1.0 connections,
|
||
|
* which should work with any server.
|
||
|
*/
|
||
|
void setMode( ConnMode mode ) { m_connMode = mode; }
|
||
|
|
||
|
// reimplemented from ConnectionBase
|
||
|
virtual ConnectionError connect();
|
||
|
|
||
|
// reimplemented from ConnectionBase
|
||
|
virtual ConnectionError recv( int timeout = -1 );
|
||
|
|
||
|
// reimplemented from ConnectionBase
|
||
|
virtual bool send( const std::string& data );
|
||
|
|
||
|
// reimplemented from ConnectionBase
|
||
|
virtual ConnectionError receive();
|
||
|
|
||
|
// reimplemented from ConnectionBase
|
||
|
virtual void disconnect();
|
||
|
|
||
|
// reimplemented from ConnectionBase
|
||
|
virtual void cleanup();
|
||
|
|
||
|
// reimplemented from ConnectionBase
|
||
|
virtual void getStatistics( long int& totalIn, long int& totalOut );
|
||
|
|
||
|
// reimplemented from ConnectionDataHandler
|
||
|
virtual void handleReceivedData( const ConnectionBase* connection, const std::string& data );
|
||
|
|
||
|
// reimplemented from ConnectionDataHandler
|
||
|
virtual void handleConnect( const ConnectionBase* connection );
|
||
|
|
||
|
// reimplemented from ConnectionDataHandler
|
||
|
virtual void handleDisconnect( const ConnectionBase* connection, ConnectionError reason );
|
||
|
|
||
|
// reimplemented from ConnectionDataHandler
|
||
|
virtual ConnectionBase* newInstance() const;
|
||
|
|
||
|
// reimplemented from TagHandler
|
||
|
virtual void handleTag( Tag* tag );
|
||
|
|
||
|
private:
|
||
|
ConnectionBOSH& operator=( const ConnectionBOSH& );
|
||
|
void initInstance( ConnectionBase* connection, const std::string& xmppServer, const int xmppPort );
|
||
|
bool sendRequest( const std::string& xml );
|
||
|
bool sendXML();
|
||
|
const std::string getHTTPField( const std::string& field );
|
||
|
ConnectionBase* getConnection();
|
||
|
ConnectionBase* activateConnection();
|
||
|
void putConnection();
|
||
|
|
||
|
//ConnectionBase *m_connection;
|
||
|
const LogSink& m_logInstance;
|
||
|
|
||
|
Parser m_parser; // Used for parsing XML section of responses
|
||
|
std::string m_boshHost; // The hostname of the BOSH connection manager
|
||
|
std::string m_boshedHost; // The hostname of the BOSH connection manager + : + port
|
||
|
std::string m_path; // The path part of the URL that we need to request
|
||
|
|
||
|
// BOSH parameters
|
||
|
unsigned long m_rid;
|
||
|
std::string m_sid;
|
||
|
|
||
|
bool m_initialStreamSent;
|
||
|
int m_openRequests;
|
||
|
int m_maxOpenRequests;
|
||
|
int m_wait;
|
||
|
int m_hold;
|
||
|
|
||
|
bool m_streamRestart; // Set to true if we are waiting for an acknowledgement of a stream restart
|
||
|
|
||
|
time_t m_lastRequestTime;
|
||
|
unsigned long m_minTimePerRequest;
|
||
|
|
||
|
std::string m_buffer; // Buffer of received data
|
||
|
std::string m_bufferHeader; // HTTP header of data currently in buffer // FIXME doens't need to be member
|
||
|
std::string::size_type m_bufferContentLength; // Length of the data in the current response
|
||
|
|
||
|
std::string m_sendBuffer; // Data waiting to be sent
|
||
|
|
||
|
typedef std::list<ConnectionBase*> ConnectionList;
|
||
|
ConnectionList m_activeConnections;
|
||
|
ConnectionList m_connectionPool;
|
||
|
ConnMode m_connMode;
|
||
|
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif // CONNECTIONBOSH_H__
|