10Sigor@sysoev.ru
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru */
60Sigor@sysoev.ru
70Sigor@sysoev.ru #include <nxt_main.h>
80Sigor@sysoev.ru
90Sigor@sysoev.ru
100Sigor@sysoev.ru #ifdef NXT_TEST_BUILD_HPUX_SENDFILE
110Sigor@sysoev.ru
120Sigor@sysoev.ru ssize_t nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b,
130Sigor@sysoev.ru size_t limit);
140Sigor@sysoev.ru
nxt_sys_sendfile(int s,int fd,off_t offset,size_t nbytes,const struct iovec * hdtrl,int flags)150Sigor@sysoev.ru static ssize_t nxt_sys_sendfile(int s, int fd, off_t offset, size_t nbytes,
16*1008Szelenkov@nginx.com const struct iovec *hdtrl, int flags)
170Sigor@sysoev.ru {
180Sigor@sysoev.ru return -1;
190Sigor@sysoev.ru }
200Sigor@sysoev.ru
210Sigor@sysoev.ru #else
220Sigor@sysoev.ru
230Sigor@sysoev.ru /* sendfile() is not declared if _XOPEN_SOURCE_EXTENDED is defined. */
240Sigor@sysoev.ru
250Sigor@sysoev.ru sbsize_t sendfile(int s, int fd, off_t offset, bsize_t nbytes,
26*1008Szelenkov@nginx.com const struct iovec *hdtrl, int flags);
270Sigor@sysoev.ru
280Sigor@sysoev.ru #define nxt_sys_sendfile sendfile
290Sigor@sysoev.ru
300Sigor@sysoev.ru #endif
310Sigor@sysoev.ru
320Sigor@sysoev.ru
330Sigor@sysoev.ru ssize_t
nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t * c,nxt_buf_t * b,size_t limit)340Sigor@sysoev.ru nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, size_t limit)
350Sigor@sysoev.ru {
360Sigor@sysoev.ru size_t file_size;
370Sigor@sysoev.ru ssize_t n;
380Sigor@sysoev.ru nxt_buf_t *fb;
390Sigor@sysoev.ru nxt_err_t err;
400Sigor@sysoev.ru nxt_uint_t nhd, ntr;
410Sigor@sysoev.ru struct iovec iov[NXT_IOBUF_MAX], *hdtrl;
420Sigor@sysoev.ru nxt_sendbuf_coalesce_t sb;
430Sigor@sysoev.ru
440Sigor@sysoev.ru sb.buf = b;
450Sigor@sysoev.ru sb.iobuf = iov;
460Sigor@sysoev.ru sb.nmax = NXT_IOBUF_MAX;
470Sigor@sysoev.ru sb.sync = 0;
480Sigor@sysoev.ru sb.size = 0;
490Sigor@sysoev.ru sb.limit = limit;
500Sigor@sysoev.ru
5113Sigor@sysoev.ru nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);
520Sigor@sysoev.ru
530Sigor@sysoev.ru if (nhd == 0 && sb.sync) {
540Sigor@sysoev.ru return 0;
550Sigor@sysoev.ru }
560Sigor@sysoev.ru
570Sigor@sysoev.ru if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) {
580Sigor@sysoev.ru return nxt_event_conn_io_writev(c, iov, nhd);
590Sigor@sysoev.ru }
600Sigor@sysoev.ru
610Sigor@sysoev.ru fb = sb.buf;
620Sigor@sysoev.ru
630Sigor@sysoev.ru file_size = nxt_sendbuf_file_coalesce(&sb);
640Sigor@sysoev.ru
650Sigor@sysoev.ru if (file_size == 0) {
660Sigor@sysoev.ru return nxt_event_conn_io_writev(c, iov, nhd);
670Sigor@sysoev.ru }
680Sigor@sysoev.ru
690Sigor@sysoev.ru sb.iobuf = &iov[1];
700Sigor@sysoev.ru sb.nmax = 1;
710Sigor@sysoev.ru
7213Sigor@sysoev.ru ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);
730Sigor@sysoev.ru
740Sigor@sysoev.ru /*
750Sigor@sysoev.ru * Disposal of surplus kernel operations
760Sigor@sysoev.ru * if there are no headers and trailers.
770Sigor@sysoev.ru */
780Sigor@sysoev.ru
790Sigor@sysoev.ru if (nhd == 0) {
800Sigor@sysoev.ru hdtrl = NULL;
810Sigor@sysoev.ru iov[0].iov_base = NULL;
820Sigor@sysoev.ru iov[0].iov_len = 0;
830Sigor@sysoev.ru
840Sigor@sysoev.ru } else {
850Sigor@sysoev.ru hdtrl = iov;
860Sigor@sysoev.ru }
870Sigor@sysoev.ru
880Sigor@sysoev.ru if (ntr == 0) {
890Sigor@sysoev.ru iov[1].iov_base = NULL;
900Sigor@sysoev.ru iov[1].iov_len = 0;
910Sigor@sysoev.ru
920Sigor@sysoev.ru } else {
930Sigor@sysoev.ru hdtrl = iov;
940Sigor@sysoev.ru }
950Sigor@sysoev.ru
9613Sigor@sysoev.ru nxt_debug(c->socket.task, "sendfile(%d, %FD, @%O, %uz) hd:%ui tr:%ui",
970Sigor@sysoev.ru c->socket.fd, fb->file->fd, fb->file_pos, file_size,
980Sigor@sysoev.ru nhd, ntr);
990Sigor@sysoev.ru
1000Sigor@sysoev.ru n = nxt_sys_sendfile(c->socket.fd, fb->file->fd, fb->file_pos,
1010Sigor@sysoev.ru file_size, hdtrl, 0);
1020Sigor@sysoev.ru
1030Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0;
1040Sigor@sysoev.ru
10513Sigor@sysoev.ru nxt_debug(c->socket.task, "sendfile(): %uz", n);
1060Sigor@sysoev.ru
1070Sigor@sysoev.ru if (n == -1) {
1080Sigor@sysoev.ru switch (err) {
1090Sigor@sysoev.ru
1100Sigor@sysoev.ru case NXT_EAGAIN:
1110Sigor@sysoev.ru c->socket.write_ready = 0;
1120Sigor@sysoev.ru break;
1130Sigor@sysoev.ru
1140Sigor@sysoev.ru case NXT_EINTR:
1150Sigor@sysoev.ru break;
1160Sigor@sysoev.ru
1170Sigor@sysoev.ru default:
1180Sigor@sysoev.ru c->socket.error = err;
11913Sigor@sysoev.ru nxt_log(c->socket.task, nxt_socket_error_level(err),
12013Sigor@sysoev.ru "sendfile(%d, %FD, @%O, %uz) failed \"%FN\" hd:%ui tr:%ui",
12113Sigor@sysoev.ru c->socket.fd, fb->file_pos, file_size, &fb->file->name,
12213Sigor@sysoev.ru nhd, ntr);
1230Sigor@sysoev.ru
1240Sigor@sysoev.ru return NXT_ERROR;
1250Sigor@sysoev.ru }
1260Sigor@sysoev.ru
12713Sigor@sysoev.ru nxt_debug(c->socket.task, "sendfile() %E", err);
1280Sigor@sysoev.ru
1290Sigor@sysoev.ru return 0;
1300Sigor@sysoev.ru }
1310Sigor@sysoev.ru
1320Sigor@sysoev.ru if (n < (ssize_t) sb.size) {
1330Sigor@sysoev.ru c->socket.write_ready = 0;
1340Sigor@sysoev.ru }
1350Sigor@sysoev.ru
1360Sigor@sysoev.ru return n;
1370Sigor@sysoev.ru }
138