/* * Copyright (c) 2023 Egor Tensin * This file is part of the "cimple" project. * For details, see https://github.com/egor-tensin/cimple. * Distributed under the MIT License. */ #include "protocol.h" #include "base64.h" #include "const.h" #include "log.h" #include "msg.h" #include "process.h" #include "run_queue.h" #include "string.h" #include #include #include static int check_msg_length(const struct msg *msg, size_t expected) { size_t actual = msg_get_length(msg); if (actual != expected) { log_err("Invalid number of arguments for a message: %zu\n", actual); msg_dump(msg); return -1; } return 0; } int msg_run_parse(const struct msg *msg, struct run **run) { int ret = check_msg_length(msg, 3); if (ret < 0) return ret; const char **argv = msg_get_strings(msg); /* We don't know the ID yet. */ return run_create(run, 0, argv[1], argv[2]); } int msg_new_worker_create(struct msg **msg) { static const char *argv[] = {CMD_NEW_WORKER, NULL}; return msg_from_argv(msg, argv); } int msg_start_create(struct msg **msg, const struct run *run) { char id[16]; snprintf(id, sizeof(id), "%d", run_get_id(run)); const char *argv[] = {CMD_START, id, run_get_url(run), run_get_rev(run), NULL}; return msg_from_argv(msg, argv); } int msg_start_parse(const struct msg *msg, struct run **run) { int ret = 0; ret = check_msg_length(msg, 4); if (ret < 0) return ret; const char **argv = msg_get_strings(msg); int id = 0; ret = string_to_int(argv[1], &id); if (ret < 0) return ret; return run_create(run, id, argv[2], argv[3]); } int msg_finished_create(struct msg **msg, int run_id, const struct proc_output *output) { int ret = 0; char id[16]; char ec[16]; snprintf(id, sizeof(id), "%d", run_id); snprintf(ec, sizeof(ec), "%d", output->ec); char *b64data = NULL; ret = base64_encode(output->data, output->data_size, &b64data); if (ret < 0) return ret; const char *argv[] = {CMD_FINISHED, id, ec, b64data, NULL}; ret = msg_from_argv(msg, argv); if (ret < 0) goto free_b64data; free_b64data: free(b64data); return ret; } int msg_finished_parse(const struct msg *msg, int *run_id, struct proc_output **_output) { int ret = 0; ret = check_msg_length(msg, 4); if (ret < 0) return ret; const char **argv = msg_get_strings(msg); struct proc_output *output = NULL; ret = proc_output_create(&output); if (ret < 0) return ret; ret = string_to_int(argv[1], run_id); if (ret < 0) goto free_output; ret = string_to_int(argv[2], &output->ec); if (ret < 0) goto free_output; const char *b64data = argv[3]; ret = base64_decode(b64data, &output->data, &output->data_size); if (ret < 0) goto free_output; *_output = output; return ret; free_output: proc_output_destroy(output); return ret; }