示例#1
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);
}
示例#2
0
static void li_connection_reset2(liConnection *con) {
	con->response_headers_sent = FALSE;
	con->expect_100_cont = FALSE;
	con->out_has_all_data = FALSE;

	con_iostream_close(con);

	li_server_socket_release(con->srv_sock);
	con->srv_sock = NULL;
	con->info.is_ssl = FALSE;
	con->info.aborted = FALSE;
	con->info.out_queue_length = 0;

	li_stream_reset(&con->in);
	li_stream_reset(&con->out);

	li_vrequest_reset(con->mainvr, FALSE);

	li_http_request_parser_reset(&con->req_parser_ctx);

	g_string_truncate(con->info.remote_addr_str, 0);
	li_sockaddr_clear(&con->info.remote_addr);
	g_string_truncate(con->info.local_addr_str, 0);
	li_sockaddr_clear(&con->info.local_addr);

	con->info.keep_alive = TRUE;
	if (con->keep_alive_data.link) {
		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_stop(&con->keep_alive_data.watcher);
	con->keep_alive_requests = 0;

	/* 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;

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

	li_job_reset(&con->job_reset);
}
示例#3
0
static void li_memcached_con_free(liMemcachedCon* con) {
	if (!con) return;

	if (-1 != li_event_io_fd(&con->con_watcher)) {
		close(li_event_io_fd(&con->con_watcher));
		li_event_clear(&con->con_watcher);
		con->fd = -1;
	}

	send_queue_reset(&con->out);
	cancel_all_requests(con);

	li_buffer_release(con->buf);
	li_buffer_release(con->line);
	li_buffer_release(con->remaining);
	li_buffer_release(con->data);
	reset_item(&con->curitem);

	li_sockaddr_clear(&con->addr);
	g_string_free(con->tmpstr, TRUE);

	g_clear_error(&con->err);

	g_slice_free(liMemcachedCon, con);
}
示例#4
0
/* not every context has srv ready, extract from context instead */
static void mc_ctx_release(liServer *_srv, gpointer param) {
	memcached_ctx *ctx = param;
	liServer *srv;
	guint i;
	UNUSED(_srv);

	if (NULL == ctx) return;
	srv = ctx->srv;

	assert(g_atomic_int_get(&ctx->refcount) > 0);
	if (!g_atomic_int_dec_and_test(&ctx->refcount)) return;

	if (ctx->worker_client_ctx) {
		for (i = 0; i < srv->worker_count; i++) {
			li_memcached_con_release(ctx->worker_client_ctx[i]);
		}
		g_slice_free1(sizeof(liMemcachedCon*) * srv->worker_count, ctx->worker_client_ctx);
	}

	li_sockaddr_clear(&ctx->addr);

	li_pattern_free(ctx->pattern);

	li_action_release(srv, ctx->act_found);
	li_action_release(srv, ctx->act_miss);

	if (ctx->mconf_link.data) { /* still in LI_SERVER_INIT */
		memcached_config *mconf = ctx->p->data;
		g_queue_unlink(&mconf->prepare_ctx, &ctx->mconf_link);
		ctx->mconf_link.data = NULL;
	}

	ctx->srv = NULL;
	g_slice_free(memcached_ctx, ctx);
}
示例#5
0
static void mod_limit_timeout_callback(liWaitQueue *wq, gpointer data) {
	liWaitQueueElem *wqe;
	mod_limit_req_ip_data *rid;
	gpointer addr;
	guint32 bits;

	UNUSED(data);

	while ((wqe = li_waitqueue_pop(wq)) != NULL) {
		rid = wqe->data;

		/* IPv4 or IPv6? */
		if (rid->ip.addr->plain.sa_family == AF_INET) {
			addr = &rid->ip.addr->ipv4.sin_addr.s_addr;
			bits = 32;
		} else {
			addr = &rid->ip.addr->ipv6.sin6_addr.s6_addr;
			bits = 128;
		}

		g_mutex_lock(rid->ctx->mutex);
		li_radixtree_remove(rid->ctx->pool.req_ip, addr, bits);
		g_mutex_unlock(rid->ctx->mutex);
		li_sockaddr_clear(&rid->ip);
		g_slice_free(mod_limit_req_ip_data, rid);
	}

	li_waitqueue_update(wq);
}
示例#6
0
static void li_memcached_con_free(liMemcachedCon* con) {
	if (!con) return;

	if (-1 != con->con_watcher.fd) {
		close(con->con_watcher.fd);
		/* as io has a reference on con, we don't need to stop it here */
		ev_io_set(&con->con_watcher, -1, 0);
		con->fd = -1;
	}

	send_queue_reset(&con->out);
	cancel_all_requests(con);

	li_buffer_release(con->buf);
	li_buffer_release(con->line);
	li_buffer_release(con->remaining);
	li_buffer_release(con->data);
	reset_item(&con->curitem);

	li_sockaddr_clear(&con->addr);
	g_string_free(con->tmpstr, TRUE);

	g_clear_error(&con->err);

	g_slice_free(liMemcachedCon, con);
}
示例#7
0
static void proxy_context_release(proxy_context *ctx) {
	if (!ctx) return;
	assert(g_atomic_int_get(&ctx->refcount) > 0);
	if (g_atomic_int_dec_and_test(&ctx->refcount)) {
		li_sockaddr_clear(&ctx->socket);
		g_string_free(ctx->socket_str, TRUE);
		g_slice_free(proxy_context, ctx);
	}
}
示例#8
0
static void throttle_vrclose(liVRequest *vr, liPlugin *p) {
	GArray *vr_ip_pools = (GArray*) g_ptr_array_index(vr->plugin_ctx, p->id);
	guint i, len;
	liServer *srv = vr->wrk->srv;

	if (NULL != vr_ip_pools) {
		g_ptr_array_index(vr->plugin_ctx, p->id) = NULL;
		for (i = 0, len = vr_ip_pools->len; i < len; ++i) {
			vr_ip_pools_entry *ventry = &g_array_index(vr_ip_pools, vr_ip_pools_entry, i);
			free_ip_pool(srv, ventry->pools, &ventry->remote_addr_copy);
			li_sockaddr_clear(&ventry->remote_addr_copy);
		}
		g_array_free(vr_ip_pools, TRUE);
	}
}
示例#9
0
static memcached_ctx* mc_ctx_parse(liServer *srv, liPlugin *p, liValue *config) {
	memcached_ctx *ctx;
	memcached_config *mconf = p->data;
	GString def_server = li_const_gstring(CONST_STR_LEN("127.0.0.1:11211"));

	if (config && config->type != LI_VALUE_HASH) {
		ERROR(srv, "%s", "memcache expects an optional hash of options");
		return NULL;
	}

	ctx = g_slice_new0(memcached_ctx);
	ctx->srv = srv;
	ctx->refcount = 1;
	ctx->p = p;

	ctx->addr = li_sockaddr_from_string(&def_server, 11211);

	ctx->pattern = li_pattern_new(srv, "%{req.path}");

	ctx->flags = 0;
	ctx->ttl = 30;
	ctx->maxsize = 64*1024; /* 64 kB */
	ctx->headers = FALSE;

	if (config) {
		GHashTable *ht = config->data.hash;
		GHashTableIter it;
		gpointer pkey, pvalue;

		g_hash_table_iter_init(&it, ht);
		while (g_hash_table_iter_next(&it, &pkey, &pvalue)) {
			GString *key = pkey;
			liValue *value = pvalue;

			if (g_string_equal(key, &mon_server)) {
				if (value->type != LI_VALUE_STRING) {
					ERROR(srv, "memcache option '%s' expects string as parameter", mon_server.str);
					goto option_failed;
				}
				li_sockaddr_clear(&ctx->addr);
				ctx->addr = li_sockaddr_from_string(value->data.string, 11211);
				if (NULL == ctx->addr.addr) {
					ERROR(srv, "invalid socket address: '%s'", value->data.string->str);
					goto option_failed;
				}
			} else if (g_string_equal(key, &mon_key)) {
				if (value->type != LI_VALUE_STRING) {
					ERROR(srv, "memcache option '%s' expects string as parameter", mon_key.str);
					goto option_failed;
				}
				li_pattern_free(ctx->pattern);
				ctx->pattern = li_pattern_new(srv,  value->data.string->str);
				if (NULL == ctx->pattern) {
					ERROR(srv, "memcache: couldn't parse pattern for key '%s'", value->data.string->str);
					goto option_failed;
				}
			} else if (g_string_equal(key, &mon_flags)) {
				if (value->type != LI_VALUE_NUMBER || value->data.number <= 0) {
					ERROR(srv, "memcache option '%s' expects positive integer as parameter", mon_flags.str);
					goto option_failed;
				}
				ctx->flags = value->data.number;
			} else if (g_string_equal(key, &mon_ttl)) {
				if (value->type != LI_VALUE_NUMBER || value->data.number < 0) {
					ERROR(srv, "memcache option '%s' expects non-negative integer as parameter", mon_ttl.str);
					goto option_failed;
				}
				ctx->ttl = value->data.number;
			} else if (g_string_equal(key, &mon_maxsize)) {
				if (value->type != LI_VALUE_NUMBER || value->data.number <= 0) {
					ERROR(srv, "memcache option '%s' expects positive integer as parameter", mon_maxsize.str);
					goto option_failed;
				}
				ctx->maxsize = value->data.number;
			} else if (g_string_equal(key, &mon_headers)) {
				if (value->type != LI_VALUE_BOOLEAN) {
					ERROR(srv, "memcache option '%s' expects boolean as parameter", mon_headers.str);
					goto option_failed;
				}
				ctx->headers = value->data.boolean;
				if (ctx->headers) {
					ERROR(srv, "%s", "memcache: lookup/storing headers not supported yet");
					goto option_failed;
				}
			} else {
				ERROR(srv, "unknown option for memcache '%s'", key->str);
				goto option_failed;
			}
		}
	}

	if (LI_SERVER_INIT != g_atomic_int_get(&srv->state)) {
		ctx->worker_client_ctx = g_slice_alloc0(sizeof(liMemcachedCon*) * srv->worker_count);
	} else {
		ctx->mconf_link.data = ctx;
		g_queue_push_tail_link(&mconf->prepare_ctx, &ctx->mconf_link);
	}

	return ctx;

option_failed:
	mc_ctx_release(NULL, ctx);
	return NULL;
}
示例#10
0
static void proxy_backend_free(liBackendPool *bpool) {
	liBackendConfig *config = (liBackendConfig*) bpool->config;
	li_sockaddr_clear(&config->sock_addr);
	g_slice_free(liBackendConfig, config);
}