1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

For #1657: Remove duplicated code, merge http api with conn

This commit is contained in:
winlin 2020-11-05 16:46:16 +08:00
parent 9cf4203201
commit 0a3a38762a
6 changed files with 117 additions and 228 deletions

View file

@ -1674,22 +1674,11 @@ srs_error_t SrsGoApiTcmalloc::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
}
#endif
SrsHttpApi::SrsHttpApi(ISrsResourceManager* cm, srs_netfd_t fd, SrsHttpServeMux* m, string cip, int cport)
SrsHttpApi::SrsHttpApi(ISrsResourceManager* cm, srs_netfd_t fd, SrsHttpServeMux* m, string cip, int port)
{
mux = m;
cors = new SrsHttpCorsMux();
parser = new SrsHttpParser();
skt = new SrsTcpConnection(fd);
manager = cm;
ip = cip;
port = cport;
create_time = srsu2ms(srs_get_system_time());
clk = new SrsWallClock();
kbps = new SrsKbps(clk);
kbps->set_io(skt, skt);
trd = new SrsSTCoroutine("api", this);
conn = new SrsHttpConn(this, fd, m, cip, port);
_srs_config->subscribe(this);
}
@ -1697,15 +1686,30 @@ SrsHttpApi::~SrsHttpApi()
{
_srs_config->unsubscribe(this);
trd->interrupt();
srs_freep(trd);
srs_freep(conn);
}
srs_freep(parser);
srs_freep(cors);
srs_error_t SrsHttpApi::on_http_message(ISrsHttpMessage* req)
{
srs_error_t err = srs_success;
srs_freep(kbps);
srs_freep(clk);
srs_freep(skt);
// read all rest bytes in request body.
char buf[SRS_HTTP_READ_CACHE_BYTES];
ISrsHttpResponseReader* br = req->body_reader();
while (!br->eof()) {
if ((err = br->read(buf, SRS_HTTP_READ_CACHE_BYTES, NULL)) != srs_success) {
return srs_error_wrap(err, "read response");
}
}
return err;
}
void SrsHttpApi::on_conn_done()
{
// Because we use manager to manage this object,
// not the http connection object, so we must remove it here.
manager->remove(this);
}
std::string SrsHttpApi::desc()
@ -1715,168 +1719,38 @@ std::string SrsHttpApi::desc()
void SrsHttpApi::remark(int64_t* in, int64_t* out)
{
kbps->remark(in, out);
}
srs_error_t SrsHttpApi::do_cycle()
{
srs_error_t err = srs_success;
// Create context for API.
_srs_context->set_id(_srs_context->generate_id());
srs_trace("API server client, ip=%s:%d", ip.c_str(), port);
// initialize parser
if ((err = parser->initialize(HTTP_REQUEST, true)) != srs_success) {
return srs_error_wrap(err, "init parser");
}
// set the recv timeout, for some clients never disconnect the connection.
// @see https://github.com/ossrs/srs/issues/398
skt->set_recv_timeout(SRS_HTTP_RECV_TIMEOUT);
// initialize the cors, which will proxy to mux.
bool crossdomain_enabled = _srs_config->get_http_api_crossdomain();
if ((err = cors->initialize(mux, crossdomain_enabled)) != srs_success) {
return srs_error_wrap(err, "init cors");
}
// process http messages.
while ((err = trd->pull()) == srs_success) {
ISrsHttpMessage* req = NULL;
// get a http message
if ((err = parser->parse_message(skt, &req)) != srs_success) {
// For HTTP timeout, we think it's ok.
if (srs_error_code(err) == ERROR_SOCKET_TIMEOUT) {
srs_freep(err);
return srs_error_wrap(srs_success, "http api timeout");
}
return srs_error_wrap(err, "parse message");
}
// if SUCCESS, always NOT-NULL.
// always free it in this scope.
srs_assert(req);
SrsAutoFree(ISrsHttpMessage, req);
// Attach owner connection to message.
SrsHttpMessage* hreq = (SrsHttpMessage*)req;
hreq->set_connection(this);
// ok, handle http request.
SrsHttpResponseWriter writer(skt);
if ((err = process_request(&writer, req)) != srs_success) {
return srs_error_wrap(err, "process request");
}
// read all rest bytes in request body.
char buf[SRS_HTTP_READ_CACHE_BYTES];
ISrsHttpResponseReader* br = req->body_reader();
while (!br->eof()) {
if ((err = br->read(buf, SRS_HTTP_READ_CACHE_BYTES, NULL)) != srs_success) {
return srs_error_wrap(err, "read response");
}
}
// donot keep alive, disconnect it.
// @see https://github.com/ossrs/srs/issues/399
if (!req->is_keep_alive()) {
break;
}
}
return err;
}
srs_error_t SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
srs_error_t err = srs_success;
SrsHttpMessage* hm = dynamic_cast<SrsHttpMessage*>(r);
srs_assert(hm);
srs_trace("HTTP API %s:%d %s %s, content-length=%" PRId64 ", chunked=%d", ip.c_str(), port, r->method_str().c_str(),
r->url().c_str(), r->content_length(), hm->is_chunked());
// use cors server mux to serve http request, which will proxy to mux.
if ((err = cors->serve_http(w, r)) != srs_success) {
return srs_error_wrap(err, "mux serve");
}
return err;
conn->remark(in, out);
}
srs_error_t SrsHttpApi::on_reload_http_api_crossdomain()
{
srs_error_t err = srs_success;
bool crossdomain_enabled = _srs_config->get_http_api_crossdomain();
if ((err = cors->initialize(mux, crossdomain_enabled)) != srs_success) {
return srs_error_wrap(err, "reload");
}
return err;
bool v = _srs_config->get_http_api_crossdomain();
return conn->set_crossdomain_enabled(v);
}
srs_error_t SrsHttpApi::start()
{
srs_error_t err = srs_success;
if ((err = skt->initialize()) != srs_success) {
return srs_error_wrap(err, "init socket");
bool v = _srs_config->get_http_api_crossdomain();
if ((err = conn->set_crossdomain_enabled(v)) != srs_success) {
return srs_error_wrap(err, "set cors=%d", v);
}
if ((err = trd->start()) != srs_success) {
return srs_error_wrap(err, "coroutine");
if ((err = conn->set_jsonp(true)) != srs_success) {
return srs_error_wrap(err, "set jsonp");
}
return err;
}
srs_error_t SrsHttpApi::cycle()
{
srs_error_t err = do_cycle();
// Notify manager to remove it.
// Note that we create this object, so we use manager to remove it.
manager->remove(this);
// success.
if (err == srs_success) {
srs_trace("client finished.");
return err;
}
// It maybe success with message.
if (srs_error_code(err) == ERROR_SUCCESS) {
srs_trace("client finished%s.", srs_error_summary(err).c_str());
srs_freep(err);
return err;
}
// client close peer.
// TODO: FIXME: Only reset the error when client closed it.
if (srs_is_client_gracefully_close(err)) {
srs_warn("client disconnect peer. ret=%d", srs_error_code(err));
} else if (srs_is_server_gracefully_close(err)) {
srs_warn("server disconnect. ret=%d", srs_error_code(err));
} else {
srs_error("serve error %s", srs_error_desc(err).c_str());
}
srs_freep(err);
return srs_success;
return conn->start();
}
string SrsHttpApi::remote_ip()
{
return ip;
return conn->remote_ip();
}
const SrsContextId& SrsHttpApi::get_id()
{
return trd->cid();
return conn->get_id();
}