ngx——请求处理——listen

1. 代码分析

只考虑最简单指令

listen 81;
static char *
ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_srv_conf_t *cscf = conf;

    ngx_str_t              *value, size;
    ngx_url_t               u;   
    ngx_uint_t              n;   
    ngx_http_listen_opt_t   lsopt;

    cscf->listen = 1; 

    value = cf->args->elts;
                                                                                                                                                                                                                                                                               
    ngx_memzero(&u, sizeof(ngx_url_t));

    u.url = value[1];
    u.listen = 1; 
    u.default_port = 80;
    // 此时,u.url 为 "80",将 url 转换成 u.addrs
    if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
        if (u.err) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "%s in \"%V\" of the \"listen\" directive",
                               u.err, &u.url);
        }    

        return NGX_CONF_ERROR;
    }   

    ...
    // listen 80;的配置下, u.naddrs = 1
    // 将u.addrs 添加到 cscf中
    for (n = 0; n < u.naddrs; n++) {
        lsopt.sockaddr = u.addrs[n].sockaddr;
        lsopt.socklen = u.addrs[n].socklen;   // sizeof(struct sockaddr_in)
        lsopt.addr_text = u.addrs[n].name;    // 0.0.0.0:80
        lsopt.wildcard = ngx_inet_wildcard(lsopt.sockaddr);

        if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
    }

    return NGX_CONF_OK; 
}
  // 将 lsopt 信息 添加到 cmcf->ports 中
  // cmcf->ports 是以 端口号和IP族 为索引的 链表数组,每个数组为 相同 端口号和IP族 的 不同 ip地址 的元素 集合
  // 所以本函数是 根据 端口号和ip族找到  lsopt 对应 ports数组元素
  ngx_int_t
  ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
      ngx_http_listen_opt_t *lsopt)
  {
      in_port_t                   p;   
      ngx_uint_t                  i;   
      struct sockaddr            *sa; 
      ngx_http_conf_port_t       *port;
      ngx_http_core_main_conf_t  *cmcf;
  
      cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
  
      if (cmcf->ports == NULL) {
          cmcf->ports = ngx_array_create(cf->temp_pool, 2,
                                         sizeof(ngx_http_conf_port_t));
          if (cmcf->ports == NULL) {
              return NGX_ERROR;
          }    
      }    
  
      sa = lsopt->sockaddr;
      p = ngx_inet_get_port(sa);
  
      port = cmcf->ports->elts;                                                                                                                                                                                                                                                
      for (i = 0; i < cmcf->ports->nelts; i++) {
  
          if (p != port[i].port || sa->sa_family != port[i].family) {
              continue;
          }    
  
          /* a port is already in the port list */
  
          return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
      }    
  
      /* add a port to the port list */
  
      port = ngx_array_push(cmcf->ports);
      if (port == NULL) {
          return NGX_ERROR;
      }    
  
      port->family = sa->sa_family;
      port->port = p; 
      port->addrs.elts = NULL;
  
      return ngx_http_add_address(cf, cscf, port, lsopt);
  }
  // 
  static ngx_int_t
  ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
      ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
  {                                                                                                                                                                                                                                                                            
      ngx_http_conf_addr_t  *addr;
  
      if (port->addrs.elts == NULL) {
          if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
                             sizeof(ngx_http_conf_addr_t))
              != NGX_OK)
          {
              return NGX_ERROR;
          }
      }
  
      addr = ngx_array_push(&port->addrs);
      if (addr == NULL) {
          return NGX_ERROR;
      }
  
      addr->opt = *lsopt;  // lsopt 存储了地址,所以addr->opt可以找到 ip地址信息
      addr->hash.buckets = NULL;
      addr->hash.size = 0;
      addr->wc_head = NULL;
      addr->wc_tail = NULL;
  #if (NGX_PCRE)
      addr->nregex = 0;
      addr->regex = NULL;
  #endif
      addr->default_server = cscf;
      addr->servers.elts = NULL;
  
      return ngx_http_add_server(cf, cscf, addr);
  }
            
  // 将 server块配置 核心信息 添加到 ports
  static ngx_int_t
  ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
      ngx_http_conf_addr_t *addr)
  {
      ngx_uint_t                  i;
      ngx_http_core_srv_conf_t  **server;
  
      if (addr->servers.elts == NULL) {
          if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
                             sizeof(ngx_http_core_srv_conf_t *))
              != NGX_OK)
          {
              return NGX_ERROR;
          }
  
      } else {
          server = addr->servers.elts;
          for (i = 0; i < addr->servers.nelts; i++) {
              if (server[i] == cscf) {
                  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                     "a duplicate listen %V",
                                     &addr->opt.addr_text);
                  return NGX_ERROR;
              }
          }
      }
  
      server = ngx_array_push(&addr->servers);
      if (server == NULL) {
          return NGX_ERROR;
      }
  
      *server = cscf;
  
      return NGX_OK;
  }   

2. 数据结构

ngx——请求处理——listen

上一篇:nginx 配置日志格式并且采集POST请求信息放入日志


下一篇:ngx——naxsi——示例