static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) { uv_loop_t *loop = handle->loop; struct session *s = handle->data; struct worker_ctx *worker = loop->data; /* TCP pipelining is rather complicated and requires cooperation from the worker * so the whole message reassembly and demuxing logic is inside worker */ int ret = 0; if (s->has_tls) { ret = tls_process(worker, handle, (const uint8_t *)buf->base, nread); } else { ret = worker_process_tcp(worker, handle, (const uint8_t *)buf->base, nread); } if (ret < 0) { worker_end_tcp(worker, (uv_handle_t *)handle); /* Exceeded per-connection quota for outstanding requests * stop reading from stream and close after last message is processed. */ if (!s->outgoing && !uv_is_closing((uv_handle_t *)&s->timeout)) { uv_timer_stop(&s->timeout); if (s->tasks.len == 0) { uv_close((uv_handle_t *)&s->timeout, tcp_timeout); } else { /* If there are tasks running, defer until they finish. */ uv_timer_start(&s->timeout, tcp_timeout_trigger, 1, KR_CONN_RTT_MAX/2); } } /* Connection spawned more than one request, reset its deadline for next query. */ } else if (ret > 0 && !s->outgoing) { uv_timer_again(&s->timeout); } mp_flush(worker->pkt_pool.ctx); }
static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) { uv_loop_t *loop = handle->loop; struct worker_ctx *worker = loop->data; /* Check for originator connection close. */ if (nread <= 0) { if (handle->data) { worker_exec(worker, (uv_handle_t *)handle, NULL, NULL); } if (!uv_is_closing((uv_handle_t *)handle)) { uv_close((uv_handle_t *)handle, handle_free); } return; } int ret = worker_process_tcp(worker, (uv_handle_t *)handle, (const uint8_t *)buf->base, nread); if (ret == 0) { /* Push - pull, stop reading from this handle until * the task is finished. Since the handle has no track of the * pending tasks, it might be freed before the task finishes * leading various errors. */ uv_unref((uv_handle_t *)handle); io_stop_read((uv_handle_t *)handle); } mp_flush(worker->pkt_pool.ctx); }