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 = &ll;

    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>");
    }
}