summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_hpux_sendfile.c
blob: df200b64c1fa08b47e1079ce2a4064f0a40b9bdb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) NGINX, Inc.
 */

#include <nxt_main.h>


#ifdef NXT_TEST_BUILD_HPUX_SENDFILE

ssize_t nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b,
    size_t limit);

static ssize_t nxt_sys_sendfile(int s, int fd, off_t offset, size_t nbytes,
    const struct iovec *hdtrl, int flags)
{
    return -1;
}

#else

/* sendfile() is not declared if _XOPEN_SOURCE_EXTENDED is defined. */

sbsize_t sendfile(int s, int fd, off_t offset, bsize_t nbytes,
    const struct iovec *hdtrl, int flags);

#define nxt_sys_sendfile  sendfile

#endif


ssize_t
nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, size_t limit)
{
    size_t                  file_size;
    ssize_t                 n;
    nxt_buf_t               *fb;
    nxt_err_t               err;
    nxt_uint_t              nhd, ntr;
    struct iovec            iov[NXT_IOBUF_MAX], *hdtrl;
    nxt_sendbuf_coalesce_t  sb;

    sb.buf = b;
    sb.iobuf = iov;
    sb.nmax = NXT_IOBUF_MAX;
    sb.sync = 0;
    sb.size = 0;
    sb.limit = limit;

    nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);

    if (nhd == 0 && sb.sync) {
        return 0;
    }

    if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) {
        return nxt_event_conn_io_writev(c, iov, nhd);
    }

    fb = sb.buf;

    file_size = nxt_sendbuf_file_coalesce(&sb);

    if (file_size == 0) {
        return nxt_event_conn_io_writev(c, iov, nhd);
    }

    sb.iobuf = &iov[1];
    sb.nmax = 1;

    ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb);

    /*
     * Disposal of surplus kernel operations
     * if there are no headers and trailers.
     */

    if (nhd == 0) {
        hdtrl = NULL;
        iov[0].iov_base = NULL;
        iov[0].iov_len = 0;

    } else {
        hdtrl = iov;
    }

    if (ntr == 0) {
        iov[1].iov_base = NULL;
        iov[1].iov_len = 0;

    } else {
        hdtrl = iov;
    }

    nxt_debug(c->socket.task, "sendfile(%d, %FD, @%O, %uz) hd:%ui tr:%ui",
                  c->socket.fd, fb->file->fd, fb->file_pos, file_size,
                  nhd, ntr);

    n = nxt_sys_sendfile(c->socket.fd, fb->file->fd, fb->file_pos,
                         file_size, hdtrl, 0);

    err = (n == -1) ? nxt_errno : 0;

    nxt_debug(c->socket.task, "sendfile(): %uz", n);

    if (n == -1) {
        switch (err) {

        case NXT_EAGAIN:
            c->socket.write_ready = 0;
            break;

        case NXT_EINTR:
            break;

        default:
            c->socket.error = err;
            nxt_log(c->socket.task, nxt_socket_error_level(err),
                    "sendfile(%d, %FD, @%O, %uz) failed \"%FN\" hd:%ui tr:%ui",
                    c->socket.fd, fb->file_pos, file_size, &fb->file->name,
                    nhd, ntr);

            return NXT_ERROR;
        }

        nxt_debug(c->socket.task, "sendfile() %E", err);

        return 0;
    }

    if (n < (ssize_t) sb.size) {
        c->socket.write_ready = 0;
    }

    return n;
}