From ac3ce22c35db2133816ca30a0a2148ca3dfa6da3 Mon Sep 17 00:00:00 2001 From: OpenGnSys Support Team Date: Wed, 10 Nov 2021 12:24:30 +0100 Subject: #1064 revisit error handling from ogClient 200 => successful command, run next pending command 202 => successful command in progress, do not run next pending command 403 => server sent a malformed HTTP header, should not ever happen, close connection (server is buggy?). 500 => client fails to run command, report error and run next pending command 503 => client is busy, report error and do not run next pending command Anything else, should not ever happen (client is buggy?), close connection with client. On error, when processing response from ogClient, do not close the connection, instead annotate in the database that command was not successful and run next pending command. *Only* if client replies status code 500 set last_cmd to UNSPEC so its state is not BSY as reported by og_client_status function and pending cmds can be sent. --- src/client.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/core.c | 3 --- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/src/client.c b/src/client.c index 44e7c1b..f6de95e 100644 --- a/src/client.c +++ b/src/client.c @@ -610,29 +610,82 @@ static int og_resp_image_restore(json_t *data, struct og_client *cli) return 0; } +static int og_agent_http_response_code(const char *buf) +{ + if (!strncmp(buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) { + return 200; + } else if (!strncmp(buf, "HTTP/1.0 202 Accepted", + strlen("HTTP/1.0 202 Accepted"))) { + return 202; + } else if (!strncmp(buf, "HTTP/1.0 400 Bad Request", + strlen("HTTP/1.0 400 Bad Request"))) { + return 400; + } else if (!strncmp(buf, "HTTP/1.0 500 Internal Server Error", + strlen("HTTP/1.0 500 Internal Server Error"))) { + return 500; + } else if (!strncmp(buf, "HTTP/1.0 503 Service Unavailable", + strlen("HTTP/1.0 503 Service Unavailable"))) { + return 503; + } + + return -1; +} + int og_agent_state_process_response(struct og_client *cli) { + int ret, err = -1, code; json_error_t json_err; + bool success; json_t *root; - int err = -1; char *body; - if (!strncmp(cli->buf, "HTTP/1.0 202 Accepted", - strlen("HTTP/1.0 202 Accepted"))) { - og_dbi_update_action(cli->last_cmd_id, true); - cli->last_cmd_id = 0; - return 1; + code = og_agent_http_response_code(cli->buf); + switch (code) { + case 200: + ret = 0; + success = true; + break; + case 202: + ret = 1; + success = true; + break; + case 400: + ret = -1; + success = false; + syslog(LOG_ERR, "Client %s:%hu reports malformed HTTP request from server\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + break; + case 500: + ret = 0; + success = false; + cli->last_cmd = OG_CMD_UNSPEC; + syslog(LOG_ERR, "Client %s:%hu reports failure to process command\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + /* ... cancel pending actions related to this task for this client here */ + break; + case 503: + ret = 1; + success = false; + syslog(LOG_ERR, "Client %s:%hu is busy to process command\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + break; + default: + ret = -1; + success = false; + syslog(LOG_ERR, "Client %s:%hu reports unknown HTTP response code\n", + inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port)); + break; } - if (strncmp(cli->buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) { - og_dbi_update_action(cli->last_cmd_id, false); + if (code != 200) { + og_dbi_update_action(cli->last_cmd_id, success); cli->last_cmd_id = 0; - return -1; + return ret; } - og_dbi_update_action(cli->last_cmd_id, true); - cli->last_cmd_id = 0; if (!cli->content_length) { + og_dbi_update_action(cli->last_cmd_id, true); + cli->last_cmd_id = 0; cli->last_cmd = OG_CMD_UNSPEC; return 0; } @@ -677,6 +730,15 @@ int og_agent_state_process_response(struct og_client *cli) } json_decref(root); + + if (err < 0) { + err = 0; + success = false; + /* ... cancel pending actions related to this task for this client here */ + } + + og_dbi_update_action(cli->last_cmd_id, success); + cli->last_cmd_id = 0; cli->last_cmd = OG_CMD_UNSPEC; return err; diff --git a/src/core.c b/src/core.c index 9fe83bf..cc523c6 100644 --- a/src/core.c +++ b/src/core.c @@ -251,9 +251,6 @@ static void og_agent_read_cb(struct ev_loop *loop, struct ev_io *io, int events) case OG_AGENT_PROCESSING_RESPONSE: ret = og_agent_state_process_response(cli); if (ret < 0) { - syslog(LOG_ERR, "Failed to process HTTP request from %s:%hu\n", - inet_ntoa(cli->addr.sin_addr), - ntohs(cli->addr.sin_port)); goto close; } else if (ret == 0) { og_agent_deliver_pending_cmd(cli); -- cgit v1.2.3-18-g5258