Logo
~Sockets~
~Examples~
~Contact~


Ajp13Socket Class Reference

#include <Ajp13Socket.h>

Inheritance diagram for Ajp13Socket:
Collaboration diagram for Ajp13Socket:

List of all members.


Public Member Functions

 Ajp13Socket (ISocketHandler &h)
void OnHeader (short id, short len)
void OnPacket (const char *buf, size_t sz)
void Respond (const HttpResponse &res)
 Send response.
void OnTransferLimit ()
 This callback fires when the output buffer drops below the value set by SetTransferLimit.

Private Member Functions

void ReceiveBody (const char *buf, size_t sz)
void ReceiveForwardRequest (const char *buf, size_t sz)
void ReceiveShutdown (const char *buf, size_t sz)
void ReceivePing (const char *buf, size_t sz)
void ReceiveCPing (const char *buf, size_t sz)
void Execute ()

Private Attributes

size_t m_body_size_left
HttpRequest m_req
HttpResponse m_res

Detailed Description

Definition at line 46 of file Ajp13Socket.h.


Constructor & Destructor Documentation

Ajp13Socket::Ajp13Socket ( ISocketHandler h  ) 

Definition at line 53 of file Ajp13Socket.cpp.

00053                                           : AjpBaseSocket(h)
00054 , m_body_size_left(0)
00055 {
00056 }


Member Function Documentation

void Ajp13Socket::OnHeader ( short  id,
short  len 
) [virtual]

Implements AjpBaseSocket.

Definition at line 60 of file Ajp13Socket.cpp.

References DEB, and Socket::SetCloseAndDelete().

00061 {
00062         if (id != 0x1234)
00063         {
00064                 fprintf(stderr, "ABORT: bad packet id: %x\n", id);
00065                 SetCloseAndDelete();
00066         }
00067         else
00068         {
00069                 DEB(fprintf(stderr, "Packet size: %d bytes\n", len);)
00070         }
00071 }

void Ajp13Socket::OnPacket ( const char *  buf,
size_t  sz 
) [virtual]

Implements AjpBaseSocket.

Definition at line 379 of file Ajp13Socket.cpp.

References DEB, m_body_size_left, ReceiveBody(), ReceiveCPing(), ReceiveForwardRequest(), ReceivePing(), ReceiveShutdown(), and Socket::SetCloseAndDelete().

00380 {
00381         DEB(fprintf(stderr, "OnPacket: %d bytes, code 0x%02x %02x %02x %02x\n", sz, *buf, buf[1], buf[2], buf[3]);)
00382 
00383         // check body size left to read, if non-zero packet is body data
00384         if (m_body_size_left) // must be a body packet
00385         {
00386                 ReceiveBody(buf, sz);
00387                 return;
00388         }
00389         switch (*buf)
00390         {
00391         case 0x2: // Forward Request
00392                 ReceiveForwardRequest(buf, sz);
00393                 break;
00394         case 0x7: // Shutdown
00395                 ReceiveShutdown(buf, sz);
00396                 break;
00397         case 0x8: // Ping
00398                 ReceivePing(buf, sz);
00399                 break;
00400         case 0xa: // CPing
00401                 ReceiveCPing(buf, sz);
00402                 break;
00403         default:
00404                 fprintf(stderr, "Unknown packet type: 0x%02x\n", *buf);
00405                 SetCloseAndDelete();
00406         }
00407 
00408 }

void Ajp13Socket::Respond ( const HttpResponse res  )  [virtual]

Send response.

Implements IHttpServer.

Definition at line 258 of file Ajp13Socket.cpp.

References HttpTransaction::ContentLength(), HttpResponse::Cookie(), HttpResponse::CookieNames(), HttpResponse::GetFile(), HttpTransaction::Headers(), HttpResponse::HttpStatusCode(), HttpResponse::HttpStatusMsg(), Socket::Init(), m_res, OnTransferLimit(), AjpBaseSocket::put_byte(), AjpBaseSocket::put_integer(), AjpBaseSocket::put_string(), TcpSocket::SendBuf(), and IFile::size().

00259 {
00260         char msg[8192];
00261         msg[0] = 'A';
00262         msg[1] = 'B';
00263 
00264         m_res = res;
00265 
00266 // reply codes
00267 //      0x3 Send Body Chunk
00268 //      0x4 Send Headers
00269 //      0x5 End Response
00270 //      0x6 Get Body Chunk
00271 //      0x9 CPong Reply
00272 
00273         // check content length
00274         if (!m_res.ContentLength() && m_res.GetFile().size())
00275         {
00276 //              m_res.SetContentLength( m_res.GetFile().size() );
00277         }
00278 
00279         // Send Headers
00280         {
00281                 int ptr = 4;
00282                 put_byte(msg, ptr, 0x04); // send headers
00283                 put_integer(msg, ptr, m_res.HttpStatusCode() );
00284                 put_string(msg, ptr, m_res.HttpStatusMsg() );
00285                 put_integer(msg, ptr, (short)m_res.Headers().size() );
00286                 for (Utility::ncmap<std::string>::const_iterator it = m_res.Headers().begin(); it != m_res.Headers().end(); ++it)
00287                 {
00288                         Utility::ncmap<int>::const_iterator it2 = Init.ResponseHeader.find( it -> first );
00289                         if (it2 != Init.ResponseHeader.end())
00290                         {
00291                                 put_integer(msg, ptr, it2 -> second);
00292                         }
00293                         else
00294                         {
00295                                 put_string(msg, ptr, it -> first);
00296                         }
00297                         put_string(msg, ptr, it -> second);
00298                 }
00299                 std::list<std::string> vec = m_res.CookieNames();
00300                 {
00301                         for (std::list<std::string>::iterator it = vec.begin(); it != vec.end(); it++)
00302                         {
00303                                 Utility::ncmap<int>::const_iterator it2 = Init.ResponseHeader.find( "set-cookie" );
00304                                 if (it2 != Init.ResponseHeader.end())
00305                                 {
00306                                         put_integer(msg, ptr, it2 -> second);
00307                                 }
00308                                 else
00309                                 {
00310                                         put_string(msg, ptr, "set-cookie");
00311                                 }
00312                                 put_string(msg, ptr, m_res.Cookie(*it) );
00313                         }
00314                 }
00315 
00316                 short len = htons( ptr - 4 );
00317                 memcpy( msg + 2, &len, 2 );
00318 
00319                 SendBuf( msg, ptr );
00320         }
00321         // Send Body Chunk
00322         OnTransferLimit();
00323 }

void Ajp13Socket::OnTransferLimit (  )  [virtual]

This callback fires when the output buffer drops below the value set by SetTransferLimit.

Default: 0 (disabled).

Reimplemented from TcpSocket.

Definition at line 327 of file Ajp13Socket.cpp.

References IFile::fclose(), IFile::fread(), HttpResponse::GetFile(), TcpSocket::GetOutputLength(), m_res, IHttpServer::OnResponseComplete(), AjpBaseSocket::put_boolean(), AjpBaseSocket::put_byte(), AjpBaseSocket::put_integer(), TcpSocket::SendBuf(), and TcpSocket::SetTransferLimit().

Referenced by Respond().

00328 {
00329         char msg[8192];
00330         msg[0] = 'A';
00331         msg[1] = 'B';
00332 
00333         // Send Body Chunk
00334         size_t n = m_res.GetFile().fread(msg + 7, 1, 8100);
00335         while (n > 0)
00336         {
00337                 int ptr = 4;
00338                 put_byte(msg, ptr, 0x03); // send body chunk
00339                 put_integer(msg, ptr, (short)n);
00340                 ptr += (int)n;
00341 
00342                 short len = htons( ptr - 4 );
00343                 memcpy( msg + 2, &len, 2 );
00344 
00345                 SendBuf( msg, ptr );
00346                 if (GetOutputLength() > 1)
00347                 {
00348                         SetTransferLimit( 1 );
00349                         break;
00350                 }
00351 
00352                 //
00353                 n = m_res.GetFile().fread(msg + 7, 1, 8100);
00354         }
00355         if (!GetOutputLength()) // all body data sent and no data in output buffer - send end response
00356         {
00357                 // End Response
00358                 int ptr = 4;
00359                 put_byte(msg, ptr, 0x05); // end response
00360                 put_boolean(msg, ptr, false); // reuse
00361                 /*
00362                         don't reuse
00363                         - but with m_req.Reset() and m_res.Reset() it should be possible
00364                         - also reset any AjpBaseSocket/Ajp13Socket specific states
00365                 */
00366 
00367                 short len = htons( ptr - 4 );
00368                 memcpy( msg + 2, &len, 2 );
00369 
00370                 SendBuf( msg, ptr );
00371 
00372                 m_res.GetFile().fclose();
00373                 OnResponseComplete();
00374         }
00375 }

void Ajp13Socket::ReceiveBody ( const char *  buf,
size_t  sz 
) [private]

Definition at line 75 of file Ajp13Socket.cpp.

References HttpRequest::CloseBody(), Execute(), m_body_size_left, m_req, AjpBaseSocket::put_byte(), AjpBaseSocket::put_integer(), TcpSocket::SendBuf(), Socket::SetCloseAndDelete(), and HttpRequest::Write().

Referenced by OnPacket().

00076 {
00077         if (sz - 2 > m_body_size_left)
00078         {
00079                 fprintf(stderr, "More body data received than expected\n");
00080                 SetCloseAndDelete();
00081                 return;
00082         }
00083 
00084         m_req.Write( buf + 2, sz - 2 );
00085         m_body_size_left -= sz - 2;
00086 
00087         // request more body data
00088         if (m_body_size_left)
00089         {
00090                 int ptr = 4;
00091                 char msg[100];
00092                 msg[0] = 'A';
00093                 msg[1] = 'B';
00094 
00095 // reply codes
00096 //      0x3 Send Body Chunk
00097 //      0x4 Send Headers
00098 //      0x5 End Response
00099 //      0x6 Get Body Chunk      <------
00100 //      0x9 CPong Reply
00101 
00102                 put_byte(msg, ptr, 0x06); // GET_BODY_CHUNK;
00103                 put_integer(msg, ptr, 1000); // request 1000 bytes
00104 
00105                 short len = htons( ptr - 4 );
00106                 memcpy( msg + 2, &len, 2 );
00107 
00108                 SendBuf( msg, ptr );
00109                 return;
00110         }
00111 
00112         // Close
00113         m_req.CloseBody();
00114 
00115         // no more body data left to read - execute
00116         Execute();
00117 
00118 }

void Ajp13Socket::ReceiveForwardRequest ( const char *  buf,
size_t  sz 
) [private]

Definition at line 122 of file Ajp13Socket.cpp.

References HttpRequest::AddCookie(), HttpTransaction::ContentLength(), Execute(), AjpBaseSocket::get_boolean(), AjpBaseSocket::get_byte(), AjpBaseSocket::get_integer(), AjpBaseSocket::get_string(), Socket::Init(), HttpRequest::InitBody(), Utility::l2string(), m_body_size_left, m_req, HttpRequest::SetAttribute(), Socket::SetCloseAndDelete(), HttpTransaction::SetHeader(), HttpRequest::SetHttpMethod(), HttpRequest::SetHttpVersion(), HttpRequest::SetIsSsl(), HttpRequest::SetRemoteAddr(), HttpRequest::SetRemoteHost(), HttpRequest::SetServerName(), HttpRequest::SetServerPort(), HttpRequest::SetUri(), and Utility::ToLower().

Referenced by OnPacket().

00123 {
00124         //
00125         int ptr = 0;
00126 
00127         get_byte(buf, ptr); // skip first byte: prefix_code
00128         unsigned char method = get_byte(buf, ptr);
00129         std::string      protocol = get_string(buf, ptr);
00130         std::string      req_uri = get_string(buf, ptr);
00131         std::string      remote_addr = get_string(buf, ptr);
00132         std::string      remote_host = get_string(buf, ptr);
00133         std::string      server_name = get_string(buf, ptr);
00134         short                            server_port = get_integer(buf, ptr);
00135         bool                                    is_ssl = get_boolean(buf, ptr);
00136 
00137         std::string method_str = Utility::l2string( method );
00138         std::map<int, std::string>::const_iterator it = Init.Method.find( method );
00139         if (it != Init.Method.end())
00140         {
00141                 method_str = it -> second;
00142         }
00143         m_req.SetHttpMethod( method_str );
00144         m_req.SetHttpVersion( protocol );
00145         m_req.SetUri( req_uri );
00146         m_req.SetRemoteAddr( remote_addr );
00147         m_req.SetRemoteHost( remote_host );
00148         m_req.SetServerName( server_name );
00149         m_req.SetServerPort( server_port );
00150         m_req.SetIsSsl( is_ssl );
00151 
00152         // Get Headers
00153         short                            num_headers = get_integer(buf, ptr);
00154         for (int i = 0; i < num_headers; i++)
00155         {
00156                 std::string key;
00157                 switch ( (unsigned char)buf[ptr]) // 0xa0
00158                 {
00159                 case 0xa0:
00160                         {
00161                                 unsigned short x = (unsigned short)get_integer(buf, ptr);
00162                                 std::map<int, std::string>::const_iterator it;
00163                                 if ( (it = Init.Header.find(x)) != Init.Header.end())
00164                                 {
00165                                         key = it -> second;
00166                                 }
00167                                 else
00168                                 {
00169                                         fprintf(stderr, "Unknown header key value: %x\n", x);
00170                                         SetCloseAndDelete();
00171                                 }
00172                         }
00173                         break;
00174 
00175                 default: // string
00176                         key = get_string(buf, ptr);
00177                 }
00178                 if (Utility::ToLower(key) == "cookie" || Utility::ToLower(key) == "cookie2")
00179                         m_req.AddCookie(get_string(buf, ptr));
00180                 else
00181                         m_req.SetHeader(key, get_string(buf, ptr));
00182         } // for
00183 
00184         // size left to read from web server
00185         m_body_size_left = m_req.ContentLength();
00186 
00187         // Get Attributes
00188         while ( (unsigned char)buf[ptr] != 0xff)
00189         {
00190                 std::string key;
00191                 unsigned char code = buf[ptr++];
00192                 switch ( code)
00193                 {
00194                 case 10: // req_attribute, attribute name follow
00195                         key = get_string(buf, ptr);
00196                         break;
00197                 default:
00198                         {
00199                                 std::map<int, std::string>::const_iterator it = Init.Attribute.find( code );
00200                                 if (it != Init.Attribute.end())
00201                                 {
00202                                         key = it -> second;
00203                                 }
00204                                 else
00205                                 {
00206                                         fprintf(stderr, "Unknown attribute key: 0x%02x\n", buf[ptr]);
00207                                         SetCloseAndDelete();
00208                                 }
00209                         }
00210                 }
00211                 m_req.SetAttribute(key, get_string(buf, ptr));
00212         } // while
00213 
00214         // execute at once if no body data
00215         if (!m_body_size_left)
00216         {
00217                 Execute();
00218         }
00219         else
00220         {
00221                 // open temporary file for body data
00222                 m_req.InitBody( m_body_size_left );
00223         }
00224 }

void Ajp13Socket::ReceiveShutdown ( const char *  buf,
size_t  sz 
) [private]

Definition at line 228 of file Ajp13Socket.cpp.

Referenced by OnPacket().

00229 {
00230 }

void Ajp13Socket::ReceivePing ( const char *  buf,
size_t  sz 
) [private]

Definition at line 234 of file Ajp13Socket.cpp.

Referenced by OnPacket().

00235 {
00236 }

void Ajp13Socket::ReceiveCPing ( const char *  buf,
size_t  sz 
) [private]

Definition at line 240 of file Ajp13Socket.cpp.

Referenced by OnPacket().

00241 {
00242 }

void Ajp13Socket::Execute (  )  [private]

Definition at line 246 of file Ajp13Socket.cpp.

References m_req, IHttpServer::OnExec(), and HttpRequest::ParseBody().

Referenced by ReceiveBody(), and ReceiveForwardRequest().

00247 {
00248         // parse form data / query_string and cookie header if available
00249         m_req.ParseBody();
00250 
00251         // prepare page
00252         OnExec( m_req );
00253 
00254 }


Member Data Documentation

Definition at line 67 of file Ajp13Socket.h.

Referenced by OnPacket(), ReceiveBody(), and ReceiveForwardRequest().

Definition at line 68 of file Ajp13Socket.h.

Referenced by Execute(), ReceiveBody(), and ReceiveForwardRequest().

Definition at line 69 of file Ajp13Socket.h.

Referenced by OnTransferLimit(), and Respond().


The documentation for this class was generated from the following files:
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4