mirror of
https://github.com/nginx/nginx.git
synced 2025-06-10 03:22:48 +08:00
nginx-0.0.3-2004-06-01-10:04:46 import
This commit is contained in:
parent
369145cef1
commit
67f450d7bc
@ -142,29 +142,6 @@ typedef struct {
|
|||||||
(ngx_buf_in_memory(b) ? (size_t) (b->last - b->pos): \
|
(ngx_buf_in_memory(b) ? (size_t) (b->last - b->pos): \
|
||||||
(size_t) (b->file_last - b->file_pos))
|
(size_t) (b->file_last - b->file_pos))
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
#define ngx_hunk_in_memory_only(h) \
|
|
||||||
((h->type & (NGX_HUNK_IN_MEMORY|NGX_HUNK_FILE)) == NGX_HUNK_IN_MEMORY)
|
|
||||||
/*
|
|
||||||
((h->type & (NGX_HUNK_TEMP|NGX_HUNK_MEMORY|NGX_HUNK_MMAP|NGX_HUNK_FILE)) \
|
|
||||||
== (h->type & (NGX_HUNK_TEMP|NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define ngx_hunk_special(b) \
|
|
||||||
(b->type == (b->type & (NGX_HUNK_FLUSH|NGX_HUNK_LAST)))
|
|
||||||
|
|
||||||
|
|
||||||
#define ngx_hunk_size(b) \
|
|
||||||
((b->type & NGX_HUNK_IN_MEMORY) ? (size_t) (b->last - b->pos): \
|
|
||||||
(size_t) (b->file_last - b->file_pos))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
|
ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
|
||||||
ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
|
ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
|
||||||
|
|
||||||
|
@ -60,6 +60,13 @@ typedef enum {
|
|||||||
} ngx_connection_log_error_e;
|
} ngx_connection_log_error_e;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NGX_TCP_NOPUSH_DISABLED = -1,
|
||||||
|
NGX_TCP_NOPUSH_UNSET = 0,
|
||||||
|
NGX_TCP_NOPUSH_SET
|
||||||
|
} ngx_connection_tcp_nopush_e;
|
||||||
|
|
||||||
|
|
||||||
struct ngx_connection_s {
|
struct ngx_connection_s {
|
||||||
void *data;
|
void *data;
|
||||||
ngx_event_t *read;
|
ngx_event_t *read;
|
||||||
|
@ -38,7 +38,7 @@ int ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add the incoming hunk to the chain ctx->in */
|
/* add the incoming buf to the chain ctx->in */
|
||||||
|
|
||||||
if (in) {
|
if (in) {
|
||||||
if (ngx_chain_add_copy(ctx->pool, &ctx->in, in) == NGX_ERROR) {
|
if (ngx_chain_add_copy(ctx->pool, &ctx->in, in) == NGX_ERROR) {
|
||||||
|
@ -15,10 +15,6 @@
|
|||||||
#define SIGRTMIN 33
|
#define SIGRTMIN 33
|
||||||
#define si_fd __spare__[0]
|
#define si_fd __spare__[0]
|
||||||
|
|
||||||
int sigtimedwait(const sigset_t *set, siginfo_t *info,
|
|
||||||
const struct timespec *timeout);
|
|
||||||
|
|
||||||
|
|
||||||
int sigtimedwait(const sigset_t *set, siginfo_t *info,
|
int sigtimedwait(const sigset_t *set, siginfo_t *info,
|
||||||
const struct timespec *timeout)
|
const struct timespec *timeout)
|
||||||
{
|
{
|
||||||
@ -105,6 +101,7 @@ static int ngx_rtsig_init(ngx_cycle_t *cycle)
|
|||||||
|
|
||||||
sigemptyset(&set);
|
sigemptyset(&set);
|
||||||
sigaddset(&set, rtscf->signo);
|
sigaddset(&set, rtscf->signo);
|
||||||
|
sigaddset(&set, rtscf->signo + 1);
|
||||||
sigaddset(&set, SIGIO);
|
sigaddset(&set, SIGIO);
|
||||||
|
|
||||||
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
|
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
|
||||||
@ -133,12 +130,15 @@ static void ngx_rtsig_done(ngx_cycle_t *cycle)
|
|||||||
|
|
||||||
static int ngx_rtsig_add_connection(ngx_connection_t *c)
|
static int ngx_rtsig_add_connection(ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
|
int signo;
|
||||||
ngx_rtsig_conf_t *rtscf;
|
ngx_rtsig_conf_t *rtscf;
|
||||||
|
|
||||||
rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
|
rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
|
||||||
|
|
||||||
|
signo = rtscf->signo + c->read->instance;
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
"rtsig add connection: fd:%d signo:%d", c->fd, rtscf->signo);
|
"rtsig add connection: fd:%d signo:%d", c->fd, signo);
|
||||||
|
|
||||||
if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) {
|
if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC) == -1) {
|
||||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||||
@ -146,13 +146,13 @@ static int ngx_rtsig_add_connection(ngx_connection_t *c)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcntl(c->fd, F_SETSIG, rtscf->signo) == -1) {
|
if (fcntl(c->fd, F_SETSIG, signo) == -1) {
|
||||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||||
"fcntl(F_SETSIG) failed");
|
"fcntl(F_SETSIG) failed");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcntl(c->fd, F_SETOWN, ngx_getpid()) == -1) {
|
if (fcntl(c->fd, F_SETOWN, ngx_pid) == -1) {
|
||||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||||
"fcntl(F_SETOWN) failed");
|
"fcntl(F_SETOWN) failed");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
@ -175,6 +175,9 @@ static int ngx_rtsig_add_connection(ngx_connection_t *c)
|
|||||||
|
|
||||||
static int ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags)
|
static int ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags)
|
||||||
{
|
{
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
|
"rtsig del connection: fd:%d", c->fd);
|
||||||
|
|
||||||
if (!(flags & NGX_CLOSE_EVENT)) {
|
if (!(flags & NGX_CLOSE_EVENT)) {
|
||||||
if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK) == -1) {
|
if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK) == -1) {
|
||||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||||
@ -273,9 +276,9 @@ int ngx_rtsig_process_events(ngx_cycle_t *cycle)
|
|||||||
ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
|
ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
ngx_accept_mutex_unlock();
|
||||||
ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
|
ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
|
||||||
cycle->log, err, "sigtimedwait() failed");
|
cycle->log, err, "sigtimedwait() failed");
|
||||||
ngx_accept_mutex_unlock();
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,17 +290,40 @@ int ngx_rtsig_process_events(ngx_cycle_t *cycle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
||||||
"signo:%d fd:%d band:%X", signo, si.si_fd, si.si_band);
|
"rtsig signo:%d fd:%d band:%X", signo, si.si_fd, si.si_band);
|
||||||
|
|
||||||
rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
|
rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
|
||||||
|
|
||||||
if (signo == rtscf->signo) {
|
if (signo == rtscf->signo || signo == rtscf->signo + 1) {
|
||||||
|
|
||||||
/* TODO: old_cycles */
|
/* TODO: old_cycles */
|
||||||
|
|
||||||
c = &ngx_cycle->connections[si.si_fd];
|
c = &ngx_cycle->connections[si.si_fd];
|
||||||
|
|
||||||
/* TODO: stale signals */
|
instance = signo - rtscf->signo;
|
||||||
|
|
||||||
|
if (si.si_band & POLLIN) {
|
||||||
|
c->read->returned_instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (si.si_band & POLLOUT) {
|
||||||
|
c->write->returned_instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->read->instance != instance) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the stale event from a file descriptor
|
||||||
|
* that was just closed in this iteration
|
||||||
|
*/
|
||||||
|
|
||||||
|
ngx_accept_mutex_unlock();
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
|
||||||
|
"rtsig: stale event " PTR_FMT, c);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (si.si_band & (POLLIN|POLLHUP|POLLERR)) {
|
if (si.si_band & (POLLIN|POLLHUP|POLLERR)) {
|
||||||
if (c->read->active) {
|
if (c->read->active) {
|
||||||
@ -307,7 +333,7 @@ int ngx_rtsig_process_events(ngx_cycle_t *cycle)
|
|||||||
c->read->event_handler(c->read);
|
c->read->event_handler(c->read);
|
||||||
|
|
||||||
} else if (c->read->accept) {
|
} else if (c->read->accept) {
|
||||||
if (ngx_accept_disabled > 0) {
|
if (ngx_accept_disabled <= 0) {
|
||||||
c->read->event_handler(c->read);
|
c->read->event_handler(c->read);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,9 +397,11 @@ int ngx_rtsig_process_events(ngx_cycle_t *cycle)
|
|||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
ngx_accept_mutex_unlock();
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||||
"sigtimedwait() returned unexpected signal: %d", signo);
|
"sigtimedwait() returned unexpected signal: %d", signo);
|
||||||
ngx_accept_mutex_unlock();
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,9 +372,16 @@ static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle)
|
|||||||
rev->event_handler = &ngx_event_accept;
|
rev->event_handler = &ngx_event_accept;
|
||||||
|
|
||||||
if (ngx_event_flags & NGX_USE_SIGIO_EVENT) {
|
if (ngx_event_flags & NGX_USE_SIGIO_EVENT) {
|
||||||
|
|
||||||
|
if (ngx_accept_mutex) {
|
||||||
|
ngx_accept_mutex_held = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
if (ngx_add_conn(c) == NGX_ERROR) {
|
if (ngx_add_conn(c) == NGX_ERROR) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
|
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
|
@ -264,6 +264,16 @@ int ngx_event_connect_peer(ngx_peer_connection_t *pc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_add_conn) {
|
||||||
|
if (rc == -1) {
|
||||||
|
/* NGX_EINPROGRESS */
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pc->log, 0, "connected");
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_event_flags & NGX_USE_AIO_EVENT) {
|
if (ngx_event_flags & NGX_USE_AIO_EVENT) {
|
||||||
|
|
||||||
/* aio, iocp */
|
/* aio, iocp */
|
||||||
@ -294,8 +304,6 @@ int ngx_event_connect_peer(ngx_peer_connection_t *pc)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: epoll */
|
|
||||||
|
|
||||||
if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { /* kqueue */
|
if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { /* kqueue */
|
||||||
event = NGX_CLEAR_EVENT;
|
event = NGX_CLEAR_EVENT;
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ ngx_int_t ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
|
|||||||
/* if there're no bufs to read in then disable a level event */
|
/* if there're no bufs to read in then disable a level event */
|
||||||
|
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
|
||||||
"no pipe hunks to read in");
|
"no pipe bufs to read in");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -435,9 +435,9 @@ static int ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We preallocate a memory for zlib in one hunk (200K-400K), this
|
* We preallocate a memory for zlib in one buffer (200K-400K), this
|
||||||
* dicreases a number of malloc() and free() calls and also probably
|
* dicreases a number of malloc() and free() calls and also probably
|
||||||
* dicreases a number of syscalls.
|
* dicreases a number of syscalls (sbrk() or so).
|
||||||
* Besides we free() this memory as soon as the gzipping will complete
|
* Besides we free() this memory as soon as the gzipping will complete
|
||||||
* and do not wait while a whole response will be sent to a client.
|
* and do not wait while a whole response will be sent to a client.
|
||||||
*
|
*
|
||||||
|
@ -701,7 +701,7 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
|
|||||||
|
|
||||||
/* rc == NGX_OK */
|
/* rc == NGX_OK */
|
||||||
|
|
||||||
if (c->tcp_nopush) {
|
if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
|
||||||
if (ngx_tcp_push(c->fd) == NGX_ERROR) {
|
if (ngx_tcp_push(c->fd) == NGX_ERROR) {
|
||||||
ngx_log_error(NGX_LOG_CRIT, c->log,
|
ngx_log_error(NGX_LOG_CRIT, c->log,
|
||||||
ngx_socket_errno,
|
ngx_socket_errno,
|
||||||
@ -710,7 +710,7 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->tcp_nopush = 0;
|
c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1138,7 +1138,7 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: preallocate event_pipe hunks, look "Content-Length" */
|
/* TODO: preallocate event_pipe bufs, look "Content-Length" */
|
||||||
|
|
||||||
rc = ngx_http_send_header(r);
|
rc = ngx_http_send_header(r);
|
||||||
|
|
||||||
|
@ -567,7 +567,7 @@ int ngx_http_find_location_config(ngx_http_request_t *r)
|
|||||||
|
|
||||||
if (!clcf->tcp_nopush) {
|
if (!clcf->tcp_nopush) {
|
||||||
/* disable TCP_NOPUSH/TCP_CORK use */
|
/* disable TCP_NOPUSH/TCP_CORK use */
|
||||||
r->connection->tcp_nopush = -1;
|
r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ void ngx_http_init_connection(ngx_connection_t *c)
|
|||||||
if (rev->ready) {
|
if (rev->ready) {
|
||||||
/* deferred accept, aio, iocp */
|
/* deferred accept, aio, iocp */
|
||||||
|
|
||||||
if (*ngx_accept_mutex) {
|
if (ngx_accept_mutex) {
|
||||||
if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
|
if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
|
||||||
ngx_http_close_connection(c);
|
ngx_http_close_connection(c);
|
||||||
return;
|
return;
|
||||||
@ -562,10 +562,10 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's a pipelined request and a request line is not complete
|
* If it's a pipelined request and a request line is not complete
|
||||||
* then we have to copy it to the start of the r->header_in hunk.
|
* then we have to copy it to the start of the r->header_in buf.
|
||||||
* We have to copy it here only if the large client headers
|
* We have to copy it here only if the large client headers
|
||||||
* are enabled otherwise a request line had been already copied
|
* are enabled otherwise a request line had been already copied
|
||||||
* to the start of the r->header_in hunk in ngx_http_set_keepalive().
|
* to the start of the r->header_in buf in ngx_http_set_keepalive().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||||
@ -757,8 +757,10 @@ static void ngx_http_process_request_headers(ngx_event_t *rev)
|
|||||||
|
|
||||||
if (r->header_in->last == r->header_in->end) {
|
if (r->header_in->last == r->header_in->end) {
|
||||||
|
|
||||||
/* if the large client headers are enabled then
|
/*
|
||||||
we need to compact r->header_in hunk */
|
* if the large client headers are enabled then
|
||||||
|
* we need to compact r->header_in buf
|
||||||
|
*/
|
||||||
|
|
||||||
if (cscf->large_client_header) {
|
if (cscf->large_client_header) {
|
||||||
offset = r->header_name_start - r->header_in->start;
|
offset = r->header_name_start - r->header_in->start;
|
||||||
@ -1315,13 +1317,13 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
|
|||||||
|
|
||||||
ctx->action = "keepalive";
|
ctx->action = "keepalive";
|
||||||
|
|
||||||
if (c->tcp_nopush == 1) {
|
if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
|
||||||
if (ngx_tcp_push(c->fd) == NGX_ERROR) {
|
if (ngx_tcp_push(c->fd) == NGX_ERROR) {
|
||||||
ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
|
ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
|
||||||
ngx_http_close_connection(c);
|
ngx_http_close_connection(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
c->tcp_nopush = 0;
|
c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rev->ready) {
|
if (rev->ready) {
|
||||||
|
@ -223,15 +223,6 @@ struct ngx_http_request_s {
|
|||||||
|
|
||||||
ngx_http_request_body_t *request_body;
|
ngx_http_request_body_t *request_body;
|
||||||
|
|
||||||
#if 0
|
|
||||||
ngx_temp_file_t *temp_file;
|
|
||||||
ngx_chain_t *request_hunks;
|
|
||||||
ngx_hunk_t *request_body_hunk;
|
|
||||||
size_t remaining_body_len;
|
|
||||||
void (*request_body_handler) (void *data);
|
|
||||||
void *data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
time_t lingering_time;
|
time_t lingering_time;
|
||||||
|
|
||||||
ngx_uint_t method;
|
ngx_uint_t method;
|
||||||
|
@ -129,8 +129,8 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
ngx_http_write_filter_module);
|
ngx_http_write_filter_module);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* avoid the output if there is no last hunk, no flush point,
|
* avoid the output if there is no last buf, no flush point,
|
||||||
* there are the incoming hunks and the size of all hunks
|
* there are the incoming bufs and the size of all bufs
|
||||||
* is smaller than "postpone_output" directive
|
* is smaller than "postpone_output" directive
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl,
|
|||||||
ngx_err_t err;
|
ngx_err_t err;
|
||||||
ngx_array_t io;
|
ngx_array_t io;
|
||||||
|
|
||||||
/* use pwrite() if there's the only hunk in a chain */
|
/* use pwrite() if there's the only buf in a chain */
|
||||||
|
|
||||||
if (cl->next == NULL) {
|
if (cl->next == NULL) {
|
||||||
return ngx_write_file(file, cl->buf->pos,
|
return ngx_write_file(file, cl->buf->pos,
|
||||||
|
@ -162,7 +162,9 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
|
|
||||||
if (ngx_freebsd_use_tcp_nopush && c->tcp_nopush == 0) {
|
if (ngx_freebsd_use_tcp_nopush
|
||||||
|
&& c->tcp_nopush == NGX_TCP_NOPUSH_UNSET)
|
||||||
|
{
|
||||||
|
|
||||||
if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
|
if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
|
||||||
err = ngx_errno;
|
err = ngx_errno;
|
||||||
@ -180,7 +182,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
c->tcp_nopush = 1;
|
c->tcp_nopush = NGX_TCP_NOPUSH_SET;
|
||||||
|
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
"tcp_nopush");
|
"tcp_nopush");
|
||||||
}
|
}
|
||||||
|
@ -58,32 +58,32 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
/* create the iovec and coalesce the neighbouring bufs */
|
/* create the iovec and coalesce the neighbouring bufs */
|
||||||
|
|
||||||
for (cl = in; cl && header.nelts < IOV_MAX; cl = cl->next) {
|
for (cl = in; cl && header.nelts < IOV_MAX; cl = cl->next) {
|
||||||
if (ngx_hunk_special(cl->hunk)) {
|
if (ngx_buf_special(cl->buf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ngx_hunk_in_memory_only(cl->hunk)) {
|
if (!ngx_buf_in_memory_only(cl->buf)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev == cl->hunk->pos) {
|
if (prev == cl->buf->pos) {
|
||||||
iov->iov_len += cl->hunk->last - cl->hunk->pos;
|
iov->iov_len += cl->buf->last - cl->buf->pos;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
|
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
|
||||||
iov->iov_base = (void *) cl->hunk->pos;
|
iov->iov_base = (void *) cl->buf->pos;
|
||||||
iov->iov_len = cl->hunk->last - cl->hunk->pos;
|
iov->iov_len = cl->buf->last - cl->buf->pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = cl->hunk->last;
|
prev = cl->buf->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set TCP_CORK if there is a header before a file */
|
/* set TCP_CORK if there is a header before a file */
|
||||||
|
|
||||||
if (!c->tcp_nopush == 0
|
if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET
|
||||||
&& header.nelts != 0
|
&& header.nelts != 0
|
||||||
&& cl
|
&& cl
|
||||||
&& cl->hunk->type & NGX_HUNK_FILE)
|
&& cl->buf->in_file)
|
||||||
{
|
{
|
||||||
if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
|
if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
|
||||||
err = ngx_errno;
|
err = ngx_errno;
|
||||||
@ -100,32 +100,33 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
c->tcp_nopush = 1;
|
c->tcp_nopush = NGX_TCP_NOPUSH_SET;
|
||||||
|
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
"tcp_nopush");
|
"tcp_nopush");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.nelts == 0 && cl && cl->hunk->type & NGX_HUNK_FILE) {
|
if (header.nelts == 0 && cl && cl->buf->in_file) {
|
||||||
|
|
||||||
/* get the file hunk */
|
/* get the file buf */
|
||||||
|
|
||||||
file = cl->hunk;
|
file = cl->buf;
|
||||||
fsize = (size_t) (file->file_last - file->file_pos);
|
fsize = (size_t) (file->file_last - file->file_pos);
|
||||||
fprev = file->file_last;
|
fprev = file->file_last;
|
||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
|
|
||||||
/* coalesce the neighbouring file hunks */
|
/* coalesce the neighbouring file bufs */
|
||||||
|
|
||||||
while (cl && (cl->hunk->type & NGX_HUNK_FILE)) {
|
while (cl && (cl->buf->in_file)) {
|
||||||
if (file->file->fd != cl->hunk->file->fd
|
if (file->file->fd != cl->buf->file->fd
|
||||||
|| fprev != cl->hunk->file_pos)
|
|| fprev != cl->buf->file_pos)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsize += (size_t) (cl->hunk->file_last - cl->hunk->file_pos);
|
fsize += (size_t) (cl->buf->file_last - cl->buf->file_pos);
|
||||||
fprev = cl->hunk->file_last;
|
fprev = cl->buf->file_last;
|
||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +200,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
for (cl = in; cl; cl = cl->next) {
|
for (cl = in; cl; cl = cl->next) {
|
||||||
|
|
||||||
if (ngx_hunk_special(cl->hunk)) {
|
if (ngx_buf_special(cl->buf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,28 +208,28 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = ngx_hunk_size(cl->hunk);
|
size = ngx_buf_size(cl->buf);
|
||||||
|
|
||||||
if (sent >= size) {
|
if (sent >= size) {
|
||||||
sent -= size;
|
sent -= size;
|
||||||
|
|
||||||
if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
|
if (ngx_buf_in_memory(cl->buf)) {
|
||||||
cl->hunk->pos = cl->hunk->last;
|
cl->buf->pos = cl->buf->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl->hunk->type & NGX_HUNK_FILE) {
|
if (cl->buf->in_file) {
|
||||||
cl->hunk->file_pos = cl->hunk->file_last;
|
cl->buf->file_pos = cl->buf->file_last;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
|
if (ngx_buf_in_memory(cl->buf)) {
|
||||||
cl->hunk->pos += sent;
|
cl->buf->pos += sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl->hunk->type & NGX_HUNK_FILE) {
|
if (cl->buf->in_file) {
|
||||||
cl->hunk->file_pos += sent;
|
cl->buf->file_pos += sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -43,42 +43,42 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
/* create the sendfilevec and coalesce the neighbouring bufs */
|
/* create the sendfilevec and coalesce the neighbouring bufs */
|
||||||
|
|
||||||
for (cl = in; cl && vec.nelts < IOV_MAX; cl = cl->next) {
|
for (cl = in; cl && vec.nelts < IOV_MAX; cl = cl->next) {
|
||||||
if (ngx_hunk_special(cl->hunk)) {
|
if (ngx_buf_special(cl->buf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_hunk_in_memory_only(cl->hunk)) {
|
if (ngx_buf_in_memory_only(cl->buf)) {
|
||||||
fd = SFV_FD_SELF;
|
fd = SFV_FD_SELF;
|
||||||
|
|
||||||
if (prev == cl->hunk->pos) {
|
if (prev == cl->buf->pos) {
|
||||||
sfv->sfv_len += cl->hunk->last - cl->hunk->pos;
|
sfv->sfv_len += cl->buf->last - cl->buf->pos;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
||||||
sfv->sfv_fd = SFV_FD_SELF;
|
sfv->sfv_fd = SFV_FD_SELF;
|
||||||
sfv->sfv_flag = 0;
|
sfv->sfv_flag = 0;
|
||||||
sfv->sfv_off = (off_t) (uintptr_t) cl->hunk->pos;
|
sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
|
||||||
sfv->sfv_len = cl->hunk->last - cl->hunk->pos;
|
sfv->sfv_len = cl->buf->last - cl->buf->pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = cl->hunk->last;
|
prev = cl->buf->last;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
|
|
||||||
if (fd == cl->hunk->file->fd && fprev == cl->hunk->file_pos) {
|
if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
|
||||||
sfv->sfv_len += cl->hunk->file_last - cl->hunk->file_pos;
|
sfv->sfv_len += cl->buf->file_last - cl->buf->file_pos;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
|
||||||
fd = cl->hunk->file->fd;
|
fd = cl->buf->file->fd;
|
||||||
sfv->sfv_fd = fd;
|
sfv->sfv_fd = fd;
|
||||||
sfv->sfv_flag = 0;
|
sfv->sfv_flag = 0;
|
||||||
sfv->sfv_off = cl->hunk->file_pos;
|
sfv->sfv_off = cl->buf->file_pos;
|
||||||
sfv->sfv_len = cl->hunk->file_last - cl->hunk->file_pos;
|
sfv->sfv_len = cl->buf->file_last - cl->buf->file_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprev = cl->hunk->file_last;
|
fprev = cl->buf->file_last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
for (cl = in; cl; cl = cl->next) {
|
for (cl = in; cl; cl = cl->next) {
|
||||||
|
|
||||||
if (ngx_hunk_special(cl->hunk)) {
|
if (ngx_buf_special(cl->buf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,28 +125,28 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = ngx_hunk_size(cl->hunk);
|
size = ngx_buf_size(cl->buf);
|
||||||
|
|
||||||
if (sent >= size) {
|
if (sent >= size) {
|
||||||
sent -= size;
|
sent -= size;
|
||||||
|
|
||||||
if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
|
if (ngx_buf_in_memory(cl->buf)) {
|
||||||
cl->hunk->pos = cl->hunk->last;
|
cl->buf->pos = cl->buf->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl->hunk->type & NGX_HUNK_FILE) {
|
if (cl->buf->in_file) {
|
||||||
cl->hunk->file_pos = cl->hunk->file_last;
|
cl->buf->file_pos = cl->buf->file_last;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
|
if (ngx_buf_in_memory(cl->buf)) {
|
||||||
cl->hunk->pos += sent;
|
cl->buf->pos += sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl->hunk->type & NGX_HUNK_FILE) {
|
if (cl->buf->in_file) {
|
||||||
cl->hunk->file_pos += sent;
|
cl->buf->file_pos += sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -143,7 +143,7 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl,
|
|||||||
prev = buf;
|
prev = buf;
|
||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
/* coalesce the neighbouring hunks */
|
/* coalesce the neighbouring bufs */
|
||||||
|
|
||||||
while (cl && prev == cl->buf->pos) {
|
while (cl && prev == cl->buf->pos) {
|
||||||
size += cl->buf->last - cl->buf->pos;
|
size += cl->buf->last - cl->buf->pos;
|
||||||
|
@ -241,180 +241,3 @@ ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|||||||
|
|
||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char *prev;
|
|
||||||
size_t size, sent;
|
|
||||||
LPWSABUF wsabuf;
|
|
||||||
ngx_err_t err;
|
|
||||||
ngx_event_t *wev;
|
|
||||||
ngx_array_t wsabufs;
|
|
||||||
ngx_chain_t *ce;
|
|
||||||
LPWSAOVERLAPPED ovlp;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
iocp:
|
|
||||||
if ready
|
|
||||||
get result
|
|
||||||
update chain
|
|
||||||
return if done;
|
|
||||||
wsasend
|
|
||||||
|
|
||||||
non-block
|
|
||||||
for ( ;; ) {
|
|
||||||
wsasend
|
|
||||||
if no again
|
|
||||||
update chain
|
|
||||||
return if done;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for ( ;; ) {
|
|
||||||
|
|
||||||
make buffers and limit data for both ovlp and nonblocked,
|
|
||||||
configured in events module
|
|
||||||
|
|
||||||
if (iocp && ready) {
|
|
||||||
get result
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (file)
|
|
||||||
transmitfile
|
|
||||||
else
|
|
||||||
wsasend
|
|
||||||
|
|
||||||
if (iocp)
|
|
||||||
return chain
|
|
||||||
return chain if again
|
|
||||||
here is result
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
update chain;
|
|
||||||
return chain if done
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wev = c->write;
|
|
||||||
|
|
||||||
if (((ngx_event_flags & NGX_USE_AIO_EVENT) && !wev->ready)
|
|
||||||
|| ((ngx_event_flags & NGX_USE_AIO_EVENT) == 0))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* WSABUFs must be 4-byte aligned otherwise
|
|
||||||
* WSASend() will return undocumented WSAEINVAL error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR);
|
|
||||||
|
|
||||||
prev = NULL;
|
|
||||||
wsabuf = NULL;
|
|
||||||
|
|
||||||
/* create the WSABUF and coalesce the neighbouring chain entries */
|
|
||||||
for (ce = in; ce; ce = ce->next) {
|
|
||||||
|
|
||||||
if (prev == ce->hunk->pos) {
|
|
||||||
wsabuf->len += ce->hunk->last - ce->hunk->pos;
|
|
||||||
prev = ce->hunk->last;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ngx_test_null(wsabuf, ngx_push_array(&wsabufs),
|
|
||||||
NGX_CHAIN_ERROR);
|
|
||||||
wsabuf->buf = ce->hunk->pos;
|
|
||||||
wsabuf->len = ce->hunk->last - ce->hunk->pos;
|
|
||||||
prev = ce->hunk->last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngx_event_flags & NGX_USE_AIO_EVENT) {
|
|
||||||
ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
|
|
||||||
ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ovlp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, ovlp, NULL);
|
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
err = ngx_errno;
|
|
||||||
if (err == WSA_IO_PENDING) {
|
|
||||||
sent = 0;
|
|
||||||
|
|
||||||
} else if (err == WSAEWOULDBLOCK) {
|
|
||||||
sent = 0;
|
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, err, "WSASend() EAGAIN");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSASend() failed");
|
|
||||||
return NGX_CHAIN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If a socket was bound with I/O completion port then
|
|
||||||
* GetQueuedCompletionStatus() would anyway return its status
|
|
||||||
* despite that WSASend() was already completed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
sent = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
|
|
||||||
wev->ready = 0;
|
|
||||||
|
|
||||||
/* the overlapped WSASend() completed */
|
|
||||||
|
|
||||||
if (wev->ovlp.error) {
|
|
||||||
ngx_log_error(NGX_LOG_ERR, c->log, wev->ovlp.error,
|
|
||||||
"WSASend() failed");
|
|
||||||
return NGX_CHAIN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
sent = wev->available;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_log_debug(c->log, "WSASend(): %d" _ sent);
|
|
||||||
|
|
||||||
c->sent += sent;
|
|
||||||
|
|
||||||
for (ce = in; ce && sent > 0; ce = ce->next) {
|
|
||||||
|
|
||||||
size = ce->hunk->last - ce->hunk->pos;
|
|
||||||
|
|
||||||
if (sent >= size) {
|
|
||||||
sent -= size;
|
|
||||||
|
|
||||||
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
|
|
||||||
ce->hunk->pos = ce->hunk->last;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
|
|
||||||
ce->hunk->pos += sent;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ce;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
Loading…
Reference in New Issue
Block a user