From 88178234620a8413a0890ccee8232ae8a88df220 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 10 Jun 2014 11:34:35 +0800 Subject: [PATCH] add rtmp detecter --- trunk/research/librtmp/srs_detect_rtmp.c | 100 +++++++++++++++++++++-- trunk/research/librtmp/srs_play.c | 2 +- trunk/src/libs/srs_librtmp.cpp | 80 ++++++++++++++++-- trunk/src/libs/srs_librtmp.hpp | 15 +++- 4 files changed, 182 insertions(+), 15 deletions(-) diff --git a/trunk/research/librtmp/srs_detect_rtmp.c b/trunk/research/librtmp/srs_detect_rtmp.c index 853c2a797..c97b8d21e 100644 --- a/trunk/research/librtmp/srs_detect_rtmp.c +++ b/trunk/research/librtmp/srs_detect_rtmp.c @@ -33,35 +33,77 @@ int main(int argc, char** argv) { srs_rtmp_t rtmp; + // time + int64_t time_startup = srs_get_time_ms(); + int64_t time_dns_resolve = 0; + int64_t time_socket_connect = 0; + int64_t time_play_stream = 0; + int64_t time_first_packet = 0; + int64_t time_cleanup = 0; + // delay = actual - expect time when quit. + int delay = 0; + // packet data int type, size; u_int32_t timestamp = 0; char* data; - if (argc <= 1) { + // user options + const char* rtmp_url = NULL; + int duration = 0; + int timeout = 0; + + if (argc <= 3) { printf("detect stream on RTMP server\n" - "Usage: %s \n" + "Usage: %s \n" " rtmp_url RTMP stream url to play\n" + " duration how long to play, in seconds, stream time.\n" + " timeout how long to timeout, in seconds, system time.\n" "For example:\n" - " %s rtmp://127.0.0.1:1935/live/livestream\n", + " %s rtmp://127.0.0.1:1935/live/livestream 3 10\n", argv[0]); int ret = 1; exit(ret); return ret; } - rtmp = srs_rtmp_create(argv[1]); + rtmp_url = argv[1]; + duration = atoi(argv[2]); + timeout = atoi(argv[3]); printf("detect rtmp stream\n"); printf("srs(simple-rtmp-server) client librtmp library.\n"); printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); - printf("rtmp url: %s\n", rtmp); + printf("rtmp url: %s\n", rtmp_url); + printf("duration: %ds, timeout:%ds\n", duration, timeout); + + if (duration <= 0 || timeout <= 0) { + printf("duration and timeout must be positive.\n"); + exit(1); + return 1; + } + + rtmp = srs_rtmp_create(rtmp_url); + + if (__srs_dns_resolve(rtmp) != 0) { + printf("dns resolve failed.\n"); + goto rtmp_destroy; + } + printf("dns resolve success\n"); + time_dns_resolve = srs_get_time_ms(); + + if (__srs_connect_server(rtmp) != 0) { + printf("socket connect failed.\n"); + goto rtmp_destroy; + } + printf("socket connect success\n"); + time_socket_connect = srs_get_time_ms(); - if (srs_simple_handshake(rtmp) != 0) { - printf("simple handshake failed.\n"); + if (__srs_do_simple_handshake(rtmp) != 0) { + printf("do simple handshake failed.\n"); goto rtmp_destroy; } - printf("simple handshake success\n"); + printf("do simple handshake success\n"); if (srs_connect_app(rtmp) != 0) { printf("connect vhost/app failed.\n"); @@ -74,6 +116,7 @@ int main(int argc, char** argv) goto rtmp_destroy; } printf("play stream success\n"); + time_play_stream = srs_get_time_ms(); for (;;) { if (srs_read_packet(rtmp, &type, ×tamp, &data, &size) != 0) { @@ -81,11 +124,52 @@ int main(int argc, char** argv) } printf("got packet: type=%s, time=%d, size=%d\n", srs_type2string(type), timestamp, size); + if (time_first_packet <= 0) { + time_first_packet = srs_get_time_ms(); + } + free(data); + + if (srs_get_time_ms() - time_startup > timeout * 1000) { + printf("timeout, terminate.\n"); + goto rtmp_destroy; + } + + if (timestamp > duration * 1000) { + printf("duration exceed, terminate.\n"); + goto rtmp_destroy; + } } rtmp_destroy: srs_rtmp_destroy(rtmp); + time_cleanup = srs_get_time_ms(); + + // print result to stderr. + fprintf(stderr, "{" + "\"%s\":%d, " //#1 + "\"%s\":%d, " // #2 + "\"%s\":%d, " // #3 + "\"%s\":%d, " // #4 + "\"%s\":%d, " // #5 + "\"%s\":%d, " // #6 + "\"%s\":%d, " // #7 + "%s}", + // total = dns + tcp_connect + start_play + first_packet + last_packet + "total", (int)(time_cleanup - time_startup), //#1 + "dns", (int)(time_dns_resolve - time_startup), //#2 + "tcp_connect", (int)(time_socket_connect - time_dns_resolve), //#3 + "start_play", (int)(time_play_stream - time_socket_connect), //#4 + "first_packet", (int)(time_first_packet - time_play_stream), //#5 + "last_packet", (int)(time_cleanup - time_first_packet), //#6 + // expect = time_cleanup - time_first_packet + // actual = timestamp + // delay = actual - expect + "delay", (int)(timestamp - (time_cleanup - time_first_packet)), //#7 + // unit in ms. + "\"unit\": \"ms\"" + ); + printf("\n"); return 0; } diff --git a/trunk/research/librtmp/srs_play.c b/trunk/research/librtmp/srs_play.c index 9a22908dd..644794477 100644 --- a/trunk/research/librtmp/srs_play.c +++ b/trunk/research/librtmp/srs_play.c @@ -55,7 +55,7 @@ int main(int argc, char** argv) printf("suck rtmp stream like rtmpdump\n"); printf("srs(simple-rtmp-server) client librtmp library.\n"); printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); - printf("rtmp url: %s\n", rtmp); + printf("rtmp url: %s\n", argv[1]); if (srs_simple_handshake(rtmp) != 0) { printf("simple handshake failed.\n"); diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index 7acb5cae6..d362b54c0 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -57,6 +57,7 @@ struct Context std::string url; std::string tcUrl; std::string host; + std::string ip; std::string port; std::string vhost; std::string app; @@ -77,7 +78,7 @@ struct Context } }; -int srs_librtmp_context_connect(Context* context) +int srs_librtmp_context_parse_uri(Context* context) { int ret = ERROR_SUCCESS; @@ -123,6 +124,13 @@ int srs_librtmp_context_connect(Context* context) } } + return ret; +} + +int srs_librtmp_context_resolve_host(Context* context) +{ + int ret = ERROR_SUCCESS; + // create socket srs_freep(context->skt); context->skt = new SimpleSocketStream(); @@ -132,11 +140,24 @@ int srs_librtmp_context_connect(Context* context) } // connect to server:port - string server = srs_dns_resolve(context->host); - if (server.empty()) { + context->ip = srs_dns_resolve(context->host); + if (context->ip.empty()) { return -1; } - if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) { + + return ret; +} + +int srs_librtmp_context_connect(Context* context) +{ + int ret = ERROR_SUCCESS; + + srs_assert(context->skt); + + std::string ip = context->ip; + int port = ::atoi(context->port.c_str()); + + if ((ret = context->skt->connect(ip.c_str(), port)) != ERROR_SUCCESS) { return ret; } @@ -166,14 +187,63 @@ int srs_simple_handshake(srs_rtmp_t rtmp) { int ret = ERROR_SUCCESS; + if ((ret = __srs_dns_resolve(rtmp)) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = __srs_connect_server(rtmp)) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = __srs_do_simple_handshake(rtmp)) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + +int __srs_dns_resolve(srs_rtmp_t rtmp) +{ + int ret = ERROR_SUCCESS; + + srs_assert(rtmp != NULL); + Context* context = (Context*)rtmp; + + // parse uri + if ((ret = srs_librtmp_context_parse_uri(context)) != ERROR_SUCCESS) { + return ret; + } + // resolve host + if ((ret = srs_librtmp_context_resolve_host(context)) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + +int __srs_connect_server(srs_rtmp_t rtmp) +{ + int ret = ERROR_SUCCESS; + srs_assert(rtmp != NULL); Context* context = (Context*)rtmp; - // parse uri, resolve host, connect to server:port if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) { return ret; } + return ret; +} + +int __srs_do_simple_handshake(srs_rtmp_t rtmp) +{ + int ret = ERROR_SUCCESS; + + srs_assert(rtmp != NULL); + Context* context = (Context*)rtmp; + + srs_assert(context->skt != NULL); + // simple handshake srs_freep(context->rtmp); context->rtmp = new SrsRtmpClient(context->skt); diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index 2563a76c9..c104852eb 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -55,7 +55,7 @@ srs_rtmp_t srs_rtmp_create(const char* url); void srs_rtmp_destroy(srs_rtmp_t rtmp); /** -* handshake with server +* connect and handshake with server * category: publish/play * previous: rtmp-create * next: connect-app @@ -65,7 +65,20 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp); * simple handshake specifies in rtmp 1.0, * not depends on ssl. */ +/** +* srs_simple_handshake equals to invoke: +* __srs_dns_resolve() +* __srs_connect_server() +* __srs_do_simple_handshake() +* user can use these functions if needed. +*/ int srs_simple_handshake(srs_rtmp_t rtmp); +// parse uri, create socket, resolve host +int __srs_dns_resolve(srs_rtmp_t rtmp); +// connect socket to server +int __srs_connect_server(srs_rtmp_t rtmp); +// do simple handshake over socket. +int __srs_do_simple_handshake(srs_rtmp_t rtmp); /** * connect to rtmp vhost/app