gloox  1.0.28
connectionhttpproxy.cpp
1 /*
2  Copyright (c) 2004-2023 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 
14 
15 #include "gloox.h"
16 
17 #include "connectionhttpproxy.h"
18 #include "dns.h"
19 #include "logsink.h"
20 #include "prep.h"
21 #include "base64.h"
22 #include "util.h"
23 
24 #include <string>
25 
26 namespace gloox
27 {
28 
30  const LogSink& logInstance,
31  const std::string& server, int port )
32  : ConnectionBase( 0 ), m_connection( connection ),
33  m_logInstance( logInstance ), m_http11( false )
34  {
35 // FIXME check return value?
37  m_port = port;
38 
39  if( m_connection )
40  m_connection->registerConnectionDataHandler( this );
41  }
42 
44  ConnectionBase* connection,
45  const LogSink& logInstance,
46  const std::string& server, int port )
47  : ConnectionBase( cdh ), m_connection( connection ),
48  m_logInstance( logInstance )
49  {
50 // FIXME check return value?
52  m_port = port;
53 
54  if( m_connection )
55  m_connection->registerConnectionDataHandler( this );
56  }
57 
59  {
60  delete m_connection;
61  }
62 
64  {
65  ConnectionBase* conn = m_connection ? m_connection->newInstance() : 0;
66  return new ConnectionHTTPProxy( m_handler, conn, m_logInstance, m_server, m_port );
67  }
68 
70  {
71  if( m_connection )
72  delete m_connection;
73 
74  m_connection = connection;
75  }
76 
78  {
79  if( m_connection && m_handler )
80  {
82  return m_connection->connect();
83  }
84 
85  return ConnNotConnected;
86  }
87 
89  {
91  if( m_connection )
92  m_connection->disconnect();
93  }
94 
96  {
97  return m_connection ? m_connection->recv( timeout ) : ConnNotConnected;
98  }
99 
101  {
102  return m_connection ? m_connection->receive() : ConnNotConnected;
103  }
104 
105  bool ConnectionHTTPProxy::send( const std::string& data )
106  {
107  return m_connection && m_connection->send( data );
108  }
109 
111  {
113 
114  if( m_connection )
115  m_connection->cleanup();
116  }
117 
118  void ConnectionHTTPProxy::getStatistics( long int& totalIn, long int& totalOut )
119  {
120  if( m_connection )
121  m_connection->getStatistics( totalIn, totalOut );
122  else
123  totalIn = totalOut = 0;
124  }
125 
127  const std::string& data )
128  {
129  if( !m_handler )
130  return;
131 
132  if( m_state == StateConnecting )
133  {
134  m_proxyHandshakeBuffer += data;
135  if( ( !m_proxyHandshakeBuffer.compare( 0, 12, "HTTP/1.0 200" )
136  || !m_proxyHandshakeBuffer.compare( 0, 12, "HTTP/1.1 200" ) )
137  && !m_proxyHandshakeBuffer.compare( m_proxyHandshakeBuffer.length() - 4, 4, "\r\n\r\n" ) )
138  {
139  m_proxyHandshakeBuffer = EmptyString;
141  m_logInstance.dbg( LogAreaClassConnectionHTTPProxy,
142  "HTTP proxy connection established" );
143  m_handler->handleConnect( this );
144  }
145  else if( !m_proxyHandshakeBuffer.compare( 9, 3, "407" ) )
146  {
148  m_connection->disconnect();
149  }
150  else if( !m_proxyHandshakeBuffer.compare( 9, 3, "403" )
151  || !m_proxyHandshakeBuffer.compare( 9, 3, "404" ) )
152  {
154  m_connection->disconnect();
155  }
156  }
157  else if( m_state == StateConnected )
158  m_handler->handleReceivedData( this, data );
159  }
160 
162  {
163  if( m_connection )
164  {
165  std::string server = m_server;
166  int port = m_port;
167  if( port == -1 )
168  {
169  const DNS::HostMap& servers = DNS::resolve( m_server, m_logInstance );
170  if( !servers.empty() )
171  {
172  const std::pair< std::string, int >& host = *servers.begin();
173  server = host.first;
174  port = host.second;
175  }
176  }
177  std::string message = "Requesting HTTP proxy connection to " + server + ":"
178  + util::int2string( port );
179  m_logInstance.dbg( LogAreaClassConnectionHTTPProxy, message );
180 
181  std::string os = "CONNECT " + server + ":" + util::int2string( port ) + " HTTP/1."
182  + util::int2string( m_http11 ? 1 : 0 ) + "\r\n"
183  "Host: " + server + "\r\n"
184  "Content-Length: 0\r\n"
185  "Proxy-Connection: Keep-Alive\r\n"
186  "Pragma: no-cache\r\n"
187  "User-Agent: gloox/" + GLOOX_VERSION + "\r\n";
188 
189  if( !m_proxyUser.empty() && !m_proxyPwd.empty() )
190  {
191  os += "Proxy-Authorization: Basic " + Base64::encode64( m_proxyUser + ":" + m_proxyPwd )
192  + "\r\n";
193  }
194  os += "\r\n";
195 
196  if( !m_connection->send( os ) )
197  {
199  if( m_handler )
201  }
202  }
203  }
204 
206  ConnectionError reason )
207  {
209  m_logInstance.dbg( LogAreaClassConnectionHTTPProxy, "HTTP Proxy connection closed" );
210 
211  if( m_handler )
212  m_handler->handleDisconnect( this, reason );
213  }
214 
215 }
An abstract base class for a connection.
virtual void cleanup()
const std::string & server() const
ConnectionState m_state
virtual ConnectionError recv(int timeout=-1)=0
virtual bool send(const std::string &data)=0
ConnectionDataHandler * m_handler
virtual ConnectionError connect()=0
virtual ConnectionError receive()=0
virtual void getStatistics(long int &totalIn, long int &totalOut)=0
virtual void disconnect()=0
virtual ConnectionBase * newInstance() const =0
void registerConnectionDataHandler(ConnectionDataHandler *cdh)
This is an abstract base class to receive events from a ConnectionBase-derived object.
virtual void handleReceivedData(const ConnectionBase *connection, const std::string &data)=0
virtual void handleDisconnect(const ConnectionBase *connection, ConnectionError reason)=0
virtual void handleConnect(const ConnectionBase *connection)=0
virtual void handleDisconnect(const ConnectionBase *connection, ConnectionError reason)
virtual ConnectionError recv(int timeout=-1)
virtual void handleConnect(const ConnectionBase *connection)
virtual void handleReceivedData(const ConnectionBase *connection, const std::string &data)
virtual ConnectionBase * newInstance() const
virtual ConnectionError connect()
void setConnectionImpl(ConnectionBase *connection)
virtual bool send(const std::string &data)
ConnectionHTTPProxy(ConnectionBase *connection, const LogSink &logInstance, const std::string &server, int port=-1)
virtual ConnectionError receive()
virtual void getStatistics(long int &totalIn, long int &totalOut)
static HostMap resolve(const std::string &service, const std::string &proto, const std::string &domain, const LogSink &logInstance)
Definition: dns.cpp:83
std::map< std::string, int > HostMap
Definition: dns.h:68
An implementation of log sink and source.
Definition: logsink.h:39
void dbg(LogArea area, const std::string &message) const
Definition: logsink.h:66
const std::string encode64(const std::string &input)
Definition: base64.cpp:38
bool idna(const std::string &domain, std::string &out)
Definition: prep.cpp:107
The namespace for the gloox library.
Definition: adhoc.cpp:28
const std::string GLOOX_VERSION
Definition: gloox.cpp:119
ConnectionError
Definition: gloox.h:684
@ ConnNotConnected
Definition: gloox.h:715
@ ConnProxyAuthFailed
Definition: gloox.h:692
@ ConnProxyAuthRequired
Definition: gloox.h:690
@ ConnIoError
Definition: gloox.h:696
@ LogAreaClassConnectionHTTPProxy
Definition: gloox.h:1060
const std::string EmptyString
Definition: gloox.cpp:124
@ StateDisconnected
Definition: gloox.h:642
@ StateConnected
Definition: gloox.h:644
@ StateConnecting
Definition: gloox.h:643