source: ogServer-Git/src/client.c @ f03425e

Last change on this file since f03425e was f03425e, checked in by Javier Sánchez Parra <jsanchez@…>, 3 years ago

#915 Add support for link speed in the refresh response

Add ogServer support for parsing and storing the link speed from
ogClient's refresh response.

Probe response already has client's link speed, but this API is
deprecated.

  • Property mode set to 100644
File size: 20.8 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        uint32_t link;
359        json_t *value;
360        int err = 0;
361        bool res;
362
363        if (json_typeof(data) != JSON_OBJECT)
364                return -1;
365
366        json_object_foreach(data, key, value) {
367                if (!strcmp(key, "disk_setup")) {
368                        err = og_json_parse_partition_array(value, disks);
369                } else if (!strcmp(key, "partition_setup")) {
370                        err = og_json_parse_partition_array(value, partitions);
371                } else if (!strcmp(key, "serial_number")) {
372                        err = og_json_parse_string(value, &serial_number);
373                } else if (!strcmp(key, "status")) {
374                        err = og_json_parse_string(value, &status);
375                } else if (!strcmp(key, "link")) {
376                        err = og_json_parse_uint(value, &link);
377                }
378
379                if (err < 0)
380                        return err;
381        }
382
383        if (link)
384                cli->speed = link;
385
386        if (status) {
387                if (!strncmp(status, "LINUX", strlen("LINUX"))) {
388                        cli->status = OG_CLIENT_STATUS_LINUX;
389                } else if (!strncmp(status, "WIN", strlen("WIN"))) {
390                        cli->status = OG_CLIENT_STATUS_WIN;
391                }
392                return 0;
393        }
394
395        if (strlen(serial_number) > 0)
396                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
397
398        for (i = 0; i < OG_DISK_MAX; i++) {
399                if (!disks[i].disk || !disks[i].number ||
400                    !disks[i].code || !disks[i].filesystem ||
401                    !disks[i].os || !disks[i].size ||
402                    !disks[i].used_size)
403                        continue;
404
405                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
406                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\tdtype=%s\n",
407                         disks[i].disk, disks[i].number,
408                         disks[i].code, disks[i].filesystem,
409                         disks[i].os, disks[i].size,
410                         disks[i].used_size, disks[i].disk_type);
411        }
412
413        for (i = 0; i < OG_PARTITION_MAX; i++) {
414                if (!partitions[i].disk || !partitions[i].number ||
415                    !partitions[i].code || !partitions[i].filesystem ||
416                    !partitions[i].os || !partitions[i].size ||
417                    !partitions[i].used_size)
418                        continue;
419
420                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
421                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
422                         partitions[i].disk, partitions[i].number,
423                         partitions[i].code, partitions[i].filesystem,
424                         partitions[i].os, partitions[i].size,
425                         partitions[i].used_size);
426        }
427
428        dbi = og_dbi_open(&ogconfig.db);
429        if (!dbi) {
430                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
431                                  __func__, __LINE__);
432                return -1;
433        }
434
435        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
436        if (err < 0) {
437                og_dbi_close(dbi);
438                return -1;
439        }
440
441        res = actualizaConfiguracion(dbi, cfg, computer.id);
442        og_dbi_close(dbi);
443
444        if (!res) {
445                syslog(LOG_ERR, "Problem updating client configuration\n");
446                return -1;
447        }
448
449        if (!cli->autorun && computer.procedure_id) {
450                cli->autorun = true;
451
452                if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
453                        return -1;
454        }
455
456        return 0;
457}
458
459static int update_image_info(struct og_dbi *dbi, const char *image_id,
460                             const char *clonator, const char *compressor,
461                             const char *filesystem, const uint64_t datasize)
462{
463        const char *msglog;
464        dbi_result result;
465
466        result = dbi_conn_queryf(dbi->conn,
467                "UPDATE imagenes"
468                "   SET clonator='%s', compressor='%s',"
469                "       filesystem='%s', datasize=%lld"
470                " WHERE idimagen=%s", clonator, compressor, filesystem,
471                datasize, image_id);
472
473        if (!result) {
474                dbi_conn_error(dbi->conn, &msglog);
475                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
476                       __func__, __LINE__, msglog);
477                return -1;
478        }
479        dbi_result_free(result);
480
481        return 0;
482}
483
484static int og_resp_image_create(json_t *data, struct og_client *cli)
485{
486        struct og_software_legacy soft_legacy;
487        struct og_image_legacy img_legacy;
488        struct og_computer computer = {};
489        const char *compressor = NULL;
490        const char *filesystem = NULL;
491        const char *partition = NULL;
492        const char *software = NULL;
493        const char *image_id = NULL;
494        const char *clonator = NULL;
495        const char *disk = NULL;
496        const char *code = NULL;
497        const char *name = NULL;
498        const char *repo = NULL;
499        uint64_t datasize = 0;
500        struct og_dbi *dbi;
501        const char *key;
502        json_t *value;
503        int err = 0;
504        bool res;
505
506        if (json_typeof(data) != JSON_OBJECT)
507                return -1;
508
509        json_object_foreach(data, key, value) {
510                if (!strcmp(key, "software"))
511                        err = og_json_parse_string(value, &software);
512                else if (!strcmp(key, "partition"))
513                        err = og_json_parse_string(value, &partition);
514                else if (!strcmp(key, "disk"))
515                        err = og_json_parse_string(value, &disk);
516                else if (!strcmp(key, "code"))
517                        err = og_json_parse_string(value, &code);
518                else if (!strcmp(key, "id"))
519                        err = og_json_parse_string(value, &image_id);
520                else if (!strcmp(key, "name"))
521                        err = og_json_parse_string(value, &name);
522                else if (!strcmp(key, "repository"))
523                        err = og_json_parse_string(value, &repo);
524                else if (!strcmp(key, "clonator"))
525                        err = og_json_parse_string(value, &clonator);
526                else if (!strcmp(key, "compressor"))
527                        err = og_json_parse_string(value, &compressor);
528                else if (!strcmp(key, "filesystem"))
529                        err = og_json_parse_string(value, &filesystem);
530                else if (!strcmp(key, "datasize"))
531                        err = og_json_parse_uint64(value, &datasize);
532
533                if (err < 0)
534                        return err;
535        }
536
537        if (!software || !partition || !disk || !code || !image_id || !name ||
538            !repo || !clonator || !compressor || !filesystem || !datasize) {
539                syslog(LOG_ERR, "malformed response json\n");
540                return -1;
541        }
542
543        dbi = og_dbi_open(&ogconfig.db);
544        if (!dbi) {
545                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
546                       __func__, __LINE__);
547                return -1;
548        }
549
550        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
551        if (err < 0) {
552                og_dbi_close(dbi);
553                return -1;
554        }
555
556        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
557                 computer.center);
558        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
559                 software);
560        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
561                 image_id);
562        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
563        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
564        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
565        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
566        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
567        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
568
569        res = actualizaSoftware(dbi,
570                                soft_legacy.software,
571                                img_legacy.part,
572                                soft_legacy.id,
573                                computer.name,
574                                soft_legacy.center);
575        if (!res) {
576                og_dbi_close(dbi);
577                syslog(LOG_ERR, "Problem updating client configuration\n");
578                return -1;
579        }
580
581        res = actualizaCreacionImagen(dbi,
582                                      img_legacy.image_id,
583                                      img_legacy.disk,
584                                      img_legacy.part,
585                                      img_legacy.code,
586                                      img_legacy.repo,
587                                      soft_legacy.id);
588        if (!res) {
589                og_dbi_close(dbi);
590                syslog(LOG_ERR, "Problem updating client configuration\n");
591                return -1;
592        }
593
594        res = update_image_info(dbi, image_id, clonator, compressor,
595                                filesystem, datasize);
596        og_dbi_close(dbi);
597
598        if (res) {
599                syslog(LOG_ERR, "Problem updating image info\n");
600                return -1;
601        }
602
603        return 0;
604}
605
606static int og_resp_image_restore(json_t *data, struct og_client *cli)
607{
608        struct og_software_legacy soft_legacy;
609        struct og_image_legacy img_legacy;
610        struct og_computer computer = {};
611        const char *partition = NULL;
612        const char *image_id = NULL;
613        const char *disk = NULL;
614        const char *msglog;
615        struct og_dbi *dbi;
616        dbi_result result;
617        const char *key;
618        json_t *value;
619        int err = 0;
620
621        if (json_typeof(data) != JSON_OBJECT)
622                return -1;
623
624        json_object_foreach(data, key, value) {
625                if (!strcmp(key, "partition"))
626                        err = og_json_parse_string(value, &partition);
627                else if (!strcmp(key, "disk"))
628                        err = og_json_parse_string(value, &disk);
629                else if (!strcmp(key, "image_id"))
630                        err = og_json_parse_string(value, &image_id);
631
632                if (err < 0)
633                        return err;
634        }
635
636        if (!partition || !disk || !image_id) {
637                syslog(LOG_ERR, "malformed response json\n");
638                return -1;
639        }
640
641        dbi = og_dbi_open(&ogconfig.db);
642        if (!dbi) {
643                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
644                       __func__, __LINE__);
645                return -1;
646        }
647
648        result = dbi_conn_queryf(dbi->conn,
649                                 "SELECT idperfilsoft FROM imagenes "
650                                 " WHERE idimagen='%s'", image_id);
651        if (!result) {
652                og_dbi_close(dbi);
653                syslog(LOG_ERR, "failed to query database\n");
654                return -1;
655        }
656        if (!dbi_result_next_row(result)) {
657                dbi_result_free(result);
658                og_dbi_close(dbi);
659                syslog(LOG_ERR, "software profile does not exist in database\n");
660                return -1;
661        }
662        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
663                 "%d", dbi_result_get_uint(result, "idperfilsoft"));
664        dbi_result_free(result);
665
666        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
667        if (err < 0) {
668                og_dbi_close(dbi);
669                return -1;
670        }
671
672        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
673                 image_id);
674        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
675        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
676        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
677
678        result = dbi_conn_queryf(dbi->conn,
679                                 "UPDATE ordenadores_particiones"
680                                 "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
681                                 "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
682                                 "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
683                                 " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
684                                 img_legacy.image_id, img_legacy.software_id,
685                                 img_legacy.image_id, img_legacy.software_id,
686                                 soft_legacy.id, img_legacy.disk, img_legacy.part);
687        if (!result) {
688                dbi_conn_error(dbi->conn, &msglog);
689                syslog(LOG_ERR, "failed to update database (%s:%d) %s\n",
690                       __func__, __LINE__, msglog);
691                og_dbi_close(dbi);
692                return -1;
693        }
694        dbi_result_free(result);
695        og_dbi_close(dbi);
696
697        return 0;
698}
699
700static int og_agent_http_response_code(const char *buf)
701{
702        if (!strncmp(buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
703                return 200;
704        } else if (!strncmp(buf, "HTTP/1.0 202 Accepted",
705                            strlen("HTTP/1.0 202 Accepted"))) {
706                return 202;
707        } else if (!strncmp(buf, "HTTP/1.0 400 Bad Request",
708                            strlen("HTTP/1.0 400 Bad Request"))) {
709                return 400;
710        } else if (!strncmp(buf, "HTTP/1.0 500 Internal Server Error",
711                            strlen("HTTP/1.0 500 Internal Server Error"))) {
712                return 500;
713        } else if (!strncmp(buf, "HTTP/1.0 503 Service Unavailable",
714                            strlen("HTTP/1.0 503 Service Unavailable"))) {
715                return 503;
716        } else if (!strncmp(buf, "HTTP/1.0 103 Early Hints",
717                            strlen("HTTP/1.0 103 Early Hints"))) {
718                return 103;
719        }
720
721        return -1;
722}
723
724int og_agent_state_process_response(struct og_client *cli)
725{
726        int ret, err = -1, code;
727        json_error_t json_err;
728        bool success;
729        json_t *root;
730        char *body;
731
732        code = og_agent_http_response_code(cli->buf);
733        switch (code) {
734        case 103:
735        case 200:
736                ret = 0;
737                success = true;
738                break;
739        case 202:
740                ret = 1;
741                success = true;
742                break;
743        case 400:
744                ret = -1;
745                success = false;
746                syslog(LOG_ERR, "Client %s:%hu reports malformed HTTP request from server\n",
747                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
748                break;
749        case 500:
750                ret = 0;
751                success = false;
752                cli->last_cmd = OG_CMD_UNSPEC;
753                syslog(LOG_ERR, "Client %s:%hu reports failure to process command\n",
754                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
755                /* ... cancel pending actions related to this task for this client here */
756                break;
757        case 503:
758                ret = 1;
759                success = false;
760                syslog(LOG_ERR, "Client %s:%hu is busy to process command\n",
761                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
762                break;
763        default:
764                ret = -1;
765                success = false;
766                syslog(LOG_ERR, "Client %s:%hu reports unknown HTTP response code\n",
767                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
768                break;
769        }
770
771        if (code != 200 && code != 103) {
772                og_dbi_update_action(cli->last_cmd_id, success);
773                cli->last_cmd_id = 0;
774                return ret;
775        }
776
777        if (!cli->content_length) {
778                og_dbi_update_action(cli->last_cmd_id, true);
779                cli->last_cmd_id = 0;
780                cli->last_cmd = OG_CMD_UNSPEC;
781                return 0;
782        }
783
784        body = strstr(cli->buf, "\r\n\r\n") + 4;
785
786        root = json_loads(body, 0, &json_err);
787        if (!root) {
788                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
789                       __FILE__, __LINE__, json_err.line, json_err.text);
790                return -1;
791        }
792
793        if (code == 103) {
794                err = og_resp_early_hints(cli, root);
795                json_decref(root);
796                return err;
797        }
798
799        switch (cli->last_cmd) {
800        case OG_CMD_PROBE:
801                err = og_resp_probe(cli, root);
802                break;
803        case OG_CMD_SHELL_RUN:
804                err = og_resp_shell_run(cli, root);
805                break;
806        case OG_CMD_HARDWARE:
807                err = og_resp_hardware(root, cli);
808                break;
809        case OG_CMD_SOFTWARE:
810                err = og_resp_software(root, cli);
811                break;
812        case OG_CMD_REFRESH:
813                err = og_resp_refresh(root, cli);
814                break;
815        case OG_CMD_SETUP:
816                err = og_resp_refresh(root, cli);
817                break;
818        case OG_CMD_IMAGE_CREATE:
819                err = og_resp_image_create(root, cli);
820                break;
821        case OG_CMD_IMAGE_RESTORE:
822                err = og_resp_image_restore(root, cli);
823                break;
824        default:
825                err = -1;
826                break;
827        }
828
829        json_decref(root);
830
831        if (err < 0) {
832                err = 0;
833                success = false;
834                /* ... cancel pending actions related to this task for this client here */
835        }
836
837        og_dbi_update_action(cli->last_cmd_id, success);
838        cli->last_cmd_id = 0;
839        cli->last_cmd = OG_CMD_UNSPEC;
840
841        return err;
842}
Note: See TracBrowser for help on using the repository browser.