mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-05-13 23:51:08 +02:00
added external get-style arguments to notifiers; implemented on_done notification
This commit is contained in:
parent
d21a240b12
commit
63c4269a91
13
README
13
README
|
@ -77,7 +77,7 @@ rtmp {
|
|||
record_max_size 1K;
|
||||
|
||||
# append current timestamp to each flv
|
||||
#record_unique on;
|
||||
record_unique on;
|
||||
|
||||
# publish only from localhost
|
||||
allow publish 127.0.0.1;
|
||||
|
@ -147,6 +147,17 @@ rtmp {
|
|||
# Same with playing
|
||||
on_play http://localhost:8080/play;
|
||||
|
||||
# Publish/play end (repeats on disconnect)
|
||||
on_done http://localhost:8080/done;
|
||||
|
||||
# All above mentioned notifications receive
|
||||
# standard connect() arguments as well as
|
||||
# play/publish ones. If any arguments are sent
|
||||
# with GET-style syntax to play & publish
|
||||
# these are also included.
|
||||
# Example URL:
|
||||
# rtmp://localhost/myapp/mystream?a=b&c=d
|
||||
|
||||
# record 10 video keyframes (no audio) every 2 minutes
|
||||
record keyframes;
|
||||
record_path /tmp/vc;
|
||||
|
|
|
@ -379,14 +379,18 @@ ngx_rtmp_cmd_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t *v)
|
|||
|
||||
|
||||
static void
|
||||
ngx_rtmp_cmd_cutoff_args(u_char *s)
|
||||
ngx_rtmp_cmd_fill_args(u_char name[NGX_RTMP_MAX_NAME],
|
||||
u_char args[NGX_RTMP_MAX_ARGS])
|
||||
{
|
||||
u_char *p;
|
||||
|
||||
p = (u_char *)ngx_strchr(s, '?');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
p = (u_char *)ngx_strchr(name, '?');
|
||||
if (p == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
*p++ = 0;
|
||||
ngx_cpystrn(args, p, NGX_RTMP_MAX_ARGS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -425,7 +429,7 @@ ngx_rtmp_cmd_publish_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_rtmp_cmd_cutoff_args(v.name);
|
||||
ngx_rtmp_cmd_fill_args(v.name, v.args);
|
||||
|
||||
return ngx_rtmp_publish
|
||||
? ngx_rtmp_publish(s, &v)
|
||||
|
@ -474,9 +478,9 @@ ngx_rtmp_cmd_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
|||
out_inf, sizeof(out_inf) },
|
||||
};
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"publish: name='%s' type=%s silent=%d",
|
||||
v->name, v->type, v->silent);
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"publish: name='%s' args='%s' type=%s silent=%d",
|
||||
v->name, v->args, v->type, v->silent);
|
||||
|
||||
if (v->silent) {
|
||||
return NGX_OK;
|
||||
|
@ -634,7 +638,7 @@ ngx_rtmp_cmd_play_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_rtmp_cmd_cutoff_args(v.name);
|
||||
ngx_rtmp_cmd_fill_args(v.name, v.args);
|
||||
|
||||
return ngx_rtmp_play
|
||||
? ngx_rtmp_play(s, &v)
|
||||
|
@ -752,9 +756,10 @@ ngx_rtmp_cmd_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
|
|||
out4_inf, sizeof(out4_inf) },
|
||||
};
|
||||
|
||||
ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"play: name='%s' start=%uD duration=%uD reset=%d silent=%d",
|
||||
v->name, (uint32_t)v->start,
|
||||
ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"play: name='%s' args='%s' start=%uD duration=%uD "
|
||||
"reset=%d silent=%d",
|
||||
v->name, v->args, (uint32_t)v->start,
|
||||
(uint32_t)v->duration, v->reset, v->silent);
|
||||
|
||||
if (v->silent) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define NGX_RTMP_MAX_APP 128
|
||||
#define NGX_RTMP_MAX_NAME 256
|
||||
#define NGX_RTMP_MAX_URL 256
|
||||
#define NGX_RTMP_MAX_ARGS NGX_RTMP_MAX_NAME
|
||||
|
||||
|
||||
/* Basic RTMP call support */
|
||||
|
@ -46,6 +47,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
u_char name[NGX_RTMP_MAX_NAME];
|
||||
u_char args[NGX_RTMP_MAX_ARGS];
|
||||
u_char type[16];
|
||||
int silent;
|
||||
} ngx_rtmp_publish_t;
|
||||
|
@ -63,6 +65,7 @@ typedef ngx_rtmp_fcpublish_t ngx_rtmp_fcunsubscribe_t;
|
|||
|
||||
typedef struct {
|
||||
u_char name[NGX_RTMP_MAX_NAME];
|
||||
u_char args[NGX_RTMP_MAX_ARGS];
|
||||
double start;
|
||||
double duration;
|
||||
int reset;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
static ngx_rtmp_publish_pt next_publish;
|
||||
static ngx_rtmp_play_pt next_play;
|
||||
static ngx_rtmp_delete_stream_pt next_delete_stream;
|
||||
|
||||
|
||||
static char *ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
|
@ -26,9 +27,16 @@ static char * ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf,
|
|||
typedef struct {
|
||||
ngx_url_t *publish_url;
|
||||
ngx_url_t *play_url;
|
||||
ngx_url_t *done_url;
|
||||
} ngx_rtmp_notify_app_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char name[NGX_RTMP_MAX_NAME];
|
||||
u_char args[NGX_RTMP_MAX_ARGS];
|
||||
} ngx_rtmp_notify_ctx_t;
|
||||
|
||||
|
||||
static ngx_command_t ngx_rtmp_notify_commands[] = {
|
||||
|
||||
{ ngx_string("on_publish"),
|
||||
|
@ -45,6 +53,13 @@ static ngx_command_t ngx_rtmp_notify_commands[] = {
|
|||
0,
|
||||
NULL },
|
||||
|
||||
{ ngx_string("on_done"),
|
||||
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_null_command
|
||||
};
|
||||
|
||||
|
@ -113,7 +128,7 @@ ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
|
|||
ngx_rtmp_notify_app_conf_t *nacf;
|
||||
ngx_chain_t *hl, *cl, *pl;
|
||||
ngx_buf_t *b;
|
||||
size_t name_len, type_len;
|
||||
size_t name_len, type_len, args_len;
|
||||
|
||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||
|
||||
|
@ -133,11 +148,13 @@ ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
|
|||
|
||||
name_len = ngx_strlen(v->name);
|
||||
type_len = ngx_strlen(v->type);
|
||||
args_len = ngx_strlen(v->args);
|
||||
|
||||
b = ngx_create_temp_buf(pool,
|
||||
sizeof("&call=publish") +
|
||||
sizeof("&name=") + name_len * 3 +
|
||||
sizeof("&type=") + type_len * 3);
|
||||
sizeof("&type=") + type_len * 3 +
|
||||
1 + args_len);
|
||||
if (b == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -153,6 +170,11 @@ ngx_rtmp_notify_publish_create(ngx_rtmp_session_t *s, void *arg,
|
|||
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);
|
||||
|
||||
if (args_len) {
|
||||
*b->last++ = '&';
|
||||
b->last = (u_char *)ngx_cpymem(b->last, v->args, args_len);
|
||||
}
|
||||
|
||||
/* HTTP header */
|
||||
hl = ngx_rtmp_netcall_http_format_header(nacf->publish_url, pool,
|
||||
cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
||||
|
@ -179,7 +201,7 @@ ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
|
|||
ngx_rtmp_notify_app_conf_t *nacf;
|
||||
ngx_chain_t *hl, *cl, *pl;
|
||||
ngx_buf_t *b;
|
||||
size_t name_len;
|
||||
size_t name_len, args_len;
|
||||
|
||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||
|
||||
|
@ -198,11 +220,12 @@ ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
|
|||
}
|
||||
|
||||
name_len = ngx_strlen(v->name);
|
||||
args_len = ngx_strlen(v->args);
|
||||
|
||||
b = ngx_create_temp_buf(pool,
|
||||
sizeof("&call=play") +
|
||||
sizeof("&name=") + name_len * 3
|
||||
+ 10 * 2 + 1);
|
||||
+ 10 * 2 + 1 + 1 + args_len);
|
||||
if (b == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -219,6 +242,11 @@ ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
|
|||
"&start=%uD&duration=%uD&reset=%d",
|
||||
(uint32_t)v->start, (uint32_t)v->duration, v->reset & 1);
|
||||
|
||||
if (args_len) {
|
||||
*b->last++ = '&';
|
||||
b->last = (u_char *)ngx_cpymem(b->last, v->args, args_len);
|
||||
}
|
||||
|
||||
/* HTTP header */
|
||||
hl = ngx_rtmp_netcall_http_format_header(nacf->play_url, pool,
|
||||
cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
||||
|
@ -236,6 +264,75 @@ ngx_rtmp_notify_play_create(ngx_rtmp_session_t *s, void *arg,
|
|||
}
|
||||
|
||||
|
||||
static ngx_chain_t *
|
||||
ngx_rtmp_notify_done_create(ngx_rtmp_session_t *s, void *arg,
|
||||
ngx_pool_t *pool)
|
||||
{
|
||||
ngx_rtmp_notify_app_conf_t *nacf;
|
||||
ngx_chain_t *hl, *cl, *pl;
|
||||
ngx_buf_t *b;
|
||||
size_t name_len, args_len;
|
||||
ngx_rtmp_notify_ctx_t *ctx;
|
||||
|
||||
nacf = ngx_rtmp_get_module_app_conf(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);
|
||||
|
||||
if (pl == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name_len = ctx ? ngx_strlen(ctx->name) : 0;
|
||||
args_len = ctx ? ngx_strlen(ctx->args) : 0;
|
||||
|
||||
b = ngx_create_temp_buf(pool,
|
||||
sizeof("&call=done") +
|
||||
sizeof("&name=") + name_len * 3
|
||||
+ 1 + args_len);
|
||||
if (b == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pl->buf = b;
|
||||
|
||||
b->last = ngx_cpymem(b->last, (u_char*)"&call=done",
|
||||
sizeof("&call=done") - 1);
|
||||
|
||||
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, 0);
|
||||
}
|
||||
|
||||
if (args_len) {
|
||||
*b->last++ = '&';
|
||||
b->last = (u_char *)ngx_cpymem(b->last, ctx->args, args_len);
|
||||
}
|
||||
|
||||
/* HTTP header */
|
||||
hl = ngx_rtmp_netcall_http_format_header(nacf->done_url, pool,
|
||||
cl->buf->last - cl->buf->pos + (pl->buf->last - pl->buf->pos),
|
||||
&ngx_rtmp_netcall_content_type_urlencoded);
|
||||
|
||||
if (hl == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hl->next = cl;
|
||||
cl->next = pl;
|
||||
pl->next = NULL;
|
||||
|
||||
return hl;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_notify_parse_http_retcode(ngx_rtmp_session_t *s,
|
||||
ngx_chain_t *in)
|
||||
|
@ -297,6 +394,26 @@ ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_rtmp_notify_save_name_args(ngx_rtmp_session_t *s,
|
||||
u_char name[NGX_RTMP_MAX_NAME], u_char args[NGX_RTMP_MAX_ARGS])
|
||||
{
|
||||
ngx_rtmp_notify_ctx_t *ctx;
|
||||
|
||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module);
|
||||
if (ctx == NULL) {
|
||||
ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_notify_ctx_t));
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_notify_module);
|
||||
}
|
||||
|
||||
ngx_memcpy(ctx->name, name, sizeof(name));
|
||||
ngx_memcpy(ctx->args, args, sizeof(args));
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_notify_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
||||
{
|
||||
|
@ -304,8 +421,16 @@ ngx_rtmp_notify_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
|||
ngx_rtmp_netcall_init_t ci;
|
||||
|
||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||
if (nacf == NULL || nacf->publish_url == NULL) {
|
||||
return next_publish(s, v);
|
||||
if (nacf == NULL) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (nacf->done_url) {
|
||||
ngx_rtmp_notify_save_name_args(s, v->name, v->args);
|
||||
}
|
||||
|
||||
if (nacf->publish_url == NULL) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
ngx_memzero(&ci, sizeof(ci));
|
||||
|
@ -316,6 +441,9 @@ ngx_rtmp_notify_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v)
|
|||
ci.argsize = sizeof(*v);
|
||||
|
||||
return ngx_rtmp_netcall_create(s, &ci);
|
||||
|
||||
next:
|
||||
return next_publish(s, v);
|
||||
}
|
||||
|
||||
|
||||
|
@ -326,8 +454,16 @@ ngx_rtmp_notify_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
|
|||
ngx_rtmp_netcall_init_t ci;
|
||||
|
||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||
if (nacf == NULL || nacf->play_url == NULL) {
|
||||
return next_play(s, v);
|
||||
if (nacf == NULL) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (nacf->done_url) {
|
||||
ngx_rtmp_notify_save_name_args(s, v->name, v->args);
|
||||
}
|
||||
|
||||
if (nacf->play_url == NULL) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
ngx_memzero(&ci, sizeof(ci));
|
||||
|
@ -338,6 +474,32 @@ ngx_rtmp_notify_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v)
|
|||
ci.argsize = sizeof(*v);
|
||||
|
||||
return ngx_rtmp_netcall_create(s, &ci);
|
||||
|
||||
next:
|
||||
return next_play(s, v);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_notify_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t
|
||||
*v)
|
||||
{
|
||||
ngx_rtmp_notify_app_conf_t *nacf;
|
||||
ngx_rtmp_netcall_init_t ci;
|
||||
|
||||
nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module);
|
||||
if (nacf == NULL || nacf->done_url == NULL) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
ngx_memzero(&ci, sizeof(ci));
|
||||
ci.url = nacf->done_url;
|
||||
ci.create = ngx_rtmp_notify_done_create;
|
||||
|
||||
ngx_rtmp_netcall_create(s, &ci);
|
||||
|
||||
next:
|
||||
return next_delete_stream(s, v);
|
||||
}
|
||||
|
||||
|
||||
|
@ -380,10 +542,15 @@ ngx_rtmp_notify_on_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
|
||||
nacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_notify_module);
|
||||
|
||||
if (name->len == sizeof("on_play") - 1) {
|
||||
nacf->play_url = u;
|
||||
} else { /* on_publish */
|
||||
nacf->publish_url = u;
|
||||
switch (name->data[4]) {
|
||||
case 'l': /* on_pLay */
|
||||
nacf->play_url = u;
|
||||
break;
|
||||
case 'u': /* on_pUblish */
|
||||
nacf->publish_url = u;
|
||||
break;
|
||||
case 'o': /* on_dOne */
|
||||
nacf->done_url = u;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
|
@ -399,6 +566,9 @@ ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf)
|
|||
next_play = ngx_rtmp_play;
|
||||
ngx_rtmp_play = ngx_rtmp_notify_play;
|
||||
|
||||
next_delete_stream = ngx_rtmp_delete_stream;
|
||||
ngx_rtmp_delete_stream = ngx_rtmp_notify_delete_stream;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue