Line data Source code
1 : /* SPDX-License-Identifier: Apache-2.0 */
2 : /**
3 : * Copyright (C) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
4 : *
5 : * @file nnstreamer-edge-util.c
6 : * @date 24 August 2022
7 : * @brief Utility functions.
8 : * @see https://github.com/nnstreamer/nnstreamer-edge
9 : * @author Jaeyun Jung <jy1210.jung@samsung.com>
10 : * @bug No known bugs except for NYI items
11 : */
12 :
13 : #define _GNU_SOURCE
14 : #include <stdio.h>
15 : #include <stdarg.h>
16 : #include <inttypes.h>
17 : #include "nnstreamer-edge-log.h"
18 : #include "nnstreamer-edge-util.h"
19 :
20 : /**
21 : * @brief Generate ID.
22 : */
23 : int64_t
24 3 : nns_edge_generate_id (void)
25 : {
26 : struct timespec ts;
27 : int64_t _id;
28 :
29 3 : clock_gettime (CLOCK_MONOTONIC, &ts);
30 3 : _id = ((int64_t) ts.tv_sec) * 1000000 + ts.tv_nsec / 1000;
31 :
32 3 : return _id;
33 : }
34 :
35 : /**
36 : * @brief Get the version of nnstreamer-edge.
37 : */
38 : void
39 99 : nns_edge_get_version (unsigned int *major, unsigned int *minor,
40 : unsigned int *micro)
41 : {
42 99 : if (major)
43 99 : *major = VERSION_MAJOR;
44 99 : if (minor)
45 99 : *minor = VERSION_MINOR;
46 99 : if (micro)
47 99 : *micro = VERSION_MICRO;
48 99 : }
49 :
50 : /**
51 : * @brief Generate the version key.
52 : */
53 : uint64_t
54 98 : nns_edge_generate_version_key (void)
55 : {
56 : unsigned int major, minor, micro;
57 :
58 98 : nns_edge_get_version (&major, &minor, µ);
59 :
60 98 : return (0xefdd000000000000ULL | (micro << 24) | (major << 12) | minor);
61 : }
62 :
63 : /**
64 : * @brief Parse the version key.
65 : */
66 : bool
67 101 : nns_edge_parse_version_key (const uint64_t version_key, unsigned int *major,
68 : unsigned int *minor, unsigned int *micro)
69 : {
70 101 : if ((version_key & 0xffff000000000000ULL) != 0xefdd000000000000ULL)
71 0 : return false;
72 :
73 101 : if (minor)
74 1 : *minor = (unsigned int) (version_key & 0xfff);
75 101 : if (major)
76 1 : *major = (unsigned int) ((version_key >> 12) & 0xfff);
77 101 : if (micro)
78 1 : *micro = (unsigned int) ((version_key >> 24) & 0xfff);
79 :
80 101 : return true;
81 : }
82 :
83 : /**
84 : * @brief Internal util function to get available port number.
85 : */
86 : int
87 8 : nns_edge_get_available_port (void)
88 : {
89 : struct sockaddr_in sin;
90 8 : int port = 0, sock;
91 8 : socklen_t len = sizeof (struct sockaddr);
92 :
93 8 : sin.sin_family = AF_INET;
94 8 : sin.sin_addr.s_addr = INADDR_ANY;
95 8 : sin.sin_port = 0;
96 :
97 8 : sock = socket (AF_INET, SOCK_STREAM, 0);
98 8 : if (sock < 0) {
99 0 : nns_edge_loge ("Failed to get available port, socket creation failure.");
100 8 : return 0;
101 : }
102 :
103 8 : if (bind (sock, (struct sockaddr *) &sin, sizeof (struct sockaddr)) == 0) {
104 8 : if (getsockname (sock, (struct sockaddr *) &sin, &len) == 0) {
105 8 : port = ntohs (sin.sin_port);
106 8 : nns_edge_logd ("Available port number: %d", port);
107 : } else {
108 0 : nns_edge_logw ("Failed to read local socket info.");
109 : }
110 : }
111 8 : close (sock);
112 :
113 8 : return port;
114 : }
115 :
116 : /**
117 : * @brief Get host string (host:port). Caller should release returned string using nns_edge_free().
118 : */
119 : char *
120 4 : nns_edge_get_host_string (const char *host, const int port)
121 : {
122 4 : return nns_edge_strdup_printf ("%s:%d", host, port);
123 : }
124 :
125 : /**
126 : * @brief Parse string and get host string (host:port).
127 : */
128 : void
129 4 : nns_edge_parse_host_string (const char *host_str, char **host, int *port)
130 : {
131 4 : char *p = strchr (host_str, ':');
132 :
133 4 : if (p) {
134 4 : *host = nns_edge_strndup (host_str, (p - host_str));
135 4 : *port = (int) strtoll (p + 1, NULL, 10);
136 : }
137 4 : }
138 :
139 : /**
140 : * @brief Parse string and get port number. Return negative value when failed to get port number.
141 : */
142 : int
143 8 : nns_edge_parse_port_number (const char *port_str)
144 : {
145 : int port;
146 :
147 8 : if (!port_str)
148 0 : return -1;
149 :
150 8 : port = (int) strtoll (port_str, NULL, 10);
151 :
152 8 : if (port == 0) {
153 0 : port = nns_edge_get_available_port ();
154 : }
155 :
156 8 : if (!PORT_IS_VALID (port)) {
157 2 : nns_edge_loge ("Invalid port number %d.", port);
158 2 : port = -1;
159 : }
160 :
161 8 : return port;
162 : }
163 :
164 : /**
165 : * @brief Allocate new memory. The max size is SIZE_MAX.
166 : * @note Caller should release newly allocated memory using nns_edge_free().
167 : */
168 : void *
169 1184 : nns_edge_malloc (nns_size_t size)
170 : {
171 1184 : void *mem = NULL;
172 :
173 1184 : if (size > 0 && size <= SIZE_MAX)
174 1184 : mem = malloc (size);
175 :
176 1184 : if (!mem)
177 0 : nns_edge_loge ("Failed to allocate memory (%" PRIu64 ").", size);
178 :
179 1184 : return mem;
180 : }
181 :
182 : /**
183 : * @brief Free allocated memory.
184 : */
185 : void
186 133 : nns_edge_free (void *data)
187 : {
188 133 : if (data)
189 133 : free (data);
190 133 : }
191 :
192 : /**
193 : * @brief Allocate new memory and copy bytes.
194 : * @note Caller should release newly allocated memory using nns_edge_free().
195 : */
196 : void *
197 125 : nns_edge_memdup (const void *data, nns_size_t size)
198 : {
199 125 : void *mem = NULL;
200 :
201 125 : if (data && size > 0) {
202 125 : mem = nns_edge_malloc (size);
203 :
204 125 : if (mem)
205 125 : memcpy (mem, data, size);
206 : }
207 :
208 125 : return mem;
209 : }
210 :
211 : /**
212 : * @brief Allocate new memory and copy string.
213 : * @note Caller should release newly allocated string using nns_edge_free().
214 : */
215 : char *
216 935 : nns_edge_strdup (const char *str)
217 : {
218 935 : char *new_str = NULL;
219 :
220 935 : if (str)
221 935 : new_str = nns_edge_strndup (str, strlen (str));
222 :
223 935 : return new_str;
224 : }
225 :
226 : /**
227 : * @brief Allocate new memory and copy bytes of string.
228 : * @note Caller should release newly allocated string using nns_edge_free().
229 : */
230 : char *
231 942 : nns_edge_strndup (const char *str, nns_size_t len)
232 : {
233 942 : char *new_str = NULL;
234 :
235 942 : if (str) {
236 942 : new_str = (char *) nns_edge_malloc (len + 1);
237 :
238 942 : if (new_str) {
239 942 : strncpy (new_str, str, len);
240 942 : new_str[len] = '\0';
241 : }
242 : }
243 :
244 942 : return new_str;
245 : }
246 :
247 : /**
248 : * @brief Allocate new memory and print formatted string.
249 : * @note Caller should release newly allocated string using nns_edge_free().
250 : */
251 : char *
252 66 : nns_edge_strdup_printf (const char *format, ...)
253 : {
254 66 : char *new_str = NULL;
255 : va_list args;
256 : int len;
257 :
258 66 : va_start (args, format);
259 66 : len = vasprintf (&new_str, format, args);
260 66 : if (len < 0)
261 0 : new_str = NULL;
262 66 : va_end (args);
263 :
264 66 : return new_str;
265 : }
|