diff --git a/trunk/configure b/trunk/configure index f11cd25e7..f479e1272 100755 --- a/trunk/configure +++ b/trunk/configure @@ -159,7 +159,7 @@ MODULE_DEPENDS=("CORE" "KERNEL") ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSSLRoot}) MODULE_FILES=("srs_rtmp_amf0" "srs_rtmp_io" "srs_rtmp_stack" "srs_rtmp_handshake" "srs_rtmp_utility" "srs_rtmp_msg_array" "srs_protocol_buffer" - "srs_raw_avc" "srs_rtsp_stack" "srs_http_stack" "srs_protocol_kbps") + "srs_raw_avc" "srs_rtsp_stack" "srs_http_stack" "srs_protocol_kbps" "srs_protocol_json") PROTOCOL_INCS="src/protocol"; MODULE_DIR=${PROTOCOL_INCS} . auto/modules.sh PROTOCOL_OBJS="${MODULE_OBJS[@]}" # @@ -172,7 +172,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder" "srs_app_http_stream" "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config" "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks" - "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" + "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_http_static" "srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds" "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call" diff --git a/trunk/ide/srs_upp/srs_upp.upp b/trunk/ide/srs_upp/srs_upp.upp index 68d0a115b..f3a43e124 100755 --- a/trunk/ide/srs_upp/srs_upp.upp +++ b/trunk/ide/srs_upp/srs_upp.upp @@ -58,6 +58,8 @@ file ../../src/protocol/srs_rtmp_amf0.cpp, ../../src/protocol/srs_protocol_buffer.hpp, ../../src/protocol/srs_protocol_buffer.cpp, + ../../src/protocol/srs_protocol_json.hpp, + ../../src/protocol/srs_protocol_json.cpp, ../../src/protocol/srs_rtmp_handshake.hpp, ../../src/protocol/srs_rtmp_handshake.cpp, ../../src/protocol/srs_rtmp_io.hpp, @@ -109,8 +111,6 @@ file ../../src/app/srs_app_http_static.cpp, ../../src/app/srs_app_ingest.hpp, ../../src/app/srs_app_ingest.cpp, - ../../src/app/srs_app_json.hpp, - ../../src/app/srs_app_json.cpp, ../../src/app/srs_app_listener.hpp, ../../src/app/srs_app_listener.cpp, ../../src/app/srs_app_log.hpp, diff --git a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj index bba0489a7..a9b9fd372 100644 --- a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj +++ b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 3C036B561B2D0AC10078E2E0 /* srs_app_http_stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C036B531B2D0AC10078E2E0 /* srs_app_http_stream.cpp */; }; 3C068D6A1B10149F00AA722C /* srs_protocol_kbps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C068D681B10149F00AA722C /* srs_protocol_kbps.cpp */; }; 3C068D6D1B10175500AA722C /* srs_protocol_buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C068D6B1B10175500AA722C /* srs_protocol_buffer.cpp */; }; + 3C0D422E1B87165900C2508B /* srs_protocol_json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C0D422C1B87165900C2508B /* srs_protocol_json.cpp */; }; 3C0E1B8D1B0F5ADF003ADEF7 /* srs_http_stack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C0E1B8B1B0F5ADF003ADEF7 /* srs_http_stack.cpp */; }; 3C1231F61AAE652D00CE8F6C /* srs_core_autofree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1231F01AAE652C00CE8F6C /* srs_core_autofree.cpp */; }; 3C1231F71AAE652D00CE8F6C /* srs_core_performance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1231F21AAE652C00CE8F6C /* srs_core_performance.cpp */; }; @@ -52,7 +53,6 @@ 3C1232A11AAE81D900CE8F6C /* srs_app_http_conn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232661AAE81D900CE8F6C /* srs_app_http_conn.cpp */; }; 3C1232A21AAE81D900CE8F6C /* srs_app_http_hooks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232681AAE81D900CE8F6C /* srs_app_http_hooks.cpp */; }; 3C1232A41AAE81D900CE8F6C /* srs_app_ingest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12326C1AAE81D900CE8F6C /* srs_app_ingest.cpp */; }; - 3C1232A51AAE81D900CE8F6C /* srs_app_json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C12326E1AAE81D900CE8F6C /* srs_app_json.cpp */; }; 3C1232A71AAE81D900CE8F6C /* srs_app_listener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232721AAE81D900CE8F6C /* srs_app_listener.cpp */; }; 3C1232A81AAE81D900CE8F6C /* srs_app_log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232741AAE81D900CE8F6C /* srs_app_log.cpp */; }; 3C1232A91AAE81D900CE8F6C /* srs_app_mpegts_udp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1232761AAE81D900CE8F6C /* srs_app_mpegts_udp.cpp */; }; @@ -131,6 +131,8 @@ 3C068D691B10149F00AA722C /* srs_protocol_kbps.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_protocol_kbps.hpp; path = ../../../src/protocol/srs_protocol_kbps.hpp; sourceTree = ""; }; 3C068D6B1B10175500AA722C /* srs_protocol_buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_protocol_buffer.cpp; path = ../../../src/protocol/srs_protocol_buffer.cpp; sourceTree = ""; }; 3C068D6C1B10175500AA722C /* srs_protocol_buffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_protocol_buffer.hpp; path = ../../../src/protocol/srs_protocol_buffer.hpp; sourceTree = ""; }; + 3C0D422C1B87165900C2508B /* srs_protocol_json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_protocol_json.cpp; path = ../../../src/protocol/srs_protocol_json.cpp; sourceTree = ""; }; + 3C0D422D1B87165900C2508B /* srs_protocol_json.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_protocol_json.hpp; path = ../../../src/protocol/srs_protocol_json.hpp; sourceTree = ""; }; 3C0E1B8B1B0F5ADF003ADEF7 /* srs_http_stack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_http_stack.cpp; path = ../../../src/protocol/srs_http_stack.cpp; sourceTree = ""; }; 3C0E1B8C1B0F5ADF003ADEF7 /* srs_http_stack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_http_stack.hpp; path = ../../../src/protocol/srs_http_stack.hpp; sourceTree = ""; }; 3C1231E51AAE64A400CE8F6C /* srs_xcode */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = srs_xcode; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -214,8 +216,6 @@ 3C1232691AAE81D900CE8F6C /* srs_app_http_hooks.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_http_hooks.hpp; path = ../../../src/app/srs_app_http_hooks.hpp; sourceTree = ""; }; 3C12326C1AAE81D900CE8F6C /* srs_app_ingest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_ingest.cpp; path = ../../../src/app/srs_app_ingest.cpp; sourceTree = ""; }; 3C12326D1AAE81D900CE8F6C /* srs_app_ingest.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_ingest.hpp; path = ../../../src/app/srs_app_ingest.hpp; sourceTree = ""; }; - 3C12326E1AAE81D900CE8F6C /* srs_app_json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_json.cpp; path = ../../../src/app/srs_app_json.cpp; sourceTree = ""; }; - 3C12326F1AAE81D900CE8F6C /* srs_app_json.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_json.hpp; path = ../../../src/app/srs_app_json.hpp; sourceTree = ""; }; 3C1232721AAE81D900CE8F6C /* srs_app_listener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_listener.cpp; path = ../../../src/app/srs_app_listener.cpp; sourceTree = ""; }; 3C1232731AAE81D900CE8F6C /* srs_app_listener.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = srs_app_listener.hpp; path = ../../../src/app/srs_app_listener.hpp; sourceTree = ""; }; 3C1232741AAE81D900CE8F6C /* srs_app_log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = srs_app_log.cpp; path = ../../../src/app/srs_app_log.cpp; sourceTree = ""; }; @@ -496,6 +496,8 @@ 3C0E1B8C1B0F5ADF003ADEF7 /* srs_http_stack.hpp */, 3C068D6B1B10175500AA722C /* srs_protocol_buffer.cpp */, 3C068D6C1B10175500AA722C /* srs_protocol_buffer.hpp */, + 3C0D422C1B87165900C2508B /* srs_protocol_json.cpp */, + 3C0D422D1B87165900C2508B /* srs_protocol_json.hpp */, 3C068D681B10149F00AA722C /* srs_protocol_kbps.cpp */, 3C068D691B10149F00AA722C /* srs_protocol_kbps.hpp */, 3C12322D1AAE81A400CE8F6C /* srs_raw_avc.cpp */, @@ -563,8 +565,6 @@ 3C036B541B2D0AC10078E2E0 /* srs_app_http_stream.hpp */, 3C12326C1AAE81D900CE8F6C /* srs_app_ingest.cpp */, 3C12326D1AAE81D900CE8F6C /* srs_app_ingest.hpp */, - 3C12326E1AAE81D900CE8F6C /* srs_app_json.cpp */, - 3C12326F1AAE81D900CE8F6C /* srs_app_json.hpp */, 3C1232721AAE81D900CE8F6C /* srs_app_listener.cpp */, 3C1232731AAE81D900CE8F6C /* srs_app_listener.hpp */, 3C1232741AAE81D900CE8F6C /* srs_app_log.cpp */, @@ -862,12 +862,12 @@ 3C689F961AB6AAAC00C9CEEE /* event.c in Sources */, 3C1232A81AAE81D900CE8F6C /* srs_app_log.cpp in Sources */, 3C1232A41AAE81D900CE8F6C /* srs_app_ingest.cpp in Sources */, + 3C0D422E1B87165900C2508B /* srs_protocol_json.cpp in Sources */, 3C1232B41AAE81D900CE8F6C /* srs_app_st.cpp in Sources */, 3C1232481AAE81A400CE8F6C /* srs_rtmp_stack.cpp in Sources */, 3C1232B01AAE81D900CE8F6C /* srs_app_security.cpp in Sources */, 3C12322B1AAE814D00CE8F6C /* srs_kernel_utility.cpp in Sources */, 3C12324A1AAE81A400CE8F6C /* srs_rtsp_stack.cpp in Sources */, - 3C1232A51AAE81D900CE8F6C /* srs_app_json.cpp in Sources */, 3C36DB5D1ABD1CB90066CCAF /* srs_librtmp.cpp in Sources */, 3C12329F1AAE81D900CE8F6C /* srs_app_http_api.cpp in Sources */, 3C1EE6AE1AB1055800576EE9 /* srs_app_hds.cpp in Sources */, diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index ad1330bb9..2f1e6ab58 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -40,7 +40,7 @@ using namespace std; #include #include #include -#include +#include #include // update the flv duration and filesize every this interval in ms. diff --git a/trunk/src/app/srs_app_heartbeat.cpp b/trunk/src/app/srs_app_heartbeat.cpp index 75a502b63..1d3e7fe48 100644 --- a/trunk/src/app/srs_app_heartbeat.cpp +++ b/trunk/src/app/srs_app_heartbeat.cpp @@ -32,7 +32,7 @@ using namespace std; #include #include #include -#include +#include #include #include #include diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index c80de04d2..2825713c7 100755 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -33,7 +33,7 @@ using namespace std; #include #include #include -#include +#include #include #include #include @@ -112,6 +112,7 @@ int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) << SRS_JFIELD_STR("requests", "the request itself, for http debug") << SRS_JFIELD_CONT << SRS_JFIELD_STR("vhosts", "dumps vhost to json") << SRS_JFIELD_CONT << SRS_JFIELD_STR("streams", "dumps streams to json") << SRS_JFIELD_CONT + << SRS_JFIELD_STR("clients", "dumps clients to json") << SRS_JFIELD_CONT << SRS_JFIELD_ORG("test", SRS_JOBJECT_START) << SRS_JFIELD_STR("requests", "show the request info") << SRS_JFIELD_CONT << SRS_JFIELD_STR("errors", "always return an error 100") << SRS_JFIELD_CONT @@ -442,17 +443,45 @@ SrsGoApiVhosts::~SrsGoApiVhosts() int SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) { - std::stringstream data; - SrsStatistic* stat = SrsStatistic::instance(); - int ret = stat->dumps_vhosts(data); + int ret = ERROR_SUCCESS; + SrsStatistic* stat = SrsStatistic::instance(); std::stringstream ss; - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("vhosts", data.str()) - << SRS_JOBJECT_END; + // path: {pattern}{vhost_id} + // e.g. /api/v1/vhosts/100 pattern= /api/v1/vhosts/, vhost_id=100 + int vid = r->parse_rest_id(entry->pattern); + SrsStatisticVhost* vhost = NULL; + + if (vid > 0 && (vhost = stat->find_vhost(vid)) == NULL) { + ret = ERROR_RTMP_STREAM_NOT_FOUND; + srs_error("vhost id=%d not found. ret=%d", vid, ret); + return srs_http_response_code(w, ret); + } + + if (r->is_http_get()) { + std::stringstream data; + + if (!vhost) { + ret = stat->dumps_vhosts(data); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("vhosts", data.str()) + << SRS_JOBJECT_END; + } else { + ret = vhost->dumps(data); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("vhost", data.str()) + << SRS_JOBJECT_END; + } + + return srs_http_response_json(w, ss.str()); + } return srs_http_response_json(w, ss.str()); } @@ -468,63 +497,114 @@ SrsGoApiStreams::~SrsGoApiStreams() int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) { int ret = ERROR_SUCCESS; + SrsStatistic* stat = SrsStatistic::instance(); std::stringstream ss; + + // path: {pattern}{stream_id} + // e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100 + int sid = r->parse_rest_id(entry->pattern); + + SrsStatisticStream* stream = NULL; + if (sid >= 0 && (stream = stat->find_stream(sid)) == NULL) { + ret = ERROR_RTMP_STREAM_NOT_FOUND; + srs_error("stream stream_id=%d not found. ret=%d", sid, ret); + return srs_http_response_code(w, ret); + } if (r->is_http_delete()) { - // path: {pattern}{stream_id} - // e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100 - string sid = r->path().substr((int)entry->pattern.length()); - if (sid.empty()) { - ret = ERROR_REQUEST_DATA; - srs_error("invalid param, stream_id=%s. ret=%d", sid.c_str(), ret); - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) - << SRS_JOBJECT_END; - - return srs_http_response_json(w, ss.str()); - } - - int stream_id = ::atoi(sid.c_str()); - SrsStatisticStream* stream = stat->find_stream(stream_id); - if (stream == NULL) { - ret = ERROR_RTMP_STREAM_NOT_FOUND; - srs_error("stream stream_id=%s not found. ret=%d", sid.c_str(), ret); - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) - << SRS_JOBJECT_END; - - return srs_http_response_json(w, ss.str()); - } - - SrsSource* source = SrsSource::fetch(stream->vhost->vhost, stream->app, stream->stream); - if (source) { - source->set_expired(); - srs_warn("disconnent stream=%d successfully. vhost=%s, app=%s, stream=%s.", - stream_id, stream->vhost->vhost.c_str(), stream->app.c_str(), stream->stream.c_str()); - } else { - ret = ERROR_SOURCE_NOT_FOUND; - } - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) - << SRS_JOBJECT_END; - - return srs_http_response_json(w, ss.str()); - } else { - std::stringstream data; - int ret = stat->dumps_streams(data); + srs_assert(stream); - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("streams", data.str()) - << SRS_JOBJECT_END; + SrsSource* source = SrsSource::fetch(stream->vhost->vhost, stream->app, stream->stream); + if (!source) { + ret = ERROR_SOURCE_NOT_FOUND; + srs_warn("source not found for sid=%d", sid); + return srs_http_response_code(w, ret); + } + + source->set_expired(); + srs_warn("disconnent stream=%d successfully. vhost=%s, app=%s, stream=%s.", + sid, stream->vhost->vhost.c_str(), stream->app.c_str(), stream->stream.c_str()); + return srs_http_response_code(w, ret); + } else if (r->is_http_get()) { + std::stringstream data; + + if (!stream) { + ret = stat->dumps_streams(data); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("streams", data.str()) + << SRS_JOBJECT_END; + } else { + ret = stream->dumps(data); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("stream", data.str()) + << SRS_JOBJECT_END; + } return srs_http_response_json(w, ss.str()); } + + return ret; +} + +SrsGoApiClients::SrsGoApiClients() +{ +} + +SrsGoApiClients::~SrsGoApiClients() +{ +} + +int SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) +{ + int ret = ERROR_SUCCESS; + + SrsStatistic* stat = SrsStatistic::instance(); + std::stringstream ss; + + // path: {pattern}{client_id} + // e.g. /api/v1/clients/100 pattern= /api/v1/clients/, client_id=100 + int cid = r->parse_rest_id(entry->pattern); + + SrsStatisticClient* client = NULL; + if (cid >= 0 && (client = stat->find_client(cid)) == NULL) { + ret = ERROR_RTMP_STREAM_NOT_FOUND; + srs_error("stream client_id=%d not found. ret=%d", cid, ret); + return srs_http_response_code(w, ret); + + } + + if (r->is_http_get()) { + std::stringstream data; + + if (!client) { + ret = stat->dumps_clients(data, 0, 10); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("clients", data.str()) + << SRS_JOBJECT_END; + } else { + ret = client->dumps(data); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("client", data.str()) + << SRS_JOBJECT_END; + } + + return srs_http_response_json(w, ss.str()); + } + + return ret; } SrsGoApiError::SrsGoApiError() @@ -537,15 +617,7 @@ SrsGoApiError::~SrsGoApiError() int SrsGoApiError::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) { - std::stringstream ss; - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(100) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("msg", "SRS demo error.") << SRS_JFIELD_CONT - << SRS_JFIELD_STR("path", r->path()) - << SRS_JOBJECT_END; - - return srs_http_response_json(w, ss.str()); + return srs_http_response_code(w, 100); } diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp index cdc5d0af0..8bb3124f2 100644 --- a/trunk/src/app/srs_app_http_api.hpp +++ b/trunk/src/app/srs_app_http_api.hpp @@ -159,6 +159,15 @@ public: virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); }; +class SrsGoApiClients : public ISrsHttpHandler +{ +public: + SrsGoApiClients(); + virtual ~SrsGoApiClients(); +public: + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); +}; + class SrsGoApiError : public ISrsHttpHandler { public: diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index d4637cc01..b74830eeb 100755 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -654,6 +654,7 @@ string SrsHttpMessage::uri() uri += host(); uri += path(); + return uri; } @@ -677,6 +678,21 @@ string SrsHttpMessage::ext() return _ext; } +int SrsHttpMessage::parse_rest_id(string pattern) +{ + string p = _uri->get_path(); + if (p.length() <= pattern.length()) { + return -1; + } + + string id = p.substr((int)pattern.length()); + if (!id.empty()) { + return ::atoi(id.c_str()); + } + + return -1; +} + int SrsHttpMessage::body_read_all(string& body) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp index 7bc06cd01..731a00b6f 100644 --- a/trunk/src/app/srs_app_http_conn.hpp +++ b/trunk/src/app/srs_app_http_conn.hpp @@ -246,6 +246,10 @@ public: virtual std::string host(); virtual std::string path(); virtual std::string ext(); + /** + * get the RESTful matched id. + */ + virtual int parse_rest_id(std::string pattern); public: /** * read body to string. diff --git a/trunk/src/app/srs_app_http_hooks.cpp b/trunk/src/app/srs_app_http_hooks.cpp index 426b3313f..3a361201d 100644 --- a/trunk/src/app/srs_app_http_hooks.cpp +++ b/trunk/src/app/srs_app_http_hooks.cpp @@ -31,7 +31,7 @@ using namespace std; #include #include #include -#include +#include #include #include #include diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index ace385252..afc82e965 100755 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -773,10 +773,10 @@ int SrsServer::http_handle() if ((ret = http_api_mux->handle("/", new SrsHttpNotFoundHandler())) != ERROR_SUCCESS) { return ret; } - if ((ret = http_api_mux->handle("/api", new SrsGoApiApi())) != ERROR_SUCCESS) { + if ((ret = http_api_mux->handle("/api/", new SrsGoApiApi())) != ERROR_SUCCESS) { return ret; } - if ((ret = http_api_mux->handle("/api/v1", new SrsGoApiV1())) != ERROR_SUCCESS) { + if ((ret = http_api_mux->handle("/api/v1/", new SrsGoApiV1())) != ERROR_SUCCESS) { return ret; } if ((ret = http_api_mux->handle("/api/v1/versions", new SrsGoApiVersion())) != ERROR_SUCCESS) { @@ -800,12 +800,15 @@ int SrsServer::http_handle() if ((ret = http_api_mux->handle("/api/v1/authors", new SrsGoApiAuthors())) != ERROR_SUCCESS) { return ret; } - if ((ret = http_api_mux->handle("/api/v1/vhosts", new SrsGoApiVhosts())) != ERROR_SUCCESS) { + if ((ret = http_api_mux->handle("/api/v1/vhosts/", new SrsGoApiVhosts())) != ERROR_SUCCESS) { return ret; } if ((ret = http_api_mux->handle("/api/v1/streams/", new SrsGoApiStreams())) != ERROR_SUCCESS) { return ret; } + if ((ret = http_api_mux->handle("/api/v1/clients/", new SrsGoApiClients())) != ERROR_SUCCESS) { + return ret; + } // test the request info. if ((ret = http_api_mux->handle("/api/v1/test/requests", new SrsGoApiRequests())) != ERROR_SUCCESS) { diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index ff971e8d7..0453c46d3 100755 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -28,7 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using namespace std; #include -#include +#include #include #include #include @@ -47,6 +47,8 @@ SrsStatisticVhost::SrsStatisticVhost() kbps = new SrsKbps(); kbps->set_io(NULL, NULL); + + nb_clients = 0; } SrsStatisticVhost::~SrsStatisticVhost() @@ -54,6 +56,33 @@ SrsStatisticVhost::~SrsStatisticVhost() srs_freep(kbps); } +int SrsStatisticVhost::dumps(stringstream& ss) +{ + int ret = ERROR_SUCCESS; + + // dumps the config of vhost. + bool hls_enabled = _srs_config->get_hls_enabled(vhost); + bool enabled = _srs_config->get_vhost_enabled(vhost); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ORG("id", id) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("name", vhost) << SRS_JFIELD_CONT + << SRS_JFIELD_BOOL("enabled", enabled) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("clients", nb_clients) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("send_bytes", kbps->get_send_bytes()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("recv_bytes", kbps->get_recv_bytes()) << SRS_JFIELD_CONT + << SRS_JFIELD_NAME("hls") << SRS_JOBJECT_START + << SRS_JFIELD_BOOL("enabled", hls_enabled); + if (hls_enabled) { + ss << SRS_JFIELD_CONT; + ss << SRS_JFIELD_ORG("fragment", _srs_config->get_hls_fragment(vhost)); + } + ss << SRS_JOBJECT_END + << SRS_JOBJECT_END; + + return ret; +} + SrsStatisticStream::SrsStatisticStream() { id = srs_generate_id(); @@ -73,6 +102,8 @@ SrsStatisticStream::SrsStatisticStream() kbps = new SrsKbps(); kbps->set_io(NULL, NULL); + + nb_clients = 0; } SrsStatisticStream::~SrsStatisticStream() @@ -80,6 +111,48 @@ SrsStatisticStream::~SrsStatisticStream() srs_freep(kbps); } +int SrsStatisticStream::dumps(stringstream& ss) +{ + int ret = ERROR_SUCCESS; + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ORG("id", id) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("name", stream) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("vhost", vhost->id) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("app", app) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("clients", nb_clients) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("send_bytes", kbps->get_send_bytes()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("recv_bytes", kbps->get_recv_bytes()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("live_ms", srs_get_system_time_ms()) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("status", status) << SRS_JFIELD_CONT; + + if (!has_video) { + ss << SRS_JFIELD_NULL("video") << SRS_JFIELD_CONT; + } else { + ss << SRS_JFIELD_NAME("video") << SRS_JOBJECT_START + << SRS_JFIELD_STR("codec", srs_codec_video2str(vcodec)) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("profile", srs_codec_avc_profile2str(avc_profile)) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("level", srs_codec_avc_level2str(avc_level)) + << SRS_JOBJECT_END + << SRS_JFIELD_CONT; + } + + if (!has_audio) { + ss << SRS_JFIELD_NULL("audio"); + } else { + ss << SRS_JFIELD_NAME("audio") << SRS_JOBJECT_START + << SRS_JFIELD_STR("codec", srs_codec_audio2str(acodec)) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("sample_rate", (int)flv_sample_rates[asample_rate]) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("channel", (int)asound_type + 1) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("profile", srs_codec_aac_object2str(aac_object)) + << SRS_JOBJECT_END; + } + + ss << SRS_JOBJECT_END; + + return ret; +} + void SrsStatisticStream::publish() { status = STATISTIC_STREAM_STATUS_PUBLISHING; @@ -92,6 +165,26 @@ void SrsStatisticStream::close() status = STATISTIC_STREAM_STATUS_IDLING; } +SrsStatisticClient::SrsStatisticClient() +{ + id = 0; +} + +SrsStatisticClient::~SrsStatisticClient() +{ +} + +int SrsStatisticClient::dumps(stringstream& ss) +{ + int ret = ERROR_SUCCESS; + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ORG("id", id) + << SRS_JOBJECT_END; + + return ret; +} + SrsStatistic* SrsStatistic::_instance = new SrsStatistic(); SrsStatistic::SrsStatistic() @@ -107,14 +200,14 @@ SrsStatistic::~SrsStatistic() srs_freep(kbps); if (true) { - std::map::iterator it; + std::map::iterator it; for (it = vhosts.begin(); it != vhosts.end(); it++) { SrsStatisticVhost* vhost = it->second; srs_freep(vhost); } } if (true) { - std::map::iterator it; + std::map::iterator it; for (it = streams.begin(); it != streams.end(); it++) { SrsStatisticStream* stream = it->second; srs_freep(stream); @@ -127,6 +220,11 @@ SrsStatistic::~SrsStatistic() srs_freep(client); } } + + vhosts.clear(); + rvhosts.clear(); + streams.clear(); + rstreams.clear(); } SrsStatistic* SrsStatistic::instance() @@ -134,16 +232,29 @@ SrsStatistic* SrsStatistic::instance() return _instance; } -SrsStatisticStream* SrsStatistic::find_stream(int stream_id) +SrsStatisticVhost* SrsStatistic::find_vhost(int vid) +{ + std::map::iterator it; + if ((it = vhosts.find(vid)) != vhosts.end()) { + return it->second; + } + return NULL; +} + +SrsStatisticStream* SrsStatistic::find_stream(int sid) +{ + std::map::iterator it; + if ((it = streams.find(sid)) != streams.end()) { + return it->second; + } + return NULL; +} + +SrsStatisticClient* SrsStatistic::find_client(int cid) { std::map::iterator it; - for (it = clients.begin(); it != clients.end(); it++) { - SrsStatisticClient* client = it->second; - SrsStatisticStream* stream = client->stream; - - if (stream_id == stream->id) { - return stream; - } + if ((it = clients.find(cid)) != clients.end()) { + return it->second; } return NULL; } @@ -215,6 +326,10 @@ int SrsStatistic::on_client(int id, SrsRequest* req) } else { client = clients[id]; } + + // got client. + stream->nb_clients++; + vhost->nb_clients++; return ret; } @@ -222,12 +337,19 @@ int SrsStatistic::on_client(int id, SrsRequest* req) void SrsStatistic::on_disconnect(int id) { std::map::iterator it; - it = clients.find(id); - if (it != clients.end()) { - SrsStatisticClient* client = it->second; - srs_freep(client); - clients.erase(it); + if ((it = clients.find(id)) == clients.end()) { + return; } + + SrsStatisticClient* client = it->second; + SrsStatisticStream* stream = client->stream; + SrsStatisticVhost* vhost = stream->vhost; + + srs_freep(client); + clients.erase(it); + + stream->nb_clients--; + vhost->nb_clients--; } void SrsStatistic::kbps_add_delta(SrsConnection* conn) @@ -256,14 +378,14 @@ SrsKbps* SrsStatistic::kbps_sample() { kbps->sample(); if (true) { - std::map::iterator it; + std::map::iterator it; for (it = vhosts.begin(); it != vhosts.end(); it++) { SrsStatisticVhost* vhost = it->second; vhost->kbps->sample(); } } if (true) { - std::map::iterator it; + std::map::iterator it; for (it = streams.begin(); it != streams.end(); it++) { SrsStatisticStream* stream = it->second; stream->kbps->sample(); @@ -283,29 +405,17 @@ int SrsStatistic::dumps_vhosts(stringstream& ss) int ret = ERROR_SUCCESS; ss << SRS_JARRAY_START; - std::map::iterator it; + std::map::iterator it; for (it = vhosts.begin(); it != vhosts.end(); it++) { SrsStatisticVhost* vhost = it->second; + if (it != vhosts.begin()) { ss << SRS_JFIELD_CONT; } - // dumps the config of vhost. - bool hls_enabled = _srs_config->get_hls_enabled(vhost->vhost); - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ORG("id", vhost->id) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("name", vhost->vhost) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("send_bytes", vhost->kbps->get_send_bytes()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("recv_bytes", vhost->kbps->get_recv_bytes()) << SRS_JFIELD_CONT - << SRS_JFIELD_NAME("hls") << SRS_JOBJECT_START - << SRS_JFIELD_BOOL("enabled", hls_enabled); - if (hls_enabled) { - ss << SRS_JFIELD_CONT; - ss << SRS_JFIELD_ORG("fragment", _srs_config->get_hls_fragment(vhost->vhost)); + if ((ret = vhost->dumps(ss)) != ERROR_SUCCESS) { + return ret; } - ss << SRS_JOBJECT_END - << SRS_JOBJECT_END; } ss << SRS_JARRAY_END; @@ -317,77 +427,64 @@ int SrsStatistic::dumps_streams(stringstream& ss) int ret = ERROR_SUCCESS; ss << SRS_JARRAY_START; - std::map::iterator it; + std::map::iterator it; for (it = streams.begin(); it != streams.end(); it++) { SrsStatisticStream* stream = it->second; + if (it != streams.begin()) { ss << SRS_JFIELD_CONT; } - int client_num = 0; - std::map::iterator it_client; - for (it_client = clients.begin(); it_client != clients.end(); it_client++) { - SrsStatisticClient* client = it_client->second; - if (client->stream == stream) { - client_num++; - } + if ((ret = stream->dumps(ss)) != ERROR_SUCCESS) { + return ret; } - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ORG("id", stream->id) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("name", stream->stream) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("vhost", stream->vhost->id) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("app", stream->app) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("clients", client_num) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("send_bytes", stream->kbps->get_send_bytes()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("recv_bytes", stream->kbps->get_recv_bytes()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("live_ms", srs_get_system_time_ms()) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("status", stream->status) << SRS_JFIELD_CONT; - - if (!stream->has_video) { - ss << SRS_JFIELD_NULL("video") << SRS_JFIELD_CONT; - } else { - ss << SRS_JFIELD_NAME("video") - << SRS_JOBJECT_START - << SRS_JFIELD_STR("codec", srs_codec_video2str(stream->vcodec)) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("profile", srs_codec_avc_profile2str(stream->avc_profile)) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("level", srs_codec_avc_level2str(stream->avc_level)) - << SRS_JOBJECT_END - << SRS_JFIELD_CONT; - } - - if (!stream->has_audio) { - ss << SRS_JFIELD_NULL("audio"); - } else { - ss << SRS_JFIELD_NAME("audio") - << SRS_JOBJECT_START - << SRS_JFIELD_STR("codec", srs_codec_audio2str(stream->acodec)) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("sample_rate", (int)flv_sample_rates[stream->asample_rate]) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("channel", (int)stream->asound_type + 1) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("profile", srs_codec_aac_object2str(stream->aac_object)) - << SRS_JOBJECT_END; - } - - ss << SRS_JOBJECT_END; } ss << SRS_JARRAY_END; return ret; } +int SrsStatistic::dumps_clients(stringstream& ss, int start, int count) +{ + int ret = ERROR_SUCCESS; + + ss << SRS_JARRAY_START; + std::map::iterator it = clients.begin(); + for (int i = 0; i < count && it != clients.end(); it++) { + if (i < start) { + continue; + } + + SrsStatisticClient* client = it->second; + + if (i != start) { + ss << SRS_JFIELD_CONT; + } + + if ((ret = client->dumps(ss)) != ERROR_SUCCESS) { + return ret; + } + } + ss << SRS_JARRAY_END; + + + return ret; +} + SrsStatisticVhost* SrsStatistic::create_vhost(SrsRequest* req) { SrsStatisticVhost* vhost = NULL; // create vhost if not exists. - if (vhosts.find(req->vhost) == vhosts.end()) { + if (rvhosts.find(req->vhost) == rvhosts.end()) { vhost = new SrsStatisticVhost(); vhost->vhost = req->vhost; - vhosts[req->vhost] = vhost; + rvhosts[req->vhost] = vhost; + vhosts[vhost->id] = vhost; return vhost; } - vhost = vhosts[req->vhost]; + vhost = rvhosts[req->vhost]; return vhost; } @@ -399,17 +496,18 @@ SrsStatisticStream* SrsStatistic::create_stream(SrsStatisticVhost* vhost, SrsReq SrsStatisticStream* stream = NULL; // create stream if not exists. - if (streams.find(url) == streams.end()) { + if (rstreams.find(url) == rstreams.end()) { stream = new SrsStatisticStream(); stream->vhost = vhost; stream->stream = req->stream; stream->app = req->app; stream->url = url; - streams[url] = stream; + rstreams[url] = stream; + streams[stream->id] = stream; return stream; } - stream = streams[url]; + stream = rstreams[url]; return stream; } diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index fb56d04f8..9a8483245 100755 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -47,6 +47,7 @@ struct SrsStatisticVhost public: int64_t id; std::string vhost; + int nb_clients; public: /** * vhost total kbps. @@ -55,6 +56,8 @@ public: public: SrsStatisticVhost(); virtual ~SrsStatisticVhost(); +public: + virtual int dumps(std::stringstream& ss); }; struct SrsStatisticStream @@ -66,6 +69,7 @@ public: std::string stream; std::string url; std::string status; + int nb_clients; public: /** * stream total kbps. @@ -93,6 +97,8 @@ public: public: SrsStatisticStream(); virtual ~SrsStatisticStream(); +public: + virtual int dumps(std::stringstream& ss); public: /** * publish the stream. @@ -109,6 +115,11 @@ struct SrsStatisticClient public: SrsStatisticStream* stream; int id; +public: + SrsStatisticClient(); + virtual ~SrsStatisticClient(); +public: + virtual int dumps(std::stringstream& ss); }; class SrsStatistic @@ -117,10 +128,19 @@ private: static SrsStatistic *_instance; // the id to identify the sever. int64_t _server_id; - // key: vhost name, value: vhost object. - std::map vhosts; - // key: stream url, value: stream object. - std::map streams; +private: + // key: vhost id, value: vhost object. + std::map vhosts; + // key: vhost url, value: vhost Object. + // @remark a fast index for vhosts. + std::map rvhosts; +private: + // key: stream id, value: stream Object. + std::map streams; + // key: stream url, value: stream Object. + // @remark a fast index for streams. + std::map rstreams; +private: // key: client id, value: stream object. std::map clients; // server total kbps. @@ -131,7 +151,10 @@ private: public: static SrsStatistic* instance(); public: - virtual SrsStatisticStream* find_stream(int stream_id); + virtual SrsStatisticVhost* find_vhost(int vid); + virtual SrsStatisticStream* find_stream(int sid); + virtual SrsStatisticClient* find_client(int cid); +public: /** * when got video info for stream. */ @@ -192,6 +215,12 @@ public: * dumps the streams to sstream in json. */ virtual int dumps_streams(std::stringstream& ss); + /** + * dumps the clients to sstream in json. + * @param start the start index, from 0. + * @param count the max count of clients to dump. + */ + virtual int dumps_clients(std::stringstream& ss, int start, int count); private: virtual SrsStatisticVhost* create_vhost(SrsRequest* req); virtual SrsStatisticStream* create_stream(SrsStatisticVhost* vhost, SrsRequest* req); diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index c1698321c..2d95d3dee 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -43,7 +43,7 @@ using namespace std; #include #include #include -#include +#include #include // the longest time to wait for a process to quit. diff --git a/trunk/src/protocol/srs_http_stack.cpp b/trunk/src/protocol/srs_http_stack.cpp index 172dfbf45..75c55e5e3 100755 --- a/trunk/src/protocol/srs_http_stack.cpp +++ b/trunk/src/protocol/srs_http_stack.cpp @@ -32,6 +32,7 @@ using namespace std; #include #include #include +#include #define SRS_HTTP_DEFAULT_PAGE "index.html" @@ -143,6 +144,17 @@ int srs_http_response_json(ISrsHttpResponseWriter* w, string data) return w->write((char*)data.data(), (int)data.length()); } +int srs_http_response_code(ISrsHttpResponseWriter* w, int code) +{ + std::stringstream ss; + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(code) + << SRS_JOBJECT_END; + + return srs_http_response_json(w, ss.str()); +} + SrsHttpHeader::SrsHttpHeader() { } diff --git a/trunk/src/protocol/srs_http_stack.hpp b/trunk/src/protocol/srs_http_stack.hpp index bf12477ac..2888ce186 100644 --- a/trunk/src/protocol/srs_http_stack.hpp +++ b/trunk/src/protocol/srs_http_stack.hpp @@ -78,6 +78,11 @@ class ISrsHttpResponseWriter; // helper function: response in json format. extern int srs_http_response_json(ISrsHttpResponseWriter* w, std::string data); +/** + * response a typical code object, for example: + * {code : 100} + */ +extern int srs_http_response_code(ISrsHttpResponseWriter* w, int code); // get the status text of code. extern std::string srs_generate_http_status_text(int status); @@ -488,6 +493,14 @@ public: virtual std::string host() = 0; virtual std::string path() = 0; virtual std::string ext() = 0; + /** + * get the RESTful id, + * for example, pattern is /api/v1/streams, path is /api/v1/streams/100, + * then the rest id is 100. + * @param pattern the handler pattern which will serve the request. + * @return the REST id; -1 if not matched. + */ + virtual int parse_rest_id(std::string pattern) = 0; public: /** * read body to string. diff --git a/trunk/src/app/srs_app_json.cpp b/trunk/src/protocol/srs_protocol_json.cpp similarity index 99% rename from trunk/src/app/srs_app_json.cpp rename to trunk/src/protocol/srs_protocol_json.cpp index 5afda5abf..d6e1b1185 100644 --- a/trunk/src/app/srs_app_json.cpp +++ b/trunk/src/protocol/srs_protocol_json.cpp @@ -21,7 +21,7 @@ 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 +#include using namespace std; diff --git a/trunk/src/app/srs_app_json.hpp b/trunk/src/protocol/srs_protocol_json.hpp similarity index 98% rename from trunk/src/app/srs_app_json.hpp rename to trunk/src/protocol/srs_protocol_json.hpp index 2e555bcd4..3f5e1e1de 100644 --- a/trunk/src/app/srs_app_json.hpp +++ b/trunk/src/protocol/srs_protocol_json.hpp @@ -21,11 +21,11 @@ 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. */ -#ifndef SRS_APP_JSON_HPP -#define SRS_APP_JSON_HPP +#ifndef SRS_PROTOCOL_JSON_HPP +#define SRS_PROTOCOL_JSON_HPP /* -#include +#include */ #include