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