winlin

refine code, extract http hooks.

@@ -427,7 +427,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke @@ -427,7 +427,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke
427 "srs_app_codec" "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder" 427 "srs_app_codec" "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder"
428 "srs_app_http" "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" 428 "srs_app_http" "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log"
429 "srs_app_config" "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" 429 "srs_app_config" "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api"
430 - "srs_app_http_conn") 430 + "srs_app_http_conn" "srs_app_http_hooks")
431 APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh 431 APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
432 APP_OBJS="${MODULE_OBJS[@]}" 432 APP_OBJS="${MODULE_OBJS[@]}"
433 # 433 #
@@ -23,26 +23,46 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -23,26 +23,46 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 23
24 #include <srs_app_http.hpp> 24 #include <srs_app_http.hpp>
25 25
26 -#ifdef SRS_HTTP_CALLBACK  
27 -  
28 -#include <sstream>  
29 -using namespace std; 26 +#ifdef SRS_HTTP_PARSER
30 27
31 #include <stdlib.h> 28 #include <stdlib.h>
32 -#include <sys/socket.h>  
33 -#include <netinet/in.h>  
34 -#include <arpa/inet.h>  
35 29
36 #include <srs_kernel_error.hpp> 30 #include <srs_kernel_error.hpp>
37 -#include <srs_protocol_rtmp.hpp>  
38 #include <srs_kernel_log.hpp> 31 #include <srs_kernel_log.hpp>
39 #include <srs_app_socket.hpp> 32 #include <srs_app_socket.hpp>
40 33
41 #define SRS_DEFAULT_HTTP_PORT 80 34 #define SRS_DEFAULT_HTTP_PORT 80
42 -#define SRS_HTTP_RESPONSE_OK "0"  
43 35
44 -#define SRS_HTTP_HEADER_BUFFER 1024  
45 -#define SRS_HTTP_BODY_BUFFER 32 * 1024 36 +SrsHttpMessage::SrsHttpMessage()
  37 +{
  38 + body = new SrsBuffer();
  39 + state = SrsHttpParseStateInit;
  40 +}
  41 +
  42 +SrsHttpMessage::~SrsHttpMessage()
  43 +{
  44 + srs_freep(body);
  45 +}
  46 +
  47 +void SrsHttpMessage::reset()
  48 +{
  49 + state = SrsHttpParseStateInit;
  50 + body->clear();
  51 + url = "";
  52 +}
  53 +
  54 +bool SrsHttpMessage::is_complete()
  55 +{
  56 + return state == SrsHttpParseStateComplete;
  57 +}
  58 +
  59 +SrsHttpParser::SrsHttpParser()
  60 +{
  61 +}
  62 +
  63 +SrsHttpParser::~SrsHttpParser()
  64 +{
  65 +}
46 66
47 SrsHttpUri::SrsHttpUri() 67 SrsHttpUri::SrsHttpUri()
48 { 68 {
@@ -130,692 +150,4 @@ std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, ht @@ -130,692 +150,4 @@ std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, ht
130 return uri.substr(offset, len); 150 return uri.substr(offset, len);
131 } 151 }
132 152
133 -SrsHttpClient::SrsHttpClient()  
134 -{  
135 - connected = false;  
136 - stfd = NULL;  
137 -}  
138 -  
139 -SrsHttpClient::~SrsHttpClient()  
140 -{  
141 - disconnect();  
142 -}  
143 -  
144 -int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)  
145 -{  
146 - int ret = ERROR_SUCCESS;  
147 -  
148 - if ((ret = connect(uri)) != ERROR_SUCCESS) {  
149 - srs_error("http connect server failed. ret=%d", ret);  
150 - return ret;  
151 - }  
152 -  
153 - // send POST request to uri  
154 - // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s  
155 - std::stringstream ss;  
156 - ss << "POST " << uri->get_path() << " "  
157 - << "HTTP/1.1" << __CRLF  
158 - << "Host: " << uri->get_host() << __CRLF  
159 - << "Connection: Keep-Alive" << __CRLF  
160 - << "Content-Length: " << std::dec << req.length() << __CRLF  
161 - << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __CRLF  
162 - << "Content-Type: text/html" << __CRLF  
163 - << __CRLF  
164 - << req;  
165 -  
166 - SrsSocket skt(stfd);  
167 -  
168 - std::string data = ss.str();  
169 - ssize_t nwrite;  
170 - if ((ret = skt.write(data.c_str(), data.length(), &nwrite)) != ERROR_SUCCESS) {  
171 - // disconnect when error.  
172 - disconnect();  
173 -  
174 - srs_error("write http post failed. ret=%d", ret);  
175 - return ret;  
176 - }  
177 -  
178 - if ((ret = parse_response(uri, &skt, &res)) != ERROR_SUCCESS) {  
179 - srs_error("parse http post response failed. ret=%d", ret);  
180 - return ret;  
181 - }  
182 - srs_info("parse http post response success.");  
183 -  
184 - return ret;  
185 -}  
186 -  
187 -void SrsHttpClient::disconnect()  
188 -{  
189 - connected = false;  
190 -  
191 - srs_close_stfd(stfd);  
192 -}  
193 -  
194 -int SrsHttpClient::connect(SrsHttpUri* uri)  
195 -{  
196 - int ret = ERROR_SUCCESS;  
197 -  
198 - if (connected) {  
199 - return ret;  
200 - }  
201 -  
202 - disconnect();  
203 -  
204 - std::string ip = srs_dns_resolve(uri->get_host());  
205 - if (ip.empty()) {  
206 - ret = ERROR_SYSTEM_IP_INVALID;  
207 - srs_error("dns resolve server error, ip empty. ret=%d", ret);  
208 - return ret;  
209 - }  
210 -  
211 - int sock = socket(AF_INET, SOCK_STREAM, 0);  
212 - if(sock == -1){  
213 - ret = ERROR_SOCKET_CREATE;  
214 - srs_error("create socket error. ret=%d", ret);  
215 - return ret;  
216 - }  
217 -  
218 - stfd = st_netfd_open_socket(sock);  
219 - if(stfd == NULL){  
220 - ret = ERROR_ST_OPEN_SOCKET;  
221 - srs_error("st_netfd_open_socket failed. ret=%d", ret);  
222 - return ret;  
223 - }  
224 -  
225 - sockaddr_in addr;  
226 - addr.sin_family = AF_INET;  
227 - addr.sin_port = htons(uri->get_port());  
228 - addr.sin_addr.s_addr = inet_addr(ip.c_str());  
229 -  
230 - if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){  
231 - ret = ERROR_ST_CONNECT;  
232 - srs_error("connect to server error. "  
233 - "ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret);  
234 - return ret;  
235 - }  
236 - srs_info("connect to server success. "  
237 - "http url=%s, server=%s, ip=%s, port=%d",  
238 - uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());  
239 -  
240 - connected = true;  
241 -  
242 - return ret;  
243 -}  
244 -  
245 -int SrsHttpClient::parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response)  
246 -{  
247 - int ret = ERROR_SUCCESS;  
248 -  
249 - int body_received = 0;  
250 - if ((ret = parse_response_header(skt, response, body_received)) != ERROR_SUCCESS) {  
251 - srs_error("parse response header failed. ret=%d", ret);  
252 - return ret;  
253 - }  
254 -  
255 - if ((ret = parse_response_body(uri, skt, response, body_received)) != ERROR_SUCCESS) {  
256 - srs_error("parse response body failed. ret=%d", ret);  
257 - return ret;  
258 - }  
259 -  
260 - srs_info("url %s download, body size=%"PRId64, uri->get_url(), http_header.content_length);  
261 -  
262 - return ret;  
263 -}  
264 -  
265 -int SrsHttpClient::parse_response_header(SrsSocket* skt, std::string* response, int& body_received)  
266 -{  
267 - int ret = ERROR_SUCCESS;  
268 -  
269 - http_parser_settings settings;  
270 -  
271 - memset(&settings, 0, sizeof(settings));  
272 - settings.on_headers_complete = on_headers_complete;  
273 -  
274 - http_parser parser;  
275 - http_parser_init(&parser, HTTP_RESPONSE);  
276 - // callback object ptr.  
277 - parser.data = (void*)this;  
278 -  
279 - // reset response header.  
280 - memset(&http_header, 0, sizeof(http_header));  
281 -  
282 - // parser header.  
283 - char buf[SRS_HTTP_HEADER_BUFFER];  
284 - for (;;) {  
285 - ssize_t nread;  
286 - if ((ret = skt->read(buf, (size_t)sizeof(buf), &nread)) != ERROR_SUCCESS) {  
287 - srs_error("read body from server failed. ret=%d", ret);  
288 - return ret;  
289 - }  
290 -  
291 - ssize_t nparsed = http_parser_execute(&parser, &settings, buf, nread);  
292 - srs_info("read_size=%d, nparsed=%d", (int)nread, (int)nparsed);  
293 -  
294 - // check header size.  
295 - if (http_header.nread != 0) {  
296 - body_received = nread - nparsed;  
297 -  
298 - srs_info("http header parsed, size=%d, content-length=%"PRId64", body-received=%d",  
299 - http_header.nread, http_header.content_length, body_received);  
300 -  
301 - if(response != NULL && body_received > 0){  
302 - response->append(buf + nparsed, body_received);  
303 - }  
304 -  
305 - return ret;  
306 - }  
307 -  
308 - if (nparsed != nread) {  
309 - ret = ERROR_HTTP_PARSE_HEADER;  
310 - srs_error("parse response error, parsed(%d)!=read(%d), ret=%d", (int)nparsed, (int)nread, ret);  
311 - return ret;  
312 - }  
313 - }  
314 -  
315 - return ret;  
316 -}  
317 -  
318 -int SrsHttpClient::parse_response_body(SrsHttpUri* uri, SrsSocket* skt, std::string* response, int body_received)  
319 -{  
320 - int ret = ERROR_SUCCESS;  
321 -  
322 - srs_assert(uri != NULL);  
323 -  
324 - uint64_t body_left = http_header.content_length - body_received;  
325 -  
326 - if (body_left <= 0) {  
327 - return ret;  
328 - }  
329 -  
330 - if (response != NULL) {  
331 - char buf[SRS_HTTP_BODY_BUFFER];  
332 -  
333 - return parse_response_body_data(  
334 - uri, skt, response, (size_t)body_left,  
335 - (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER  
336 - );  
337 - } else {  
338 - // if ignore response, use shared fast memory.  
339 - static char buf[SRS_HTTP_BODY_BUFFER];  
340 -  
341 - return parse_response_body_data(  
342 - uri, skt, response, (size_t)body_left,  
343 - (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER  
344 - );  
345 - }  
346 -  
347 - return ret;  
348 -}  
349 -  
350 -int SrsHttpClient::parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std::string* response, size_t body_left, const void* buf, size_t size)  
351 -{  
352 - int ret = ERROR_SUCCESS;  
353 -  
354 - srs_assert(uri != NULL);  
355 -  
356 - while (body_left > 0) {  
357 - ssize_t nread;  
358 - int size_to_read = srs_min(size, body_left);  
359 - if ((ret = skt->read(buf, size_to_read, &nread)) != ERROR_SUCCESS) {  
360 - srs_error("read header from server failed. ret=%d", ret);  
361 - return ret;  
362 - }  
363 -  
364 - if (response != NULL && nread > 0) {  
365 - response->append((char*)buf, nread);  
366 - }  
367 -  
368 - body_left -= nread;  
369 - srs_info("read url(%s) content partial %"PRId64"/%"PRId64"",  
370 - uri->get_url(), http_header.content_length - body_left, http_header.content_length);  
371 - }  
372 -  
373 - return ret;  
374 -}  
375 -  
376 -int SrsHttpClient::on_headers_complete(http_parser* parser)  
377 -{  
378 - SrsHttpClient* obj = (SrsHttpClient*)parser->data;  
379 - obj->complete_header(parser);  
380 -  
381 - // see http_parser.c:1570, return 1 to skip body.  
382 - return 1;  
383 -}  
384 -  
385 -void SrsHttpClient::complete_header(http_parser* parser)  
386 -{  
387 - // save the parser status when header parse completed.  
388 - memcpy(&http_header, parser, sizeof(http_header));  
389 -}  
390 -  
391 -SrsHttpHooks::SrsHttpHooks()  
392 -{  
393 -}  
394 -  
395 -SrsHttpHooks::~SrsHttpHooks()  
396 -{  
397 -}  
398 -  
399 -int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req)  
400 -{  
401 - int ret = ERROR_SUCCESS;  
402 -  
403 - SrsHttpUri uri;  
404 - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {  
405 - srs_error("http uri parse on_connect url failed. "  
406 - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);  
407 - return ret;  
408 - }  
409 -  
410 - /**  
411 - {  
412 - "action": "on_connect",  
413 - "client_id": 1985,  
414 - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",  
415 - "pageUrl": "http://www.test.com/live.html"  
416 - }  
417 - */  
418 - std::stringstream ss;  
419 - ss << "{"  
420 - // action  
421 - << '"' << "action" << '"' << ':'  
422 - << '"' << "on_connect" << '"'  
423 - << ','  
424 - // client_id  
425 - << '"' << "client_id" << '"' << ':'  
426 - << std::dec << client_id  
427 - << ','  
428 - // ip  
429 - << '"' << "ip" << '"' << ':'  
430 - << '"' << ip << '"'  
431 - << ','  
432 - // vhost  
433 - << '"' << "vhost" << '"' << ':'  
434 - << '"' << req->vhost << '"'  
435 - << ','  
436 - // app  
437 - << '"' << "app" << '"' << ':'  
438 - << '"' << req->app << '"'  
439 - << ','  
440 - // pageUrl  
441 - << '"' << "pageUrl" << '"' << ':'  
442 - << '"' << req->pageUrl << '"'  
443 - //<< ','  
444 - << "}";  
445 - std::string data = ss.str();  
446 - std::string res;  
447 -  
448 - SrsHttpClient http;  
449 - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {  
450 - srs_error("http post on_connect uri failed. "  
451 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
452 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
453 - return ret;  
454 - }  
455 -  
456 - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {  
457 - ret = ERROR_HTTP_DATA_INVLIAD;  
458 - srs_error("http hook on_connect validate failed. "  
459 - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);  
460 - return ret;  
461 - }  
462 -  
463 - srs_trace("http hook on_connect success. "  
464 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
465 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
466 -  
467 - return ret;  
468 -}  
469 -  
470 -void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req)  
471 -{  
472 - int ret = ERROR_SUCCESS;  
473 -  
474 - SrsHttpUri uri;  
475 - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {  
476 - srs_warn("http uri parse on_close url failed, ignored. "  
477 - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);  
478 - return;  
479 - }  
480 -  
481 - /**  
482 - {  
483 - "action": "on_close",  
484 - "client_id": 1985,  
485 - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",  
486 - "stream": "livestream"  
487 - }  
488 - */  
489 - std::stringstream ss;  
490 - ss << "{"  
491 - // action  
492 - << '"' << "action" << '"' << ':'  
493 - << '"' << "on_close" << '"'  
494 - << ','  
495 - // client_id  
496 - << '"' << "client_id" << '"' << ':'  
497 - << std::dec << client_id  
498 - << ','  
499 - // ip  
500 - << '"' << "ip" << '"' << ':'  
501 - << '"' << ip << '"'  
502 - << ','  
503 - // vhost  
504 - << '"' << "vhost" << '"' << ':'  
505 - << '"' << req->vhost << '"'  
506 - << ','  
507 - // app  
508 - << '"' << "app" << '"' << ':'  
509 - << '"' << req->app << '"'  
510 - //<< ','  
511 - << "}";  
512 - std::string data = ss.str();  
513 - std::string res;  
514 -  
515 - SrsHttpClient http;  
516 - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {  
517 - srs_warn("http post on_close uri failed, ignored. "  
518 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
519 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
520 - return;  
521 - }  
522 -  
523 - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {  
524 - ret = ERROR_HTTP_DATA_INVLIAD;  
525 - srs_warn("http hook on_close validate failed, ignored. "  
526 - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);  
527 - return;  
528 - }  
529 -  
530 - srs_trace("http hook on_close success. "  
531 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
532 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
533 -  
534 - return;  
535 -}  
536 -  
537 -int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req)  
538 -{  
539 - int ret = ERROR_SUCCESS;  
540 -  
541 - SrsHttpUri uri;  
542 - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {  
543 - srs_error("http uri parse on_publish url failed. "  
544 - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);  
545 - return ret;  
546 - }  
547 -  
548 - /**  
549 - {  
550 - "action": "on_publish",  
551 - "client_id": 1985,  
552 - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",  
553 - "stream": "livestream"  
554 - }  
555 - */  
556 - std::stringstream ss;  
557 - ss << "{"  
558 - // action  
559 - << '"' << "action" << '"' << ':'  
560 - << '"' << "on_publish" << '"'  
561 - << ','  
562 - // client_id  
563 - << '"' << "client_id" << '"' << ':'  
564 - << std::dec << client_id  
565 - << ','  
566 - // ip  
567 - << '"' << "ip" << '"' << ':'  
568 - << '"' << ip << '"'  
569 - << ','  
570 - // vhost  
571 - << '"' << "vhost" << '"' << ':'  
572 - << '"' << req->vhost << '"'  
573 - << ','  
574 - // app  
575 - << '"' << "app" << '"' << ':'  
576 - << '"' << req->app << '"'  
577 - << ','  
578 - // stream  
579 - << '"' << "stream" << '"' << ':'  
580 - << '"' << req->stream << '"'  
581 - //<< ','  
582 - << "}";  
583 - std::string data = ss.str();  
584 - std::string res;  
585 -  
586 - SrsHttpClient http;  
587 - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {  
588 - srs_error("http post on_publish uri failed. "  
589 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
590 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
591 - return ret;  
592 - }  
593 -  
594 - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {  
595 - ret = ERROR_HTTP_DATA_INVLIAD;  
596 - srs_error("http hook on_publish validate failed. "  
597 - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);  
598 - return ret;  
599 - }  
600 -  
601 - srs_trace("http hook on_publish success. "  
602 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
603 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
604 -  
605 - return ret;  
606 -}  
607 -  
608 -void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req)  
609 -{  
610 - int ret = ERROR_SUCCESS;  
611 -  
612 - SrsHttpUri uri;  
613 - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {  
614 - srs_warn("http uri parse on_unpublish url failed, ignored. "  
615 - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);  
616 - return;  
617 - }  
618 -  
619 - /**  
620 - {  
621 - "action": "on_unpublish",  
622 - "client_id": 1985,  
623 - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",  
624 - "stream": "livestream"  
625 - }  
626 - */  
627 - std::stringstream ss;  
628 - ss << "{"  
629 - // action  
630 - << '"' << "action" << '"' << ':'  
631 - << '"' << "on_unpublish" << '"'  
632 - << ','  
633 - // client_id  
634 - << '"' << "client_id" << '"' << ':'  
635 - << std::dec << client_id  
636 - << ','  
637 - // ip  
638 - << '"' << "ip" << '"' << ':'  
639 - << '"' << ip << '"'  
640 - << ','  
641 - // vhost  
642 - << '"' << "vhost" << '"' << ':'  
643 - << '"' << req->vhost << '"'  
644 - << ','  
645 - // app  
646 - << '"' << "app" << '"' << ':'  
647 - << '"' << req->app << '"'  
648 - << ','  
649 - // stream  
650 - << '"' << "stream" << '"' << ':'  
651 - << '"' << req->stream << '"'  
652 - //<< ','  
653 - << "}";  
654 - std::string data = ss.str();  
655 - std::string res;  
656 -  
657 - SrsHttpClient http;  
658 - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {  
659 - srs_warn("http post on_unpublish uri failed, ignored. "  
660 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
661 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
662 - return;  
663 - }  
664 -  
665 - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {  
666 - ret = ERROR_HTTP_DATA_INVLIAD;  
667 - srs_warn("http hook on_unpublish validate failed, ignored. "  
668 - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);  
669 - return;  
670 - }  
671 -  
672 - srs_trace("http hook on_unpublish success. "  
673 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
674 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
675 -  
676 - return;  
677 -}  
678 -  
679 -int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req)  
680 -{  
681 - int ret = ERROR_SUCCESS;  
682 -  
683 - SrsHttpUri uri;  
684 - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {  
685 - srs_error("http uri parse on_play url failed. "  
686 - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);  
687 - return ret;  
688 - }  
689 -  
690 - /**  
691 - {  
692 - "action": "on_play",  
693 - "client_id": 1985,  
694 - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",  
695 - "stream": "livestream"  
696 - }  
697 - */  
698 - std::stringstream ss;  
699 - ss << "{"  
700 - // action  
701 - << '"' << "action" << '"' << ':'  
702 - << '"' << "on_play" << '"'  
703 - << ','  
704 - // client_id  
705 - << '"' << "client_id" << '"' << ':'  
706 - << std::dec << client_id  
707 - << ','  
708 - // ip  
709 - << '"' << "ip" << '"' << ':'  
710 - << '"' << ip << '"'  
711 - << ','  
712 - // vhost  
713 - << '"' << "vhost" << '"' << ':'  
714 - << '"' << req->vhost << '"'  
715 - << ','  
716 - // app  
717 - << '"' << "app" << '"' << ':'  
718 - << '"' << req->app << '"'  
719 - << ','  
720 - // stream  
721 - << '"' << "stream" << '"' << ':'  
722 - << '"' << req->stream << '"'  
723 - //<< ','  
724 - << "}";  
725 - std::string data = ss.str();  
726 - std::string res;  
727 -  
728 - SrsHttpClient http;  
729 - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {  
730 - srs_error("http post on_play uri failed. "  
731 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
732 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
733 - return ret;  
734 - }  
735 -  
736 - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {  
737 - ret = ERROR_HTTP_DATA_INVLIAD;  
738 - srs_error("http hook on_play validate failed. "  
739 - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);  
740 - return ret;  
741 - }  
742 -  
743 - srs_trace("http hook on_play success. "  
744 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
745 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
746 -  
747 - return ret;  
748 -}  
749 -  
750 -void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req)  
751 -{  
752 - int ret = ERROR_SUCCESS;  
753 -  
754 - SrsHttpUri uri;  
755 - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {  
756 - srs_warn("http uri parse on_stop url failed, ignored. "  
757 - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);  
758 - return;  
759 - }  
760 -  
761 - /**  
762 - {  
763 - "action": "on_stop",  
764 - "client_id": 1985,  
765 - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",  
766 - "stream": "livestream"  
767 - }  
768 - */  
769 - std::stringstream ss;  
770 - ss << "{"  
771 - // action  
772 - << '"' << "action" << '"' << ':'  
773 - << '"' << "on_stop" << '"'  
774 - << ','  
775 - // client_id  
776 - << '"' << "client_id" << '"' << ':'  
777 - << std::dec << client_id  
778 - << ','  
779 - // ip  
780 - << '"' << "ip" << '"' << ':'  
781 - << '"' << ip << '"'  
782 - << ','  
783 - // vhost  
784 - << '"' << "vhost" << '"' << ':'  
785 - << '"' << req->vhost << '"'  
786 - << ','  
787 - // app  
788 - << '"' << "app" << '"' << ':'  
789 - << '"' << req->app << '"'  
790 - << ','  
791 - // stream  
792 - << '"' << "stream" << '"' << ':'  
793 - << '"' << req->stream << '"'  
794 - //<< ','  
795 - << "}";  
796 - std::string data = ss.str();  
797 - std::string res;  
798 -  
799 - SrsHttpClient http;  
800 - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {  
801 - srs_warn("http post on_stop uri failed, ignored. "  
802 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
803 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
804 - return;  
805 - }  
806 -  
807 - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {  
808 - ret = ERROR_HTTP_DATA_INVLIAD;  
809 - srs_warn("http hook on_stop validate failed, ignored. "  
810 - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);  
811 - return;  
812 - }  
813 -  
814 - srs_trace("http hook on_stop success. "  
815 - "client_id=%d, url=%s, request=%s, response=%s, ret=%d",  
816 - client_id, url.c_str(), data.c_str(), res.c_str(), ret);  
817 -  
818 - return;  
819 -}  
820 -  
821 #endif 153 #endif
@@ -29,9 +29,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -29,9 +29,17 @@ 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 +#ifdef SRS_HTTP_PARSER
  33 +
  34 +#include <string>
  35 +
  36 +#include <http_parser.h>
  37 +
32 #include <srs_app_st.hpp> 38 #include <srs_app_st.hpp>
33 39
34 -#ifdef SRS_HTTP_PARSER 40 +class SrsBuffer;
  41 +class SrsRequest;
  42 +class SrsSocket;
35 43
36 // http specification 44 // http specification
37 // CR = <US-ASCII CR, carriage return (13)> 45 // CR = <US-ASCII CR, carriage return (13)>
@@ -49,16 +57,42 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -49,16 +57,42 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 #define __CRLF "\r\n" // 0x0D0A 57 #define __CRLF "\r\n" // 0x0D0A
50 #define __CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A 58 #define __CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
51 59
52 -#endif  
53 -  
54 -#ifdef SRS_HTTP_CALLBACK  
55 -  
56 -class SrsRequest;  
57 -class SrsSocket; 60 +enum SrsHttpParseState {
  61 + SrsHttpParseStateInit = 0,
  62 + SrsHttpParseStateStart,
  63 + SrsHttpParseStateComplete
  64 +};
58 65
59 -#include <string> 66 +/**
  67 +* the http message, request or response.
  68 +*/
  69 +class SrsHttpMessage
  70 +{
  71 +public:
  72 + std::string url;
  73 + http_parser header;
  74 + SrsBuffer* body;
  75 + SrsHttpParseState state;
  76 +
  77 + SrsHttpMessage();
  78 + virtual ~SrsHttpMessage();
  79 +
  80 + virtual void reset();
  81 + virtual bool is_complete();
  82 +};
60 83
61 -#include <http_parser.h> 84 +/**
  85 +* wrapper for http-parser,
  86 +* provides HTTP message originted service.
  87 +*/
  88 +class SrsHttpParser
  89 +{
  90 +public:
  91 + SrsHttpParser();
  92 + virtual ~SrsHttpParser();
  93 +public:
  94 + //virtual int parse_requst(SrsHttpMessage** ppreq);
  95 +};
62 96
63 /** 97 /**
64 * used to resolve the http uri. 98 * used to resolve the http uri.
@@ -93,97 +127,6 @@ private: @@ -93,97 +127,6 @@ private:
93 virtual std::string get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field); 127 virtual std::string get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field);
94 }; 128 };
95 129
96 -/**  
97 -* http client to GET/POST/PUT/DELETE uri  
98 -*/  
99 -class SrsHttpClient  
100 -{  
101 -private:  
102 - bool connected;  
103 - st_netfd_t stfd;  
104 -private:  
105 - http_parser http_header;  
106 -public:  
107 - SrsHttpClient();  
108 - virtual ~SrsHttpClient();  
109 -public:  
110 - /**  
111 - * to post data to the uri.  
112 - * @param req the data post to uri.  
113 - * @param res the response data from server.  
114 - */  
115 - virtual int post(SrsHttpUri* uri, std::string req, std::string& res);  
116 -private:  
117 - virtual void disconnect();  
118 - virtual int connect(SrsHttpUri* uri);  
119 -private:  
120 - virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response);  
121 - virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received);  
122 - virtual int parse_response_body(SrsHttpUri* uri, SrsSocket* skt, std::string* response, int body_received);  
123 - virtual int parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std::string* response, size_t body_left, const void* buf, size_t size);  
124 -private:  
125 - static int on_headers_complete(http_parser* parser);  
126 - virtual void complete_header(http_parser* parser);  
127 -};  
128 -  
129 -/**  
130 -* the http hooks, http callback api,  
131 -* for some event, such as on_connect, call  
132 -* a http api(hooks).  
133 -*/  
134 -class SrsHttpHooks  
135 -{  
136 -public:  
137 - SrsHttpHooks();  
138 - virtual ~SrsHttpHooks();  
139 -public:  
140 - /**  
141 - * on_connect hook, when client connect to srs.  
142 - * @param client_id the id of client on server.  
143 - * @param url the api server url, to valid the client.  
144 - * ignore if empty.  
145 - * @return valid failed or connect to the url failed.  
146 - */  
147 - virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req);  
148 - /**  
149 - * on_close hook, when client disconnect to srs, where client is valid by on_connect.  
150 - * @param client_id the id of client on server.  
151 - * @param url the api server url, to process the event.  
152 - * ignore if empty.  
153 - */  
154 - virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req);  
155 - /**  
156 - * on_publish hook, when client(encoder) start to publish stream  
157 - * @param client_id the id of client on server.  
158 - * @param url the api server url, to valid the client.  
159 - * ignore if empty.  
160 - * @return valid failed or connect to the url failed.  
161 - */  
162 - virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);  
163 - /**  
164 - * on_unpublish hook, when client(encoder) stop publish stream.  
165 - * @param client_id the id of client on server.  
166 - * @param url the api server url, to process the event.  
167 - * ignore if empty.  
168 - */  
169 - virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);  
170 - /**  
171 - * on_play hook, when client start to play stream.  
172 - * @param client_id the id of client on server.  
173 - * @param url the api server url, to valid the client.  
174 - * ignore if empty.  
175 - * @return valid failed or connect to the url failed.  
176 - */  
177 - virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req);  
178 - /**  
179 - * on_stop hook, when client stop to play the stream.  
180 - * @param client_id the id of client on server.  
181 - * @param url the api server url, to process the event.  
182 - * ignore if empty.  
183 - */  
184 - virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);  
185 -};  
186 -  
187 #endif 130 #endif
188 131
189 #endif 132 #endif
@@ -36,33 +36,10 @@ using namespace std; @@ -36,33 +36,10 @@ using namespace std;
36 36
37 #define SRS_HTTP_HEADER_BUFFER 1024 37 #define SRS_HTTP_HEADER_BUFFER 1024
38 38
39 -SrsHttpRequest::SrsHttpRequest()  
40 -{  
41 - body = new SrsBuffer();  
42 - state = SrsHttpParseStateInit;  
43 -}  
44 -  
45 -SrsHttpRequest::~SrsHttpRequest()  
46 -{  
47 - srs_freep(body);  
48 -}  
49 -  
50 -void SrsHttpRequest::reset()  
51 -{  
52 - state = SrsHttpParseStateInit;  
53 - body->clear();  
54 - url = "";  
55 -}  
56 -  
57 -bool SrsHttpRequest::is_complete()  
58 -{  
59 - return state == SrsHttpParseStateComplete;  
60 -}  
61 -  
62 SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd) 39 SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd)
63 : SrsConnection(srs_server, client_stfd) 40 : SrsConnection(srs_server, client_stfd)
64 { 41 {
65 - req = new SrsHttpRequest(); 42 + req = new SrsHttpMessage();
66 } 43 }
67 44
68 SrsHttpConn::~SrsHttpConn() 45 SrsHttpConn::~SrsHttpConn()
@@ -38,33 +38,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -38,33 +38,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #include <http_parser.h> 38 #include <http_parser.h>
39 39
40 class SrsSocket; 40 class SrsSocket;
41 -class SrsBuffer;  
42 -  
43 -enum SrsHttpParseState {  
44 - SrsHttpParseStateInit = 0,  
45 - SrsHttpParseStateStart,  
46 - SrsHttpParseStateComplete  
47 -};  
48 -  
49 -class SrsHttpRequest  
50 -{  
51 -public:  
52 - std::string url;  
53 - http_parser header;  
54 - SrsBuffer* body;  
55 - SrsHttpParseState state;  
56 -  
57 - SrsHttpRequest();  
58 - virtual ~SrsHttpRequest();  
59 -  
60 - virtual void reset();  
61 - virtual bool is_complete();  
62 -}; 41 +class SrsHttpMessage;
63 42
64 class SrsHttpConn : public SrsConnection 43 class SrsHttpConn : public SrsConnection
65 { 44 {
66 private: 45 private:
67 - SrsHttpRequest* req; 46 + SrsHttpMessage* req;
68 public: 47 public:
69 SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd); 48 SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd);
70 virtual ~SrsHttpConn(); 49 virtual ~SrsHttpConn();
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_app_http_hooks.hpp>
  25 +
  26 +#ifdef SRS_HTTP_CALLBACK
  27 +
  28 +#include <sstream>
  29 +using namespace std;
  30 +
  31 +#include <arpa/inet.h>
  32 +
  33 +#include <srs_kernel_error.hpp>
  34 +#include <srs_protocol_rtmp.hpp>
  35 +#include <srs_kernel_log.hpp>
  36 +#include <srs_app_socket.hpp>
  37 +#include <srs_app_http.hpp>
  38 +
  39 +#define SRS_HTTP_RESPONSE_OK "0"
  40 +
  41 +#define SRS_HTTP_HEADER_BUFFER 1024
  42 +#define SRS_HTTP_BODY_BUFFER 32 * 1024
  43 +
  44 +SrsHttpClient::SrsHttpClient()
  45 +{
  46 + connected = false;
  47 + stfd = NULL;
  48 +}
  49 +
  50 +SrsHttpClient::~SrsHttpClient()
  51 +{
  52 + disconnect();
  53 +}
  54 +
  55 +int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
  56 +{
  57 + int ret = ERROR_SUCCESS;
  58 +
  59 + if ((ret = connect(uri)) != ERROR_SUCCESS) {
  60 + srs_error("http connect server failed. ret=%d", ret);
  61 + return ret;
  62 + }
  63 +
  64 + // send POST request to uri
  65 + // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
  66 + std::stringstream ss;
  67 + ss << "POST " << uri->get_path() << " "
  68 + << "HTTP/1.1" << __CRLF
  69 + << "Host: " << uri->get_host() << __CRLF
  70 + << "Connection: Keep-Alive" << __CRLF
  71 + << "Content-Length: " << std::dec << req.length() << __CRLF
  72 + << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __CRLF
  73 + << "Content-Type: text/html" << __CRLF
  74 + << __CRLF
  75 + << req;
  76 +
  77 + SrsSocket skt(stfd);
  78 +
  79 + std::string data = ss.str();
  80 + ssize_t nwrite;
  81 + if ((ret = skt.write(data.c_str(), data.length(), &nwrite)) != ERROR_SUCCESS) {
  82 + // disconnect when error.
  83 + disconnect();
  84 +
  85 + srs_error("write http post failed. ret=%d", ret);
  86 + return ret;
  87 + }
  88 +
  89 + if ((ret = parse_response(uri, &skt, &res)) != ERROR_SUCCESS) {
  90 + srs_error("parse http post response failed. ret=%d", ret);
  91 + return ret;
  92 + }
  93 + srs_info("parse http post response success.");
  94 +
  95 + return ret;
  96 +}
  97 +
  98 +void SrsHttpClient::disconnect()
  99 +{
  100 + connected = false;
  101 +
  102 + srs_close_stfd(stfd);
  103 +}
  104 +
  105 +int SrsHttpClient::connect(SrsHttpUri* uri)
  106 +{
  107 + int ret = ERROR_SUCCESS;
  108 +
  109 + if (connected) {
  110 + return ret;
  111 + }
  112 +
  113 + disconnect();
  114 +
  115 + std::string ip = srs_dns_resolve(uri->get_host());
  116 + if (ip.empty()) {
  117 + ret = ERROR_SYSTEM_IP_INVALID;
  118 + srs_error("dns resolve server error, ip empty. ret=%d", ret);
  119 + return ret;
  120 + }
  121 +
  122 + int sock = socket(AF_INET, SOCK_STREAM, 0);
  123 + if(sock == -1){
  124 + ret = ERROR_SOCKET_CREATE;
  125 + srs_error("create socket error. ret=%d", ret);
  126 + return ret;
  127 + }
  128 +
  129 + stfd = st_netfd_open_socket(sock);
  130 + if(stfd == NULL){
  131 + ret = ERROR_ST_OPEN_SOCKET;
  132 + srs_error("st_netfd_open_socket failed. ret=%d", ret);
  133 + return ret;
  134 + }
  135 +
  136 + sockaddr_in addr;
  137 + addr.sin_family = AF_INET;
  138 + addr.sin_port = htons(uri->get_port());
  139 + addr.sin_addr.s_addr = inet_addr(ip.c_str());
  140 +
  141 + if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
  142 + ret = ERROR_ST_CONNECT;
  143 + srs_error("connect to server error. "
  144 + "ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret);
  145 + return ret;
  146 + }
  147 + srs_info("connect to server success. "
  148 + "http url=%s, server=%s, ip=%s, port=%d",
  149 + uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());
  150 +
  151 + connected = true;
  152 +
  153 + return ret;
  154 +}
  155 +
  156 +int SrsHttpClient::parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response)
  157 +{
  158 + int ret = ERROR_SUCCESS;
  159 +
  160 + int body_received = 0;
  161 + if ((ret = parse_response_header(skt, response, body_received)) != ERROR_SUCCESS) {
  162 + srs_error("parse response header failed. ret=%d", ret);
  163 + return ret;
  164 + }
  165 +
  166 + if ((ret = parse_response_body(uri, skt, response, body_received)) != ERROR_SUCCESS) {
  167 + srs_error("parse response body failed. ret=%d", ret);
  168 + return ret;
  169 + }
  170 +
  171 + srs_info("url %s download, body size=%"PRId64, uri->get_url(), http_header.content_length);
  172 +
  173 + return ret;
  174 +}
  175 +
  176 +int SrsHttpClient::parse_response_header(SrsSocket* skt, std::string* response, int& body_received)
  177 +{
  178 + int ret = ERROR_SUCCESS;
  179 +
  180 + http_parser_settings settings;
  181 +
  182 + memset(&settings, 0, sizeof(settings));
  183 + settings.on_headers_complete = on_headers_complete;
  184 +
  185 + http_parser parser;
  186 + http_parser_init(&parser, HTTP_RESPONSE);
  187 + // callback object ptr.
  188 + parser.data = (void*)this;
  189 +
  190 + // reset response header.
  191 + memset(&http_header, 0, sizeof(http_header));
  192 +
  193 + // parser header.
  194 + char buf[SRS_HTTP_HEADER_BUFFER];
  195 + for (;;) {
  196 + ssize_t nread;
  197 + if ((ret = skt->read(buf, (size_t)sizeof(buf), &nread)) != ERROR_SUCCESS) {
  198 + srs_error("read body from server failed. ret=%d", ret);
  199 + return ret;
  200 + }
  201 +
  202 + ssize_t nparsed = http_parser_execute(&parser, &settings, buf, nread);
  203 + srs_info("read_size=%d, nparsed=%d", (int)nread, (int)nparsed);
  204 +
  205 + // check header size.
  206 + if (http_header.nread != 0) {
  207 + body_received = nread - nparsed;
  208 +
  209 + srs_info("http header parsed, size=%d, content-length=%"PRId64", body-received=%d",
  210 + http_header.nread, http_header.content_length, body_received);
  211 +
  212 + if(response != NULL && body_received > 0){
  213 + response->append(buf + nparsed, body_received);
  214 + }
  215 +
  216 + return ret;
  217 + }
  218 +
  219 + if (nparsed != nread) {
  220 + ret = ERROR_HTTP_PARSE_HEADER;
  221 + srs_error("parse response error, parsed(%d)!=read(%d), ret=%d", (int)nparsed, (int)nread, ret);
  222 + return ret;
  223 + }
  224 + }
  225 +
  226 + return ret;
  227 +}
  228 +
  229 +int SrsHttpClient::parse_response_body(SrsHttpUri* uri, SrsSocket* skt, std::string* response, int body_received)
  230 +{
  231 + int ret = ERROR_SUCCESS;
  232 +
  233 + srs_assert(uri != NULL);
  234 +
  235 + uint64_t body_left = http_header.content_length - body_received;
  236 +
  237 + if (body_left <= 0) {
  238 + return ret;
  239 + }
  240 +
  241 + if (response != NULL) {
  242 + char buf[SRS_HTTP_BODY_BUFFER];
  243 +
  244 + return parse_response_body_data(
  245 + uri, skt, response, (size_t)body_left,
  246 + (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
  247 + );
  248 + } else {
  249 + // if ignore response, use shared fast memory.
  250 + static char buf[SRS_HTTP_BODY_BUFFER];
  251 +
  252 + return parse_response_body_data(
  253 + uri, skt, response, (size_t)body_left,
  254 + (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
  255 + );
  256 + }
  257 +
  258 + return ret;
  259 +}
  260 +
  261 +int SrsHttpClient::parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std::string* response, size_t body_left, const void* buf, size_t size)
  262 +{
  263 + int ret = ERROR_SUCCESS;
  264 +
  265 + srs_assert(uri != NULL);
  266 +
  267 + while (body_left > 0) {
  268 + ssize_t nread;
  269 + int size_to_read = srs_min(size, body_left);
  270 + if ((ret = skt->read(buf, size_to_read, &nread)) != ERROR_SUCCESS) {
  271 + srs_error("read header from server failed. ret=%d", ret);
  272 + return ret;
  273 + }
  274 +
  275 + if (response != NULL && nread > 0) {
  276 + response->append((char*)buf, nread);
  277 + }
  278 +
  279 + body_left -= nread;
  280 + srs_info("read url(%s) content partial %"PRId64"/%"PRId64"",
  281 + uri->get_url(), http_header.content_length - body_left, http_header.content_length);
  282 + }
  283 +
  284 + return ret;
  285 +}
  286 +
  287 +int SrsHttpClient::on_headers_complete(http_parser* parser)
  288 +{
  289 + SrsHttpClient* obj = (SrsHttpClient*)parser->data;
  290 + obj->complete_header(parser);
  291 +
  292 + // see http_parser.c:1570, return 1 to skip body.
  293 + return 1;
  294 +}
  295 +
  296 +void SrsHttpClient::complete_header(http_parser* parser)
  297 +{
  298 + // save the parser status when header parse completed.
  299 + memcpy(&http_header, parser, sizeof(http_header));
  300 +}
  301 +
  302 +SrsHttpHooks::SrsHttpHooks()
  303 +{
  304 +}
  305 +
  306 +SrsHttpHooks::~SrsHttpHooks()
  307 +{
  308 +}
  309 +
  310 +int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req)
  311 +{
  312 + int ret = ERROR_SUCCESS;
  313 +
  314 + SrsHttpUri uri;
  315 + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
  316 + srs_error("http uri parse on_connect url failed. "
  317 + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
  318 + return ret;
  319 + }
  320 +
  321 + /**
  322 + {
  323 + "action": "on_connect",
  324 + "client_id": 1985,
  325 + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
  326 + "pageUrl": "http://www.test.com/live.html"
  327 + }
  328 + */
  329 + std::stringstream ss;
  330 + ss << "{"
  331 + // action
  332 + << '"' << "action" << '"' << ':'
  333 + << '"' << "on_connect" << '"'
  334 + << ','
  335 + // client_id
  336 + << '"' << "client_id" << '"' << ':'
  337 + << std::dec << client_id
  338 + << ','
  339 + // ip
  340 + << '"' << "ip" << '"' << ':'
  341 + << '"' << ip << '"'
  342 + << ','
  343 + // vhost
  344 + << '"' << "vhost" << '"' << ':'
  345 + << '"' << req->vhost << '"'
  346 + << ','
  347 + // app
  348 + << '"' << "app" << '"' << ':'
  349 + << '"' << req->app << '"'
  350 + << ','
  351 + // pageUrl
  352 + << '"' << "pageUrl" << '"' << ':'
  353 + << '"' << req->pageUrl << '"'
  354 + //<< ','
  355 + << "}";
  356 + std::string data = ss.str();
  357 + std::string res;
  358 +
  359 + SrsHttpClient http;
  360 + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
  361 + srs_error("http post on_connect uri failed. "
  362 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  363 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  364 + return ret;
  365 + }
  366 +
  367 + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
  368 + ret = ERROR_HTTP_DATA_INVLIAD;
  369 + srs_error("http hook on_connect validate failed. "
  370 + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
  371 + return ret;
  372 + }
  373 +
  374 + srs_trace("http hook on_connect success. "
  375 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  376 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  377 +
  378 + return ret;
  379 +}
  380 +
  381 +void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req)
  382 +{
  383 + int ret = ERROR_SUCCESS;
  384 +
  385 + SrsHttpUri uri;
  386 + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
  387 + srs_warn("http uri parse on_close url failed, ignored. "
  388 + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
  389 + return;
  390 + }
  391 +
  392 + /**
  393 + {
  394 + "action": "on_close",
  395 + "client_id": 1985,
  396 + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
  397 + "stream": "livestream"
  398 + }
  399 + */
  400 + std::stringstream ss;
  401 + ss << "{"
  402 + // action
  403 + << '"' << "action" << '"' << ':'
  404 + << '"' << "on_close" << '"'
  405 + << ','
  406 + // client_id
  407 + << '"' << "client_id" << '"' << ':'
  408 + << std::dec << client_id
  409 + << ','
  410 + // ip
  411 + << '"' << "ip" << '"' << ':'
  412 + << '"' << ip << '"'
  413 + << ','
  414 + // vhost
  415 + << '"' << "vhost" << '"' << ':'
  416 + << '"' << req->vhost << '"'
  417 + << ','
  418 + // app
  419 + << '"' << "app" << '"' << ':'
  420 + << '"' << req->app << '"'
  421 + //<< ','
  422 + << "}";
  423 + std::string data = ss.str();
  424 + std::string res;
  425 +
  426 + SrsHttpClient http;
  427 + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
  428 + srs_warn("http post on_close uri failed, ignored. "
  429 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  430 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  431 + return;
  432 + }
  433 +
  434 + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
  435 + ret = ERROR_HTTP_DATA_INVLIAD;
  436 + srs_warn("http hook on_close validate failed, ignored. "
  437 + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
  438 + return;
  439 + }
  440 +
  441 + srs_trace("http hook on_close success. "
  442 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  443 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  444 +
  445 + return;
  446 +}
  447 +
  448 +int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req)
  449 +{
  450 + int ret = ERROR_SUCCESS;
  451 +
  452 + SrsHttpUri uri;
  453 + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
  454 + srs_error("http uri parse on_publish url failed. "
  455 + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
  456 + return ret;
  457 + }
  458 +
  459 + /**
  460 + {
  461 + "action": "on_publish",
  462 + "client_id": 1985,
  463 + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
  464 + "stream": "livestream"
  465 + }
  466 + */
  467 + std::stringstream ss;
  468 + ss << "{"
  469 + // action
  470 + << '"' << "action" << '"' << ':'
  471 + << '"' << "on_publish" << '"'
  472 + << ','
  473 + // client_id
  474 + << '"' << "client_id" << '"' << ':'
  475 + << std::dec << client_id
  476 + << ','
  477 + // ip
  478 + << '"' << "ip" << '"' << ':'
  479 + << '"' << ip << '"'
  480 + << ','
  481 + // vhost
  482 + << '"' << "vhost" << '"' << ':'
  483 + << '"' << req->vhost << '"'
  484 + << ','
  485 + // app
  486 + << '"' << "app" << '"' << ':'
  487 + << '"' << req->app << '"'
  488 + << ','
  489 + // stream
  490 + << '"' << "stream" << '"' << ':'
  491 + << '"' << req->stream << '"'
  492 + //<< ','
  493 + << "}";
  494 + std::string data = ss.str();
  495 + std::string res;
  496 +
  497 + SrsHttpClient http;
  498 + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
  499 + srs_error("http post on_publish uri failed. "
  500 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  501 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  502 + return ret;
  503 + }
  504 +
  505 + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
  506 + ret = ERROR_HTTP_DATA_INVLIAD;
  507 + srs_error("http hook on_publish validate failed. "
  508 + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
  509 + return ret;
  510 + }
  511 +
  512 + srs_trace("http hook on_publish success. "
  513 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  514 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  515 +
  516 + return ret;
  517 +}
  518 +
  519 +void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req)
  520 +{
  521 + int ret = ERROR_SUCCESS;
  522 +
  523 + SrsHttpUri uri;
  524 + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
  525 + srs_warn("http uri parse on_unpublish url failed, ignored. "
  526 + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
  527 + return;
  528 + }
  529 +
  530 + /**
  531 + {
  532 + "action": "on_unpublish",
  533 + "client_id": 1985,
  534 + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
  535 + "stream": "livestream"
  536 + }
  537 + */
  538 + std::stringstream ss;
  539 + ss << "{"
  540 + // action
  541 + << '"' << "action" << '"' << ':'
  542 + << '"' << "on_unpublish" << '"'
  543 + << ','
  544 + // client_id
  545 + << '"' << "client_id" << '"' << ':'
  546 + << std::dec << client_id
  547 + << ','
  548 + // ip
  549 + << '"' << "ip" << '"' << ':'
  550 + << '"' << ip << '"'
  551 + << ','
  552 + // vhost
  553 + << '"' << "vhost" << '"' << ':'
  554 + << '"' << req->vhost << '"'
  555 + << ','
  556 + // app
  557 + << '"' << "app" << '"' << ':'
  558 + << '"' << req->app << '"'
  559 + << ','
  560 + // stream
  561 + << '"' << "stream" << '"' << ':'
  562 + << '"' << req->stream << '"'
  563 + //<< ','
  564 + << "}";
  565 + std::string data = ss.str();
  566 + std::string res;
  567 +
  568 + SrsHttpClient http;
  569 + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
  570 + srs_warn("http post on_unpublish uri failed, ignored. "
  571 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  572 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  573 + return;
  574 + }
  575 +
  576 + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
  577 + ret = ERROR_HTTP_DATA_INVLIAD;
  578 + srs_warn("http hook on_unpublish validate failed, ignored. "
  579 + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
  580 + return;
  581 + }
  582 +
  583 + srs_trace("http hook on_unpublish success. "
  584 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  585 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  586 +
  587 + return;
  588 +}
  589 +
  590 +int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req)
  591 +{
  592 + int ret = ERROR_SUCCESS;
  593 +
  594 + SrsHttpUri uri;
  595 + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
  596 + srs_error("http uri parse on_play url failed. "
  597 + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
  598 + return ret;
  599 + }
  600 +
  601 + /**
  602 + {
  603 + "action": "on_play",
  604 + "client_id": 1985,
  605 + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
  606 + "stream": "livestream"
  607 + }
  608 + */
  609 + std::stringstream ss;
  610 + ss << "{"
  611 + // action
  612 + << '"' << "action" << '"' << ':'
  613 + << '"' << "on_play" << '"'
  614 + << ','
  615 + // client_id
  616 + << '"' << "client_id" << '"' << ':'
  617 + << std::dec << client_id
  618 + << ','
  619 + // ip
  620 + << '"' << "ip" << '"' << ':'
  621 + << '"' << ip << '"'
  622 + << ','
  623 + // vhost
  624 + << '"' << "vhost" << '"' << ':'
  625 + << '"' << req->vhost << '"'
  626 + << ','
  627 + // app
  628 + << '"' << "app" << '"' << ':'
  629 + << '"' << req->app << '"'
  630 + << ','
  631 + // stream
  632 + << '"' << "stream" << '"' << ':'
  633 + << '"' << req->stream << '"'
  634 + //<< ','
  635 + << "}";
  636 + std::string data = ss.str();
  637 + std::string res;
  638 +
  639 + SrsHttpClient http;
  640 + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
  641 + srs_error("http post on_play uri failed. "
  642 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  643 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  644 + return ret;
  645 + }
  646 +
  647 + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
  648 + ret = ERROR_HTTP_DATA_INVLIAD;
  649 + srs_error("http hook on_play validate failed. "
  650 + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
  651 + return ret;
  652 + }
  653 +
  654 + srs_trace("http hook on_play success. "
  655 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  656 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  657 +
  658 + return ret;
  659 +}
  660 +
  661 +void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req)
  662 +{
  663 + int ret = ERROR_SUCCESS;
  664 +
  665 + SrsHttpUri uri;
  666 + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
  667 + srs_warn("http uri parse on_stop url failed, ignored. "
  668 + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
  669 + return;
  670 + }
  671 +
  672 + /**
  673 + {
  674 + "action": "on_stop",
  675 + "client_id": 1985,
  676 + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
  677 + "stream": "livestream"
  678 + }
  679 + */
  680 + std::stringstream ss;
  681 + ss << "{"
  682 + // action
  683 + << '"' << "action" << '"' << ':'
  684 + << '"' << "on_stop" << '"'
  685 + << ','
  686 + // client_id
  687 + << '"' << "client_id" << '"' << ':'
  688 + << std::dec << client_id
  689 + << ','
  690 + // ip
  691 + << '"' << "ip" << '"' << ':'
  692 + << '"' << ip << '"'
  693 + << ','
  694 + // vhost
  695 + << '"' << "vhost" << '"' << ':'
  696 + << '"' << req->vhost << '"'
  697 + << ','
  698 + // app
  699 + << '"' << "app" << '"' << ':'
  700 + << '"' << req->app << '"'
  701 + << ','
  702 + // stream
  703 + << '"' << "stream" << '"' << ':'
  704 + << '"' << req->stream << '"'
  705 + //<< ','
  706 + << "}";
  707 + std::string data = ss.str();
  708 + std::string res;
  709 +
  710 + SrsHttpClient http;
  711 + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
  712 + srs_warn("http post on_stop uri failed, ignored. "
  713 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  714 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  715 + return;
  716 + }
  717 +
  718 + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
  719 + ret = ERROR_HTTP_DATA_INVLIAD;
  720 + srs_warn("http hook on_stop validate failed, ignored. "
  721 + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
  722 + return;
  723 + }
  724 +
  725 + srs_trace("http hook on_stop success. "
  726 + "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
  727 + client_id, url.c_str(), data.c_str(), res.c_str(), ret);
  728 +
  729 + return;
  730 +}
  731 +
  732 +#endif
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_APP_HTTP_HOOKS_HPP
  25 +#define SRS_APP_HTTP_HOOKS_HPP
  26 +
  27 +/*
  28 +#include <srs_app_http_hooks.hpp>
  29 +*/
  30 +#include <srs_core.hpp>
  31 +
  32 +#ifdef SRS_HTTP_CALLBACK
  33 +
  34 +#include <http_parser.h>
  35 +
  36 +class SrsHttpUri;
  37 +class SrsSocket;
  38 +class SrsRequest;
  39 +
  40 +#include <srs_app_st.hpp>
  41 +
  42 +/**
  43 +* http client to GET/POST/PUT/DELETE uri
  44 +*/
  45 +class SrsHttpClient
  46 +{
  47 +private:
  48 + bool connected;
  49 + st_netfd_t stfd;
  50 +private:
  51 + http_parser http_header;
  52 +public:
  53 + SrsHttpClient();
  54 + virtual ~SrsHttpClient();
  55 +public:
  56 + /**
  57 + * to post data to the uri.
  58 + * @param req the data post to uri.
  59 + * @param res the response data from server.
  60 + */
  61 + virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
  62 +private:
  63 + virtual void disconnect();
  64 + virtual int connect(SrsHttpUri* uri);
  65 +private:
  66 + virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response);
  67 + virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received);
  68 + virtual int parse_response_body(SrsHttpUri* uri, SrsSocket* skt, std::string* response, int body_received);
  69 + virtual int parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std::string* response, size_t body_left, const void* buf, size_t size);
  70 +private:
  71 + static int on_headers_complete(http_parser* parser);
  72 + virtual void complete_header(http_parser* parser);
  73 +};
  74 +
  75 +/**
  76 +* the http hooks, http callback api,
  77 +* for some event, such as on_connect, call
  78 +* a http api(hooks).
  79 +*/
  80 +class SrsHttpHooks
  81 +{
  82 +public:
  83 + SrsHttpHooks();
  84 + virtual ~SrsHttpHooks();
  85 +public:
  86 + /**
  87 + * on_connect hook, when client connect to srs.
  88 + * @param client_id the id of client on server.
  89 + * @param url the api server url, to valid the client.
  90 + * ignore if empty.
  91 + * @return valid failed or connect to the url failed.
  92 + */
  93 + virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req);
  94 + /**
  95 + * on_close hook, when client disconnect to srs, where client is valid by on_connect.
  96 + * @param client_id the id of client on server.
  97 + * @param url the api server url, to process the event.
  98 + * ignore if empty.
  99 + */
  100 + virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req);
  101 + /**
  102 + * on_publish hook, when client(encoder) start to publish stream
  103 + * @param client_id the id of client on server.
  104 + * @param url the api server url, to valid the client.
  105 + * ignore if empty.
  106 + * @return valid failed or connect to the url failed.
  107 + */
  108 + virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
  109 + /**
  110 + * on_unpublish hook, when client(encoder) stop publish stream.
  111 + * @param client_id the id of client on server.
  112 + * @param url the api server url, to process the event.
  113 + * ignore if empty.
  114 + */
  115 + virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);
  116 + /**
  117 + * on_play hook, when client start to play stream.
  118 + * @param client_id the id of client on server.
  119 + * @param url the api server url, to valid the client.
  120 + * ignore if empty.
  121 + * @return valid failed or connect to the url failed.
  122 + */
  123 + virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req);
  124 + /**
  125 + * on_stop hook, when client stop to play the stream.
  126 + * @param client_id the id of client on server.
  127 + * @param url the api server url, to process the event.
  128 + * ignore if empty.
  129 + */
  130 + virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
  131 +};
  132 +
  133 +#endif
  134 +
  135 +#endif
@@ -41,6 +41,7 @@ using namespace std; @@ -41,6 +41,7 @@ using namespace std;
41 #include <srs_app_http.hpp> 41 #include <srs_app_http.hpp>
42 #include <srs_app_bandwidth.hpp> 42 #include <srs_app_bandwidth.hpp>
43 #include <srs_app_socket.hpp> 43 #include <srs_app_socket.hpp>
  44 +#include <srs_app_http_hooks.hpp>
44 45
45 SrsRtmpConn::SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd) 46 SrsRtmpConn::SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd)
46 : SrsConnection(srs_server, client_stfd) 47 : SrsConnection(srs_server, client_stfd)
@@ -59,6 +59,8 @@ file @@ -59,6 +59,8 @@ file
59 ..\app\srs_app_http_api.cpp, 59 ..\app\srs_app_http_api.cpp,
60 ..\app\srs_app_http_conn.hpp, 60 ..\app\srs_app_http_conn.hpp,
61 ..\app\srs_app_http_conn.cpp, 61 ..\app\srs_app_http_conn.cpp,
  62 + ..\app\srs_app_http_hooks.hpp,
  63 + ..\app\srs_app_http_hooks.cpp,
62 ..\app\srs_app_log.hpp, 64 ..\app\srs_app_log.hpp,
63 ..\app\srs_app_log.cpp, 65 ..\app\srs_app_log.cpp,
64 ..\app\srs_app_refer.hpp, 66 ..\app\srs_app_refer.hpp,