From 7411ff1fcaf8a0b819c6232bc2cad5f97f705242 Mon Sep 17 00:00:00 2001 From: Alexander Alashkin Date: Fri, 28 Oct 2016 18:16:58 +0100 Subject: [PATCH] Drop load_balancer example PUBLISHED_FROM=d823db5e8b2831201e22bbdd3188e93bbbbbbb09 --- examples/Makefile | 2 +- examples/load_balancer/Dockerfile | 10 - examples/load_balancer/Makefile | 39 -- examples/load_balancer/README.md | 44 -- examples/load_balancer/load_balancer.c | 646 ------------------------- examples/load_balancer/unit_test.sh | 21 - 6 files changed, 1 insertion(+), 761 deletions(-) delete mode 100644 examples/load_balancer/Dockerfile delete mode 100644 examples/load_balancer/Makefile delete mode 100644 examples/load_balancer/README.md delete mode 100644 examples/load_balancer/load_balancer.c delete mode 100644 examples/load_balancer/unit_test.sh diff --git a/examples/Makefile b/examples/Makefile index 08d173a8..2aae2ccb 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -6,7 +6,7 @@ SUBDIRS = $(sort $(dir $(wildcard ./*/))) SUBDIRS:=$(filter-out ./ ./CC3200/ ./ESP8266_RTOS/ ./MSP432/ ./NXP_K64/ ./PIC32/ ./STM32F4_CC3100/ ./mbed/ ./nRF51/ ./nRF52/, $(SUBDIRS)) ifeq ($(OS), Windows_NT) - SUBDIRS:=$(filter-out ./load_balancer/ ./netcat/ ./raspberry_pi_mjpeg_led/ ./captive_dns_server/, $(SUBDIRS)) + SUBDIRS:=$(filter-out ./netcat/ ./raspberry_pi_mjpeg_led/ ./captive_dns_server/, $(SUBDIRS)) endif .PHONY: $(SUBDIRS) diff --git a/examples/load_balancer/Dockerfile b/examples/load_balancer/Dockerfile deleted file mode 100644 index caeec8a9..00000000 --- a/examples/load_balancer/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM cesanta/mongoose - -COPY load_balancer.c /mongoose/ -WORKDIR /mongoose -RUN mkdir /mongoose/certs; \ - sed -i 's:#include "../../mongoose.h":#include "mongoose.h":' load_balancer.c; \ - cc load_balancer.c mongoose.c -o load_balancer -W -Wall -pthread -DMG_ENABLE_SSL -lssl -lcrypto -EXPOSE 8000 -VOLUME ["/mongoose/certs"] -ENTRYPOINT ["/mongoose/load_balancer"] diff --git a/examples/load_balancer/Makefile b/examples/load_balancer/Makefile deleted file mode 100644 index 50ac1285..00000000 --- a/examples/load_balancer/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# To build with SSL under windows, do: -# wine make load_balancer.exe SSL=openssl # OpenSSL build -# wine make load_balancer.exe SSL=krypton # Krypton build - -PROG = load_balancer -SOURCES = $(PROG).c ../../mongoose.c -CFLAGS = -W -Wall -pthread $(CFLAGS_EXTRA) - -ifeq ($(SSL), openssl) - OPENSSL_PATH = ./openssl-0.9.8 - CFLAGS_EXTRA += -DMG_ENABLE_SSL -I$(OPENSSL_PATH)/include - CFLAGS_EXTRA += /link /libpath:$(OPENSSL_PATH)/lib ssleay32.lib libeay32.lib -endif - -ifeq ($(SSL), krypton) - KRYPTON_PATH = ../../../krypton - CFLAGS_EXTRA += -DMG_ENABLE_SSL $(KRYPTON_PATH)/krypton.c -I$(KRYPTON_PATH) -endif - -all: $(PROG) - -$(PROG): $(SOURCES) - $(CC) $(SOURCES) -o $@ $(CFLAGS) - -$(PROG).exe: $(SOURCES) - cl $(SOURCES) /I.. /MD /Fe$@ /DMG_ENABLE_THREADS advapi32.lib $(CFLAGS_EXTRA) - -test: $(PROG) - $(MAKE) -C ../api_server - sh unit_test.sh $$(pwd)/$(PROG) - -docker-build: - docker build -t cesanta/load_balancer . - -docker-push: - docker push cesanta/load_balancer - -clean: - rm -rf *.gc* *.dSYM *.exe *.obj *.o a.out $(PROG) diff --git a/examples/load_balancer/README.md b/examples/load_balancer/README.md deleted file mode 100644 index ec5551a3..00000000 --- a/examples/load_balancer/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Mongoose-based HTTP load balancer - -## Configuration - -Load balancer is configured with command-line flags. - -### Global flags - -* `-p port` – TCP port to listen on. Default: 8000. -* `-l log_file` – path to the log file. Default: none. -* `-s ssl_cert` – path to SSL certificate. Default: none. - -### Backend configuration - -Main flag is `-b uri_prefix host_port` – it adds a new backend for a given -URI prefix. Example: `-b /stuff/ 127.0.0.1:8080` will route all requests that -start with '/stuff/' to a backend at port 8080 on localhost. There is a special -syntax for `uri_prefix` that allows you to change the URIs that get passed to -backends: - -* `-b /stuff/=/ 127.0.0.1:8080` – for '/stuff/thing' backend will see '/thing'. -* `-b /stuff/=/other/ 127.0.0.1:8080` – '/stuff/thing' => '/other/thing'. - -Also there are few per-backend flags that can be placed before `-b` and apply -only to the next backend: - -* `-r` – instead of proxying requests load balancer will reply with 302 -redirect. -* `-v vhost` – match not only URI prefix but 'Host:' header as well. - -### Example - -``` -load_balancer -s path/to/cert.pem \ - -v example.com -b /site/=/ 127.0.0.1:8080 \ - -b /static/ 127.0.0.1:8081 \ - -b /static/ 127.0.0.1:8082 -``` - -In this example requests to 'example.com/site/' will be forwarded to the -backend on port 8080 with '/site' prefix stripped off and requests to -'/static/' on any virtual host will be balanced in round-robin fashion between -backends on ports 8081 and 8082. - diff --git a/examples/load_balancer/load_balancer.c b/examples/load_balancer/load_balancer.c deleted file mode 100644 index 52760bdd..00000000 --- a/examples/load_balancer/load_balancer.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Copyright (c) 2014 Cesanta Software Limited - * All rights reserved - */ - -#include "../../mongoose.h" -#include - -#define MAX_IDLE_CONNS 5 -#define CONN_IDLE_TIMEOUT 30 - -struct http_backend; - -struct be_conn { - struct http_backend *be; - struct mg_connection *nc; - time_t idle_deadline; - - STAILQ_ENTRY(be_conn) conns; -}; - -STAILQ_HEAD(be_conn_list_head, be_conn); -struct http_backend { - const char *vhost; /* NULL if any host */ - const char *uri_prefix; /* URI prefix, e.g. "/api/v1/", "/static/" */ - const char *uri_prefix_replacement; /* if not NULL, will replace uri_prefix in - requests to backends */ - const char *host_port; /* Backend address */ - int redirect; /* if true redirect instead of proxy */ - int usage_counter; /* Number of times this backend was chosen */ - - struct be_conn_list_head conns; - int num_conns; -}; - -struct peer { - struct mg_connection *nc; - int64_t body_len; /* Size of the HTTP body to forward */ - int64_t body_sent; /* Number of bytes already forwarded */ - struct { - /* Headers have been sent, no more headers. */ - unsigned int headers_sent : 1; - unsigned int keep_alive : 1; - } flags; -}; - -struct conn_data { - struct be_conn *be_conn; /* Chosen backend */ - struct peer client; /* Client peer */ - struct peer backend; /* Backend peer */ - time_t last_activity; -}; - -static const char *s_error_500 = "HTTP/1.1 500 Failed\r\n"; -static const char *s_content_len_0 = "Content-Length: 0\r\n"; -static const char *s_connection_close = "Connection: close\r\n"; -static const char *s_http_port = "8000"; -static struct http_backend s_vhost_backends[100], s_default_backends[100]; -static int s_num_vhost_backends = 0, s_num_default_backends = 0; -static int s_sig_num = 0; -static int s_backend_keepalive = 0; -static FILE *s_log_file = NULL; -#if MG_ENABLE_SSL -const char *s_ssl_cert = NULL; -#endif - -static void ev_handler(struct mg_connection *nc, int ev, void *ev_data); -static void write_log(const char *fmt, ...); - -static void signal_handler(int sig_num) { - signal(sig_num, signal_handler); - s_sig_num = sig_num; -} - -static void send_http_err(struct mg_connection *nc, const char *err_line) { - mg_printf(nc, "%s%s%s\r\n", err_line, s_content_len_0, s_connection_close); -} - -static void respond_with_error(struct conn_data *conn, const char *err_line) { - struct mg_connection *nc = conn->client.nc; - int headers_sent = conn->client.flags.headers_sent; -#ifdef DEBUG - write_log("conn=%p nc=%p respond_with_error %d\n", conn, nc, headers_sent); -#endif - if (nc == NULL) return; - if (!headers_sent) { - send_http_err(nc, err_line); - conn->client.flags.headers_sent = 1; - } - nc->flags |= MG_F_SEND_AND_CLOSE; -} - -static int has_prefix(const struct mg_str *uri, const char *prefix) { - size_t prefix_len = strlen(prefix); - return uri->len >= prefix_len && memcmp(uri->p, prefix, prefix_len) == 0; -} - -static int matches_vhost(const struct mg_str *host, const char *vhost) { - size_t vhost_len; - if (vhost == NULL) { - return 1; - } - vhost_len = strlen(vhost); - return host->len == vhost_len && memcmp(host->p, vhost, vhost_len) == 0; -} - -static void write_log(const char *fmt, ...) { - va_list ap; - if (s_log_file != NULL) { - va_start(ap, fmt); - vfprintf(s_log_file, fmt, ap); - fflush(s_log_file); - va_end(ap); - } -} - -static struct http_backend *choose_backend_from_list( - struct http_message *hm, struct http_backend *backends, int num_backends) { - int i; - struct mg_str vhost = {"", 0}; - const struct mg_str *host = mg_get_http_header(hm, "host"); - if (host != NULL) vhost = *host; - - const char *vhost_end = vhost.p; - - while (vhost_end < vhost.p + vhost.len && *vhost_end != ':') { - vhost_end++; - } - vhost.len = vhost_end - vhost.p; - - struct http_backend *chosen = NULL; - for (i = 0; i < num_backends; i++) { - struct http_backend *be = &backends[i]; - if (has_prefix(&hm->uri, be->uri_prefix) && - matches_vhost(&vhost, be->vhost) && - (chosen == NULL || - /* Prefer most specific URI prefixes */ - strlen(be->uri_prefix) > strlen(chosen->uri_prefix) || - /* Among prefixes of the same length chose the least used. */ - (strlen(be->uri_prefix) == strlen(chosen->uri_prefix) && - be->usage_counter < chosen->usage_counter))) { - chosen = be; - } - } - - return chosen; -} - -static struct http_backend *choose_backend(struct http_message *hm) { - struct http_backend *chosen = - choose_backend_from_list(hm, s_vhost_backends, s_num_vhost_backends); - - /* Nothing was chosen for this vhost, look for vhost == NULL backends. */ - if (chosen == NULL) { - chosen = choose_backend_from_list(hm, s_default_backends, - s_num_default_backends); - } - - if (chosen != NULL) chosen->usage_counter++; - - return chosen; -} - -static void forward_body(struct peer *src, struct peer *dst) { - struct mbuf *src_io = &src->nc->recv_mbuf; - if (src->body_sent < src->body_len) { - size_t to_send = src->body_len - src->body_sent; - if (src_io->len < to_send) { - to_send = src_io->len; - } - mg_send(dst->nc, src_io->buf, to_send); - src->body_sent += to_send; - mbuf_remove(src_io, to_send); - } -#ifdef DEBUG - write_log("forward_body %p (ka=%d) -> %p sent %d of %d\n", src->nc, - src->flags.keep_alive, dst->nc, src->body_sent, src->body_len); -#endif -} - -static void forward(struct conn_data *conn, struct http_message *hm, - struct peer *src_peer, struct peer *dst_peer) { - struct mg_connection *src = src_peer->nc; - struct mg_connection *dst = dst_peer->nc; - struct mbuf *io = &src->recv_mbuf; - int i; - int is_request = (src_peer == &conn->client); - src_peer->body_len = hm->body.len; - struct http_backend *be = conn->be_conn->be; - - if (is_request) { - /* Write rewritten request line. */ - size_t trim_len = strlen(be->uri_prefix); - mg_printf(dst, "%.*s%s%.*s\r\n", (int) (hm->uri.p - io->buf), io->buf, - be->uri_prefix_replacement, - (int) (hm->proto.p + hm->proto.len - (hm->uri.p + trim_len)), - hm->uri.p + trim_len); - } else { - /* Reply line goes without modification */ - mg_printf(dst, "%.*s %d %.*s\r\n", (int) hm->proto.len, hm->proto.p, - (int) hm->resp_code, (int) hm->resp_status_msg.len, - hm->resp_status_msg.p); - } - - /* Headers. */ - for (i = 0; i < MG_MAX_HTTP_HEADERS && hm->header_names[i].len > 0; i++) { - struct mg_str hn = hm->header_names[i]; - struct mg_str hv = hm->header_values[i]; -#if MG_ENABLE_SSL - /* - * If we terminate SSL and backend redirects to local HTTP port, - * strip protocol to let client use HTTPS. - * TODO(lsm): web page content may also contain local HTTP references, - * they need to be rewritten too. - */ - if (mg_vcasecmp(&hn, "Location") == 0 && s_ssl_cert != NULL) { - size_t hlen = strlen(be->host_port); - const char *hp = be->host_port, *p = memchr(hp, ':', hlen); - - if (p == NULL) { - p = hp + hlen; - } - - if (mg_ncasecmp(hv.p, "http://", 7) == 0 && - mg_ncasecmp(hv.p + 7, hp, (p - hp)) == 0) { - mg_printf(dst, "Location: %.*s\r\n", (int) (hv.len - (7 + (p - hp))), - hv.p + 7 + (p - hp)); - continue; - } - } -#endif - - /* We always rewrite the connection header depending on the settings. */ - if (mg_vcasecmp(&hn, "Connection") == 0) continue; - - /* Don't pass chunked transfer encoding to the client */ - if (mg_vcasecmp(&hn, "Transfer-encoding") == 0 && - mg_vcasecmp(&hv, "chunked") == 0) { - continue; - } - - mg_printf(dst, "%.*s: %.*s\r\n", (int) hn.len, hn.p, (int) hv.len, hv.p); - } - - /* Emit the connection header. */ - const char *connection_mode = "close"; - if (dst_peer == &conn->backend) { - if (s_backend_keepalive) connection_mode = "keep-alive"; - } else { - if (conn->client.flags.keep_alive) connection_mode = "keep-alive"; - } - mg_printf(dst, "Connection: %s\r\n", connection_mode); - - mg_printf(dst, "%s", "\r\n"); - - mbuf_remove(io, hm->body.p - hm->message.p); /* We've forwarded headers */ - dst_peer->flags.headers_sent = 1; - - forward_body(src_peer, dst_peer); -} - -struct be_conn *get_conn(struct http_backend *be) { - if (STAILQ_EMPTY(&be->conns)) return NULL; - struct be_conn *result = STAILQ_FIRST(&be->conns); - STAILQ_REMOVE_HEAD(&be->conns, conns); - be->num_conns--; - return result; -} - -/* - * choose_backend parses incoming HTTP request and routes it to the appropriate - * backend. It assumes that clients don't do HTTP pipelining, handling only - * one request request for each connection. To give a hint to backend about - * this it inserts "Connection: close" header into each forwarded request. - */ -static int connect_backend(struct conn_data *conn, struct http_message *hm) { - struct mg_connection *nc = conn->client.nc; - struct http_backend *be = choose_backend(hm); - - write_log("%ld %.*s %.*s backend=%s\n", (long) time(NULL), - (int) hm->method.len, hm->method.p, (int) hm->uri.len, hm->uri.p, - be ? be->host_port : "not defined"); - - if (be == NULL) return 0; - if (be->redirect != 0) { - mg_printf(nc, "HTTP/1.1 302 Found\r\nLocation: %s\r\n\r\n", be->host_port); - return 1; - } - struct be_conn *bec = get_conn(be); - if (bec != NULL) { - bec->nc->handler = ev_handler; -#ifdef DEBUG - write_log("conn=%p to %p (%s) reusing bec=%p\n", conn, be, be->host_port, - bec); -#endif - } else { - bec = malloc(sizeof(*conn->be_conn)); - memset(bec, 0, sizeof(*bec)); - bec->nc = mg_connect(nc->mgr, be->host_port, ev_handler); -#ifdef DEBUG - write_log("conn=%p new conn to %p (%s) bec=%p\n", conn, be, be->host_port, - bec); -#endif - if (bec->nc == NULL) { - free(bec); - write_log("Connection to [%s] failed\n", be->host_port); - return 0; - } - } - bec->be = be; - conn->be_conn = bec; - conn->backend.nc = bec->nc; - conn->backend.nc->user_data = conn; - mg_set_protocol_http_websocket(conn->backend.nc); - return 1; -} - -static int is_keep_alive(struct http_message *hm) { - const struct mg_str *connection_header = mg_get_http_header(hm, "Connection"); - if (connection_header == NULL) { - /* HTTP/1.1 connections are keep-alive by default. */ - if (mg_vcasecmp(&hm->proto, "HTTP/1.1") != 0) return 0; - } else if (mg_vcasecmp(connection_header, "keep-alive") != 0) { - return 0; - } - // We must also have Content-Length. - return mg_get_http_header(hm, "Content-Length") != NULL; -} - -static void idle_backend_handler(struct mg_connection *nc, int ev, - void *ev_data) { - (void) ev_data; /* Unused. */ - struct be_conn *bec = nc->user_data; - const time_t now = time(NULL); -#ifdef DEBUG - write_log("%d idle bec=%p nc=%p ev=%d deadline=%d\n", now, bec, nc, ev, - bec->idle_deadline); -#endif - switch (ev) { - case MG_EV_POLL: { - if (bec->idle_deadline > 0 && now > bec->idle_deadline) { -#ifdef DEBUG - write_log("bec=%p nc=%p closing due to idleness\n", bec, bec->nc); -#endif - bec->nc->flags |= MG_F_CLOSE_IMMEDIATELY; - } - break; - } - - case MG_EV_CLOSE: { -#ifdef DEBUG - write_log("bec=%p closed\n", bec); -#endif - if (bec->idle_deadline > 0) { - STAILQ_REMOVE(&bec->be->conns, bec, be_conn, conns); - } - free(bec); - break; - } - } -} - -void release_backend(struct conn_data *conn) { - /* Disassociate the backend, put back on the pool. */ - struct be_conn *bec = conn->be_conn; - conn->be_conn = NULL; - if (bec->nc == NULL) { - free(bec); - memset(&conn->backend, 0, sizeof(conn->backend)); - return; - } - struct http_backend *be = bec->be; - bec->nc->user_data = bec; - bec->nc->handler = idle_backend_handler; - if (conn->backend.flags.keep_alive) { - bec->idle_deadline = time(NULL) + CONN_IDLE_TIMEOUT; - STAILQ_INSERT_TAIL(&be->conns, bec, conns); -#ifdef DEBUG - write_log("bec=%p becoming idle\n", bec); -#endif - be->num_conns++; - while (be->num_conns > MAX_IDLE_CONNS) { - bec = STAILQ_FIRST(&be->conns); - STAILQ_REMOVE_HEAD(&be->conns, conns); - be->num_conns--; - bec->idle_deadline = 0; - bec->nc->flags = MG_F_CLOSE_IMMEDIATELY; -#ifdef DEBUG - write_log("bec=%p evicted\n", bec); -#endif - } - } else { - bec->idle_deadline = 0; - bec->nc->flags |= MG_F_CLOSE_IMMEDIATELY; - } - memset(&conn->backend, 0, sizeof(conn->backend)); -} - -static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { - struct conn_data *conn = (struct conn_data *) nc->user_data; - const time_t now = time(NULL); -#ifdef DEBUG - write_log("%d conn=%p nc=%p ev=%d ev_data=%p bec=%p bec_nc=%p\n", now, conn, - nc, ev, ev_data, conn != NULL ? conn->be_conn : NULL, - conn != NULL && conn->be_conn != NULL ? conn->be_conn->nc : NULL); -#endif - - if (conn == NULL) { - if (ev == MG_EV_ACCEPT) { - conn = calloc(1, sizeof(*conn)); - if (conn == NULL) { - send_http_err(nc, s_error_500); - } else { - memset(conn, 0, sizeof(*conn)); - nc->user_data = conn; - conn->client.nc = nc; - conn->client.body_len = -1; - conn->backend.body_len = -1; - conn->last_activity = now; - } - return; - } else { - if (ev != MG_EV_POLL) { - nc->flags |= MG_F_CLOSE_IMMEDIATELY; - } - return; - } - } - - if (ev != MG_EV_POLL) conn->last_activity = now; - - switch (ev) { - case MG_EV_HTTP_REQUEST: { /* From client */ - assert(conn != NULL); - assert(conn->be_conn == NULL); - struct http_message *hm = (struct http_message *) ev_data; - conn->client.flags.keep_alive = is_keep_alive(hm); - - if (!connect_backend(conn, hm)) { - respond_with_error(conn, s_error_500); - break; - } - - if (conn->backend.nc == NULL) { - /* This is a redirect, we're done. */ - conn->client.nc->flags |= MG_F_SEND_AND_CLOSE; - break; - } - - forward(conn, hm, &conn->client, &conn->backend); - break; - } - - case MG_EV_CONNECT: { /* To backend */ - assert(conn != NULL); - assert(conn->be_conn != NULL); - int status = *(int *) ev_data; - if (status != 0) { - write_log("Error connecting to %s: %d (%s)\n", - conn->be_conn->be->host_port, status, strerror(status)); - /* TODO(lsm): mark backend as defunct, try it later on */ - respond_with_error(conn, s_error_500); - conn->be_conn->nc = NULL; - release_backend(conn); - break; - } - break; - } - - case MG_EV_HTTP_REPLY: { /* From backend */ - assert(conn != NULL); - struct http_message *hm = (struct http_message *) ev_data; - conn->backend.flags.keep_alive = s_backend_keepalive && is_keep_alive(hm); - forward(conn, hm, &conn->backend, &conn->client); - release_backend(conn); - if (!conn->client.flags.keep_alive) { - conn->client.nc->flags |= MG_F_SEND_AND_CLOSE; - } else { -#ifdef DEBUG - write_log("conn=%p remains open\n", conn); -#endif - } - break; - } - - case MG_EV_POLL: { - assert(conn != NULL); - if (now - conn->last_activity > CONN_IDLE_TIMEOUT && - conn->backend.nc == NULL /* not waiting for backend */) { -#ifdef DEBUG - write_log("conn=%p has been idle for too long\n", conn); - conn->client.nc->flags |= MG_F_SEND_AND_CLOSE; -#endif - } - break; - } - - case MG_EV_CLOSE: { - assert(conn != NULL); - if (nc == conn->client.nc) { -#ifdef DEBUG - write_log("conn=%p nc=%p client closed, body_sent=%d\n", conn, nc, - conn->backend.body_sent); -#endif - conn->client.nc = NULL; - if (conn->backend.nc != NULL) { - conn->backend.nc->flags |= MG_F_CLOSE_IMMEDIATELY; - } - } else if (nc == conn->backend.nc) { -#ifdef DEBUG - write_log("conn=%p nc=%p backend closed\n", conn, nc); -#endif - conn->backend.nc = NULL; - if (conn->client.nc != NULL && - (conn->backend.body_len < 0 || - conn->backend.body_sent < conn->backend.body_len)) { - write_log("Backend %s disconnected.\n", conn->be_conn->be->host_port); - respond_with_error(conn, s_error_500); - } - } - if (conn->client.nc == NULL && conn->backend.nc == NULL) { - free(conn); - } - break; - } - } -} - -static void print_usage_and_exit(const char *prog_name) { - fprintf(stderr, - "Usage: %s [-D debug_dump_file] [-p http_port] [-l log] [-k]" -#if MG_ENABLE_SSL - "[-s ssl_cert] " -#endif - "<[-r] [-v vhost] -b uri_prefix[=replacement] host_port> ... \n", - prog_name); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) { - struct mg_mgr mgr; - struct mg_connection *nc; - int i, redirect = 0; - const char *vhost = NULL; - - mg_mgr_init(&mgr, NULL); - - /* Parse command line arguments */ - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-D") == 0) { - mgr.hexdump_file = argv[i + 1]; - i++; - } else if (strcmp(argv[i], "-k") == 0) { - s_backend_keepalive = 1; - } else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) { - if (strcmp(argv[i + 1], "-") == 0) { - s_log_file = stdout; - } else { - s_log_file = fopen(argv[i + 1], "a"); - if (s_log_file == NULL) { - perror("fopen"); - exit(EXIT_FAILURE); - } - } - i++; - } else if (strcmp(argv[i], "-p") == 0) { - s_http_port = argv[i + 1]; - i++; - } else if (strcmp(argv[i], "-r") == 0 && i + 1 < argc) { - redirect = 1; - } else if (strcmp(argv[i], "-v") == 0 && i + 1 < argc) { - if (strcmp(argv[i + 1], "") == 0) { - vhost = NULL; - } else { - vhost = argv[i + 1]; - } - i++; - } else if (strcmp(argv[i], "-b") == 0 && i + 2 < argc) { - struct http_backend *be = - vhost != NULL ? &s_vhost_backends[s_num_vhost_backends++] - : &s_default_backends[s_num_default_backends++]; - STAILQ_INIT(&be->conns); - char *r = NULL; - be->vhost = vhost; - be->uri_prefix = argv[i + 1]; - be->host_port = argv[i + 2]; - be->redirect = redirect; - be->uri_prefix_replacement = be->uri_prefix; - if ((r = strchr(be->uri_prefix, '=')) != NULL) { - *r = '\0'; - be->uri_prefix_replacement = r + 1; - } - printf( - "Adding backend for %s%s : %s " - "[redirect=%d,prefix_replacement=%s]\n", - be->vhost == NULL ? "" : be->vhost, be->uri_prefix, be->host_port, - be->redirect, be->uri_prefix_replacement); - vhost = NULL; - redirect = 0; - i += 2; -#if MG_ENABLE_SSL - } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) { - s_ssl_cert = argv[++i]; -#endif - } else { - print_usage_and_exit(argv[0]); - } - } - - /* Open listening socket */ - if ((nc = mg_bind(&mgr, s_http_port, ev_handler)) == NULL) { - fprintf(stderr, "mg_bind(%s) failed\n", s_http_port); - exit(EXIT_FAILURE); - } - -#if MG_ENABLE_SSL - if (s_ssl_cert != NULL) { - const char *err_str = mg_set_ssl(nc, s_ssl_cert, NULL); - if (err_str != NULL) { - fprintf(stderr, "Error loading SSL cert: %s\n", err_str); - exit(1); - } - } -#endif - mg_set_protocol_http_websocket(nc); - - if (s_num_vhost_backends + s_num_default_backends == 0) { - print_usage_and_exit(argv[0]); - } - - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - - /* Run event loop until signal is received */ - printf("Starting LB on port %s\n", s_http_port); - while (s_sig_num == 0) { - mg_mgr_poll(&mgr, 1000); - } - - /* Cleanup */ - mg_mgr_free(&mgr); - - printf("Exiting on signal %d\n", s_sig_num); - - return EXIT_SUCCESS; -} diff --git a/examples/load_balancer/unit_test.sh b/examples/load_balancer/unit_test.sh deleted file mode 100644 index 019fafda..00000000 --- a/examples/load_balancer/unit_test.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -PROG=$1 -PORT=8002 - -cleanup() { - kill -9 $PID >/dev/null 2>&1 -} - -#set -x -trap cleanup EXIT - -cleanup -$PROG -p $PORT -b /api/ 127.0.0.1:8000 & -PID=$! - -# Perform api_server unit test through the load balancer by passing -# load balancer port to the unit test script -(cd ../api_server && make && sh unit_test.sh ./api_server $PORT) - -exit $?