summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_sendbuf.h
blob: fcbe1a25bd5214d7a2ff15ea94faf67c6f9e9510 (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

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

#ifndef _NXT_SENDBUF_H_INCLUDED_
#define _NXT_SENDBUF_H_INCLUDED_


/*
 * The sendbuf interface is intended to send a buffer chain to a connection.
 * It uses sendfile interface if available.  Otherwise it can send only
 * memory buffers, so file buffers must be read in memory in advance.
 *
 * The sendbuf interface sets c->socket.write_ready to appropriate state
 * and returns:
 *
 *   N > 0      if sendbuf sent N bytes.
 *
 *   0          if sendbuf was interrupted (EINTR and so on),
 *              or sendbuf sent previously buffered data,
 *              or single sync buffer has been encountered.
 *              In all these cases sendbuf is ready to continue
 *              operation, unless c->socket.write_ready is cleared.
 *
 *   NXT_AGAIN  if sendbuf did not send any bytes.
 *
 *   NXT_ERROR  if there was erorr.
 *
 * The sendbuf limit is size_t type since size_t is large enough and many
 * sendfile implementations do not support anyway sending more than size_t
 * at once.  The limit support is located at the sendbuf level otherwise
 * an additional limited chain must be created on each sendbuf call.
 */


typedef struct {
    nxt_buf_t     *buf;
    void          *tls;
    nxt_socket_t  socket;
    nxt_err_t     error;
    nxt_off_t     sent;
    size_t        size;
    size_t        limit;

    uint8_t       ready;   /* 1 bit */
    uint8_t       once;    /* 1 bit */
    uint8_t       sync;    /* 1 bit */
    uint8_t       last;    /* 1 bit */
} nxt_sendbuf_t;


typedef struct {
    nxt_buf_t    *buf;
    nxt_iobuf_t  *iobuf;
    nxt_uint_t   niov;

    uint32_t     nmax;
    uint8_t      sync;   /* 1 bit */
    uint8_t      last;   /* 1 bit */
    uint8_t      limit_reached;
    uint8_t      nmax_reached;

    size_t       size;
    size_t       limit;
} nxt_sendbuf_coalesce_t;


#if (NXT_HAVE_LINUX_SENDFILE)
#define NXT_HAVE_SENDFILE  1
ssize_t nxt_linux_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b,
    size_t limit);
#endif

#if (NXT_HAVE_FREEBSD_SENDFILE)
#define NXT_HAVE_SENDFILE  1
ssize_t nxt_freebsd_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b,
    size_t limit);
#endif

#if (NXT_HAVE_SOLARIS_SENDFILEV)
#define NXT_HAVE_SENDFILE  1
ssize_t nxt_solaris_event_conn_io_sendfilev(nxt_conn_t *c, nxt_buf_t *b,
    size_t limit);
#endif

#if (NXT_HAVE_MACOSX_SENDFILE)
#define NXT_HAVE_SENDFILE  1
ssize_t nxt_macosx_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b,
    size_t limit);
#endif

#if (NXT_HAVE_AIX_SEND_FILE)
#define NXT_HAVE_SENDFILE  1
ssize_t nxt_aix_event_conn_io_send_file(nxt_conn_t *c, nxt_buf_t *b,
    size_t limit);
#endif

#if (NXT_HAVE_HPUX_SENDFILE)
#define NXT_HAVE_SENDFILE  1
ssize_t nxt_hpux_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b,
    size_t limit);
#endif

ssize_t nxt_event_conn_io_sendbuf(nxt_conn_t *c, nxt_buf_t *b,
    size_t limit);


nxt_uint_t nxt_sendbuf_mem_coalesce0(nxt_task_t *task, nxt_sendbuf_t *sb,
    struct iovec *iov, nxt_uint_t niov_max);
nxt_uint_t nxt_sendbuf_mem_coalesce(nxt_task_t *task,
    nxt_sendbuf_coalesce_t *sb);
size_t nxt_sendbuf_file_coalesce(nxt_sendbuf_coalesce_t *sb);

/*
 * Auxiliary nxt_sendbuf_copy_coalesce() interface copies small memory
 * buffers into internal buffer before output.  It is intended for
 * SSL/TLS libraries which lack vector I/O interface yet add noticeable
 * overhead to each SSL/TLS record.
 */
ssize_t nxt_sendbuf_copy_coalesce(nxt_conn_t *c, nxt_buf_mem_t *bm,
    nxt_buf_t *b, size_t limit);

nxt_buf_t *nxt_sendbuf_update(nxt_buf_t *b, size_t sent);
nxt_buf_t *nxt_sendbuf_completion(nxt_task_t *task, nxt_work_queue_t *wq,
    nxt_buf_t *b);
void nxt_sendbuf_drain(nxt_task_t *task, nxt_work_queue_t *wq, nxt_buf_t *b);


#endif /* _NXT_SENDBUF_H_INCLUDED_ */