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.
 
 
 
 

247 lines
5.8 KiB

  1. #ifdef __MINGW32__
  2. #include <windows.h>
  3. #include <mswsock.h>
  4. #include <errno.h>
  5. #include "io_internal.h"
  6. #include "iob_internal.h"
  7. #include <stdio.h>
  8. int64 iob_send(int64 s,io_batch* b) {
  9. /* Windows has a sendfile called TransmitFile, which can send one
  10. * header and one trailer buffer. */
  11. iob_entry* x,* last;
  12. io_entry* e;
  13. int64 sent;
  14. int i;
  15. if (b->bytesleft==0) return 0;
  16. sent=-1;
  17. e=iarray_get(&io_fds,s);
  18. if (!e) { errno=EBADF; return -3; }
  19. if (!(x=array_get(&b->b,sizeof(iob_entry),b->next)))
  20. return -3; /* can't happen error */
  21. last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b));
  22. fprintf(stderr,"iob_send() called!\n");
  23. if (e->canwrite || e->sendfilequeued==1) {
  24. fprintf(stderr,"...reaping finished WriteFile/TransmitFile.\n");
  25. /* An overlapping write finished. Reap the result. */
  26. if (e->bytes_written==-1) return -3;
  27. if (e->bytes_written<x->n) {
  28. sent=e->bytes_written;
  29. if (x->n < e->bytes_written) {
  30. e->bytes_written-=x->n;
  31. x->n=0;
  32. ++x;
  33. }
  34. x->n -= e->bytes_written;
  35. x->offset += e->bytes_written;
  36. b->bytesleft -= e->bytes_written;
  37. }
  38. e->canwrite=0; e->sendfilequeued=0;
  39. }
  40. for (i=0; x+i<last; ++i)
  41. if (x[i].n) break;
  42. if (x[i].type==FROMBUF) {
  43. fprintf(stderr,"found non-sent buffer batch entry at %d\n",i);
  44. if (x+i+1 < last &&
  45. (x[i+1].type==FROMFILE)) {
  46. fprintf(stderr,"Next is a file, can use TransmitFile\n",i);
  47. TRANSMIT_FILE_BUFFERS tfb;
  48. e->sendfilequeued=1;
  49. memset(&tfb,0,sizeof(tfb));
  50. memset(&e[i].os,0,sizeof(e[i].os));
  51. e[i].os.Offset=x[i].offset;
  52. e[i].os.OffsetHigh=(x[i].offset>>32);
  53. fprintf(stderr,"Calling TransmitFile on %p...",s);
  54. if (!TransmitFile(s,(HANDLE)x[i].fd,
  55. x[i].n+tfb.HeadLength>0xffff?0xffff:x[i].n,
  56. 0,&e[i].os,&tfb,TF_USE_KERNEL_APC)) {
  57. if (GetLastError()==ERROR_IO_PENDING) {
  58. fprintf(stderr," pending.!\n");
  59. e->writequeued=1;
  60. errno=EAGAIN;
  61. e->errorcode=0;
  62. return -1;
  63. } else {
  64. fprintf(stderr," failed!\n");
  65. e->errorcode=errno;
  66. return -3;
  67. }
  68. }
  69. fprintf(stderr," OK!\n");
  70. return sent;
  71. } else {
  72. e->writequeued=1;
  73. fprintf(stderr,"Queueing WriteFile on %p...",s);
  74. if (!WriteFile(s,x[i].buf+x[i].offset,x[i].n,0,&e->ow)) {
  75. if (GetLastError()==ERROR_IO_PENDING) {
  76. fprintf(stderr," pending.\n");
  77. e->writequeued=1;
  78. errno=EAGAIN;
  79. e->errorcode=0;
  80. return -1;
  81. } else {
  82. fprintf(stderr," failed.\n");
  83. e->errorcode=errno;
  84. return -3;
  85. }
  86. }
  87. return sent;
  88. }
  89. } else {
  90. fprintf(stderr,"Calling TransmitFile...\n");
  91. e->sendfilequeued=1;
  92. memset(&e[i].os,0,sizeof(e[i].os));
  93. e[i].os.Offset=x[i].offset;
  94. e[i].os.OffsetHigh=(x[i].offset>>32);
  95. if (!TransmitFile(s,(HANDLE)x[i].fd,
  96. x[i].n>0xffff?0xffff:x[i].n,
  97. 0,&e[i].os,0,TF_USE_KERNEL_APC))
  98. return -3;
  99. return sent;
  100. }
  101. }
  102. #else
  103. #include "havebsdsf.h"
  104. #include <sys/types.h>
  105. #include <sys/socket.h>
  106. #include <sys/uio.h>
  107. #include <errno.h>
  108. #include <netinet/in.h>
  109. #include <netinet/tcp.h>
  110. #include <stdlib.h>
  111. #include <unistd.h>
  112. #include "havealloca.h"
  113. #include "iob_internal.h"
  114. int64 iob_send(int64 s,io_batch* b) {
  115. iob_entry* e,* last;
  116. struct iovec* v;
  117. uint64 total;
  118. int64 sent;
  119. long i;
  120. long headers;
  121. #ifdef HAVE_BSDSENDFILE
  122. long trailers;
  123. #endif
  124. if (b->bytesleft==0) return 0;
  125. last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b));
  126. v=alloca(b->bufs*sizeof(struct iovec));
  127. total=0;
  128. for (;;) {
  129. if (!(e=array_get(&b->b,sizeof(iob_entry),b->next)))
  130. return -3; /* can't happen error */
  131. #ifdef HAVE_BSDSENDFILE
  132. /* BSD sendfile can send headers and trailers. If we run on BSD, we
  133. * should try to exploit this. */
  134. headers=trailers=0;
  135. #endif
  136. for (i=0; e+i<last; ++i) {
  137. if (e[i].type==FROMFILE) break;
  138. v[i].iov_base=(char*)(e[i].buf+e[i].offset);
  139. v[i].iov_len=e[i].n;
  140. }
  141. headers=i;
  142. #ifdef HAVE_BSDSENDFILE
  143. if (e[i].type==FROMFILE) {
  144. off_t sbytes;
  145. struct sf_hdtr hdr;
  146. int r;
  147. for (++i; e+i<last; ++i) {
  148. if (e[i].type==FROMFILE) break;
  149. v[i-1].iov_base=(char*)(e[i].buf+e[i].offset);
  150. v[i-1].iov_len=e[i].n;
  151. ++trailers;
  152. }
  153. hdr.headers=v; hdr.hdr_cnt=headers;
  154. hdr.trailers=v+headers; hdr.trl_cnt=trailers;
  155. r=sendfile(e[headers].fd,s,e[headers].offset,e[headers].n,&hdr,&sbytes,0);
  156. if (r==0)
  157. sent=b->bytesleft;
  158. else if (r==-1 && errno==EAGAIN) {
  159. if (!(sent=sbytes)) {
  160. sent=-1;
  161. goto eagain;
  162. }
  163. } else
  164. sent=-3;
  165. } else {
  166. if (headers==1) /* cosmetics for strace */
  167. sent=write(s,v[0].iov_base,v[0].iov_len);
  168. else
  169. sent=writev(s,v,headers);
  170. if (sent==-1) {
  171. if (errno!=EAGAIN)
  172. sent=-3;
  173. else {
  174. eagain:
  175. io_eagain(s);
  176. return -1;
  177. }
  178. }
  179. }
  180. #else
  181. #ifdef TCP_CORK
  182. if (b->bufs && b->files && !b->next) {
  183. static int one=1;
  184. setsockopt(s,IPPROTO_TCP,TCP_CORK,&one,sizeof(one));
  185. }
  186. #endif
  187. if (headers) {
  188. if (headers==1) /* cosmetics for strace */
  189. sent=write(s,v[0].iov_base,v[0].iov_len);
  190. else
  191. sent=writev(s,v,headers);
  192. if (sent==-1) {
  193. if (errno==EAGAIN) {
  194. io_eagain(s);
  195. return -1;
  196. }
  197. sent=-3;
  198. }
  199. } else
  200. sent=io_sendfile(s,e->fd,e->offset,e->n);
  201. #endif
  202. if (sent>0)
  203. total+=sent;
  204. else
  205. return total?total:(uint64)sent;
  206. if ((uint64)sent==b->bytesleft) {
  207. #ifdef TCP_CORK
  208. if (b->bufs && b->files) {
  209. static int zero=0;
  210. setsockopt(s,IPPROTO_TCP,TCP_CORK,&zero,sizeof(zero));
  211. }
  212. #endif
  213. iob_reset(b);
  214. break;
  215. } else if (sent>0) {
  216. uint64 rest=sent;
  217. b->bytesleft-=rest;
  218. for (i=0; e+i<last; ++i) {
  219. if (e[i].n<=rest) {
  220. rest-=e[i].n;
  221. ++b->next;
  222. if (!rest) break;
  223. } else {
  224. e[i].offset+=rest;
  225. e[i].n-=rest;
  226. goto abort;
  227. }
  228. }
  229. } else break;
  230. }
  231. abort:
  232. return total;
  233. }
  234. #endif