xref: /unit/src/nxt_aix_send_file.c (revision 13:3a52b2c3d3f1)
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 /* send_file() has been introduced in AIX 4.3.2 */
110Sigor@sysoev.ru 
120Sigor@sysoev.ru ssize_t nxt_aix_event_conn_io_send_file(nxt_event_conn_t *c, nxt_buf_t *b,
130Sigor@sysoev.ru     size_t limit);
140Sigor@sysoev.ru 
150Sigor@sysoev.ru 
160Sigor@sysoev.ru ssize_t
nxt_aix_event_conn_io_send_file(nxt_event_conn_t * c,nxt_buf_t * b,size_t limit)170Sigor@sysoev.ru nxt_aix_event_conn_io_send_file(nxt_event_conn_t *c, nxt_buf_t *b, size_t limit)
180Sigor@sysoev.ru {
190Sigor@sysoev.ru     ssize_t                 n;
200Sigor@sysoev.ru     nxt_buf_t               *fb;
210Sigor@sysoev.ru     nxt_err_t               err;
220Sigor@sysoev.ru     nxt_off_t               file_size, sent;
230Sigor@sysoev.ru     nxt_uint_t              nhd, ntr;
240Sigor@sysoev.ru     struct iovec            hd[NXT_IOBUF_MAX], tr;
250Sigor@sysoev.ru     struct sf_parms         sfp;
260Sigor@sysoev.ru     nxt_sendbuf_coalesce_t  sb;
270Sigor@sysoev.ru 
280Sigor@sysoev.ru     sb.buf = b;
290Sigor@sysoev.ru     sb.iobuf = hd;
300Sigor@sysoev.ru     sb.nmax = NXT_IOBUF_MAX;
310Sigor@sysoev.ru     sb.sync = 0;
320Sigor@sysoev.ru     sb.size = 0;
330Sigor@sysoev.ru     sb.limit = limit;
340Sigor@sysoev.ru 
35*13Sigor@sysoev.ru     nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);
360Sigor@sysoev.ru 
370Sigor@sysoev.ru     if (nhd == 0 && sb.sync) {
380Sigor@sysoev.ru         return 0;
390Sigor@sysoev.ru     }
400Sigor@sysoev.ru 
410Sigor@sysoev.ru     if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) {
420Sigor@sysoev.ru         return nxt_event_conn_io_writev(c, hd, nhd);
430Sigor@sysoev.ru     }
440Sigor@sysoev.ru 
450Sigor@sysoev.ru     fb = sb.buf;
460Sigor@sysoev.ru 
470Sigor@sysoev.ru     file_size = nxt_sendbuf_file_coalesce(&sb);
480Sigor@sysoev.ru 
490Sigor@sysoev.ru     if (file_size == 0) {
500Sigor@sysoev.ru         return nxt_event_conn_io_writev(c, hd, nhd);
510Sigor@sysoev.ru     }
520Sigor@sysoev.ru 
530Sigor@sysoev.ru     sb.iobuf = &tr;
540Sigor@sysoev.ru     sb.nmax = 1;
550Sigor@sysoev.ru 
56*13Sigor@sysoev.ru     ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);
570Sigor@sysoev.ru 
580Sigor@sysoev.ru     nxt_memzero(&sfp, sizeof(struct sf_parms));
590Sigor@sysoev.ru 
600Sigor@sysoev.ru     if (nhd != 0) {
610Sigor@sysoev.ru         sfp.header_data = hd[0].iov_base;
620Sigor@sysoev.ru         sfp.header_length = hd[0].iov_len;
630Sigor@sysoev.ru     }
640Sigor@sysoev.ru 
650Sigor@sysoev.ru     sfp.file_descriptor = fb->file->fd;
660Sigor@sysoev.ru     sfp.file_offset = fb->file_pos;
670Sigor@sysoev.ru     sfp.file_bytes = file_size;
680Sigor@sysoev.ru 
690Sigor@sysoev.ru     if (ntr != 0) {
700Sigor@sysoev.ru         sfp.trailer_data = tr.iov_base;
710Sigor@sysoev.ru         sfp.trailer_length = tr.iov_len;
720Sigor@sysoev.ru     }
730Sigor@sysoev.ru 
74*13Sigor@sysoev.ru     nxt_debug(c->socket.task, "send_file(%d) fd:%FD @%O:%O hd:%ui tr:%ui",
75*13Sigor@sysoev.ru               c->socket.fd, fb->file->fd, fb->file_pos, file_size, nhd, ntr);
760Sigor@sysoev.ru 
770Sigor@sysoev.ru     n = send_file(&c->socket.fd, &sfp, 0);
780Sigor@sysoev.ru 
790Sigor@sysoev.ru     err = (n == -1) ? nxt_errno : 0;
800Sigor@sysoev.ru     sent = sfp.bytes_sent;
810Sigor@sysoev.ru 
82*13Sigor@sysoev.ru     nxt_debug(c->socket.task, "send_file(%d): %d sent:%O",
83*13Sigor@sysoev.ru               c->socket.fd, n, sent);
840Sigor@sysoev.ru 
850Sigor@sysoev.ru     /*
860Sigor@sysoev.ru      * -1  an error has occurred, errno contains the error code;
870Sigor@sysoev.ru      *  0  the command has completed successfully;
880Sigor@sysoev.ru      *  1  the command was completed partially, some data has been
890Sigor@sysoev.ru      *     transmitted but the command has to return for some reason,
900Sigor@sysoev.ru      *     for example, the command was interrupted by signals.
910Sigor@sysoev.ru      */
920Sigor@sysoev.ru     if (n == -1) {
930Sigor@sysoev.ru         switch (err) {
940Sigor@sysoev.ru 
950Sigor@sysoev.ru         case NXT_EAGAIN:
960Sigor@sysoev.ru             c->socket.write_ready = 0;
970Sigor@sysoev.ru             break;
980Sigor@sysoev.ru 
990Sigor@sysoev.ru         case NXT_EINTR:
1000Sigor@sysoev.ru             break;
1010Sigor@sysoev.ru 
1020Sigor@sysoev.ru         default:
1030Sigor@sysoev.ru             c->socket.error = err;
104*13Sigor@sysoev.ru             nxt_log(c->socket.task, nxt_socket_error_level(err),
105*13Sigor@sysoev.ru                 "send_file(%d) failed %E \"%FN\" fd:%FD @%O:%O hd:%ui tr:%ui",
106*13Sigor@sysoev.ru                 c->socket.fd, err, fb->file->name, fb->file->fd, fb->file_pos,
107*13Sigor@sysoev.ru                 file_size, nhd, ntr);
1080Sigor@sysoev.ru 
1090Sigor@sysoev.ru             return NXT_ERROR;
1100Sigor@sysoev.ru         }
1110Sigor@sysoev.ru 
112*13Sigor@sysoev.ru         nxt_debug(c->socket.task, "sendfile() %E", err);
1130Sigor@sysoev.ru 
1140Sigor@sysoev.ru         return sent;
1150Sigor@sysoev.ru     }
1160Sigor@sysoev.ru 
1170Sigor@sysoev.ru     if (n == 1) {
1180Sigor@sysoev.ru         return sent;
1190Sigor@sysoev.ru     }
1200Sigor@sysoev.ru 
1210Sigor@sysoev.ru     if (sent < (nxt_off_t) sb.size) {
1220Sigor@sysoev.ru         c->socket.write_ready = 0;
1230Sigor@sysoev.ru     }
1240Sigor@sysoev.ru 
1250Sigor@sysoev.ru     return sent;
1260Sigor@sysoev.ru }
127