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 111268Sigor@sysoev.ru typedef ssize_t (*nxt_conn_io_read_t)(nxt_task_t *task, nxt_conn_t *c); 1262Sigor@sysoev.ru typedef nxt_msec_t (*nxt_conn_timer_value_t)(nxt_conn_t *c, uintptr_t data); 1362Sigor@sysoev.ru 1462Sigor@sysoev.ru 1562Sigor@sysoev.ru typedef struct { 1662Sigor@sysoev.ru nxt_work_handler_t ready_handler; 1762Sigor@sysoev.ru nxt_work_handler_t close_handler; 1862Sigor@sysoev.ru nxt_work_handler_t error_handler; 1962Sigor@sysoev.ru 20629Sigor@sysoev.ru nxt_conn_io_read_t io_read_handler; 21629Sigor@sysoev.ru 2262Sigor@sysoev.ru nxt_work_handler_t timer_handler; 2362Sigor@sysoev.ru nxt_conn_timer_value_t timer_value; 2462Sigor@sysoev.ru uintptr_t timer_data; 2562Sigor@sysoev.ru 2662Sigor@sysoev.ru uint8_t timer_autoreset; 2762Sigor@sysoev.ru } nxt_conn_state_t; 2862Sigor@sysoev.ru 2962Sigor@sysoev.ru 3062Sigor@sysoev.ru typedef struct { 3162Sigor@sysoev.ru double average; 3262Sigor@sysoev.ru size_t limit; 3362Sigor@sysoev.ru size_t limit_after; 3462Sigor@sysoev.ru size_t max_limit; 3562Sigor@sysoev.ru nxt_msec_t last; 3662Sigor@sysoev.ru } nxt_event_write_rate_t; 3762Sigor@sysoev.ru 3862Sigor@sysoev.ru 3962Sigor@sysoev.ru typedef struct { 4062Sigor@sysoev.ru 4162Sigor@sysoev.ru nxt_work_handler_t connect; 4262Sigor@sysoev.ru nxt_work_handler_t accept; 4362Sigor@sysoev.ru 4462Sigor@sysoev.ru /* 4562Sigor@sysoev.ru * The read() with NULL c->read buffer waits readiness of a connection 4662Sigor@sysoev.ru * to avoid allocation of read buffer if the connection will time out 4762Sigor@sysoev.ru * or will be closed with error. The kqueue-specific read() can also 4862Sigor@sysoev.ru * detect case if a client did not sent anything and has just closed the 4962Sigor@sysoev.ru * connection without errors. In the latter case state's close_handler 5062Sigor@sysoev.ru * is called. 5162Sigor@sysoev.ru */ 5262Sigor@sysoev.ru nxt_work_handler_t read; 5362Sigor@sysoev.ru 5462Sigor@sysoev.ru ssize_t (*recvbuf)(nxt_conn_t *c, nxt_buf_t *b); 5562Sigor@sysoev.ru 5662Sigor@sysoev.ru ssize_t (*recv)(nxt_conn_t *c, void *buf, 5762Sigor@sysoev.ru size_t size, nxt_uint_t flags); 5862Sigor@sysoev.ru 59771Sigor@sysoev.ru /* The write() is an interface to write a buffer chain. */ 6062Sigor@sysoev.ru nxt_work_handler_t write; 6162Sigor@sysoev.ru 6262Sigor@sysoev.ru /* 6362Sigor@sysoev.ru * The sendbuf() is an interface for OS-specific sendfile 6462Sigor@sysoev.ru * implementations or simple writev(). 6562Sigor@sysoev.ru */ 66771Sigor@sysoev.ru ssize_t (*sendbuf)(nxt_task_t *task, 67771Sigor@sysoev.ru nxt_sendbuf_t *sb); 68771Sigor@sysoev.ru /* 69771Sigor@sysoev.ru * The sendbuf() is an interface for OS-specific sendfile 70771Sigor@sysoev.ru * implementations or simple writev(). 71771Sigor@sysoev.ru */ 72771Sigor@sysoev.ru ssize_t (*old_sendbuf)(nxt_conn_t *c, nxt_buf_t *b, 7362Sigor@sysoev.ru size_t limit); 7462Sigor@sysoev.ru /* 7562Sigor@sysoev.ru * The writev() is an interface to write several nxt_iobuf_t buffers. 7662Sigor@sysoev.ru */ 7762Sigor@sysoev.ru ssize_t (*writev)(nxt_conn_t *c, 7862Sigor@sysoev.ru nxt_iobuf_t *iob, nxt_uint_t niob); 7962Sigor@sysoev.ru /* 8062Sigor@sysoev.ru * The send() is an interface to write a single buffer. SSL/TLS 8162Sigor@sysoev.ru * libraries' send() interface handles also the libraries' errors. 8262Sigor@sysoev.ru */ 8362Sigor@sysoev.ru ssize_t (*send)(nxt_conn_t *c, void *buf, 8462Sigor@sysoev.ru size_t size); 8562Sigor@sysoev.ru 8662Sigor@sysoev.ru nxt_work_handler_t shutdown; 8762Sigor@sysoev.ru } nxt_conn_io_t; 8862Sigor@sysoev.ru 8962Sigor@sysoev.ru 9062Sigor@sysoev.ru /* 9162Sigor@sysoev.ru * The nxt_listen_event_t is separated from nxt_listen_socket_t 9262Sigor@sysoev.ru * because nxt_listen_socket_t is one per process whilst each worker 9362Sigor@sysoev.ru * thread uses own nxt_listen_event_t. 9462Sigor@sysoev.ru */ 9562Sigor@sysoev.ru typedef struct { 9662Sigor@sysoev.ru /* Must be the first field. */ 9762Sigor@sysoev.ru nxt_fd_event_t socket; 9862Sigor@sysoev.ru 9962Sigor@sysoev.ru nxt_task_t task; 10062Sigor@sysoev.ru 10162Sigor@sysoev.ru uint32_t ready; 10262Sigor@sysoev.ru uint32_t batch; 103683Sigor@sysoev.ru uint32_t count; 10462Sigor@sysoev.ru 10562Sigor@sysoev.ru /* An accept() interface is cached to minimize memory accesses. */ 10662Sigor@sysoev.ru nxt_work_handler_t accept; 10762Sigor@sysoev.ru 10862Sigor@sysoev.ru nxt_listen_socket_t *listen; 1091458Sigor@sysoev.ru nxt_conn_t *next; 11062Sigor@sysoev.ru nxt_work_queue_t *work_queue; 11162Sigor@sysoev.ru 11262Sigor@sysoev.ru nxt_timer_t timer; 11362Sigor@sysoev.ru 11462Sigor@sysoev.ru nxt_queue_link_t link; 11562Sigor@sysoev.ru } nxt_listen_event_t; 11662Sigor@sysoev.ru 11762Sigor@sysoev.ru 11862Sigor@sysoev.ru struct nxt_conn_s { 11962Sigor@sysoev.ru /* 12062Sigor@sysoev.ru * Must be the first field, since nxt_fd_event_t 12162Sigor@sysoev.ru * and nxt_conn_t are used interchangeably. 12262Sigor@sysoev.ru */ 12362Sigor@sysoev.ru nxt_fd_event_t socket; 12462Sigor@sysoev.ru 12562Sigor@sysoev.ru nxt_buf_t *read; 12662Sigor@sysoev.ru const nxt_conn_state_t *read_state; 12762Sigor@sysoev.ru nxt_work_queue_t *read_work_queue; 12862Sigor@sysoev.ru nxt_timer_t read_timer; 12962Sigor@sysoev.ru 13062Sigor@sysoev.ru nxt_buf_t *write; 13162Sigor@sysoev.ru const nxt_conn_state_t *write_state; 13262Sigor@sysoev.ru nxt_work_queue_t *write_work_queue; 13362Sigor@sysoev.ru nxt_event_write_rate_t *rate; 13462Sigor@sysoev.ru nxt_timer_t write_timer; 13562Sigor@sysoev.ru 13662Sigor@sysoev.ru nxt_off_t sent; 13762Sigor@sysoev.ru uint32_t max_chunk; 13862Sigor@sysoev.ru uint32_t nbytes; 13962Sigor@sysoev.ru 14062Sigor@sysoev.ru nxt_conn_io_t *io; 14162Sigor@sysoev.ru 14262Sigor@sysoev.ru union { 143771Sigor@sysoev.ru #if (NXT_TLS) 144771Sigor@sysoev.ru void *tls; 14562Sigor@sysoev.ru #endif 14662Sigor@sysoev.ru nxt_thread_pool_t *thread_pool; 14762Sigor@sysoev.ru } u; 14862Sigor@sysoev.ru 14965Sigor@sysoev.ru nxt_mp_t *mem_pool; 15062Sigor@sysoev.ru 15162Sigor@sysoev.ru nxt_task_t task; 15262Sigor@sysoev.ru nxt_log_t log; 15362Sigor@sysoev.ru 154683Sigor@sysoev.ru nxt_listen_event_t *listen; 155359Sigor@sysoev.ru 15662Sigor@sysoev.ru nxt_sockaddr_t *remote; 15762Sigor@sysoev.ru nxt_sockaddr_t *local; 15862Sigor@sysoev.ru const char *action; 15962Sigor@sysoev.ru 160979Sigor@sysoev.ru uint8_t block_read; /* 1 bit */ 161979Sigor@sysoev.ru uint8_t block_write; /* 1 bit */ 16262Sigor@sysoev.ru uint8_t delayed; /* 1 bit */ 1632185Svbart@nginx.com uint8_t idle; /* 1 bit */ 16462Sigor@sysoev.ru 16562Sigor@sysoev.ru #define NXT_CONN_SENDFILE_OFF 0 16662Sigor@sysoev.ru #define NXT_CONN_SENDFILE_ON 1 16762Sigor@sysoev.ru #define NXT_CONN_SENDFILE_UNSET 3 16862Sigor@sysoev.ru 16962Sigor@sysoev.ru uint8_t sendfile; /* 2 bits */ 17062Sigor@sysoev.ru uint8_t tcp_nodelay; /* 1 bit */ 17162Sigor@sysoev.ru 17262Sigor@sysoev.ru nxt_queue_link_t link; 17362Sigor@sysoev.ru }; 17462Sigor@sysoev.ru 17562Sigor@sysoev.ru 17662Sigor@sysoev.ru #define nxt_conn_timer_init(ev, c, wq) \ 17762Sigor@sysoev.ru do { \ 17862Sigor@sysoev.ru (ev)->work_queue = (wq); \ 17962Sigor@sysoev.ru (ev)->log = &(c)->log; \ 180811Svbart@nginx.com (ev)->bias = NXT_TIMER_DEFAULT_BIAS; \ 18162Sigor@sysoev.ru } while (0) 18262Sigor@sysoev.ru 18362Sigor@sysoev.ru 18462Sigor@sysoev.ru #define nxt_read_timer_conn(ev) \ 18562Sigor@sysoev.ru nxt_timer_data(ev, nxt_conn_t, read_timer) 18662Sigor@sysoev.ru 18762Sigor@sysoev.ru 18862Sigor@sysoev.ru #define nxt_write_timer_conn(ev) \ 18962Sigor@sysoev.ru nxt_timer_data(ev, nxt_conn_t, write_timer) 19062Sigor@sysoev.ru 19162Sigor@sysoev.ru 19262Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 19362Sigor@sysoev.ru 19462Sigor@sysoev.ru #define nxt_conn_tcp_nodelay_on(task, c) \ 19562Sigor@sysoev.ru do { \ 19662Sigor@sysoev.ru nxt_int_t ret; \ 19762Sigor@sysoev.ru \ 19862Sigor@sysoev.ru if ((c)->remote->u.sockaddr.sa_family != AF_UNIX) { \ 19962Sigor@sysoev.ru ret = nxt_socket_setsockopt(task, (c)->socket.fd, IPPROTO_TCP, \ 20062Sigor@sysoev.ru TCP_NODELAY, 1); \ 20162Sigor@sysoev.ru \ 20262Sigor@sysoev.ru (c)->tcp_nodelay = (ret == NXT_OK); \ 20362Sigor@sysoev.ru } \ 20462Sigor@sysoev.ru } while (0) 20562Sigor@sysoev.ru 20662Sigor@sysoev.ru 20762Sigor@sysoev.ru #else 20862Sigor@sysoev.ru 20962Sigor@sysoev.ru #define nxt_conn_tcp_nodelay_on(task, c) \ 21062Sigor@sysoev.ru do { \ 21162Sigor@sysoev.ru nxt_int_t ret; \ 21262Sigor@sysoev.ru \ 21362Sigor@sysoev.ru ret = nxt_socket_setsockopt(task, (c)->socket.fd, IPPROTO_TCP, \ 21462Sigor@sysoev.ru TCP_NODELAY, 1); \ 21562Sigor@sysoev.ru \ 21662Sigor@sysoev.ru (c)->tcp_nodelay = (ret == NXT_OK); \ 21762Sigor@sysoev.ru } while (0) 21862Sigor@sysoev.ru 21962Sigor@sysoev.ru #endif 22062Sigor@sysoev.ru 22162Sigor@sysoev.ru 22265Sigor@sysoev.ru NXT_EXPORT nxt_conn_t *nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task); 223386Sigor@sysoev.ru NXT_EXPORT void nxt_conn_free(nxt_task_t *task, nxt_conn_t *c); 22462Sigor@sysoev.ru NXT_EXPORT void nxt_conn_close(nxt_event_engine_t *engine, nxt_conn_t *c); 22562Sigor@sysoev.ru 22662Sigor@sysoev.ru NXT_EXPORT void nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c, 22762Sigor@sysoev.ru const nxt_conn_state_t *state, nxt_timer_t *tev); 22862Sigor@sysoev.ru NXT_EXPORT void nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq); 229431Sigor@sysoev.ru NXT_EXPORT nxt_sockaddr_t *nxt_conn_local_addr(nxt_task_t *task, 230431Sigor@sysoev.ru nxt_conn_t *c); 23162Sigor@sysoev.ru 23262Sigor@sysoev.ru void nxt_conn_sys_socket(nxt_task_t *task, void *obj, void *data); 23362Sigor@sysoev.ru void nxt_conn_io_connect(nxt_task_t *task, void *obj, void *data); 23462Sigor@sysoev.ru nxt_int_t nxt_conn_socket(nxt_task_t *task, nxt_conn_t *c); 23562Sigor@sysoev.ru void nxt_conn_connect_test(nxt_task_t *task, void *obj, void *data); 23662Sigor@sysoev.ru void nxt_conn_connect_error(nxt_task_t *task, void *obj, void *data); 23762Sigor@sysoev.ru 23862Sigor@sysoev.ru NXT_EXPORT nxt_listen_event_t *nxt_listen_event(nxt_task_t *task, 23962Sigor@sysoev.ru nxt_listen_socket_t *ls); 24062Sigor@sysoev.ru void nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data); 24162Sigor@sysoev.ru NXT_EXPORT void nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, 24262Sigor@sysoev.ru nxt_conn_t *c); 24362Sigor@sysoev.ru void nxt_conn_accept_error(nxt_task_t *task, nxt_listen_event_t *lev, 24462Sigor@sysoev.ru const char *accept_syscall, nxt_err_t err); 24562Sigor@sysoev.ru 24662Sigor@sysoev.ru void nxt_conn_wait(nxt_conn_t *c); 24762Sigor@sysoev.ru 24862Sigor@sysoev.ru void nxt_conn_io_read(nxt_task_t *task, void *obj, void *data); 24962Sigor@sysoev.ru ssize_t nxt_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b); 25062Sigor@sysoev.ru ssize_t nxt_conn_io_recv(nxt_conn_t *c, void *buf, size_t size, 25162Sigor@sysoev.ru nxt_uint_t flags); 25262Sigor@sysoev.ru 25362Sigor@sysoev.ru void nxt_conn_io_write(nxt_task_t *task, void *obj, void *data); 25462Sigor@sysoev.ru ssize_t nxt_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb); 25562Sigor@sysoev.ru ssize_t nxt_conn_io_writev(nxt_task_t *task, nxt_sendbuf_t *sb, 25662Sigor@sysoev.ru nxt_iobuf_t *iob, nxt_uint_t niob); 25762Sigor@sysoev.ru ssize_t nxt_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, void *buf, 25862Sigor@sysoev.ru size_t size); 25962Sigor@sysoev.ru 26062Sigor@sysoev.ru size_t nxt_event_conn_write_limit(nxt_conn_t *c); 26162Sigor@sysoev.ru nxt_bool_t nxt_event_conn_write_delayed(nxt_event_engine_t *engine, 26262Sigor@sysoev.ru nxt_conn_t *c, size_t sent); 26362Sigor@sysoev.ru ssize_t nxt_event_conn_io_writev(nxt_conn_t *c, nxt_iobuf_t *iob, 26462Sigor@sysoev.ru nxt_uint_t niob); 26562Sigor@sysoev.ru ssize_t nxt_event_conn_io_send(nxt_conn_t *c, void *buf, size_t size); 26662Sigor@sysoev.ru 26762Sigor@sysoev.ru NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task, 26862Sigor@sysoev.ru nxt_conn_t *c); 26962Sigor@sysoev.ru 27062Sigor@sysoev.ru 27162Sigor@sysoev.ru #define nxt_conn_connect(engine, c) \ 27262Sigor@sysoev.ru nxt_work_queue_add(&engine->socket_work_queue, nxt_conn_sys_socket, \ 27362Sigor@sysoev.ru c->socket.task, c, c->socket.data) 27462Sigor@sysoev.ru 27562Sigor@sysoev.ru 27662Sigor@sysoev.ru #define nxt_conn_read(engine, c) \ 27762Sigor@sysoev.ru do { \ 27862Sigor@sysoev.ru nxt_event_engine_t *e = engine; \ 27962Sigor@sysoev.ru \ 28062Sigor@sysoev.ru c->socket.read_work_queue = &e->read_work_queue; \ 28162Sigor@sysoev.ru \ 28262Sigor@sysoev.ru nxt_work_queue_add(&e->read_work_queue, c->io->read, \ 28362Sigor@sysoev.ru c->socket.task, c, c->socket.data); \ 28462Sigor@sysoev.ru } while (0) 28562Sigor@sysoev.ru 28662Sigor@sysoev.ru 287431Sigor@sysoev.ru #define nxt_conn_write(engine, c) \ 28862Sigor@sysoev.ru do { \ 289431Sigor@sysoev.ru nxt_event_engine_t *e = engine; \ 29062Sigor@sysoev.ru \ 291431Sigor@sysoev.ru c->socket.write_work_queue = &e->write_work_queue; \ 29262Sigor@sysoev.ru \ 293431Sigor@sysoev.ru nxt_work_queue_add(&e->write_work_queue, c->io->write, \ 29462Sigor@sysoev.ru c->socket.task, c, c->socket.data); \ 29562Sigor@sysoev.ru } while (0) 29662Sigor@sysoev.ru 29762Sigor@sysoev.ru 2982185Svbart@nginx.com #define nxt_conn_idle(engine, c) \ 2992185Svbart@nginx.com do { \ 3002185Svbart@nginx.com nxt_event_engine_t *e = engine; \ 3012185Svbart@nginx.com \ 3022185Svbart@nginx.com nxt_queue_insert_head(&e->idle_connections, &c->link); \ 3032185Svbart@nginx.com \ 3042185Svbart@nginx.com c->idle = 1; \ 3052185Svbart@nginx.com e->idle_conns_cnt++; \ 3062185Svbart@nginx.com } while (0) 3072185Svbart@nginx.com 3082185Svbart@nginx.com 3092185Svbart@nginx.com #define nxt_conn_active(engine, c) \ 3102185Svbart@nginx.com do { \ 3112185Svbart@nginx.com nxt_event_engine_t *e = engine; \ 3122185Svbart@nginx.com \ 3132185Svbart@nginx.com nxt_queue_remove(&c->link); \ 3142185Svbart@nginx.com \ 315*2204Sz.hong@f5.com e->idle_conns_cnt -= c->idle; \ 3162185Svbart@nginx.com } while (0) 3172185Svbart@nginx.com 3182185Svbart@nginx.com 31962Sigor@sysoev.ru extern nxt_conn_io_t nxt_unix_conn_io; 32062Sigor@sysoev.ru 32162Sigor@sysoev.ru 32262Sigor@sysoev.ru typedef struct { 32362Sigor@sysoev.ru /* 32462Sigor@sysoev.ru * Client and peer connections are not embedded because already 32562Sigor@sysoev.ru * existent connections can be switched to the event connection proxy. 32662Sigor@sysoev.ru */ 32762Sigor@sysoev.ru nxt_conn_t *client; 32862Sigor@sysoev.ru nxt_conn_t *peer; 32962Sigor@sysoev.ru nxt_buf_t *client_buffer; 33062Sigor@sysoev.ru nxt_buf_t *peer_buffer; 33162Sigor@sysoev.ru 33262Sigor@sysoev.ru size_t client_buffer_size; 33362Sigor@sysoev.ru size_t peer_buffer_size; 33462Sigor@sysoev.ru 33562Sigor@sysoev.ru nxt_msec_t client_wait_timeout; 33662Sigor@sysoev.ru nxt_msec_t connect_timeout; 33762Sigor@sysoev.ru nxt_msec_t reconnect_timeout; 33862Sigor@sysoev.ru nxt_msec_t peer_wait_timeout; 33962Sigor@sysoev.ru nxt_msec_t client_write_timeout; 34062Sigor@sysoev.ru nxt_msec_t peer_write_timeout; 34162Sigor@sysoev.ru 34262Sigor@sysoev.ru uint8_t connected; /* 1 bit */ 34362Sigor@sysoev.ru uint8_t delayed; /* 1 bit */ 34462Sigor@sysoev.ru uint8_t retries; /* 8 bits */ 34562Sigor@sysoev.ru uint8_t retain; /* 2 bits */ 34662Sigor@sysoev.ru 34762Sigor@sysoev.ru nxt_work_handler_t completion_handler; 34862Sigor@sysoev.ru } nxt_conn_proxy_t; 34962Sigor@sysoev.ru 35062Sigor@sysoev.ru 35162Sigor@sysoev.ru NXT_EXPORT nxt_conn_proxy_t *nxt_conn_proxy_create(nxt_conn_t *c); 35262Sigor@sysoev.ru NXT_EXPORT void nxt_conn_proxy(nxt_task_t *task, nxt_conn_proxy_t *p); 35362Sigor@sysoev.ru 35462Sigor@sysoev.ru 35562Sigor@sysoev.ru /* STUB */ 35662Sigor@sysoev.ru #define nxt_event_conn_t nxt_conn_t 35762Sigor@sysoev.ru #define nxt_event_conn_state_t nxt_conn_state_t 35862Sigor@sysoev.ru #define nxt_event_conn_proxy_t nxt_conn_proxy_t 35962Sigor@sysoev.ru #define nxt_event_conn_read nxt_conn_read 36062Sigor@sysoev.ru #define nxt_event_conn_write nxt_conn_write 36162Sigor@sysoev.ru #define nxt_event_conn_close nxt_conn_close 36262Sigor@sysoev.ru 36362Sigor@sysoev.ru 36462Sigor@sysoev.ru #endif /* _NXT_CONN_H_INCLUDED_ */ 365