winlin

add http client

@@ -131,6 +131,19 @@ vhost dev { @@ -131,6 +131,19 @@ vhost dev {
131 } 131 }
132 } 132 }
133 } 133 }
  134 +# the http hook callback vhost, srs will invoke the hooks for specified events.
  135 +vhost hooks.callback.vhost.com {
  136 + # when client connect to vhost/app, call the hook,
  137 + # the request in the POST data string is a object encode by json:
  138 + # {
  139 + # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
  140 + # "pageUrl": "http://www.test.com/live.html"
  141 + # }
  142 + # if valid, the hook must return HTTP code 200(Stauts OK) and response
  143 + # an int value specifies the error code(0 corresponding to success):
  144 + # 0
  145 + on_connect http://127.0.0.1:8085/api/v1/clients;
  146 +}
134 # the mirror filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction 147 # the mirror filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction
135 vhost mirror.transcode.vhost.com { 148 vhost mirror.transcode.vhost.com {
136 transcode { 149 transcode {
@@ -37,6 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -37,6 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 #include <srs_core_config.hpp> 37 #include <srs_core_config.hpp>
38 #include <srs_core_refer.hpp> 38 #include <srs_core_refer.hpp>
39 #include <srs_core_hls.hpp> 39 #include <srs_core_hls.hpp>
  40 +#include <srs_core_http.hpp>
40 41
41 #define SRS_PULSE_TIMEOUT_MS 100 42 #define SRS_PULSE_TIMEOUT_MS 100
42 #define SRS_SEND_TIMEOUT_US 5000000L 43 #define SRS_SEND_TIMEOUT_US 5000000L
@@ -51,6 +52,9 @@ SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd) @@ -51,6 +52,9 @@ SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd)
51 res = new SrsResponse(); 52 res = new SrsResponse();
52 rtmp = new SrsRtmp(client_stfd); 53 rtmp = new SrsRtmp(client_stfd);
53 refer = new SrsRefer(); 54 refer = new SrsRefer();
  55 +#ifdef SRS_HTTP
  56 + http_hooks = new SrsHttpHooks();
  57 +#endif
54 } 58 }
55 59
56 SrsClient::~SrsClient() 60 SrsClient::~SrsClient()
@@ -60,6 +64,9 @@ SrsClient::~SrsClient() @@ -60,6 +64,9 @@ SrsClient::~SrsClient()
60 srs_freep(res); 64 srs_freep(res);
61 srs_freep(rtmp); 65 srs_freep(rtmp);
62 srs_freep(refer); 66 srs_freep(refer);
  67 +#ifdef SRS_HTTP
  68 + srs_freep(http_hooks);
  69 +#endif
63 } 70 }
64 71
65 // TODO: return detail message when error for client. 72 // TODO: return detail message when error for client.
@@ -249,6 +256,11 @@ int SrsClient::check_vhost() @@ -249,6 +256,11 @@ int SrsClient::check_vhost()
249 srs_info("ignore the empty http callback: on_connect"); 256 srs_info("ignore the empty http callback: on_connect");
250 return ret; 257 return ret;
251 } 258 }
  259 +
  260 + if ((ret = http_hooks->on_connect(on_connect, ip, req)) != ERROR_SUCCESS) {
  261 + srs_error("hook client failed. ret=%d", ret);
  262 + return ret;
  263 + }
252 #endif 264 #endif
253 265
254 return ret; 266 return ret;
@@ -39,6 +39,9 @@ class SrsSource; @@ -39,6 +39,9 @@ class SrsSource;
39 class SrsRefer; 39 class SrsRefer;
40 class SrsConsumer; 40 class SrsConsumer;
41 class SrsCommonMessage; 41 class SrsCommonMessage;
  42 +#ifdef SRS_HTTP
  43 +class SrsHttpHooks;
  44 +#endif
42 45
43 /** 46 /**
44 * the client provides the main logic control for RTMP clients. 47 * the client provides the main logic control for RTMP clients.
@@ -51,6 +54,9 @@ private: @@ -51,6 +54,9 @@ private:
51 SrsResponse* res; 54 SrsResponse* res;
52 SrsRtmp* rtmp; 55 SrsRtmp* rtmp;
53 SrsRefer* refer; 56 SrsRefer* refer;
  57 +#ifdef SRS_HTTP
  58 + SrsHttpHooks* http_hooks;
  59 +#endif
54 public: 60 public:
55 SrsClient(SrsServer* srs_server, st_netfd_t client_stfd); 61 SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
56 virtual ~SrsClient(); 62 virtual ~SrsClient();
@@ -142,4 +142,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -142,4 +142,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
142 #define ERROR_ENCODER_OPEN 715 142 #define ERROR_ENCODER_OPEN 715
143 #define ERROR_ENCODER_DUP2 716 143 #define ERROR_ENCODER_DUP2 716
144 144
  145 +#define ERROR_HTTP_PARSE_URI 800
  146 +#define ERROR_HTTP_DATA_INVLIAD 801
  147 +
145 #endif 148 #endif
@@ -23,5 +23,179 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -23,5 +23,179 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 23
24 #include <srs_core_http.hpp> 24 #include <srs_core_http.hpp>
25 25
  26 +#include <stdlib.h>
  27 +
  28 +#include <srs_core_error.hpp>
  29 +#include <srs_core_rtmp.hpp>
  30 +#include <srs_core_log.hpp>
  31 +
26 #ifdef SRS_HTTP 32 #ifdef SRS_HTTP
  33 +
  34 +#define SRS_DEFAULT_HTTP_PORT 80
  35 +#define SRS_HTTP_RESPONSE_OK "0"
  36 +
  37 +SrsHttpUri::SrsHttpUri()
  38 +{
  39 + port = SRS_DEFAULT_HTTP_PORT;
  40 +}
  41 +
  42 +SrsHttpUri::~SrsHttpUri()
  43 +{
  44 +}
  45 +
  46 +int SrsHttpUri::initialize(std::string _url)
  47 +{
  48 + int ret = ERROR_SUCCESS;
  49 +
  50 + url = _url;
  51 + const char* purl = url.c_str();
  52 +
  53 + http_parser_url hp_u;
  54 + if((ret = http_parser_parse_url(purl, url.length(), 0, &hp_u)) != 0){
  55 + int code = ret;
  56 + ret = ERROR_HTTP_PARSE_URI;
  57 +
  58 + srs_error("parse url %s failed, code=%d, ret=%d", purl, code, ret);
  59 + return ret;
  60 + }
  61 +
  62 + std::string field = get_uri_field(url, &hp_u, UF_SCHEMA);
  63 + if(!field.empty()){
  64 + schema = field;
  65 + }
  66 +
  67 + host = get_uri_field(url, &hp_u, UF_HOST);
  68 +
  69 + field = get_uri_field(url, &hp_u, UF_PORT);
  70 + if(!field.empty()){
  71 + port = atoi(field.c_str());
  72 + }
  73 +
  74 + path = get_uri_field(url, &hp_u, UF_PATH);
  75 + srs_info("parse url %s success", purl);
  76 +
  77 + return ret;
  78 +}
  79 +
  80 +const char* SrsHttpUri::get_url()
  81 +{
  82 + return url.c_str();
  83 +}
  84 +
  85 +const char* SrsHttpUri::get_schema()
  86 +{
  87 + return schema.c_str();
  88 +}
  89 +
  90 +const char* SrsHttpUri::get_host()
  91 +{
  92 + return host.c_str();
  93 +}
  94 +
  95 +int SrsHttpUri::get_port()
  96 +{
  97 + return port;
  98 +}
  99 +
  100 +std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field)
  101 +{
  102 + if((hp_u->field_set & (1 << field)) == 0){
  103 + return "";
  104 + }
  105 +
  106 + srs_verbose("uri field matched, off=%d, len=%d, value=%.*s",
  107 + hp_u->field_data[field].off,
  108 + hp_u->field_data[field].len,
  109 + hp_u->field_data[field].len,
  110 + uri.c_str() + hp_u->field_data[field].off);
  111 +
  112 + int offset = hp_u->field_data[field].off;
  113 + int len = hp_u->field_data[field].len;
  114 +
  115 + return uri.substr(offset, len);
  116 +}
  117 +
  118 +SrsHttpClient::SrsHttpClient()
  119 +{
  120 +}
  121 +
  122 +SrsHttpClient::~SrsHttpClient()
  123 +{
  124 +}
  125 +
  126 +int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
  127 +{
  128 + int ret = ERROR_SUCCESS;
  129 + return ret;
  130 +}
  131 +
  132 +SrsHttpHooks::SrsHttpHooks()
  133 +{
  134 +}
  135 +
  136 +SrsHttpHooks::~SrsHttpHooks()
  137 +{
  138 +}
  139 +
  140 +int SrsHttpHooks::on_connect(std::string url, std::string ip, SrsRequest* req)
  141 +{
  142 + int ret = ERROR_SUCCESS;
  143 +
  144 + SrsHttpUri uri;
  145 + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
  146 + srs_error("http uri parse url failed. "
  147 + "url=%s, ret=%d", url.c_str(), ret);
  148 + return ret;
  149 + }
  150 +
  151 + std::string res;
  152 + std::string data;
  153 + /**
  154 + {
  155 + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
  156 + "pageUrl": "http://www.test.com/live.html"
  157 + }
  158 + */
  159 + data += "{";
  160 + // ip
  161 + data += "\"ip\":";
  162 + data += "\"" + ip + "\"";
  163 + data += ",";
  164 + // vhost
  165 + data += "\"vhost\":";
  166 + data += "\"" + req->vhost + "\"";
  167 + data += ",";
  168 + data += ",";
  169 + // app
  170 + data += "\"vhost\":";
  171 + data += "\"" + req->app + "\"";
  172 + data += ",";
  173 + // pageUrl
  174 + data += "\"vhost\":";
  175 + data += "\"" + req->pageUrl + "\"";
  176 + //data += ",";
  177 + data += "}";
  178 +
  179 + SrsHttpClient http;
  180 + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
  181 + srs_error("http post uri failed. "
  182 + "url=%s, request=%s, response=%s, ret=%d",
  183 + url.c_str(), data.c_str(), res.c_str(), ret);
  184 + return ret;
  185 + }
  186 +
  187 + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
  188 + ret = ERROR_HTTP_DATA_INVLIAD;
  189 + srs_error("http hook validate failed. "
  190 + "res=%s, ret=%d", res.c_str(), ret);
  191 + return ret;
  192 + }
  193 +
  194 + srs_trace("http hook on_connect success. "
  195 + "url=%s, request=%s, response=%s, ret=%d",
  196 + url.c_str(), data.c_str(), res.c_str(), ret);
  197 +
  198 + return ret;
  199 +}
  200 +
27 #endif 201 #endif
@@ -29,7 +29,83 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -29,7 +29,83 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 */ 29 */
30 #include <srs_core.hpp> 30 #include <srs_core.hpp>
31 31
  32 +class SrsRequest;
  33 +
  34 +#include <string>
  35 +
32 #ifdef SRS_HTTP 36 #ifdef SRS_HTTP
  37 +
  38 +#include <http_parser.h>
  39 +
  40 +/**
  41 +* used to resolve the http uri.
  42 +*/
  43 +class SrsHttpUri
  44 +{
  45 +private:
  46 + std::string url;
  47 + std::string schema;
  48 + std::string host;
  49 + int port;
  50 + std::string path;
  51 +public:
  52 + SrsHttpUri();
  53 + virtual ~SrsHttpUri();
  54 +public:
  55 + /**
  56 + * initialize the http uri.
  57 + */
  58 + virtual int initialize(std::string _url);
  59 +public:
  60 + virtual const char* get_url();
  61 + virtual const char* get_schema();
  62 + virtual const char* get_host();
  63 + virtual int get_port();
  64 +private:
  65 + /**
  66 + * get the parsed url field.
  67 + * @return return empty string if not set.
  68 + */
  69 + virtual std::string get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field);
  70 +};
  71 +
  72 +/**
  73 +* http client to GET/POST/PUT/DELETE uri
  74 +*/
  75 +class SrsHttpClient
  76 +{
  77 +public:
  78 + SrsHttpClient();
  79 + virtual ~SrsHttpClient();
  80 +public:
  81 + /**
  82 + * to post data to the uri.
  83 + * @param req the data post to uri.
  84 + * @param res the response data from server.
  85 + */
  86 + virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
  87 +};
  88 +
  89 +/**
  90 +* the http hooks, http callback api,
  91 +* for some event, such as on_connect, call
  92 +* a http api(hooks).
  93 +*/
  94 +class SrsHttpHooks
  95 +{
  96 +public:
  97 + SrsHttpHooks();
  98 + virtual ~SrsHttpHooks();
  99 +public:
  100 + /**
  101 + * on_connect hook,
  102 + * @param url the api server url, to valid the client.
  103 + * ignore if empty.
  104 + * @return valid failed or connect to the url failed.
  105 + */
  106 + virtual int on_connect(std::string url, std::string ip, SrsRequest* req);
  107 +};
  108 +
33 #endif 109 #endif
34 110
35 #endif 111 #endif