supervisor: Setup services for local API use
[src/app-framework-binder.git] / src / uuid.c
1 /*
2  * Copyright (C) 2016-2019 "IoT.bzh"
3  * Author: José Bollo <jose.bollo@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <stdint.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <uuid/uuid.h>
24
25 #include "uuid.h"
26
27 /**
28  * generate a new fresh 'uuid'
29  */
30 void uuid_new_binary(uuid_binary_t uuid)
31 {
32 #if defined(USE_UUID_GENERATE)
33         uuid_generate(uuid);
34 #else
35         struct timespec ts;
36         static uint16_t pid;
37         static uint16_t counter;
38         static char state[32];
39         static struct random_data rdata;
40
41         int32_t x;
42         clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
43         if (pid == 0) {
44                 pid = (uint16_t)getpid();
45                 counter = (uint16_t)(ts.tv_nsec >> 8);
46                 rdata.state = NULL;
47                 initstate_r((((unsigned)pid) << 16) + ((unsigned)counter),
48                                         state, sizeof state, &rdata);
49         }
50         ts.tv_nsec ^= (long)ts.tv_sec;
51         if (++counter == 0)
52                 counter = 1;
53
54         uuid[0] = (char)(ts.tv_nsec >> 24);
55         uuid[1] = (char)(ts.tv_nsec >> 16);
56         uuid[2] = (char)(ts.tv_nsec >> 8);
57         uuid[3] = (char)(ts.tv_nsec);
58
59         uuid[4] = (char)(pid >> 8);
60         uuid[5] = (char)(pid);
61
62         random_r(&rdata, &x);
63         uuid[6] = (char)(((x >> 16) & 0x0f) | 0x40); /* pseudo-random version */
64         uuid[7] = (char)(x >> 8);
65
66         random_r(&rdata, &x);
67         uuid[8] = (char)(((x >> 16) & 0x3f) | 0x80); /* variant RFC4122 */
68         uuid[9] = (char)(x >> 8);
69
70         random_r(&rdata, &x);
71         uuid[10] = (char)(x >> 16);
72         uuid[11] = (char)(x >> 8);
73
74         random_r(&rdata, &x);
75         uuid[12] = (char)(x >> 16);
76         uuid[13] = (char)(x >> 8);
77
78         uuid[14] = (char)(counter >> 8);
79         uuid[15] = (char)(counter);
80 #endif
81 }
82
83 void uuid_new_stringz(uuid_stringz_t uuid)
84 {
85         uuid_t newuuid;
86         uuid_new_binary(newuuid);
87         uuid_unparse_lower(newuuid, uuid);
88 }