ngx_http_init_connection()
void
ngx_http_init_connection(ngx_connection_t *c)
{
ngx_uint_t i;
ngx_event_t *rev;
struct sockaddr_in *sin;
ngx_http_port_t *port;
ngx_http_in_addr_t *addr;
ngx_http_log_ctx_t *ctx;
ngx_http_connection_t *hc;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
ngx_http_in6_addr_t *addr6;
#endif
// 分配一个ngx_http_connection_t结构体
hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
if (hc == NULL) {
ngx_http_close_connection(c);
return;
}
c->data = hc;
/* find the server configuration for the address:port */
port = c->listening->servers;
if (port->naddrs > 1) {
/*
* there are several addresses on this port and one of them
* is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
* is required to determine a server address
*/
if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
switch (c->local_sockaddr->sa_family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
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;
}
}
hc->addr_conf = &addr6[i].conf;
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) c->local_sockaddr;
addr = port->addrs;
/* the last address is "*" */
for (i = 0; i < port->naddrs - 1; i++) {
if (addr[i].addr == sin->sin_addr.s_addr) {
break;
}
}
hc->addr_conf = &addr[i].conf;
break;
}
} else {
switch (c->local_sockaddr->sa_family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
addr6 = port->addrs;
hc->addr_conf = &addr6[0].conf;
break;
#endif
default: /* AF_INET */
addr = port->addrs;
hc->addr_conf = &addr[0].conf;
break;
}
}
/* the default server configuration for the address:port */
hc->conf_ctx = hc->addr_conf->default_server->ctx;
ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
if (ctx == NULL) {
ngx_http_close_connection(c);
return;
}
ctx->connection = c;
ctx->request = NULL;
ctx->current_request = NULL;
c->log->connection = c->number;
c->log->handler = ngx_http_log_error;
c->log->data = ctx;
c->log->action = "waiting for request";
c->log_error = NGX_ERROR_INFO;
// 设置读事件的回调函数为ngx_http_wait_request_handler(),写事件的回调函数为ngx_http_empty_handler()
rev = c->read;
rev->handler = ngx_http_wait_request_handler;
c->write->handler = ngx_http_empty_handler;
#if (NGX_HTTP_V2)
if (hc->addr_conf->http2) {
rev->handler = ngx_http_v2_init;
}
#endif
#if (NGX_HTTP_SSL)
{
ngx_http_ssl_srv_conf_t *sscf;
sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
if (sscf->enable || hc->addr_conf->ssl) {
c->log->action = "SSL handshaking";
if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"no \"ssl_certificate\" is defined "
"in server listening on SSL port");
ngx_http_close_connection(c);
return;
}
hc->ssl = 1;
rev->handler = ngx_http_ssl_handshake;
}
}
#endif
if (hc->addr_conf->proxy_protocol) {
hc->proxy_protocol = 1;
c->log->action = "reading PROXY protocol";
}
// 若读事件准备就绪
if (rev->ready) {
/* the deferred accept(), iocp */
// 若使用了accept_mutex,将读事件加入到post队列中
if (ngx_use_accept_mutex) {
ngx_post_event(rev, &ngx_posted_events);
return;
}
// 若没有使用accept_mutex,直接调用ngx_http_wait_request_handler()
rev->handler(rev);
return;
}
// 若读事件未准备就绪,将读事件加入到定时器和epoll中
ngx_add_timer(rev, c->listening->post_accept_timeout);
ngx_reusable_connection(c, 1);
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
}
ngx_http_wait_request_handler()
http://lib.csdn.net/article/architecture/5760
static void
ngx_http_wait_request_handler(ngx_event_t *rev)
{
u_char *p;
size_t size;
ssize_t n;
ngx_buf_t *b;
ngx_connection_t *c;
ngx_http_connection_t *hc;
ngx_http_core_srv_conf_t *cscf;
c = rev->data;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler");
// 若当前连接的读事件已经超时
if (rev->timedout) {
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
ngx_http_close_connection(c);
return;
}
// 若当前连接要关闭
if (c->close) {
ngx_http_close_connection(c);
return;
}
hc = c->data;
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
size = cscf->client_header_buffer_size;
// 缓冲区
b = c->buffer;
if (b == NULL) {
b = ngx_create_temp_buf(c->pool, size);
if (b == NULL) {
ngx_http_close_connection(c);
return;
}
c->buffer = b;
} else if (b->start == NULL) {
b->start = ngx_palloc(c->pool, size);
if (b->start == NULL) {
ngx_http_close_connection(c);
return;
}
b->pos = b->start;
b->last = b->start;
b->end = b->last + size;
}
// 调用recv()接收数据
n = c->recv(c, b->last, size);
/* 若服务端正在接收数据,但还没接收完(即客户端正在发送数据,但还没发送完)
当客户端开始发送数据,套接字准备好读,epoll_wait()检测到读事件 */
if (n == NGX_AGAIN) {
if (!rev->timer_set) {
ngx_add_timer(rev, c->listening->post_accept_timeout);
ngx_reusable_connection(c, 1);
}
// 把当前连接的读事件加入到epoll中
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
/*
* We are trying to not hold c->buffer's memory for an idle connection.
*/
if (ngx_pfree(c->pool, b->start) == NGX_OK) {
b->start = NULL;
}
return;
}
// 若当前连接错误
if (n == NGX_ERROR) {
ngx_http_close_connection(c);
return;
}
// 若客户端关闭当前连接的读一半(接收到客户端发来的FIN)
if (n == 0) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client closed connection");
ngx_http_close_connection(c);
return;
}
b->last += n;
if (hc->proxy_protocol) {
hc->proxy_protocol = 0;
p = ngx_proxy_protocol_read(c, b->pos, b->last);
if (p == NULL) {
ngx_http_close_connection(c);
return;
}
b->pos = p;
if (b->pos == b->last) {
c->log->action = "waiting for request";
b->pos = b->start;
b->last = b->start;
ngx_post_event(rev, &ngx_posted_events);
return;
}
}
c->log->action = "reading client request line";
ngx_reusable_connection(c, 0);
// 创建ngx_http_request_t结构体并初始化部分参数
c->data = ngx_http_create_request(c);
if (c->data == NULL) {
ngx_http_close_connection(c);
return;
}
// 修改当前连接的读事件的回调函数为ngx_http_process_request_line()并调用该函数
rev->handler = ngx_http_process_request_line;
ngx_http_process_request_line(rev);
}