1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_main.h>
8
9
10 /* send_file() has been introduced in AIX 4.3.2 */
11
12 ssize_t nxt_aix_event_conn_io_send_file(nxt_event_conn_t *c, nxt_buf_t *b,
13 size_t limit);
14
15
16 ssize_t
nxt_aix_event_conn_io_send_file(nxt_event_conn_t * c,nxt_buf_t * b,size_t limit)17 nxt_aix_event_conn_io_send_file(nxt_event_conn_t *c, nxt_buf_t *b, size_t limit)
18 {
19 ssize_t n;
20 nxt_buf_t *fb;
21 nxt_err_t err;
22 nxt_off_t file_size, sent;
23 nxt_uint_t nhd, ntr;
24 struct iovec hd[NXT_IOBUF_MAX], tr;
25 struct sf_parms sfp;
26 nxt_sendbuf_coalesce_t sb;
27
28 sb.buf = b;
29 sb.iobuf = hd;
30 sb.nmax = NXT_IOBUF_MAX;
31 sb.sync = 0;
32 sb.size = 0;
33 sb.limit = limit;
34
35 nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);
36
37 if (nhd == 0 && sb.sync) {
38 return 0;
39 }
40
41 if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) {
42 return nxt_event_conn_io_writev(c, hd, nhd);
43 }
44
45 fb = sb.buf;
46
47 file_size = nxt_sendbuf_file_coalesce(&sb);
48
49 if (file_size == 0) {
50 return nxt_event_conn_io_writev(c, hd, nhd);
51 }
52
53 sb.iobuf = &tr;
54 sb.nmax = 1;
55
56 ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);
57
58 nxt_memzero(&sfp, sizeof(struct sf_parms));
59
60 if (nhd != 0) {
61 sfp.header_data = hd[0].iov_base;
62 sfp.header_length = hd[0].iov_len;
63 }
64
65 sfp.file_descriptor = fb->file->fd;
66 sfp.file_offset = fb->file_pos;
67 sfp.file_bytes = file_size;
68
69 if (ntr != 0) {
70 sfp.trailer_data = tr.iov_base;
71 sfp.trailer_length = tr.iov_len;
72 }
73
74 nxt_debug(c->socket.task, "send_file(%d) fd:%FD @%O:%O hd:%ui tr:%ui",
75 c->socket.fd, fb->file->fd, fb->file_pos, file_size, nhd, ntr);
76
77 n = send_file(&c->socket.fd, &sfp, 0);
78
79 err = (n == -1) ? nxt_errno : 0;
80 sent = sfp.bytes_sent;
81
82 nxt_debug(c->socket.task, "send_file(%d): %d sent:%O",
83 c->socket.fd, n, sent);
84
85 /*
86 * -1 an error has occurred, errno contains the error code;
87 * 0 the command has completed successfully;
88 * 1 the command was completed partially, some data has been
89 * transmitted but the command has to return for some reason,
90 * for example, the command was interrupted by signals.
91 */
92 if (n == -1) {
93 switch (err) {
94
95 case NXT_EAGAIN:
96 c->socket.write_ready = 0;
97 break;
98
99 case NXT_EINTR:
100 break;
101
102 default:
103 c->socket.error = err;
104 nxt_log(c->socket.task, nxt_socket_error_level(err),
105 "send_file(%d) failed %E \"%FN\" fd:%FD @%O:%O hd:%ui tr:%ui",
106 c->socket.fd, err, fb->file->name, fb->file->fd, fb->file_pos,
107 file_size, nhd, ntr);
108
109 return NXT_ERROR;
110 }
111
112 nxt_debug(c->socket.task, "sendfile() %E", err);
113
114 return sent;
115 }
116
117 if (n == 1) {
118 return sent;
119 }
120
121 if (sent < (nxt_off_t) sb.size) {
122 c->socket.write_ready = 0;
123 }
124
125 return sent;
126 }
127