Mercurial > sci
view req.c @ 7:a7e36b32e20a
make: tests need jansson
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 23 Jun 2021 11:45:00 +0200 |
parents | 215c0c3b3609 |
children | 3ef8128e244f |
line wrap: on
line source
#include <sys/socket.h> #include <sys/time.h> #include <sys/un.h> #include <assert.h> #include <err.h> #include <errno.h> #include <limits.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "config.h" #include "req.h" #include "types.h" #include "util.h" static char path[PATH_MAX] = VARDIR "/run/sci.sock"; static int attach(const char *path) { struct sockaddr_un sun; struct timeval tv = { .tv_sec = 3 }; int sock; if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) return -1; sun.sun_family = PF_LOCAL; strlcpy(sun.sun_path, path, sizeof (sun.sun_path)); if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv)) < 0 || setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof (tv)) < 0 || connect(sock, (const struct sockaddr *)&sun, sizeof (sun)) < 0) { close(sock); return -1; } return sock; } static struct req exchange(const char *cmd, json_t *doc) { char *json, *response, buf[BUFSIZ]; struct req res = {0}; int sock; ssize_t nr; FILE *fp; if ((sock = attach(path)) < 0) goto connect_err; json_object_set(doc, "cmd", json_string(cmd)); json = json_dumps(doc, JSON_COMPACT); if (send(sock, json, strlen(json), MSG_NOSIGNAL) <= 0 || send(sock, "\r\n", 2, MSG_NOSIGNAL) <= 0) goto send_err; response = util_malloc(SCI_MSG_MAX); fp = util_fmemopen(response, SCI_MSG_MAX, "w"); setbuf(fp, NULL); while ((nr = recv(sock, buf, sizeof (buf), MSG_NOSIGNAL)) > 0) if (fwrite(buf, 1, nr, fp) != (size_t)nr) goto io_err; if (!(res.msg = json_loads(response, 0, NULL))) errno = EILSEQ; else errno = 0; /* TODO: generic error handling */ io_err: fclose(fp); free(response); send_err: close(sock); free(json); connect_err: res.status = errno; json_decref(doc); return res; } void req_set_path(const char *newpath) { assert(newpath); strlcpy(path, newpath, sizeof (path)); } struct req req_job_add(const struct job *job) { assert(job); return exchange("job-add", job_to(job, 1)); } struct req req_job_todo(struct job *jobs, size_t *jobsz, const char *worker) { assert(jobs); assert(jobsz); assert(worker); struct req st; struct worker wk; /* * Retrieve worker id first, we don't need JSON document to stay * because we only refer to the id field. */ if ((st = req_worker_find(&wk, worker)).status) return st; req_finish(&st); if ((st = exchange("job-todo", json_pack("{si}", "worker_id", wk.id))).status) return st; if ((*jobsz = job_from(jobs, *jobsz, st.msg)) == (size_t)-1) { json_decref(st.msg); st.msg = NULL; st.status = errno; } return st; } struct req req_jobresult_add(const struct jobresult *res) { assert(res); return exchange("jobresult-add", jobresult_to(res, 1)); } struct req req_project_add(const struct project *p) { assert(p); return exchange("project-add", project_to(p, 1)); } struct req req_project_find(struct project *p, const char *name) { assert(p); assert(name); struct req st; if ((st = exchange("project-find", json_pack("{ss}", "name", name))).status) return st; if (project_from(p, 1, st.msg) < 0) { json_decref(st.msg); st.msg = NULL; st.status = errno; } return st; } struct req req_project_find_id(struct project *p, int id) { assert(p); struct req st; if ((st = exchange("project-find-id", json_pack("{si}", "id", id))).status) return st; if (project_from(p, 1, st.msg) < 0) { json_decref(st.msg); st.msg = NULL; st.status = errno; } return st; } struct req req_project_list(struct project *projects, size_t *projectsz) { assert(projects); assert(projectsz); struct req st; if ((st = exchange("project-list", json_object())).status) return st; if ((*projectsz = project_from(projects, *projectsz, st.msg)) == (size_t)-1) { json_decref(st.msg); st.msg = NULL; st.status = errno; } return st; } struct req req_worker_add(const struct worker *w) { assert(w); return exchange("worker-add", worker_to(w, 1)); } struct req req_worker_find(struct worker *wk, const char *name) { assert(wk); assert(name); struct req st; if ((st = exchange("worker-find", json_pack("{ss}", "name", name))).status) return st; if (worker_from(wk, 1, st.msg) < 0) { json_decref(st.msg); st.msg = NULL; st.status = errno; } return st; } struct req req_worker_find_id(struct worker *wk, int id) { assert(wk); struct req st; if ((st = exchange("worker-find-id", json_pack("{si}", "id", id))).status) return st; if (worker_from(wk, 1, st.msg) < 0) { json_decref(st.msg); st.msg = NULL; st.status = errno; } return st; } struct req req_worker_list(struct worker *wk, size_t *wksz) { assert(wk); assert(wksz); struct req st; if ((st = exchange("worker-list", json_object())).status) return st; if ((*wksz = worker_from(wk, *wksz, st.msg)) == (size_t)-1) { json_decref(st.msg); st.msg = NULL; st.status = errno; } return st; } void req_finish(struct req *st) { if (st->msg) json_decref(st->msg); memset(st, 0, sizeof (*st)); }