diff --git a/inc_internal/internal_model.h b/inc_internal/internal_model.h index 0866192c..345702de 100644 --- a/inc_internal/internal_model.h +++ b/inc_internal/internal_model.h @@ -48,6 +48,7 @@ XX(identity, ziti_identity, ptr, identity, __VA_ARGS__) \ XX(posture_query_set, ziti_posture_query_set, array, postureQueries, __VA_ARGS__) #define ZITI_ERROR_MODEL(XX, ...) \ +XX(err, int, none, , __VA_ARGS__) \ XX(http_code, int, none, , __VA_ARGS__) \ XX(code, string, none, code, __VA_ARGS__) \ XX(message, string, none, message, __VA_ARGS__) diff --git a/includes/ziti/error_defs.h b/includes/ziti/error_defs.h index 96178943..884e8625 100644 --- a/includes/ziti/error_defs.h +++ b/includes/ziti/error_defs.h @@ -77,7 +77,9 @@ limitations under the License. /** SDK detected invalid cryptographic state of Ziti connection */ \ XX(CRYPTO_FAIL, "crypto failure") \ /** connection was closed */ \ - XX(CONN_CLOSED, "connection is closed") \ + XX(CONN_CLOSED, "connection is closed") \ + /** failed posture check */ \ + XX(INVALID_POSTURE, "failed posture checek") \ /** Inspired by the Android SDK: What a Terrible Failure. A condition that should never happen. */ \ XX(WTF, "WTF: programming error") diff --git a/includes/ziti/ziti.h b/includes/ziti/ziti.h index f9d3de2c..188483b6 100644 --- a/includes/ziti/ziti.h +++ b/includes/ziti/ziti.h @@ -736,7 +736,9 @@ extern int ziti_accept(ziti_connection clt, ziti_conn_cb cb, ziti_data_cb data_c * @param conn the #ziti_connection to be closed * @param close_cb callback called after connection is closed * - * @return #ZITI_OK or corresponding #ZITI_ERRORS + * @return #ZITI_OK + * #ZITI_CONN_CLOSED if connection was already ziti_close() was already called on the given connection + * other #ZITI_ERRORS */ ZITI_FUNC extern int ziti_close(ziti_connection conn, ziti_close_cb close_cb); diff --git a/library/connect.c b/library/connect.c index ae6ba9b8..c425a3ae 100644 --- a/library/connect.c +++ b/library/connect.c @@ -281,7 +281,10 @@ static void on_channel_connected(ziti_channel_t *ch, void *ctx, int status) { static void complete_conn_req(struct ziti_conn *conn, int code) { if (conn->conn_req && conn->conn_req->cb) { - conn->conn_req->failed = code != ZITI_OK; + if (code != ZITI_OK) { + conn_set_state(conn, Disconnected); + conn->conn_req->failed = true; + } conn->conn_req->cb(conn, code); conn->conn_req->cb = NULL; if(conn->conn_req->conn_timeout != NULL) { @@ -392,9 +395,13 @@ static void connect_get_net_session_cb(ziti_net_session * s, ziti_error *err, vo if (err != NULL) { CONN_LOG(ERROR, "failed to get session for service[%s]: %s(%s)", conn->service, err->code, err->message); + if (err->err == ZITI_NOT_AUTHORIZED) { + ziti_force_session_refresh(ztx); + } } if (s == NULL) { complete_conn_req(conn, ZITI_SERVICE_UNAVAILABLE); + uv_close((uv_handle_t *) ar, free_handle); } else { req->session = s; @@ -581,6 +588,12 @@ static void ziti_disconnect_cb(ziti_connection conn, ssize_t status, void *ctx) static void ziti_disconnect_async(uv_async_t *ar) { struct ziti_conn *conn = ar->data; + + if (conn->channel == NULL) { + CONN_LOG(DEBUG, "no channel -- no disconnect"); + ziti_disconnect_cb(conn, 0, NULL); + } + switch (conn->state) { case Bound: case Accepting: @@ -602,6 +615,11 @@ static void ziti_disconnect_async(uv_async_t *ar) { } static int ziti_disconnect(struct ziti_conn *conn) { + if (conn->disconnector) { + CONN_LOG(DEBUG, "already disconnecting"); + return ZITI_OK; + } + if (conn->state < Timedout) { NEWP(ar, uv_async_t); uv_async_init(conn->ziti_ctx->loop, ar, ziti_disconnect_async); @@ -1125,13 +1143,13 @@ static int send_fin_message(ziti_connection conn) { } int ziti_close(ziti_connection conn, ziti_close_cb close_cb) { - if (conn != NULL) { - conn->close = true; - conn->close_cb = close_cb; - ziti_disconnect(conn); - } - return ZITI_OK; + if (conn == NULL) return ZITI_INVALID_STATE; + if (conn->close) return ZITI_CONN_CLOSED; + + conn->close = true; + conn->close_cb = close_cb; + return ziti_disconnect(conn); } diff --git a/library/ziti.c b/library/ziti.c index f631fed1..ed67831b 100644 --- a/library/ziti.c +++ b/library/ziti.c @@ -548,10 +548,11 @@ static void update_services(ziti_service_array services, ziti_error *error, void if (error) { ZTX_LOG(ERROR, "failed to get service updates err[%s/%s] from ctrl[%s]", error->code, error->message, ztx->opts->controller); - if (strcmp(error->code, "UNAUTHORIZED") == 0) { + if (error->err == ZITI_NOT_AUTHORIZED) { ZTX_LOG(WARN, "API session is no longer valid. Trying to re-auth"); ziti_re_auth(ztx); - } else { + } + else { update_ctrl_status(ztx, ZITI_CONTROLLER_UNAVAILABLE, error->message); } return; @@ -700,7 +701,7 @@ static void session_cb(ziti_session *session, ziti_error *err, void *ctx) { ziti_context ztx = init_req->ztx; ztx->loop_thread = uv_thread_self(); - int errCode = err ? code_to_error(err->code) : ZITI_OK; + int errCode = err ? err->err : ZITI_OK; if (session) { ZTX_LOG(DEBUG, "%s successfully => api_session[%s]", ztx->session ? "refreshed" : "logged in", session->id); diff --git a/library/ziti_ctrl.c b/library/ziti_ctrl.c index 60c3070b..bd70ee3d 100644 --- a/library/ziti_ctrl.c +++ b/library/ziti_ctrl.c @@ -64,13 +64,16 @@ int code_to_error(const char *code) { XX(CONTROLLER_UNAVAILABLE, ZITI_CONTROLLER_UNAVAILABLE) \ XX(NO_ROUTABLE_INGRESS_NODES, ZITI_GATEWAY_UNAVAILABLE) \ XX(NO_EDGE_ROUTERS_AVAILABLE, ZITI_GATEWAY_UNAVAILABLE) \ -XX(INVALID_AUTHENTICATION, ZITI_NOT_AUTHORIZED) \ -XX(REQUIRES_CERT_AUTH, ZITI_NOT_AUTHORIZED)\ -XX(UNAUTHORIZED, ZITI_NOT_AUTHORIZED)\ +XX(INVALID_AUTHENTICATION, ZITI_NOT_AUTHORIZED) \ +XX(REQUIRES_CERT_AUTH, ZITI_NOT_AUTHORIZED) \ +XX(UNAUTHORIZED, ZITI_NOT_AUTHORIZED) \ +XX(INVALID_POSTURE, ZITI_INVALID_POSTURE) \ XX(INVALID_AUTH, ZITI_NOT_AUTHORIZED) #define CODE_MATCH(c, err) if (strcmp(code,#c) == 0) return err; + if (code == NULL) { return ZITI_OK; } + CODE_MAP(CODE_MATCH) ZITI_LOG(WARN, "unmapped error code: %s", code); @@ -115,6 +118,7 @@ static void ctrl_resp_cb(um_http_resp_t *r, void *data) { resp->status = r->code; if (r->code < 0) { NEWP(err, ziti_error); + err->err = ZITI_CONTROLLER_UNAVAILABLE; err->code = strdup("CONTROLLER_UNAVAILABLE"); err->message = strdup(uv_strerror(r->code)); ctrl_default_cb(NULL, err, resp); @@ -211,6 +215,7 @@ static void ctrl_body_cb(um_http_req_t *req, const char *b, ssize_t len) { if (rc < 0) { ZITI_LOG(ERROR, "failed to parse controller response of req[%s]", req->path); cr.error = alloc_ziti_error(); + cr.error->err = ZITI_WTF; cr.error->code = strdup("INVALID_CONTROLLER_RESPONSE"); cr.error->message = strdup(req->resp.status); } @@ -250,6 +255,7 @@ static void ctrl_body_cb(um_http_req_t *req, const char *b, ssize_t len) { } if (cr.error) { + cr.error->err = code_to_error(cr.error->code); cr.error->http_code = req->resp.code; } diff --git a/programs/ziti-prox-c/proxy.c b/programs/ziti-prox-c/proxy.c index 89a61067..1a1784d9 100644 --- a/programs/ziti-prox-c/proxy.c +++ b/programs/ziti-prox-c/proxy.c @@ -296,7 +296,6 @@ void on_ziti_connect(ziti_connection conn, int status) { ziti_context ztx = ziti_conn_context(conn); struct proxy_app_ctx *app = ziti_app_ctx(ztx); struct client *c = clt->data; - LIST_INSERT_HEAD(&app->clients, c, next); } else { ZITI_LOG(ERROR, "ziti connect failed: %s(%d)", ziti_errorstr(status), status); @@ -377,7 +376,6 @@ static void on_client(uv_stream_t *server, int status) { int len = sizeof(clt->addr); TRY(uv, uv_tcp_getpeername(c, (struct sockaddr *) &clt->addr, &len)); sprintf(clt->addr_s, "%s:%hu", inet_ntoa(clt->addr.sin_addr), ntohs(clt->addr.sin_port)); - CATCH(uv) { return; } @@ -385,6 +383,7 @@ static void on_client(uv_stream_t *server, int status) { struct listener *l = server->data; ZITI_LOG(DEBUG, "client connection accepted from %s (%s:%d)", clt->addr_s, l->service_name, l->port); + LIST_INSERT_HEAD(&l->app_ctx->clients, clt, next); PREPF(ziti, ziti_errorstr); TRY(ziti, ziti_conn_init(l->app_ctx->ziti, &clt->ziti_conn, c));