Unset ip_resolved_cb on vine_service_destroy
[platform/core/api/vine.git] / src / vine-service.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdbool.h>
18 #include <net/if.h>
19
20 #include "vine.h"
21 #include "vine-constants.h"
22 #include "vine-disc.h"
23 #include "vine-service.h"
24 #include "vine-log.h"
25 #include "vine-utils.h"
26
27 typedef enum {
28         VINE_SERVICE_TYPE_PUBLISHED,
29         VINE_SERVICE_TYPE_DISCOVERED,
30 } vine_service_type_e;
31
32 typedef struct {
33         vine_service_type_e type;
34         char service_type[VINE_MAX_SERVICE_TYPE_LEN + 1];
35         char service_name[VINE_MAX_SERVICE_NAME_LEN + 1];
36         char host_name[VINE_MAX_HOST_NAME_LEN + 1];
37         char ip[VINE_MAX_IP_LEN + 1];
38         vine_address_family_e family;
39         int port;
40         map<string, string> attributes;
41         char iface_name[IF_NAMESIZE + 1];
42         vine_service_state_e state;
43
44         // For IP resolving
45         void *disc_handle;      // Used to resolve IP address
46         vine_session_h ip_resolving_session;
47         vine_session_ip_resolved_cb ip_resolved_cb;
48         void *ip_resolved_cb_data;
49 } vine_service_s;
50
51 bool _vine_service_check_service_type(const char *service_type)
52 {
53         RET_VAL_IF(service_type == NULL, false, "service_type is NULL");
54         int len = strlen(service_type);
55         return len > 0 && len <= VINE_MAX_SERVICE_TYPE_LEN;
56 }
57
58 static bool _vine_service_check_service_name(const char *service_name)
59 {
60         RET_VAL_IF(service_name == NULL, false, "service_name is NULL");
61         int len = strlen(service_name);
62         return len > 0 && len <= VINE_MAX_SERVICE_NAME_LEN;
63 }
64
65 bool _is_discovered_service(vine_service_h service)
66 {
67         vine_service_s *s = (vine_service_s *)service;
68         return s->type == VINE_SERVICE_TYPE_DISCOVERED;
69 }
70
71 int _vine_service_create(vine_service_h *service, bool published)
72 {
73         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
74
75         vine_service_s *s = new vine_service_s;
76         s->type = published ? VINE_SERVICE_TYPE_PUBLISHED : VINE_SERVICE_TYPE_DISCOVERED;
77         memset(s->service_type, 0, VINE_MAX_SERVICE_TYPE_LEN + 1);
78         memset(s->service_name, 0, VINE_MAX_SERVICE_NAME_LEN + 1);
79         memset(s->host_name, 0, VINE_MAX_HOST_NAME_LEN + 1);
80         memset(s->iface_name, 0, IF_NAMESIZE + 1);
81         s->port = -1;
82         s->state = VINE_SERVICE_UNAVAILABLE;
83
84         s->disc_handle = NULL;
85         s->ip_resolving_session = NULL;
86         s->ip_resolved_cb = NULL;
87         s->ip_resolved_cb_data = NULL;
88
89         *service = s;
90
91         return VINE_ERROR_NONE;
92 }
93
94 int _vine_service_destroy(vine_service_h service)
95 {
96         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
97         vine_service_s *s = (vine_service_s *)service;
98
99         if (s->ip_resolving_session != NULL && s->ip_resolved_cb != NULL) {
100                 vine_session_unset_ip_resolved_cb(s->ip_resolving_session, service);
101         }
102         s->attributes.clear();
103         delete s;
104         return VINE_ERROR_NONE;
105 }
106
107 int _vine_service_clone(vine_service_h origin, vine_service_h *cloned)
108 {
109         RET_VAL_IF(origin == NULL, VINE_ERROR_INVALID_PARAMETER, "origin is NULL");
110         RET_VAL_IF(cloned == NULL, VINE_ERROR_INVALID_PARAMETER, "cloned is NULL");
111
112         vine_service_s *origin_service = (vine_service_s *)origin;
113         vine_service_s *cloned_service = new vine_service_s;
114
115         cloned_service->type = origin_service->type;
116         strncpy(cloned_service->service_type, origin_service->service_type, VINE_MAX_SERVICE_TYPE_LEN);
117         strncpy(cloned_service->service_name, origin_service->service_name, VINE_MAX_SERVICE_NAME_LEN);
118         strncpy(cloned_service->host_name, origin_service->host_name, VINE_MAX_HOST_NAME_LEN);
119         strncpy(cloned_service->ip, origin_service->ip, VINE_MAX_IP_LEN);
120         cloned_service->family = origin_service->family;
121         cloned_service->port = origin_service->port;
122         cloned_service->attributes = origin_service->attributes;
123         strncpy(cloned_service->iface_name, origin_service->iface_name, IF_NAMESIZE);
124         cloned_service->state = origin_service->state;
125
126         cloned_service->disc_handle = NULL;
127         cloned_service->ip_resolved_cb = NULL;
128         cloned_service->ip_resolved_cb_data = NULL;
129
130         *cloned = cloned_service;
131         VINE_LOGD("Cloned service[%p]", cloned_service);
132
133         return VINE_ERROR_NONE;
134 }
135
136 int _vine_service_set_type(
137         vine_service_h service, const char *service_type)
138 {
139         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
140         RET_VAL_IF(_vine_service_check_service_type(service_type) == false,
141                 VINE_ERROR_INVALID_PARAMETER, "invalid length of service_type");
142
143         vine_service_s *s = (vine_service_s *)service;
144         strncpy(s->service_type, service_type, VINE_MAX_SERVICE_TYPE_LEN);
145
146         return VINE_ERROR_NONE;
147 }
148
149 const char *_vine_service_get_type(vine_service_h service)
150 {
151         RET_VAL_IF(service == NULL, NULL, "service is NULL");
152
153         vine_service_s *s = (vine_service_s *)service;
154         return s->service_type;
155 }
156
157 int _vine_service_set_name(
158         vine_service_h service, const char *service_name)
159 {
160         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
161         RET_VAL_IF(_vine_service_check_service_name(service_name) == false,
162                 VINE_ERROR_INVALID_PARAMETER, "invalid length of service_name");
163
164         vine_service_s *s = (vine_service_s *)service;
165         strncpy(s->service_name, service_name, VINE_MAX_SERVICE_TYPE_LEN);
166
167         return VINE_ERROR_NONE;
168 }
169
170 const char *_vine_service_get_name(vine_service_h service)
171 {
172         RET_VAL_IF(service == NULL, NULL, "service is NULL");
173
174         vine_service_s *s = (vine_service_s *)service;
175         return s->service_name;
176 }
177
178 int _vine_service_set_host_name(
179         vine_service_h service, const char *host_name)
180 {
181         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
182
183         vine_service_s *s = (vine_service_s *)service;
184         strncpy(s->host_name, host_name, VINE_MAX_HOST_NAME_LEN);
185
186         return VINE_ERROR_NONE;
187 }
188
189 const char *_vine_service_get_host_name(vine_service_h service)
190 {
191         RET_VAL_IF(service == NULL, NULL, "service is NULL");
192
193         vine_service_s *s = (vine_service_s *)service;
194         return s->host_name;
195 }
196
197 static bool __check_len_key(const char *key)
198 {
199         RET_VAL_IF(key == NULL, false, "key is NULL");
200         int len = strlen(key);
201         return len > 0 && len <= VINE_MAX_KEY_LEN;
202 }
203
204 int _vine_service_add_attribute(vine_service_h service,
205         const char *key, const char *value)
206 {
207         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
208         RET_VAL_IF(__check_len_key(key) == false,
209                 VINE_ERROR_INVALID_PARAMETER, "invalid length of key");
210
211         VINE_LOGD("Key[%s] value[%s]", key, value);
212
213         vine_service_s *s = (vine_service_s *)service;
214
215         if (s->attributes.find(key) != s->attributes.end()) {
216                 VINE_LOGE("Key[%s] already exits", key);
217                 return VINE_ERROR_INVALID_OPERATION;
218         }
219
220         // value can be NULL, which represents an empty string.
221         s->attributes[key] = value ? value : "";
222
223         return VINE_ERROR_NONE;
224 }
225
226 int _vine_service_remove_attribute(vine_service_h service, const char *key)
227 {
228         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
229         RET_VAL_IF(key == NULL, VINE_ERROR_INVALID_PARAMETER, "key is NULL");
230
231         vine_service_s *s = (vine_service_s *)service;
232
233         string attr_key(key);
234         if (s->attributes.find(attr_key) == s->attributes.end()) {
235                 VINE_LOGE("No key[%s]", key);
236                 return VINE_ERROR_INVALID_PARAMETER;
237         }
238
239         s->attributes.erase(attr_key);
240         return VINE_ERROR_NONE;
241 }
242
243 map<string, string> _vine_service_get_attributes(vine_service_h service)
244 {
245         if (service == NULL) {
246                 VINE_LOGE("service is NULL");
247                 return map<string, string>();
248         }
249
250         vine_service_s *s = (vine_service_s *)service;
251         return s->attributes;
252 }
253
254 int _vine_service_foreach_attribute(vine_service_h service,
255         vine_service_attribute_cb callback, void *user_data)
256 {
257         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
258         RET_VAL_IF(callback == NULL, VINE_ERROR_INVALID_PARAMETER, "callback is NULL");
259
260         vine_service_s *s = (vine_service_s *)service;
261
262         for (const auto &kv : s->attributes) {
263                 if (!callback(kv.first.c_str(), kv.second.c_str(), user_data))
264                         break;
265         }
266
267         return VINE_ERROR_NONE;
268 }
269
270 int _vine_service_set_iface_name(vine_service_h service, const char *iface_name)
271 {
272         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
273
274         vine_service_s *s = (vine_service_s *)service;
275         strncpy(s->iface_name, iface_name, IF_NAMESIZE);
276
277         return VINE_ERROR_NONE;
278 }
279
280 const char *_vine_service_get_iface_name(vine_service_h service)
281 {
282         RET_VAL_IF(service == NULL, NULL, "service is NULL");
283
284         vine_service_s *s = (vine_service_s *)service;
285         return s->iface_name;
286 }
287
288 int _vine_service_get_disc_handle(vine_service_h service,
289         vine_discovery_method_e disc_method, void **disc_handle)
290 {
291         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
292
293         vine_service_s *s = (vine_service_s *)service;
294         if (s->disc_handle == NULL) {
295                 int ret = vine_disc_create(disc_method, &s->disc_handle);
296                 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_create");
297         }
298         *disc_handle = s->disc_handle;
299         return VINE_ERROR_NONE;
300 }
301
302 int _vine_service_set_ip_resolved_cb(vine_service_h service, vine_session_h session,
303         vine_session_ip_resolved_cb callback, void *user_data)
304 {
305         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
306         RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
307         RET_VAL_IF(callback == NULL, VINE_ERROR_INVALID_PARAMETER, "callback is NULL");
308
309         RET_VAL_IF(!_is_discovered_service(service), VINE_ERROR_INVALID_OPERATION,
310                         "only for discovered service");
311
312         vine_service_s *s = (vine_service_s *)service;
313         s->ip_resolving_session = session;
314         s->ip_resolved_cb = callback;
315         s->ip_resolved_cb_data = user_data;
316
317         return VINE_ERROR_NONE;
318 }
319
320 int _vine_service_unset_ip_resolved_cb(vine_service_h service)
321 {
322         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
323
324         RET_VAL_IF(!_is_discovered_service(service), VINE_ERROR_INVALID_OPERATION,
325                         "only for discovered service");
326
327         vine_service_s *s = (vine_service_s *)service;
328         s->ip_resolving_session = NULL;
329         s->ip_resolved_cb = NULL;
330         s->ip_resolved_cb_data = NULL;
331
332         return VINE_ERROR_NONE;
333 }
334
335 vine_session_ip_resolved_cb _vine_service_ip_resolved_cb(vine_service_h service)
336 {
337         RET_VAL_IF(service == NULL, NULL, "service is NULL");
338
339         vine_service_s *s = (vine_service_s *)service;
340         return s->ip_resolved_cb;
341 }
342
343 void * _vine_service_ip_resolved_cb_data(vine_service_h service)
344 {
345         RET_VAL_IF(service == NULL, NULL, "service is NULL");
346
347         vine_service_s *s = (vine_service_s *)service;
348         return s->ip_resolved_cb_data;
349 }
350
351 static bool __check_port_number(int port)
352 {
353         return port >= 0 && port <= 65535;
354 }
355
356 int _vine_service_set_port(vine_service_h service, int port)
357 {
358         RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
359         RET_VAL_IF(__check_port_number(port) == false,
360                 VINE_ERROR_INVALID_PARAMETER, "A port number ranges from 0 to 65535");
361
362         vine_service_s *s = (vine_service_s *)service;
363         s->port = port;
364         return VINE_ERROR_NONE;
365 }
366
367 int _vine_service_get_port(vine_service_h service)
368 {
369         RET_VAL_IF(service == NULL, 0, "service is NULL");
370
371         vine_service_s *s = (vine_service_s *)service;
372         return s->port;
373 }
374
375 int _vine_service_set_state(vine_service_h service, vine_service_state_e state)
376 {
377         RET_VAL_IF(service == NULL, 0, "service is NULL");
378         vine_service_s *s = (vine_service_s *)service;
379         s->state = state;
380         return VINE_ERROR_NONE;
381 }
382
383 vine_service_state_e _vine_service_get_state(vine_service_h service)
384 {
385         RET_VAL_IF(service == NULL, VINE_SERVICE_UNAVAILABLE, "service is NULL");
386         vine_service_s *s = (vine_service_s *)service;
387         return s->state;
388 }
389
390 int _vine_service_set_disc_handle(vine_service_h service, void *disc_handle)
391 {
392         RET_VAL_IF(service == NULL, 0, "service is NULL");
393         vine_service_s *s = (vine_service_s *)service;
394         s->disc_handle = disc_handle;
395         return VINE_ERROR_NONE;
396 }