00001
00002
00003 #include "ace/INet/HTTP_SessionBase.h"
00004
00005 #if !defined (__ACE_INLINE__)
00006 #include "ace/INet/HTTP_SessionBase.inl"
00007 #endif
00008
00009 #include "ace/INet/INet_Log.h"
00010 #include "ace/INet/HTTP_StreamPolicy.h"
00011 #include "ace/INet/String_IOStream.h"
00012 #include "ace/INet/IOS_util.h"
00013 #include "ace/INet/HTTP_URL.h"
00014 #include "ace/INET_Addr.h"
00015 #include "ace/String_Base.h"
00016 #include <istream>
00017 #include <ostream>
00018
00019 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00020
00021 namespace ACE
00022 {
00023 namespace HTTP
00024 {
00025
00026 SessionBase::SessionBase (u_short port, bool keep_alive)
00027 : port_ (port),
00028 reactive_ (false),
00029 in_stream_ (0),
00030 out_stream_ (0),
00031 http_timeout_ (DEFAULT_TIMEOUT),
00032 keep_alive_timeout_ (DEFAULT_KEEP_ALIVE_TIMEOUT),
00033 reconnect_timer_ (DEFAULT_KEEP_ALIVE_TIMEOUT),
00034 reconnect_countdown_ (&reconnect_timer_),
00035 keep_alive_ (keep_alive),
00036 needs_reconnect_ (false),
00037 cannot_reconnect_ (false),
00038 expects_response_body_ (false)
00039 {
00040 INET_TRACE ("ACE_HTTP_SessionBase - ctor");
00041 }
00042
00043 SessionBase::SessionBase (u_short port,
00044 const ACE_Time_Value& timeout,
00045 bool keep_alive,
00046 const ACE_Time_Value* alive_timeout)
00047 : port_ (port),
00048 reactive_ (false),
00049 in_stream_ (0),
00050 out_stream_ (0),
00051 http_timeout_ (timeout),
00052 keep_alive_timeout_ (DEFAULT_KEEP_ALIVE_TIMEOUT),
00053 reconnect_timer_ (DEFAULT_KEEP_ALIVE_TIMEOUT),
00054 reconnect_countdown_ (&reconnect_timer_),
00055 keep_alive_ (keep_alive),
00056 needs_reconnect_ (false),
00057 cannot_reconnect_ (false),
00058 expects_response_body_ (false)
00059 {
00060 INET_TRACE ("ACE_HTTP_SessionBase - ctor");
00061 if (keep_alive && alive_timeout)
00062 {
00063 this->keep_alive_timeout_ = *alive_timeout;
00064 }
00065 }
00066
00067 SessionBase::~SessionBase ()
00068 {
00069 INET_TRACE ("ACE_HTTP_SessionBase - dtor");
00070 this->close_streams ();
00071 }
00072
00073 bool SessionBase::connect (bool use_reactor)
00074 {
00075 INET_TRACE ("ACE_HTTP_SessionBase::connect");
00076
00077 this->close ();
00078
00079 unsigned long f_reactor = use_reactor ? ACE_Synch_Options::USE_REACTOR : 0;
00080 ACE_Synch_Options sync_opt (ACE_Synch_Options::USE_TIMEOUT | f_reactor,
00081 this->http_timeout_);
00082
00083 return this->connect_i (sync_opt);
00084 }
00085
00086 std::ostream& SessionBase::send_request (Request& request)
00087 {
00088 INET_TRACE ("ACE_HTTP_SessionBase::send_request");
00089
00090 if (this->in_stream_)
00091 {
00092 delete this->in_stream_;
00093 this->in_stream_ = 0;
00094 }
00095
00096 bool keep_alive = this->keep_alive ();
00097 if ((this->is_connected () && !keep_alive) || this->reconnect_needed ())
00098 {
00099 close();
00100 this->needs_reconnect_ = false;
00101 }
00102
00103 if (this->out_stream_)
00104 {
00105 delete this->out_stream_;
00106 this->out_stream_ = 0;
00107 }
00108
00109 if (!this->is_connected ())
00110 {
00111 if (this->cannot_reconnect_ || !this->connect(this->reactive_))
00112 {
00113 if (!this->cannot_reconnect_)
00114 INET_ERROR (1, (LM_ERROR, DLINFO
00115 ACE_TEXT ("(%d) HTTP_SessionBase::send_request - ")
00116 ACE_TEXT ("reconnect failed\n"),
00117 ACE_OS::last_error ()));
00118 return ACE::IOS::Null::out_stream_;
00119 }
00120 }
00121 if (!keep_alive)
00122 request.set_keep_alive (false);
00123 if (!request.has_host ())
00124 {
00125 if (this->port_ == URL::HTTP_PORT)
00126 request.set_host (this->host_);
00127 else
00128 request.set_host (this->host_, this->port_);
00129 }
00130
00131 this->expects_response_body_ = request.get_method() != Request::HTTP_HEAD;
00132
00133 if (request.has_chunked_transfer_encoding ())
00134 {
00135 request.write (this->sock_stream ());
00136 ChunkedTransferStreamPolicy* pol;
00137 ACE_NEW_RETURN (pol,
00138 ChunkedTransferStreamPolicy (),
00139 ACE::IOS::Null::out_stream_);
00140 ACE_NEW_RETURN (this->out_stream_,
00141 OStream (this->sock_stream (), pol),
00142 ACE::IOS::Null::out_stream_);
00143 }
00144 else if (request.get_content_length () != Header::UNKNOWN_CONTENT_LENGTH)
00145 {
00146 ACE::IOS::CString_OStream cs;
00147 request.write (cs);
00148 FixedLengthStreamPolicy* pol;
00149 ACE_NEW_RETURN (pol,
00150 FixedLengthStreamPolicy (cs.str ().length () + request.get_content_length ()),
00151 ACE::IOS::Null::out_stream_);
00152 ACE_NEW_RETURN (this->out_stream_,
00153 OStream (this->sock_stream (), pol),
00154 ACE::IOS::Null::out_stream_);
00155 (*this->out_stream_) << cs.str ().c_str ();
00156 }
00157 else if (request.get_method () != Request::HTTP_PUT && request.get_method() != Request::HTTP_POST)
00158 {
00159 ACE::IOS::CString_OStream cs;
00160 request.write (cs);
00161 FixedLengthStreamPolicy* pol;
00162 ACE_NEW_RETURN (pol,
00163 FixedLengthStreamPolicy (cs.str ().length ()),
00164 ACE::IOS::Null::out_stream_);
00165 ACE_NEW_RETURN (this->out_stream_,
00166 OStream (this->sock_stream (), pol),
00167 ACE::IOS::Null::out_stream_);
00168 (*this->out_stream_) << cs.str ().c_str ();
00169 }
00170 else
00171 {
00172 ACE_NEW_RETURN (this->out_stream_,
00173 OStream (this->sock_stream ()),
00174 ACE::IOS::Null::out_stream_);
00175 request.write (*this->out_stream_);
00176 }
00177
00178 this->reconnect_timer_ = this->keep_alive_timeout_;
00179 this->reconnect_countdown_.start ();
00180
00181 return *this->out_stream_;
00182 }
00183
00184 std::ostream& SessionBase::request_stream ()
00185 {
00186 if (this->out_stream_)
00187 return *this->out_stream_;
00188 else
00189 return ACE::IOS::Null::out_stream_;
00190 }
00191
00192 std::ostream& SessionBase::request_stream (
00193 ACE::IOS::StreamInterceptor& interceptor)
00194 {
00195 if (this->out_stream_)
00196 {
00197 this->out_stream_->set_interceptor (interceptor);
00198 return *this->out_stream_;
00199 }
00200 else
00201 return ACE::IOS::Null::out_stream_;
00202 }
00203
00204 std::istream& SessionBase::receive_response (Response& response)
00205 {
00206 INET_TRACE ("ACE_HTTP_SessionBase::receive_response");
00207
00208 if (this->in_stream_)
00209 {
00210 INET_ERROR (1, (LM_ERROR, DLINFO
00211 ACE_TEXT ("HTTP_Session::receive_response - ")
00212 ACE_TEXT ("invalid invocation without send_request\n")));
00213
00214
00215 return ACE::IOS::Null::in_stream_;
00216 }
00217
00218 if (this->out_stream_)
00219 {
00220 delete this->out_stream_;
00221 this->out_stream_ = 0;
00222 }
00223
00224 this->sock_stream ().flush ();
00225
00226 do
00227 {
00228 response.clear ();
00229 if (!response.read (this->sock_stream ()))
00230 {
00231 INET_ERROR (1, (LM_ERROR, DLINFO
00232 ACE_TEXT ("(%d) HTTP_Session::receive_response - ")
00233 ACE_TEXT ("failed to read response\n"),
00234 ACE_OS::last_error ()));
00235 return ACE::IOS::Null::in_stream_;
00236 }
00237 }
00238 while (response.get_status ().get_status() == Status::HTTP_CONTINUE);
00239
00240 this->needs_reconnect_ = this->keep_alive () && !response.has_keep_alive ();
00241
00242 if (!this->expects_response_body_)
00243 {
00244 FixedLengthStreamPolicy* pol;
00245 ACE_NEW_RETURN (pol,
00246 FixedLengthStreamPolicy (0),
00247 ACE::IOS::Null::in_stream_);
00248 ACE_NEW_RETURN (this->in_stream_,
00249 IStream (this->sock_stream (), pol),
00250 ACE::IOS::Null::in_stream_);
00251 }
00252 else if (response.has_chunked_transfer_encoding ())
00253 {
00254 ChunkedTransferStreamPolicy* pol;
00255 ACE_NEW_RETURN (pol,
00256 ChunkedTransferStreamPolicy (),
00257 ACE::IOS::Null::in_stream_);
00258 ACE_NEW_RETURN (this->in_stream_,
00259 IStream (this->sock_stream (), pol),
00260 ACE::IOS::Null::in_stream_);
00261 }
00262 else if (response.get_content_length () != Header::UNKNOWN_CONTENT_LENGTH)
00263 {
00264 FixedLengthStreamPolicy* pol;
00265 ACE_NEW_RETURN (pol,
00266 FixedLengthStreamPolicy (response.get_content_length ()),
00267 ACE::IOS::Null::in_stream_);
00268 ACE_NEW_RETURN (this->in_stream_,
00269 IStream (this->sock_stream (), pol),
00270 ACE::IOS::Null::in_stream_);
00271 }
00272 else
00273 {
00274 ACE_NEW_RETURN (this->in_stream_,
00275 IStream (this->sock_stream ()),
00276 ACE::IOS::Null::in_stream_);
00277 }
00278
00279 return *this->in_stream_;
00280 }
00281
00282 std::istream& SessionBase::response_stream ()
00283 {
00284 if (this->in_stream_)
00285 return *this->in_stream_;
00286 else
00287 return ACE::IOS::Null::in_stream_;
00288 }
00289
00290 std::istream& SessionBase::response_stream (
00291 ACE::IOS::StreamInterceptor& interceptor)
00292 {
00293 if (this->in_stream_)
00294 {
00295 this->in_stream_->set_interceptor (interceptor);
00296 return *this->in_stream_;
00297 }
00298 else
00299 return ACE::IOS::Null::in_stream_;
00300 }
00301
00302 void SessionBase::close ()
00303 {
00304 INET_TRACE ("ACE_HTTP_SessionBase::close");
00305
00306 this->close_streams ();
00307
00308 this->close_i ();
00309 }
00310
00311 }
00312 }
00313
00314 ACE_END_VERSIONED_NAMESPACE_DECL