winlin

refine http

@@ -409,7 +409,7 @@ LIBS_OBJS="${MODULE_OBJS[@]}" @@ -409,7 +409,7 @@ LIBS_OBJS="${MODULE_OBJS[@]}"
409 if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then 409 if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then
410 MODULE_ID="MAIN" 410 MODULE_ID="MAIN"
411 MODULE_DEPENDS=("CORE" "KERNEL" "RTMP" "APP") 411 MODULE_DEPENDS=("CORE" "KERNEL" "RTMP" "APP")
412 - ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot}) 412 + ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot} ${LibHttpParserRoot})
413 MODULE_FILES=("srs_main_server") 413 MODULE_FILES=("srs_main_server")
414 MAIN_INCS="src/main"; MODULE_DIR=${MAIN_INCS} . auto/modules.sh 414 MAIN_INCS="src/main"; MODULE_DIR=${MAIN_INCS} . auto/modules.sh
415 MAIN_OBJS="${MODULE_OBJS[@]}" 415 MAIN_OBJS="${MODULE_OBJS[@]}"
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE QtCreatorProject> 2 <!DOCTYPE QtCreatorProject>
3 -<!-- Written by QtCreator 3.1.1, 2015-01-29T11:22:06. --> 3 +<!-- Written by QtCreator 3.1.1, 2015-03-05T20:44:44. -->
4 <qtcreator> 4 <qtcreator>
5 <data> 5 <data>
6 <variable>ProjectExplorer.Project.ActiveTarget</variable> 6 <variable>ProjectExplorer.Project.ActiveTarget</variable>
@@ -56,12 +56,12 @@ @@ -56,12 +56,12 @@
56 <valuemap type="QVariantMap"> 56 <valuemap type="QVariantMap">
57 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value> 57 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
58 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value> 58 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
59 - <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{fa2d28f9-85de-4a75-8e79-69d805f974bf}</value> 59 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{fdda5a74-8ef6-4e67-b28c-c5be6c667578}</value>
60 <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value> 60 <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
61 <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value> 61 <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
62 <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value> 62 <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
63 <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0"> 63 <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
64 - <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/winlin/git/simple-rtmp-server/trunk/src/build-qt-Desktop-Debug</value> 64 + <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/winlin/git/simple-rtmp-server/trunk/ide/build-srs-qt-Desktop-Debug</value>
65 <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> 65 <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
66 <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> 66 <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
67 <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> 67 <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
@@ -119,7 +119,66 @@ @@ -119,7 +119,66 @@
119 <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value> 119 <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
120 <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> 120 <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
121 </valuemap> 121 </valuemap>
122 - <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value> 122 + <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
  123 + <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/winlin/git/simple-rtmp-server/trunk/ide/build-srs-qt-Desktop-Release</value>
  124 + <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
  125 + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
  126 + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
  127 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
  128 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
  129 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
  130 + <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
  131 + <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
  132 + <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
  133 + <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
  134 + </valuemap>
  135 + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
  136 + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
  137 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
  138 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
  139 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
  140 + <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
  141 + <value type="QString">-w</value>
  142 + <value type="QString">-r</value>
  143 + </valuelist>
  144 + <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
  145 + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
  146 + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
  147 + </valuemap>
  148 + <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
  149 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
  150 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
  151 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
  152 + </valuemap>
  153 + <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
  154 + <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
  155 + <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
  156 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
  157 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
  158 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
  159 + <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
  160 + <value type="QString">-w</value>
  161 + <value type="QString">-r</value>
  162 + </valuelist>
  163 + <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
  164 + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
  165 + <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
  166 + </valuemap>
  167 + <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
  168 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
  169 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
  170 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
  171 + </valuemap>
  172 + <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
  173 + <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
  174 + <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
  175 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
  176 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
  177 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
  178 + <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
  179 + <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
  180 + </valuemap>
  181 + <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
123 <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0"> 182 <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
124 <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> 183 <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
125 <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value> 184 <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
@@ -172,13 +231,13 @@ @@ -172,13 +231,13 @@
172 <value type="int" key="PE.EnvironmentAspect.Base">2</value> 231 <value type="int" key="PE.EnvironmentAspect.Base">2</value>
173 <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> 232 <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
174 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">srs-qt</value> 233 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">srs-qt</value>
175 - <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">srs-qt2</value> 234 + <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
176 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/winlin/git/simple-rtmp-server/trunk/ide/srs_qt/srs-qt.pro</value> 235 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/winlin/git/simple-rtmp-server/trunk/ide/srs_qt/srs-qt.pro</value>
177 - <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments">-c console.conf</value> 236 + <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
178 <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">srs-qt.pro</value> 237 <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">srs-qt.pro</value>
179 <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value> 238 <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
180 <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">true</value> 239 <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">true</value>
181 - <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory">/home/winlin/srs</value> 240 + <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
182 <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value> 241 <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
183 <value type="bool" key="RunConfiguration.UseCppDebugger">false</value> 242 <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
184 <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> 243 <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
@@ -904,6 +904,7 @@ int SrsHttpResponseReader::read(int max, std::string& data) @@ -904,6 +904,7 @@ int SrsHttpResponseReader::read(int max, std::string& data)
904 904
905 SrsHttpMessage::SrsHttpMessage(SrsStSocket* io) 905 SrsHttpMessage::SrsHttpMessage(SrsStSocket* io)
906 { 906 {
  907 + chunked = false;
907 _uri = new SrsHttpUri(); 908 _uri = new SrsHttpUri();
908 _body = new SrsHttpResponseReader(this, io); 909 _body = new SrsHttpResponseReader(this, io);
909 _http_ts_send_buffer = new char[__SRS_HTTP_TS_SEND_BUFFER_SIZE]; 910 _http_ts_send_buffer = new char[__SRS_HTTP_TS_SEND_BUFFER_SIZE];
@@ -924,6 +925,11 @@ int SrsHttpMessage::initialize(string url, http_parser* header, string body, vec @@ -924,6 +925,11 @@ int SrsHttpMessage::initialize(string url, http_parser* header, string body, vec
924 _header = *header; 925 _header = *header;
925 _headers = headers; 926 _headers = headers;
926 927
  928 + // whether chunked.
  929 + std::string transfer_encoding = get_request_header("Transfer-Encoding");
  930 + chunked = (transfer_encoding == "chunked");
  931 +
  932 + // TODO: FIXME: remove it, use fast buffer instead.
927 if (!body.empty()) { 933 if (!body.empty()) {
928 _body->append((char*)body.data(), (int)body.length()); 934 _body->append((char*)body.data(), (int)body.length());
929 } 935 }
@@ -1031,6 +1037,11 @@ bool SrsHttpMessage::is_http_options() @@ -1031,6 +1037,11 @@ bool SrsHttpMessage::is_http_options()
1031 return _header.method == SRS_CONSTS_HTTP_OPTIONS; 1037 return _header.method == SRS_CONSTS_HTTP_OPTIONS;
1032 } 1038 }
1033 1039
  1040 +bool SrsHttpMessage::is_chunked()
  1041 +{
  1042 + return chunked;
  1043 +}
  1044 +
1034 string SrsHttpMessage::uri() 1045 string SrsHttpMessage::uri()
1035 { 1046 {
1036 std::string uri = _uri->get_schema(); 1047 std::string uri = _uri->get_schema();
@@ -1104,6 +1115,11 @@ int SrsHttpMessage::body_read_all(string body) @@ -1104,6 +1115,11 @@ int SrsHttpMessage::body_read_all(string body)
1104 return ret; 1115 return ret;
1105 } 1116 }
1106 1117
  1118 +ISrsHttpResponseReader* SrsHttpMessage::body_reader()
  1119 +{
  1120 + return _body;
  1121 +}
  1122 +
1107 int64_t SrsHttpMessage::content_length() 1123 int64_t SrsHttpMessage::content_length()
1108 { 1124 {
1109 return _header.content_length; 1125 return _header.content_length;
@@ -1258,6 +1274,11 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt) @@ -1258,6 +1274,11 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt)
1258 return ret; 1274 return ret;
1259 } 1275 }
1260 } 1276 }
  1277 +
  1278 + // parse last header.
  1279 + if (!filed_name.empty() && !field_value.empty()) {
  1280 + headers.push_back(std::make_pair(filed_name, field_value));
  1281 + }
1261 1282
1262 // when parse completed, cache the left body. 1283 // when parse completed, cache the left body.
1263 if (nread && nparsed < nread) { 1284 if (nread && nparsed < nread) {
@@ -1341,7 +1362,7 @@ int SrsHttpParser::on_header_field(http_parser* parser, const char* at, size_t l @@ -1341,7 +1362,7 @@ int SrsHttpParser::on_header_field(http_parser* parser, const char* at, size_t l
1341 obj->filed_name.append(at, (int)length); 1362 obj->filed_name.append(at, (int)length);
1342 } 1363 }
1343 1364
1344 - srs_trace("Header field(%d bytes): %.*s", (int)length, (int)length, at); 1365 + srs_info("Header field(%d bytes): %.*s", (int)length, (int)length, at);
1345 return 0; 1366 return 0;
1346 } 1367 }
1347 1368
@@ -1355,7 +1376,7 @@ int SrsHttpParser::on_header_value(http_parser* parser, const char* at, size_t l @@ -1355,7 +1376,7 @@ int SrsHttpParser::on_header_value(http_parser* parser, const char* at, size_t l
1355 } 1376 }
1356 obj->expect_filed_name = false; 1377 obj->expect_filed_name = false;
1357 1378
1358 - srs_trace("Header value(%d bytes): %.*s", (int)length, (int)length, at); 1379 + srs_info("Header value(%d bytes): %.*s", (int)length, (int)length, at);
1359 return 0; 1380 return 0;
1360 } 1381 }
1361 1382
@@ -49,6 +49,7 @@ class SrsFileReader; @@ -49,6 +49,7 @@ class SrsFileReader;
49 class SrsSimpleBuffer; 49 class SrsSimpleBuffer;
50 class SrsHttpMuxEntry; 50 class SrsHttpMuxEntry;
51 class ISrsHttpResponseWriter; 51 class ISrsHttpResponseWriter;
  52 +class SrsFastBuffer;
52 53
53 // http specification 54 // http specification
54 // CR = <US-ASCII CR, carriage return (13)> 55 // CR = <US-ASCII CR, carriage return (13)>
@@ -442,6 +443,10 @@ private: @@ -442,6 +443,10 @@ private:
442 */ 443 */
443 SrsHttpResponseReader* _body; 444 SrsHttpResponseReader* _body;
444 /** 445 /**
  446 + * whether the body is chunked.
  447 + */
  448 + bool chunked;
  449 + /**
445 * uri parser 450 * uri parser
446 */ 451 */
447 SrsHttpUri* _uri; 452 SrsHttpUri* _uri;
@@ -474,12 +479,14 @@ public: @@ -474,12 +479,14 @@ public:
474 virtual bool is_http_post(); 479 virtual bool is_http_post();
475 virtual bool is_http_delete(); 480 virtual bool is_http_delete();
476 virtual bool is_http_options(); 481 virtual bool is_http_options();
  482 + virtual bool is_chunked();
477 virtual std::string uri(); 483 virtual std::string uri();
478 virtual std::string url(); 484 virtual std::string url();
479 virtual std::string host(); 485 virtual std::string host();
480 virtual std::string path(); 486 virtual std::string path();
481 public: 487 public:
482 virtual int body_read_all(std::string body); 488 virtual int body_read_all(std::string body);
  489 + virtual ISrsHttpResponseReader* body_reader();
483 virtual int64_t content_length(); 490 virtual int64_t content_length();
484 /** 491 /**
485 * get the param in query string, 492 * get the param in query string,
@@ -502,6 +509,8 @@ class SrsHttpParser @@ -502,6 +509,8 @@ class SrsHttpParser
502 private: 509 private:
503 http_parser_settings settings; 510 http_parser_settings settings;
504 http_parser parser; 511 http_parser parser;
  512 + // the global parse buffer.
  513 + SrsFastBuffer* fbuffer;
505 private: 514 private:
506 // http parse data, reset before parse message. 515 // http parse data, reset before parse message.
507 bool expect_filed_name; 516 bool expect_filed_name;
@@ -45,6 +45,7 @@ SrsHttpClient::SrsHttpClient() @@ -45,6 +45,7 @@ SrsHttpClient::SrsHttpClient()
45 connected = false; 45 connected = false;
46 stfd = NULL; 46 stfd = NULL;
47 parser = NULL; 47 parser = NULL;
  48 + skt = NULL;
48 } 49 }
49 50
50 SrsHttpClient::~SrsHttpClient() 51 SrsHttpClient::~SrsHttpClient()
@@ -86,10 +87,8 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r @@ -86,10 +87,8 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r
86 << __SRS_HTTP_CRLF 87 << __SRS_HTTP_CRLF
87 << req; 88 << req;
88 89
89 - SrsStSocket skt(stfd);  
90 -  
91 std::string data = ss.str(); 90 std::string data = ss.str();
92 - if ((ret = skt.write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { 91 + if ((ret = skt->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) {
93 // disconnect when error. 92 // disconnect when error.
94 disconnect(); 93 disconnect();
95 94
@@ -98,7 +97,7 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r @@ -98,7 +97,7 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r
98 } 97 }
99 98
100 SrsHttpMessage* msg = NULL; 99 SrsHttpMessage* msg = NULL;
101 - if ((ret = parser->parse_message(&skt, &msg)) != ERROR_SUCCESS) { 100 + if ((ret = parser->parse_message(skt, &msg)) != ERROR_SUCCESS) {
102 srs_error("parse http post response failed. ret=%d", ret); 101 srs_error("parse http post response failed. ret=%d", ret);
103 return ret; 102 return ret;
104 } 103 }
@@ -119,11 +118,67 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r @@ -119,11 +118,67 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r
119 return ret; 118 return ret;
120 } 119 }
121 120
  121 +int SrsHttpClient::get(SrsHttpUri* uri, std::string req, SrsHttpMessage** ppmsg)
  122 +{
  123 + *ppmsg = NULL;
  124 +
  125 + int ret = ERROR_SUCCESS;
  126 +
  127 + if (!parser) {
  128 + parser = new SrsHttpParser();
  129 +
  130 + if ((ret = parser->initialize(HTTP_RESPONSE)) != ERROR_SUCCESS) {
  131 + srs_error("initialize parser failed. ret=%d", ret);
  132 + return ret;
  133 + }
  134 + }
  135 +
  136 + if ((ret = connect(uri)) != ERROR_SUCCESS) {
  137 + srs_warn("http connect server failed. ret=%d", ret);
  138 + return ret;
  139 + }
  140 +
  141 + // send POST request to uri
  142 + // GET %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
  143 + std::stringstream ss;
  144 + ss << "GET " << uri->get_path() << " "
  145 + << "HTTP/1.1" << __SRS_HTTP_CRLF
  146 + << "Host: " << uri->get_host() << __SRS_HTTP_CRLF
  147 + << "Connection: Keep-Alive" << __SRS_HTTP_CRLF
  148 + << "Content-Length: " << std::dec << req.length() << __SRS_HTTP_CRLF
  149 + << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __SRS_HTTP_CRLF
  150 + << "Content-Type: application/json" << __SRS_HTTP_CRLF
  151 + << __SRS_HTTP_CRLF
  152 + << req;
  153 +
  154 + std::string data = ss.str();
  155 + if ((ret = skt->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) {
  156 + // disconnect when error.
  157 + disconnect();
  158 +
  159 + srs_error("write http get failed. ret=%d", ret);
  160 + return ret;
  161 + }
  162 +
  163 + SrsHttpMessage* msg = NULL;
  164 + if ((ret = parser->parse_message(skt, &msg)) != ERROR_SUCCESS) {
  165 + srs_error("parse http post response failed. ret=%d", ret);
  166 + return ret;
  167 + }
  168 +
  169 + srs_assert(msg);
  170 + *ppmsg = msg;
  171 + srs_info("parse http get response success.");
  172 +
  173 + return ret;
  174 +}
  175 +
122 void SrsHttpClient::disconnect() 176 void SrsHttpClient::disconnect()
123 { 177 {
124 connected = false; 178 connected = false;
125 179
126 srs_close_stfd(stfd); 180 srs_close_stfd(stfd);
  181 + srs_freep(skt);
127 } 182 }
128 183
129 int SrsHttpClient::connect(SrsHttpUri* uri) 184 int SrsHttpClient::connect(SrsHttpUri* uri)
@@ -149,6 +204,8 @@ int SrsHttpClient::connect(SrsHttpUri* uri) @@ -149,6 +204,8 @@ int SrsHttpClient::connect(SrsHttpUri* uri)
149 srs_info("connect to server success. http url=%s, server=%s, port=%d", 204 srs_info("connect to server success. http url=%s, server=%s, port=%d",
150 uri->get_url(), uri->get_host(), uri->get_port()); 205 uri->get_url(), uri->get_host(), uri->get_port());
151 206
  207 + srs_assert(!skt);
  208 + skt = new SrsStSocket(stfd);
152 connected = true; 209 connected = true;
153 210
154 return ret; 211 return ret;
@@ -37,6 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -37,6 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 37
38 class SrsHttpUri; 38 class SrsHttpUri;
39 class SrsHttpParser; 39 class SrsHttpParser;
  40 +class SrsHttpMessage;
  41 +class SrsStSocket;
40 42
41 /** 43 /**
42 * http client to GET/POST/PUT/DELETE uri 44 * http client to GET/POST/PUT/DELETE uri
@@ -46,6 +48,7 @@ class SrsHttpClient @@ -46,6 +48,7 @@ class SrsHttpClient
46 private: 48 private:
47 bool connected; 49 bool connected;
48 st_netfd_t stfd; 50 st_netfd_t stfd;
  51 + SrsStSocket* skt;
49 SrsHttpParser* parser; 52 SrsHttpParser* parser;
50 public: 53 public:
51 SrsHttpClient(); 54 SrsHttpClient();
@@ -53,11 +56,17 @@ public: @@ -53,11 +56,17 @@ public:
53 public: 56 public:
54 /** 57 /**
55 * to post data to the uri. 58 * to post data to the uri.
56 - * @param req the data post to uri. 59 + * @param req the data post to uri. empty string to ignore.
57 * @param status_code the output status code response by server. 60 * @param status_code the output status code response by server.
58 * @param res output the response data from server. 61 * @param res output the response data from server.
59 */ 62 */
60 virtual int post(SrsHttpUri* uri, std::string req, int& status_code, std::string& res); 63 virtual int post(SrsHttpUri* uri, std::string req, int& status_code, std::string& res);
  64 + /**
  65 + * to get data from the uri.
  66 + * @param req the data post to uri. empty string to ignore.
  67 + * @param ppmsg output the http message to read the response.
  68 + */
  69 + virtual int get(SrsHttpUri* uri, std::string req, SrsHttpMessage** ppmsg);
61 private: 70 private:
62 virtual void disconnect(); 71 virtual void disconnect();
63 virtual int connect(SrsHttpUri* uri); 72 virtual int connect(SrsHttpUri* uri);
@@ -131,7 +131,7 @@ int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) @@ -131,7 +131,7 @@ int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
131 131
132 SrsRtspAudioCache::SrsRtspAudioCache() 132 SrsRtspAudioCache::SrsRtspAudioCache()
133 { 133 {
134 - dts = NULL; 134 + dts = 0;
135 audio_samples = NULL; 135 audio_samples = NULL;
136 payload = NULL; 136 payload = NULL;
137 } 137 }
@@ -312,6 +312,8 @@ int run() @@ -312,6 +312,8 @@ int run()
312 return run_master(); 312 return run_master();
313 } 313 }
314 314
  315 +#include <srs_app_http.hpp>
  316 +#include <srs_app_http_client.hpp>
315 int run_master() 317 int run_master()
316 { 318 {
317 int ret = ERROR_SUCCESS; 319 int ret = ERROR_SUCCESS;
@@ -327,6 +329,22 @@ int run_master() @@ -327,6 +329,22 @@ int run_master()
327 if ((ret = _srs_server->initialize_st()) != ERROR_SUCCESS) { 329 if ((ret = _srs_server->initialize_st()) != ERROR_SUCCESS) {
328 return ret; 330 return ret;
329 } 331 }
  332 +/*SrsHttpClient client;
  333 +SrsHttpUri uri;
  334 +if ((ret = uri.initialize("http://ossrs.net:8081/live/livestream.flv")) != ERROR_SUCCESS) {
  335 + return ret;
  336 +}
  337 +SrsHttpMessage* msg = NULL;
  338 +if ((ret = client.get(&uri, "", &msg)) != ERROR_SUCCESS) {
  339 + return ret;
  340 +}
  341 +for (;;) {
  342 + ISrsHttpResponseReader* br = msg->body_reader();
  343 + std::string data;
  344 + if ((ret = br->read(0, data)) != ERROR_SUCCESS) {
  345 + return ret;
  346 + }
  347 +}*/
330 348
331 if ((ret = _srs_server->listen()) != ERROR_SUCCESS) { 349 if ((ret = _srs_server->listen()) != ERROR_SUCCESS) {
332 return ret; 350 return ret;
@@ -130,6 +130,7 @@ public: @@ -130,6 +130,7 @@ public:
130 * @param v true to ename merged read. 130 * @param v true to ename merged read.
131 * @param handler the handler when merge read is enabled. 131 * @param handler the handler when merge read is enabled.
132 * @see https://github.com/winlinvip/simple-rtmp-server/issues/241 132 * @see https://github.com/winlinvip/simple-rtmp-server/issues/241
  133 + * @remark the merged read is optional, ignore if not specifies.
133 */ 134 */
134 virtual void set_merge_read(bool v, IMergeReadHandler* handler); 135 virtual void set_merge_read(bool v, IMergeReadHandler* handler);
135 #endif 136 #endif