mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 11:51:57 +00:00
Merge branch '2.0release' into develop
This commit is contained in:
commit
0a4d78383c
18 changed files with 434 additions and 178 deletions
4
trunk/configure
vendored
4
trunk/configure
vendored
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
|
@ -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 */,
|
||||
|
|
|
@ -40,7 +40,7 @@ using namespace std;
|
|||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_rtmp_amf0.hpp>
|
||||
#include <srs_kernel_stream.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
|
||||
// update the flv duration and filesize every this interval in ms.
|
||||
|
|
|
@ -32,7 +32,7 @@ using namespace std;
|
|||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_http_client.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_app_http_conn.hpp>
|
||||
|
|
|
@ -33,7 +33,7 @@ using namespace std;
|
|||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -31,7 +31,7 @@ using namespace std;
|
|||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_rtmp_stack.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
#include <srs_app_dvr.hpp>
|
||||
#include <srs_app_http_client.hpp>
|
||||
#include <srs_core_autofree.hpp>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -28,7 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
using namespace std;
|
||||
|
||||
#include <srs_rtmp_stack.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
#include <srs_protocol_kbps.hpp>
|
||||
#include <srs_app_conn.hpp>
|
||||
#include <srs_app_config.hpp>
|
||||
|
@ -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<std::string, SrsStatisticVhost*>::iterator it;
|
||||
std::map<int64_t, SrsStatisticVhost*>::iterator it;
|
||||
for (it = vhosts.begin(); it != vhosts.end(); it++) {
|
||||
SrsStatisticVhost* vhost = it->second;
|
||||
srs_freep(vhost);
|
||||
}
|
||||
}
|
||||
if (true) {
|
||||
std::map<std::string, SrsStatisticStream*>::iterator it;
|
||||
std::map<int64_t, SrsStatisticStream*>::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<int64_t, SrsStatisticVhost*>::iterator it;
|
||||
if ((it = vhosts.find(vid)) != vhosts.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SrsStatisticStream* SrsStatistic::find_stream(int sid)
|
||||
{
|
||||
std::map<int64_t, SrsStatisticStream*>::iterator it;
|
||||
if ((it = streams.find(sid)) != streams.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SrsStatisticClient* SrsStatistic::find_client(int cid)
|
||||
{
|
||||
std::map<int, SrsStatisticClient*>::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<int, SrsStatisticClient*>::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<std::string, SrsStatisticVhost*>::iterator it;
|
||||
std::map<int64_t, SrsStatisticVhost*>::iterator it;
|
||||
for (it = vhosts.begin(); it != vhosts.end(); it++) {
|
||||
SrsStatisticVhost* vhost = it->second;
|
||||
vhost->kbps->sample();
|
||||
}
|
||||
}
|
||||
if (true) {
|
||||
std::map<std::string, SrsStatisticStream*>::iterator it;
|
||||
std::map<int64_t, SrsStatisticStream*>::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<std::string, SrsStatisticVhost*>::iterator it;
|
||||
std::map<int64_t, SrsStatisticVhost*>::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<std::string, SrsStatisticStream*>::iterator it;
|
||||
std::map<int64_t, SrsStatisticStream*>::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<int, SrsStatisticClient*>::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<int, SrsStatisticClient*>::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;
|
||||
}
|
||||
|
|
|
@ -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<std::string, SrsStatisticVhost*> vhosts;
|
||||
// key: stream url, value: stream object.
|
||||
std::map<std::string, SrsStatisticStream*> streams;
|
||||
private:
|
||||
// key: vhost id, value: vhost object.
|
||||
std::map<int64_t, SrsStatisticVhost*> vhosts;
|
||||
// key: vhost url, value: vhost Object.
|
||||
// @remark a fast index for vhosts.
|
||||
std::map<std::string, SrsStatisticVhost*> rvhosts;
|
||||
private:
|
||||
// key: stream id, value: stream Object.
|
||||
std::map<int64_t, SrsStatisticStream*> streams;
|
||||
// key: stream url, value: stream Object.
|
||||
// @remark a fast index for streams.
|
||||
std::map<std::string, SrsStatisticStream*> rstreams;
|
||||
private:
|
||||
// key: client id, value: stream object.
|
||||
std::map<int, SrsStatisticClient*> 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);
|
||||
|
|
|
@ -43,7 +43,7 @@ using namespace std;
|
|||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_protocol_kbps.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
#include <srs_kernel_stream.hpp>
|
||||
|
||||
// the longest time to wait for a process to quit.
|
||||
|
|
|
@ -32,6 +32,7 @@ using namespace std;
|
|||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
|
||||
#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()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 <srs_app_json.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -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 <srs_app_json.hpp>
|
||||
#include <srs_protocol_json.hpp>
|
||||
*/
|
||||
#include <srs_core.hpp>
|
||||
|
Loading…
Reference in a new issue