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_set_discovered_service(discovered_service,
297 service_type, service_name, host_name, port, attr, iface_name);
298 if (ret != VINE_ERROR_NONE) {
299 VINE_LOGE("Fail to set a service. error(%d)", ret);
300 _vine_service_destroy(discovered_service);
304 vine_service_state_e state = available ? VINE_SERVICE_AVAILABLE
305 : VINE_SERVICE_UNAVAILABLE;
306 _vine_service_set_state(discovered_service, state);
308 if (s->discovered_cb)
309 s->discovered_cb(s, discovered_service, state, s->discovered_cb_data);
311 _vine_service_destroy(discovered_service);
314 int _vine_session_start_discovery(vine_session_h session,
315 const char *service_type, const char *iface_name)
317 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
318 RET_VAL_IF(_vine_service_check_service_type(service_type) == false,
319 VINE_ERROR_INVALID_PARAMETER, "invalid length of service_type");
320 RET_VAL_IF(__vine_session_is_running(session), VINE_ERROR_INVALID_OPERATION,
321 "session is already running");
323 VINE_LOGD("Subscribe a service. session[%p] service_type[%s]", session, service_type);
324 int ret = VINE_ERROR_NONE;
325 vine_session_s *s = (vine_session_s *)session;
327 if (s->disc_handle == NULL) {
328 ret = vine_disc_create(s->disc_method, &s->disc_handle);
329 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_create");
332 ret = vine_disc_subscribe(s->disc_handle, service_type, iface_name,
333 __discovered_cb, session,
335 if (ret != VINE_ERROR_NONE) {
336 VINE_LOGE("Fail to vine_disc_subscribe");
337 vine_disc_destroy(s->disc_handle);
338 s->disc_handle = NULL;
342 __vine_session_set_is_running(session, true);
343 __vine_session_set_discovered(s, true);
345 return VINE_ERROR_NONE;
348 int _vine_session_stop_discovery(vine_session_h session)
350 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
351 RET_VAL_IF(!__vine_session_is_running(session), VINE_ERROR_INVALID_OPERATION,
352 "session is not running");
353 RET_VAL_IF(!__vine_session_is_discovered(session), VINE_ERROR_INVALID_OPERATION,
354 "session doesn't start discovery");
356 int ret = VINE_ERROR_NONE;
357 vine_session_s *s = (vine_session_s *)session;
359 ret = vine_disc_stop_subscribe(s->disc_handle);
360 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_stop_subscribe");
362 __vine_session_set_is_running(session, false);
363 __vine_session_set_discovered(session, false);
365 return VINE_ERROR_NONE;
368 static void __ip_resolved_cb(vine_disc_h disc, vine_service_h service, bool add,
369 const char *ip, vine_address_family_e address_family, void *user_data)
371 VINE_LOGD("IP is resolved");
373 vine_session_s *s = (vine_session_s *)user_data;
374 VINE_LOGD("session[%p] service[%p]", s, service);
375 VINE_LOGD("IP[%s], address family[%d] %s", ip, address_family,
376 add ? "Add" : "Remove");
378 vine_session_ip_resolved_cb cb = _vine_service_ip_resolved_cb(service);
379 void *cb_data = _vine_service_ip_resolved_cb_data(service);
381 cb(s, service, ip, address_family, cb_data);
384 int _vine_session_set_ip_resolved_cb(vine_session_h session,
385 vine_service_h service, vine_session_ip_resolved_cb callback, void *user_data)
387 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
388 RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
390 VINE_LOGD("Resolve IP address for a service[%p]. session[%p]", service, session);
392 int ret = VINE_ERROR_NONE;
393 vine_session_s *s = (vine_session_s *)session;
395 vine_disc_h disc_handle;
396 ret = vine_disc_create(s->disc_method, &disc_handle);
397 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_create");
399 ret = _vine_service_set_disc_handle(service, disc_handle);
400 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set disc_handle");
402 _vine_service_set_ip_resolved_cb(service, callback, user_data);
404 ret = vine_disc_resolve_ip(disc_handle, service,
405 __ip_resolved_cb, session,
407 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_resolve_ip");
409 return VINE_ERROR_NONE;
412 int _vine_session_unset_ip_resolved_cb(vine_session_h session,
413 vine_service_h service)
415 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
416 RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL");
418 VINE_LOGD("Cancel resolving IP address for a service[%p]. session[%p]", service, session);
420 int ret = VINE_ERROR_NONE;
421 vine_disc_h disc_handle = NULL;
422 ret = _vine_service_get_disc_handle(service, VINE_DISCOVERY_METHOD_DNS_SD, &disc_handle);
423 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to _vine_service_get_disc_handle");
425 _vine_service_set_ip_resolved_cb(service, NULL, NULL);
427 ret = vine_disc_cancel_resolve_ip(disc_handle, service);
428 RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_cancel_resolve_ip");
430 return VINE_ERROR_NONE;
433 int _vine_session_get_event_queue(vine_session_h session, vine_event_queue_h *eq)
435 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
437 vine_session_s *s = (vine_session_s *)session;
439 return VINE_ERROR_NONE;
442 int _vine_session_get_event_fd(vine_session_h session, int *fd)
444 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
446 vine_session_s *s = (vine_session_s *)session;
447 vine_event_loop_get_eventfd(s->event_fd, fd);
448 return VINE_ERROR_NONE;
451 int _vine_session_process_event(vine_session_h session)
453 RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL");
455 VINE_LOGD("Process event. session[%p]", session);
456 vine_session_s *s = (vine_session_s *)session;
457 return vine_event_loop_process(s->event_fd);