Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / ACE / protocols / ace / INet / HTTPS_Session.cpp
bloba92d4a054cb6fb16ecbc073413c08047831ddfec
1 #ifndef ACE_HTTPS_SESSION_CPP
2 #define ACE_HTTPS_SESSION_CPP
4 #include "ace/INet/HTTPS_Session.h"
5 #include "ace/INet/INet_Log.h"
6 #include "ace/INet/IOS_util.h"
7 #include "ace/INet/HTTPS_URL.h"
8 #include "ace/INet/Sock_IOStream.h"
9 #include "ace/INet/String_IOStream.h"
10 #include "ace/INet/SSL_Proxy_Connector.h"
11 #include "ace/INET_Addr.h"
12 #include "ace/Event_Handler.h"
13 #include "ace/Connector.h"
14 #include "ace/SSL/SSL_SOCK_Connector.h"
15 #include "ace/String_Base.h"
16 #include <istream>
17 #include <ostream>
19 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
21 namespace ACE
23 namespace HTTPS
25 template <ACE_SYNCH_DECL>
26 Session_T<ACE_SYNCH_USE>::Session_T (bool keep_alive
27 #if defined (SSL_HAS_SSL_set_SSL_CTX) && (SSL_HAS_SSL_set_SSL_CTX == 1)
28 , Context* ctx
29 #endif
31 : SessionBase (URL::HTTPS_PORT, keep_alive),
32 connection_ (0),
33 sock_stream_ (0)
34 #if defined (SSL_HAS_SSL_set_SSL_CTX) && (SSL_HAS_SSL_set_SSL_CTX == 1)
35 , context_ (ctx)
36 #endif
38 INET_TRACE ("ACE_HTTPS_Session - ctor");
41 template <ACE_SYNCH_DECL>
42 Session_T<ACE_SYNCH_USE>::Session_T (const ACE_Time_Value& timeout,
43 bool keep_alive,
44 const ACE_Time_Value* alive_timeout
45 #if defined (SSL_HAS_SSL_set_SSL_CTX) && (SSL_HAS_SSL_set_SSL_CTX == 1)
46 , Context* ctx
47 #endif
49 : SessionBase (URL::HTTPS_PORT, timeout, keep_alive, alive_timeout),
50 connection_ (0),
51 sock_stream_ (0)
52 #if defined (SSL_HAS_SSL_set_SSL_CTX) && (SSL_HAS_SSL_set_SSL_CTX == 1)
53 , context_ (ctx)
54 #endif
56 INET_TRACE ("ACE_HTTPS_Session - ctor");
57 this->close_streams ();
58 this->close_connection ();
61 template <ACE_SYNCH_DECL>
62 Session_T<ACE_SYNCH_USE>::~Session_T ()
64 INET_TRACE ("ACE_HTTPS_Session - dtor");
67 template <ACE_SYNCH_DECL>
68 bool Session_T<ACE_SYNCH_USE>::is_connected () const
70 return this->connection_ && this->connection_->is_connected ();
73 template <ACE_SYNCH_DECL>
74 bool Session_T<ACE_SYNCH_USE>::connect_i (const ACE_Synch_Options& sync_opt)
76 INET_TRACE ("ACE_HTTPS_Session::connect_i");
78 connection_type* new_connection = 0;
80 if (this->is_proxy_connection ())
82 typedef ACE::IOS::StreamHandler<ACE_SOCK_STREAM, ACE_SYNCH_USE> proxy_connection_type;
83 typedef ACE_Connector<proxy_connection_type, ACE_SOCK_CONNECTOR> proxy_connector_type;
84 typedef ACE::IOS::Sock_IOStreamBase<ACE_SYNCH_USE> proxy_stream_type;
86 proxy_connection_type proxy_connection(sync_opt);
87 proxy_connector_type proxy_connector;
89 proxy_connection_type* proxy_connection_ptr = &proxy_connection;
90 if (proxy_connector.connect (proxy_connection_ptr,
91 ACE_INET_Addr (this->port_,
92 this->host_.c_str ()),
93 ACE_Synch_Options (0,this->http_timeout_)) == -1)
95 INET_ERROR (1, (LM_ERROR, DLINFO
96 ACE_TEXT ("(%d) ACE_HTTPS_Session::connect_i - ")
97 ACE_TEXT ("failed to connect to proxy; host=%C, port=%d\n"),
98 ACE_OS::last_error (), this->host_.c_str (), this->port_));
99 return false;
102 proxy_stream_type proxy_stream (&proxy_connection);
103 ACE::IOS::CString_OStream target_address;
104 target_address << this->proxy_target_host_ << ':' << this->proxy_target_port_;
105 ACE::HTTP::Request connect_request (ACE::HTTP::Request::HTTP_CONNECT,
106 target_address.str ().c_str (),
107 ACE::HTTP::Request::HTTP_1_1);
108 connect_request.set("Proxy-Connection", "keep-alive");
109 connect_request.set_host(this->proxy_target_host_);
110 ACE::HTTP::Response connect_response;
112 connect_request.write (proxy_stream);
113 proxy_stream.flush ();
114 if (!connect_response.read (proxy_stream) ||
115 !connect_response.get_status ().is_ok ())
117 INET_ERROR (1, (LM_ERROR, DLINFO
118 ACE_TEXT ("ACE_HTTPS_Session::connect_i - ")
119 ACE_TEXT ("cannot setup proxy tunnel; proxy replied: %d:%C\n"),
120 connect_response.get_status ().get_status(),
121 connect_response.get_status ().get_reason().c_str ()));
122 return false;
125 ACE_NEW_RETURN (new_connection,
126 connection_type(sync_opt),
127 false);
128 #if defined (SSL_HAS_SSL_set_SSL_CTX) && (SSL_HAS_SSL_set_SSL_CTX == 1)
129 // set the provided SSL context for the SSL structure of the SSL_SOCK_Stream
130 if (this->context_ != 0)
132 ::SSL * ssl_ptr = new_connection->peer ().ssl ();
133 ::SSL_set_SSL_CTX (ssl_ptr, this->context_->ssl_context ().context ());
135 #endif
136 ACE_HANDLE proxy_conn_handle = proxy_connection.peer ().get_handle ();
137 proxy_connection.peer ().set_handle (ACE_INVALID_HANDLE);
139 ACE::INet::SSL_Proxy_Connector proxy_ssl_connector;
140 ACE_Time_Value conn_timeout (this->http_timeout_);
141 if (proxy_ssl_connector.connect (new_connection->peer (),
142 proxy_conn_handle,
143 &conn_timeout) != 0)
145 INET_ERROR (1, (LM_ERROR, DLINFO
146 ACE_TEXT ("ACE_HTTPS_Session::connect_i - ")
147 ACE_TEXT ("failed to setup proxy SSL connection\n")));
148 return false;
150 new_connection->open (); // mark stream handler as connected
152 else
154 ACE_NEW_RETURN (new_connection,
155 connection_type(sync_opt),
156 false);
157 #if defined (SSL_HAS_SSL_set_SSL_CTX) && (SSL_HAS_SSL_set_SSL_CTX == 1)
158 // set the provided SSL context for the SSL structure of the SSL_SOCK_Stream
159 if (this->context_ != 0)
161 ::SSL * ssl_ptr = new_connection->peer ().ssl ();
162 ::SSL_set_SSL_CTX (ssl_ptr, this->context_->ssl_context ().context ());
164 #endif
165 typedef ACE_Connector<connection_type, ACE_SSL_SOCK_Connector> connector_type;
167 connector_type connector;
169 if (connector.connect (new_connection,
170 ACE_INET_Addr (this->port_,
171 this->host_.c_str ()),
172 ACE_Synch_Options (0,this->http_timeout_)) == -1)
174 INET_ERROR (1, (LM_ERROR, DLINFO
175 ACE_TEXT ("(%d) ACE_HTTPS_Session::connect_i - ")
176 ACE_TEXT ("failed to connect; host=%C, port=%d\n"),
177 ACE_OS::last_error (), this->host_.c_str (), this->port_));
178 // as the connection was dynamically allocated
179 // the connector causes it to be destroyed after
180 // the connection failure
181 return false;
185 this->connection_ = new_connection;
186 this->connection_->reference_counting_policy ().value (
187 ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
189 ACE_NEW_NORETURN (this->sock_stream_,
190 sock_stream_type (this->connection_));
191 if (this->sock_stream_)
193 this->cannot_reconnect_ = false;
194 this->reactive_ = sync_opt[ACE_Synch_Options::USE_REACTOR];
196 // reset reconnect timer
197 this->reconnect_timer_ = this->keep_alive_timeout_;
198 this->reconnect_countdown_.start ();
200 return true;
202 else
204 this->close ();
205 return false;
209 template <ACE_SYNCH_DECL>
210 bool Session_T<ACE_SYNCH_USE>::attach_connection (connection_type* connection)
212 INET_TRACE ("ACE_HTTPS_Session::attach_connection");
214 if (!connection->is_connected ())
215 return false;
217 this->close ();
219 ACE_INET_Addr remote;
220 connection->peer ().get_remote_addr (remote);
221 this->host_ = remote.get_host_name ();
222 this->port_ = remote.get_port_number ();
224 this->connection_ = connection;
225 this->connection_->add_reference ();
227 ACE_NEW_NORETURN (this->sock_stream_,
228 sock_stream_type (this->connection_));
230 if (this->sock_stream_)
232 this->keep_alive_ = true;
233 this->keep_alive_timeout_ = ACE_Time_Value::zero;
234 this->cannot_reconnect_ = true;
235 return true;
237 else
239 this->close ();
240 return false;
244 template <ACE_SYNCH_DECL>
245 void Session_T<ACE_SYNCH_USE>::close_connection ()
247 if (this->sock_stream_)
249 delete this->sock_stream_;
250 this->sock_stream_ = 0;
253 if (this->connection_)
255 // this should be the last referece and removing it
256 // causes the connection to be destroyed
257 this->connection_->remove_reference ();
258 this->connection_ = 0;
262 template <ACE_SYNCH_DECL>
263 void Session_T<ACE_SYNCH_USE>::close_i ()
265 INET_TRACE ("ACE_HTTPS_Session::close_i");
267 this->close_connection ();
270 template <ACE_SYNCH_DECL>
271 std::iostream& Session_T<ACE_SYNCH_USE>::sock_stream ()
273 return *this->sock_stream_;
279 ACE_END_VERSIONED_NAMESPACE_DECL
281 #endif /* ACE_HTTPS_SESSION_CPP */