mirror of
https://github.com/openziti/ziti-sdk-c.git
synced 2026-09-11 01:05:38 +00:00
239 lines
6.7 KiB
C
239 lines
6.7 KiB
C
/*
|
|
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.
|
|
*/
|
|
|
|
#include <ziti/errors.h>
|
|
#include <ziti/ziti.h>
|
|
#include <string.h>
|
|
|
|
#define DIE(v) do { \
|
|
int code = (v);\
|
|
if (code != ZITI_OK) {\
|
|
fprintf(stderr, "ERROR: " #v " => %s\n", ziti_errorstr(code));\
|
|
exit(code);\
|
|
}} while(0)
|
|
|
|
|
|
static ziti_context ziti;
|
|
static int server = 0;
|
|
static const char *service;
|
|
|
|
static void on_client_write(ziti_connection clt, ssize_t status, void *ctx) {
|
|
free(ctx);
|
|
}
|
|
|
|
static ssize_t on_client_data(ziti_connection clt, const uint8_t *data, ssize_t len) {
|
|
if (len > 0) {
|
|
printf("client sent:%.*s\n", (int) len, data);
|
|
char *reply = malloc(128);
|
|
size_t l = sprintf(reply, "%zd", len);
|
|
ziti_write(clt, (uint8_t *) reply, l, on_client_write, reply);
|
|
}
|
|
else if (len == ZITI_EOF) {
|
|
printf("client disconnected\n");
|
|
ziti_close_write(clt);
|
|
}
|
|
else {
|
|
fprintf(stderr, "error: %zd(%s)", len, ziti_errorstr(len));
|
|
ziti_close(clt, NULL);
|
|
}
|
|
return len;
|
|
}
|
|
|
|
static void on_client_connect(ziti_connection clt, int status) {
|
|
if (status == ZITI_OK) {
|
|
const char *msg = "Hello from byte counter!";
|
|
ziti_write(clt, (uint8_t *) msg, strlen(msg), on_client_write, NULL);
|
|
}
|
|
}
|
|
|
|
static void on_client(ziti_connection serv, ziti_connection client, int status, const ziti_client_ctx *clt_ctx) {
|
|
if (status == ZITI_OK) {
|
|
const char *source_identity = clt_ctx->caller_id;
|
|
if (source_identity != NULL) {
|
|
fprintf(stderr, "incoming connection from '%s'\n", source_identity);
|
|
}
|
|
else {
|
|
fprintf(stderr, "incoming connection from unidentified client\n");
|
|
}
|
|
if (clt_ctx->app_data != NULL) {
|
|
fprintf(stderr, "got app data '%.*s'!\n", (int) clt_ctx->app_data_sz, clt_ctx->app_data);
|
|
}
|
|
ziti_accept(client, on_client_connect, on_client_data);
|
|
} else {
|
|
fprintf(stderr, "failed to accept client: %s(%d)\n", ziti_errorstr(status), status);
|
|
}
|
|
}
|
|
|
|
static void listen_cb(ziti_connection serv, int status) {
|
|
if (status == ZITI_OK) {
|
|
printf("Byte Counter is ready! %d(%s)\n", status, ziti_errorstr(status));
|
|
}
|
|
else {
|
|
printf("ERROR The Byte Counter could not be started: %d(%s)\n", status, ziti_errorstr(status));
|
|
ziti_close(serv, NULL);
|
|
}
|
|
}
|
|
|
|
static void on_write(ziti_connection conn, ssize_t status, void *ctx) {
|
|
if (status < 0) {
|
|
fprintf(stderr, "request failed to submit status[%zd]: %s\n", status, ziti_errorstr((int) status));
|
|
}
|
|
else {
|
|
printf("request success: %zd bytes sent\n", status);
|
|
}
|
|
|
|
if (ctx) {
|
|
free(ctx);
|
|
}
|
|
}
|
|
|
|
static void input_alloc(uv_handle_t *s, size_t len, uv_buf_t *b) {
|
|
b->base = malloc(len);
|
|
if (b->base) {
|
|
b->len = len;
|
|
}
|
|
}
|
|
|
|
static void input_read(uv_stream_t *s, ssize_t len, const uv_buf_t *b) {
|
|
ziti_connection conn = s->data;
|
|
|
|
if (len > 0) {
|
|
DIE(ziti_write(conn, (uint8_t *) b->base, len, on_write, b->base));
|
|
}
|
|
else {
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
void on_connect(ziti_connection conn, int status) {
|
|
DIE(status);
|
|
uv_loop_t *l = ziti_app_ctx(ziti_conn_context(conn));
|
|
uv_pipe_t *input = calloc(1, sizeof(uv_pipe_t));
|
|
uv_pipe_init(l, input, 0);
|
|
input->data = conn;
|
|
DIE(uv_pipe_open(input, 0));
|
|
DIE(uv_read_start((uv_stream_t *) input, input_alloc, input_read));
|
|
}
|
|
|
|
static size_t total;
|
|
|
|
ssize_t on_data(ziti_connection c, const uint8_t *buf, ssize_t len) {
|
|
if (len == ZITI_EOF) {
|
|
|
|
printf("request completed: %s\n", ziti_errorstr(len));
|
|
ziti_close(c, NULL);
|
|
ziti_shutdown(ziti);
|
|
|
|
}
|
|
else if (len < 0) {
|
|
fprintf(stderr, "unexpected error: %s\n", ziti_errorstr(len));
|
|
ziti_close(c, NULL);
|
|
ziti_shutdown(ziti);
|
|
}
|
|
else {
|
|
total += len;
|
|
printf("%.*s", (int)len, buf);
|
|
}
|
|
return len;
|
|
}
|
|
static uv_signal_t sig;
|
|
static void on_signal(uv_signal_t *h, int signal) {
|
|
ziti_context ztx = h->data;
|
|
ziti_dump(ztx, (int (*)(void *, const char *, ...)) fprintf, stdout);
|
|
}
|
|
|
|
static void on_ziti_init(ziti_context ztx, const ziti_event_t *ev) {
|
|
if (ev->type != ZitiContextEvent) return;
|
|
|
|
if (ev->ctx.ctrl_status == ZITI_PARTIALLY_AUTHENTICATED) return;
|
|
|
|
if (ev->ctx.ctrl_status != ZITI_OK) {
|
|
DIE(ev->ctx.ctrl_status);
|
|
return;
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
sig.data = ztx;
|
|
uv_signal_start(&sig, on_signal, SIGUSR1);
|
|
#endif
|
|
|
|
ziti = ztx;
|
|
ziti_connection conn;
|
|
ziti_conn_init(ziti, &conn, NULL);
|
|
if (server) {
|
|
ziti_listen_opts listen_opts = {
|
|
// .identity = "itsamee",
|
|
.bind_using_edge_identity = false,
|
|
// .terminator_precedence = PRECEDENCE_REQUIRED,
|
|
// .terminator_cost = 10,
|
|
};
|
|
ziti_listen_with_options(conn, service, &listen_opts, listen_cb, on_client);
|
|
}
|
|
else {
|
|
char *app_data = "here is some data from the client to get you started";
|
|
ziti_dial_opts dial_opts = {
|
|
// .identity = "itsamee",
|
|
.app_data = app_data,
|
|
.app_data_sz = strlen(app_data) + 1,
|
|
};
|
|
DIE(ziti_dial_with_options(conn, service, &dial_opts, on_connect, on_data));
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
#if _WIN32
|
|
//changes the output to UTF-8 so that the windows output looks correct and not all jumbly
|
|
SetConsoleOutputCP(65001);
|
|
|
|
#endif
|
|
if (argc != 4) {
|
|
fprintf(stderr, "Usage: %s <client|server> <config-file> <service-name>", argv[0]);
|
|
exit(1);
|
|
}
|
|
uv_loop_t *loop = uv_default_loop();
|
|
|
|
if (strcmp("server", argv[1]) != 0) {
|
|
printf("Running as client\n");
|
|
}
|
|
else {
|
|
printf("Running as server\n");
|
|
server = 1;
|
|
}
|
|
|
|
service = argv[3];
|
|
|
|
ziti_config cfg;
|
|
ziti_context ztx;
|
|
DIE(ziti_load_config(&cfg, argv[2]));
|
|
DIE(ziti_context_init(&ztx, &cfg));
|
|
DIE(ziti_context_set_options(ztx, &(ziti_options){
|
|
.event_cb = on_ziti_init,
|
|
.events = ZitiContextEvent,
|
|
}));
|
|
|
|
DIE(ziti_context_run(ztx, loop));
|
|
|
|
uv_signal_init(loop, &sig);
|
|
// loop will finish after the request is complete and ziti_shutdown is called
|
|
uv_run(loop, UV_RUN_DEFAULT);
|
|
|
|
printf("========================\n"
|
|
"uv loop is done\n");
|
|
|
|
ziti_shutdown(ziti);
|
|
}
|
|
|