mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-05-09 22:11:08 +02:00
Update:
- fix config option parse - append redirect support in on_connect handler - add support of rtmpdump handlers for RTMP commands - try to catch with FMLE
This commit is contained in:
parent
3497601b6b
commit
bb67548636
|
@ -27,7 +27,7 @@ ngx_rtmp_amf_reverse_copy(void *dst, void* src, size_t len)
|
|||
return dst;
|
||||
}
|
||||
|
||||
#define NGX_RTMP_AMF_DEBUG_SIZE 16
|
||||
#define NGX_RTMP_AMF_DEBUG_SIZE 72
|
||||
|
||||
#ifdef NGX_DEBUG
|
||||
static void
|
||||
|
|
|
@ -28,6 +28,8 @@ static char *ngx_rtmp_notify_on_app_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);
|
||||
static char *ngx_rtmp_notify_send_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
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 char * ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf,
|
||||
|
@ -70,16 +72,17 @@ typedef struct {
|
|||
ngx_url_t *url[NGX_RTMP_NOTIFY_APP_MAX];
|
||||
ngx_flag_t active;
|
||||
ngx_uint_t method;
|
||||
ngx_flag_t send_redirect;
|
||||
ngx_msec_t update_timeout;
|
||||
ngx_flag_t update_strict;
|
||||
ngx_flag_t relay_redirect;
|
||||
ngx_flag_t send_redirect;
|
||||
} ngx_rtmp_notify_app_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_url_t *url[NGX_RTMP_NOTIFY_SRV_MAX];
|
||||
ngx_uint_t method;
|
||||
ngx_flag_t send_redirect;
|
||||
} ngx_rtmp_notify_srv_conf_t;
|
||||
|
||||
|
||||
|
@ -194,9 +197,9 @@ static ngx_command_t ngx_rtmp_notify_commands[] = {
|
|||
|
||||
{ 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_notify_send_redirect,
|
||||
NGX_RTMP_APP_CONF_OFFSET,
|
||||
offsetof(ngx_rtmp_notify_app_conf_t, send_redirect),
|
||||
0,
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
|
@ -247,10 +250,10 @@ ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf)
|
|||
}
|
||||
|
||||
nacf->method = NGX_CONF_UNSET_UINT;
|
||||
nacf->send_redirect = NGX_CONF_UNSET;
|
||||
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;
|
||||
}
|
||||
|
@ -276,11 +279,11 @@ ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
ngx_conf_merge_uint_value(conf->method, prev->method,
|
||||
NGX_RTMP_NETCALL_HTTP_POST);
|
||||
ngx_conf_merge_value(conf->send_redirect, prev->send_redirect, 0);
|
||||
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);
|
||||
ngx_conf_merge_value(conf->send_redirect, prev->send_redirect, 0);
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
@ -302,6 +305,7 @@ ngx_rtmp_notify_create_srv_conf(ngx_conf_t *cf)
|
|||
}
|
||||
|
||||
nscf->method = NGX_CONF_UNSET_UINT;
|
||||
nscf->send_redirect = NGX_CONF_UNSET;
|
||||
|
||||
return nscf;
|
||||
}
|
||||
|
@ -320,6 +324,7 @@ ngx_rtmp_notify_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
|
||||
ngx_conf_merge_uint_value(conf->method, prev->method,
|
||||
NGX_RTMP_NETCALL_HTTP_POST);
|
||||
ngx_conf_merge_value(conf->send_redirect, prev->send_redirect, 0);
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
@ -967,7 +972,9 @@ ngx_rtmp_notify_connect_handle(ngx_rtmp_session_t *s,
|
|||
void *arg, ngx_chain_t *in)
|
||||
{
|
||||
ngx_rtmp_connect_t *v = arg;
|
||||
ngx_int_t rc;
|
||||
ngx_int_t rc, send;
|
||||
ngx_str_t local_name;
|
||||
ngx_rtmp_notify_srv_conf_t *nscf;
|
||||
u_char app[NGX_RTMP_MAX_NAME];
|
||||
|
||||
static ngx_str_t location = ngx_string("location");
|
||||
|
@ -977,19 +984,81 @@ ngx_rtmp_notify_connect_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: connect redirect received");
|
||||
|
||||
rc = ngx_rtmp_notify_parse_http_header(s, in, &location, app,
|
||||
sizeof(app) - 1);
|
||||
if (rc > 0) {
|
||||
*ngx_cpymem(v->app, app, rc) = 0;
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: connect redirect to '%s'", v->app);
|
||||
}
|
||||
if (rc != NGX_AGAIN) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* HTTP 3xx */
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: connect redirect received");
|
||||
|
||||
rc = ngx_rtmp_notify_parse_http_header(s, in, &location, app,
|
||||
sizeof(app) - 1);
|
||||
if (rc <= 0) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: parsed location '%*s'", rc, app);
|
||||
|
||||
/* switch app */
|
||||
|
||||
if (ngx_strncasecmp(app, (u_char *) "rtmp://", 7)) {
|
||||
*ngx_cpymem(v->app, app, rc) = 0;
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: connect redirect to '%s'", v->app);
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* redirect */
|
||||
|
||||
nscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_notify_module);
|
||||
|
||||
if (nscf->send_redirect) {
|
||||
// Send 302 redirect and go next
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: connect send 302 redirect");
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: -- for app '%s' to new location '%*s'", v->app, rc, app);
|
||||
|
||||
local_name.data = ngx_palloc(s->connection->pool, rc+1);
|
||||
local_name.len = rc;
|
||||
*ngx_cpymem(local_name.data, app, rc) = 0;
|
||||
|
||||
/* MAGICK HERE */
|
||||
|
||||
if (!ngx_strncasecmp(s->flashver.data, (u_char *) "FMLE/", 5)) {
|
||||
// Official method, by FMS SDK
|
||||
send = ngx_rtmp_send_redirect_status(s, "onStatus", "Connect here", local_name);
|
||||
send &= ngx_rtmp_send_redirect_status(s, "netStatus", "Connect here", local_name);
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: connect send(o) status = '%ui'", send == NGX_OK);
|
||||
} else {
|
||||
// Something by rtmpdump lib
|
||||
send = ngx_rtmp_send_redirect_status(s, "_error", "Connect here", local_name);
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: connect send(e) status = '%ui'", send == NGX_OK);
|
||||
}
|
||||
|
||||
ngx_pfree(s->connection->pool, local_name.data);
|
||||
|
||||
// Something by rtmpdump lib
|
||||
send = ngx_rtmp_send_close_method(s, "close");
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: connect send(e) close method = '%ui'", send == NGX_OK);
|
||||
|
||||
return send;
|
||||
// return next_disconnect(s);
|
||||
// Don't close connection here! Client must catch message and do it by itself.
|
||||
// goto next;
|
||||
}
|
||||
|
||||
next:
|
||||
|
||||
return next_connect(s, v);
|
||||
}
|
||||
|
||||
|
@ -1015,7 +1084,7 @@ 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;
|
||||
ngx_int_t rc, send;
|
||||
ngx_str_t local_name;
|
||||
ngx_rtmp_relay_target_t target;
|
||||
ngx_url_t *u;
|
||||
|
@ -1036,7 +1105,7 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s,
|
|||
|
||||
/* HTTP 3xx */
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: publish redirect received");
|
||||
|
||||
rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name,
|
||||
|
@ -1060,23 +1129,46 @@ ngx_rtmp_notify_publish_handle(ngx_rtmp_session_t *s,
|
|||
// Send 302 redirect and go next
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: send 302 redirect for stream '%s' to new location '%*s'", v->name, rc, name);
|
||||
"notify: publish send 302 redirect");
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: -- for stream '%s' to new location '%*s'", v->name, rc, name);
|
||||
|
||||
local_name.data = ngx_palloc(s->connection->pool, rc);
|
||||
local_name.data = ngx_palloc(s->connection->pool, rc+1);
|
||||
local_name.len = rc;
|
||||
*ngx_cpymem(local_name.data, name, rc) = 0;
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: check redirect to location: '%s'", local_name.data);
|
||||
/* MAGICK HERE */
|
||||
|
||||
ngx_rtmp_send_redirect_status(s, "Publish here", local_name);
|
||||
if (!ngx_strncasecmp(s->flashver.data, (u_char *) "FMLE/", 5)) {
|
||||
// Official method, by FMS SDK
|
||||
send = ngx_rtmp_send_redirect_status(s, "onStatus", "Connect here", local_name);
|
||||
send &= ngx_rtmp_send_redirect_status(s, "netStatus", "Connect here", local_name);
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: release location memory");
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: publish send(o) status = '%ui'", send == NGX_OK);
|
||||
} else {
|
||||
|
||||
// Something by rtmpdump lib
|
||||
send = ngx_rtmp_send_redirect_status(s, "_error", "Connect here", local_name);
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: publish send(e) status = '%ui'", send == NGX_OK);
|
||||
}
|
||||
|
||||
ngx_pfree(s->connection->pool, local_name.data);
|
||||
|
||||
goto next;
|
||||
ngx_rtmp_notify_clear_flag(s, NGX_RTMP_NOTIFY_PUBLISHING);
|
||||
// return send;
|
||||
|
||||
// Something by rtmpdump lib
|
||||
send = ngx_rtmp_send_close_method(s);
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"notify: publish send(e) close method = '%ui'", send == NGX_OK);
|
||||
|
||||
return send;
|
||||
// return next_disconnect(s);
|
||||
// Don't close connection here! Client must catch message and do it by itself.
|
||||
// goto next;
|
||||
|
||||
} else if (nacf->relay_redirect) {
|
||||
// Relay local streams, change name
|
||||
|
@ -1737,6 +1829,37 @@ ngx_rtmp_notify_method(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
static char *
|
||||
ngx_rtmp_notify_send_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_rtmp_notify_app_conf_t *nacf = conf;
|
||||
|
||||
ngx_rtmp_notify_srv_conf_t *nscf;
|
||||
ngx_str_t *value;
|
||||
|
||||
value = cf->args->elts;
|
||||
value++;
|
||||
|
||||
if (value->len == sizeof("on") - 1 &&
|
||||
ngx_strncasecmp(value->data, (u_char *) "on", value->len) == 0)
|
||||
{
|
||||
nacf->send_redirect = 1;
|
||||
|
||||
} else if (value->len == sizeof("off") - 1 &&
|
||||
ngx_strncasecmp(value->data, (u_char *) "off", value->len) == 0)
|
||||
{
|
||||
nacf->send_redirect = 0;
|
||||
|
||||
} else {
|
||||
return "got unexpected send_redirect value";
|
||||
}
|
||||
|
||||
nscf = ngx_rtmp_conf_get_module_srv_conf(cf, ngx_rtmp_notify_module);
|
||||
nscf->send_redirect = nacf->send_redirect;
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf)
|
||||
|
|
|
@ -491,7 +491,7 @@ ngx_rtmp_create_status(ngx_rtmp_session_t *s, char *code, char* level,
|
|||
NULL, 0 },
|
||||
|
||||
{ NGX_RTMP_AMF_OBJECT,
|
||||
ngx_string("info"),
|
||||
ngx_null_string,
|
||||
out_inf,
|
||||
sizeof(out_inf) },
|
||||
};
|
||||
|
@ -503,6 +503,7 @@ ngx_rtmp_create_status(ngx_rtmp_session_t *s, char *code, char* level,
|
|||
out_inf[0].data = level;
|
||||
out_inf[1].data = code;
|
||||
out_inf[2].data = desc;
|
||||
trans = 0;
|
||||
|
||||
memset(&h, 0, sizeof(h));
|
||||
|
||||
|
@ -597,18 +598,18 @@ 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, ngx_str_t to_url)
|
||||
ngx_rtmp_create_redirect_status(ngx_rtmp_session_t *s, char *callMethod, char *desc, ngx_str_t to_url)
|
||||
{
|
||||
ngx_rtmp_header_t h;
|
||||
static double trans;
|
||||
static double dtrans;
|
||||
static double dcode;
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"create redirect status: got data");
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"create redirect status: status code='%s' level='%s' "
|
||||
"ex.code=%ui ex.redirect='%s'",
|
||||
"NetConnection.Connect.Rejected", "Error", 302, to_url.data);
|
||||
"create redirect status: method='%s', status code='%s' level='%s' "
|
||||
"ex.code=%ui ex.redirect='%s'", callMethod,
|
||||
"NetConnection.Connect.Rejected", "error", 302, to_url.data);
|
||||
|
||||
static ngx_rtmp_amf_elt_t out_inf_ex_data[] = {
|
||||
|
||||
|
@ -624,12 +625,12 @@ ngx_rtmp_create_redirect_status(ngx_rtmp_session_t *s, char *desc, ngx_str_t to_
|
|||
static ngx_rtmp_amf_elt_t out_inf[] = {
|
||||
|
||||
{ NGX_RTMP_AMF_STRING,
|
||||
ngx_string("code"),
|
||||
NULL, 0 },
|
||||
ngx_string("level"),
|
||||
"error", 0 },
|
||||
|
||||
{ NGX_RTMP_AMF_STRING,
|
||||
ngx_string("level"),
|
||||
NULL, 0 },
|
||||
ngx_string("code"),
|
||||
"NetConnection.Connect.Rejected", 0 },
|
||||
|
||||
{ NGX_RTMP_AMF_STRING,
|
||||
ngx_string("description"),
|
||||
|
@ -645,18 +646,18 @@ ngx_rtmp_create_redirect_status(ngx_rtmp_session_t *s, char *desc, ngx_str_t to_
|
|||
|
||||
{ NGX_RTMP_AMF_STRING,
|
||||
ngx_null_string,
|
||||
"onStatus", 0 },
|
||||
NULL, 0 },
|
||||
|
||||
{ NGX_RTMP_AMF_NUMBER,
|
||||
ngx_null_string,
|
||||
&trans, 0 },
|
||||
&dtrans, 0 },
|
||||
|
||||
{ NGX_RTMP_AMF_NULL,
|
||||
ngx_null_string,
|
||||
NULL, 0 },
|
||||
|
||||
{ NGX_RTMP_AMF_OBJECT,
|
||||
ngx_string("info"),
|
||||
ngx_null_string,
|
||||
out_inf,
|
||||
sizeof(out_inf) },
|
||||
};
|
||||
|
@ -664,15 +665,15 @@ ngx_rtmp_create_redirect_status(ngx_rtmp_session_t *s, char *desc, ngx_str_t to_
|
|||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"create redirect status: set structure data");
|
||||
|
||||
out_inf[0].data = "NetConnection.Connect.Rejected";
|
||||
out_inf[1].data = "Error";
|
||||
out_elts[0].data = callMethod;
|
||||
out_inf[2].data = desc;
|
||||
dcode = 302;
|
||||
dtrans = 0;
|
||||
out_inf_ex_data[1].data = to_url.data;
|
||||
|
||||
memset(&h, 0, sizeof(h));
|
||||
ngx_memzero(&h, sizeof(h));
|
||||
|
||||
h.type = NGX_RTMP_MSG_AMF_META;
|
||||
h.type = NGX_RTMP_MSG_AMF_CMD;
|
||||
h.csid = NGX_RTMP_CSID_AMF;
|
||||
h.msid = NGX_RTMP_MSID;
|
||||
|
||||
|
@ -683,10 +684,52 @@ ngx_rtmp_create_redirect_status(ngx_rtmp_session_t *s, char *desc, ngx_str_t to_
|
|||
|
||||
ngx_int_t
|
||||
ngx_rtmp_send_redirect_status(ngx_rtmp_session_t *s,
|
||||
char *desc, ngx_str_t to_url)
|
||||
char *callMethod, char *desc, ngx_str_t to_url)
|
||||
{
|
||||
return ngx_rtmp_send_shared_packet(s,
|
||||
ngx_rtmp_create_redirect_status(s, desc, to_url));
|
||||
ngx_rtmp_create_redirect_status(s, callMethod, desc, to_url));
|
||||
}
|
||||
|
||||
|
||||
ngx_chain_t *
|
||||
ngx_rtmp_create_close_method(ngx_rtmp_session_t *s, char *methodName)
|
||||
{
|
||||
ngx_rtmp_header_t h;
|
||||
static double dtrans;
|
||||
|
||||
static ngx_rtmp_amf_elt_t out_elts[] = {
|
||||
|
||||
{ NGX_RTMP_AMF_STRING,
|
||||
ngx_null_string,
|
||||
NULL, 0 },
|
||||
|
||||
{ NGX_RTMP_AMF_NUMBER,
|
||||
ngx_null_string,
|
||||
&dtrans, 0 },
|
||||
};
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
|
||||
"create close method: set structure data");
|
||||
|
||||
out_elts[0].data = methodName;
|
||||
dtrans = 0;
|
||||
|
||||
ngx_memzero(&h, sizeof(h));
|
||||
|
||||
h.type = NGX_RTMP_MSG_AMF_CMD;
|
||||
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_close_method(ngx_rtmp_session_t *s, char *methodName)
|
||||
{
|
||||
return ngx_rtmp_send_shared_packet(s,
|
||||
ngx_rtmp_create_close_method(s, methodName));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue