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 #include <nxt_main.h> 862Sigor@sysoev.ru 962Sigor@sysoev.ru 1062Sigor@sysoev.ru nxt_conn_io_t nxt_unix_conn_io = { 1162Sigor@sysoev.ru nxt_conn_io_connect, 1262Sigor@sysoev.ru nxt_conn_io_accept, 1362Sigor@sysoev.ru 1462Sigor@sysoev.ru nxt_conn_io_read, 1562Sigor@sysoev.ru nxt_conn_io_recvbuf, 1662Sigor@sysoev.ru nxt_conn_io_recv, 1762Sigor@sysoev.ru 1862Sigor@sysoev.ru nxt_conn_io_write, 1962Sigor@sysoev.ru nxt_event_conn_io_write_chunk, 2062Sigor@sysoev.ru 2162Sigor@sysoev.ru #if (NXT_HAVE_LINUX_SENDFILE) 2262Sigor@sysoev.ru nxt_linux_event_conn_io_sendfile, 2362Sigor@sysoev.ru #elif (NXT_HAVE_FREEBSD_SENDFILE) 2462Sigor@sysoev.ru nxt_freebsd_event_conn_io_sendfile, 2562Sigor@sysoev.ru #elif (NXT_HAVE_MACOSX_SENDFILE) 2662Sigor@sysoev.ru nxt_macosx_event_conn_io_sendfile, 2762Sigor@sysoev.ru #elif (NXT_HAVE_SOLARIS_SENDFILEV) 2862Sigor@sysoev.ru nxt_solaris_event_conn_io_sendfilev, 2962Sigor@sysoev.ru #elif (NXT_HAVE_AIX_SEND_FILE) 3062Sigor@sysoev.ru nxt_aix_event_conn_io_send_file, 3162Sigor@sysoev.ru #elif (NXT_HAVE_HPUX_SENDFILE) 3262Sigor@sysoev.ru nxt_hpux_event_conn_io_sendfile, 3362Sigor@sysoev.ru #else 3462Sigor@sysoev.ru nxt_event_conn_io_sendbuf, 3562Sigor@sysoev.ru #endif 3662Sigor@sysoev.ru 3762Sigor@sysoev.ru nxt_event_conn_io_writev, 3862Sigor@sysoev.ru nxt_event_conn_io_send, 3962Sigor@sysoev.ru 4062Sigor@sysoev.ru nxt_conn_io_shutdown, 4162Sigor@sysoev.ru }; 4262Sigor@sysoev.ru 4362Sigor@sysoev.ru 4462Sigor@sysoev.ru nxt_conn_t * 45*65Sigor@sysoev.ru nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task) 4662Sigor@sysoev.ru { 4762Sigor@sysoev.ru nxt_conn_t *c; 4862Sigor@sysoev.ru nxt_thread_t *thr; 4962Sigor@sysoev.ru 50*65Sigor@sysoev.ru c = nxt_mp_zget(mp, sizeof(nxt_conn_t)); 5162Sigor@sysoev.ru if (nxt_slow_path(c == NULL)) { 5262Sigor@sysoev.ru return NULL; 5362Sigor@sysoev.ru } 5462Sigor@sysoev.ru 5562Sigor@sysoev.ru c->mem_pool = mp; 5662Sigor@sysoev.ru 5762Sigor@sysoev.ru c->socket.fd = -1; 5862Sigor@sysoev.ru 5962Sigor@sysoev.ru c->socket.log = &c->log; 6062Sigor@sysoev.ru c->log = *task->log; 6162Sigor@sysoev.ru 6262Sigor@sysoev.ru /* The while loop skips possible uint32_t overflow. */ 6362Sigor@sysoev.ru 6462Sigor@sysoev.ru while (c->log.ident == 0) { 6562Sigor@sysoev.ru c->log.ident = nxt_task_next_ident(); 6662Sigor@sysoev.ru } 6762Sigor@sysoev.ru 6862Sigor@sysoev.ru thr = nxt_thread(); 6962Sigor@sysoev.ru thr->engine->connections++; 7062Sigor@sysoev.ru 7162Sigor@sysoev.ru c->task.thread = thr; 7262Sigor@sysoev.ru c->task.log = &c->log; 7362Sigor@sysoev.ru c->task.ident = c->log.ident; 7462Sigor@sysoev.ru c->socket.task = &c->task; 7562Sigor@sysoev.ru c->read_timer.task = &c->task; 7662Sigor@sysoev.ru c->write_timer.task = &c->task; 7762Sigor@sysoev.ru 7862Sigor@sysoev.ru c->io = thr->engine->event.io; 7962Sigor@sysoev.ru c->max_chunk = NXT_INT32_T_MAX; 8062Sigor@sysoev.ru c->sendfile = NXT_CONN_SENDFILE_UNSET; 8162Sigor@sysoev.ru 8262Sigor@sysoev.ru c->socket.read_work_queue = &thr->engine->fast_work_queue; 8362Sigor@sysoev.ru c->socket.write_work_queue = &thr->engine->fast_work_queue; 8462Sigor@sysoev.ru 8562Sigor@sysoev.ru nxt_conn_timer_init(&c->read_timer, c, c->socket.read_work_queue); 8662Sigor@sysoev.ru nxt_conn_timer_init(&c->write_timer, c, c->socket.write_work_queue); 8762Sigor@sysoev.ru 8862Sigor@sysoev.ru nxt_log_debug(&c->log, "connections: %uD", thr->engine->connections); 8962Sigor@sysoev.ru 9062Sigor@sysoev.ru return c; 9162Sigor@sysoev.ru } 9262Sigor@sysoev.ru 9362Sigor@sysoev.ru 9462Sigor@sysoev.ru void 9562Sigor@sysoev.ru nxt_conn_io_shutdown(nxt_task_t *task, void *obj, void *data) 9662Sigor@sysoev.ru { 9762Sigor@sysoev.ru int ret; 9862Sigor@sysoev.ru socklen_t len; 9962Sigor@sysoev.ru nxt_conn_t *c; 10062Sigor@sysoev.ru struct linger linger; 10162Sigor@sysoev.ru 10262Sigor@sysoev.ru c = obj; 10362Sigor@sysoev.ru 10462Sigor@sysoev.ru nxt_debug(task, "event conn shutdown"); 10562Sigor@sysoev.ru 10662Sigor@sysoev.ru if (c->socket.timedout) { 10762Sigor@sysoev.ru /* 10862Sigor@sysoev.ru * Resetting of timed out connection on close 10962Sigor@sysoev.ru * releases kernel memory associated with socket. 11062Sigor@sysoev.ru * This also causes sending TCP/IP RST to a peer. 11162Sigor@sysoev.ru */ 11262Sigor@sysoev.ru linger.l_onoff = 1; 11362Sigor@sysoev.ru linger.l_linger = 0; 11462Sigor@sysoev.ru len = sizeof(struct linger); 11562Sigor@sysoev.ru 11662Sigor@sysoev.ru ret = setsockopt(c->socket.fd, SOL_SOCKET, SO_LINGER, &linger, len); 11762Sigor@sysoev.ru 11862Sigor@sysoev.ru if (nxt_slow_path(ret != 0)) { 11962Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "setsockopt(%d, SO_LINGER) failed %E", 12062Sigor@sysoev.ru c->socket.fd, nxt_socket_errno); 12162Sigor@sysoev.ru } 12262Sigor@sysoev.ru } 12362Sigor@sysoev.ru 12462Sigor@sysoev.ru c->write_state->close_handler(task, c, data); 12562Sigor@sysoev.ru } 12662Sigor@sysoev.ru 12762Sigor@sysoev.ru 12862Sigor@sysoev.ru void 12962Sigor@sysoev.ru nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c, 13062Sigor@sysoev.ru const nxt_conn_state_t *state, nxt_timer_t *timer) 13162Sigor@sysoev.ru { 13262Sigor@sysoev.ru nxt_msec_t value; 13362Sigor@sysoev.ru 13462Sigor@sysoev.ru if (state->timer_value != NULL) { 13562Sigor@sysoev.ru value = state->timer_value(c, state->timer_data); 13662Sigor@sysoev.ru 13762Sigor@sysoev.ru if (value != 0) { 13862Sigor@sysoev.ru timer->handler = state->timer_handler; 13962Sigor@sysoev.ru nxt_timer_add(engine, timer, value); 14062Sigor@sysoev.ru } 14162Sigor@sysoev.ru } 14262Sigor@sysoev.ru } 14362Sigor@sysoev.ru 14462Sigor@sysoev.ru 14562Sigor@sysoev.ru void 14662Sigor@sysoev.ru nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq) 14762Sigor@sysoev.ru { 14862Sigor@sysoev.ru c->read_work_queue = wq; 14962Sigor@sysoev.ru c->write_work_queue = wq; 15062Sigor@sysoev.ru c->read_timer.work_queue = wq; 15162Sigor@sysoev.ru c->write_timer.work_queue = wq; 15262Sigor@sysoev.ru } 153