2017-03-25 09:21:39 +00:00
|
|
|
/**
|
|
|
|
* The MIT License (MIT)
|
|
|
|
*
|
2017-03-25 13:29:29 +00:00
|
|
|
* Copyright (c) 2013-2017 OSSRS(winlin)
|
2017-03-25 09:21:39 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2014-04-04 15:06:46 +00:00
|
|
|
|
|
|
|
#include <srs_app_http_conn.hpp>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
2014-05-26 05:57:08 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
using namespace std;
|
2014-04-04 15:06:46 +00:00
|
|
|
|
2015-09-22 01:01:47 +00:00
|
|
|
#include <srs_protocol_stream.hpp>
|
2015-09-22 01:11:07 +00:00
|
|
|
#include <srs_protocol_utility.hpp>
|
2014-04-04 15:06:46 +00:00
|
|
|
#include <srs_kernel_log.hpp>
|
|
|
|
#include <srs_kernel_error.hpp>
|
2015-06-14 00:43:38 +00:00
|
|
|
#include <srs_app_st.hpp>
|
2014-04-04 15:06:46 +00:00
|
|
|
#include <srs_core_autofree.hpp>
|
|
|
|
#include <srs_app_config.hpp>
|
2014-06-08 05:03:03 +00:00
|
|
|
#include <srs_kernel_utility.hpp>
|
2015-01-18 01:12:53 +00:00
|
|
|
#include <srs_kernel_file.hpp>
|
|
|
|
#include <srs_kernel_flv.hpp>
|
2015-06-13 08:04:59 +00:00
|
|
|
#include <srs_rtmp_stack.hpp>
|
2015-01-18 11:49:03 +00:00
|
|
|
#include <srs_app_source.hpp>
|
2015-01-23 02:07:20 +00:00
|
|
|
#include <srs_rtmp_msg_array.hpp>
|
2015-01-18 14:51:07 +00:00
|
|
|
#include <srs_kernel_aac.hpp>
|
2015-01-19 01:25:07 +00:00
|
|
|
#include <srs_kernel_mp3.hpp>
|
2015-01-22 09:08:38 +00:00
|
|
|
#include <srs_kernel_ts.hpp>
|
2015-02-19 10:56:21 +00:00
|
|
|
#include <srs_app_pithy_print.hpp>
|
2015-03-14 11:45:13 +00:00
|
|
|
#include <srs_app_source.hpp>
|
|
|
|
#include <srs_app_server.hpp>
|
2015-06-14 06:06:39 +00:00
|
|
|
#include <srs_app_http_static.hpp>
|
|
|
|
#include <srs_app_http_stream.hpp>
|
|
|
|
#include <srs_app_http_api.hpp>
|
2015-09-17 05:36:02 +00:00
|
|
|
#include <srs_protocol_json.hpp>
|
|
|
|
#include <srs_app_http_hooks.hpp>
|
2015-09-22 01:05:21 +00:00
|
|
|
#include <srs_protocol_amf0.hpp>
|
2016-01-12 03:53:52 +00:00
|
|
|
#include <srs_app_utility.hpp>
|
2017-05-01 08:49:09 +00:00
|
|
|
#include <srs_app_st.hpp>
|
2015-01-18 01:12:53 +00:00
|
|
|
|
2017-05-30 01:05:02 +00:00
|
|
|
SrsHttpConn::SrsHttpConn(IConnectionManager* cm, srs_netfd_t fd, ISrsHttpServeMux* m, string cip)
|
2017-03-25 09:21:39 +00:00
|
|
|
: SrsConnection(cm, fd, cip)
|
2014-04-04 15:06:46 +00:00
|
|
|
{
|
|
|
|
parser = new SrsHttpParser();
|
2016-12-15 08:22:04 +00:00
|
|
|
cors = new SrsHttpCorsMux();
|
2015-05-03 15:34:59 +00:00
|
|
|
http_mux = m;
|
2014-04-04 15:06:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SrsHttpConn::~SrsHttpConn()
|
|
|
|
{
|
|
|
|
srs_freep(parser);
|
2016-12-15 08:22:04 +00:00
|
|
|
srs_freep(cors);
|
2014-04-04 15:06:46 +00:00
|
|
|
}
|
|
|
|
|
2015-03-08 11:59:10 +00:00
|
|
|
void SrsHttpConn::resample()
|
2014-06-19 07:28:05 +00:00
|
|
|
{
|
|
|
|
// TODO: FIXME: implements it
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t SrsHttpConn::get_send_bytes_delta()
|
|
|
|
{
|
|
|
|
// TODO: FIXME: implements it
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t SrsHttpConn::get_recv_bytes_delta()
|
|
|
|
{
|
|
|
|
// TODO: FIXME: implements it
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-03-08 11:59:10 +00:00
|
|
|
void SrsHttpConn::cleanup()
|
|
|
|
{
|
|
|
|
// TODO: FIXME: implements it
|
|
|
|
}
|
|
|
|
|
2014-04-04 15:06:46 +00:00
|
|
|
int SrsHttpConn::do_cycle()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-05-30 01:20:51 +00:00
|
|
|
srs_trace("HTTP client ip=%s", ip.c_str());
|
2014-04-04 15:06:46 +00:00
|
|
|
|
|
|
|
// initialize parser
|
2015-09-12 14:22:33 +00:00
|
|
|
if ((ret = parser->initialize(HTTP_REQUEST, false)) != ERROR_SUCCESS) {
|
2014-04-04 15:06:46 +00:00
|
|
|
srs_error("http initialize http parser failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2015-05-22 05:57:04 +00:00
|
|
|
// set the recv timeout, for some clients never disconnect the connection.
|
2015-11-11 02:37:50 +00:00
|
|
|
// @see https://github.com/ossrs/srs/issues/398
|
2017-01-17 04:25:30 +00:00
|
|
|
skt->set_recv_timeout(SRS_HTTP_RECV_TMMS);
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2015-09-17 05:36:02 +00:00
|
|
|
SrsRequest* last_req = NULL;
|
|
|
|
SrsAutoFree(SrsRequest, last_req);
|
2016-12-15 08:22:04 +00:00
|
|
|
|
|
|
|
// initialize the cors, which will proxy to mux.
|
|
|
|
bool crossdomain_enabled = _srs_config->get_http_stream_crossdomain();
|
|
|
|
if ((ret = cors->initialize(http_mux, crossdomain_enabled)) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2014-04-04 15:06:46 +00:00
|
|
|
// process http messages.
|
2017-05-29 11:45:19 +00:00
|
|
|
while (!trd->pull()) {
|
2015-05-22 14:24:05 +00:00
|
|
|
ISrsHttpMessage* req = NULL;
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2014-04-04 15:06:46 +00:00
|
|
|
// get a http message
|
2015-09-17 05:36:02 +00:00
|
|
|
if ((ret = parser->parse_message(skt, this, &req)) != ERROR_SUCCESS) {
|
|
|
|
break;
|
2014-04-04 15:06:46 +00:00
|
|
|
}
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2015-03-04 10:20:15 +00:00
|
|
|
// if SUCCESS, always NOT-NULL.
|
2014-04-04 15:06:46 +00:00
|
|
|
srs_assert(req);
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2014-04-04 15:06:46 +00:00
|
|
|
// always free it in this scope.
|
2015-05-22 14:24:05 +00:00
|
|
|
SrsAutoFree(ISrsHttpMessage, req);
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2015-09-17 05:36:02 +00:00
|
|
|
// get the last request, for report the info of request on connection disconnect.
|
|
|
|
delete last_req;
|
|
|
|
SrsHttpMessage* hreq = dynamic_cast<SrsHttpMessage*>(req);
|
|
|
|
last_req = hreq->to_request(hreq->host());
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2015-05-04 10:11:52 +00:00
|
|
|
// may should discard the body.
|
|
|
|
if ((ret = on_got_http_message(req)) != ERROR_SUCCESS) {
|
2015-09-17 05:36:02 +00:00
|
|
|
break;
|
2015-03-04 10:20:15 +00:00
|
|
|
}
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2014-04-04 15:06:46 +00:00
|
|
|
// ok, handle http request.
|
2015-09-17 05:36:02 +00:00
|
|
|
SrsHttpResponseWriter writer(skt);
|
2015-01-17 15:00:40 +00:00
|
|
|
if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) {
|
2015-09-17 05:36:02 +00:00
|
|
|
break;
|
2014-04-04 15:06:46 +00:00
|
|
|
}
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2015-05-22 08:27:48 +00:00
|
|
|
// donot keep alive, disconnect it.
|
2015-11-11 02:37:50 +00:00
|
|
|
// @see https://github.com/ossrs/srs/issues/399
|
2015-05-22 08:27:48 +00:00
|
|
|
if (!req->is_keep_alive()) {
|
|
|
|
break;
|
|
|
|
}
|
2014-04-04 15:06:46 +00:00
|
|
|
}
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2015-09-17 05:36:02 +00:00
|
|
|
int disc_ret = ERROR_SUCCESS;
|
|
|
|
if ((disc_ret = on_disconnect(last_req)) != ERROR_SUCCESS) {
|
|
|
|
srs_warn("connection on disconnect peer failed, but ignore this error. disc_ret=%d, ret=%d", disc_ret, ret);
|
|
|
|
}
|
2017-03-25 09:21:39 +00:00
|
|
|
|
2014-04-04 15:06:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-03-25 09:21:39 +00:00
|
|
|
int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
|
2014-04-04 15:06:46 +00:00
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2017-05-06 06:05:22 +00:00
|
|
|
srs_trace("HTTP %s %s, content-length=%" PRId64 "",
|
2017-03-25 09:21:39 +00:00
|
|
|
r->method_str().c_str(), r->url().c_str(), r->content_length());
|
2014-04-04 15:06:46 +00:00
|
|
|
|
2016-12-15 08:22:04 +00:00
|
|
|
// use cors server mux to serve http request, which will proxy to http_remux.
|
|
|
|
if ((ret = cors->serve_http(w, r)) != ERROR_SUCCESS) {
|
2015-01-17 15:00:40 +00:00
|
|
|
if (!srs_is_client_gracefully_close(ret)) {
|
|
|
|
srs_error("serve http msg failed. ret=%d", ret);
|
|
|
|
}
|
2014-04-04 15:06:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-17 05:36:02 +00:00
|
|
|
int SrsHttpConn::on_disconnect(SrsRequest* req)
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
// TODO: implements it.s
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-12-15 08:22:04 +00:00
|
|
|
int SrsHttpConn::on_reload_http_stream_crossdomain()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
// initialize the cors, which will proxy to mux.
|
|
|
|
bool crossdomain_enabled = _srs_config->get_http_stream_crossdomain();
|
|
|
|
if ((ret = cors->initialize(http_mux, crossdomain_enabled)) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-05-30 01:05:02 +00:00
|
|
|
SrsResponseOnlyHttpConn::SrsResponseOnlyHttpConn(IConnectionManager* cm, srs_netfd_t fd, ISrsHttpServeMux* m, string cip)
|
2017-03-25 09:21:39 +00:00
|
|
|
: SrsHttpConn(cm, fd, m, cip)
|
2015-05-04 10:11:52 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-06-14 11:42:43 +00:00
|
|
|
SrsResponseOnlyHttpConn::~SrsResponseOnlyHttpConn()
|
2015-05-04 10:11:52 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-04-30 04:03:31 +00:00
|
|
|
int SrsResponseOnlyHttpConn::pop_message(ISrsHttpMessage** preq)
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2017-05-01 08:49:09 +00:00
|
|
|
SrsStSocket skt;
|
|
|
|
|
|
|
|
if ((ret = skt.initialize(stfd)) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
2017-04-30 04:03:31 +00:00
|
|
|
|
|
|
|
if ((ret = parser->parse_message(&skt, this, preq)) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-06-14 11:42:43 +00:00
|
|
|
int SrsResponseOnlyHttpConn::on_got_http_message(ISrsHttpMessage* msg)
|
2015-05-04 10:11:52 +00:00
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2015-06-14 11:42:43 +00:00
|
|
|
ISrsHttpResponseReader* br = msg->body_reader();
|
2015-05-04 10:11:52 +00:00
|
|
|
|
2015-12-29 10:33:02 +00:00
|
|
|
// when not specified the content length, ignore.
|
|
|
|
if (msg->content_length() == -1) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-06-14 11:42:43 +00:00
|
|
|
// drop all request body.
|
|
|
|
while (!br->eof()) {
|
|
|
|
char body[4096];
|
|
|
|
if ((ret = br->read(body, 4096, NULL)) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
2015-05-04 10:11:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-06-14 06:06:39 +00:00
|
|
|
SrsHttpServer::SrsHttpServer(SrsServer* svr)
|
|
|
|
{
|
|
|
|
server = svr;
|
|
|
|
http_stream = new SrsHttpStreamServer(svr);
|
|
|
|
http_static = new SrsHttpStaticServer(svr);
|
|
|
|
}
|
|
|
|
|
|
|
|
SrsHttpServer::~SrsHttpServer()
|
|
|
|
{
|
|
|
|
srs_freep(http_stream);
|
|
|
|
srs_freep(http_static);
|
|
|
|
}
|
|
|
|
|
2017-06-09 05:29:23 +00:00
|
|
|
srs_error_t SrsHttpServer::initialize()
|
2015-06-14 06:06:39 +00:00
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
2017-06-09 05:29:23 +00:00
|
|
|
srs_error_t err = srs_success;
|
2015-06-14 06:06:39 +00:00
|
|
|
|
|
|
|
// for SRS go-sharp to detect the status of HTTP server of SRS HTTP FLV Cluster.
|
|
|
|
if ((ret = http_static->mux.handle("/api/v1/versions", new SrsGoApiVersion())) != ERROR_SUCCESS) {
|
2017-06-09 05:29:23 +00:00
|
|
|
return srs_error_new(ret, "handle versin");
|
2015-06-14 06:06:39 +00:00
|
|
|
}
|
|
|
|
|
2017-06-09 05:29:23 +00:00
|
|
|
if ((err = http_stream->initialize()) != srs_success) {
|
|
|
|
return srs_error_wrap(err, "http stream");
|
2015-06-14 06:06:39 +00:00
|
|
|
}
|
|
|
|
|
2017-06-09 05:29:23 +00:00
|
|
|
if ((err = http_static->initialize()) != srs_success) {
|
|
|
|
return srs_error_wrap(err, "http static");
|
2015-06-14 06:06:39 +00:00
|
|
|
}
|
|
|
|
|
2017-06-09 05:29:23 +00:00
|
|
|
return err;
|
2015-06-14 06:06:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int SrsHttpServer::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
|
|
|
|
{
|
|
|
|
// try http stream first.
|
|
|
|
if (http_stream->mux.can_serve(r)) {
|
|
|
|
return http_stream->mux.serve_http(w, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
return http_static->mux.serve_http(w, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsHttpServer::http_mount(SrsSource* s, SrsRequest* r)
|
|
|
|
{
|
|
|
|
return http_stream->http_mount(s, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsHttpServer::http_unmount(SrsSource* s, SrsRequest* r)
|
|
|
|
{
|
|
|
|
http_stream->http_unmount(s, r);
|
|
|
|
}
|
|
|
|
|