![]() |
HttpdSocket Class ReferenceWeb server socket framework.
More...
|
Public Member Functions | |
HttpdSocket (ISocketHandler &) | |
~HttpdSocket () | |
void | OnFirst () |
Callback executes when first line has been received. | |
void | OnHeader (const std::string &key, const std::string &value) |
For each header line this callback is executed. | |
void | OnHeaderComplete () |
Callback fires when all http headers have been received. | |
void | OnData (const char *, size_t) |
Chunk of http body data recevied. | |
virtual void | Exec ()=0 |
This method needs to be implemented with logic to produce a response to an incoming request. | |
const std::string & | GetHttpDate () const |
Get current date in http rfc format. | |
HttpdCookies * | GetCookies () |
Get pointer to cookie class. | |
const HttpdForm * | GetForm () const |
Get pointer to query string/form data class. | |
size_t | ContentLength () const |
const IFile * | Body () const |
int | RequestId () const |
Protected Member Functions | |
HttpdSocket (const HttpdSocket &s) | |
void | Send64 (const std::string &str64, const std::string &type) |
Decode and send a base64-encoded string. | |
std::string | datetime2httpdate (const std::string &dt) |
std::string | GetDate () |
void | Reset () |
Reset state of socket to sucessfully implement keep-alive. | |
Protected Attributes | |
std::string | m_http_cookie |
std::string | m_content_type |
std::string | m_content_length_str |
std::string | m_if_modified_since |
Private Member Functions | |
HttpdSocket & | operator= (const HttpdSocket &s) |
Private Attributes | |
size_t | m_content_length |
IFile * | m_file |
size_t | m_received |
int | m_request_id |
std::string | m_http_date |
HttpdCookies * | m_cookies |
HttpdForm * | m_form |
Static Private Attributes | |
static int | m_request_count = 0 |
static std::string | m_start = "" |
Definition at line 49 of file HttpdSocket.h.
HttpdSocket::HttpdSocket | ( | ISocketHandler & | h | ) |
Definition at line 52 of file HttpdSocket.cpp.
References datetime2httpdate(), GetDate(), m_http_date, and m_start.
00053 :HTTPSocket(h) 00054 ,m_content_length(0) 00055 ,m_file(NULL) 00056 ,m_received(0) 00057 ,m_request_id(++m_request_count) 00058 ,m_cookies(NULL) 00059 ,m_form(NULL) 00060 { 00061 m_http_date = datetime2httpdate(GetDate()); 00062 if (!m_start.size()) 00063 m_start = m_http_date; 00064 }
HttpdSocket::~HttpdSocket | ( | ) |
HttpdSocket::HttpdSocket | ( | const HttpdSocket & | s | ) | [inline, protected] |
void HttpdSocket::OnFirst | ( | ) | [virtual] |
Callback executes when first line has been received.
GetMethod, GetUrl/GetUri, and GetHttpVersion are valid when this callback is executed.
Implements HTTPSocket.
Definition at line 80 of file HttpdSocket.cpp.
void HttpdSocket::OnHeader | ( | const std::string & | key, | |
const std::string & | value | |||
) | [virtual] |
For each header line this callback is executed.
key | Http header name | |
value | Http header value |
Implements HTTPSocket.
Definition at line 85 of file HttpdSocket.cpp.
References m_content_length, m_content_length_str, m_content_type, m_http_cookie, and m_if_modified_since.
00086 { 00087 if (!strcasecmp(key.c_str(),"content-length")) 00088 { 00089 m_content_length = atoi(value.c_str()); 00090 m_content_length_str = value; 00091 } 00092 else 00093 if (!strcasecmp(key.c_str(),"cookie")) 00094 { 00095 m_http_cookie = value; 00096 } 00097 else 00098 if (!strcasecmp(key.c_str(),"content-type")) 00099 { 00100 m_content_type = value; 00101 } 00102 else 00103 if (!strcasecmp(key.c_str(),"if-modified-since")) 00104 { 00105 m_if_modified_since = value; 00106 } 00107 }
void HttpdSocket::OnHeaderComplete | ( | ) | [virtual] |
Callback fires when all http headers have been received.
Implements HTTPSocket.
Definition at line 110 of file HttpdSocket.cpp.
References HTTPSocket::AddResponseHeader(), datetime2httpdate(), Exec(), GetDate(), GetHttpDate(), HTTPSocket::GetMethod(), HTTPSocket::GetQueryString(), HTTPSocket::GetUri(), Utility::Logo, m_content_length_str, m_content_type, m_cookies, m_file, m_form, m_http_cookie, Reset(), Send64(), HTTPSocket::SendResponse(), Utility::SetEnv(), HTTPSocket::SetStatus(), and HTTPSocket::SetStatusText().
00111 { 00112 m_cookies = new HttpdCookies(m_http_cookie); 00113 00114 if (GetMethod() == "GET") 00115 { 00116 Utility::SetEnv("QUERY_STRING", GetQueryString()); 00117 } 00118 Utility::SetEnv("REQUEST_METHOD", GetMethod()); 00119 Utility::SetEnv("HTTP_COOKIE", m_http_cookie); 00120 Utility::SetEnv("CONTENT_TYPE", m_content_type); 00121 Utility::SetEnv("CONTENT_LENGTH", m_content_length_str); 00122 if (GetMethod() == "POST") 00123 { 00124 m_file = new MemFile; 00125 } 00126 else 00127 if (GetMethod() == "GET") 00128 { 00129 m_form = new HttpdForm(GetQueryString(), GetQueryString().size() ); 00130 AddResponseHeader("Date", datetime2httpdate(GetDate()) ); 00131 if (GetUri() == "/image") 00132 { 00133 Send64(Utility::Logo, "image/png"); 00134 } 00135 else 00136 { 00137 Exec(); 00138 } 00139 Reset(); // prepare for next request 00140 } 00141 else 00142 { 00143 AddResponseHeader("Date", GetHttpDate()); 00144 AddResponseHeader("Connection", "close"); 00145 SetStatus("405"); 00146 SetStatusText("Method not allowed"); 00147 SendResponse(); 00148 } 00149 }
void HttpdSocket::OnData | ( | const char * | , | |
size_t | ||||
) | [virtual] |
Chunk of http body data recevied.
Implements HTTPSocket.
Definition at line 152 of file HttpdSocket.cpp.
References HTTPSocket::AddResponseHeader(), datetime2httpdate(), Exec(), GetDate(), HTTPSocket::GetUri(), Utility::Logo, m_content_length, m_content_type, m_file, m_form, m_received, Reset(), and Send64().
00153 { 00154 if (m_file) 00155 { 00156 m_file -> fwrite(p,1,l); 00157 } 00158 m_received += l; 00159 if (m_received >= m_content_length && m_content_length) 00160 { 00161 // all done 00162 if (m_file && !m_form) 00163 { 00164 m_form = new HttpdForm(m_file, m_content_type, m_content_length); 00165 AddResponseHeader("Date", datetime2httpdate(GetDate()) ); 00166 if (GetUri() == "/image") 00167 { 00168 Send64(Utility::Logo, "image/png"); 00169 } 00170 else 00171 { 00172 Exec(); 00173 } 00174 Reset(); // prepare for next request 00175 } 00176 } 00177 }
virtual void HttpdSocket::Exec | ( | ) | [pure virtual] |
This method needs to be implemented with logic to produce a response to an incoming request.
Referenced by OnData(), and OnHeaderComplete().
const std::string & HttpdSocket::GetHttpDate | ( | ) | const |
Get current date in http rfc format.
Definition at line 303 of file HttpdSocket.cpp.
References m_http_date.
Referenced by OnHeaderComplete().
00304 { 00305 return m_http_date; 00306 }
HttpdCookies * HttpdSocket::GetCookies | ( | ) |
Get pointer to cookie class.
Definition at line 309 of file HttpdSocket.cpp.
References m_cookies.
00310 { 00311 return m_cookies; 00312 }
const HttpdForm * HttpdSocket::GetForm | ( | ) | const |
Get pointer to query string/form data class.
Definition at line 315 of file HttpdSocket.cpp.
References m_form.
00316 { 00317 return m_form; 00318 }
size_t HttpdSocket::ContentLength | ( | ) | const [inline] |
const IFile* HttpdSocket::Body | ( | ) | const [inline] |
int HttpdSocket::RequestId | ( | ) | const [inline] |
void HttpdSocket::Send64 | ( | const std::string & | str64, | |
const std::string & | type | |||
) | [protected] |
Decode and send a base64-encoded string.
str64 | Base64-encoded string | |
type | Mime type of content (content-type header) |
Definition at line 180 of file HttpdSocket.cpp.
References HTTPSocket::AddResponseHeader(), Base64::decode(), Base64::decode_length(), Utility::l2string(), m_if_modified_since, m_start, TcpSocket::SendBuf(), HTTPSocket::SendResponse(), HTTPSocket::SetStatus(), and HTTPSocket::SetStatusText().
Referenced by OnData(), and OnHeaderComplete().
00181 { 00182 Base64 bb; 00183 00184 if (!strcasecmp(m_start.c_str(), m_if_modified_since.c_str())) 00185 { 00186 SetStatus("304"); 00187 SetStatusText("Not Modified"); 00188 SendResponse(); 00189 } 00190 else 00191 { 00192 size_t len = bb.decode_length(str64); 00193 unsigned char *buf = new unsigned char[len]; 00194 00195 SetStatus("200"); 00196 SetStatusText("OK"); 00197 00198 AddResponseHeader("Content-length", Utility::l2string( (long)len) ); 00199 AddResponseHeader("Content-type", type ); 00200 AddResponseHeader("Last-modified", m_start); 00201 SendResponse(); 00202 00203 bb.decode(str64, buf, len); 00204 SendBuf( (char *)buf, len); 00205 delete[] buf; 00206 } 00207 }
std::string HttpdSocket::datetime2httpdate | ( | const std::string & | dt | ) | [protected] |
Definition at line 210 of file HttpdSocket.cpp.
References Socket::Handler(), and ISocketHandler::LogError().
Referenced by HttpdSocket(), OnData(), and OnHeaderComplete().
00211 { 00212 struct tm tp; 00213 time_t t; 00214 const char *days[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; 00215 const char *months[] = { "Jan","Feb","Mar","Apr","May","Jun", 00216 "Jul","Aug","Sep","Oct","Nov","Dec" }; 00217 int i; 00218 char s[40]; 00219 00220 /* 1997-12-16 09:50:40 */ 00221 00222 if (dt.size() == 19) 00223 { 00224 tp.tm_year = atoi(dt.substr(0,4).c_str()) - 1900; 00225 i = atoi(dt.substr(5,2).c_str()) - 1; 00226 tp.tm_mon = i >= 0 ? i : 0; 00227 tp.tm_mday = atoi(dt.substr(8,2).c_str()); 00228 tp.tm_hour = atoi(dt.substr(11,2).c_str()); 00229 tp.tm_min = atoi(dt.substr(14,2).c_str()); 00230 tp.tm_sec = atoi(dt.substr(17,2).c_str()); 00231 tp.tm_wday = 0; 00232 tp.tm_yday = 0; 00233 tp.tm_isdst = 0; 00234 t = mktime(&tp); 00235 if (t == -1) 00236 { 00237 Handler().LogError(this, "datetime2httpdate", 0, "mktime() failed"); 00238 } 00239 00240 snprintf(s,sizeof(s),"%s, %02d %s %d %02d:%02d:%02d GMT", 00241 days[tp.tm_wday], 00242 tp.tm_mday, 00243 months[tp.tm_mon], 00244 tp.tm_year + 1900, 00245 tp.tm_hour,tp.tm_min,tp.tm_sec); 00246 } 00247 else 00248 { 00249 *s = 0; 00250 } 00251 return s; 00252 }
std::string HttpdSocket::GetDate | ( | ) | [protected] |
Definition at line 255 of file HttpdSocket.cpp.
Referenced by HttpdSocket(), OnData(), and OnHeaderComplete().
00256 { 00257 time_t t = time(NULL); 00258 char slask[40]; // yyyy-mm-dd hh:mm:ss 00259 #ifdef __CYGWIN__ 00260 struct tm *tp = localtime(&t); 00261 snprintf(slask,sizeof(slask),"%d-%02d-%02d %02d:%02d:%02d", 00262 tp -> tm_year + 1900, 00263 tp -> tm_mon + 1, 00264 tp -> tm_mday, 00265 tp -> tm_hour,tp -> tm_min,tp -> tm_sec); 00266 #else 00267 struct tm tp; 00268 #if defined( _WIN32) && !defined(__CYGWIN__) 00269 localtime_s(&tp, &t); 00270 #else 00271 localtime_r(&t, &tp); 00272 #endif 00273 snprintf(slask,sizeof(slask),"%d-%02d-%02d %02d:%02d:%02d", 00274 tp.tm_year + 1900, 00275 tp.tm_mon + 1, 00276 tp.tm_mday, 00277 tp.tm_hour,tp.tm_min,tp.tm_sec); 00278 #endif 00279 return slask; 00280 }
void HttpdSocket::Reset | ( | ) | [protected, virtual] |
Reset state of socket to sucessfully implement keep-alive.
Reimplemented from HTTPSocket.
Definition at line 283 of file HttpdSocket.cpp.
References m_content_length, m_cookies, m_file, m_form, m_received, m_request_count, m_request_id, and HTTPSocket::Reset().
Referenced by OnData(), and OnHeaderComplete().
00284 { 00285 HTTPSocket::Reset(); 00286 m_content_length = 0; 00287 if (m_file) 00288 { 00289 delete m_file; 00290 m_file = NULL; 00291 } 00292 m_received = 0; 00293 m_request_id = ++m_request_count; 00294 if (m_cookies) 00295 delete m_cookies; 00296 m_cookies = NULL; 00297 if (m_form) 00298 delete m_form; 00299 m_form = NULL; 00300 }
HttpdSocket& HttpdSocket::operator= | ( | const HttpdSocket & | s | ) | [inline, private] |
std::string HttpdSocket::m_http_cookie [protected] |
std::string HttpdSocket::m_content_type [protected] |
Definition at line 85 of file HttpdSocket.h.
Referenced by OnData(), OnHeader(), and OnHeaderComplete().
std::string HttpdSocket::m_content_length_str [protected] |
std::string HttpdSocket::m_if_modified_since [protected] |
int HttpdSocket::m_request_count = 0 [static, private] |
std::string HttpdSocket::m_start = "" [static, private] |
size_t HttpdSocket::m_content_length [private] |
IFile* HttpdSocket::m_file [private] |
Definition at line 94 of file HttpdSocket.h.
Referenced by OnData(), OnHeaderComplete(), Reset(), and ~HttpdSocket().
size_t HttpdSocket::m_received [private] |
int HttpdSocket::m_request_id [private] |
std::string HttpdSocket::m_http_date [private] |
HttpdCookies* HttpdSocket::m_cookies [private] |
Definition at line 98 of file HttpdSocket.h.
Referenced by GetCookies(), OnHeaderComplete(), Reset(), and ~HttpdSocket().
HttpdForm* HttpdSocket::m_form [private] |
Definition at line 99 of file HttpdSocket.h.
Referenced by GetForm(), OnData(), OnHeaderComplete(), Reset(), and ~HttpdSocket().