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); }
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); }
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); }
/* 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); }
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); }
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); }
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); } }
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); } }
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; }
static void proxy_backend_free(liBackendPool *bpool) { liBackendConfig *config = (liBackendConfig*) bpool->config; li_sockaddr_clear(&config->sock_addr); g_slice_free(liBackendConfig, config); }