Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / ACE / protocols / ace / INet / HTTP_SessionBase.cpp
blob0248382bb0d266766e8183cf5decb95a7c76d806
1 #include "ace/INet/HTTP_SessionBase.h"
3 #if !defined (__ACE_INLINE__)
4 #include "ace/INet/HTTP_SessionBase.inl"
5 #endif
7 #include "ace/INet/INet_Log.h"
8 #include "ace/INet/HTTP_StreamPolicy.h"
9 #include "ace/INet/String_IOStream.h"
10 #include "ace/INet/IOS_util.h"
11 #include "ace/INet/HTTP_URL.h"
12 #include "ace/INET_Addr.h"
13 #include "ace/String_Base.h"
14 #include <istream>
15 #include <ostream>
17 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
19 namespace ACE
21 namespace HTTP
23 SessionBase::SessionBase (u_short port, bool keep_alive)
24 : port_ (port),
25 reactive_ (false),
26 in_stream_ (0),
27 out_stream_ (0),
28 http_timeout_ (DEFAULT_TIMEOUT),
29 keep_alive_timeout_ (DEFAULT_KEEP_ALIVE_TIMEOUT),
30 reconnect_timer_ (DEFAULT_KEEP_ALIVE_TIMEOUT),
31 reconnect_countdown_ (&reconnect_timer_),
32 keep_alive_ (keep_alive),
33 needs_reconnect_ (false),
34 cannot_reconnect_ (false),
35 expects_response_body_ (false)
37 INET_TRACE ("ACE_HTTP_SessionBase - ctor");
40 SessionBase::SessionBase (u_short port,
41 const ACE_Time_Value& timeout,
42 bool keep_alive,
43 const ACE_Time_Value* alive_timeout)
44 : port_ (port),
45 reactive_ (false),
46 in_stream_ (0),
47 out_stream_ (0),
48 http_timeout_ (timeout),
49 keep_alive_timeout_ (DEFAULT_KEEP_ALIVE_TIMEOUT),
50 reconnect_timer_ (DEFAULT_KEEP_ALIVE_TIMEOUT),
51 reconnect_countdown_ (&reconnect_timer_),
52 keep_alive_ (keep_alive),
53 needs_reconnect_ (false),
54 cannot_reconnect_ (false),
55 expects_response_body_ (false)
57 INET_TRACE ("ACE_HTTP_SessionBase - ctor");
58 if (keep_alive && alive_timeout)
60 this->keep_alive_timeout_ = *alive_timeout;
64 SessionBase::~SessionBase ()
66 INET_TRACE ("ACE_HTTP_SessionBase - dtor");
67 this->close_streams ();
70 bool SessionBase::connect (bool use_reactor)
72 INET_TRACE ("ACE_HTTP_SessionBase::connect");
74 this->close ();
76 unsigned long f_reactor = use_reactor ? ACE_Synch_Options::USE_REACTOR : 0;
77 ACE_Synch_Options sync_opt (ACE_Synch_Options::USE_TIMEOUT | f_reactor,
78 this->http_timeout_);
80 return this->connect_i (sync_opt);
83 std::ostream& SessionBase::send_request (Request& request)
85 INET_TRACE ("ACE_HTTP_SessionBase::send_request");
87 if (this->in_stream_)
89 delete this->in_stream_;
90 this->in_stream_ = 0;
93 bool keep_alive = this->keep_alive ();
94 if ((this->is_connected () && !keep_alive) || this->reconnect_needed ())
96 close();
97 this->needs_reconnect_ = false;
100 if (this->out_stream_)
102 delete this->out_stream_;
103 this->out_stream_ = 0;
106 if (!this->is_connected ())
108 if (this->cannot_reconnect_ || !this->connect(this->reactive_))
110 if (!this->cannot_reconnect_)
111 INET_ERROR (1, (LM_ERROR, DLINFO
112 ACE_TEXT ("(%d) HTTP_SessionBase::send_request - ")
113 ACE_TEXT ("reconnect failed\n"),
114 ACE_OS::last_error ()));
115 return ACE::IOS::Null::out_stream_;
118 if (!keep_alive)
119 request.set_keep_alive (false);
120 if (!request.has_host ())
122 if (this->port_ == URL::HTTP_PORT)
123 request.set_host (this->host_);
124 else
125 request.set_host (this->host_, this->port_);
128 this->expects_response_body_ = request.get_method() != Request::HTTP_HEAD;
130 if (request.has_chunked_transfer_encoding ())
132 request.write (this->sock_stream ());
133 ChunkedTransferStreamPolicy* pol;
134 ACE_NEW_RETURN (pol,
135 ChunkedTransferStreamPolicy (),
136 ACE::IOS::Null::out_stream_);
137 ACE_NEW_RETURN (this->out_stream_,
138 OStream (this->sock_stream (), pol),
139 ACE::IOS::Null::out_stream_);
141 else if (request.get_content_length () != Header::UNKNOWN_CONTENT_LENGTH)
143 ACE::IOS::CString_OStream cs;
144 request.write (cs);
145 FixedLengthStreamPolicy* pol;
146 ACE_NEW_RETURN (pol,
147 FixedLengthStreamPolicy (cs.str ().length () + request.get_content_length ()),
148 ACE::IOS::Null::out_stream_);
149 ACE_NEW_RETURN (this->out_stream_,
150 OStream (this->sock_stream (), pol),
151 ACE::IOS::Null::out_stream_);
152 (*this->out_stream_) << cs.str ().c_str ();
154 else if (request.get_method () != Request::HTTP_PUT && request.get_method() != Request::HTTP_POST)
156 ACE::IOS::CString_OStream cs;
157 request.write (cs);
158 FixedLengthStreamPolicy* pol;
159 ACE_NEW_RETURN (pol,
160 FixedLengthStreamPolicy (cs.str ().length ()),
161 ACE::IOS::Null::out_stream_);
162 ACE_NEW_RETURN (this->out_stream_,
163 OStream (this->sock_stream (), pol),
164 ACE::IOS::Null::out_stream_);
165 (*this->out_stream_) << cs.str ().c_str ();
167 else
169 ACE_NEW_RETURN (this->out_stream_,
170 OStream (this->sock_stream ()),
171 ACE::IOS::Null::out_stream_);
172 request.write (*this->out_stream_);
174 // reset reconnect timer
175 this->reconnect_timer_ = this->keep_alive_timeout_;
176 this->reconnect_countdown_.start ();
178 return *this->out_stream_;
181 std::ostream& SessionBase::request_stream ()
183 if (this->out_stream_)
184 return *this->out_stream_;
185 else
186 return ACE::IOS::Null::out_stream_;
189 std::ostream& SessionBase::request_stream (
190 ACE::IOS::StreamInterceptor& interceptor)
192 if (this->out_stream_)
194 this->out_stream_->set_interceptor (interceptor);
195 return *this->out_stream_;
197 else
198 return ACE::IOS::Null::out_stream_;
201 std::istream& SessionBase::receive_response (Response& response)
203 INET_TRACE ("ACE_HTTP_SessionBase::receive_response");
205 if (this->in_stream_)
207 INET_ERROR (1, (LM_ERROR, DLINFO
208 ACE_TEXT ("HTTP_Session::receive_response - ")
209 ACE_TEXT ("invalid invocation without send_request\n")));
210 // receive_response called second time without
211 // new send_request in between
212 return ACE::IOS::Null::in_stream_;
215 if (this->out_stream_)
217 delete this->out_stream_;
218 this->out_stream_ = 0;
221 this->sock_stream ().flush ();
225 response.clear ();
226 if (!response.read (this->sock_stream ()))
228 INET_ERROR (1, (LM_ERROR, DLINFO
229 ACE_TEXT ("(%d) HTTP_Session::receive_response - ")
230 ACE_TEXT ("failed to read response\n"),
231 ACE_OS::last_error ()));
232 return ACE::IOS::Null::in_stream_;
235 while (response.get_status ().get_status() == Status::HTTP_CONTINUE);
237 this->needs_reconnect_ = this->keep_alive () && !response.has_keep_alive ();
239 if (!this->expects_response_body_)
241 FixedLengthStreamPolicy* pol;
242 ACE_NEW_RETURN (pol,
243 FixedLengthStreamPolicy (0),
244 ACE::IOS::Null::in_stream_);
245 ACE_NEW_RETURN (this->in_stream_,
246 IStream (this->sock_stream (), pol),
247 ACE::IOS::Null::in_stream_);
249 else if (response.has_chunked_transfer_encoding ())
251 ChunkedTransferStreamPolicy* pol;
252 ACE_NEW_RETURN (pol,
253 ChunkedTransferStreamPolicy (),
254 ACE::IOS::Null::in_stream_);
255 ACE_NEW_RETURN (this->in_stream_,
256 IStream (this->sock_stream (), pol),
257 ACE::IOS::Null::in_stream_);
259 else if (response.get_content_length () != Header::UNKNOWN_CONTENT_LENGTH)
261 FixedLengthStreamPolicy* pol;
262 ACE_NEW_RETURN (pol,
263 FixedLengthStreamPolicy (response.get_content_length ()),
264 ACE::IOS::Null::in_stream_);
265 ACE_NEW_RETURN (this->in_stream_,
266 IStream (this->sock_stream (), pol),
267 ACE::IOS::Null::in_stream_);
269 else
271 ACE_NEW_RETURN (this->in_stream_,
272 IStream (this->sock_stream ()),
273 ACE::IOS::Null::in_stream_);
276 return *this->in_stream_;
279 std::istream& SessionBase::response_stream ()
281 if (this->in_stream_)
282 return *this->in_stream_;
283 else
284 return ACE::IOS::Null::in_stream_;
287 std::istream& SessionBase::response_stream (
288 ACE::IOS::StreamInterceptor& interceptor)
290 if (this->in_stream_)
292 this->in_stream_->set_interceptor (interceptor);
293 return *this->in_stream_;
295 else
296 return ACE::IOS::Null::in_stream_;
299 void SessionBase::close ()
301 INET_TRACE ("ACE_HTTP_SessionBase::close");
303 this->close_streams ();
305 this->close_i ();
311 ACE_END_VERSIONED_NAMESPACE_DECL