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 IHttpServer_Respond (const HttpResponse &res)
 Send response.
void OnTransferLimit ()
 This callback fires when the output buffer drops below the value set by SetTransferLimit.
void SetReused (bool x=true)
bool IsReused ()

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 ()
void Reset ()

Private Attributes

size_t m_body_size_left
HttpRequest m_req
HttpResponse m_res
bool m_b_reused

Detailed Description

Definition at line 48 of file Ajp13Socket.h.


Constructor & Destructor Documentation

Ajp13Socket::Ajp13Socket ( ISocketHandler h  ) 

Definition at line 51 of file Ajp13Socket.cpp.

00051                                           : AjpBaseSocket(h)
00052 , m_body_size_left(0)
00053 , m_b_reused(false)
00054 {
00055 }


Member Function Documentation

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

Implements AjpBaseSocket.

Definition at line 59 of file Ajp13Socket.cpp.

References DEB, and Socket::SetCloseAndDelete().

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

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

Implements AjpBaseSocket.

Definition at line 413 of file Ajp13Socket.cpp.

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

00414 {
00415         DEB(fprintf(stderr, "OnPacket: %d bytes, code 0x%02x %02x %02x %02x\n", sz, *buf, buf[1], buf[2], buf[3]);)
00416 
00417         // check body size left to read, if non-zero packet is body data
00418         if (m_body_size_left) // must be a body packet
00419         {
00420                 ReceiveBody(buf, sz);
00421                 return;
00422         }
00423         switch (*buf)
00424         {
00425         case 0x2: // Forward Request
00426                 ReceiveForwardRequest(buf, sz);
00427                 break;
00428         case 0x7: // Shutdown
00429                 ReceiveShutdown(buf, sz);
00430                 break;
00431         case 0x8: // Ping
00432                 ReceivePing(buf, sz);
00433                 break;
00434         case 0xa: // CPing
00435                 ReceiveCPing(buf, sz);
00436                 break;
00437         default:
00438 DEB(            fprintf(stderr, "Unknown packet type: 0x%02x\n", *buf);)
00439                 SetCloseAndDelete();
00440         }
00441 
00442 }

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

Send response.

Implements IHttpServer.

Definition at line 276 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().

00277 {
00278         char msg[8192];
00279         msg[0] = 'A';
00280         msg[1] = 'B';
00281 
00282         m_res = res;
00283 
00284 // reply codes
00285 //      0x3 Send Body Chunk
00286 //      0x4 Send Headers
00287 //      0x5 End Response
00288 //      0x6 Get Body Chunk
00289 //      0x9 CPong Reply
00290 
00291         // check content length
00292         if (!m_res.ContentLength() && m_res.GetFile().size())
00293         {
00294 //              m_res.SetContentLength( m_res.GetFile().size() );
00295         }
00296 
00297         // Send Headers
00298         {
00299                 int ptr = 4;
00300                 put_byte(msg, ptr, 0x04); // send headers
00301                 put_integer(msg, ptr, m_res.HttpStatusCode() );
00302                 put_string(msg, ptr, m_res.HttpStatusMsg() );
00303                 put_integer(msg, ptr, (short)m_res.Headers().size() );
00304                 for (Utility::ncmap<std::string>::const_iterator it = m_res.Headers().begin(); it != m_res.Headers().end(); ++it)
00305                 {
00306                         Utility::ncmap<int>::const_iterator it2 = Init.ResponseHeader.find( it -> first );
00307                         if (it2 != Init.ResponseHeader.end())
00308                         {
00309                                 put_integer(msg, ptr, it2 -> second);
00310                         }
00311                         else
00312                         {
00313                                 put_string(msg, ptr, it -> first);
00314                         }
00315                         put_string(msg, ptr, it -> second);
00316                 }
00317                 std::list<std::string> vec = m_res.CookieNames();
00318                 {
00319                         for (std::list<std::string>::iterator it = vec.begin(); it != vec.end(); ++it)
00320                         {
00321                                 Utility::ncmap<int>::const_iterator it2 = Init.ResponseHeader.find( "set-cookie" );
00322                                 if (it2 != Init.ResponseHeader.end())
00323                                 {
00324                                         put_integer(msg, ptr, it2 -> second);
00325                                 }
00326                                 else
00327                                 {
00328                                         put_string(msg, ptr, "set-cookie");
00329                                 }
00330                                 put_string(msg, ptr, m_res.Cookie(*it) );
00331                         }
00332                 }
00333 
00334                 short len = htons( ptr - 4 );
00335                 memcpy( msg + 2, &len, 2 );
00336 
00337                 SendBuf( msg, ptr );
00338         }
00339         // Send Body Chunk
00340         OnTransferLimit();
00341 }

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 345 of file Ajp13Socket.cpp.

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

Referenced by IHttpServer_Respond().

00346 {
00347         char msg[8192];
00348         msg[0] = 'A';
00349         msg[1] = 'B';
00350 
00351         // Send Body Chunk
00352         size_t n = m_res.GetFile().fread(msg + 7, 1, 8100);
00353         while (n > 0)
00354         {
00355                 int ptr = 4;
00356                 put_byte(msg, ptr, 0x03); // send body chunk
00357                 put_integer(msg, ptr, (short)n);
00358                 ptr += (int)n;
00359                 put_byte(msg, ptr, 0); // chunk terminator
00360 
00361                 short len = htons( ptr - 4 );
00362                 memcpy( msg + 2, &len, 2 );
00363 
00364                 SendBuf( msg, ptr );
00365                 if (GetOutputLength() > 1)
00366                 {
00367                         SetTransferLimit( 1 );
00368                         break;
00369                 }
00370 
00371                 //
00372                 n = m_res.GetFile().fread(msg + 7, 1, 8100);
00373         }
00374         if (!GetOutputLength()) // all body data sent and no data in output buffer - send end response
00375         {
00376                 // End Response
00377                 int ptr = 4;
00378                 put_byte(msg, ptr, 0x05); // end response
00379                 put_boolean(msg, ptr, m_b_reused); // reuse
00380                 /*
00381                         don't reuse
00382                         - but with m_req.Reset() and m_res.Reset() it should be possible
00383                         - also reset any AjpBaseSocket/Ajp13Socket specific states
00384                 */
00385 
00386                 short len = htons( ptr - 4 );
00387                 memcpy( msg + 2, &len, 2 );
00388 
00389                 SendBuf( msg, ptr );
00390 
00391                 SetTransferLimit(0);
00392                 m_res.GetFile().fclose();
00393                 IHttpServer_OnResponseComplete();
00394                 if (m_b_reused)
00395                 {
00396                         Reset();
00397                 }
00398         }
00399 }

void Ajp13Socket::SetReused ( bool  x = true  ) 

Definition at line 446 of file Ajp13Socket.cpp.

References m_b_reused.

00447 {
00448         m_b_reused = x;
00449 }

bool Ajp13Socket::IsReused (  ) 

Definition at line 453 of file Ajp13Socket.cpp.

References m_b_reused.

00454 {
00455         return m_b_reused;
00456 }

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

Definition at line 74 of file Ajp13Socket.cpp.

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

Referenced by OnPacket().

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

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

Definition at line 121 of file Ajp13Socket.cpp.

References HttpRequest::AddCookie(), HttpTransaction::ContentLength(), DEB, 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().

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

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

Definition at line 232 of file Ajp13Socket.cpp.

Referenced by OnPacket().

00233 {
00234 }

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

Definition at line 238 of file Ajp13Socket.cpp.

Referenced by OnPacket().

00239 {
00240 }

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

Definition at line 244 of file Ajp13Socket.cpp.

References m_b_reused, AjpBaseSocket::put_byte(), AjpBaseSocket::reset(), and TcpSocket::SendBuf().

Referenced by OnPacket().

00245 {
00246        char msg[5]; 
00247        msg[0] = 'A';
00248        msg[1] = 'B';
00249 
00250        int ptr = 4;
00251        put_byte(msg, ptr, 0x09); // send CPong Reply
00252 
00253        short len = htons( ptr - 4 );
00254        memcpy( msg + 2, &len, 2 );
00255 
00256        SendBuf( msg, ptr );
00257 
00258        if (m_b_reused)
00259                reset();
00260 }

void Ajp13Socket::Execute (  )  [private]

Definition at line 264 of file Ajp13Socket.cpp.

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

Referenced by ReceiveBody(), and ReceiveForwardRequest().

00265 {
00266         // parse form data / query_string and cookie header if available
00267         m_req.ParseBody();
00268 
00269         // prepare page
00270         IHttpServer_OnExec( m_req );
00271 
00272 }

void Ajp13Socket::Reset (  )  [private]

Definition at line 403 of file Ajp13Socket.cpp.

References m_body_size_left, m_req, m_res, HttpResponse::Reset(), HttpRequest::Reset(), and AjpBaseSocket::reset().

Referenced by OnTransferLimit().

00404 {
00405         reset();
00406         m_body_size_left = 0;
00407         m_req.Reset();
00408         m_res.Reset();
00409 }


Member Data Documentation

Definition at line 73 of file Ajp13Socket.h.

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

Definition at line 74 of file Ajp13Socket.h.

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

Definition at line 75 of file Ajp13Socket.h.

Referenced by IHttpServer_Respond(), OnTransferLimit(), and Reset().

bool Ajp13Socket::m_b_reused [private]

Definition at line 76 of file Ajp13Socket.h.

Referenced by IsReused(), OnTransferLimit(), ReceiveCPing(), and SetReused().


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