Fix bugs reported by static analyzer
[platform/core/connectivity/asp-manager.git] / src / tech / asp-tech-p2p.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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  * Standard headers
19  *****************************************************************************/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25
26 /*****************************************************************************
27  * System headers
28  *****************************************************************************/
29
30 #include <glib.h>
31 #include <dlog.h>
32 #include <gio/gio.h>
33
34 /*****************************************************************************
35  * Application Service Platform Daemon headers
36  *****************************************************************************/
37 #include "asp-manager.h"
38 #include "asp-manager-util.h"
39 #include "asp-service.h"
40 #include "asp-session.h"
41 #include "asp-tech.h"
42 #include "asp-tech-p2p.h"
43
44 /*****************************************************************************
45  * Macros and Typedefs
46  *****************************************************************************/
47
48 #define ASP_TECH_P2P_ROLE_NEW 1
49 #define ASP_TECH_P2P_ROLE_GC 2
50 #define ASP_TECH_P2P_ROLE_GO 4
51
52 #define WFD_MANAGER_SERVICE                     "net.wifidirect"
53 #define WFD_MANAGER_PATH                        "/net/wifidirect"
54 #define WFD_MANAGER_MANAGE_INTERFACE            WFD_MANAGER_SERVICE
55 #define WFD_MANAGER_CONFIG_INTERFACE            WFD_MANAGER_SERVICE ".config"
56 #define WFD_MANAGER_GROUP_INTERFACE             WFD_MANAGER_SERVICE ".group"
57 #define WFD_MANAGER_ASP_INTERFACE                        WFD_MANAGER_SERVICE ".asp"
58
59 #define DBUS_REPLY_TIMEOUT_SYNC     10 * 1000
60 #define DBUS_OBJECT_PATH_MAX                    150
61
62 #define WFD_MANAGER_QUARK (g_quark_from_string("wifi-direct-manager"))
63
64 #define asp_tech_p2p_dbus_method_call_sync(interface_name, method, params, error) \
65         __asp_tech_p2p_dbus_method_call_sync_debug(interface_name, method, params, error, __func__)
66
67 #define DBUS_DEBUG_VARIANT(parameters) \
68         do {\
69                 gchar *parameters_debug_str = NULL;\
70                 if (parameters)\
71                         parameters_debug_str = g_variant_print(parameters, TRUE);\
72                 ASP_LOGD("signal params [%s]", parameters_debug_str ? parameters_debug_str : "NULL");\
73                 g_free(parameters_debug_str);\
74         } while (0)
75
76 asp_tech_ops_s asp_tech_p2p_ops;
77
78 void asp_tech_p2p_process_activation(GDBusConnection *connection,
79                 const gchar *object_path, GVariant *parameters);
80
81 void asp_tech_p2p_process_deactivation(GDBusConnection *connection,
82                 const gchar *object_path, GVariant *parameters);
83
84 void asp_tech_p2p_process_search_result(GDBusConnection *connection,
85                 const gchar *object_path, GVariant *parameters);
86
87 void asp_tech_p2p_process_session_request(GDBusConnection *connection,
88                 const gchar *object_path, GVariant *parameters);
89
90 void asp_tech_p2p_process_session_config_request(GDBusConnection *connection,
91                 const gchar *object_path, GVariant *parameters);
92
93 void asp_tech_p2p_process_connect_status(GDBusConnection *connection,
94                 const gchar *object_path, GVariant *parameters);
95
96 void asp_tech_p2p_process_session_peer_ip(GDBusConnection *connection,
97                 const gchar *object_path, GVariant *parameters);
98
99 /*****************************************************************************
100  * Global Variables
101  *****************************************************************************/
102
103 static GDBusConnection *g_wfd_gdbus_conn;
104 static guint g_wfd_signal_id;
105
106 static struct {
107         const gchar *interface;
108         const gchar *member;
109         void (*function) (GDBusConnection *connection,
110                           const gchar *object_path,
111                           GVariant *parameters);
112 } asp_tech_p2p_dbus_signal_map[] = {
113                 {
114                                 WFD_MANAGER_MANAGE_INTERFACE,
115                                 "Activation",
116                                 asp_tech_p2p_process_activation
117                 },
118                 {
119                                 WFD_MANAGER_MANAGE_INTERFACE,
120                                 "Deactivation",
121                                 asp_tech_p2p_process_deactivation
122                 },
123                 {
124                                 WFD_MANAGER_ASP_INTERFACE,
125                                 "SearchResult",
126                                 asp_tech_p2p_process_search_result
127                 },
128                 {
129                                 WFD_MANAGER_ASP_INTERFACE,
130                                 "SessionRequest",
131                                 asp_tech_p2p_process_session_request
132                 },
133                 {
134                                 WFD_MANAGER_ASP_INTERFACE,
135                                 "SessionConfigRequest",
136                                 asp_tech_p2p_process_session_config_request
137                 },
138                 {
139                                 WFD_MANAGER_ASP_INTERFACE,
140                                 "ConnectStatus",
141                                 asp_tech_p2p_process_connect_status
142                 },
143                 {
144                                 WFD_MANAGER_ASP_INTERFACE,
145                                 "SessionPeerIPAssigned",
146                                 asp_tech_p2p_process_session_peer_ip
147                 },
148                 {
149                                 NULL,
150                                 NULL,
151                                 NULL
152                 }
153 };
154
155 /*****************************************************************************
156  * Local Functions Definition
157  *****************************************************************************/
158
159 static gint32 __net_wifidirect_gerror_to_enum(GError* error)
160 {
161         gint32 res = 0;
162         if (error == NULL) {
163                 ASP_LOGI("GError is NULL!!");
164                 return res;
165         }
166
167         ASP_LOGE("wifi_direct_dbus_method_call_sync() failed. error [%d: %s]",
168                         error->code, error->message);
169
170         res = -1;
171         /*
172         if (NULL == strstr(error->message, "net.wifidirect.Error")) {
173                 if (NULL != strstr(error->message, ".AccessDenied")) {
174                         ASP_LOGE("Client doesn't have wifidirect privilege");
175                         res = -1;
176                 } else {
177                         ASP_LOGE("DBus failure");
178                         res = -1;
179                 }
180         } else {
181                 if (NULL != strstr(error->message, "InvalidParameter"))
182                         res = -1;
183                 else if (NULL != strstr(error->message, "NotPermitted"))
184                         res = -1;
185                 else if (NULL != strstr(error->message, "OperationFailed"))
186                         res = -1;
187                 else if (NULL != strstr(error->message, "TooManyClient"))
188                         res = -1;
189                 else
190                         res = -1;
191         }
192         */
193         return res;
194 }
195
196
197 static void __asp_tech_p2p_dbus_signal_cb(GDBusConnection *connection,
198                 const gchar *sender, const gchar *object_path,
199                 const gchar *interface, const gchar *signal,
200                 GVariant *parameters, gpointer user_data)
201 {
202         gint32 i = 0;
203
204         ASP_LOGD("Signal Name [%s]", signal);
205         DBUS_DEBUG_VARIANT(parameters);
206
207         for (i = 0; asp_tech_p2p_dbus_signal_map[i].member != NULL; i++) {
208                 if (!g_strcmp0(signal, asp_tech_p2p_dbus_signal_map[i].member) &&
209                     !g_strcmp0(interface, asp_tech_p2p_dbus_signal_map[i].interface) &&
210                     asp_tech_p2p_dbus_signal_map[i].function != NULL) {
211                         asp_tech_p2p_dbus_signal_map[i].function(connection, object_path, parameters);
212                         break;
213                 }
214         }
215 }
216
217 static GVariant *__g_hash_table_to_g_variant(GHashTable *hash)
218 {
219         GVariantBuilder builder;
220
221         g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
222
223         GHashTableIter iter;
224         gpointer key, value;
225
226         g_hash_table_iter_init(&iter, hash);
227         while (g_hash_table_iter_next(&iter, &key, &value)) {
228                 ASP_LOGD("%s %s", key, value);
229                 g_variant_builder_add(&builder, "{sv}", key, g_variant_new_string(value));
230         }
231
232         return g_variant_builder_end(&builder);
233 }
234
235 static GVariant *__g_hash_keys_to_g_variant(GHashTable *hash)
236 {
237         GVariantBuilder builder;
238
239         g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
240
241         GHashTableIter iter;
242         gpointer key, value;
243
244         g_hash_table_iter_init(&iter, hash);
245         while (g_hash_table_iter_next(&iter, &key, &value))
246                 g_variant_builder_add(&builder, "s", key);
247
248         return g_variant_builder_end(&builder);
249 }
250
251 GVariant *__asp_tech_p2p_dbus_method_call_sync_debug(const gchar* interface_name,
252                                                   const gchar* method,
253                                                   GVariant *params,
254                                                   GError **error,
255                                                   const gchar *calling_func)
256 {
257         GVariant *reply = NULL;
258
259         if (g_wfd_gdbus_conn == NULL) {
260                 ASP_LOGE("GDBusconnection is NULL");
261                 return reply;
262         }
263
264         ASP_LOGD("[%s][%s.%s]", calling_func, interface_name, method);
265         DBUS_DEBUG_VARIANT(params);
266
267         reply = g_dbus_connection_call_sync(g_wfd_gdbus_conn,
268                                             WFD_MANAGER_SERVICE, /* bus name */
269                                             WFD_MANAGER_PATH, /* object path */
270                                             interface_name, /* interface name */
271                                             method, /* method name */
272                                             params, /* GVariant *params */
273                                             NULL, /* reply_type */
274                                             G_DBUS_CALL_FLAGS_NONE, /* flags */
275                                             DBUS_REPLY_TIMEOUT_SYNC, /* timeout */
276                                             NULL, /* cancellable */
277                                             error); /* error */
278         DBUS_DEBUG_VARIANT(reply);
279         return reply;
280 }
281
282 void asp_tech_p2p_process_activation(GDBusConnection *connection,
283                 const gchar *object_path, GVariant *parameters)
284 {
285         __ASP_LOG_FUNC_ENTER__;
286
287         ASP_LOGE("Wi-Fi Direct activated");
288
289         __ASP_LOG_FUNC_EXIT__;
290         return;
291 }
292
293 void asp_tech_p2p_process_deactivation(GDBusConnection *connection,
294                 const gchar *object_path, GVariant *parameters)
295 {
296         __ASP_LOG_FUNC_ENTER__;
297
298         ASP_LOGE("Wi-Fi Direct deactivated");
299
300         __ASP_LOG_FUNC_EXIT__;
301         return;
302 }
303
304 static void __service_info_to_g_hash(const gchar *service_info,
305                 GHashTable *service_info_map)
306 {
307         const gchar *key = NULL;
308         const gchar *value = NULL;
309         gsize pos = 0;
310         gsize key_length = 0;
311         gsize value_length = 0;
312         gsize info_length = 0;
313
314         info_length = strlen(service_info);
315
316         while (service_info[pos] != '\0' && pos < info_length) {
317                 key = &service_info[pos];
318                 while (service_info[pos] != '=' && pos < info_length) {
319                         key_length++;
320                         pos++;
321                 }
322
323                 if (pos >= info_length - 1) {
324                         g_hash_table_replace(service_info_map, g_strndup(key, key_length),
325                                         g_strdup(""));
326                         break;
327                 }
328
329                 pos++;
330                 value = &service_info[pos];
331                 while (service_info[pos] != ',' && pos < info_length) {
332                         value_length++;
333                         pos++;
334                 }
335
336                 g_hash_table_replace(service_info_map, g_strndup(key, key_length),
337                                 g_strndup(value, value_length));
338                 ASP_LOGD("Insert (%s, %s) to hash.", key, value);
339
340                 if (service_info[pos] == ',' && pos == info_length)
341                         break;
342         }
343         return;
344 }
345
346 void asp_tech_p2p_process_search_result(GDBusConnection *connection,
347                 const gchar *object_path, GVariant *parameters)
348 {
349         __ASP_LOG_FUNC_ENTER__;
350
351         GVariantIter *iter = NULL;
352         GVariant *var = NULL;
353         GHashTable *service_info_map = NULL;
354         asp_event_data event;
355         const gchar *service_mac = NULL;
356         const gchar *key = NULL;
357         const gchar *str = NULL;
358         long long unsigned search_id = 0;
359         gchar *device_name = NULL;
360         guint32 advertisement_id = 0;
361         guint32 config_method = 0;
362         gchar *instance_name = NULL;
363         guint8 status = 0;
364
365         if (!parameters) {
366                 __ASP_LOG_FUNC_EXIT__;
367                 return;
368         }
369
370         g_variant_get(parameters, "(a{sv})", &iter);
371         while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
372                 if (!g_strcmp0(key, "search_id")) {
373                         g_variant_get(var, "t", &search_id);
374                 } else if (!g_strcmp0(key, "service_mac")) {
375                         g_variant_get(var, "&s", &service_mac);
376                 } else if (!g_strcmp0(key, "device_name")) {
377                         g_variant_get(var, "&s", &str);
378                         device_name = g_strndup(str, ASP_SERVICE_DEVICE_NAME_LEN);
379                 }  else if (!g_strcmp0(key, "advertisement_id")) {
380                         g_variant_get(var, "u", &advertisement_id);
381                 } else if (!g_strcmp0(key, "config_method")) {
382                         g_variant_get(var, "u", &config_method);
383                 }  else if (!g_strcmp0(key, "instance_name")) {
384                         g_variant_get(var, "&s", &str);
385                         instance_name = g_strdup(str);
386                 } else if (!g_strcmp0(key, "status")) {
387                         g_variant_get(var, "y", &status);
388                 }  else if (!g_strcmp0(key, "service_info")) {
389                         g_variant_get(var, "&s", &str);
390                         service_info_map = g_hash_table_new_full(g_str_hash,
391                                         g_str_equal, g_free, g_free);
392                         __service_info_to_g_hash(str, service_info_map);
393                 }   else {
394                                 ;/* Do Nothing */
395                 }
396         }
397
398         memset(&event, 0x0, sizeof(asp_event_data));
399         event.search_result.tech = ASP_TECH_P2P;
400         event.search_result.search_id = search_id;
401         event.search_result.advertisement_id = advertisement_id;
402         event.search_result.service_status = status;
403         if (service_mac)
404                 memcpy(event.search_result.service_mac, service_mac, MACSTR_LEN + 1);
405         event.search_result.device_name = device_name;
406         event.search_result.instance_name = instance_name;
407         event.search_result.service_info = service_info_map;
408         asp_manager_event(NULL, ASP_EVENT_SEARCH_RESULT, &event);
409
410         g_free(device_name);
411         g_free(instance_name);
412         g_hash_table_unref(service_info_map);
413         g_variant_iter_free(iter);
414
415         __ASP_LOG_FUNC_EXIT__;
416         return;
417 }
418
419 void asp_tech_p2p_process_session_request(GDBusConnection *connection,
420                 const gchar *object_path, GVariant *parameters)
421 {
422         __ASP_LOG_FUNC_ENTER__;
423
424         GVariantIter *iter = NULL;
425         GVariant *var = NULL;
426         const gchar *key = NULL;
427         const gchar *str = NULL;
428         guint8 session_mac[MAC_LEN] = {0,};
429         guint32 session_id = 0;
430         guint32 adv_id = 0;
431         gchar *device_name = NULL;
432         size_t name_length = 0;
433         guint8 *session_info = NULL;
434         size_t info_length = 0;
435         gboolean get_pin = FALSE;
436         guint32 pin = 0;
437
438         if (!parameters) {
439                 __ASP_LOG_FUNC_EXIT__;
440                 return;
441         }
442
443         g_variant_get(parameters, "(a{sv})", &iter);
444         while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
445                 if (!g_strcmp0(key, "adv_id")) {
446                         g_variant_get(var, "u", &adv_id);
447                 } else if (!g_strcmp0(key, "session_mac")) {
448                         if (asp_dbus_unpack_ay(session_mac, var, MAC_LEN) < 0) {
449                                 g_free(device_name);
450                                 g_free(session_info);
451                                 g_variant_iter_free(iter);
452                                 return;
453                         }
454                 }  else if (!g_strcmp0(key, "session_id")) {
455                         g_variant_get(var, "u", &session_id);
456                 }  else if (!g_strcmp0(key, "device_name")) {
457                         g_variant_get(var, "&s", &str);
458                         device_name = g_strndup(str, ASP_SERVICE_DEVICE_NAME_LEN);
459                         name_length = strlen(str);
460                 } else if (!g_strcmp0(key, "get_pin")) {
461                         g_variant_get(var, "b", &get_pin);
462                 } else if (!g_strcmp0(key, "pin")) {
463                         g_variant_get(var, "&s", &str);
464                         pin = (guint32)atoi(str);
465                 } else if (!g_strcmp0(key, "session_info")) {
466                         str = NULL;
467                         g_variant_get(var, "&s", &str);
468                         if (!str)
469                                 continue;
470                         info_length = strlen(str);
471                         g_free(session_info);
472                         session_info = g_try_malloc0(info_length + 1);
473                         if (session_info)
474                                 memcpy(session_info, str, info_length);
475                 } else {
476                                 ;/* Do Nothing */
477                 }
478         }
479
480         if (asp_tech_p2p_ops.session_request_cb) {
481                 asp_tech_p2p_ops.session_request_cb(0, session_mac, session_id,
482                                 adv_id, device_name, name_length,
483                                 session_info, info_length, get_pin, pin,
484                                 asp_tech_p2p_ops.session_request_cb_user_data);
485         }
486
487         g_variant_iter_free(iter);
488         g_free(device_name);
489         g_free(session_info);
490
491         __ASP_LOG_FUNC_EXIT__;
492         return;
493 }
494
495 void asp_tech_p2p_process_session_config_request(GDBusConnection *connection,
496                 const gchar *object_path, GVariant *parameters)
497 {
498         __ASP_LOG_FUNC_ENTER__;
499
500         GVariantIter *iter = NULL;
501         GVariant *var = NULL;
502         const gchar *key = NULL;
503         const gchar *str = NULL;
504         const guint8 session_mac[MAC_LEN] = {0,};
505         guint32 session_id = 0;
506         gboolean get_pin = FALSE;
507         guint32 pin = 0;
508
509         if (!parameters) {
510                 __ASP_LOG_FUNC_EXIT__;
511                 return;
512         }
513
514         g_variant_get(parameters, "(a{sv})", &iter);
515         while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
516                 if (!g_strcmp0(key, "session_id")) {
517                         g_variant_get(var, "u", &session_id);
518                 } else if (!g_strcmp0(key, "get_pin")) {
519                         g_variant_get(var, "b", &get_pin);
520                 } else if (!g_strcmp0(key, "pin")) {
521                         g_variant_get(var, "&s", &str);
522                         pin = (guint32)atoi(str);
523                 } else {
524                         ;/* Do Nothing */
525                 }
526         }
527
528         if (asp_tech_p2p_ops.session_config_request_cb) {
529                 asp_tech_p2p_ops.session_config_request_cb(0,
530                                 session_mac, session_id, get_pin, pin,
531                                 asp_tech_p2p_ops.session_config_request_cb_user_data);
532         }
533         g_variant_iter_free(iter);
534
535         __ASP_LOG_FUNC_EXIT__;
536         return;
537 }
538
539 void asp_tech_p2p_process_connect_status(GDBusConnection *connection,
540                 const gchar *object_path, GVariant *parameters)
541 {
542         __ASP_LOG_FUNC_ENTER__;
543
544         GVariantIter *iter = NULL;
545         GVariant *var = NULL;
546         const gchar *key = NULL;
547         const gchar *str = NULL;
548         guint8 session_mac[MAC_LEN] = {0,};
549         guint32 session_id = 0;
550         guint32 status = 0;
551         gchar *deferred = NULL;
552
553         if (!parameters) {
554                 __ASP_LOG_FUNC_EXIT__;
555                 return;
556         }
557
558         g_variant_get(parameters, "(a{sv})", &iter);
559         while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
560                 if (!g_strcmp0(key, "session_mac")) {
561                         if (asp_dbus_unpack_ay(session_mac, var, MAC_LEN) < 0) {
562                                 g_variant_iter_free(iter);
563                                 g_free(deferred);
564                                 return;
565                         }
566                 } else if (!g_strcmp0(key, "session_id")) {
567                         g_variant_get(var, "u", &session_id);
568                 } else if (!g_strcmp0(key, "status")) {
569                         g_variant_get(var, "i", &status);
570                 } else if (!g_strcmp0(key, "deferred")) {
571                         g_variant_get(var, "&s", &str);
572                         g_free(deferred);
573                         deferred = g_strdup(str);
574                 } else {
575                         ;/* Do Nothing */
576                 }
577         }
578
579         if (asp_tech_p2p_ops.connect_status_cb) {
580                 asp_tech_p2p_ops.connect_status_cb(0,
581                                 session_mac, session_id, status,
582                                 asp_tech_p2p_ops.connect_status_cb_user_data);
583         }
584
585         g_variant_iter_free(iter);
586         g_free(deferred);
587
588         __ASP_LOG_FUNC_EXIT__;
589         return;
590 }
591
592 void asp_tech_p2p_process_session_peer_ip(GDBusConnection *connection,
593                 const gchar *object_path, GVariant *parameters)
594 {
595         __ASP_LOG_FUNC_ENTER__;
596
597         GVariantIter *iter = NULL;
598         GVariant *var = NULL;
599         const gchar *key = NULL;
600         guint8 session_mac[MAC_LEN] = {0,};
601         guint8 service_mac[MAC_LEN] = {0,};
602         guint32 session_id = 0;
603         gchar *peer_ip = NULL;
604
605         if (!parameters) {
606                 __ASP_LOG_FUNC_EXIT__;
607                 return;
608         }
609
610         g_variant_get(parameters, "(a{sv})", &iter);
611         while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
612                 if (!g_strcmp0(key, "session_mac")) {
613                         if (asp_dbus_unpack_ay(session_mac, var, MAC_LEN) < 0) {
614                                 g_variant_iter_free(iter);
615                                 return;
616                         }
617                 } else if (!g_strcmp0(key, "session_id")) {
618                         g_variant_get(var, "u", &session_id);
619                 } else if (!g_strcmp0(key, "service_mac")) {
620                         if (asp_dbus_unpack_ay(service_mac, var, MAC_LEN) < 0) {
621                                 g_variant_iter_free(iter);
622                                 return;
623                         }
624
625                 } else if (!g_strcmp0(key, "assigned_ip_address")) {
626                         g_variant_get(var, "&s", &peer_ip);
627                 } else {
628                         ;/* Do Nothing */
629                 }
630         }
631
632         if (peer_ip == NULL) {
633                 ASP_LOGE("Invalid peer IP address");
634                 g_variant_iter_free(iter);
635                 return;
636         }
637
638         if (asp_tech_p2p_ops.ip_assigned_cb) {
639                 asp_tech_p2p_ops.ip_assigned_cb(0,
640                                 session_mac, session_id, service_mac, peer_ip,
641                                 strlen(peer_ip), asp_tech_p2p_ops.ip_assigned_cb_user_data);
642         }
643
644         g_variant_iter_free(iter);
645
646         __ASP_LOG_FUNC_EXIT__;
647         return;
648 }
649
650 gint32 asp_tech_p2p_advertise(asp_service_advertise_s *service, gint32 replace)
651 {
652         __ASP_LOG_FUNC_ENTER__;
653         GVariantBuilder *builder = NULL;
654         GVariant *params = NULL;
655         GError *error = NULL;
656         GVariant *reply = NULL;
657         gint32 result = 0;
658
659         if (!service || !g_wfd_gdbus_conn) {
660                 ASP_LOGE("Invalid parameter!");
661                 __ASP_LOG_FUNC_EXIT__;
662                 return -1;
663         }
664
665         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
666         g_variant_builder_add(builder, "{sv}", "adv_id", g_variant_new("u", service->adv_id));
667         g_variant_builder_add(builder, "{sv}", "discovery_tech", g_variant_new("i", service->discovery_tech));
668         g_variant_builder_add(builder, "{sv}", "preferred_connection", g_variant_new("y", service->preferred_connection));
669         g_variant_builder_add(builder, "{sv}", "auto_accept", g_variant_new("i", service->auto_accept));
670         g_variant_builder_add(builder, "{sv}", "status", g_variant_new("y", service->status));
671         g_variant_builder_add(builder, "{sv}", "role", g_variant_new("y", service->role));
672         g_variant_builder_add(builder, "{sv}", "replace", g_variant_new("i", replace));
673         g_variant_builder_add(builder, "{sv}", "config_method", g_variant_new("u", service->config_method));
674
675         if (service->instance_name)
676                 g_variant_builder_add(builder, "{sv}", "instance_name", g_variant_new("s", service->instance_name));
677         if (service->service_type)
678                 g_variant_builder_add(builder, "{sv}", "service_type", g_variant_new("s", service->service_type));
679         if (service->service_info_map != NULL)
680                 g_variant_builder_add(builder, "{sv}", "service_info",
681                                 __g_hash_table_to_g_variant(service->service_info_map));
682         if (service->rsp_info)
683                 g_variant_builder_add(builder, "{sv}", "rsp_info", g_variant_new("s", service->rsp_info));
684         params = g_variant_new("(a{sv})", builder);
685         g_variant_builder_unref(builder);
686
687         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_ASP_INTERFACE,
688                                                   "AdvertiseService", params, &error);
689         if (error != NULL) {
690                 result = __net_wifidirect_gerror_to_enum(error);
691                 g_error_free(error);
692                 __ASP_LOG_FUNC_EXIT__;
693                 return result;
694         }
695
696         g_variant_get(reply, "(i)", &result);
697         g_variant_unref(reply);
698
699         ASP_LOGD("%s() return : [%d]", __func__, result);
700
701         __ASP_LOG_FUNC_EXIT__;
702         return result;
703 }
704
705 gint32 asp_tech_p2p_cancel_advertise(asp_service_advertise_s *service)
706 {
707         __ASP_LOG_FUNC_ENTER__;
708         GVariant *params = NULL;
709         GError *error = NULL;
710         GVariant *reply = NULL;
711         gint32 result = 0;
712
713         if (!service || !g_wfd_gdbus_conn) {
714                 ASP_LOGE("Invalid parameter!");
715                 __ASP_LOG_FUNC_EXIT__;
716                 return -1;
717         }
718
719         params = g_variant_new("(u)", service->adv_id);
720         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_ASP_INTERFACE,
721                                                   "CancelAdvertiseService", params, &error);
722         if (error != NULL) {
723                 result = __net_wifidirect_gerror_to_enum(error);
724                 g_error_free(error);
725                 __ASP_LOG_FUNC_EXIT__;
726                 return result;
727         }
728
729         g_variant_get(reply, "(i)", &result);
730         g_variant_unref(reply);
731
732         ASP_LOGD("%s() return : [%d]", __func__, result);
733
734         __ASP_LOG_FUNC_EXIT__;
735         return result;
736 }
737
738 gint32 asp_tech_p2p_seek(asp_service_seek_s *service)
739 {
740         __ASP_LOG_FUNC_ENTER__;
741         GVariantBuilder *builder = NULL;
742         GVariant *params = NULL;
743         GError *error = NULL;
744         GVariant *reply = NULL;
745         gint32 result = 0;
746
747         if (!service || !g_wfd_gdbus_conn) {
748                 ASP_LOGE("Invalid parameter!");
749                 __ASP_LOG_FUNC_EXIT__;
750                 return -1;
751         }
752
753
754         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
755         g_variant_builder_add(builder, "{sv}", "discovery_tech", g_variant_new("i", service->discovery_tech));
756         g_variant_builder_add(builder, "{sv}", "preferred_connection", g_variant_new("y", service->preferred_connection));
757         g_variant_builder_add(builder, "{sv}", "search_id", g_variant_new("t", service->search_id));
758         g_variant_builder_add(builder, "{sv}", "service_type", g_variant_new("s", service->service_type));
759         if (service->service_info_map != NULL)
760                 g_variant_builder_add(builder, "{sv}", "service_info", __g_hash_keys_to_g_variant(service->service_info_map));
761         params = g_variant_new("(a{sv})", builder);
762         g_variant_builder_unref(builder);
763         ASP_LOGI("instance name (%s)", service->instance_name);
764
765         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_ASP_INTERFACE,
766                                                   "SeekService", params, &error);
767         if (error != NULL) {
768                 result = __net_wifidirect_gerror_to_enum(error);
769                 g_error_free(error);
770                 __ASP_LOG_FUNC_EXIT__;
771                 return result;
772         }
773
774         g_variant_get(reply, "(i)", &result);
775         g_variant_unref(reply);
776
777         ASP_LOGD("%s() return : [%d]", __func__, result);
778
779         __ASP_LOG_FUNC_EXIT__;
780         return result;
781 }
782
783 gint32 asp_tech_p2p_cancel_seek(asp_service_seek_s *service)
784 {
785         __ASP_LOG_FUNC_ENTER__;
786         GVariant *params = NULL;
787         GError *error = NULL;
788         GVariant *reply = NULL;
789         gint32 result = 0;
790
791         if (!service || !g_wfd_gdbus_conn) {
792                 ASP_LOGE("Invalid parameter!");
793                 __ASP_LOG_FUNC_EXIT__;
794                 return -1;
795         }
796
797         params = g_variant_new("(t)", service->search_id);
798         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_ASP_INTERFACE,
799                                                   "CancelSeekService", params, &error);
800         if (error != NULL) {
801                 result = __net_wifidirect_gerror_to_enum(error);
802                 g_error_free(error);
803                 __ASP_LOG_FUNC_EXIT__;
804                 return result;
805         }
806
807         g_variant_get(reply, "(i)", &result);
808         g_variant_unref(reply);
809
810         ASP_LOGD("%s() return : [%d]", __func__, result);
811
812         __ASP_LOG_FUNC_EXIT__;
813         return result;
814 }
815
816 gint32 asp_tech_p2p_init()
817 {
818         __ASP_LOG_FUNC_ENTER__;
819         GError* error = NULL;
820         GVariant *reply = NULL;
821         g_wfd_gdbus_conn = NULL;
822         asp_s *asp = NULL;
823         const gchar *str = NULL;
824         gint32 result = 0;
825
826         asp = asp_get_manager();
827         if (asp == NULL) {
828                 ASP_LOGE("Failed to get asp");
829                 __ASP_LOG_FUNC_EXIT__;
830                 return -1;
831         }
832
833         g_wfd_gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
834         if (g_wfd_gdbus_conn == NULL) {
835                 ASP_LOGE("Failed to get connection, Error[%s]", error->message);
836                 g_error_free(error);
837                 __ASP_LOG_FUNC_EXIT__;
838                 return -1;
839         }
840
841         /* subscribe signal handler */
842         g_wfd_signal_id = g_dbus_connection_signal_subscribe(g_wfd_gdbus_conn,
843                         WFD_MANAGER_SERVICE, /* bus name */
844                         NULL, /* interface */
845                         NULL, /* member */
846                         WFD_MANAGER_PATH, /* object_path */
847                         NULL, /* arg0 */
848                         G_DBUS_SIGNAL_FLAGS_NONE,
849                         __asp_tech_p2p_dbus_signal_cb,
850                         NULL,
851                         NULL);
852         ASP_LOGI("Subscribed dbus signals [%d]", g_wfd_signal_id);
853
854         /* Get local P2P device address*/
855         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_CONFIG_INTERFACE,
856                                                   "GetMacAddress", NULL, &error);
857         if (error != NULL) {
858                 result = __net_wifidirect_gerror_to_enum(error);
859                 g_error_free(error);
860                 __ASP_LOG_FUNC_EXIT__;
861                 return result;
862         }
863         g_variant_get(reply, "(i&s)", &result, &str);
864         g_strlcpy(asp->p2p_local_address_str, str, MACSTR_LEN + 1);
865         macaddr_atoe(str, asp->p2p_local_address);
866
867         g_variant_unref(reply);
868
869         /* Get local P2P Device Name*/
870         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_CONFIG_INTERFACE,
871                                                   "GetDeviceName", NULL, &error);
872         if (error != NULL) {
873                 result = __net_wifidirect_gerror_to_enum(error);
874                 g_error_free(error);
875                 __ASP_LOG_FUNC_EXIT__;
876                 return result;
877         }
878         g_variant_get(reply, "(i&s)", &result, &str);
879         g_strlcpy(asp->p2p_device_name, str, DEVICE_NAME_LEN + 1);
880
881         g_variant_unref(reply);
882
883         __ASP_LOG_FUNC_EXIT__;
884         return result;
885 }
886
887 gint32 asp_tech_p2p_deinit()
888 {
889         __ASP_LOG_FUNC_ENTER__;
890         gint32 result = 0;
891
892         if (g_wfd_gdbus_conn == NULL)
893                 return -1;
894
895         /* unsubscribe signal handler */
896         g_dbus_connection_signal_unsubscribe(g_wfd_gdbus_conn, g_wfd_signal_id);
897         g_wfd_signal_id = 0;
898
899         /* unref gdbus connection */
900         g_object_unref(g_wfd_gdbus_conn);
901         g_wfd_gdbus_conn = NULL;
902
903         __ASP_LOG_FUNC_EXIT__;
904         return result;
905 }
906
907 gint32 asp_tech_p2p_get_peer_role(const guint8 *mac_addr, gint32 *is_connected, gint32 *role)
908 {
909         __ASP_LOG_FUNC_ENTER__;
910         GVariant *params = NULL;
911         GVariant *reply = NULL;
912         GError* error = NULL;
913
914         GVariantIter *iter_peer = NULL;
915         GVariant *var = NULL;
916         gchar *key = NULL;
917         gchar mac_address[18] = {0,};
918         gboolean is_group_client = FALSE;
919         gboolean is_group_owner = FALSE;
920         gboolean is_in_group = FALSE;
921         gint32 result = 0;
922
923         /* Get P2P peer info*/
924         g_snprintf(mac_address, MACSTR_LEN + 1, MACSTR, MAC2STR(mac_addr));
925         params = g_variant_new("(s)", mac_address);
926         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_MANAGE_INTERFACE,
927                                                   "GetPeerInfo", params, &error);
928         if (error != NULL) {
929                 result = __net_wifidirect_gerror_to_enum(error);
930                 g_error_free(error);
931                 __ASP_LOG_FUNC_EXIT__;
932                 return result;
933         }
934
935         g_variant_get(reply, "(ia{sv})", &result, &iter_peer);
936         if (result != 0) {
937                 __ASP_LOG_FUNC_EXIT__;
938                 return -1;
939         }
940
941         while (g_variant_iter_loop(iter_peer, "{sv}", &key, &var)) {
942                 if (!g_strcmp0(key, "IsConnected"))
943                         is_group_client = g_variant_get_boolean(var);
944
945                 else if (!g_strcmp0(key, "IsGroupOwner"))
946                         is_group_owner = g_variant_get_boolean(var);
947
948                 else if (!g_strcmp0(key, "IsInGroup"))
949                         is_in_group = g_variant_get_boolean(var);
950
951                 else
952                         ;/* Do Nothing */
953         }
954
955         g_variant_iter_free(iter_peer);
956         g_variant_unref(reply);
957         if (is_group_owner)
958                 *role = ASP_TECH_P2P_ROLE_GO;
959         if (is_group_client)
960                 *role = ASP_TECH_P2P_ROLE_GC;
961
962         if (is_in_group)
963                 *is_connected = is_in_group;
964
965         __ASP_LOG_FUNC_EXIT__;
966         return result;
967 }
968
969 gint32 __asp_tech_p2p_send_prov(asp_tech_session_request_params_s *params)
970 {
971         GVariantBuilder *builder = NULL;
972         GVariant *variant_params = NULL;
973         GVariant *reply = NULL;
974         GError* error = NULL;
975         gchar mac_str[MACSTR_LEN + 1] = {0, };
976         gint32 result = 0;
977
978         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
979
980         g_snprintf(mac_str, MACSTR_LEN + 1, MACSTR, MAC2STR(params->service_mac));
981         g_variant_builder_add(builder, "{sv}", "service_mac", g_variant_new("s", mac_str));
982         g_variant_builder_add(builder, "{sv}", "adv_id", g_variant_new("u", params->advertisement_id));
983
984         g_snprintf(mac_str, MACSTR_LEN + 1, MACSTR, MAC2STR(params->session_mac));
985         g_variant_builder_add(builder, "{sv}", "session_mac", g_variant_new("s", mac_str));
986         g_variant_builder_add(builder, "{sv}", "session_id", g_variant_new("u", params->session_id));
987         g_variant_builder_add(builder, "{sv}", "role", g_variant_new("y", params->network_role));
988         g_variant_builder_add(builder, "{sv}", "config_method", g_variant_new("u", params->network_config));
989         if (params->session_information)
990                 g_variant_builder_add(builder, "{sv}", "session _info", g_variant_new("s", params->session_information));
991
992         variant_params = g_variant_new("(a{sv})", builder);
993         g_variant_builder_unref(builder);
994
995         /* Connect ASP session via P2P group */
996         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_ASP_INTERFACE,
997                                                   "ConnectSession", variant_params, &error);
998         if (error != NULL) {
999                 result = __net_wifidirect_gerror_to_enum(error);
1000                 g_error_free(error);
1001                 __ASP_LOG_FUNC_EXIT__;
1002                 return result;
1003         }
1004
1005         g_variant_get(reply, "(i)", &result);
1006         g_variant_unref(reply);
1007
1008         __ASP_LOG_FUNC_EXIT__;
1009         return result;
1010 }
1011
1012 gint32 asp_tech_p2p_connect_session(asp_tech_session_request_params_s *params)
1013 {
1014         __ASP_LOG_FUNC_ENTER__;
1015         gint32 is_connected = 0;
1016         gint32 role = ASP_TECH_P2P_ROLE_NEW;
1017         gint32 result = 0;
1018
1019         result = asp_tech_p2p_get_peer_role(params->service_mac, &is_connected, &role);
1020         if (result < 0) {
1021                 ASP_LOGE("get peer role failed");
1022                         __ASP_LOG_FUNC_EXIT__;
1023                         return ASP_ERROR_OPERATION_FAILED;
1024         }
1025
1026         if (params->network_role != ASP_TECH_P2P_ROLE_NEW &&
1027                         params->network_role == role) {
1028                 ASP_LOGE("Device can't be requested role");
1029                         __ASP_LOG_FUNC_EXIT__;
1030                         return ASP_ERROR_NETWORK_ROLE_REJECTED;
1031         }
1032         result = __asp_tech_p2p_send_prov(params);
1033
1034         __ASP_LOG_FUNC_EXIT__;
1035         return result;
1036 }
1037
1038 gint32 asp_tech_p2p_confirm_session(const guint8 *session_mac, gint32 session_id, gint32 confirm, guint32 pin)
1039 {
1040         __ASP_LOG_FUNC_ENTER__;
1041         GVariantBuilder *builder = NULL;
1042         GVariant *params = NULL;
1043         GVariant *reply = NULL;
1044         GError* error = NULL;
1045         guint8 *service_mac = NULL;
1046         guint32 adv_id = 0;
1047         gchar mac_str[MACSTR_LEN + 1] = {0, };
1048         gchar pin_str[PINSTR_LEN + 1] = {0, };
1049         gint32 result = 0;
1050
1051         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1052
1053         g_snprintf(mac_str, MACSTR_LEN + 1, MACSTR, MAC2STR(session_mac));
1054         g_variant_builder_add(builder, "{sv}", "session_mac", g_variant_new("s", mac_str));
1055         g_variant_builder_add(builder, "{sv}", "session_id", g_variant_new("u", session_id));
1056         g_variant_builder_add(builder, "{sv}", "confirm", g_variant_new("i", confirm));
1057         if (pin != 0) {
1058                 g_snprintf(pin_str, PINSTR_LEN + 1, "%u", pin);
1059                 g_variant_builder_add(builder, "{sv}", "pin", g_variant_new("s", pin_str));
1060         }
1061         if (asp_session_get_advertisement_mac(session_mac, session_id, &service_mac)) {
1062                 g_snprintf(mac_str, MACSTR_LEN + 1, MACSTR, MAC2STR(service_mac));
1063                 g_variant_builder_add(builder, "{sv}", "service_mac", g_variant_new("s", mac_str));
1064         }
1065         if (asp_session_get_advertisement_id(session_mac, session_id, &adv_id))
1066                 g_variant_builder_add(builder, "{sv}", "adv_id", g_variant_new("u", adv_id));
1067
1068         params = g_variant_new("(a{sv})", builder);
1069         g_variant_builder_unref(builder);
1070
1071         /* Confirm session requested via P2P */
1072         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_ASP_INTERFACE,
1073                                                   "ConfirmSession", params, &error);
1074         if (error != NULL) {
1075                 result = __net_wifidirect_gerror_to_enum(error);
1076                 g_error_free(error);
1077                 __ASP_LOG_FUNC_EXIT__;
1078                 return result;
1079         }
1080
1081         g_variant_get(reply, "(i)", &result);
1082         g_variant_unref(reply);
1083
1084         __ASP_LOG_FUNC_EXIT__;
1085         return result;
1086 }
1087
1088 gint32 asp_tech_p2p_destroy_connection(const guint8 *peer_id, gint32 peer_id_length)
1089 {
1090         __ASP_LOG_FUNC_ENTER__;
1091         GVariant *reply = NULL;
1092         GError* error = NULL;
1093         gchar mac_str[MACSTR_LEN + 1] = {0, };
1094         gint32 result = 0;
1095
1096         g_snprintf(mac_str, MACSTR_LEN + 1, MACSTR, MAC2STR(peer_id));
1097         /* Destroy ASP P2P Group */
1098         reply = asp_tech_p2p_dbus_method_call_sync(WFD_MANAGER_GROUP_INTERFACE,
1099                                                   "DestroyGroup", NULL, &error);
1100         if (error != NULL) {
1101                 result = __net_wifidirect_gerror_to_enum(error);
1102                 g_error_free(error);
1103                 __ASP_LOG_FUNC_EXIT__;
1104                 return result;
1105         }
1106
1107         g_variant_get(reply, "(i)", &result);
1108         g_variant_unref(reply);
1109
1110         __ASP_LOG_FUNC_EXIT__;
1111         return result;
1112 }
1113
1114 gint32 asp_tech_p2p_is_peer_connected(const guint8 *peer_id, gint32 peer_id_length, gint32 *is_connected)
1115 {
1116         __ASP_LOG_FUNC_ENTER__;
1117         gint32 role = 0;
1118         gint32 result = 0;
1119
1120         result = asp_tech_p2p_get_peer_role(peer_id, is_connected, &role);
1121
1122         __ASP_LOG_FUNC_EXIT__;
1123         return result;
1124 }
1125
1126 asp_tech_ops_s asp_tech_p2p_ops = {
1127                 .init = asp_tech_p2p_init,
1128                 .deinit = asp_tech_p2p_deinit,
1129                 .advertise = asp_tech_p2p_advertise,
1130                 .cancel_advertise = asp_tech_p2p_cancel_advertise,
1131                 .seek = asp_tech_p2p_seek,
1132                 .cancel_seek = asp_tech_p2p_cancel_seek,
1133                 .connect_session = asp_tech_p2p_connect_session,
1134                 .confirm_session = asp_tech_p2p_confirm_session,
1135                 .destroy_connection = asp_tech_p2p_destroy_connection,
1136                 .is_peer_connected = asp_tech_p2p_is_peer_connected,
1137                 .session_request_cb = NULL,
1138                 .session_request_cb_user_data = NULL,
1139                 .session_config_request_cb = NULL,
1140                 .connect_status_cb = NULL,
1141                 .connect_status_cb_user_data = NULL,
1142                 .ip_assigned_cb = NULL,
1143                 .ip_assigned_cb_user_data = NULL,
1144 };