• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-mcu / 1510560513

24 Oct 2024 12:04PM UTC coverage: 2.013% (+0.007%) from 2.006%
1510560513

push

gitlab-ci

lluiscampos
chore: Move variable declaration so that its always initialized at END

Clears `clang` warning:
```
.../mender-api.c:250:9: error: variable 'provides' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized]
  250 |     if (NULL == cJSON_AddStringToObject(json_provides, "device_type", mender_api_config.device_type)) {
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/llvm-18/lib/clang/18/include/__stddef_null.h:26:14: note: expanded from macro 'NULL'
   26 | #define NULL ((void*)0)
      |              ^
.../mender-api.c:302:35: note: uninitialized use occurs here
  302 |     mender_utils_free_linked_list(provides);
      |                                   ^~~~~~~~
.../mender-api.c:250:5: note: remove the 'if' if its condition is always false
  250 |     if (NULL == cJSON_AddStringToObject(json_provides, "device_type", mender_api_config.device_type)) {
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  251 |         mender_log_error("Unable to allocate memory");
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  252 |         goto END;
      |         ~~~~~~~~~
  253 |     }
      |     ~

```

Signed-off-by: Lluis Campos <lluis.campos@northern.tech>

31 of 1540 relevant lines covered (2.01%)

0.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/core/src/mender-api.c
1
/**
2
 * @file      mender-api.c
3
 * @brief     Implementation of the Mender API
4
 *
5
 * Copyright joelguittet and mender-mcu-client contributors
6
 * Copyright Northern.tech AS
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
#define _GNU_SOURCE // asprintf
22
#include <stdio.h>  // asprintf
23

24
#include "mender-api.h"
25
#include "mender-artifact.h"
26
#include "mender-storage.h"
27
#include "mender-http.h"
28
#include "mender-log.h"
29
#include "mender-tls.h"
30

31
/**
32
 * @brief Paths of the mender-server APIs
33
 */
34
#define MENDER_API_PATH_POST_AUTHENTICATION_REQUESTS "/api/devices/v1/authentication/auth_requests"
35
#define MENDER_API_PATH_GET_NEXT_DEPLOYMENT          "/api/devices/v1/deployments/device/deployments/next"
36
#define MENDER_API_PATH_POST_NEXT_DEPLOYMENT_V2      "/api/devices/v2/deployments/device/deployments/next"
37
#define MENDER_API_PATH_PUT_DEPLOYMENT_STATUS        "/api/devices/v1/deployments/device/deployments/%s/status"
38
#define MENDER_API_PATH_GET_DEVICE_CONFIGURATION     "/api/devices/v1/deviceconfig/configuration"
39
#define MENDER_API_PATH_PUT_DEVICE_CONFIGURATION     "/api/devices/v1/deviceconfig/configuration"
40
#define MENDER_API_PATH_GET_DEVICE_CONNECT           "/api/devices/v1/deviceconnect/connect"
41
#define MENDER_API_PATH_PUT_DEVICE_ATTRIBUTES        "/api/devices/v1/inventory/device/attributes"
42

43
/**
44
 * @brief Mender API configuration
45
 */
46
static mender_api_config_t mender_api_config;
47

48
/**
49
 * @brief Authentication token
50
 */
51
static char *mender_api_jwt = NULL;
52

53
/**
54
 * @brief HTTP callback used to handle text content
55
 * @param event HTTP client event
56
 * @param data Data received
57
 * @param data_length Data length
58
 * @param params Callback parameters
59
 * @return MENDER_OK if the function succeeds, error code otherwise
60
 */
61
static mender_err_t mender_api_http_text_callback(mender_http_client_event_t event, void *data, size_t data_length, void *params);
62

63
/**
64
 * @brief Artifact name variable
65
 */
66
static char *artifact_name = NULL;
67

68
mender_err_t
69
mender_api_init(mender_api_config_t *config) {
×
70

71
    assert(NULL != config);
×
72
    assert(NULL != config->device_type);
×
73
    assert(NULL != config->host);
×
74
    mender_err_t ret;
75

76
    /* Load and set artifact_name here */
77
    if ((MENDER_OK != mender_storage_get_artifact_name(&artifact_name)) && (NULL != artifact_name)) {
×
78
        mender_log_error("Unable to get artifact name");
×
79
        return MENDER_FAIL;
×
80
    }
81
    /* Save configuration */
82
    memcpy(&mender_api_config, config, sizeof(mender_api_config_t));
×
83

84
    /* Initializations */
85
    mender_http_config_t mender_http_config = { .host = mender_api_config.host };
×
86
    if (MENDER_OK != (ret = mender_http_init(&mender_http_config))) {
×
87
        mender_log_error("Unable to initialize HTTP");
×
88
        return ret;
×
89
    }
90

91
    return ret;
×
92
}
93

94
bool
95
mender_api_is_authenticated(void) {
×
96
    return NULL != mender_api_jwt;
×
97
}
98

99
mender_err_t
100
mender_api_perform_authentication(mender_err_t (*get_identity)(mender_identity_t **identity)) {
×
101

102
    assert(NULL != get_identity);
×
103
    mender_err_t       ret;
104
    char              *public_key_pem       = NULL;
×
105
    cJSON             *json_identity        = NULL;
×
106
    mender_identity_t *identity             = NULL;
×
107
    char              *unformatted_identity = NULL;
×
108
    cJSON             *json_payload         = NULL;
×
109
    char              *payload              = NULL;
×
110
    char              *response             = NULL;
×
111
    char              *signature            = NULL;
×
112
    size_t             signature_length     = 0;
×
113
    int                status               = 0;
×
114

115
    /* Get public key in PEM format */
116
    if (MENDER_OK != (ret = mender_tls_get_public_key_pem(&public_key_pem))) {
×
117
        mender_log_error("Unable to get public key");
×
118
        goto END;
×
119
    }
120

121
    /* Get identity */
122
    if (MENDER_OK != (ret = get_identity(&identity))) {
×
123
        mender_log_error("Unable to get identity");
×
124
        goto END;
×
125
    }
126

127
    /* Format identity */
128
    if (MENDER_OK != (ret = mender_utils_identity_to_json(identity, &json_identity))) {
×
129
        mender_log_error("Unable to format identity");
×
130
        goto END;
×
131
    }
132
    if (NULL == (unformatted_identity = cJSON_PrintUnformatted(json_identity))) {
×
133
        mender_log_error("Unable to allocate memory");
×
134
        ret = MENDER_FAIL;
×
135
        goto END;
×
136
    }
137

138
    /* Format payload */
139
    if (NULL == (json_payload = cJSON_CreateObject())) {
×
140
        mender_log_error("Unable to allocate memory");
×
141
        ret = MENDER_FAIL;
×
142
        goto END;
×
143
    }
144
    cJSON_AddStringToObject(json_payload, "id_data", unformatted_identity);
×
145
    cJSON_AddStringToObject(json_payload, "pubkey", public_key_pem);
×
146
    if (NULL != mender_api_config.tenant_token) {
×
147
        cJSON_AddStringToObject(json_payload, "tenant_token", mender_api_config.tenant_token);
×
148
    }
149
    if (NULL == (payload = cJSON_PrintUnformatted(json_payload))) {
×
150
        mender_log_error("Unable to allocate memory");
×
151
        ret = MENDER_FAIL;
×
152
        goto END;
×
153
    }
154

155
    /* Sign payload */
156
    if (MENDER_OK != (ret = mender_tls_sign_payload(payload, &signature, &signature_length))) {
×
157
        mender_log_error("Unable to sign payload");
×
158
        goto END;
×
159
    }
160

161
    /* Perform HTTP request */
162
    if (MENDER_OK
×
163
        != (ret = mender_http_perform(NULL,
×
164
                                      MENDER_API_PATH_POST_AUTHENTICATION_REQUESTS,
165
                                      MENDER_HTTP_POST,
166
                                      payload,
167
                                      signature,
168
                                      &mender_api_http_text_callback,
169
                                      (void *)&response,
170
                                      &status))) {
171
        mender_log_error("Unable to perform HTTP request");
×
172
        goto END;
×
173
    }
174

175
    /* Treatment depending of the status */
176
    if (200 == status) {
×
177
        if (NULL == response) {
×
178
            mender_log_error("Response is empty");
×
179
            ret = MENDER_FAIL;
×
180
            goto END;
×
181
        }
182
        if (NULL != mender_api_jwt) {
×
183
            free(mender_api_jwt);
×
184
        }
185
        if (NULL == (mender_api_jwt = strdup(response))) {
×
186
            mender_log_error("Unable to allocate memory");
×
187
            ret = MENDER_FAIL;
×
188
            goto END;
×
189
        }
190
        ret = MENDER_OK;
×
191
    } else {
192
        mender_api_print_response_error(response, status);
×
193
        ret = MENDER_FAIL;
×
194
    }
195

196
END:
×
197

198
    /* Release memory */
199
    free(unformatted_identity);
×
200
    free(response);
×
201
    free(signature);
×
202
    free(payload);
×
203
    cJSON_Delete(json_payload);
×
204
    cJSON_Delete(json_identity);
×
205
    free(public_key_pem);
×
206

207
    return ret;
×
208
}
209

210
static mender_err_t
211
api_check_for_deployment_v2(int *status, void *response) {
×
212
    assert(NULL != status);
×
213
    assert(NULL != response);
×
214
    assert(NULL != artifact_name);
×
215

216
    mender_err_t ret          = MENDER_FAIL;
×
217
    cJSON       *json_payload = NULL;
×
218
    char        *payload      = NULL;
×
219
#ifdef CONFIG_MENDER_PROVIDES_DEPENDS
220
#ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT
221
    mender_key_value_list_t *provides = NULL;
222
#endif /* CONFIG_MENDER_FULL_PARSE_ARTIFACT */
223
#endif /* CONFIG_MENDER_PROVIDES_DEPENDS */
224

225
    /* Create payload */
226
    if (NULL == (json_payload = cJSON_CreateObject())) {
×
227
        mender_log_error("Unable to allocate memory");
×
228
        goto END;
×
229
    }
230

231
    /* Add "device_provides" entity to payload */
232
    cJSON *json_provides = NULL;
×
233
    if (NULL == (json_provides = cJSON_AddObjectToObject(json_payload, "device_provides"))) {
×
234
        mender_log_error("Unable to allocate memory");
×
235
        goto END;
×
236
    }
237

238
    if (NULL == cJSON_AddStringToObject(json_provides, "device_type", mender_api_config.device_type)) {
×
239
        mender_log_error("Unable to allocate memory");
×
240
        goto END;
×
241
    }
242

243
#ifdef CONFIG_MENDER_PROVIDES_DEPENDS
244
#ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT
245
    /* Add provides from storage */
246
    if (MENDER_FAIL == mender_storage_get_provides(&provides)) {
247
        mender_log_error("Unable to get provides");
248
        goto END;
249
    }
250
    for (mender_key_value_list_t *item = provides; NULL != item; item = item->next) {
251
        if (NULL == cJSON_AddStringToObject(json_provides, item->key, item->value)) {
252
            mender_log_error("Unable to allocate memory");
253
            goto END;
254
        }
255
    }
256
#endif /* CONFIG_MENDER_FULL_PARSE_ARTIFACT */
257
#endif /* CONFIG_MENDER_PROVIDES_DEPENDS */
258

259
    if (NULL == cJSON_AddStringToObject(json_provides, "artifact_name", artifact_name)) {
×
260
        mender_log_error("Unable to allocate memory");
×
261
        goto END;
×
262
    }
263

264
    if (NULL == (payload = cJSON_PrintUnformatted(json_payload))) {
×
265
        mender_log_error("Unable to allocate memory");
×
266
        goto END;
×
267
    }
268

269
    /* Perform HTTP request */
270
    if (MENDER_OK
×
271
        != (ret = mender_http_perform(mender_api_jwt,
×
272
                                      MENDER_API_PATH_POST_NEXT_DEPLOYMENT_V2,
273
                                      MENDER_HTTP_POST,
274
                                      payload,
275
                                      NULL,
276
                                      &mender_api_http_text_callback,
277
                                      (void *)response,
278
                                      status))) {
279
        mender_log_error("Unable to perform HTTP request");
×
280
        goto END;
×
281
    }
282

283
    ret = MENDER_OK;
×
284

285
END:
×
286

287
#ifdef CONFIG_MENDER_PROVIDES_DEPENDS
288
#ifdef CONFIG_MENDER_FULL_PARSE_ARTIFACT
289
    mender_utils_free_linked_list(provides);
290
#endif /* CONFIG_MENDER_FULL_PARSE_ARTIFACT */
291
#endif /* CONFIG_MENDER_PROVIDES_DEPENDS */
292
    cJSON_Delete(json_payload);
×
293
    free(payload);
×
294
    return ret;
×
295
}
296

297
static mender_err_t
298
api_check_for_deployment_v1(int *status, void *response) {
×
299

300
    assert(NULL != status);
×
301
    assert(NULL != response);
×
302
    assert(NULL != artifact_name);
×
303

304
    mender_err_t ret  = MENDER_FAIL;
×
305
    char        *path = NULL;
×
306

307
    /* Compute path */
308
    if (-1 == asprintf(&path, MENDER_API_PATH_GET_NEXT_DEPLOYMENT "?artifact_name=%s&device_type=%s", artifact_name, mender_api_config.device_type)) {
×
309
        mender_log_error("Unable to allocate memory");
×
310
        goto END;
×
311
    }
312

313
    /* Perform HTTP request */
314
    if (MENDER_OK != (ret = mender_http_perform(mender_api_jwt, path, MENDER_HTTP_GET, NULL, NULL, &mender_api_http_text_callback, (void *)response, status))) {
×
315
        mender_log_error("Unable to perform HTTP request");
×
316
        goto END;
×
317
    }
318

319
    ret = MENDER_OK;
×
320

321
END:
×
322

323
    /* Release memory */
324
    free(path);
×
325

326
    return ret;
×
327
}
328

329
mender_err_t
330
mender_api_check_for_deployment(mender_api_deployment_data_t *deployment) {
×
331

332
    assert(NULL != deployment);
×
333
    mender_err_t ret      = MENDER_FAIL;
×
334
    char        *response = NULL;
×
335
    int          status   = 0;
×
336

337
    if (MENDER_FAIL == (ret = api_check_for_deployment_v2(&status, (void *)&response))) {
×
338
        goto END;
×
339
    }
340

341
    /* Yes, 404 still means MENDER_OK above */
342
    if (404 == status) {
×
343
        mender_log_debug("POST request to v2 version of the deployments API failed, falling back to v1 version and GET");
344
        FREE_AND_NULL(response);
×
345
        if (MENDER_FAIL == (ret = api_check_for_deployment_v1(&status, (void *)&response))) {
×
346
            goto END;
×
347
        }
348
    }
349

350
    /* Treatment depending of the status */
351
    if (200 == status) {
×
352
        cJSON *json_response = cJSON_Parse(response);
×
353
        if (NULL != json_response) {
×
354
            cJSON *json_id = cJSON_GetObjectItem(json_response, "id");
×
355
            if (NULL != json_id) {
×
356
                if (NULL == (deployment->id = strdup(cJSON_GetStringValue(json_id)))) {
×
357
                    ret = MENDER_FAIL;
×
358
                    goto END;
×
359
                }
360
            }
361
            cJSON *json_artifact = cJSON_GetObjectItem(json_response, "artifact");
×
362
            if (NULL != json_artifact) {
×
363
                cJSON *json_artifact_name = cJSON_GetObjectItem(json_artifact, "artifact_name");
×
364
                if (NULL != json_artifact_name) {
×
365
                    if (NULL == (deployment->artifact_name = strdup(cJSON_GetStringValue(json_artifact_name)))) {
×
366
                        ret = MENDER_FAIL;
×
367
                        goto END;
×
368
                    }
369
                }
370
                cJSON *json_source = cJSON_GetObjectItem(json_artifact, "source");
×
371
                if (NULL != json_source) {
×
372
                    cJSON *json_uri = cJSON_GetObjectItem(json_source, "uri");
×
373
                    if (NULL != json_uri) {
×
374
                        if (NULL == (deployment->uri = strdup(cJSON_GetStringValue(json_uri)))) {
×
375
                            ret = MENDER_FAIL;
×
376
                            goto END;
×
377
                        }
378
                        ret = MENDER_OK;
×
379
                    } else {
380
                        mender_log_error("Invalid response");
×
381
                        ret = MENDER_FAIL;
×
382
                    }
383
                } else {
384
                    mender_log_error("Invalid response");
×
385
                    ret = MENDER_FAIL;
×
386
                }
387
                cJSON *json_device_types_compatible = cJSON_GetObjectItem(json_artifact, "device_types_compatible");
×
388
                if (NULL != json_device_types_compatible && cJSON_IsArray(json_device_types_compatible)) {
×
389
                    deployment->device_types_compatible_size = cJSON_GetArraySize(json_device_types_compatible);
×
390
                    deployment->device_types_compatible      = (char **)malloc(deployment->device_types_compatible_size * sizeof(char *));
×
391
                    if (NULL == deployment->device_types_compatible) {
×
392
                        mender_log_error("Unable to allocate memory");
×
393
                        ret = MENDER_FAIL;
×
394
                        goto END;
×
395
                    }
396
                    for (size_t i = 0; i < deployment->device_types_compatible_size; i++) {
×
397
                        cJSON *json_device_type = cJSON_GetArrayItem(json_device_types_compatible, i);
×
398
                        if (NULL != json_device_type && cJSON_IsString(json_device_type)) {
×
399
                            if (NULL == (deployment->device_types_compatible[i] = strdup(cJSON_GetStringValue(json_device_type)))) {
×
400
                                ret = MENDER_FAIL;
×
401
                                goto END;
×
402
                            }
403
                        } else {
404
                            mender_log_error("Could not get device type form device_types_compatible array");
×
405
                            ret = MENDER_FAIL;
×
406
                        }
407
                    }
408
                } else {
409
                    mender_log_error("Could not load device_types_compatible");
×
410
                    ret = MENDER_FAIL;
×
411
                }
412
            } else {
413
                mender_log_error("Invalid response");
×
414
                ret = MENDER_FAIL;
×
415
            }
416
            cJSON_Delete(json_response);
×
417
        } else {
418
            mender_log_error("Invalid response");
×
419
            ret = MENDER_FAIL;
×
420
        }
421
    } else if (204 == status) {
×
422
        /* No response expected */
423
        ret = MENDER_NOT_FOUND;
×
424
    } else {
425
        mender_api_print_response_error(response, status);
×
426
        ret = MENDER_FAIL;
×
427
    }
428

429
END:
×
430

431
    /* Release memory */
432
    free(response);
×
433

434
    return ret;
×
435
}
436

437
mender_err_t
438
mender_api_publish_deployment_status(const char *id, mender_deployment_status_t deployment_status) {
×
439

440
    assert(NULL != id);
×
441
    mender_err_t ret;
442
    char        *value        = NULL;
×
443
    cJSON       *json_payload = NULL;
×
444
    char        *payload      = NULL;
×
445
    char        *path         = NULL;
×
446
    char        *response     = NULL;
×
447
    int          status       = 0;
×
448

449
    /* Deployment status to string */
450
    if (NULL == (value = mender_utils_deployment_status_to_string(deployment_status))) {
×
451
        mender_log_error("Invalid status");
×
452
        ret = MENDER_FAIL;
×
453
        goto END;
×
454
    }
455

456
    /* Format payload */
457
    if (NULL == (json_payload = cJSON_CreateObject())) {
×
458
        mender_log_error("Unable to allocate memory");
×
459
        ret = MENDER_FAIL;
×
460
        goto END;
×
461
    }
462
    cJSON_AddStringToObject(json_payload, "status", value);
×
463
    if (NULL == (payload = cJSON_PrintUnformatted(json_payload))) {
×
464
        mender_log_error("Unable to allocate memory");
×
465
        ret = MENDER_FAIL;
×
466
        goto END;
×
467
    }
468

469
    /* Compute path */
470
    size_t str_length = strlen(MENDER_API_PATH_PUT_DEPLOYMENT_STATUS) - strlen("%s") + strlen(id) + 1;
×
471
    if (NULL == (path = (char *)malloc(str_length))) {
×
472
        mender_log_error("Unable to allocate memory");
×
473
        ret = MENDER_FAIL;
×
474
        goto END;
×
475
    }
476
    snprintf(path, str_length, MENDER_API_PATH_PUT_DEPLOYMENT_STATUS, id);
×
477

478
    /* Perform HTTP request */
479
    if (MENDER_OK
×
480
        != (ret = mender_http_perform(mender_api_jwt, path, MENDER_HTTP_PUT, payload, NULL, &mender_api_http_text_callback, (void *)&response, &status))) {
×
481
        mender_log_error("Unable to perform HTTP request");
×
482
        goto END;
×
483
    }
484

485
    /* Treatment depending of the status */
486
    if (204 == status) {
×
487
        /* No response expected */
488
        ret = MENDER_OK;
×
489
    } else {
490
        mender_api_print_response_error(response, status);
×
491
        ret = MENDER_FAIL;
×
492
    }
493

494
END:
×
495

496
    /* Release memory */
497
    free(response);
×
498
    free(path);
×
499
    free(payload);
×
500
    cJSON_Delete(json_payload);
×
501

502
    return ret;
×
503
}
504

505
#ifdef CONFIG_MENDER_CLIENT_INVENTORY
506

507
mender_err_t
508
mender_api_publish_inventory_data(mender_keystore_t *inventory) {
509

510
    assert(NULL != artifact_name);
511

512
    mender_err_t ret;
513
    char        *payload  = NULL;
514
    char        *response = NULL;
515
    int          status   = 0;
516

517
    /* Format payload */
518
    cJSON *object = cJSON_CreateArray();
519
    if (NULL == object) {
520
        mender_log_error("Unable to allocate memory");
521
        ret = MENDER_FAIL;
522
        goto END;
523
    }
524
    cJSON *item = cJSON_CreateObject();
525
    if (NULL == item) {
526
        mender_log_error("Unable to allocate memory");
527
        ret = MENDER_FAIL;
528
        goto END;
529
    }
530
    cJSON_AddStringToObject(item, "name", "artifact_name");
531
    cJSON_AddStringToObject(item, "value", artifact_name);
532
    cJSON_AddItemToArray(object, item);
533
    item = cJSON_CreateObject();
534
    if (NULL == item) {
535
        mender_log_error("Unable to allocate memory");
536
        ret = MENDER_FAIL;
537
        goto END;
538
    }
539
    cJSON_AddStringToObject(item, "name", "rootfs-image.version");
540
    cJSON_AddStringToObject(item, "value", artifact_name);
541
    cJSON_AddItemToArray(object, item);
542
    item = cJSON_CreateObject();
543
    if (NULL == item) {
544
        mender_log_error("Unable to allocate memory");
545
        ret = MENDER_FAIL;
546
        goto END;
547
    }
548
    cJSON_AddStringToObject(item, "name", "device_type");
549
    cJSON_AddStringToObject(item, "value", mender_api_config.device_type);
550
    cJSON_AddItemToArray(object, item);
551
    if (NULL != inventory) {
552
        size_t index = 0;
553
        while ((NULL != inventory[index].name) && (NULL != inventory[index].value)) {
554
            if (NULL == (item = cJSON_CreateObject())) {
555
                mender_log_error("Unable to allocate memory");
556
                ret = MENDER_FAIL;
557
                goto END;
558
            }
559
            cJSON_AddStringToObject(item, "name", inventory[index].name);
560
            cJSON_AddStringToObject(item, "value", inventory[index].value);
561
            cJSON_AddItemToArray(object, item);
562
            index++;
563
        }
564
    }
565
    if (NULL == (payload = cJSON_PrintUnformatted(object))) {
566
        mender_log_error("Unable to allocate memory");
567
        ret = MENDER_FAIL;
568
        goto END;
569
    }
570

571
    /* Perform HTTP request */
572
    if (MENDER_OK
573
        != (ret = mender_http_perform(mender_api_jwt,
574
                                      MENDER_API_PATH_PUT_DEVICE_ATTRIBUTES,
575
                                      MENDER_HTTP_PUT,
576
                                      payload,
577
                                      NULL,
578
                                      &mender_api_http_text_callback,
579
                                      (void *)&response,
580
                                      &status))) {
581
        mender_log_error("Unable to perform HTTP request");
582
        goto END;
583
    }
584

585
    /* Treatment depending of the status */
586
    if (200 == status) {
587
        /* No response expected */
588
        ret = MENDER_OK;
589
    } else {
590
        mender_api_print_response_error(response, status);
591
        ret = MENDER_FAIL;
592
    }
593

594
END:
595

596
    /* Release memory */
597
    free(response);
598
    free(payload);
599
    cJSON_Delete(object);
600

601
    return ret;
602
}
603

604
#endif /* CONFIG_MENDER_CLIENT_INVENTORY */
605

606
mender_err_t
607
mender_api_exit(void) {
×
608

609
    /* Release all modules */
610
    mender_http_exit();
×
611

612
    /* Release memory */
613
    FREE_AND_NULL(mender_api_jwt);
×
614
    FREE_AND_NULL(artifact_name);
×
615

616
    return MENDER_OK;
×
617
}
618

619
static mender_err_t
620
mender_api_http_text_callback(mender_http_client_event_t event, void *data, size_t data_length, void *params) {
×
621

622
    assert(NULL != params);
×
623
    char       **response = (char **)params;
×
624
    mender_err_t ret      = MENDER_OK;
×
625
    char        *tmp;
626

627
    /* Treatment depending of the event */
628
    switch (event) {
×
629
        case MENDER_HTTP_EVENT_CONNECTED:
×
630
            /* Nothing to do */
631
            break;
×
632
        case MENDER_HTTP_EVENT_DATA_RECEIVED:
×
633
            /* Check input data */
634
            if ((NULL == data) || (0 == data_length)) {
×
635
                mender_log_error("Invalid data received");
×
636
                ret = MENDER_FAIL;
×
637
                break;
×
638
            }
639
            /* Concatenate data to the response */
640
            size_t response_length = (NULL != *response) ? strlen(*response) : 0;
×
641
            if (NULL == (tmp = realloc(*response, response_length + data_length + 1))) {
×
642
                mender_log_error("Unable to allocate memory");
×
643
                ret = MENDER_FAIL;
×
644
                break;
×
645
            }
646
            *response = tmp;
×
647
            memcpy((*response) + response_length, data, data_length);
×
648
            *((*response) + response_length + data_length) = '\0';
×
649
            break;
×
650
        case MENDER_HTTP_EVENT_DISCONNECTED:
×
651
            /* Nothing to do */
652
            break;
×
653
        case MENDER_HTTP_EVENT_ERROR:
×
654
            /* Downloading the response fails */
655
            mender_log_error("An error occurred");
×
656
            ret = MENDER_FAIL;
×
657
            break;
×
658
        default:
×
659
            /* Should no occur */
660
            ret = MENDER_FAIL;
×
661
            break;
×
662
    }
663

664
    return ret;
×
665
}
666

667
void
668
mender_api_print_response_error(char *response, int status) {
×
669

670
    char *desc;
671

672
    /* Treatment depending of the status */
673
    if (NULL != (desc = mender_utils_http_status_to_string(status))) {
×
674
        if (NULL != response) {
×
675
            cJSON *json_response = cJSON_Parse(response);
×
676
            if (NULL != json_response) {
×
677
                cJSON *json_error = cJSON_GetObjectItemCaseSensitive(json_response, "error");
×
678
                if (NULL != json_error) {
×
679
                    mender_log_error("[%d] %s: %s", status, desc, cJSON_GetStringValue(json_error));
×
680
                } else {
681
                    mender_log_error("[%d] %s: unknown error", status, desc);
×
682
                }
683
                cJSON_Delete(json_response);
×
684
            } else {
685
                mender_log_error("[%d] %s: unknown error", status, desc);
×
686
            }
687
        } else {
688
            mender_log_error("[%d] %s: unknown error", status, desc);
×
689
        }
690
    } else {
691
        mender_log_error("Unknown error occurred, status=%d", status);
×
692
    }
693
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc