winlin

refine code, extrat the ISrsHttpMessage.

@@ -82,14 +82,14 @@ void SrsHttpHeartbeat::heartbeat() @@ -82,14 +82,14 @@ void SrsHttpHeartbeat::heartbeat()
82 return; 82 return;
83 } 83 }
84 84
85 - SrsHttpMessage* msg = NULL; 85 + ISrsHttpMessage* msg = NULL;
86 if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) { 86 if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) {
87 srs_info("http post hartbeart uri failed. " 87 srs_info("http post hartbeart uri failed. "
88 "url=%s, request=%s, response=%s, ret=%d", 88 "url=%s, request=%s, response=%s, ret=%d",
89 url.c_str(), req.c_str(), res.c_str(), ret); 89 url.c_str(), req.c_str(), res.c_str(), ret);
90 return; 90 return;
91 } 91 }
92 - SrsAutoFree(SrsHttpMessage, msg); 92 + SrsAutoFree(ISrsHttpMessage, msg);
93 93
94 std::string res; 94 std::string res;
95 if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) { 95 if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) {
@@ -25,726 +25,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -25,726 +25,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 25
26 #ifdef SRS_AUTO_HTTP_PARSER 26 #ifdef SRS_AUTO_HTTP_PARSER
27 27
28 -#include <stdlib.h>  
29 -#include <sys/stat.h>  
30 -#include <algorithm> 28 +#include <sstream>
31 using namespace std; 29 using namespace std;
32 30
33 #include <srs_kernel_error.hpp> 31 #include <srs_kernel_error.hpp>
34 #include <srs_kernel_log.hpp> 32 #include <srs_kernel_log.hpp>
35 #include <srs_app_st_socket.hpp> 33 #include <srs_app_st_socket.hpp>
36 -#include <srs_app_http_api.hpp>  
37 -#include <srs_app_http_conn.hpp>  
38 -#include <srs_app_json.hpp>  
39 -#include <srs_kernel_utility.hpp>  
40 -#include <srs_rtmp_buffer.hpp>  
41 -#include <srs_kernel_file.hpp>  
42 -#include <srs_core_autofree.hpp>  
43 -#include <srs_rtmp_buffer.hpp>  
44 #include <srs_rtmp_sdk.hpp> 34 #include <srs_rtmp_sdk.hpp>
  35 +#include <srs_rtmp_buffer.hpp>
  36 +#include <srs_kernel_utility.hpp>
45 #include <srs_rtmp_utility.hpp> 37 #include <srs_rtmp_utility.hpp>
46 -  
47 -#define SRS_DEFAULT_HTTP_PORT 80  
48 -  
49 -// for http parser macros  
50 -#define SRS_CONSTS_HTTP_OPTIONS HTTP_OPTIONS  
51 -#define SRS_CONSTS_HTTP_GET HTTP_GET  
52 -#define SRS_CONSTS_HTTP_POST HTTP_POST  
53 -#define SRS_CONSTS_HTTP_PUT HTTP_PUT  
54 -#define SRS_CONSTS_HTTP_DELETE HTTP_DELETE  
55 -  
56 -// for ead all of http body, read each time.  
57 -#define SRS_HTTP_READ_CACHE_BYTES 4096  
58 -  
59 -#define SRS_HTTP_DEFAULT_PAGE "index.html"  
60 -  
61 -int srs_http_response_json(ISrsHttpResponseWriter* w, string data)  
62 -{  
63 - w->header()->set_content_length(data.length());  
64 - w->header()->set_content_type("application/json");  
65 -  
66 - return w->write((char*)data.data(), (int)data.length());  
67 -}  
68 -  
69 -// get the status text of code.  
70 -string srs_generate_http_status_text(int status)  
71 -{  
72 - static std::map<int, std::string> _status_map;  
73 - if (_status_map.empty()) {  
74 - _status_map[SRS_CONSTS_HTTP_Continue ] = SRS_CONSTS_HTTP_Continue_str ;  
75 - _status_map[SRS_CONSTS_HTTP_SwitchingProtocols ] = SRS_CONSTS_HTTP_SwitchingProtocols_str ;  
76 - _status_map[SRS_CONSTS_HTTP_OK ] = SRS_CONSTS_HTTP_OK_str ;  
77 - _status_map[SRS_CONSTS_HTTP_Created ] = SRS_CONSTS_HTTP_Created_str ;  
78 - _status_map[SRS_CONSTS_HTTP_Accepted ] = SRS_CONSTS_HTTP_Accepted_str ;  
79 - _status_map[SRS_CONSTS_HTTP_NonAuthoritativeInformation ] = SRS_CONSTS_HTTP_NonAuthoritativeInformation_str ;  
80 - _status_map[SRS_CONSTS_HTTP_NoContent ] = SRS_CONSTS_HTTP_NoContent_str ;  
81 - _status_map[SRS_CONSTS_HTTP_ResetContent ] = SRS_CONSTS_HTTP_ResetContent_str ;  
82 - _status_map[SRS_CONSTS_HTTP_PartialContent ] = SRS_CONSTS_HTTP_PartialContent_str ;  
83 - _status_map[SRS_CONSTS_HTTP_MultipleChoices ] = SRS_CONSTS_HTTP_MultipleChoices_str ;  
84 - _status_map[SRS_CONSTS_HTTP_MovedPermanently ] = SRS_CONSTS_HTTP_MovedPermanently_str ;  
85 - _status_map[SRS_CONSTS_HTTP_Found ] = SRS_CONSTS_HTTP_Found_str ;  
86 - _status_map[SRS_CONSTS_HTTP_SeeOther ] = SRS_CONSTS_HTTP_SeeOther_str ;  
87 - _status_map[SRS_CONSTS_HTTP_NotModified ] = SRS_CONSTS_HTTP_NotModified_str ;  
88 - _status_map[SRS_CONSTS_HTTP_UseProxy ] = SRS_CONSTS_HTTP_UseProxy_str ;  
89 - _status_map[SRS_CONSTS_HTTP_TemporaryRedirect ] = SRS_CONSTS_HTTP_TemporaryRedirect_str ;  
90 - _status_map[SRS_CONSTS_HTTP_BadRequest ] = SRS_CONSTS_HTTP_BadRequest_str ;  
91 - _status_map[SRS_CONSTS_HTTP_Unauthorized ] = SRS_CONSTS_HTTP_Unauthorized_str ;  
92 - _status_map[SRS_CONSTS_HTTP_PaymentRequired ] = SRS_CONSTS_HTTP_PaymentRequired_str ;  
93 - _status_map[SRS_CONSTS_HTTP_Forbidden ] = SRS_CONSTS_HTTP_Forbidden_str ;  
94 - _status_map[SRS_CONSTS_HTTP_NotFound ] = SRS_CONSTS_HTTP_NotFound_str ;  
95 - _status_map[SRS_CONSTS_HTTP_MethodNotAllowed ] = SRS_CONSTS_HTTP_MethodNotAllowed_str ;  
96 - _status_map[SRS_CONSTS_HTTP_NotAcceptable ] = SRS_CONSTS_HTTP_NotAcceptable_str ;  
97 - _status_map[SRS_CONSTS_HTTP_ProxyAuthenticationRequired ] = SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str ;  
98 - _status_map[SRS_CONSTS_HTTP_RequestTimeout ] = SRS_CONSTS_HTTP_RequestTimeout_str ;  
99 - _status_map[SRS_CONSTS_HTTP_Conflict ] = SRS_CONSTS_HTTP_Conflict_str ;  
100 - _status_map[SRS_CONSTS_HTTP_Gone ] = SRS_CONSTS_HTTP_Gone_str ;  
101 - _status_map[SRS_CONSTS_HTTP_LengthRequired ] = SRS_CONSTS_HTTP_LengthRequired_str ;  
102 - _status_map[SRS_CONSTS_HTTP_PreconditionFailed ] = SRS_CONSTS_HTTP_PreconditionFailed_str ;  
103 - _status_map[SRS_CONSTS_HTTP_RequestEntityTooLarge ] = SRS_CONSTS_HTTP_RequestEntityTooLarge_str ;  
104 - _status_map[SRS_CONSTS_HTTP_RequestURITooLarge ] = SRS_CONSTS_HTTP_RequestURITooLarge_str ;  
105 - _status_map[SRS_CONSTS_HTTP_UnsupportedMediaType ] = SRS_CONSTS_HTTP_UnsupportedMediaType_str ;  
106 - _status_map[SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable ] = SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str ;  
107 - _status_map[SRS_CONSTS_HTTP_ExpectationFailed ] = SRS_CONSTS_HTTP_ExpectationFailed_str ;  
108 - _status_map[SRS_CONSTS_HTTP_InternalServerError ] = SRS_CONSTS_HTTP_InternalServerError_str ;  
109 - _status_map[SRS_CONSTS_HTTP_NotImplemented ] = SRS_CONSTS_HTTP_NotImplemented_str ;  
110 - _status_map[SRS_CONSTS_HTTP_BadGateway ] = SRS_CONSTS_HTTP_BadGateway_str ;  
111 - _status_map[SRS_CONSTS_HTTP_ServiceUnavailable ] = SRS_CONSTS_HTTP_ServiceUnavailable_str ;  
112 - _status_map[SRS_CONSTS_HTTP_GatewayTimeout ] = SRS_CONSTS_HTTP_GatewayTimeout_str ;  
113 - _status_map[SRS_CONSTS_HTTP_HTTPVersionNotSupported ] = SRS_CONSTS_HTTP_HTTPVersionNotSupported_str ;  
114 - }  
115 -  
116 - std::string status_text;  
117 - if (_status_map.find(status) == _status_map.end()) {  
118 - status_text = "Status Unknown";  
119 - } else {  
120 - status_text = _status_map[status];  
121 - }  
122 -  
123 - return status_text;  
124 -}  
125 -  
126 -// bodyAllowedForStatus reports whether a given response status code  
127 -// permits a body. See RFC2616, section 4.4.  
128 -bool srs_go_http_body_allowd(int status)  
129 -{  
130 - if (status >= 100 && status <= 199) {  
131 - return false;  
132 - } else if (status == 204 || status == 304) {  
133 - return false;  
134 - }  
135 -  
136 - return true;  
137 -}  
138 -  
139 -// DetectContentType implements the algorithm described  
140 -// at http://mimesniff.spec.whatwg.org/ to determine the  
141 -// Content-Type of the given data. It considers at most the  
142 -// first 512 bytes of data. DetectContentType always returns  
143 -// a valid MIME type: if it cannot determine a more specific one, it  
144 -// returns "application/octet-stream".  
145 -string srs_go_http_detect(char* data, int size)  
146 -{  
147 - // detect only when data specified.  
148 - if (data) {  
149 - }  
150 - return "application/octet-stream"; // fallback  
151 -}  
152 -  
153 -// Error replies to the request with the specified error message and HTTP code.  
154 -// The error message should be plain text.  
155 -int srs_go_http_error(ISrsHttpResponseWriter* w, int code, string error)  
156 -{  
157 - int ret = ERROR_SUCCESS;  
158 -  
159 - w->header()->set_content_type("text/plain; charset=utf-8");  
160 - w->header()->set_content_length(error.length());  
161 - w->write_header(code);  
162 - w->write((char*)error.data(), (int)error.length());  
163 -  
164 - return ret;  
165 -}  
166 -  
167 -SrsHttpHeader::SrsHttpHeader()  
168 -{  
169 -}  
170 -  
171 -SrsHttpHeader::~SrsHttpHeader()  
172 -{  
173 -}  
174 -  
175 -void SrsHttpHeader::set(string key, string value)  
176 -{  
177 - headers[key] = value;  
178 -}  
179 -  
180 -string SrsHttpHeader::get(string key)  
181 -{  
182 - std::string v;  
183 -  
184 - if (headers.find(key) != headers.end()) {  
185 - v = headers[key];  
186 - }  
187 -  
188 - return v;  
189 -}  
190 -  
191 -int64_t SrsHttpHeader::content_length()  
192 -{  
193 - std::string cl = get("Content-Length");  
194 -  
195 - if (cl.empty()) {  
196 - return -1;  
197 - }  
198 -  
199 - return (int64_t)::atof(cl.c_str());  
200 -}  
201 -  
202 -void SrsHttpHeader::set_content_length(int64_t size)  
203 -{  
204 - char buf[64];  
205 - snprintf(buf, sizeof(buf), "%"PRId64, size);  
206 - set("Content-Length", buf);  
207 -}  
208 -  
209 -string SrsHttpHeader::content_type()  
210 -{  
211 - return get("Content-Type");  
212 -}  
213 -  
214 -void SrsHttpHeader::set_content_type(string ct)  
215 -{  
216 - set("Content-Type", ct);  
217 -}  
218 -  
219 -void SrsHttpHeader::write(stringstream& ss)  
220 -{  
221 - std::map<std::string, std::string>::iterator it;  
222 - for (it = headers.begin(); it != headers.end(); ++it) {  
223 - ss << it->first << ": " << it->second << SRS_HTTP_CRLF;  
224 - }  
225 -}  
226 -  
227 -ISrsHttpResponseWriter::ISrsHttpResponseWriter()  
228 -{  
229 -}  
230 -  
231 -ISrsHttpResponseWriter::~ISrsHttpResponseWriter()  
232 -{  
233 -}  
234 -  
235 -ISrsHttpResponseReader::ISrsHttpResponseReader()  
236 -{  
237 -}  
238 -  
239 -ISrsHttpResponseReader::~ISrsHttpResponseReader()  
240 -{  
241 -}  
242 -  
243 -ISrsHttpHandler::ISrsHttpHandler()  
244 -{  
245 - entry = NULL;  
246 -}  
247 -  
248 -ISrsHttpHandler::~ISrsHttpHandler()  
249 -{  
250 -}  
251 -  
252 -SrsHttpRedirectHandler::SrsHttpRedirectHandler(string u, int c)  
253 -{  
254 - url = u;  
255 - code = c;  
256 -}  
257 -  
258 -SrsHttpRedirectHandler::~SrsHttpRedirectHandler()  
259 -{  
260 -}  
261 -  
262 -int SrsHttpRedirectHandler::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)  
263 -{  
264 - int ret = ERROR_SUCCESS;  
265 - // TODO: FIXME: implements it.  
266 - return ret;  
267 -}  
268 -  
269 -SrsHttpNotFoundHandler::SrsHttpNotFoundHandler()  
270 -{  
271 -}  
272 -  
273 -SrsHttpNotFoundHandler::~SrsHttpNotFoundHandler()  
274 -{  
275 -}  
276 -  
277 -int SrsHttpNotFoundHandler::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)  
278 -{  
279 - return srs_go_http_error(w,  
280 - SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str);  
281 -}  
282 -  
283 -SrsHttpFileServer::SrsHttpFileServer(string root_dir)  
284 -{  
285 - dir = root_dir;  
286 -}  
287 -  
288 -SrsHttpFileServer::~SrsHttpFileServer()  
289 -{  
290 -}  
291 -  
292 -int SrsHttpFileServer::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)  
293 -{  
294 - string upath = r->path();  
295 -  
296 - // add default pages.  
297 - if (srs_string_ends_with(upath, "/")) {  
298 - upath += SRS_HTTP_DEFAULT_PAGE;  
299 - }  
300 -  
301 - string fullpath = dir + "/";  
302 -  
303 - // remove the virtual directory.  
304 - srs_assert(entry);  
305 - size_t pos = entry->pattern.find("/");  
306 - if (upath.length() > entry->pattern.length() && pos != string::npos) {  
307 - fullpath += upath.substr(entry->pattern.length() - pos);  
308 - } else {  
309 - fullpath += upath;  
310 - }  
311 -  
312 - // stat current dir, if exists, return error.  
313 - if (!srs_path_exists(fullpath)) {  
314 - srs_warn("http miss file=%s, pattern=%s, upath=%s",  
315 - fullpath.c_str(), entry->pattern.c_str(), upath.c_str());  
316 - return SrsHttpNotFoundHandler().serve_http(w, r);  
317 - }  
318 - srs_trace("http match file=%s, pattern=%s, upath=%s",  
319 - fullpath.c_str(), entry->pattern.c_str(), upath.c_str());  
320 -  
321 - // handle file according to its extension.  
322 - // use vod stream for .flv/.fhv  
323 - if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) {  
324 - return serve_flv_file(w, r, fullpath);  
325 - } else if (srs_string_ends_with(fullpath, ".mp4")) {  
326 - return serve_mp4_file(w, r, fullpath);  
327 - }  
328 -  
329 - // serve common static file.  
330 - return serve_file(w, r, fullpath);  
331 -}  
332 -  
333 -int SrsHttpFileServer::serve_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath)  
334 -{  
335 - int ret = ERROR_SUCCESS;  
336 -  
337 - // open the target file.  
338 - SrsFileReader fs;  
339 -  
340 - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {  
341 - srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);  
342 - return ret;  
343 - }  
344 -  
345 - int64_t length = fs.filesize();  
346 -  
347 - // unset the content length to encode in chunked encoding.  
348 - w->header()->set_content_length(length);  
349 -  
350 - static std::map<std::string, std::string> _mime;  
351 - if (_mime.empty()) {  
352 - _mime[".ts"] = "video/MP2T";  
353 - _mime[".flv"] = "video/x-flv";  
354 - _mime[".m4v"] = "video/x-m4v";  
355 - _mime[".3gpp"] = "video/3gpp";  
356 - _mime[".3gp"] = "video/3gpp";  
357 - _mime[".mp4"] = "video/mp4";  
358 - _mime[".aac"] = "audio/x-aac";  
359 - _mime[".mp3"] = "audio/mpeg";  
360 - _mime[".m4a"] = "audio/x-m4a";  
361 - _mime[".ogg"] = "audio/ogg";  
362 - // @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 5.  
363 - _mime[".m3u8"] = "application/vnd.apple.mpegurl"; // application/x-mpegURL  
364 - _mime[".rss"] = "application/rss+xml";  
365 - _mime[".json"] = "application/json";  
366 - _mime[".swf"] = "application/x-shockwave-flash";  
367 - _mime[".doc"] = "application/msword";  
368 - _mime[".zip"] = "application/zip";  
369 - _mime[".rar"] = "application/x-rar-compressed";  
370 - _mime[".xml"] = "text/xml";  
371 - _mime[".html"] = "text/html";  
372 - _mime[".js"] = "text/javascript";  
373 - _mime[".css"] = "text/css";  
374 - _mime[".ico"] = "image/x-icon";  
375 - _mime[".png"] = "image/png";  
376 - _mime[".jpeg"] = "image/jpeg";  
377 - _mime[".jpg"] = "image/jpeg";  
378 - _mime[".gif"] = "image/gif";  
379 - }  
380 -  
381 - if (true) {  
382 - size_t pos;  
383 - std::string ext = fullpath;  
384 - if ((pos = ext.rfind(".")) != string::npos) {  
385 - ext = ext.substr(pos);  
386 - }  
387 -  
388 - if (_mime.find(ext) == _mime.end()) {  
389 - w->header()->set_content_type("application/octet-stream");  
390 - } else {  
391 - w->header()->set_content_type(_mime[ext]);  
392 - }  
393 - }  
394 -  
395 - // write body.  
396 - int64_t left = length;  
397 - if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {  
398 - if (!srs_is_client_gracefully_close(ret)) {  
399 - srs_error("read file=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);  
400 - }  
401 - return ret;  
402 - }  
403 -  
404 - return w->final_request();  
405 -}  
406 -  
407 -int SrsHttpFileServer::serve_flv_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath)  
408 -{  
409 - std::string start = r->query_get("start");  
410 - if (start.empty()) {  
411 - return serve_file(w, r, fullpath);  
412 - }  
413 -  
414 - int offset = ::atoi(start.c_str());  
415 - if (offset <= 0) {  
416 - return serve_file(w, r, fullpath);  
417 - }  
418 -  
419 - return serve_flv_stream(w, r, fullpath, offset);  
420 -}  
421 -  
422 -int SrsHttpFileServer::serve_mp4_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath)  
423 -{  
424 - // for flash to request mp4 range in query string.  
425 - // for example, http://digitalprimates.net/dash/DashTest.html?url=http://dashdemo.edgesuite.net/digitalprimates/nexus/oops-20120802-manifest.mpd  
426 - std::string range = r->query_get("range");  
427 - // or, use bytes to request range,  
428 - // for example, http://dashas.castlabs.com/demo/try.html  
429 - if (range.empty()) {  
430 - range = r->query_get("bytes");  
431 - }  
432 -  
433 - // rollback to serve whole file.  
434 - size_t pos = string::npos;  
435 - if (range.empty() || (pos = range.find("-")) == string::npos) {  
436 - return serve_file(w, r, fullpath);  
437 - }  
438 -  
439 - // parse the start in query string  
440 - int start = 0;  
441 - if (pos > 0) {  
442 - start = ::atoi(range.substr(0, pos).c_str());  
443 - }  
444 -  
445 - // parse end in query string.  
446 - int end = -1;  
447 - if (pos < range.length() - 1) {  
448 - end = ::atoi(range.substr(pos + 1).c_str());  
449 - }  
450 -  
451 - // invalid param, serve as whole mp4 file.  
452 - if (start < 0 || (end != -1 && start > end)) {  
453 - return serve_file(w, r, fullpath);  
454 - }  
455 -  
456 - return serve_mp4_stream(w, r, fullpath, start, end);  
457 -}  
458 -  
459 -int SrsHttpFileServer::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset)  
460 -{  
461 - return serve_file(w, r, fullpath);  
462 -}  
463 -  
464 -int SrsHttpFileServer::serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end)  
465 -{  
466 - return serve_file(w, r, fullpath);  
467 -}  
468 -  
469 -int SrsHttpFileServer::copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size)  
470 -{  
471 - int ret = ERROR_SUCCESS;  
472 -  
473 - int left = size;  
474 - char* buf = r->http_ts_send_buffer();  
475 -  
476 - while (left > 0) {  
477 - ssize_t nread = -1;  
478 - int max_read = srs_min(left, SRS_HTTP_TS_SEND_BUFFER_SIZE);  
479 - if ((ret = fs->read(buf, max_read, &nread)) != ERROR_SUCCESS) {  
480 - break;  
481 - }  
482 -  
483 - left -= nread;  
484 - if ((ret = w->write(buf, (int)nread)) != ERROR_SUCCESS) {  
485 - break;  
486 - }  
487 - }  
488 -  
489 - return ret;  
490 -}  
491 -  
492 -SrsHttpMuxEntry::SrsHttpMuxEntry()  
493 -{  
494 - enabled = true;  
495 - explicit_match = false;  
496 - handler = NULL;  
497 -}  
498 -  
499 -SrsHttpMuxEntry::~SrsHttpMuxEntry()  
500 -{  
501 - srs_freep(handler);  
502 -}  
503 -  
504 -ISrsHttpMatchHijacker::ISrsHttpMatchHijacker()  
505 -{  
506 -}  
507 -  
508 -ISrsHttpMatchHijacker::~ISrsHttpMatchHijacker()  
509 -{  
510 -}  
511 -  
512 -SrsHttpServeMux::SrsHttpServeMux()  
513 -{  
514 -}  
515 -  
516 -SrsHttpServeMux::~SrsHttpServeMux()  
517 -{  
518 - std::map<std::string, SrsHttpMuxEntry*>::iterator it;  
519 - for (it = entries.begin(); it != entries.end(); ++it) {  
520 - SrsHttpMuxEntry* entry = it->second;  
521 - srs_freep(entry);  
522 - }  
523 - entries.clear();  
524 -  
525 - vhosts.clear();  
526 - hijackers.clear();  
527 -}  
528 -  
529 -int SrsHttpServeMux::initialize()  
530 -{  
531 - int ret = ERROR_SUCCESS;  
532 - // TODO: FIXME: implements it.  
533 - return ret;  
534 -}  
535 -  
536 -void SrsHttpServeMux::hijack(ISrsHttpMatchHijacker* h)  
537 -{  
538 - std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h);  
539 - if (it != hijackers.end()) {  
540 - return;  
541 - }  
542 - hijackers.push_back(h);  
543 -}  
544 -  
545 -void SrsHttpServeMux::unhijack(ISrsHttpMatchHijacker* h)  
546 -{  
547 - std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h);  
548 - if (it == hijackers.end()) {  
549 - return;  
550 - }  
551 - hijackers.erase(it);  
552 -}  
553 -  
554 -int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler)  
555 -{  
556 - int ret = ERROR_SUCCESS;  
557 -  
558 - srs_assert(handler);  
559 -  
560 - if (pattern.empty()) {  
561 - ret = ERROR_HTTP_PATTERN_EMPTY;  
562 - srs_error("http: empty pattern. ret=%d", ret);  
563 - return ret;  
564 - }  
565 -  
566 - if (entries.find(pattern) != entries.end()) {  
567 - SrsHttpMuxEntry* exists = entries[pattern];  
568 - if (exists->explicit_match) {  
569 - ret = ERROR_HTTP_PATTERN_DUPLICATED;  
570 - srs_error("http: multiple registrations for %s. ret=%d", pattern.c_str(), ret);  
571 - return ret;  
572 - }  
573 - }  
574 -  
575 - std::string vhost = pattern;  
576 - if (pattern.at(0) != '/') {  
577 - if (pattern.find("/") != string::npos) {  
578 - vhost = pattern.substr(0, pattern.find("/"));  
579 - }  
580 - vhosts[vhost] = handler;  
581 - }  
582 -  
583 - if (true) {  
584 - SrsHttpMuxEntry* entry = new SrsHttpMuxEntry();  
585 - entry->explicit_match = true;  
586 - entry->handler = handler;  
587 - entry->pattern = pattern;  
588 - entry->handler->entry = entry;  
589 -  
590 - if (entries.find(pattern) != entries.end()) {  
591 - SrsHttpMuxEntry* exists = entries[pattern];  
592 - srs_freep(exists);  
593 - }  
594 - entries[pattern] = entry;  
595 - }  
596 -  
597 - // Helpful behavior:  
598 - // If pattern is /tree/, insert an implicit permanent redirect for /tree.  
599 - // It can be overridden by an explicit registration.  
600 - if (pattern != "/" && !pattern.empty() && pattern.at(pattern.length() - 1) == '/') {  
601 - std::string rpattern = pattern.substr(0, pattern.length() - 1);  
602 - SrsHttpMuxEntry* entry = NULL;  
603 -  
604 - // free the exists not explicit entry  
605 - if (entries.find(rpattern) != entries.end()) {  
606 - SrsHttpMuxEntry* exists = entries[rpattern];  
607 - if (!exists->explicit_match) {  
608 - entry = exists;  
609 - }  
610 - }  
611 -  
612 - // create implicit redirect.  
613 - if (!entry || entry->explicit_match) {  
614 - srs_freep(entry);  
615 -  
616 - entry = new SrsHttpMuxEntry();  
617 - entry->explicit_match = false;  
618 - entry->handler = new SrsHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_MovedPermanently);  
619 - entry->pattern = pattern;  
620 - entry->handler->entry = entry;  
621 -  
622 - entries[rpattern] = entry;  
623 - }  
624 - }  
625 -  
626 - return ret;  
627 -}  
628 -  
629 -int SrsHttpServeMux::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)  
630 -{  
631 - int ret = ERROR_SUCCESS;  
632 -  
633 - ISrsHttpHandler* h = NULL;  
634 - if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) {  
635 - srs_error("find handler failed. ret=%d", ret);  
636 - return ret;  
637 - }  
638 -  
639 - srs_assert(h);  
640 - if ((ret = h->serve_http(w, r)) != ERROR_SUCCESS) {  
641 - if (!srs_is_client_gracefully_close(ret)) {  
642 - srs_error("handler serve http failed. ret=%d", ret);  
643 - }  
644 - return ret;  
645 - }  
646 -  
647 - return ret;  
648 -}  
649 -  
650 -int SrsHttpServeMux::find_handler(SrsHttpMessage* r, ISrsHttpHandler** ph)  
651 -{  
652 - int ret = ERROR_SUCCESS;  
653 -  
654 - // TODO: FIXME: support the path . and ..  
655 - if (r->url().find("..") != std::string::npos) {  
656 - ret = ERROR_HTTP_URL_NOT_CLEAN;  
657 - srs_error("htt url not canonical, url=%s. ret=%d", r->url().c_str(), ret);  
658 - return ret;  
659 - }  
660 -  
661 - if ((ret = match(r, ph)) != ERROR_SUCCESS) {  
662 - srs_error("http match handler failed. ret=%d", ret);  
663 - return ret;  
664 - }  
665 -  
666 - // always hijack.  
667 - if (!hijackers.empty()) {  
668 - // notice all hijacker the match failed.  
669 - std::vector<ISrsHttpMatchHijacker*>::iterator it;  
670 - for (it = hijackers.begin(); it != hijackers.end(); ++it) {  
671 - ISrsHttpMatchHijacker* hijacker = *it;  
672 - if ((ret = hijacker->hijack(r, ph)) != ERROR_SUCCESS) {  
673 - srs_error("hijacker match failed. ret=%d", ret);  
674 - return ret;  
675 - }  
676 - }  
677 - }  
678 -  
679 - if (*ph == NULL) {  
680 - // TODO: FIXME: memory leak.  
681 - *ph = new SrsHttpNotFoundHandler();  
682 - }  
683 -  
684 - return ret;  
685 -}  
686 -  
687 -int SrsHttpServeMux::match(SrsHttpMessage* r, ISrsHttpHandler** ph)  
688 -{  
689 - int ret = ERROR_SUCCESS;  
690 -  
691 - std::string path = r->path();  
692 -  
693 - // Host-specific pattern takes precedence over generic ones  
694 - if (!vhosts.empty() && vhosts.find(r->host()) != vhosts.end()) {  
695 - path = r->host() + path;  
696 - }  
697 -  
698 - int nb_matched = 0;  
699 - ISrsHttpHandler* h = NULL;  
700 -  
701 - std::map<std::string, SrsHttpMuxEntry*>::iterator it;  
702 - for (it = entries.begin(); it != entries.end(); ++it) {  
703 - std::string pattern = it->first;  
704 - SrsHttpMuxEntry* entry = it->second;  
705 -  
706 - if (!entry->enabled) {  
707 - continue;  
708 - }  
709 -  
710 - if (!path_match(pattern, path)) {  
711 - continue;  
712 - }  
713 -  
714 - if (!h || (int)pattern.length() > nb_matched) {  
715 - nb_matched = (int)pattern.length();  
716 - h = entry->handler;  
717 - }  
718 - }  
719 -  
720 - *ph = h;  
721 -  
722 - return ret;  
723 -}  
724 -  
725 -bool SrsHttpServeMux::path_match(string pattern, string path)  
726 -{  
727 - if (pattern.empty()) {  
728 - return false;  
729 - }  
730 -  
731 - int n = (int)pattern.length();  
732 -  
733 - // not endswith '/', exactly match.  
734 - if (pattern.at(n - 1) != '/') {  
735 - return pattern == path;  
736 - }  
737 -  
738 - // endswith '/', match any,  
739 - // for example, '/api/' match '/api/[N]'  
740 - if ((int)path.length() >= n) {  
741 - if (memcmp(pattern.data(), path.data(), n) == 0) {  
742 - return true;  
743 - }  
744 - }  
745 -  
746 - return false;  
747 -} 38 +#include <srs_core_autofree.hpp>
748 39
749 SrsHttpResponseWriter::SrsHttpResponseWriter(SrsStSocket* io) 40 SrsHttpResponseWriter::SrsHttpResponseWriter(SrsStSocket* io)
750 { 41 {
@@ -800,7 +91,7 @@ int SrsHttpResponseWriter::write(char* data, int size) @@ -800,7 +91,7 @@ int SrsHttpResponseWriter::write(char* data, int size)
800 srs_error("http: send header failed. ret=%d", ret); 91 srs_error("http: send header failed. ret=%d", ret);
801 return ret; 92 return ret;
802 } 93 }
803 - 94 +
804 // ignore NULL content. 95 // ignore NULL content.
805 if (!data) { 96 if (!data) {
806 return ret; 97 return ret;
@@ -854,9 +145,9 @@ int SrsHttpResponseWriter::send_header(char* data, int size) @@ -854,9 +145,9 @@ int SrsHttpResponseWriter::send_header(char* data, int size)
854 std::stringstream ss; 145 std::stringstream ss;
855 146
856 // status_line 147 // status_line
857 - ss << "HTTP/1.1 " << status << " "  
858 - << srs_generate_http_status_text(status) << SRS_HTTP_CRLF;  
859 - 148 + ss << "HTTP/1.1 " << status << " "
  149 + << srs_generate_http_status_text(status) << SRS_HTTP_CRLF;
  150 +
860 // detect content type 151 // detect content type
861 if (srs_go_http_body_allowd(status)) { 152 if (srs_go_http_body_allowd(status)) {
862 if (hdr->content_type().empty()) { 153 if (hdr->content_type().empty()) {
@@ -873,7 +164,7 @@ int SrsHttpResponseWriter::send_header(char* data, int size) @@ -873,7 +164,7 @@ int SrsHttpResponseWriter::send_header(char* data, int size)
873 if (content_length == -1) { 164 if (content_length == -1) {
874 hdr->set("Transfer-Encoding", "chunked"); 165 hdr->set("Transfer-Encoding", "chunked");
875 } 166 }
876 - 167 +
877 // keep alive to make vlc happy. 168 // keep alive to make vlc happy.
878 hdr->set("Connection", "Keep-Alive"); 169 hdr->set("Connection", "Keep-Alive");
879 170
@@ -1036,7 +327,7 @@ int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read) @@ -1036,7 +327,7 @@ int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read)
1036 return ret; 327 return ret;
1037 } 328 }
1038 buffer->read_slice(2); 329 buffer->read_slice(2);
1039 - 330 +
1040 return ret; 331 return ret;
1041 } 332 }
1042 333
@@ -1078,7 +369,7 @@ int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read) @@ -1078,7 +369,7 @@ int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read)
1078 return ret; 369 return ret;
1079 } 370 }
1080 371
1081 -SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c) 372 +SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c) : ISrsHttpMessage()
1082 { 373 {
1083 conn = c; 374 conn = c;
1084 chunked = false; 375 chunked = false;
@@ -1098,11 +389,11 @@ SrsHttpMessage::~SrsHttpMessage() @@ -1098,11 +389,11 @@ SrsHttpMessage::~SrsHttpMessage()
1098 int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, vector<SrsHttpHeaderField>& headers) 389 int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, vector<SrsHttpHeaderField>& headers)
1099 { 390 {
1100 int ret = ERROR_SUCCESS; 391 int ret = ERROR_SUCCESS;
1101 - 392 +
1102 _url = url; 393 _url = url;
1103 _header = *header; 394 _header = *header;
1104 _headers = headers; 395 _headers = headers;
1105 - 396 +
1106 // whether chunked. 397 // whether chunked.
1107 std::string transfer_encoding = get_request_header("Transfer-Encoding"); 398 std::string transfer_encoding = get_request_header("Transfer-Encoding");
1108 chunked = (transfer_encoding == "chunked"); 399 chunked = (transfer_encoding == "chunked");
@@ -1117,8 +408,8 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, @@ -1117,8 +408,8 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body,
1117 408
1118 // parse uri from url. 409 // parse uri from url.
1119 std::string host = get_request_header("Host"); 410 std::string host = get_request_header("Host");
1120 -  
1121 - // donot parse the empty host for uri, 411 +
  412 + // donot parse the empty host for uri,
1122 // for example, the response contains no host, 413 // for example, the response contains no host,
1123 // ignore it is ok. 414 // ignore it is ok.
1124 if (host.empty()) { 415 if (host.empty()) {
@@ -1165,11 +456,6 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, @@ -1165,11 +456,6 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body,
1165 return ret; 456 return ret;
1166 } 457 }
1167 458
1168 -char* SrsHttpMessage::http_ts_send_buffer()  
1169 -{  
1170 - return _http_ts_send_buffer;  
1171 -}  
1172 -  
1173 SrsConnection* SrsHttpMessage::connection() 459 SrsConnection* SrsHttpMessage::connection()
1174 { 460 {
1175 return conn; 461 return conn;
@@ -1409,7 +695,7 @@ int SrsHttpParser::initialize(enum http_parser_type type) @@ -1409,7 +695,7 @@ int SrsHttpParser::initialize(enum http_parser_type type)
1409 return ret; 695 return ret;
1410 } 696 }
1411 697
1412 -int SrsHttpParser::parse_message(SrsStSocket* skt, SrsConnection* conn, SrsHttpMessage** ppmsg) 698 +int SrsHttpParser::parse_message(SrsStSocket* skt, SrsConnection* conn, ISrsHttpMessage** ppmsg)
1413 { 699 {
1414 *ppmsg = NULL; 700 *ppmsg = NULL;
1415 701
@@ -34,366 +34,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -34,366 +34,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include <map> 34 #include <map>
35 #include <string> 35 #include <string>
36 #include <vector> 36 #include <vector>
37 -#include <sstream>  
38 37
39 #include <http_parser.h> 38 #include <http_parser.h>
40 39
41 #include <srs_app_st.hpp> 40 #include <srs_app_st.hpp>
42 -#include <srs_kernel_consts.hpp>  
43 #include <srs_http_stack.hpp> 41 #include <srs_http_stack.hpp>
44 42
45 class SrsRequest; 43 class SrsRequest;
46 class SrsStSocket; 44 class SrsStSocket;
47 -class SrsHttpUri;  
48 class SrsHttpMessage; 45 class SrsHttpMessage;
49 -class SrsFileReader;  
50 -class SrsSimpleBuffer;  
51 -class SrsHttpMuxEntry;  
52 -class ISrsHttpResponseWriter;  
53 class SrsFastBuffer; 46 class SrsFastBuffer;
  47 +class SrsHttpUri;
54 class SrsConnection; 48 class SrsConnection;
55 49
56 -// http specification  
57 -// CR = <US-ASCII CR, carriage return (13)>  
58 -#define SRS_HTTP_CR SRS_CONSTS_CR // 0x0D  
59 -// LF = <US-ASCII LF, linefeed (10)>  
60 -#define SRS_HTTP_LF SRS_CONSTS_LF // 0x0A  
61 -// SP = <US-ASCII SP, space (32)>  
62 -#define SRS_HTTP_SP ' ' // 0x20  
63 -// HT = <US-ASCII HT, horizontal-tab (9)>  
64 -#define SRS_HTTP_HT '\x09' // 0x09  
65 -  
66 -// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all  
67 -// protocol elements except the entity-body (see appendix 19.3 for  
68 -// tolerant applications).  
69 -#define SRS_HTTP_CRLF "\r\n" // 0x0D0A  
70 -#define SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A  
71 -  
72 -// @see SrsHttpMessage._http_ts_send_buffer  
73 -#define SRS_HTTP_TS_SEND_BUFFER_SIZE 4096  
74 -  
75 -// helper function: response in json format.  
76 -extern int srs_http_response_json(ISrsHttpResponseWriter* w, std::string data);  
77 -  
78 -// state of message  
79 -enum SrsHttpParseState {  
80 - SrsHttpParseStateInit = 0,  
81 - SrsHttpParseStateStart,  
82 - SrsHttpParseStateHeaderComplete,  
83 - SrsHttpParseStateMessageComplete  
84 -};  
85 -  
86 -// A Header represents the key-value pairs in an HTTP header.  
87 -class SrsHttpHeader  
88 -{  
89 -private:  
90 - std::map<std::string, std::string> headers;  
91 -public:  
92 - SrsHttpHeader();  
93 - virtual ~SrsHttpHeader();  
94 -public:  
95 - // Add adds the key, value pair to the header.  
96 - // It appends to any existing values associated with key.  
97 - virtual void set(std::string key, std::string value);  
98 - // Get gets the first value associated with the given key.  
99 - // If there are no values associated with the key, Get returns "".  
100 - // To access multiple values of a key, access the map directly  
101 - // with CanonicalHeaderKey.  
102 - virtual std::string get(std::string key);  
103 -public:  
104 - /**  
105 - * get the content length. -1 if not set.  
106 - */  
107 - virtual int64_t content_length();  
108 - /**  
109 - * set the content length by header "Content-Length"  
110 - */  
111 - virtual void set_content_length(int64_t size);  
112 -public:  
113 - /**  
114 - * get the content type. empty string if not set.  
115 - */  
116 - virtual std::string content_type();  
117 - /**  
118 - * set the content type by header "Content-Type"  
119 - */  
120 - virtual void set_content_type(std::string ct);  
121 -public:  
122 - /**  
123 - * write all headers to string stream.  
124 - */  
125 - virtual void write(std::stringstream& ss);  
126 -};  
127 -  
128 -// A ResponseWriter interface is used by an HTTP handler to  
129 -// construct an HTTP response.  
130 -// Usage 1, response with specified length content:  
131 -// ISrsHttpResponseWriter* w; // create or get response.  
132 -// std::string msg = "Hello, HTTP!";  
133 -// w->header()->set_content_type("text/plain; charset=utf-8");  
134 -// w->header()->set_content_length(msg.length());  
135 -// w->write_header(SRS_CONSTS_HTTP_OK);  
136 -// w->write((char*)msg.data(), (int)msg.length());  
137 -// w->final_request(); // optional flush.  
138 -// Usage 2, response with HTTP code only, zero content length.  
139 -// ISrsHttpResponseWriter* w; // create or get response.  
140 -// w->header()->set_content_length(0);  
141 -// w->write_header(SRS_CONSTS_HTTP_OK);  
142 -// w->final_request();  
143 -// Usage 3, response in chunked encoding.  
144 -// ISrsHttpResponseWriter* w; // create or get response.  
145 -// std::string msg = "Hello, HTTP!";  
146 -// w->header()->set_content_type("application/octet-stream");  
147 -// w->write_header(SRS_CONSTS_HTTP_OK);  
148 -// w->write((char*)msg.data(), (int)msg.length());  
149 -// w->write((char*)msg.data(), (int)msg.length());  
150 -// w->write((char*)msg.data(), (int)msg.length());  
151 -// w->write((char*)msg.data(), (int)msg.length());  
152 -// w->final_request(); // required to end the chunked and flush.  
153 -class ISrsHttpResponseWriter  
154 -{  
155 -public:  
156 - ISrsHttpResponseWriter();  
157 - virtual ~ISrsHttpResponseWriter();  
158 -public:  
159 - // when chunked mode,  
160 - // final the request to complete the chunked encoding.  
161 - // for no-chunked mode,  
162 - // final to send request, for example, content-length is 0.  
163 - virtual int final_request() = 0;  
164 -  
165 - // Header returns the header map that will be sent by WriteHeader.  
166 - // Changing the header after a call to WriteHeader (or Write) has  
167 - // no effect.  
168 - virtual SrsHttpHeader* header() = 0;  
169 -  
170 - // Write writes the data to the connection as part of an HTTP reply.  
171 - // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)  
172 - // before writing the data. If the Header does not contain a  
173 - // Content-Type line, Write adds a Content-Type set to the result of passing  
174 - // the initial 512 bytes of written data to DetectContentType.  
175 - // @param data, the data to send. NULL to flush header only.  
176 - virtual int write(char* data, int size) = 0;  
177 -  
178 - // WriteHeader sends an HTTP response header with status code.  
179 - // If WriteHeader is not called explicitly, the first call to Write  
180 - // will trigger an implicit WriteHeader(http.StatusOK).  
181 - // Thus explicit calls to WriteHeader are mainly used to  
182 - // send error codes.  
183 - // @remark, user must set header then write or write_header.  
184 - virtual void write_header(int code) = 0;  
185 -};  
186 -  
187 /** 50 /**
188 -* the reader interface for http response.  
189 -*/  
190 -class ISrsHttpResponseReader  
191 -{  
192 -public:  
193 - ISrsHttpResponseReader();  
194 - virtual ~ISrsHttpResponseReader();  
195 -public:  
196 - /**  
197 - * whether response read EOF.  
198 - */  
199 - virtual bool eof() = 0;  
200 - /**  
201 - * read from the response body.  
202 - * @param data, the buffer to read data buffer to.  
203 - * @param nb_data, the max size of data buffer.  
204 - * @param nb_read, the actual read size of bytes. NULL to ignore.  
205 - * @remark when eof(), return error.  
206 - */  
207 - virtual int read(char* data, int nb_data, int* nb_read) = 0;  
208 -};  
209 -  
210 -// Objects implementing the Handler interface can be  
211 -// registered to serve a particular path or subtree  
212 -// in the HTTP server.  
213 -//  
214 -// ServeHTTP should write reply headers and data to the ResponseWriter  
215 -// and then return. Returning signals that the request is finished  
216 -// and that the HTTP server can move on to the next request on  
217 -// the connection.  
218 -class ISrsHttpHandler  
219 -{  
220 -public:  
221 - SrsHttpMuxEntry* entry;  
222 -public:  
223 - ISrsHttpHandler();  
224 - virtual ~ISrsHttpHandler();  
225 -public:  
226 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) = 0;  
227 -};  
228 -  
229 -// Redirect to a fixed URL  
230 -class SrsHttpRedirectHandler : public ISrsHttpHandler  
231 -{  
232 -private:  
233 - std::string url;  
234 - int code;  
235 -public:  
236 - SrsHttpRedirectHandler(std::string u, int c);  
237 - virtual ~SrsHttpRedirectHandler();  
238 -public:  
239 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r);  
240 -};  
241 -  
242 -// NotFound replies to the request with an HTTP 404 not found error.  
243 -class SrsHttpNotFoundHandler : public ISrsHttpHandler  
244 -{  
245 -public:  
246 - SrsHttpNotFoundHandler();  
247 - virtual ~SrsHttpNotFoundHandler();  
248 -public:  
249 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r);  
250 -};  
251 -  
252 -// FileServer returns a handler that serves HTTP requests  
253 -// with the contents of the file system rooted at root.  
254 -//  
255 -// To use the operating system's file system implementation,  
256 -// use http.Dir:  
257 -//  
258 -// http.Handle("/", SrsHttpFileServer("/tmp"))  
259 -// http.Handle("/", SrsHttpFileServer("static-dir"))  
260 -class SrsHttpFileServer : public ISrsHttpHandler  
261 -{  
262 -protected:  
263 - std::string dir;  
264 -public:  
265 - SrsHttpFileServer(std::string root_dir);  
266 - virtual ~SrsHttpFileServer();  
267 -public:  
268 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r);  
269 -private:  
270 - /**  
271 - * serve the file by specified path  
272 - */  
273 - virtual int serve_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath);  
274 - virtual int serve_flv_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath);  
275 - virtual int serve_mp4_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath);  
276 -protected:  
277 - /**  
278 - * when access flv file with x.flv?start=xxx  
279 - */  
280 - virtual int serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset);  
281 - /**  
282 - * when access mp4 file with x.mp4?range=start-end  
283 - * @param start the start offset in bytes.  
284 - * @param end the end offset in bytes. -1 to end of file.  
285 - * @remark response data in [start, end].  
286 - */  
287 - virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int start, int end);  
288 -protected:  
289 - /**  
290 - * copy the fs to response writer in size bytes.  
291 - */  
292 - virtual int copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size);  
293 -};  
294 -  
295 -// the mux entry for server mux.  
296 -// the matcher info, for example, the pattern and handler.  
297 -class SrsHttpMuxEntry  
298 -{  
299 -public:  
300 - bool explicit_match;  
301 - ISrsHttpHandler* handler;  
302 - std::string pattern;  
303 - bool enabled;  
304 -public:  
305 - SrsHttpMuxEntry();  
306 - virtual ~SrsHttpMuxEntry();  
307 -};  
308 -  
309 -/**  
310 -* the hijacker for http pattern match.  
311 -*/  
312 -class ISrsHttpMatchHijacker  
313 -{  
314 -public:  
315 - ISrsHttpMatchHijacker();  
316 - virtual ~ISrsHttpMatchHijacker();  
317 -public:  
318 - /**  
319 - * when match the request failed, no handler to process request.  
320 - * @param request the http request message to match the handler.  
321 - * @param ph the already matched handler, hijack can rewrite it.  
322 - */  
323 - virtual int hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) = 0;  
324 -};  
325 -  
326 -// ServeMux is an HTTP request multiplexer.  
327 -// It matches the URL of each incoming request against a list of registered  
328 -// patterns and calls the handler for the pattern that  
329 -// most closely matches the URL.  
330 -//  
331 -// Patterns name fixed, rooted paths, like "/favicon.ico",  
332 -// or rooted subtrees, like "/images/" (note the trailing slash).  
333 -// Longer patterns take precedence over shorter ones, so that  
334 -// if there are handlers registered for both "/images/"  
335 -// and "/images/thumbnails/", the latter handler will be  
336 -// called for paths beginning "/images/thumbnails/" and the  
337 -// former will receive requests for any other paths in the  
338 -// "/images/" subtree.  
339 -//  
340 -// Note that since a pattern ending in a slash names a rooted subtree,  
341 -// the pattern "/" matches all paths not matched by other registered  
342 -// patterns, not just the URL with Path == "/".  
343 -//  
344 -// Patterns may optionally begin with a host name, restricting matches to  
345 -// URLs on that host only. Host-specific patterns take precedence over  
346 -// general patterns, so that a handler might register for the two patterns  
347 -// "/codesearch" and "codesearch.google.com/" without also taking over  
348 -// requests for "http://www.google.com/".  
349 -//  
350 -// ServeMux also takes care of sanitizing the URL request path,  
351 -// redirecting any request containing . or .. elements to an  
352 -// equivalent .- and ..-free URL.  
353 -class SrsHttpServeMux  
354 -{  
355 -private:  
356 - // the pattern handler, to handle the http request.  
357 - std::map<std::string, SrsHttpMuxEntry*> entries;  
358 - // the vhost handler.  
359 - // when find the handler to process the request,  
360 - // append the matched vhost when pattern not starts with /,  
361 - // for example, for pattern /live/livestream.flv of vhost ossrs.net,  
362 - // the path will rewrite to ossrs.net/live/livestream.flv  
363 - std::map<std::string, ISrsHttpHandler*> vhosts;  
364 - // all hijackers for http match.  
365 - // for example, the hstrs(http stream trigger rtmp source)  
366 - // can hijack and install handler when request incoming and no handler.  
367 - std::vector<ISrsHttpMatchHijacker*> hijackers;  
368 -public:  
369 - SrsHttpServeMux();  
370 - virtual ~SrsHttpServeMux();  
371 -public:  
372 - /**  
373 - * initialize the http serve mux.  
374 - */  
375 - virtual int initialize();  
376 - /**  
377 - * hijack the http match.  
378 - */  
379 - virtual void hijack(ISrsHttpMatchHijacker* h);  
380 - virtual void unhijack(ISrsHttpMatchHijacker* h);  
381 -public:  
382 - // Handle registers the handler for the given pattern.  
383 - // If a handler already exists for pattern, Handle panics.  
384 - virtual int handle(std::string pattern, ISrsHttpHandler* handler);  
385 -// interface ISrsHttpHandler  
386 -public:  
387 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r);  
388 -private:  
389 - virtual int find_handler(SrsHttpMessage* r, ISrsHttpHandler** ph);  
390 - virtual int match(SrsHttpMessage* r, ISrsHttpHandler** ph);  
391 - virtual bool path_match(std::string pattern, std::string path);  
392 -};  
393 -  
394 -/**  
395 -* response writer use st socket  
396 -*/ 51 + * response writer use st socket
  52 + */
397 class SrsHttpResponseWriter : public ISrsHttpResponseWriter 53 class SrsHttpResponseWriter : public ISrsHttpResponseWriter
398 { 54 {
399 private: 55 private:
@@ -402,7 +58,7 @@ private: @@ -402,7 +58,7 @@ private:
402 private: 58 private:
403 // reply header has been (logically) written 59 // reply header has been (logically) written
404 bool header_wrote; 60 bool header_wrote;
405 - // status code passed to WriteHeader 61 + // status code passed to WriteHeader
406 int status; 62 int status;
407 private: 63 private:
408 // explicitly-declared Content-Length; or -1 64 // explicitly-declared Content-Length; or -1
@@ -427,8 +83,8 @@ public: @@ -427,8 +83,8 @@ public:
427 }; 83 };
428 84
429 /** 85 /**
430 -* response reader use st socket.  
431 -*/ 86 + * response reader use st socket.
  87 + */
432 class SrsHttpResponseReader : virtual public ISrsHttpResponseReader 88 class SrsHttpResponseReader : virtual public ISrsHttpResponseReader
433 { 89 {
434 private: 90 private:
@@ -447,10 +103,10 @@ public: @@ -447,10 +103,10 @@ public:
447 virtual ~SrsHttpResponseReader(); 103 virtual ~SrsHttpResponseReader();
448 public: 104 public:
449 /** 105 /**
450 - * initialize the response reader with buffer.  
451 - */ 106 + * initialize the response reader with buffer.
  107 + */
452 virtual int initialize(SrsFastBuffer* buffer); 108 virtual int initialize(SrsFastBuffer* buffer);
453 -// interface ISrsHttpResponseReader 109 + // interface ISrsHttpResponseReader
454 public: 110 public:
455 virtual bool eof(); 111 virtual bool eof();
456 virtual int read(char* data, int nb_data, int* nb_read); 112 virtual int read(char* data, int nb_data, int* nb_read);
@@ -469,31 +125,31 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField; @@ -469,31 +125,31 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField;
469 // usage. In addition to the notes on the fields below, see the 125 // usage. In addition to the notes on the fields below, see the
470 // documentation for Request.Write and RoundTripper. 126 // documentation for Request.Write and RoundTripper.
471 /** 127 /**
472 -* the http message, request or response.  
473 -*/  
474 -class SrsHttpMessage 128 + * the http message, request or response.
  129 + */
  130 +class SrsHttpMessage : public ISrsHttpMessage
475 { 131 {
476 private: 132 private:
477 /** 133 /**
478 - * parsed url.  
479 - */ 134 + * parsed url.
  135 + */
480 std::string _url; 136 std::string _url;
481 /** 137 /**
482 - * the extension of file, for example, .flv  
483 - */ 138 + * the extension of file, for example, .flv
  139 + */
484 std::string _ext; 140 std::string _ext;
485 /** 141 /**
486 - * parsed http header.  
487 - */ 142 + * parsed http header.
  143 + */
488 http_parser _header; 144 http_parser _header;
489 /** 145 /**
490 - * body object, reader object.  
491 - * @remark, user can get body in string by get_body().  
492 - */ 146 + * body object, reader object.
  147 + * @remark, user can get body in string by get_body().
  148 + */
493 SrsHttpResponseReader* _body; 149 SrsHttpResponseReader* _body;
494 /** 150 /**
495 - * whether the body is chunked.  
496 - */ 151 + * whether the body is chunked.
  152 + */
497 bool chunked; 153 bool chunked;
498 /** 154 /**
499 * whether the request indicates should keep alive 155 * whether the request indicates should keep alive
@@ -501,12 +157,12 @@ private: @@ -501,12 +157,12 @@ private:
501 */ 157 */
502 bool keep_alive; 158 bool keep_alive;
503 /** 159 /**
504 - * uri parser  
505 - */ 160 + * uri parser
  161 + */
506 SrsHttpUri* _uri; 162 SrsHttpUri* _uri;
507 /** 163 /**
508 - * use a buffer to read and send ts file.  
509 - */ 164 + * use a buffer to read and send ts file.
  165 + */
510 // TODO: FIXME: remove it. 166 // TODO: FIXME: remove it.
511 char* _http_ts_send_buffer; 167 char* _http_ts_send_buffer;
512 // http headers 168 // http headers
@@ -520,20 +176,19 @@ public: @@ -520,20 +176,19 @@ public:
520 virtual ~SrsHttpMessage(); 176 virtual ~SrsHttpMessage();
521 public: 177 public:
522 /** 178 /**
523 - * set the original messages, then update the message.  
524 - */  
525 - virtual int update(std::string url, http_parser* header, 179 + * set the original messages, then update the message.
  180 + */
  181 + virtual int update(std::string url, http_parser* header,
526 SrsFastBuffer* body, std::vector<SrsHttpHeaderField>& headers 182 SrsFastBuffer* body, std::vector<SrsHttpHeaderField>& headers
527 ); 183 );
528 -public:  
529 - virtual char* http_ts_send_buffer(); 184 +private:
530 virtual SrsConnection* connection(); 185 virtual SrsConnection* connection();
531 public: 186 public:
532 virtual u_int8_t method(); 187 virtual u_int8_t method();
533 virtual u_int16_t status_code(); 188 virtual u_int16_t status_code();
534 /** 189 /**
535 - * method helpers.  
536 - */ 190 + * method helpers.
  191 + */
537 virtual std::string method_str(); 192 virtual std::string method_str();
538 virtual bool is_http_get(); 193 virtual bool is_http_get();
539 virtual bool is_http_put(); 194 virtual bool is_http_put();
@@ -541,57 +196,57 @@ public: @@ -541,57 +196,57 @@ public:
541 virtual bool is_http_delete(); 196 virtual bool is_http_delete();
542 virtual bool is_http_options(); 197 virtual bool is_http_options();
543 /** 198 /**
544 - * whether body is chunked encoding, for reader only.  
545 - */ 199 + * whether body is chunked encoding, for reader only.
  200 + */
546 virtual bool is_chunked(); 201 virtual bool is_chunked();
547 /** 202 /**
548 * whether should keep the connection alive. 203 * whether should keep the connection alive.
549 */ 204 */
550 virtual bool is_keep_alive(); 205 virtual bool is_keep_alive();
551 /** 206 /**
552 - * the uri contains the host and path.  
553 - */ 207 + * the uri contains the host and path.
  208 + */
554 virtual std::string uri(); 209 virtual std::string uri();
555 /** 210 /**
556 - * the url maybe the path.  
557 - */ 211 + * the url maybe the path.
  212 + */
558 virtual std::string url(); 213 virtual std::string url();
559 virtual std::string host(); 214 virtual std::string host();
560 virtual std::string path(); 215 virtual std::string path();
561 virtual std::string ext(); 216 virtual std::string ext();
562 public: 217 public:
563 /** 218 /**
564 - * read body to string.  
565 - * @remark for small http body.  
566 - */ 219 + * read body to string.
  220 + * @remark for small http body.
  221 + */
567 virtual int body_read_all(std::string& body); 222 virtual int body_read_all(std::string& body);
568 /** 223 /**
569 - * get the body reader, to read one by one.  
570 - * @remark when body is very large, or chunked, use this.  
571 - */ 224 + * get the body reader, to read one by one.
  225 + * @remark when body is very large, or chunked, use this.
  226 + */
572 virtual ISrsHttpResponseReader* body_reader(); 227 virtual ISrsHttpResponseReader* body_reader();
573 /** 228 /**
574 - * the content length, -1 for chunked or not set.  
575 - */ 229 + * the content length, -1 for chunked or not set.
  230 + */
576 virtual int64_t content_length(); 231 virtual int64_t content_length();
577 /** 232 /**
578 - * get the param in query string,  
579 - * for instance, query is "start=100&end=200",  
580 - * then query_get("start") is "100", and query_get("end") is "200"  
581 - */ 233 + * get the param in query string,
  234 + * for instance, query is "start=100&end=200",
  235 + * then query_get("start") is "100", and query_get("end") is "200"
  236 + */
582 virtual std::string query_get(std::string key); 237 virtual std::string query_get(std::string key);
583 /** 238 /**
584 - * get the headers.  
585 - */ 239 + * get the headers.
  240 + */
586 virtual int request_header_count(); 241 virtual int request_header_count();
587 virtual std::string request_header_key_at(int index); 242 virtual std::string request_header_key_at(int index);
588 virtual std::string request_header_value_at(int index); 243 virtual std::string request_header_value_at(int index);
589 virtual std::string get_request_header(std::string name); 244 virtual std::string get_request_header(std::string name);
590 public: 245 public:
591 /** 246 /**
592 - * convert the http message to a request.  
593 - * @remark user must free the return request.  
594 - */ 247 + * convert the http message to a request.
  248 + * @remark user must free the return request.
  249 + */
595 virtual SrsRequest* to_request(std::string vhost); 250 virtual SrsRequest* to_request(std::string vhost);
596 }; 251 };
597 252
@@ -631,7 +286,7 @@ public: @@ -631,7 +286,7 @@ public:
631 * or error and *ppmsg must be NULL. 286 * or error and *ppmsg must be NULL.
632 * @remark, if success, *ppmsg always NOT-NULL, *ppmsg always is_complete(). 287 * @remark, if success, *ppmsg always NOT-NULL, *ppmsg always is_complete().
633 */ 288 */
634 - virtual int parse_message(SrsStSocket* skt, SrsConnection* conn, SrsHttpMessage** ppmsg); 289 + virtual int parse_message(SrsStSocket* skt, SrsConnection* conn, ISrsHttpMessage** ppmsg);
635 private: 290 private:
636 /** 291 /**
637 * parse the HTTP message to member field: msg. 292 * parse the HTTP message to member field: msg.
@@ -48,7 +48,7 @@ SrsGoApiRoot::~SrsGoApiRoot() @@ -48,7 +48,7 @@ SrsGoApiRoot::~SrsGoApiRoot()
48 { 48 {
49 } 49 }
50 50
51 -int SrsGoApiRoot::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 51 +int SrsGoApiRoot::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
52 { 52 {
53 std::stringstream ss; 53 std::stringstream ss;
54 54
@@ -70,7 +70,7 @@ SrsGoApiApi::~SrsGoApiApi() @@ -70,7 +70,7 @@ SrsGoApiApi::~SrsGoApiApi()
70 { 70 {
71 } 71 }
72 72
73 -int SrsGoApiApi::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 73 +int SrsGoApiApi::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
74 { 74 {
75 std::stringstream ss; 75 std::stringstream ss;
76 76
@@ -92,7 +92,7 @@ SrsGoApiV1::~SrsGoApiV1() @@ -92,7 +92,7 @@ SrsGoApiV1::~SrsGoApiV1()
92 { 92 {
93 } 93 }
94 94
95 -int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 95 +int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
96 { 96 {
97 std::stringstream ss; 97 std::stringstream ss;
98 98
@@ -123,7 +123,7 @@ SrsGoApiVersion::~SrsGoApiVersion() @@ -123,7 +123,7 @@ SrsGoApiVersion::~SrsGoApiVersion()
123 { 123 {
124 } 124 }
125 125
126 -int SrsGoApiVersion::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 126 +int SrsGoApiVersion::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
127 { 127 {
128 std::stringstream ss; 128 std::stringstream ss;
129 129
@@ -148,7 +148,7 @@ SrsGoApiSummaries::~SrsGoApiSummaries() @@ -148,7 +148,7 @@ SrsGoApiSummaries::~SrsGoApiSummaries()
148 { 148 {
149 } 149 }
150 150
151 -int SrsGoApiSummaries::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 151 +int SrsGoApiSummaries::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
152 { 152 {
153 std::stringstream ss; 153 std::stringstream ss;
154 srs_api_dump_summaries(ss); 154 srs_api_dump_summaries(ss);
@@ -163,7 +163,7 @@ SrsGoApiRusages::~SrsGoApiRusages() @@ -163,7 +163,7 @@ SrsGoApiRusages::~SrsGoApiRusages()
163 { 163 {
164 } 164 }
165 165
166 -int SrsGoApiRusages::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* req) 166 +int SrsGoApiRusages::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* req)
167 { 167 {
168 std::stringstream ss; 168 std::stringstream ss;
169 169
@@ -204,7 +204,7 @@ SrsGoApiSelfProcStats::~SrsGoApiSelfProcStats() @@ -204,7 +204,7 @@ SrsGoApiSelfProcStats::~SrsGoApiSelfProcStats()
204 { 204 {
205 } 205 }
206 206
207 -int SrsGoApiSelfProcStats::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 207 +int SrsGoApiSelfProcStats::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
208 { 208 {
209 std::stringstream ss; 209 std::stringstream ss;
210 210
@@ -274,7 +274,7 @@ SrsGoApiSystemProcStats::~SrsGoApiSystemProcStats() @@ -274,7 +274,7 @@ SrsGoApiSystemProcStats::~SrsGoApiSystemProcStats()
274 { 274 {
275 } 275 }
276 276
277 -int SrsGoApiSystemProcStats::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 277 +int SrsGoApiSystemProcStats::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
278 { 278 {
279 std::stringstream ss; 279 std::stringstream ss;
280 280
@@ -309,7 +309,7 @@ SrsGoApiMemInfos::~SrsGoApiMemInfos() @@ -309,7 +309,7 @@ SrsGoApiMemInfos::~SrsGoApiMemInfos()
309 { 309 {
310 } 310 }
311 311
312 -int SrsGoApiMemInfos::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 312 +int SrsGoApiMemInfos::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
313 { 313 {
314 std::stringstream ss; 314 std::stringstream ss;
315 315
@@ -345,7 +345,7 @@ SrsGoApiAuthors::~SrsGoApiAuthors() @@ -345,7 +345,7 @@ SrsGoApiAuthors::~SrsGoApiAuthors()
345 { 345 {
346 } 346 }
347 347
348 -int SrsGoApiAuthors::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 348 +int SrsGoApiAuthors::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
349 { 349 {
350 std::stringstream ss; 350 std::stringstream ss;
351 351
@@ -370,9 +370,9 @@ SrsGoApiRequests::~SrsGoApiRequests() @@ -370,9 +370,9 @@ SrsGoApiRequests::~SrsGoApiRequests()
370 { 370 {
371 } 371 }
372 372
373 -int SrsGoApiRequests::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 373 +int SrsGoApiRequests::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
374 { 374 {
375 - SrsHttpMessage* req = r; 375 + ISrsHttpMessage* req = r;
376 376
377 std::stringstream ss; 377 std::stringstream ss;
378 378
@@ -431,7 +431,7 @@ SrsGoApiVhosts::~SrsGoApiVhosts() @@ -431,7 +431,7 @@ SrsGoApiVhosts::~SrsGoApiVhosts()
431 { 431 {
432 } 432 }
433 433
434 -int SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 434 +int SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
435 { 435 {
436 std::stringstream data; 436 std::stringstream data;
437 SrsStatistic* stat = SrsStatistic::instance(); 437 SrsStatistic* stat = SrsStatistic::instance();
@@ -456,7 +456,7 @@ SrsGoApiStreams::~SrsGoApiStreams() @@ -456,7 +456,7 @@ SrsGoApiStreams::~SrsGoApiStreams()
456 { 456 {
457 } 457 }
458 458
459 -int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 459 +int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
460 { 460 {
461 std::stringstream data; 461 std::stringstream data;
462 SrsStatistic* stat = SrsStatistic::instance(); 462 SrsStatistic* stat = SrsStatistic::instance();
@@ -529,7 +529,7 @@ int SrsHttpApi::do_cycle() @@ -529,7 +529,7 @@ int SrsHttpApi::do_cycle()
529 529
530 // process http messages. 530 // process http messages.
531 for (;;) { 531 for (;;) {
532 - SrsHttpMessage* req = NULL; 532 + ISrsHttpMessage* req = NULL;
533 533
534 // get a http message 534 // get a http message
535 if ((ret = parser->parse_message(&skt, this, &req)) != ERROR_SUCCESS) { 535 if ((ret = parser->parse_message(&skt, this, &req)) != ERROR_SUCCESS) {
@@ -540,7 +540,7 @@ int SrsHttpApi::do_cycle() @@ -540,7 +540,7 @@ int SrsHttpApi::do_cycle()
540 srs_assert(req); 540 srs_assert(req);
541 541
542 // always free it in this scope. 542 // always free it in this scope.
543 - SrsAutoFree(SrsHttpMessage, req); 543 + SrsAutoFree(ISrsHttpMessage, req);
544 544
545 // TODO: FIXME: use the post body. 545 // TODO: FIXME: use the post body.
546 std::string res; 546 std::string res;
@@ -566,7 +566,7 @@ int SrsHttpApi::do_cycle() @@ -566,7 +566,7 @@ int SrsHttpApi::do_cycle()
566 return ret; 566 return ret;
567 } 567 }
568 568
569 -int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 569 +int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
570 { 570 {
571 int ret = ERROR_SUCCESS; 571 int ret = ERROR_SUCCESS;
572 572
@@ -33,7 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -33,7 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #ifdef SRS_AUTO_HTTP_API 33 #ifdef SRS_AUTO_HTTP_API
34 34
35 class SrsStSocket; 35 class SrsStSocket;
36 -class SrsHttpMessage; 36 +class ISrsHttpMessage;
37 class SrsHttpParser; 37 class SrsHttpParser;
38 class SrsHttpHandler; 38 class SrsHttpHandler;
39 39
@@ -48,7 +48,7 @@ public: @@ -48,7 +48,7 @@ public:
48 SrsGoApiRoot(); 48 SrsGoApiRoot();
49 virtual ~SrsGoApiRoot(); 49 virtual ~SrsGoApiRoot();
50 public: 50 public:
51 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 51 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
52 }; 52 };
53 53
54 class SrsGoApiApi : public ISrsHttpHandler 54 class SrsGoApiApi : public ISrsHttpHandler
@@ -57,7 +57,7 @@ public: @@ -57,7 +57,7 @@ public:
57 SrsGoApiApi(); 57 SrsGoApiApi();
58 virtual ~SrsGoApiApi(); 58 virtual ~SrsGoApiApi();
59 public: 59 public:
60 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 60 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
61 }; 61 };
62 62
63 class SrsGoApiV1 : public ISrsHttpHandler 63 class SrsGoApiV1 : public ISrsHttpHandler
@@ -66,7 +66,7 @@ public: @@ -66,7 +66,7 @@ public:
66 SrsGoApiV1(); 66 SrsGoApiV1();
67 virtual ~SrsGoApiV1(); 67 virtual ~SrsGoApiV1();
68 public: 68 public:
69 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 69 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
70 }; 70 };
71 71
72 class SrsGoApiVersion : public ISrsHttpHandler 72 class SrsGoApiVersion : public ISrsHttpHandler
@@ -75,7 +75,7 @@ public: @@ -75,7 +75,7 @@ public:
75 SrsGoApiVersion(); 75 SrsGoApiVersion();
76 virtual ~SrsGoApiVersion(); 76 virtual ~SrsGoApiVersion();
77 public: 77 public:
78 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 78 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
79 }; 79 };
80 80
81 class SrsGoApiSummaries : public ISrsHttpHandler 81 class SrsGoApiSummaries : public ISrsHttpHandler
@@ -84,7 +84,7 @@ public: @@ -84,7 +84,7 @@ public:
84 SrsGoApiSummaries(); 84 SrsGoApiSummaries();
85 virtual ~SrsGoApiSummaries(); 85 virtual ~SrsGoApiSummaries();
86 public: 86 public:
87 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 87 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
88 }; 88 };
89 89
90 class SrsGoApiRusages : public ISrsHttpHandler 90 class SrsGoApiRusages : public ISrsHttpHandler
@@ -93,7 +93,7 @@ public: @@ -93,7 +93,7 @@ public:
93 SrsGoApiRusages(); 93 SrsGoApiRusages();
94 virtual ~SrsGoApiRusages(); 94 virtual ~SrsGoApiRusages();
95 public: 95 public:
96 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 96 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
97 }; 97 };
98 98
99 class SrsGoApiSelfProcStats : public ISrsHttpHandler 99 class SrsGoApiSelfProcStats : public ISrsHttpHandler
@@ -102,7 +102,7 @@ public: @@ -102,7 +102,7 @@ public:
102 SrsGoApiSelfProcStats(); 102 SrsGoApiSelfProcStats();
103 virtual ~SrsGoApiSelfProcStats(); 103 virtual ~SrsGoApiSelfProcStats();
104 public: 104 public:
105 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 105 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
106 }; 106 };
107 107
108 class SrsGoApiSystemProcStats : public ISrsHttpHandler 108 class SrsGoApiSystemProcStats : public ISrsHttpHandler
@@ -111,7 +111,7 @@ public: @@ -111,7 +111,7 @@ public:
111 SrsGoApiSystemProcStats(); 111 SrsGoApiSystemProcStats();
112 virtual ~SrsGoApiSystemProcStats(); 112 virtual ~SrsGoApiSystemProcStats();
113 public: 113 public:
114 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 114 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
115 }; 115 };
116 116
117 class SrsGoApiMemInfos : public ISrsHttpHandler 117 class SrsGoApiMemInfos : public ISrsHttpHandler
@@ -120,7 +120,7 @@ public: @@ -120,7 +120,7 @@ public:
120 SrsGoApiMemInfos(); 120 SrsGoApiMemInfos();
121 virtual ~SrsGoApiMemInfos(); 121 virtual ~SrsGoApiMemInfos();
122 public: 122 public:
123 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 123 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
124 }; 124 };
125 125
126 class SrsGoApiAuthors : public ISrsHttpHandler 126 class SrsGoApiAuthors : public ISrsHttpHandler
@@ -129,7 +129,7 @@ public: @@ -129,7 +129,7 @@ public:
129 SrsGoApiAuthors(); 129 SrsGoApiAuthors();
130 virtual ~SrsGoApiAuthors(); 130 virtual ~SrsGoApiAuthors();
131 public: 131 public:
132 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 132 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
133 }; 133 };
134 134
135 class SrsGoApiRequests : public ISrsHttpHandler 135 class SrsGoApiRequests : public ISrsHttpHandler
@@ -138,7 +138,7 @@ public: @@ -138,7 +138,7 @@ public:
138 SrsGoApiRequests(); 138 SrsGoApiRequests();
139 virtual ~SrsGoApiRequests(); 139 virtual ~SrsGoApiRequests();
140 public: 140 public:
141 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 141 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
142 }; 142 };
143 143
144 class SrsGoApiVhosts : public ISrsHttpHandler 144 class SrsGoApiVhosts : public ISrsHttpHandler
@@ -147,7 +147,7 @@ public: @@ -147,7 +147,7 @@ public:
147 SrsGoApiVhosts(); 147 SrsGoApiVhosts();
148 virtual ~SrsGoApiVhosts(); 148 virtual ~SrsGoApiVhosts();
149 public: 149 public:
150 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 150 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
151 }; 151 };
152 152
153 class SrsGoApiStreams : public ISrsHttpHandler 153 class SrsGoApiStreams : public ISrsHttpHandler
@@ -156,7 +156,7 @@ public: @@ -156,7 +156,7 @@ public:
156 SrsGoApiStreams(); 156 SrsGoApiStreams();
157 virtual ~SrsGoApiStreams(); 157 virtual ~SrsGoApiStreams();
158 public: 158 public:
159 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 159 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
160 }; 160 };
161 161
162 class SrsHttpApi : public SrsConnection 162 class SrsHttpApi : public SrsConnection
@@ -177,7 +177,7 @@ public: @@ -177,7 +177,7 @@ public:
177 protected: 177 protected:
178 virtual int do_cycle(); 178 virtual int do_cycle();
179 private: 179 private:
180 - virtual int process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 180 + virtual int process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
181 }; 181 };
182 182
183 #endif 183 #endif
@@ -71,7 +71,7 @@ int SrsHttpClient::initialize(string h, int p, int64_t t_us) @@ -71,7 +71,7 @@ int SrsHttpClient::initialize(string h, int p, int64_t t_us)
71 return ret; 71 return ret;
72 } 72 }
73 73
74 -int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) 74 +int SrsHttpClient::post(string path, string req, ISrsHttpMessage** ppmsg)
75 { 75 {
76 *ppmsg = NULL; 76 *ppmsg = NULL;
77 77
@@ -104,7 +104,7 @@ int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) @@ -104,7 +104,7 @@ int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg)
104 return ret; 104 return ret;
105 } 105 }
106 106
107 - SrsHttpMessage* msg = NULL; 107 + ISrsHttpMessage* msg = NULL;
108 if ((ret = parser->parse_message(skt, NULL, &msg)) != ERROR_SUCCESS) { 108 if ((ret = parser->parse_message(skt, NULL, &msg)) != ERROR_SUCCESS) {
109 srs_error("parse http post response failed. ret=%d", ret); 109 srs_error("parse http post response failed. ret=%d", ret);
110 return ret; 110 return ret;
@@ -117,7 +117,7 @@ int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) @@ -117,7 +117,7 @@ int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg)
117 return ret; 117 return ret;
118 } 118 }
119 119
120 -int SrsHttpClient::get(string path, std::string req, SrsHttpMessage** ppmsg) 120 +int SrsHttpClient::get(string path, std::string req, ISrsHttpMessage** ppmsg)
121 { 121 {
122 *ppmsg = NULL; 122 *ppmsg = NULL;
123 123
@@ -150,7 +150,7 @@ int SrsHttpClient::get(string path, std::string req, SrsHttpMessage** ppmsg) @@ -150,7 +150,7 @@ int SrsHttpClient::get(string path, std::string req, SrsHttpMessage** ppmsg)
150 return ret; 150 return ret;
151 } 151 }
152 152
153 - SrsHttpMessage* msg = NULL; 153 + ISrsHttpMessage* msg = NULL;
154 if ((ret = parser->parse_message(skt, NULL, &msg)) != ERROR_SUCCESS) { 154 if ((ret = parser->parse_message(skt, NULL, &msg)) != ERROR_SUCCESS) {
155 srs_error("parse http post response failed. ret=%d", ret); 155 srs_error("parse http post response failed. ret=%d", ret);
156 return ret; 156 return ret;
@@ -37,7 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -37,7 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 37
38 class SrsHttpUri; 38 class SrsHttpUri;
39 class SrsHttpParser; 39 class SrsHttpParser;
40 -class SrsHttpMessage; 40 +class ISrsHttpMessage;
41 class SrsStSocket; 41 class SrsStSocket;
42 42
43 // the default timeout for http client. 43 // the default timeout for http client.
@@ -73,14 +73,14 @@ public: @@ -73,14 +73,14 @@ public:
73 * @param req the data post to uri. empty string to ignore. 73 * @param req the data post to uri. empty string to ignore.
74 * @param ppmsg output the http message to read the response. 74 * @param ppmsg output the http message to read the response.
75 */ 75 */
76 - virtual int post(std::string path, std::string req, SrsHttpMessage** ppmsg); 76 + virtual int post(std::string path, std::string req, ISrsHttpMessage** ppmsg);
77 /** 77 /**
78 * to get data from the uri. 78 * to get data from the uri.
79 * @param the path to request on. 79 * @param the path to request on.
80 * @param req the data post to uri. empty string to ignore. 80 * @param req the data post to uri. empty string to ignore.
81 * @param ppmsg output the http message to read the response. 81 * @param ppmsg output the http message to read the response.
82 */ 82 */
83 - virtual int get(std::string path, std::string req, SrsHttpMessage** ppmsg); 83 + virtual int get(std::string path, std::string req, ISrsHttpMessage** ppmsg);
84 private: 84 private:
85 virtual void disconnect(); 85 virtual void disconnect();
86 virtual int connect(); 86 virtual int connect();
@@ -60,7 +60,7 @@ SrsVodStream::~SrsVodStream() @@ -60,7 +60,7 @@ SrsVodStream::~SrsVodStream()
60 { 60 {
61 } 61 }
62 62
63 -int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) 63 +int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int offset)
64 { 64 {
65 int ret = ERROR_SUCCESS; 65 int ret = ERROR_SUCCESS;
66 66
@@ -144,7 +144,7 @@ int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, @@ -144,7 +144,7 @@ int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r,
144 return ret; 144 return ret;
145 } 145 }
146 146
147 -int SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end) 147 +int SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int start, int end)
148 { 148 {
149 int ret = ERROR_SUCCESS; 149 int ret = ERROR_SUCCESS;
150 150
@@ -567,7 +567,7 @@ SrsLiveStream::~SrsLiveStream() @@ -567,7 +567,7 @@ SrsLiveStream::~SrsLiveStream()
567 srs_freep(req); 567 srs_freep(req);
568 } 568 }
569 569
570 -int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 570 +int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
571 { 571 {
572 int ret = ERROR_SUCCESS; 572 int ret = ERROR_SUCCESS;
573 573
@@ -743,7 +743,7 @@ void SrsHlsM3u8Stream::set_m3u8(std::string v) @@ -743,7 +743,7 @@ void SrsHlsM3u8Stream::set_m3u8(std::string v)
743 m3u8 = v; 743 m3u8 = v;
744 } 744 }
745 745
746 -int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 746 +int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
747 { 747 {
748 int ret = ERROR_SUCCESS; 748 int ret = ERROR_SUCCESS;
749 749
@@ -775,7 +775,7 @@ void SrsHlsTsStream::set_ts(std::string v) @@ -775,7 +775,7 @@ void SrsHlsTsStream::set_ts(std::string v)
775 ts = v; 775 ts = v;
776 } 776 }
777 777
778 -int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 778 +int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
779 { 779 {
780 int ret = ERROR_SUCCESS; 780 int ret = ERROR_SUCCESS;
781 781
@@ -1110,7 +1110,7 @@ int SrsHttpServer::on_reload_vhost_hls(string vhost) @@ -1110,7 +1110,7 @@ int SrsHttpServer::on_reload_vhost_hls(string vhost)
1110 return ret; 1110 return ret;
1111 } 1111 }
1112 1112
1113 -int SrsHttpServer::hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) 1113 +int SrsHttpServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph)
1114 { 1114 {
1115 int ret = ERROR_SUCCESS; 1115 int ret = ERROR_SUCCESS;
1116 1116
@@ -1169,8 +1169,12 @@ int SrsHttpServer::hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) @@ -1169,8 +1169,12 @@ int SrsHttpServer::hijack(SrsHttpMessage* request, ISrsHttpHandler** ph)
1169 } 1169 }
1170 } 1170 }
1171 1171
  1172 + // convert to concreate class.
  1173 + SrsHttpMessage* hreq = dynamic_cast<SrsHttpMessage*>(request);
  1174 + srs_assert(hreq);
  1175 +
1172 // hijack for entry. 1176 // hijack for entry.
1173 - SrsRequest* r = request->to_request(vhost->arg0()); 1177 + SrsRequest* r = hreq->to_request(vhost->arg0());
1174 SrsAutoFree(SrsRequest, r); 1178 SrsAutoFree(SrsRequest, r);
1175 SrsSource* s = SrsSource::fetch(r); 1179 SrsSource* s = SrsSource::fetch(r);
1176 if (!s) { 1180 if (!s) {
@@ -1389,7 +1393,7 @@ int SrsHttpConn::do_cycle() @@ -1389,7 +1393,7 @@ int SrsHttpConn::do_cycle()
1389 1393
1390 // process http messages. 1394 // process http messages.
1391 for (;;) { 1395 for (;;) {
1392 - SrsHttpMessage* req = NULL; 1396 + ISrsHttpMessage* req = NULL;
1393 1397
1394 // get a http message 1398 // get a http message
1395 if ((ret = parser->parse_message(&skt, this, &req)) != ERROR_SUCCESS) { 1399 if ((ret = parser->parse_message(&skt, this, &req)) != ERROR_SUCCESS) {
@@ -1400,7 +1404,7 @@ int SrsHttpConn::do_cycle() @@ -1400,7 +1404,7 @@ int SrsHttpConn::do_cycle()
1400 srs_assert(req); 1404 srs_assert(req);
1401 1405
1402 // always free it in this scope. 1406 // always free it in this scope.
1403 - SrsAutoFree(SrsHttpMessage, req); 1407 + SrsAutoFree(ISrsHttpMessage, req);
1404 1408
1405 // may should discard the body. 1409 // may should discard the body.
1406 if ((ret = on_got_http_message(req)) != ERROR_SUCCESS) { 1410 if ((ret = on_got_http_message(req)) != ERROR_SUCCESS) {
@@ -1423,7 +1427,7 @@ int SrsHttpConn::do_cycle() @@ -1423,7 +1427,7 @@ int SrsHttpConn::do_cycle()
1423 return ret; 1427 return ret;
1424 } 1428 }
1425 1429
1426 -int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r) 1430 +int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
1427 { 1431 {
1428 int ret = ERROR_SUCCESS; 1432 int ret = ERROR_SUCCESS;
1429 1433
@@ -1450,7 +1454,7 @@ SrsStaticHttpConn::~SrsStaticHttpConn() @@ -1450,7 +1454,7 @@ SrsStaticHttpConn::~SrsStaticHttpConn()
1450 { 1454 {
1451 } 1455 }
1452 1456
1453 -int SrsStaticHttpConn::on_got_http_message(SrsHttpMessage* msg) 1457 +int SrsStaticHttpConn::on_got_http_message(ISrsHttpMessage* msg)
1454 { 1458 {
1455 int ret = ERROR_SUCCESS; 1459 int ret = ERROR_SUCCESS;
1456 1460
@@ -49,7 +49,7 @@ class SrsAacEncoder; @@ -49,7 +49,7 @@ class SrsAacEncoder;
49 class SrsMp3Encoder; 49 class SrsMp3Encoder;
50 class SrsFlvEncoder; 50 class SrsFlvEncoder;
51 class SrsHttpParser; 51 class SrsHttpParser;
52 -class SrsHttpMessage; 52 +class ISrsHttpMessage;
53 class SrsHttpHandler; 53 class SrsHttpHandler;
54 class SrsMessageQueue; 54 class SrsMessageQueue;
55 class SrsSharedPtrMessage; 55 class SrsSharedPtrMessage;
@@ -66,8 +66,8 @@ public: @@ -66,8 +66,8 @@ public:
66 SrsVodStream(std::string root_dir); 66 SrsVodStream(std::string root_dir);
67 virtual ~SrsVodStream(); 67 virtual ~SrsVodStream();
68 protected: 68 protected:
69 - virtual int serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset);  
70 - virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int start, int end); 69 + virtual int serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int offset);
  70 + virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int start, int end);
71 }; 71 };
72 72
73 /** 73 /**
@@ -243,7 +243,7 @@ public: @@ -243,7 +243,7 @@ public:
243 SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c); 243 SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c);
244 virtual ~SrsLiveStream(); 244 virtual ~SrsLiveStream();
245 public: 245 public:
246 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 246 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
247 private: 247 private:
248 virtual int streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs); 248 virtual int streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs);
249 }; 249 };
@@ -289,7 +289,7 @@ public: @@ -289,7 +289,7 @@ public:
289 public: 289 public:
290 virtual void set_m3u8(std::string v); 290 virtual void set_m3u8(std::string v);
291 public: 291 public:
292 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 292 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
293 }; 293 };
294 294
295 /** 295 /**
@@ -305,7 +305,7 @@ public: @@ -305,7 +305,7 @@ public:
305 public: 305 public:
306 virtual void set_ts(std::string v); 306 virtual void set_ts(std::string v);
307 public: 307 public:
308 - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 308 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
309 }; 309 };
310 310
311 /** 311 /**
@@ -365,7 +365,7 @@ public: @@ -365,7 +365,7 @@ public:
365 virtual int on_reload_vhost_hls(std::string vhost); 365 virtual int on_reload_vhost_hls(std::string vhost);
366 // interface ISrsHttpMatchHijacker 366 // interface ISrsHttpMatchHijacker
367 public: 367 public:
368 - virtual int hijack(SrsHttpMessage* request, ISrsHttpHandler** ph); 368 + virtual int hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph);
369 private: 369 private:
370 virtual int initialize_static_file(); 370 virtual int initialize_static_file();
371 virtual int initialize_flv_streaming(); 371 virtual int initialize_flv_streaming();
@@ -392,9 +392,9 @@ protected: @@ -392,9 +392,9 @@ protected:
392 // when got http message, 392 // when got http message,
393 // for the static service or api, discard any body. 393 // for the static service or api, discard any body.
394 // for the stream caster, for instance, http flv streaming, may discard the flv header or not. 394 // for the stream caster, for instance, http flv streaming, may discard the flv header or not.
395 - virtual int on_got_http_message(SrsHttpMessage* msg) = 0; 395 + virtual int on_got_http_message(ISrsHttpMessage* msg) = 0;
396 private: 396 private:
397 - virtual int process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r); 397 + virtual int process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
398 }; 398 };
399 399
400 class SrsStaticHttpConn : public SrsHttpConn 400 class SrsStaticHttpConn : public SrsHttpConn
@@ -403,7 +403,7 @@ public: @@ -403,7 +403,7 @@ public:
403 SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m); 403 SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m);
404 virtual ~SrsStaticHttpConn(); 404 virtual ~SrsStaticHttpConn();
405 public: 405 public:
406 - virtual int on_got_http_message(SrsHttpMessage* msg); 406 + virtual int on_got_http_message(ISrsHttpMessage* msg);
407 }; 407 };
408 408
409 #endif 409 #endif
@@ -371,11 +371,11 @@ int SrsHttpHooks::on_hls_notify(std::string url, SrsRequest* req, std::string ts @@ -371,11 +371,11 @@ int SrsHttpHooks::on_hls_notify(std::string url, SrsRequest* req, std::string ts
371 } 371 }
372 srs_warn("GET %s", path.c_str()); 372 srs_warn("GET %s", path.c_str());
373 373
374 - SrsHttpMessage* msg = NULL; 374 + ISrsHttpMessage* msg = NULL;
375 if ((ret = http.get(path.c_str(), "", &msg)) != ERROR_SUCCESS) { 375 if ((ret = http.get(path.c_str(), "", &msg)) != ERROR_SUCCESS) {
376 return ret; 376 return ret;
377 } 377 }
378 - SrsAutoFree(SrsHttpMessage, msg); 378 + SrsAutoFree(ISrsHttpMessage, msg);
379 379
380 int nb_buf = srs_min(nb_notify, SRS_HTTP_READ_BUFFER); 380 int nb_buf = srs_min(nb_notify, SRS_HTTP_READ_BUFFER);
381 char* buf = new char[nb_buf]; 381 char* buf = new char[nb_buf];
@@ -416,11 +416,11 @@ int SrsHttpHooks::do_post(std::string url, std::string req, int& code, string& r @@ -416,11 +416,11 @@ int SrsHttpHooks::do_post(std::string url, std::string req, int& code, string& r
416 return ret; 416 return ret;
417 } 417 }
418 418
419 - SrsHttpMessage* msg = NULL; 419 + ISrsHttpMessage* msg = NULL;
420 if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) { 420 if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) {
421 return ret; 421 return ret;
422 } 422 }
423 - SrsAutoFree(SrsHttpMessage, msg); 423 + SrsAutoFree(ISrsHttpMessage, msg);
424 424
425 code = msg->status_code(); 425 code = msg->status_code();
426 if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) { 426 if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) {
@@ -383,14 +383,14 @@ int SrsIngestSrsInput::parseM3u8(SrsHttpUri* url, double& td, double& duration) @@ -383,14 +383,14 @@ int SrsIngestSrsInput::parseM3u8(SrsHttpUri* url, double& td, double& duration)
383 return ret; 383 return ret;
384 } 384 }
385 385
386 - SrsHttpMessage* msg = NULL; 386 + ISrsHttpMessage* msg = NULL;
387 if ((ret = client.get(url->get_path(), "", &msg)) != ERROR_SUCCESS) { 387 if ((ret = client.get(url->get_path(), "", &msg)) != ERROR_SUCCESS) {
388 srs_error("HTTP GET %s failed. ret=%d", url->get_url(), ret); 388 srs_error("HTTP GET %s failed. ret=%d", url->get_url(), ret);
389 return ret; 389 return ret;
390 } 390 }
391 391
392 srs_assert(msg); 392 srs_assert(msg);
393 - SrsAutoFree(SrsHttpMessage, msg); 393 + SrsAutoFree(ISrsHttpMessage, msg);
394 394
395 std::string body; 395 std::string body;
396 if ((ret = msg->body_read_all(body)) != ERROR_SUCCESS) { 396 if ((ret = msg->body_read_all(body)) != ERROR_SUCCESS) {
@@ -605,14 +605,14 @@ int SrsIngestSrsInput::SrsTsPiece::fetch(string m3u8) @@ -605,14 +605,14 @@ int SrsIngestSrsInput::SrsTsPiece::fetch(string m3u8)
605 return ret; 605 return ret;
606 } 606 }
607 607
608 - SrsHttpMessage* msg = NULL; 608 + ISrsHttpMessage* msg = NULL;
609 if ((ret = client.get(uri.get_path(), "", &msg)) != ERROR_SUCCESS) { 609 if ((ret = client.get(uri.get_path(), "", &msg)) != ERROR_SUCCESS) {
610 srs_error("HTTP GET %s failed. ret=%d", uri.get_url(), ret); 610 srs_error("HTTP GET %s failed. ret=%d", uri.get_url(), ret);
611 return ret; 611 return ret;
612 } 612 }
613 613
614 srs_assert(msg); 614 srs_assert(msg);
615 - SrsAutoFree(SrsHttpMessage, msg); 615 + SrsAutoFree(ISrsHttpMessage, msg);
616 616
617 if ((ret = msg->body_read_all(body)) != ERROR_SUCCESS) { 617 if ((ret = msg->body_read_all(body)) != ERROR_SUCCESS) {
618 srs_error("read ts failed. ret=%d", ret); 618 srs_error("read ts failed. ret=%d", ret);
@@ -22,3 +22,717 @@ @@ -22,3 +22,717 @@
22 */ 22 */
23 23
24 #include <srs_http_stack.hpp> 24 #include <srs_http_stack.hpp>
  25 +
  26 +#include <sstream>
  27 +using namespace std;
  28 +
  29 +#include <srs_kernel_error.hpp>
  30 +#include <srs_kernel_log.hpp>
  31 +#include <srs_kernel_utility.hpp>
  32 +#include <srs_kernel_file.hpp>
  33 +
  34 +#define SRS_HTTP_DEFAULT_PAGE "index.html"
  35 +
  36 +// get the status text of code.
  37 +string srs_generate_http_status_text(int status)
  38 +{
  39 + static std::map<int, std::string> _status_map;
  40 + if (_status_map.empty()) {
  41 + _status_map[SRS_CONSTS_HTTP_Continue ] = SRS_CONSTS_HTTP_Continue_str ;
  42 + _status_map[SRS_CONSTS_HTTP_SwitchingProtocols ] = SRS_CONSTS_HTTP_SwitchingProtocols_str ;
  43 + _status_map[SRS_CONSTS_HTTP_OK ] = SRS_CONSTS_HTTP_OK_str ;
  44 + _status_map[SRS_CONSTS_HTTP_Created ] = SRS_CONSTS_HTTP_Created_str ;
  45 + _status_map[SRS_CONSTS_HTTP_Accepted ] = SRS_CONSTS_HTTP_Accepted_str ;
  46 + _status_map[SRS_CONSTS_HTTP_NonAuthoritativeInformation ] = SRS_CONSTS_HTTP_NonAuthoritativeInformation_str ;
  47 + _status_map[SRS_CONSTS_HTTP_NoContent ] = SRS_CONSTS_HTTP_NoContent_str ;
  48 + _status_map[SRS_CONSTS_HTTP_ResetContent ] = SRS_CONSTS_HTTP_ResetContent_str ;
  49 + _status_map[SRS_CONSTS_HTTP_PartialContent ] = SRS_CONSTS_HTTP_PartialContent_str ;
  50 + _status_map[SRS_CONSTS_HTTP_MultipleChoices ] = SRS_CONSTS_HTTP_MultipleChoices_str ;
  51 + _status_map[SRS_CONSTS_HTTP_MovedPermanently ] = SRS_CONSTS_HTTP_MovedPermanently_str ;
  52 + _status_map[SRS_CONSTS_HTTP_Found ] = SRS_CONSTS_HTTP_Found_str ;
  53 + _status_map[SRS_CONSTS_HTTP_SeeOther ] = SRS_CONSTS_HTTP_SeeOther_str ;
  54 + _status_map[SRS_CONSTS_HTTP_NotModified ] = SRS_CONSTS_HTTP_NotModified_str ;
  55 + _status_map[SRS_CONSTS_HTTP_UseProxy ] = SRS_CONSTS_HTTP_UseProxy_str ;
  56 + _status_map[SRS_CONSTS_HTTP_TemporaryRedirect ] = SRS_CONSTS_HTTP_TemporaryRedirect_str ;
  57 + _status_map[SRS_CONSTS_HTTP_BadRequest ] = SRS_CONSTS_HTTP_BadRequest_str ;
  58 + _status_map[SRS_CONSTS_HTTP_Unauthorized ] = SRS_CONSTS_HTTP_Unauthorized_str ;
  59 + _status_map[SRS_CONSTS_HTTP_PaymentRequired ] = SRS_CONSTS_HTTP_PaymentRequired_str ;
  60 + _status_map[SRS_CONSTS_HTTP_Forbidden ] = SRS_CONSTS_HTTP_Forbidden_str ;
  61 + _status_map[SRS_CONSTS_HTTP_NotFound ] = SRS_CONSTS_HTTP_NotFound_str ;
  62 + _status_map[SRS_CONSTS_HTTP_MethodNotAllowed ] = SRS_CONSTS_HTTP_MethodNotAllowed_str ;
  63 + _status_map[SRS_CONSTS_HTTP_NotAcceptable ] = SRS_CONSTS_HTTP_NotAcceptable_str ;
  64 + _status_map[SRS_CONSTS_HTTP_ProxyAuthenticationRequired ] = SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str ;
  65 + _status_map[SRS_CONSTS_HTTP_RequestTimeout ] = SRS_CONSTS_HTTP_RequestTimeout_str ;
  66 + _status_map[SRS_CONSTS_HTTP_Conflict ] = SRS_CONSTS_HTTP_Conflict_str ;
  67 + _status_map[SRS_CONSTS_HTTP_Gone ] = SRS_CONSTS_HTTP_Gone_str ;
  68 + _status_map[SRS_CONSTS_HTTP_LengthRequired ] = SRS_CONSTS_HTTP_LengthRequired_str ;
  69 + _status_map[SRS_CONSTS_HTTP_PreconditionFailed ] = SRS_CONSTS_HTTP_PreconditionFailed_str ;
  70 + _status_map[SRS_CONSTS_HTTP_RequestEntityTooLarge ] = SRS_CONSTS_HTTP_RequestEntityTooLarge_str ;
  71 + _status_map[SRS_CONSTS_HTTP_RequestURITooLarge ] = SRS_CONSTS_HTTP_RequestURITooLarge_str ;
  72 + _status_map[SRS_CONSTS_HTTP_UnsupportedMediaType ] = SRS_CONSTS_HTTP_UnsupportedMediaType_str ;
  73 + _status_map[SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable ] = SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str ;
  74 + _status_map[SRS_CONSTS_HTTP_ExpectationFailed ] = SRS_CONSTS_HTTP_ExpectationFailed_str ;
  75 + _status_map[SRS_CONSTS_HTTP_InternalServerError ] = SRS_CONSTS_HTTP_InternalServerError_str ;
  76 + _status_map[SRS_CONSTS_HTTP_NotImplemented ] = SRS_CONSTS_HTTP_NotImplemented_str ;
  77 + _status_map[SRS_CONSTS_HTTP_BadGateway ] = SRS_CONSTS_HTTP_BadGateway_str ;
  78 + _status_map[SRS_CONSTS_HTTP_ServiceUnavailable ] = SRS_CONSTS_HTTP_ServiceUnavailable_str ;
  79 + _status_map[SRS_CONSTS_HTTP_GatewayTimeout ] = SRS_CONSTS_HTTP_GatewayTimeout_str ;
  80 + _status_map[SRS_CONSTS_HTTP_HTTPVersionNotSupported ] = SRS_CONSTS_HTTP_HTTPVersionNotSupported_str ;
  81 + }
  82 +
  83 + std::string status_text;
  84 + if (_status_map.find(status) == _status_map.end()) {
  85 + status_text = "Status Unknown";
  86 + } else {
  87 + status_text = _status_map[status];
  88 + }
  89 +
  90 + return status_text;
  91 +}
  92 +
  93 +// bodyAllowedForStatus reports whether a given response status code
  94 +// permits a body. See RFC2616, section 4.4.
  95 +bool srs_go_http_body_allowd(int status)
  96 +{
  97 + if (status >= 100 && status <= 199) {
  98 + return false;
  99 + } else if (status == 204 || status == 304) {
  100 + return false;
  101 + }
  102 +
  103 + return true;
  104 +}
  105 +
  106 +// DetectContentType implements the algorithm described
  107 +// at http://mimesniff.spec.whatwg.org/ to determine the
  108 +// Content-Type of the given data. It considers at most the
  109 +// first 512 bytes of data. DetectContentType always returns
  110 +// a valid MIME type: if it cannot determine a more specific one, it
  111 +// returns "application/octet-stream".
  112 +string srs_go_http_detect(char* data, int size)
  113 +{
  114 + // detect only when data specified.
  115 + if (data) {
  116 + }
  117 + return "application/octet-stream"; // fallback
  118 +}
  119 +
  120 +// Error replies to the request with the specified error message and HTTP code.
  121 +// The error message should be plain text.
  122 +int srs_go_http_error(ISrsHttpResponseWriter* w, int code, string error)
  123 +{
  124 + int ret = ERROR_SUCCESS;
  125 +
  126 + w->header()->set_content_type("text/plain; charset=utf-8");
  127 + w->header()->set_content_length(error.length());
  128 + w->write_header(code);
  129 + w->write((char*)error.data(), (int)error.length());
  130 +
  131 + return ret;
  132 +}
  133 +
  134 +int srs_http_response_json(ISrsHttpResponseWriter* w, string data)
  135 +{
  136 + SrsHttpHeader* h = w->header();
  137 +
  138 + h->set_content_length(data.length());
  139 + h->set_content_type("application/json");
  140 +
  141 + return w->write((char*)data.data(), (int)data.length());
  142 +}
  143 +
  144 +SrsHttpHeader::SrsHttpHeader()
  145 +{
  146 +}
  147 +
  148 +SrsHttpHeader::~SrsHttpHeader()
  149 +{
  150 +}
  151 +
  152 +void SrsHttpHeader::set(string key, string value)
  153 +{
  154 + headers[key] = value;
  155 +}
  156 +
  157 +string SrsHttpHeader::get(string key)
  158 +{
  159 + std::string v;
  160 +
  161 + if (headers.find(key) != headers.end()) {
  162 + v = headers[key];
  163 + }
  164 +
  165 + return v;
  166 +}
  167 +
  168 +int64_t SrsHttpHeader::content_length()
  169 +{
  170 + std::string cl = get("Content-Length");
  171 +
  172 + if (cl.empty()) {
  173 + return -1;
  174 + }
  175 +
  176 + return (int64_t)::atof(cl.c_str());
  177 +}
  178 +
  179 +void SrsHttpHeader::set_content_length(int64_t size)
  180 +{
  181 + char buf[64];
  182 + snprintf(buf, sizeof(buf), "%"PRId64, size);
  183 + set("Content-Length", buf);
  184 +}
  185 +
  186 +string SrsHttpHeader::content_type()
  187 +{
  188 + return get("Content-Type");
  189 +}
  190 +
  191 +void SrsHttpHeader::set_content_type(string ct)
  192 +{
  193 + set("Content-Type", ct);
  194 +}
  195 +
  196 +void SrsHttpHeader::write(stringstream& ss)
  197 +{
  198 + std::map<std::string, std::string>::iterator it;
  199 + for (it = headers.begin(); it != headers.end(); ++it) {
  200 + ss << it->first << ": " << it->second << SRS_HTTP_CRLF;
  201 + }
  202 +}
  203 +
  204 +ISrsHttpResponseWriter::ISrsHttpResponseWriter()
  205 +{
  206 +}
  207 +
  208 +ISrsHttpResponseWriter::~ISrsHttpResponseWriter()
  209 +{
  210 +}
  211 +
  212 +ISrsHttpResponseReader::ISrsHttpResponseReader()
  213 +{
  214 +}
  215 +
  216 +ISrsHttpResponseReader::~ISrsHttpResponseReader()
  217 +{
  218 +}
  219 +
  220 +ISrsHttpHandler::ISrsHttpHandler()
  221 +{
  222 + entry = NULL;
  223 +}
  224 +
  225 +ISrsHttpHandler::~ISrsHttpHandler()
  226 +{
  227 +}
  228 +
  229 +SrsHttpRedirectHandler::SrsHttpRedirectHandler(string u, int c)
  230 +{
  231 + url = u;
  232 + code = c;
  233 +}
  234 +
  235 +SrsHttpRedirectHandler::~SrsHttpRedirectHandler()
  236 +{
  237 +}
  238 +
  239 +int SrsHttpRedirectHandler::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  240 +{
  241 + int ret = ERROR_SUCCESS;
  242 + // TODO: FIXME: implements it.
  243 + return ret;
  244 +}
  245 +
  246 +SrsHttpNotFoundHandler::SrsHttpNotFoundHandler()
  247 +{
  248 +}
  249 +
  250 +SrsHttpNotFoundHandler::~SrsHttpNotFoundHandler()
  251 +{
  252 +}
  253 +
  254 +int SrsHttpNotFoundHandler::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  255 +{
  256 + return srs_go_http_error(w, SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str);
  257 +}
  258 +
  259 +SrsHttpFileServer::SrsHttpFileServer(string root_dir)
  260 +{
  261 + dir = root_dir;
  262 +}
  263 +
  264 +SrsHttpFileServer::~SrsHttpFileServer()
  265 +{
  266 +}
  267 +
  268 +int SrsHttpFileServer::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  269 +{
  270 + string upath = r->path();
  271 +
  272 + // add default pages.
  273 + if (srs_string_ends_with(upath, "/")) {
  274 + upath += SRS_HTTP_DEFAULT_PAGE;
  275 + }
  276 +
  277 + string fullpath = dir + "/";
  278 +
  279 + // remove the virtual directory.
  280 + srs_assert(entry);
  281 + size_t pos = entry->pattern.find("/");
  282 + if (upath.length() > entry->pattern.length() && pos != string::npos) {
  283 + fullpath += upath.substr(entry->pattern.length() - pos);
  284 + } else {
  285 + fullpath += upath;
  286 + }
  287 +
  288 + // stat current dir, if exists, return error.
  289 + if (!srs_path_exists(fullpath)) {
  290 + srs_warn("http miss file=%s, pattern=%s, upath=%s",
  291 + fullpath.c_str(), entry->pattern.c_str(), upath.c_str());
  292 + return SrsHttpNotFoundHandler().serve_http(w, r);
  293 + }
  294 + srs_trace("http match file=%s, pattern=%s, upath=%s",
  295 + fullpath.c_str(), entry->pattern.c_str(), upath.c_str());
  296 +
  297 + // handle file according to its extension.
  298 + // use vod stream for .flv/.fhv
  299 + if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) {
  300 + return serve_flv_file(w, r, fullpath);
  301 + } else if (srs_string_ends_with(fullpath, ".mp4")) {
  302 + return serve_mp4_file(w, r, fullpath);
  303 + }
  304 +
  305 + // serve common static file.
  306 + return serve_file(w, r, fullpath);
  307 +}
  308 +
  309 +int SrsHttpFileServer::serve_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath)
  310 +{
  311 + int ret = ERROR_SUCCESS;
  312 +
  313 + // open the target file.
  314 + SrsFileReader fs;
  315 +
  316 + if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
  317 + srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
  318 + return ret;
  319 + }
  320 +
  321 + int64_t length = fs.filesize();
  322 +
  323 + // unset the content length to encode in chunked encoding.
  324 + w->header()->set_content_length(length);
  325 +
  326 + static std::map<std::string, std::string> _mime;
  327 + if (_mime.empty()) {
  328 + _mime[".ts"] = "video/MP2T";
  329 + _mime[".flv"] = "video/x-flv";
  330 + _mime[".m4v"] = "video/x-m4v";
  331 + _mime[".3gpp"] = "video/3gpp";
  332 + _mime[".3gp"] = "video/3gpp";
  333 + _mime[".mp4"] = "video/mp4";
  334 + _mime[".aac"] = "audio/x-aac";
  335 + _mime[".mp3"] = "audio/mpeg";
  336 + _mime[".m4a"] = "audio/x-m4a";
  337 + _mime[".ogg"] = "audio/ogg";
  338 + // @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 5.
  339 + _mime[".m3u8"] = "application/vnd.apple.mpegurl"; // application/x-mpegURL
  340 + _mime[".rss"] = "application/rss+xml";
  341 + _mime[".json"] = "application/json";
  342 + _mime[".swf"] = "application/x-shockwave-flash";
  343 + _mime[".doc"] = "application/msword";
  344 + _mime[".zip"] = "application/zip";
  345 + _mime[".rar"] = "application/x-rar-compressed";
  346 + _mime[".xml"] = "text/xml";
  347 + _mime[".html"] = "text/html";
  348 + _mime[".js"] = "text/javascript";
  349 + _mime[".css"] = "text/css";
  350 + _mime[".ico"] = "image/x-icon";
  351 + _mime[".png"] = "image/png";
  352 + _mime[".jpeg"] = "image/jpeg";
  353 + _mime[".jpg"] = "image/jpeg";
  354 + _mime[".gif"] = "image/gif";
  355 + }
  356 +
  357 + if (true) {
  358 + size_t pos;
  359 + std::string ext = fullpath;
  360 + if ((pos = ext.rfind(".")) != string::npos) {
  361 + ext = ext.substr(pos);
  362 + }
  363 +
  364 + if (_mime.find(ext) == _mime.end()) {
  365 + w->header()->set_content_type("application/octet-stream");
  366 + } else {
  367 + w->header()->set_content_type(_mime[ext]);
  368 + }
  369 + }
  370 +
  371 + // write body.
  372 + int64_t left = length;
  373 + if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {
  374 + if (!srs_is_client_gracefully_close(ret)) {
  375 + srs_error("read file=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);
  376 + }
  377 + return ret;
  378 + }
  379 +
  380 + return w->final_request();
  381 +}
  382 +
  383 +int SrsHttpFileServer::serve_flv_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath)
  384 +{
  385 + std::string start = r->query_get("start");
  386 + if (start.empty()) {
  387 + return serve_file(w, r, fullpath);
  388 + }
  389 +
  390 + int offset = ::atoi(start.c_str());
  391 + if (offset <= 0) {
  392 + return serve_file(w, r, fullpath);
  393 + }
  394 +
  395 + return serve_flv_stream(w, r, fullpath, offset);
  396 +}
  397 +
  398 +int SrsHttpFileServer::serve_mp4_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath)
  399 +{
  400 + // for flash to request mp4 range in query string.
  401 + // for example, http://digitalprimates.net/dash/DashTest.html?url=http://dashdemo.edgesuite.net/digitalprimates/nexus/oops-20120802-manifest.mpd
  402 + std::string range = r->query_get("range");
  403 + // or, use bytes to request range,
  404 + // for example, http://dashas.castlabs.com/demo/try.html
  405 + if (range.empty()) {
  406 + range = r->query_get("bytes");
  407 + }
  408 +
  409 + // rollback to serve whole file.
  410 + size_t pos = string::npos;
  411 + if (range.empty() || (pos = range.find("-")) == string::npos) {
  412 + return serve_file(w, r, fullpath);
  413 + }
  414 +
  415 + // parse the start in query string
  416 + int start = 0;
  417 + if (pos > 0) {
  418 + start = ::atoi(range.substr(0, pos).c_str());
  419 + }
  420 +
  421 + // parse end in query string.
  422 + int end = -1;
  423 + if (pos < range.length() - 1) {
  424 + end = ::atoi(range.substr(pos + 1).c_str());
  425 + }
  426 +
  427 + // invalid param, serve as whole mp4 file.
  428 + if (start < 0 || (end != -1 && start > end)) {
  429 + return serve_file(w, r, fullpath);
  430 + }
  431 +
  432 + return serve_mp4_stream(w, r, fullpath, start, end);
  433 +}
  434 +
  435 +int SrsHttpFileServer::serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int offset)
  436 +{
  437 + return serve_file(w, r, fullpath);
  438 +}
  439 +
  440 +int SrsHttpFileServer::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int start, int end)
  441 +{
  442 + return serve_file(w, r, fullpath);
  443 +}
  444 +
  445 +int SrsHttpFileServer::copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, ISrsHttpMessage* r, int size)
  446 +{
  447 + int ret = ERROR_SUCCESS;
  448 +
  449 + int left = size;
  450 + char* buf = r->http_ts_send_buffer();
  451 +
  452 + while (left > 0) {
  453 + ssize_t nread = -1;
  454 + int max_read = srs_min(left, SRS_HTTP_TS_SEND_BUFFER_SIZE);
  455 + if ((ret = fs->read(buf, max_read, &nread)) != ERROR_SUCCESS) {
  456 + break;
  457 + }
  458 +
  459 + left -= nread;
  460 + if ((ret = w->write(buf, (int)nread)) != ERROR_SUCCESS) {
  461 + break;
  462 + }
  463 + }
  464 +
  465 + return ret;
  466 +}
  467 +
  468 +SrsHttpMuxEntry::SrsHttpMuxEntry()
  469 +{
  470 + enabled = true;
  471 + explicit_match = false;
  472 + handler = NULL;
  473 +}
  474 +
  475 +SrsHttpMuxEntry::~SrsHttpMuxEntry()
  476 +{
  477 + srs_freep(handler);
  478 +}
  479 +
  480 +ISrsHttpMatchHijacker::ISrsHttpMatchHijacker()
  481 +{
  482 +}
  483 +
  484 +ISrsHttpMatchHijacker::~ISrsHttpMatchHijacker()
  485 +{
  486 +}
  487 +
  488 +SrsHttpServeMux::SrsHttpServeMux()
  489 +{
  490 +}
  491 +
  492 +SrsHttpServeMux::~SrsHttpServeMux()
  493 +{
  494 + std::map<std::string, SrsHttpMuxEntry*>::iterator it;
  495 + for (it = entries.begin(); it != entries.end(); ++it) {
  496 + SrsHttpMuxEntry* entry = it->second;
  497 + srs_freep(entry);
  498 + }
  499 + entries.clear();
  500 +
  501 + vhosts.clear();
  502 + hijackers.clear();
  503 +}
  504 +
  505 +int SrsHttpServeMux::initialize()
  506 +{
  507 + int ret = ERROR_SUCCESS;
  508 + // TODO: FIXME: implements it.
  509 + return ret;
  510 +}
  511 +
  512 +void SrsHttpServeMux::hijack(ISrsHttpMatchHijacker* h)
  513 +{
  514 + std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h);
  515 + if (it != hijackers.end()) {
  516 + return;
  517 + }
  518 + hijackers.push_back(h);
  519 +}
  520 +
  521 +void SrsHttpServeMux::unhijack(ISrsHttpMatchHijacker* h)
  522 +{
  523 + std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h);
  524 + if (it == hijackers.end()) {
  525 + return;
  526 + }
  527 + hijackers.erase(it);
  528 +}
  529 +
  530 +int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler)
  531 +{
  532 + int ret = ERROR_SUCCESS;
  533 +
  534 + srs_assert(handler);
  535 +
  536 + if (pattern.empty()) {
  537 + ret = ERROR_HTTP_PATTERN_EMPTY;
  538 + srs_error("http: empty pattern. ret=%d", ret);
  539 + return ret;
  540 + }
  541 +
  542 + if (entries.find(pattern) != entries.end()) {
  543 + SrsHttpMuxEntry* exists = entries[pattern];
  544 + if (exists->explicit_match) {
  545 + ret = ERROR_HTTP_PATTERN_DUPLICATED;
  546 + srs_error("http: multiple registrations for %s. ret=%d", pattern.c_str(), ret);
  547 + return ret;
  548 + }
  549 + }
  550 +
  551 + std::string vhost = pattern;
  552 + if (pattern.at(0) != '/') {
  553 + if (pattern.find("/") != string::npos) {
  554 + vhost = pattern.substr(0, pattern.find("/"));
  555 + }
  556 + vhosts[vhost] = handler;
  557 + }
  558 +
  559 + if (true) {
  560 + SrsHttpMuxEntry* entry = new SrsHttpMuxEntry();
  561 + entry->explicit_match = true;
  562 + entry->handler = handler;
  563 + entry->pattern = pattern;
  564 + entry->handler->entry = entry;
  565 +
  566 + if (entries.find(pattern) != entries.end()) {
  567 + SrsHttpMuxEntry* exists = entries[pattern];
  568 + srs_freep(exists);
  569 + }
  570 + entries[pattern] = entry;
  571 + }
  572 +
  573 + // Helpful behavior:
  574 + // If pattern is /tree/, insert an implicit permanent redirect for /tree.
  575 + // It can be overridden by an explicit registration.
  576 + if (pattern != "/" && !pattern.empty() && pattern.at(pattern.length() - 1) == '/') {
  577 + std::string rpattern = pattern.substr(0, pattern.length() - 1);
  578 + SrsHttpMuxEntry* entry = NULL;
  579 +
  580 + // free the exists not explicit entry
  581 + if (entries.find(rpattern) != entries.end()) {
  582 + SrsHttpMuxEntry* exists = entries[rpattern];
  583 + if (!exists->explicit_match) {
  584 + entry = exists;
  585 + }
  586 + }
  587 +
  588 + // create implicit redirect.
  589 + if (!entry || entry->explicit_match) {
  590 + srs_freep(entry);
  591 +
  592 + entry = new SrsHttpMuxEntry();
  593 + entry->explicit_match = false;
  594 + entry->handler = new SrsHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_MovedPermanently);
  595 + entry->pattern = pattern;
  596 + entry->handler->entry = entry;
  597 +
  598 + entries[rpattern] = entry;
  599 + }
  600 + }
  601 +
  602 + return ret;
  603 +}
  604 +
  605 +int SrsHttpServeMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
  606 +{
  607 + int ret = ERROR_SUCCESS;
  608 +
  609 + ISrsHttpHandler* h = NULL;
  610 + if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) {
  611 + srs_error("find handler failed. ret=%d", ret);
  612 + return ret;
  613 + }
  614 +
  615 + srs_assert(h);
  616 + if ((ret = h->serve_http(w, r)) != ERROR_SUCCESS) {
  617 + if (!srs_is_client_gracefully_close(ret)) {
  618 + srs_error("handler serve http failed. ret=%d", ret);
  619 + }
  620 + return ret;
  621 + }
  622 +
  623 + return ret;
  624 +}
  625 +
  626 +int SrsHttpServeMux::find_handler(ISrsHttpMessage* r, ISrsHttpHandler** ph)
  627 +{
  628 + int ret = ERROR_SUCCESS;
  629 +
  630 + // TODO: FIXME: support the path . and ..
  631 + if (r->url().find("..") != std::string::npos) {
  632 + ret = ERROR_HTTP_URL_NOT_CLEAN;
  633 + srs_error("htt url not canonical, url=%s. ret=%d", r->url().c_str(), ret);
  634 + return ret;
  635 + }
  636 +
  637 + if ((ret = match(r, ph)) != ERROR_SUCCESS) {
  638 + srs_error("http match handler failed. ret=%d", ret);
  639 + return ret;
  640 + }
  641 +
  642 + // always hijack.
  643 + if (!hijackers.empty()) {
  644 + // notice all hijacker the match failed.
  645 + std::vector<ISrsHttpMatchHijacker*>::iterator it;
  646 + for (it = hijackers.begin(); it != hijackers.end(); ++it) {
  647 + ISrsHttpMatchHijacker* hijacker = *it;
  648 + if ((ret = hijacker->hijack(r, ph)) != ERROR_SUCCESS) {
  649 + srs_error("hijacker match failed. ret=%d", ret);
  650 + return ret;
  651 + }
  652 + }
  653 + }
  654 +
  655 + if (*ph == NULL) {
  656 + // TODO: FIXME: memory leak.
  657 + *ph = new SrsHttpNotFoundHandler();
  658 + }
  659 +
  660 + return ret;
  661 +}
  662 +
  663 +int SrsHttpServeMux::match(ISrsHttpMessage* r, ISrsHttpHandler** ph)
  664 +{
  665 + int ret = ERROR_SUCCESS;
  666 +
  667 + std::string path = r->path();
  668 +
  669 + // Host-specific pattern takes precedence over generic ones
  670 + if (!vhosts.empty() && vhosts.find(r->host()) != vhosts.end()) {
  671 + path = r->host() + path;
  672 + }
  673 +
  674 + int nb_matched = 0;
  675 + ISrsHttpHandler* h = NULL;
  676 +
  677 + std::map<std::string, SrsHttpMuxEntry*>::iterator it;
  678 + for (it = entries.begin(); it != entries.end(); ++it) {
  679 + std::string pattern = it->first;
  680 + SrsHttpMuxEntry* entry = it->second;
  681 +
  682 + if (!entry->enabled) {
  683 + continue;
  684 + }
  685 +
  686 + if (!path_match(pattern, path)) {
  687 + continue;
  688 + }
  689 +
  690 + if (!h || (int)pattern.length() > nb_matched) {
  691 + nb_matched = (int)pattern.length();
  692 + h = entry->handler;
  693 + }
  694 + }
  695 +
  696 + *ph = h;
  697 +
  698 + return ret;
  699 +}
  700 +
  701 +bool SrsHttpServeMux::path_match(string pattern, string path)
  702 +{
  703 + if (pattern.empty()) {
  704 + return false;
  705 + }
  706 +
  707 + int n = (int)pattern.length();
  708 +
  709 + // not endswith '/', exactly match.
  710 + if (pattern.at(n - 1) != '/') {
  711 + return pattern == path;
  712 + }
  713 +
  714 + // endswith '/', match any,
  715 + // for example, '/api/' match '/api/[N]'
  716 + if ((int)path.length() >= n) {
  717 + if (memcmp(pattern.data(), path.data(), n) == 0) {
  718 + return true;
  719 + }
  720 + }
  721 +
  722 + return false;
  723 +}
  724 +
  725 +ISrsHttpMessage::ISrsHttpMessage()
  726 +{
  727 + _http_ts_send_buffer = new char[SRS_HTTP_TS_SEND_BUFFER_SIZE];
  728 +}
  729 +
  730 +ISrsHttpMessage::~ISrsHttpMessage()
  731 +{
  732 + srs_freep(_http_ts_send_buffer);
  733 +}
  734 +
  735 +char* ISrsHttpMessage::http_ts_send_buffer()
  736 +{
  737 + return _http_ts_send_buffer;
  738 +}
@@ -29,4 +29,466 @@ @@ -29,4 +29,466 @@
29 */ 29 */
30 #include <srs_core.hpp> 30 #include <srs_core.hpp>
31 31
  32 +#include <map>
  33 +#include <string>
  34 +#include <vector>
  35 +
  36 +class SrsFileReader;
  37 +class SrsHttpHeader;
  38 +class ISrsHttpMessage;
  39 +class SrsHttpMuxEntry;
  40 +class ISrsHttpResponseWriter;
  41 +
  42 +// http specification
  43 +// CR = <US-ASCII CR, carriage return (13)>
  44 +#define SRS_HTTP_CR SRS_CONSTS_CR // 0x0D
  45 +// LF = <US-ASCII LF, linefeed (10)>
  46 +#define SRS_HTTP_LF SRS_CONSTS_LF // 0x0A
  47 +// SP = <US-ASCII SP, space (32)>
  48 +#define SRS_HTTP_SP ' ' // 0x20
  49 +// HT = <US-ASCII HT, horizontal-tab (9)>
  50 +#define SRS_HTTP_HT '\x09' // 0x09
  51 +
  52 +// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
  53 +// protocol elements except the entity-body (see appendix 19.3 for
  54 +// tolerant applications).
  55 +#define SRS_HTTP_CRLF "\r\n" // 0x0D0A
  56 +#define SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
  57 +
  58 +// @see ISrsHttpMessage._http_ts_send_buffer
  59 +#define SRS_HTTP_TS_SEND_BUFFER_SIZE 4096
  60 +
  61 +// for ead all of http body, read each time.
  62 +#define SRS_HTTP_READ_CACHE_BYTES 4096
  63 +
  64 +// default http listen port.
  65 +#define SRS_DEFAULT_HTTP_PORT 80
  66 +
  67 +// for http parser macros
  68 +#define SRS_CONSTS_HTTP_OPTIONS HTTP_OPTIONS
  69 +#define SRS_CONSTS_HTTP_GET HTTP_GET
  70 +#define SRS_CONSTS_HTTP_POST HTTP_POST
  71 +#define SRS_CONSTS_HTTP_PUT HTTP_PUT
  72 +#define SRS_CONSTS_HTTP_DELETE HTTP_DELETE
  73 +
  74 +// helper function: response in json format.
  75 +extern int srs_http_response_json(ISrsHttpResponseWriter* w, std::string data);
  76 +
  77 +// get the status text of code.
  78 +extern std::string srs_generate_http_status_text(int status);
  79 +
  80 +// bodyAllowedForStatus reports whether a given response status code
  81 +// permits a body. See RFC2616, section 4.4.
  82 +extern bool srs_go_http_body_allowd(int status);
  83 +
  84 +// DetectContentType implements the algorithm described
  85 +// at http://mimesniff.spec.whatwg.org/ to determine the
  86 +// Content-Type of the given data. It considers at most the
  87 +// first 512 bytes of data. DetectContentType always returns
  88 +// a valid MIME type: if it cannot determine a more specific one, it
  89 +// returns "application/octet-stream".
  90 +extern std::string srs_go_http_detect(char* data, int size);
  91 +
  92 +// state of message
  93 +enum SrsHttpParseState {
  94 + SrsHttpParseStateInit = 0,
  95 + SrsHttpParseStateStart,
  96 + SrsHttpParseStateHeaderComplete,
  97 + SrsHttpParseStateMessageComplete
  98 +};
  99 +
  100 +// A Header represents the key-value pairs in an HTTP header.
  101 +class SrsHttpHeader
  102 +{
  103 +private:
  104 + std::map<std::string, std::string> headers;
  105 +public:
  106 + SrsHttpHeader();
  107 + virtual ~SrsHttpHeader();
  108 +public:
  109 + // Add adds the key, value pair to the header.
  110 + // It appends to any existing values associated with key.
  111 + virtual void set(std::string key, std::string value);
  112 + // Get gets the first value associated with the given key.
  113 + // If there are no values associated with the key, Get returns "".
  114 + // To access multiple values of a key, access the map directly
  115 + // with CanonicalHeaderKey.
  116 + virtual std::string get(std::string key);
  117 +public:
  118 + /**
  119 + * get the content length. -1 if not set.
  120 + */
  121 + virtual int64_t content_length();
  122 + /**
  123 + * set the content length by header "Content-Length"
  124 + */
  125 + virtual void set_content_length(int64_t size);
  126 +public:
  127 + /**
  128 + * get the content type. empty string if not set.
  129 + */
  130 + virtual std::string content_type();
  131 + /**
  132 + * set the content type by header "Content-Type"
  133 + */
  134 + virtual void set_content_type(std::string ct);
  135 +public:
  136 + /**
  137 + * write all headers to string stream.
  138 + */
  139 + virtual void write(std::stringstream& ss);
  140 +};
  141 +
  142 +// A ResponseWriter interface is used by an HTTP handler to
  143 +// construct an HTTP response.
  144 +// Usage 1, response with specified length content:
  145 +// ISrsHttpResponseWriter* w; // create or get response.
  146 +// std::string msg = "Hello, HTTP!";
  147 +// w->header()->set_content_type("text/plain; charset=utf-8");
  148 +// w->header()->set_content_length(msg.length());
  149 +// w->write_header(SRS_CONSTS_HTTP_OK);
  150 +// w->write((char*)msg.data(), (int)msg.length());
  151 +// w->final_request(); // optional flush.
  152 +// Usage 2, response with HTTP code only, zero content length.
  153 +// ISrsHttpResponseWriter* w; // create or get response.
  154 +// w->header()->set_content_length(0);
  155 +// w->write_header(SRS_CONSTS_HTTP_OK);
  156 +// w->final_request();
  157 +// Usage 3, response in chunked encoding.
  158 +// ISrsHttpResponseWriter* w; // create or get response.
  159 +// std::string msg = "Hello, HTTP!";
  160 +// w->header()->set_content_type("application/octet-stream");
  161 +// w->write_header(SRS_CONSTS_HTTP_OK);
  162 +// w->write((char*)msg.data(), (int)msg.length());
  163 +// w->write((char*)msg.data(), (int)msg.length());
  164 +// w->write((char*)msg.data(), (int)msg.length());
  165 +// w->write((char*)msg.data(), (int)msg.length());
  166 +// w->final_request(); // required to end the chunked and flush.
  167 +class ISrsHttpResponseWriter
  168 +{
  169 +public:
  170 + ISrsHttpResponseWriter();
  171 + virtual ~ISrsHttpResponseWriter();
  172 +public:
  173 + // when chunked mode,
  174 + // final the request to complete the chunked encoding.
  175 + // for no-chunked mode,
  176 + // final to send request, for example, content-length is 0.
  177 + virtual int final_request() = 0;
  178 +
  179 + // Header returns the header map that will be sent by WriteHeader.
  180 + // Changing the header after a call to WriteHeader (or Write) has
  181 + // no effect.
  182 + virtual SrsHttpHeader* header() = 0;
  183 +
  184 + // Write writes the data to the connection as part of an HTTP reply.
  185 + // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
  186 + // before writing the data. If the Header does not contain a
  187 + // Content-Type line, Write adds a Content-Type set to the result of passing
  188 + // the initial 512 bytes of written data to DetectContentType.
  189 + // @param data, the data to send. NULL to flush header only.
  190 + virtual int write(char* data, int size) = 0;
  191 +
  192 + // WriteHeader sends an HTTP response header with status code.
  193 + // If WriteHeader is not called explicitly, the first call to Write
  194 + // will trigger an implicit WriteHeader(http.StatusOK).
  195 + // Thus explicit calls to WriteHeader are mainly used to
  196 + // send error codes.
  197 + // @remark, user must set header then write or write_header.
  198 + virtual void write_header(int code) = 0;
  199 +};
  200 +
  201 +/**
  202 + * the reader interface for http response.
  203 + */
  204 +class ISrsHttpResponseReader
  205 +{
  206 +public:
  207 + ISrsHttpResponseReader();
  208 + virtual ~ISrsHttpResponseReader();
  209 +public:
  210 + /**
  211 + * whether response read EOF.
  212 + */
  213 + virtual bool eof() = 0;
  214 + /**
  215 + * read from the response body.
  216 + * @param data, the buffer to read data buffer to.
  217 + * @param nb_data, the max size of data buffer.
  218 + * @param nb_read, the actual read size of bytes. NULL to ignore.
  219 + * @remark when eof(), return error.
  220 + */
  221 + virtual int read(char* data, int nb_data, int* nb_read) = 0;
  222 +};
  223 +
  224 +// Objects implementing the Handler interface can be
  225 +// registered to serve a particular path or subtree
  226 +// in the HTTP server.
  227 +//
  228 +// ServeHTTP should write reply headers and data to the ResponseWriter
  229 +// and then return. Returning signals that the request is finished
  230 +// and that the HTTP server can move on to the next request on
  231 +// the connection.
  232 +class ISrsHttpHandler
  233 +{
  234 +public:
  235 + SrsHttpMuxEntry* entry;
  236 +public:
  237 + ISrsHttpHandler();
  238 + virtual ~ISrsHttpHandler();
  239 +public:
  240 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) = 0;
  241 +};
  242 +
  243 +// Redirect to a fixed URL
  244 +class SrsHttpRedirectHandler : public ISrsHttpHandler
  245 +{
  246 +private:
  247 + std::string url;
  248 + int code;
  249 +public:
  250 + SrsHttpRedirectHandler(std::string u, int c);
  251 + virtual ~SrsHttpRedirectHandler();
  252 +public:
  253 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
  254 +};
  255 +
  256 +// NotFound replies to the request with an HTTP 404 not found error.
  257 +class SrsHttpNotFoundHandler : public ISrsHttpHandler
  258 +{
  259 +public:
  260 + SrsHttpNotFoundHandler();
  261 + virtual ~SrsHttpNotFoundHandler();
  262 +public:
  263 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
  264 +};
  265 +
  266 +// FileServer returns a handler that serves HTTP requests
  267 +// with the contents of the file system rooted at root.
  268 +//
  269 +// To use the operating system's file system implementation,
  270 +// use http.Dir:
  271 +//
  272 +// http.Handle("/", SrsHttpFileServer("/tmp"))
  273 +// http.Handle("/", SrsHttpFileServer("static-dir"))
  274 +class SrsHttpFileServer : public ISrsHttpHandler
  275 +{
  276 +protected:
  277 + std::string dir;
  278 +public:
  279 + SrsHttpFileServer(std::string root_dir);
  280 + virtual ~SrsHttpFileServer();
  281 +public:
  282 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
  283 +private:
  284 + /**
  285 + * serve the file by specified path
  286 + */
  287 + virtual int serve_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath);
  288 + virtual int serve_flv_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath);
  289 + virtual int serve_mp4_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath);
  290 +protected:
  291 + /**
  292 + * when access flv file with x.flv?start=xxx
  293 + */
  294 + virtual int serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int offset);
  295 + /**
  296 + * when access mp4 file with x.mp4?range=start-end
  297 + * @param start the start offset in bytes.
  298 + * @param end the end offset in bytes. -1 to end of file.
  299 + * @remark response data in [start, end].
  300 + */
  301 + virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int start, int end);
  302 +protected:
  303 + /**
  304 + * copy the fs to response writer in size bytes.
  305 + */
  306 + virtual int copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, ISrsHttpMessage* r, int size);
  307 +};
  308 +
  309 +// the mux entry for server mux.
  310 +// the matcher info, for example, the pattern and handler.
  311 +class SrsHttpMuxEntry
  312 +{
  313 +public:
  314 + bool explicit_match;
  315 + ISrsHttpHandler* handler;
  316 + std::string pattern;
  317 + bool enabled;
  318 +public:
  319 + SrsHttpMuxEntry();
  320 + virtual ~SrsHttpMuxEntry();
  321 +};
  322 +
  323 +/**
  324 + * the hijacker for http pattern match.
  325 + */
  326 +class ISrsHttpMatchHijacker
  327 +{
  328 +public:
  329 + ISrsHttpMatchHijacker();
  330 + virtual ~ISrsHttpMatchHijacker();
  331 +public:
  332 + /**
  333 + * when match the request failed, no handler to process request.
  334 + * @param request the http request message to match the handler.
  335 + * @param ph the already matched handler, hijack can rewrite it.
  336 + */
  337 + virtual int hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) = 0;
  338 +};
  339 +
  340 +// ServeMux is an HTTP request multiplexer.
  341 +// It matches the URL of each incoming request against a list of registered
  342 +// patterns and calls the handler for the pattern that
  343 +// most closely matches the URL.
  344 +//
  345 +// Patterns name fixed, rooted paths, like "/favicon.ico",
  346 +// or rooted subtrees, like "/images/" (note the trailing slash).
  347 +// Longer patterns take precedence over shorter ones, so that
  348 +// if there are handlers registered for both "/images/"
  349 +// and "/images/thumbnails/", the latter handler will be
  350 +// called for paths beginning "/images/thumbnails/" and the
  351 +// former will receive requests for any other paths in the
  352 +// "/images/" subtree.
  353 +//
  354 +// Note that since a pattern ending in a slash names a rooted subtree,
  355 +// the pattern "/" matches all paths not matched by other registered
  356 +// patterns, not just the URL with Path == "/".
  357 +//
  358 +// Patterns may optionally begin with a host name, restricting matches to
  359 +// URLs on that host only. Host-specific patterns take precedence over
  360 +// general patterns, so that a handler might register for the two patterns
  361 +// "/codesearch" and "codesearch.google.com/" without also taking over
  362 +// requests for "http://www.google.com/".
  363 +//
  364 +// ServeMux also takes care of sanitizing the URL request path,
  365 +// redirecting any request containing . or .. elements to an
  366 +// equivalent .- and ..-free URL.
  367 +class SrsHttpServeMux
  368 +{
  369 +private:
  370 + // the pattern handler, to handle the http request.
  371 + std::map<std::string, SrsHttpMuxEntry*> entries;
  372 + // the vhost handler.
  373 + // when find the handler to process the request,
  374 + // append the matched vhost when pattern not starts with /,
  375 + // for example, for pattern /live/livestream.flv of vhost ossrs.net,
  376 + // the path will rewrite to ossrs.net/live/livestream.flv
  377 + std::map<std::string, ISrsHttpHandler*> vhosts;
  378 + // all hijackers for http match.
  379 + // for example, the hstrs(http stream trigger rtmp source)
  380 + // can hijack and install handler when request incoming and no handler.
  381 + std::vector<ISrsHttpMatchHijacker*> hijackers;
  382 +public:
  383 + SrsHttpServeMux();
  384 + virtual ~SrsHttpServeMux();
  385 +public:
  386 + /**
  387 + * initialize the http serve mux.
  388 + */
  389 + virtual int initialize();
  390 + /**
  391 + * hijack the http match.
  392 + */
  393 + virtual void hijack(ISrsHttpMatchHijacker* h);
  394 + virtual void unhijack(ISrsHttpMatchHijacker* h);
  395 +public:
  396 + // Handle registers the handler for the given pattern.
  397 + // If a handler already exists for pattern, Handle panics.
  398 + virtual int handle(std::string pattern, ISrsHttpHandler* handler);
  399 + // interface ISrsHttpHandler
  400 +public:
  401 + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
  402 +private:
  403 + virtual int find_handler(ISrsHttpMessage* r, ISrsHttpHandler** ph);
  404 + virtual int match(ISrsHttpMessage* r, ISrsHttpHandler** ph);
  405 + virtual bool path_match(std::string pattern, std::string path);
  406 +};
  407 +
  408 +// for http header.
  409 +typedef std::pair<std::string, std::string> SrsHttpHeaderField;
  410 +
  411 +// A Request represents an HTTP request received by a server
  412 +// or to be sent by a client.
  413 +//
  414 +// The field semantics differ slightly between client and server
  415 +// usage. In addition to the notes on the fields below, see the
  416 +// documentation for Request.Write and RoundTripper.
  417 +/**
  418 + * the http message, request or response.
  419 + */
  420 +class ISrsHttpMessage
  421 +{
  422 +private:
  423 + /**
  424 + * use a buffer to read and send ts file.
  425 + */
  426 + // TODO: FIXME: remove it.
  427 + char* _http_ts_send_buffer;
  428 +public:
  429 + ISrsHttpMessage();
  430 + virtual ~ISrsHttpMessage();
  431 +public:
  432 + /**
  433 + * the http request level cache.
  434 + */
  435 + virtual char* http_ts_send_buffer();
  436 +public:
  437 + virtual u_int8_t method() = 0;
  438 + virtual u_int16_t status_code() = 0;
  439 + /**
  440 + * method helpers.
  441 + */
  442 + virtual std::string method_str() = 0;
  443 + virtual bool is_http_get() = 0;
  444 + virtual bool is_http_put() = 0;
  445 + virtual bool is_http_post() = 0;
  446 + virtual bool is_http_delete() = 0;
  447 + virtual bool is_http_options() = 0;
  448 +public:
  449 + /**
  450 + * whether should keep the connection alive.
  451 + */
  452 + virtual bool is_keep_alive() = 0;
  453 + /**
  454 + * the uri contains the host and path.
  455 + */
  456 + virtual std::string uri() = 0;
  457 + /**
  458 + * the url maybe the path.
  459 + */
  460 + virtual std::string url() = 0;
  461 + virtual std::string host() = 0;
  462 + virtual std::string path() = 0;
  463 + virtual std::string ext() = 0;
  464 +public:
  465 + /**
  466 + * read body to string.
  467 + * @remark for small http body.
  468 + */
  469 + virtual int body_read_all(std::string& body) = 0;
  470 + /**
  471 + * get the body reader, to read one by one.
  472 + * @remark when body is very large, or chunked, use this.
  473 + */
  474 + virtual ISrsHttpResponseReader* body_reader() = 0;
  475 + /**
  476 + * the content length, -1 for chunked or not set.
  477 + */
  478 + virtual int64_t content_length() = 0;
  479 +public:
  480 + /**
  481 + * get the param in query string,
  482 + * for instance, query is "start=100&end=200",
  483 + * then query_get("start") is "100", and query_get("end") is "200"
  484 + */
  485 + virtual std::string query_get(std::string key) = 0;
  486 + /**
  487 + * get the headers.
  488 + */
  489 + virtual int request_header_count() = 0;
  490 + virtual std::string request_header_key_at(int index) = 0;
  491 + virtual std::string request_header_value_at(int index) = 0;
  492 +};
  493 +
32 #endif 494 #endif