rtmp用户请求连接建立

  上一节,我们介绍了rtmp模块的初始化;在上一节中,我们提到了,当有rtmp模块的请求到达时,nginx处理网络事件的event模块会回调rtmp模块的ngx_rtmp_init_connection接口,本节中,我们将分析一下RTMP模块是如何处理连接请求的。

我们首先看一下ngx_rtmp_init_connection该函数的函数体,在函数体部分有对关键部分的解释说明:

void
ngx_rtmp_init_connection(ngx_connection_t *c)
{
    ngx_uint_t             i;
    ngx_rtmp_port_t       *port;
    struct sockaddr       *sa;
    struct sockaddr_in    *sin;
    ngx_rtmp_in_addr_t    *addr;
    ngx_rtmp_session_t    *s;
    ngx_rtmp_addr_conf_t  *addr_conf;
    ngx_int_t              unix_socket;
#if (NGX_HAVE_INET6)
    struct sockaddr_in6   *sin6;
    ngx_rtmp_in6_addr_t   *addr6;
#endif
	//该变量是全局变量,用来统计rtmp模块的请求总数
    ++ngx_rtmp_naccepted;

    /* find the server configuration for the address:port */

    /* AF_INET only */
    //由于server域配置的是监听的端口,在多网卡机器上,会出现同一个端口port,有多个ip监听的情况,所以需要知道,具体请求时哪个ip地址上来的
    port = c->listening->servers;
    unix_socket = 0;

    if (port->naddrs > 1) {
    //当该端口port上,存在多个ip地址,也就是说多个ip地址在监听这个端口的情况
        /*
         * There are several addresses on this port and one of them
         * is the "*:port" wildcard so getsockname() is needed to determine
         * the server address.
         *
         * AcceptEx() already gave this address.
         */
         //获取该处理该连接请求的本地IP地址,也就是监听的ip地址,这个地址可以更具fd获取到
        if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
            ngx_rtmp_close_connection(c);
            return;
        }

        sa = c->local_sockaddr;

        switch (sa->sa_family) {

#if (NGX_HAVE_INET6)
        case AF_INET6:
            sin6 = (struct sockaddr_in6 *) sa;

            addr6 = port->addrs;

            /* the last address is "*" */

            for (i = 0; i < port->naddrs - 1; i++) {
                if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
                    break;
                }
            }

            addr_conf = &addr6[i].conf;

            break;
#endif

        case AF_UNIX:
            unix_socket = 1;
            /* fall through */

        default: /* AF_INET */
            sin = (struct sockaddr_in *) sa;

            addr = port->addrs;

            /* the last address is "*" */
            //根据fd获取到的地址,匹配配置文件中配置的监听地址,以获取配置文件中关于该监听地址的配置信息
            for (i = 0; i < port->naddrs - 1; i++) {
                if (addr[i].addr == sin->sin_addr.s_addr) {
                    break;
                }
            }

            addr_conf = &addr[i].conf;

            break;
        }

    } else {
    //当端口只被一个地址监听的情况,获取配置中的监听信息
        switch (c->local_sockaddr->sa_family) {

#if (NGX_HAVE_INET6)
        case AF_INET6:
            addr6 = port->addrs;
            addr_conf = &addr6[0].conf;
            break;
#endif

        case AF_UNIX:
            unix_socket = 1;
            /* fall through */

        default: /* AF_INET */
            addr = port->addrs;
            addr_conf = &addr[0].conf;
            break;
        }
    }

    ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client connected '%V'",
                  c->number, &c->addr_text);
    //当没有一个用户请求,rtmp模块都会为他创建一个会话的session,后续用户的操作,都是基于这个session尽情的,在这个地方去为用户的请求创建session
    s = ngx_rtmp_init_session(c, addr_conf);
    if (s == NULL) {
        return;
    }

    /* only auto-pushed connections are
     * done through unix socket */
    //设置该session的auto_push标志为,只有本机通信的时候,才会时auto_push
    s->auto_pushed = unix_socket;
    //根据地址的配置信息,查看该地址时候时代理协议的地址,不同的监听地址,会进行不同的处理
    if (addr_conf->proxy_protocol) {
        ngx_rtmp_proxy_protocol(s);

    } else {
    //当该地址时rtmp真实服务的地址的话,就进行rtmp协议中的三次握手
        ngx_rtmp_handshake(s);
    }
}

  上面给出了ngx_rtmp_init_connection函数处理用户连接请求的主要过程,在整个请求处理过程中,有以下几个重要的地方
  1、获取监听的ip的相关配置信息
  2、为用户请求创建session
  3、针对于ip地址信息,做不同的处理

 接下来我们看一下时如何为用户创建会话的session的

//从ngx_rtmp_init_connection函数中,我们可以知道,调用的两个参数,一个为用户请求的connection信息,一个为监听地址的配置信息
ngx_rtmp_session_t *ngx_rtmp_init_session(ngx_connection_t *c, ngx_rtmp_addr_conf_t *addr_conf)
{
    ngx_rtmp_session_t             *s;
    ngx_rtmp_core_srv_conf_t       *cscf;
    ngx_rtmp_error_log_ctx_t       *ctx;
    //为session创建内存空间
    s = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_session_t) +
            sizeof(ngx_chain_t *) * ((ngx_rtmp_core_srv_conf_t *)
                addr_conf->ctx-> srv_conf[ngx_rtmp_core_module
                    .ctx_index])->out_queue);
    if (s == NULL) {
        ngx_rtmp_close_connection(c);
        return NULL;
    }
    
    //将配置文件rtmp{}域和所属的server{}域的信息拷贝到用户的session中
    s->main_conf = addr_conf->ctx->main_conf;
    s->srv_conf = addr_conf->ctx->srv_conf;
    //将地址信息拷贝到session域中
    s->addr_text = &addr_conf->addr_text;
	//将session的地址存放到connection信息的data指针中,也可以理解为将session和connect绑定
    c->data = s;
    //指定session时属于哪个connection对象的
    s->connection = c;

	//为该用户连接分配日志存储空间并设置日志相关的信息
    ctx = ngx_palloc(c->pool, sizeof(ngx_rtmp_error_log_ctx_t));
    if (ctx == NULL) {
        ngx_rtmp_close_connection(c);
        return NULL;
    }

    ctx->client = &c->addr_text;
    ctx->session = s;

    c->log->connection = c->number;
    c->log->handler = ngx_rtmp_log_error;
    c->log->data = ctx;
    c->log->action = NULL;

    c->log_error = NGX_ERROR_INFO;

	//为,欸一个模块分配一个指针数据空间,以备后用
    s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_rtmp_max_module);
    if (s->ctx == NULL) {
        ngx_rtmp_close_connection(c);
        return NULL;
    }
	//获取所在的server{}域的配置信息
    cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
    //为session设置相关的参数信息,这些信息都是在server{}域配置信息中配置的
    s->out_queue = cscf->out_queue;
    s->out_cork = cscf->out_cork;
    s->in_streams = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_stream_t)
            * cscf->max_streams);
    if (s->in_streams == NULL) {
        ngx_rtmp_close_connection(c);
        return NULL;
    }

#if (nginx_version >= 1007005)
    ngx_queue_init(&s->posted_dry_events);
#endif
	//设置当前的时间
    s->epoch = ngx_current_msec;
    s->timeout = cscf->timeout;
    s->buflen = cscf->buflen;
    ngx_rtmp_set_chunk_size(s, NGX_RTMP_DEFAULT_CHUNK_SIZE);//设置当前默认的chunk的size大小,默认为128byte

	//触发rtmp的connect事件
    if (ngx_rtmp_fire_event(s, NGX_RTMP_CONNECT, NULL, NULL) != NGX_OK) {
        ngx_rtmp_finalize_session(s);
        return NULL;
    }
    //最后返回创建好的session
    return s;
}

NGX_RTMP_CONNECT事件是在rtmp_limit模块中的,主要就是校验请求是否超过能够处理的上线的,后面我们在分模块处理的时候,将会做详细介绍;
  这就是创建session的整个过程,执行完后,用户连接请求处理成功,并且为用户分配了一个session,后续用户的所有请求操作都是基于这个session进行

总结:
  上面这个就是rtmp模块处理用户连接请求的过程,这个过程中主要就是为用户创建一个session,并将session和用户连接的connection对象关联起来

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

brid.huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值