Coding Rule check
[platform/core/convergence/d2d-conv-manager.git] / daemon / service_provider / RemoteAppControlServiceProvider.cpp
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 #ifdef __SUPPORTED_APP_CONTROL_SERVICE__
18
19 #include <bundle.h>
20 #include <bundle_internal.h>
21 #include <app_control_internal.h>
22 #include "RemoteAppControlServiceProvider.h"
23 #include "../ClientManager.h"
24 #include "../Util.h"
25 #include "../Server.h"
26 #if defined(_D2D_INTERNAL_ACL_)
27 #include "../access_control/ACLManager.h"
28
29 using namespace conv::acl_manager;
30 #else
31 #include <rdm_iface.h>
32 #endif
33
34 using namespace std;
35
36 struct app_control_cb_info_s {
37         int req_id;
38         iotcon_request_h request_handle;
39 };
40
41 struct response_cb_info_s {
42         int req_id;
43         conv::Request* requestObj;
44 };
45
46 static int get_req_id()
47 {
48         static int req_id = 0;
49
50         if (++req_id < 0) {
51                 req_id = 1;
52         }
53
54         return req_id;
55 }
56
57 static std::map<long long, app_control_cb_info_s> app_control_cb_map;
58 static std::map<int, response_cb_info_s> response_cb_map;
59 static std::map<std::string, guint> dbus_listener_info_map;
60
61 static void vconf_update_cb(keynode_t *node, void* user_data)
62 {
63         conv::RemoteAppControlServiceProvider* instance = static_cast<conv::RemoteAppControlServiceProvider*>(user_data);
64         IF_FAIL_VOID_TAG(instance, _E, "static_cast failed");
65
66         instance->handleVconfUpdate(node);
67 }
68
69 conv::RemoteAppControlServiceProvider::RemoteAppControlServiceProvider()
70 {
71         __type = CONV_SERVICE_TYPE_REMOTE_APP_CONTROL;
72         __resourceType = CONV_RESOURCE_TYPE_REMOTE_APP_CONTROL;
73         __uri = CONV_URI_REMOTE_APP_CONTROL;
74         iotcon_resource = NULL;
75
76         if (conv::util::isServiceActivated()) {
77                 __activationState = 1;
78         } else {
79                 __activationState = 0;
80         }
81
82         vconf_notify_key_changed(VCONFKEY_SETAPPL_D2D_CONVERGENCE_SERVICE, vconf_update_cb, this);
83 #if !defined(_D2D_INTERNAL_ACL_)
84         int error = rdm_init();
85         if (error != RDM_ERROR_SUCCESS)
86                 _E("rdm init error : %d", error);
87 #endif
88 }
89
90 conv::RemoteAppControlServiceProvider::~RemoteAppControlServiceProvider()
91 {
92         app_control_cb_map.clear();
93         response_cb_map.clear();
94         dbus_listener_info_map.clear();
95
96 #if !defined(_D2D_INTERNAL_ACL_)
97         int error = rdm_deinit();
98         if (error != RDM_ERROR_SUCCESS)
99                 _E("rdm deinit error : %d", error);
100 #endif
101 }
102
103 int conv::RemoteAppControlServiceProvider::handleVconfUpdate(keynode_t *node)
104 {
105         int current_state = vconf_keynode_get_int(node);
106
107         if (current_state > 0) {
108                 __activationState = 1;
109                 init();
110         } else {
111                 __activationState = 0;
112                 release();
113         }
114
115         return CONV_ERROR_NONE;
116 }
117
118 static int _send_response(iotcon_request_h request, iotcon_representation_h repr,
119                 iotcon_response_result_e result)
120 {
121         int ret;
122         iotcon_response_h response;
123
124         ret = iotcon_response_create(request, &response);
125         if (IOTCON_ERROR_NONE != ret) {
126                 _E("iotcon_response_create() Fail(%d)", ret);
127                 return CONV_ERROR_INVALID_OPERATION;
128         }
129
130         ret = iotcon_response_set_result(response, result);
131         if (IOTCON_ERROR_NONE != ret) {
132                 _E("iotcon_response_set_result() Fail(%d)", ret);
133                 iotcon_response_destroy(response);
134                 return CONV_ERROR_INVALID_OPERATION;
135         }
136
137         ret = iotcon_response_set_representation(response, repr);
138         if (IOTCON_ERROR_NONE != ret) {
139                 _E("iotcon_response_set_representation() Fail(%d)", ret);
140                 iotcon_response_destroy(response);
141                 return CONV_ERROR_INVALID_OPERATION;
142         }
143
144         /* send Representation to the client */
145         ret = iotcon_response_send(response);
146         if (IOTCON_ERROR_NONE != ret) {
147                 _E("iotcon_response_send() Fail(%d)", ret);
148                 iotcon_response_destroy(response);
149                 return CONV_ERROR_INVALID_OPERATION;
150         }
151
152         iotcon_response_destroy(response);
153
154         return CONV_ERROR_NONE;
155 }
156
157 static int sendResponse(conv::Json payload, const char* request_type, conv_error_e error, conv::Request* requestObj)
158 {
159         _D(RED("publishing_response"));
160         IF_FAIL_RETURN_TAG(requestObj != NULL, CONV_ERROR_INVALID_OPERATION, _E, "listener_cb is not registered");
161
162         conv::Json result;
163         conv::Json description = requestObj->getDescription();
164
165         payload.set(NULL, CONV_JSON_RESULT_TYPE, request_type);
166
167         result.set(NULL, CONV_JSON_DESCRIPTION, description);
168         result.set(NULL, CONV_JSON_PAYLOAD, payload);
169         requestObj->publish(error, result, 0, NULL);
170
171         return CONV_ERROR_NONE;
172 }
173
174 //callback function handles app control reply callback from callee application
175 static void _app_control_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data)
176 {
177         _D("app control reply received");
178
179         long long reply_id = (long long)user_data;
180
181         std::map<long long, app_control_cb_info_s>::iterator find_iter = app_control_cb_map.find(reply_id);
182
183         IF_FAIL_VOID_TAG(find_iter != app_control_cb_map.end(), _E, "No reply data");
184
185         app_control_cb_info_s cb_info = find_iter->second;
186
187         bundle* p_bundle;
188         bundle* p_bundle_request;
189         iotcon_representation_h rep;
190         iotcon_representation_create(&rep);
191         iotcon_attributes_h attributes;
192         iotcon_attributes_create(&attributes);
193
194         app_control_export_as_bundle(reply, &p_bundle);
195         app_control_export_as_bundle(request, &p_bundle_request);
196
197         bundle_raw* p_bundle_raw;
198         bundle_raw* p_bundle_request_raw;
199
200         int len, len_request;
201         bundle_encode(p_bundle, &p_bundle_raw, &len);
202         char* bundle_raw = reinterpret_cast<char*>(p_bundle_raw);
203
204         bundle_encode(p_bundle_request, &p_bundle_request_raw, &len_request);
205         char* bundle_request_raw = reinterpret_cast<char*>(p_bundle_request_raw);
206
207         iotcon_attributes_add_str(attributes, CONV_JSON_APP_CONTROL_REPLY, bundle_raw);
208         iotcon_attributes_add_str(attributes, CONV_JSON_APP_CONTROL_REQUEST, bundle_request_raw);
209         iotcon_attributes_add_int(attributes, CONV_JSON_REQ_ID, cb_info.req_id);
210         iotcon_attributes_add_int(attributes, CONV_JSON_APP_CONTROL_RESULT,  result);
211
212         iotcon_representation_set_attributes(rep, attributes);
213
214         _D("Send response to sender");
215         _send_response(cb_info.request_handle, rep, IOTCON_RESPONSE_OK);
216         _D("Response sent");
217
218         iotcon_attributes_destroy(attributes);
219         iotcon_representation_destroy(rep);
220
221         bundle_free(p_bundle);
222         bundle_free(p_bundle_request);
223         app_control_cb_map.erase(find_iter);
224 }
225
226 #if !defined(_D2D_INTERNAL_ACL_)
227 static void __acl_state_callback(void *userdata, const rdm_device_s* pRdmDevice)
228 {
229         IF_FAIL_VOID_TAG(pRdmDevice, _E, "pRdmDevice is NULL");
230     _D("macAddress:%s aclState:%d", pRdmDevice->wifiMac, pRdmDevice->status);
231
232     conv::RemoteAppControlAclRequestInfo *aclInfo = reinterpret_cast<conv::RemoteAppControlAclRequestInfo*>(userdata);
233     string policy;
234
235         IF_FAIL_VOID_TAG(aclInfo, _E, "aclInfo casting failed");
236
237     switch (pRdmDevice->status)
238     {
239         case RDM_STATUS_ALLOW: // permitted
240                 _D("Permitted");
241                 policy = CONV_ACCESS_CONTROL_PERMITTED;
242                 break;
243
244         case RDM_STATUS_DENY: // denied
245                 _D("Denied");
246                 policy = CONV_ACCESS_CONTROL_DENIED;
247                 break;
248
249         case RDM_STATUS_UNDECIDED: // undecided
250                 _D("Undecided");
251                 policy = CONV_ACCESS_CONTROL_DENIED;
252                 break;
253
254         case RDM_STATUS_REMOVED: // device removed
255                 _D("Device Removed");
256                 policy = CONV_ACCESS_CONTROL_DENIED;
257                 break;
258         default:
259                 _D("Unknown State");
260                 policy = CONV_ACCESS_CONTROL_DENIED;
261                 break;
262     }
263
264         iotcon_response_result_e result;
265         result = IOTCON_RESPONSE_OK;
266
267         iotcon_representation_h representation;
268         iotcon_representation_create(&representation);
269         iotcon_attributes_h attributes;
270         iotcon_attributes_create(&attributes);
271
272         iotcon_attributes_add_str(attributes, CONV_JSON_ACCESS_REQUEST_RESULT, (char*)policy.c_str());
273
274         iotcon_representation_set_attributes(representation, attributes);
275
276         _send_response(aclInfo->request, representation, result);
277
278         iotcon_attributes_destroy(attributes);
279         iotcon_representation_destroy(representation);
280
281         rdm_callback_deregister(aclInfo->aclHandler);
282
283         delete aclInfo;
284 }
285 #endif
286
287
288 static int __access_control(iotcon_request_h request, iotcon_attributes_h attributes)
289 {
290         _D("Access Request Handling");
291
292         string policy;
293
294         char *deviceName;
295         int ret = iotcon_attributes_get_str(attributes, CONV_JSON_DEVICE_NAME, &deviceName);
296         IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_representation_get_attributes() Fail(%d)", ret);
297
298         char *deviceType;
299         ret = iotcon_attributes_get_str(attributes, CONV_JSON_DEVICE_TYPE, &deviceType);
300         IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_representation_get_attributes() Fail(%d)", ret);
301
302         char *hostAddress;
303         ret = iotcon_request_get_host_address(request, &hostAddress);
304         IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_request_get_host_address() Fail(%d)", ret);
305
306         string hostAddressString(hostAddress);
307         string ip = conv::util::getIpAddress(hostAddressString);
308
309         char macAddress[127] = {0, };
310
311         IF_FAIL_RETURN_TAG(conv::util::getPeerMac(ip, -1, macAddress), CONV_ERROR_INVALID_PARAMETER, _E, "getPeerMac failed");
312
313         _D("Device Name : %s, Device IP : %s, Mac : %s, DeviceType : %s", deviceName, ip.c_str(), macAddress, deviceType);
314
315         char *access_request_type = NULL;
316         ret = iotcon_attributes_get_str(attributes, CONV_JSON_ACCESS_REQUEST_TYPE, &access_request_type);
317         _D("Access Request : %s", access_request_type);
318         IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_representation_get_attributes() Fail(%d)", ret);
319
320         if (!strcmp(CONV_ACCESS_CONTROL_REQUEST, access_request_type)) {
321 #if defined(_D2D_INTERNAL_ACL_)
322                 ACManagerPolicy acManagerPolicy = ACMANAGER_POLICY_U;
323 #if defined(_TV_) || defined(TIZEN_PROFILE_TV) || defined(TIZEN_TV)
324                 _D("Internal ACL for Odroid.");
325                 acManagerPolicy = ACMANAGER_POLICY_P;
326 #else
327                 _D("Internal ACL for Mobile & Wearable.");
328                 IF_FAIL_RETURN_TAG(AddACLDevice(macAddress, deviceName, ip.c_str(), &acManagerPolicy) == ACLResult_OK, CONV_ERROR_INVALID_OPERATION, _E, "AddACLDevice failed");
329 #endif
330                 if (acManagerPolicy == ACMANAGER_POLICY_P) {
331                         _D("PERMITTED");
332                         policy = CONV_ACCESS_CONTROL_PERMITTED;
333                 } else if (acManagerPolicy == ACMANAGER_POLICY_D) {
334                         _D("DENIED");
335                         policy = CONV_ACCESS_CONTROL_DENIED;
336                 } else if (acManagerPolicy == ACMANAGER_POLICY_U) {
337                         _D("UNDECIDED");
338                         policy = CONV_ACCESS_CONTROL_DENIED;
339                 } else if (acManagerPolicy == ACMANAGER_POLICY_U2) {
340                         _D("UNDECIDED");
341                         conv::acl_manager::LaunchPasskeyShowPopup(deviceName);
342                         policy = CONV_ACCESS_CONTROL_PASSKEY_REQUEST;
343                 }
344                 _D("acManagerPolicy:%d", acManagerPolicy);
345 #else
346                 rdm_device_s rdmDevice;
347                 IF_FAIL_RETURN_TAG(rdm_init_device(&rdmDevice, deviceName, NULL, macAddress, NULL, RDM_DEVICE_TYPE_PHONE, RDM_DEVICE_ICON_PHONE_DEFAULT) == RDM_ERROR_SUCCESS, CONV_ERROR_INVALID_OPERATION, _E, "rdm_init_device failed");
348
349                 ret = rdm_request_access(&rdmDevice);
350
351                 if (ret == RDM_ERROR_SUCCESS) {
352                         _D("PERMITTED");
353                         policy = CONV_ACCESS_CONTROL_PERMITTED;
354                 } else if (ret == RDM_ERROR_DEVICE_IS_DENIED) {
355                         _D("DENIED");
356                         policy = CONV_ACCESS_CONTROL_DENIED;
357                 } else if (ret == RDM_ERROR_INPROGRESS){
358                         _D("UNDECIDED");
359                         conv::RemoteAppControlAclRequestInfo *aclRequest = new(std::nothrow) conv::RemoteAppControlAclRequestInfo();
360                         aclRequest->request = request;
361                         if (rdm_callback_register(__acl_state_callback, aclRequest, &aclRequest->aclHandler) == RDM_ERROR_SUCCESS) {
362                                 _D("Register callback for ACL");
363                                 return CONV_ERROR_NONE;
364                         } else {
365                                 _D("Register callback failed");
366                                 policy = CONV_ACCESS_CONTROL_DENIED;
367                         }
368                 }
369                 _D("rdm_request_access:%d", ret);
370 #endif
371         } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_RESPONSE, access_request_type)) {
372 #if defined(_D2D_INTERNAL_ACL_)
373                 char *input_passkey;
374                 ret = iotcon_attributes_get_str(attributes, CONV_JSON_PASSKEY, &input_passkey);
375                 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_attributes_get_str() Fail(%d)", ret);
376
377                 ret = conv::acl_manager::PasskeyChecker(input_passkey);
378                 if (ret == ACLResult_OK) {
379                         policy = CONV_ACCESS_CONTROL_PASSKEY_RIGHT;
380                         conv::acl_manager::SetDeviceInfoAndACL(macAddress, deviceType, deviceName, ip.c_str(), ACMANAGER_POLICY_P);
381                         conv::acl_manager::LaunchAccessAllowedToast(deviceName);
382                 } else if (ret == ACLResult_Error) {
383                         policy = CONV_ACCESS_CONTROL_PASSKEY_WRONG;
384                 } else if (ret == ACLResult_Close) {
385                         policy = CONV_ACCESS_CONTROL_PASSKEY_REJECTED;
386                 }
387 #endif
388         } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_CANCEL, access_request_type)) {
389 #if defined(_D2D_INTERNAL_ACL_)
390                 _D("Access Cancel Handling");
391                 policy = CONV_ACCESS_CONTROL_DENIED;
392                 conv::acl_manager::LaunchPopupCancelToast();
393 #endif
394         }
395
396         iotcon_response_result_e result;
397         result = IOTCON_RESPONSE_OK;
398
399         iotcon_representation_h representation;
400         iotcon_representation_create(&representation);
401         iotcon_attributes_h attributesReply;
402         iotcon_attributes_create(&attributesReply);
403
404         iotcon_attributes_add_str(attributesReply, CONV_JSON_ACCESS_REQUEST_RESULT, (char*)policy.c_str());
405
406         iotcon_representation_set_attributes(representation, attributesReply);
407
408         _send_response(request, representation, result);
409
410         iotcon_attributes_destroy(attributesReply);
411         iotcon_representation_destroy(representation);
412
413         return CONV_ERROR_NONE;
414 }
415
416 static int __app_control_launch(iotcon_request_h request, iotcon_attributes_h attributes)
417 {
418         char *hostAddress;
419         int req_id = -1;
420         int ret = iotcon_request_get_host_address(request, &hostAddress);
421         IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_request_get_host_address() Fail(%d)", ret);
422         string hostAddressString(hostAddress);
423         string ip = conv::util::getIpAddress(hostAddressString);
424
425         char macAddress[127] = {0, };
426         IF_FAIL_RETURN_TAG(conv::util::getPeerMac(ip, -1, macAddress), CONV_ERROR_INVALID_PARAMETER, _E, "getPeerMac failed");
427
428         _D("Device IP : %s, Mac : %s", ip.c_str(), macAddress);
429
430 #if defined(_D2D_INTERNAL_ACL_)
431         ACManagerPolicy acManagerPolicy = ACMANAGER_POLICY_U;
432 #if defined(_TV_) || defined(TIZEN_PROFILE_TV) || defined(TIZEN_TV)
433         _D("Internal ACL for Odroid.");
434         acManagerPolicy = ACMANAGER_POLICY_P;
435 #else
436         _D("Internal ACL for Mobile & Wearable.");
437         IF_FAIL_RETURN_TAG(GetACLState(macAddress, &acManagerPolicy) == ACLResult_OK, CONV_ERROR_INVALID_OPERATION, _E, "ACL check failed");
438 #endif
439         if (acManagerPolicy == ACMANAGER_POLICY_P) {
440                 _D("PERMITTED");
441         } else {
442                 _D("Device is not permitted %d", acManagerPolicy);
443                 return CONV_ERROR_INVALID_OPERATION;
444         }
445 #else
446         rdm_status_e eStatus = RDM_STATUS_NONE;
447         ret = rdm_get_status(macAddress, RDM_TECH_IND_WIFI, &eStatus);
448
449         if (ret == RDM_ERROR_SUCCESS) {
450             if (eStatus == RDM_STATUS_ALLOW) {
451                 _D("PERMITTED");
452             } else {
453                 _D("Device is not permitted %d", eStatus);
454                 return CONV_ERROR_INVALID_OPERATION;
455             }
456         } else if (ret == RDM_ERROR_DEVICE_NOT_FOUND) {
457             _D("Device is not found");
458         return CONV_ERROR_INVALID_OPERATION;
459         } else {
460             _D("rdm_get_status failed (%d)", ret);
461             return CONV_ERROR_INVALID_OPERATION;
462         }
463 #endif
464         iotcon_attributes_get_int(attributes, CONV_JSON_REQ_ID, &req_id);
465         app_control_h app_control;
466         int reply = 0;
467         char *appctl_char;
468
469         ret = iotcon_attributes_get_str(attributes, CONV_JSON_APP_CONTROL, &appctl_char);
470         IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_attributes_get_str() Fail(%d)", ret);
471
472         bundle_raw* encoded = reinterpret_cast<unsigned char*>(appctl_char);
473         bundle* appctl_bundle = bundle_decode(encoded, strlen(appctl_char));
474
475         app_control_create(&app_control);
476         app_control_import_from_bundle(app_control, appctl_bundle);
477
478         iotcon_attributes_get_int(attributes, CONV_JSON_REPLY, &reply);
479
480         if (reply == 1) {
481                 bool waiting_reply = false;
482
483                 // check if it's already launched and waiting for app_control response
484                 for(std::map<long long, app_control_cb_info_s>::iterator it = app_control_cb_map.begin(); it != app_control_cb_map.end(); it++) {
485                         app_control_cb_info_s found_cb_info = it->second;
486                         if(found_cb_info.request_handle == request) {
487                                 waiting_reply = true;
488                                 _D("app_control_send_launch_request is already called...waiting reply");
489                                 break;
490                         }
491                 }
492
493                 if (!waiting_reply) {
494                         long long reply_id = get_req_id();
495
496                         app_control_cb_info_s cb_info;
497                         cb_info.req_id = req_id;
498                         cb_info.request_handle = request;
499                         app_control_cb_map[reply_id] = cb_info;
500
501                         ret = app_control_send_launch_request(app_control, _app_control_cb, (void*)reply_id);
502                         _D("app_control_send_launch_request with callback");
503
504                         if (ret != APP_CONTROL_ERROR_NONE) {
505                                 _E("Launch request failed(%d)", ret);
506                                 iotcon_response_result_e result = IOTCON_RESPONSE_ERROR;
507                                 iotcon_attributes_h attr;
508                                 iotcon_representation_h rep;
509                                 iotcon_attributes_create(&attr);
510                                 iotcon_attributes_add_int(attr, CONV_JSON_REQ_ID, req_id);
511                                 iotcon_representation_create(&rep);
512                                 iotcon_representation_set_attributes(rep, attr);
513                                 _send_response(request, rep, result);
514                                 iotcon_representation_destroy(rep);
515                                 iotcon_attributes_destroy(attr);
516                                 app_control_cb_map.erase(reply_id);
517                         }
518                 }
519
520                 bundle_free(appctl_bundle);
521                 app_control_destroy(app_control);
522         } else {
523                 _D("no waiting for reply. send response immediately");
524                 iotcon_response_result_e result;
525                 ret = app_control_send_launch_request(app_control, NULL, NULL);
526
527                 if (ret != APP_CONTROL_ERROR_NONE) {
528                         _E("Launch request failed(%d)", ret);
529                         result = IOTCON_RESPONSE_ERROR;
530                 } else {
531                         _D("Launch request succeeded");
532                         result = IOTCON_RESPONSE_OK;
533                 }
534                 bundle_free(appctl_bundle);
535                 app_control_destroy(app_control);
536
537                 iotcon_attributes_h attr;
538                 iotcon_representation_h rep;
539                 iotcon_attributes_create(&attr);
540                 iotcon_attributes_add_int(attr, CONV_JSON_REQ_ID, req_id);
541                 iotcon_representation_create(&rep);
542                 iotcon_representation_set_attributes(rep, attr);
543                 _send_response(request, rep, result);
544                 iotcon_representation_destroy(rep);
545                 iotcon_attributes_destroy(attr);
546         }
547
548         return CONV_ERROR_NONE;
549 }
550
551 //callback function handles put command for remote-app-control resource
552 static int __handle_request(iotcon_representation_h rep, iotcon_request_h request)
553 {
554         iotcon_attributes_h attributes;
555         char *requestType;
556
557         int ret = iotcon_representation_get_attributes(rep, &attributes);
558         IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_representation_get_attributes() Fail(%d)", ret);
559
560         // Handles Access Request
561         ret = iotcon_attributes_get_str(attributes, CONV_JSON_REQUEST_TYPE, &requestType);
562         IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_attributes_get_str() Fail(%d)", ret);
563
564         if (!strcmp(CONV_ACCESS_CONTROL_REQUEST, requestType)) {
565                 return __access_control(request, attributes);
566         } else if (!strcmp(CONV_LAUNCH_REQUEST, requestType)) {
567                 return __app_control_launch(request, attributes);
568         }
569
570         return CONV_ERROR_INVALID_PARAMETER;
571 }
572
573 //callback function handles requests for remote-app-control resource
574 void conv::RemoteAppControlServiceProvider::__iotcon_request_cb(iotcon_resource_h resource, iotcon_request_h request, void *user_data)
575 {
576         _D("request cb called");
577
578         int ret;
579         iotcon_request_type_e type;
580         char *hostAddress;
581         int req_id = -1;
582         iotcon_representation_h reqRep = NULL;
583
584         IF_FAIL_VOID_TAG(request, _E, "request is NULL");
585
586         ret = iotcon_request_get_representation(request, &reqRep);
587         IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_response_get_representation() Failed(%d)", ret);
588
589         ret = iotcon_request_get_host_address(request, &hostAddress);
590         IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_request_get_host_address() Failed(%d)", ret);
591
592         _I("host_address : %s", hostAddress);
593
594         ret = iotcon_request_get_request_type(request, &type);
595         IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_request_get_request_type() Failed(%d)", ret);
596         _D("request type : %d", type);
597
598         if (IOTCON_REQUEST_PUT == type) {
599                 _I("PUT request");
600                 IF_FAIL_CATCH_TAG(__handle_request(reqRep, request) == CONV_ERROR_NONE, _E, "__handle_request() Failed(%d)", ret);
601         }
602
603         if (reqRep) {
604                 iotcon_representation_destroy(reqRep);
605                 reqRep = NULL;
606         }
607
608         return;
609
610 CATCH:
611         iotcon_attributes_h attributes = NULL;
612         iotcon_representation_h responseRep = NULL;
613         iotcon_representation_create(&responseRep);
614         iotcon_attributes_h responseAttributes = NULL;
615         iotcon_attributes_create(&responseAttributes);
616
617         if (reqRep != NULL) {
618                 ret = iotcon_representation_get_attributes(reqRep, &attributes);
619                 if (ret == IOTCON_ERROR_NONE) {
620                         iotcon_attributes_get_int(attributes, CONV_JSON_REQ_ID, &req_id);
621                 }
622         }
623
624         iotcon_attributes_add_int(responseAttributes, CONV_JSON_REQ_ID, req_id);
625         iotcon_representation_set_attributes(responseRep, responseAttributes);
626
627         _send_response(request, responseRep, IOTCON_RESPONSE_ERROR);
628
629         if (attributes) {
630                 iotcon_attributes_destroy(attributes);
631                 attributes = NULL;
632         }
633         if (responseAttributes) {
634                 iotcon_attributes_destroy(responseAttributes);
635                 responseAttributes = NULL;
636         }
637         if (reqRep) {
638                 iotcon_representation_destroy(reqRep);
639                 reqRep = NULL;
640         }
641         if (responseRep) {
642                 iotcon_representation_destroy(responseRep);
643                 responseRep = NULL;
644         }
645 }
646
647 int conv::RemoteAppControlServiceProvider::init()
648 {
649         if (iotcon_resource == NULL) {
650                 // register resource
651                 int properties;
652                 iotcon_resource_interfaces_h resource_ifaces = NULL;
653                 iotcon_resource_types_h resource_types = NULL;
654                 int error;
655
656                 properties = IOTCON_RESOURCE_NO_POLICY;
657
658                 error = iotcon_resource_types_create(&resource_types);
659                 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "rt creation failed");
660
661                 iotcon_resource_types_add(resource_types, __resourceType.c_str());
662
663                 error = iotcon_resource_interfaces_create(&resource_ifaces);
664                 IF_FAIL_CATCH_TAG(error == IOTCON_ERROR_NONE, _E, "ri creation failed");
665
666                 iotcon_resource_interfaces_add(resource_ifaces, IOTCON_INTERFACE_DEFAULT);
667
668                 error = iotcon_resource_create(CONV_URI_REMOTE_APP_CONTROL, resource_types, resource_ifaces, properties, __iotcon_request_cb, NULL, &iotcon_resource);
669                 IF_FAIL_CATCH_TAG(error == IOTCON_ERROR_NONE, _E, "resource creation failed");
670
671                 _D("RemoteAppControlServiceProvider init done");
672 CATCH:
673                 iotcon_resource_types_destroy(resource_types);
674                 iotcon_resource_interfaces_destroy(resource_ifaces);
675                 IF_FAIL_RETURN(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION);
676
677         } else {
678                 _D("RemoteAppControlServiceProvider is already initiated");
679         }
680
681         return CONV_ERROR_NONE;
682 }
683
684 int conv::RemoteAppControlServiceProvider::release()
685 {
686         if (iotcon_resource == NULL) {
687                 _D("RemoteAppControlServiceProvider is already released");
688         } else {
689                 // unregister resource
690                 int error = iotcon_resource_destroy(iotcon_resource);
691                 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "resource destroy failed");
692                 iotcon_resource = NULL;
693                 _D("RemoteAppControlServiceProvider release done");
694         }
695
696         return CONV_ERROR_NONE;
697 }
698
699 static void passkey_popup_callback(void *user_data, int result, char *passkey);
700
701 //callback function handles reply from access control request
702 static void __on_access_response(iotcon_remote_resource_h resource, iotcon_error_e err,
703                 iotcon_request_type_e request_type, iotcon_response_h response, void *user_data)
704 {
705         _D("__on_access_response called");
706         int ret;
707         iotcon_response_result_e response_result;
708         iotcon_representation_h repr;
709
710         if (!response) {
711                 _D("response is NULL");
712                 return;
713         }
714
715         conv::RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<conv::RemoteAppControlServiceInfo*>(user_data);
716
717         ret = iotcon_response_get_result(response, &response_result);
718         if (IOTCON_ERROR_NONE != ret) {
719                 _E("iotcon_response_get_result() Fail(%d)", ret);
720                 conv::Json result;
721                 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
722                 return;
723         }
724
725         if (IOTCON_RESPONSE_RESOURCE_CHANGED != response_result) {
726                 _E("_on_response_observe Response error(%d)", response_result);
727                 conv::Json result;
728                 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
729                 return;
730         }
731
732         ret = iotcon_response_get_representation(response, &repr);
733
734         char* accessControlResult;
735         iotcon_attributes_h attributes;
736         iotcon_representation_get_attributes(repr, &attributes);
737         ret = iotcon_attributes_get_str(attributes, CONV_JSON_ACCESS_REQUEST_RESULT, &accessControlResult);
738         if (IOTCON_ERROR_NONE != ret) {
739                 _E("iotcon_attributes_get_str() Fail(%d)", ret);
740                 conv::Json result;
741                 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
742                 return;
743         }
744
745         if (!strcmp(CONV_ACCESS_CONTROL_PERMITTED, accessControlResult)) {
746                 _D("__on_access_response PERMITTED");
747                 conv::Json result;
748                 svcInfo->accessControlState = ACCESS_CONTROL_STATE_PERMITTED;
749                 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_NONE, svcInfo->registeredRequest);
750                 return;
751         } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_REQUEST, accessControlResult)) {
752 #if defined(_D2D_INTERNAL_ACL_)
753                 _D("__on_access_response PASSKEY REQUEST");
754                 conv::acl_manager::LaunchPasskeyInputPopup(passkey_popup_callback, svcInfo);
755                 return;
756 #endif
757         } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_RIGHT, accessControlResult)) {
758 #if defined(_D2D_INTERNAL_ACL_)
759                 _D("__on_access_response PASSKEY RIGHT");
760                 conv::acl_manager::LaunchAccessAllowedToast((char*)svcInfo->deviceName.c_str());
761                 conv::Json result;
762                 svcInfo->accessControlState = ACCESS_CONTROL_STATE_PERMITTED;
763                 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_NONE, svcInfo->registeredRequest);
764                 return;
765 #endif
766         } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_WRONG, accessControlResult)) {
767 #if defined(_D2D_INTERNAL_ACL_)
768                 _D("__on_access_response PASSKEY WRONG");
769                 conv::acl_manager::LaunchPasskeyWrongToast();
770                 return;
771 #endif
772         } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_REJECTED, accessControlResult)) {
773 #if defined(_D2D_INTERNAL_ACL_)
774                 _D("__on_access_response PASSKEY REJECTED");
775                 conv::acl_manager::LaunchAccessRejectedToast();
776                 conv::Json result;
777                 svcInfo->accessControlState = ACCESS_CONTROL_STATE_DENIED;
778                 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
779                 return;
780 #endif
781         } else {
782                 _D("__on_access_response DENIED");
783                 conv::Json result;
784                 svcInfo->accessControlState = ACCESS_CONTROL_STATE_DENIED;
785                 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
786                 return;
787         }
788 }
789
790 #if defined(_D2D_INTERNAL_ACL_)
791 static void passkey_popup_callback(void *user_data, int result, char *passkey)
792 {
793         conv::RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<conv::RemoteAppControlServiceInfo*>(user_data);
794
795         iotcon_representation_h representation;
796         iotcon_representation_create(&representation);
797
798         iotcon_attributes_h attributes;
799         iotcon_attributes_create(&attributes);
800
801         if (result == ACLResult_Cancel) {
802                 iotcon_attributes_add_str(attributes, CONV_JSON_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_REQUEST);
803                 iotcon_attributes_add_str(attributes, CONV_JSON_ACCESS_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_PASSKEY_CANCEL);
804                 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_NAME, (char*)conv::util::getDeviceName().c_str());
805                 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_TYPE, (char*)conv::util::getDeviceType().c_str());
806
807         } else if (result == ACLResult_Connect) {
808                 iotcon_attributes_add_str(attributes, CONV_JSON_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_REQUEST);
809                 iotcon_attributes_add_str(attributes, CONV_JSON_ACCESS_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_PASSKEY_RESPONSE);
810                 iotcon_attributes_add_str(attributes, CONV_JSON_PASSKEY, passkey);
811                 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_NAME, (char*)conv::util::getDeviceName().c_str());
812                 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_TYPE, (char*)conv::util::getDeviceType().c_str());
813         }
814
815         iotcon_representation_set_attributes(representation, attributes);
816         svcInfo->iotconInfoObj.iotconRepresentationHandle = representation;
817         iotcon_attributes_destroy(attributes);
818
819         iotcon_remote_resource_put(svcInfo->iotconInfoObj.iotconResourceHandle, representation, NULL, __on_access_response, svcInfo);
820 }
821 #endif
822
823 static int stop_request(conv::Request* requestObj);
824
825 static void _dbusDisconnectListenerFreeCallback(gpointer userData)
826 {
827         _D(RED("_dbusDisconnectListenerFreeCallback"));
828
829         conv::Request *_requestObj = reinterpret_cast<conv::Request *>(userData);
830         if (_requestObj == NULL) {
831                 return;
832         }
833
834         delete _requestObj;
835         _requestObj = NULL;
836 }
837
838 static void _dbusDisconnectListener(GDBusConnection* conn, const gchar* sender, const gchar* path, const gchar* iface, const gchar* name, GVariant* param, gpointer userData)
839 {
840         conv::Request *_requestObj = reinterpret_cast<conv::Request *>(userData);
841
842         char* disconnectName;
843         g_variant_get_child(param, 0, "&s", &disconnectName);
844
845         if (_requestObj == NULL) {
846                 _E("requestObj is NULL");
847                 return;
848         }
849
850         if (!strcmp(disconnectName, _requestObj->getSender())) {
851                 _D("Detected the dbus disconnection.");
852                 _requestObj->setIsConnect(false);
853
854                 conv::RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<conv::RemoteAppControlServiceInfo*>(_requestObj->getServiceInfo());
855
856                 if (svcInfo->registeredRequest != NULL) {
857                         delete svcInfo->registeredRequest;
858                         svcInfo->registeredRequest = NULL;
859                 }
860
861                 stop_request(_requestObj);
862
863                 _D("request stop");
864
865                 std::map<std::string, guint>::iterator iter = dbus_listener_info_map.end();
866                 iter = dbus_listener_info_map.find(_requestObj->getSender());
867
868                 if (iter != dbus_listener_info_map.end()) {
869                         guint listener_id = reinterpret_cast<guint>(iter->second);
870                         dbus_listener_info_map.erase(iter);
871
872                         if (_requestObj->getInvocation() != NULL) {
873                                 g_dbus_connection_signal_unsubscribe(conn, listener_id);
874                                 _D("Delete dbus disconnect listener.");
875                         } else {
876                                 _E("requestObj invocation is NULL");
877                         }
878                 }
879         } else {
880                 _D("Not found dbus disconnect listener.");
881         }
882 }
883
884 static void registDbusDisconnectListener(conv::Request* requestObj)
885 {
886         std::map<std::string, guint>::iterator iter = dbus_listener_info_map.end();
887         iter = dbus_listener_info_map.find(requestObj->getSender());
888
889         if (iter != dbus_listener_info_map.end()) {
890                 guint listener_id = reinterpret_cast<guint>(iter->second);
891                 dbus_listener_info_map.erase(iter);
892
893                 GDBusConnection *conn = g_dbus_method_invocation_get_connection(requestObj->getInvocation());
894                 g_dbus_connection_signal_unsubscribe(conn, listener_id);
895                 _D("Delete dbus disconnect listener.");
896         }
897
898         conv::Request *_requestObj = requestObj->clone();
899         GDBusConnection *conn = g_dbus_method_invocation_get_connection(_requestObj->getInvocation());
900         guint listener_id = g_dbus_connection_signal_subscribe(conn, "org.freedesktop.DBus", "org.freedesktop.DBus", "NameOwnerChanged", "/org/freedesktop/DBus",
901                 _requestObj->getSender(), G_DBUS_SIGNAL_FLAGS_NONE, _dbusDisconnectListener, _requestObj, _dbusDisconnectListenerFreeCallback);
902
903         if (listener_id == 0) {
904                 _E("Dbus signal listener registration failed.");
905                 delete _requestObj;
906                 _requestObj = NULL;
907         } else {
908                 dbus_listener_info_map[_requestObj->getSender()] = listener_id;
909                 _D("Subscribe the dbus signal. id = %d", listener_id);
910         }
911 }
912
913 int conv::RemoteAppControlServiceProvider::startRequest(Request* requestObj)
914 {
915         _D("communcation/start requested");
916
917         int error;
918         Json result;
919
920         int properties;
921         iotcon_resource_interfaces_h resource_ifaces = NULL;
922         iotcon_resource_types_h resource_types = NULL;
923
924         RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
925
926         if (svcInfo->iotconInfoObj.iotconResourceHandle != NULL) {
927                 _D("already started");
928                 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
929                 return CONV_ERROR_INVALID_OPERATION;
930         }
931
932         properties = IOTCON_RESOURCE_NO_POLICY;
933
934         error = iotcon_resource_types_create(&resource_types);
935         IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "rt creation failed");
936
937         iotcon_resource_types_add(resource_types, svcInfo->iotconInfoObj.resourceType.c_str());
938
939         error = iotcon_resource_interfaces_create(&resource_ifaces);
940         IF_FAIL_CATCH_TAG(error == IOTCON_ERROR_NONE, _E, "ri creation failed");
941
942         iotcon_resource_interfaces_add(resource_ifaces, IOTCON_INTERFACE_DEFAULT);
943
944         error = iotcon_remote_resource_create(svcInfo->iotconInfoObj.address.c_str(), IOTCON_CONNECTIVITY_IP, svcInfo->iotconInfoObj.uri.c_str(), properties, resource_types, resource_ifaces,
945                         &(svcInfo->iotconInfoObj.iotconResourceHandle));
946
947         _D("remote resource created : %s, %s", svcInfo->iotconInfoObj.address.c_str(), svcInfo->iotconInfoObj.uri.c_str());
948         IF_FAIL_CATCH_TAG(error == IOTCON_ERROR_NONE, _E, "remote resource creation failed %s, %s", svcInfo->iotconInfoObj.address.c_str(), svcInfo->iotconInfoObj.uri.c_str());
949
950         registDbusDisconnectListener(requestObj);
951
952 CATCH:
953         iotcon_resource_types_destroy(resource_types);
954         iotcon_resource_interfaces_destroy(resource_ifaces);
955         IF_FAIL_RETURN(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION);
956
957         //send message for access request
958         iotcon_representation_h representation;
959         iotcon_representation_create(&representation);
960         iotcon_attributes_h attributes;
961         iotcon_attributes_create(&attributes);
962
963         iotcon_attributes_add_str(attributes, CONV_JSON_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_REQUEST);
964         iotcon_attributes_add_str(attributes, CONV_JSON_ACCESS_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_REQUEST);
965         iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_NAME, (char*)conv::util::getDeviceName().c_str());
966         iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_TYPE, (char*)conv::util::getDeviceType().c_str());
967
968         iotcon_representation_set_attributes(representation, attributes);
969         svcInfo->iotconInfoObj.iotconRepresentationHandle = representation;
970
971         iotcon_attributes_destroy(attributes);
972
973         error = iotcon_remote_resource_put(svcInfo->iotconInfoObj.iotconResourceHandle, representation, NULL, __on_access_response, svcInfo);
974
975         return CONV_ERROR_NONE;
976 }
977
978 int conv::RemoteAppControlServiceProvider::stopRequest(Request* requestObj)
979 {
980         _D("communcation/stop requested");
981         return stop_request(requestObj);
982 }
983
984 static int stop_request(conv::Request* requestObj)
985 {
986         conv::Json result;
987         conv::RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<conv::RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
988
989         if (svcInfo->iotconInfoObj.iotconResourceHandle == NULL) {
990                 _D("not even started");
991                 sendResponse(result, CONV_JSON_ON_STOP, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
992                 return CONV_ERROR_INVALID_OPERATION;
993         }
994
995         iotcon_remote_resource_destroy(svcInfo->iotconInfoObj.iotconResourceHandle);
996         svcInfo->iotconInfoObj.iotconResourceHandle = NULL;
997
998         sendResponse(result, CONV_JSON_ON_STOP, CONV_ERROR_NONE, svcInfo->registeredRequest);
999         return CONV_ERROR_NONE;
1000 }
1001
1002 int conv::RemoteAppControlServiceProvider::checkStateRequest(Request* requestObj)
1003 {
1004         _D("communcation/check_state requested");
1005
1006         RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
1007
1008         if (svcInfo->iotconInfoObj.iotconResourceHandle == NULL) {
1009                 _D("not started");
1010                 return CONV_ERROR_INVALID_OPERATION;
1011         } else {
1012                 _D("started");
1013                 return CONV_ERROR_NONE;
1014         }
1015 }
1016
1017 int conv::RemoteAppControlServiceProvider::readRequest(Request* requestObj)
1018 {
1019         return CONV_ERROR_NONE;
1020 }
1021
1022 //callback function handles reply from publish request
1023 static void __on_response(iotcon_remote_resource_h resource, iotcon_error_e err,
1024                 iotcon_request_type_e request_type, iotcon_response_h response, void *user_data)
1025 {
1026         int ret;
1027         int appcontrol_result = -1;
1028         iotcon_response_result_e response_result;
1029         iotcon_representation_h repr;
1030         char* appctl_char = NULL;
1031         char* appctl_request_char = NULL;
1032         int appctl_result = -1;
1033         int req_id = -1;
1034         iotcon_attributes_h attributes;
1035         std::map<int, response_cb_info_s>::iterator find_iter = response_cb_map.end();
1036         response_cb_info_s cb_info;
1037         cb_info.requestObj = NULL;
1038
1039         if (!response) {
1040                 _D("response is NULL");
1041                 return;
1042         }
1043
1044         ret = iotcon_response_get_representation(response, &repr);
1045         IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_response_get_representation() Failed(%d)", ret);
1046
1047         iotcon_representation_get_attributes(repr, &attributes);
1048         ret = iotcon_attributes_get_int(attributes, CONV_JSON_REQ_ID, &req_id);
1049         IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_attributes_get_int() Failed(%d)", ret);
1050
1051         find_iter = response_cb_map.find(req_id);
1052         IF_FAIL_CATCH_TAG(find_iter != response_cb_map.end(), _E, "No callback found for response");
1053         cb_info = find_iter->second;
1054
1055         ret = iotcon_response_get_result(response, &response_result);
1056         IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_response_get_result() Failed(%d)", ret);
1057         IF_FAIL_CATCH_TAG(response_result == IOTCON_RESPONSE_RESOURCE_CHANGED, _E, "not response of PUT method(%d)", response_result);
1058
1059         ret = iotcon_attributes_get_str(attributes, CONV_JSON_APP_CONTROL_REPLY, &appctl_char);
1060         if (IOTCON_ERROR_NONE != ret) {
1061                 _E("iotcon_attributes_get_str() Fail(%d)", ret);
1062         }
1063
1064         ret = iotcon_attributes_get_str(attributes, CONV_JSON_APP_CONTROL_REQUEST, &appctl_request_char);
1065         if (IOTCON_ERROR_NONE != ret) {
1066                 _E("iotcon_attributes_get_str() Fail(%d)", ret);
1067         }
1068
1069         appcontrol_result = iotcon_attributes_get_int(attributes, CONV_JSON_APP_CONTROL_RESULT, &appctl_result);
1070         if (IOTCON_ERROR_NONE != appcontrol_result) {
1071                 _E("iotcon_attributes_get_int() Fail(%d)", appcontrol_result);
1072         }
1073
1074         _D(RED("publishing_response"));
1075         if (cb_info.requestObj) {
1076                 conv::Json result;
1077                 conv::Json payload;
1078                 conv::Json description;
1079
1080                 string resultStr = to_string(appctl_result);
1081                 payload.set(NULL, CONV_JSON_RESULT_TYPE, CONV_JSON_ON_PUBLISH);
1082                 if (appctl_char) {
1083                         payload.set(NULL, CONV_JSON_APP_CONTROL_REPLY, appctl_char);
1084                 }
1085                 if (appctl_request_char) {
1086                         payload.set(NULL, CONV_JSON_APP_CONTROL_REQUEST, appctl_request_char);
1087                 }
1088                 if (appcontrol_result == IOTCON_ERROR_NONE) {
1089                         payload.set(NULL, CONV_JSON_APP_CONTROL_RESULT, resultStr.c_str());
1090                 }
1091                 description = cb_info.requestObj->getDescription();
1092                 result.set(NULL, CONV_JSON_DESCRIPTION, description);
1093                 result.set(NULL, CONV_JSON_PAYLOAD, payload);
1094
1095                 cb_info.requestObj->publish(CONV_ERROR_NONE, result, 0, NULL);
1096                 _D("response published");
1097         } else {
1098                 _D("request obj is NULL");
1099         }
1100         if (find_iter != response_cb_map.end()) {
1101                 response_cb_map.erase(find_iter);
1102         }
1103         return;
1104 CATCH:
1105         if (cb_info.requestObj) {
1106                 conv::Json result;
1107                 conv::Json payload;
1108                 conv::Json description;
1109
1110                 string resultStr = to_string(appctl_result);
1111                 payload.set(NULL, CONV_JSON_RESULT_TYPE, CONV_JSON_ON_PUBLISH);
1112                 if (appctl_char) {
1113                         payload.set(NULL, CONV_JSON_APP_CONTROL_REPLY, appctl_char);
1114                 }
1115                 if (appctl_request_char) {
1116                         payload.set(NULL, CONV_JSON_APP_CONTROL_REQUEST, appctl_request_char);
1117                 }
1118
1119                 description = cb_info.requestObj->getDescription();
1120                 result.set(NULL, CONV_JSON_DESCRIPTION, description);
1121                 result.set(NULL, CONV_JSON_PAYLOAD, payload);
1122
1123                 cb_info.requestObj->publish(CONV_ERROR_INVALID_OPERATION, result, 0, NULL);
1124                 _D("response error published");
1125         } else {
1126                 _D("request obj is NULL");
1127         }
1128         if (find_iter != response_cb_map.end()) {
1129                 response_cb_map.erase(find_iter);
1130         }
1131         return;
1132 }
1133
1134 int conv::RemoteAppControlServiceProvider::publishRequest(Request* requestObj)
1135 {
1136         RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
1137         int error;
1138
1139         IF_FAIL_RETURN_TAG(svcInfo->accessControlState == ACCESS_CONTROL_STATE_PERMITTED, CONV_ERROR_INVALID_OPERATION, _E, "Access to device is not permitted");
1140
1141         requestObj->setCommunicationInfo(&(svcInfo->iotconInfoObj));
1142
1143         iotcon_representation_h representation;
1144         iotcon_representation_create(&representation);
1145
1146         Json payload;
1147         requestObj->getPayloadFromDescription(&payload);
1148
1149         string app_control;
1150         int reply;
1151
1152         payload.get(NULL, CONV_JSON_APP_CONTROL, &app_control);
1153         payload.get(NULL, CONV_JSON_REPLY, &reply);
1154
1155         iotcon_attributes_h attributes;
1156         iotcon_attributes_create(&attributes);
1157
1158         char* appControl = new char[app_control.size() + 1];
1159
1160         memset(appControl, 0, app_control.size() + 1);
1161         strncpy(appControl, app_control.c_str(), app_control.size()+1);
1162
1163         iotcon_attributes_add_str(attributes, CONV_JSON_APP_CONTROL, appControl);
1164         iotcon_attributes_add_int(attributes, CONV_JSON_REPLY, reply);
1165         iotcon_attributes_add_str(attributes, CONV_JSON_REQUEST_TYPE, (char *)CONV_LAUNCH_REQUEST);
1166
1167         delete[] appControl;
1168
1169         int req_id = get_req_id();
1170         iotcon_attributes_add_int(attributes, CONV_JSON_REQ_ID, req_id);
1171
1172         response_cb_info_s cb_info;
1173         cb_info.req_id = req_id;
1174         cb_info.requestObj = svcInfo->registeredRequest;
1175         response_cb_map[req_id] = cb_info;
1176
1177         iotcon_representation_set_attributes(representation, attributes);
1178         svcInfo->iotconInfoObj.iotconRepresentationHandle = representation;
1179
1180         iotcon_attributes_destroy(attributes);
1181
1182         error = iotcon_remote_resource_put(svcInfo->iotconInfoObj.iotconResourceHandle, representation, NULL, __on_response, NULL);
1183
1184         if (error != IOTCON_ERROR_NONE) {
1185                 _E("iotcon_remote_resource_put failed");
1186                 response_cb_map.erase(req_id);
1187                 Json result;
1188                 sendResponse(result, CONV_JSON_ON_PUBLISH, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
1189                 return CONV_ERROR_INVALID_OPERATION;
1190         }
1191
1192         return CONV_ERROR_NONE;
1193 }
1194
1195 int conv::RemoteAppControlServiceProvider::registerRequest(Request* requestObj)
1196 {
1197         _D("communcation/recv requested");
1198         RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
1199
1200         switch (requestObj->getType()) {
1201         case REQ_SUBSCRIBE:
1202                 if (svcInfo->registeredRequest != NULL) {
1203                         for (std::map<int, response_cb_info_s>::iterator it = response_cb_map.begin(); it != response_cb_map.end(); ++it) {
1204                                 if (((response_cb_info_s)it->second).requestObj == svcInfo->registeredRequest) {
1205                                         response_cb_info_s cbInfo;
1206                                         cbInfo.req_id = ((response_cb_info_s)it->second).req_id;
1207                                         cbInfo.requestObj = requestObj;
1208
1209                                         it->second = cbInfo;
1210                                 }
1211                         }
1212                         delete svcInfo->registeredRequest;
1213                 }
1214                 svcInfo->registeredRequest = requestObj;
1215                 requestObj->reply(CONV_ERROR_NONE);
1216                 _D("subscribe requested");
1217                 break;
1218         case REQ_UNSUBSCRIBE:
1219                 for (std::map<int, response_cb_info_s>::iterator it = response_cb_map.begin(); it != response_cb_map.end(); ++it) {
1220                         if (((response_cb_info_s)it->second).requestObj == svcInfo->registeredRequest) {
1221                                 response_cb_info_s cbInfo;
1222                                 cbInfo.req_id = ((response_cb_info_s)it->second).req_id;
1223                                 cbInfo.requestObj = NULL;
1224
1225                                 it->second = cbInfo;
1226                         }
1227                 }
1228                 delete svcInfo->registeredRequest;
1229                 svcInfo->registeredRequest = NULL;
1230                 requestObj->reply(CONV_ERROR_NONE);
1231                 delete requestObj;
1232                 break;
1233         default:
1234                 requestObj->reply(CONV_ERROR_INVALID_OPERATION);
1235                 delete requestObj;
1236                 return CONV_ERROR_INVALID_OPERATION;
1237                 break;
1238         }
1239
1240         return CONV_ERROR_NONE;
1241 }
1242
1243 int conv::RemoteAppControlServiceProvider::loadServiceInfo(Request* requestObj)
1244 {
1245         string client;
1246         conv::ClientInfo* clientObj = NULL;
1247
1248         client = requestObj->getSender();
1249         _D("client id : %s", client.c_str());
1250         clientObj = conv::client_manager::getClient(client);
1251         IF_FAIL_RETURN_TAG(clientObj, CONV_ERROR_OUT_OF_MEMORY, _E, "client info alloc failed");
1252
1253         Json description = requestObj->getDescription();
1254         Json service;
1255         Json device;
1256
1257         string deviceId;
1258         string deviceName;
1259         string deviceAddress;
1260         string uri;
1261
1262         description.get(NULL, CONV_JSON_SERVICE, &service);
1263         description.get(NULL, CONV_JSON_DEVICE, &device);
1264
1265         service.get(NULL, CONV_SERVICE_ID, &uri);
1266
1267         device.get(NULL, CONV_DEVICE_ID, &deviceId);
1268         device.get(NULL, CONV_DEVICE_NAME, &deviceName);
1269         device.get(NULL, CONV_JSON_DEVICE_ADDRESS, &deviceAddress);
1270
1271         RemoteAppControlServiceInfo *svcInfo = NULL;
1272         IServiceInfo* svcInfoBase = clientObj->getServiceInfo(__type, deviceId);
1273
1274         if (svcInfoBase != NULL) {
1275                 _D("service instance already exists");
1276                 svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(svcInfoBase);
1277         } else {
1278                 _D("allocating new service instance");
1279                 svcInfo = new(std::nothrow) RemoteAppControlServiceInfo();
1280                 IF_FAIL_RETURN_TAG(svcInfo, CONV_ERROR_OUT_OF_MEMORY, _E, "svcInfo alloc failed");
1281
1282                 svcInfo->deviceId = deviceId;
1283                 svcInfo->deviceName = deviceName;
1284                 svcInfo->deviceAddress = deviceAddress;
1285
1286                 svcInfo->iotconInfoObj.address = deviceAddress;
1287                 svcInfo->iotconInfoObj.uri = CONV_URI_REMOTE_APP_CONTROL;
1288                 svcInfo->iotconInfoObj.resourceType = __resourceType;
1289                 svcInfo->iotconInfoObj.iotconResourceHandle = NULL;
1290
1291                 //save service info
1292                 clientObj->addServiceInfo(__type, deviceId, (IServiceInfo*)svcInfo);
1293
1294                 _D("remote app control service is created");
1295         }
1296
1297         requestObj->setServiceInfo(svcInfo);
1298         return CONV_ERROR_NONE;
1299 }
1300
1301 int conv::RemoteAppControlServiceProvider::getServiceInfoForDiscovery(Json* jsonObj)
1302 {
1303         jsonObj->set(NULL, CONV_JSON_DISCOVERY_SERVICE_TYPE, CONV_SERVICE_REMOTE_APP_CONTROL);
1304
1305         // set data for service handle
1306         Json info;
1307         info.set(NULL, CONV_SERVICE_ID, __uri);
1308         info.set(NULL, CONV_SERVICE_VERSION, "1.0");
1309
1310         jsonObj->set(NULL, CONV_JSON_DISCOVERY_SERVICE_INFO, info);
1311
1312         return CONV_ERROR_NONE;
1313 }
1314
1315 #endif