annotate src/stream/ngx_stream_write_filter_module.c @ 8006:32b0ba4855a6

HTTP/2: made it possible to flush response headers (ticket #1743). Response headers can be buffered in the SSL buffer. But stream's fake connection buffered flag did not reflect this, so any attempts to flush the buffer without sending additional data were stopped by the write filter. It does not seem to be possible to reflect this in fc->buffered though, as we never known if main connection's c->buffered corresponds to the particular stream or not. As such, fc->buffered might prevent request finalization due to sending data on some other stream. Fix is to implement handling of flush buffers when the c->need_flush_buf flag is set, similarly to the existing last buffer handling. The same flag is now used for UDP sockets in the stream module instead of explicit checking of c->type.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 03 Feb 2022 01:44:38 +0300
parents d127837c714f
children 9ea62b6250f2
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 (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
108 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
109 "zero size buf in writer "
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
110 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
111 cl->buf->temporary,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
112 cl->buf->recycled,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
113 cl->buf->in_file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
114 cl->buf->start,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
115 cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
116 cl->buf->last,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
117 cl->buf->file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
118 cl->buf->file_pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
119 cl->buf->file_last);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
120
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
121 ngx_debug_point();
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
122 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
123 }
7401
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
124
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
125 if (ngx_buf_size(cl->buf) < 0) {
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
126 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
127 "negative size buf in writer "
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
128 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
129 cl->buf->temporary,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
130 cl->buf->recycled,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
131 cl->buf->in_file,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
132 cl->buf->start,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
133 cl->buf->pos,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
134 cl->buf->last,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
135 cl->buf->file,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
136 cl->buf->file_pos,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
137 cl->buf->file_last);
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
138
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
139 ngx_debug_point();
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
140 return NGX_ERROR;
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
141 }
6692
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
142
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
143 size += ngx_buf_size(cl->buf);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
144
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
145 if (cl->buf->flush || cl->buf->recycled) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
146 flush = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
147 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
148
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
149 if (cl->buf->sync) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
150 sync = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
151 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
152
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
153 if (cl->buf->last_buf) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
154 last = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
155 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
156 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
157
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
158 /* add the new chain to the existent one */
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
159
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
160 for (ln = in; ln; ln = ln->next) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
161 cl = ngx_alloc_chain_link(c->pool);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
162 if (cl == NULL) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
163 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
164 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
165
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
166 cl->buf = ln->buf;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
167 *ll = cl;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
168 ll = &cl->next;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
169
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
170 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
171 "write new buf t:%d f:%d %p, pos %p, size: %z "
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
172 "file: %O, size: %O",
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
173 cl->buf->temporary, cl->buf->in_file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
174 cl->buf->start, cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
175 cl->buf->last - cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
176 cl->buf->file_pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
177 cl->buf->file_last - cl->buf->file_pos);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
178
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
179 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
180 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
181 "zero size buf in writer "
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
182 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
183 cl->buf->temporary,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
184 cl->buf->recycled,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
185 cl->buf->in_file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
186 cl->buf->start,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
187 cl->buf->pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
188 cl->buf->last,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
189 cl->buf->file,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
190 cl->buf->file_pos,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
191 cl->buf->file_last);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
192
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
193 ngx_debug_point();
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
194 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
195 }
7401
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
196
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
197 if (ngx_buf_size(cl->buf) < 0) {
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
198 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
199 "negative size buf in writer "
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
200 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
201 cl->buf->temporary,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
202 cl->buf->recycled,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
203 cl->buf->in_file,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
204 cl->buf->start,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
205 cl->buf->pos,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
206 cl->buf->last,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
207 cl->buf->file,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
208 cl->buf->file_pos,
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
209 cl->buf->file_last);
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
210
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
211 ngx_debug_point();
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
212 return NGX_ERROR;
a7ff19afbb14 Negative size buffers detection.
Maxim Dounin <mdounin@mdounin.ru>
parents: 6692
diff changeset
213 }
6692
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
214
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
215 size += ngx_buf_size(cl->buf);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
216
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
217 if (cl->buf->flush || cl->buf->recycled) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
218 flush = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
219 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
220
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
221 if (cl->buf->sync) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
222 sync = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
223 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
224
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
225 if (cl->buf->last_buf) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
226 last = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
227 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
228 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
229
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
230 *ll = NULL;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
231
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
232 ngx_log_debug3(NGX_LOG_DEBUG_STREAM, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
233 "stream write filter: l:%ui f:%ui s:%O", last, flush, size);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
234
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
235 if (size == 0
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
236 && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
7665
d127837c714f Stream: fixed processing of zero length UDP packets (ticket #1982).
Vladimir Homutov <vl@nginx.com>
parents: 7401
diff changeset
237 && !(last && c->need_last_buf)
8006
32b0ba4855a6 HTTP/2: made it possible to flush response headers (ticket #1743).
Maxim Dounin <mdounin@mdounin.ru>
parents: 7665
diff changeset
238 && !(flush && c->need_flush_buf))
6692
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
239 {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
240 if (last || flush || sync) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
241 for (cl = *out; cl; /* void */) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
242 ln = cl;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
243 cl = cl->next;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
244 ngx_free_chain(c->pool, ln);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
245 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
246
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
247 *out = NULL;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
248 c->buffered &= ~NGX_STREAM_WRITE_BUFFERED;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
249
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
250 return NGX_OK;
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 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
254 "the stream output chain is empty");
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
255
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
256 ngx_debug_point();
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
257
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
258 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
259 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
260
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
261 chain = c->send_chain(c, *out, 0);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
262
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
263 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
264 "stream write filter %p", chain);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
265
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
266 if (chain == NGX_CHAIN_ERROR) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
267 c->error = 1;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
268 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
269 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
270
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
271 for (cl = *out; cl && cl != chain; /* void */) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
272 ln = cl;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
273 cl = cl->next;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
274 ngx_free_chain(c->pool, ln);
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
275 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
276
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
277 *out = chain;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
278
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
279 if (chain) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
280 if (c->shared) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
281 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
282 "shared connection is busy");
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
283 return NGX_ERROR;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
284 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
285
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
286 c->buffered |= NGX_STREAM_WRITE_BUFFERED;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
287 return NGX_AGAIN;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
288 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
289
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
290 c->buffered &= ~NGX_STREAM_WRITE_BUFFERED;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
291
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
292 if (c->buffered & NGX_LOWLEVEL_BUFFERED) {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
293 return NGX_AGAIN;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
294 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
295
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
296 return NGX_OK;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
297 }
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
298
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
299
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
300 static ngx_int_t
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
301 ngx_stream_write_filter_init(ngx_conf_t *cf)
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
302 {
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
303 ngx_stream_top_filter = ngx_stream_write_filter;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
304
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
305 return NGX_OK;
56fc55e32f23 Stream: filters.
Roman Arutyunyan <arut@nginx.com>
parents:
diff changeset
306 }