コード例 #1
0
static void
ngx_stream_return_write_handler(ngx_event_t *ev)
{
    ssize_t                   n;
    ngx_buf_t                *b;
    ngx_connection_t         *c;
    ngx_stream_session_t     *s;
    ngx_stream_return_ctx_t  *ctx;

    c = ev->data;
    s = c->data;

    if (ev->timedout) {
        ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out");
        ngx_stream_close_connection(c);
        return;
    }

    if (ev->ready) {
        ctx = ngx_stream_get_module_ctx(s, ngx_stream_return_module);

        b = &ctx->buf;

        n = c->send(c, b->pos, b->last - b->pos);
        if (n == NGX_ERROR) {
            ngx_stream_close_connection(c);
            return;
        }

        if (n > 0) {
            b->pos += n;

            if (b->pos == b->last) {
                ngx_stream_close_connection(c);
                return;
            }
        }
    }

    if (ngx_handle_write_event(ev, 0) != NGX_OK) {
        ngx_stream_close_connection(c);
        return;
    }

    ngx_add_timer(ev, 5000);
}
コード例 #2
0
ファイル: ngx_stream_hello_module.c プロジェクト: lw1a2/test
static void
ngx_stream_hello_handler(ngx_stream_session_t *s)
{
    ngx_stream_hello_srv_conf_t *hscf;

    hscf = ngx_stream_get_module_srv_conf(s, ngx_stream_hello_module);

    s->connection->send(s->connection, hscf->hello.data, hscf->hello.len);
    ngx_stream_close_connection(s->connection);
}
コード例 #3
0
static void
ngx_stream_return_handler(ngx_stream_session_t *s)
{
    ngx_str_t                      text;
    ngx_connection_t              *c;
    ngx_stream_return_ctx_t       *ctx;
    ngx_stream_return_srv_conf_t  *rscf;

    c = s->connection;

    c->log->action = "returning text";

    rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_return_module);

    if (ngx_stream_complex_value(s, &rscf->text, &text) != NGX_OK) {
        ngx_stream_close_connection(c);
        return;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
                   "stream return text: \"%V\"", &text);

    if (text.len == 0) {
        ngx_stream_close_connection(c);
        return;
    }

    ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_return_ctx_t));
    if (ctx == NULL) {
        ngx_stream_close_connection(c);
        return;
    }

    ngx_stream_set_ctx(s, ctx, ngx_stream_return_module);

    ctx->buf.pos = text.data;
    ctx->buf.last = text.data + text.len;

    c->write->handler = ngx_stream_return_write_handler;

    ngx_stream_return_write_handler(c->write);
}
コード例 #4
0
static void
ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
{
    if (!c->ssl->handshaked) {
        ngx_stream_close_connection(c);
        return;
    }

    if (c->read->timer_set) {
        ngx_del_timer(c->read);
    }

    ngx_stream_init_session(c);
}
コード例 #5
0
ファイル: conn_srv.c プロジェクト: a1406/nginx_proxy
static void conn_srv_close_connection(ngx_connection_t *c)
{
    conn_node_data *conn_node = c->data;
	if (!conn_node)
		goto done;
	int ret;
	do {
		ret = del_list_buf(&conn_node->recv);
	} while (ret == 0);
	do {
		ret = del_list_buf(&conn_node->send);
	} while (ret == 0);
done:
	ngx_stream_close_connection(c);
}
コード例 #6
0
static void
ngx_stream_init_session(ngx_connection_t *c)
{
    ngx_stream_session_t        *s;
    ngx_stream_core_srv_conf_t  *cscf;

    s = c->data;
    c->log->action = "handling client connection";

    cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);

    s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_stream_max_module);
    if (s->ctx == NULL) {
        ngx_stream_close_connection(c);
        return;
    }

    cscf->handler(s);
}
コード例 #7
0
static void
ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_int_t rc)
{
    ngx_connection_t       *pc;
    ngx_stream_upstream_t  *u;

    ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
                   "finalize stream proxy: %i", rc);

    u = s->upstream;

    if (u == NULL) {
        goto noupstream;
    }

    if (u->peer.free && u->peer.sockaddr) {
        u->peer.free(&u->peer, u->peer.data, 0);
        u->peer.sockaddr = NULL;
    }

    pc = u->peer.connection;

    if (pc) {
        ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
                       "close stream proxy upstream connection: %d", pc->fd);

#if (NGX_STREAM_SSL)
        if (pc->ssl) {
            pc->ssl->no_wait_shutdown = 1;
            (void) ngx_ssl_shutdown(pc);
        }
#endif

        ngx_close_connection(pc);
        u->peer.connection = NULL;
    }

noupstream:

    ngx_stream_close_connection(s->connection);
}
コード例 #8
0
static void
ngx_stream_app_handler(ngx_stream_session_t *s)
{
    ngx_connection_t                *c;
    ngx_stream_app_srv_conf_t     *pscf;

    c = s->connection;

    pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_app_module);

    ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
                   "NGX_LOG_DEBUG_STREAM:app connection handler");

    s->upstream = NULL;

    s->log_handler = ngx_stream_app_log_error;

    c->write->handler = ngx_stream_app_finalize;
    c->read->handler = ngx_app_wait_request_handler;

    if (c->read->ready) {
 	   c->read->handler(c->read);
	   return;
    }
	
	if (!c->read->timer_set) {
		ngx_add_timer(c->read, pscf->client_timeout);
	}

//    ngx_reusable_connection(c, 1);
    if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
        ngx_stream_close_connection(c);
        return;
    }

}
コード例 #9
0
// 在ngx_stream_optimize_servers里设置有连接发生时的回调函数
// 调用发生在ngx_event_accept.c:ngx_event_accept()
//
// 创建一个处理tcp的会话对象
// 要先检查限速和访问限制这两个功能模块
// 最后调用ngx_stream_init_session
// 创建ctx数组,用于存储模块的ctx数据
// 调用handler,处理tcp数据,收发等等
void
ngx_stream_init_connection(ngx_connection_t *c)
{
    int                           tcp_nodelay;
    u_char                        text[NGX_SOCKADDR_STRLEN];
    size_t                        len;
    ngx_int_t                     rc;
    ngx_uint_t                    i;
    struct sockaddr              *sa;
    ngx_stream_port_t            *port;
    struct sockaddr_in           *sin;
    ngx_stream_in_addr_t         *addr;
    ngx_stream_session_t         *s;
    ngx_stream_addr_conf_t       *addr_conf;
#if (NGX_HAVE_INET6)
    struct sockaddr_in6          *sin6;
    ngx_stream_in6_addr_t        *addr6;
#endif
    ngx_stream_core_srv_conf_t   *cscf;
    ngx_stream_core_main_conf_t  *cmcf;

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

    // 取监听同一端口的server信息
    port = c->listening->servers;

    if (port->naddrs > 1) {

        /*
         * 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.
         */

        if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
            ngx_stream_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

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

            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;
                }
            }

            addr_conf = &addr[i].conf;

            break;
        }

    } else {
        // 唯一监听端口的server
        // addr_conf就是端口所在的server的配置数组
        switch (c->local_sockaddr->sa_family) {

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

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

    // 创建一个处理tcp的会话对象
    s = ngx_pcalloc(c->pool, sizeof(ngx_stream_session_t));
    if (s == NULL) {
        ngx_stream_close_connection(c);
        return;
    }

    // 设置会话对象的标志
    s->signature = NGX_STREAM_MODULE;

    //设置会话正确的配置结构体
    // addr_conf就是端口所在的server的配置数组
    // 之后就可以用宏正确地获取模块的配置信息
    s->main_conf = addr_conf->ctx->main_conf;
    s->srv_conf = addr_conf->ctx->srv_conf;

    // 设置会话关联的连接对象
    s->connection = c;

    // 连接的data指针指向会话对象
    c->data = s;

    // 获取相关的core配置
    cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);

    ngx_set_connection_log(c, cscf->error_log);

    len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1);

    ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V",
                  c->number, len, text, &addr_conf->addr_text);

    // log的一些参数
    c->log->connection = c->number;
    c->log->handler = ngx_stream_log_error;
    c->log->data = s;
    c->log->action = "initializing connection";
    c->log_error = NGX_ERROR_INFO;

    // 一个stream{}块只能有一个main conf
    // 所以连接限速、访问限制的处理函数是相同的
    // 但配置参数每个server可以不同
    cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);

    // 是否有连接限速设置,在ngx_stream_limit_conn_module.c里设置
    if (cmcf->limit_conn_handler) {
        rc = cmcf->limit_conn_handler(s);

        if (rc != NGX_DECLINED) {
            ngx_stream_close_connection(c);
            return;
        }
    }

    // 是否有访问限制
    if (cmcf->access_handler) {
        rc = cmcf->access_handler(s);

        if (rc != NGX_OK && rc != NGX_DECLINED) {
            ngx_stream_close_connection(c);
            return;
        }
    }

    // 设置TCP_NODELAY,默认启用
    if (cscf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
        ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay");

        tcp_nodelay = 1;

        if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
                       (const void *) &tcp_nodelay, sizeof(int)) == -1)
        {
            ngx_connection_error(c, ngx_socket_errno,
                                 "setsockopt(TCP_NODELAY) failed");
            ngx_stream_close_connection(c);
            return;
        }

        c->tcp_nodelay = NGX_TCP_NODELAY_SET;
    }


#if (NGX_STREAM_SSL)
    {
        ngx_stream_ssl_conf_t  *sslcf;

        sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);

        if (addr_conf->ssl) {
            c->log->action = "SSL handshaking";

            if (sslcf->ssl.ctx == NULL) {
                ngx_log_error(NGX_LOG_ERR, c->log, 0,
                              "no \"ssl_certificate\" is defined "
                              "in server listening on SSL port");
                ngx_stream_close_connection(c);
                return;
            }

            ngx_stream_ssl_init_connection(&sslcf->ssl, c);
            return;
        }
    }
#endif

    // 创建ctx数组,用于存储模块的ctx数据
    // 调用handler,处理tcp数据,收发等等
    ngx_stream_init_session(c);
}
コード例 #10
0
void
ngx_stream_init_connection(ngx_connection_t *c)
{
    u_char                        text[NGX_SOCKADDR_STRLEN];
    size_t                        len;
    ngx_int_t                     rc;
    ngx_uint_t                    i;
    struct sockaddr              *sa;
    ngx_stream_port_t            *port;
    struct sockaddr_in           *sin;
    ngx_stream_in_addr_t         *addr;
    ngx_stream_session_t         *s;
    ngx_stream_addr_conf_t       *addr_conf;
#if (NGX_HAVE_INET6)
    struct sockaddr_in6          *sin6;
    ngx_stream_in6_addr_t        *addr6;
#endif
    ngx_stream_core_srv_conf_t   *cscf;
    ngx_stream_core_main_conf_t  *cmcf;

    /* 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 the "*:port" wildcard so getsockname() is needed to determine
         * the server address.
         *
         * AcceptEx() already gave this address.
         */

        if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
            ngx_stream_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

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

            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;
                }
            }

            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

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

    s = ngx_pcalloc(c->pool, sizeof(ngx_stream_session_t));
    if (s == NULL) {
        ngx_stream_close_connection(c);
        return;
    }

    s->signature = NGX_STREAM_MODULE;
    s->main_conf = addr_conf->ctx->main_conf;
    s->srv_conf = addr_conf->ctx->srv_conf;

    s->connection = c;
    c->data = s;

    cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);

    ngx_set_connection_log(c, cscf->error_log);

    len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1);

    ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V",
                  c->number, len, text, &addr_conf->addr_text);

    c->log->connection = c->number;
    c->log->handler = ngx_stream_log_error;
    c->log->data = s;
    c->log->action = "initializing connection";
    c->log_error = NGX_ERROR_INFO;

    cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);

    if (cmcf->access_handler) {
        rc = cmcf->access_handler(s);

        if (rc != NGX_OK && rc != NGX_DECLINED) {
            ngx_stream_close_connection(c);
            return;
        }
    }

#if (NGX_STREAM_SSL)
    {
    ngx_stream_ssl_conf_t  *sslcf;

    sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);

    if (addr_conf->ssl) {
        c->log->action = "SSL handshaking";

        if (sslcf->ssl.ctx == NULL) {
            ngx_log_error(NGX_LOG_ERR, c->log, 0,
                          "no \"ssl_certificate\" is defined "
                          "in server listening on SSL port");
            ngx_stream_close_connection(c);
            return;
        }

        ngx_stream_ssl_init_connection(&sslcf->ssl, c);
        return;
    }
    }
#endif

    ngx_stream_init_session(c);
}
コード例 #11
0
/*
static void ngx_app_empty_handler(ngx_event_t *wev)
{

}
*/
static void ngx_app_wait_request_handler(ngx_event_t *ev)
{
    ngx_connection_t      *c;
    ngx_stream_session_t  *s;
	ngx_stream_app_main_conf_t  *cscf;
	ngx_stream_app_srv_conf_t  *ascf;
	ngx_stream_app_ctx_t  *s_ctx;
	ngx_app_task_t		  *t;
	ngx_buf_t             *b;
	ngx_str_t			  log_buf;
	ssize_t                n;
	size_t                 size;
	u_char				   *tmp;
    c = ev->data;
    s = c->data;

    if (ev->timedout) {
        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
        ngx_stream_close_connection(c);
        return;
    }

    if (c->close) {
        ngx_stream_close_connection(c);
        return;
    }

	cscf = ngx_stream_get_module_main_conf(s, ngx_stream_app_module);

	ascf = ngx_stream_get_module_srv_conf(s, ngx_stream_app_module);
		
	s_ctx = ngx_stream_get_module_ctx(s,ngx_stream_app_module);
	if(s_ctx == NULL){
		s_ctx = ngx_palloc(c->pool, sizeof(ngx_stream_app_ctx_t));
		if(s_ctx == NULL)
			return;
		s_ctx->header = 0;
		ngx_stream_set_ctx(s,s_ctx,ngx_stream_app_module);
	}

	b = c->buffer;

	if (b == NULL) {
		size = ascf->header_len;
		b = ngx_create_temp_buf(c->pool, size);
		if (b == NULL) {
			ngx_stream_close_connection(c);
			return;
		}

		c->buffer = b;

	} else if (b->start == NULL) {

		size = s_ctx->header == 0?ascf->header_len:s_ctx->body_len;

		b->start = ngx_palloc(c->pool, size);
		if (b->start == NULL) {
			ngx_stream_close_connection(c);
			return;
		}

		b->pos = b->start;
		b->last = b->start;
		b->end = b->last + size;
	}
	else {

		size = ascf->header_len + s_ctx->body_len - s->received;
//		size = b->end - b->last;
	}

	n = c->recv(c, b->last, size);
	
    if (n == NGX_AGAIN) {

        if (!c->read->timer_set) {
            ngx_add_timer(c->read, ascf->client_timeout);
        }

        if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
            ngx_stream_close_connection(c);
            return;
        }

        return;
    }

	if (n == NGX_ERROR) {
        ngx_stream_close_connection(c);
        return;
    }
	
    if (n == 0) {
        ngx_log_error(NGX_LOG_INFO, c->log, 0,
                      "client closed connection");
        ngx_stream_close_connection(c);
        return;
    }

    b->last += n;
	s->received +=n;

	c->log->action = "reading client request line";
	
	log_buf.len = s->received;
	log_buf.data = b->start;
	ngx_log_error(NGX_LOG_ALERT, c->log, 0, "%d recved [%V],[%d:%d]",n,&log_buf,b->end,b->last);

	if(b->end != b->last){
        if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
            ngx_stream_close_connection(c);
            return;
        }
	}
	else {
		if(s_ctx->header == 0){
			s_ctx->body_len = ngx_atoi(b->start,ascf->header_len);
			s_ctx->header = 1;
			if(s_ctx->body_len > 0 ){
				
				tmp = ngx_pcalloc(c->pool, ascf->header_len + s_ctx->body_len);
				if (tmp == NULL) {
					ngx_stream_close_connection(c);
					return;
				}

				ngx_memcpy(tmp,b->start,ascf->header_len);
				ngx_pfree(c->pool, b->start);
				b->start = tmp;
				
				b->pos = b->start + ascf->header_len;
				b->last = b->pos;
				b->end = b->last + s_ctx->body_len;
				
				ngx_app_wait_request_handler(ev);
			}
			else{
				ngx_log_error(NGX_LOG_INFO, c->log, 0, "empty request body");
				ngx_stream_close_connection(c);
				return;
			}

			ngx_log_error(NGX_LOG_ALERT, c->log, 0, "recv header,len[%d]",s_ctx->body_len);

		}
		else{
//			c->read->handler = ngx_app_empty_handler;

			t = (ngx_app_task_t *)ngx_thread_task_alloc(c->pool,
				sizeof(ngx_app_task_t) - sizeof(ngx_thread_task_t));
			if(t == NULL){
				ngx_log_error(NGX_LOG_ERR, c->log, 0, "create thread task failed");
				ngx_stream_close_connection(c);
			}
			t->data = s;
			t->task.handler = ngx_stream_app_process;
			t->task.event.handler = ngx_stream_app_finalize;
			t->task.event.data= c;
			ngx_log_error(NGX_LOG_ALERT, c->log, 0, "t->data[%d]=[%d][%d]",t->data,t->task.ctx,t);
			if(ngx_thread_task_post(cscf->tp,(ngx_thread_task_t *)t) != NGX_OK){
				ngx_log_error(NGX_LOG_ERR, c->log, 0, "post task to thread pool failed");
				ngx_stream_close_connection(c);
				return;
			}
			ngx_log_error(NGX_LOG_ALERT, c->log, 0, "after post task");
		}
	}

	return;
}