2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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.
17 /*****************************************************************************
19 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
34 #include <vconf-keys.h>
37 #include <dns-sd-internal.h>
39 #include <wifi-manager.h>
41 /*****************************************************************************
42 * Application Service Platform Daemon headers
43 *****************************************************************************/
44 #include "asp-manager-util.h"
45 #include "asp-service.h"
46 #include "asp-session.h"
48 #include "asp-tech-infra.h"
50 /*****************************************************************************
52 *****************************************************************************/
54 /* TODO : define service data structure */
56 /*****************************************************************************
58 *****************************************************************************/
59 static __thread GHashTable *g_local_service_hash = NULL;
60 static __thread GHashTable *g_browser_hash = NULL;
63 /* TODO : define local memory for service data structure */
65 /*****************************************************************************
66 * Local Functions Definition
67 *****************************************************************************/
68 static void _advertise_status_cb(dnssd_error_e result,
69 dnssd_service_h local_service, gpointer user_data)
71 guint32 adv_id = GPOINTER_TO_UINT(user_data);
72 asp_service_advertise_status_e status = 0;
73 asp_service_advertise_reason_e reason = 0;
76 case DNSSD_ERROR_NONE:
77 case DNSSD_ERROR_ALREADY_REGISTERED:
78 status = ASP_SERVICE_ADV_STATUS_ADVERTISED;
79 reason = ASP_SERVICE_ADVERTISE_REASON_SUCCESS;
81 case DNSSD_ERROR_NAME_CONFLICT:
82 status = ASP_SERVICE_ADV_STATUS_NOT_ADVERTISED;
83 reason = ASP_SERVICE_ADVERTISE_REASON_DUP;
86 status = ASP_SERVICE_ADV_STATUS_NOT_ADVERTISED;
87 reason = ASP_SERVICE_ADVERTISE_REASON_OTHER;
90 asp_service_notify_advertise_status(adv_id, status, reason);
93 static void __txt_record_to_g_hash(unsigned short txt_len, const gchar *txt_records,
94 GHashTable *service_info_map)
96 const gchar *ptr = txt_records;
97 const gchar *max = txt_records + txt_len;
99 ASP_LOGD("Parsing TXT record. Length: %hu", txt_len);
102 unsigned short len = ptr[0];
103 gchar *buf = g_strndup(ptr + 1, len);
104 ASP_LOGD("buf: %s", buf);
107 gchar *save_str = NULL;
108 key = strtok_r(buf, "=", &save_str);
109 value = strtok_r(NULL, "=", &save_str);
110 g_hash_table_replace(service_info_map, g_strdup(key), g_strdup(value));
111 ASP_LOGD("Insert (%s, %s) to hash. len: %d)", key, value, len);
117 static asp_service_status_e __get_service_status(dnssd_service_state_e service_state)
119 asp_service_status_e service_status;
120 switch (service_state) {
121 case DNSSD_SERVICE_STATE_AVAILABLE:
122 service_status = ASP_SERVICE_STATUS_AVAILABLE;
124 case DNSSD_SERVICE_STATE_UNAVAILABLE:
125 case DNSSD_SERVICE_STATE_NAME_LOOKUP_FAILED:
126 case DNSSD_SERVICE_STATE_HOST_NAME_LOOKUP_FAILED:
127 case DNSSD_SERVICE_STATE_ADDRESS_LOOKUP_FAILED:
128 service_status = ASP_SERVICE_STATUS_NOT_AVAILABLE;
131 service_status = ASP_SERVICE_STATUS_NOT_AVAILABLE;
134 return service_status;
137 static void _search_result_cb(dnssd_service_state_e service_state,
138 dnssd_service_h remote_service, gpointer user_data)
140 asp_event_data event;
141 guint32 search_id = -1;
142 gchar *service_mac = NULL;
143 gchar *service_device_name = NULL;
145 gchar *service_name = NULL;
146 GHashTable *service_info_map = NULL;
147 asp_service_status_e service_status;
148 unsigned short txt_len = 0;
150 const gchar *adv_id_str = NULL;
152 ASP_LOGD("A service is found %u", remote_service);
154 search_id = GPOINTER_TO_UINT(user_data);
155 dnssd_service_get_name(remote_service, &service_name);
156 ASP_LOGD("Service name: %s", service_name);
158 service_status = __get_service_status(service_state);
159 ASP_LOGD("Service status: %s",
160 service_status == ASP_SERVICE_STATUS_AVAILABLE ? "Available" : "Unavailable");
162 dnssd_service_get_all_txt_record(remote_service, &txt_len, (gpointer)&txt);
164 service_info_map = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
165 __txt_record_to_g_hash(txt_len, txt, service_info_map);
166 if (g_hash_table_contains(service_info_map, ASP_INFRA_ADV_KEY)) {
167 adv_id_str = g_hash_table_lookup(service_info_map, ASP_INFRA_ADV_KEY);
168 adv_id = g_ascii_strtoll(adv_id_str, NULL, 10);
169 ASP_LOGD("Advertisement ID: %u", adv_id);
171 ASP_LOGE("TXT records don't contain advertisement ID");
172 g_hash_table_unref(service_info_map);
173 g_free(service_name);
178 if (g_hash_table_contains(service_info_map, ASP_INFRA_MAC_ADDR_KEY)) {
179 service_mac = g_strdup(g_hash_table_lookup(service_info_map, ASP_INFRA_MAC_ADDR_KEY));
180 ASP_LOGD("Advertisement MAC Address: %s", service_mac);
182 ASP_LOGE("TXT records don't contain advertisement MAC");
183 g_hash_table_unref(service_info_map);
184 g_free(service_name);
189 if (g_hash_table_contains(service_info_map, ASP_INFRA_DEV_NAME)) {
190 service_device_name = g_strdup(g_hash_table_lookup(service_info_map, ASP_INFRA_DEV_NAME));
191 ASP_LOGD("Service device name: %s", service_device_name);
194 ASP_LOGE("Found service should has at least one TXT record");
195 g_free(service_name);
200 memset(&event, 0x0, sizeof(asp_event_data));
201 event.search_result.tech = ASP_TECH_INFRA;
202 event.search_result.search_id = search_id;
203 event.search_result.advertisement_id = adv_id;
204 event.search_result.service_status = service_status;
205 g_strlcpy(event.search_result.service_mac, service_mac, MACSTR_LEN + 1);
206 event.search_result.device_name = NULL;
207 event.search_result.instance_name = service_name;
208 event.search_result.service_info = service_info_map;
209 asp_manager_event(NULL, ASP_EVENT_SEARCH_RESULT, &event);
211 g_hash_table_unref(service_info_map);
212 g_free(service_device_name);
217 static gint32 __asp_service_infra_convert_error_type(gint32 dnssd_error)
219 switch (dnssd_error) {
220 case DNSSD_ERROR_NONE:
221 return ASP_ERROR_NONE;
222 case DNSSD_ERROR_OUT_OF_MEMORY:
223 return ASP_ERROR_MEMORY;
224 case DNSSD_ERROR_INVALID_PARAMETER:
225 return ASP_ERROR_INVALIED_PARAMS;
226 case DNSSD_ERROR_NOT_SUPPORTED:
227 return ASP_ERROR_NOT_SUPPORTED_TECH;
228 case DNSSD_ERROR_SERVICE_NOT_FOUND:
229 return ASP_ERROR_SERVICE_NOT_FOUND;
230 case DNSSD_ERROR_INVALID_OPERATION:
231 case DNSSD_ERROR_NOT_INITIALIZED:
232 case DNSSD_ERROR_ALREADY_REGISTERED:
233 case DNSSD_ERROR_NAME_CONFLICT:
234 case DNSSD_ERROR_SERVICE_NOT_RUNNING:
235 case DNSSD_ERROR_OPERATION_FAILED:
236 return ASP_ERROR_OPERATION_FAILED;
238 return ASP_ERROR_UNKNOWN;
243 static void __init_hash_tables()
245 g_local_service_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
246 g_browser_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
249 static void __g_hash_free_handle(gpointer key, gpointer value, gpointer user_data)
253 static void __deinit_hash_tables()
255 g_hash_table_foreach(g_local_service_hash, (GHFunc)__g_hash_free_handle, NULL);
256 g_hash_table_foreach(g_browser_hash, (GHFunc)__g_hash_free_handle, NULL);
258 g_local_service_hash = NULL;
259 g_browser_hash = NULL;
262 static gint32 __add_txt_record(dnssd_service_h handle, const gchar* key, const gchar* value, gint32 len)
265 unsigned short txt_length;
266 gpointer txt_data = NULL;
268 result = dnssd_service_add_txt_record(handle, key, (unsigned short)len, value);
269 if (result != DNSSD_ERROR_NONE) {
270 result = __asp_service_infra_convert_error_type(result);
273 ASP_LOGD("Add (%s=%s) TXT record. length: %d", key, value, len);
275 result = dnssd_service_get_all_txt_record(handle, &txt_length, &txt_data);
276 if (result != DNSSD_ERROR_NONE) {
277 result = __asp_service_infra_convert_error_type(result);
280 ASP_LOGD("Get all TXT records");
282 result = dnssd_service_set_record(handle,
283 ASP_INFRA_DNSSD_TXT_RECORD_TYPE, txt_length, txt_data);
284 if (result != DNSSD_ERROR_NONE) {
285 ASP_LOGE("Failed to add record");
286 result = __asp_service_infra_convert_error_type(result);
290 ASP_LOGD("Add TXT records");
294 gint32 asp_tech_infra_init()
296 __ASP_LOG_FUNC_ENTER__;
299 result = dnssd_initialize();
300 if (result != DNSSD_ERROR_NONE) {
301 result = __asp_service_infra_convert_error_type(result);
305 __init_hash_tables();
307 __ASP_LOG_FUNC_EXIT__;
311 gint32 asp_tech_infra_deinit()
313 __ASP_LOG_FUNC_ENTER__;
316 result = dnssd_deinitialize();
317 if (result != DNSSD_ERROR_NONE) {
318 result = __asp_service_infra_convert_error_type(result);
322 __deinit_hash_tables();
324 __ASP_LOG_FUNC_EXIT__;
328 gint32 asp_tech_infra_advertise(asp_service_advertise_s *service, gint32 replace)
330 __ASP_LOG_FUNC_ENTER__;
332 dnssd_service_h service_handle = 0;
333 gchar adv_id[ASP_SERVICE_ADV_ID_LEN + 1];
334 gint32 adv_id_len = 0;
337 gint32 port = 1234; /* TODO */
339 wifi_manager_h wifi_handle = NULL;
341 ASP_LOGD("Infrastructure advertise service. replace: %d", replace);
348 result = dnssd_create_local_service(service->service_type, &service_handle);
349 if (result != DNSSD_ERROR_NONE) {
350 result = __asp_service_infra_convert_error_type(result);
353 ASP_LOGD("Success to create local service handle: %u, service type: %s",
354 service_handle, service->service_type);
356 result = dnssd_service_set_name(service_handle, service->instance_name);
357 if (result != DNSSD_ERROR_NONE) {
358 result = __asp_service_infra_convert_error_type(result);
361 ASP_LOGD("Success to set service name %s", service->instance_name);
364 result = dnssd_service_set_port(service_handle, port);
365 if (result != DNSSD_ERROR_NONE) {
366 result = __asp_service_infra_convert_error_type(result);
369 ASP_LOGD("Success to set port %d", port);
371 result = wifi_manager_initialize(&wifi_handle);
372 if (result != WIFI_MANAGER_ERROR_NONE) {
373 ASP_LOGD("Failed to initialize wifi-manager");
374 return ASP_ERROR_OPERATION_FAILED;
376 result = wifi_manager_get_network_interface_name(wifi_handle, &if_name);
377 if (result != WIFI_MANAGER_ERROR_NONE) {
378 ASP_LOGD("Failed to get interface name");
379 return ASP_ERROR_OPERATION_FAILED;
381 ASP_LOGD("Success to get wifi interface name %s", if_name);
382 result = wifi_manager_deinitialize(wifi_handle);
383 if (result != WIFI_MANAGER_ERROR_NONE) {
384 ASP_LOGD("Failed to deinitialize wifi_manager");
386 return ASP_ERROR_OPERATION_FAILED;
389 result = dnssd_service_set_interface(service_handle, if_name);
390 if (result != DNSSD_ERROR_NONE) {
391 result = __asp_service_infra_convert_error_type(result);
395 ASP_LOGD("Success to set interface %s", if_name);
398 result = dnssd_register_local_service(service_handle,
399 _advertise_status_cb, GUINT_TO_POINTER(service->adv_id));
400 if (result != DNSSD_ERROR_NONE) {
401 result = __asp_service_infra_convert_error_type(result);
404 ASP_LOGD("Success to register local service %u", service_handle);
406 g_hash_table_insert(g_local_service_hash,
407 GUINT_TO_POINTER(service->adv_id), GUINT_TO_POINTER(service_handle));
409 ASP_LOGD("Insert (%u, %u) to g_local_service_hash (size: %d)",
410 service->adv_id, service_handle,
411 g_hash_table_size(g_local_service_hash));
414 /* Add TXT records */
415 /* First of all, add Advertisement ID */
416 snprintf(adv_id, ASP_SERVICE_ADV_ID_LEN + 1, "%u", service->adv_id);
417 adv_id_len = strlen(adv_id);
418 result = __add_txt_record(service_handle, ASP_INFRA_ADV_KEY, adv_id, adv_id_len);
419 if (result != DNSSD_ERROR_NONE) {
420 result = __asp_service_infra_convert_error_type(result);
424 /* Add MAC Address to TXT record */
425 mac_addr = vconf_get_str(VCONFKEY_WIFI_BSSID_ADDRESS);
427 ASP_LOGE("Failed to get vconf value for %s", VCONFKEY_WIFI_BSSID_ADDRESS);
428 return ASP_ERROR_OPERATION_FAILED;
431 mac_addr_len = strlen(mac_addr);
432 result = __add_txt_record(service_handle, ASP_INFRA_MAC_ADDR_KEY, mac_addr, mac_addr_len);
433 if (result != DNSSD_ERROR_NONE) {
434 result = __asp_service_infra_convert_error_type(result);
440 /* Other TXT records */
441 if (service->service_info_map != NULL) {
445 g_hash_table_iter_init(&iter, service->service_info_map);
446 while (g_hash_table_iter_next(&iter, &key, &value)) {
447 unsigned short len = (unsigned short)strlen(value);
448 result = __add_txt_record(service_handle, key, value, len);
452 __ASP_LOG_FUNC_EXIT__;
456 gint32 asp_tech_infra_cancel_advertise(asp_service_advertise_s *service)
458 __ASP_LOG_FUNC_ENTER__;
460 dnssd_service_h service_handle;
462 service_handle = (dnssd_service_h)GPOINTER_TO_UINT(g_hash_table_lookup(g_local_service_hash,
463 GUINT_TO_POINTER(service->adv_id)));
465 if (!service_handle) {
467 ASP_LOGE("Failed to lookup advertisement id %u", service->adv_id);
471 result = dnssd_deregister_local_service(service_handle);
472 if (result != DNSSD_ERROR_NONE) {
473 result = __asp_service_infra_convert_error_type(result);
474 ASP_LOGE("Failed to deregister local service %u", service_handle);
477 ASP_LOGD("Success to deregister local service: %u", service_handle);
479 result = dnssd_destroy_local_service(service_handle);
480 if (result != DNSSD_ERROR_NONE) {
481 result = __asp_service_infra_convert_error_type(result);
484 ASP_LOGD("Success to destroy local service: %u", service_handle);
486 __ASP_LOG_FUNC_EXIT__;
490 gint32 asp_tech_infra_seek(asp_service_seek_s *service)
492 __ASP_LOG_FUNC_ENTER__;
494 dnssd_browser_h browser_handle;
496 wifi_manager_h wifi_handle = NULL;
498 result = wifi_manager_initialize(&wifi_handle);
499 if (result != WIFI_MANAGER_ERROR_NONE) {
500 ASP_LOGD("Failed to initialize wifi-manager");
501 return ASP_ERROR_OPERATION_FAILED;
503 result = wifi_manager_get_network_interface_name(wifi_handle, &if_name);
504 if (result != WIFI_MANAGER_ERROR_NONE) {
505 ASP_LOGD("Failed to get interface name");
506 return ASP_ERROR_OPERATION_FAILED;
508 ASP_LOGD("Success to get wifi interface name %s", if_name);
509 result = wifi_manager_deinitialize(wifi_handle);
510 if (result != WIFI_MANAGER_ERROR_NONE) {
511 ASP_LOGD("Failed to deinitialize wifi-manager");
513 return ASP_ERROR_OPERATION_FAILED;
516 result = dnssd_start_browsing_service_on_interface(service->service_type,
517 if_name, &browser_handle,
519 GUINT_TO_POINTER(service->search_id));
521 if (result != DNSSD_ERROR_NONE) {
522 result = __asp_service_infra_convert_error_type(result);
526 ASP_LOGD("Success to start browsing service. service_type: %s, browser_handle: %u",
527 service->service_type, browser_handle);
529 g_hash_table_insert(g_browser_hash,
530 GUINT_TO_POINTER(service->search_id), GUINT_TO_POINTER(browser_handle));
532 ASP_LOGD("Insert (%" G_GUINT64_FORMAT ", %u) to g_browser_hash (size: %d)",
533 service->search_id, browser_handle,
534 g_hash_table_size(g_browser_hash));
537 __ASP_LOG_FUNC_EXIT__;
541 gint32 asp_tech_infra_cancel_seek(asp_service_seek_s *service)
543 __ASP_LOG_FUNC_ENTER__;
545 dnssd_browser_h browser_handle;
547 browser_handle = (dnssd_browser_h)GPOINTER_TO_UINT(g_hash_table_lookup(g_browser_hash,
548 GUINT_TO_POINTER(service->search_id)));
550 if (!browser_handle) {
552 ASP_LOGE("Failed to lookup search id %" G_GUINT64_FORMAT, service->search_id);
556 result = dnssd_stop_browsing_service(browser_handle);
557 if (result != DNSSD_ERROR_NONE) {
558 result = __asp_service_infra_convert_error_type(result);
561 ASP_LOGD("Success to stop browsing. browser_handle: %u", browser_handle);
563 __ASP_LOG_FUNC_EXIT__;
567 gint32 asp_tech_infra_connect_session(asp_tech_session_request_params_s *params)
569 __ASP_LOG_FUNC_ENTER__;
572 __ASP_LOG_FUNC_EXIT__;
576 gint32 asp_tech_infra_confirm_session(const guint8 *session_mac, gint32 session_id, gint32 confirm, guint32 pin)
578 __ASP_LOG_FUNC_ENTER__;
581 __ASP_LOG_FUNC_EXIT__;
585 gint32 asp_tech_infra_destroy_connection(const guint8 *peer_id, gint32 peer_id_length)
587 __ASP_LOG_FUNC_ENTER__;
590 __ASP_LOG_FUNC_EXIT__;
594 gint32 asp_tech_infra_is_peer_connected(const guint8 *peer_id, gint32 peer_id_length, gint32 *is_connected)
596 __ASP_LOG_FUNC_ENTER__;
599 __ASP_LOG_FUNC_EXIT__;
603 asp_tech_ops_s asp_tech_infra_ops = {
604 .init = asp_tech_infra_init,
605 .deinit = asp_tech_infra_deinit,
606 .advertise = asp_tech_infra_advertise,
607 .cancel_advertise = asp_tech_infra_cancel_advertise,
608 .seek = asp_tech_infra_seek,
609 .cancel_seek = asp_tech_infra_cancel_seek,
610 .connect_session = asp_tech_infra_connect_session,
611 .confirm_session = asp_tech_infra_confirm_session,
612 .destroy_connection = asp_tech_infra_destroy_connection,
613 .is_peer_connected = asp_tech_infra_is_peer_connected,
614 .session_request_cb = NULL,
615 .session_request_cb_user_data = NULL,
616 .session_config_request_cb = NULL,
617 .connect_status_cb = NULL,
618 .connect_status_cb_user_data = NULL,
619 .ip_assigned_cb = NULL,
620 .ip_assigned_cb_user_data = NULL,