1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00
srs/trunk/src/app/srs_app_http_client.cpp

248 lines
6.9 KiB
C++
Raw Normal View History

2014-05-19 07:45:04 +00:00
/*
The MIT License (MIT)
2016-12-16 03:57:25 +00:00
Copyright (c) 2013-2017 SRS(ossrs)
2014-05-19 07:45:04 +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.
*/
#include <srs_app_http_client.hpp>
2014-05-19 09:39:01 +00:00
#include <arpa/inet.h>
using namespace std;
#include <srs_kernel_error.hpp>
#include <srs_kernel_log.hpp>
2015-06-14 00:43:38 +00:00
#include <srs_app_st.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_app_utility.hpp>
2015-03-04 10:20:15 +00:00
#include <srs_core_autofree.hpp>
2015-05-22 14:34:03 +00:00
#include <srs_app_http_conn.hpp>
2015-12-29 10:33:02 +00:00
#include <srs_protocol_kbps.hpp>
2014-05-19 09:39:01 +00:00
SrsHttpClient::SrsHttpClient()
{
transport = NULL;
2015-12-29 10:33:02 +00:00
kbps = new SrsKbps();
parser = NULL;
timeout = SRS_CONSTS_NO_TMMS;
2015-09-17 05:36:02 +00:00
port = 0;
2014-05-19 09:39:01 +00:00
}
SrsHttpClient::~SrsHttpClient()
{
disconnect();
2015-10-14 02:48:08 +00:00
2015-12-29 10:33:02 +00:00
srs_freep(kbps);
2014-05-19 09:39:01 +00:00
srs_freep(parser);
}
// TODO: FIXME: use ms for timeout.
int SrsHttpClient::initialize(string h, int p, int64_t tm)
2014-05-19 09:39:01 +00:00
{
int ret = ERROR_SUCCESS;
srs_freep(parser);
parser = new SrsHttpParser();
if ((ret = parser->initialize(HTTP_RESPONSE, false)) != ERROR_SUCCESS) {
srs_error("initialize parser failed. ret=%d", ret);
return ret;
2014-05-19 09:39:01 +00:00
}
// Always disconnect the transport.
host = h;
port = p;
timeout = tm;
disconnect();
2015-12-29 10:33:02 +00:00
// ep used for host in header.
string ep = host;
if (port > 0 && port != SRS_CONSTS_HTTP_DEFAULT_PORT) {
ep += ":" + srs_int2str(port);
}
// Set default value for headers.
2015-12-29 10:33:02 +00:00
headers["Host"] = ep;
headers["Connection"] = "Keep-Alive";
headers["User-Agent"] = RTMP_SIG_SRS_SERVER;
headers["Content-Type"] = "application/json";
return ret;
}
2015-12-29 10:33:02 +00:00
SrsHttpClient* SrsHttpClient::set_header(string k, string v)
{
headers[k] = v;
return this;
}
int SrsHttpClient::post(string path, string req, ISrsHttpMessage** ppmsg)
{
*ppmsg = NULL;
int ret = ERROR_SUCCESS;
2015-12-29 10:33:02 +00:00
// always set the content length.
headers["Content-Length"] = srs_int2str(req.length());
if ((ret = connect()) != ERROR_SUCCESS) {
srs_warn("http connect server failed. ret=%d", ret);
2014-05-19 09:39:01 +00:00
return ret;
}
// send POST request to uri
// POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
std::stringstream ss;
2015-12-29 10:33:02 +00:00
ss << "POST " << path << " " << "HTTP/1.1" << SRS_HTTP_CRLF;
for (map<string, string>::iterator it = headers.begin(); it != headers.end(); ++it) {
string key = it->first;
string value = it->second;
ss << key << ": " << value << SRS_HTTP_CRLF;
}
ss << SRS_HTTP_CRLF << req;
2014-05-19 09:39:01 +00:00
std::string data = ss.str();
2015-10-14 02:48:08 +00:00
if ((ret = transport->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) {
// Disconnect the transport when channel error, reconnect for next operation.
2014-05-19 09:39:01 +00:00
disconnect();
srs_error("write http post failed. ret=%d", ret);
return ret;
}
ISrsHttpMessage* msg = NULL;
2015-10-14 02:48:08 +00:00
if ((ret = parser->parse_message(transport, NULL, &msg)) != ERROR_SUCCESS) {
2014-05-19 09:39:01 +00:00
srs_error("parse http post response failed. ret=%d", ret);
return ret;
}
srs_assert(msg);
if (ppmsg) {
*ppmsg = msg;
} else {
srs_freep(msg);
}
2014-05-19 09:39:01 +00:00
srs_info("parse http post response success.");
return ret;
}
2015-12-29 10:33:02 +00:00
int SrsHttpClient::get(string path, string req, ISrsHttpMessage** ppmsg)
2015-03-05 13:45:01 +00:00
{
*ppmsg = NULL;
int ret = ERROR_SUCCESS;
2015-12-29 10:33:02 +00:00
// always set the content length.
headers["Content-Length"] = srs_int2str(req.length());
2015-03-05 13:45:01 +00:00
if ((ret = connect()) != ERROR_SUCCESS) {
2015-03-05 13:45:01 +00:00
srs_warn("http connect server failed. ret=%d", ret);
return ret;
}
// send POST request to uri
// GET %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
std::stringstream ss;
2015-12-29 10:33:02 +00:00
ss << "GET " << path << " " << "HTTP/1.1" << SRS_HTTP_CRLF;
for (map<string, string>::iterator it = headers.begin(); it != headers.end(); ++it) {
string key = it->first;
string value = it->second;
ss << key << ": " << value << SRS_HTTP_CRLF;
}
ss << SRS_HTTP_CRLF << req;
2015-03-05 13:45:01 +00:00
std::string data = ss.str();
2015-10-14 02:48:08 +00:00
if ((ret = transport->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) {
// Disconnect the transport when channel error, reconnect for next operation.
2015-03-05 13:45:01 +00:00
disconnect();
srs_error("write http get failed. ret=%d", ret);
return ret;
}
ISrsHttpMessage* msg = NULL;
2015-10-14 02:48:08 +00:00
if ((ret = parser->parse_message(transport, NULL, &msg)) != ERROR_SUCCESS) {
2015-03-05 13:45:01 +00:00
srs_error("parse http post response failed. ret=%d", ret);
return ret;
}
srs_assert(msg);
2015-03-06 03:36:26 +00:00
if (ppmsg) {
*ppmsg = msg;
} else {
srs_freep(msg);
}
2015-03-05 13:45:01 +00:00
srs_info("parse http get response success.");
return ret;
}
void SrsHttpClient::set_recv_timeout(int64_t tm)
2015-12-29 10:33:02 +00:00
{
transport->set_recv_timeout(tm);
2015-12-29 10:33:02 +00:00
}
void SrsHttpClient::kbps_sample(const char* label, int64_t age)
{
kbps->sample();
int sr = kbps->get_send_kbps();
int sr30s = kbps->get_send_kbps_30s();
int sr5m = kbps->get_send_kbps_5m();
int rr = kbps->get_recv_kbps();
int rr30s = kbps->get_recv_kbps_30s();
int rr5m = kbps->get_recv_kbps_5m();
srs_trace("<- %s time=%"PRId64", okbps=%d,%d,%d, ikbps=%d,%d,%d", label, age, sr, sr30s, sr5m, rr, rr30s, rr5m);
}
2014-05-19 09:39:01 +00:00
void SrsHttpClient::disconnect()
{
2015-12-29 10:33:02 +00:00
kbps->set_io(NULL, NULL);
srs_freep(transport);
2014-05-19 09:39:01 +00:00
}
int SrsHttpClient::connect()
2014-05-19 09:39:01 +00:00
{
int ret = ERROR_SUCCESS;
// When transport connected, ignore.
if (transport) {
2014-05-19 09:39:01 +00:00
return ret;
}
transport = new SrsTcpClient(host, port, timeout);
if ((ret = transport->connect()) != ERROR_SUCCESS) {
disconnect();
srs_warn("http client failed, server=%s, port=%d, timeout=%"PRId64", ret=%d", host.c_str(), port, timeout, ret);
2014-05-19 09:39:01 +00:00
return ret;
}
srs_info("connect to server success. server=%s, port=%d", host.c_str(), port);
2014-05-19 09:39:01 +00:00
// Set the recv/send timeout in ms.
transport->set_recv_timeout(timeout);
transport->set_send_timeout(timeout);
2015-04-10 05:45:21 +00:00
2015-12-29 10:33:02 +00:00
kbps->set_io(transport, transport);
2014-05-19 09:39:01 +00:00
return ret;
}