static void ngx_rtmp_stat_bw(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_bandwidth_t *bw, char *name, ngx_uint_t flags) { u_char buf[NGX_INT64_LEN + 9]; ngx_rtmp_update_bandwidth(bw, 0); if (flags & NGX_RTMP_STAT_BW) { NGX_RTMP_STAT_L("<bw_"); NGX_RTMP_STAT_CS(name); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), ">%uL</bw_", bw->bandwidth * 8) - buf); NGX_RTMP_STAT_CS(name); NGX_RTMP_STAT_L(">\r\n"); } if (flags & NGX_RTMP_STAT_BYTES) { NGX_RTMP_STAT_L("<bytes_"); NGX_RTMP_STAT_CS(name); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), ">%uL</bytes_", bw->bytes) - buf); NGX_RTMP_STAT_CS(name); NGX_RTMP_STAT_L(">\r\n"); } }
static void ngx_rtmp_stat_bw(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_bandwidth_t *bw_in, ngx_rtmp_bandwidth_t *bw_out) { u_char buf[NGX_OFF_T_LEN + 1]; ngx_rtmp_update_bandwidth(bw_in, 0); ngx_rtmp_update_bandwidth(bw_out, 0); NGX_RTMP_STAT_L("<in>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%uz", bw_in->bytes) - buf); NGX_RTMP_STAT_L("</in>\r\n"); NGX_RTMP_STAT_L("<out>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%uz", bw_out->bytes) - buf); NGX_RTMP_STAT_L("</out>\r\n"); NGX_RTMP_STAT_L("<bwin>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%uz", bw_in->bandwidth * 8) - buf); NGX_RTMP_STAT_L("</bwin>\r\n"); NGX_RTMP_STAT_L("<bwout>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%uz", bw_out->bandwidth * 8) - buf); NGX_RTMP_STAT_L("</bwout>\r\n"); }
static void ngx_rtmp_stat_dump_pool(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_pool_t *pool) { ngx_uint_t nlarge, size; u_char buf[NGX_INT_T_LEN]; size = 0; nlarge = 0; ngx_rtmp_stat_get_pool_size(pool, &nlarge, &size); NGX_RTMP_STAT_L("<pool><nlarge>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", nlarge) - buf); NGX_RTMP_STAT_L("</nlarge><size>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", size) - buf); NGX_RTMP_STAT_L("</size></pool>\r\n"); }
static void ngx_rtmp_stat_client(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_session_t *s) { u_char buf[NGX_INT_T_LEN]; #ifdef NGX_RTMP_POOL_DEBUG ngx_rtmp_stat_dump_pool(r, lll, s->connection->pool); #endif NGX_RTMP_STAT_L("<id>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", (ngx_uint_t) s->connection->number) - buf); NGX_RTMP_STAT_L("</id>"); NGX_RTMP_STAT_L("<address>"); NGX_RTMP_STAT_ES(&s->connection->addr_text); NGX_RTMP_STAT_L("</address>"); NGX_RTMP_STAT_L("<time>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%i", (ngx_int_t) (ngx_current_msec - s->epoch)) - buf); NGX_RTMP_STAT_L("</time>"); if (s->flashver.len) { NGX_RTMP_STAT_L("<flashver>"); NGX_RTMP_STAT_ES(&s->flashver); NGX_RTMP_STAT_L("</flashver>"); } if (s->page_url.len) { NGX_RTMP_STAT_L("<pageurl>"); NGX_RTMP_STAT_ES(&s->page_url); NGX_RTMP_STAT_L("</pageurl>"); } if (s->swf_url.len) { NGX_RTMP_STAT_L("<swfurl>"); NGX_RTMP_STAT_ES(&s->swf_url); NGX_RTMP_STAT_L("</swfurl>"); } }
static ngx_int_t ngx_rtmp_stat_handler(ngx_http_request_t *r) { ngx_rtmp_stat_loc_conf_t *slcf; ngx_rtmp_core_main_conf_t *cmcf; ngx_rtmp_core_srv_conf_t **cscf; ngx_chain_t *cl, *l, **ll, ***lll; size_t n; off_t len; static u_char tbuf[NGX_TIME_T_LEN + 1]; static u_char nbuf[NGX_OFF_T_LEN + 1]; slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); if (slcf->stat == 0) { return NGX_DECLINED; } cmcf = ngx_rtmp_core_main_conf; if (cmcf == NULL) { goto error; } cl = NULL; ll = &cl; lll = ≪ NGX_RTMP_STAT_L("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"); if (slcf->stylesheet.len) { NGX_RTMP_STAT_L("<?xml-stylesheet type=\"text/xsl\" href=\""); NGX_RTMP_STAT_ES(&slcf->stylesheet); NGX_RTMP_STAT_L("\" ?>\r\n"); } NGX_RTMP_STAT_L("<rtmp>\r\n"); #ifdef NGINX_VERSION NGX_RTMP_STAT_L("<version>" NGINX_VERSION "</version>\r\n"); #endif #ifdef NGX_COMPILER NGX_RTMP_STAT_L("<compiler>" NGX_COMPILER "</compiler>\r\n"); #endif NGX_RTMP_STAT_L("<built>" __DATE__ " " __TIME__ "</built>\r\n"); NGX_RTMP_STAT_L("<pid>"); NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf), "%ui", (ngx_uint_t) ngx_getpid()) - nbuf); NGX_RTMP_STAT_L("</pid>\r\n"); NGX_RTMP_STAT_L("<uptime>"); NGX_RTMP_STAT(tbuf, ngx_snprintf(tbuf, sizeof(tbuf), "%T", ngx_cached_time->sec - start_time) - tbuf); NGX_RTMP_STAT_L("</uptime>\r\n"); NGX_RTMP_STAT_L("<naccepted>"); NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf), "%ui", ngx_rtmp_naccepted) - nbuf); NGX_RTMP_STAT_L("</naccepted>\r\n"); ngx_rtmp_stat_bw(r, lll, &ngx_rtmp_bw_in, &ngx_rtmp_bw_out); cscf = cmcf->servers.elts; for (n = 0; n < cmcf->servers.nelts; ++n, ++cscf) { ngx_rtmp_stat_server(r, lll, *cscf); } NGX_RTMP_STAT_L("</rtmp>\r\n"); len = 0; for (l = cl; l; l = l->next) { len += (l->buf->last - l->buf->pos); } ngx_str_set(&r->headers_out.content_type, "text/xml"); r->headers_out.content_length_n = len; r->headers_out.status = NGX_HTTP_OK; ngx_http_send_header(r); (*ll)->buf->last_buf = 1; return ngx_http_output_filter(r, cl); error: r->headers_out.status = NGX_HTTP_INTERNAL_SERVER_ERROR; r->headers_out.content_length_n = 0; return ngx_http_send_header(r); }
static void ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_live_app_conf_t *lacf) { ngx_rtmp_live_stream_t *stream; ngx_rtmp_codec_ctx_t *codec; ngx_rtmp_live_ctx_t *ctx; ngx_rtmp_session_t *s; ngx_int_t n; size_t nclients, total_nclients; u_char buf[NGX_OFF_T_LEN + 1]; ngx_rtmp_stat_loc_conf_t *slcf; u_char *cname; slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); NGX_RTMP_STAT_L("<live>\r\n"); total_nclients = 0; for (n = 0; n < lacf->nbuckets; ++n) { for (stream = lacf->streams[n]; stream; stream = stream->next) { NGX_RTMP_STAT_L("<stream>\r\n"); NGX_RTMP_STAT_L("<name>"); NGX_RTMP_STAT_ECS(stream->name); NGX_RTMP_STAT_L("</name>\r\n"); NGX_RTMP_STAT_L("<time>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%M", ngx_current_msec - stream->epoch) - buf); NGX_RTMP_STAT_L("</time>"); ngx_rtmp_stat_bw(r, lll, &stream->bw_in, &stream->bw_out); nclients = 0; codec = NULL; for (ctx = stream->ctx; ctx; ctx = ctx->next, ++nclients) { s = ctx->session; if (slcf->stat & NGX_RTMP_STAT_CLIENTS) { NGX_RTMP_STAT_L("<client>"); #ifdef NGX_RTMP_POOL_DEBUG ngx_rtmp_stat_dump_pool(r, lll, s->connection->pool); #endif NGX_RTMP_STAT_L("<id>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", (ngx_uint_t) s->connection->number) - buf); NGX_RTMP_STAT_L("</id>"); NGX_RTMP_STAT_L("<address>"); NGX_RTMP_STAT_S(&s->connection->addr_text); NGX_RTMP_STAT_L("</address>"); NGX_RTMP_STAT_L("<time>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%M", ngx_current_msec - s->epoch) - buf); NGX_RTMP_STAT_L("</time>"); NGX_RTMP_STAT_L("<dropped>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%uD/%uD", ctx->cs[1].dropped, ctx->cs[0].dropped) - buf); NGX_RTMP_STAT_L("</dropped>"); NGX_RTMP_STAT_L("<avsync>"); if (!lacf->interleave) { NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%L", (int64_t) ctx->cs[1].timestamp - (int64_t) ctx->cs[0].timestamp) - buf); } NGX_RTMP_STAT_L("</avsync>"); if (s->flashver.len) { NGX_RTMP_STAT_L("<flashver>"); NGX_RTMP_STAT_ES(&s->flashver); NGX_RTMP_STAT_L("</flashver>"); } if (s->page_url.len) { NGX_RTMP_STAT_L("<pageurl>"); NGX_RTMP_STAT_ES(&s->page_url); NGX_RTMP_STAT_L("</pageurl>"); } if (s->swf_url.len) { NGX_RTMP_STAT_L("<swfurl>"); NGX_RTMP_STAT_ES(&s->swf_url); NGX_RTMP_STAT_L("</swfurl>"); } if (ctx->publishing) { NGX_RTMP_STAT_L("<publishing/>"); } if (ctx->active) { NGX_RTMP_STAT_L("<active/>"); } NGX_RTMP_STAT_L("</client>\r\n"); } if (ctx->publishing) { codec = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); } } total_nclients += nclients; if (codec) { NGX_RTMP_STAT_L("<meta><width>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", codec->width) - buf); NGX_RTMP_STAT_L("</width><height>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", codec->height) - buf); NGX_RTMP_STAT_L("</height><framerate>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", codec->frame_rate) - buf); NGX_RTMP_STAT_L("</framerate>"); cname = ngx_rtmp_get_video_codec_name(codec->video_codec_id); if (*cname) { NGX_RTMP_STAT_L("<video>"); NGX_RTMP_STAT_ECS(cname); NGX_RTMP_STAT_L("</video>"); } cname = ngx_rtmp_get_audio_codec_name(codec->audio_codec_id); if (*cname) { NGX_RTMP_STAT_L("<audio>"); NGX_RTMP_STAT_ECS(cname); NGX_RTMP_STAT_L("</audio>"); } if (*codec->profile) { NGX_RTMP_STAT_L("<profile>"); NGX_RTMP_STAT_ECS(codec->profile); NGX_RTMP_STAT_L("</profile>"); } if (*codec->level) { NGX_RTMP_STAT_L("<level>"); NGX_RTMP_STAT_ECS(codec->level); NGX_RTMP_STAT_L("</level>"); } NGX_RTMP_STAT_L("</meta>\r\n"); } NGX_RTMP_STAT_L("<nclients>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%uz", nclients) - buf); NGX_RTMP_STAT_L("</nclients>\r\n"); if (stream->publishing) { NGX_RTMP_STAT_L("<publishing/>\r\n"); } if (stream->active) { NGX_RTMP_STAT_L("<active/>\r\n"); } NGX_RTMP_STAT_L("</stream>\r\n"); } } NGX_RTMP_STAT_L("<nclients>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%uz", total_nclients) - buf); NGX_RTMP_STAT_L("</nclients>\r\n"); NGX_RTMP_STAT_L("</live>\r\n"); }
static void ngx_rtmp_stat_play(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_play_app_conf_t *pacf) { ngx_rtmp_play_ctx_t *ctx, *sctx; ngx_rtmp_session_t *s; ngx_uint_t n, nclients, total_nclients; u_char buf[NGX_INT_T_LEN]; ngx_rtmp_stat_loc_conf_t *slcf; if (pacf->entries.nelts == 0) { return; } slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); NGX_RTMP_STAT_L("<play>\r\n"); total_nclients = 0; for (n = 0; n < pacf->nbuckets; ++n) { for (ctx = pacf->ctx[n]; ctx; ) { NGX_RTMP_STAT_L("<stream>\r\n"); NGX_RTMP_STAT_L("<name>"); NGX_RTMP_STAT_ECS(ctx->name); NGX_RTMP_STAT_L("</name>\r\n"); nclients = 0; sctx = ctx; for (; ctx; ctx = ctx->next) { if (ngx_strcmp(ctx->name, sctx->name)) { break; } nclients++; s = ctx->session; if (slcf->stat & NGX_RTMP_STAT_CLIENTS) { NGX_RTMP_STAT_L("<client>"); ngx_rtmp_stat_client(r, lll, s); NGX_RTMP_STAT_L("</client>\r\n"); } } total_nclients += nclients; NGX_RTMP_STAT_L("<active/>"); NGX_RTMP_STAT_L("<nclients>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", nclients) - buf); NGX_RTMP_STAT_L("</nclients>\r\n"); NGX_RTMP_STAT_L("</stream>\r\n"); } } NGX_RTMP_STAT_L("<nclients>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", total_nclients) - buf); NGX_RTMP_STAT_L("</nclients>\r\n"); NGX_RTMP_STAT_L("</play>\r\n"); }
static void ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_live_app_conf_t *lacf) { ngx_rtmp_live_stream_t *stream; ngx_rtmp_codec_ctx_t *codec; ngx_rtmp_live_ctx_t *ctx; ngx_rtmp_session_t *s; ngx_int_t n; ngx_uint_t nclients, total_nclients; u_char buf[NGX_INT_T_LEN]; u_char bbuf[NGX_INT32_LEN]; ngx_rtmp_stat_loc_conf_t *slcf; u_char *cname; if (!lacf->live) { return; } slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); NGX_RTMP_STAT_L("<live>\r\n"); total_nclients = 0; for (n = 0; n < lacf->nbuckets; ++n) { for (stream = lacf->streams[n]; stream; stream = stream->next) { NGX_RTMP_STAT_L("<stream>\r\n"); NGX_RTMP_STAT_L("<name>"); NGX_RTMP_STAT_ECS(stream->name); NGX_RTMP_STAT_L("</name>\r\n"); NGX_RTMP_STAT_L("<time>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%i", (ngx_int_t) (ngx_current_msec - stream->epoch)) - buf); NGX_RTMP_STAT_L("</time>"); ngx_rtmp_stat_bw(r, lll, &stream->bw_in, &stream->bw_out); nclients = 0; codec = NULL; for (ctx = stream->ctx; ctx; ctx = ctx->next, ++nclients) { s = ctx->session; if (slcf->stat & NGX_RTMP_STAT_CLIENTS) { NGX_RTMP_STAT_L("<client>"); ngx_rtmp_stat_client(r, lll, s); NGX_RTMP_STAT_L("<dropped>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", ctx->ndropped) - buf); NGX_RTMP_STAT_L("</dropped>"); NGX_RTMP_STAT_L("<avsync>"); if (!lacf->interleave) { NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf), "%D", ctx->cs[1].timestamp - ctx->cs[0].timestamp) - bbuf); } NGX_RTMP_STAT_L("</avsync>"); if (ctx->publishing) { NGX_RTMP_STAT_L("<publishing/>"); } if (ctx->active) { NGX_RTMP_STAT_L("<active/>"); } NGX_RTMP_STAT_L("</client>\r\n"); } if (ctx->publishing) { codec = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); } } total_nclients += nclients; if (codec) { NGX_RTMP_STAT_L("<meta><width>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", codec->width) - buf); NGX_RTMP_STAT_L("</width><height>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", codec->height) - buf); NGX_RTMP_STAT_L("</height><framerate>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", codec->frame_rate) - buf); NGX_RTMP_STAT_L("</framerate>"); cname = ngx_rtmp_get_video_codec_name(codec->video_codec_id); if (*cname) { NGX_RTMP_STAT_L("<video>"); NGX_RTMP_STAT_ECS(cname); NGX_RTMP_STAT_L("</video>"); } cname = ngx_rtmp_get_audio_codec_name(codec->audio_codec_id); if (*cname) { NGX_RTMP_STAT_L("<audio>"); NGX_RTMP_STAT_ECS(cname); NGX_RTMP_STAT_L("</audio>"); } if (*codec->profile) { NGX_RTMP_STAT_L("<profile>"); NGX_RTMP_STAT_ECS(codec->profile); NGX_RTMP_STAT_L("</profile>"); } if (*codec->level) { NGX_RTMP_STAT_L("<level>"); NGX_RTMP_STAT_ECS(codec->level); NGX_RTMP_STAT_L("</level>"); } NGX_RTMP_STAT_L("</meta>\r\n"); } NGX_RTMP_STAT_L("<nclients>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", nclients) - buf); NGX_RTMP_STAT_L("</nclients>\r\n"); if (stream->publishing) { NGX_RTMP_STAT_L("<publishing/>\r\n"); } if (stream->active) { NGX_RTMP_STAT_L("<active/>\r\n"); } NGX_RTMP_STAT_L("</stream>\r\n"); } } NGX_RTMP_STAT_L("<nclients>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", total_nclients) - buf); NGX_RTMP_STAT_L("</nclients>\r\n"); NGX_RTMP_STAT_L("</live>\r\n"); }
static void ngx_rtmp_stat_client(ngx_http_request_t *r, ngx_chain_t ***lll, ngx_rtmp_session_t *s) { u_char buf[NGX_INT_T_LEN]; struct sockaddr_in *tmp; struct sockaddr_in sa; socklen_t len = sizeof(struct sockaddr); #ifdef NGX_RTMP_POOL_DEBUG ngx_rtmp_stat_dump_pool(r, lll, s->connection->pool); #endif NGX_RTMP_STAT_L("<id>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", (ngx_uint_t) s->connection->number) - buf); NGX_RTMP_STAT_L("</id>"); NGX_RTMP_STAT_L("<address>"); NGX_RTMP_STAT_ES(&s->connection->addr_text); NGX_RTMP_STAT_L("</address>"); /* ** Displays socket port number */ NGX_RTMP_STAT_L("<port>"); if (s->connection->listening) { tmp = (struct sockaddr_in *) s->connection->listening->sockaddr; NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", (ngx_uint_t) ntohs(tmp->sin_port)) - buf); } else if (getsockname(s->connection->fd, (struct sockaddr *) &sa, &len) != -1) { NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", (ngx_uint_t) ntohs(sa.sin_port)) - buf); } NGX_RTMP_STAT_L("</port>"); NGX_RTMP_STAT_L("<time>"); NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%i", (ngx_int_t) (ngx_current_msec - s->epoch)) - buf); NGX_RTMP_STAT_L("</time>"); if (s->flashver.len) { NGX_RTMP_STAT_L("<flashver>"); NGX_RTMP_STAT_ES(&s->flashver); NGX_RTMP_STAT_L("</flashver>"); } if (s->page_url.len) { NGX_RTMP_STAT_L("<pageurl>"); NGX_RTMP_STAT_ES(&s->page_url); NGX_RTMP_STAT_L("</pageurl>"); } if (s->swf_url.len) { NGX_RTMP_STAT_L("<swfurl>"); NGX_RTMP_STAT_ES(&s->swf_url); NGX_RTMP_STAT_L("</swfurl>"); } }