1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_main.h>
8
9
10 #ifdef NXT_TEST_BUILD_HPUX_SENDFILE
11
12 ssize_t nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b,
13 size_t limit);
14
nxt_sys_sendfile(int s,int fd,off_t offset,size_t nbytes,const struct iovec * hdtrl,int flags)15 static ssize_t nxt_sys_sendfile(int s, int fd, off_t offset, size_t nbytes,
16 const struct iovec *hdtrl, int flags)
17 {
18 return -1;
19 }
20
21 #else
22
23 /* sendfile() is not declared if _XOPEN_SOURCE_EXTENDED is defined. */
24
25 sbsize_t sendfile(int s, int fd, off_t offset, bsize_t nbytes,
26 const struct iovec *hdtrl, int flags);
27
28 #define nxt_sys_sendfile sendfile
29
30 #endif
31
32
33 ssize_t
nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t * c,nxt_buf_t * b,size_t limit)34 nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, size_t limit)
35 {
36 size_t file_size;
37 ssize_t n;
38 nxt_buf_t *fb;
39 nxt_err_t err;
40 nxt_uint_t nhd, ntr;
41 struct iovec iov[NXT_IOBUF_MAX], *hdtrl;
42 nxt_sendbuf_coalesce_t sb;
43
44 sb.buf = b;
45 sb.iobuf = iov;
46 sb.nmax = NXT_IOBUF_MAX;
47 sb.sync = 0;
48 sb.size = 0;
49 sb.limit = limit;
50
51 nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);
52
53 if (nhd == 0 && sb.sync) {
54 return 0;
55 }
56
57 if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) {
58 return nxt_event_conn_io_writev(c, iov, nhd);
59 }
60
61 fb = sb.buf;
62
63 file_size = nxt_sendbuf_file_coalesce(&sb);
64
65 if (file_size == 0) {
66 return nxt_event_conn_io_writev(c, iov, nhd);
67 }
68
69 sb.iobuf = &iov[1];
70 sb.nmax = 1;
71
72 ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);
73
74 /*
75 * Disposal of surplus kernel operations
76 * if there are no headers and trailers.
77 */
78
79 if (nhd == 0) {
80 hdtrl = NULL;
81 iov[0].iov_base = NULL;
82 iov[0].iov_len = 0;
83
84 } else {
85 hdtrl = iov;
86 }
87
88 if (ntr == 0) {
89 iov[1].iov_base = NULL;
90 iov[1].iov_len = 0;
91
92 } else {
93 hdtrl = iov;
94 }
95
96 nxt_debug(c->socket.task, "sendfile(%d, %FD, @%O, %uz) hd:%ui tr:%ui",
97 c->socket.fd, fb->file->fd, fb->file_pos, file_size,
98 nhd, ntr);
99
100 n = nxt_sys_sendfile(c->socket.fd, fb->file->fd, fb->file_pos,
101 file_size, hdtrl, 0);
102
103 err = (n == -1) ? nxt_errno : 0;
104
105 nxt_debug(c->socket.task, "sendfile(): %uz", n);
106
107 if (n == -1) {
108 switch (err) {
109
110 case NXT_EAGAIN:
111 c->socket.write_ready = 0;
112 break;
113
114 case NXT_EINTR:
115 break;
116
117 default:
118 c->socket.error = err;
119 nxt_log(c->socket.task, nxt_socket_error_level(err),
120 "sendfile(%d, %FD, @%O, %uz) failed \"%FN\" hd:%ui tr:%ui",
121 c->socket.fd, fb->file_pos, file_size, &fb->file->name,
122 nhd, ntr);
123
124 return NXT_ERROR;
125 }
126
127 nxt_debug(c->socket.task, "sendfile() %E", err);
128
129 return 0;
130 }
131
132 if (n < (ssize_t) sb.size) {
133 c->socket.write_ready = 0;
134 }
135
136 return n;
137 }
138