예제 #1
0
static liHandlerResult proxy_handle(liVRequest *vr, gpointer param, gpointer *context) {
	liBackendWait *bwait = (liBackendWait*) *context;
	liBackendConnection *bcon = NULL;
	proxy_context *ctx = (proxy_context*) param;
	liBackendResult bres;

	if (li_vrequest_is_handled(vr)) return LI_HANDLER_GO_ON;

	LI_VREQUEST_WAIT_FOR_REQUEST_BODY(vr);

	if (vr->request.content_length < 0) {
		VR_ERROR(vr, "%s", "proxy can't handle progressive uploads yet. enable request body buffering!");
		return LI_HANDLER_ERROR;
	}

	bres = li_backend_get(vr, ctx->pool, &bcon, &bwait);
	*context = bwait;
	switch (bres) {
	case LI_BACKEND_SUCCESS:
		LI_FORCE_ASSERT(NULL == bwait);
		LI_FORCE_ASSERT(NULL != bcon);
		break;
	case LI_BACKEND_WAIT:
		LI_FORCE_ASSERT(NULL != bwait);
		return LI_HANDLER_WAIT_FOR_EVENT;
	case LI_BACKEND_TIMEOUT:
		li_vrequest_backend_dead(vr);
		return LI_HANDLER_GO_ON;
	}

	proxy_connection_new(vr, bcon, ctx);
	return LI_HANDLER_GO_ON;
}
예제 #2
0
void li_connection_free(liConnection *con) {
	LI_FORCE_ASSERT(NULL == con->con_sock.data);
	LI_FORCE_ASSERT(LI_CON_STATE_DEAD == con->state);

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

	li_server_socket_release(con->srv_sock);
	con->srv_sock = NULL;

	g_string_free(con->info.remote_addr_str, TRUE);
	li_sockaddr_clear(&con->info.remote_addr);
	g_string_free(con->info.local_addr_str, TRUE);
	li_sockaddr_clear(&con->info.local_addr);

	li_vrequest_free(con->mainvr);
	li_http_request_parser_clear(&con->req_parser_ctx);

	con->info.keep_alive = TRUE;
	if (con->keep_alive_data.link && con->wrk) {
		g_queue_delete_link(&con->wrk->keep_alive_queue, con->keep_alive_data.link);
		con->keep_alive_data.link = NULL;
	}
	con->keep_alive_data.timeout = 0;
	con->keep_alive_data.max_idle = 0;
	li_event_clear(&con->keep_alive_data.watcher);

	/* remove from timeout queue */
	li_waitqueue_remove(&con->wrk->io_timeout_queue, &con->io_timeout_elem);

	li_job_clear(&con->job_reset);

	g_slice_free(liConnection, con);
}
예제 #3
0
static liHandlerResult core_handle_throttle_ip(liVRequest *vr, gpointer param, gpointer *context) {
	throttle_ip_pools *pools = param;
	liThrottleState *state = vr_get_throttle_out_state(vr);
	UNUSED(context);

	if (NULL != state) {
		refcounted_pool_entry *entry = create_ip_pool(vr->wrk->srv, pools, &vr->coninfo->remote_addr);
		if (NULL != entry) {
			if (!li_throttle_add_pool(vr->wrk, state, entry->pool)) {
				/* we already had a reference */
				g_atomic_int_add(&pools->refcount, -1);
				LI_FORCE_ASSERT(g_atomic_int_get(&pools->refcount) > 0);
				g_atomic_int_add(&entry->refcount, -1);
				LI_FORCE_ASSERT(g_atomic_int_get(&entry->refcount) > 0);
			} else {
				GArray *vr_ip_pools = (GArray*) g_ptr_array_index(vr->plugin_ctx, pools->plugin_id);
				vr_ip_pools_entry ventry;
				if (NULL == vr_ip_pools) {
					vr_ip_pools = g_array_new(FALSE, TRUE, sizeof(vr_ip_pools_entry));
					g_ptr_array_index(vr->plugin_ctx, pools->plugin_id) = vr_ip_pools;
				}
				ventry.pools = pools;
				ventry.remote_addr_copy = li_sockaddr_dup(vr->coninfo->remote_addr);
				g_array_append_val(vr_ip_pools, ventry);
			}
		}
	}

	return LI_HANDLER_GO_ON;
}
예제 #4
0
static void simple_tcp_io_cb(liIOStream *stream, liIOStreamEvent event) {
	simple_tcp_connection *data = stream->data;
	LI_FORCE_ASSERT(NULL != data);
	LI_FORCE_ASSERT(NULL == data->con || data == data->con->con_sock.data);
	LI_FORCE_ASSERT(NULL == data->sock_stream || stream == data->sock_stream);

	li_connection_simple_tcp(&data->con, stream, &data->simple_tcp_context, event);

	if (NULL != data->con && data->con->out_has_all_data
	    && (NULL == stream->stream_out.out || 0 == stream->stream_out.out->length)) {
		li_stream_simple_socket_flush(stream);
		li_connection_request_done(data->con);
	}

	switch (event) {
	case LI_IOSTREAM_DESTROY:
		LI_FORCE_ASSERT(NULL == data->con);
		LI_FORCE_ASSERT(NULL == data->sock_stream);
		stream->data = NULL;
		g_slice_free(simple_tcp_connection, data);
		break;
	default:
		break;
	}
}
예제 #5
0
static void tcp_io_cb(liIOStream *stream, liIOStreamEvent event) {
	mod_connection_ctx *conctx = stream->data;
	LI_FORCE_ASSERT(NULL == conctx->sock_stream || conctx->sock_stream == stream);

	if (LI_IOSTREAM_DESTROY == event) {
		li_stream_simple_socket_close(stream, TRUE); /* kill it, ssl sent an close alert message */
	}

	li_connection_simple_tcp(&conctx->con, stream, &conctx->simple_socket_data, event);

	if (NULL != conctx->con && conctx->con->out_has_all_data
	    && (NULL == stream->stream_out.out || 0 == stream->stream_out.out->length)
	    && li_streams_empty(conctx->con->con_sock.raw_out, NULL)) {
		li_stream_simple_socket_flush(stream);
		li_connection_request_done(conctx->con);
	}

	switch (event) {
	case LI_IOSTREAM_DESTROY:
		LI_FORCE_ASSERT(NULL == conctx->sock_stream);
		LI_FORCE_ASSERT(NULL == conctx->tls_filter);
		LI_FORCE_ASSERT(NULL == conctx->con);
		stream->data = NULL;
		g_slice_free(mod_connection_ctx, conctx);
		return;
	default:
		break;
	}
}
예제 #6
0
static void free_ip_pool(liServer *srv, throttle_ip_pools *pools, liSocketAddress *remote_addr) {
	refcounted_pool_entry *entry;

	switch (remote_addr->addr->plain.sa_family) {
	case AF_INET:
	case AF_INET6:
		break;
	default:
		return;
	}

	g_mutex_lock(pools->lock);
		if (remote_addr->addr->plain.sa_family == AF_INET) {
			entry = li_radixtree_lookup_exact(pools->ipv4_pools, &remote_addr->addr->ipv4.sin_addr.s_addr, pools->masklen_ipv4);
		} else {
			entry = li_radixtree_lookup_exact(pools->ipv6_pools, &remote_addr->addr->ipv6.sin6_addr.s6_addr, pools->masklen_ipv6);
		}
		LI_FORCE_ASSERT(NULL != entry);
		LI_FORCE_ASSERT(g_atomic_int_get(&entry->refcount) > 0);
		if (g_atomic_int_dec_and_test(&entry->refcount)) {
			if (remote_addr->addr->plain.sa_family == AF_INET) {
				li_radixtree_remove(pools->ipv4_pools, &remote_addr->addr->ipv4.sin_addr.s_addr, pools->masklen_ipv4);
			} else {
				li_radixtree_remove(pools->ipv6_pools, &remote_addr->addr->ipv6.sin6_addr.s6_addr, pools->masklen_ipv6);
			}
			li_throttle_pool_release(entry->pool, srv);
			g_slice_free(refcounted_pool_entry, entry);
		}
	g_mutex_unlock(pools->lock);

	ip_pools_free(pools);
}
예제 #7
0
static void close_cb(liGnuTLSFilter *f, gpointer data) {
	mod_connection_ctx *conctx = data;
	liConnection *con = conctx->con;
	LI_FORCE_ASSERT(conctx->tls_filter == f);

	conctx->tls_filter = NULL;
	li_gnutls_filter_free(f);
	gnutls_deinit(conctx->session);

	if (NULL != conctx->ctx) {
		mod_gnutls_context_release(conctx->ctx);
		conctx->ctx = NULL;
	}

	if (NULL != conctx->con) {
		liStream *raw_out = con->con_sock.raw_out, *raw_in = con->con_sock.raw_in;
		LI_FORCE_ASSERT(con->con_sock.data == conctx);
		conctx->con = NULL;
		con->con_sock.data = NULL;
		con->con_sock.callbacks = NULL;
		li_stream_acquire(raw_in);
		li_stream_reset(raw_out);
		li_stream_reset(raw_in);
		li_stream_release(raw_in);
	}

#ifdef USE_SNI
	if (NULL != conctx->sni_db_wait) {
		li_fetch_cancel(&conctx->sni_db_wait);
	}
	if (NULL != conctx->sni_entry) {
		li_fetch_entry_release(conctx->sni_entry);
		conctx->sni_entry = NULL;
	}
#endif

	if (NULL != conctx->client_hello_stream) {
		li_ssl_client_hello_stream_ready(conctx->client_hello_stream);
		li_stream_release(conctx->client_hello_stream);
		conctx->client_hello_stream = NULL;
	}

#ifdef USE_SNI
	if (NULL != conctx->sni_jobref) {
		li_job_ref_release(conctx->sni_jobref);
		conctx->sni_jobref = NULL;
	}
	li_job_clear(&conctx->sni_job);

	if (NULL != conctx->sni_server_name) {
		g_string_free(conctx->sni_server_name, TRUE);
		conctx->sni_server_name = NULL;
	}
#endif

	LI_FORCE_ASSERT(NULL != conctx->sock_stream);
	li_iostream_safe_release(&conctx->sock_stream);
}
예제 #8
0
static void event_async_cb(struct ev_loop *loop, ev_async *w, int revents) {
	liEventAsync *async = LI_CONTAINER_OF(w, liEventAsync, libevmess.async);
	liEventLoop *my_loop = async->base.link_watchers.data;
	UNUSED(revents);

	LI_FORCE_ASSERT(NULL != my_loop);
	LI_FORCE_ASSERT(loop == my_loop->loop);

	async->base.callback(&async->base, LI_EV_WAKEUP);
}
예제 #9
0
static void event_check_cb(struct ev_loop *loop, ev_check *w, int revents) {
	liEventCheck *check = LI_CONTAINER_OF(w, liEventCheck, libevmess.check);
	liEventLoop *my_loop = check->base.link_watchers.data;
	UNUSED(revents);

	LI_FORCE_ASSERT(NULL != my_loop);
	LI_FORCE_ASSERT(loop == my_loop->loop);

	check->base.callback(&check->base, LI_EV_WAKEUP);
}
예제 #10
0
static void event_prepare_cb(struct ev_loop *loop, ev_prepare *w, int revents) {
	liEventPrepare *prepare = LI_CONTAINER_OF(w, liEventPrepare, libevmess.prepare);
	liEventLoop *my_loop = prepare->base.link_watchers.data;
	UNUSED(revents);

	LI_FORCE_ASSERT(NULL != my_loop);
	LI_FORCE_ASSERT(loop == my_loop->loop);

	prepare->base.callback(&prepare->base, LI_EV_WAKEUP);
}
예제 #11
0
static void event_signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
	liEventSignal *sig = LI_CONTAINER_OF(w, liEventSignal, libevmess.sig);
	liEventLoop *my_loop = sig->base.link_watchers.data;
	UNUSED(revents);

	LI_FORCE_ASSERT(NULL != my_loop);
	LI_FORCE_ASSERT(loop == my_loop->loop);

	sig->base.callback(&sig->base, LI_EV_WAKEUP);
}
예제 #12
0
static void event_io_cb(struct ev_loop *loop, ev_io *w, int revents) {
	liEventIO *io = LI_CONTAINER_OF(w, liEventIO, libevmess.io);
	liEventLoop *my_loop = io->base.link_watchers.data;
	int events = 0;

	LI_FORCE_ASSERT(NULL != my_loop);
	LI_FORCE_ASSERT(loop == my_loop->loop);

	if (revents & EV_READ) events |= LI_EV_READ;
	if (revents & EV_WRITE) events |= LI_EV_WRITE;

	io->base.callback(&io->base, events);
}
예제 #13
0
static void mimetype_insert(liMimetypeNode *node, GString *suffix, GString *mimetype, guint depth) {
	guchar c, cdiff;
	gpointer ptr;
	liMimetypeNode *next_node;
	LI_FORCE_ASSERT(!MIME_IS_NODE(mimetype));

	/* start of suffix reached */
	if (depth == suffix->len) {
		if (node->mimetype)
			g_string_free(node->mimetype, TRUE);

		node->mimetype = mimetype;
		return;
	}

	c = (guchar) suffix->str[suffix->len - depth - 1];
	LI_FORCE_ASSERT(c != '\0');

	if (NULL == node->children) {
		node->cmin = node->cmax = c;
		node->children = g_malloc(sizeof(gpointer));
		node->children[0] = NULL;
	} else if (c < node->cmin) {
		cdiff = node->cmin - c; /* how much space we need in front */
		node->children = g_realloc(node->children, sizeof(gpointer) * (MIME_COUNT_CHILDREN(node) + cdiff)); /* make room for more children */
		memmove(&node->children[(guint)cdiff], node->children, sizeof(gpointer) * MIME_COUNT_CHILDREN(node)); /* move existing children to the back */
		memset(node->children, 0, cdiff * sizeof(gpointer));
		node->cmin = c;
	} else if (c > node->cmax) {
		cdiff = c - node->cmax;
		node->children = g_realloc(node->children, sizeof(gpointer) * (MIME_COUNT_CHILDREN(node) + cdiff)); /* make room for more children */
		memset(&node->children[MIME_COUNT_CHILDREN(node)], 0, cdiff * sizeof(gpointer));
		node->cmax = c;
	}

	ptr = node->children[c - node->cmin];

	if (NULL != ptr && MIME_IS_NODE(ptr)) {
		/* slot contains another node */
		next_node = MIME_UNMARK_NODE(ptr);
	} else {
		/* slot not used yet or contains a mimetype, split into node */
		next_node = g_slice_new(liMimetypeNode);
		next_node->mimetype = ptr;
		next_node->cmax = next_node->cmin = 0;
		next_node->children = NULL;
		node->children[c - node->cmin] = MIME_MARK_NODE(next_node);
	}

	mimetype_insert(next_node, suffix, mimetype, depth+1);
}
예제 #14
0
void li_buffer_release(liBuffer *buf) {
	if (!buf) return;
	LI_FORCE_ASSERT(g_atomic_int_get(&buf->refcount) > 0);
	if (g_atomic_int_dec_and_test(&buf->refcount)) {
		_buffer_destroy(buf);
	}
}
예제 #15
0
static void con_iostream_close(liConnection *con) { /* force close */
	if (con->con_sock.callbacks) {
		con->info.aborted = TRUE;
		con->con_sock.callbacks->finish(con, TRUE);
	}
	LI_FORCE_ASSERT(NULL == con->con_sock.data);
}
예제 #16
0
struct ev_loop* li_event_loop_clear(liEventLoop *loop) {
	struct ev_loop* evloop = loop->loop;
	GList *lnk;

	li_event_loop_end(loop);
	li_job_queue_clear(&loop->jobqueue);

	while (NULL != (lnk = loop->watchers.head)) {
		liEventBase *base = LI_CONTAINER_OF(lnk, liEventBase, link_watchers);
		LI_FORCE_ASSERT(li_event_attached_(base));
		li_event_detach_(base);
		LI_FORCE_ASSERT(lnk != loop->watchers.head);
	}
	loop->loop = NULL;
	return evloop;
}
예제 #17
0
static void event_child_cb(struct ev_loop *loop, ev_child *w, int revents) {
	liEventChild *child = LI_CONTAINER_OF(w, liEventChild, libevmess.child);
	liEventLoop *my_loop = child->base.link_watchers.data;
	UNUSED(revents);

	LI_FORCE_ASSERT(NULL != my_loop);
	LI_FORCE_ASSERT(loop == my_loop->loop);

	if (ev_is_active(w)) {
		if (!child->base.keep_loop_alive) ev_ref(loop);
		ev_child_stop(loop, w);
	}
	child->base.active = 0;

	child->base.callback(&child->base, LI_EV_WAKEUP);
}
예제 #18
0
void li_memcached_con_release(liMemcachedCon* con) {
	if (!con) return;
	LI_FORCE_ASSERT(g_atomic_int_get(&con->refcount) > 0);
	if (g_atomic_int_dec_and_test(&con->refcount)) {
		li_memcached_con_free(con);
	}
}
예제 #19
0
static void event_timer_cb(struct ev_loop *loop, ev_timer *w, int revents) {
	liEventTimer *timer = LI_CONTAINER_OF(w, liEventTimer, libevmess.timer);
	liEventLoop *my_loop = timer->base.link_watchers.data;
	UNUSED(revents);

	LI_FORCE_ASSERT(NULL != my_loop);
	LI_FORCE_ASSERT(loop == my_loop->loop);

	if (ev_is_active(w)) {
		if (!timer->base.keep_loop_alive) ev_ref(loop);
		ev_timer_stop(loop, w);
	}
	timer->base.active = 0;

	timer->base.callback(&timer->base, LI_EV_WAKEUP);
}
예제 #20
0
static void mainvr_connection_upgrade(liVRequest *vr, liStream *backend_drain, liStream *backend_source) {
	liConnection* con = li_connection_from_vrequest(vr);
	LI_FORCE_ASSERT(NULL != con);

	if (con->response_headers_sent || NULL != con->out.source) {
		li_connection_error(con);
		return;
	}
	if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
		VR_DEBUG(vr, "%s", "connection upgrade: write response headers");
	}
	con->response_headers_sent = TRUE;
	con->info.keep_alive = FALSE;
	li_response_send_headers(vr, con->out.out, NULL, TRUE);
	con->state = LI_CON_STATE_UPGRADED;
	vr->response.transfer_encoding = 0;
	li_connection_update_io_wait(con);

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

	li_stream_connect(&con->in, backend_drain);
	li_stream_connect(backend_source, &con->out);

	li_vrequest_reset(con->mainvr, TRUE);

	if (NULL != con->in.source) {
		li_chunkqueue_steal_all(con->out.out, backend_drain->out);
	}
	con->info.out_queue_length = con->out.out->length;

	li_stream_notify(&con->out);
	li_stream_notify(&con->in);
}
예제 #21
0
static void auth_file_data_release(AuthFileData *data) {
	if (!data) return;
	LI_FORCE_ASSERT(g_atomic_int_get(&data->refcount) > 0);
	if (!g_atomic_int_dec_and_test(&data->refcount)) return;

	g_hash_table_destroy(data->users);
	g_free(data->contents);
	g_slice_free(AuthFileData, data);
}
예제 #22
0
static void proxy_context_release(proxy_context *ctx) {
	if (!ctx) return;
	LI_FORCE_ASSERT(g_atomic_int_get(&ctx->refcount) > 0);
	if (g_atomic_int_dec_and_test(&ctx->refcount)) {
		li_backend_pool_free(ctx->pool);
		g_string_free(ctx->socket_str, TRUE);
		g_slice_free(proxy_context, ctx);
	}
}
예제 #23
0
void li_value_wrap_in_list(liValue *val) {
	liValue *item;
	LI_FORCE_ASSERT(NULL != val);

	item = li_value_extract(val);
	val->type = LI_VALUE_LIST;
	val->data.list = g_ptr_array_new();
	g_ptr_array_add(val->data.list, item);
}
예제 #24
0
void li_connection_start(liConnection *con, liSocketAddress remote_addr, int s, liServerSocket *srv_sock) {
	LI_FORCE_ASSERT(NULL == con->con_sock.data);

	con->srv_sock = srv_sock;
	con->state = LI_CON_STATE_REQUEST_START;
	con->mainvr->ts_started = con->ts_started = li_cur_ts(con->wrk);

	con->info.remote_addr = remote_addr;
	li_sockaddr_to_string(remote_addr, con->info.remote_addr_str, FALSE);

	con->info.local_addr = li_sockaddr_dup(srv_sock->local_addr);
	li_sockaddr_to_string(con->info.local_addr, con->info.local_addr_str, FALSE);

	con->info.aborted = FALSE;

	li_stream_init(&con->in, &con->wrk->loop, _connection_http_in_cb);
	li_stream_init(&con->out, &con->wrk->loop, _connection_http_out_cb);

	con->info.req = &con->in;
	con->info.resp = &con->out;

	li_connection_update_io_wait(con);

	if (srv_sock->new_cb) {
		if (!srv_sock->new_cb(con, s)) {
			li_connection_error(con);
			return;
		}
	} else {
		simple_tcp_new(con, s);
	}

	LI_FORCE_ASSERT(NULL != con->con_sock.raw_in || NULL != con->con_sock.raw_out);

	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);

	li_stream_connect(&con->out, con->con_sock.raw_out);
	li_stream_connect(con->con_sock.raw_in, &con->in);

	li_chunk_parser_init(&con->req_parser_ctx.chunk_ctx, con->con_sock.raw_in->out);
}
예제 #25
0
static void gnutls_tcp_finished(liConnection *con, gboolean aborted) {
	mod_connection_ctx *conctx = con->con_sock.data;
	UNUSED(aborted);

	con->info.is_ssl = FALSE;
	con->con_sock.callbacks = NULL;

	if (NULL != conctx) {
		LI_FORCE_ASSERT(con == conctx->con);
		close_cb(conctx->tls_filter, conctx);
		LI_FORCE_ASSERT(NULL == con->con_sock.data);
	}

	{
		liStream *raw_out = con->con_sock.raw_out, *raw_in = con->con_sock.raw_in;
		con->con_sock.raw_out = con->con_sock.raw_in = NULL;
		if (NULL != raw_out) { li_stream_reset(raw_out); li_stream_release(raw_out); }
		if (NULL != raw_in) { li_stream_reset(raw_in); li_stream_release(raw_in); }
	}
}
예제 #26
0
void li_release_optionptr(liServer *srv, liOptionPtrValue *value) {
	liServerOptionPtr *sopt;
	LI_FORCE_ASSERT(NULL != srv);

	if (NULL == value) return;

	LI_FORCE_ASSERT(g_atomic_int_get(&value->refcount) > 0);
	if (!g_atomic_int_dec_and_test(&value->refcount)) return;

	sopt = value->sopt;
	value->sopt = NULL;
	if (!sopt->free_option) {
		switch (sopt->type) {
		case LI_VALUE_NONE:
		case LI_VALUE_BOOLEAN:
		case LI_VALUE_NUMBER:
			/* Nothing to free */
			break;
		case LI_VALUE_STRING:
			if (value->data.string)
				g_string_free(value->data.string, TRUE);
			break;
		case LI_VALUE_LIST:
			if (value->data.list)
				li_value_list_free(value->data.list);
			break;
		case LI_VALUE_ACTION:
			if (value->data.action)
				li_action_release(srv, value->data.action);
			break;
		case LI_VALUE_CONDITION:
			if (value->data.cond)
				li_condition_release(srv, value->data.cond);
			break;
		}
	} else {
		sopt->free_option(srv, sopt->p, sopt->module_index, value->data.ptr);
	}
	g_slice_free(liOptionPtrValue, value);
}
예제 #27
0
static void ip_pools_free(throttle_ip_pools *pools) {
	LI_FORCE_ASSERT(g_atomic_int_get(&pools->refcount) > 0);

	if (g_atomic_int_dec_and_test(&pools->refcount)) {
		g_mutex_free(pools->lock);
		pools->lock = NULL;

		/* entries keep references, so radix trees must be empty */
		li_radixtree_free(pools->ipv4_pools, NULL, NULL);
		li_radixtree_free(pools->ipv6_pools, NULL, NULL);
		g_slice_free(throttle_ip_pools, pools);
	}
}
예제 #28
0
void li_gnutls_filter_free(liGnuTLSFilter *f) {
	LI_FORCE_ASSERT(NULL != f->callbacks);
	f->callbacks = NULL;
	f->callback_data = NULL;

	f_close_gnutls(f);

	li_stream_release(&f->crypt_source);
	li_stream_release(&f->crypt_drain);
	li_stream_release(&f->plain_source);
	li_stream_release(&f->plain_drain);
	f_release(f);
}
예제 #29
0
static refcounted_pool_entry* create_ip_pool(liServer *srv, throttle_ip_pools *pools, liSocketAddress *remote_addr) {
	refcounted_pool_entry *result;

	switch (remote_addr->addr->plain.sa_family) {
	case AF_INET:
	case AF_INET6:
		break;
	default:
		return NULL;
	}

	LI_FORCE_ASSERT(g_atomic_int_get(&pools->refcount) > 0);
	g_atomic_int_inc(&pools->refcount);

	g_mutex_lock(pools->lock);
		if (remote_addr->addr->plain.sa_family == AF_INET) {
			result = li_radixtree_lookup_exact(pools->ipv4_pools, &remote_addr->addr->ipv4.sin_addr.s_addr, pools->masklen_ipv4);
		} else {
			result = li_radixtree_lookup_exact(pools->ipv6_pools, &remote_addr->addr->ipv6.sin6_addr.s6_addr, pools->masklen_ipv6);
		}
		if (NULL == result) {
			result = g_slice_new0(refcounted_pool_entry);
			result->refcount = 1;
			result->pool = li_throttle_pool_new(srv, pools->rate, pools->burst);

			if (remote_addr->addr->plain.sa_family == AF_INET) {
				li_radixtree_insert(pools->ipv4_pools, &remote_addr->addr->ipv4.sin_addr.s_addr, pools->masklen_ipv4, result);
			} else {
				li_radixtree_insert(pools->ipv6_pools, &remote_addr->addr->ipv6.sin6_addr.s6_addr, pools->masklen_ipv6, result);
			}
		} else {
			LI_FORCE_ASSERT(g_atomic_int_get(&result->refcount) > 0);
			g_atomic_int_inc(&result->refcount);
		}
	g_mutex_unlock(pools->lock);

	return result;
}
예제 #30
0
static void f_close_gnutls(liGnuTLSFilter *f) {
	if (NULL != f->session && !f->closing) {
		liCQLimit *limit;
		f->closing = TRUE;
		f->session = NULL;

		LI_FORCE_ASSERT(NULL != f->crypt_source.out);
		LI_FORCE_ASSERT(NULL != f->crypt_source.out->limit);
		limit = f->crypt_source.out->limit;
		limit->notify = NULL;
		limit->context = NULL;

		li_stream_disconnect(&f->plain_source); /* crypt in -> plain out */

		li_stream_disconnect(&f->plain_drain); /* app -> plain in */
		li_stream_disconnect_dest(&f->plain_source); /* plain out -> app */

		f->log_context = NULL;
		if (NULL != f->callbacks && NULL != f->callbacks->closed_cb) {
			f->callbacks->closed_cb(f, f->callback_data);
		}
	}
}