source: ogServer-Git/src/client.c @ 216986e

Last change on this file since 216986e was 6e70916, checked in by OpenGnSys Support Team <soporte-og@…>, 3 years ago

#915 remove shim code to update database after image restore command

Make direct call to dbi API to update database instead.

  • Property mode set to 100644
File size: 20.9 KB
Line 
1/*
2 * Copyright (C) 2020-2021 Soleta Networks <info@soleta.eu>
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
6 * Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 */
9
10#include "ogAdmServer.h"
11#include "cfg.h"
12#include "dbi.h"
13#include "utils.h"
14#include "list.h"
15#include "rest.h"
16#include "json.h"
17#include "schedule.h"
18#include <syslog.h>
19#include <sys/ioctl.h>
20#include <ifaddrs.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <jansson.h>
25#include <time.h>
26
27static int og_status_session_start(struct og_client *cli)
28{
29        switch (cli->status) {
30        case OG_CLIENT_STATUS_LINUX:
31                cli->status = OG_CLIENT_STATUS_LINUX_SESSION;
32                break;
33        case OG_CLIENT_STATUS_WIN:
34                cli->status = OG_CLIENT_STATUS_WIN_SESSION;
35                break;
36        default:
37                syslog(LOG_ERR, "%s:%d: invalid session start for status %d\n",
38                       __FILE__, __LINE__, cli->status);
39                return -1;
40        }
41        return 0;
42}
43
44static int og_status_session_stop(struct og_client *cli)
45{
46        switch (cli->status) {
47        case OG_CLIENT_STATUS_WIN_SESSION:
48                cli->status = OG_CLIENT_STATUS_WIN;
49                break;
50        case OG_CLIENT_STATUS_LINUX_SESSION:
51                cli->status = OG_CLIENT_STATUS_LINUX;
52                break;
53        default:
54                syslog(LOG_ERR, "%s:%d: invalid session stop for status %d\n",
55                       __FILE__, __LINE__, cli->status);
56                return -1;
57        }
58        return 0;
59}
60
61static int og_resp_early_hints(struct og_client *cli, json_t *data)
62{
63        const char *event, *action, *user;
64        const char *key;
65        json_t *value;
66        int err = 0;
67
68        if (json_typeof(data) != JSON_OBJECT)
69                return -1;
70
71        json_object_foreach(data, key, value) {
72                if (!strcmp(key, "event")) {
73                        err = og_json_parse_string(value, &event);
74                        if (err < 0)
75                                return err;
76                } else if (!strcmp(key, "action")) {
77                        err = og_json_parse_string(value, &action);
78                        if (err < 0)
79                                return err;
80                } else if (!strcmp(key, "user")) {
81                        err = og_json_parse_string(value, &user);
82                        if (err < 0)
83                                return err;
84                }
85        }
86
87        syslog(LOG_INFO, "Received event %s %s %s\n", event, action, user);
88
89        if (strncmp(event, "session", strlen("session")))
90                return -1;
91
92        if (!strncmp(action, "start", strlen("start")))
93                return og_status_session_start(cli);
94        if (!strncmp(action, "stop", strlen("stop")))
95                return og_status_session_stop(cli);
96
97        syslog(LOG_ERR, "Invalid action for event %s %s %s\n", event, action, user);
98        return -1;
99}
100
101static int og_resp_probe(struct og_client *cli, json_t *data)
102{
103        const char *status = NULL;
104        const char *key;
105        uint32_t speed;
106        json_t *value;
107        int err = 0;
108
109        if (json_typeof(data) != JSON_OBJECT)
110                return -1;
111
112        json_object_foreach(data, key, value) {
113                if (!strcmp(key, "status")) {
114                        err = og_json_parse_string(value, &status);
115                        if (err < 0)
116                                return err;
117                } else if (!strcmp(key, "speed")) {
118                        err = og_json_parse_uint(value, &speed);
119                        if (err < 0)
120                                return err;
121                        cli->speed = speed;
122                }
123        }
124
125        if (!strcmp(status, "BSY"))
126                cli->status = OG_CLIENT_STATUS_BUSY;
127        else if (!strcmp(status, "OPG"))
128                cli->status = OG_CLIENT_STATUS_OGLIVE;
129        else if (!strcmp(status, "VDI"))
130                cli->status = OG_CLIENT_STATUS_VIRTUAL;
131
132        return status ? 0 : -1;
133}
134
135static int og_resp_shell_run(struct og_client *cli, json_t *data)
136{
137        const char *output = NULL;
138        char filename[4096];
139        const char *key;
140        json_t *value;
141        int err = -1;
142        FILE *file;
143
144        if (json_typeof(data) != JSON_OBJECT)
145                return -1;
146
147        json_object_foreach(data, key, value) {
148                if (!strcmp(key, "out")) {
149                        err = og_json_parse_string(value, &output);
150                        if (err < 0)
151                                return err;
152                }
153        }
154
155        if (!output) {
156                syslog(LOG_ERR, "%s:%d: malformed json response\n",
157                       __FILE__, __LINE__);
158                return -1;
159        }
160
161        sprintf(filename, "/tmp/_Seconsola_%s", inet_ntoa(cli->addr.sin_addr));
162        file = fopen(filename, "wt");
163        if (!file) {
164                syslog(LOG_ERR, "cannot open file %s: %s\n",
165                       filename, strerror(errno));
166                return -1;
167        }
168
169        fprintf(file, "%s", output);
170        fclose(file);
171
172        return 0;
173}
174
175struct og_computer_legacy  {
176        char center[OG_DB_INT_MAXLEN + 1];
177        char id[OG_DB_INT_MAXLEN + 1];
178        char hardware[8192];
179};
180
181static int og_resp_hardware(json_t *data, struct og_client *cli)
182{
183        struct og_computer_legacy legacy = {};
184        struct og_computer computer = {};
185        const char *hardware = NULL;
186        struct og_dbi *dbi;
187        const char *key;
188        json_t *value;
189        int err = 0;
190        bool res;
191
192        if (json_typeof(data) != JSON_OBJECT)
193                return -1;
194
195        json_object_foreach(data, key, value) {
196                if (!strcmp(key, "hardware")) {
197                        err = og_json_parse_string(value, &hardware);
198                        if (err < 0)
199                                return -1;
200                }
201        }
202
203        if (!hardware) {
204                syslog(LOG_ERR, "malformed response json\n");
205                return -1;
206        }
207
208        dbi = og_dbi_open(&ogconfig.db);
209        if (!dbi) {
210                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
211                       __func__, __LINE__);
212                return -1;
213        }
214
215        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
216        if (err < 0) {
217                og_dbi_close(dbi);
218                return -1;
219        }
220
221        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
222        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
223        snprintf(legacy.hardware, sizeof(legacy.hardware), "%s", hardware);
224
225        res = actualizaHardware(dbi, legacy.hardware, legacy.id, computer.name,
226                                legacy.center);
227        og_dbi_close(dbi);
228
229        if (!res) {
230                syslog(LOG_ERR, "Problem updating client configuration\n");
231                return -1;
232        }
233
234        return 0;
235}
236
237struct og_software_legacy {
238        char software[8192];
239        char center[OG_DB_INT_MAXLEN + 1];
240        char part[OG_DB_SMALLINT_MAXLEN + 1];
241        char id[OG_DB_INT_MAXLEN + 1];
242};
243
244static int og_resp_software(json_t *data, struct og_client *cli)
245{
246        struct og_software_legacy legacy = {};
247        struct og_computer computer = {};
248        const char *partition = NULL;
249        const char *software = NULL;
250        struct og_dbi *dbi;
251        const char *key;
252        json_t *value;
253        int err = 0;
254        bool res;
255
256        if (json_typeof(data) != JSON_OBJECT)
257                return -1;
258
259        json_object_foreach(data, key, value) {
260                if (!strcmp(key, "software"))
261                        err = og_json_parse_string(value, &software);
262                else if (!strcmp(key, "partition"))
263                        err = og_json_parse_string(value, &partition);
264
265                if (err < 0)
266                        return -1;
267        }
268
269        if (!software || !partition) {
270                syslog(LOG_ERR, "malformed response json\n");
271                return -1;
272        }
273
274        dbi = og_dbi_open(&ogconfig.db);
275        if (!dbi) {
276                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
277                       __func__, __LINE__);
278                return -1;
279        }
280
281        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
282        if (err < 0) {
283                og_dbi_close(dbi);
284                return -1;
285        }
286
287        snprintf(legacy.software, sizeof(legacy.software), "%s", software);
288        snprintf(legacy.part, sizeof(legacy.part), "%s", partition);
289        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
290        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
291
292        res = actualizaSoftware(dbi, legacy.software, legacy.part, legacy.id,
293                                computer.name, legacy.center);
294        og_dbi_close(dbi);
295
296        if (!res) {
297                syslog(LOG_ERR, "Problem updating client configuration\n");
298                return -1;
299        }
300
301        return 0;
302}
303
304#define OG_PARAMS_RESP_REFRESH  (OG_PARAM_PART_DISK |           \
305                                 OG_PARAM_PART_NUMBER |         \
306                                 OG_PARAM_PART_CODE |           \
307                                 OG_PARAM_PART_FILESYSTEM |     \
308                                 OG_PARAM_PART_OS |             \
309                                 OG_PARAM_PART_SIZE |           \
310                                 OG_PARAM_PART_USED_SIZE)
311
312static int og_json_parse_partition_array(json_t *value,
313                                         struct og_partition *partitions)
314{
315        json_t *element;
316        int i, err;
317
318        if (json_typeof(value) != JSON_ARRAY)
319                return -1;
320
321        for (i = 0; i < json_array_size(value) && i < OG_PARTITION_MAX; i++) {
322                element = json_array_get(value, i);
323
324                err = og_json_parse_partition(element, &partitions[i],
325                                              OG_PARAMS_RESP_REFRESH);
326                if (err < 0)
327                        return err;
328        }
329
330        return 0;
331}
332
333static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
334{
335        struct og_task dummy_task = {
336                .scope          = computer_id,
337                .type_scope     = AMBITO_ORDENADORES,
338                .procedure_id   = proc_id,
339        };
340        struct og_dbi *dbi;
341
342        dbi = og_dbi_open(&ogconfig.db);
343        if (!dbi) {
344                syslog(LOG_ERR, "cannot open connection database "
345                                "(%s:%d)\n", __func__, __LINE__);
346                return -1;
347        }
348        if (og_dbi_queue_procedure(dbi, &dummy_task)) {
349                og_dbi_close(dbi);
350                return -1;
351        }
352        og_dbi_close(dbi);
353
354        return 0;
355}
356
357static int og_resp_refresh(json_t *data, struct og_client *cli)
358{
359        struct og_partition partitions[OG_PARTITION_MAX] = {};
360        struct og_partition disks[OG_DISK_MAX] = {};
361        const char *serial_number = NULL;
362        struct og_computer computer = {};
363        const char *status = NULL;
364        char cfg[4096] = {};
365        struct og_dbi *dbi;
366        const char *key;
367        unsigned int i;
368        json_t *value;
369        int err = 0;
370        bool res;
371
372        if (json_typeof(data) != JSON_OBJECT)
373                return -1;
374
375        json_object_foreach(data, key, value) {
376                if (!strcmp(key, "disk_setup")) {
377                        err = og_json_parse_partition_array(value, disks);
378                } else if (!strcmp(key, "partition_setup")) {
379                        err = og_json_parse_partition_array(value, partitions);
380                } else if (!strcmp(key, "serial_number")) {
381                        err = og_json_parse_string(value, &serial_number);
382                } else if (!strcmp(key, "status")) {
383                        err = og_json_parse_string(value, &status);
384                }
385
386                if (err < 0)
387                        return err;
388        }
389
390        if (status) {
391                if (!strncmp(status, "LINUX", strlen("LINUX"))) {
392                        cli->status = OG_CLIENT_STATUS_LINUX;
393                } else if (!strncmp(status, "WIN", strlen("WIN"))) {
394                        cli->status = OG_CLIENT_STATUS_WIN;
395                }
396                return 0;
397        }
398
399        if (strlen(serial_number) > 0)
400                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
401
402        for (i = 0; i < OG_DISK_MAX; i++) {
403                if (!disks[i].disk || !disks[i].number ||
404                    !disks[i].code || !disks[i].filesystem ||
405                    !disks[i].os || !disks[i].size ||
406                    !disks[i].used_size)
407                        continue;
408
409                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
410                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\tdtype=%s\n",
411                         disks[i].disk, disks[i].number,
412                         disks[i].code, disks[i].filesystem,
413                         disks[i].os, disks[i].size,
414                         disks[i].used_size, disks[i].disk_type);
415        }
416
417        for (i = 0; i < OG_PARTITION_MAX; i++) {
418                if (!partitions[i].disk || !partitions[i].number ||
419                    !partitions[i].code || !partitions[i].filesystem ||
420                    !partitions[i].os || !partitions[i].size ||
421                    !partitions[i].used_size)
422                        continue;
423
424                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
425                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
426                         partitions[i].disk, partitions[i].number,
427                         partitions[i].code, partitions[i].filesystem,
428                         partitions[i].os, partitions[i].size,
429                         partitions[i].used_size);
430        }
431
432        dbi = og_dbi_open(&ogconfig.db);
433        if (!dbi) {
434                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
435                                  __func__, __LINE__);
436                return -1;
437        }
438
439        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
440        if (err < 0) {
441                og_dbi_close(dbi);
442                return -1;
443        }
444
445        res = actualizaConfiguracion(dbi, cfg, computer.id);
446        og_dbi_close(dbi);
447
448        if (!res) {
449                syslog(LOG_ERR, "Problem updating client configuration\n");
450                return -1;
451        }
452
453        if (!cli->autorun && computer.procedure_id) {
454                cli->autorun = true;
455
456                if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
457                        return -1;
458        }
459
460        return 0;
461}
462
463static int update_image_info(struct og_dbi *dbi, const char *image_id,
464                             const char *clonator, const char *compressor,
465                             const char *filesystem, const uint64_t datasize)
466{
467        const char *msglog;
468        dbi_result result;
469
470        result = dbi_conn_queryf(dbi->conn,
471                "UPDATE imagenes"
472                "   SET clonator='%s', compressor='%s',"
473                "       filesystem='%s', datasize=%lld"
474                " WHERE idimagen=%s", clonator, compressor, filesystem,
475                datasize, image_id);
476
477        if (!result) {
478                dbi_conn_error(dbi->conn, &msglog);
479                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
480                       __func__, __LINE__, msglog);
481                return -1;
482        }
483        dbi_result_free(result);
484
485        return 0;
486}
487
488static int og_resp_image_create(json_t *data, struct og_client *cli)
489{
490        struct og_software_legacy soft_legacy;
491        struct og_image_legacy img_legacy;
492        struct og_computer computer = {};
493        const char *compressor = NULL;
494        const char *filesystem = NULL;
495        const char *partition = NULL;
496        const char *software = NULL;
497        const char *image_id = NULL;
498        const char *clonator = NULL;
499        const char *disk = NULL;
500        const char *code = NULL;
501        const char *name = NULL;
502        const char *repo = NULL;
503        uint64_t datasize = 0;
504        struct og_dbi *dbi;
505        const char *key;
506        json_t *value;
507        int err = 0;
508        bool res;
509
510        if (json_typeof(data) != JSON_OBJECT)
511                return -1;
512
513        json_object_foreach(data, key, value) {
514                if (!strcmp(key, "software"))
515                        err = og_json_parse_string(value, &software);
516                else if (!strcmp(key, "partition"))
517                        err = og_json_parse_string(value, &partition);
518                else if (!strcmp(key, "disk"))
519                        err = og_json_parse_string(value, &disk);
520                else if (!strcmp(key, "code"))
521                        err = og_json_parse_string(value, &code);
522                else if (!strcmp(key, "id"))
523                        err = og_json_parse_string(value, &image_id);
524                else if (!strcmp(key, "name"))
525                        err = og_json_parse_string(value, &name);
526                else if (!strcmp(key, "repository"))
527                        err = og_json_parse_string(value, &repo);
528                else if (!strcmp(key, "clonator"))
529                        err = og_json_parse_string(value, &clonator);
530                else if (!strcmp(key, "compressor"))
531                        err = og_json_parse_string(value, &compressor);
532                else if (!strcmp(key, "filesystem"))
533                        err = og_json_parse_string(value, &filesystem);
534                else if (!strcmp(key, "datasize"))
535                        err = og_json_parse_uint64(value, &datasize);
536
537                if (err < 0)
538                        return err;
539        }
540
541        if (!software || !partition || !disk || !code || !image_id || !name ||
542            !repo || !clonator || !compressor || !filesystem || !datasize) {
543                syslog(LOG_ERR, "malformed response json\n");
544                return -1;
545        }
546
547        dbi = og_dbi_open(&ogconfig.db);
548        if (!dbi) {
549                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
550                       __func__, __LINE__);
551                return -1;
552        }
553
554        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
555        if (err < 0) {
556                og_dbi_close(dbi);
557                return -1;
558        }
559
560        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
561                 computer.center);
562        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
563                 software);
564        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
565                 image_id);
566        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
567        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
568        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
569        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
570        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
571        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
572
573        res = actualizaSoftware(dbi,
574                                soft_legacy.software,
575                                img_legacy.part,
576                                soft_legacy.id,
577                                computer.name,
578                                soft_legacy.center);
579        if (!res) {
580                og_dbi_close(dbi);
581                syslog(LOG_ERR, "Problem updating client configuration\n");
582                return -1;
583        }
584
585        res = actualizaCreacionImagen(dbi,
586                                      img_legacy.image_id,
587                                      img_legacy.disk,
588                                      img_legacy.part,
589                                      img_legacy.code,
590                                      img_legacy.repo,
591                                      soft_legacy.id);
592        if (!res) {
593                og_dbi_close(dbi);
594                syslog(LOG_ERR, "Problem updating client configuration\n");
595                return -1;
596        }
597
598        res = update_image_info(dbi, image_id, clonator, compressor,
599                                filesystem, datasize);
600        og_dbi_close(dbi);
601
602        if (res) {
603                syslog(LOG_ERR, "Problem updating image info\n");
604                return -1;
605        }
606
607        return 0;
608}
609
610static int og_resp_image_restore(json_t *data, struct og_client *cli)
611{
612        struct og_software_legacy soft_legacy;
613        struct og_image_legacy img_legacy;
614        struct og_computer computer = {};
615        const char *partition = NULL;
616        const char *image_id = NULL;
617        const char *disk = NULL;
618        const char *msglog;
619        struct og_dbi *dbi;
620        dbi_result result;
621        const char *key;
622        json_t *value;
623        int err = 0;
624
625        if (json_typeof(data) != JSON_OBJECT)
626                return -1;
627
628        json_object_foreach(data, key, value) {
629                if (!strcmp(key, "partition"))
630                        err = og_json_parse_string(value, &partition);
631                else if (!strcmp(key, "disk"))
632                        err = og_json_parse_string(value, &disk);
633                else if (!strcmp(key, "image_id"))
634                        err = og_json_parse_string(value, &image_id);
635
636                if (err < 0)
637                        return err;
638        }
639
640        if (!partition || !disk || !image_id) {
641                syslog(LOG_ERR, "malformed response json\n");
642                return -1;
643        }
644
645        dbi = og_dbi_open(&ogconfig.db);
646        if (!dbi) {
647                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
648                       __func__, __LINE__);
649                return -1;
650        }
651
652        result = dbi_conn_queryf(dbi->conn,
653                                 "SELECT idperfilsoft FROM imagenes "
654                                 " WHERE idimagen='%s'", image_id);
655        if (!result) {
656                og_dbi_close(dbi);
657                syslog(LOG_ERR, "failed to query database\n");
658                return -1;
659        }
660        if (!dbi_result_next_row(result)) {
661                dbi_result_free(result);
662                og_dbi_close(dbi);
663                syslog(LOG_ERR, "software profile does not exist in database\n");
664                return -1;
665        }
666        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
667                 "%d", dbi_result_get_uint(result, "idperfilsoft"));
668        dbi_result_free(result);
669
670        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
671        if (err < 0) {
672                og_dbi_close(dbi);
673                return -1;
674        }
675
676        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
677                 image_id);
678        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
679        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
680        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
681
682        result = dbi_conn_queryf(dbi->conn,
683                                 "UPDATE ordenadores_particiones"
684                                 "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
685                                 "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
686                                 "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
687                                 " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
688                                 img_legacy.image_id, img_legacy.software_id,
689                                 img_legacy.image_id, img_legacy.software_id,
690                                 soft_legacy.id, img_legacy.disk, img_legacy.part);
691        if (!result) {
692                dbi_conn_error(dbi->conn, &msglog);
693                syslog(LOG_ERR, "failed to update database (%s:%d) %s\n",
694                       __func__, __LINE__, msglog);
695                og_dbi_close(dbi);
696                return -1;
697        }
698        dbi_result_free(result);
699        og_dbi_close(dbi);
700
701        return 0;
702}
703
704static int og_agent_http_response_code(const char *buf)
705{
706        if (!strncmp(buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
707                return 200;
708        } else if (!strncmp(buf, "HTTP/1.0 202 Accepted",
709                            strlen("HTTP/1.0 202 Accepted"))) {
710                return 202;
711        } else if (!strncmp(buf, "HTTP/1.0 400 Bad Request",
712                            strlen("HTTP/1.0 400 Bad Request"))) {
713                return 400;
714        } else if (!strncmp(buf, "HTTP/1.0 500 Internal Server Error",
715                            strlen("HTTP/1.0 500 Internal Server Error"))) {
716                return 500;
717        } else if (!strncmp(buf, "HTTP/1.0 503 Service Unavailable",
718                            strlen("HTTP/1.0 503 Service Unavailable"))) {
719                return 503;
720        } else if (!strncmp(buf, "HTTP/1.0 103 Early Hints",
721                            strlen("HTTP/1.0 103 Early Hints"))) {
722                return 103;
723        }
724
725        return -1;
726}
727
728int og_agent_state_process_response(struct og_client *cli)
729{
730        int ret, err = -1, code;
731        json_error_t json_err;
732        bool success;
733        json_t *root;
734        char *body;
735
736        code = og_agent_http_response_code(cli->buf);
737        switch (code) {
738        case 103:
739        case 200:
740                ret = 0;
741                success = true;
742                break;
743        case 202:
744                ret = 1;
745                success = true;
746                break;
747        case 400:
748                ret = -1;
749                success = false;
750                syslog(LOG_ERR, "Client %s:%hu reports malformed HTTP request from server\n",
751                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
752                break;
753        case 500:
754                ret = 0;
755                success = false;
756                cli->last_cmd = OG_CMD_UNSPEC;
757                syslog(LOG_ERR, "Client %s:%hu reports failure to process command\n",
758                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
759                /* ... cancel pending actions related to this task for this client here */
760                break;
761        case 503:
762                ret = 1;
763                success = false;
764                syslog(LOG_ERR, "Client %s:%hu is busy to process command\n",
765                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
766                break;
767        default:
768                ret = -1;
769                success = false;
770                syslog(LOG_ERR, "Client %s:%hu reports unknown HTTP response code\n",
771                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
772                break;
773        }
774
775        if (code != 200 && code != 103) {
776                og_dbi_update_action(cli->last_cmd_id, success);
777                cli->last_cmd_id = 0;
778                return ret;
779        }
780
781        if (!cli->content_length) {
782                og_dbi_update_action(cli->last_cmd_id, true);
783                cli->last_cmd_id = 0;
784                cli->last_cmd = OG_CMD_UNSPEC;
785                return 0;
786        }
787
788        body = strstr(cli->buf, "\r\n\r\n") + 4;
789
790        root = json_loads(body, 0, &json_err);
791        if (!root) {
792                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
793                       __FILE__, __LINE__, json_err.line, json_err.text);
794                return -1;
795        }
796
797        if (code == 103) {
798                err = og_resp_early_hints(cli, root);
799                json_decref(root);
800                return err;
801        }
802
803        switch (cli->last_cmd) {
804        case OG_CMD_PROBE:
805                err = og_resp_probe(cli, root);
806                break;
807        case OG_CMD_SHELL_RUN:
808                err = og_resp_shell_run(cli, root);
809                break;
810        case OG_CMD_HARDWARE:
811                err = og_resp_hardware(root, cli);
812                break;
813        case OG_CMD_SOFTWARE:
814                err = og_resp_software(root, cli);
815                break;
816        case OG_CMD_REFRESH:
817                err = og_resp_refresh(root, cli);
818                break;
819        case OG_CMD_SETUP:
820                err = og_resp_refresh(root, cli);
821                break;
822        case OG_CMD_IMAGE_CREATE:
823                err = og_resp_image_create(root, cli);
824                break;
825        case OG_CMD_IMAGE_RESTORE:
826                err = og_resp_image_restore(root, cli);
827                break;
828        default:
829                err = -1;
830                break;
831        }
832
833        json_decref(root);
834
835        if (err < 0) {
836                err = 0;
837                success = false;
838                /* ... cancel pending actions related to this task for this client here */
839        }
840
841        og_dbi_update_action(cli->last_cmd_id, success);
842        cli->last_cmd_id = 0;
843        cli->last_cmd = OG_CMD_UNSPEC;
844
845        return err;
846}
Note: See TracBrowser for help on using the repository browser.