annotate src/stream/ngx_stream_write_filter_module.c @ 7098:7bfbf73db920

Stream: relaxed next upstream condition (ticket #1317). When switching to a next upstream, some buffers could be stuck in the middle of the filter chain. A condition existed that raised an error when this happened. As it turned out, this condition prevented switching to a next upstream if ssl preread was used with the TCP protocol (see the ticket). In fact, the condition does not make sense for TCP, since after successful connection to an upstream switching to another upstream never happens. As for UDP, the issue with stuck buffers is unlikely to happen, but is still possible. Specifically, if a filter delays sending data to upstream. The condition can be relaxed to only check the "buffered" bitmask of the upstream connection. The new condition is simpler and fixes the ticket issue as well. Additionally, the upstream_out chain is now reset for UDP prior to connecting to a new upstream to prevent repeating the client data twice.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 11 Sep 2017 15:32:31 +0300
parents 56fc55e32f23
children a7ff19afbb14
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6692
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
1
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
2 /*
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
3 * Copyright (C) Igor Sysoev
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
4 * Copyright (C) Nginx, Inc.
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
5 */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
6
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
7
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
8 #include <ngx_config.h>
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
9 #include <ngx_core.h>
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
10 #include <ngx_stream.h>
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
11
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
12
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
13 typedef struct {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
14 ngx_chain_t *from_upstream;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
15 ngx_chain_t *from_downstream;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
16 } ngx_stream_write_filter_ctx_t;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
17
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
18
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
19 static ngx_int_t ngx_stream_write_filter(ngx_stream_session_t *s,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
20 ngx_chain_t *in, ngx_uint_t from_upstream);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
21 static ngx_int_t ngx_stream_write_filter_init(ngx_conf_t *cf);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
22
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
23
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
24 static ngx_stream_module_t ngx_stream_write_filter_module_ctx = {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
25 NULL, /* preconfiguration */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
26 ngx_stream_write_filter_init, /* postconfiguration */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
27
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
28 NULL, /* create main configuration */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
29 NULL, /* init main configuration */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
30
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
31 NULL, /* create server configuration */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
32 NULL /* merge server configuration */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
33 };
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
34
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
35
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
36 ngx_module_t ngx_stream_write_filter_module = {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
37 NGX_MODULE_V1,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
38 &ngx_stream_write_filter_module_ctx, /* module context */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
39 NULL, /* module directives */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
40 NGX_STREAM_MODULE, /* module type */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
41 NULL, /* init master */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
42 NULL, /* init module */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
43 NULL, /* init process */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
44 NULL, /* init thread */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
45 NULL, /* exit thread */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
46 NULL, /* exit process */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
47 NULL, /* exit master */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
48 NGX_MODULE_V1_PADDING
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
49 };
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
50
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
51
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
52 static ngx_int_t
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
53 ngx_stream_write_filter(ngx_stream_session_t *s, ngx_chain_t *in,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
54 ngx_uint_t from_upstream)
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
55 {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
56 off_t size;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
57 ngx_uint_t last, flush, sync;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
58 ngx_chain_t *cl, *ln, **ll, **out, *chain;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
59 ngx_connection_t *c;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
60 ngx_stream_write_filter_ctx_t *ctx;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
61
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
62 ctx = ngx_stream_get_module_ctx(s, ngx_stream_write_filter_module);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
63
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
64 if (ctx == NULL) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
65 ctx = ngx_pcalloc(s->connection->pool,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
66 sizeof(ngx_stream_write_filter_ctx_t));
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
67 if (ctx == NULL) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
68 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
69 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
70
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
71 ngx_stream_set_ctx(s, ctx, ngx_stream_write_filter_module);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
72 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
73
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
74 if (from_upstream) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
75 c = s->connection;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
76 out = &ctx->from_upstream;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
77
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
78 } else {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
79 c = s->upstream->peer.connection;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
80 out = &ctx->from_downstream;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
81 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
82
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
83 if (c->error) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
84 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
85 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
86
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
87 size = 0;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
88 flush = 0;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
89 sync = 0;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
90 last = 0;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
91 ll = out;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
92
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
93 /* find the size, the flush point and the last link of the saved chain */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
94
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
95 for (cl = *out; cl; cl = cl->next) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
96 ll = &cl->next;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
97
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
98 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
99 "write old buf t:%d f:%d %p, pos %p, size: %z "
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
100 "file: %O, size: %O",
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
101 cl->buf->temporary, cl->buf->in_file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
102 cl->buf->start, cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
103 cl->buf->last - cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
104 cl->buf->file_pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
105 cl->buf->file_last - cl->buf->file_pos);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
106
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
107 #if 1
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
108 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
109 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
110 "zero size buf in writer "
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
111 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
112 cl->buf->temporary,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
113 cl->buf->recycled,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
114 cl->buf->in_file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
115 cl->buf->start,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
116 cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
117 cl->buf->last,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
118 cl->buf->file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
119 cl->buf->file_pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
120 cl->buf->file_last);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
121
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
122 ngx_debug_point();
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
123 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
124 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
125 #endif
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
126
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
127 size += ngx_buf_size(cl->buf);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
128
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
129 if (cl->buf->flush || cl->buf->recycled) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
130 flush = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
131 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
132
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
133 if (cl->buf->sync) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
134 sync = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
135 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
136
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
137 if (cl->buf->last_buf) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
138 last = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
139 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
140 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
141
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
142 /* add the new chain to the existent one */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
143
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
144 for (ln = in; ln; ln = ln->next) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
145 cl = ngx_alloc_chain_link(c->pool);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
146 if (cl == NULL) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
147 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
148 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
149
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
150 cl->buf = ln->buf;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
151 *ll = cl;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
152 ll = &cl->next;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
153
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
154 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
155 "write new buf t:%d f:%d %p, pos %p, size: %z "
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
156 "file: %O, size: %O",
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
157 cl->buf->temporary, cl->buf->in_file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
158 cl->buf->start, cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
159 cl->buf->last - cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
160 cl->buf->file_pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
161 cl->buf->file_last - cl->buf->file_pos);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
162
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
163 #if 1
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
164 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
165 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
166 "zero size buf in writer "
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
167 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
168 cl->buf->temporary,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
169 cl->buf->recycled,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
170 cl->buf->in_file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
171 cl->buf->start,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
172 cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
173 cl->buf->last,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
174 cl->buf->file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
175 cl->buf->file_pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
176 cl->buf->file_last);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
177
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
178 ngx_debug_point();
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
179 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
180 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
181 #endif
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
182
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
183 size += ngx_buf_size(cl->buf);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
184
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
185 if (cl->buf->flush || cl->buf->recycled) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
186 flush = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
187 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
188
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
189 if (cl->buf->sync) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
190 sync = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
191 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
192
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
193 if (cl->buf->last_buf) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
194 last = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
195 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
196 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
197
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
198 *ll = NULL;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
199
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
200 ngx_log_debug3(NGX_LOG_DEBUG_STREAM, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
201 "stream write filter: l:%ui f:%ui s:%O", last, flush, size);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
202
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
203 if (size == 0
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
204 && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
205 && !(last && c->need_last_buf))
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
206 {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
207 if (last || flush || sync) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
208 for (cl = *out; cl; /* void */) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
209 ln = cl;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
210 cl = cl->next;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
211 ngx_free_chain(c->pool, ln);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
212 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
213
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
214 *out = NULL;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
215 c->buffered &= ~NGX_STREAM_WRITE_BUFFERED;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
216
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
217 return NGX_OK;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
218 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
219
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
220 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
221 "the stream output chain is empty");
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
222
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
223 ngx_debug_point();
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
224
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
225 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
226 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
227
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
228 chain = c->send_chain(c, *out, 0);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
229
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
230 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
231 "stream write filter %p", chain);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
232
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
233 if (chain == NGX_CHAIN_ERROR) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
234 c->error = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
235 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
236 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
237
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
238 for (cl = *out; cl && cl != chain; /* void */) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
239 ln = cl;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
240 cl = cl->next;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
241 ngx_free_chain(c->pool, ln);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
242 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
243
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
244 *out = chain;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
245
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
246 if (chain) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
247 if (c->shared) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
248 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
249 "shared connection is busy");
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
250 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
251 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
252
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
253 c->buffered |= NGX_STREAM_WRITE_BUFFERED;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
254 return NGX_AGAIN;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
255 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
256
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
257 c->buffered &= ~NGX_STREAM_WRITE_BUFFERED;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
258
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
259 if (c->buffered & NGX_LOWLEVEL_BUFFERED) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
260 return NGX_AGAIN;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
261 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
262
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
263 return NGX_OK;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
264 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
265
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
266
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
267 static ngx_int_t
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
268 ngx_stream_write_filter_init(ngx_conf_t *cf)
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
269 {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
270 ngx_stream_top_filter = ngx_stream_write_filter;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
271
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
272 return NGX_OK;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
273 }