mirror of
https://github.com/arut/nginx-rtmp-module.git
synced 2025-08-06 15:00:18 +08:00
Merge branch 'master' into new-live3
This commit is contained in:
30
README.md
30
README.md
@ -2,19 +2,26 @@
|
|||||||
## nginx-rtmp-module
|
## nginx-rtmp-module
|
||||||
|
|
||||||
|
|
||||||
### Project blog:
|
### Project blog
|
||||||
|
|
||||||
http://rarut.wordpress.com
|
http://rarut.wordpress.com
|
||||||
|
|
||||||
### Wiki manual:
|
### Wiki manual
|
||||||
|
|
||||||
https://github.com/arut/nginx-rtmp-module/wiki/Directives
|
https://github.com/arut/nginx-rtmp-module/wiki/Directives
|
||||||
|
|
||||||
### Features:
|
### Google group
|
||||||
|
|
||||||
|
https://groups.google.com/group/nginx-rtmp
|
||||||
|
|
||||||
|
https://groups.google.com/group/nginx-rtmp-ru (Russian)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
* Live streaming of video/audio
|
* Live streaming of video/audio
|
||||||
|
|
||||||
* Video on demand FLV/MP4
|
* Video on demand FLV/MP4,
|
||||||
|
playing from local filesystem or HTTP
|
||||||
|
|
||||||
* Stream relay support for distributed
|
* Stream relay support for distributed
|
||||||
streaming: push & pull models
|
streaming: push & pull models
|
||||||
@ -29,10 +36,12 @@
|
|||||||
requires recent libavformat
|
requires recent libavformat
|
||||||
(>= 53.31.100) from ffmpeg (ffmpeg.org)
|
(>= 53.31.100) from ffmpeg (ffmpeg.org)
|
||||||
|
|
||||||
* HTTP callbacks (publish/play/record etc)
|
* HTTP callbacks (publish/play/record/update etc)
|
||||||
|
|
||||||
* Running external programs on certain events (exec)
|
* Running external programs on certain events (exec)
|
||||||
|
|
||||||
|
* HTTP control module for recording audio/video and dropping clients
|
||||||
|
|
||||||
* Advanced buffering techniques
|
* Advanced buffering techniques
|
||||||
to keep memory allocations at a minimum
|
to keep memory allocations at a minimum
|
||||||
level for faster streaming and low
|
level for faster streaming and low
|
||||||
@ -49,7 +58,7 @@
|
|||||||
* Linux/FreeBSD/MacOS
|
* Linux/FreeBSD/MacOS
|
||||||
|
|
||||||
|
|
||||||
### Build:
|
### Build
|
||||||
|
|
||||||
cd to NGINX source directory & run this:
|
cd to NGINX source directory & run this:
|
||||||
|
|
||||||
@ -57,8 +66,11 @@ cd to NGINX source directory & run this:
|
|||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
See this article about building nginx-rtmp with HLS support:
|
||||||
|
https://github.com/arut/nginx-rtmp-module/wiki/Building-nginx-rtmp-with-HLS-support
|
||||||
|
|
||||||
### RTMP URL format:
|
|
||||||
|
### RTMP URL format
|
||||||
|
|
||||||
rtmp://rtmp.example.com/app[/name]
|
rtmp://rtmp.example.com/app[/name]
|
||||||
|
|
||||||
@ -77,7 +89,7 @@ to nginx workers. This option is toggled with
|
|||||||
rtmp_auto_push directive.
|
rtmp_auto_push directive.
|
||||||
|
|
||||||
|
|
||||||
### Example nginx.conf:
|
### Example nginx.conf
|
||||||
|
|
||||||
rtmp {
|
rtmp {
|
||||||
|
|
||||||
@ -262,8 +274,8 @@ rtmp_auto_push directive.
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### Multi-worker streaming example
|
||||||
|
|
||||||
# Multi-worker streaming
|
|
||||||
rtmp_auto_push on;
|
rtmp_auto_push on;
|
||||||
|
|
||||||
rtmp {
|
rtmp {
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
static ngx_rtmp_publish_pt next_publish;
|
static ngx_rtmp_publish_pt next_publish;
|
||||||
static ngx_rtmp_play_pt next_play;
|
static ngx_rtmp_play_pt next_play;
|
||||||
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
static ngx_rtmp_close_stream_pt next_close_stream;
|
||||||
static ngx_rtmp_record_done_pt next_record_done;
|
static ngx_rtmp_record_done_pt next_record_done;
|
||||||
|
|
||||||
|
|
||||||
@ -402,7 +402,7 @@ next:
|
|||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_enotify_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t
|
ngx_rtmp_enotify_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t
|
||||||
*v)
|
*v)
|
||||||
{
|
{
|
||||||
ngx_rtmp_enotify_ctx_t *ctx;
|
ngx_rtmp_enotify_ctx_t *ctx;
|
||||||
@ -450,7 +450,7 @@ ngx_rtmp_enotify_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t
|
|||||||
ctx->flags = 0;
|
ctx->flags = 0;
|
||||||
|
|
||||||
next:
|
next:
|
||||||
return next_delete_stream(s, v);
|
return next_close_stream(s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -567,8 +567,8 @@ ngx_rtmp_enotify_postconfiguration(ngx_conf_t *cf)
|
|||||||
next_play = ngx_rtmp_play;
|
next_play = ngx_rtmp_play;
|
||||||
ngx_rtmp_play = ngx_rtmp_enotify_play;
|
ngx_rtmp_play = ngx_rtmp_enotify_play;
|
||||||
|
|
||||||
next_delete_stream = ngx_rtmp_delete_stream;
|
next_close_stream = ngx_rtmp_close_stream;
|
||||||
ngx_rtmp_delete_stream = ngx_rtmp_enotify_delete_stream;
|
ngx_rtmp_close_stream = ngx_rtmp_enotify_close_stream;
|
||||||
|
|
||||||
next_record_done = ngx_rtmp_record_done;
|
next_record_done = ngx_rtmp_record_done;
|
||||||
ngx_rtmp_record_done = ngx_rtmp_enotify_record_done;
|
ngx_rtmp_record_done = ngx_rtmp_enotify_record_done;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static ngx_rtmp_publish_pt next_publish;
|
static ngx_rtmp_publish_pt next_publish;
|
||||||
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
static ngx_rtmp_close_stream_pt next_close_stream;
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t ngx_rtmp_exec_postconfiguration(ngx_conf_t *cf);
|
static ngx_int_t ngx_rtmp_exec_postconfiguration(ngx_conf_t *cf);
|
||||||
@ -431,7 +431,7 @@ ngx_rtmp_exec_run(ngx_rtmp_session_t *s, size_t n)
|
|||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_exec_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t *v)
|
ngx_rtmp_exec_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
|
||||||
{
|
{
|
||||||
ngx_rtmp_exec_app_conf_t *eacf;
|
ngx_rtmp_exec_app_conf_t *eacf;
|
||||||
ngx_rtmp_exec_ctx_t *ctx;
|
ngx_rtmp_exec_ctx_t *ctx;
|
||||||
@ -457,7 +457,7 @@ ngx_rtmp_exec_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t *v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
return next_delete_stream(s, v);
|
return next_close_stream(s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -599,8 +599,8 @@ ngx_rtmp_exec_postconfiguration(ngx_conf_t *cf)
|
|||||||
next_publish = ngx_rtmp_publish;
|
next_publish = ngx_rtmp_publish;
|
||||||
ngx_rtmp_publish = ngx_rtmp_exec_publish;
|
ngx_rtmp_publish = ngx_rtmp_exec_publish;
|
||||||
|
|
||||||
next_delete_stream = ngx_rtmp_delete_stream;
|
next_close_stream = ngx_rtmp_close_stream;
|
||||||
ngx_rtmp_delete_stream = ngx_rtmp_exec_delete_stream;
|
ngx_rtmp_close_stream = ngx_rtmp_exec_close_stream;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
@ -880,7 +880,7 @@ ngx_rtmp_mp4_parse_stsc(ngx_rtmp_session_t *s, u_char *pos, u_char *last)
|
|||||||
|
|
||||||
t->chunks = (ngx_rtmp_mp4_chunks_t *) pos;
|
t->chunks = (ngx_rtmp_mp4_chunks_t *) pos;
|
||||||
|
|
||||||
if (pos + sizeof(*t->chunks) + ngx_rtmp_r32(t->times->entry_count) *
|
if (pos + sizeof(*t->chunks) + ngx_rtmp_r32(t->chunks->entry_count) *
|
||||||
sizeof(t->chunks->entries[0])
|
sizeof(t->chunks->entries[0])
|
||||||
<= last)
|
<= last)
|
||||||
{
|
{
|
||||||
|
@ -55,14 +55,14 @@ static ngx_command_t ngx_rtmp_netcall_commands[] = {
|
|||||||
{ ngx_string("netcall_timeout"),
|
{ ngx_string("netcall_timeout"),
|
||||||
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_msec_slot,
|
ngx_conf_set_msec_slot,
|
||||||
NGX_RTMP_SRV_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_netcall_app_conf_t, timeout),
|
offsetof(ngx_rtmp_netcall_app_conf_t, timeout),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("netcall_buffer"),
|
{ ngx_string("netcall_buffer"),
|
||||||
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_size_slot,
|
ngx_conf_set_size_slot,
|
||||||
NGX_RTMP_SRV_CONF_OFFSET,
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
offsetof(ngx_rtmp_netcall_app_conf_t, bufsize),
|
offsetof(ngx_rtmp_netcall_app_conf_t, bufsize),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
@ -491,58 +491,76 @@ ngx_rtmp_netcall_send(ngx_event_t *wev)
|
|||||||
|
|
||||||
|
|
||||||
ngx_chain_t *
|
ngx_chain_t *
|
||||||
ngx_rtmp_netcall_http_format_header(ngx_int_t method, ngx_str_t *uri,
|
ngx_rtmp_netcall_http_format_request(ngx_int_t method, ngx_str_t *host,
|
||||||
ngx_str_t *host, ngx_pool_t *pool,
|
ngx_str_t *uri, ngx_chain_t *args,
|
||||||
size_t content_length,
|
ngx_chain_t *body, ngx_pool_t *pool,
|
||||||
ngx_str_t *content_type)
|
ngx_str_t *content_type)
|
||||||
{
|
{
|
||||||
ngx_chain_t *cl;
|
ngx_chain_t *al, *bl, *ret;
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
const char *method_s;
|
size_t content_length;
|
||||||
|
static const char *methods[2] = { "GET", "POST" };
|
||||||
static char rq_tmpl[] =
|
static const char rq_tmpl[] = " HTTP/1.0\r\n"
|
||||||
"%s %V HTTP/1.0\r\n"
|
|
||||||
"Host: %V\r\n"
|
"Host: %V\r\n"
|
||||||
"Content-Type: %V\r\n"
|
"Content-Type: %V\r\n"
|
||||||
"Connection: Close\r\n"
|
"Connection: Close\r\n"
|
||||||
"Content-Length: %uz\r\n"
|
"Content-Length: %uz\r\n"
|
||||||
"\r\n"
|
"\r\n";
|
||||||
;
|
|
||||||
|
|
||||||
cl = ngx_alloc_chain_link(pool);
|
content_length = 0;
|
||||||
if (cl == NULL) {
|
for (al = body; al; al = al->next) {
|
||||||
|
b = al->buf;
|
||||||
|
content_length += (b->last - b->pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create first buffer */
|
||||||
|
|
||||||
|
al = ngx_alloc_chain_link(pool);
|
||||||
|
if (al == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = ngx_create_temp_buf(pool, sizeof(rq_tmpl)
|
b = ngx_create_temp_buf(pool, sizeof("POST") + /* longest method + 1 */
|
||||||
+ sizeof("POST") - 1 /* longest method */
|
uri->len);
|
||||||
+ uri->len
|
|
||||||
+ host->len
|
|
||||||
+ content_type->len
|
|
||||||
+ 5);
|
|
||||||
|
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cl->buf = b;
|
b->last = ngx_snprintf(b->last, b->end - b->last, "%s %V",
|
||||||
cl->next = NULL;
|
methods[method], uri);
|
||||||
|
|
||||||
switch (method) {
|
al->buf = b;
|
||||||
case NGX_RTMP_NETCALL_HTTP_GET:
|
|
||||||
method_s = "GET";
|
ret = al;
|
||||||
break;
|
|
||||||
case NGX_RTMP_NETCALL_HTTP_POST:
|
if (args) {
|
||||||
method_s = "POST";
|
*b->last++ = '?';
|
||||||
break;
|
al->next = args;
|
||||||
default:
|
for (al = args; al->next; al = al->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create second buffer */
|
||||||
|
|
||||||
|
bl = ngx_alloc_chain_link(pool);
|
||||||
|
if (bl == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
b->last = ngx_snprintf(b->last, b->end - b->last, rq_tmpl,
|
b = ngx_create_temp_buf(pool, sizeof(rq_tmpl) + host->len +
|
||||||
method_s, uri, host, content_type, content_length);
|
content_type->len + NGX_OFF_T_LEN);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return cl;
|
bl->buf = b;
|
||||||
|
|
||||||
|
b->last = ngx_snprintf(b->last, b->end - b->last, rq_tmpl,
|
||||||
|
host, content_type, content_length);
|
||||||
|
|
||||||
|
al->next = bl;
|
||||||
|
bl->next = body;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -551,6 +569,9 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
|
|||||||
{
|
{
|
||||||
ngx_chain_t *cl;
|
ngx_chain_t *cl;
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
|
ngx_str_t *addr_text;
|
||||||
|
|
||||||
|
addr_text = &s->connection->addr_text;
|
||||||
|
|
||||||
cl = ngx_alloc_chain_link(pool);
|
cl = ngx_alloc_chain_link(pool);
|
||||||
if (cl == NULL) {
|
if (cl == NULL) {
|
||||||
@ -562,7 +583,8 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
|
|||||||
sizeof("&flashver=") - 1 + s->flashver.len * 3 +
|
sizeof("&flashver=") - 1 + s->flashver.len * 3 +
|
||||||
sizeof("&swfurl=") - 1 + s->swf_url.len * 3 +
|
sizeof("&swfurl=") - 1 + s->swf_url.len * 3 +
|
||||||
sizeof("&tcurl=") - 1 + s->tc_url.len * 3 +
|
sizeof("&tcurl=") - 1 + s->tc_url.len * 3 +
|
||||||
sizeof("&pageurl=") - 1 + s->page_url.len * 3
|
sizeof("&pageurl=") - 1 + s->page_url.len * 3 +
|
||||||
|
sizeof("&addr=") - 1 + addr_text->len * 3
|
||||||
);
|
);
|
||||||
|
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
@ -570,29 +592,35 @@ ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, ngx_pool_t *pool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cl->buf = b;
|
cl->buf = b;
|
||||||
|
cl->next = NULL;
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "app=", sizeof("app=") - 1);
|
b->last = ngx_cpymem(b->last, (u_char*) "app=", sizeof("app=") - 1);
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, s->app.data, s->app.len, 0);
|
b->last = (u_char*) ngx_escape_uri(b->last, s->app.data, s->app.len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&flashver=",
|
b->last = ngx_cpymem(b->last, (u_char*) "&flashver=",
|
||||||
sizeof("&flashver=") - 1);
|
sizeof("&flashver=") - 1);
|
||||||
b->last = (u_char*) ngx_escape_uri(b->last, s->flashver.data,
|
b->last = (u_char*) ngx_escape_uri(b->last, s->flashver.data,
|
||||||
s->flashver.len, 0);
|
s->flashver.len, NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=",
|
b->last = ngx_cpymem(b->last, (u_char*) "&swfurl=",
|
||||||
sizeof("&swfurl=") - 1);
|
sizeof("&swfurl=") - 1);
|
||||||
b->last = (u_char*) ngx_escape_uri(b->last, s->swf_url.data,
|
b->last = (u_char*) ngx_escape_uri(b->last, s->swf_url.data,
|
||||||
s->swf_url.len, 0);
|
s->swf_url.len, NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=",
|
b->last = ngx_cpymem(b->last, (u_char*) "&tcurl=",
|
||||||
sizeof("&tcurl=") - 1);
|
sizeof("&tcurl=") - 1);
|
||||||
b->last = (u_char*) ngx_escape_uri(b->last, s->tc_url.data,
|
b->last = (u_char*) ngx_escape_uri(b->last, s->tc_url.data,
|
||||||
s->tc_url.len, 0);
|
s->tc_url.len, NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=",
|
b->last = ngx_cpymem(b->last, (u_char*) "&pageurl=",
|
||||||
sizeof("&pageurl=") - 1);
|
sizeof("&pageurl=") - 1);
|
||||||
b->last = (u_char*) ngx_escape_uri(b->last, s->page_url.data,
|
b->last = (u_char*) ngx_escape_uri(b->last, s->page_url.data,
|
||||||
s->page_url.len, 0);
|
s->page_url.len, NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
|
b->last = ngx_cpymem(b->last, (u_char*) "&addr=", sizeof("&addr=") -1);
|
||||||
|
b->last = (u_char*) ngx_escape_uri(b->last, addr_text->data,
|
||||||
|
addr_text->len, NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ typedef ngx_int_t (*ngx_rtmp_netcall_sink_pt)(ngx_rtmp_session_t *s,
|
|||||||
typedef ngx_int_t (*ngx_rtmp_netcall_handle_pt)(ngx_rtmp_session_t *s,
|
typedef ngx_int_t (*ngx_rtmp_netcall_handle_pt)(ngx_rtmp_session_t *s,
|
||||||
void *arg, ngx_chain_t *in);
|
void *arg, ngx_chain_t *in);
|
||||||
|
|
||||||
#define NGX_RTMP_NETCALL_HTTP_GET 1
|
#define NGX_RTMP_NETCALL_HTTP_GET 0
|
||||||
#define NGX_RTMP_NETCALL_HTTP_POST 2
|
#define NGX_RTMP_NETCALL_HTTP_POST 1
|
||||||
|
|
||||||
|
|
||||||
/* If handle is NULL then netcall is created detached
|
/* If handle is NULL then netcall is created detached
|
||||||
@ -51,9 +51,9 @@ ngx_int_t ngx_rtmp_netcall_create(ngx_rtmp_session_t *s,
|
|||||||
/* HTTP handling */
|
/* HTTP handling */
|
||||||
ngx_chain_t * ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s,
|
ngx_chain_t * ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s,
|
||||||
ngx_pool_t *pool);
|
ngx_pool_t *pool);
|
||||||
ngx_chain_t * ngx_rtmp_netcall_http_format_header(ngx_int_t method,
|
ngx_chain_t * ngx_rtmp_netcall_http_format_request(ngx_int_t method,
|
||||||
ngx_str_t *uri, ngx_str_t *host, ngx_pool_t *pool,
|
ngx_str_t *host, ngx_str_t *uri, ngx_chain_t *args, ngx_chain_t *body,
|
||||||
size_t content_length, ngx_str_t *content_type);
|
ngx_pool_t *pool, ngx_str_t *content_type);
|
||||||
ngx_chain_t * ngx_rtmp_netcall_http_skip_header(ngx_chain_t *in);
|
ngx_chain_t * ngx_rtmp_netcall_http_skip_header(ngx_chain_t *in);
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,18 +14,20 @@
|
|||||||
|
|
||||||
static ngx_rtmp_publish_pt next_publish;
|
static ngx_rtmp_publish_pt next_publish;
|
||||||
static ngx_rtmp_play_pt next_play;
|
static ngx_rtmp_play_pt next_play;
|
||||||
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
static ngx_rtmp_close_stream_pt next_close_stream;
|
||||||
static ngx_rtmp_record_done_pt next_record_done;
|
static ngx_rtmp_record_done_pt next_record_done;
|
||||||
|
|
||||||
|
|
||||||
static char *ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
|
static char *ngx_rtmp_notify_method(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
|
void *conf);
|
||||||
static ngx_int_t ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf);
|
static ngx_int_t ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf);
|
||||||
static void * ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf);
|
static void * ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf);
|
||||||
static char * ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf,
|
static char * ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf,
|
||||||
void *parent, void *child);
|
void *parent, void *child);
|
||||||
static ngx_int_t ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname,
|
static ngx_int_t ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname,
|
||||||
ngx_url_t *url);
|
ngx_uint_t url_idx);
|
||||||
|
|
||||||
|
|
||||||
ngx_str_t ngx_rtmp_notify_urlencoded =
|
ngx_str_t ngx_rtmp_notify_urlencoded =
|
||||||
@ -43,6 +45,7 @@ enum {
|
|||||||
NGX_RTMP_NOTIFY_PUBLISH_DONE,
|
NGX_RTMP_NOTIFY_PUBLISH_DONE,
|
||||||
NGX_RTMP_NOTIFY_DONE,
|
NGX_RTMP_NOTIFY_DONE,
|
||||||
NGX_RTMP_NOTIFY_RECORD_DONE,
|
NGX_RTMP_NOTIFY_RECORD_DONE,
|
||||||
|
NGX_RTMP_NOTIFY_UPDATE,
|
||||||
NGX_RTMP_NOTIFY_MAX
|
NGX_RTMP_NOTIFY_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,6 +53,9 @@ enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_url_t *url[NGX_RTMP_NOTIFY_MAX];
|
ngx_url_t *url[NGX_RTMP_NOTIFY_MAX];
|
||||||
ngx_flag_t active;
|
ngx_flag_t active;
|
||||||
|
ngx_uint_t method;
|
||||||
|
ngx_msec_t update_timeout;
|
||||||
|
ngx_flag_t update_strict;
|
||||||
} ngx_rtmp_notify_app_conf_t;
|
} ngx_rtmp_notify_app_conf_t;
|
||||||
|
|
||||||
|
|
||||||
@ -57,12 +63,13 @@ typedef struct {
|
|||||||
ngx_uint_t flags;
|
ngx_uint_t flags;
|
||||||
u_char name[NGX_RTMP_MAX_NAME];
|
u_char name[NGX_RTMP_MAX_NAME];
|
||||||
u_char args[NGX_RTMP_MAX_ARGS];
|
u_char args[NGX_RTMP_MAX_ARGS];
|
||||||
|
ngx_event_t update_evt;
|
||||||
} ngx_rtmp_notify_ctx_t;
|
} ngx_rtmp_notify_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u_char *cbname;
|
u_char *cbname;
|
||||||
ngx_url_t *url;
|
ngx_uint_t url_idx;
|
||||||
} ngx_rtmp_notify_done_t;
|
} ngx_rtmp_notify_done_t;
|
||||||
|
|
||||||
|
|
||||||
@ -111,6 +118,34 @@ static ngx_command_t ngx_rtmp_notify_commands[] = {
|
|||||||
0,
|
0,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("on_update"),
|
||||||
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_rtmp_notify_on_event,
|
||||||
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("notify_method"),
|
||||||
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_rtmp_notify_method,
|
||||||
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("notify_update_timeout"),
|
||||||
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_msec_slot,
|
||||||
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
|
offsetof(ngx_rtmp_notify_app_conf_t, update_timeout),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("notify_update_strict"),
|
||||||
|
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_flag_slot,
|
||||||
|
NGX_RTMP_APP_CONF_OFFSET,
|
||||||
|
offsetof(ngx_rtmp_notify_app_conf_t, update_strict),
|
||||||
|
NULL },
|
||||||
|
|
||||||
ngx_null_command
|
ngx_null_command
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -158,6 +193,10 @@ ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf)
|
|||||||
nacf->url[n] = NGX_CONF_UNSET_PTR;
|
nacf->url[n] = NGX_CONF_UNSET_PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nacf->method = NGX_CONF_UNSET;
|
||||||
|
nacf->update_timeout = NGX_CONF_UNSET;
|
||||||
|
nacf->update_strict = NGX_CONF_UNSET;
|
||||||
|
|
||||||
return nacf;
|
return nacf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,35 +219,60 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
prev->active = 1;
|
prev->active = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngx_conf_merge_uint_value(conf->method, prev->method,
|
||||||
|
NGX_RTMP_NETCALL_HTTP_POST);
|
||||||
|
ngx_conf_merge_msec_value(conf->update_timeout, prev->update_timeout,
|
||||||
|
30000);
|
||||||
|
ngx_conf_merge_value(conf->update_strict, prev->update_strict, 0);
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_chain_t *
|
||||||
|
ngx_rtmp_notify_create_request(ngx_rtmp_session_t *s, ngx_pool_t *pool,
|
||||||
|
ngx_uint_t url_idx, ngx_chain_t *args)
|
||||||
|
{
|
||||||
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
|
ngx_chain_t *al, *bl, *cl;
|
||||||
|
ngx_url_t *url;
|
||||||
|
|
||||||
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
|
url = nacf->url[url_idx];
|
||||||
|
|
||||||
|
al = ngx_rtmp_netcall_http_format_session(s, pool);
|
||||||
|
if (al == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
al->next = args;
|
||||||
|
|
||||||
|
bl = NULL;
|
||||||
|
|
||||||
|
if (nacf->method == NGX_RTMP_NETCALL_HTTP_POST) {
|
||||||
|
cl = al;
|
||||||
|
al = bl;
|
||||||
|
bl = cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_rtmp_netcall_http_format_request(nacf->method, &url->host,
|
||||||
|
&url->uri, al, bl, pool,
|
||||||
|
&ngx_rtmp_notify_urlencoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_chain_t *
|
static ngx_chain_t *
|
||||||
ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
|
ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
|
||||||
ngx_pool_t *pool)
|
ngx_pool_t *pool)
|
||||||
{
|
{
|
||||||
ngx_rtmp_publish_t *v = arg;
|
ngx_rtmp_publish_t *v = arg;
|
||||||
|
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_chain_t *pl;
|
||||||
ngx_chain_t *hl, *cl, *pl;
|
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
ngx_str_t *addr_text;
|
|
||||||
ngx_url_t *url;
|
|
||||||
size_t name_len, type_len, args_len;
|
size_t name_len, type_len, args_len;
|
||||||
|
|
||||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
|
||||||
|
|
||||||
/* common variables */
|
|
||||||
cl = ngx_rtmp_netcall_http_format_session(s, pool);
|
|
||||||
|
|
||||||
if (cl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* publish variables */
|
|
||||||
pl = ngx_alloc_chain_link(pool);
|
pl = ngx_alloc_chain_link(pool);
|
||||||
|
|
||||||
if (pl == NULL) {
|
if (pl == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -216,11 +280,9 @@ ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
|
|||||||
name_len = ngx_strlen(v->name);
|
name_len = ngx_strlen(v->name);
|
||||||
type_len = ngx_strlen(v->type);
|
type_len = ngx_strlen(v->type);
|
||||||
args_len = ngx_strlen(v->args);
|
args_len = ngx_strlen(v->args);
|
||||||
addr_text = &s->connection->addr_text;
|
|
||||||
|
|
||||||
b = ngx_create_temp_buf(pool,
|
b = ngx_create_temp_buf(pool,
|
||||||
sizeof("&call=publish") +
|
sizeof("&call=publish") +
|
||||||
sizeof("&addr=") + addr_text->len *3 +
|
|
||||||
sizeof("&name=") + name_len * 3 +
|
sizeof("&name=") + name_len * 3 +
|
||||||
sizeof("&type=") + type_len * 3 +
|
sizeof("&type=") + type_len * 3 +
|
||||||
1 + args_len);
|
1 + args_len);
|
||||||
@ -229,41 +291,25 @@ ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pl->buf = b;
|
pl->buf = b;
|
||||||
|
pl->next = NULL;
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&call=publish",
|
b->last = ngx_cpymem(b->last, (u_char*) "&call=publish",
|
||||||
sizeof("&call=publish") - 1);
|
sizeof("&call=publish") - 1);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
|
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
|
|
||||||
addr_text->len, 0);
|
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, v->name, name_len, 0);
|
b->last = (u_char*) ngx_escape_uri(b->last, v->name, name_len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&type=", sizeof("&type=") - 1);
|
b->last = ngx_cpymem(b->last, (u_char*) "&type=", sizeof("&type=") - 1);
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, v->type, type_len, 0);
|
b->last = (u_char*) ngx_escape_uri(b->last, v->type, type_len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
if (args_len) {
|
if (args_len) {
|
||||||
*b->last++ = '&';
|
*b->last++ = '&';
|
||||||
b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
|
b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTTP header */
|
return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_PUBLISH, pl);
|
||||||
url = nacf->url[NGX_RTMP_NOTIFY_PUBLISH];
|
|
||||||
hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
|
|
||||||
&url->uri, &url->host,
|
|
||||||
pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
|
||||||
&ngx_rtmp_notify_urlencoded);
|
|
||||||
|
|
||||||
if (hl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hl->next = cl;
|
|
||||||
cl->next = pl;
|
|
||||||
pl->next = NULL;
|
|
||||||
|
|
||||||
return hl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -273,80 +319,48 @@ ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
|
|||||||
{
|
{
|
||||||
ngx_rtmp_play_t *v = arg;
|
ngx_rtmp_play_t *v = arg;
|
||||||
|
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_chain_t *pl;
|
||||||
ngx_chain_t *hl, *cl, *pl;
|
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
ngx_str_t *addr_text;
|
|
||||||
ngx_url_t *url;
|
|
||||||
size_t name_len, args_len;
|
size_t name_len, args_len;
|
||||||
|
|
||||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
|
||||||
|
|
||||||
/* common variables */
|
|
||||||
cl = ngx_rtmp_netcall_http_format_session(s, pool);
|
|
||||||
|
|
||||||
if (cl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* play variables */
|
|
||||||
pl = ngx_alloc_chain_link(pool);
|
pl = ngx_alloc_chain_link(pool);
|
||||||
|
|
||||||
if (pl == NULL) {
|
if (pl == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
name_len = ngx_strlen(v->name);
|
name_len = ngx_strlen(v->name);
|
||||||
args_len = ngx_strlen(v->args);
|
args_len = ngx_strlen(v->args);
|
||||||
addr_text = &s->connection->addr_text;
|
|
||||||
|
|
||||||
b = ngx_create_temp_buf(pool,
|
b = ngx_create_temp_buf(pool,
|
||||||
sizeof("&call=play") +
|
sizeof("&call=play") +
|
||||||
sizeof("&addr=") + addr_text->len * 3 +
|
|
||||||
sizeof("&name=") + name_len * 3 +
|
sizeof("&name=") + name_len * 3 +
|
||||||
sizeof("&start=&duration=&reset=") + NGX_OFF_T_LEN * 3
|
sizeof("&start=&duration=&reset=") +
|
||||||
+ 1 + args_len);
|
NGX_OFF_T_LEN * 3 + 1 + args_len);
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pl->buf = b;
|
pl->buf = b;
|
||||||
|
pl->next = NULL;
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&call=play",
|
b->last = ngx_cpymem(b->last, (u_char*) "&call=play",
|
||||||
sizeof("&call=play") - 1);
|
sizeof("&call=play") - 1);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
|
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
|
|
||||||
addr_text->len, 0);
|
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, v->name, name_len, 0);
|
b->last = (u_char*) ngx_escape_uri(b->last, v->name, name_len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
b->last = ngx_snprintf(b->last, b->end - b->last,
|
b->last = ngx_snprintf(b->last, b->end - b->last,
|
||||||
"&start=%uD&duration=%uD&reset=%d",
|
"&start=%uD&duration=%uD&reset=%d",
|
||||||
(uint32_t)v->start, (uint32_t)v->duration, v->reset & 1);
|
(uint32_t) v->start, (uint32_t) v->duration,
|
||||||
|
v->reset & 1);
|
||||||
|
|
||||||
if (args_len) {
|
if (args_len) {
|
||||||
*b->last++ = '&';
|
*b->last++ = '&';
|
||||||
b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
|
b->last = (u_char *) ngx_cpymem(b->last, v->args, args_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTTP header */
|
return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_PLAY, pl);
|
||||||
url = nacf->url[NGX_RTMP_NOTIFY_PLAY];
|
|
||||||
hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
|
|
||||||
&url->uri, &url->host,
|
|
||||||
pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
|
||||||
&ngx_rtmp_notify_urlencoded);
|
|
||||||
|
|
||||||
if (hl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hl->next = cl;
|
|
||||||
cl->next = pl;
|
|
||||||
pl->next = NULL;
|
|
||||||
|
|
||||||
return hl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -356,23 +370,14 @@ ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
|
|||||||
{
|
{
|
||||||
ngx_rtmp_notify_done_t *ds = arg;
|
ngx_rtmp_notify_done_t *ds = arg;
|
||||||
|
|
||||||
ngx_chain_t *hl, *cl, *pl;
|
ngx_chain_t *pl;
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
size_t cbname_len, name_len, args_len;
|
size_t cbname_len, name_len, args_len;
|
||||||
ngx_str_t *addr_text;
|
|
||||||
ngx_rtmp_notify_ctx_t *ctx;
|
ngx_rtmp_notify_ctx_t *ctx;
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
/* common variables */
|
|
||||||
cl = ngx_rtmp_netcall_http_format_session(s, pool);
|
|
||||||
|
|
||||||
if (cl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl = ngx_alloc_chain_link(pool);
|
pl = ngx_alloc_chain_link(pool);
|
||||||
|
|
||||||
if (pl == NULL) {
|
if (pl == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -380,29 +385,25 @@ ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
|
|||||||
cbname_len = ngx_strlen(ds->cbname);
|
cbname_len = ngx_strlen(ds->cbname);
|
||||||
name_len = ctx ? ngx_strlen(ctx->name) : 0;
|
name_len = ctx ? ngx_strlen(ctx->name) : 0;
|
||||||
args_len = ctx ? ngx_strlen(ctx->args) : 0;
|
args_len = ctx ? ngx_strlen(ctx->args) : 0;
|
||||||
addr_text = &s->connection->addr_text;
|
|
||||||
|
|
||||||
b = ngx_create_temp_buf(pool,
|
b = ngx_create_temp_buf(pool,
|
||||||
sizeof("&call=") + cbname_len +
|
sizeof("&call=") + cbname_len +
|
||||||
sizeof("&addr=") + addr_text->len * 3 +
|
sizeof("&name=") + name_len * 3 +
|
||||||
sizeof("&name=") + name_len * 3
|
1 + args_len);
|
||||||
+ 1 + args_len);
|
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pl->buf = b;
|
pl->buf = b;
|
||||||
|
pl->next = NULL;
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&call=", sizeof("&call=") - 1);
|
b->last = ngx_cpymem(b->last, (u_char*) "&call=", sizeof("&call=") - 1);
|
||||||
b->last = ngx_cpymem(b->last, ds->cbname, cbname_len);
|
b->last = ngx_cpymem(b->last, ds->cbname, cbname_len);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
|
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
|
|
||||||
addr_text->len, 0);
|
|
||||||
|
|
||||||
if (name_len) {
|
if (name_len) {
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, ctx->name, name_len, 0);
|
b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_len) {
|
if (args_len) {
|
||||||
@ -410,21 +411,65 @@ ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
|
|||||||
b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
|
b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTTP header */
|
return ngx_rtmp_notify_create_request(s, pool, ds->url_idx, pl);
|
||||||
hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
|
}
|
||||||
&ds->url->uri, &ds->url->host,
|
|
||||||
pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
|
||||||
&ngx_rtmp_notify_urlencoded);
|
|
||||||
|
|
||||||
if (hl == NULL) {
|
|
||||||
|
static ngx_chain_t *
|
||||||
|
ngx_rtmp_notify_update_create(ngx_rtmp_session_t *s, void *arg,
|
||||||
|
ngx_pool_t *pool)
|
||||||
|
{
|
||||||
|
ngx_chain_t *pl;
|
||||||
|
ngx_buf_t *b;
|
||||||
|
size_t name_len, args_len;
|
||||||
|
ngx_rtmp_notify_ctx_t *ctx;
|
||||||
|
ngx_str_t sfx;
|
||||||
|
|
||||||
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
|
pl = ngx_alloc_chain_link(pool);
|
||||||
|
if (pl == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hl->next = cl;
|
if (ctx->flags & NGX_RTMP_NOTIFY_PUBLISHING) {
|
||||||
cl->next = pl;
|
ngx_str_set(&sfx, "_publish");
|
||||||
|
} else if (ctx->flags & NGX_RTMP_NOTIFY_PLAYING) {
|
||||||
|
ngx_str_set(&sfx, "_play");
|
||||||
|
} else {
|
||||||
|
ngx_str_null(&sfx);
|
||||||
|
}
|
||||||
|
|
||||||
|
name_len = ctx ? ngx_strlen(ctx->name) : 0;
|
||||||
|
args_len = ctx ? ngx_strlen(ctx->args) : 0;
|
||||||
|
|
||||||
|
b = ngx_create_temp_buf(pool,
|
||||||
|
sizeof("&call=update") + sfx.len +
|
||||||
|
sizeof("&name=") + name_len * 3 +
|
||||||
|
1 + args_len);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl->buf = b;
|
||||||
pl->next = NULL;
|
pl->next = NULL;
|
||||||
|
|
||||||
return hl;
|
b->last = ngx_cpymem(b->last, (u_char*) "&call=update",
|
||||||
|
sizeof("&call=update") - 1);
|
||||||
|
b->last = ngx_cpymem(b->last, sfx.data, sfx.len);
|
||||||
|
|
||||||
|
if (name_len) {
|
||||||
|
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
||||||
|
b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args_len) {
|
||||||
|
*b->last++ = '&';
|
||||||
|
b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_UPDATE, pl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -434,48 +479,33 @@ ngx_rtmp_notify_record_done_create(ngx_rtmp_session_t *s, void *arg,
|
|||||||
{
|
{
|
||||||
ngx_rtmp_record_done_t *v = arg;
|
ngx_rtmp_record_done_t *v = arg;
|
||||||
|
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
|
||||||
ngx_rtmp_notify_ctx_t *ctx;
|
ngx_rtmp_notify_ctx_t *ctx;
|
||||||
ngx_chain_t *hl, *cl, *pl;
|
ngx_chain_t *pl;
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
ngx_str_t *addr_text;
|
|
||||||
ngx_url_t *url;
|
|
||||||
size_t name_len, args_len;
|
size_t name_len, args_len;
|
||||||
|
|
||||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
|
||||||
|
|
||||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
/* common variables */
|
|
||||||
cl = ngx_rtmp_netcall_http_format_session(s, pool);
|
|
||||||
|
|
||||||
if (cl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* publish variables */
|
|
||||||
pl = ngx_alloc_chain_link(pool);
|
pl = ngx_alloc_chain_link(pool);
|
||||||
|
|
||||||
if (pl == NULL) {
|
if (pl == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
name_len = ngx_strlen(ctx->name);
|
name_len = ngx_strlen(ctx->name);
|
||||||
args_len = ngx_strlen(ctx->args);
|
args_len = ngx_strlen(ctx->args);
|
||||||
addr_text = &s->connection->addr_text;
|
|
||||||
|
|
||||||
b = ngx_create_temp_buf(pool,
|
b = ngx_create_temp_buf(pool,
|
||||||
sizeof("&call=record_done") +
|
sizeof("&call=record_done") +
|
||||||
sizeof("&recorder=") + v->recorder.len +
|
sizeof("&recorder=") + v->recorder.len +
|
||||||
sizeof("&addr=") + addr_text->len *3 +
|
|
||||||
sizeof("&name=") + name_len * 3 +
|
sizeof("&name=") + name_len * 3 +
|
||||||
sizeof("&path=") + v->path.len * 3 +
|
sizeof("&path=") + v->path.len * 3 +
|
||||||
+ 1 + args_len);
|
1 + args_len);
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pl->buf = b;
|
pl->buf = b;
|
||||||
|
pl->next = NULL;
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&call=record_done",
|
b->last = ngx_cpymem(b->last, (u_char*) "&call=record_done",
|
||||||
sizeof("&call=record_done") - 1);
|
sizeof("&call=record_done") - 1);
|
||||||
@ -483,39 +513,23 @@ ngx_rtmp_notify_record_done_create(ngx_rtmp_session_t *s, void *arg,
|
|||||||
b->last = ngx_cpymem(b->last, (u_char *) "&recorder=",
|
b->last = ngx_cpymem(b->last, (u_char *) "&recorder=",
|
||||||
sizeof("&recorder=") - 1);
|
sizeof("&recorder=") - 1);
|
||||||
b->last = (u_char*) ngx_escape_uri(b->last, v->recorder.data,
|
b->last = (u_char*) ngx_escape_uri(b->last, v->recorder.data,
|
||||||
v->recorder.len, 0);
|
v->recorder.len, NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*)"&addr=", sizeof("&addr=") -1);
|
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, addr_text->data,
|
|
||||||
addr_text->len, 0);
|
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
b->last = ngx_cpymem(b->last, (u_char*) "&name=", sizeof("&name=") - 1);
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, ctx->name, name_len, 0);
|
b->last = (u_char*) ngx_escape_uri(b->last, ctx->name, name_len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
b->last = ngx_cpymem(b->last, (u_char*) "&path=", sizeof("&path=") - 1);
|
b->last = ngx_cpymem(b->last, (u_char*) "&path=", sizeof("&path=") - 1);
|
||||||
b->last = (u_char*)ngx_escape_uri(b->last, v->path.data, v->path.len, 0);
|
b->last = (u_char*) ngx_escape_uri(b->last, v->path.data, v->path.len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
|
|
||||||
if (args_len) {
|
if (args_len) {
|
||||||
*b->last++ = '&';
|
*b->last++ = '&';
|
||||||
b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
|
b->last = (u_char *) ngx_cpymem(b->last, ctx->args, args_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTTP header */
|
return ngx_rtmp_notify_create_request(s, pool, NGX_RTMP_NOTIFY_RECORD_DONE,
|
||||||
url = nacf->url[NGX_RTMP_NOTIFY_RECORD_DONE];
|
pl);
|
||||||
hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_POST,
|
|
||||||
&url->uri, &url->host,
|
|
||||||
pool, cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
|
||||||
&ngx_rtmp_notify_urlencoded);
|
|
||||||
|
|
||||||
if (hl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hl->next = cl;
|
|
||||||
cl->next = pl;
|
|
||||||
pl->next = NULL;
|
|
||||||
|
|
||||||
return hl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -550,9 +564,15 @@ ngx_rtmp_notify_parse_http_retcode(ngx_rtmp_session_t *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||||
"notify: invalid HTTP response");
|
"notify: empty or broken HTTP response");
|
||||||
|
|
||||||
return NGX_ERROR;
|
/*
|
||||||
|
* not enough data;
|
||||||
|
* it can happen in case of empty or broken reply;
|
||||||
|
* let the caller decide if that's an error or not
|
||||||
|
*/
|
||||||
|
|
||||||
|
return NGX_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -580,6 +600,74 @@ ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_rtmp_notify_update_handle(ngx_rtmp_session_t *s,
|
||||||
|
void *arg, ngx_chain_t *in)
|
||||||
|
{
|
||||||
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
|
ngx_rtmp_notify_ctx_t *ctx;
|
||||||
|
ngx_int_t rc;
|
||||||
|
|
||||||
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
|
rc = ngx_rtmp_notify_parse_http_retcode(s, in);
|
||||||
|
|
||||||
|
if ((!nacf->update_strict && rc == NGX_ERROR) ||
|
||||||
|
(nacf->update_strict && rc != NGX_OK))
|
||||||
|
{
|
||||||
|
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||||
|
"notify: update failed");
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
|
"notify: schedule update %Mms",
|
||||||
|
nacf->update_timeout);
|
||||||
|
|
||||||
|
ngx_add_timer(&ctx->update_evt, nacf->update_timeout);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_rtmp_notify_update(ngx_event_t *e)
|
||||||
|
{
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_rtmp_session_t *s;
|
||||||
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
|
ngx_rtmp_netcall_init_t ci;
|
||||||
|
ngx_url_t *url;
|
||||||
|
|
||||||
|
c = e->data;
|
||||||
|
s = c->data;
|
||||||
|
|
||||||
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
|
url = nacf->url[NGX_RTMP_NOTIFY_UPDATE];
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||||
|
"notify: update '%V'", &url->url);
|
||||||
|
|
||||||
|
ngx_memzero(&ci, sizeof(ci));
|
||||||
|
|
||||||
|
ci.url = url;
|
||||||
|
ci.create = ngx_rtmp_notify_update_create;
|
||||||
|
ci.handle = ngx_rtmp_notify_update_handle;
|
||||||
|
|
||||||
|
if (ngx_rtmp_netcall_create(s, &ci) == NGX_OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* schedule next update on connection error */
|
||||||
|
|
||||||
|
ngx_rtmp_notify_update_handle(s, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_rtmp_notify_init(ngx_rtmp_session_t *s,
|
ngx_rtmp_notify_init(ngx_rtmp_session_t *s,
|
||||||
u_char name[NGX_RTMP_MAX_NAME], u_char args[NGX_RTMP_MAX_ARGS],
|
u_char name[NGX_RTMP_MAX_NAME], u_char args[NGX_RTMP_MAX_ARGS],
|
||||||
@ -587,9 +675,9 @@ ngx_rtmp_notify_init(ngx_rtmp_session_t *s,
|
|||||||
{
|
{
|
||||||
ngx_rtmp_notify_ctx_t *ctx;
|
ngx_rtmp_notify_ctx_t *ctx;
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
|
ngx_event_t *e;
|
||||||
|
|
||||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
if (!nacf->active) {
|
if (!nacf->active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -609,6 +697,28 @@ ngx_rtmp_notify_init(ngx_rtmp_session_t *s,
|
|||||||
ngx_memcpy(ctx->args, args, NGX_RTMP_MAX_ARGS);
|
ngx_memcpy(ctx->args, args, NGX_RTMP_MAX_ARGS);
|
||||||
|
|
||||||
ctx->flags |= flags;
|
ctx->flags |= flags;
|
||||||
|
|
||||||
|
if (nacf->url[NGX_RTMP_NOTIFY_UPDATE] == NULL ||
|
||||||
|
nacf->update_timeout == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->update_evt.timer_set) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = &ctx->update_evt;
|
||||||
|
|
||||||
|
e->data = s->connection;
|
||||||
|
e->log = s->connection->log;
|
||||||
|
e->handler = ngx_rtmp_notify_update;
|
||||||
|
|
||||||
|
ngx_add_timer(e, nacf->update_timeout);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||||
|
"notify: schedule initial update %Mms",
|
||||||
|
nacf->update_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -617,30 +727,31 @@ ngx_rtmp_notify_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
|||||||
{
|
{
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
ngx_rtmp_netcall_init_t ci;
|
ngx_rtmp_netcall_init_t ci;
|
||||||
|
ngx_url_t *url;
|
||||||
|
|
||||||
if (s->auto_pushed) {
|
if (s->auto_pushed) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
if (nacf == NULL) {
|
if (nacf == NULL) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
url = nacf->url[NGX_RTMP_NOTIFY_PUBLISH];
|
||||||
|
|
||||||
ngx_rtmp_notify_init(s, v->name, v->args, NGX_RTMP_NOTIFY_PUBLISHING);
|
ngx_rtmp_notify_init(s, v->name, v->args, NGX_RTMP_NOTIFY_PUBLISHING);
|
||||||
|
|
||||||
if (nacf->url[NGX_RTMP_NOTIFY_PUBLISH] == NULL) {
|
if (url == NULL) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||||
"notify: publish '%V'",
|
"notify: publish '%V'", &url->url);
|
||||||
&nacf->url[NGX_RTMP_NOTIFY_PUBLISH]->url);
|
|
||||||
|
|
||||||
ngx_memzero(&ci, sizeof(ci));
|
ngx_memzero(&ci, sizeof(ci));
|
||||||
|
|
||||||
ci.url = nacf->url[NGX_RTMP_NOTIFY_PUBLISH];
|
ci.url = url;
|
||||||
ci.create = ngx_rtmp_notify_publish_create;
|
ci.create = ngx_rtmp_notify_publish_create;
|
||||||
ci.handle = ngx_rtmp_notify_publish_handle;
|
ci.handle = ngx_rtmp_notify_publish_handle;
|
||||||
ci.arg = v;
|
ci.arg = v;
|
||||||
@ -658,30 +769,31 @@ ngx_rtmp_notify_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
|
|||||||
{
|
{
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
ngx_rtmp_netcall_init_t ci;
|
ngx_rtmp_netcall_init_t ci;
|
||||||
|
ngx_url_t *url;
|
||||||
|
|
||||||
if (s->auto_pushed) {
|
if (s->auto_pushed) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
if (nacf == NULL) {
|
if (nacf == NULL) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
url = nacf->url[NGX_RTMP_NOTIFY_PLAY];
|
||||||
|
|
||||||
ngx_rtmp_notify_init(s, v->name, v->args, NGX_RTMP_NOTIFY_PLAYING);
|
ngx_rtmp_notify_init(s, v->name, v->args, NGX_RTMP_NOTIFY_PLAYING);
|
||||||
|
|
||||||
if (nacf->url[NGX_RTMP_NOTIFY_PLAY] == NULL) {
|
if (url == NULL) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||||
"notify: play '%V'",
|
"notify: play '%V'", &url->url);
|
||||||
&nacf->url[NGX_RTMP_NOTIFY_PLAY]->url);
|
|
||||||
|
|
||||||
ngx_memzero(&ci, sizeof(ci));
|
ngx_memzero(&ci, sizeof(ci));
|
||||||
|
|
||||||
ci.url = nacf->url[NGX_RTMP_NOTIFY_PLAY];
|
ci.url = url;
|
||||||
ci.create = ngx_rtmp_notify_play_create;
|
ci.create = ngx_rtmp_notify_play_create;
|
||||||
ci.handle = ngx_rtmp_notify_play_handle;
|
ci.handle = ngx_rtmp_notify_play_handle;
|
||||||
ci.arg = v;
|
ci.arg = v;
|
||||||
@ -695,8 +807,8 @@ next:
|
|||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_notify_delete_stream(ngx_rtmp_session_t *s,
|
ngx_rtmp_notify_close_stream(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_delete_stream_t *v)
|
ngx_rtmp_close_stream_t *v)
|
||||||
{
|
{
|
||||||
ngx_rtmp_notify_ctx_t *ctx;
|
ngx_rtmp_notify_ctx_t *ctx;
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
@ -717,28 +829,26 @@ ngx_rtmp_notify_delete_stream(ngx_rtmp_session_t *s,
|
|||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nacf->url[NGX_RTMP_NOTIFY_PUBLISH_DONE] &&
|
if (ctx->flags & NGX_RTMP_NOTIFY_PUBLISHING) {
|
||||||
(ctx->flags & NGX_RTMP_NOTIFY_PUBLISHING))
|
ngx_rtmp_notify_done(s, "publish_done", NGX_RTMP_NOTIFY_PUBLISH_DONE);
|
||||||
{
|
|
||||||
ngx_rtmp_notify_done(s, "publish_done",
|
|
||||||
nacf->url[NGX_RTMP_NOTIFY_PUBLISH_DONE]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nacf->url[NGX_RTMP_NOTIFY_PLAY_DONE] &&
|
if (ctx->flags & NGX_RTMP_NOTIFY_PLAYING) {
|
||||||
(ctx->flags & NGX_RTMP_NOTIFY_PLAYING))
|
ngx_rtmp_notify_done(s, "play_done", NGX_RTMP_NOTIFY_PLAY_DONE);
|
||||||
{
|
|
||||||
ngx_rtmp_notify_done(s, "play_done",
|
|
||||||
nacf->url[NGX_RTMP_NOTIFY_PLAY_DONE]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nacf->url[NGX_RTMP_NOTIFY_DONE] && ctx->flags) {
|
if (ctx->flags) {
|
||||||
ngx_rtmp_notify_done(s, "done", nacf->url[NGX_RTMP_NOTIFY_DONE]);
|
ngx_rtmp_notify_done(s, "done", NGX_RTMP_NOTIFY_DONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->update_evt.timer_set) {
|
||||||
|
ngx_del_timer(&ctx->update_evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->flags = 0;
|
ctx->flags = 0;
|
||||||
|
|
||||||
next:
|
next:
|
||||||
return next_delete_stream(s, v);
|
return next_close_stream(s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -776,16 +886,25 @@ next:
|
|||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname, ngx_url_t *url)
|
ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname, ngx_uint_t url_idx)
|
||||||
{
|
{
|
||||||
ngx_rtmp_netcall_init_t ci;
|
ngx_rtmp_netcall_init_t ci;
|
||||||
ngx_rtmp_notify_done_t ds;
|
ngx_rtmp_notify_done_t ds;
|
||||||
|
ngx_rtmp_notify_app_conf_t *nacf;
|
||||||
|
ngx_url_t *url;
|
||||||
|
|
||||||
|
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||||
|
|
||||||
|
url = nacf->url[url_idx];
|
||||||
|
if (url == NULL) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||||
"notify: %s '%V'", cbname, &url->url);
|
"notify: %s '%V'", cbname, &url->url);
|
||||||
|
|
||||||
ds.cbname = (u_char *) cbname;
|
ds.cbname = (u_char *) cbname;
|
||||||
ds.url = url;
|
ds.url_idx = url_idx;
|
||||||
|
|
||||||
ngx_memzero(&ci, sizeof(ci));
|
ngx_memzero(&ci, sizeof(ci));
|
||||||
|
|
||||||
@ -800,7 +919,8 @@ ngx_rtmp_notify_done(ngx_rtmp_session_t *s, char *cbname, ngx_url_t *url)
|
|||||||
static char *
|
static char *
|
||||||
ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
ngx_rtmp_notify_app_conf_t *nacf;
|
ngx_rtmp_notify_app_conf_t *nacf = conf;
|
||||||
|
|
||||||
ngx_str_t *url, *name;
|
ngx_str_t *url, *name;
|
||||||
ngx_url_t *u;
|
ngx_url_t *u;
|
||||||
size_t add;
|
size_t add;
|
||||||
@ -835,8 +955,6 @@ ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
nacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_notify_module);
|
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
switch (name->len) {
|
switch (name->len) {
|
||||||
@ -848,6 +966,10 @@ ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case sizeof("on_update") - 1:
|
||||||
|
n = NGX_RTMP_NOTIFY_UPDATE;
|
||||||
|
break;
|
||||||
|
|
||||||
case sizeof("on_publish") - 1:
|
case sizeof("on_publish") - 1:
|
||||||
n = NGX_RTMP_NOTIFY_PUBLISH;
|
n = NGX_RTMP_NOTIFY_PUBLISH;
|
||||||
break;
|
break;
|
||||||
@ -871,6 +993,34 @@ ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_rtmp_notify_method(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
ngx_rtmp_notify_app_conf_t *nacf = conf;
|
||||||
|
|
||||||
|
ngx_str_t *value;
|
||||||
|
|
||||||
|
value = cf->args->elts;
|
||||||
|
value++;
|
||||||
|
|
||||||
|
if (value->len == sizeof("get") - 1 &&
|
||||||
|
ngx_strncasecmp(value->data, (u_char *) "get", value->len) == 0)
|
||||||
|
{
|
||||||
|
nacf->method = NGX_RTMP_NETCALL_HTTP_GET;
|
||||||
|
|
||||||
|
} else if (value->len == sizeof("post") - 1 &&
|
||||||
|
ngx_strncasecmp(value->data, (u_char *) "post", value->len) == 0)
|
||||||
|
{
|
||||||
|
nacf->method = NGX_RTMP_NETCALL_HTTP_POST;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return "got unexpected method";
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf)
|
ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
@ -880,8 +1030,8 @@ ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf)
|
|||||||
next_play = ngx_rtmp_play;
|
next_play = ngx_rtmp_play;
|
||||||
ngx_rtmp_play = ngx_rtmp_notify_play;
|
ngx_rtmp_play = ngx_rtmp_notify_play;
|
||||||
|
|
||||||
next_delete_stream = ngx_rtmp_delete_stream;
|
next_close_stream = ngx_rtmp_close_stream;
|
||||||
ngx_rtmp_delete_stream = ngx_rtmp_notify_delete_stream;
|
ngx_rtmp_close_stream = ngx_rtmp_notify_close_stream;
|
||||||
|
|
||||||
next_record_done = ngx_rtmp_record_done;
|
next_record_done = ngx_rtmp_record_done;
|
||||||
ngx_rtmp_record_done = ngx_rtmp_notify_record_done;
|
ngx_rtmp_record_done = ngx_rtmp_notify_record_done;
|
||||||
|
@ -642,7 +642,6 @@ ngx_rtmp_play_remote_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool)
|
|||||||
|
|
||||||
ngx_rtmp_play_app_conf_t *pacf;
|
ngx_rtmp_play_app_conf_t *pacf;
|
||||||
ngx_rtmp_play_ctx_t *ctx;
|
ngx_rtmp_play_ctx_t *ctx;
|
||||||
ngx_chain_t *hl;
|
|
||||||
ngx_str_t *addr_text, uri;
|
ngx_str_t *addr_text, uri;
|
||||||
u_char *p;
|
u_char *p;
|
||||||
size_t args_len, len;
|
size_t args_len, len;
|
||||||
@ -674,7 +673,8 @@ ngx_rtmp_play_remote_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool)
|
|||||||
|
|
||||||
p = ngx_cpymem(p, ctx->name.data, ctx->name.len);
|
p = ngx_cpymem(p, ctx->name.data, ctx->name.len);
|
||||||
p = ngx_cpymem(p, (u_char*)"?addr=", sizeof("&addr=") -1);
|
p = ngx_cpymem(p, (u_char*)"?addr=", sizeof("&addr=") -1);
|
||||||
p = (u_char*)ngx_escape_uri(p, addr_text->data, addr_text->len, 0);
|
p = (u_char*)ngx_escape_uri(p, addr_text->data, addr_text->len,
|
||||||
|
NGX_ESCAPE_ARGS);
|
||||||
if (args_len) {
|
if (args_len) {
|
||||||
*p++ = '&';
|
*p++ = '&';
|
||||||
p = (u_char *) ngx_cpymem(p, v->args, args_len);
|
p = (u_char *) ngx_cpymem(p, v->args, args_len);
|
||||||
@ -682,15 +682,9 @@ ngx_rtmp_play_remote_create(ngx_rtmp_session_t *s, void *arg, ngx_pool_t *pool)
|
|||||||
|
|
||||||
uri.len = p - uri.data;
|
uri.len = p - uri.data;
|
||||||
|
|
||||||
/* HTTP header */
|
return ngx_rtmp_netcall_http_format_request(NGX_RTMP_NETCALL_HTTP_GET,
|
||||||
hl = ngx_rtmp_netcall_http_format_header(NGX_RTMP_NETCALL_HTTP_GET,
|
&pacf->url->host, &uri,
|
||||||
&uri, &pacf->url->host, pool, 0, &text_plain);
|
NULL, NULL, pool, &text_plain);
|
||||||
|
|
||||||
if (hl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -385,6 +385,19 @@ ngx_rtmp_record_make_path(ngx_rtmp_session_t *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_rtmp_record_notify_error(ngx_rtmp_session_t *s,
|
||||||
|
ngx_rtmp_record_app_conf_t *rracf)
|
||||||
|
{
|
||||||
|
if (!rracf->notify) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_rtmp_send_status(s, "NetStream.Record.Failed", "error",
|
||||||
|
rracf->id.data ? (char *) rracf->id.data : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
||||||
ngx_rtmp_record_rec_ctx_t *rctx)
|
ngx_rtmp_record_rec_ctx_t *rctx)
|
||||||
@ -425,6 +438,8 @@ ngx_rtmp_record_node_open(ngx_rtmp_session_t *s,
|
|||||||
&rracf->id, &path);
|
&rracf->id, &path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngx_rtmp_record_notify_error(s, rracf);
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,6 +587,8 @@ ngx_rtmp_record_node_close(ngx_rtmp_session_t *s,
|
|||||||
err = ngx_errno;
|
err = ngx_errno;
|
||||||
ngx_log_error(NGX_LOG_CRIT, s->connection->log, err,
|
ngx_log_error(NGX_LOG_CRIT, s->connection->log, err,
|
||||||
"record: %V error closing file", &rracf->id);
|
"record: %V error closing file", &rracf->id);
|
||||||
|
|
||||||
|
ngx_rtmp_record_notify_error(s, rracf);
|
||||||
}
|
}
|
||||||
|
|
||||||
rctx->file.fd = NGX_INVALID_FILE;
|
rctx->file.fd = NGX_INVALID_FILE;
|
||||||
@ -673,6 +690,10 @@ ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s,
|
|||||||
if (ngx_write_file(&rctx->file, hdr, ph - hdr, rctx->file.offset)
|
if (ngx_write_file(&rctx->file, hdr, ph - hdr, rctx->file.offset)
|
||||||
== NGX_ERROR)
|
== NGX_ERROR)
|
||||||
{
|
{
|
||||||
|
ngx_rtmp_record_notify_error(s, rracf);
|
||||||
|
|
||||||
|
ngx_close_file(rctx->file.fd);
|
||||||
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,44 @@ ngx_module_t ngx_rtmp_stat_module = {
|
|||||||
#define NGX_RTMP_STAT_BUFSIZE 256
|
#define NGX_RTMP_STAT_BUFSIZE 256
|
||||||
|
|
||||||
|
|
||||||
|
/* ngx_escape_html does not escape characters out of ASCII range
|
||||||
|
* which are bad for xslt */
|
||||||
|
|
||||||
|
static void *
|
||||||
|
ngx_rtmp_stat_escape(ngx_http_request_t *r, void *data, size_t len)
|
||||||
|
{
|
||||||
|
u_char *p, *np;
|
||||||
|
void *new_data;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
p = data;
|
||||||
|
|
||||||
|
for (n = 0; n < len; ++n, ++p) {
|
||||||
|
if (*p < 0x20 || *p >= 0x7f) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == len) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_data = ngx_palloc(r->pool, len);
|
||||||
|
if (new_data == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = data;
|
||||||
|
np = new_data;
|
||||||
|
|
||||||
|
for (n = 0; n < len; ++n, ++p, ++np) {
|
||||||
|
*np = (*p < 0x20 || *p >= 0x7f) ? (u_char) ' ' : *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_rtmp_stat_output(ngx_http_request_t *r, ngx_chain_t ***lll,
|
ngx_rtmp_stat_output(ngx_http_request_t *r, ngx_chain_t ***lll,
|
||||||
void *data, size_t len, ngx_uint_t escape)
|
void *data, size_t len, ngx_uint_t escape)
|
||||||
@ -112,6 +150,13 @@ ngx_rtmp_stat_output(ngx_http_request_t *r, ngx_chain_t ***lll,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (escape) {
|
||||||
|
data = ngx_rtmp_stat_escape(r, data, len);
|
||||||
|
if (data == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
real_len = escape
|
real_len = escape
|
||||||
? len + ngx_escape_html(NULL, data, len)
|
? len + ngx_escape_html(NULL, data, len)
|
||||||
: len;
|
: len;
|
||||||
|
Reference in New Issue
Block a user