PHDC P2P Handling
[platform/core/connectivity/nfc-manager-neard.git] / daemon / net_nfc_server_phdc.c
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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 #include "net_nfc_debug_internal.h"
18 #include "net_nfc_util_internal.h"
19 #include "net_nfc_util_gdbus_internal.h"
20 #include "net_nfc_server_controller.h"
21 #include "net_nfc_gdbus.h"
22 #include "net_nfc_server_common.h"
23 #include "net_nfc_server_tag.h"
24 #include "net_nfc_server_context.h"
25 #include "net_nfc_server_process_phdc.h"
26 #include "net_nfc_server_phdc.h"
27 #include "net_nfc_server_llcp.h"
28
29 typedef struct _PhdcSendData PhdcSendData;
30
31 struct _PhdcSendData
32 {
33         NetNfcGDbusPhdc *phdc;
34         GDBusMethodInvocation *invocation;
35         guint32 phdc_handle;
36         data_s data;
37 };
38
39 static NetNfcGDbusPhdc *phdc_skeleton = NULL;
40
41
42 static gboolean _phdc_send_request_cb_(net_nfc_phdc_handle_h handle,
43                 net_nfc_error_e result, net_nfc_server_phdc_indication_type indication,
44                 gpointer *user_data)
45 {
46
47         NFC_DBG("phdc_send_request_cb_result [%d]",result);
48
49         GVariant *parameter = (GVariant *)user_data;
50
51         g_assert(parameter != NULL);
52
53         NetNfcGDbusPhdc *object;
54         GDBusMethodInvocation *invocation;
55         net_nfc_phdc_handle_h phdc_handle;
56         GVariant *phdc_data ;
57
58         g_variant_get(parameter,
59                 "(uuu@a(y))",
60                 (guint *)&object,
61                 (guint *)&invocation,
62                 (guint *)&phdc_handle,
63                 (guint *)&phdc_data);
64
65         net_nfc_gdbus_phdc_complete_send(object, invocation, (gint)result);
66
67         g_variant_unref(phdc_data);
68         g_object_unref(invocation);
69         g_object_unref(object);
70         g_variant_unref(parameter);
71
72         result = NET_NFC_OK;
73         return result;
74
75 }
76
77 static void phdc_send_data_thread_func(gpointer user_data)
78 {
79         NetNfcGDbusPhdc *object;
80         GDBusMethodInvocation *invocation;
81         net_nfc_error_e result;
82         net_nfc_phdc_handle_h handle = NULL;
83         GVariant *phdc_data;
84         data_s data = { NULL, };
85
86         if (NULL == user_data)
87         {
88                 NFC_ERR("cannot get PHDC client data");
89                 return;
90         }
91
92         NFC_DBG(">>> phdc_send_data_thread_func");
93
94         g_variant_get((GVariant *)user_data,
95                 "(uuu@a(y))",
96                 (guint *)&object,
97                 (guint *)&invocation,
98                 (guint *)&handle,
99                 &phdc_data);
100
101         g_assert(object != NULL);
102         g_assert(invocation != NULL);
103
104         net_nfc_util_gdbus_variant_to_data_s(phdc_data, &data);
105
106         result = net_nfc_server_phdc_agent_request(handle, &data,
107                         _phdc_send_request_cb_, user_data);
108
109         if (result != NET_NFC_OK)
110         {
111                 net_nfc_gdbus_phdc_complete_send(object, invocation, (gint)result);
112
113                 g_object_unref(invocation);
114                 g_object_unref(object);
115                 g_variant_unref(user_data);
116         }
117
118         g_variant_unref(phdc_data);
119 }
120
121 static gboolean phdc_handle_send(NetNfcGDbusPhdc *phdc,
122         GDBusMethodInvocation *invocation, //object for handling remote calls,provides a way to asynly return data
123         guint handle,
124         GVariant* user_data,
125         GVariant *smack_privilege)
126 {
127         bool ret;
128         gboolean result;
129         GVariant *parameter = NULL;
130
131         NFC_INFO(">>> REQUEST from [%s]",g_dbus_method_invocation_get_sender(invocation));
132
133         /* check privilege and update client context */
134         ret = net_nfc_server_gdbus_check_privilege(invocation, smack_privilege,
135                         "nfc-manager::p2p", "w");
136
137         if(FALSE == ret)
138         {
139                 NFC_ERR("permission denied, and finished request");
140                 result = NET_NFC_SECURITY_FAIL;
141                 goto ERROR;
142         }
143
144         parameter = g_variant_new("(uuu@a(y))",
145                 GPOINTER_TO_UINT(g_object_ref(phdc)),
146                 GPOINTER_TO_UINT(g_object_ref(invocation)),
147                 handle,
148                 user_data);
149
150         if (NULL == parameter)
151         {
152                 NFC_ERR("Memory allocation failed");
153                 result = NET_NFC_ALLOC_FAIL;
154
155                 goto ERROR;
156         }
157
158         result = net_nfc_server_controller_async_queue_push(phdc_send_data_thread_func, parameter);
159
160         if (FALSE == result)
161         {
162                 /* return error if queue was blocked */
163                 NFC_ERR("controller is processing important message..");
164                 result = NET_NFC_BUSY;
165
166                 goto ERROR;
167
168         }
169
170         return TRUE;
171
172         ERROR :
173
174         if (parameter != NULL)
175         {
176                 g_object_unref(invocation);
177                 g_object_unref(phdc);
178                 g_variant_unref(parameter);
179         }
180
181         net_nfc_gdbus_phdc_complete_send(phdc, invocation, result);
182         return TRUE;
183 }
184
185 void net_nfc_server_phdc_data_received_indication(data_s *arg_data)
186 {
187         NFC_INFO("=net_nfc_server_phdc_transport_data_received_indication=");
188
189         GVariant *data;
190         data = net_nfc_util_gdbus_data_to_variant(arg_data);
191
192         if (NULL == phdc_skeleton)
193         {
194                 NFC_ERR("phdc_skeleton is not initialized");
195                 return;
196         }
197
198         net_nfc_gdbus_phdc_emit_phdc_received(phdc_skeleton, data);
199 }
200
201 static void _emit_phdc_event_signal(GVariant *parameter,
202                 net_nfc_phdc_handle_h handle, net_nfc_error_e result, uint32_t type)
203 {
204         gboolean ret;
205         char *client_id = NULL;
206         void *user_data = NULL;
207         GError *error = NULL;
208         GDBusConnection *connection;
209
210         g_variant_get(parameter, "(usu)", (guint *)&connection, &client_id,
211                         (guint *)&user_data);
212
213         ret = g_dbus_connection_emit_signal(
214                         connection,
215                         client_id,
216                         "/org/tizen/NetNfcService/Phdc",
217                         "org.tizen.NetNfcService.Phdc",
218                         "PhdcEvent",
219                         g_variant_new("(iuu)", (gint)result, type,
220                                 GPOINTER_TO_UINT(user_data)), &error);
221
222         if (FALSE == ret)
223         {
224                 if (error != NULL && error->message != NULL)
225                         NFC_ERR("g_dbus_connection_emit_signal failed : %s", error->message);
226                 else
227                         NFC_ERR("g_dbus_connection_emit_signal failed");
228         }
229
230         g_free(client_id);
231 }
232
233 static void _server_phdc_agent_cb_(net_nfc_phdc_handle_h handle,
234                 net_nfc_error_e result, net_nfc_server_phdc_indication_type indication, data_s *data)
235 {
236         if(NET_NFC_OK != result)
237         {
238                 net_nfc_server_phdc_transport_disconnect_indication();
239                 return;
240         }
241
242         RET_IF(NULL == handle);
243
244         NFC_DBG(" handle [%p], result[%d]", handle, result);
245
246         if( NET_NFC_PHDC_TARGET_CONNECTED == indication)
247                 net_nfc_server_phdc_transport_connect_indication(handle);
248         else if(NET_NFC_PHDC_DATA_RECEIVED == indication)
249                 net_nfc_server_phdc_data_received_indication(data);
250
251         return;
252 }
253
254
255 static void _phdc_agent_activate_cb(int event, net_nfc_target_handle_s *handle,
256                 uint32_t sap, const char *san, void *user_param)
257 {
258         net_nfc_error_e result = NET_NFC_OK;
259         GVariant *parameter = (GVariant *)user_param;
260         char *client_id = NULL;
261         void *user_data = NULL;
262         GVariant *param = NULL;
263         GDBusConnection *connection = NULL;
264
265         NFC_DBG("event [%d], handle [%p], sap [%d], san [%s]", event, handle, sap, san);
266
267         if (NET_NFC_LLCP_START == event)
268         {
269                 g_variant_get(parameter, "(usu)", (guint *)&connection, &client_id, (guint *)&user_data);
270
271                 param = g_variant_new("(usu)", GPOINTER_TO_UINT(g_object_ref(connection)),client_id,
272                                 GPOINTER_TO_UINT(user_data));
273
274                 g_free(client_id);
275
276                 /* start phdc agent service*/
277                 result = net_nfc_server_phdc_agent_start(handle, (char *)san, sap,
278                                 _server_phdc_agent_cb_, param);
279
280                 if (NET_NFC_OK == result)
281                 {
282                         _emit_phdc_event_signal(parameter, handle, result, event);
283                 }
284                 else
285                 {
286                         NFC_ERR("net_nfc_server_phdc_manager_start failed, [%d]", result);
287                         g_variant_unref(param);
288                 }
289         }
290         else
291         {
292                 _emit_phdc_event_signal(parameter, handle, result, NET_NFC_LLCP_UNREGISTERED);
293                 /* unregister server */
294                 g_variant_unref(parameter);
295         }
296
297 }
298
299 static void _server_phdc_manager_cb_(net_nfc_phdc_handle_h handle,
300                 net_nfc_error_e result, net_nfc_server_phdc_indication_type indication, data_s *data)
301 {
302
303         if(NET_NFC_OK != result)
304         {
305                 net_nfc_server_phdc_transport_disconnect_indication();
306                 return;
307         }
308
309         RET_IF(NULL == handle);
310
311         NFC_DBG("result [%d], data [%p]", result, data);
312
313         if( NET_NFC_PHDC_TARGET_CONNECTED == indication)
314                 net_nfc_server_phdc_transport_connect_indication(handle);
315         else if(NET_NFC_PHDC_DATA_RECEIVED == indication)
316                 net_nfc_server_phdc_data_received_indication(data);
317
318         return ;
319 }
320
321
322 static void _phdc_manager_activate_cb(int event, net_nfc_target_handle_s *handle,
323                 uint32_t sap, const char *san, void *user_param)
324 {
325         net_nfc_error_e result = NET_NFC_OK;
326         GVariant *parameter = (GVariant *)user_param;
327         char *client_id = NULL;
328         void *user_data = NULL;
329         GVariant *param = NULL;
330         GDBusConnection *connection = NULL;
331
332         NFC_DBG("event [%d], handle [%p], sap [%d], san [%s]", event, handle, sap, san);
333
334         if (NET_NFC_LLCP_START == event)
335         {
336                 g_variant_get(parameter, "(usu)", (guint *)&connection, &client_id, (guint *)&user_data);
337
338                 param = g_variant_new("(usu)", GPOINTER_TO_UINT(g_object_ref(connection)),client_id,
339                                 GPOINTER_TO_UINT(user_data));
340
341                 g_free(client_id);
342
343                 /* start phdc manager service*/
344                 result = net_nfc_server_phdc_manager_start(handle, (char *)san, sap,
345                                 _server_phdc_manager_cb_, param);
346
347                 if (NET_NFC_OK == result)
348                 {
349                         _emit_phdc_event_signal(parameter, handle, result, event);
350                 }
351                 else
352                 {
353                         NFC_ERR("net_nfc_server_phdc_manager_start failed, [%d]", result);
354                         g_variant_unref(param);
355                 }
356         }
357         else
358         {
359                 _emit_phdc_event_signal(parameter, handle, result, NET_NFC_LLCP_UNREGISTERED);
360                 /* unregister server */
361                 g_variant_unref(parameter);
362         }
363
364 }
365
366 static void phdc_register_server_thread_func(gpointer user_data)
367 {
368         gchar *arg_san = NULL;
369         guint arg_role;
370         guint arg_sap;
371         guint arg_user_data;
372         net_nfc_error_e result = NET_NFC_OK;
373         NetNfcGDbusPhdc *object = NULL;
374         g_assert(user_data != NULL);
375         GVariant *parameter = NULL;
376         GDBusConnection *connection = NULL;
377         GDBusMethodInvocation *invocation = NULL;
378
379         g_variant_get((GVariant *)user_data, "(uuusu)", (guint *)&object, (guint *)&invocation,
380                         &arg_role, &arg_san, &arg_user_data);
381
382         g_assert(object != NULL);
383         g_assert(invocation != NULL);
384
385         connection = g_dbus_method_invocation_get_connection(invocation);
386
387         parameter = g_variant_new("(usu)", GPOINTER_TO_UINT(g_object_ref(connection)),
388                         g_dbus_method_invocation_get_sender(invocation), arg_user_data);
389
390         if (parameter != NULL)
391         {
392                 if(!strcmp(arg_san,PHDC_SAN))
393                 {
394                         arg_san = PHDC_SAN;
395                         arg_sap = PHDC_SAP;
396                 }
397                 else if (!strcmp(arg_san,PHDS_SAN))
398                 {
399                         arg_san = PHDS_SAN;
400                         arg_sap = PHDS_SAP;
401                 }
402                 else
403                 {
404                         // anything else, as of now,defaulting to PHDC default server
405                         arg_san = PHDC_SAN;
406                         arg_sap = PHDC_SAP;
407                 }
408
409                 if(NET_NFC_PHDC_MANAGER == arg_role)
410                 {
411                         result = net_nfc_server_llcp_register_service(
412                                         g_dbus_method_invocation_get_sender(invocation), arg_sap,
413                                         arg_san, _phdc_manager_activate_cb,     parameter);
414                 }
415                 else if(NET_NFC_PHDC_AGENT == arg_role)
416                 {
417                         result = net_nfc_server_llcp_register_service(
418                                         g_dbus_method_invocation_get_sender(invocation), arg_sap,
419                                         arg_san, _phdc_agent_activate_cb,       parameter);
420                 }
421
422                 if (result != NET_NFC_OK)
423                 {
424                         NFC_ERR("net_nfc_service_llcp_register_service failed, [%d]", result);
425                         g_object_unref(connection);
426                         g_variant_unref(parameter);
427                 }
428         }
429         else
430         {
431                 result = NET_NFC_ALLOC_FAIL;
432                 g_object_unref(connection);
433         }
434
435         net_nfc_gdbus_phdc_complete_register_role(object, invocation, result);
436
437
438         g_variant_unref(user_data);
439
440
441 }
442
443 static gboolean phdc_handle_register(
444                 NetNfcGDbusPhdc *object,
445                 GDBusMethodInvocation *invocation,
446                 guint arg_role,
447                 const gchar *arg_san,
448                 guint arg_user_data,
449                 GVariant *arg_privilege)
450 {
451         bool ret;
452         gboolean result;
453         GVariant *parameter = NULL;
454
455         NFC_INFO(">>> REQUEST from [%s]", g_dbus_method_invocation_get_sender(invocation));
456
457         /* check privilege and update client context */
458         ret = net_nfc_server_gdbus_check_privilege(invocation, arg_privilege,
459                         "nfc-manager::p2p", "rw");
460         if (FALSE == ret)
461         {
462                 NFC_ERR("permission denied, and finished request");
463                 result = NET_NFC_SECURITY_FAIL;
464                 goto ERROR;
465         }
466
467         parameter = g_variant_new("(uuusu)", GPOINTER_TO_UINT(g_object_ref(object)),
468                         GPOINTER_TO_UINT(g_object_ref(invocation)), arg_role, arg_san, arg_user_data);
469
470         if (parameter == NULL)
471         {
472                 NFC_ERR("Memory allocation failed");
473                 result = NET_NFC_ALLOC_FAIL;
474                 goto ERROR;
475         }
476         if(net_nfc_server_controller_async_queue_push(
477                         phdc_register_server_thread_func, parameter) == FALSE)
478         {
479                 NFC_ERR("controller is processing important message.");
480                 result = NET_NFC_ALLOC_FAIL;
481                 goto ERROR;
482         }
483
484         return TRUE;
485
486         ERROR :
487         if (parameter != NULL)
488         {
489                 g_object_unref(invocation);
490                 g_object_unref(object);
491                 g_variant_unref(parameter);
492         }
493
494         net_nfc_gdbus_phdc_complete_register_role(object,
495                 invocation,
496                 result);
497
498         return TRUE;
499 }
500
501 static void phdc_unregister_server_thread_func(gpointer user_data)
502 {
503         guint arg_role;
504         guint arg_sap;
505         gchar *arg_san = NULL;
506         net_nfc_error_e result;
507         NetNfcGDbusSnep *object = NULL;
508         GDBusMethodInvocation *invocation = NULL;
509
510         g_assert(user_data != NULL);
511
512         g_variant_get((GVariant *)user_data, "(uuus)", (guint *)&object, (guint *)&invocation,
513                         &arg_role, &arg_san);
514
515         g_assert(object != NULL);
516         g_assert(invocation != NULL);
517
518         if(!strcmp(arg_san,PHDS_SAN))
519                 arg_sap = PHDS_SAP;
520         else
521                 arg_sap = PHDC_SAP;
522
523         result = net_nfc_server_llcp_unregister_service(
524                         g_dbus_method_invocation_get_sender(invocation), arg_sap, arg_san);
525
526         net_nfc_gdbus_snep_complete_server_unregister(object, invocation, result);
527
528         g_free(arg_san);
529
530         g_object_unref(invocation);
531         g_object_unref(object);
532
533         g_variant_unref(user_data);
534 }
535
536 static gboolean phdc_handle_unregister(
537                 NetNfcGDbusPhdc *object,
538                 GDBusMethodInvocation *invocation,
539                 guint arg_role,
540                 const gchar *arg_san,
541                 GVariant *arg_privilege)
542 {
543         bool ret;
544         gboolean result;
545         GVariant *parameter = NULL;
546
547         NFC_INFO(">>> REQUEST from [%s]", g_dbus_method_invocation_get_sender(invocation));
548
549         /* check privilege and update client context */
550         ret = net_nfc_server_gdbus_check_privilege(invocation, arg_privilege,
551                         "nfc-manager::p2p", "rw");
552
553         if (FALSE == ret)
554         {
555                 NFC_ERR("permission denied, and finished request");
556                 result = NET_NFC_SECURITY_FAIL;
557                 goto ERROR;
558         }
559
560         parameter = g_variant_new("(uuus)", GPOINTER_TO_UINT(g_object_ref(object)),
561                         GPOINTER_TO_UINT(g_object_ref(invocation)), arg_role, arg_san);
562
563         if (parameter == NULL)
564         {
565                 NFC_ERR("Memory allocation failed");
566                 result = NET_NFC_ALLOC_FAIL;
567                 goto ERROR;
568         }
569         if(net_nfc_server_controller_async_queue_push(
570                         phdc_unregister_server_thread_func, parameter) == FALSE)
571         {
572                 NFC_ERR("controller is processing important message.");
573                 result = NET_NFC_ALLOC_FAIL;
574                 goto ERROR;
575         }
576
577         return TRUE;
578
579         ERROR :
580         if (parameter != NULL)
581         {
582                         g_object_unref(invocation);
583                         g_object_unref(object);
584
585                         g_variant_unref(parameter);
586         }
587
588         net_nfc_gdbus_phdc_complete_register_role(object,
589                 invocation,
590                 result);
591
592         return TRUE;
593 }
594
595
596 gboolean net_nfc_server_phdc_init(GDBusConnection *connection)
597 {
598         gboolean result;
599         GError *error = NULL;
600
601         if (phdc_skeleton)
602                 net_nfc_server_phdc_deinit();
603
604         phdc_skeleton = net_nfc_gdbus_phdc_skeleton_new();
605
606         g_signal_connect(phdc_skeleton,"handle-send", G_CALLBACK(phdc_handle_send), NULL);
607
608         g_signal_connect(phdc_skeleton,"handle-register-role", G_CALLBACK(phdc_handle_register), NULL);
609
610         g_signal_connect(phdc_skeleton,"handle-unregister-role", G_CALLBACK(phdc_handle_unregister), NULL);
611
612         result = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(phdc_skeleton),
613                         connection, "/org/tizen/NetNfcService/Phdc", &error);
614
615         if (FALSE == result)
616         {
617                 g_error_free(error);
618                 net_nfc_server_phdc_deinit();
619         }
620
621         return result;
622 }
623
624 void net_nfc_server_phdc_deinit(void)
625 {
626         if (phdc_skeleton)
627         {
628                 g_object_unref(phdc_skeleton);
629                 phdc_skeleton = NULL;
630         }
631 }
632
633 void net_nfc_server_phdc_transport_disconnect_indication(void)
634 {
635         NFC_INFO("====== phdc target disconnected ======");
636
637         /* release target information */
638         net_nfc_server_free_target_info();
639
640         if (phdc_skeleton != NULL)
641                 net_nfc_gdbus_phdc_emit_phdc_disconnect(phdc_skeleton);
642 }
643
644
645 void net_nfc_server_phdc_transport_connect_indication(net_nfc_phdc_handle_h handle)
646 {
647         NFC_INFO("====== phdc target connected ======");
648
649         if (NULL == phdc_skeleton)
650         {
651                 NFC_ERR("phdc_skeleton is not initialized");
652                 return;
653         }
654
655         net_nfc_gdbus_phdc_emit_phdc_connect(phdc_skeleton, GPOINTER_TO_UINT(handle));
656 }
657
658 void net_nfc_server_phdc_data_sent(net_nfc_error_e result, gpointer user_data)
659 {
660         PhdcSendData *data = (PhdcSendData *)user_data;
661
662         g_assert(data != NULL);
663         g_assert(data->phdc != NULL);
664         g_assert(data->invocation != NULL);
665
666         net_nfc_gdbus_phdc_complete_send(data->phdc, data->invocation, (gint)result);
667
668         net_nfc_util_free_data(&data->data);
669
670         g_object_unref(data->invocation);
671         g_object_unref(data->phdc);
672
673         g_free(data);
674 }
675