Skip to content

Commit

Permalink
Merge pull request #423 from openziti/ziti-prox-c.hosting
Browse files Browse the repository at this point in the history
add binding option to ziti-prox-c (reverse proxy mode)
  • Loading branch information
ekoby authored Jul 1, 2022
2 parents c6ee0f9 + ed4a093 commit 068b528
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 36 deletions.
41 changes: 25 additions & 16 deletions inc_internal/utils.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
/*
Copyright 2019-2020 NetFoundry, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright (c) 2022. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ZITI_TLS_UTILS_H
#define ZITI_TLS_UTILS_H
Expand All @@ -24,6 +22,7 @@ limitations under the License.
#include <stdlib.h>
#include <uv_mbed/queue.h>
#include <ziti/ziti_log.h>
#include "ziti/model_collections.h"

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -108,11 +107,21 @@ if (!uv_is_closing((uv_handle_t*)(h))) uv_close((uv_handle_t*)(h), (uv_close_cb)
}}while(0)



void ziti_alloc_cb(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);

int get_url_data(const char *url, struct http_parser_url *parser, int uf, char *out, size_t maxout);

/**
* Split string based on delimiters.
* strings are appended to the provided list. Caller is responsible to freeing resulting strings -
* possibly via `model_list_clear(result, free)`
* @param str
* @param delim
* @param result
* @return number of tokens
*/
extern size_t str_split(const char *str, const char *delim, model_list *result);

#ifdef __cplusplus
}
#endif
Expand Down
53 changes: 37 additions & 16 deletions library/utils.c
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
/*
Copyright 2019-2020 NetFoundry, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright (c) 2022. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <uv.h>
#include <uv_mbed/uv_mbed.h>
Expand Down Expand Up @@ -405,10 +403,33 @@ void hexify(const uint8_t *bin, size_t bin_len, char sep, char **buf) {
char *p = out;
for (int i = 0; i < bin_len; i++) {
unsigned char b = bin[i];
if (sep && i > 0) *p++ = sep;
if (sep && i > 0) { *p++ = sep; }
*p++ = hex[b >> 4];
*p++ = hex[b & 0xf];
}
*p = 0;
*buf = out;
}


size_t str_split(const char *str, const char *delim, model_list *result) {
size_t count = 0;
if (str) {
const char *sep = str;
do {
const char *s = sep;
char *val;
if ((sep = strpbrk(s, delim)) != NULL) {
size_t tok_len = sep++ - s;
val = calloc(1, tok_len + 1);
strncpy(val, s, tok_len);
} else {
val = strdup(s);
}
model_list_append(result, val);
count++;
} while (sep);
}

return count;
}
125 changes: 121 additions & 4 deletions programs/ziti-prox-c/proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,17 @@ static struct sig_handlers {

struct proxy_app_ctx {
model_map listeners;
model_map bindings;
LIST_HEAD(clients, client) clients;
ziti_context ziti;
};

struct binding {
char *service_name;
ziti_connection conn;
struct addrinfo *addr;
};

struct listener {
char *service_name;
int port;
Expand Down Expand Up @@ -133,10 +140,20 @@ static void process_stop(uv_loop_t *loop, struct proxy_app_ctx *app_ctx) {
}

static void debug_dump(struct proxy_app_ctx *app_ctx) {
printf("==== listeners ====\n");
MODEL_MAP_FOR(it, app_ctx->listeners) {
struct listener *l = model_map_it_value(it);
printf("listening for service[%s] on port[%d]\n", l->service_name, l->port);
}

printf("\n==== bindings ====\n");
MODEL_MAP_FOR(it, app_ctx->bindings) {
struct binding *b = model_map_it_value(it);
char addr[24];
uv_getnameinfo_t name;
uv_getnameinfo(global_loop, &name, NULL, b->addr->ai_addr, NI_NUMERICHOST);
printf("bound to service[%s] -> %s:%s\n", b->service_name, name.host, name.service);
}
ziti_dump(app_ctx->ziti, fprintf, stdout);
}

Expand Down Expand Up @@ -283,13 +300,73 @@ static void update_listener(ziti_service *service, int status, struct listener *
}
}

static void binding_listen_cb(ziti_connection srv, int status) {
struct binding *b = ziti_conn_data(srv);
if (status != ZITI_OK) {
ZITI_LOG(WARN, "failed to bind to service[%s]", b->service_name);
ziti_close(b->conn, NULL);
b->conn = NULL;
}
}

static void on_ziti_accept(ziti_connection clt, int status) {
uv_stream_t *s = ziti_conn_data(clt);
if (status == ZITI_OK) {
ziti_conn_bridge(clt, s, on_bridge_close);
} else {
ziti_close(clt, NULL);
uv_close(s, on_bridge_close);
}
}

static void on_tcp_connect(uv_connect_t *conn_req, int status) {
ziti_connection clt = conn_req->data;
if (status == 0) {
ziti_conn_set_data(clt, conn_req->handle);
ziti_accept(clt, on_ziti_accept, NULL);
} else {
uv_close((uv_handle_t *) conn_req->handle, on_bridge_close);
ziti_close(clt, NULL);
}
free(conn_req);
}

static void binding_client_cb(ziti_connection srv, ziti_connection clt, int status, ziti_client_ctx *clt_ctx) {
struct binding *b = ziti_conn_data(srv);

if (status == ZITI_OK) {
NEWP(tcp, uv_tcp_t);
uv_tcp_init(global_loop, tcp);

NEWP(conn_req, uv_connect_t);
conn_req->data = clt;
if (uv_tcp_connect(conn_req, tcp, b->addr->ai_addr, on_tcp_connect) != 0) {
ziti_close(clt, NULL);
uv_close((uv_handle_t *) tcp, (uv_close_cb) free);
free(conn_req);
}
} else {
ZITI_LOG(WARN, "stopping serving[%s] due to %d/%s", b->service_name, status, ziti_errorstr(status));
ziti_close(b->conn, NULL);
b->conn = NULL;
}
}

static void service_check_cb(ziti_context ztx, ziti_service *service, int status, void *ctx) {
struct proxy_app_ctx *app_ctx = ctx;
ZITI_LOG(DEBUG, "service[%s]: %s", service->name, ziti_errorstr(status));
struct listener *l = model_map_get(&app_ctx->listeners, service->name);
if (l) {
update_listener(service, status, l);
}

struct binding *b = model_map_get(&app_ctx->bindings, service->name);
if (b && (service->perm_flags & ZITI_CAN_BIND) != 0) {
if (b->conn == NULL) {
ziti_conn_init(ztx, &b->conn, b);
ziti_listen(b->conn, b->service_name, binding_listen_cb, binding_client_cb);
}
}
}

static void on_ziti_event(ziti_context ztx, const ziti_event_t *event) {
Expand Down Expand Up @@ -440,7 +517,7 @@ void mfa_auth_event_handler(ziti_context ztx) {
uv_queue_work(global_loop, &mfa_wr->w, mfa_worker, mfa_worker_done);
}


static struct proxy_app_ctx app_ctx = {0};
void run(int argc, char **argv) {

PREPF(uv, uv_strerror);
Expand All @@ -449,7 +526,7 @@ void run(int argc, char **argv) {
uv_loop_init(loop);
global_loop = loop;

struct proxy_app_ctx app_ctx = {0};

for (int i = 0; i < argc; i++) {

char *p = strchr(argv[i], ':');
Expand Down Expand Up @@ -533,7 +610,8 @@ int run_opts(int argc, char **argv) {
{"debug", optional_argument, NULL, 'd'},
{"config", required_argument, NULL, 'c'},
{"metrics", optional_argument, NULL, 'm'},
{NULL, 0, NULL, 0}
{"bind", required_argument, NULL, 'b'},
{NULL, 0, NULL, 0}
};

int c, option_index, errors = 0;
Expand All @@ -542,7 +620,7 @@ int run_opts(int argc, char **argv) {

optind = 0;

while ((c = getopt_long(argc, argv, "d:c:m:",
while ((c = getopt_long(argc, argv, "b:c:d:m:",
long_options, &option_index)) != -1) {
switch (c) {
case 'd':
Expand All @@ -565,6 +643,45 @@ int run_opts(int argc, char **argv) {
}
break;

case 'b':
if (!optarg) {
fprintf(stderr, "-b|--bind option requires <service:address> argument\n");
errors++;
break;
}

model_list args = {0};
str_split(optarg, ":", &args);
size_t args_len = model_list_size(&args);
if (args_len < 2) {
fprintf(stderr, "-b|--bind option should be <service:host:port>\n");
errors++;
break;
}
model_list_iter it = model_list_iterator(&args);
NEWP(b, struct binding);
b->service_name = model_list_it_element(it);
it = model_list_it_remove(it);

if (model_list_size(&args) > 1) {
char *host = model_list_it_element(it);
if (strlen(host) == 0) {
host = "localhost";
}
it = model_list_it_next(it);
char *port = model_list_it_element(it);

int rc = getaddrinfo(host, port, NULL, &b->addr);
if (rc != 0) {
errors++;
fprintf(stderr, "failed to resolve %s:%s for service[%s] binding", host, port, b->service_name);
}
model_map_set(&app_ctx.bindings, b->service_name, b);
}

model_list_clear(&args, free);
break;

default: {
fprintf(stderr, "Unknown option \"%c\"\n", c);
errors++;
Expand Down

0 comments on commit 068b528

Please sign in to comment.