32
32
static const int MAX_FAILED_TRIES = 5 ;
33
33
34
34
ssize_t
35
- lwan_writev (struct lwan_request * request , struct iovec * iov , int iov_count )
35
+ lwan_writev_fd (struct lwan_request * request , int fd , struct iovec * iov , int iov_count )
36
36
{
37
37
ssize_t total_written = 0 ;
38
38
int curr_iov = 0 ;
@@ -44,14 +44,14 @@ lwan_writev(struct lwan_request *request, struct iovec *iov, int iov_count)
44
44
45
45
if (remaining_len == 1 ) {
46
46
const struct iovec * vec = & iov [curr_iov ];
47
- return lwan_send (request , vec -> iov_base , vec -> iov_len , flags );
47
+ return lwan_send_fd (request , fd , vec -> iov_base , vec -> iov_len , flags );
48
48
}
49
49
50
50
struct msghdr hdr = {
51
51
.msg_iov = iov + curr_iov ,
52
52
.msg_iovlen = (size_t )remaining_len ,
53
53
};
54
- written = sendmsg (request -> fd , & hdr , flags );
54
+ written = sendmsg (fd , & hdr , flags );
55
55
56
56
if (UNLIKELY (written < 0 )) {
57
57
/* FIXME: Consider short writes as another try as well? */
@@ -62,7 +62,7 @@ lwan_writev(struct lwan_request *request, struct iovec *iov, int iov_count)
62
62
case EINTR :
63
63
goto try_again ;
64
64
default :
65
- goto out ;
65
+ return - errno ;
66
66
}
67
67
}
68
68
@@ -81,23 +81,20 @@ lwan_writev(struct lwan_request *request, struct iovec *iov, int iov_count)
81
81
iov [curr_iov ].iov_len -= (size_t )written ;
82
82
83
83
try_again :
84
- coro_yield (request -> conn -> coro , CONN_CORO_WANT_WRITE );
84
+ lwan_request_await_read (request , fd );
85
85
}
86
86
87
- out :
88
- coro_yield (request -> conn -> coro , CONN_CORO_ABORT );
89
- __builtin_unreachable ();
87
+ return - ETIMEDOUT ;
90
88
}
91
89
92
90
ssize_t
93
- lwan_readv (struct lwan_request * request , struct iovec * iov , int iov_count )
91
+ lwan_readv_fd (struct lwan_request * request , int fd , struct iovec * iov , int iov_count )
94
92
{
95
93
ssize_t total_bytes_read = 0 ;
96
94
int curr_iov = 0 ;
97
95
98
96
for (int tries = MAX_FAILED_TRIES ; tries ;) {
99
- ssize_t bytes_read =
100
- readv (request -> fd , iov + curr_iov , iov_count - curr_iov );
97
+ ssize_t bytes_read = readv (fd , iov + curr_iov , iov_count - curr_iov );
101
98
if (UNLIKELY (bytes_read < 0 )) {
102
99
/* FIXME: Consider short reads as another try as well? */
103
100
tries -- ;
@@ -107,7 +104,7 @@ lwan_readv(struct lwan_request *request, struct iovec *iov, int iov_count)
107
104
case EINTR :
108
105
goto try_again ;
109
106
default :
110
- goto out ;
107
+ return - errno ;
111
108
}
112
109
}
113
110
@@ -126,26 +123,25 @@ lwan_readv(struct lwan_request *request, struct iovec *iov, int iov_count)
126
123
iov [curr_iov ].iov_len -= (size_t )bytes_read ;
127
124
128
125
try_again :
129
- coro_yield (request -> conn -> coro , CONN_CORO_WANT_READ );
126
+ lwan_request_await_read (request , fd );
130
127
}
131
128
132
- out :
133
- coro_yield (request -> conn -> coro , CONN_CORO_ABORT );
134
- __builtin_unreachable ();
129
+ return - ETIMEDOUT ;
135
130
}
136
131
137
- ssize_t lwan_send (struct lwan_request * request ,
138
- const void * buf ,
139
- size_t count ,
140
- int flags )
132
+ ssize_t lwan_send_fd (struct lwan_request * request ,
133
+ int fd ,
134
+ const void * buf ,
135
+ size_t count ,
136
+ int flags )
141
137
{
142
138
ssize_t total_sent = 0 ;
143
139
144
140
if (request -> conn -> flags & CONN_CORK )
145
141
flags |= MSG_MORE ;
146
142
147
143
for (int tries = MAX_FAILED_TRIES ; tries ;) {
148
- ssize_t written = send (request -> fd , buf , count , flags );
144
+ ssize_t written = send (fd , buf , count , flags );
149
145
if (UNLIKELY (written < 0 )) {
150
146
tries -- ;
151
147
@@ -154,7 +150,7 @@ ssize_t lwan_send(struct lwan_request *request,
154
150
case EINTR :
155
151
goto try_again ;
156
152
default :
157
- goto out ;
153
+ return - errno ;
158
154
}
159
155
}
160
156
@@ -165,21 +161,19 @@ ssize_t lwan_send(struct lwan_request *request,
165
161
buf = (char * )buf + written ;
166
162
167
163
try_again :
168
- coro_yield (request -> conn -> coro , CONN_CORO_WANT_WRITE );
164
+ lwan_request_await_write (request , fd );
169
165
}
170
166
171
- out :
172
- coro_yield (request -> conn -> coro , CONN_CORO_ABORT );
173
- __builtin_unreachable ();
167
+ return - ETIMEDOUT ;
174
168
}
175
169
176
170
ssize_t
177
- lwan_recv (struct lwan_request * request , void * buf , size_t count , int flags )
171
+ lwan_recv_fd (struct lwan_request * request , int fd , void * buf , size_t count , int flags )
178
172
{
179
173
ssize_t total_recv = 0 ;
180
174
181
175
for (int tries = MAX_FAILED_TRIES ; tries ;) {
182
- ssize_t recvd = recv (request -> fd , buf , count , flags );
176
+ ssize_t recvd = recv (fd , buf , count , flags );
183
177
if (UNLIKELY (recvd < 0 )) {
184
178
tries -- ;
185
179
@@ -191,7 +185,7 @@ lwan_recv(struct lwan_request *request, void *buf, size_t count, int flags)
191
185
case EINTR :
192
186
goto try_again ;
193
187
default :
194
- goto out ;
188
+ return - errno ;
195
189
}
196
190
}
197
191
@@ -202,21 +196,20 @@ lwan_recv(struct lwan_request *request, void *buf, size_t count, int flags)
202
196
buf = (char * )buf + recvd ;
203
197
204
198
try_again :
205
- coro_yield (request -> conn -> coro , CONN_CORO_WANT_READ );
199
+ lwan_request_await_read (request , fd );
206
200
}
207
201
208
- out :
209
- coro_yield (request -> conn -> coro , CONN_CORO_ABORT );
210
- __builtin_unreachable ();
202
+ return - ETIMEDOUT ;
211
203
}
212
204
213
205
#if defined(__linux__ )
214
- void lwan_sendfile (struct lwan_request * request ,
215
- int in_fd ,
216
- off_t offset ,
217
- size_t count ,
218
- const char * header ,
219
- size_t header_len )
206
+ int lwan_sendfile_fd (struct lwan_request * request ,
207
+ int out_fd ,
208
+ int in_fd ,
209
+ off_t offset ,
210
+ size_t count ,
211
+ const char * header ,
212
+ size_t header_len )
220
213
{
221
214
/* Clamp each chunk to 2^21 bytes[1] to balance throughput and
222
215
* scalability. This used to be capped to 2^14 bytes, as that's the
@@ -227,47 +220,51 @@ void lwan_sendfile(struct lwan_request *request,
227
220
* sent using MSG_MORE. Subsequent chunks are sized 2^21 bytes. (Do
228
221
* this regardless of this connection being TLS or not for simplicity.)
229
222
*
230
- * [1] https://www.kernel.org/doc/html/v5.12/networking/tls.html#sending-tls-application-data
223
+ * [1]
224
+ * https://www.kernel.org/doc/html/v5.12/networking/tls.html#sending-tls-application-data
231
225
* [2] https://github.com/lpereira/lwan/issues/334
232
226
*/
233
227
size_t chunk_size = LWAN_MIN (count , (1ul << 21 ) - header_len );
234
228
size_t to_be_written = count ;
229
+ ssize_t r ;
235
230
236
231
assert (header_len < (1ul << 21 ));
237
232
238
- lwan_send (request , header , header_len , MSG_MORE );
233
+ r = lwan_send_fd (request , out_fd , header , header_len , MSG_MORE );
234
+ if (r < 0 )
235
+ return (int )r ;
239
236
240
237
while (true) {
241
- ssize_t written = sendfile (request -> fd , in_fd , & offset , chunk_size );
238
+ ssize_t written = sendfile (out_fd , in_fd , & offset , chunk_size );
242
239
if (written < 0 ) {
243
240
switch (errno ) {
244
241
case EAGAIN :
245
242
case EINTR :
246
243
goto try_again ;
247
244
default :
248
- coro_yield (request -> conn -> coro , CONN_CORO_ABORT );
249
- __builtin_unreachable ();
245
+ return - errno ;
250
246
}
251
247
}
252
248
253
249
to_be_written -= (size_t )written ;
254
250
if (!to_be_written )
255
- break ;
251
+ return 0 ;
256
252
257
253
chunk_size = LWAN_MIN (to_be_written , 1ul << 21 );
258
254
lwan_readahead_queue (in_fd , offset , chunk_size );
259
255
260
256
try_again :
261
- coro_yield (request -> conn -> coro , CONN_CORO_WANT_WRITE );
257
+ lwan_request_await_write (request , out_fd );
262
258
}
263
259
}
264
260
#elif defined(__FreeBSD__ ) || defined(__APPLE__ )
265
- void lwan_sendfile (struct lwan_request * request ,
266
- int in_fd ,
267
- off_t offset ,
268
- size_t count ,
269
- const char * header ,
270
- size_t header_len )
261
+ int lwan_sendfile (struct lwan_request * request ,
262
+ int out_fd ,
263
+ int in_fd ,
264
+ off_t offset ,
265
+ size_t count ,
266
+ const char * header ,
267
+ size_t header_len )
271
268
{
272
269
struct sf_hdtr headers = {.headers =
273
270
(struct iovec []){{.iov_base = (void * )header ,
@@ -277,41 +274,40 @@ void lwan_sendfile(struct lwan_request *request,
277
274
278
275
if (!count ) {
279
276
/* FreeBSD's sendfile() won't send the headers when count is 0. Why? */
280
- return (void )lwan_writev (request , headers .headers , headers .hdr_cnt );
277
+ return lwan_writev_fd (request , out_fd , headers .headers ,
278
+ headers .hdr_cnt );
281
279
}
282
280
283
281
while (true) {
284
282
int r ;
285
283
286
284
#ifdef __APPLE__
287
- r = sendfile (in_fd , request -> fd , offset , & sbytes , & headers , 0 );
285
+ r = sendfile (in_fd , out_fd , offset , & sbytes , & headers , 0 );
288
286
#else
289
- r = sendfile (in_fd , request -> fd , offset , count , & headers , & sbytes ,
287
+ r = sendfile (in_fd , out_fd , offset , count , & headers , & sbytes ,
290
288
SF_MNOWAIT );
291
289
#endif
292
-
293
290
if (UNLIKELY (r < 0 )) {
294
291
switch (errno ) {
295
292
case EAGAIN :
296
293
case EBUSY :
297
294
case EINTR :
298
295
goto try_again ;
299
296
default :
300
- coro_yield (request -> conn -> coro , CONN_CORO_ABORT );
301
- __builtin_unreachable ();
297
+ return - errno ;
302
298
}
303
299
}
304
300
305
301
count -= (size_t )sbytes ;
306
302
if (!count )
307
- break ;
303
+ return 0 ;
308
304
309
305
try_again :
310
- coro_yield (request -> conn -> coro , CONN_CORO_WANT_WRITE );
306
+ lwan_request_await_write (request , out_fd );
311
307
}
312
308
}
313
309
#else
314
- static size_t try_pread_file (struct lwan_request * request ,
310
+ static ssize_t try_pread_file (struct lwan_request * request ,
315
311
int fd ,
316
312
void * buffer ,
317
313
size_t len ,
@@ -332,7 +328,7 @@ static size_t try_pread_file(struct lwan_request *request,
332
328
coro_yield (request -> conn -> coro , CONN_CORO_YIELD );
333
329
continue ;
334
330
default :
335
- break ;
331
+ return - errno ;
336
332
}
337
333
}
338
334
@@ -344,25 +340,36 @@ static size_t try_pread_file(struct lwan_request *request,
344
340
offset += r ;
345
341
}
346
342
347
- coro_yield (request -> conn -> coro , CONN_CORO_ABORT );
348
- __builtin_unreachable ();
343
+ return - ETIMEDOUT ;
349
344
}
350
345
351
- void lwan_sendfile (struct lwan_request * request ,
352
- int in_fd ,
353
- off_t offset ,
354
- size_t count ,
355
- const char * header ,
356
- size_t header_len )
346
+ int lwan_sendfile_fd (struct lwan_request * request ,
347
+ int out_fd ,
348
+ int in_fd ,
349
+ off_t offset ,
350
+ size_t count ,
351
+ const char * header ,
352
+ size_t header_len )
357
353
{
358
354
unsigned char buffer [512 ];
355
+ ssize_t r ;
359
356
360
- lwan_send (request , header , header_len , MSG_MORE );
357
+ r = lwan_send_fd (request , out_fd , header , header_len , MSG_MORE );
358
+ if (UNLIKELY (r < 0 )) {
359
+ return (int )r ;
360
+ }
361
361
362
362
while (count ) {
363
- size_t bytes_read = try_pread_file (
364
- request , in_fd , buffer , LWAN_MIN (count , sizeof (buffer )), offset );
365
- lwan_send (request , buffer , bytes_read , 0 );
363
+ r = try_pread_file (request , in_fd , buffer ,
364
+ LWAN_MIN (count , sizeof (buffer )), offset );
365
+ if (UNLIKELY (r < 0 ))
366
+ return (int )r ;
367
+
368
+ size_t bytes_read = (size_t )r ;
369
+ r = lwan_send_fd (request , out_fd , buffer , bytes_read , 0 );
370
+ if (UNLIKELY (r < 0 ))
371
+ return (int )r ;
372
+
366
373
count -= bytes_read ;
367
374
offset += bytes_read ;
368
375
}
0 commit comments