mirror of
https://github.com/nginx/nginx.git
synced 2025-06-12 13:42:55 +08:00
Stream: phases.
This commit is contained in:
parent
04b9434b18
commit
05a455ff21
@ -12,6 +12,10 @@
|
|||||||
|
|
||||||
|
|
||||||
static char *ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
static char *ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||||
|
static ngx_int_t ngx_stream_init_phases(ngx_conf_t *cf,
|
||||||
|
ngx_stream_core_main_conf_t *cmcf);
|
||||||
|
static ngx_int_t ngx_stream_init_phase_handlers(ngx_conf_t *cf,
|
||||||
|
ngx_stream_core_main_conf_t *cmcf);
|
||||||
static ngx_int_t ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
|
static ngx_int_t ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
|
||||||
ngx_stream_listen_t *listen);
|
ngx_stream_listen_t *listen);
|
||||||
static char *ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
|
static char *ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
|
||||||
@ -219,6 +223,10 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_stream_init_phases(cf, cmcf) != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
for (m = 0; cf->cycle->modules[m]; m++) {
|
for (m = 0; cf->cycle->modules[m]; m++) {
|
||||||
if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
|
if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
|
||||||
continue;
|
continue;
|
||||||
@ -239,6 +247,9 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
*cf = pcf;
|
*cf = pcf;
|
||||||
|
|
||||||
|
if (ngx_stream_init_phase_handlers(cf, cmcf) != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t))
|
if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t))
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
@ -258,6 +269,105 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_init_phases(ngx_conf_t *cf, ngx_stream_core_main_conf_t *cmcf)
|
||||||
|
{
|
||||||
|
if (ngx_array_init(&cmcf->phases[NGX_STREAM_POST_ACCEPT_PHASE].handlers,
|
||||||
|
cf->pool, 1, sizeof(ngx_stream_handler_pt))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_array_init(&cmcf->phases[NGX_STREAM_PREACCESS_PHASE].handlers,
|
||||||
|
cf->pool, 1, sizeof(ngx_stream_handler_pt))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_array_init(&cmcf->phases[NGX_STREAM_ACCESS_PHASE].handlers,
|
||||||
|
cf->pool, 1, sizeof(ngx_stream_handler_pt))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (NGX_STREAM_SSL)
|
||||||
|
if (ngx_array_init(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers,
|
||||||
|
cf->pool, 1, sizeof(ngx_stream_handler_pt))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ngx_array_init(&cmcf->phases[NGX_STREAM_LOG_PHASE].handlers,
|
||||||
|
cf->pool, 1, sizeof(ngx_stream_handler_pt))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_init_phase_handlers(ngx_conf_t *cf,
|
||||||
|
ngx_stream_core_main_conf_t *cmcf)
|
||||||
|
{
|
||||||
|
ngx_int_t j;
|
||||||
|
ngx_uint_t i, n;
|
||||||
|
ngx_stream_handler_pt *h;
|
||||||
|
ngx_stream_phase_handler_t *ph;
|
||||||
|
ngx_stream_phase_handler_pt checker;
|
||||||
|
|
||||||
|
n = 1 /* content phase */;
|
||||||
|
|
||||||
|
for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) {
|
||||||
|
n += cmcf->phases[i].handlers.nelts;
|
||||||
|
}
|
||||||
|
|
||||||
|
ph = ngx_pcalloc(cf->pool,
|
||||||
|
n * sizeof(ngx_stream_phase_handler_t) + sizeof(void *));
|
||||||
|
if (ph == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmcf->phase_engine.handlers = ph;
|
||||||
|
n = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) {
|
||||||
|
h = cmcf->phases[i].handlers.elts;
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
|
||||||
|
case NGX_STREAM_CONTENT_PHASE:
|
||||||
|
ph->checker = ngx_stream_core_content_phase;
|
||||||
|
n++;
|
||||||
|
ph++;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
checker = ngx_stream_core_generic_phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
n += cmcf->phases[i].handlers.nelts;
|
||||||
|
|
||||||
|
for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) {
|
||||||
|
ph->checker = checker;
|
||||||
|
ph->handler = h[j];
|
||||||
|
ph->next = n;
|
||||||
|
ph++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
|
ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
|
||||||
ngx_stream_listen_t *listen)
|
ngx_stream_listen_t *listen)
|
||||||
|
@ -115,17 +115,48 @@ typedef struct {
|
|||||||
} ngx_stream_conf_addr_t;
|
} ngx_stream_conf_addr_t;
|
||||||
|
|
||||||
|
|
||||||
typedef ngx_int_t (*ngx_stream_access_pt)(ngx_stream_session_t *s);
|
typedef enum {
|
||||||
|
NGX_STREAM_POST_ACCEPT_PHASE = 0,
|
||||||
|
NGX_STREAM_PREACCESS_PHASE,
|
||||||
|
NGX_STREAM_ACCESS_PHASE,
|
||||||
|
#if (NGX_STREAM_SSL)
|
||||||
|
NGX_STREAM_SSL_PHASE,
|
||||||
|
#endif
|
||||||
|
NGX_STREAM_CONTENT_PHASE,
|
||||||
|
NGX_STREAM_LOG_PHASE
|
||||||
|
} ngx_stream_phases;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ngx_stream_phase_handler_s ngx_stream_phase_handler_t;
|
||||||
|
|
||||||
|
typedef ngx_int_t (*ngx_stream_phase_handler_pt)(ngx_stream_session_t *s,
|
||||||
|
ngx_stream_phase_handler_t *ph);
|
||||||
|
typedef ngx_int_t (*ngx_stream_handler_pt)(ngx_stream_session_t *s);
|
||||||
|
typedef void (*ngx_stream_content_handler_pt)(ngx_stream_session_t *s);
|
||||||
|
|
||||||
|
|
||||||
|
struct ngx_stream_phase_handler_s {
|
||||||
|
ngx_stream_phase_handler_pt checker;
|
||||||
|
ngx_stream_handler_pt handler;
|
||||||
|
ngx_uint_t next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_stream_phase_handler_t *handlers;
|
||||||
|
} ngx_stream_phase_engine_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_array_t handlers;
|
||||||
|
} ngx_stream_phase_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_array_t servers; /* ngx_stream_core_srv_conf_t */
|
ngx_array_t servers; /* ngx_stream_core_srv_conf_t */
|
||||||
ngx_array_t listen; /* ngx_stream_listen_t */
|
ngx_array_t listen; /* ngx_stream_listen_t */
|
||||||
|
|
||||||
ngx_stream_access_pt realip_handler;
|
ngx_stream_phase_engine_t phase_engine;
|
||||||
ngx_stream_access_pt limit_conn_handler;
|
|
||||||
ngx_stream_access_pt access_handler;
|
|
||||||
ngx_stream_access_pt access_log_handler;
|
|
||||||
|
|
||||||
ngx_hash_t variables_hash;
|
ngx_hash_t variables_hash;
|
||||||
|
|
||||||
@ -136,14 +167,13 @@ typedef struct {
|
|||||||
ngx_uint_t variables_hash_bucket_size;
|
ngx_uint_t variables_hash_bucket_size;
|
||||||
|
|
||||||
ngx_hash_keys_arrays_t *variables_keys;
|
ngx_hash_keys_arrays_t *variables_keys;
|
||||||
|
|
||||||
|
ngx_stream_phase_t phases[NGX_STREAM_LOG_PHASE + 1];
|
||||||
} ngx_stream_core_main_conf_t;
|
} ngx_stream_core_main_conf_t;
|
||||||
|
|
||||||
|
|
||||||
typedef void (*ngx_stream_handler_pt)(ngx_stream_session_t *s);
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_stream_handler_pt handler;
|
ngx_stream_content_handler_pt handler;
|
||||||
|
|
||||||
ngx_stream_conf_ctx_t *ctx;
|
ngx_stream_conf_ctx_t *ctx;
|
||||||
|
|
||||||
@ -189,6 +219,7 @@ struct ngx_stream_session_s {
|
|||||||
u_char *captures_data;
|
u_char *captures_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ngx_int_t phase_handler;
|
||||||
ngx_uint_t status;
|
ngx_uint_t status;
|
||||||
|
|
||||||
#if (NGX_STREAM_SSL)
|
#if (NGX_STREAM_SSL)
|
||||||
@ -246,7 +277,15 @@ typedef struct {
|
|||||||
#define NGX_STREAM_WRITE_BUFFERED 0x10
|
#define NGX_STREAM_WRITE_BUFFERED 0x10
|
||||||
|
|
||||||
|
|
||||||
|
void ngx_stream_core_run_phases(ngx_stream_session_t *s);
|
||||||
|
ngx_int_t ngx_stream_core_generic_phase(ngx_stream_session_t *s,
|
||||||
|
ngx_stream_phase_handler_t *ph);
|
||||||
|
ngx_int_t ngx_stream_core_content_phase(ngx_stream_session_t *s,
|
||||||
|
ngx_stream_phase_handler_t *ph);
|
||||||
|
|
||||||
|
|
||||||
void ngx_stream_init_connection(ngx_connection_t *c);
|
void ngx_stream_init_connection(ngx_connection_t *c);
|
||||||
|
void ngx_stream_session_handler(ngx_event_t *rev);
|
||||||
void ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc);
|
void ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc);
|
||||||
|
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ ngx_stream_access_found(ngx_stream_session_t *s, ngx_uint_t deny)
|
|||||||
if (deny) {
|
if (deny) {
|
||||||
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
|
||||||
"access forbidden by rule");
|
"access forbidden by rule");
|
||||||
return NGX_ABORT;
|
return NGX_STREAM_FORBIDDEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
@ -443,10 +443,17 @@ ngx_stream_access_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_access_init(ngx_conf_t *cf)
|
ngx_stream_access_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
|
ngx_stream_handler_pt *h;
|
||||||
ngx_stream_core_main_conf_t *cmcf;
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
||||||
cmcf->access_handler = ngx_stream_access_handler;
|
|
||||||
|
h = ngx_array_push(&cmcf->phases[NGX_STREAM_ACCESS_PHASE].handlers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = ngx_stream_access_handler;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,108 @@ ngx_module_t ngx_stream_core_module = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ngx_stream_core_run_phases(ngx_stream_session_t *s)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_stream_phase_handler_t *ph;
|
||||||
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
|
cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
|
||||||
|
|
||||||
|
ph = cmcf->phase_engine.handlers;
|
||||||
|
|
||||||
|
while (ph[s->phase_handler].checker) {
|
||||||
|
|
||||||
|
rc = ph[s->phase_handler].checker(s, &ph[s->phase_handler]);
|
||||||
|
|
||||||
|
if (rc == NGX_OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_stream_core_generic_phase(ngx_stream_session_t *s,
|
||||||
|
ngx_stream_phase_handler_t *ph)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* generic phase checker,
|
||||||
|
* used by all phases, except for content
|
||||||
|
*/
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
|
||||||
|
"generic phase: %ui", s->phase_handler);
|
||||||
|
|
||||||
|
rc = ph->handler(s);
|
||||||
|
|
||||||
|
if (rc == NGX_OK) {
|
||||||
|
s->phase_handler = ph->next;
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
s->phase_handler++;
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_AGAIN || rc == NGX_DONE) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_stream_finalize_session(s, rc);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_stream_core_content_phase(ngx_stream_session_t *s,
|
||||||
|
ngx_stream_phase_handler_t *ph)
|
||||||
|
{
|
||||||
|
int tcp_nodelay;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_stream_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
|
c = s->connection;
|
||||||
|
|
||||||
|
c->log->action = NULL;
|
||||||
|
|
||||||
|
cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
|
||||||
|
|
||||||
|
if (c->type == SOCK_STREAM
|
||||||
|
&& 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_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->tcp_nodelay = NGX_TCP_NODELAY_SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
cscf->handler(s);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_core_preconfiguration(ngx_conf_t *cf)
|
ngx_stream_core_preconfiguration(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
|
@ -11,15 +11,10 @@
|
|||||||
#include <ngx_stream.h>
|
#include <ngx_stream.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void ngx_stream_log_session(ngx_stream_session_t *s);
|
||||||
static void ngx_stream_close_connection(ngx_connection_t *c);
|
static void ngx_stream_close_connection(ngx_connection_t *c);
|
||||||
static u_char *ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
static u_char *ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
||||||
static void ngx_stream_proxy_protocol_handler(ngx_event_t *rev);
|
static void ngx_stream_proxy_protocol_handler(ngx_event_t *rev);
|
||||||
static void ngx_stream_init_session_handler(ngx_event_t *rev);
|
|
||||||
|
|
||||||
#if (NGX_STREAM_SSL)
|
|
||||||
static void ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
|
|
||||||
static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -154,7 +149,7 @@ ngx_stream_init_connection(ngx_connection_t *c)
|
|||||||
c->log->connection = c->number;
|
c->log->connection = c->number;
|
||||||
c->log->handler = ngx_stream_log_error;
|
c->log->handler = ngx_stream_log_error;
|
||||||
c->log->data = s;
|
c->log->data = s;
|
||||||
c->log->action = "initializing connection";
|
c->log->action = "initializing session";
|
||||||
c->log_error = NGX_ERROR_INFO;
|
c->log_error = NGX_ERROR_INFO;
|
||||||
|
|
||||||
s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_stream_max_module);
|
s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_stream_max_module);
|
||||||
@ -179,7 +174,7 @@ ngx_stream_init_connection(ngx_connection_t *c)
|
|||||||
s->start_msec = tp->msec;
|
s->start_msec = tp->msec;
|
||||||
|
|
||||||
rev = c->read;
|
rev = c->read;
|
||||||
rev->handler = ngx_stream_init_session_handler;
|
rev->handler = ngx_stream_session_handler;
|
||||||
|
|
||||||
if (addr_conf->proxy_protocol) {
|
if (addr_conf->proxy_protocol) {
|
||||||
c->log->action = "reading PROXY protocol";
|
c->log->action = "reading PROXY protocol";
|
||||||
@ -279,192 +274,57 @@ ngx_stream_proxy_protocol_handler(ngx_event_t *rev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_stream_init_session_handler(rev);
|
c->log->action = "initializing session";
|
||||||
|
|
||||||
|
ngx_stream_session_handler(rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
void
|
||||||
ngx_stream_init_session_handler(ngx_event_t *rev)
|
ngx_stream_session_handler(ngx_event_t *rev)
|
||||||
{
|
{
|
||||||
int tcp_nodelay;
|
ngx_connection_t *c;
|
||||||
ngx_int_t rc;
|
ngx_stream_session_t *s;
|
||||||
ngx_connection_t *c;
|
|
||||||
ngx_stream_session_t *s;
|
|
||||||
ngx_stream_core_srv_conf_t *cscf;
|
|
||||||
ngx_stream_core_main_conf_t *cmcf;
|
|
||||||
|
|
||||||
c = rev->data;
|
c = rev->data;
|
||||||
s = c->data;
|
s = c->data;
|
||||||
|
|
||||||
c->log->action = "initializing session";
|
ngx_stream_core_run_phases(s);
|
||||||
|
|
||||||
cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
|
|
||||||
|
|
||||||
if (cmcf->realip_handler) {
|
|
||||||
rc = cmcf->realip_handler(s);
|
|
||||||
|
|
||||||
if (rc == NGX_ERROR) {
|
|
||||||
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmcf->limit_conn_handler) {
|
|
||||||
rc = cmcf->limit_conn_handler(s);
|
|
||||||
|
|
||||||
if (rc == NGX_ERROR) {
|
|
||||||
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == NGX_ABORT) {
|
|
||||||
ngx_stream_finalize_session(s, NGX_STREAM_SERVICE_UNAVAILABLE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmcf->access_handler) {
|
|
||||||
rc = cmcf->access_handler(s);
|
|
||||||
|
|
||||||
if (rc == NGX_ERROR) {
|
|
||||||
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == NGX_ABORT) {
|
|
||||||
ngx_stream_finalize_session(s, NGX_STREAM_FORBIDDEN);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
|
|
||||||
|
|
||||||
if (c->type == SOCK_STREAM
|
|
||||||
&& 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_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
|
||||||
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 (s->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_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_stream_ssl_init_connection(&sslcf->ssl, c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
c->log->action = "handling client connection";
|
|
||||||
|
|
||||||
cscf->handler(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if (NGX_STREAM_SSL)
|
|
||||||
|
|
||||||
static void
|
|
||||||
ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
|
|
||||||
{
|
|
||||||
ngx_stream_session_t *s;
|
|
||||||
ngx_stream_ssl_conf_t *sslcf;
|
|
||||||
|
|
||||||
s = c->data;
|
|
||||||
|
|
||||||
if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) {
|
|
||||||
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngx_ssl_handshake(c) == NGX_AGAIN) {
|
|
||||||
sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
|
||||||
|
|
||||||
ngx_add_timer(c->read, sslcf->handshake_timeout);
|
|
||||||
|
|
||||||
c->ssl->handler = ngx_stream_ssl_handshake_handler;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_stream_ssl_handshake_handler(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
|
|
||||||
{
|
|
||||||
ngx_stream_session_t *s;
|
|
||||||
ngx_stream_core_srv_conf_t *cscf;
|
|
||||||
|
|
||||||
if (!c->ssl->handshaked) {
|
|
||||||
ngx_stream_finalize_session(c->data, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->read->timer_set) {
|
|
||||||
ngx_del_timer(c->read);
|
|
||||||
}
|
|
||||||
|
|
||||||
c->log->action = "handling client connection";
|
|
||||||
|
|
||||||
s = c->data;
|
|
||||||
|
|
||||||
cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
|
|
||||||
|
|
||||||
cscf->handler(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc)
|
ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc)
|
||||||
{
|
{
|
||||||
ngx_stream_core_main_conf_t *cmcf;
|
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
|
||||||
"finalize stream session: %i", rc);
|
"finalize stream session: %i", rc);
|
||||||
|
|
||||||
s->status = rc;
|
s->status = rc;
|
||||||
|
|
||||||
cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
|
ngx_stream_log_session(s);
|
||||||
|
|
||||||
if (cmcf->access_log_handler) {
|
|
||||||
(void) cmcf->access_log_handler(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_stream_close_connection(s->connection);
|
ngx_stream_close_connection(s->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_stream_log_session(ngx_stream_session_t *s)
|
||||||
|
{
|
||||||
|
ngx_uint_t i, n;
|
||||||
|
ngx_stream_handler_pt *log_handler;
|
||||||
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
|
cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
|
||||||
|
|
||||||
|
log_handler = cmcf->phases[NGX_STREAM_LOG_PHASE].handlers.elts;
|
||||||
|
n = cmcf->phases[NGX_STREAM_LOG_PHASE].handlers.nelts;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
log_handler[i](s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_stream_close_connection(ngx_connection_t *c)
|
ngx_stream_close_connection(ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
|
@ -178,7 +178,7 @@ ngx_stream_limit_conn_handler(ngx_stream_session_t *s)
|
|||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
ngx_shmtx_unlock(&shpool->mutex);
|
ngx_shmtx_unlock(&shpool->mutex);
|
||||||
ngx_stream_limit_conn_cleanup_all(s->connection->pool);
|
ngx_stream_limit_conn_cleanup_all(s->connection->pool);
|
||||||
return NGX_ABORT;
|
return NGX_STREAM_SERVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
lc = (ngx_stream_limit_conn_node_t *) &node->color;
|
lc = (ngx_stream_limit_conn_node_t *) &node->color;
|
||||||
@ -203,7 +203,7 @@ ngx_stream_limit_conn_handler(ngx_stream_session_t *s)
|
|||||||
&limits[i].shm_zone->shm.name);
|
&limits[i].shm_zone->shm.name);
|
||||||
|
|
||||||
ngx_stream_limit_conn_cleanup_all(s->connection->pool);
|
ngx_stream_limit_conn_cleanup_all(s->connection->pool);
|
||||||
return NGX_ABORT;
|
return NGX_STREAM_SERVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
lc->conn++;
|
lc->conn++;
|
||||||
@ -630,11 +630,17 @@ ngx_stream_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_limit_conn_init(ngx_conf_t *cf)
|
ngx_stream_limit_conn_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
|
ngx_stream_handler_pt *h;
|
||||||
ngx_stream_core_main_conf_t *cmcf;
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
||||||
|
|
||||||
cmcf->limit_conn_handler = ngx_stream_limit_conn_handler;
|
h = ngx_array_push(&cmcf->phases[NGX_STREAM_PREACCESS_PHASE].handlers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = ngx_stream_limit_conn_handler;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
@ -1464,11 +1464,17 @@ ngx_stream_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_log_init(ngx_conf_t *cf)
|
ngx_stream_log_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
|
ngx_stream_handler_pt *h;
|
||||||
ngx_stream_core_main_conf_t *cmcf;
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
||||||
|
|
||||||
cmcf->access_log_handler = ngx_stream_log_handler;
|
h = ngx_array_push(&cmcf->phases[NGX_STREAM_LOG_PHASE].handlers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = ngx_stream_log_handler;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
@ -279,11 +279,17 @@ ngx_stream_realip_add_variables(ngx_conf_t *cf)
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_realip_init(ngx_conf_t *cf)
|
ngx_stream_realip_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
|
ngx_stream_handler_pt *h;
|
||||||
ngx_stream_core_main_conf_t *cmcf;
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
||||||
|
|
||||||
cmcf->realip_handler = ngx_stream_realip_handler;
|
h = ngx_array_push(&cmcf->phases[NGX_STREAM_POST_ACCEPT_PHASE].handlers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = ngx_stream_realip_handler;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,10 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
|
|||||||
#define NGX_DEFAULT_ECDH_CURVE "auto"
|
#define NGX_DEFAULT_ECDH_CURVE "auto"
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t ngx_stream_ssl_handler(ngx_stream_session_t *s);
|
||||||
|
static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl,
|
||||||
|
ngx_connection_t *c);
|
||||||
|
static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
|
||||||
static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
|
static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
|
||||||
ngx_stream_variable_value_t *v, uintptr_t data);
|
ngx_stream_variable_value_t *v, uintptr_t data);
|
||||||
static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s,
|
static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s,
|
||||||
@ -32,6 +36,7 @@ static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||||||
void *conf);
|
void *conf);
|
||||||
static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
|
static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf);
|
||||||
|
|
||||||
|
|
||||||
static ngx_conf_bitmask_t ngx_stream_ssl_protocols[] = {
|
static ngx_conf_bitmask_t ngx_stream_ssl_protocols[] = {
|
||||||
@ -143,7 +148,7 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
|
|||||||
|
|
||||||
static ngx_stream_module_t ngx_stream_ssl_module_ctx = {
|
static ngx_stream_module_t ngx_stream_ssl_module_ctx = {
|
||||||
ngx_stream_ssl_add_variables, /* preconfiguration */
|
ngx_stream_ssl_add_variables, /* preconfiguration */
|
||||||
NULL, /* postconfiguration */
|
ngx_stream_ssl_init, /* postconfiguration */
|
||||||
|
|
||||||
NULL, /* create main configuration */
|
NULL, /* create main configuration */
|
||||||
NULL, /* init main configuration */
|
NULL, /* init main configuration */
|
||||||
@ -193,6 +198,88 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = {
|
|||||||
static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM");
|
static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM");
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_ssl_handler(ngx_stream_session_t *s)
|
||||||
|
{
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_stream_ssl_conf_t *sslcf;
|
||||||
|
|
||||||
|
c = s->connection;
|
||||||
|
|
||||||
|
sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
||||||
|
|
||||||
|
if (s->ssl && c->ssl == NULL) {
|
||||||
|
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");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_stream_ssl_init_connection(&sslcf->ssl, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_stream_session_t *s;
|
||||||
|
ngx_stream_ssl_conf_t *sslcf;
|
||||||
|
|
||||||
|
s = c->data;
|
||||||
|
|
||||||
|
if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_ssl_handshake(c);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_AGAIN) {
|
||||||
|
sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
||||||
|
|
||||||
|
ngx_add_timer(c->read, sslcf->handshake_timeout);
|
||||||
|
|
||||||
|
c->ssl->handler = ngx_stream_ssl_handshake_handler;
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rc == NGX_OK */
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
|
||||||
|
{
|
||||||
|
ngx_stream_session_t *s;
|
||||||
|
|
||||||
|
s = c->data;
|
||||||
|
|
||||||
|
if (!c->ssl->handshaked) {
|
||||||
|
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->read->timer_set) {
|
||||||
|
ngx_del_timer(c->read);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_stream_core_run_phases(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
|
ngx_stream_ssl_static_variable(ngx_stream_session_t *s,
|
||||||
ngx_stream_variable_value_t *v, uintptr_t data)
|
ngx_stream_variable_value_t *v, uintptr_t data)
|
||||||
@ -565,3 +652,22 @@ invalid:
|
|||||||
|
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_ssl_init(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_stream_handler_pt *h;
|
||||||
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
|
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
||||||
|
|
||||||
|
h = ngx_array_push(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = ngx_stream_ssl_handler;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user