#include #include #include "main.h" #include "uring.h" #include "server.h" #include "proxy.h" #include "utils.h" void proxy_refdump(struct server_proxy *proxy) { uring_task_refdump(&proxy->task); uring_task_refdump(&proxy->clienttask); uring_task_refdump(&proxy->servertask); } static void format_bytes(char *buf, size_t len, uint64_t val) { uint64_t tmp; const char *suffix = "B"; tmp = val * 10; if (val > 1152921504606846976ULL) { tmp = val / 115292150460684697ULL; suffix= "EiB"; } else if (val > 1125899906842624ULL) { tmp /= 1125899906842624ULL; suffix = "PiB"; } else if (val > 1099511627776ULL) { tmp /= 1099511627776ULL; suffix = "TiB"; } else if (val > 1073741824ULL) { tmp /= 1073741824ULL; suffix = "GiB"; } else if (val > 1048576) { tmp /= 1048576; suffix = "MiB"; } else if (val > 1024) { tmp /= 1024; suffix = "KiB"; } snprintf(buf, len, "%lu.%lu %s", tmp / 10, tmp % 10, suffix); } static void format_time(char *buf, size_t len, time_t diff) { unsigned hh, mm, ss; hh = diff / 3600; diff %= 3600; mm = diff / 60; diff %= 60; ss = diff; snprintf(buf, len, "%02u:%02u:%02u", hh, mm, ss); } static void proxy_free(struct uring_task *task) { struct server_proxy *proxy = container_of(task, struct server_proxy, task); char cts[100]; char stc[100]; char duration[100]; fprintf(stderr, "%s: %s\n", __func__, proxy->scfg->name); if (proxy->begin > 0) { format_time(duration, sizeof(duration), time(NULL) - proxy->begin); format_bytes(cts, sizeof(cts), proxy->client_bytes); format_bytes(stc, sizeof(stc), proxy->server_bytes); fprintf(stderr, "%s: proxy connection %s -> %s closed " "(CtS: %s, StC: %s), duration %s\n", proxy->scfg->name, proxy->client_conn.remotestr, proxy->server_conn.remotestr, cts, stc, duration); } list_del(&proxy->list); xfree(proxy); } static void proxy_client_free(struct uring_task *task) { struct server_proxy *proxy = container_of(task, struct server_proxy, clienttask); fprintf(stderr, "%s: %s client connection closed\n", __func__, proxy->scfg->name); } static void proxy_server_free(struct uring_task *task) { struct server_proxy *proxy = container_of(task, struct server_proxy, servertask); fprintf(stderr, "%s: %s server connection closed\n", __func__, proxy->scfg->name); } void proxy_delete(struct cfg *cfg, struct server_proxy *proxy) { fprintf(stderr, "%s: shutting down proxy 0x%p\n", __func__, proxy); uring_task_destroy(cfg, &proxy->servertask); uring_task_destroy(cfg, &proxy->clienttask); uring_task_destroy(cfg, &proxy->task); } static void proxy_client_data_in(struct cfg *cfg, struct uring_task *task, int res); static void proxy_client_data_out(struct cfg *cfg, struct uring_task *task, int res) { struct server_proxy *proxy = container_of(task, struct server_proxy, clienttask); fprintf(stderr, "%s: result was %i\n", __func__, res); if (res <= 0) { uring_task_close_fd(cfg, task); proxy_delete(cfg, proxy); return; } proxy->client_bytes += res; uring_task_set_fd(&proxy->clienttask, proxy->cfd); uring_tbuf_read(cfg, task, proxy_client_data_in); } static void proxy_client_data_in(struct cfg *cfg, struct uring_task *task, int res) { struct server_proxy *proxy = container_of(task, struct server_proxy, clienttask); fprintf(stderr, "%s: result was %i\n", __func__, res); if (res <= 0) { uring_task_close_fd(cfg, task); proxy_delete(cfg, proxy); return; } uring_task_set_fd(&proxy->clienttask, proxy->sfd); uring_tbuf_write(cfg, task, proxy_client_data_out); } static void proxy_server_data_in(struct cfg *cfg, struct uring_task *task, int res); static void proxy_server_data_out(struct cfg *cfg, struct uring_task *task, int res) { struct server_proxy *proxy = container_of(task, struct server_proxy, servertask); fprintf(stderr, "%s: result was %i\n", __func__, res); if (res <= 0) { uring_task_close_fd(cfg, task); proxy_delete(cfg, proxy); return; } proxy->server_bytes += res; uring_task_set_fd(&proxy->servertask, proxy->sfd); uring_tbuf_read(cfg, &proxy->servertask, proxy_server_data_in); } static void proxy_server_data_in(struct cfg *cfg, struct uring_task *task, int res) { struct server_proxy *proxy = container_of(task, struct server_proxy, servertask); fprintf(stderr, "%s: result was %i\n", __func__, res); if (res <= 0) { uring_task_close_fd(cfg, task); proxy_delete(cfg, proxy); return; } uring_task_set_fd(&proxy->servertask, proxy->cfd); uring_tbuf_write(cfg, task, proxy_server_data_out); } static void proxy_connected_cb(struct cfg *cfg, struct connection *conn, int res) { struct server_proxy *proxy = container_of(conn, struct server_proxy, server_conn); if (res < 0) { fprintf(stderr, "%s: proxy connection to remote server failed\n", proxy->scfg->name); proxy_delete(cfg, proxy); return; } proxy->sfd = proxy->servertask.fd; fprintf(stderr, "%s: proxy connection %s -> %s opened\n", proxy->scfg->name, proxy->client_conn.remotestr, proxy->server_conn.remotestr); proxy->begin = time(NULL); uring_tbuf_read(cfg, &proxy->clienttask, proxy_client_data_in); uring_tbuf_read(cfg, &proxy->servertask, proxy_server_data_in); } struct server_proxy * proxy_new(struct cfg *cfg, struct server *scfg, struct sockaddr_in46 *client, int fd) { struct server_proxy *proxy; proxy = zmalloc(sizeof(*proxy)); if (!proxy) { perror("malloc"); return NULL; } proxy->sfd = -1; proxy->cfd = fd; proxy->scfg = scfg; uring_task_init(&proxy->task, "proxy", &scfg->task, proxy_free); connection_set_local(cfg, &proxy->client_conn, fd); connection_set_remote(cfg, &proxy->client_conn, client); uring_task_init(&proxy->clienttask, "proxy_client", &proxy->task, proxy_client_free); uring_task_set_buf(&proxy->clienttask, &proxy->clientbuf); uring_task_set_fd(&proxy->clienttask, fd); uring_task_init(&proxy->servertask, "proxy_server", &proxy->task, proxy_server_free); uring_task_set_buf(&proxy->servertask, &proxy->serverbuf); list_add(&proxy->list, &scfg->proxys); connect_any(cfg, &proxy->servertask, &scfg->remotes, &proxy->server_conn, proxy_connected_cb); return proxy; }