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

Last change on this file since ff9dbd9 was ff9dbd9, checked in by Jose M. Guisado <jguisado@…>, 3 years ago

#1065 split og_status_session_toggle

Handles non usual situations like a client sending more than
one event of same type.

When toggling, receiving two events of the same type is the
same as receiving two different ones (eg. start, then stop).

Split into _session_start and _session_stop in order to check
valid client status.

  • Property mode set to 100644
File size: 20.5 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        dbi_result query_result;
619        struct og_dbi *dbi;
620        const char *key;
621        json_t *value;
622        int err = 0;
623        bool res;
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        query_result = dbi_conn_queryf(dbi->conn,
653                                       "SELECT idperfilsoft FROM imagenes "
654                                       " WHERE idimagen='%s'",
655                                       image_id);
656        if (!query_result) {
657                og_dbi_close(dbi);
658                syslog(LOG_ERR, "failed to query database\n");
659                return -1;
660        }
661        if (!dbi_result_next_row(query_result)) {
662                dbi_result_free(query_result);
663                og_dbi_close(dbi);
664                syslog(LOG_ERR, "software profile does not exist in database\n");
665                return -1;
666        }
667        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
668                 "%d", dbi_result_get_uint(query_result, "idperfilsoft"));
669        dbi_result_free(query_result);
670
671        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
672        if (err < 0) {
673                og_dbi_close(dbi);
674                return -1;
675        }
676
677        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
678                 image_id);
679        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
680        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
681        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
682
683        res = actualizaRestauracionImagen(dbi,
684                                          img_legacy.image_id,
685                                          img_legacy.disk,
686                                          img_legacy.part,
687                                          soft_legacy.id,
688                                          img_legacy.software_id);
689        og_dbi_close(dbi);
690
691        if (!res) {
692                syslog(LOG_ERR, "Problem updating client configuration\n");
693                return -1;
694        }
695
696        return 0;
697}
698
699static int og_agent_http_response_code(const char *buf)
700{
701        if (!strncmp(buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
702                return 200;
703        } else if (!strncmp(buf, "HTTP/1.0 202 Accepted",
704                            strlen("HTTP/1.0 202 Accepted"))) {
705                return 202;
706        } else if (!strncmp(buf, "HTTP/1.0 400 Bad Request",
707                            strlen("HTTP/1.0 400 Bad Request"))) {
708                return 400;
709        } else if (!strncmp(buf, "HTTP/1.0 500 Internal Server Error",
710                            strlen("HTTP/1.0 500 Internal Server Error"))) {
711                return 500;
712        } else if (!strncmp(buf, "HTTP/1.0 503 Service Unavailable",
713                            strlen("HTTP/1.0 503 Service Unavailable"))) {
714                return 503;
715        } else if (!strncmp(buf, "HTTP/1.0 103 Early Hints",
716                            strlen("HTTP/1.0 103 Early Hints"))) {
717                return 103;
718        }
719
720        return -1;
721}
722
723int og_agent_state_process_response(struct og_client *cli)
724{
725        int ret, err = -1, code;
726        json_error_t json_err;
727        bool success;
728        json_t *root;
729        char *body;
730
731        code = og_agent_http_response_code(cli->buf);
732        switch (code) {
733        case 103:
734        case 200:
735                ret = 0;
736                success = true;
737                break;
738        case 202:
739                ret = 1;
740                success = true;
741                break;
742        case 400:
743                ret = -1;
744                success = false;
745                syslog(LOG_ERR, "Client %s:%hu reports malformed HTTP request from server\n",
746                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
747                break;
748        case 500:
749                ret = 0;
750                success = false;
751                cli->last_cmd = OG_CMD_UNSPEC;
752                syslog(LOG_ERR, "Client %s:%hu reports failure to process command\n",
753                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
754                /* ... cancel pending actions related to this task for this client here */
755                break;
756        case 503:
757                ret = 1;
758                success = false;
759                syslog(LOG_ERR, "Client %s:%hu is busy to process command\n",
760                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
761                break;
762        default:
763                ret = -1;
764                success = false;
765                syslog(LOG_ERR, "Client %s:%hu reports unknown HTTP response code\n",
766                       inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
767                break;
768        }
769
770        if (code != 200 && code != 103) {
771                og_dbi_update_action(cli->last_cmd_id, success);
772                cli->last_cmd_id = 0;
773                return ret;
774        }
775
776        if (!cli->content_length) {
777                og_dbi_update_action(cli->last_cmd_id, true);
778                cli->last_cmd_id = 0;
779                cli->last_cmd = OG_CMD_UNSPEC;
780                return 0;
781        }
782
783        body = strstr(cli->buf, "\r\n\r\n") + 4;
784
785        root = json_loads(body, 0, &json_err);
786        if (!root) {
787                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
788                       __FILE__, __LINE__, json_err.line, json_err.text);
789                return -1;
790        }
791
792        if (code == 103) {
793                err = og_resp_early_hints(cli, root);
794                json_decref(root);
795                return err;
796        }
797
798        switch (cli->last_cmd) {
799        case OG_CMD_PROBE:
800                err = og_resp_probe(cli, root);
801                break;
802        case OG_CMD_SHELL_RUN:
803                err = og_resp_shell_run(cli, root);
804                break;
805        case OG_CMD_HARDWARE:
806                err = og_resp_hardware(root, cli);
807                break;
808        case OG_CMD_SOFTWARE:
809                err = og_resp_software(root, cli);
810                break;
811        case OG_CMD_REFRESH:
812                err = og_resp_refresh(root, cli);
813                break;
814        case OG_CMD_SETUP:
815                err = og_resp_refresh(root, cli);
816                break;
817        case OG_CMD_IMAGE_CREATE:
818                err = og_resp_image_create(root, cli);
819                break;
820        case OG_CMD_IMAGE_RESTORE:
821                err = og_resp_image_restore(root, cli);
822                break;
823        default:
824                err = -1;
825                break;
826        }
827
828        json_decref(root);
829
830        if (err < 0) {
831                err = 0;
832                success = false;
833                /* ... cancel pending actions related to this task for this client here */
834        }
835
836        og_dbi_update_action(cli->last_cmd_id, success);
837        cli->last_cmd_id = 0;
838        cli->last_cmd = OG_CMD_UNSPEC;
839
840        return err;
841}
Note: See TracBrowser for help on using the repository browser.