source: ogServer-Git/src/client.c @ 3b4aa72

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

#915 remove temporary file to store shell output

Remove legacy behaviour, store it in the client object instead of a temporary
file.

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