Exemplo n.º 1
0
static void proxy_io_cb(liIOStream *stream, liIOStreamEvent event) {
	proxy_connection *con = stream->data;
	liWorker *wrk = li_worker_from_iostream(stream);

	li_stream_simple_socket_io_cb_with_context(stream, event, &con->simple_socket_data);

	switch (event) {
	case LI_IOSTREAM_DESTROY:
		li_stream_simple_socket_close(stream, FALSE);
		li_event_io_set_fd(&con->bcon->watcher, -1);

		li_backend_put(wrk, con->ctx->pool, con->bcon, TRUE);
		con->bcon = NULL;

		proxy_context_release(con->ctx);
		g_slice_free(proxy_connection, con);

		stream->data = NULL;
		return;
	default:
		break;
	}

	if ((NULL == stream->stream_in.out || stream->stream_in.out->is_closed) &&
		!(NULL == stream->stream_out.out || stream->stream_out.out->is_closed)) {
		stream->stream_out.out->is_closed = TRUE;
		li_stream_again_later(&stream->stream_out);
	}
}
Exemplo n.º 2
0
void li_connection_simple_tcp(liConnection **pcon, liIOStream *stream, gpointer *context, liIOStreamEvent event) {
	liConnection *con;
	goffset transfer_in = 0, transfer_out = 0;

	transfer_in = (NULL != stream->stream_in.out) ? stream->stream_in.out->bytes_in : 0;
	transfer_out = (NULL != stream->stream_out.out) ? stream->stream_out.out->bytes_out : 0;

	li_stream_simple_socket_io_cb_with_context(stream, event, context);

	/* li_stream_simple_socket_io_cb_with_context might lead to *pcon == NULL */
	con = *pcon;
	if (NULL != con) {
		if (NULL != stream->stream_in.out) {
			transfer_in = stream->stream_in.out->bytes_in - transfer_in;
			if (transfer_in > 0) {
				li_connection_update_io_timeout(con);
				li_vrequest_update_stats_in(con->mainvr, transfer_in);
			}
		}
		if (NULL != stream->stream_out.out) {
			transfer_out = stream->stream_out.out->bytes_out - transfer_out;
			if (transfer_out > 0) {
				li_connection_update_io_timeout(con);
				li_vrequest_update_stats_out(con->mainvr, transfer_out);
			}
		}
	}

	switch (event) {
	case LI_IOSTREAM_DESTROY:
		li_stream_simple_socket_close(stream, FALSE);
		return;
	case LI_IOSTREAM_DISCONNECTED_DEST:
		if (NULL != stream->stream_in.out && !stream->stream_in.out->is_closed) {
			li_stream_simple_socket_close(stream, TRUE);
			return;
		}
		break;
	case LI_IOSTREAM_DISCONNECTED_SOURCE:
		if (NULL != stream->stream_out.out && !stream->stream_out.out->is_closed) {
			li_stream_simple_socket_close(stream, TRUE);
			return;
		}
		break;
	default:
		break;
	}

	if ((NULL == stream->stream_in.out || stream->stream_in.out->is_closed) &&
		!(NULL == stream->stream_out.out || stream->stream_out.out->is_closed)) {
		stream->stream_out.out->is_closed = TRUE;
		li_stream_again_later(&stream->stream_out);
	}
}
Exemplo n.º 3
0
void li_filter_buffer_on_disk_stop(liStream *stream) {
	bod_state *state;

	if (NULL == stream) return;
	assert(bod_cb == stream->cb);

	li_stream_acquire(stream);
	state = LI_CONTAINER_OF(stream, bod_state, stream);
	bod_stop(state);
	li_stream_again_later(stream);
	li_stream_release(stream);
}
Exemplo n.º 4
0
static void li_connection_reset_keep_alive(liConnection *con) {
	liVRequest *vr = con->mainvr;

	if (NULL == con->con_sock.raw_in || NULL == con->con_sock.raw_out || con->in.source != con->con_sock.raw_in) {
		li_connection_reset(con);
		return;
	}

	/* only start keep alive watcher if there isn't more input data already */
	if (con->con_sock.raw_in->out->length == 0) {
		li_event_stop(&con->keep_alive_data.watcher);
		{
			con->keep_alive_data.max_idle = CORE_OPTION(LI_CORE_OPTION_MAX_KEEP_ALIVE_IDLE).number;
			if (con->keep_alive_data.max_idle == 0) {
				con->state = LI_CON_STATE_CLOSE;
				con_iostream_shutdown(con);
				li_connection_reset(con);
				return;
			}

			con->keep_alive_data.timeout = li_cur_ts(con->wrk) + con->keep_alive_data.max_idle;

			if (con->keep_alive_data.max_idle == con->srv->keep_alive_queue_timeout) {
				/* queue is sorted by con->keep_alive_data.timeout */
				gboolean need_start = (0 == con->wrk->keep_alive_queue.length);
				con->keep_alive_data.timeout = li_cur_ts(con->wrk) + con->srv->keep_alive_queue_timeout;
				g_queue_push_tail(&con->wrk->keep_alive_queue, con);
				con->keep_alive_data.link = g_queue_peek_tail_link(&con->wrk->keep_alive_queue);
				if (need_start)
					li_worker_check_keepalive(con->wrk);
			} else {
				li_event_timer_once(&con->keep_alive_data.watcher, con->keep_alive_data.max_idle);
			}
		}
	} else {
		li_stream_again_later(&con->in);
	}

	con->state = LI_CON_STATE_KEEP_ALIVE;
	con->response_headers_sent = FALSE;
	con->expect_100_cont = FALSE;
	con->out_has_all_data = FALSE;

	con->info.keep_alive = TRUE;

	li_connection_update_io_wait(con);

	li_vrequest_reset(con->mainvr, TRUE);
	li_http_request_parser_reset(&con->req_parser_ctx);

	li_stream_disconnect(&con->out);
	li_stream_disconnect_dest(&con->in);
	con->out.out->is_closed = FALSE;

	memset(&con->in_chunked_decode_state, 0, sizeof(con->in_chunked_decode_state));

	/* restore chunkqueue limits */
	li_chunkqueue_use_limit(con->con_sock.raw_in->out, LI_CONNECTION_DEFAULT_CHUNKQUEUE_LIMIT);
	li_chunkqueue_use_limit(con->con_sock.raw_out->out, LI_CONNECTION_DEFAULT_CHUNKQUEUE_LIMIT);

	/* reset stats */
	con->info.stats.bytes_in = G_GUINT64_CONSTANT(0);
	con->info.stats.bytes_in_5s = G_GUINT64_CONSTANT(0);
	con->info.stats.bytes_in_5s_diff = G_GUINT64_CONSTANT(0);
	con->info.stats.bytes_out = G_GUINT64_CONSTANT(0);
	con->info.stats.bytes_out_5s = G_GUINT64_CONSTANT(0);
	con->info.stats.bytes_out_5s_diff = G_GUINT64_CONSTANT(0);
	con->info.stats.last_avg = 0;
}
Exemplo n.º 5
0
static void stream_crypt_source_limit_notify_cb(gpointer context, gboolean locked) {
	liGnuTLSFilter *f = context;
	if (!locked) li_stream_again_later(&f->plain_drain);
}
Exemplo n.º 6
0
static void do_gnutls_write(liGnuTLSFilter *f) {
	const ssize_t blocksize = 16*1024; /* 16k */
	char *block_data;
	off_t block_len;
	ssize_t r;
	off_t write_max;
#ifdef USE_CORK
	gboolean corked = FALSE;
#endif
	liChunkQueue *cq = f->plain_drain.out;

	f_acquire(f);

	f->write_wants_read = FALSE;

	/* use space in (encrypted) outgoing buffer as amounts of bytes we try to write from (plain) output
	 * don't care if we write a little bit more than the limit allowed */
	write_max = li_chunkqueue_limit_available(f->crypt_source.out);
	LI_FORCE_ASSERT(write_max >= 0); /* we set a limit! */
	if (0 == write_max) goto out;
	/* if we start writing, try to write at least blocksize bytes */
	if (write_max < blocksize) write_max = blocksize;

	if (NULL != f->session && !f->initial_handshaked_finished && !do_gnutls_handshake(f, TRUE)) goto out;
	if (NULL == f->session) {
		f_abort_gnutls(f);
		goto out;
	}

#ifdef USE_CORK
	if (0 != cq->length && cq->queue.length > 1) {
		corked = TRUE;
		gnutls_record_cork(f->session);
	}
#endif

	do {
		GError *err = NULL;
		liChunkIter ci;

		if (0 == cq->length) break;

		ci = li_chunkqueue_iter(cq);
		switch (li_chunkiter_read(ci, 0, blocksize, &block_data, &block_len, &err)) {
		case LI_HANDLER_GO_ON:
			break;
		case LI_HANDLER_ERROR:
			if (NULL != err) {
				_ERROR(f->srv, f->wrk, f->log_context, "Couldn't read data from chunkqueue: %s", err->message);
				g_error_free(err);
			}
			/* fall through */
		default:
			f_abort_gnutls(f);
			goto out;
		}

		r = gnutls_record_send(f->session, block_data, block_len);
		if (r <= 0) {
			do_handle_error(f, "gnutls_record_send", r, TRUE);
			goto out;
		}

		li_chunkqueue_skip(cq, r);
		write_max -= r;
	} while (r == block_len && write_max > 0);

	if (cq->is_closed && 0 == cq->length) {
		r = gnutls_bye(f->session, GNUTLS_SHUT_RDWR);
		switch (r) {
		case GNUTLS_E_SUCCESS:
		case GNUTLS_E_AGAIN:
		case GNUTLS_E_INTERRUPTED:
			f->plain_source.out->is_closed = TRUE;
			f->crypt_source.out->is_closed = TRUE;
			f->crypt_drain.out->is_closed = TRUE;
			li_stream_disconnect(&f->crypt_source); /* plain in -> crypt out */
			f_close_gnutls(f);
			break;
		default:
			do_handle_error(f, "gnutls_bye", r, TRUE);
			f_abort_gnutls(f);
			break;
		}
	} else if (0 < cq->length && 0 != li_chunkqueue_limit_available(f->crypt_source.out)) {
		li_stream_again_later(&f->plain_drain);
	}

out:
#ifdef USE_CORK
	if (NULL != f->session && corked) {
		corked = TRUE;
		gnutls_record_uncork(f->session, 0);
	}
#endif

	f_release(f);
}