143 ssize_t r = read(st->fd, buf, nbytes); |
150 ssize_t r = read(st->fd, buf, nbytes); |
144 st->read += r; |
151 st->read += r; |
145 return r; |
152 return r; |
146 } |
153 } |
147 |
154 |
|
155 #ifndef WS_NO_SENDFILE |
148 ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd) { |
156 ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd) { |
149 ssize_t ret = 0; |
157 ssize_t ret = 0; |
150 off_t fileoffset = sfd->offset; |
158 off_t fileoffset = sfd->offset; |
151 if(sfd->fd->fd != -1) { |
159 if(sfd->fd->fd != -1) { |
152 #ifdef BSD |
160 #ifdef BSD |
283 return IO_ERROR; |
292 return IO_ERROR; |
284 } |
293 } |
285 } else { |
294 } else { |
286 // stream/file does not support sendfile |
295 // stream/file does not support sendfile |
287 // do regular copy |
296 // do regular copy |
288 char *buf = malloc(4096); |
297 return net_fallback_sendfile(fd, sfd); |
289 if(!buf) { |
|
290 // TODO: out of memory error |
|
291 return IO_ERROR; |
|
292 } |
|
293 char *header = (char*)sfd->header; |
|
294 int hlen = sfd->hlen; |
|
295 char *trailer = (char*)sfd->trailer; |
|
296 int tlen = sfd->tlen; |
|
297 if(header == NULL) { |
|
298 hlen = 0; |
|
299 } |
|
300 if(trailer == NULL) { |
|
301 tlen = 0; |
|
302 } |
|
303 |
|
304 ssize_t r; |
|
305 while(hlen > 0) { |
|
306 r = out->st.write(fd, header, hlen); |
|
307 header += r; |
|
308 hlen -= r; |
|
309 if(r <= 0) { |
|
310 free(buf); |
|
311 return IO_ERROR; |
|
312 } |
|
313 } |
|
314 |
|
315 if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) { |
|
316 free(buf); |
|
317 return IO_ERROR; |
|
318 } |
|
319 |
|
320 size_t length = sfd->len; |
|
321 while(length > 0) { |
|
322 if((r = system_fread(sfd->fd, buf, 4096)) <= 0) { |
|
323 break; |
|
324 } |
|
325 char *write_buf = buf; |
|
326 while(r > 0) { |
|
327 ssize_t w = out->st.write(fd, write_buf, r); |
|
328 r -= w; |
|
329 length -= w; |
|
330 write_buf += w; |
|
331 } |
|
332 } |
|
333 free(buf); |
|
334 if(length > 0) { |
|
335 return IO_ERROR; |
|
336 } |
|
337 |
|
338 while(tlen > 0) { |
|
339 r = out->st.write(fd, trailer, tlen); |
|
340 trailer += r; |
|
341 tlen -= r; |
|
342 if(r <= 0) { |
|
343 return IO_ERROR; |
|
344 } |
|
345 } |
|
346 |
|
347 return sfd->hlen + sfd->len + sfd->tlen; |
|
348 } |
298 } |
349 return IO_ERROR; |
299 return IO_ERROR; |
350 } |
300 } |
351 |
301 |
352 int net_flush(SYS_NETFD sd) { |
302 int net_flush(SYS_NETFD sd) { |
358 ((IOStream*)fd)->close(fd); |
308 ((IOStream*)fd)->close(fd); |
359 } |
309 } |
360 |
310 |
361 void net_finish(SYS_NETFD fd) { |
311 void net_finish(SYS_NETFD fd) { |
362 ((IOStream*)fd)->finish(fd); |
312 ((IOStream*)fd)->finish(fd); |
|
313 } |
|
314 |
|
315 |
|
316 ssize_t net_fallback_sendfile(NetIOStream *st, sendfiledata *sfd) { |
|
317 SYS_NETFD fd = st; |
|
318 |
|
319 char *buf = malloc(4096); |
|
320 if(!buf) { |
|
321 // TODO: out of memory error |
|
322 return IO_ERROR; |
|
323 } |
|
324 char *header = (char*)sfd->header; |
|
325 int hlen = sfd->hlen; |
|
326 char *trailer = (char*)sfd->trailer; |
|
327 int tlen = sfd->tlen; |
|
328 if(header == NULL) { |
|
329 hlen = 0; |
|
330 } |
|
331 if(trailer == NULL) { |
|
332 tlen = 0; |
|
333 } |
|
334 |
|
335 ssize_t r; |
|
336 while(hlen > 0) { |
|
337 r = st->st.write(fd, header, hlen); |
|
338 header += r; |
|
339 hlen -= r; |
|
340 if(r <= 0) { |
|
341 free(buf); |
|
342 return IO_ERROR; |
|
343 } |
|
344 } |
|
345 |
|
346 if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) { |
|
347 free(buf); |
|
348 return IO_ERROR; |
|
349 } |
|
350 |
|
351 size_t length = sfd->len; |
|
352 while(length > 0) { |
|
353 if((r = system_fread(sfd->fd, buf, 4096)) <= 0) { |
|
354 break; |
|
355 } |
|
356 char *write_buf = buf; |
|
357 while(r > 0) { |
|
358 ssize_t w = st->st.write(fd, write_buf, r); |
|
359 r -= w; |
|
360 length -= w; |
|
361 write_buf += w; |
|
362 } |
|
363 } |
|
364 free(buf); |
|
365 if(length > 0) { |
|
366 return IO_ERROR; |
|
367 } |
|
368 |
|
369 while(tlen > 0) { |
|
370 r = st->st.write(fd, trailer, tlen); |
|
371 trailer += r; |
|
372 tlen -= r; |
|
373 if(r <= 0) { |
|
374 return IO_ERROR; |
|
375 } |
|
376 } |
|
377 |
|
378 return sfd->hlen + sfd->len + sfd->tlen; |
363 } |
379 } |
364 |
380 |
365 |
381 |
366 /* iovec buffer */ |
382 /* iovec buffer */ |
367 iovec_buf_t *iovec_buf_create(pool_handle_t *pool) { |
383 iovec_buf_t *iovec_buf_create(pool_handle_t *pool) { |