winlin

fix #277, refine http server refer to go http-framework. 2.0.98

@@ -510,6 +510,7 @@ Supported operating systems and hardware: @@ -510,6 +510,7 @@ Supported operating systems and hardware:
510 510
511 ## History 511 ## History
512 512
  513 +* v2.0, 2015-01-17, fix [#277](https://github.com/winlinvip/simple-rtmp-server/issues/277), refine http server refer to go http-framework. 2.0.98
513 * v2.0, 2015-01-17, for [#277](https://github.com/winlinvip/simple-rtmp-server/issues/277), refine http api refer to go http-framework. 2.0.97 514 * v2.0, 2015-01-17, for [#277](https://github.com/winlinvip/simple-rtmp-server/issues/277), refine http api refer to go http-framework. 2.0.97
514 * v2.0, 2015-01-17, hotfix [#290](https://github.com/winlinvip/simple-rtmp-server/issues/290), use iformat only for rtmp input. 2.0.95 515 * v2.0, 2015-01-17, hotfix [#290](https://github.com/winlinvip/simple-rtmp-server/issues/290), use iformat only for rtmp input. 2.0.95
515 * v2.0, 2015-01-08, hotfix [#281](https://github.com/winlinvip/simple-rtmp-server/issues/281), fix hls bug ignore type-9 send aud. 2.0.93 516 * v2.0, 2015-01-08, hotfix [#281](https://github.com/winlinvip/simple-rtmp-server/issues/281), fix hls bug ignore type-9 send aud. 2.0.93
@@ -37,6 +37,7 @@ using namespace std; @@ -37,6 +37,7 @@ using namespace std;
37 #include <srs_app_json.hpp> 37 #include <srs_app_json.hpp>
38 #include <srs_kernel_utility.hpp> 38 #include <srs_kernel_utility.hpp>
39 #include <srs_protocol_buffer.hpp> 39 #include <srs_protocol_buffer.hpp>
  40 +#include <srs_kernel_file.hpp>
40 41
41 #define SRS_DEFAULT_HTTP_PORT 80 42 #define SRS_DEFAULT_HTTP_PORT 80
42 43
@@ -49,24 +50,7 @@ using namespace std; @@ -49,24 +50,7 @@ using namespace std;
49 #define SRS_CONSTS_HTTP_PUT HTTP_PUT 50 #define SRS_CONSTS_HTTP_PUT HTTP_PUT
50 #define SRS_CONSTS_HTTP_DELETE HTTP_DELETE 51 #define SRS_CONSTS_HTTP_DELETE HTTP_DELETE
51 52
52 -bool srs_path_equals(const char* expect, const char* path, int nb_path)  
53 -{  
54 - int size = strlen(expect);  
55 -  
56 - if (size != nb_path) {  
57 - return false;  
58 - }  
59 -  
60 - bool equals = !memcmp(expect, path, size);  
61 - return equals;  
62 -}  
63 -  
64 -bool srs_path_like(const char* expect, const char* path, int nb_path)  
65 -{  
66 - int size = strlen(expect);  
67 - bool equals = !strncmp(expect, path, srs_min(size, nb_path));  
68 - return equals;  
69 -} 53 +#define SRS_HTTP_DEFAULT_PAGE "index.html"
70 54
71 int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, string data) 55 int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, string data)
72 { 56 {
@@ -278,6 +262,82 @@ int SrsGoHttpNotFoundHandler::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMes @@ -278,6 +262,82 @@ int SrsGoHttpNotFoundHandler::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMes
278 SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str); 262 SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str);
279 } 263 }
280 264
  265 +SrsGoHttpFileServer::SrsGoHttpFileServer(string root_dir)
  266 +{
  267 + dir = root_dir;
  268 +}
  269 +
  270 +SrsGoHttpFileServer::~SrsGoHttpFileServer()
  271 +{
  272 +}
  273 +
  274 +int SrsGoHttpFileServer::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
  275 +{
  276 + int ret = ERROR_SUCCESS;
  277 +
  278 + string upath = r->path();
  279 +
  280 + // add default pages.
  281 + if (srs_string_ends_with(upath, "/")) {
  282 + upath += SRS_HTTP_DEFAULT_PAGE;
  283 + }
  284 +
  285 + string fullpath = dir + "/" + upath;
  286 +
  287 + // open the target file.
  288 + SrsFileReader fs;
  289 +
  290 + if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {
  291 + srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
  292 + return ret;
  293 + }
  294 +
  295 + int64_t length = fs.filesize();
  296 +
  297 + w->header()->set_content_length(length);
  298 +
  299 + if (srs_string_ends_with(fullpath, ".ts")) {
  300 + w->header()->set_content_type("video/MP2T");
  301 + } else if (srs_string_ends_with(fullpath, ".m3u8")) {
  302 + w->header()->set_content_type("application/x-mpegURL;charset=utf-8");
  303 + } else if (srs_string_ends_with(fullpath, ".flv")) {
  304 + w->header()->set_content_type("video/x-flv");
  305 + } else if (srs_string_ends_with(fullpath, ".xml")) {
  306 + w->header()->set_content_type("text/xml;charset=utf-8");
  307 + } else if (srs_string_ends_with(fullpath, ".js")) {
  308 + w->header()->set_content_type("text/javascript");
  309 + } else if (srs_string_ends_with(fullpath, ".json")) {
  310 + w->header()->set_content_type("application/json;charset=utf-8");
  311 + } else if (srs_string_ends_with(fullpath, ".swf")) {
  312 + w->header()->set_content_type("application/x-shockwave-flash");
  313 + } else if (srs_string_ends_with(fullpath, ".css")) {
  314 + w->header()->set_content_type("text/css;charset=utf-8");
  315 + } else if (srs_string_ends_with(fullpath, ".ico")) {
  316 + w->header()->set_content_type("image/x-icon");
  317 + } else {
  318 + w->header()->set_content_type("text/html;charset=utf-8");
  319 + }
  320 +
  321 + // write body.
  322 + int64_t left = length;
  323 + char* buf = r->http_ts_send_buffer();
  324 +
  325 + while (left > 0) {
  326 + ssize_t nread = -1;
  327 + if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) {
  328 + srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);
  329 + break;
  330 + }
  331 +
  332 + left -= nread;
  333 + if ((ret = w->write(buf, nread)) != ERROR_SUCCESS) {
  334 + break;
  335 + }
  336 + }
  337 +
  338 + return ret;
  339 +}
  340 +
281 SrsGoHttpMuxEntry::SrsGoHttpMuxEntry() 341 SrsGoHttpMuxEntry::SrsGoHttpMuxEntry()
282 { 342 {
283 explicit_match = false; 343 explicit_match = false;
@@ -565,473 +625,11 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size) @@ -565,473 +625,11 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size)
565 return skt->write((void*)buf.c_str(), buf.length(), NULL); 625 return skt->write((void*)buf.c_str(), buf.length(), NULL);
566 } 626 }
567 627
568 -SrsHttpHandlerMatch::SrsHttpHandlerMatch()  
569 -{  
570 - handler = NULL;  
571 -}  
572 -  
573 -SrsHttpHandler::SrsHttpHandler()  
574 -{  
575 -}  
576 -  
577 -SrsHttpHandler::~SrsHttpHandler()  
578 -{  
579 - std::vector<SrsHttpHandler*>::iterator it;  
580 - for (it = handlers.begin(); it != handlers.end(); ++it) {  
581 - SrsHttpHandler* handler = *it;  
582 - srs_freep(handler);  
583 - }  
584 - handlers.clear();  
585 -}  
586 -  
587 -int SrsHttpHandler::initialize()  
588 -{  
589 - int ret = ERROR_SUCCESS;  
590 - return ret;  
591 -}  
592 -  
593 -bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/, const char** /*pchild*/)  
594 -{  
595 - return false;  
596 -}  
597 -  
598 -int SrsHttpHandler::process_request(SrsStSocket* skt, SrsHttpMessage* req)  
599 -{  
600 - if (req->method() == SRS_CONSTS_HTTP_OPTIONS) {  
601 - req->set_requires_crossdomain(true);  
602 - return res_options(skt);  
603 - }  
604 -  
605 - int status_code;  
606 - std::string reason_phrase;  
607 - if (!is_handler_valid(req, status_code, reason_phrase)) {  
608 - std::stringstream ss;  
609 -  
610 - ss << __SRS_JOBJECT_START  
611 - << __SRS_JFIELD_ERROR(ERROR_HTTP_HANDLER_INVALID) << __SRS_JFIELD_CONT  
612 - << __SRS_JFIELD_ORG("data", __SRS_JOBJECT_START)  
613 - << __SRS_JFIELD_ORG("status_code", status_code) << __SRS_JFIELD_CONT  
614 - << __SRS_JFIELD_STR("reason_phrase", reason_phrase) << __SRS_JFIELD_CONT  
615 - << __SRS_JFIELD_STR("url", req->url())  
616 - << __SRS_JOBJECT_END  
617 - << __SRS_JOBJECT_END;  
618 -  
619 - return res_error(skt, req, status_code, reason_phrase, ss.str());  
620 - }  
621 -  
622 - return do_process_request(skt, req);  
623 -}  
624 -  
625 -bool SrsHttpHandler::is_handler_valid(SrsHttpMessage* req, int& status_code, string& reason_phrase)  
626 -{  
627 - if (!req->match()->unmatched_url.empty()) {  
628 - status_code = SRS_CONSTS_HTTP_NotFound;  
629 - reason_phrase = SRS_CONSTS_HTTP_NotFound_str;  
630 -  
631 - return false;  
632 - }  
633 -  
634 - return true;  
635 -}  
636 -  
637 -int SrsHttpHandler::do_process_request(SrsStSocket* /*skt*/, SrsHttpMessage* /*req*/)  
638 -{  
639 - int ret = ERROR_SUCCESS;  
640 - return ret;  
641 -}  
642 -  
643 -int SrsHttpHandler::response_error(SrsStSocket* skt, SrsHttpMessage* req, int code, string desc)  
644 -{  
645 - std::stringstream ss;  
646 - ss << __SRS_JOBJECT_START  
647 - << __SRS_JFIELD_ERROR(code) << __SRS_JFIELD_CONT  
648 - << __SRS_JFIELD_STR("desc", desc)  
649 - << __SRS_JOBJECT_END;  
650 -  
651 - return res_json(skt, req, ss.str());  
652 -}  
653 -  
654 -int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch)  
655 -{  
656 - int ret = ERROR_SUCCESS;  
657 -  
658 - SrsHttpHandler* handler = NULL;  
659 - const char* match_start = NULL;  
660 - int match_length = 0;  
661 -  
662 - for (;;) {  
663 - // ensure cur is not NULL.  
664 - // ensure p not NULL and has bytes to parse.  
665 - if (!path || length <= 0) {  
666 - break;  
667 - }  
668 -  
669 - const char* p = NULL;  
670 - for (p = path + 1; p - path < length && *p != SRS_CONSTS_HTTP_PATH_SEP; p++) {  
671 - }  
672 -  
673 - // whether the handler can handler the node.  
674 - const char* pchild = p;  
675 - if (!can_handle(path, p - path, &pchild)) {  
676 - break;  
677 - }  
678 -  
679 - // save current handler, it's ok for current handler atleast.  
680 - handler = this;  
681 - match_start = path;  
682 - match_length = p - path;  
683 -  
684 - // find the best matched child handler.  
685 - std::vector<SrsHttpHandler*>::iterator it;  
686 - for (it = handlers.begin(); it != handlers.end(); ++it) {  
687 - SrsHttpHandler* h = *it;  
688 -  
689 - // matched, donot search more.  
690 - if (h->best_match(pchild, length - (pchild - path), ppmatch) == ERROR_SUCCESS) {  
691 - break;  
692 - }  
693 - }  
694 -  
695 - // whatever, donot loop.  
696 - break;  
697 - }  
698 -  
699 - // if already matched by child, return.  
700 - if (*ppmatch) {  
701 - return ret;  
702 - }  
703 -  
704 - // not matched, error.  
705 - if (handler == NULL) {  
706 - ret = ERROR_HTTP_HANDLER_MATCH_URL;  
707 - return ret;  
708 - }  
709 -  
710 - // matched by this handler.  
711 - *ppmatch = new SrsHttpHandlerMatch();  
712 - (*ppmatch)->handler = handler;  
713 - (*ppmatch)->matched_url.append(match_start, match_length);  
714 -  
715 - int unmatch_length = length - match_length;  
716 - if (unmatch_length > 0) {  
717 - (*ppmatch)->unmatched_url.append(match_start + match_length, unmatch_length);  
718 - }  
719 -  
720 - return ret;  
721 -}  
722 -  
723 -SrsHttpHandler* SrsHttpHandler::res_status_line(stringstream& ss)  
724 -{  
725 - ss << "HTTP/1.1 200 OK " << __SRS_CRLF  
726 - << "Server: "RTMP_SIG_SRS_KEY"/"RTMP_SIG_SRS_VERSION"" << __SRS_CRLF;  
727 - return this;  
728 -}  
729 -  
730 -SrsHttpHandler* SrsHttpHandler::res_status_line_error(stringstream& ss, int code, string reason_phrase)  
731 -{  
732 - ss << "HTTP/1.1 " << code << " " << reason_phrase << __SRS_CRLF  
733 - << "Server: SRS/"RTMP_SIG_SRS_VERSION"" << __SRS_CRLF;  
734 - return this;  
735 -}  
736 -  
737 -SrsHttpHandler* SrsHttpHandler::res_content_type(stringstream& ss)  
738 -{  
739 - ss << "Content-Type: text/html;charset=utf-8" << __SRS_CRLF  
740 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
741 - return this;  
742 -}  
743 -  
744 -SrsHttpHandler* SrsHttpHandler::res_content_type_xml(stringstream& ss)  
745 -{  
746 - ss << "Content-Type: text/xml;charset=utf-8" << __SRS_CRLF  
747 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
748 - return this;  
749 -}  
750 -  
751 -SrsHttpHandler* SrsHttpHandler::res_content_type_javascript(stringstream& ss)  
752 -{  
753 - ss << "Content-Type: text/javascript" << __SRS_CRLF  
754 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
755 - return this;  
756 -}  
757 -  
758 -SrsHttpHandler* SrsHttpHandler::res_content_type_swf(stringstream& ss)  
759 -{  
760 - ss << "Content-Type: application/x-shockwave-flash" << __SRS_CRLF  
761 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
762 - return this;  
763 -}  
764 -  
765 -SrsHttpHandler* SrsHttpHandler::res_content_type_css(stringstream& ss)  
766 -{  
767 - ss << "Content-Type: text/css;charset=utf-8" << __SRS_CRLF  
768 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
769 - return this;  
770 -}  
771 -  
772 -SrsHttpHandler* SrsHttpHandler::res_content_type_ico(stringstream& ss)  
773 -{  
774 - ss << "Content-Type: image/x-icon" << __SRS_CRLF  
775 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
776 - return this;  
777 -}  
778 -  
779 -SrsHttpHandler* SrsHttpHandler::res_content_type_json(stringstream& ss)  
780 -{  
781 - ss << "Content-Type: application/json;charset=utf-8" << __SRS_CRLF  
782 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
783 - return this;  
784 -}  
785 -  
786 -SrsHttpHandler* SrsHttpHandler::res_content_type_m3u8(stringstream& ss)  
787 -{  
788 - ss << "Content-Type: application/x-mpegURL;charset=utf-8" << __SRS_CRLF  
789 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
790 - return this;  
791 -}  
792 -  
793 -SrsHttpHandler* SrsHttpHandler::res_content_type_mpegts(stringstream& ss)  
794 -{  
795 - ss << "Content-Type: video/MP2T" << __SRS_CRLF  
796 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
797 - return this;  
798 -}  
799 -  
800 -SrsHttpHandler* SrsHttpHandler::res_content_type_flv(stringstream& ss)  
801 -{  
802 - ss << "Content-Type: video/x-flv" << __SRS_CRLF  
803 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __SRS_CRLF;  
804 - return this;  
805 -}  
806 -  
807 -SrsHttpHandler* SrsHttpHandler::res_content_length(stringstream& ss, int64_t length)  
808 -{  
809 - ss << "Content-Length: "<< length << __SRS_CRLF;  
810 - return this;  
811 -}  
812 -  
813 -SrsHttpHandler* SrsHttpHandler::res_enable_crossdomain(stringstream& ss)  
814 -{  
815 - ss << "Access-Control-Allow-Origin: *" << __SRS_CRLF  
816 - << "Access-Control-Allow-Methods: "  
817 - << "GET, POST, HEAD, PUT, DELETE" << __SRS_CRLF  
818 - << "Access-Control-Allow-Headers: "  
819 - << "Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type" << __SRS_CRLF;  
820 - return this;  
821 -}  
822 -  
823 -SrsHttpHandler* SrsHttpHandler::res_header_eof(stringstream& ss)  
824 -{  
825 - ss << __SRS_CRLF;  
826 - return this;  
827 -}  
828 -  
829 -SrsHttpHandler* SrsHttpHandler::res_body(stringstream& ss, string body)  
830 -{  
831 - ss << body;  
832 - return this;  
833 -}  
834 -  
835 -int SrsHttpHandler::res_flush(SrsStSocket* skt, stringstream& ss)  
836 -{  
837 - return skt->write((void*)ss.str().c_str(), ss.str().length(), NULL);  
838 -}  
839 -  
840 -int SrsHttpHandler::res_options(SrsStSocket* skt)  
841 -{  
842 - std::stringstream ss;  
843 -  
844 - res_status_line(ss)->res_content_type(ss)  
845 - ->res_content_length(ss, 0)->res_enable_crossdomain(ss)  
846 - ->res_header_eof(ss);  
847 -  
848 - return res_flush(skt, ss);  
849 -}  
850 -  
851 -int SrsHttpHandler::res_text(SrsStSocket* skt, SrsHttpMessage* req, string body)  
852 -{  
853 - std::stringstream ss;  
854 -  
855 - res_status_line(ss)->res_content_type(ss)  
856 - ->res_content_length(ss, (int)body.length());  
857 -  
858 - if (req->requires_crossdomain()) {  
859 - res_enable_crossdomain(ss);  
860 - }  
861 -  
862 - res_header_eof(ss)  
863 - ->res_body(ss, body);  
864 -  
865 - return res_flush(skt, ss);  
866 -}  
867 -  
868 -int SrsHttpHandler::res_xml(SrsStSocket* skt, SrsHttpMessage* req, string body)  
869 -{  
870 - std::stringstream ss;  
871 -  
872 - res_status_line(ss)->res_content_type_xml(ss)  
873 - ->res_content_length(ss, (int)body.length());  
874 -  
875 - if (req->requires_crossdomain()) {  
876 - res_enable_crossdomain(ss);  
877 - }  
878 -  
879 - res_header_eof(ss)  
880 - ->res_body(ss, body);  
881 -  
882 - return res_flush(skt, ss);  
883 -}  
884 -  
885 -int SrsHttpHandler::res_javascript(SrsStSocket* skt, SrsHttpMessage* req, string body)  
886 -{  
887 - std::stringstream ss;  
888 -  
889 - res_status_line(ss)->res_content_type_javascript(ss)  
890 - ->res_content_length(ss, (int)body.length());  
891 -  
892 - if (req->requires_crossdomain()) {  
893 - res_enable_crossdomain(ss);  
894 - }  
895 -  
896 - res_header_eof(ss)  
897 - ->res_body(ss, body);  
898 -  
899 - return res_flush(skt, ss);  
900 -}  
901 -  
902 -int SrsHttpHandler::res_swf(SrsStSocket* skt, SrsHttpMessage* req, string body)  
903 -{  
904 - std::stringstream ss;  
905 -  
906 - res_status_line(ss)->res_content_type_swf(ss)  
907 - ->res_content_length(ss, (int)body.length());  
908 -  
909 - if (req->requires_crossdomain()) {  
910 - res_enable_crossdomain(ss);  
911 - }  
912 -  
913 - res_header_eof(ss)  
914 - ->res_body(ss, body);  
915 -  
916 - return res_flush(skt, ss);  
917 -}  
918 -  
919 -int SrsHttpHandler::res_css(SrsStSocket* skt, SrsHttpMessage* req, string body)  
920 -{  
921 - std::stringstream ss;  
922 -  
923 - res_status_line(ss)->res_content_type_css(ss)  
924 - ->res_content_length(ss, (int)body.length());  
925 -  
926 - if (req->requires_crossdomain()) {  
927 - res_enable_crossdomain(ss);  
928 - }  
929 -  
930 - res_header_eof(ss)  
931 - ->res_body(ss, body);  
932 -  
933 - return res_flush(skt, ss);  
934 -}  
935 -  
936 -int SrsHttpHandler::res_ico(SrsStSocket* skt, SrsHttpMessage* req, string body)  
937 -{  
938 - std::stringstream ss;  
939 -  
940 - res_status_line(ss)->res_content_type_ico(ss)  
941 - ->res_content_length(ss, (int)body.length());  
942 -  
943 - if (req->requires_crossdomain()) {  
944 - res_enable_crossdomain(ss);  
945 - }  
946 -  
947 - res_header_eof(ss)  
948 - ->res_body(ss, body);  
949 -  
950 - return res_flush(skt, ss);  
951 -}  
952 -  
953 -int SrsHttpHandler::res_m3u8(SrsStSocket* skt, SrsHttpMessage* req, string body)  
954 -{  
955 - std::stringstream ss;  
956 -  
957 - res_status_line(ss)->res_content_type_m3u8(ss)  
958 - ->res_content_length(ss, (int)body.length());  
959 -  
960 - if (req->requires_crossdomain()) {  
961 - res_enable_crossdomain(ss);  
962 - }  
963 -  
964 - res_header_eof(ss)  
965 - ->res_body(ss, body);  
966 -  
967 - return res_flush(skt, ss);  
968 -}  
969 -  
970 -int SrsHttpHandler::res_mpegts(SrsStSocket* skt, SrsHttpMessage* req, string body)  
971 -{  
972 - std::stringstream ss;  
973 -  
974 - res_status_line(ss)->res_content_type_mpegts(ss)  
975 - ->res_content_length(ss, (int)body.length());  
976 -  
977 - if (req->requires_crossdomain()) {  
978 - res_enable_crossdomain(ss);  
979 - }  
980 -  
981 - res_header_eof(ss)  
982 - ->res_body(ss, body);  
983 -  
984 - return res_flush(skt, ss);  
985 -}  
986 -  
987 -int SrsHttpHandler::res_json(SrsStSocket* skt, SrsHttpMessage* req, string json)  
988 -{  
989 - std::stringstream ss;  
990 -  
991 - res_status_line(ss)->res_content_type_json(ss)  
992 - ->res_content_length(ss, (int)json.length());  
993 -  
994 - if (req->requires_crossdomain()) {  
995 - res_enable_crossdomain(ss);  
996 - }  
997 -  
998 - res_header_eof(ss)  
999 - ->res_body(ss, json);  
1000 -  
1001 - return res_flush(skt, ss);  
1002 -}  
1003 -  
1004 -int SrsHttpHandler::res_error(SrsStSocket* skt, SrsHttpMessage* req, int code, string reason_phrase, string body)  
1005 -{  
1006 - std::stringstream ss;  
1007 -  
1008 - res_status_line_error(ss, code, reason_phrase)->res_content_type_json(ss)  
1009 - ->res_content_length(ss, (int)body.length());  
1010 -  
1011 - if (req->requires_crossdomain()) {  
1012 - res_enable_crossdomain(ss);  
1013 - }  
1014 -  
1015 - res_header_eof(ss)  
1016 - ->res_body(ss, body);  
1017 -  
1018 - return res_flush(skt, ss);  
1019 -}  
1020 -  
1021 -#ifdef SRS_AUTO_HTTP_SERVER  
1022 -SrsHttpHandler* SrsHttpHandler::create_http_stream()  
1023 -{  
1024 - return new SrsHttpRoot();  
1025 -}  
1026 -#endif  
1027 -  
1028 SrsHttpMessage::SrsHttpMessage() 628 SrsHttpMessage::SrsHttpMessage()
1029 { 629 {
1030 _body = new SrsSimpleBuffer(); 630 _body = new SrsSimpleBuffer();
1031 _state = SrsHttpParseStateInit; 631 _state = SrsHttpParseStateInit;
1032 _uri = new SrsHttpUri(); 632 _uri = new SrsHttpUri();
1033 - _match = NULL;  
1034 - _requires_crossdomain = false;  
1035 _http_ts_send_buffer = new char[__SRS_HTTP_TS_SEND_BUFFER_SIZE]; 633 _http_ts_send_buffer = new char[__SRS_HTTP_TS_SEND_BUFFER_SIZE];
1036 } 634 }
1037 635
@@ -1039,7 +637,6 @@ SrsHttpMessage::~SrsHttpMessage() @@ -1039,7 +637,6 @@ SrsHttpMessage::~SrsHttpMessage()
1039 { 637 {
1040 srs_freep(_body); 638 srs_freep(_body);
1041 srs_freep(_uri); 639 srs_freep(_uri);
1042 - srs_freep(_match);  
1043 srs_freep(_http_ts_send_buffer); 640 srs_freep(_http_ts_send_buffer);
1044 } 641 }
1045 642
@@ -1204,16 +801,6 @@ int64_t SrsHttpMessage::content_length() @@ -1204,16 +801,6 @@ int64_t SrsHttpMessage::content_length()
1204 return _header.content_length; 801 return _header.content_length;
1205 } 802 }
1206 803
1207 -SrsHttpHandlerMatch* SrsHttpMessage::match()  
1208 -{  
1209 - return _match;  
1210 -}  
1211 -  
1212 -bool SrsHttpMessage::requires_crossdomain()  
1213 -{  
1214 - return _requires_crossdomain;  
1215 -}  
1216 -  
1217 void SrsHttpMessage::set_url(string url) 804 void SrsHttpMessage::set_url(string url)
1218 { 805 {
1219 _url = url; 806 _url = url;
@@ -1229,17 +816,6 @@ void SrsHttpMessage::set_header(http_parser* header) @@ -1229,17 +816,6 @@ void SrsHttpMessage::set_header(http_parser* header)
1229 memcpy(&_header, header, sizeof(http_parser)); 816 memcpy(&_header, header, sizeof(http_parser));
1230 } 817 }
1231 818
1232 -void SrsHttpMessage::set_match(SrsHttpHandlerMatch* match)  
1233 -{  
1234 - srs_freep(_match);  
1235 - _match = match;  
1236 -}  
1237 -  
1238 -void SrsHttpMessage::set_requires_crossdomain(bool requires_crossdomain)  
1239 -{  
1240 - _requires_crossdomain = requires_crossdomain;  
1241 -}  
1242 -  
1243 void SrsHttpMessage::append_body(const char* body, int length) 819 void SrsHttpMessage::append_body(const char* body, int length)
1244 { 820 {
1245 _body->append(body, length); 821 _body->append(body, length);
@@ -70,15 +70,6 @@ class ISrsGoHttpResponseWriter; @@ -70,15 +70,6 @@ class ISrsGoHttpResponseWriter;
70 // helper function: response in json format. 70 // helper function: response in json format.
71 extern int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, std::string data); 71 extern int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, std::string data);
72 72
73 -// compare the path.  
74 -// full compare, extractly match.  
75 -// used for api match.  
76 -extern bool srs_path_equals(const char* expect, const char* path, int nb_path);  
77 -// compare the path use like,  
78 -// used for http stream to match,  
79 -// if the path like the requires  
80 -extern bool srs_path_like(const char* expect, const char* path, int nb_path);  
81 -  
82 // state of message 73 // state of message
83 enum SrsHttpParseState { 74 enum SrsHttpParseState {
84 SrsHttpParseStateInit = 0, 75 SrsHttpParseStateInit = 0,
@@ -196,6 +187,25 @@ public: @@ -196,6 +187,25 @@ public:
196 virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); 187 virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
197 }; 188 };
198 189
  190 +// FileServer returns a handler that serves HTTP requests
  191 +// with the contents of the file system rooted at root.
  192 +//
  193 +// To use the operating system's file system implementation,
  194 +// use http.Dir:
  195 +//
  196 +// http.Handle("/", SrsGoHttpFileServer("/tmp"))
  197 +// http.Handle("/", SrsGoHttpFileServer("static-dir"))
  198 +class SrsGoHttpFileServer : public ISrsGoHttpHandler
  199 +{
  200 +private:
  201 + std::string dir;
  202 +public:
  203 + SrsGoHttpFileServer(std::string root_dir);
  204 + virtual ~SrsGoHttpFileServer();
  205 +public:
  206 + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
  207 +};
  208 +
199 // the mux entry for server mux. 209 // the mux entry for server mux.
200 class SrsGoHttpMuxEntry 210 class SrsGoHttpMuxEntry
201 { 211 {
@@ -294,115 +304,6 @@ public: @@ -294,115 +304,6 @@ public:
294 virtual int send_header(char* data, int size); 304 virtual int send_header(char* data, int size);
295 }; 305 };
296 306
297 -/**  
298 -* the matched handler info.  
299 -*/  
300 -class SrsHttpHandlerMatch  
301 -{  
302 -public:  
303 - SrsHttpHandler* handler;  
304 - std::string matched_url;  
305 - std::string unmatched_url;  
306 -public:  
307 - SrsHttpHandlerMatch();  
308 -};  
309 -  
310 -/**  
311 -* resource handler for HTTP RESTful api.  
312 -*/  
313 -class SrsHttpHandler  
314 -{  
315 -protected:  
316 - /**  
317 - * we use handler chain to process request.  
318 - */  
319 - std::vector<SrsHttpHandler*> handlers;  
320 -public:  
321 - SrsHttpHandler();  
322 - virtual ~SrsHttpHandler();  
323 -public:  
324 - /**  
325 - * initialize the handler.  
326 - */  
327 - virtual int initialize();  
328 - /**  
329 - * whether current handler can handle the specified path.  
330 - * @pchild set the next child path, if needed.  
331 - * for example, the root handler will reset pchild to path,  
332 - * to reparse the path use child handlers.  
333 - */  
334 - virtual bool can_handle(const char* path, int length, const char** pchild);  
335 - /**  
336 - * use the handler to process the request.  
337 - * @remark sub classes should override the do_process_request.  
338 - */  
339 - virtual int process_request(SrsStSocket* skt, SrsHttpMessage* req);  
340 -public:  
341 - /**  
342 - * find the best matched handler  
343 - */  
344 - virtual int best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch);  
345 -// factory methods  
346 -protected:  
347 - /**  
348 - * check whether the handler is valid.  
349 - * for example, user access /apis, actually it's not found,  
350 - * we will find the root handler to process it.  
351 - * @remark user can override this method, and should invoke it first.  
352 - * @see SrsApiRoot::is_handler_valid  
353 - */  
354 - virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase);  
355 - /**  
356 - * do the actual process of request., format as, for example:  
357 - * {"code":0, "data":{}}  
358 - */  
359 - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);  
360 - /**  
361 - * response error, format as, for example:  
362 - * {"code":100, "desc":"description"}  
363 - */  
364 - virtual int response_error(SrsStSocket* skt, SrsHttpMessage* req, int code, std::string desc);  
365 -// response writer  
366 -public:  
367 - virtual SrsHttpHandler* res_status_line(std::stringstream& ss);  
368 - virtual SrsHttpHandler* res_status_line_error(std::stringstream& ss, int code, std::string reason_phrase);  
369 - virtual SrsHttpHandler* res_content_type(std::stringstream& ss);  
370 - virtual SrsHttpHandler* res_content_type_xml(std::stringstream& ss);  
371 - virtual SrsHttpHandler* res_content_type_javascript(std::stringstream& ss);  
372 - virtual SrsHttpHandler* res_content_type_swf(std::stringstream& ss);  
373 - virtual SrsHttpHandler* res_content_type_css(std::stringstream& ss);  
374 - virtual SrsHttpHandler* res_content_type_ico(std::stringstream& ss);  
375 - virtual SrsHttpHandler* res_content_type_json(std::stringstream& ss);  
376 - virtual SrsHttpHandler* res_content_type_m3u8(std::stringstream& ss);  
377 - virtual SrsHttpHandler* res_content_type_mpegts(std::stringstream& ss);  
378 - virtual SrsHttpHandler* res_content_type_flv(std::stringstream& ss);  
379 - virtual SrsHttpHandler* res_content_length(std::stringstream& ss, int64_t length);  
380 - virtual SrsHttpHandler* res_enable_crossdomain(std::stringstream& ss);  
381 - virtual SrsHttpHandler* res_header_eof(std::stringstream& ss);  
382 - virtual SrsHttpHandler* res_body(std::stringstream& ss, std::string body);  
383 - virtual int res_flush(SrsStSocket* skt, std::stringstream& ss);  
384 -public:  
385 - virtual int res_options(SrsStSocket* skt);  
386 - virtual int res_text(SrsStSocket* skt, SrsHttpMessage* req, std::string body);  
387 - virtual int res_xml(SrsStSocket* skt, SrsHttpMessage* req, std::string body);  
388 - virtual int res_javascript(SrsStSocket* skt, SrsHttpMessage* req, std::string body);  
389 - virtual int res_swf(SrsStSocket* skt, SrsHttpMessage* req, std::string body);  
390 - virtual int res_css(SrsStSocket* skt, SrsHttpMessage* req, std::string body);  
391 - virtual int res_ico(SrsStSocket* skt, SrsHttpMessage* req, std::string body);  
392 - virtual int res_m3u8(SrsStSocket* skt, SrsHttpMessage* req, std::string body);  
393 - virtual int res_mpegts(SrsStSocket* skt, SrsHttpMessage* req, std::string body);  
394 - virtual int res_json(SrsStSocket* skt, SrsHttpMessage* req, std::string json);  
395 - virtual int res_error(SrsStSocket* skt, SrsHttpMessage* req, int code, std::string reason_phrase, std::string body);  
396 -// object creator  
397 -public:  
398 - /**  
399 - * create http stream resource handler.  
400 - */  
401 -#ifdef SRS_AUTO_HTTP_SERVER  
402 - static SrsHttpHandler* create_http_stream();  
403 -#endif  
404 -};  
405 -  
406 // A Request represents an HTTP request received by a server 307 // A Request represents an HTTP request received by a server
407 // or to be sent by a client. 308 // or to be sent by a client.
408 // 309 //
@@ -438,14 +339,6 @@ private: @@ -438,14 +339,6 @@ private:
438 */ 339 */
439 SrsHttpUri* _uri; 340 SrsHttpUri* _uri;
440 /** 341 /**
441 - * best matched handler.  
442 - */  
443 - SrsHttpHandlerMatch* _match;  
444 - /**  
445 - * whether the message requires crossdomain.  
446 - */  
447 - bool _requires_crossdomain;  
448 - /**  
449 * use a buffer to read and send ts file. 342 * use a buffer to read and send ts file.
450 */ 343 */
451 char* _http_ts_send_buffer; 344 char* _http_ts_send_buffer;
@@ -481,13 +374,9 @@ public: @@ -481,13 +374,9 @@ public:
481 virtual char* body_raw(); 374 virtual char* body_raw();
482 virtual int64_t body_size(); 375 virtual int64_t body_size();
483 virtual int64_t content_length(); 376 virtual int64_t content_length();
484 - virtual SrsHttpHandlerMatch* match();  
485 - virtual bool requires_crossdomain();  
486 virtual void set_url(std::string url); 377 virtual void set_url(std::string url);
487 virtual void set_state(SrsHttpParseState state); 378 virtual void set_state(SrsHttpParseState state);
488 virtual void set_header(http_parser* header); 379 virtual void set_header(http_parser* header);
489 - virtual void set_match(SrsHttpHandlerMatch* match);  
490 - virtual void set_requires_crossdomain(bool requires_crossdomain);  
491 virtual void append_body(const char* body, int length); 380 virtual void append_body(const char* body, int length);
492 /** 381 /**
493 * get the param in query string, 382 * get the param in query string,
@@ -431,8 +431,6 @@ SrsGoApiVhosts::~SrsGoApiVhosts() @@ -431,8 +431,6 @@ SrsGoApiVhosts::~SrsGoApiVhosts()
431 431
432 int SrsGoApiVhosts::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) 432 int SrsGoApiVhosts::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
433 { 433 {
434 - SrsHttpMessage* req = r;  
435 -  
436 std::stringstream data; 434 std::stringstream data;
437 SrsStatistic* stat = SrsStatistic::instance(); 435 SrsStatistic* stat = SrsStatistic::instance();
438 int ret = stat->dumps_vhosts(data); 436 int ret = stat->dumps_vhosts(data);
@@ -40,20 +40,16 @@ using namespace std; @@ -40,20 +40,16 @@ using namespace std;
40 #include <srs_app_config.hpp> 40 #include <srs_app_config.hpp>
41 #include <srs_kernel_flv.hpp> 41 #include <srs_kernel_flv.hpp>
42 #include <srs_kernel_utility.hpp> 42 #include <srs_kernel_utility.hpp>
43 -#include <srs_kernel_file.hpp>  
44 43
45 -#define SRS_HTTP_DEFAULT_PAGE "index.html"  
46 -  
47 -SrsHttpRoot::SrsHttpRoot() 44 +SrsHttpServer::SrsHttpServer()
48 { 45 {
49 - // TODO: FIXME: support reload vhosts.  
50 } 46 }
51 47
52 -SrsHttpRoot::~SrsHttpRoot() 48 +SrsHttpServer::~SrsHttpServer()
53 { 49 {
54 } 50 }
55 51
56 -int SrsHttpRoot::initialize() 52 +int SrsHttpServer::initialize()
57 { 53 {
58 int ret = ERROR_SUCCESS; 54 int ret = ERROR_SUCCESS;
59 55
@@ -76,7 +72,10 @@ int SrsHttpRoot::initialize() @@ -76,7 +72,10 @@ int SrsHttpRoot::initialize()
76 std::string mount = _srs_config->get_vhost_http_mount(vhost); 72 std::string mount = _srs_config->get_vhost_http_mount(vhost);
77 std::string dir = _srs_config->get_vhost_http_dir(vhost); 73 std::string dir = _srs_config->get_vhost_http_dir(vhost);
78 74
79 - handlers.push_back(new SrsHttpVhost(vhost, mount, dir)); 75 + if ((ret = mux.handle(mount, new SrsGoHttpFileServer(dir))) != ERROR_SUCCESS) {
  76 + srs_error("http: mount dir=%s for vhost=%s failed. ret=%d", dir.c_str(), vhost.c_str(), ret);
  77 + return ret;
  78 + }
80 79
81 if (mount == "/") { 80 if (mount == "/") {
82 default_root_exists = true; 81 default_root_exists = true;
@@ -85,403 +84,21 @@ int SrsHttpRoot::initialize() @@ -85,403 +84,21 @@ int SrsHttpRoot::initialize()
85 84
86 if (!default_root_exists) { 85 if (!default_root_exists) {
87 // add root 86 // add root
88 - handlers.push_back(new SrsHttpVhost(  
89 - "__http__", "/", _srs_config->get_http_stream_dir()));  
90 - }  
91 -  
92 - return ret;  
93 -}  
94 -  
95 -int SrsHttpRoot::best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch)  
96 -{  
97 - int ret = ERROR_SUCCESS;  
98 -  
99 - // find the best matched child handler.  
100 - std::vector<SrsHttpHandler*>::iterator it;  
101 - for (it = handlers.begin(); it != handlers.end(); ++it) {  
102 - SrsHttpHandler* h = *it;  
103 -  
104 - // search all child handlers.  
105 - h->best_match(path, length, ppmatch);  
106 - }  
107 -  
108 - // if already matched by child, return.  
109 - if (*ppmatch) {  
110 - return ret;  
111 - }  
112 -  
113 - // not matched, error.  
114 - return ERROR_HTTP_HANDLER_MATCH_URL;  
115 -}  
116 -  
117 -bool SrsHttpRoot::is_handler_valid(SrsHttpMessage* /*req*/, int& status_code, std::string& reason_phrase)  
118 -{  
119 - status_code = SRS_CONSTS_HTTP_InternalServerError;  
120 - reason_phrase = SRS_CONSTS_HTTP_InternalServerError_str;  
121 -  
122 - return false;  
123 -}  
124 -  
125 -int SrsHttpRoot::do_process_request(SrsStSocket* /*skt*/, SrsHttpMessage* /*req*/)  
126 -{  
127 - int ret = ERROR_SUCCESS;  
128 - return ret;  
129 -}  
130 -  
131 -SrsHttpVhost::SrsHttpVhost(std::string vhost, std::string mount, std::string dir)  
132 -{  
133 - _vhost = vhost;  
134 - _mount = mount;  
135 - _dir = dir;  
136 -}  
137 -  
138 -SrsHttpVhost::~SrsHttpVhost()  
139 -{  
140 -}  
141 -  
142 -bool SrsHttpVhost::can_handle(const char* path, int length, const char** /*pchild*/)  
143 -{  
144 - return srs_path_like(_mount.c_str(), path, length);  
145 -}  
146 -  
147 -bool SrsHttpVhost::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase)  
148 -{  
149 - std::string fullpath = get_request_file(req);  
150 -  
151 - if (::access(fullpath.c_str(), F_OK | R_OK) < 0) {  
152 - srs_warn("check file %s does not exists", fullpath.c_str());  
153 -  
154 - status_code = SRS_CONSTS_HTTP_NotFound;  
155 - reason_phrase = SRS_CONSTS_HTTP_NotFound_str;  
156 - return false;  
157 - }  
158 -  
159 - return true;  
160 -}  
161 -  
162 -int SrsHttpVhost::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)  
163 -{  
164 - std::string fullpath = get_request_file(req);  
165 -  
166 - // TODO: FIXME: support mp4, @see https://github.com/winlinvip/simple-rtmp-server/issues/174  
167 - if (srs_string_ends_with(fullpath, ".ts")) {  
168 - return response_ts_file(skt, req, fullpath);  
169 - } else if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) {  
170 - std::string start = req->query_get("start");  
171 - if (start.empty()) {  
172 - return response_flv_file(skt, req, fullpath);  
173 - }  
174 -  
175 - int offset = ::atoi(start.c_str());  
176 - if (offset <= 0) {  
177 - return response_flv_file(skt, req, fullpath);  
178 - }  
179 -  
180 - return response_flv_file2(skt, req, fullpath, offset);  
181 - }  
182 -  
183 - return response_regular_file(skt, req, fullpath);  
184 -}  
185 -  
186 -int SrsHttpVhost::response_regular_file(SrsStSocket* skt, SrsHttpMessage* req, string fullpath)  
187 -{  
188 - int ret = ERROR_SUCCESS;  
189 -  
190 - SrsFileReader fs;  
191 -  
192 - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {  
193 - srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);  
194 - return ret;  
195 - }  
196 -  
197 - int64_t length = fs.filesize();  
198 -  
199 - char* buf = new char[length];  
200 - SrsAutoFree(char, buf);  
201 -  
202 - if ((ret = fs.read(buf, length, NULL)) != ERROR_SUCCESS) {  
203 - srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);  
204 - return ret;  
205 - }  
206 -  
207 - std::string str;  
208 - str.append(buf, length);  
209 -  
210 - if (srs_string_ends_with(fullpath, ".ts")) {  
211 - return res_mpegts(skt, req, str);  
212 - } else if (srs_string_ends_with(fullpath, ".m3u8")) {  
213 - return res_m3u8(skt, req, str);  
214 - } else if (srs_string_ends_with(fullpath, ".xml")) {  
215 - return res_xml(skt, req, str);  
216 - } else if (srs_string_ends_with(fullpath, ".js")) {  
217 - return res_javascript(skt, req, str);  
218 - } else if (srs_string_ends_with(fullpath, ".json")) {  
219 - return res_json(skt, req, str);  
220 - } else if (srs_string_ends_with(fullpath, ".swf")) {  
221 - return res_swf(skt, req, str);  
222 - } else if (srs_string_ends_with(fullpath, ".css")) {  
223 - return res_css(skt, req, str);  
224 - } else if (srs_string_ends_with(fullpath, ".ico")) {  
225 - return res_ico(skt, req, str);  
226 - } else {  
227 - return res_text(skt, req, str);  
228 - }  
229 -  
230 - return ret;  
231 -}  
232 -  
233 -int SrsHttpVhost::response_flv_file(SrsStSocket* skt, SrsHttpMessage* req, string fullpath)  
234 -{  
235 - int ret = ERROR_SUCCESS;  
236 -  
237 - SrsFileReader fs;  
238 -  
239 - // TODO: FIXME: use more advance cache.  
240 - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {  
241 - srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);  
242 - return ret;  
243 - }  
244 -  
245 - int64_t length = fs.filesize();  
246 -  
247 - // write http header for ts.  
248 - std::stringstream ss;  
249 -  
250 - res_status_line(ss)->res_content_type_flv(ss)  
251 - ->res_content_length(ss, (int)length);  
252 -  
253 - if (req->requires_crossdomain()) {  
254 - res_enable_crossdomain(ss);  
255 - }  
256 -  
257 - res_header_eof(ss);  
258 -  
259 - // flush http header to peer  
260 - if ((ret = res_flush(skt, ss)) != ERROR_SUCCESS) {  
261 - return ret;  
262 - }  
263 -  
264 - // write body.  
265 - int64_t left = length;  
266 - char* buf = req->http_ts_send_buffer();  
267 -  
268 - while (left > 0) {  
269 - ssize_t nread = -1;  
270 - if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) {  
271 - srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);  
272 - break;  
273 - }  
274 -  
275 - left -= nread;  
276 - if ((ret = skt->write(buf, nread, NULL)) != ERROR_SUCCESS) {  
277 - break;  
278 - }  
279 - }  
280 -  
281 - return ret;  
282 -}  
283 -  
284 -int SrsHttpVhost::response_flv_file2(SrsStSocket* skt, SrsHttpMessage* req, string fullpath, int offset)  
285 -{  
286 - int ret = ERROR_SUCCESS;  
287 -  
288 - SrsFileReader fs;  
289 -  
290 - // open flv file  
291 - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {  
292 - return ret;  
293 - }  
294 -  
295 - if (offset > fs.filesize()) {  
296 - ret = ERROR_HTTP_FLV_OFFSET_OVERFLOW;  
297 - srs_warn("http flv streaming %s overflow. size=%"PRId64", offset=%d, ret=%d",  
298 - fullpath.c_str(), fs.filesize(), offset, ret);  
299 - return ret;  
300 - }  
301 -  
302 - SrsFlvVodStreamDecoder ffd;  
303 -  
304 - // open fast decoder  
305 - if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) {  
306 - return ret;  
307 - }  
308 -  
309 - // save header, send later.  
310 - char flv_header[13];  
311 -  
312 - // send flv header  
313 - if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) {  
314 - return ret;  
315 - }  
316 -  
317 - // save sequence header, send later  
318 - char* sh_data = NULL;  
319 - int sh_size = 0;  
320 -  
321 - if (true) {  
322 - // send sequence header  
323 - int64_t start = 0;  
324 - if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) {  
325 - return ret;  
326 - }  
327 - if (sh_size <= 0) {  
328 - ret = ERROR_HTTP_FLV_SEQUENCE_HEADER;  
329 - srs_warn("http flv streaming no sequence header. size=%d, ret=%d", sh_size, ret); 87 + std::string dir = _srs_config->get_http_stream_dir();
  88 + if ((ret = mux.handle("/", new SrsGoHttpFileServer(dir))) != ERROR_SUCCESS) {
  89 + srs_error("http: mount root dir=%s failed. ret=%d", dir.c_str(), ret);
330 return ret; 90 return ret;
331 } 91 }
332 } 92 }
333 - sh_data = new char[sh_size];  
334 - SrsAutoFree(char, sh_data);  
335 - if ((ret = fs.read(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {  
336 - return ret;  
337 - }  
338 -  
339 - // seek to data offset  
340 - int64_t left = fs.filesize() - offset;  
341 -  
342 - // write http header for ts.  
343 - std::stringstream ss;  
344 -  
345 - res_status_line(ss)->res_content_type_flv(ss)  
346 - ->res_content_length(ss, (int)(sizeof(flv_header) + sh_size + left));  
347 -  
348 - if (req->requires_crossdomain()) {  
349 - res_enable_crossdomain(ss);  
350 - }  
351 -  
352 - res_header_eof(ss);  
353 -  
354 - // flush http header to peer  
355 - if ((ret = res_flush(skt, ss)) != ERROR_SUCCESS) {  
356 - return ret;  
357 - }  
358 -  
359 - if ((ret = skt->write(flv_header, sizeof(flv_header), NULL)) != ERROR_SUCCESS) {  
360 - return ret;  
361 - }  
362 - if (sh_size > 0 && (ret = skt->write(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {  
363 - return ret;  
364 - }  
365 -  
366 - // write body.  
367 - char* buf = req->http_ts_send_buffer();  
368 - if ((ret = ffd.lseek(offset)) != ERROR_SUCCESS) {  
369 - return ret;  
370 - }  
371 -  
372 - // send data  
373 - while (left > 0) {  
374 - ssize_t nread = -1;  
375 - if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) {  
376 - return ret;  
377 - }  
378 -  
379 - left -= nread;  
380 - if ((ret = skt->write(buf, nread, NULL)) != ERROR_SUCCESS) {  
381 - return ret;  
382 - }  
383 - }  
384 -  
385 - return ret;  
386 -}  
387 -  
388 -int SrsHttpVhost::response_ts_file(SrsStSocket* skt, SrsHttpMessage* req, string fullpath)  
389 -{  
390 - int ret = ERROR_SUCCESS;  
391 -  
392 - SrsFileReader fs;  
393 -  
394 - // TODO: FIXME: use more advance cache.  
395 - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) {  
396 - srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);  
397 - return ret;  
398 - }  
399 -  
400 - int64_t length = fs.filesize();  
401 -  
402 - // write http header for ts.  
403 - std::stringstream ss;  
404 -  
405 - res_status_line(ss)->res_content_type_mpegts(ss)  
406 - ->res_content_length(ss, (int)length);  
407 -  
408 - if (req->requires_crossdomain()) {  
409 - res_enable_crossdomain(ss);  
410 - }  
411 -  
412 - res_header_eof(ss);  
413 -  
414 - // flush http header to peer  
415 - if ((ret = res_flush(skt, ss)) != ERROR_SUCCESS) {  
416 - return ret;  
417 - }  
418 -  
419 - // write body.  
420 - int64_t left = length;  
421 - char* buf = req->http_ts_send_buffer();  
422 -  
423 - while (left > 0) {  
424 - ssize_t nread = -1;  
425 - if ((ret = fs.read(buf, __SRS_HTTP_TS_SEND_BUFFER_SIZE, &nread)) != ERROR_SUCCESS) {  
426 - srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);  
427 - break;  
428 - }  
429 -  
430 - left -= nread;  
431 - if ((ret = skt->write(buf, nread, NULL)) != ERROR_SUCCESS) {  
432 - break;  
433 - }  
434 - }  
435 93
436 return ret; 94 return ret;
437 } 95 }
438 96
439 -string SrsHttpVhost::get_request_file(SrsHttpMessage* req)  
440 -{  
441 - std::string fullpath = _dir + "/";  
442 -  
443 - // if root, directly use the matched url.  
444 - if (_mount == "/") {  
445 - // add the dir  
446 - fullpath += req->match()->matched_url;  
447 - // if file speicified, add the file.  
448 - if (!req->match()->unmatched_url.empty()) {  
449 - fullpath += "/" + req->match()->unmatched_url;  
450 - }  
451 - } else {  
452 - // virtual path, ignore the virutal path.  
453 - fullpath += req->match()->unmatched_url;  
454 - }  
455 -  
456 - // add default pages.  
457 - if (srs_string_ends_with(fullpath, "/")) {  
458 - fullpath += SRS_HTTP_DEFAULT_PAGE;  
459 - }  
460 -  
461 - return fullpath;  
462 -}  
463 -  
464 -string SrsHttpVhost::vhost()  
465 -{  
466 - return _vhost;  
467 -}  
468 -  
469 -string SrsHttpVhost::mount()  
470 -{  
471 - return _mount;  
472 -}  
473 -  
474 -string SrsHttpVhost::dir()  
475 -{  
476 - return _dir;  
477 -}  
478 -  
479 -SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)  
480 - : SrsConnection(srs_server, client_stfd) 97 +SrsHttpConn::SrsHttpConn(SrsServer* svr, st_netfd_t fd, SrsHttpServer* m)
  98 + : SrsConnection(svr, fd)
481 { 99 {
482 parser = new SrsHttpParser(); 100 parser = new SrsHttpParser();
483 - handler = _handler;  
484 - requires_crossdomain = false; 101 + mux = m;
485 } 102 }
486 103
487 SrsHttpConn::~SrsHttpConn() 104 SrsHttpConn::~SrsHttpConn()
@@ -538,7 +155,8 @@ int SrsHttpConn::do_cycle() @@ -538,7 +155,8 @@ int SrsHttpConn::do_cycle()
538 SrsAutoFree(SrsHttpMessage, req); 155 SrsAutoFree(SrsHttpMessage, req);
539 156
540 // ok, handle http request. 157 // ok, handle http request.
541 - if ((ret = process_request(&skt, req)) != ERROR_SUCCESS) { 158 + SrsGoHttpResponseWriter writer(&skt);
  159 + if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) {
542 return ret; 160 return ret;
543 } 161 }
544 } 162 }
@@ -546,41 +164,21 @@ int SrsHttpConn::do_cycle() @@ -546,41 +164,21 @@ int SrsHttpConn::do_cycle()
546 return ret; 164 return ret;
547 } 165 }
548 166
549 -int SrsHttpConn::process_request(SrsStSocket* skt, SrsHttpMessage* req) 167 +int SrsHttpConn::process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
550 { 168 {
551 int ret = ERROR_SUCCESS; 169 int ret = ERROR_SUCCESS;
552 170
553 srs_trace("HTTP %s %s, content-length=%"PRId64"", 171 srs_trace("HTTP %s %s, content-length=%"PRId64"",
554 - req->method_str().c_str(), req->url().c_str(), req->content_length());  
555 -  
556 - // TODO: maybe need to parse the url.  
557 - std::string url = req->path();  
558 -  
559 - SrsHttpHandlerMatch* p = NULL;  
560 - if ((ret = handler->best_match(url.data(), url.length(), &p)) != ERROR_SUCCESS) {  
561 - srs_warn("failed to find the best match handler for url. ret=%d", ret);  
562 - return ret;  
563 - }  
564 -  
565 - // if success, p and pstart should be valid.  
566 - srs_assert(p);  
567 - srs_assert(p->handler);  
568 - srs_assert(p->matched_url.length() <= url.length());  
569 - srs_info("best match handler, matched_url=%s", p->matched_url.c_str());  
570 -  
571 - req->set_match(p);  
572 - req->set_requires_crossdomain(requires_crossdomain); 172 + r->method_str().c_str(), r->url().c_str(), r->content_length());
573 173
574 - // use handler to process request.  
575 - if ((ret = p->handler->process_request(skt, req)) != ERROR_SUCCESS) {  
576 - srs_warn("handler failed to process http request. ret=%d", ret); 174 + // use default server mux to serve http request.
  175 + if ((ret = mux->mux.serve_http(w, r)) != ERROR_SUCCESS) {
  176 + if (!srs_is_client_gracefully_close(ret)) {
  177 + srs_error("serve http msg failed. ret=%d", ret);
  178 + }
577 return ret; 179 return ret;
578 } 180 }
579 181
580 - if (req->requires_crossdomain()) {  
581 - requires_crossdomain = true;  
582 - }  
583 -  
584 return ret; 182 return ret;
585 } 183 }
586 184
@@ -41,54 +41,25 @@ class SrsHttpParser; @@ -41,54 +41,25 @@ class SrsHttpParser;
41 class SrsHttpMessage; 41 class SrsHttpMessage;
42 class SrsHttpHandler; 42 class SrsHttpHandler;
43 43
44 -// for http root.  
45 -class SrsHttpRoot : public SrsHttpHandler 44 +// for http server.
  45 +class SrsHttpServer
46 { 46 {
47 public: 47 public:
48 - SrsHttpRoot();  
49 - virtual ~SrsHttpRoot(); 48 + SrsGoHttpServeMux mux;
50 public: 49 public:
51 - virtual int initialize();  
52 - virtual int best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch);  
53 -protected:  
54 - virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase);  
55 - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);  
56 -};  
57 -  
58 -class SrsHttpVhost : public SrsHttpHandler  
59 -{  
60 -private:  
61 - std::string _vhost;  
62 - std::string _mount;  
63 - std::string _dir; 50 + SrsHttpServer();
  51 + virtual ~SrsHttpServer();
64 public: 52 public:
65 - SrsHttpVhost(std::string vhost, std::string mount, std::string dir);  
66 - virtual ~SrsHttpVhost();  
67 -public:  
68 - virtual bool can_handle(const char* path, int length, const char** pchild);  
69 -protected:  
70 - virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase);  
71 - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);  
72 -private:  
73 - virtual int response_regular_file(SrsStSocket* skt, SrsHttpMessage* req, std::string fullpath);  
74 - virtual int response_flv_file(SrsStSocket* skt, SrsHttpMessage* req, std::string fullpath);  
75 - virtual int response_flv_file2(SrsStSocket* skt, SrsHttpMessage* req, std::string fullpath, int offset);  
76 - virtual int response_ts_file(SrsStSocket* skt, SrsHttpMessage* req, std::string fullpath);  
77 - virtual std::string get_request_file(SrsHttpMessage* req);  
78 -public:  
79 - virtual std::string vhost();  
80 - virtual std::string mount();  
81 - virtual std::string dir(); 53 + virtual int initialize();
82 }; 54 };
83 55
84 class SrsHttpConn : public SrsConnection 56 class SrsHttpConn : public SrsConnection
85 { 57 {
86 private: 58 private:
87 SrsHttpParser* parser; 59 SrsHttpParser* parser;
88 - SrsHttpHandler* handler;  
89 - bool requires_crossdomain; 60 + SrsHttpServer* mux;
90 public: 61 public:
91 - SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler); 62 + SrsHttpConn(SrsServer* svr, st_netfd_t fd, SrsHttpServer* m);
92 virtual ~SrsHttpConn(); 63 virtual ~SrsHttpConn();
93 public: 64 public:
94 virtual void kbps_resample(); 65 virtual void kbps_resample();
@@ -99,7 +70,7 @@ public: @@ -99,7 +70,7 @@ public:
99 protected: 70 protected:
100 virtual int do_cycle(); 71 virtual int do_cycle();
101 private: 72 private:
102 - virtual int process_request(SrsStSocket* skt, SrsHttpMessage* req); 73 + virtual int process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
103 }; 74 };
104 75
105 #endif 76 #endif
@@ -333,7 +333,7 @@ SrsServer::SrsServer() @@ -333,7 +333,7 @@ SrsServer::SrsServer()
333 http_api_mux = new SrsGoHttpServeMux(); 333 http_api_mux = new SrsGoHttpServeMux();
334 #endif 334 #endif
335 #ifdef SRS_AUTO_HTTP_SERVER 335 #ifdef SRS_AUTO_HTTP_SERVER
336 - http_stream_handler = NULL; 336 + http_stream_mux = new SrsHttpServer();
337 #endif 337 #endif
338 #ifdef SRS_AUTO_HTTP_PARSER 338 #ifdef SRS_AUTO_HTTP_PARSER
339 http_heartbeat = NULL; 339 http_heartbeat = NULL;
@@ -367,7 +367,7 @@ void SrsServer::destroy() @@ -367,7 +367,7 @@ void SrsServer::destroy()
367 #endif 367 #endif
368 368
369 #ifdef SRS_AUTO_HTTP_SERVER 369 #ifdef SRS_AUTO_HTTP_SERVER
370 - srs_freep(http_stream_handler); 370 + srs_freep(http_stream_mux);
371 #endif 371 #endif
372 372
373 #ifdef SRS_AUTO_HTTP_PARSER 373 #ifdef SRS_AUTO_HTTP_PARSER
@@ -462,25 +462,24 @@ int SrsServer::initialize() @@ -462,25 +462,24 @@ int SrsServer::initialize()
462 return ret; 462 return ret;
463 } 463 }
464 #endif 464 #endif
  465 +
465 #ifdef SRS_AUTO_HTTP_SERVER 466 #ifdef SRS_AUTO_HTTP_SERVER
466 - srs_assert(!http_stream_handler);  
467 - http_stream_handler = SrsHttpHandler::create_http_stream(); 467 + srs_assert(http_stream_mux);
  468 + if ((ret = http_stream_mux->initialize()) != ERROR_SUCCESS) {
  469 + return ret;
  470 + }
468 #endif 471 #endif
  472 +
469 #ifdef SRS_AUTO_HTTP_PARSER 473 #ifdef SRS_AUTO_HTTP_PARSER
470 srs_assert(!http_heartbeat); 474 srs_assert(!http_heartbeat);
471 http_heartbeat = new SrsHttpHeartbeat(); 475 http_heartbeat = new SrsHttpHeartbeat();
472 #endif 476 #endif
  477 +
473 #ifdef SRS_AUTO_INGEST 478 #ifdef SRS_AUTO_INGEST
474 srs_assert(!ingester); 479 srs_assert(!ingester);
475 ingester = new SrsIngester(); 480 ingester = new SrsIngester();
476 #endif 481 #endif
477 482
478 -#ifdef SRS_AUTO_HTTP_SERVER  
479 - if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) {  
480 - return ret;  
481 - }  
482 -#endif  
483 -  
484 return ret; 483 return ret;
485 } 484 }
486 485
@@ -942,7 +941,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) @@ -942,7 +941,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
942 #endif 941 #endif
943 } else if (type == SrsListenerHttpStream) { 942 } else if (type == SrsListenerHttpStream) {
944 #ifdef SRS_AUTO_HTTP_SERVER 943 #ifdef SRS_AUTO_HTTP_SERVER
945 - conn = new SrsHttpConn(this, client_stfd, http_stream_handler); 944 + conn = new SrsHttpConn(this, client_stfd, http_stream_mux);
946 #else 945 #else
947 srs_warn("close http client for server not support http-server"); 946 srs_warn("close http client for server not support http-server");
948 srs_close_stfd(client_stfd); 947 srs_close_stfd(client_stfd);
@@ -1019,10 +1018,10 @@ int SrsServer::on_reload_vhost_http_updated() @@ -1019,10 +1018,10 @@ int SrsServer::on_reload_vhost_http_updated()
1019 int ret = ERROR_SUCCESS; 1018 int ret = ERROR_SUCCESS;
1020 1019
1021 #ifdef SRS_AUTO_HTTP_SERVER 1020 #ifdef SRS_AUTO_HTTP_SERVER
1022 - srs_freep(http_stream_handler);  
1023 - http_stream_handler = SrsHttpHandler::create_http_stream(); 1021 + srs_freep(http_stream_mux);
  1022 + http_stream_mux = new SrsHttpServer();
1024 1023
1025 - if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) { 1024 + if ((ret = http_stream_mux->initialize()) != ERROR_SUCCESS) {
1026 return ret; 1025 return ret;
1027 } 1026 }
1028 #endif 1027 #endif
@@ -39,7 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -39,7 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 class SrsServer; 39 class SrsServer;
40 class SrsConnection; 40 class SrsConnection;
41 class SrsGoHttpServeMux; 41 class SrsGoHttpServeMux;
42 -class SrsHttpHandler; 42 +class SrsHttpServer;
43 class SrsIngester; 43 class SrsIngester;
44 class SrsHttpHeartbeat; 44 class SrsHttpHeartbeat;
45 class SrsKbps; 45 class SrsKbps;
@@ -120,7 +120,7 @@ private: @@ -120,7 +120,7 @@ private:
120 SrsGoHttpServeMux* http_api_mux; 120 SrsGoHttpServeMux* http_api_mux;
121 #endif 121 #endif
122 #ifdef SRS_AUTO_HTTP_SERVER 122 #ifdef SRS_AUTO_HTTP_SERVER
123 - SrsHttpHandler* http_stream_handler; 123 + SrsHttpServer* http_stream_mux;
124 #endif 124 #endif
125 #ifdef SRS_AUTO_HTTP_PARSER 125 #ifdef SRS_AUTO_HTTP_PARSER
126 SrsHttpHeartbeat* http_heartbeat; 126 SrsHttpHeartbeat* http_heartbeat;
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR 2 32 #define VERSION_MAJOR 2
33 #define VERSION_MINOR 0 33 #define VERSION_MINOR 0
34 -#define VERSION_REVISION 96 34 +#define VERSION_REVISION 98
35 35
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"