4 Commits

3 changed files with 41 additions and 32 deletions

View File

@@ -352,6 +352,7 @@ static int proxy_connect(proxy_ctx_t *proxy, host_config_t *conf, http_res *res,
proxy->initialized = 1; proxy->initialized = 1;
proxy->cnx_s = clock_micros(); proxy->cnx_s = clock_micros();
proxy->host = conf->name; proxy->host = conf->name;
proxy->http_timeout = 0;
info(BLUE_STR "Established new connection with " BLD_STR "[%s]:%i", addr_buf, conf->proxy.port); info(BLUE_STR "Established new connection with " BLD_STR "[%s]:%i", addr_buf, conf->proxy.port);
@@ -361,49 +362,52 @@ static int proxy_connect(proxy_ctx_t *proxy, host_config_t *conf, http_res *res,
int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_status_ctx *ctx, host_config_t *conf, sock *client, http_status *custom_status, char *err_msg) { int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_status_ctx *ctx, host_config_t *conf, sock *client, http_status *custom_status, char *err_msg) {
char buffer[CHUNK_SIZE], err_buf[256]; char buffer[CHUNK_SIZE], err_buf[256];
long ret; long ret;
int tries = 0, retry = 1; int tries = 0, retry = 1, srv_error = 0;
*proxy_ptr = proxy_get_by_conf(conf); *proxy_ptr = proxy_get_by_conf(conf);
proxy_ctx_t *proxy = *proxy_ptr; proxy_ctx_t *proxy = *proxy_ptr;
proxy->client = NULL; proxy->client = NULL;
const char *connection = http_get_header_field(&req->hdr, "Connection");
if (strcontains(connection, "upgrade") || strcontains(connection, "Upgrade")) {
const char *upgrade = http_get_header_field(&req->hdr, "Upgrade");
const char *ws_version = http_get_header_field(&req->hdr, "Sec-WebSocket-Version");
if (streq(upgrade, "websocket") && streq(ws_version, "13")) {
ctx->ws_key = http_get_header_field(&req->hdr, "Sec-WebSocket-Key");
} else {
res->status = http_get_status(501);
ctx->origin = INTERNAL;
return -1;
}
} else {
http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "Connection", "keep-alive");
}
ret = proxy_request_header(req, client);
if (ret != 0) {
res->status = http_get_status(500);
ctx->origin = INTERNAL;
return -1;
}
while (retry) { while (retry) {
errno = 0; errno = 0;
if (!proxy->initialized || sock_has_pending(&proxy->proxy) != 0) { if (!proxy->initialized || sock_has_pending(&proxy->proxy) != 0 || srv_error ||
(proxy->http_timeout != 0 && (clock_micros() - proxy->proxy.ts_last) > proxy->http_timeout))
{
if (proxy->initialized) if (proxy->initialized)
proxy_close(proxy); proxy_close(proxy);
retry = 0; retry = 0;
srv_error = 0;
tries++; tries++;
if (proxy_connect(proxy, conf, res, ctx, err_msg) != 0) if (proxy_connect(proxy, conf, res, ctx, err_msg) != 0)
continue; continue;
} }
const char *connection = http_get_header_field(&req->hdr, "Connection");
if (strcontains(connection, "upgrade") || strcontains(connection, "Upgrade")) {
const char *upgrade = http_get_header_field(&req->hdr, "Upgrade");
const char *ws_version = http_get_header_field(&req->hdr, "Sec-WebSocket-Version");
if (streq(upgrade, "websocket") && streq(ws_version, "13")) {
ctx->ws_key = http_get_header_field(&req->hdr, "Sec-WebSocket-Key");
} else {
res->status = http_get_status(501);
ctx->origin = INTERNAL;
return -1;
}
} else {
http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "Connection", "keep-alive");
}
ret = proxy_request_header(req, client);
if (ret != 0) {
res->status = http_get_status(500);
ctx->origin = INTERNAL;
return -1;
}
ret = http_send_request(&proxy->proxy, req); ret = http_send_request(&proxy->proxy, req);
if (ret < 0) { if (ret < 0) {
res->status = http_get_status(502); res->status = http_get_status(502);
@@ -411,6 +415,7 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu
error("Unable to send request to server (1)"); error("Unable to send request to server (1)");
sprintf(err_msg, "Unable to send request to server: %s.", error_str(errno, err_buf, sizeof(err_buf))); sprintf(err_msg, "Unable to send request to server: %s.", error_str(errno, err_buf, sizeof(err_buf)));
retry = tries < 4; retry = tries < 4;
srv_error = 1;
continue; continue;
} }
@@ -431,8 +436,7 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu
ctx->origin = SERVER_REQ; ctx->origin = SERVER_REQ;
error("Unable to send request to server (2)"); error("Unable to send request to server (2)");
sprintf(err_msg, "Unable to send request to server: %s.", error_str(errno, err_buf, sizeof(err_buf))); sprintf(err_msg, "Unable to send request to server: %s.", error_str(errno, err_buf, sizeof(err_buf)));
retry = tries < 4; return -1;
continue;
} else if (ret == -1) { } else if (ret == -1) {
res->status = http_get_status(400); res->status = http_get_status(400);
ctx->origin = CLIENT_REQ; ctx->origin = CLIENT_REQ;
@@ -458,8 +462,7 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu
} }
error("Unable to receive response from server"); error("Unable to receive response from server");
sprintf(err_msg, "Unable to receive response from server: %s.", error_str(errno, err_buf, sizeof(err_buf))); sprintf(err_msg, "Unable to receive response from server: %s.", error_str(errno, err_buf, sizeof(err_buf)));
retry = tries < 4; return -1;
continue;
} }
buffer[ret] = 0; buffer[ret] = 0;
@@ -533,6 +536,8 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu
} }
sock_recv_x(&proxy->proxy, buffer, header_len, 0); sock_recv_x(&proxy->proxy, buffer, header_len, 0);
// TODO read timeout from Keep-Alive
ret = proxy_response_header(req, res, conf); ret = proxy_response_header(req, res, conf);
if (ret != 0) { if (ret != 0) {
res->status = http_get_status(500); res->status = http_get_status(500);

View File

@@ -22,6 +22,7 @@ typedef struct {
unsigned char initialized:1, in_use:1; unsigned char initialized:1, in_use:1;
sock proxy; sock proxy;
long cnx_s, cnx_e; long cnx_s, cnx_e;
long http_timeout;
char *host; char *host;
void *client; void *client;
} proxy_ctx_t; } proxy_ctx_t;

View File

@@ -87,6 +87,9 @@ int sock_init(sock *s, int fd, int flags) {
s->ts_start = clock_micros(); s->ts_start = clock_micros();
s->ts_last = s->ts_start; s->ts_last = s->ts_start;
s->timeout_us = -1; s->timeout_us = -1;
s->ssl = NULL;
s->addr = NULL;
s->s_addr = NULL;
return 0; return 0;
} }
@@ -200,7 +203,7 @@ int sock_set_timeout(sock *s, double sec) {
} }
long sock_send(sock *s, void *buf, unsigned long len, int flags) { long sock_send(sock *s, void *buf, unsigned long len, int flags) {
if (s->socket == 0) { if (s->socket < 0) {
errno = ENOTCONN; errno = ENOTCONN;
return -1; return -1;
} }
@@ -242,7 +245,7 @@ long sock_send_x(sock *s, void *buf, unsigned long len, int flags) {
} }
long sock_recv(sock *s, void *buf, unsigned long len, int flags) { long sock_recv(sock *s, void *buf, unsigned long len, int flags) {
if (s->socket == 0) { if (s->socket < 0) {
errno = ENOTCONN; errno = ENOTCONN;
return -1; return -1;
} }
@@ -377,7 +380,7 @@ int sock_close(sock *s) {
s->ssl = NULL; s->ssl = NULL;
} }
close(s->socket); close(s->socket);
s->socket = 0; s->socket = -1;
s->enc = 0, s->pipe = 0; s->enc = 0, s->pipe = 0;
errno = e; errno = e;
return 0; return 0;