sendrecv.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "fspr_arch_networkio.h"
  17. #include "fspr_support.h"
  18. #if APR_HAS_SENDFILE
  19. /* This file is needed to allow us access to the fspr_file_t internals. */
  20. #include "fspr_arch_file_io.h"
  21. #endif /* APR_HAS_SENDFILE */
  22. /* osreldate.h is only needed on FreeBSD for sendfile detection */
  23. #if defined(__FreeBSD__)
  24. #include <osreldate.h>
  25. #endif
  26. #include <assert.h> /* assert() */
  27. fspr_status_t fspr_socket_send(fspr_socket_t *sock, const char *buf,
  28. fspr_size_t *len)
  29. {
  30. fspr_ssize_t rv;
  31. if (sock->options & APR_INCOMPLETE_WRITE) {
  32. sock->options &= ~APR_INCOMPLETE_WRITE;
  33. goto do_select;
  34. }
  35. do {
  36. rv = write(sock->socketdes, buf, (*len));
  37. } while (rv == -1 && errno == EINTR);
  38. while (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
  39. && (sock->timeout > 0)) {
  40. fspr_status_t arv;
  41. do_select:
  42. arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  43. if (arv != APR_SUCCESS) {
  44. *len = 0;
  45. return arv;
  46. }
  47. else {
  48. do {
  49. rv = write(sock->socketdes, buf, (*len));
  50. } while (rv == -1 && errno == EINTR);
  51. }
  52. }
  53. if (rv == -1) {
  54. *len = 0;
  55. return errno;
  56. }
  57. if ((sock->timeout > 0) && (rv < *len)) {
  58. sock->options |= APR_INCOMPLETE_WRITE;
  59. }
  60. (*len) = rv;
  61. return APR_SUCCESS;
  62. }
  63. fspr_status_t fspr_socket_recv(fspr_socket_t *sock, char *buf, fspr_size_t *len)
  64. {
  65. fspr_ssize_t rv;
  66. fspr_status_t arv;
  67. if (sock->options & APR_INCOMPLETE_READ) {
  68. sock->options &= ~APR_INCOMPLETE_READ;
  69. goto do_select;
  70. }
  71. do {
  72. rv = read(sock->socketdes, buf, (*len));
  73. } while (rv == -1 && errno == EINTR);
  74. while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
  75. && (sock->timeout > 0)) {
  76. do_select:
  77. arv = fspr_wait_for_io_or_timeout(NULL, sock, 1);
  78. if (arv != APR_SUCCESS) {
  79. *len = 0;
  80. return arv;
  81. }
  82. else {
  83. do {
  84. rv = read(sock->socketdes, buf, (*len));
  85. } while (rv == -1 && errno == EINTR);
  86. }
  87. }
  88. if (rv == -1) {
  89. (*len) = 0;
  90. return errno;
  91. }
  92. if ((sock->timeout > 0) && (rv < *len)) {
  93. sock->options |= APR_INCOMPLETE_READ;
  94. }
  95. (*len) = rv;
  96. if (rv == 0) {
  97. return APR_EOF;
  98. }
  99. return APR_SUCCESS;
  100. }
  101. fspr_status_t fspr_socket_sendto(fspr_socket_t *sock, fspr_sockaddr_t *where,
  102. fspr_int32_t flags, const char *buf,
  103. fspr_size_t *len)
  104. {
  105. fspr_ssize_t rv;
  106. do {
  107. rv = sendto(sock->socketdes, buf, (*len), flags,
  108. (const struct sockaddr*)&where->sa,
  109. where->salen);
  110. } while (rv == -1 && errno == EINTR);
  111. while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
  112. && (sock->timeout > 0)) {
  113. fspr_status_t arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  114. if (arv != APR_SUCCESS) {
  115. *len = 0;
  116. return arv;
  117. } else {
  118. do {
  119. rv = sendto(sock->socketdes, buf, (*len), flags,
  120. (const struct sockaddr*)&where->sa,
  121. where->salen);
  122. } while (rv == -1 && errno == EINTR);
  123. }
  124. }
  125. if (rv == -1) {
  126. *len = 0;
  127. return errno;
  128. }
  129. *len = rv;
  130. return APR_SUCCESS;
  131. }
  132. fspr_status_t fspr_socket_recvfrom(fspr_sockaddr_t *from, fspr_socket_t *sock,
  133. fspr_int32_t flags, char *buf,
  134. fspr_size_t *len)
  135. {
  136. fspr_ssize_t rv;
  137. from->salen = sizeof(from->sa);
  138. do {
  139. rv = recvfrom(sock->socketdes, buf, (*len), flags,
  140. (struct sockaddr*)&from->sa, &from->salen);
  141. } while (rv == -1 && errno == EINTR);
  142. while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
  143. && (sock->timeout > 0)) {
  144. fspr_status_t arv = fspr_wait_for_io_or_timeout(NULL, sock, 1);
  145. if (arv != APR_SUCCESS) {
  146. *len = 0;
  147. return arv;
  148. } else {
  149. do {
  150. rv = recvfrom(sock->socketdes, buf, (*len), flags,
  151. (struct sockaddr*)&from->sa, &from->salen);
  152. } while (rv == -1 && errno == EINTR);
  153. }
  154. }
  155. if (rv == -1) {
  156. (*len) = 0;
  157. return errno;
  158. }
  159. fspr_sockaddr_vars_set(from, from->sa.sin.sin_family, ntohs(from->sa.sin.sin_port));
  160. (*len) = rv;
  161. if (rv == 0 && sock->type == SOCK_STREAM) {
  162. return APR_EOF;
  163. }
  164. return APR_SUCCESS;
  165. }
  166. fspr_status_t fspr_socket_sendv(fspr_socket_t * sock, const struct iovec *vec,
  167. fspr_int32_t nvec, fspr_size_t *len)
  168. {
  169. #ifdef HAVE_WRITEV
  170. fspr_ssize_t rv;
  171. fspr_size_t requested_len = 0;
  172. fspr_int32_t i;
  173. for (i = 0; i < nvec; i++) {
  174. requested_len += vec[i].iov_len;
  175. }
  176. if (sock->options & APR_INCOMPLETE_WRITE) {
  177. sock->options &= ~APR_INCOMPLETE_WRITE;
  178. goto do_select;
  179. }
  180. do {
  181. rv = writev(sock->socketdes, vec, nvec);
  182. } while (rv == -1 && errno == EINTR);
  183. while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
  184. && (sock->timeout > 0)) {
  185. fspr_status_t arv;
  186. do_select:
  187. arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  188. if (arv != APR_SUCCESS) {
  189. *len = 0;
  190. return arv;
  191. }
  192. else {
  193. do {
  194. rv = writev(sock->socketdes, vec, nvec);
  195. } while (rv == -1 && errno == EINTR);
  196. }
  197. }
  198. if (rv == -1) {
  199. *len = 0;
  200. return errno;
  201. }
  202. if ((sock->timeout > 0) && (rv < requested_len)) {
  203. sock->options |= APR_INCOMPLETE_WRITE;
  204. }
  205. (*len) = rv;
  206. return APR_SUCCESS;
  207. #else
  208. *len = vec[0].iov_len;
  209. return fspr_socket_send(sock, vec[0].iov_base, len);
  210. #endif
  211. }
  212. #if APR_HAS_SENDFILE
  213. /* TODO: Verify that all platforms handle the fd the same way,
  214. * i.e. that they don't move the file pointer.
  215. */
  216. /* TODO: what should flags be? int_32? */
  217. /* Define a structure to pass in when we have a NULL header value */
  218. static fspr_hdtr_t no_hdtr;
  219. #if defined(__linux__) && defined(HAVE_WRITEV)
  220. fspr_status_t fspr_socket_sendfile(fspr_socket_t *sock, fspr_file_t *file,
  221. fspr_hdtr_t *hdtr, fspr_off_t *offset,
  222. fspr_size_t *len, fspr_int32_t flags)
  223. {
  224. int rv, nbytes = 0, total_hdrbytes, i;
  225. fspr_status_t arv;
  226. #if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILE64)
  227. fspr_off_t off = *offset;
  228. #define sendfile sendfile64
  229. #elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4
  230. /* 64-bit fspr_off_t but no sendfile64(): fail if trying to send
  231. * past the 2Gb limit. */
  232. off_t off;
  233. if ((fspr_int64_t)*offset + *len > INT_MAX) {
  234. return EINVAL;
  235. }
  236. off = *offset;
  237. #else
  238. off_t off = *offset;
  239. /* Multiple reports have shown sendfile failing with EINVAL if
  240. * passed a >=2Gb count value on some 64-bit kernels. It won't
  241. * noticably hurt performance to limit each call to <2Gb at a
  242. * time, so avoid that issue here: */
  243. if (sizeof(off_t) == 8 && *len > INT_MAX) {
  244. *len = INT_MAX;
  245. }
  246. #endif
  247. if (!hdtr) {
  248. hdtr = &no_hdtr;
  249. }
  250. /* Ignore flags for now. */
  251. flags = 0;
  252. assert(flags==0);
  253. if (hdtr->numheaders > 0) {
  254. fspr_size_t hdrbytes;
  255. /* cork before writing headers */
  256. rv = fspr_socket_opt_set(sock, APR_TCP_NOPUSH, 1);
  257. if (rv != APR_SUCCESS) {
  258. return rv;
  259. }
  260. /* Now write the headers */
  261. arv = fspr_socket_sendv(sock, hdtr->headers, hdtr->numheaders,
  262. &hdrbytes);
  263. if (arv != APR_SUCCESS) {
  264. *len = 0;
  265. return errno;
  266. }
  267. nbytes += hdrbytes;
  268. /* If this was a partial write and we aren't doing timeouts,
  269. * return now with the partial byte count; this is a non-blocking
  270. * socket.
  271. */
  272. total_hdrbytes = 0;
  273. for (i = 0; i < hdtr->numheaders; i++) {
  274. total_hdrbytes += hdtr->headers[i].iov_len;
  275. }
  276. if (hdrbytes < total_hdrbytes) {
  277. *len = hdrbytes;
  278. return fspr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
  279. }
  280. }
  281. if (sock->options & APR_INCOMPLETE_WRITE) {
  282. sock->options &= ~APR_INCOMPLETE_WRITE;
  283. goto do_select;
  284. }
  285. do {
  286. rv = sendfile(sock->socketdes, /* socket */
  287. file->filedes, /* open file descriptor of the file to be sent */
  288. &off, /* where in the file to start */
  289. *len); /* number of bytes to send */
  290. } while (rv == -1 && errno == EINTR);
  291. while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
  292. && (sock->timeout > 0)) {
  293. do_select:
  294. arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  295. if (arv != APR_SUCCESS) {
  296. *len = 0;
  297. return arv;
  298. }
  299. else {
  300. do {
  301. rv = sendfile(sock->socketdes, /* socket */
  302. file->filedes, /* open file descriptor of the file to be sent */
  303. &off, /* where in the file to start */
  304. *len); /* number of bytes to send */
  305. } while (rv == -1 && errno == EINTR);
  306. }
  307. }
  308. if (rv == -1) {
  309. *len = nbytes;
  310. rv = errno;
  311. fspr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
  312. return rv;
  313. }
  314. nbytes += rv;
  315. if (rv < *len) {
  316. *len = nbytes;
  317. arv = fspr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
  318. if (rv > 0) {
  319. /* If this was a partial write, return now with the
  320. * partial byte count; this is a non-blocking socket.
  321. */
  322. if (sock->timeout > 0) {
  323. sock->options |= APR_INCOMPLETE_WRITE;
  324. }
  325. return arv;
  326. }
  327. else {
  328. /* If the file got smaller mid-request, eventually the offset
  329. * becomes equal to the new file size and the kernel returns 0.
  330. * Make this an error so the caller knows to log something and
  331. * exit.
  332. */
  333. return APR_EOF;
  334. }
  335. }
  336. /* Now write the footers */
  337. if (hdtr->numtrailers > 0) {
  338. fspr_size_t trbytes;
  339. arv = fspr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers,
  340. &trbytes);
  341. nbytes += trbytes;
  342. if (arv != APR_SUCCESS) {
  343. *len = nbytes;
  344. rv = errno;
  345. fspr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
  346. return rv;
  347. }
  348. }
  349. fspr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
  350. (*len) = nbytes;
  351. return rv < 0 ? errno : APR_SUCCESS;
  352. }
  353. #elif defined(DARWIN)
  354. /* OS/X Release 10.5 or greater */
  355. fspr_status_t fspr_socket_sendfile(fspr_socket_t * sock, fspr_file_t * file,
  356. fspr_hdtr_t * hdtr, fspr_off_t * offset,
  357. fspr_size_t * len, fspr_int32_t flags)
  358. {
  359. fspr_off_t nbytes = *len;
  360. int rv;
  361. struct sf_hdtr headerstruct;
  362. /* Ignore flags for now. */
  363. flags = 0;
  364. if (!hdtr) {
  365. hdtr = &no_hdtr;
  366. }
  367. headerstruct.headers = hdtr->headers;
  368. headerstruct.hdr_cnt = hdtr->numheaders;
  369. headerstruct.trailers = hdtr->trailers;
  370. headerstruct.trl_cnt = hdtr->numtrailers;
  371. /* BSD can send the headers/footers as part of the system call */
  372. do {
  373. if (sock->options & APR_INCOMPLETE_WRITE) {
  374. fspr_status_t arv;
  375. sock->options &= ~APR_INCOMPLETE_WRITE;
  376. arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  377. if (arv != APR_SUCCESS) {
  378. *len = 0;
  379. return arv;
  380. }
  381. }
  382. if (nbytes) {
  383. /* We won't dare call sendfile() if we don't have
  384. * header or file bytes to send because nbytes == 0
  385. * means send the remaining file to EOF.
  386. */
  387. rv = sendfile(file->filedes, /* file to be sent */
  388. sock->socketdes, /* socket */
  389. *offset, /* where in the file to start */
  390. &nbytes, /* number of bytes to write/written */
  391. &headerstruct, /* Headers/footers */
  392. flags); /* undefined, set to 0 */
  393. if (rv == -1) {
  394. if (errno == EAGAIN) {
  395. if (sock->timeout > 0) {
  396. sock->options |= APR_INCOMPLETE_WRITE;
  397. }
  398. /* BSD's sendfile can return -1/EAGAIN even if it
  399. * sent bytes. Sanitize the result so we get normal EAGAIN
  400. * semantics w.r.t. bytes sent.
  401. */
  402. if (nbytes) {
  403. /* normal exit for a big file & non-blocking io */
  404. (*len) = nbytes;
  405. return APR_SUCCESS;
  406. }
  407. }
  408. }
  409. else { /* rv == 0 (or the kernel is broken) */
  410. if (nbytes == 0) {
  411. /* Most likely the file got smaller after the stat.
  412. * Return an error so the caller can do the Right Thing.
  413. */
  414. (*len) = nbytes;
  415. return APR_EOF;
  416. }
  417. }
  418. }
  419. else {
  420. /* just trailer bytes... use writev()
  421. */
  422. rv = writev(sock->socketdes,
  423. hdtr->trailers,
  424. hdtr->numtrailers);
  425. if (rv > 0) {
  426. nbytes = rv;
  427. rv = 0;
  428. }
  429. else {
  430. nbytes = 0;
  431. }
  432. }
  433. if ((rv == -1) && (errno == EAGAIN)
  434. && (sock->timeout > 0)) {
  435. fspr_status_t arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  436. if (arv != APR_SUCCESS) {
  437. *len = 0;
  438. return arv;
  439. }
  440. }
  441. } while (rv == -1 && (errno == EINTR || errno == EAGAIN));
  442. (*len) = nbytes;
  443. if (rv == -1) {
  444. return errno;
  445. }
  446. return APR_SUCCESS;
  447. }
  448. #elif defined(__FreeBSD__) || defined(__DragonFly__)
  449. /* Release 3.1 or greater */
  450. fspr_status_t fspr_socket_sendfile(fspr_socket_t * sock, fspr_file_t * file,
  451. fspr_hdtr_t * hdtr, fspr_off_t * offset,
  452. fspr_size_t * len, fspr_int32_t flags)
  453. {
  454. off_t nbytes = 0;
  455. int rv;
  456. #if defined(__FreeBSD_version) && __FreeBSD_version < 460001
  457. int i;
  458. #endif
  459. struct sf_hdtr headerstruct;
  460. fspr_size_t bytes_to_send = *len;
  461. /* Ignore flags for now. */
  462. flags = 0;
  463. if (!hdtr) {
  464. hdtr = &no_hdtr;
  465. }
  466. #if defined(__FreeBSD_version) && __FreeBSD_version < 460001
  467. else if (hdtr->numheaders) {
  468. /* On early versions of FreeBSD sendfile, the number of bytes to send
  469. * must include the length of the headers. Don't look at the man page
  470. * for this :( Instead, look at the the logic in
  471. * src/sys/kern/uipc_syscalls::sendfile().
  472. *
  473. * This was fixed in the middle of 4.6-STABLE
  474. */
  475. for (i = 0; i < hdtr->numheaders; i++) {
  476. bytes_to_send += hdtr->headers[i].iov_len;
  477. }
  478. }
  479. #endif
  480. headerstruct.headers = hdtr->headers;
  481. headerstruct.hdr_cnt = hdtr->numheaders;
  482. headerstruct.trailers = hdtr->trailers;
  483. headerstruct.trl_cnt = hdtr->numtrailers;
  484. /* FreeBSD can send the headers/footers as part of the system call */
  485. do {
  486. if (sock->options & APR_INCOMPLETE_WRITE) {
  487. fspr_status_t arv;
  488. sock->options &= ~APR_INCOMPLETE_WRITE;
  489. arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  490. if (arv != APR_SUCCESS) {
  491. *len = 0;
  492. return arv;
  493. }
  494. }
  495. if (bytes_to_send) {
  496. /* We won't dare call sendfile() if we don't have
  497. * header or file bytes to send because bytes_to_send == 0
  498. * means send the whole file.
  499. */
  500. rv = sendfile(file->filedes, /* file to be sent */
  501. sock->socketdes, /* socket */
  502. *offset, /* where in the file to start */
  503. bytes_to_send, /* number of bytes to send */
  504. &headerstruct, /* Headers/footers */
  505. &nbytes, /* number of bytes written */
  506. flags); /* undefined, set to 0 */
  507. if (rv == -1) {
  508. if (errno == EAGAIN) {
  509. if (sock->timeout > 0) {
  510. sock->options |= APR_INCOMPLETE_WRITE;
  511. }
  512. /* FreeBSD's sendfile can return -1/EAGAIN even if it
  513. * sent bytes. Sanitize the result so we get normal EAGAIN
  514. * semantics w.r.t. bytes sent.
  515. */
  516. if (nbytes) {
  517. /* normal exit for a big file & non-blocking io */
  518. (*len) = nbytes;
  519. return APR_SUCCESS;
  520. }
  521. }
  522. }
  523. else { /* rv == 0 (or the kernel is broken) */
  524. if (nbytes == 0) {
  525. /* Most likely the file got smaller after the stat.
  526. * Return an error so the caller can do the Right Thing.
  527. */
  528. (*len) = nbytes;
  529. return APR_EOF;
  530. }
  531. }
  532. }
  533. else {
  534. /* just trailer bytes... use writev()
  535. */
  536. rv = writev(sock->socketdes,
  537. hdtr->trailers,
  538. hdtr->numtrailers);
  539. if (rv > 0) {
  540. nbytes = rv;
  541. rv = 0;
  542. }
  543. else {
  544. nbytes = 0;
  545. }
  546. }
  547. if ((rv == -1) && (errno == EAGAIN)
  548. && (sock->timeout > 0)) {
  549. fspr_status_t arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  550. if (arv != APR_SUCCESS) {
  551. *len = 0;
  552. return arv;
  553. }
  554. }
  555. } while (rv == -1 && (errno == EINTR || errno == EAGAIN));
  556. (*len) = nbytes;
  557. if (rv == -1) {
  558. return errno;
  559. }
  560. return APR_SUCCESS;
  561. }
  562. #elif defined(__APPLE__)
  563. /*
  564. int
  565. sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr,
  566. int flags);
  567. */
  568. fspr_status_t fspr_socket_sendfile(fspr_socket_t * sock, fspr_file_t * file,
  569. fspr_hdtr_t * hdtr, fspr_off_t * offset,
  570. fspr_size_t * len, fspr_int32_t flags)
  571. {
  572. int rv, i;
  573. struct sf_hdtr headerstruct;
  574. fspr_off_t bytes_to_send = *len;
  575. /* Ignore flags for now. */
  576. flags = 0;
  577. if (!hdtr) {
  578. hdtr = &no_hdtr;
  579. }
  580. else{
  581. if(hdtr->numheaders){
  582. for (i = 0; i < hdtr->numheaders; i++) {
  583. bytes_to_send += hdtr->headers[i].iov_len;
  584. }
  585. }
  586. else hdtr->headers=NULL; //for us having headers pointing to a valid buffer, but numheaders=0 constitues EINVAL..
  587. }
  588. headerstruct.headers = hdtr->headers;
  589. headerstruct.hdr_cnt = hdtr->numheaders;
  590. headerstruct.trailers = hdtr->trailers;
  591. headerstruct.trl_cnt = hdtr->numtrailers;
  592. do {
  593. if (sock->options & APR_INCOMPLETE_WRITE) {
  594. fspr_status_t arv;
  595. sock->options &= ~APR_INCOMPLETE_WRITE;
  596. arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  597. if (arv != APR_SUCCESS) {
  598. *len = 0;
  599. return arv;
  600. }
  601. }
  602. if (bytes_to_send) {
  603. /* We won't dare call sendfile() if we don't have
  604. * header or file bytes to send because bytes_to_send == 0
  605. * means send the whole file.
  606. */
  607. int lflags = fcntl(sock->socketdes,F_GETFL,0);
  608. lflags &= ~O_NONBLOCK;
  609. fcntl(sock->socketdes,F_SETFL,lflags);
  610. rv = sendfile(file->filedes, /* file to be sent */
  611. sock->socketdes, /* socket */
  612. *offset, /* where in the file to start */
  613. &bytes_to_send, /* number of bytes to send */
  614. &headerstruct, /* Headers/footers */
  615. flags); /* undefined, set to 0 */
  616. lflags |= O_NONBLOCK;
  617. fcntl(sock->socketdes,F_SETFL,lflags);
  618. if (rv == -1) {
  619. if (errno == EAGAIN) {
  620. if (sock->timeout > 0) {
  621. sock->options |= APR_INCOMPLETE_WRITE;
  622. }
  623. /* FreeBSD's sendfile can return -1/EAGAIN even if it
  624. * sent bytes. Sanitize the result so we get normal EAGAIN
  625. * semantics w.r.t. bytes sent.
  626. */
  627. if (bytes_to_send) {
  628. /* normal exit for a big file & non-blocking io */
  629. (*len) = bytes_to_send;
  630. return APR_SUCCESS;
  631. }
  632. }
  633. }
  634. else { /* rv == 0 (or the kernel is broken) */
  635. if (bytes_to_send == 0) {
  636. /* Most likely the file got smaller after the stat.
  637. * Return an error so the caller can do the Right Thing.
  638. */
  639. (*len) = bytes_to_send;
  640. return APR_EOF;
  641. }
  642. }
  643. }
  644. else {
  645. /* just trailer bytes... use writev()
  646. */
  647. rv = writev(sock->socketdes,
  648. hdtr->trailers,
  649. hdtr->numtrailers);
  650. if (rv > 0) {
  651. bytes_to_send = rv;
  652. rv = 0;
  653. }
  654. else {
  655. bytes_to_send = 0;
  656. }
  657. }
  658. if ((rv == -1) && (errno == EAGAIN)
  659. && (sock->timeout > 0)) {
  660. fspr_status_t arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  661. if (arv != APR_SUCCESS) {
  662. *len = 0;
  663. return arv;
  664. }
  665. }
  666. } while (rv == -1 && (errno == EINTR || errno == EAGAIN));
  667. (*len) = bytes_to_send;
  668. if (rv == -1) {
  669. return errno;
  670. }
  671. return APR_SUCCESS;
  672. }
  673. #elif defined(__hpux) || defined(__hpux__)
  674. /* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */
  675. /* HP-UX Version 10.30 or greater
  676. * (no worries, because we only get here if autoconfiguration found sendfile)
  677. */
  678. /* ssize_t sendfile(int s, int fd, off_t offset, size_t nbytes,
  679. * const struct iovec *hdtrl, int flags);
  680. *
  681. * nbytes is the number of bytes to send just from the file; as with FreeBSD,
  682. * if nbytes == 0, the rest of the file (from offset) is sent
  683. */
  684. fspr_status_t fspr_socket_sendfile(fspr_socket_t *sock, fspr_file_t *file,
  685. fspr_hdtr_t *hdtr, fspr_off_t *offset,
  686. fspr_size_t *len, fspr_int32_t flags)
  687. {
  688. int i;
  689. fspr_ssize_t rc;
  690. fspr_size_t nbytes = *len, headerlen, trailerlen;
  691. struct iovec hdtrarray[2];
  692. char *headerbuf, *trailerbuf;
  693. #if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILE64)
  694. /* later HP-UXes have a sendfile64() */
  695. #define sendfile sendfile64
  696. fspr_off_t off = *offset;
  697. #elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4
  698. /* HP-UX 11.00 doesn't have a sendfile64(): fail if trying to send
  699. * past the 2Gb limit */
  700. off_t off;
  701. if ((fspr_int64_t)*offset + *len > INT_MAX) {
  702. return EINVAL;
  703. }
  704. off = *offset;
  705. #else
  706. fspr_off_t off = *offset;
  707. #endif
  708. if (!hdtr) {
  709. hdtr = &no_hdtr;
  710. }
  711. /* Ignore flags for now. */
  712. flags = 0;
  713. /* HP-UX can only send one header iovec and one footer iovec; try to
  714. * only allocate storage to combine input iovecs when we really have to
  715. */
  716. switch(hdtr->numheaders) {
  717. case 0:
  718. hdtrarray[0].iov_base = NULL;
  719. hdtrarray[0].iov_len = 0;
  720. break;
  721. case 1:
  722. hdtrarray[0] = hdtr->headers[0];
  723. break;
  724. default:
  725. headerlen = 0;
  726. for (i = 0; i < hdtr->numheaders; i++) {
  727. headerlen += hdtr->headers[i].iov_len;
  728. }
  729. /* XXX: BUHHH? wow, what a memory leak! */
  730. headerbuf = hdtrarray[0].iov_base = fspr_palloc(sock->pool, headerlen);
  731. hdtrarray[0].iov_len = headerlen;
  732. for (i = 0; i < hdtr->numheaders; i++) {
  733. memcpy(headerbuf, hdtr->headers[i].iov_base,
  734. hdtr->headers[i].iov_len);
  735. headerbuf += hdtr->headers[i].iov_len;
  736. }
  737. }
  738. switch(hdtr->numtrailers) {
  739. case 0:
  740. hdtrarray[1].iov_base = NULL;
  741. hdtrarray[1].iov_len = 0;
  742. break;
  743. case 1:
  744. hdtrarray[1] = hdtr->trailers[0];
  745. break;
  746. default:
  747. trailerlen = 0;
  748. for (i = 0; i < hdtr->numtrailers; i++) {
  749. trailerlen += hdtr->trailers[i].iov_len;
  750. }
  751. /* XXX: BUHHH? wow, what a memory leak! */
  752. trailerbuf = hdtrarray[1].iov_base = fspr_palloc(sock->pool, trailerlen);
  753. hdtrarray[1].iov_len = trailerlen;
  754. for (i = 0; i < hdtr->numtrailers; i++) {
  755. memcpy(trailerbuf, hdtr->trailers[i].iov_base,
  756. hdtr->trailers[i].iov_len);
  757. trailerbuf += hdtr->trailers[i].iov_len;
  758. }
  759. }
  760. do {
  761. if (nbytes) { /* any bytes to send from the file? */
  762. rc = sendfile(sock->socketdes, /* socket */
  763. file->filedes, /* file descriptor to send */
  764. off, /* where in the file to start */
  765. nbytes, /* number of bytes to send from file */
  766. hdtrarray, /* Headers/footers */
  767. flags); /* undefined, set to 0 */
  768. }
  769. else { /* we can't call sendfile() with no bytes to send from the file */
  770. rc = writev(sock->socketdes, hdtrarray, 2);
  771. }
  772. } while (rc == -1 && errno == EINTR);
  773. while ((rc == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
  774. && (sock->timeout > 0)) {
  775. fspr_status_t arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  776. if (arv != APR_SUCCESS) {
  777. *len = 0;
  778. return arv;
  779. }
  780. else {
  781. do {
  782. if (nbytes) {
  783. rc = sendfile(sock->socketdes, /* socket */
  784. file->filedes, /* file descriptor to send */
  785. off, /* where in the file to start */
  786. nbytes, /* number of bytes to send from file */
  787. hdtrarray, /* Headers/footers */
  788. flags); /* undefined, set to 0 */
  789. }
  790. else { /* we can't call sendfile() with no bytes to send from the file */
  791. rc = writev(sock->socketdes, hdtrarray, 2);
  792. }
  793. } while (rc == -1 && errno == EINTR);
  794. }
  795. }
  796. if (rc == -1) {
  797. *len = 0;
  798. return errno;
  799. }
  800. /* Set len to the number of bytes written */
  801. *len = rc;
  802. return APR_SUCCESS;
  803. }
  804. #elif defined(_AIX) || defined(__MVS__)
  805. /* AIX and OS/390 have the same send_file() interface.
  806. *
  807. * subtle differences:
  808. * AIX doesn't update the file ptr but OS/390 does
  809. *
  810. * availability (correctly determined by autoconf):
  811. *
  812. * AIX - version 4.3.2 with APAR IX85388, or version 4.3.3 and above
  813. * OS/390 - V2R7 and above
  814. */
  815. fspr_status_t fspr_socket_sendfile(fspr_socket_t * sock, fspr_file_t * file,
  816. fspr_hdtr_t * hdtr, fspr_off_t * offset,
  817. fspr_size_t * len, fspr_int32_t flags)
  818. {
  819. int i, ptr, rv = 0;
  820. void * hbuf=NULL, * tbuf=NULL;
  821. fspr_status_t arv;
  822. struct sf_parms parms;
  823. if (!hdtr) {
  824. hdtr = &no_hdtr;
  825. }
  826. /* Ignore flags for now. */
  827. flags = 0;
  828. /* word to the wise: by default, AIX stores files sent by send_file()
  829. * in the network buffer cache... there are supposedly scenarios
  830. * where the most recent copy of the file won't be sent, but I can't
  831. * recreate the potential problem, perhaps because of the way we
  832. * use send_file()... if you suspect such a problem, try turning
  833. * on the SF_SYNC_CACHE flag
  834. */
  835. /* AIX can also send the headers/footers as part of the system call */
  836. parms.header_length = 0;
  837. if (hdtr && hdtr->numheaders) {
  838. if (hdtr->numheaders == 1) {
  839. parms.header_data = hdtr->headers[0].iov_base;
  840. parms.header_length = hdtr->headers[0].iov_len;
  841. }
  842. else {
  843. for (i = 0; i < hdtr->numheaders; i++) {
  844. parms.header_length += hdtr->headers[i].iov_len;
  845. }
  846. #if 0
  847. /* Keepalives make fspr_palloc a bad idea */
  848. hbuf = malloc(parms.header_length);
  849. #else
  850. /* but headers are small, so maybe we can hold on to the
  851. * memory for the life of the socket...
  852. */
  853. hbuf = fspr_palloc(sock->pool, parms.header_length);
  854. #endif
  855. ptr = 0;
  856. for (i = 0; i < hdtr->numheaders; i++) {
  857. memcpy((char *)hbuf + ptr, hdtr->headers[i].iov_base,
  858. hdtr->headers[i].iov_len);
  859. ptr += hdtr->headers[i].iov_len;
  860. }
  861. parms.header_data = hbuf;
  862. }
  863. }
  864. else parms.header_data = NULL;
  865. parms.trailer_length = 0;
  866. if (hdtr && hdtr->numtrailers) {
  867. if (hdtr->numtrailers == 1) {
  868. parms.trailer_data = hdtr->trailers[0].iov_base;
  869. parms.trailer_length = hdtr->trailers[0].iov_len;
  870. }
  871. else {
  872. for (i = 0; i < hdtr->numtrailers; i++) {
  873. parms.trailer_length += hdtr->trailers[i].iov_len;
  874. }
  875. #if 0
  876. /* Keepalives make fspr_palloc a bad idea */
  877. tbuf = malloc(parms.trailer_length);
  878. #else
  879. tbuf = fspr_palloc(sock->pool, parms.trailer_length);
  880. #endif
  881. ptr = 0;
  882. for (i = 0; i < hdtr->numtrailers; i++) {
  883. memcpy((char *)tbuf + ptr, hdtr->trailers[i].iov_base,
  884. hdtr->trailers[i].iov_len);
  885. ptr += hdtr->trailers[i].iov_len;
  886. }
  887. parms.trailer_data = tbuf;
  888. }
  889. }
  890. else {
  891. parms.trailer_data = NULL;
  892. }
  893. /* Whew! Headers and trailers set up. Now for the file data */
  894. parms.file_descriptor = file->filedes;
  895. parms.file_offset = *offset;
  896. parms.file_bytes = *len;
  897. /* O.K. All set up now. Let's go to town */
  898. if (sock->options & APR_INCOMPLETE_WRITE) {
  899. sock->options &= ~APR_INCOMPLETE_WRITE;
  900. goto do_select;
  901. }
  902. do {
  903. rv = send_file(&(sock->socketdes), /* socket */
  904. &(parms), /* all data */
  905. flags); /* flags */
  906. } while (rv == -1 && errno == EINTR);
  907. while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK)
  908. && (sock->timeout > 0)) {
  909. do_select:
  910. arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  911. if (arv != APR_SUCCESS) {
  912. *len = 0;
  913. return arv;
  914. }
  915. else {
  916. do {
  917. rv = send_file(&(sock->socketdes), /* socket */
  918. &(parms), /* all data */
  919. flags); /* flags */
  920. } while (rv == -1 && errno == EINTR);
  921. }
  922. }
  923. (*len) = parms.bytes_sent;
  924. #if 0
  925. /* Clean up after ourselves */
  926. if(hbuf) free(hbuf);
  927. if(tbuf) free(tbuf);
  928. #endif
  929. if (rv == -1) {
  930. return errno;
  931. }
  932. if ((sock->timeout > 0)
  933. && (parms.bytes_sent
  934. < (parms.file_bytes + parms.header_length + parms.trailer_length))) {
  935. sock->options |= APR_INCOMPLETE_WRITE;
  936. }
  937. return APR_SUCCESS;
  938. }
  939. #elif defined(__osf__) && defined (__alpha)
  940. /* Tru64's sendfile implementation doesn't work, and we need to make sure that
  941. * we don't use it until it is fixed. If it is used as it is now, it will
  942. * hang the machine and the only way to fix it is a reboot.
  943. */
  944. #elif defined(HAVE_SENDFILEV)
  945. /* Solaris 8's sendfilev() interface
  946. *
  947. * SFV_FD_SELF refers to our memory space.
  948. *
  949. * Required Sparc patches (or newer):
  950. * 111297-01, 108528-09, 109472-06, 109234-03, 108995-02, 111295-01, 109025-03,
  951. * 108991-13
  952. * Required x86 patches (or newer):
  953. * 111298-01, 108529-09, 109473-06, 109235-04, 108996-02, 111296-01, 109026-04,
  954. * 108992-13
  955. */
  956. #if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILEV64)
  957. #define sendfilevec_t sendfilevec64_t
  958. #define sendfilev sendfilev64
  959. #endif
  960. fspr_status_t fspr_socket_sendfile(fspr_socket_t *sock, fspr_file_t *file,
  961. fspr_hdtr_t *hdtr, fspr_off_t *offset,
  962. fspr_size_t *len, fspr_int32_t flags)
  963. {
  964. fspr_status_t rv, arv;
  965. fspr_size_t nbytes;
  966. sendfilevec_t *sfv;
  967. int vecs, curvec, i, repeat;
  968. fspr_size_t requested_len = 0;
  969. if (!hdtr) {
  970. hdtr = &no_hdtr;
  971. }
  972. /* Ignore flags for now. */
  973. flags = 0;
  974. /* Calculate how much space we need. */
  975. vecs = hdtr->numheaders + hdtr->numtrailers + 1;
  976. sfv = fspr_palloc(sock->pool, sizeof(sendfilevec_t) * vecs);
  977. curvec = 0;
  978. /* Add the headers */
  979. for (i = 0; i < hdtr->numheaders; i++, curvec++) {
  980. sfv[curvec].sfv_fd = SFV_FD_SELF;
  981. sfv[curvec].sfv_flag = 0;
  982. /* Cast to unsigned long to prevent sign extension of the
  983. * pointer value for the LFS case; see PR 39463. */
  984. sfv[curvec].sfv_off = (unsigned long)hdtr->headers[i].iov_base;
  985. sfv[curvec].sfv_len = hdtr->headers[i].iov_len;
  986. requested_len += sfv[curvec].sfv_len;
  987. }
  988. /* If the len is 0, we skip the file. */
  989. if (*len)
  990. {
  991. sfv[curvec].sfv_fd = file->filedes;
  992. sfv[curvec].sfv_flag = 0;
  993. sfv[curvec].sfv_off = *offset;
  994. sfv[curvec].sfv_len = *len;
  995. requested_len += sfv[curvec].sfv_len;
  996. curvec++;
  997. }
  998. else {
  999. vecs--;
  1000. }
  1001. /* Add the footers */
  1002. for (i = 0; i < hdtr->numtrailers; i++, curvec++) {
  1003. sfv[curvec].sfv_fd = SFV_FD_SELF;
  1004. sfv[curvec].sfv_flag = 0;
  1005. sfv[curvec].sfv_off = (unsigned long)hdtr->trailers[i].iov_base;
  1006. sfv[curvec].sfv_len = hdtr->trailers[i].iov_len;
  1007. requested_len += sfv[curvec].sfv_len;
  1008. }
  1009. /* If the last write couldn't send all the requested data,
  1010. * wait for the socket to become writable before proceeding
  1011. */
  1012. if (sock->options & APR_INCOMPLETE_WRITE) {
  1013. sock->options &= ~APR_INCOMPLETE_WRITE;
  1014. arv = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  1015. if (arv != APR_SUCCESS) {
  1016. *len = 0;
  1017. return arv;
  1018. }
  1019. }
  1020. /* Actually do the sendfilev
  1021. *
  1022. * Solaris may return -1/EAGAIN even if it sent bytes on a non-block sock.
  1023. *
  1024. * If no bytes were originally sent (nbytes == 0) and we are on a TIMEOUT
  1025. * socket (which as far as the OS is concerned is a non-blocking socket),
  1026. * we want to retry after waiting for the other side to read the data (as
  1027. * determined by poll). Once it is clear to send, we want to retry
  1028. * sending the sendfilevec_t once more.
  1029. */
  1030. arv = 0;
  1031. do {
  1032. /* Clear out the repeat */
  1033. repeat = 0;
  1034. /* socket, vecs, number of vecs, bytes written */
  1035. rv = sendfilev(sock->socketdes, sfv, vecs, &nbytes);
  1036. if (rv == -1 && errno == EAGAIN) {
  1037. if (nbytes) {
  1038. rv = 0;
  1039. }
  1040. else if (!arv && (sock->timeout > 0)) {
  1041. fspr_status_t t = fspr_wait_for_io_or_timeout(NULL, sock, 0);
  1042. if (t != APR_SUCCESS) {
  1043. *len = 0;
  1044. return t;
  1045. }
  1046. arv = 1;
  1047. repeat = 1;
  1048. }
  1049. }
  1050. } while ((rv == -1 && errno == EINTR) || repeat);
  1051. if (rv == -1) {
  1052. *len = 0;
  1053. return errno;
  1054. }
  1055. /* Update how much we sent */
  1056. *len = nbytes;
  1057. if ((sock->timeout > 0) && (*len < requested_len)) {
  1058. sock->options |= APR_INCOMPLETE_WRITE;
  1059. }
  1060. return APR_SUCCESS;
  1061. }
  1062. #else
  1063. #error APR has detected sendfile on your system, but nobody has written a
  1064. #error version of it for APR yet. To get past this, either write
  1065. #error fspr_socket_sendfile or change APR_HAS_SENDFILE in apr.h to 0.
  1066. #endif /* __linux__, __FreeBSD__, __DragonFly__, __HPUX__, _AIX, __MVS__,
  1067. Tru64/OSF1 */
  1068. #endif /* APR_HAS_SENDFILE */