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 150Sigor@sysoev.ru static ssize_t nxt_sys_sendfile(int s, int fd, off_t offset, size_t nbytes, 160Sigor@sysoev.ru 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, 260Sigor@sysoev.ru 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 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 51*13Sigor@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 72*13Sigor@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 96*13Sigor@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 105*13Sigor@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; 119*13Sigor@sysoev.ru nxt_log(c->socket.task, nxt_socket_error_level(err), 120*13Sigor@sysoev.ru "sendfile(%d, %FD, @%O, %uz) failed \"%FN\" hd:%ui tr:%ui", 121*13Sigor@sysoev.ru c->socket.fd, fb->file_pos, file_size, &fb->file->name, 122*13Sigor@sysoev.ru nhd, ntr); 1230Sigor@sysoev.ru 1240Sigor@sysoev.ru return NXT_ERROR; 1250Sigor@sysoev.ru } 1260Sigor@sysoev.ru 127*13Sigor@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