Use semaphores to keep track of proxy connections
This commit is contained in:
@ -24,7 +24,9 @@
|
|||||||
|
|
||||||
static SSL_CTX *proxy_ctx = NULL;
|
static SSL_CTX *proxy_ctx = NULL;
|
||||||
static proxy_ctx_t *proxies = NULL;
|
static proxy_ctx_t *proxies = NULL;
|
||||||
|
static sem_t *available = NULL;
|
||||||
static sem_t lock;
|
static sem_t lock;
|
||||||
|
static int num_proxy_hosts = -1;
|
||||||
|
|
||||||
int proxy_preload(void) {
|
int proxy_preload(void) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@ -45,42 +47,53 @@ int proxy_preload(void) {
|
|||||||
proxy_unload();
|
proxy_unload();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(proxies, 0, n * MAX_PROXY_CNX_PER_HOST * sizeof(proxy_ctx_t));
|
memset(proxies, 0, n * MAX_PROXY_CNX_PER_HOST * sizeof(proxy_ctx_t));
|
||||||
|
|
||||||
|
available = malloc(n * sizeof(*available));
|
||||||
|
if (available == NULL) {
|
||||||
|
proxy_unload();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
if (sem_init(&available[i], 0, MAX_PROXY_CNX_PER_HOST) != 0) {
|
||||||
|
proxy_unload();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sem_init(&lock, 0, 1) != 0) {
|
if (sem_init(&lock, 0, 1) != 0) {
|
||||||
proxy_unload();
|
proxy_unload();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
num_proxy_hosts = n;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void proxy_unload(void) {
|
void proxy_unload(void) {
|
||||||
int e = errno;
|
int e = errno;
|
||||||
sem_destroy(&lock);
|
|
||||||
SSL_CTX_free(proxy_ctx);
|
SSL_CTX_free(proxy_ctx);
|
||||||
|
sem_destroy(&lock);
|
||||||
|
if (num_proxy_hosts != -1) {
|
||||||
|
for (int i = 0; i < num_proxy_hosts; i++) {
|
||||||
|
sem_destroy(&available[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(available);
|
||||||
free(proxies);
|
free(proxies);
|
||||||
errno = e;
|
errno = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void proxy_close_all(void) {
|
void proxy_close_all(void) {
|
||||||
int n = 0;
|
|
||||||
for (int i = 0; i < CONFIG_MAX_HOST_CONFIG; i++) {
|
|
||||||
host_config_t *hc = &config.hosts[i];
|
|
||||||
if (hc->type == CONFIG_TYPE_UNSET) break;
|
|
||||||
if (hc->type != CONFIG_TYPE_REVERSE_PROXY) continue;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy_ctx_t *ptr = proxies;
|
proxy_ctx_t *ptr = proxies;
|
||||||
for (int i = 0; i < MAX_PROXY_CNX_PER_HOST * n; i++, ptr++) {
|
for (int i = 0; i < MAX_PROXY_CNX_PER_HOST * num_proxy_hosts; i++, ptr++) {
|
||||||
if (ptr->initialized)
|
if (ptr->initialized)
|
||||||
proxy_close(ptr);
|
proxy_close(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static proxy_ctx_t *proxy_get_by_conf(host_config_t *conf) {
|
proxy_ctx_t *proxy_get_by_conf(host_config_t *conf) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (int i = 0; i < CONFIG_MAX_HOST_CONFIG; i++) {
|
for (int i = 0; i < CONFIG_MAX_HOST_CONFIG; i++) {
|
||||||
host_config_t *hc = &config.hosts[i];
|
host_config_t *hc = &config.hosts[i];
|
||||||
@ -90,12 +103,21 @@ static proxy_ctx_t *proxy_get_by_conf(host_config_t *conf) {
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO use semaphore to keep track of number of free proxy connections
|
try_again_1:
|
||||||
try_again:
|
if (sem_wait(&available[n]) != 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
goto try_again_1;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try_again_2:
|
||||||
if (sem_wait(&lock) != 0) {
|
if (sem_wait(&lock) != 0) {
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
goto try_again;
|
goto try_again_2;
|
||||||
} else {
|
} else {
|
||||||
|
sem_post(&available[n]);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,9 +132,16 @@ static proxy_ctx_t *proxy_get_by_conf(host_config_t *conf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sem_post(&lock);
|
sem_post(&lock);
|
||||||
|
sem_post(&available[n]);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void proxy_unlock_ctx(proxy_ctx_t *ctx) {
|
||||||
|
int n = (int) ((ctx - proxies) / MAX_PROXY_CNX_PER_HOST);
|
||||||
|
ctx->in_use = 0;
|
||||||
|
sem_post(&available[n]);
|
||||||
|
}
|
||||||
|
|
||||||
int proxy_request_header(http_req *req, sock *sock) {
|
int proxy_request_header(http_req *req, sock *sock) {
|
||||||
char buf1[256], buf2[256];
|
char buf1[256], buf2[256];
|
||||||
int p_len;
|
int p_len;
|
||||||
|
@ -34,6 +34,10 @@ void proxy_unload(void);
|
|||||||
|
|
||||||
void proxy_close_all(void);
|
void proxy_close_all(void);
|
||||||
|
|
||||||
|
proxy_ctx_t *proxy_get_by_conf(host_config_t *conf);
|
||||||
|
|
||||||
|
void proxy_unlock_ctx(proxy_ctx_t *ctx);
|
||||||
|
|
||||||
int proxy_request_header(http_req *req, sock *sock);
|
int proxy_request_header(http_req *req, sock *sock);
|
||||||
|
|
||||||
int proxy_response_header(http_req *req, http_res *res, host_config_t *conf);
|
int proxy_response_header(http_req *req, http_res *res, host_config_t *conf);
|
||||||
|
@ -26,13 +26,13 @@ void proxy_handler_func(client_ctx_t *ctx) {
|
|||||||
respond(ctx);
|
respond(ctx);
|
||||||
|
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
ctx->proxy->in_use = 0;
|
proxy_unlock_ctx(ctx->proxy);
|
||||||
ctx->proxy = NULL;
|
ctx->proxy = NULL;
|
||||||
} else if (ctx->use_proxy == 0) {
|
} else if (ctx->use_proxy == 0) {
|
||||||
proxy_close(ctx->proxy);
|
proxy_close(ctx->proxy);
|
||||||
} else if (ctx->use_proxy == 1) {
|
} else if (ctx->use_proxy == 1) {
|
||||||
proxy_handler_2(ctx);
|
proxy_handler_2(ctx);
|
||||||
ctx->proxy->in_use = 0;
|
proxy_unlock_ctx(ctx->proxy);
|
||||||
ctx->proxy = NULL;
|
ctx->proxy = NULL;
|
||||||
} else if (ctx->use_proxy == 2) {
|
} else if (ctx->use_proxy == 2) {
|
||||||
// WebSocket
|
// WebSocket
|
||||||
|
Reference in New Issue
Block a user