[-]
[+]
|
Changed |
nginx.spec
|
|
[-]
[+]
|
Changed |
nginx-rtmp-module-0.9.11.tar.bz2/config
^
|
@@ -18,6 +18,7 @@
ngx_rtmp_enotify_module \
ngx_rtmp_notify_module \
ngx_rtmp_log_module \
+ ngx_rtmp_limit_module \
"
@@ -72,6 +73,7 @@
$ngx_addon_dir/ngx_rtmp_enotify_module.c \
$ngx_addon_dir/ngx_rtmp_notify_module.c \
$ngx_addon_dir/ngx_rtmp_log_module.c \
+ $ngx_addon_dir/ngx_rtmp_limit_module.c \
"
CFLAGS="$CFLAGS -I$ngx_addon_dir"
|
[-]
[+]
|
Added |
nginx-rtmp-module-0.9.11.tar.bz2/ngx_rtmp_limit_module.c
^
|
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013 Roman Arutyunyan
+ */
+
+
+#include "ngx_rtmp.h"
+
+
+typedef struct {
+ ngx_int_t max_conn;
+ ngx_shm_zone_t *shm_zone;
+} ngx_rtmp_limit_main_conf_t;
+
+
+static ngx_str_t shm_name = ngx_string("rtmp_limit");
+
+
+static ngx_int_t ngx_rtmp_limit_postconfiguration(ngx_conf_t *cf);
+static void *ngx_rtmp_limit_create_main_conf(ngx_conf_t *cf);
+
+
+static ngx_command_t ngx_rtmp_limit_commands[] = {
+
+ { ngx_string("max_connections"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_RTMP_MAIN_CONF_OFFSET,
+ offsetof(ngx_rtmp_limit_main_conf_t, max_conn),
+ NULL },
+
+ ngx_null_command
+};
+
+
+static ngx_rtmp_module_t ngx_rtmp_limit_module_ctx = {
+ NULL, /* preconfiguration */
+ ngx_rtmp_limit_postconfiguration, /* postconfiguration */
+ ngx_rtmp_limit_create_main_conf, /* create main configuration */
+ NULL, /* init main configuration */
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+ NULL, /* create app configuration */
+ NULL /* merge app configuration */
+};
+
+
+ngx_module_t ngx_rtmp_limit_module = {
+ NGX_MODULE_V1,
+ &ngx_rtmp_limit_module_ctx, /* module context */
+ ngx_rtmp_limit_commands, /* module directives */
+ NGX_RTMP_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
+
+static void *
+ngx_rtmp_limit_create_main_conf(ngx_conf_t *cf)
+{
+ ngx_rtmp_limit_main_conf_t *lmcf;
+
+ lmcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_limit_main_conf_t));
+ if (lmcf == NULL) {
+ return NULL;
+ }
+
+ lmcf->max_conn = NGX_CONF_UNSET;
+
+ return lmcf;
+}
+
+
+static ngx_int_t
+ngx_rtmp_limit_connect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ ngx_chain_t *in)
+{
+ ngx_rtmp_limit_main_conf_t *lmcf;
+ ngx_slab_pool_t *shpool;
+ ngx_shm_zone_t *shm_zone;
+ uint32_t *nconn, n;
+ ngx_int_t rc;
+
+ lmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_limit_module);
+ if (lmcf->max_conn == NGX_CONF_UNSET) {
+ return NGX_OK;
+ }
+
+ shm_zone = lmcf->shm_zone;
+ shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
+ nconn = shm_zone->data;
+
+ ngx_shmtx_lock(&shpool->mutex);
+ n = ++*nconn;
+ ngx_shmtx_unlock(&shpool->mutex);
+
+ rc = n > lmcf->max_conn ? NGX_ERROR : NGX_OK;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "limit: inc conection counter: %uD", n);
+
+ if (rc != NGX_OK) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "limit: too many connections: %uD > %ui",
+ n, lmcf->max_conn);
+ }
+
+ return rc;
+}
+
+
+static ngx_int_t
+ngx_rtmp_limit_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
+ ngx_chain_t *in)
+{
+ ngx_rtmp_limit_main_conf_t *lmcf;
+ ngx_slab_pool_t *shpool;
+ ngx_shm_zone_t *shm_zone;
+ uint32_t *nconn, n;
+
+ lmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_limit_module);
+ if (lmcf->max_conn == NGX_CONF_UNSET) {
+ return NGX_OK;
+ }
+
+ shm_zone = lmcf->shm_zone;
+ shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
+ nconn = shm_zone->data;
+
+ ngx_shmtx_lock(&shpool->mutex);
+ n = --*nconn;
+ ngx_shmtx_unlock(&shpool->mutex);
+
+ (void) n;
+ ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "limit: dec conection counter: %uD", n);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_limit_shm_init(ngx_shm_zone_t *shm_zone, void *data)
+{
+ ngx_slab_pool_t *shpool;
+ uint32_t *nconn;
+
+ if (data) {
+ shm_zone->data = data;
+ return NGX_OK;
+ }
+
+ shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
+
+ nconn = ngx_slab_alloc(shpool, 4);
+ if (nconn == NULL) {
+ return NGX_ERROR;
+ }
+
+ *nconn = 0;
+
+ shm_zone->data = nconn;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_rtmp_limit_postconfiguration(ngx_conf_t *cf)
+{
+ ngx_rtmp_core_main_conf_t *cmcf;
+ ngx_rtmp_limit_main_conf_t *lmcf;
+ ngx_rtmp_handler_pt *h;
+
+ cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module);
+
+ h = ngx_array_push(&cmcf->events[NGX_RTMP_CONNECT]);
+ *h = ngx_rtmp_limit_connect;
+
+ h = ngx_array_push(&cmcf->events[NGX_RTMP_DISCONNECT]);
+ *h = ngx_rtmp_limit_disconnect;
+
+ lmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_limit_module);
+ if (lmcf->max_conn == NGX_CONF_UNSET) {
+ return NGX_OK;
+ }
+
+ lmcf->shm_zone = ngx_shared_memory_add(cf, &shm_name, ngx_pagesize * 2,
+ &ngx_rtmp_limit_module);
+ if (lmcf->shm_zone == NULL) {
+ return NGX_ERROR;
+ }
+
+ lmcf->shm_zone->init = ngx_rtmp_limit_shm_init;
+
+ return NGX_OK;
+}
|
[-]
[+]
|
Changed |
nginx-rtmp-module-0.9.11.tar.bz2/ngx_rtmp_play_module.c
^
|
@@ -929,6 +929,13 @@
default:
ctx->ncrs = 0;
}
+ /* 10th header byte is HTTP response header */
+ if (++ctx->nheader == 10 && *b->pos != (u_char) '2') {
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ "play: remote HTTP response code: %cxx",
+ *b->pos);
+ return NGX_ERROR;
+ }
}
if (b->pos == b->last) {
@@ -992,6 +999,7 @@
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_play_module);
ctx->ncrs = 0;
+ ctx->nheader = 0;
ctx->nbody = 0;
for ( ;; ) {
|
[-]
[+]
|
Changed |
nginx-rtmp-module-0.9.11.tar.bz2/ngx_rtmp_play_module.h
^
|
@@ -44,6 +44,7 @@
ngx_event_t send_evt;
unsigned playing:1;
ngx_uint_t ncrs;
+ ngx_uint_t nheader;
ngx_uint_t nbody;
size_t pfx_size;
ngx_str_t sfx;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-0.9.11.tar.bz2/ngx_rtmp_record_module.c
^
|
@@ -89,6 +89,14 @@
offsetof(ngx_rtmp_record_app_conf_t, unique),
NULL },
+ { ngx_string("record_append"),
+ NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|
+ NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_flag_slot,
+ NGX_RTMP_APP_CONF_OFFSET,
+ offsetof(ngx_rtmp_record_app_conf_t, append),
+ NULL },
+
{ ngx_string("record_lock"),
NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|
NGX_RTMP_REC_CONF|NGX_CONF_TAKE1,
@@ -184,6 +192,7 @@
racf->max_frames = NGX_CONF_UNSET;
racf->interval = NGX_CONF_UNSET;
racf->unique = NGX_CONF_UNSET;
+ racf->append = NGX_CONF_UNSET;
racf->lock_file = NGX_CONF_UNSET;
racf->notify = NGX_CONF_UNSET;
racf->url = NGX_CONF_UNSET_PTR;
@@ -208,6 +217,7 @@
ngx_conf_merge_size_value(conf->max_size, prev->max_size, 0);
ngx_conf_merge_size_value(conf->max_frames, prev->max_frames, 0);
ngx_conf_merge_value(conf->unique, prev->unique, 0);
+ ngx_conf_merge_value(conf->append, prev->append, 0);
ngx_conf_merge_value(conf->lock_file, prev->lock_file, 0);
ngx_conf_merge_value(conf->notify, prev->notify, 0);
ngx_conf_merge_msec_value(conf->interval, prev->interval,
@@ -421,6 +431,10 @@
ngx_rtmp_record_app_conf_t *rracf;
ngx_err_t err;
ngx_str_t path;
+ ngx_int_t mode, create_mode;
+ u_char buf[8], *p;
+ off_t file_size;
+ uint32_t tag_size, mlen, timestamp;
rracf = rctx->conf;
@@ -438,11 +452,15 @@
ngx_rtmp_record_make_path(s, rctx, &path);
+ mode = rracf->append ? NGX_FILE_RDWR : NGX_FILE_WRONLY;
+ create_mode = rracf->append ? NGX_FILE_CREATE_OR_OPEN : NGX_FILE_TRUNCATE;
+
ngx_memzero(&rctx->file, sizeof(rctx->file));
rctx->file.offset = 0;
rctx->file.log = s->connection->log;
- rctx->file.fd = ngx_open_file(path.data, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE,
+ rctx->file.fd = ngx_open_file(path.data, mode, create_mode,
NGX_FILE_DEFAULT_ACCESS);
+ ngx_str_set(&rctx->file.name, "recorded");
if (rctx->file.fd == NGX_INVALID_FILE) {
err = ngx_errno;
@@ -474,6 +492,74 @@
rracf->id.data ? (char *) rracf->id.data : "");
}
+ if (rracf->append) {
+
+ file_size = 0;
+ timestamp = 0;
+
+ file_size = lseek(rctx->file.fd, 0, SEEK_END);
+ if (file_size == (off_t) -1) {
+ ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
+ "record: %V seek failed", &rracf->id);
+ goto done;
+ }
+
+ if (file_size < 4) {
+ goto done;
+ }
+
+ if (ngx_read_file(&rctx->file, buf, 4, file_size - 4) != 4) {
+ ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
+ "record: %V tag size read failed", &rracf->id);
+ goto done;
+ }
+
+ p = (u_char *) &tag_size;
+ p[0] = buf[3];
+ p[1] = buf[2];
+ p[2] = buf[1];
+ p[3] = buf[0];
+
+ if (tag_size == 0 || tag_size + 4 > file_size) {
+ file_size = 0;
+ goto done;
+ }
+
+ if (ngx_read_file(&rctx->file, buf, 8, file_size - tag_size - 4) != 8)
+ {
+ ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
+ "record: %V tag read failed", &rracf->id);
+ goto done;
+ }
+
+ p = (u_char *) &mlen;
+ p[0] = buf[3];
+ p[1] = buf[2];
+ p[2] = buf[1];
+ p[3] = 0;
+
+ if (tag_size != mlen + 11) {
+ ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
+ "record: %V tag size mismatch: "
+ "tag_size=%uD, mlen=%uD", &rracf->id, tag_size, mlen);
+ goto done;
+ }
+
+ p = (u_char *) ×tamp;
+ p[3] = buf[7];
+ p[0] = buf[6];
+ p[1] = buf[5];
+ p[2] = buf[4];
+
+done:
+ rctx->file.offset = file_size;
+ rctx->time_shift = timestamp;
+
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
+ "record: append offset=%O, time=%uD, tag_size=%uD",
+ file_size, timestamp, tag_size);
+ }
+
return NGX_OK;
}
@@ -947,27 +1033,17 @@
return NGX_OK;
}
- if (rctx->file.offset == 0) {
- rctx->epoch = h->timestamp;
+ if (!rctx->initialized) {
- if (ngx_rtmp_record_write_header(&rctx->file) != NGX_OK) {
+ rctx->initialized = 1;
+ rctx->epoch = h->timestamp + rctx->time_shift;
+
+ if (rctx->file.offset == 0 &&
+ ngx_rtmp_record_write_header(&rctx->file) != NGX_OK)
+ {
ngx_rtmp_record_node_close(s, rctx);
return NGX_OK;
}
-#if 0
- /* metadata */
- if (codec_ctx->meta) {
- ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
- "record: writing metadata");
- ch.type = NGX_RTMP_MSG_AMF_META;
- ch.mlen = ngx_rtmp_record_get_chain_mlen(codec_ctx->meta);
- if (ngx_rtmp_record_write_frame(s, &ch, codec_ctx->meta)
- != NGX_OK)
- {
- return NGX_OK;
- }
- }
-#endif
}
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
|
[-]
[+]
|
Changed |
nginx-rtmp-module-0.9.11.tar.bz2/ngx_rtmp_record_module.h
^
|
@@ -26,6 +26,7 @@
ngx_msec_t interval;
ngx_str_t suffix;
ngx_flag_t unique;
+ ngx_flag_t append;
ngx_flag_t lock_file;
ngx_flag_t notify;
ngx_url_t *url;
@@ -39,10 +40,11 @@
ngx_rtmp_record_app_conf_t *conf;
ngx_file_t file;
ngx_uint_t nframes;
- uint32_t epoch;
+ uint32_t epoch, time_shift;
ngx_time_t last;
time_t timestamp;
unsigned failed:1;
+ unsigned initialized:1;
unsigned aac_header_sent:1;
unsigned avc_header_sent:1;
unsigned video_key_sent:1;
|
[-]
[+]
|
Changed |
nginx-rtmp-module-0.9.11.tar.bz2/ngx_rtmp_relay_module.c
^
|
@@ -10,6 +10,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 ngx_rtmp_close_stream_pt next_close_stream;
static ngx_int_t ngx_rtmp_relay_init_process(ngx_cycle_t *cycle);
@@ -48,6 +49,7 @@
ngx_log_t *log;
ngx_uint_t nbuckets;
ngx_msec_t buflen;
+ ngx_flag_t session_relay;
ngx_msec_t push_reconnect;
ngx_msec_t pull_reconnect;
ngx_rtmp_relay_ctx_t **ctx;
@@ -110,6 +112,13 @@
offsetof(ngx_rtmp_relay_app_conf_t, pull_reconnect),
NULL },
+ { ngx_string("session_relay"),
+ 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_relay_app_conf_t, session_relay),
+ NULL },
+
ngx_null_command
};
@@ -176,6 +185,7 @@
racf->nbuckets = 1024;
racf->log = &cf->cycle->new_log;
racf->buflen = NGX_CONF_UNSET;
+ racf->session_relay = NGX_CONF_UNSET;
racf->push_reconnect = NGX_CONF_UNSET;
racf->pull_reconnect = NGX_CONF_UNSET;
@@ -192,6 +202,7 @@
conf->ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_relay_ctx_t *)
* conf->nbuckets);
+ ngx_conf_merge_value(conf->session_relay, prev->session_relay, 0);
ngx_conf_merge_msec_value(conf->buflen, prev->buflen, 5000);
ngx_conf_merge_msec_value(conf->push_reconnect, prev->push_reconnect,
3000);
@@ -1293,8 +1304,8 @@
}
-static ngx_int_t
-ngx_rtmp_relay_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t *v)
+static void
+ngx_rtmp_relay_close(ngx_rtmp_session_t *s)
{
ngx_rtmp_relay_app_conf_t *racf;
ngx_rtmp_relay_ctx_t *ctx, **cctx;
@@ -1304,16 +1315,16 @@
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_relay_module);
if (ctx == NULL) {
- goto next;
+ return;
}
if (s->static_relay) {
ngx_add_timer(ctx->static_evt, racf->pull_reconnect);
- goto next;
+ return;
}
if (ctx->publish == NULL) {
- goto next;
+ return;
}
/* play end disconnect? */
@@ -1340,7 +1351,7 @@
{
ngx_uint_t n = 0;
for (cctx = &ctx->publish->play; *cctx; cctx = &(*cctx)->next, ++n);
- ngx_log_debug3(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0,
+ ngx_log_debug3(NGX_LOG_DEBUG_RTMP, ctx->session->connection->log, 0,
"relay: play left after disconnect app='%V' name='%V': %ui",
&ctx->app, &ctx->name, n);
}
@@ -1356,7 +1367,7 @@
ctx->publish = NULL;
- goto next;
+ return;
}
/* publish end disconnect */
@@ -1383,8 +1394,28 @@
if (*cctx) {
*cctx = ctx->next;
}
+}
+
+
+static ngx_int_t
+ngx_rtmp_relay_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v)
+{
+ ngx_rtmp_relay_app_conf_t *racf;
+
+ racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_relay_module);
+ if (racf && !racf->session_relay) {
+ ngx_rtmp_relay_close(s);
+ }
+
+ return next_close_stream(s, v);
+}
+
+
+static ngx_int_t
+ngx_rtmp_relay_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t *v)
+{
+ ngx_rtmp_relay_close(s);
-next:
return next_delete_stream(s, v);
}
@@ -1624,6 +1655,9 @@
next_delete_stream = ngx_rtmp_delete_stream;
ngx_rtmp_delete_stream = ngx_rtmp_relay_delete_stream;
+ next_close_stream = ngx_rtmp_close_stream;
+ ngx_rtmp_close_stream = ngx_rtmp_relay_close_stream;
+
ch = ngx_array_push(&cmcf->amf);
ngx_str_set(&ch->name, "_result");
|