Mercurial > hg > nginx-quic
view src/imap/ngx_imap.c @ 1050:5d9451a01c5d
add comment
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 18 Jan 2007 20:23:16 +0000 |
parents | 5e8fb59c18c1 |
children |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> #include <ngx_imap.h> static char *ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static int ngx_libc_cdecl ngx_imap_cmp_conf_in_addrs(const void *one, const void *two); ngx_uint_t ngx_imap_max_module; static ngx_command_t ngx_imap_commands[] = { { ngx_string("imap"), NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, ngx_imap_block, 0, 0, NULL }, ngx_null_command }; static ngx_core_module_t ngx_imap_module_ctx = { ngx_string("imap"), NULL, NULL }; ngx_module_t ngx_imap_module = { NGX_MODULE_V1, &ngx_imap_module_ctx, /* module context */ ngx_imap_commands, /* module directives */ NGX_CORE_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING }; static char * ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; u_char *text; size_t len; ngx_uint_t i, a, l, m, mi, s, p, last, bind_all, done; ngx_conf_t pcf; ngx_array_t in_ports; ngx_listening_t *ls; ngx_imap_listen_t *imls; ngx_imap_module_t *module; ngx_imap_in_port_t *imip; ngx_imap_conf_ctx_t *ctx; ngx_imap_conf_in_port_t *in_port; ngx_imap_conf_in_addr_t *in_addr; ngx_imap_core_srv_conf_t **cscfp; ngx_imap_core_main_conf_t *cmcf; /* the main imap context */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_imap_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } *(ngx_imap_conf_ctx_t **) conf = ctx; /* count the number of the http modules and set up their indices */ ngx_imap_max_module = 0; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_IMAP_MODULE) { continue; } ngx_modules[m]->ctx_index = ngx_imap_max_module++; } /* the imap main_conf context, it is the same in the all imap contexts */ ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_imap_max_module); if (ctx->main_conf == NULL) { return NGX_CONF_ERROR; } /* * the imap null srv_conf context, it is used to merge * the server{}s' srv_conf's */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_imap_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } /* * create the main_conf's, the null srv_conf's, and the null loc_conf's * of the all imap modules */ for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_IMAP_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); if (ctx->main_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_srv_conf) { ctx->srv_conf[mi] = module->create_srv_conf(cf); if (ctx->srv_conf[mi] == NULL) { return NGX_CONF_ERROR; } } } /* parse inside the imap{} block */ pcf = *cf; cf->ctx = ctx; cf->module_type = NGX_IMAP_MODULE; cf->cmd_type = NGX_IMAP_MAIN_CONF; rv = ngx_conf_parse(cf, NULL); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } /* init imap{} main_conf's, merge the server{}s' srv_conf's */ cmcf = ctx->main_conf[ngx_imap_core_module.ctx_index]; cscfp = cmcf->servers.elts; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_IMAP_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; /* init imap{} main_conf's */ if (module->init_main_conf) { rv = module->init_main_conf(cf, ctx->main_conf[mi]); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } } for (s = 0; s < cmcf->servers.nelts; s++) { /* merge the server{}s' srv_conf's */ if (module->merge_srv_conf) { rv = module->merge_srv_conf(cf, ctx->srv_conf[mi], cscfp[s]->ctx->srv_conf[mi]); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } } } } /* imap{}'s cf->ctx was needed while the configuration merging */ *cf = pcf; if (ngx_array_init(&in_ports, cf->temp_pool, 4, sizeof(ngx_imap_conf_in_port_t)) != NGX_OK) { return NGX_CONF_ERROR; } imls = cmcf->listen.elts; for (l = 0; l < cmcf->listen.nelts; l++) { /* AF_INET only */ in_port = in_ports.elts; for (p = 0; p < in_ports.nelts; p++) { if (in_port[p].port == imls[l].port) { in_port = &in_port[p]; goto found; } } in_port = ngx_array_push(&in_ports); if (in_port == NULL) { return NGX_CONF_ERROR; } in_port->port = imls[l].port; if (ngx_array_init(&in_port->addrs, cf->temp_pool, 2, sizeof(ngx_imap_conf_in_addr_t)) != NGX_OK) { return NGX_CONF_ERROR; } found: in_addr = ngx_array_push(&in_port->addrs); if (in_addr == NULL) { return NGX_CONF_ERROR; } in_addr->addr = imls[l].addr; in_addr->ctx = imls[l].ctx; in_addr->bind = imls[l].bind; } /* optimize the lists of ports and addresses */ /* AF_INET only */ in_port = in_ports.elts; for (p = 0; p < in_ports.nelts; p++) { ngx_qsort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts, sizeof(ngx_imap_conf_in_addr_t), ngx_imap_cmp_conf_in_addrs); in_addr = in_port[p].addrs.elts; last = in_port[p].addrs.nelts; /* * if there is the binding to the "*:port" then we need to bind() * to the "*:port" only and ignore the other bindings */ if (in_addr[last - 1].addr == INADDR_ANY) { in_addr[last - 1].bind = 1; bind_all = 0; } else { bind_all = 1; } for (a = 0; a < last; /* void */ ) { if (!bind_all && !in_addr[a].bind) { a++; continue; } ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr, in_port[p].port); if (ls == NULL) { return NGX_CONF_ERROR; } ls->backlog = -1; ls->rcvbuf = -1; ls->sndbuf = -1; ls->addr_ntop = 1; ls->handler = ngx_imap_init_connection; ls->pool_size = 256; /* STUB */ ls->log = *cf->cycle->new_log; ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; /**/ imip = ngx_palloc(cf->pool, sizeof(ngx_imap_in_port_t)); if (imip == NULL) { return NGX_CONF_ERROR; } ls->servers = imip; in_addr = in_port[p].addrs.elts; if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) { imip->naddrs = 1; done = 0; } else if (in_port[p].addrs.nelts > 1 && in_addr[last - 1].addr == INADDR_ANY) { imip->naddrs = last; done = 1; } else { imip->naddrs = 1; done = 0; } #if 0 ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "%ui: %V %d %ui %ui", a, &ls->addr_text, in_addr[a].bind, imip->naddrs, last); #endif imip->addrs = ngx_pcalloc(cf->pool, imip->naddrs * sizeof(ngx_imap_in_addr_t)); if (imip->addrs == NULL) { return NGX_CONF_ERROR; } for (i = 0; i < imip->naddrs; i++) { imip->addrs[i].addr = in_addr[i].addr; imip->addrs[i].ctx = in_addr[i].ctx; text = ngx_palloc(cf->pool, INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1); if (text == NULL) { return NGX_CONF_ERROR; } len = ngx_inet_ntop(AF_INET, &in_addr[i].addr, text, INET_ADDRSTRLEN); len = ngx_sprintf(text + len, ":%d", in_port[p].port) - text; imip->addrs[i].addr_text.len = len; imip->addrs[i].addr_text.data = text; } if (done) { break; } in_addr++; in_port[p].addrs.elts = in_addr; last--; a = 0; } } return NGX_CONF_OK; } static int ngx_libc_cdecl ngx_imap_cmp_conf_in_addrs(const void *one, const void *two) { ngx_imap_conf_in_addr_t *first, *second; first = (ngx_imap_conf_in_addr_t *) one; second = (ngx_imap_conf_in_addr_t *) two; if (first->addr == INADDR_ANY) { /* the INADDR_ANY must be the last resort, shift it to the end */ return 1; } if (first->bind && !second->bind) { /* shift explicit bind()ed addresses to the start */ return -1; } if (!first->bind && second->bind) { /* shift explicit bind()ed addresses to the start */ return 1; } /* do not sort by default */ return 0; }