31
31
32
32
static const int MAX_FAILED_TRIES = 5 ;
33
33
34
- ssize_t
35
- lwan_writev_fd (struct lwan_request * request , int fd , struct iovec * iov , int iov_count )
34
+ ssize_t lwan_writev_fd (struct lwan_request * request ,
35
+ int fd ,
36
+ struct iovec * iov ,
37
+ int iov_count )
36
38
{
37
39
ssize_t total_written = 0 ;
38
40
int curr_iov = 0 ;
@@ -44,7 +46,8 @@ lwan_writev_fd(struct lwan_request *request, int fd, struct iovec *iov, int iov_
44
46
45
47
if (remaining_len == 1 ) {
46
48
const struct iovec * vec = & iov [curr_iov ];
47
- return lwan_send_fd (request , fd , vec -> iov_base , vec -> iov_len , flags );
49
+ return lwan_send_fd (request , fd , vec -> iov_base , vec -> iov_len ,
50
+ flags );
48
51
}
49
52
50
53
struct msghdr hdr = {
@@ -60,35 +63,36 @@ lwan_writev_fd(struct lwan_request *request, int fd, struct iovec *iov, int iov_
60
63
switch (errno ) {
61
64
case EAGAIN :
62
65
case EINTR :
63
- goto try_again ;
66
+ break ;
64
67
default :
65
68
return - errno ;
66
69
}
67
- }
70
+ } else {
71
+ total_written += written ;
68
72
69
- total_written += written ;
70
-
71
- while (curr_iov < iov_count &&
72
- written >= (ssize_t )iov [curr_iov ].iov_len ) {
73
- written -= (ssize_t )iov [curr_iov ].iov_len ;
74
- curr_iov ++ ;
75
- }
73
+ while (curr_iov < iov_count &&
74
+ written >= (ssize_t )iov [curr_iov ].iov_len ) {
75
+ written -= (ssize_t )iov [curr_iov ].iov_len ;
76
+ curr_iov ++ ;
77
+ }
76
78
77
- if ( curr_iov == iov_count )
78
- return total_written ;
79
+ iov [ curr_iov ]. iov_base = ( char * ) iov [ curr_iov ]. iov_base + written ;
80
+ iov [ curr_iov ]. iov_len -= ( size_t ) written ;
79
81
80
- iov [curr_iov ].iov_base = (char * )iov [curr_iov ].iov_base + written ;
81
- iov [curr_iov ].iov_len -= (size_t )written ;
82
+ if (curr_iov == iov_count && iov [curr_iov ].iov_len == 0 )
83
+ return total_written ;
84
+ }
82
85
83
- try_again :
84
86
lwan_request_await_read (request , fd );
85
87
}
86
88
87
89
return - ETIMEDOUT ;
88
90
}
89
91
90
- ssize_t
91
- lwan_readv_fd (struct lwan_request * request , int fd , struct iovec * iov , int iov_count )
92
+ ssize_t lwan_readv_fd (struct lwan_request * request ,
93
+ int fd ,
94
+ struct iovec * iov ,
95
+ int iov_count )
92
96
{
93
97
ssize_t total_bytes_read = 0 ;
94
98
int curr_iov = 0 ;
@@ -102,27 +106,27 @@ lwan_readv_fd(struct lwan_request *request, int fd, struct iovec *iov, int iov_c
102
106
switch (errno ) {
103
107
case EAGAIN :
104
108
case EINTR :
105
- goto try_again ;
109
+ break ;
106
110
default :
107
111
return - errno ;
108
112
}
109
- }
113
+ } else {
114
+ total_bytes_read += bytes_read ;
110
115
111
- total_bytes_read += bytes_read ;
112
-
113
- while (curr_iov < iov_count &&
114
- bytes_read >= (ssize_t )iov [curr_iov ].iov_len ) {
115
- bytes_read -= (ssize_t )iov [curr_iov ].iov_len ;
116
- curr_iov ++ ;
117
- }
116
+ while (curr_iov < iov_count &&
117
+ bytes_read >= (ssize_t )iov [curr_iov ].iov_len ) {
118
+ bytes_read -= (ssize_t )iov [curr_iov ].iov_len ;
119
+ curr_iov ++ ;
120
+ }
118
121
119
- if (curr_iov == iov_count )
120
- return total_bytes_read ;
122
+ iov [curr_iov ].iov_base =
123
+ (char * )iov [curr_iov ].iov_base + bytes_read ;
124
+ iov [curr_iov ].iov_len -= (size_t )bytes_read ;
121
125
122
- iov [curr_iov ].iov_base = (char * )iov [curr_iov ].iov_base + bytes_read ;
123
- iov [curr_iov ].iov_len -= (size_t )bytes_read ;
126
+ if (curr_iov == iov_count && iov [curr_iov ].iov_len == 0 )
127
+ return total_bytes_read ;
128
+ }
124
129
125
- try_again :
126
130
lwan_request_await_read (request , fd );
127
131
}
128
132
@@ -135,32 +139,30 @@ ssize_t lwan_send_fd(struct lwan_request *request,
135
139
size_t count ,
136
140
int flags )
137
141
{
138
- ssize_t total_sent = 0 ;
142
+ size_t to_send = count ;
139
143
140
144
if (request -> conn -> flags & CONN_CORK )
141
145
flags |= MSG_MORE ;
142
146
143
147
for (int tries = MAX_FAILED_TRIES ; tries ;) {
144
- ssize_t written = send (fd , buf , count , flags );
148
+ ssize_t written = send (fd , buf , to_send , flags );
145
149
if (UNLIKELY (written < 0 )) {
146
150
tries -- ;
147
151
148
152
switch (errno ) {
149
153
case EAGAIN :
150
154
case EINTR :
151
- goto try_again ;
155
+ break ;
152
156
default :
153
157
return - errno ;
154
158
}
155
- }
156
-
157
- total_sent += written ;
158
- if ((size_t )total_sent == count )
159
- return total_sent ;
160
- if ((size_t )total_sent < count )
159
+ } else {
160
+ to_send -= (size_t )written ;
161
+ if (!to_send )
162
+ return count ;
161
163
buf = (char * )buf + written ;
164
+ }
162
165
163
- try_again :
164
166
lwan_request_await_write (request , fd );
165
167
}
166
168
@@ -170,32 +172,29 @@ ssize_t lwan_send_fd(struct lwan_request *request,
170
172
ssize_t
171
173
lwan_recv_fd (struct lwan_request * request , int fd , void * buf , size_t count , int flags )
172
174
{
173
- ssize_t total_recv = 0 ;
175
+ size_t to_recv = count ;
174
176
175
177
for (int tries = MAX_FAILED_TRIES ; tries ;) {
176
- ssize_t recvd = recv (fd , buf , count , flags );
178
+ ssize_t recvd = recv (fd , buf , to_recv , flags );
177
179
if (UNLIKELY (recvd < 0 )) {
178
180
tries -- ;
179
181
180
182
switch (errno ) {
183
+ case EINTR :
181
184
case EAGAIN :
182
185
if (flags & MSG_DONTWAIT )
183
- return total_recv ;
184
- /* Fallthrough */
185
- case EINTR :
186
- goto try_again ;
186
+ return count - to_recv ;
187
+ break ;
187
188
default :
188
189
return - errno ;
189
190
}
190
- }
191
-
192
- total_recv += recvd ;
193
- if ((size_t )total_recv == count )
194
- return total_recv ;
195
- if ((size_t )total_recv < count )
191
+ } else {
192
+ to_recv -= (size_t )recvd ;
193
+ if (!to_recv )
194
+ return count ;
196
195
buf = (char * )buf + recvd ;
196
+ }
197
197
198
- try_again :
199
198
lwan_request_await_read (request , fd );
200
199
}
201
200
@@ -220,8 +219,7 @@ int lwan_sendfile_fd(struct lwan_request *request,
220
219
* sent using MSG_MORE. Subsequent chunks are sized 2^21 bytes. (Do
221
220
* this regardless of this connection being TLS or not for simplicity.)
222
221
*
223
- * [1]
224
- * https://www.kernel.org/doc/html/v5.12/networking/tls.html#sending-tls-application-data
222
+ * [1] https://www.kernel.org/doc/html/v5.12/networking/tls.html#sending-tls-application-data
225
223
* [2] https://github.com/lpereira/lwan/issues/334
226
224
*/
227
225
size_t chunk_size = LWAN_MIN (count , (1ul << 21 ) - header_len );
@@ -236,24 +234,23 @@ int lwan_sendfile_fd(struct lwan_request *request,
236
234
237
235
while (true) {
238
236
ssize_t written = sendfile (out_fd , in_fd , & offset , chunk_size );
239
- if (written < 0 ) {
237
+ if (UNLIKELY ( written < 0 ) ) {
240
238
switch (errno ) {
241
239
case EAGAIN :
242
240
case EINTR :
243
- goto try_again ;
241
+ break ;
244
242
default :
245
243
return - errno ;
246
244
}
247
- }
248
-
249
- to_be_written -= (size_t )written ;
250
- if (!to_be_written )
251
- return 0 ;
245
+ } else {
246
+ to_be_written -= (size_t )written ;
247
+ if (!to_be_written )
248
+ return 0 ;
252
249
253
- chunk_size = LWAN_MIN (to_be_written , 1ul << 21 );
254
- lwan_readahead_queue (in_fd , offset , chunk_size );
250
+ chunk_size = LWAN_MIN (to_be_written , 1ul << 21 );
251
+ lwan_readahead_queue (in_fd , offset , chunk_size );
252
+ }
255
253
256
- try_again :
257
254
lwan_request_await_write (request , out_fd );
258
255
}
259
256
}
@@ -292,39 +289,41 @@ int lwan_sendfile(struct lwan_request *request,
292
289
case EAGAIN :
293
290
case EBUSY :
294
291
case EINTR :
295
- goto try_again ;
292
+ break ;
296
293
default :
297
294
return - errno ;
298
295
}
296
+ } else {
297
+ count -= (size_t )sbytes ;
298
+ if (!count )
299
+ return 0 ;
299
300
}
300
301
301
- count -= (size_t )sbytes ;
302
- if (!count )
303
- return 0 ;
304
-
305
- try_again :
306
302
lwan_request_await_write (request , out_fd );
307
303
}
308
304
}
309
305
#else
310
306
static ssize_t try_pread_file (struct lwan_request * request ,
311
- int fd ,
312
- void * buffer ,
313
- size_t len ,
314
- off_t offset )
307
+ int fd ,
308
+ void * buffer ,
309
+ size_t len ,
310
+ off_t offset )
315
311
{
316
312
size_t total_read = 0 ;
317
313
318
314
for (int tries = MAX_FAILED_TRIES ; tries ;) {
319
315
ssize_t r = pread (fd , buffer , len , offset );
320
316
317
+ if (r == 0 ) {
318
+ return total_read ;
319
+ }
321
320
if (UNLIKELY (r < 0 )) {
322
321
tries -- ;
323
322
324
323
switch (errno ) {
325
324
case EAGAIN :
326
325
case EINTR :
327
- /* fd is a file, re-read -- but give other coros some time, too */
326
+ /* fd is a file, re-read -- but give other coros some time */
328
327
coro_yield (request -> conn -> coro , CONN_CORO_YIELD );
329
328
continue ;
330
329
default :
@@ -333,9 +332,9 @@ static ssize_t try_pread_file(struct lwan_request *request,
333
332
}
334
333
335
334
total_read += (size_t )r ;
336
-
337
- if (r == 0 || total_read == len )
335
+ if (total_read == len ) {
338
336
return total_read ;
337
+ }
339
338
340
339
offset += r ;
341
340
}
@@ -362,11 +361,12 @@ int lwan_sendfile_fd(struct lwan_request *request,
362
361
while (count ) {
363
362
r = try_pread_file (request , in_fd , buffer ,
364
363
LWAN_MIN (count , sizeof (buffer )), offset );
365
- if (UNLIKELY (r < 0 ))
364
+ if (UNLIKELY (r <= 0 ))
366
365
return (int )r ;
367
366
368
367
size_t bytes_read = (size_t )r ;
369
- r = lwan_send_fd (request , out_fd , buffer , bytes_read , 0 );
368
+ r = lwan_send_fd (request , out_fd , buffer , bytes_read ,
369
+ bytes_read < sizeof (buffer ) ? 0 : MSG_MORE );
370
370
if (UNLIKELY (r < 0 ))
371
371
return (int )r ;
372
372
0 commit comments