Fix build warning
[platform/core/api/vine.git] / plugins / nan / nan-plugin.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
18 #include <string>
19 #include <map>
20
21 #include <glib.h>
22
23 #include <wifi-aware.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <net/if.h>
27 #include <errno.h>
28
29 #include "vine-constants.h"
30 #include "vine-disc-plugin.h"
31 #include "vine-log.h"
32 #include "vine-utils.h"
33 #include "nan-plugin.h"
34
35 typedef struct {
36         void *disc_handle;      // vine_disc handle
37         wifi_aware_publish_h publish_config;
38         wifi_aware_subscribe_h subscribe_config;
39         wifi_aware_session_h session;
40         std::map<string, wifi_aware_peer_h> peers;      // <mac, peer>
41         std::map<wifi_aware_peer_h, wifi_aware_data_path_h> ndps;       // <peer, ndp>
42
43         char published_service_name[VINE_MAX_NAN_SERVICE_NAME_LEN + 1];
44         char service_type[VINE_MAX_NAN_SERVICE_TYPE_LEN + 1];
45         int port;
46 } vine_nan_s;
47
48 static vine_disc_plugin_callbacks event_callbacks;
49
50 static vine_disc_error __convert_nan_error_to_vine_disc_error(int error)
51 {
52         return VINE_DISC_ERROR_NONE;
53 }
54
55 static bool __is_data_path_request_message(const unsigned char *message, size_t len)
56 {
57         RET_VAL_IF(len != strlen(VINE_FOLLOWUP_MESSAGE), false, "Wrong message");
58         return memcmp(message, VINE_FOLLOWUP_MESSAGE, strlen(VINE_FOLLOWUP_MESSAGE)) == 0;
59 }
60
61 static void __add_ndp(vine_nan_s *nan_handle,
62         wifi_aware_data_path_h ndp, wifi_aware_peer_h peer)
63 {
64         VINE_LOGD("Add NDP[%p]. peer[%p]", ndp, peer);
65         auto v = nan_handle->ndps.find(peer);
66         if (v == nan_handle->ndps.end()) {
67                 // TODO: Can the same peer request NAN data path?
68         }
69         nan_handle->ndps[peer] = ndp;
70 }
71
72 static void __terminated_cb(wifi_aware_data_path_h ndp,
73         wifi_aware_termination_reason_e reason, void *user_data)
74 {
75         VINE_LOGD("NDP is terminated [%p]. reason[%d]", ndp, (int)reason);
76
77         vine_nan_s *nan_handle = (vine_nan_s *)user_data;
78         if (event_callbacks.ip_resolved_cb)
79                 event_callbacks.ip_resolved_cb(nan_handle, false,
80                         nullptr, VINE_DISC_ADDR_FAMILY_IPV6, nan_handle->disc_handle);
81 }
82
83 static void __open_cb(wifi_aware_data_path_h ndp,
84         wifi_aware_error_e error, void *user_data)
85 {
86         RET_IF(!event_callbacks.ip_resolved_cb, "No callbacks");
87
88         char *ipv6;
89         if (wifi_aware_data_path_get_peer_ipv6_address(ndp, &ipv6) != WIFI_AWARE_ERROR_NONE) {
90                 VINE_LOGE("wifi_aware_data_path_get_peer_ipv6_address() fails");
91                 return;
92         }
93
94         vine_nan_s *nan_handle = (vine_nan_s *)user_data;
95
96         event_callbacks.ip_resolved_cb(nan_handle, true,
97                 ipv6, VINE_DISC_ADDR_FAMILY_IPV6, nan_handle->disc_handle);
98         g_free(ipv6);
99 }
100
101 static void __open_nan_data_path(wifi_aware_session_h session,
102         wifi_aware_peer_h peer, vine_nan_s *nan_handle)
103 {
104         VINE_LOGD("Open NAN data path. session[%p]", session);
105
106         /*
107         std::string mac;
108         bool found = false;
109         for (const auto &kv : nan_handle->peers) {
110                 if (kv.second == peer) {
111                         mac = kv.first;
112                         found = true;
113                         break;
114                 }
115         }
116
117         if (!found) {
118                 VINE_LOGE("Invalid peer");
119                 return;
120         }
121         */
122
123         wifi_aware_data_path_h ndp;
124         if (wifi_aware_data_path_create(session, peer, &ndp) != WIFI_AWARE_ERROR_NONE) {
125                 VINE_LOGE("wifi_aware_data_path_create() fails");
126                 return;
127         }
128
129         if (wifi_aware_data_path_set_terminated_cb(ndp, __terminated_cb, nan_handle)
130                 != WIFI_AWARE_ERROR_NONE) {
131                 VINE_LOGE("wifi_aware_data_path_set_terminated_cb() fails");
132                 return;
133         }
134
135         if (wifi_aware_data_path_open(ndp, __open_cb, nan_handle) != WIFI_AWARE_ERROR_NONE) {
136                 VINE_LOGE("wifi_aware_data_path_open() fails");
137                 return;
138         }
139
140         // TODO: Need to maintain ndp list?
141         __add_ndp(nan_handle, ndp, peer);
142 }
143
144 static void __received_cb(wifi_aware_session_h session, wifi_aware_peer_h peer,
145         const unsigned char *message, size_t len, void *user_data)
146 {
147         RET_IF(!user_data, "user_data is NULL");
148         VINE_LOGD("NAN message is received. session[%p], peer[%p], nan_handle[%p]",
149                 session, peer, user_data);
150
151         if (!__is_data_path_request_message(message, len)) {
152                 VINE_LOGD("This message will be not used");
153                 return;
154         }
155
156         __open_nan_data_path(session, peer, (vine_nan_s *)user_data);
157 }
158
159 static void __message_result_cb(wifi_aware_session_h session,
160         wifi_aware_error_e error, void *user_data)
161 {
162         if (error == WIFI_AWARE_ERROR_NONE) {
163                 VINE_LOGD("Message is successfully sent");
164                 return;
165         }
166
167         // TODO
168         // How can inform the failure to app?
169         // Use ip_resolved_cb with nullptr IP address?
170         // Then, in terminated_cb, I think ip_resolved_cb is called with ip address (add is false)
171 }
172
173 static int __send_nan_dp_request(wifi_aware_session_h session,
174         wifi_aware_peer_h peer, vine_nan_s *nan_handle)
175 {
176         VINE_LOGD("Send NAN Datapath request message");
177         return wifi_aware_session_send_message(session, peer,
178                 (unsigned char *)VINE_FOLLOWUP_MESSAGE, strlen(VINE_FOLLOWUP_MESSAGE),
179                 __message_result_cb, nan_handle);
180 }
181
182 vine_disc_error nan_resolve_ip(void *plugin_handle,
183                                 const char *service_type, const char *service_name,
184                                 const char *host_name, const char *mac, const char *iface_name, int family)
185 {
186         RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
187         RET_VAL_IF(!service_type, VINE_DISC_ERROR_INVALID_PARAMETER, "service_type is NULL");
188         RET_VAL_IF(!service_name, VINE_DISC_ERROR_INVALID_PARAMETER, "service_name is NULL");
189         RET_VAL_IF(!mac, VINE_DISC_ERROR_INVALID_PARAMETER, "mac is NULL");
190         // Ignore host_name and iface_name
191         RET_VAL_IF(family == VINE_DISC_ADDR_FAMILY_IPV4, VINE_DISC_ERROR_NOT_SUPPORTED,
192                 "Only IPv6 is allowed for NAN");
193
194         vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle;
195         RET_VAL_IF(nan_handle->peers.find(mac) == nan_handle->peers.end(),
196                 VINE_DISC_ERROR_INVALID_PARAMETER, "Invalid mac[%s]", mac);
197
198         VINE_LOGD("Start to resolve IP. plugin_handle[%p]\n", plugin_handle);
199         VINE_LOGD("type[%s] name[%s] mac[%s]", service_type, service_name, mac);
200
201         int ret = wifi_aware_session_set_message_received_cb(nan_handle->session,
202                 __received_cb, nan_handle);
203         if (ret != WIFI_AWARE_ERROR_NONE) {
204                 VINE_LOGE("wifi_aware_session_set_message_received_cb() fails");
205                 return __convert_nan_error_to_vine_disc_error(ret);
206         }
207
208         ret = __send_nan_dp_request(nan_handle->session, nan_handle->peers[mac], nan_handle);
209         if (ret != WIFI_AWARE_ERROR_NONE)
210                 VINE_LOGE("__send_nan_dp_request() fails");
211
212         return __convert_nan_error_to_vine_disc_error(ret);
213 }
214
215 vine_disc_error nan_cancel_resolve_ip(void *plugin_handle)
216 {
217         RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
218         VINE_LOGD("Cancel resolving IP. plugin_handle[%p]\n", plugin_handle);
219
220         return VINE_DISC_ERROR_NONE;
221 }
222
223
224 vine_disc_error nan_init(void **plugin_handle, void *disc_handle)
225 {
226         int ret = wifi_aware_initialize();
227         if (ret != WIFI_AWARE_ERROR_NONE && ret != WIFI_AWARE_ERROR_ALREADY_INITIALIZED) {
228                 VINE_LOGE("wifi_aware_initialize() fails");
229                 return __convert_nan_error_to_vine_disc_error(ret);
230         }
231
232         vine_nan_s *handle = new vine_nan_s;
233         VINE_LOGD("Create plugin_handle[%p]", handle);
234
235         handle->disc_handle = disc_handle;
236         handle->publish_config = nullptr;
237         handle->subscribe_config = nullptr;
238         handle->session = nullptr;
239
240         handle->port = -1;
241
242         *plugin_handle = handle;
243         // NAN will be enabled when publish() or subscribe()
244         // because enable function works asynchronously.
245
246         return VINE_DISC_ERROR_NONE;
247 }
248
249 void nan_deinit(void *plugin_handle)
250 {
251         RET_IF(plugin_handle == NULL, "Plugin handle is null");
252         vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle;
253
254         // TODO
255         // Disable NAN here?
256         // However, we have to check if NAN is used for data path or not
257         // , and if NAN data path is broken or not when NAN is disabled.
258
259         delete nan_handle;
260         wifi_aware_deinitialize();
261 }
262
263 static void __published_cb(wifi_aware_session_h session,
264         wifi_aware_error_e error, void *user_data)
265 {
266         VINE_LOGD("Service is published");
267         vine_nan_s *nan_handle = (vine_nan_s *)user_data;
268
269         if (event_callbacks.published_cb)
270                 event_callbacks.published_cb(nan_handle,
271                         nan_handle->published_service_name, __convert_nan_error_to_vine_disc_error(error),
272                         nan_handle->disc_handle);
273 }
274
275 static void __publish(vine_nan_s *nan_handle)
276 {
277         wifi_aware_session_h session;
278         int ret = wifi_aware_session_create(WIFI_AWARE_SESSION_PUBLISH, &session);
279         RET_IF(ret != WIFI_AWARE_ERROR_NONE, "wifi_aware_session_create() fails");
280
281         ret = wifi_aware_session_set_message_received_cb(session, __received_cb, nan_handle);
282         if (ret != WIFI_AWARE_ERROR_NONE) {
283                 VINE_LOGE("wifi_aware_session_publish() fails");
284                 goto ERR;
285         }
286
287         VINE_LOGD("Publish a NAN service");
288
289         ret = wifi_aware_session_publish(session, nan_handle->publish_config,
290                 __published_cb, nan_handle);
291         if (ret != WIFI_AWARE_ERROR_NONE) {
292                 VINE_LOGE("wifi_aware_session_publish() fails");
293                 goto ERR;
294         }
295
296         nan_handle->session = session;
297         return;
298 ERR:
299         wifi_aware_session_destroy(session);
300 }
301
302 static bool __get_attributes(const unsigned char *info, size_t len, map<string, string> &attr)
303 {
304         VINE_LOGD("Get Attributes");
305
306         const unsigned char *ptr = &info[VINE_MAX_NAN_SERVICE_NAME_LEN];
307         const unsigned char *max = info + len;
308         char key_buf[MAX_SPECIFIC_INFO_LEN + 1];
309         char value_buf[MAX_SPECIFIC_INFO_LEN + 1];
310
311         while (ptr < max) {
312                 const unsigned char *const end = ptr + 1 + ptr[0];
313                 if (end > max) {
314                         VINE_LOGE("Invalid attribute");
315                         return false;
316                 }
317                 char *buf = &key_buf[0];
318                 while (++ptr < end) {
319                         if (*ptr == '=') {
320                                 *buf = 0;
321                                 buf = &value_buf[0];
322                         } else {
323                                 *buf = *ptr;
324                                 ++buf;
325                         }
326                 }
327                 *buf = 0;
328                 VINE_LOGD("Key[%s] Value[%s]", key_buf, value_buf);
329                 string key(key_buf);
330                 string value(value_buf);
331                 attr[key] = value;
332         }
333         return true;
334 }
335
336 static void __add_peer(vine_nan_s *nan_handle, wifi_aware_peer_h peer, const char *mac)
337 {
338         VINE_LOGD("Add peer[%p]. mac[%s]", peer, mac);
339         nan_handle->peers[mac] = peer;
340 }
341
342 static void __discovered_cb(wifi_aware_session_h session,
343         wifi_aware_peer_h peer, const unsigned char *service_specific_info, size_t len,
344         int distance, void *user_data)
345 {
346         VINE_LOGD("Service Discovered. session[%p] peer[%p]", session, peer);
347         RET_IF(event_callbacks.discovered_cb == NULL, "discovered_cb is NULL");
348
349         if (len > MAX_SPECIFIC_INFO_LEN || len < VINE_MAX_NAN_SERVICE_NAME_LEN) {
350                 VINE_LOGE("Invalid info len[%d]", len);
351                 return;
352         }
353
354         char service_name[VINE_MAX_SERVICE_NAME_LEN + 1];
355         memcpy(service_name, service_specific_info, VINE_MAX_NAN_SERVICE_NAME_LEN);
356         service_name[VINE_MAX_NAN_SERVICE_NAME_LEN] = 0;
357
358         map<string, string> attributes;
359         if (__get_attributes(service_specific_info, len, attributes) == false)
360                 return;
361
362         char *mac;
363         int ret = wifi_aware_peer_get_mac(peer, (unsigned char **)&mac);
364         RET_IF(ret != WIFI_AWARE_ERROR_NONE, "wifi_aware_peer_get_mac() fails");
365
366         vine_nan_s *nan_handle = (vine_nan_s *)user_data;
367         __add_peer(nan_handle, peer, mac);
368
369         event_callbacks.discovered_cb(nan_handle, true,
370                 nan_handle->service_type, service_name, nullptr,
371                 mac, -1, attributes, nullptr, 0,
372                 nan_handle->disc_handle);
373         g_free(mac);
374 }
375
376 /**
377  * When NAN subscription is failed, it is informed with discovered_cb.
378  * If service_type and service_name are nullptr, it is considered as an error.
379  * vine_session_discovered_cb will be called with NULL vine_service_h.
380  */
381 static void __subscribe_failed(vine_nan_s *nan_handle)
382 {
383         if (event_callbacks.discovered_cb) {
384                 std::map<string, string> empty_map;
385                 event_callbacks.discovered_cb(nan_handle, false,
386                         nullptr, nullptr, nullptr, nullptr, -1, empty_map, nullptr, 0,
387                         nan_handle->disc_handle);
388         }
389 }
390
391 static void __subscribed_cb(wifi_aware_session_h session,
392         wifi_aware_error_e error, void *user_data)
393 {
394         if (error == WIFI_AWARE_ERROR_NONE) {
395                 VINE_LOGD("No error");
396                 return;
397         }
398
399         VINE_LOGE("Fails to subscribe. error: %d", __convert_nan_error_to_vine_disc_error(error));
400         __subscribe_failed((vine_nan_s *)user_data);
401 }
402
403 static void __subscribe(vine_nan_s *nan_handle)
404 {
405         wifi_aware_session_h session;
406         int ret = wifi_aware_session_create(WIFI_AWARE_SESSION_SUBSCRIBE, &session);
407         RET_IF(ret != WIFI_AWARE_ERROR_NONE, "wifi_aware_session_create() fails");
408
409         VINE_LOGD("Subscribe a NAN service");
410
411         ret = wifi_aware_session_set_service_discovered_cb(session, __discovered_cb, nan_handle);
412         if (ret != WIFI_AWARE_ERROR_NONE) {
413                 VINE_LOGE("wifi_aware_session_publish() fails");
414                 goto ERR;
415         }
416
417         ret = wifi_aware_session_subscribe(session,
418                         nan_handle->subscribe_config, __subscribed_cb, nan_handle);
419         if (ret != WIFI_AWARE_ERROR_NONE) {
420                 VINE_LOGE("wifi_aware_session_publish() fails");
421                 goto ERR;
422         }
423
424         nan_handle->session = session;
425         return;
426
427 ERR:
428         wifi_aware_session_destroy(session);
429         __subscribe_failed(nan_handle);
430 }
431
432 static void __start_session(vine_nan_s *nan_handle)
433 {
434         if (nan_handle->publish_config)
435                 __publish(nan_handle);
436         else if (nan_handle->subscribe_config)
437                 __subscribe(nan_handle);
438         else
439                 VINE_LOGE("Invalid operation");
440 }
441
442 static void __stop_session(vine_nan_s *nan_handle)
443 {
444         if (nan_handle->session) {
445                 VINE_LOGD("Stop NAN session");
446                 wifi_aware_session_stop(nan_handle->session);
447                 wifi_aware_session_destroy(nan_handle->session);
448         }
449 }
450
451 static void __enabled_cb(wifi_aware_error_e error, void *user_data)
452 {
453         RET_IF(!user_data, "nan_handle is NULL");
454
455         VINE_LOGD("NAN is enabled. nan_handle[%p]", user_data);
456         __start_session((vine_nan_s *)user_data);
457 }
458
459 static bool __check_attr_len(const map<string, string> &attributes)
460 {
461         int info_len = VINE_MAX_NAN_SERVICE_NAME_LEN;
462         for (const auto &kv : attributes) {
463                 auto key = kv.first;
464                 auto val = kv.second;
465                 info_len += key.size() + val.size() + 1;
466                 if (info_len > MAX_SPECIFIC_INFO_LEN)
467                         return false;
468         }
469         return true;
470 }
471
472 static void __fill_specific_info(unsigned char *info, const char *service_name,
473         const map<string, string> &attributes)
474 {
475         int service_name_len = strlen(service_name);
476         memcpy(info, service_name, service_name_len);
477         info[service_name_len] = 0;
478
479         unsigned char *ptr = &info[VINE_MAX_NAN_SERVICE_NAME_LEN];
480         for (const auto &kv : attributes) {
481                 auto key = kv.first;
482                 auto val = kv.second;
483                 int key_len = key.size();
484                 int val_len = val.size();
485                 *ptr = (unsigned char)(key_len + val_len + 1);
486                 ptr++;
487                 memcpy(ptr, key.c_str(), key_len);
488                 ptr += key_len;
489                 *ptr++ = '=';
490                 memcpy(ptr, val.c_str(), val_len);
491                 ptr += val_len;
492         }
493 }
494
495 vine_disc_error nan_publish(void *plugin_handle, const char *service_type,
496                 const char *service_name, int port, const map<string, string> &attributes,
497                 const char *iface_name)
498 {
499         RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
500         RET_VAL_IF(!service_type, VINE_DISC_ERROR_INVALID_PARAMETER, "service_type is NULL");
501         RET_VAL_IF(!service_name, VINE_DISC_ERROR_INVALID_PARAMETER, "service_name is NULL");
502         RET_VAL_IF(strlen(service_type) > NAN_MAX_SERVICE_NAME_LEN, VINE_DISC_ERROR_INVALID_PARAMETER,
503                 "Too long service type");
504         RET_VAL_IF(strlen(service_name) > VINE_MAX_NAN_SERVICE_NAME_LEN, VINE_DISC_ERROR_INVALID_PARAMETER,
505                 "Too long service name");
506         RET_VAL_IF(__check_attr_len(attributes) == false, VINE_DISC_ERROR_INVALID_PARAMETER,
507                 "Too long attributes");
508
509         vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle;
510         VINE_LOGD("Publish. plugin_handle[%p], service_type[%s], service_name[%s], port[%d]",
511                 plugin_handle, service_type, service_name, port);
512
513         wifi_aware_publish_h config = nullptr;
514         int ret = wifi_aware_publish_create(&config);
515         RET_VAL_IF(ret != WIFI_AWARE_ERROR_NONE, __convert_nan_error_to_vine_disc_error(ret),
516                 "wifi_aware_publish_create() fails");
517
518         unsigned char info[MAX_SPECIFIC_INFO_LEN + 1] = {0, };
519
520         ret = wifi_aware_publish_set_type(config, WIFI_AWARE_PUBLISH_TYPE_UNSOLICITED);
521         if (ret != WIFI_AWARE_ERROR_NONE) {
522                 VINE_LOGE("wifi_aware_publish_set_type() fails");
523                 goto ERR;
524         }
525
526         ret = wifi_aware_publish_set_service_name(config, service_type);
527         if (ret != WIFI_AWARE_ERROR_NONE) {
528                 VINE_LOGE("wifi_aware_publish_set_service_name() fails");
529                 goto ERR;
530         }
531
532         __fill_specific_info(info, service_name, attributes);
533
534         ret = wifi_aware_enable(__enabled_cb, nan_handle);
535         if (ret != WIFI_AWARE_ERROR_NONE) {
536                 VINE_LOGE("wifi_aware_enable() fails");
537                 goto ERR;
538         }
539
540         nan_handle->publish_config = config;
541         nan_handle->port = port;        // port will be set for NAN data path
542         strncpy(nan_handle->published_service_name, service_name, VINE_MAX_SERVICE_NAME_LEN);
543
544         return VINE_DISC_ERROR_NONE;
545
546 ERR:
547         wifi_aware_publish_destroy(config);
548         return __convert_nan_error_to_vine_disc_error(ret);
549 }
550
551 vine_disc_error nan_stop_publish(void *plugin_handle)
552 {
553         RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
554
555         VINE_LOGD("Stop publish. plugin_handle[%p]", plugin_handle);
556         vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle;
557         __stop_session(nan_handle);
558
559         if (nan_handle->publish_config)
560                 wifi_aware_publish_destroy(nan_handle->publish_config);
561
562         return VINE_DISC_ERROR_NONE;
563 }
564
565 vine_disc_error nan_subscribe(void *plugin_handle,
566                 const char *service_type, const char *iface_name)
567 {
568         RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
569         RET_VAL_IF(!service_type, VINE_DISC_ERROR_INVALID_PARAMETER, "service_type is NULL");
570         RET_VAL_IF(strlen(service_type) > NAN_MAX_SERVICE_NAME_LEN, VINE_DISC_ERROR_INVALID_PARAMETER,
571                 "Too long service type");
572
573         vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle;
574         VINE_LOGD("Subscribe. plugin_handle[%p], service_type[%s]",
575                 plugin_handle, service_type);
576
577         wifi_aware_subscribe_h config = nullptr;
578         int ret = wifi_aware_subscribe_create(&config);
579         RET_VAL_IF(ret != WIFI_AWARE_ERROR_NONE, __convert_nan_error_to_vine_disc_error(ret),
580                 "wifi_aware_subscribe_create() fails");
581
582         ret = wifi_aware_subscribe_set_type(config, WIFI_AWARE_SUBSCRIBE_TYPE_ACTIVE);
583         if (ret != WIFI_AWARE_ERROR_NONE) {
584                 VINE_LOGE("wifi_aware_subscribe_set_type() fails");
585                 goto ERR;
586         }
587
588         ret = wifi_aware_subscribe_set_service_name(config, service_type);
589         if (ret != WIFI_AWARE_ERROR_NONE) {
590                 VINE_LOGE("wifi_aware_subscribe_set_service_name() fails");
591                 goto ERR;
592         }
593
594         nan_handle->subscribe_config = config;
595
596         ret = wifi_aware_enable(__enabled_cb, nan_handle);
597         if (ret != WIFI_AWARE_ERROR_NONE) {
598                 VINE_LOGE("wifi_aware_enable() fails");
599                 goto ERR;
600         }
601
602         return VINE_DISC_ERROR_NONE;
603
604 ERR:
605         wifi_aware_subscribe_destroy(config);
606         return __convert_nan_error_to_vine_disc_error(ret);
607 }
608
609 vine_disc_error nan_stop_subscribe(void *plugin_handle)
610 {
611         RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL");
612
613         VINE_LOGD("Stop subscribe. plugin_handle[%p]", plugin_handle);
614         vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle;
615         __stop_session(nan_handle);
616
617         if (nan_handle->subscribe_config)
618                 wifi_aware_subscribe_destroy(nan_handle->subscribe_config);
619
620         return VINE_DISC_ERROR_NONE;
621 }
622
623
624 void nan_register_callbacks(vine_disc_plugin_callbacks callbacks)
625 {
626         event_callbacks.published_cb = callbacks.published_cb;
627         event_callbacks.discovered_cb = callbacks.discovered_cb;
628         event_callbacks.ip_resolved_cb = callbacks.ip_resolved_cb;
629         event_callbacks.fd_added_cb = nullptr;
630         event_callbacks.fd_removed_cb = nullptr;
631 }
632
633 vine_disc_error nan_process_event(void *plugin_handle, int fd)
634 {
635         VINE_LOGE("Not supported function");
636         return VINE_DISC_ERROR_NOT_SUPPORTED;
637 }
638
639 void vine_disc_plugin_init(vine_disc_plugin_fn *fn)
640 {
641         fn->init = nan_init;
642         fn->deinit = nan_deinit;
643         fn->publish = nan_publish;
644         fn->stop_publish = nan_stop_publish;
645         fn->subscribe = nan_subscribe;
646         fn->stop_subscribe = nan_stop_subscribe;
647         fn->resolve_ip = nan_resolve_ip;
648         fn->cancel_resolve_ip = nan_cancel_resolve_ip;
649         fn->register_callbacks = nan_register_callbacks;
650         fn->process_event = nan_process_event;
651 }