2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include "vine-disc.h"
21 #include "vine-event-loop.h"
22 #include "vine-session.h"
23 #include "vine-service.h"
25 #include "vine-utils.h"
30 vine_event_queue_h event_fd;
32 vine_discovery_method_e disc_method;
33 vine_disc_h disc_handle;
35 vine_session_registered_cb registered_cb;
36 void *registered_cb_data;
37 vine_session_discovered_cb discovered_cb;
38 void *discovered_cb_data;
45 static void __vine_session_set_is_running(vine_session_h session, bool is_running)
47 vine_session_s *s = (vine_session_s *)session;
48 s->is_running = is_running;
51 static bool __vine_session_is_running(vine_session_h session)
53 vine_session_s *s = (vine_session_s *)session;
57 static bool __vine_session_is_registered(vine_session_h session)
59 vine_session_s *s = (vine_session_s *)session;
63 static bool __vine_session_is_discovered(vine_session_h session)
65 vine_session_s *s = (vine_session_s *)session;
69 static void __vine_session_set_registered(vine_session_h session, bool registered)
71 vine_session_s *s = (vine_session_s *)session;
72 s->registered = registered;
75 static void __vine_session_set_discovered(vine_session_h session, bool discovered)
77 vine_session_s *s = (vine_session_s *)session;
78 s->discovered = discovered;
81 int _vine_session_create(vine_session_h *session)
83 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
86 (vine_session_s *)calloc(1, sizeof(vine_session_s));
87 RET_VAL_IF(s == NULL, VINE_ERROR_OUT_OF_MEMORY, "Out of memory");
89 VINE_LOGD("New Session. session[%p]", s);
91 s->is_running = false;
92 s->registered = false;
93 s->discovered = false;
94 s->disc_handle = NULL;
96 int ret = vine_event_queue_create(&(s->event_fd));
97 if (ret != VINE_ERROR_NONE) {
98 VINE_LOGE("Fail to create eventfd %d", ret);
103 return VINE_ERROR_NONE;
106 int _vine_session_destroy(vine_session_h session)
108 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
109 vine_session_s *s = (vine_session_s *)session;
111 VINE_LOGD("Destroy Session. session[%p]", session);
112 vine_event_queue_destroy(s->event_fd);
113 vine_disc_destroy(s->disc_handle);
114 s->disc_handle = NULL;
116 return VINE_ERROR_NONE;
119 int _vine_session_set_registered_cb(vine_session_h session,
120 vine_session_registered_cb callback, void *user_data)
122 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
123 RET_VAL_IF(callback == NULL, VINE_ERROR_INVALID_PARAMETER, "callback is NULL");
125 VINE_LOGD("Set registered callback. session[%p]", session);
126 vine_session_s *s = (vine_session_s *)session;
127 s->registered_cb = callback;
128 s->registered_cb_data = user_data;
129 return VINE_ERROR_NONE;
132 int _vine_session_unset_registered_cb(vine_session_h session)
134 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
136 VINE_LOGD("Unset registered callback. session[%p]", session);
137 vine_session_s *s = (vine_session_s *)session;
138 s->registered_cb = NULL;
139 s->registered_cb_data = NULL;
140 return VINE_ERROR_NONE;
143 int _vine_session_set_discovered_cb(vine_session_h session,
144 vine_session_discovered_cb callback, void *user_data)
146 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
147 RET_VAL_IF(callback == NULL, VINE_ERROR_INVALID_PARAMETER, "callback is NULL");
149 VINE_LOGD("Set discovered callback. session[%p]", session);
150 vine_session_s *s = (vine_session_s *)session;
151 s->discovered_cb = callback;
152 s->discovered_cb_data = user_data;
153 return VINE_ERROR_NONE;
156 int _vine_session_unset_discovered_cb(vine_session_h session)
158 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
160 VINE_LOGD("Unset discovered callback. session[%p]", session);
161 vine_session_s *s = (vine_session_s *)session;
162 s->discovered_cb = NULL;
163 s->discovered_cb_data = NULL;
164 return VINE_ERROR_NONE;
167 static bool __check_disc_method(vine_discovery_method_e method)
169 return method == VINE_DISCOVERY_METHOD_DNS_SD;
172 int _vine_session_set_discovery_method(vine_session_h session, vine_discovery_method_e method)
174 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
175 RET_VAL_IF(__check_disc_method(method) == false, VINE_ERROR_INVALID_PARAMETER,
176 "invalid service discovery method");
178 VINE_LOGD("Set service discovery method. session[%p] method[%d]", session, method);
179 vine_session_s *s = (vine_session_s *)session;
180 s->disc_method = method;
182 return VINE_ERROR_NONE;
185 static void __published_cb(vine_disc_h disc,
186 const char *service_name, vine_error_e error, void *user_data)
188 VINE_LOGD("Service is published");
190 vine_session_s *s = (vine_session_s *)user_data;
191 VINE_LOGD("session[%p] service_name[%s], error[%d]", s, service_name, error);
193 if (error != VINE_ERROR_NONE && error != VINE_ERROR_NAME_CONFLICT) {
194 VINE_LOGE("Fail to publish");
195 __vine_session_set_is_running(s, false);
197 __vine_session_set_registered(s, true);
200 if (s->registered_cb)
201 s->registered_cb(s, service_name, error, s->registered_cb_data);
204 int _vine_session_register(vine_session_h session,
205 vine_service_h service, const char *iface_name)
207 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
208 RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
209 RET_VAL_IF(__vine_session_is_running(session), VINE_ERROR_INVALID_OPERATION,
210 "session is already running");
212 VINE_LOGD("Register a service. session[%p]", session);
214 int ret = VINE_ERROR_NONE;
215 vine_session_s *s = (vine_session_s *)session;
217 if (s->disc_handle == NULL) {
218 ret = vine_disc_create(s->disc_method, &s->disc_handle);
219 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_create");
222 ret = vine_disc_publish(s->disc_handle, service, iface_name,
223 __published_cb, session,
225 if (ret != VINE_ERROR_NONE) {
226 VINE_LOGE("Fail to vine_disc_publish");
227 vine_disc_destroy(s->disc_handle);
228 s->disc_handle = NULL;
232 __vine_session_set_is_running(session, true);
233 return VINE_ERROR_NONE;
236 int _vine_session_unregister(vine_session_h session)
238 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
239 RET_VAL_IF(!__vine_session_is_running(session), VINE_ERROR_INVALID_OPERATION,
240 "session is not running");
241 RET_VAL_IF(!__vine_session_is_registered(session), VINE_ERROR_INVALID_OPERATION,
242 "session is not registered");
244 int ret = VINE_ERROR_NONE;
245 vine_session_s *s = (vine_session_s *)session;
247 ret = vine_disc_stop_publish(s->disc_handle);
248 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_stop_publish");
250 __vine_session_set_is_running(session, false);
251 __vine_session_set_registered(session, false);
253 return VINE_ERROR_NONE;
256 static int __vine_set_discovered_service(vine_service_h service,
257 const char *service_type, const char *service_name,
258 const char *host_name, int port, const map<string, string> &attr,
259 const char *iface_name)
261 int ret = VINE_ERROR_NONE;
262 ret = _vine_service_set_type(service, service_type);
263 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set service type");
264 ret = _vine_service_set_name(service, service_name);
265 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set service name");
266 ret = _vine_service_set_host_name(service, host_name);
267 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set host name");
268 ret = _vine_service_set_port(service, port);
269 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set port");
271 for (const auto &kv : attr)
272 _vine_service_add_attribute(service, kv.first.c_str(), kv.second.c_str());
274 ret = _vine_service_set_iface_name(service, iface_name);
275 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set iface_name");
277 return VINE_ERROR_NONE;
280 static void __discovered_cb(vine_disc_h disc, bool available,
281 const char *service_type, const char *service_name,
282 const char *host_name, int port, const map<string, string> &attr,
283 const char *iface_name, int more_coming, void *user_data)
285 VINE_LOGD("Service is discovered. Available[%d]", available);
286 int ret = VINE_ERROR_NONE;
288 vine_session_s *s = (vine_session_s *)user_data;
289 VINE_LOGD("session[%p] service_name[%s], host_name[%s], port[%d], iface[%s]",
290 s, service_name, host_name, port, iface_name);
292 vine_service_h discovered_service;
293 ret = _vine_service_create(&discovered_service, false);
294 RET_IF(ret != VINE_ERROR_NONE, "Fail to create a service");
296 ret = _vine_service_set_disc_handle(discovered_service, disc);
297 RET_IF(ret != VINE_ERROR_NONE, "Fail to set disc_handle");
299 ret = __vine_set_discovered_service(discovered_service,
300 service_type, service_name, host_name, port, attr, iface_name);
301 if (ret != VINE_ERROR_NONE) {
302 VINE_LOGE("Fail to set a service. error(%d)", ret);
303 _vine_service_destroy(discovered_service);
307 vine_service_state_e state = available ? VINE_SERVICE_AVAILABLE
308 : VINE_SERVICE_UNAVAILABLE;
309 _vine_service_set_state(discovered_service, state);
311 if (s->discovered_cb)
312 s->discovered_cb(s, discovered_service, state, s->discovered_cb_data);
315 int _vine_session_start_discovery(vine_session_h session,
316 const char *service_type, const char *iface_name)
318 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
319 RET_VAL_IF(_vine_service_check_service_type(service_type) == false,
320 VINE_ERROR_INVALID_PARAMETER, "invalid length of service_type");
321 RET_VAL_IF(__vine_session_is_running(session), VINE_ERROR_INVALID_OPERATION,
322 "session is already running");
324 VINE_LOGD("Subscribe a service. session[%p] service_type[%s]", session, service_type);
325 int ret = VINE_ERROR_NONE;
326 vine_session_s *s = (vine_session_s *)session;
328 if (s->disc_handle == NULL) {
329 ret = vine_disc_create(s->disc_method, &s->disc_handle);
330 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_create");
333 ret = vine_disc_subscribe(s->disc_handle, service_type, iface_name,
334 __discovered_cb, session,
336 if (ret != VINE_ERROR_NONE) {
337 VINE_LOGE("Fail to vine_disc_subscribe");
338 vine_disc_destroy(s->disc_handle);
339 s->disc_handle = NULL;
343 __vine_session_set_is_running(session, true);
344 __vine_session_set_discovered(s, true);
346 return VINE_ERROR_NONE;
349 int _vine_session_stop_discovery(vine_session_h session)
351 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
352 RET_VAL_IF(!__vine_session_is_running(session), VINE_ERROR_INVALID_OPERATION,
353 "session is not running");
354 RET_VAL_IF(!__vine_session_is_discovered(session), VINE_ERROR_INVALID_OPERATION,
355 "session doesn't start discovery");
357 int ret = VINE_ERROR_NONE;
358 vine_session_s *s = (vine_session_s *)session;
360 ret = vine_disc_stop_subscribe(s->disc_handle);
361 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_stop_subscribe");
363 __vine_session_set_is_running(session, false);
364 __vine_session_set_discovered(session, false);
366 return VINE_ERROR_NONE;
369 static void __ip_resolved_cb(vine_disc_h disc, vine_service_h service, bool add,
370 const char *ip, vine_address_family_e address_family, void *user_data)
372 VINE_LOGD("IP is resolved");
374 vine_session_s *s = (vine_session_s *)user_data;
375 VINE_LOGD("session[%p] service[%p]", s, service);
376 VINE_LOGD("IP[%s], address family[%d] %s", ip, address_family,
377 add ? "Add" : "Remove");
379 vine_session_ip_resolved_cb cb = _vine_service_ip_resolved_cb(service);
380 void *cb_data = _vine_service_ip_resolved_cb_data(service);
382 cb(s, service, ip, address_family, cb_data);
385 int _vine_session_set_ip_resolved_cb(vine_session_h session,
386 vine_service_h service, vine_session_ip_resolved_cb callback, void *user_data)
388 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
389 RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
391 VINE_LOGD("Resolve IP address for a service[%p]. session[%p]", service, session);
393 int ret = VINE_ERROR_NONE;
394 vine_session_s *s = (vine_session_s *)session;
396 vine_disc_h disc_handle;
397 ret = _vine_service_get_disc_handle(service, VINE_DISCOVERY_METHOD_DNS_SD, &disc_handle);
398 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to _vine_service_get_disc_handle");
400 _vine_service_set_ip_resolved_cb(service, callback, user_data);
402 ret = vine_disc_resolve_ip(disc_handle, service,
403 __ip_resolved_cb, session,
405 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_resolve_ip");
407 return VINE_ERROR_NONE;
410 int _vine_session_unset_ip_resolved_cb(vine_session_h session,
411 vine_service_h service)
413 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
414 RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
416 VINE_LOGD("Cancel resolving IP address for a service[%p]. session[%p]", service, session);
418 int ret = VINE_ERROR_NONE;
419 vine_disc_h disc_handle = NULL;
420 ret = _vine_service_get_disc_handle(service, VINE_DISCOVERY_METHOD_DNS_SD, &disc_handle);
421 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to _vine_service_get_disc_handle");
423 _vine_service_set_ip_resolved_cb(service, NULL, NULL);
425 ret = vine_disc_cancel_resolve_ip(disc_handle, service);
426 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_cancel_resolve_ip");
428 return VINE_ERROR_NONE;
431 int _vine_session_get_event_queue(vine_session_h session, vine_event_queue_h *eq)
433 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
435 vine_session_s *s = (vine_session_s *)session;
437 return VINE_ERROR_NONE;
440 int _vine_session_get_event_fd(vine_session_h session, int *fd)
442 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
444 vine_session_s *s = (vine_session_s *)session;
445 vine_event_loop_get_eventfd(s->event_fd, fd);
446 return VINE_ERROR_NONE;
449 int _vine_session_process_event(vine_session_h session)
451 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
453 VINE_LOGD("Process event. session[%p]", session);
454 vine_session_s *s = (vine_session_s *)session;
455 return vine_event_loop_process(s->event_fd);