diff --git a/ngx_rtmp_notify_module.c b/ngx_rtmp_notify_module.c index 2fcfffb..45661e3 100644 --- a/ngx_rtmp_notify_module.c +++ b/ngx_rtmp_notify_module.c @@ -191,6 +191,13 @@ static ngx_command_t ngx_rtmp_notify_commands[] = { offsetof(ngx_rtmp_notify_app_conf_t, relay_redirect), NULL }, + { ngx_string("notify_send_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, send_redirect), + NULL }, + ngx_null_command }; @@ -242,6 +249,7 @@ ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf) nacf->update_timeout = NGX_CONF_UNSET_MSEC; nacf->update_strict = NGX_CONF_UNSET; nacf->relay_redirect = NGX_CONF_UNSET; + nacf->send_redirect = NGX_CONF_UNSET; return nacf; } @@ -271,6 +279,7 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) 30000); ngx_conf_merge_value(conf->update_strict, prev->update_strict, 0); ngx_conf_merge_value(conf->relay_redirect, prev->relay_redirect, 0); + ngx_conf_merge_value(conf->send_redirect, prev->send_redirect, 0); return NGX_CONF_OK; } @@ -1045,7 +1054,20 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s, /* push */ nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - if (nacf->relay_redirect) { + + if (nacf->send_redirect) { + // Send 302 redirect and go next + + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "notify: send 302 redirect for stream '%s' to new location '%*s'", v->name, rc, name); + + ngx_rtmp_send_redirect_status("Publish here", name); + + goto next; + + } else if (nacf->relay_redirect) { + // Relay local streams, change name + ngx_rtmp_notify_set_name(v->name, NGX_RTMP_MAX_NAME, name, (size_t) rc); } diff --git a/ngx_rtmp_send.c b/ngx_rtmp_send.c index c65deec..0b75d0c 100644 --- a/ngx_rtmp_send.c +++ b/ngx_rtmp_send.c @@ -594,6 +594,96 @@ ngx_rtmp_send_play_status(ngx_rtmp_session_t *s, char *code, char* level, } +// ----------- Based on Adobe FMS 3 application.redirectConnection description --------- // + +ngx_chain_t * +ngx_rtmp_create_redirect_status(ngx_rtmp_session_t *s, char *desc, char *to_url) +{ + ngx_rtmp_header_t h; + static double trans; + + static ngx_rtmp_amf_elt_t out_inf_ex[] = { + + { NGX_RTMP_AMF_STRING, + ngx_string("code"), + NULL, 0 }, + + { NGX_RTMP_AMF_STRING, + ngx_string("redirect"), + NULL, 0 }, + }; + + static ngx_rtmp_amf_elt_t out_inf[] = { + + { NGX_RTMP_AMF_STRING, + ngx_string("code"), + NULL, 0 }, + + { NGX_RTMP_AMF_STRING, + ngx_string("level"), + NULL, 0 }, + + { NGX_RTMP_AMF_STRING, + ngx_string("description"), + NULL, 0 }, + + { NGX_RTMP_AMF_OBJECT, + ngx_string("ex"), + NULL, 0 }, + }; + + static ngx_rtmp_amf_elt_t out_elts[] = { + + { NGX_RTMP_AMF_STRING, + ngx_null_string, + "onStatus", 0 }, + + { NGX_RTMP_AMF_NUMBER, + ngx_null_string, + &trans, 0 }, + + { NGX_RTMP_AMF_NULL, + ngx_null_string, + NULL, 0 }, + + { NGX_RTMP_AMF_OBJECT, + ngx_null_string, + out_inf, + sizeof(out_inf) }, + }; + + ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, + "create: status code='%s' level='%s' description='%s' " + "ex.code='%s' redirect='%s'", + "NetConnection.Connect.Rejected", "Error", desc, "302", to_url); + + out_inf[0].data = "NetConnection.Connect.Rejected"; + out_inf[1].data = "Error"; + out_inf[2].data = desc; + out_inf_ex[0].data = "302"; + out_inf_ex[1].data = to_url; + out_inf[3].data = &out_inf_ex; + + memset(&h, 0, sizeof(h)); + + h.type = NGX_RTMP_MSG_AMF_META; + h.csid = NGX_RTMP_CSID_AMF; + h.msid = NGX_RTMP_MSID; + + return ngx_rtmp_create_amf(s, &h, out_elts, + sizeof(out_elts) / sizeof(out_elts[0])); +} + + +ngx_int_t +ngx_rtmp_send_redirect_status(ngx_rtmp_session_t *s, + char *desc, char *to_url) +{ + return ngx_rtmp_send_shared_packet(s, + ngx_rtmp_create_redirect_status(s, desc, to_url)); +} + + ngx_chain_t * ngx_rtmp_create_sample_access(ngx_rtmp_session_t *s) {