xref: /unit/src/nxt_conn.h (revision 359)
162Sigor@sysoev.ru 
262Sigor@sysoev.ru /*
362Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
462Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
562Sigor@sysoev.ru  */
662Sigor@sysoev.ru 
762Sigor@sysoev.ru #ifndef _NXT_CONN_H_INCLUDED_
862Sigor@sysoev.ru #define _NXT_CONN_H_INCLUDED_
962Sigor@sysoev.ru 
1062Sigor@sysoev.ru 
1162Sigor@sysoev.ru typedef nxt_msec_t (*nxt_conn_timer_value_t)(nxt_conn_t *c, uintptr_t data);
1262Sigor@sysoev.ru 
1362Sigor@sysoev.ru 
1462Sigor@sysoev.ru typedef struct {
1562Sigor@sysoev.ru     nxt_work_handler_t            ready_handler;
1662Sigor@sysoev.ru     nxt_work_handler_t            close_handler;
1762Sigor@sysoev.ru     nxt_work_handler_t            error_handler;
1862Sigor@sysoev.ru 
1962Sigor@sysoev.ru     nxt_work_handler_t            timer_handler;
2062Sigor@sysoev.ru     nxt_conn_timer_value_t        timer_value;
2162Sigor@sysoev.ru     uintptr_t                     timer_data;
2262Sigor@sysoev.ru 
2362Sigor@sysoev.ru     uint8_t                       timer_autoreset;
2462Sigor@sysoev.ru } nxt_conn_state_t;
2562Sigor@sysoev.ru 
2662Sigor@sysoev.ru 
2762Sigor@sysoev.ru typedef struct {
2862Sigor@sysoev.ru     double                        average;
2962Sigor@sysoev.ru     size_t                        limit;
3062Sigor@sysoev.ru     size_t                        limit_after;
3162Sigor@sysoev.ru     size_t                        max_limit;
3262Sigor@sysoev.ru     nxt_msec_t                    last;
3362Sigor@sysoev.ru } nxt_event_write_rate_t;
3462Sigor@sysoev.ru 
3562Sigor@sysoev.ru 
3662Sigor@sysoev.ru typedef struct {
3762Sigor@sysoev.ru 
3862Sigor@sysoev.ru     nxt_work_handler_t            connect;
3962Sigor@sysoev.ru     nxt_work_handler_t            accept;
4062Sigor@sysoev.ru 
4162Sigor@sysoev.ru     /*
4262Sigor@sysoev.ru      * The read() with NULL c->read buffer waits readiness of a connection
4362Sigor@sysoev.ru      * to avoid allocation of read buffer if the connection will time out
4462Sigor@sysoev.ru      * or will be closed with error.  The kqueue-specific read() can also
4562Sigor@sysoev.ru      * detect case if a client did not sent anything and has just closed the
4662Sigor@sysoev.ru      * connection without errors.  In the latter case state's close_handler
4762Sigor@sysoev.ru      * is called.
4862Sigor@sysoev.ru      */
4962Sigor@sysoev.ru     nxt_work_handler_t            read;
5062Sigor@sysoev.ru 
5162Sigor@sysoev.ru     ssize_t                       (*recvbuf)(nxt_conn_t *c, nxt_buf_t *b);
5262Sigor@sysoev.ru 
5362Sigor@sysoev.ru     ssize_t                       (*recv)(nxt_conn_t *c, void *buf,
5462Sigor@sysoev.ru                                       size_t size, nxt_uint_t flags);
5562Sigor@sysoev.ru 
5662Sigor@sysoev.ru     /*
5762Sigor@sysoev.ru      * The write() is an interface to write a buffer chain with a given rate
5862Sigor@sysoev.ru      * limit.  It calls write_chunk() in a loop and handles write event timer.
5962Sigor@sysoev.ru      */
6062Sigor@sysoev.ru     nxt_work_handler_t            write;
6162Sigor@sysoev.ru 
6262Sigor@sysoev.ru     /*
6362Sigor@sysoev.ru      * The write_chunk() interface writes a buffer chain with a given limit
6462Sigor@sysoev.ru      * and toggles write event.  SSL/TLS libraries' write_chunk() interface
6562Sigor@sysoev.ru      * buffers data and calls the library specific send() interface to write
6662Sigor@sysoev.ru      * the buffered data eventually.
6762Sigor@sysoev.ru      */
6862Sigor@sysoev.ru     ssize_t                       (*write_chunk)(nxt_conn_t *c,
6962Sigor@sysoev.ru                                       nxt_buf_t *b, size_t limit);
7062Sigor@sysoev.ru 
7162Sigor@sysoev.ru     /*
7262Sigor@sysoev.ru      * The sendbuf() is an interface for OS-specific sendfile
7362Sigor@sysoev.ru      * implementations or simple writev().
7462Sigor@sysoev.ru      */
7562Sigor@sysoev.ru     ssize_t                       (*sendbuf)(nxt_conn_t *c, nxt_buf_t *b,
7662Sigor@sysoev.ru                                       size_t limit);
7762Sigor@sysoev.ru     /*
7862Sigor@sysoev.ru      * The writev() is an interface to write several nxt_iobuf_t buffers.
7962Sigor@sysoev.ru      */
8062Sigor@sysoev.ru     ssize_t                       (*writev)(nxt_conn_t *c,
8162Sigor@sysoev.ru                                       nxt_iobuf_t *iob, nxt_uint_t niob);
8262Sigor@sysoev.ru     /*
8362Sigor@sysoev.ru      * The send() is an interface to write a single buffer.  SSL/TLS
8462Sigor@sysoev.ru      * libraries' send() interface handles also the libraries' errors.
8562Sigor@sysoev.ru      */
8662Sigor@sysoev.ru     ssize_t                       (*send)(nxt_conn_t *c, void *buf,
8762Sigor@sysoev.ru                                       size_t size);
8862Sigor@sysoev.ru 
8962Sigor@sysoev.ru     nxt_work_handler_t            shutdown;
9062Sigor@sysoev.ru } nxt_conn_io_t;
9162Sigor@sysoev.ru 
9262Sigor@sysoev.ru 
9362Sigor@sysoev.ru /*
9462Sigor@sysoev.ru  * The nxt_listen_event_t is separated from nxt_listen_socket_t
9562Sigor@sysoev.ru  * because nxt_listen_socket_t is one per process whilst each worker
9662Sigor@sysoev.ru  * thread uses own nxt_listen_event_t.
9762Sigor@sysoev.ru  */
9862Sigor@sysoev.ru typedef struct {
9962Sigor@sysoev.ru     /* Must be the first field. */
10062Sigor@sysoev.ru     nxt_fd_event_t                socket;
10162Sigor@sysoev.ru 
10262Sigor@sysoev.ru     nxt_task_t                    task;
10362Sigor@sysoev.ru 
10462Sigor@sysoev.ru     uint32_t                      ready;
10562Sigor@sysoev.ru     uint32_t                      batch;
10662Sigor@sysoev.ru 
10762Sigor@sysoev.ru     /* An accept() interface is cached to minimize memory accesses. */
10862Sigor@sysoev.ru     nxt_work_handler_t            accept;
10962Sigor@sysoev.ru 
11062Sigor@sysoev.ru     nxt_listen_socket_t           *listen;
11193Smax.romanov@nginx.com     nxt_conn_t                    *next;   /* STUB */
11262Sigor@sysoev.ru     nxt_work_queue_t              *work_queue;
11362Sigor@sysoev.ru 
11462Sigor@sysoev.ru     nxt_timer_t                   timer;
11562Sigor@sysoev.ru 
11662Sigor@sysoev.ru     nxt_queue_link_t              link;
11762Sigor@sysoev.ru } nxt_listen_event_t;
11862Sigor@sysoev.ru 
11962Sigor@sysoev.ru 
12062Sigor@sysoev.ru struct nxt_conn_s {
12162Sigor@sysoev.ru     /*
12262Sigor@sysoev.ru      * Must be the first field, since nxt_fd_event_t
12362Sigor@sysoev.ru      * and nxt_conn_t are used interchangeably.
12462Sigor@sysoev.ru      */
12562Sigor@sysoev.ru     nxt_fd_event_t                socket;
12662Sigor@sysoev.ru 
12762Sigor@sysoev.ru     nxt_buf_t                     *read;
12862Sigor@sysoev.ru     const nxt_conn_state_t        *read_state;
12962Sigor@sysoev.ru     nxt_work_queue_t              *read_work_queue;
13062Sigor@sysoev.ru     nxt_timer_t                   read_timer;
13162Sigor@sysoev.ru 
13262Sigor@sysoev.ru     nxt_buf_t                     *write;
13362Sigor@sysoev.ru     const nxt_conn_state_t        *write_state;
13462Sigor@sysoev.ru     nxt_work_queue_t              *write_work_queue;
13562Sigor@sysoev.ru     nxt_event_write_rate_t        *rate;
13662Sigor@sysoev.ru     nxt_timer_t                   write_timer;
13762Sigor@sysoev.ru 
13862Sigor@sysoev.ru     nxt_off_t                     sent;
13962Sigor@sysoev.ru     uint32_t                      max_chunk;
14062Sigor@sysoev.ru     uint32_t                      nbytes;
14162Sigor@sysoev.ru 
14262Sigor@sysoev.ru     nxt_conn_io_t                 *io;
14362Sigor@sysoev.ru 
14488Smax.romanov@nginx.com     nxt_queue_t                   requests; /* of nxt_req_conn_link_t */
14588Smax.romanov@nginx.com 
14662Sigor@sysoev.ru     union {
14762Sigor@sysoev.ru #if (NXT_SSLTLS)
14862Sigor@sysoev.ru         void                      *ssltls;
14962Sigor@sysoev.ru #endif
15062Sigor@sysoev.ru         nxt_thread_pool_t         *thread_pool;
15162Sigor@sysoev.ru     } u;
15262Sigor@sysoev.ru 
15365Sigor@sysoev.ru     nxt_mp_t                      *mem_pool;
15462Sigor@sysoev.ru 
15562Sigor@sysoev.ru     nxt_task_t                    task;
15662Sigor@sysoev.ru     nxt_log_t                     log;
15762Sigor@sysoev.ru 
158*359Sigor@sysoev.ru     /* STUB: socket.data should be used later. */
159*359Sigor@sysoev.ru     void                          *joint;
160*359Sigor@sysoev.ru 
16162Sigor@sysoev.ru     nxt_sockaddr_t                *remote;
16262Sigor@sysoev.ru     nxt_sockaddr_t                *local;
16362Sigor@sysoev.ru     const char                    *action;
16462Sigor@sysoev.ru 
16562Sigor@sysoev.ru     uint8_t                       peek;
16662Sigor@sysoev.ru     uint8_t                       blocked;      /* 1 bit */
16762Sigor@sysoev.ru     uint8_t                       delayed;      /* 1 bit */
16862Sigor@sysoev.ru 
16962Sigor@sysoev.ru #define NXT_CONN_SENDFILE_OFF     0
17062Sigor@sysoev.ru #define NXT_CONN_SENDFILE_ON      1
17162Sigor@sysoev.ru #define NXT_CONN_SENDFILE_UNSET   3
17262Sigor@sysoev.ru 
17362Sigor@sysoev.ru     uint8_t                       sendfile;     /* 2 bits */
17462Sigor@sysoev.ru     uint8_t                       tcp_nodelay;  /* 1 bit */
17562Sigor@sysoev.ru 
17662Sigor@sysoev.ru     nxt_queue_link_t              link;
17762Sigor@sysoev.ru };
17862Sigor@sysoev.ru 
17962Sigor@sysoev.ru 
18062Sigor@sysoev.ru #define nxt_conn_timer_init(ev, c, wq)                                        \
18162Sigor@sysoev.ru     do {                                                                      \
18262Sigor@sysoev.ru         (ev)->work_queue = (wq);                                              \
18362Sigor@sysoev.ru         (ev)->log = &(c)->log;                                                \
18462Sigor@sysoev.ru         (ev)->precision = NXT_TIMER_DEFAULT_PRECISION;                        \
18562Sigor@sysoev.ru     } while (0)
18662Sigor@sysoev.ru 
18762Sigor@sysoev.ru 
18862Sigor@sysoev.ru #define nxt_read_timer_conn(ev)                                               \
18962Sigor@sysoev.ru     nxt_timer_data(ev, nxt_conn_t, read_timer)
19062Sigor@sysoev.ru 
19162Sigor@sysoev.ru 
19262Sigor@sysoev.ru #define nxt_write_timer_conn(ev)                                              \
19362Sigor@sysoev.ru     nxt_timer_data(ev, nxt_conn_t, write_timer)
19462Sigor@sysoev.ru 
19562Sigor@sysoev.ru 
19662Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
19762Sigor@sysoev.ru 
19862Sigor@sysoev.ru #define nxt_conn_tcp_nodelay_on(task, c)                                      \
19962Sigor@sysoev.ru     do {                                                                      \
20062Sigor@sysoev.ru         nxt_int_t  ret;                                                       \
20162Sigor@sysoev.ru                                                                               \
20262Sigor@sysoev.ru         if ((c)->remote->u.sockaddr.sa_family != AF_UNIX) {                   \
20362Sigor@sysoev.ru             ret = nxt_socket_setsockopt(task, (c)->socket.fd, IPPROTO_TCP,    \
20462Sigor@sysoev.ru                                         TCP_NODELAY, 1);                      \
20562Sigor@sysoev.ru                                                                               \
20662Sigor@sysoev.ru             (c)->tcp_nodelay = (ret == NXT_OK);                               \
20762Sigor@sysoev.ru         }                                                                     \
20862Sigor@sysoev.ru     } while (0)
20962Sigor@sysoev.ru 
21062Sigor@sysoev.ru 
21162Sigor@sysoev.ru #else
21262Sigor@sysoev.ru 
21362Sigor@sysoev.ru #define nxt_conn_tcp_nodelay_on(task, c)                                      \
21462Sigor@sysoev.ru     do {                                                                      \
21562Sigor@sysoev.ru         nxt_int_t  ret;                                                       \
21662Sigor@sysoev.ru                                                                               \
21762Sigor@sysoev.ru         ret = nxt_socket_setsockopt(task, (c)->socket.fd, IPPROTO_TCP,        \
21862Sigor@sysoev.ru                                     TCP_NODELAY, 1);                          \
21962Sigor@sysoev.ru                                                                               \
22062Sigor@sysoev.ru         (c)->tcp_nodelay = (ret == NXT_OK);                                   \
22162Sigor@sysoev.ru     } while (0)
22262Sigor@sysoev.ru 
22362Sigor@sysoev.ru #endif
22462Sigor@sysoev.ru 
22562Sigor@sysoev.ru 
22665Sigor@sysoev.ru NXT_EXPORT nxt_conn_t *nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task);
22762Sigor@sysoev.ru void nxt_conn_io_shutdown(nxt_task_t *task, void *obj, void *data);
22862Sigor@sysoev.ru NXT_EXPORT void nxt_conn_close(nxt_event_engine_t *engine, nxt_conn_t *c);
22962Sigor@sysoev.ru 
23062Sigor@sysoev.ru NXT_EXPORT void nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c,
23162Sigor@sysoev.ru     const nxt_conn_state_t *state, nxt_timer_t *tev);
23262Sigor@sysoev.ru NXT_EXPORT void nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq);
23362Sigor@sysoev.ru 
23462Sigor@sysoev.ru void nxt_conn_sys_socket(nxt_task_t *task, void *obj, void *data);
23562Sigor@sysoev.ru void nxt_conn_io_connect(nxt_task_t *task, void *obj, void *data);
23662Sigor@sysoev.ru nxt_int_t nxt_conn_socket(nxt_task_t *task, nxt_conn_t *c);
23762Sigor@sysoev.ru void nxt_conn_connect_test(nxt_task_t *task, void *obj, void *data);
23862Sigor@sysoev.ru void nxt_conn_connect_error(nxt_task_t *task, void *obj, void *data);
23962Sigor@sysoev.ru 
24062Sigor@sysoev.ru NXT_EXPORT nxt_listen_event_t *nxt_listen_event(nxt_task_t *task,
24162Sigor@sysoev.ru     nxt_listen_socket_t *ls);
24262Sigor@sysoev.ru void nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data);
24362Sigor@sysoev.ru NXT_EXPORT void nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev,
24462Sigor@sysoev.ru     nxt_conn_t *c);
24562Sigor@sysoev.ru void nxt_conn_accept_error(nxt_task_t *task, nxt_listen_event_t *lev,
24662Sigor@sysoev.ru     const char *accept_syscall, nxt_err_t err);
24762Sigor@sysoev.ru 
24862Sigor@sysoev.ru void nxt_conn_wait(nxt_conn_t *c);
24962Sigor@sysoev.ru 
25062Sigor@sysoev.ru void nxt_conn_io_read(nxt_task_t *task, void *obj, void *data);
25162Sigor@sysoev.ru ssize_t nxt_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b);
25262Sigor@sysoev.ru ssize_t nxt_conn_io_recv(nxt_conn_t *c, void *buf, size_t size,
25362Sigor@sysoev.ru     nxt_uint_t flags);
25462Sigor@sysoev.ru 
25562Sigor@sysoev.ru void nxt_conn_io_write(nxt_task_t *task, void *obj, void *data);
25662Sigor@sysoev.ru ssize_t nxt_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb);
25762Sigor@sysoev.ru ssize_t nxt_conn_io_writev(nxt_task_t *task, nxt_sendbuf_t *sb,
25862Sigor@sysoev.ru     nxt_iobuf_t *iob, nxt_uint_t niob);
25962Sigor@sysoev.ru ssize_t nxt_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, void *buf,
26062Sigor@sysoev.ru     size_t size);
26162Sigor@sysoev.ru 
26262Sigor@sysoev.ru size_t nxt_event_conn_write_limit(nxt_conn_t *c);
26362Sigor@sysoev.ru nxt_bool_t nxt_event_conn_write_delayed(nxt_event_engine_t *engine,
26462Sigor@sysoev.ru     nxt_conn_t *c, size_t sent);
26562Sigor@sysoev.ru ssize_t nxt_event_conn_io_write_chunk(nxt_conn_t *c, nxt_buf_t *b,
26662Sigor@sysoev.ru     size_t limit);
26762Sigor@sysoev.ru ssize_t nxt_event_conn_io_writev(nxt_conn_t *c, nxt_iobuf_t *iob,
26862Sigor@sysoev.ru     nxt_uint_t niob);
26962Sigor@sysoev.ru ssize_t nxt_event_conn_io_send(nxt_conn_t *c, void *buf, size_t size);
27062Sigor@sysoev.ru 
27162Sigor@sysoev.ru NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task,
27262Sigor@sysoev.ru     nxt_conn_t *c);
27362Sigor@sysoev.ru 
27462Sigor@sysoev.ru 
27562Sigor@sysoev.ru #define nxt_conn_connect(engine, c)                                           \
27662Sigor@sysoev.ru     nxt_work_queue_add(&engine->socket_work_queue, nxt_conn_sys_socket,       \
27762Sigor@sysoev.ru                        c->socket.task, c, c->socket.data)
27862Sigor@sysoev.ru 
27962Sigor@sysoev.ru 
28062Sigor@sysoev.ru #define nxt_conn_read(engine, c)                                              \
28162Sigor@sysoev.ru     do {                                                                      \
28262Sigor@sysoev.ru         nxt_event_engine_t  *e = engine;                                      \
28362Sigor@sysoev.ru                                                                               \
28462Sigor@sysoev.ru         c->socket.read_work_queue = &e->read_work_queue;                      \
28562Sigor@sysoev.ru                                                                               \
28662Sigor@sysoev.ru         nxt_work_queue_add(&e->read_work_queue, c->io->read,                  \
28762Sigor@sysoev.ru                            c->socket.task, c, c->socket.data);                \
28862Sigor@sysoev.ru     } while (0)
28962Sigor@sysoev.ru 
29062Sigor@sysoev.ru 
29162Sigor@sysoev.ru #define nxt_conn_write(e, c)                                                  \
29262Sigor@sysoev.ru     do {                                                                      \
29362Sigor@sysoev.ru         nxt_event_engine_t  *engine = e;                                      \
29462Sigor@sysoev.ru                                                                               \
29562Sigor@sysoev.ru         c->socket.write_work_queue = &engine->write_work_queue;               \
29662Sigor@sysoev.ru                                                                               \
29762Sigor@sysoev.ru         nxt_work_queue_add(&engine->write_work_queue, c->io->write,           \
29862Sigor@sysoev.ru                            c->socket.task, c, c->socket.data);                \
29962Sigor@sysoev.ru     } while (0)
30062Sigor@sysoev.ru 
30162Sigor@sysoev.ru 
30262Sigor@sysoev.ru extern nxt_conn_io_t             nxt_unix_conn_io;
30362Sigor@sysoev.ru 
30462Sigor@sysoev.ru 
30562Sigor@sysoev.ru typedef struct {
30662Sigor@sysoev.ru     /*
30762Sigor@sysoev.ru      * Client and peer connections are not embedded because already
30862Sigor@sysoev.ru      * existent connections can be switched to the event connection proxy.
30962Sigor@sysoev.ru      */
31062Sigor@sysoev.ru     nxt_conn_t                   *client;
31162Sigor@sysoev.ru     nxt_conn_t                   *peer;
31262Sigor@sysoev.ru     nxt_buf_t                    *client_buffer;
31362Sigor@sysoev.ru     nxt_buf_t                    *peer_buffer;
31462Sigor@sysoev.ru 
31562Sigor@sysoev.ru     size_t                       client_buffer_size;
31662Sigor@sysoev.ru     size_t                       peer_buffer_size;
31762Sigor@sysoev.ru 
31862Sigor@sysoev.ru     nxt_msec_t                   client_wait_timeout;
31962Sigor@sysoev.ru     nxt_msec_t                   connect_timeout;
32062Sigor@sysoev.ru     nxt_msec_t                   reconnect_timeout;
32162Sigor@sysoev.ru     nxt_msec_t                   peer_wait_timeout;
32262Sigor@sysoev.ru     nxt_msec_t                   client_write_timeout;
32362Sigor@sysoev.ru     nxt_msec_t                   peer_write_timeout;
32462Sigor@sysoev.ru 
32562Sigor@sysoev.ru     uint8_t                      connected;  /* 1 bit */
32662Sigor@sysoev.ru     uint8_t                      delayed;    /* 1 bit */
32762Sigor@sysoev.ru     uint8_t                      retries;    /* 8 bits */
32862Sigor@sysoev.ru     uint8_t                      retain;     /* 2 bits */
32962Sigor@sysoev.ru 
33062Sigor@sysoev.ru     nxt_work_handler_t           completion_handler;
33162Sigor@sysoev.ru } nxt_conn_proxy_t;
33262Sigor@sysoev.ru 
33362Sigor@sysoev.ru 
33462Sigor@sysoev.ru NXT_EXPORT nxt_conn_proxy_t *nxt_conn_proxy_create(nxt_conn_t *c);
33562Sigor@sysoev.ru NXT_EXPORT void nxt_conn_proxy(nxt_task_t *task, nxt_conn_proxy_t *p);
33662Sigor@sysoev.ru 
33762Sigor@sysoev.ru 
33862Sigor@sysoev.ru /* STUB */
33962Sigor@sysoev.ru #define nxt_event_conn_t         nxt_conn_t
34062Sigor@sysoev.ru #define nxt_event_conn_state_t   nxt_conn_state_t
34162Sigor@sysoev.ru #define nxt_event_conn_proxy_t   nxt_conn_proxy_t
34262Sigor@sysoev.ru #define nxt_event_conn_read      nxt_conn_read
34362Sigor@sysoev.ru #define nxt_event_conn_write     nxt_conn_write
34462Sigor@sysoev.ru #define nxt_event_conn_close     nxt_conn_close
34562Sigor@sysoev.ru 
34662Sigor@sysoev.ru 
34762Sigor@sysoev.ru #endif /* _NXT_CONN_H_INCLUDED_ */
348