comparison src/os/win32/ngx_wsasend_chain.c @ 461:a88a3e4e158f release-0.1.5

nginx-0.1.5-RELEASE import *) Bugfix: on Solaris and Linux there may be too many "recvmsg() returned not enough data" alerts. *) Bugfix: there were the "writev() failed (22: Invalid argument)" errors on Solaris in proxy mode without sendfile. On other platforms that do not support sendfile at all the process got caught in an endless loop. *) Bugfix: segmentation fault on Solaris in proxy mode and using sendfile. *) Bugfix: segmentation fault on Solaris. *) Bugfix: on-line upgrade did not work on Linux. *) Bugfix: the ngx_http_autoindex_module module did not escape the spaces, the quotes, and the percent signs in the directory listing. *) Change: the decrease of the copy operations. *) Feature: the userid_p3p directive.
author Igor Sysoev <igor@sysoev.ru>
date Thu, 11 Nov 2004 14:07:14 +0000
parents 42d11f017717
children 8e8f3af115b5
comparison
equal deleted inserted replaced
460:5f8319142dfc 461:a88a3e4e158f
5 5
6 6
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10
11
12 #define NGX_WSABUFS 8
10 13
11 14
12 ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, 15 ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in,
13 off_t limit) 16 off_t limit)
14 { 17 {
15 int rc; 18 int rc;
16 u_char *prev; 19 u_char *prev;
17 size_t size; 20 u_long size, sent, send, sprev;
18 u_long sent; 21 ngx_uint_t complete;
19 LPWSABUF wsabuf;
20 ngx_err_t err; 22 ngx_err_t err;
21 ngx_event_t *wev; 23 ngx_event_t *wev;
22 ngx_array_t wsabufs; 24 ngx_array_t vec;
25 LPWSABUF wsabuf;
26 WSABUF wsabufs[NGX_WSABUFS];
23 ngx_chain_t *cl; 27 ngx_chain_t *cl;
24 28
25 wev = c->write; 29 wev = c->write;
26 30
27 if (!wev->ready) { 31 if (!wev->ready) {
28 return in; 32 return in;
29 } 33 }
34
35 send = 0;
36 complete = 0;
30 37
31 /* 38 /*
32 * WSABUFs must be 4-byte aligned otherwise 39 * WSABUFs must be 4-byte aligned otherwise
33 * WSASend() will return undocumented WSAEINVAL error. 40 * WSASend() will return undocumented WSAEINVAL error.
34 */ 41 */
35 42
36 ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR); 43 vec.elts = wsabufs;
37 44 vec.size = sizeof(WSABUF);
38 prev = NULL; 45 vec.nalloc = NGX_WSABUFS;
39 wsabuf = NULL; 46 vec.pool = c->pool;
40 47
41 /* create the WSABUF and coalesce the neighbouring bufs */ 48 for ( ;; ) {
42 49 prev = NULL;
43 for (cl = in; cl; cl = cl->next) { 50 wsabuf = NULL;
44 51 sprev = send;
45 if (prev == cl->buf->pos) { 52
46 wsabuf->len += cl->buf->last - cl->buf->pos; 53 vec.nelts = 0;
54
55 /* create the WSABUF and coalesce the neighbouring bufs */
56
57 for (cl = in;
58 cl && vec.nelts < ngx_max_wsabufs && send < limit;
59 cl = cl->next)
60 {
61 if (ngx_buf_special(cl->buf)) {
62 continue;
63 }
64
65 size = cl->buf->last - cl->buf->pos;
66
67 if (send + size > limit) {
68 size = (u_long) (limit - send);
69 }
70
71 if (prev == cl->buf->pos) {
72 wsabuf->len += cl->buf->last - cl->buf->pos;
73
74 } else {
75 if (!(wsabuf = ngx_array_push(&vec))) {
76 return NGX_CHAIN_ERROR;
77 }
78
79 wsabuf->buf = (char *) cl->buf->pos;
80 wsabuf->len = cl->buf->last - cl->buf->pos;
81 }
82
47 prev = cl->buf->last; 83 prev = cl->buf->last;
48 84 send += size;
49 } else { 85 }
50 ngx_test_null(wsabuf, ngx_push_array(&wsabufs), NGX_CHAIN_ERROR); 86
51 wsabuf->buf = (char *) cl->buf->pos; 87 sent = 0;
52 wsabuf->len = cl->buf->last - cl->buf->pos; 88
53 prev = cl->buf->last; 89 rc = WSASend(c->fd, vec.elts, vec.nelts, &sent, 0, NULL, NULL);
54 } 90
55 } 91 if (rc == -1) {
56 92 err = ngx_errno;
57 rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, NULL, NULL); 93
58 94 if (err == WSAEWOULDBLOCK) {
59 if (rc == -1) { 95 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
60 err = ngx_errno; 96 "WSASend() not ready");
61 97
62 if (err == WSAEWOULDBLOCK) { 98 } else {
63 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, 99 wev->error = 1;
64 "WSASend() not ready"); 100 ngx_connection_error(c, err, "WSASend() failed");
101 return NGX_CHAIN_ERROR;
102 }
103 }
104
105 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
106 "WSASend: fd:%d, s:%ul", c->fd, sent);
107
108 if (send - sprev == sent) {
109 complete = 1;
110 }
111
112 c->sent += sent;
113
114 for (cl = in; cl && sent > 0; cl = cl->next) {
115 if (ngx_buf_special(cl->buf)) {
116 continue;
117 }
118
119 if (sent == 0) {
120 break;
121 }
122
123 size = cl->buf->last - cl->buf->pos;
124
125 if (sent >= size) {
126 sent -= size;
127 cl->buf->pos = cl->buf->last;
128
129 continue;
130 }
131
132 cl->buf->pos += sent;
133
134 break;
135 }
136
137 if (!complete) {
65 wev->ready = 0; 138 wev->ready = 0;
66 return in; 139 return cl;
67 140 }
68 } else { 141
69 wev->error = 1; 142 if (send >= limit || cl == NULL) {
70 ngx_connection_error(c, err, "WSASend() failed"); 143 return cl;
71 return NGX_CHAIN_ERROR; 144 }
72 } 145
73 } 146 in = cl;
74 147 }
75 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSASend: %d", sent);
76
77 c->sent += sent;
78
79 for (cl = in; cl && sent > 0; cl = cl->next) {
80
81 size = cl->buf->last - cl->buf->pos;
82
83 if (sent >= size) {
84 sent -= size;
85
86 if (ngx_buf_in_memory(cl->buf)) {
87 cl->buf->pos = cl->buf->last;
88 }
89
90 continue;
91 }
92
93 if (ngx_buf_in_memory(cl->buf)) {
94 cl->buf->pos += sent;
95 }
96
97 break;
98 }
99
100 if (cl) {
101 wev->ready = 0;
102 }
103
104 return cl;
105 } 148 }
106 149
107 150
108 ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, 151 ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in,
109 off_t limit) 152 off_t limit)
110 { 153 {
111 int rc; 154 int rc;
112 u_char *prev; 155 u_char *prev;
113 size_t size; 156 size_t size;
114 u_long sent; 157 u_long send, sent;
115 LPWSABUF wsabuf; 158 LPWSABUF wsabuf;
116 ngx_err_t err; 159 ngx_err_t err;
117 ngx_event_t *wev; 160 ngx_event_t *wev;
118 ngx_array_t wsabufs; 161 ngx_array_t vec;
119 ngx_chain_t *cl; 162 ngx_chain_t *cl;
120 LPWSAOVERLAPPED ovlp; 163 LPWSAOVERLAPPED ovlp;
164 WSABUF wsabufs[NGX_WSABUFS];
121 165
122 wev = c->write; 166 wev = c->write;
123 167
124 if (!wev->ready) { 168 if (!wev->ready) {
125 return in; 169 return in;
126 } 170 }
171
172 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
173 "wev->complete: %d", wev->complete);
127 174
128 if (!wev->complete) { 175 if (!wev->complete) {
129 176
130 /* post the overlapped WSASend() */ 177 /* post the overlapped WSASend() */
131 178
132 /* 179 /*
133 * WSABUFs must be 4-byte aligned otherwise 180 * WSABUFs must be 4-byte aligned otherwise
134 * WSASend() will return undocumented WSAEINVAL error. 181 * WSASend() will return undocumented WSAEINVAL error.
135 */ 182 */
136 183
137 ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR); 184 vec.elts = wsabufs;
138 185 vec.nelts = 0;
186 vec.size = sizeof(WSABUF);
187 vec.nalloc = NGX_WSABUFS;
188 vec.pool = c->pool;
189
190 send = 0;
139 prev = NULL; 191 prev = NULL;
140 wsabuf = NULL; 192 wsabuf = NULL;
141 193
142 /* create the WSABUF and coalesce the neighbouring bufs */ 194 /* create the WSABUF and coalesce the neighbouring bufs */
143 195
144 for (cl = in; cl; cl = cl->next) { 196 for (cl = in;
197 cl && vec.nelts < ngx_max_wsabufs && send < limit;
198 cl = cl->next)
199 {
200 if (ngx_buf_special(cl->buf)) {
201 continue;
202 }
203
204 size = cl->buf->last - cl->buf->pos;
205
206 if (send + size > limit) {
207 size = (u_long) (limit - send);
208 }
145 209
146 if (prev == cl->buf->pos) { 210 if (prev == cl->buf->pos) {
147 wsabuf->len += cl->buf->last - cl->buf->pos; 211 wsabuf->len += cl->buf->last - cl->buf->pos;
148 prev = cl->buf->last; 212
149
150 } else { 213 } else {
151 ngx_test_null(wsabuf, ngx_push_array(&wsabufs), 214 if (!(wsabuf = ngx_array_push(&vec))) {
152 NGX_CHAIN_ERROR); 215 return NGX_CHAIN_ERROR;
216 }
217
153 wsabuf->buf = (char *) cl->buf->pos; 218 wsabuf->buf = (char *) cl->buf->pos;
154 wsabuf->len = cl->buf->last - cl->buf->pos; 219 wsabuf->len = cl->buf->last - cl->buf->pos;
155 prev = cl->buf->last; 220 }
156 } 221
222 prev = cl->buf->last;
223 send += size;
157 } 224 }
158 225
159 ovlp = (LPWSAOVERLAPPED) &c->write->ovlp; 226 ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
160 ngx_memzero(ovlp, sizeof(WSAOVERLAPPED)); 227 ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
161 228
162 rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, ovlp, NULL); 229 rc = WSASend(c->fd, vec.elts, vec.nelts, &sent, 0, ovlp, NULL);
163 230
164 wev->complete = 0; 231 wev->complete = 0;
165 232
166 if (rc == -1) { 233 if (rc == -1) {
167 err = ngx_errno; 234 err = ngx_errno;
168 235
169 if (err == WSA_IO_PENDING) { 236 if (err == WSA_IO_PENDING) {
237 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
238 "WSASend() posted");
170 wev->active = 1; 239 wev->active = 1;
171 return in; 240 return in;
172 241
173 } else { 242 } else {
174 wev->error = 1; 243 wev->error = 1;
185 */ 254 */
186 255
187 wev->active = 1; 256 wev->active = 1;
188 return in; 257 return in;
189 } 258 }
259
260 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
261 "WSASend: fd:%d, s:%ul", c->fd, sent);
190 262
191 } else { 263 } else {
192 264
193 /* the overlapped WSASend() complete */ 265 /* the overlapped WSASend() complete */
194 266
212 return NGX_CHAIN_ERROR; 284 return NGX_CHAIN_ERROR;
213 } 285 }
214 } 286 }
215 } 287 }
216 288
217 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSASend: %d", sent); 289 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
290 "WSASend ovlp: fd:%d, s:%ul", c->fd, sent);
218 291
219 c->sent += sent; 292 c->sent += sent;
220 293
221 for (cl = in; cl && sent > 0; cl = cl->next) { 294 for (cl = in; cl && sent > 0; cl = cl->next) {
295 if (ngx_buf_special(cl->buf)) {
296 continue;
297 }
298
299 if (sent == 0) {
300 break;
301 }
222 302
223 size = cl->buf->last - cl->buf->pos; 303 size = cl->buf->last - cl->buf->pos;
224 304
225 if (sent >= size) { 305 if (sent >= size) {
226 sent -= size; 306 sent -= size;
227 307 cl->buf->pos = cl->buf->last;
228 if (ngx_buf_in_memory(cl->buf)) {
229 cl->buf->pos = cl->buf->last;
230 }
231 308
232 continue; 309 continue;
233 } 310 }
234 311
235 if (ngx_buf_in_memory(cl->buf)) { 312 cl->buf->pos += sent;
236 cl->buf->pos += sent;
237 }
238 313
239 break; 314 break;
240 } 315 }
241 316
242 if (cl) { 317 if (cl) {