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 47 of file HttpdSocket.h.
| HttpdSocket::HttpdSocket | ( | ISocketHandler & | h | ) |
Definition at line 51 of file HttpdSocket.cpp.
References datetime2httpdate(), GetDate(), m_http_date, and m_start.
00052 :HTTPSocket(h) 00053 ,m_content_length(0) 00054 ,m_file(NULL) 00055 ,m_received(0) 00056 ,m_request_id(++m_request_count) 00057 ,m_cookies(NULL) 00058 ,m_form(NULL) 00059 { 00060 m_http_date = datetime2httpdate(GetDate()); 00061 if (!m_start.size()) 00062 m_start = m_http_date; 00063 }
| 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 79 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 84 of file HttpdSocket.cpp.
References m_content_length, m_content_length_str, m_content_type, m_http_cookie, and m_if_modified_since.
00085 { 00086 if (!strcasecmp(key.c_str(),"content-length")) 00087 { 00088 m_content_length = atoi(value.c_str()); 00089 m_content_length_str = value; 00090 } 00091 else 00092 if (!strcasecmp(key.c_str(),"cookie")) 00093 { 00094 m_http_cookie = value; 00095 } 00096 else 00097 if (!strcasecmp(key.c_str(),"content-type")) 00098 { 00099 m_content_type = value; 00100 } 00101 else 00102 if (!strcasecmp(key.c_str(),"if-modified-since")) 00103 { 00104 m_if_modified_since = value; 00105 } 00106 }
| void HttpdSocket::OnHeaderComplete | ( | ) | [virtual] |
Callback fires when all http headers have been received.
Implements HTTPSocket.
Definition at line 109 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().
00110 { 00111 m_cookies = new HttpdCookies(m_http_cookie); 00112 00113 if (GetMethod() == "GET") 00114 { 00115 Utility::SetEnv("QUERY_STRING", GetQueryString()); 00116 } 00117 Utility::SetEnv("REQUEST_METHOD", GetMethod()); 00118 Utility::SetEnv("HTTP_COOKIE", m_http_cookie); 00119 Utility::SetEnv("CONTENT_TYPE", m_content_type); 00120 Utility::SetEnv("CONTENT_LENGTH", m_content_length_str); 00121 if (GetMethod() == "POST") 00122 { 00123 m_file = new MemFile; 00124 } 00125 else 00126 if (GetMethod() == "GET") 00127 { 00128 m_form = new HttpdForm(GetQueryString(), GetQueryString().size() ); 00129 AddResponseHeader("Date", datetime2httpdate(GetDate()) ); 00130 if (GetUri() == "/image") 00131 { 00132 Send64(Utility::Logo, "image/png"); 00133 } 00134 else 00135 { 00136 Exec(); 00137 } 00138 Reset(); // prepare for next request 00139 } 00140 else 00141 { 00142 AddResponseHeader("Date", GetHttpDate()); 00143 AddResponseHeader("Connection", "close"); 00144 SetStatus("405"); 00145 SetStatusText("Method not allowed"); 00146 SendResponse(); 00147 } 00148 }
| void HttpdSocket::OnData | ( | const char * | , | |
| size_t | ||||
| ) | [virtual] |
Chunk of http body data recevied.
Implements HTTPSocket.
Definition at line 151 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().
00152 { 00153 if (m_file) 00154 { 00155 m_file -> fwrite(p,1,l); 00156 } 00157 m_received += l; 00158 if (m_received >= m_content_length && m_content_length) 00159 { 00160 // all done 00161 if (m_file && !m_form) 00162 { 00163 m_form = new HttpdForm(m_file, m_content_type, m_content_length); 00164 AddResponseHeader("Date", datetime2httpdate(GetDate()) ); 00165 if (GetUri() == "/image") 00166 { 00167 Send64(Utility::Logo, "image/png"); 00168 } 00169 else 00170 { 00171 Exec(); 00172 } 00173 Reset(); // prepare for next request 00174 } 00175 } 00176 }
| 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 293 of file HttpdSocket.cpp.
References m_http_date.
Referenced by OnHeaderComplete().
00294 { 00295 return m_http_date; 00296 }
| HttpdCookies * HttpdSocket::GetCookies | ( | ) |
Get pointer to cookie class.
Definition at line 299 of file HttpdSocket.cpp.
References m_cookies.
00300 { 00301 return m_cookies; 00302 }
| const HttpdForm * HttpdSocket::GetForm | ( | ) | const |
Get pointer to query string/form data class.
Definition at line 305 of file HttpdSocket.cpp.
References m_form.
00306 { 00307 return m_form; 00308 }
| 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 179 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().
00180 { 00181 Base64 bb; 00182 00183 if (!strcasecmp(m_start.c_str(), m_if_modified_since.c_str())) 00184 { 00185 SetStatus("304"); 00186 SetStatusText("Not Modified"); 00187 SendResponse(); 00188 } 00189 else 00190 { 00191 size_t len = bb.decode_length(str64); 00192 unsigned char *buf = new unsigned char[len]; 00193 00194 SetStatus("200"); 00195 SetStatusText("OK"); 00196 00197 AddResponseHeader("Content-length", Utility::l2string( (long)len) ); 00198 AddResponseHeader("Content-type", type ); 00199 AddResponseHeader("Last-modified", m_start); 00200 SendResponse(); 00201 00202 bb.decode(str64, buf, len); 00203 SendBuf( (char *)buf, len); 00204 delete[] buf; 00205 } 00206 }
| std::string HttpdSocket::datetime2httpdate | ( | const std::string & | dt | ) | [protected] |
Definition at line 209 of file HttpdSocket.cpp.
References Socket::Handler(), and ISocketHandler::LogError().
Referenced by HttpdSocket(), OnData(), and OnHeaderComplete().
00210 { 00211 struct tm tp; 00212 time_t t; 00213 const char *days[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; 00214 const char *months[] = { "Jan","Feb","Mar","Apr","May","Jun", 00215 "Jul","Aug","Sep","Oct","Nov","Dec" }; 00216 int i; 00217 char s[40]; 00218 00219 /* 1997-12-16 09:50:40 */ 00220 00221 if (dt.size() == 19) 00222 { 00223 tp.tm_year = atoi(dt.substr(0,4).c_str()) - 1900; 00224 i = atoi(dt.substr(5,2).c_str()) - 1; 00225 tp.tm_mon = i >= 0 ? i : 0; 00226 tp.tm_mday = atoi(dt.substr(8,2).c_str()); 00227 tp.tm_hour = atoi(dt.substr(11,2).c_str()); 00228 tp.tm_min = atoi(dt.substr(14,2).c_str()); 00229 tp.tm_sec = atoi(dt.substr(17,2).c_str()); 00230 tp.tm_wday = 0; 00231 tp.tm_yday = 0; 00232 tp.tm_isdst = 0; 00233 t = mktime(&tp); 00234 if (t == -1) 00235 { 00236 Handler().LogError(this, "datetime2httpdate", 0, "mktime() failed"); 00237 } 00238 00239 sprintf(s,"%s, %02d %s %d %02d:%02d:%02d GMT", 00240 days[tp.tm_wday], 00241 tp.tm_mday, 00242 months[tp.tm_mon], 00243 tp.tm_year + 1900, 00244 tp.tm_hour,tp.tm_min,tp.tm_sec); 00245 } 00246 else 00247 { 00248 *s = 0; 00249 } 00250 return s; 00251 }
| std::string HttpdSocket::GetDate | ( | ) | [protected] |
Definition at line 254 of file HttpdSocket.cpp.
Referenced by HttpdSocket(), OnData(), and OnHeaderComplete().
00255 { 00256 time_t t = time(NULL); 00257 struct tm tp; 00258 #ifdef _WIN32 00259 memcpy(&tp, localtime(&t), sizeof(tp)); 00260 #else 00261 localtime_r(&t, &tp); 00262 #endif 00263 char slask[40]; // yyyy-mm-dd hh:mm:ss 00264 sprintf(slask,"%d-%02d-%02d %02d:%02d:%02d", 00265 tp.tm_year + 1900, 00266 tp.tm_mon + 1, 00267 tp.tm_mday, 00268 tp.tm_hour,tp.tm_min,tp.tm_sec); 00269 return slask; 00270 }
| void HttpdSocket::Reset | ( | ) | [protected, virtual] |
Reset state of socket to sucessfully implement keep-alive.
Reimplemented from HTTPSocket.
Definition at line 273 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().
00274 { 00275 HTTPSocket::Reset(); 00276 m_content_length = 0; 00277 if (m_file) 00278 { 00279 delete m_file; 00280 m_file = NULL; 00281 } 00282 m_received = 0; 00283 m_request_id = ++m_request_count; 00284 if (m_cookies) 00285 delete m_cookies; 00286 m_cookies = NULL; 00287 if (m_form) 00288 delete m_form; 00289 m_form = NULL; 00290 }
| 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 83 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 92 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 96 of file HttpdSocket.h.
Referenced by GetCookies(), OnHeaderComplete(), Reset(), and ~HttpdSocket().
HttpdForm* HttpdSocket::m_form [private] |
Definition at line 97 of file HttpdSocket.h.
Referenced by GetForm(), OnData(), OnHeaderComplete(), Reset(), and ~HttpdSocket().
1.4.4