Skip to content

Commit

Permalink
Merge pull request #482 from openziti/latency-probe-disconnect-on-act…
Browse files Browse the repository at this point in the history
…ive-channel

avoid disconnecting active channel due to latency timeout
  • Loading branch information
ekoby authored Jan 12, 2023
2 parents c5b5b59 + 1501891 commit f9f80fd
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 36 deletions.
2 changes: 1 addition & 1 deletion deps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ include(FetchContent)

FetchContent_Declare(uv-mbed
GIT_REPOSITORY https://github.com/openziti/uv-mbed.git
GIT_TAG v0.14.12
GIT_TAG v0.14.13
)
set(ENABLE_UM_TESTS OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(uv-mbed)
Expand Down
4 changes: 3 additions & 1 deletion inc_internal/zt_internal.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022. NetFoundry Inc.
// Copyright (c) 2022-2023. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -88,6 +88,8 @@ typedef struct ziti_channel {

uint64_t latency;
struct waiter_s *latency_waiter;
uint64_t last_read;
uint64_t last_write;

ch_state state;
uint32_t reconnect_count;
Expand Down
2 changes: 1 addition & 1 deletion library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ endif ()
install(FILES ${uv-mbed_SOURCE_DIR}/LICENSE
COMPONENT ziti-sdk
DESTINATION ${CMAKE_INSTALL_DOCDIR}/uv_mbed)
install(FILES ${ziti_DEPS_DIR}/uv_link-src/README.md
install(FILES ${ziti_DEPS_DIR}/uv-mbed-src/deps/uv_link_t/README.md
COMPONENT ziti-sdk
DESTINATION ${CMAKE_INSTALL_DOCDIR}/uv_link_t)
install(FILES ${ziti_DEPS_DIR}/http_parser-src/LICENSE-MIT
Expand Down
36 changes: 29 additions & 7 deletions library/channel.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022. NetFoundry Inc.
// Copyright (c) 2022-2023. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -591,12 +591,20 @@ static void latency_reply_cb(void *ctx, message *reply, int err) {

static void latency_timeout(uv_timer_t *t) {
ziti_channel_t *ch = t->data;
ziti_channel_remove_waiter(ch, ch->latency_waiter);
ch->latency_waiter = NULL;
ch->latency = UINT64_MAX;
if (uv_now(t->loop) - MAX(ch->last_read, ch->last_write) < LATENCY_TIMEOUT) {
CH_LOG(DEBUG, "latency timeout on active channel, extending timeout");
uv_timer_start(t, latency_timeout, LATENCY_TIMEOUT, 0);
}
else {
CH_LOG(ERROR, "no read traffic on channel since before latency probe was sent, closing channel");

uv_mbed_close(ch->connection, NULL);
on_channel_close(ch, ZITI_TIMEOUT, UV_ETIMEDOUT);
ziti_channel_remove_waiter(ch, ch->latency_waiter);
ch->latency_waiter = NULL;
ch->latency = UINT64_MAX;

uv_mbed_close(ch->connection, NULL);
on_channel_close(ch, ZITI_TIMEOUT, UV_ETIMEDOUT);
}
}

static void send_latency_probe(uv_timer_t *t) {
Expand Down Expand Up @@ -774,6 +782,16 @@ static void on_channel_close(ziti_channel_t *ch, int ziti_err, ssize_t uv_err) {
free(con);
}

// dump all buffered data
free_buffer(ch->incoming);
ch->incoming = new_buffer();

if (ch->in_next) { // discard partially read message
message_free(ch->in_next);
pool_return_obj(ch->in_next);
ch->in_next = NULL;
}

if (ch->state != Closed) {
if (uv_err == UV_EOF) {
ZTX_LOG(VERBOSE, "edge router closed connection, trying to refresh api session");
Expand All @@ -786,12 +804,15 @@ static void on_channel_close(ziti_channel_t *ch, int ziti_err, ssize_t uv_err) {
static void on_write(uv_write_t *req, int status) {
ZITI_LOG(TRACE, "on_write(%p,%d)", req, status);
struct ch_write_req *wr = req->data;
ziti_channel_t *ch = wr->ch;

if (status < 0) {
ziti_channel_t *ch = wr->ch;
CH_LOG(ERROR, "write failed [%d/%s]", status, uv_strerror(status));
on_channel_close(ch, ZITI_CONN_CLOSED, status);
}
else {
ch->last_write = uv_now(ch->loop);
}

if (wr != NULL) {
FREE(wr->buf.base);
Expand Down Expand Up @@ -848,6 +869,7 @@ static void on_channel_data(uv_stream_t *s, ssize_t len, const uv_buf_t *buf) {
free(buf->base);
} else {
CH_LOG(TRACE, "on_data [len=%zd]", len);
ch->last_read = uv_now(ch->loop);
buffer_append(ch->incoming, buf->base, (uint32_t) len);
process_inbound(ch);
}
Expand Down
3 changes: 1 addition & 2 deletions library/internal_model.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2022. NetFoundry Inc.
// Copyright (c) 2020-2023. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -422,7 +422,6 @@ static type_meta ziti_address_META = {
.comparer = (_cmp_f) cmp_ziti_address0,
.parser = (_parse_f) parse_ziti_address0,
.jsonifier = (_to_json_f) ziti_address_write_json,
.destroyer = (_free_f) free_ziti_address0,
};

int ziti_intercept_from_client_cfg(ziti_intercept_cfg_v1 *intercept, const ziti_client_cfg_v1 *client_cfg) {
Expand Down
49 changes: 29 additions & 20 deletions library/model_support.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2022. NetFoundry Inc.
// Copyright (c) 2020-2023. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -464,14 +464,15 @@ void model_free(void *obj, type_meta *meta) {
field_meta *fm = &meta->fields[i];
void **f_addr = (void **) ((char *) obj + fm->offset);
void *f_ptr = NULL;
struct type_meta *field_meta = fm->meta();
if (fm->mod == none_mod) {
f_ptr = f_addr;
model_free(f_ptr, fm->meta());
model_free(f_ptr, field_meta);
}
else if (fm->mod == ptr_mod) {
f_ptr = (void *) (*f_addr);
if (f_ptr != NULL) {
model_free(f_ptr, fm->meta());
model_free(f_ptr, field_meta);
free(f_ptr);
}
}
Expand All @@ -480,11 +481,12 @@ void model_free(void *obj, type_meta *meta) {
if (arr != NULL) {
for (int idx = 0; arr[idx] != NULL; idx++) {
f_ptr = arr + idx;
if (fm->meta() == get_string_meta()) {
model_free(f_ptr, fm->meta());
} else {
if (field_meta == get_string_meta()) {
model_free(f_ptr, field_meta);
}
else {
void *mem_ptr = (void *) (*(void **) f_ptr);
model_free(mem_ptr, fm->meta());
model_free(mem_ptr, field_meta);
free(mem_ptr);
}
}
Expand All @@ -493,41 +495,48 @@ void model_free(void *obj, type_meta *meta) {
} else if (fm->mod == list_mod) {
model_list *list = (model_list *) f_addr;
model_list_iter it = model_list_iterator(list);
bool str_type = (fm->meta() == get_string_meta() || fm->meta() == get_json_meta());
bool str_type = (field_meta == get_string_meta() || field_meta == get_json_meta());
while (it != NULL) {
void *el = model_list_it_element(it);
it = model_list_it_remove(it);
if (fm->meta()->destroyer) {
fm->meta()->destroyer(str_type ? &el : el);
} else {
model_free(el, fm->meta());
if (str_type) {
field_meta->destroyer(&el);
}
else if (field_meta->destroyer) {
field_meta->destroyer(el);
}
else {
model_free(el, field_meta);
free(el);
}
}
model_list_clear(list, NULL);
} else if (fm->mod == map_mod) {
model_map *map = (model_map *) f_addr;
_free_f ff = NULL;
model_map_iter it = model_map_iterator(map);
while (it != NULL) {
const char *k = model_map_it_key(it);
void *v = model_map_it_value(it);
if (fm->meta() == get_string_meta() || fm->meta() == get_json_meta()) {
fm->meta()->destroyer(&v);
} else if (fm->meta()->destroyer) {
fm->meta()->destroyer(v);
if (field_meta == get_string_meta() || field_meta == get_json_meta()) {
field_meta->destroyer(&v);
}
else if (field_meta->destroyer) {
field_meta->destroyer(v);
}
else {
model_free(v, fm->meta());
model_free(v, field_meta);
}
free(v);

it = model_map_it_remove(it);
}

if (fm->meta() == get_string_meta()) {
if (field_meta == get_string_meta()) {
ff = free;
} else {
ff = fm->meta()->destroyer;
}
else {
ff = field_meta->destroyer;
}
model_map_clear(map, ff);
}
Expand Down
4 changes: 3 additions & 1 deletion tests/collections_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2022. NetFoundry Inc.
// Copyright (c) 2020-2023. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -181,4 +181,6 @@ TEST_CASE("map-non-terminated-string-keys", "[model]") {
CHECK(strlen(key) == v);
it = model_map_it_next(it);
}

model_map_clear(&m, nullptr);
}
6 changes: 4 additions & 2 deletions tests/enum_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021-2022. NetFoundry Inc.
// Copyright (c) 2021-2023. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -66,6 +66,8 @@ TEST_CASE("parse null enum", "[model]") {

CHECK_THAT(f1.name, Catch::Matchers::Equals("this is a name"));
CHECK(f1.state == 0);

free_FooWithEnum(&f1);
}

TEST_CASE("default enum", "[model]") {
Expand All @@ -84,7 +86,7 @@ TEST_CASE("default enum", "[model]") {
REQUIRE(parse_FooWithEnum(&f2, json, strlen(json)) == strlen(json));
CHECK(f2.state == State_Unknown);


free_FooWithEnum(&f2);
free(json);
}

Expand Down
15 changes: 14 additions & 1 deletion tests/test_ziti_model.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022. NetFoundry Inc.
// Copyright (c) 2022-2023. NetFoundry Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -703,4 +703,17 @@ TEST_CASE("ziti-address-match", "[model]") {
CHECK(ziti_addrstr_match_list("ff:abcd::1", &intercept.addresses) == -1);

free_ziti_intercept_cfg_v1(&intercept);
}

TEST_CASE("ziti-intercept_test", "[model]") {
ziti_client_cfg_v1 cltV1;
REQUIRE(parse_ziti_address_str(&cltV1.hostname, "httpbin.ziti") == 0);
cltV1.port = 80;

ziti_intercept_cfg_v1 interceptCfgV1;
REQUIRE(ziti_intercept_from_client_cfg(&interceptCfgV1, &cltV1) == 0);
REQUIRE(model_list_size(&interceptCfgV1.addresses) == 1);

free_ziti_intercept_cfg_v1(&interceptCfgV1);
free_ziti_client_cfg_v1(&cltV1);
}

0 comments on commit f9f80fd

Please sign in to comment.