Blame view

trunk/src/app/srs_app_http.cpp 45.7 KB
1 2 3
/*
The MIT License (MIT)
4
Copyright (c) 2013-2015 SRS(simple-rtmp-server)
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
24
#include <srs_app_http.hpp>
25
26
#ifdef SRS_AUTO_HTTP_PARSER
27
winlin authored
28
#include <stdlib.h>
29
#include <sys/stat.h>
winlin authored
30
#include <algorithm>
31 32
using namespace std;
33
#include <srs_kernel_error.hpp>
34
#include <srs_kernel_log.hpp>
35
#include <srs_app_st_socket.hpp>
winlin authored
36 37
#include <srs_app_http_api.hpp>
#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 45
#include <srs_rtmp_sdk.hpp>
#include <srs_rtmp_utility.hpp>
winlin authored
46 47 48

#define SRS_DEFAULT_HTTP_PORT 80
winlin authored
49 50 51 52 53 54 55
// for http parser macros
#define SRS_CONSTS_HTTP_OPTIONS HTTP_OPTIONS
#define SRS_CONSTS_HTTP_GET HTTP_GET
#define SRS_CONSTS_HTTP_POST HTTP_POST
#define SRS_CONSTS_HTTP_PUT HTTP_PUT
#define SRS_CONSTS_HTTP_DELETE HTTP_DELETE
56 57 58
// for ead all of http body, read each time.
#define SRS_HTTP_READ_CACHE_BYTES 4096
59
#define SRS_HTTP_DEFAULT_PAGE "index.html"
60
61
int srs_go_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
    
winlin authored
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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
{
    static std::map<int, std::string> _status_map;
    if (_status_map.empty()) {
        _status_map[SRS_CONSTS_HTTP_Continue                       ] = SRS_CONSTS_HTTP_Continue_str                     ;      
        _status_map[SRS_CONSTS_HTTP_SwitchingProtocols             ] = SRS_CONSTS_HTTP_SwitchingProtocols_str           ;      
        _status_map[SRS_CONSTS_HTTP_OK                             ] = SRS_CONSTS_HTTP_OK_str                           ;      
        _status_map[SRS_CONSTS_HTTP_Created                        ] = SRS_CONSTS_HTTP_Created_str                      ;      
        _status_map[SRS_CONSTS_HTTP_Accepted                       ] = SRS_CONSTS_HTTP_Accepted_str                     ;      
        _status_map[SRS_CONSTS_HTTP_NonAuthoritativeInformation    ] = SRS_CONSTS_HTTP_NonAuthoritativeInformation_str  ;      
        _status_map[SRS_CONSTS_HTTP_NoContent                      ] = SRS_CONSTS_HTTP_NoContent_str                    ;      
        _status_map[SRS_CONSTS_HTTP_ResetContent                   ] = SRS_CONSTS_HTTP_ResetContent_str                 ;      
        _status_map[SRS_CONSTS_HTTP_PartialContent                 ] = SRS_CONSTS_HTTP_PartialContent_str               ;      
        _status_map[SRS_CONSTS_HTTP_MultipleChoices                ] = SRS_CONSTS_HTTP_MultipleChoices_str              ;      
        _status_map[SRS_CONSTS_HTTP_MovedPermanently               ] = SRS_CONSTS_HTTP_MovedPermanently_str             ;      
        _status_map[SRS_CONSTS_HTTP_Found                          ] = SRS_CONSTS_HTTP_Found_str                        ;      
        _status_map[SRS_CONSTS_HTTP_SeeOther                       ] = SRS_CONSTS_HTTP_SeeOther_str                     ;      
        _status_map[SRS_CONSTS_HTTP_NotModified                    ] = SRS_CONSTS_HTTP_NotModified_str                  ;      
        _status_map[SRS_CONSTS_HTTP_UseProxy                       ] = SRS_CONSTS_HTTP_UseProxy_str                     ;      
        _status_map[SRS_CONSTS_HTTP_TemporaryRedirect              ] = SRS_CONSTS_HTTP_TemporaryRedirect_str            ;      
        _status_map[SRS_CONSTS_HTTP_BadRequest                     ] = SRS_CONSTS_HTTP_BadRequest_str                   ;      
        _status_map[SRS_CONSTS_HTTP_Unauthorized                   ] = SRS_CONSTS_HTTP_Unauthorized_str                 ;      
        _status_map[SRS_CONSTS_HTTP_PaymentRequired                ] = SRS_CONSTS_HTTP_PaymentRequired_str              ;      
        _status_map[SRS_CONSTS_HTTP_Forbidden                      ] = SRS_CONSTS_HTTP_Forbidden_str                    ;      
        _status_map[SRS_CONSTS_HTTP_NotFound                       ] = SRS_CONSTS_HTTP_NotFound_str                     ;      
        _status_map[SRS_CONSTS_HTTP_MethodNotAllowed               ] = SRS_CONSTS_HTTP_MethodNotAllowed_str             ;      
        _status_map[SRS_CONSTS_HTTP_NotAcceptable                  ] = SRS_CONSTS_HTTP_NotAcceptable_str                ;      
        _status_map[SRS_CONSTS_HTTP_ProxyAuthenticationRequired    ] = SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str  ;      
        _status_map[SRS_CONSTS_HTTP_RequestTimeout                 ] = SRS_CONSTS_HTTP_RequestTimeout_str               ;      
        _status_map[SRS_CONSTS_HTTP_Conflict                       ] = SRS_CONSTS_HTTP_Conflict_str                     ;      
        _status_map[SRS_CONSTS_HTTP_Gone                           ] = SRS_CONSTS_HTTP_Gone_str                         ;      
        _status_map[SRS_CONSTS_HTTP_LengthRequired                 ] = SRS_CONSTS_HTTP_LengthRequired_str               ;      
        _status_map[SRS_CONSTS_HTTP_PreconditionFailed             ] = SRS_CONSTS_HTTP_PreconditionFailed_str           ;      
        _status_map[SRS_CONSTS_HTTP_RequestEntityTooLarge          ] = SRS_CONSTS_HTTP_RequestEntityTooLarge_str        ;      
        _status_map[SRS_CONSTS_HTTP_RequestURITooLarge             ] = SRS_CONSTS_HTTP_RequestURITooLarge_str           ;      
        _status_map[SRS_CONSTS_HTTP_UnsupportedMediaType           ] = SRS_CONSTS_HTTP_UnsupportedMediaType_str         ;      
        _status_map[SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable   ] = SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str ;      
        _status_map[SRS_CONSTS_HTTP_ExpectationFailed              ] = SRS_CONSTS_HTTP_ExpectationFailed_str            ;      
        _status_map[SRS_CONSTS_HTTP_InternalServerError            ] = SRS_CONSTS_HTTP_InternalServerError_str          ;      
        _status_map[SRS_CONSTS_HTTP_NotImplemented                 ] = SRS_CONSTS_HTTP_NotImplemented_str               ;      
        _status_map[SRS_CONSTS_HTTP_BadGateway                     ] = SRS_CONSTS_HTTP_BadGateway_str                   ;      
        _status_map[SRS_CONSTS_HTTP_ServiceUnavailable             ] = SRS_CONSTS_HTTP_ServiceUnavailable_str           ;      
        _status_map[SRS_CONSTS_HTTP_GatewayTimeout                 ] = SRS_CONSTS_HTTP_GatewayTimeout_str               ;      
        _status_map[SRS_CONSTS_HTTP_HTTPVersionNotSupported        ] = SRS_CONSTS_HTTP_HTTPVersionNotSupported_str      ;      
    }
    
    std::string status_text;
    if (_status_map.find(status) == _status_map.end()) {
        status_text = "Status Unknown";
    } else {
        status_text = _status_map[status];
    }
    
    return status_text;
}

// bodyAllowedForStatus reports whether a given response status code
// permits a body.  See RFC2616, section 4.4.
bool srs_go_http_body_allowd(int status)
{
    if (status >= 100 && status <= 199) {
        return false;
    } else if (status == 204 || status == 304) {
        return false;
    }
    
	return true;
}

// DetectContentType implements the algorithm described
// at http://mimesniff.spec.whatwg.org/ to determine the
// Content-Type of the given data.  It considers at most the
// first 512 bytes of data.  DetectContentType always returns
// a valid MIME type: if it cannot determine a more specific one, it
// returns "application/octet-stream".
string srs_go_http_detect(char* data, int size)
{
147 148 149
    // detect only when data specified.
    if (data) {
    }
150 151 152 153 154
    return "application/octet-stream"; // fallback
}

// Error replies to the request with the specified error message and HTTP code.
// The error message should be plain text.
155
int srs_go_http_error(ISrsHttpResponseWriter* w, int code, string error)
156 157 158 159 160 161 162 163 164 165 166
{
    int ret = ERROR_SUCCESS;
    
    w->header()->set_content_type("text/plain; charset=utf-8");
    w->header()->set_content_length(error.length());
    w->write_header(code);
    w->write((char*)error.data(), (int)error.length());
    
    return ret;
}
167
SrsHttpHeader::SrsHttpHeader()
168 169 170
{
}
171
SrsHttpHeader::~SrsHttpHeader()
172 173 174
{
}
175
void SrsHttpHeader::set(string key, string value)
176 177 178 179
{
    headers[key] = value;
}
180
string SrsHttpHeader::get(string key)
181 182 183 184 185 186 187 188 189 190
{
    std::string v;
    
    if (headers.find(key) != headers.end()) {
        v = headers[key];
    }
    
    return v;
}
191
int64_t SrsHttpHeader::content_length()
192 193 194 195 196 197 198 199 200 201
{
    std::string cl = get("Content-Length");
    
    if (cl.empty()) {
        return -1;
    }
    
    return (int64_t)::atof(cl.c_str());
}
202
void SrsHttpHeader::set_content_length(int64_t size)
203 204 205 206 207 208
{
    char buf[64];
    snprintf(buf, sizeof(buf), "%"PRId64, size);
    set("Content-Length", buf);
}
209
string SrsHttpHeader::content_type()
210 211 212 213
{
    return get("Content-Type");
}
214
void SrsHttpHeader::set_content_type(string ct)
215 216 217 218
{
    set("Content-Type", ct);
}
219
void SrsHttpHeader::write(stringstream& ss)
220 221 222
{
    std::map<std::string, std::string>::iterator it;
    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 236 237 238 239 240 241 242
ISrsHttpResponseReader::ISrsHttpResponseReader()
{
}

ISrsHttpResponseReader::~ISrsHttpResponseReader()
{
}
243
ISrsHttpHandler::ISrsHttpHandler()
244
{
245
    entry = NULL;
246 247
}
248
ISrsHttpHandler::~ISrsHttpHandler()
249 250 251
{
}
252
SrsHttpRedirectHandler::SrsHttpRedirectHandler(string u, int c)
253 254 255 256 257
{
    url = u;
    code = c;
}
258
SrsHttpRedirectHandler::~SrsHttpRedirectHandler()
259 260 261
{
}
262
int SrsHttpRedirectHandler::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)
263 264 265 266 267 268
{
    int ret = ERROR_SUCCESS;
    // TODO: FIXME: implements it.
    return ret;
}
269
SrsHttpNotFoundHandler::SrsHttpNotFoundHandler()
270 271 272
{
}
273
SrsHttpNotFoundHandler::~SrsHttpNotFoundHandler()
274 275 276
{
}
277
int SrsHttpNotFoundHandler::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)
278 279 280 281 282
{
    return srs_go_http_error(w, 
        SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str);
}
283
SrsHttpFileServer::SrsHttpFileServer(string root_dir)
284 285 286 287
{
    dir = root_dir;
}
288
SrsHttpFileServer::~SrsHttpFileServer()
289 290 291
{
}
292
int SrsHttpFileServer::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)
293 294 295 296 297 298 299 300
{
    string upath = r->path();
    
    // add default pages.
    if (srs_string_ends_with(upath, "/")) {
        upath += SRS_HTTP_DEFAULT_PAGE;
    }
301 302
    string fullpath = dir + "/";
    
303
    // remove the virtual directory.
304
    srs_assert(entry);
305 306 307
    size_t pos = entry->pattern.find("/");
    if (upath.length() > entry->pattern.length() && pos != string::npos) {
        fullpath += upath.substr(entry->pattern.length() - pos);
308 309 310
    } else {
        fullpath += upath;
    }
311 312
    
    // stat current dir, if exists, return error.
313
    if (!srs_path_exists(fullpath)) {
314 315
        srs_warn("http miss file=%s, pattern=%s, upath=%s", 
            fullpath.c_str(), entry->pattern.c_str(), upath.c_str());
316
        return SrsHttpNotFoundHandler().serve_http(w, r);
317
    }
318 319
    srs_trace("http match file=%s, pattern=%s, upath=%s", 
        fullpath.c_str(), entry->pattern.c_str(), upath.c_str());
320
    
winlin authored
321 322
    // handle file according to its extension.
    // 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
    }
winlin authored
328 329 330

    // serve common static file.
    return serve_file(w, r, fullpath);
331 332
}
333
int SrsHttpFileServer::serve_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath)
334 335 336
{
    int ret = ERROR_SUCCESS;
    
337 338 339 340 341 342 343 344 345 346
    // open the target file.
    SrsFileReader fs;
    
    if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
        srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
        return ret;
    }

    int64_t length = fs.filesize();
    
winlin authored
347 348
    // unset the content length to encode in chunked encoding.
    w->header()->set_content_length(length);
349
    
350 351 352 353 354 355 356 357
    static std::map<std::string, std::string> _mime;
    if (_mime.empty()) {
        _mime[".ts"] = "video/MP2T";
        _mime[".flv"] = "video/x-flv";
        _mime[".m4v"] = "video/x-m4v";
        _mime[".3gpp"] = "video/3gpp";
        _mime[".3gp"] = "video/3gpp";
        _mime[".mp4"] = "video/mp4";
358
        _mime[".aac"] = "audio/x-aac";
359 360 361
        _mime[".mp3"] = "audio/mpeg";
        _mime[".m4a"] = "audio/x-m4a";
        _mime[".ogg"] = "audio/ogg";
362 363
        // @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 5.
        _mime[".m3u8"] = "application/vnd.apple.mpegurl"; // application/x-mpegURL
364
        _mime[".rss"] = "application/rss+xml";
365
        _mime[".json"] = "application/json";
366 367 368 369
        _mime[".swf"] = "application/x-shockwave-flash";
        _mime[".doc"] = "application/msword";
        _mime[".zip"] = "application/zip";
        _mime[".rar"] = "application/x-rar-compressed";
370 371
        _mime[".xml"] = "text/xml";
        _mime[".html"] = "text/html";
372
        _mime[".js"] = "text/javascript";
373
        _mime[".css"] = "text/css";
374 375 376 377 378 379 380 381
        _mime[".ico"] = "image/x-icon";
        _mime[".png"] = "image/png";
        _mime[".jpeg"] = "image/jpeg";
        _mime[".jpg"] = "image/jpeg";
        _mime[".gif"] = "image/gif";
    }
    
    if (true) {
382
        size_t pos;
383 384 385 386 387 388
        std::string ext = fullpath;
        if ((pos = ext.rfind(".")) != string::npos) {
            ext = ext.substr(pos);
        }
        
        if (_mime.find(ext) == _mime.end()) {
389
            w->header()->set_content_type("application/octet-stream");
390 391 392
        } else {
            w->header()->set_content_type(_mime[ext]);
        }
393 394 395 396
    }
    
    // write body.
    int64_t left = length;
winlin authored
397
    if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) {
398 399 400
        if (!srs_is_client_gracefully_close(ret)) {
            srs_error("read file=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret);
        }
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 410 411 412 413 414 415 416 417 418 419 420 421
{
    std::string start = r->query_get("start");
    if (start.empty()) {
        return serve_file(w, r, fullpath);
    }

    int offset = ::atoi(start.c_str());
    if (offset <= 0) {
        return serve_file(w, r, fullpath);
    }
        
    return serve_flv_stream(w, r, fullpath, offset);
}
422
int SrsHttpFileServer::serve_mp4_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath)
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
{
    // for flash to request mp4 range in query string.
    // for example, http://digitalprimates.net/dash/DashTest.html?url=http://dashdemo.edgesuite.net/digitalprimates/nexus/oops-20120802-manifest.mpd
    std::string range = r->query_get("range");
    // or, use bytes to request range,
    // for example, http://dashas.castlabs.com/demo/try.html
    if (range.empty()) {
        range = r->query_get("bytes");
    }

    // rollback to serve whole file.
    size_t pos = string::npos;
    if (range.empty() || (pos = range.find("-")) == string::npos) {
        return serve_file(w, r, fullpath);
    }

    // parse the start in query string
    int start = 0;
    if (pos > 0) {
        start = ::atoi(range.substr(0, pos).c_str());
    }

    // parse end in query string.
    int end = -1;
    if (pos < range.length() - 1) {
        end = ::atoi(range.substr(pos + 1).c_str());
    }

    // invalid param, serve as whole mp4 file.
    if (start < 0 || (end != -1 && start > end)) {
        return serve_file(w, r, fullpath);
    }
        
    return serve_mp4_stream(w, r, fullpath, start, end);
}
459
int SrsHttpFileServer::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset)
460
{
461 462
    return serve_file(w, r, fullpath);
}
463
464
int SrsHttpFileServer::serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end)
465 466 467 468
{
    return serve_file(w, r, fullpath);
}
469
int SrsHttpFileServer::copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size)
470 471
{
    int ret = ERROR_SUCCESS;
472
    
473
    int left = size;
474 475 476 477
    char* buf = r->http_ts_send_buffer();
    
    while (left > 0) {
        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;
winlin authored
484
        if ((ret = w->write(buf, (int)nread)) != ERROR_SUCCESS) {
485
            break;
486 487 488 489 490 491
        }
    }
    
    return ret;
}
492
SrsHttpMuxEntry::SrsHttpMuxEntry()
493
{
494
    enabled = true;
495 496 497 498
    explicit_match = false;
    handler = NULL;
}
499
SrsHttpMuxEntry::~SrsHttpMuxEntry()
500 501 502 503
{
    srs_freep(handler);
}
504 505 506 507 508 509 510 511
ISrsHttpMatchHijacker::ISrsHttpMatchHijacker()
{
}

ISrsHttpMatchHijacker::~ISrsHttpMatchHijacker()
{
}
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 522 523
        srs_freep(entry);
    }
    entries.clear();
524 525
    
    vhosts.clear();
526
    hijackers.clear();
527 528
}
529
int SrsHttpServeMux::initialize()
530 531 532 533 534 535
{
    int ret = ERROR_SUCCESS;
    // TODO: FIXME: implements it.
    return ret;
}
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
void SrsHttpServeMux::hijack(ISrsHttpMatchHijacker* h)
{
    std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h);
    if (it != hijackers.end()) {
        return;
    }
    hijackers.push_back(h);
}

void SrsHttpServeMux::unhijack(ISrsHttpMatchHijacker* h)
{
    std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h);
    if (it == hijackers.end()) {
        return;
    }
    hijackers.erase(it);
}
554
int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler)
555 556 557 558 559 560 561 562 563 564 565 566
{
    int ret = ERROR_SUCCESS;
    
    srs_assert(handler);
    
    if (pattern.empty()) {
        ret = ERROR_HTTP_PATTERN_EMPTY;
        srs_error("http: empty pattern. ret=%d", ret);
        return ret;
    }
    
    if (entries.find(pattern) != entries.end()) {
567
        SrsHttpMuxEntry* exists = entries[pattern];
568 569 570 571 572 573 574
        if (exists->explicit_match) {
            ret = ERROR_HTTP_PATTERN_DUPLICATED;
            srs_error("http: multiple registrations for %s. ret=%d", pattern.c_str(), ret);
            return ret;
        }
    }
    
575
    std::string vhost = pattern;
576
    if (pattern.at(0) != '/') {
577 578 579 580
        if (pattern.find("/") != string::npos) {
            vhost = pattern.substr(0, pattern.find("/"));
        }
        vhosts[vhost] = handler;
581 582
    }
    
583
    if (true) {
584
        SrsHttpMuxEntry* entry = new SrsHttpMuxEntry();
585 586 587
        entry->explicit_match = true;
        entry->handler = handler;
        entry->pattern = pattern;
588
        entry->handler->entry = entry;
589 590
        
        if (entries.find(pattern) != entries.end()) {
591
            SrsHttpMuxEntry* exists = entries[pattern];
592 593 594 595 596 597 598 599
            srs_freep(exists);
        }
        entries[pattern] = entry;
    }

    // Helpful behavior:
    // If pattern is /tree/, insert an implicit permanent redirect for /tree.
    // 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 605
        
        // free the exists not explicit entry
        if (entries.find(rpattern) != entries.end()) {
606
            SrsHttpMuxEntry* exists = entries[rpattern];
607 608 609 610 611 612 613 614 615
            if (!exists->explicit_match) {
                entry = exists;
            }
        }

        // create implicit redirect.
        if (!entry || entry->explicit_match) {
            srs_freep(entry);
            
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 623 624 625 626 627 628
            
            entries[rpattern] = entry;
        }
    }
    
    return ret;
}
629
int SrsHttpServeMux::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)
630 631 632
{
    int ret = ERROR_SUCCESS;
    
633
    ISrsHttpHandler* h = NULL;
634 635 636 637 638 639 640
    if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) {
        srs_error("find handler failed. ret=%d", ret);
        return ret;
    }
    
    srs_assert(h);
    if ((ret = h->serve_http(w, r)) != ERROR_SUCCESS) {
641 642 643
        if (!srs_is_client_gracefully_close(ret)) {
            srs_error("handler serve http failed. ret=%d", ret);
        }
644 645 646 647 648 649
        return ret;
    }
    
    return ret;
}
650
int SrsHttpServeMux::find_handler(SrsHttpMessage* r, ISrsHttpHandler** ph)
651 652 653 654 655 656 657 658 659 660 661 662 663 664
{
    int ret = ERROR_SUCCESS;
    
    // TODO: FIXME: support the path . and ..
    if (r->url().find("..") != std::string::npos) {
        ret = ERROR_HTTP_URL_NOT_CLEAN;
        srs_error("htt url not canonical, url=%s. ret=%d", r->url().c_str(), ret);
        return ret;
    }
    
    if ((ret = match(r, ph)) != ERROR_SUCCESS) {
        srs_error("http match handler failed. ret=%d", ret);
        return ret;
    }
665 666 667 668 669 670 671 672 673 674 675 676 677
    
    // always hijack.
    if (!hijackers.empty()) {
        // notice all hijacker the match failed.
        std::vector<ISrsHttpMatchHijacker*>::iterator it;
        for (it = hijackers.begin(); it != hijackers.end(); ++it) {
            ISrsHttpMatchHijacker* hijacker = *it;
            if ((ret = hijacker->hijack(r, ph)) != ERROR_SUCCESS) {
                srs_error("hijacker match failed. ret=%d", ret);
                return ret;
            }
        }
    }
678 679

    if (*ph == NULL) {
680
        // TODO: FIXME: memory leak.
681
        *ph = new SrsHttpNotFoundHandler();
682 683 684 685 686
    }
    
    return ret;
}
687
int SrsHttpServeMux::match(SrsHttpMessage* r, ISrsHttpHandler** ph)
688 689 690 691 692
{
    int ret = ERROR_SUCCESS;
    
    std::string path = r->path();
    
693
    // Host-specific pattern takes precedence over generic ones
694
    if (!vhosts.empty() && vhosts.find(r->host()) != vhosts.end()) {
695 696 697
        path = r->host() + path;
    }
    
698
    int nb_matched = 0;
699
    ISrsHttpHandler* h = NULL;
700
    
701
    std::map<std::string, SrsHttpMuxEntry*>::iterator it;
702 703
    for (it = entries.begin(); it != entries.end(); ++it) {
        std::string pattern = it->first;
704
        SrsHttpMuxEntry* entry = it->second;
705
        
706 707 708 709
        if (!entry->enabled) {
            continue;
        }
        
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
        if (!path_match(pattern, path)) {
            continue;
        }
        
        if (!h || (int)pattern.length() > nb_matched) {
            nb_matched = (int)pattern.length();
            h = entry->handler;
        }
    }
    
    *ph = h;
    
    return ret;
}
725
bool SrsHttpServeMux::path_match(string pattern, string path)
726 727 728 729 730
{
    if (pattern.empty()) {
        return false;
    }
    
winlin authored
731
    int n = (int)pattern.length();
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
    
    // not endswith '/', exactly match.
    if (pattern.at(n - 1) != '/') {
        return pattern == path;
    }
    
    // endswith '/', match any,
    // for example, '/api/' match '/api/[N]'
    if ((int)path.length() >= n) {
        if (memcmp(pattern.data(), path.data(), n) == 0) {
            return true;
        }
    }
    
    return false;
}
749
SrsHttpResponseWriter::SrsHttpResponseWriter(SrsStSocket* io)
750 751
{
    skt = io;
752
    hdr = new SrsHttpHeader();
753 754 755 756 757 758 759
    header_wrote = false;
    status = SRS_CONSTS_HTTP_OK;
    content_length = -1;
    written = 0;
    header_sent = false;
}
760
SrsHttpResponseWriter::~SrsHttpResponseWriter()
761 762 763 764
{
    srs_freep(hdr);
}
765
int SrsHttpResponseWriter::final_request()
766 767 768 769
{
    // complete the chunked encoding.
    if (content_length == -1) {
        std::stringstream ss;
770
        ss << 0 << SRS_HTTP_CRLF << SRS_HTTP_CRLF;
771 772 773 774
        std::string ch = ss.str();
        return skt->write((void*)ch.data(), (int)ch.length(), NULL);
    }
    
775 776
    // flush when send with content length
    return write(NULL, 0);
777 778
}
779
SrsHttpHeader* SrsHttpResponseWriter::header()
780 781 782 783
{
    return hdr;
}
784
int SrsHttpResponseWriter::write(char* data, int size)
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
{
    int ret = ERROR_SUCCESS;
    
    if (!header_wrote) {
        write_header(SRS_CONSTS_HTTP_OK);
    }
    
    written += size;
    if (content_length != -1 && written > content_length) {
        ret = ERROR_HTTP_CONTENT_LENGTH;
        srs_error("http: exceed content length. ret=%d", ret);
        return ret;
    }
    
    if ((ret = send_header(data, size)) != ERROR_SUCCESS) {
        srs_error("http: send header failed. ret=%d", ret);
        return ret;
    }
803 804 805 806 807

    // ignore NULL content.
    if (!data) {
        return ret;
    }
808
    
809 810 811 812 813 814 815
    // directly send with content length
    if (content_length != -1) {
        return skt->write((void*)data, size, NULL);
    }
    
    // send in chunked encoding.
    std::stringstream ss;
816
    ss << hex << size << SRS_HTTP_CRLF;
817 818 819 820 821 822 823
    std::string ch = ss.str();
    if ((ret = skt->write((void*)ch.data(), (int)ch.length(), NULL)) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = skt->write((void*)data, size, NULL)) != ERROR_SUCCESS) {
        return ret;
    }
824
    if ((ret = skt->write((void*)SRS_HTTP_CRLF, 2, NULL)) != ERROR_SUCCESS) {
825 826 827 828
        return ret;
    }
    
    return ret;
829 830
}
831
void SrsHttpResponseWriter::write_header(int code)
832 833 834 835 836 837 838 839 840 841 842 843 844
{
    if (header_wrote) {
        srs_warn("http: multiple write_header calls, code=%d", code);
        return;
    }
    
    header_wrote = true;
    status = code;
    
    // parse the content length from header.
    content_length = hdr->content_length();
}
845
int SrsHttpResponseWriter::send_header(char* data, int size)
846 847 848 849 850 851 852 853 854 855 856 857
{
    int ret = ERROR_SUCCESS;
    
    if (header_sent) {
        return ret;
    }
    header_sent = true;
    
    std::stringstream ss;
    
    // status_line
    ss << "HTTP/1.1 " << status << " " 
858
        << srs_generate_http_status_text(status) << SRS_HTTP_CRLF;
859 860 861 862 863 864 865 866 867 868 869 870 871
        
    // detect content type
    if (srs_go_http_body_allowd(status)) {
        if (hdr->content_type().empty()) {
            hdr->set_content_type(srs_go_http_detect(data, size));
        }
    }
    
    // set server if not set.
    if (hdr->get("Server").empty()) {
        hdr->set("Server", RTMP_SIG_SRS_KEY"/"RTMP_SIG_SRS_VERSION);
    }
    
872 873 874 875
    // chunked encoding
    if (content_length == -1) {
        hdr->set("Transfer-Encoding", "chunked");
    }
876 877 878

    // keep alive to make vlc happy.
    hdr->set("Connection", "Keep-Alive");
879
    
880 881 882 883
    // write headers
    hdr->write(ss);
    
    // header_eof
884
    ss << SRS_HTTP_CRLF;
885 886 887 888 889
    
    std::string buf = ss.str();
    return skt->write((void*)buf.c_str(), buf.length(), NULL);
}
890 891 892 893
SrsHttpResponseReader::SrsHttpResponseReader(SrsHttpMessage* msg, SrsStSocket* io)
{
    skt = io;
    owner = msg;
894
    is_eof = false;
895 896
    nb_total_read = 0;
    nb_left_chunk = 0;
897
    buffer = NULL;
898 899 900 901 902 903
}

SrsHttpResponseReader::~SrsHttpResponseReader()
{
}
904 905 906 907
int SrsHttpResponseReader::initialize(SrsFastBuffer* body)
{
    int ret = ERROR_SUCCESS;
    
908
    nb_chunk = 0;
909 910
    nb_left_chunk = 0;
    nb_total_read = 0;
911 912 913 914 915 916
    buffer = body;
    
    return ret;
}

bool SrsHttpResponseReader::eof()
winlin authored
917
{
918
    return is_eof;
winlin authored
919 920
}
921
int SrsHttpResponseReader::read(char* data, int nb_data, int* nb_read)
winlin authored
922 923 924
{
    int ret = ERROR_SUCCESS;
    
925 926 927 928 929
    if (is_eof) {
        ret = ERROR_HTTP_RESPONSE_EOF;
        srs_error("http: response EOF. ret=%d", ret);
        return ret;
    }
winlin authored
930
    
931 932
    // chunked encoding.
    if (owner->is_chunked()) {
933
        return read_chunked(data, nb_data, nb_read);
934 935 936
    }
    
    // read by specified content-length
937
    int max = (int)owner->content_length() - (int)nb_total_read;
938 939 940 941
    if (max <= 0) {
        is_eof = true;
        return ret;
    }
942 943 944 945
    
    // change the max to read.
    nb_data = srs_min(nb_data, max);
    return read_specified(data, nb_data, nb_read);
winlin authored
946 947
}
948
int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read)
949 950 951
{
    int ret = ERROR_SUCCESS;
    
952
    // when no bytes left in chunk,
953
    // parse the chunk length first.
954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
    if (nb_left_chunk <= 0) {
        char* at = NULL;
        int length = 0;
        while (!at) {
            // find the CRLF of chunk header end.
            char* start = buffer->bytes();
            char* end = start + buffer->size();
            for (char* p = start; p < end - 1; p++) {
                if (p[0] == SRS_HTTP_CR && p[1] == SRS_HTTP_LF) {
                    // invalid chunk, ignore.
                    if (p == start) {
                        ret = ERROR_HTTP_INVALID_CHUNK_HEADER;
                        srs_error("chunk header start with CRLF. ret=%d", ret);
                        return ret;
                    }
                    length = (int)(p - start + 2);
                    at = buffer->read_slice(length);
                    break;
972
                }
973 974 975 976
            }
            
            // got at, ok.
            if (at) {
977 978
                break;
            }
979 980 981 982 983 984 985 986
            
            // when empty, only grow 1bytes, but the buffer will cache more.
            if ((ret = buffer->grow(skt, buffer->size() + 1)) != ERROR_SUCCESS) {
                if (!srs_is_client_gracefully_close(ret)) {
                    srs_error("read body from server failed. ret=%d", ret);
                }
                return ret;
            }
987
        }
988
        srs_assert(length >= 3);
989
        
990 991 992
        // it's ok to set the pos and pos+1 to NULL.
        at[length - 1] = 0;
        at[length - 2] = 0;
993
        
994 995 996 997 998
        // size is the bytes size, excludes the chunk header and end CRLF.
        int ilength = (int)::strtol(at, NULL, 16);
        if (ilength < 0) {
            ret = ERROR_HTTP_INVALID_CHUNK_HEADER;
            srs_error("chunk header negative, length=%d. ret=%d", ilength, ret);
999 1000
            return ret;
        }
1001 1002
        
        // all bytes in chunk is left now.
1003
        nb_chunk = nb_left_chunk = ilength;
1004 1005
    }
    
1006 1007
    if (nb_chunk <= 0) {
        // for the last chunk, eof.
1008
        is_eof = true;
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
    } else {
        // for not the last chunk, there must always exists bytes.
        // left bytes in chunk, read some.
        srs_assert(nb_left_chunk);
        
        int nb_bytes = srs_min(nb_left_chunk, nb_data);
        ret = read_specified(data, nb_bytes, &nb_bytes);
        
        // the nb_bytes used for output already read size of bytes.
        if (nb_read) {
            *nb_read = nb_bytes;
        }
        nb_left_chunk -= nb_bytes;
        srs_info("http: read %d bytes of chunk", nb_bytes);
        
        // error or still left bytes in chunk, ignore and read in future.
        if (nb_left_chunk > 0 || (ret != ERROR_SUCCESS)) {
            return ret;
        }
        srs_info("http: read total chunk %dB", nb_chunk);
1029 1030
    }
    
1031
    // for both the last or not, the CRLF of chunk payload end.
1032 1033 1034 1035 1036 1037
    if ((ret = buffer->grow(skt, 2)) != ERROR_SUCCESS) {
        if (!srs_is_client_gracefully_close(ret)) {
            srs_error("read EOF of chunk from server failed. ret=%d", ret);
        }
        return ret;
    }
1038 1039 1040 1041 1042
    buffer->read_slice(2);

    return ret;
}
1043
int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read)
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
{
    int ret = ERROR_SUCCESS;
    
    if (buffer->size() <= 0) {
        // when empty, only grow 1bytes, but the buffer will cache more.
        if ((ret = buffer->grow(skt, 1)) != ERROR_SUCCESS) {
            if (!srs_is_client_gracefully_close(ret)) {
                srs_error("read body from server failed. ret=%d", ret);
            }
            return ret;
        }
    }
    
1057
    int nb_bytes = srs_min(nb_data, buffer->size());
1058
    
1059
    // read data to buffer.
1060
    srs_assert(nb_bytes);
1061 1062 1063 1064 1065 1066 1067 1068
    char* p = buffer->read_slice(nb_bytes);
    memcpy(data, p, nb_bytes);
    if (nb_read) {
        *nb_read = nb_bytes;
    }
    
    // increase the total read to determine whether EOF.
    nb_total_read += nb_bytes;
1069
    
1070 1071 1072 1073 1074 1075
    // for not chunked
    if (!owner->is_chunked()) {
        // when read completed, eof.
        if (nb_total_read >= (int)owner->content_length()) {
            is_eof = true;
        }
1076 1077 1078 1079 1080 1081
    }
    
    return ret;
}

SrsHttpMessage::SrsHttpMessage(SrsStSocket* io)
1082
{
winlin authored
1083
    chunked = false;
1084
    _uri = new SrsHttpUri();
1085
    _body = new SrsHttpResponseReader(this, io);
1086
    _http_ts_send_buffer = new char[SRS_HTTP_TS_SEND_BUFFER_SIZE];
1087 1088 1089 1090
}

SrsHttpMessage::~SrsHttpMessage()
{
1091
    srs_freep(_body);
1092
    srs_freep(_uri);
1093
    srs_freep(_http_ts_send_buffer);
1094 1095
}
1096
int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, vector<SrsHttpHeaderField>& headers)
1097 1098
{
    int ret = ERROR_SUCCESS;
1099
winlin authored
1100 1101 1102 1103
    _url = url;
    _header = *header;
    _headers = headers;
winlin authored
1104 1105 1106
    // whether chunked.
    std::string transfer_encoding = get_request_header("Transfer-Encoding");
    chunked = (transfer_encoding == "chunked");
1107 1108 1109 1110
    
    // set the buffer.
    if ((ret = _body->initialize(body)) != ERROR_SUCCESS) {
        return ret;
winlin authored
1111 1112 1113
    }
    
    // parse uri from url.
1114 1115 1116 1117 1118 1119 1120 1121
    std::string host = get_request_header("Host");

    // donot parse the empty host for uri, 
    // for example, the response contains no host,
    // ignore it is ok.
    if (host.empty()) {
        return ret;
    }
1122 1123
    
    // parse uri to schema/server:port/path?query
1124
    std::string uri = "http://" + host + _url;
1125
    if ((ret = _uri->initialize(uri)) != ERROR_SUCCESS) {
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
        return ret;
    }
    
    // must format as key=value&...&keyN=valueN
    std::string q = _uri->get_query();
    size_t pos = string::npos;
    while (!q.empty()) {
        std::string k = q;
        if ((pos = q.find("=")) != string::npos) {
            k = q.substr(0, pos);
            q = q.substr(pos + 1);
        } else {
            q = "";
        }
        
        std::string v = q;
        if ((pos = q.find("&")) != string::npos) {
            v = q.substr(0, pos);
            q = q.substr(pos + 1);
        } else {
            q = "";
        }
        
        _query[k] = v;
    }
    
1152 1153 1154 1155 1156 1157 1158 1159
    // parse ext.
    _ext = _uri->get_path();
    if ((pos = _ext.rfind(".")) != string::npos) {
        _ext = _ext.substr(pos);
    } else {
        _ext = "";
    }
    
1160 1161 1162
    return ret;
}
1163 1164 1165
char* SrsHttpMessage::http_ts_send_buffer()
{
    return _http_ts_send_buffer;
1166 1167
}
1168 1169 1170 1171 1172
u_int8_t SrsHttpMessage::method()
{
    return (u_int8_t)_header.method;
}
1173 1174 1175 1176 1177
u_int16_t SrsHttpMessage::status_code()
{
    return (u_int16_t)_header.status_code;
}
winlin authored
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
string SrsHttpMessage::method_str()
{
    if (is_http_get()) {
        return "GET";
    }
    if (is_http_put()) {
        return "PUT";
    }
    if (is_http_post()) {
        return "POST";
    }
    if (is_http_delete()) {
        return "DELETE";
    }
    if (is_http_options()) {
        return "OPTIONS";
    }
    
    return "OTHER";
}
1199 1200
bool SrsHttpMessage::is_http_get()
{
winlin authored
1201
    return _header.method == SRS_CONSTS_HTTP_GET;
1202 1203 1204 1205
}

bool SrsHttpMessage::is_http_put()
{
winlin authored
1206
    return _header.method == SRS_CONSTS_HTTP_PUT;
1207 1208 1209 1210
}

bool SrsHttpMessage::is_http_post()
{
winlin authored
1211
    return _header.method == SRS_CONSTS_HTTP_POST;
1212 1213 1214 1215
}

bool SrsHttpMessage::is_http_delete()
{
winlin authored
1216
    return _header.method == SRS_CONSTS_HTTP_DELETE;
1217 1218
}
winlin authored
1219 1220
bool SrsHttpMessage::is_http_options()
{
winlin authored
1221
    return _header.method == SRS_CONSTS_HTTP_OPTIONS;
winlin authored
1222 1223
}
winlin authored
1224 1225 1226 1227 1228
bool SrsHttpMessage::is_chunked()
{
    return chunked;
}
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240
string SrsHttpMessage::uri()
{
    std::string uri = _uri->get_schema();
    if (uri.empty()) {
        uri += "http://";
    }
    
    uri += host();
    uri += path();
    return uri;
}
1241 1242
string SrsHttpMessage::url()
{
1243 1244 1245
    return _uri->get_url();
}
1246 1247
string SrsHttpMessage::host()
{
1248
    return _uri->get_host();
1249 1250
}
1251 1252 1253 1254 1255
string SrsHttpMessage::path()
{
    return _uri->get_path();
}
1256 1257 1258 1259 1260
string SrsHttpMessage::ext()
{
    return _ext;
}
1261
int SrsHttpMessage::body_read_all(string& body)
1262
{
1263 1264
    int ret = ERROR_SUCCESS;
    
1265 1266 1267 1268
    // cache to read.
    char* buf = new char[SRS_HTTP_READ_CACHE_BYTES];
    SrsAutoFree(char, buf);
    
1269 1270
    // whatever, read util EOF.
    while (!_body->eof()) {
1271 1272
        int nb_read = 0;
        if ((ret = _body->read(buf, SRS_HTTP_READ_CACHE_BYTES, &nb_read)) != ERROR_SUCCESS) {
1273 1274
            return ret;
        }
1275
        
1276 1277 1278
        if (nb_read > 0) {
            body.append(buf, nb_read);
        }
1279 1280 1281
    }
    
    return ret;
1282 1283
}
winlin authored
1284 1285 1286 1287 1288
ISrsHttpResponseReader* SrsHttpMessage::body_reader()
{
    return _body;
}
1289 1290 1291 1292 1293
int64_t SrsHttpMessage::content_length()
{
    return _header.content_length;
}
1294 1295
string SrsHttpMessage::query_get(string key)
{
1296
    std::string v;
1297
    
1298 1299
    if (_query.find(key) != _query.end()) {
        v = _query[key];
1300 1301 1302 1303 1304
    }
    
    return v;
}
1305 1306
int SrsHttpMessage::request_header_count()
{
1307
    return (int)_headers.size();
1308 1309 1310 1311 1312
}

string SrsHttpMessage::request_header_key_at(int index)
{
    srs_assert(index < request_header_count());
1313
    SrsHttpHeaderField item = _headers[index];
1314 1315 1316 1317 1318 1319
    return item.first;
}

string SrsHttpMessage::request_header_value_at(int index)
{
    srs_assert(index < request_header_count());
1320
    SrsHttpHeaderField item = _headers[index];
1321 1322 1323 1324 1325 1326 1327
    return item.second;
}

string SrsHttpMessage::get_request_header(string name)
{
    std::vector<SrsHttpHeaderField>::iterator it;
    
1328
    for (it = _headers.begin(); it != _headers.end(); ++it) {
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
        SrsHttpHeaderField& elem = *it;
        std::string key = elem.first;
        std::string value = elem.second;
        if (key == name) {
            return value;
        }
    }
    
    return "";
}
1340 1341 1342 1343 1344
SrsRequest* SrsHttpMessage::to_request(string vhost)
{
    SrsRequest* req = new SrsRequest();
    
    req->app = _uri->get_path();
1345
    size_t pos = string::npos;
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
    if ((pos = req->app.rfind("/")) != string::npos) {
        req->stream = req->app.substr(pos + 1);
        req->app = req->app.substr(0, pos);
    }
    if ((pos = req->stream.rfind(".")) != string::npos) {
        req->stream = req->stream.substr(0, pos);
    }
    
    req->tcUrl = "rtmp://" + vhost + req->app;
    req->pageUrl = get_request_header("Referer");
    req->objectEncoding = 0;
    
    srs_discovery_tc_url(req->tcUrl,
        req->schema, req->host, req->vhost, req->app, req->port,
        req->param);
    req->strip();
    
    return req;
}
1366 1367
SrsHttpParser::SrsHttpParser()
{
1368
    buffer = new SrsFastBuffer();
1369 1370 1371 1372
}

SrsHttpParser::~SrsHttpParser()
{
1373
    srs_freep(buffer);
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
}

int SrsHttpParser::initialize(enum http_parser_type type)
{
    int ret = ERROR_SUCCESS;
    
    memset(&settings, 0, sizeof(settings));
    settings.on_message_begin = on_message_begin;
    settings.on_url = on_url;
    settings.on_header_field = on_header_field;
    settings.on_header_value = on_header_value;
    settings.on_headers_complete = on_headers_complete;
    settings.on_body = on_body;
    settings.on_message_complete = on_message_complete;
    
    http_parser_init(&parser, type);
    // callback object ptr.
    parser.data = (void*)this;
    
    return ret;
}
1396
int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg)
1397 1398 1399 1400 1401
{
    *ppmsg = NULL;
    
    int ret = ERROR_SUCCESS;
    
1402
    // reset request data.
1403
    field_name = "";
1404
    field_value = "";
1405
    expect_field_name = true;
1406 1407 1408 1409
    state = SrsHttpParseStateInit;
    header = http_parser();
    url = "";
    headers.clear();
J authored
1410
    header_parsed = 0;
1411 1412 1413 1414 1415 1416 1417 1418
    
    // do parse
    if ((ret = parse_message_imp(skt)) != ERROR_SUCCESS) {
        if (!srs_is_client_gracefully_close(ret)) {
            srs_error("parse http msg failed. ret=%d", ret);
        }
        return ret;
    }
1419
1420 1421 1422
    // create msg
    SrsHttpMessage* msg = new SrsHttpMessage(skt);
    
1423
    // initalize http msg, parse url.
1424
    if ((ret = msg->update(url, &header, buffer, headers)) != ERROR_SUCCESS) {
1425 1426 1427 1428
        srs_error("initialize http msg failed. ret=%d", ret);
        srs_freep(msg);
        return ret;
    }
1429 1430 1431 1432 1433 1434 1435
    
    // parse ok, return the msg.
    *ppmsg = msg;
    
    return ret;
}
1436
int SrsHttpParser::parse_message_imp(SrsStSocket* skt)
1437 1438 1439
{
    int ret = ERROR_SUCCESS;
    
1440
    while (true) {
winlin authored
1441 1442 1443 1444 1445
        ssize_t nparsed = 0;
        
        // when buffer not empty, parse it.
        if (buffer->size() > 0) {
            nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size());
J authored
1446
            srs_info("buffer=%d, nparsed=%d, header=%d", buffer->size(), (int)nparsed, header_parsed);
winlin authored
1447 1448 1449
        }
        
        // consume the parsed bytes.
1450
        if (nparsed && header_parsed) {
J authored
1451
            buffer->read_slice(header_parsed);
1452
        }
1453
1454 1455 1456 1457
        // ok atleast header completed,
        // never wait for body completed, for maybe chunked.
        if (state == SrsHttpParseStateHeaderComplete || state == SrsHttpParseStateMessageComplete) {
            break;
1458
        }
winlin authored
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
        
        // when nothing parsed, read more to parse.
        if (nparsed == 0) {
            // when requires more, only grow 1bytes, but the buffer will cache more.
            if ((ret = buffer->grow(skt, buffer->size() + 1)) != ERROR_SUCCESS) {
                if (!srs_is_client_gracefully_close(ret)) {
                    srs_error("read body from server failed. ret=%d", ret);
                }
                return ret;
            }
        }
1470
    }
winlin authored
1471 1472

    // parse last header.
1473 1474
    if (!field_name.empty() && !field_value.empty()) {
        headers.push_back(std::make_pair(field_name, field_value));
winlin authored
1475
    }
1476 1477 1478 1479 1480 1481 1482

    return ret;
}

int SrsHttpParser::on_message_begin(http_parser* parser)
{
    SrsHttpParser* obj = (SrsHttpParser*)parser->data;
1483 1484 1485
    srs_assert(obj);
    
    obj->state = SrsHttpParseStateStart;
1486 1487 1488 1489 1490 1491 1492 1493 1494
    
    srs_info("***MESSAGE BEGIN***");
    
    return 0;
}

int SrsHttpParser::on_headers_complete(http_parser* parser)
{
    SrsHttpParser* obj = (SrsHttpParser*)parser->data;
1495 1496 1497 1498 1499
    srs_assert(obj);
    
    obj->header = *parser;
    // save the parser when header parse completed.
    obj->state = SrsHttpParseStateHeaderComplete;
J authored
1500
    obj->header_parsed = (int)parser->nread;
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
    
    srs_info("***HEADERS COMPLETE***");
    
    // see http_parser.c:1570, return 1 to skip body.
    return 0;
}

int SrsHttpParser::on_message_complete(http_parser* parser)
{
    SrsHttpParser* obj = (SrsHttpParser*)parser->data;
1511 1512 1513 1514
    srs_assert(obj);
    
    // save the parser when body parse completed.
    obj->state = SrsHttpParseStateMessageComplete;
1515 1516 1517 1518 1519 1520 1521 1522 1523
    
    srs_info("***MESSAGE COMPLETE***\n");
    
    return 0;
}

int SrsHttpParser::on_url(http_parser* parser, const char* at, size_t length)
{
    SrsHttpParser* obj = (SrsHttpParser*)parser->data;
1524
    srs_assert(obj);
1525 1526
    
    if (length > 0) {
1527
        obj->url.append(at, (int)length);
1528 1529 1530 1531 1532 1533 1534
    }
    
    srs_info("Method: %d, Url: %.*s", parser->method, (int)length, at);
    
    return 0;
}
1535
int SrsHttpParser::on_header_field(http_parser* parser, const char* at, size_t length)
1536
{
1537
    SrsHttpParser* obj = (SrsHttpParser*)parser->data;
1538 1539 1540
    srs_assert(obj);
    
    // field value=>name, reap the field.
1541 1542
    if (!obj->expect_field_name) {
        obj->headers.push_back(std::make_pair(obj->field_name, obj->field_value));
1543
        
winlin authored
1544
        // reset the field name when parsed.
1545
        obj->field_name = "";
1546 1547
        obj->field_value = "";
    }
1548
    obj->expect_field_name = true;
1549 1550
    
    if (length > 0) {
1551
        obj->field_name.append(at, (int)length);
1552 1553
    }
    
winlin authored
1554
    srs_info("Header field(%d bytes): %.*s", (int)length, (int)length, at);
1555 1556 1557
    return 0;
}
1558
int SrsHttpParser::on_header_value(http_parser* parser, const char* at, size_t length)
1559
{
1560
    SrsHttpParser* obj = (SrsHttpParser*)parser->data;
1561
    srs_assert(obj);
1562 1563
    
    if (length > 0) {
1564
        obj->field_value.append(at, (int)length);
1565
    }
1566
    obj->expect_field_name = false;
1567
    
winlin authored
1568
    srs_info("Header value(%d bytes): %.*s", (int)length, (int)length, at);
1569 1570 1571 1572 1573 1574
    return 0;
}

int SrsHttpParser::on_body(http_parser* parser, const char* at, size_t length)
{
    SrsHttpParser* obj = (SrsHttpParser*)parser->data;
1575
    srs_assert(obj);
1576 1577 1578 1579
    
    srs_info("Body: %.*s", (int)length, at);

    return 0;
1580
}
1581
winlin authored
1582 1583
SrsHttpUri::SrsHttpUri()
{
1584
    port = SRS_DEFAULT_HTTP_PORT;
winlin authored
1585 1586 1587 1588 1589 1590
}

SrsHttpUri::~SrsHttpUri()
{
}
1591
int SrsHttpUri::initialize(string _url)
winlin authored
1592
{
1593
    int ret = ERROR_SUCCESS;
winlin authored
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
    
    url = _url;
    const char* purl = url.c_str();
    
    http_parser_url hp_u;
    if((ret = http_parser_parse_url(purl, url.length(), 0, &hp_u)) != 0){
        int code = ret;
        ret = ERROR_HTTP_PARSE_URI;
        
        srs_error("parse url %s failed, code=%d, ret=%d", purl, code, ret);
        return ret;
    }
    
1607
    std::string field = get_uri_field(url, &hp_u, UF_SCHEMA);
winlin authored
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621
    if(!field.empty()){
        schema = field;
    }
    
    host = get_uri_field(url, &hp_u, UF_HOST);
    
    field = get_uri_field(url, &hp_u, UF_PORT);
    if(!field.empty()){
        port = atoi(field.c_str());
    }
    
    path = get_uri_field(url, &hp_u, UF_PATH);
    srs_info("parse url %s success", purl);
    
1622
    query = get_uri_field(url, &hp_u, UF_QUERY);
1623
    srs_info("parse query %s success", query.c_str());
1624
    
1625
    return ret;
winlin authored
1626 1627 1628 1629
}

const char* SrsHttpUri::get_url()
{
1630
    return url.data();
winlin authored
1631 1632 1633 1634
}

const char* SrsHttpUri::get_schema()
{
1635
    return schema.data();
winlin authored
1636 1637 1638 1639
}

const char* SrsHttpUri::get_host()
{
1640
    return host.data();
winlin authored
1641 1642 1643 1644 1645 1646 1647
}

int SrsHttpUri::get_port()
{
    return port;
}
1648 1649
const char* SrsHttpUri::get_path()
{
1650 1651 1652 1653 1654
    return path.data();
}

const char* SrsHttpUri::get_query()
{
1655
    return query.data();
1656 1657
}
1658
string SrsHttpUri::get_uri_field(string uri, http_parser_url* hp_u, http_parser_url_fields field)
winlin authored
1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675
{
    if((hp_u->field_set & (1 << field)) == 0){
        return "";
    }
    
    srs_verbose("uri field matched, off=%d, len=%d, value=%.*s", 
        hp_u->field_data[field].off, 
        hp_u->field_data[field].len, 
        hp_u->field_data[field].len, 
        uri.c_str() + hp_u->field_data[field].off);
    
    int offset = hp_u->field_data[field].off;
    int len = hp_u->field_data[field].len;
    
    return uri.substr(offset, len);
}
1676
#endif
1677