Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
3.0 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
17 years ago
18 years ago
18 years ago
17 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. #include "havebsdsf.h"
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <sys/uio.h>
  5. #include <errno.h>
  6. #include <netinet/in.h>
  7. #include <netinet/tcp.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include "havealloca.h"
  11. #include "iob_internal.h"
  12. int64 iob_send(int64 s,io_batch* b) {
  13. iob_entry* e,* last;
  14. struct iovec* v;
  15. int64 total,sent;
  16. long i;
  17. long headers;
  18. #ifdef HAVE_BSDSENDFILE
  19. long trailers;
  20. #endif
  21. if (b->bytesleft==0) return 0;
  22. last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b));
  23. v=alloca(b->bufs*sizeof(struct iovec));
  24. total=0;
  25. for (;;) {
  26. if (!(e=array_get(&b->b,sizeof(iob_entry),b->next)))
  27. return -3; /* can't happen error */
  28. #ifdef HAVE_BSDSENDFILE
  29. /* BSD sendfile can send headers and trailers. If we run on BSD, we
  30. * should try to exploit this. */
  31. headers=trailers=0;
  32. #endif
  33. for (i=0; e+i<last; ++i) {
  34. if (e[i].type==FROMFILE || e[i].type==FROMFILE_CLOSE) break;
  35. v[i].iov_base=(char*)(e[i].buf+e[i].offset);
  36. v[i].iov_len=e[i].n;
  37. }
  38. headers=i;
  39. #ifdef HAVE_BSDSENDFILE
  40. if (e[i].type==FROMFILE || e[i].type==FROMFILE_CLOSE) {
  41. off_t sbytes;
  42. struct sf_hdtr hdr;
  43. int r;
  44. for (++i; e+i<last; ++i) {
  45. if (e[i].type==FROMFILE || e[i].type==FROMFILE_CLOSE) break;
  46. v[i-1].iov_base=(char*)(e[i].buf+e[i].offset);
  47. v[i-1].iov_len=e[i].n;
  48. ++trailers;
  49. }
  50. hdr.headers=v; hdr.hdr_cnt=headers;
  51. hdr.trailers=v+headers; hdr.trl_cnt=trailers;
  52. r=sendfile(e[headers].fd,s,e[headers].offset,e[headers].n,&hdr,&sbytes,0);
  53. if (r==0)
  54. sent=b->bytesleft;
  55. else if (r==-1 && errno==EAGAIN) {
  56. if (!(sent=sbytes)) {
  57. sent=-1;
  58. goto eagain;
  59. }
  60. } else
  61. sent=-3;
  62. } else {
  63. if (headers==1) /* cosmetics for strace */
  64. sent=write(s,v[0].iov_base,v[0].iov_len);
  65. else
  66. sent=writev(s,v,headers);
  67. if (sent==-1) {
  68. if (errno!=EAGAIN)
  69. sent=-3;
  70. else {
  71. eagain:
  72. io_eagain(s);
  73. return -1;
  74. }
  75. }
  76. }
  77. #else
  78. #ifdef TCP_CORK
  79. if (b->bufs && b->files && !b->next) {
  80. static int one=1;
  81. setsockopt(s,IPPROTO_TCP,TCP_CORK,&one,sizeof(one));
  82. }
  83. #endif
  84. if (headers) {
  85. if (headers==1) /* cosmetics for strace */
  86. sent=write(s,v[0].iov_base,v[0].iov_len);
  87. else
  88. sent=writev(s,v,headers);
  89. if (sent==-1) {
  90. if (errno==EAGAIN) {
  91. io_eagain(s);
  92. return -1;
  93. }
  94. sent=-3;
  95. }
  96. } else
  97. sent=io_sendfile(s,e->fd,e->offset,e->n);
  98. #endif
  99. if (sent>0)
  100. total+=sent;
  101. else
  102. return total?total:sent;
  103. if (sent==b->bytesleft) {
  104. #ifdef TCP_CORK
  105. if (b->bufs && b->files) {
  106. static int zero=0;
  107. setsockopt(s,IPPROTO_TCP,TCP_CORK,&zero,sizeof(zero));
  108. }
  109. #endif
  110. iob_reset(b);
  111. break;
  112. } else if (sent>0) {
  113. int64 rest=sent;
  114. b->bytesleft-=rest;
  115. for (i=0; e+i<last; ++i) {
  116. if (e[i].n<=rest) {
  117. rest-=e[i].n;
  118. ++b->next;
  119. if (!rest) break;
  120. } else {
  121. e[i].offset+=rest;
  122. e[i].n-=rest;
  123. goto abort;
  124. }
  125. }
  126. } else break;
  127. }
  128. abort:
  129. return total;
  130. }