PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib/apr/network_io/unix/sendrecv.c

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