static ngx_int_t ngx_rtmp_cmd_connect(ngx_rtmp_session_t *s, ngx_rtmp_connect_t *v) { ngx_rtmp_core_srv_conf_t *cscf; ngx_rtmp_core_app_conf_t **cacfp; ngx_uint_t n; size_t len; ngx_rtmp_header_t h; static double trans; static double capabilities = NGX_RTMP_CAPABILITIES; static double object_encoding = 0; static ngx_rtmp_amf_elt_t out_obj[] = { { NGX_RTMP_AMF_STRING, ngx_string("fmsVer"), NGX_RTMP_FMS_VERSION, 0 }, { NGX_RTMP_AMF_NUMBER, ngx_string("capabilities"), &capabilities, 0 }, }; static ngx_rtmp_amf_elt_t out_inf[] = { { NGX_RTMP_AMF_STRING, ngx_string("level"), "status", 0 }, { NGX_RTMP_AMF_STRING, ngx_string("code"), "NetConnection.Connect.Success", 0 }, { NGX_RTMP_AMF_STRING, ngx_string("description"), "Connection succeeded.", 0 }, { NGX_RTMP_AMF_NUMBER, ngx_string("objectEncoding"), &object_encoding, 0 } }; static ngx_rtmp_amf_elt_t out_elts[] = { { NGX_RTMP_AMF_STRING, ngx_null_string, "_result", 0 }, { NGX_RTMP_AMF_NUMBER, ngx_null_string, &trans, 0 }, { NGX_RTMP_AMF_OBJECT, ngx_null_string, out_obj, sizeof(out_obj) }, { NGX_RTMP_AMF_OBJECT, ngx_null_string, out_inf, sizeof(out_inf) }, }; if (s->connected) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "connect: duplicate connection"); return NGX_ERROR; } cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "connect: app='%s' flashver='%s' swf_url='%s' " "tc_url='%s' page_url='%s' acodecs=%uD vcodecs=%uD " "object_encoding=%ui", v->app, v->flashver, v->swf_url, v->tc_url, v->page_url, (uint32_t)v->acodecs, (uint32_t)v->vcodecs, (ngx_int_t)v->object_encoding); trans = v->trans; /* fill session parameters */ s->connected = 1; ngx_memzero(&h, sizeof(h)); h.csid = NGX_RTMP_CMD_CSID_AMF_INI; h.type = NGX_RTMP_MSG_AMF_CMD; #define NGX_RTMP_SET_STRPAR(name) \ s->name.len = ngx_strlen(v->name); \ s->name.data = ngx_palloc(s->connection->pool, s->name.len); \ ngx_memcpy(s->name.data, v->name, s->name.len) NGX_RTMP_SET_STRPAR(app); NGX_RTMP_SET_STRPAR(flashver); NGX_RTMP_SET_STRPAR(swf_url); NGX_RTMP_SET_STRPAR(tc_url); NGX_RTMP_SET_STRPAR(page_url); #undef NGX_RTMP_SET_STRPAR s->acodecs = v->acodecs; s->vcodecs = v->vcodecs; /* find application & set app_conf */ len = ngx_strlen(v->app); cacfp = cscf->applications.elts; for(n = 0; n < cscf->applications.nelts; ++n, ++cacfp) { if ((*cacfp)->name.len == len && !ngx_strncmp((*cacfp)->name.data, v->app, len)) { /* found app! */ s->app_conf = (*cacfp)->app_conf; break; } } if (s->app_conf == NULL) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "connect: application not found: '%s'", v->app); return NGX_ERROR; } object_encoding = v->object_encoding; /* send all replies */ return ngx_rtmp_send_ack_size(s, cscf->ack_window) != NGX_OK || ngx_rtmp_send_bandwidth(s, cscf->ack_window, NGX_RTMP_LIMIT_DYNAMIC) != NGX_OK || ngx_rtmp_send_chunk_size(s, cscf->chunk_size) != NGX_OK || ngx_rtmp_send_amf(s, &h, out_elts, sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK ? NGX_ERROR : NGX_OK; }
static ngx_int_t ngx_rtmp_authen_connect(ngx_rtmp_session_t *s, ngx_rtmp_connect_t *v) { ngx_rtmp_core_srv_conf_t *cscf; ngx_rtmp_core_app_conf_t **cacfp; ngx_rtmp_authen_app_conf_t *aacf; ngx_rtmp_netcall_init_t ci; ngx_uint_t n; size_t len; u_char *p; if (s->connected) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "connect (authen): duplicate connection"); return NGX_ERROR; } cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); p = ngx_strchr (v->app, '?'); if (p) { *p = 0; } ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "connect (authen): app='%s' flashver='%s' swf_url='%s' " "tc_url='%s' page_url='%s' acodecs=%uD vcodecs=%uD " "object_encoding=%ui", v->app, v->flashver, v->swf_url, v->tc_url, v->page_url, (uint32_t)v->acodecs, (uint32_t)v->vcodecs, (ngx_int_t)v->object_encoding); #define NGX_RTMP_SET_STRPAR(name) \ s->name.len = ngx_strlen(v->name); \ s->name.data = ngx_palloc(s->connection->pool, s->name.len); \ ngx_memcpy(s->name.data, v->name, s->name.len) NGX_RTMP_SET_STRPAR(app); NGX_RTMP_SET_STRPAR(flashver); NGX_RTMP_SET_STRPAR(swf_url); NGX_RTMP_SET_STRPAR(tc_url); NGX_RTMP_SET_STRPAR(page_url); #undef NGX_RTMP_SET_STRPAR s->acodecs = v->acodecs; s->vcodecs = v->vcodecs; /* find application & set app_conf */ len = ngx_strlen(v->app); cacfp = cscf->applications.elts; for(n = 0; n < cscf->applications.nelts; ++n, ++cacfp) { if ((*cacfp)->name.len == len && !ngx_strncmp((*cacfp)->name.data, v->app, len)) { /* found app! */ s->app_conf = (*cacfp)->app_conf; break; } } if (s->app_conf == NULL) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "connect: application not found: '%s'", v->app); return NGX_ERROR; } aacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_authen_module); if (aacf == NULL) { goto next; } if (aacf->connect_url == NULL) { goto next; } ngx_memzero(&ci, sizeof(ci)); ci.url = aacf->connect_url; ci.create = ngx_rtmp_authen_connect_create; ci.handle = ngx_rtmp_authen_connect_handle; ci.arg = v; ci.argsize = sizeof(*v); return ngx_rtmp_netcall_create(s, &ci) == NGX_OK ? NGX_AGAIN : NGX_ERROR; next: ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "connect (authen): bypassed"); return next_connect(s, v); }