From 11e14ee9282f2fdc5abbf8cfafa3fdad80b7f371 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Tue, 7 May 2013 17:43:03 +0400 Subject: [PATCH] implemented push/pull from on_play/on_publish --- ngx_rtmp_notify_module.c | 161 ++++++++++++++++++++++++++++++++------- 1 file changed, 132 insertions(+), 29 deletions(-) diff --git a/ngx_rtmp_notify_module.c b/ngx_rtmp_notify_module.c index d724e74..50f76d3 100644 --- a/ngx_rtmp_notify_module.c +++ b/ngx_rtmp_notify_module.c @@ -10,6 +10,7 @@ #include "ngx_rtmp_cmd_module.h" #include "ngx_rtmp_netcall_module.h" #include "ngx_rtmp_record_module.h" +#include "ngx_rtmp_relay_module.h" static ngx_rtmp_connect_pt next_connect; @@ -70,6 +71,7 @@ typedef struct { ngx_uint_t method; ngx_msec_t update_timeout; ngx_flag_t update_strict; + ngx_flag_t relay_redirect; } ngx_rtmp_notify_app_conf_t; @@ -180,6 +182,13 @@ static ngx_command_t ngx_rtmp_notify_commands[] = { offsetof(ngx_rtmp_notify_app_conf_t, update_strict), NULL }, + { ngx_string("notify_relay_redirect"), + 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, relay_redirect), + NULL }, + ngx_null_command }; @@ -230,6 +239,7 @@ ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf) nacf->method = NGX_CONF_UNSET; nacf->update_timeout = NGX_CONF_UNSET; nacf->update_strict = NGX_CONF_UNSET; + nacf->relay_redirect = NGX_CONF_UNSET; return nacf; } @@ -258,6 +268,7 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_msec_value(conf->update_timeout, prev->update_timeout, 30000); ngx_conf_merge_value(conf->update_strict, prev->update_strict, 0); + ngx_conf_merge_value(conf->relay_redirect, prev->relay_redirect, 0); return NGX_CONF_OK; } @@ -962,9 +973,13 @@ static ngx_int_t ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in) { - ngx_rtmp_publish_t *v = arg; - ngx_int_t rc; - u_char name[NGX_RTMP_MAX_NAME]; + ngx_rtmp_publish_t *v = arg; + ngx_int_t rc; + ngx_str_t local_name; + ngx_rtmp_relay_target_t target; + ngx_url_t *u; + ngx_rtmp_notify_app_conf_t *nacf; + u_char name[NGX_RTMP_MAX_NAME]; static ngx_str_t location = ngx_string("location"); @@ -974,19 +989,61 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, return NGX_ERROR; } - if (rc == NGX_AGAIN) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "notify: publish redirect received"); - - rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name, - sizeof(name) - 1); - if (rc > 0) { - *ngx_cpymem(v->name, name, rc) = 0; - ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, - "notify: publish redirect to '%s'", v->name); - } + if (rc != NGX_AGAIN) { + goto next; } + /* HTTP 3xx */ + + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "notify: publish redirect received"); + + rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name, + sizeof(name) - 1); + if (rc <= 0) { + goto next; + } + + if (ngx_strncmp(name, "rtmp://", 7)) { + *ngx_cpymem(v->name, name, rc) = 0; + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: publish redirect to '%s'", v->name); + goto next; + } + + /* push */ + + nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); + if (nacf->relay_redirect) { + *ngx_cpymem(v->name, name, rc) = 0; + } + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: push '%s' to '%s'", v->name, name); + + local_name.data = v->name; + local_name.len = ngx_strlen(v->name); + + ngx_memzero(&target, sizeof(target)); + + u = &target.url; + u->url = local_name; + u->url.data = name + 7; + u->url.len = rc - 7; + u->default_port = 1935; + u->uri_part = 1; + u->no_resolve = 1; /* want ip here */ + + if (ngx_parse_url(s->connection->pool, u) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: push failed '%V'", &local_name); + return NGX_ERROR; + } + + ngx_rtmp_relay_push(s, &local_name, &target); + +next: + return next_publish(s, v); } @@ -995,11 +1052,15 @@ static ngx_int_t ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in) { - ngx_rtmp_play_t *v = arg; - ngx_int_t rc; - u_char name[NGX_RTMP_MAX_NAME]; + ngx_rtmp_play_t *v = arg; + ngx_int_t rc; + ngx_str_t local_name; + ngx_rtmp_relay_target_t target; + ngx_url_t *u; + ngx_rtmp_notify_app_conf_t *nacf; + u_char name[NGX_RTMP_MAX_NAME]; - static ngx_str_t location = ngx_string("location"); + static ngx_str_t location = ngx_string("location"); rc = ngx_rtmp_notify_parse_http_retcode(s, in); if (rc == NGX_ERROR) { @@ -1007,19 +1068,61 @@ ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s, return NGX_ERROR; } - if (rc == NGX_AGAIN) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, - "notify: play redirect received"); - - rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name, - sizeof(name) - 1); - if (rc > 0) { - *ngx_cpymem(v->name, name, rc) = 0; - ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, - "notify: play redirect to '%s'", v->name); - } + if (rc != NGX_AGAIN) { + goto next; } + /* HTTP 3xx */ + + ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "notify: play redirect received"); + + rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name, + sizeof(name) - 1); + if (rc <= 0) { + goto next; + } + + if (ngx_strncmp(name, "rtmp://", 7)) { + *ngx_cpymem(v->name, name, rc) = 0; + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: play redirect to '%s'", v->name); + goto next; + } + + /* pull */ + + nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); + if (nacf->relay_redirect) { + *ngx_cpymem(v->name, name, rc) = 0; + } + + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: pull '%s' from '%s'", v->name, name); + + local_name.data = v->name; + local_name.len = ngx_strlen(v->name); + + ngx_memzero(&target, sizeof(target)); + + u = &target.url; + u->url = local_name; + u->url.data = name + 7; + u->url.len = rc - 7; + u->default_port = 1935; + u->uri_part = 1; + u->no_resolve = 1; /* want ip here */ + + if (ngx_parse_url(s->connection->pool, u) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "notify: pull failed '%V'", &local_name); + return NGX_ERROR; + } + + ngx_rtmp_relay_pull(s, &local_name, &target); + +next: + return next_play(s, v); }