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

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

#1065 Add support for client events

ogServer supports events from clients in an agent mode
(linux/windows).

Client sends event information (eg. user login/logout)
via a 103 Early Hints http response message.

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