2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <bundle_internal.h>
19 #include <app_control_internal.h>
20 #include "RemoteAppControlServiceProvider.h"
21 #include "../ClientManager.h"
23 #if defined(_D2D_INTERNAL_ACL_)
24 #include "../access_control/ACLManager.h"
26 using namespace conv::acl_manager;
28 #include <rdm_iface.h>
33 struct app_control_cb_info_s {
35 iotcon_request_h request_handle;
38 struct response_cb_info_s {
40 conv::Request* requestObj;
43 static int get_req_id()
45 static int req_id = 0;
54 static std::map<long long, app_control_cb_info_s> app_control_cb_map;
55 static std::map<int, response_cb_info_s> response_cb_map;
57 static void vconf_update_cb(keynode_t *node, void* user_data)
59 conv::RemoteAppControlServiceProvider* instance = static_cast<conv::RemoteAppControlServiceProvider*>(user_data);
60 IF_FAIL_VOID_TAG(instance, _E, "static_cast failed");
62 instance->handleVconfUpdate(node);
65 conv::RemoteAppControlServiceProvider::RemoteAppControlServiceProvider()
67 __type = CONV_SERVICE_TYPE_REMOTE_APP_CONTROL;
68 __resourceType = CONV_RESOURCE_TYPE_REMOTE_APP_CONTROL;
69 __uri = CONV_URI_REMOTE_APP_CONTROL;
70 iotcon_resource = NULL;
72 if (conv::util::isServiceActivated()) {
73 __activationState = 1;
75 __activationState = 0;
78 vconf_notify_key_changed(VCONFKEY_SETAPPL_D2D_CONVERGENCE_SERVICE, vconf_update_cb, this);
79 #if !defined(_D2D_INTERNAL_ACL_)
80 int error = rdm_init();
81 if (error != RDM_ERROR_SUCCESS)
82 _E("rdm init error : %d", error);
86 conv::RemoteAppControlServiceProvider::~RemoteAppControlServiceProvider()
88 app_control_cb_map.clear();
89 response_cb_map.clear();
91 #if !defined(_D2D_INTERNAL_ACL_)
92 int error = rdm_deinit();
93 if (error != RDM_ERROR_SUCCESS)
94 _E("rdm deinit error : %d", error);
98 int conv::RemoteAppControlServiceProvider::handleVconfUpdate(keynode_t *node)
100 int current_state = vconf_keynode_get_int(node);
102 if (current_state > 0) {
103 __activationState = 1;
106 __activationState = 0;
110 return CONV_ERROR_NONE;
113 static int _send_response(iotcon_request_h request, iotcon_representation_h repr,
114 iotcon_response_result_e result)
117 iotcon_response_h response;
119 ret = iotcon_response_create(request, &response);
120 if (IOTCON_ERROR_NONE != ret) {
121 _E("iotcon_response_create() Fail(%d)", ret);
122 return CONV_ERROR_INVALID_OPERATION;
125 ret = iotcon_response_set_result(response, result);
126 if (IOTCON_ERROR_NONE != ret) {
127 _E("iotcon_response_set_result() Fail(%d)", ret);
128 iotcon_response_destroy(response);
129 return CONV_ERROR_INVALID_OPERATION;
132 ret = iotcon_response_set_representation(response, repr);
133 if (IOTCON_ERROR_NONE != ret) {
134 _E("iotcon_response_set_representation() Fail(%d)", ret);
135 iotcon_response_destroy(response);
136 return CONV_ERROR_INVALID_OPERATION;
139 /* send Representation to the client */
140 ret = iotcon_response_send(response);
141 if (IOTCON_ERROR_NONE != ret) {
142 _E("iotcon_response_send() Fail(%d)", ret);
143 iotcon_response_destroy(response);
144 return CONV_ERROR_INVALID_OPERATION;
147 iotcon_response_destroy(response);
149 return CONV_ERROR_NONE;
152 static int sendResponse(conv::Json payload, const char* request_type, conv_error_e error, conv::Request* requestObj)
154 _D(RED("publishing_response"));
155 IF_FAIL_RETURN_TAG(requestObj != NULL, CONV_ERROR_INVALID_OPERATION, _E, "listener_cb is not registered");
158 conv::Json description = requestObj->getDescription();
160 payload.set(NULL, CONV_JSON_RESULT_TYPE, request_type);
162 result.set(NULL, CONV_JSON_DESCRIPTION, description);
163 result.set(NULL, CONV_JSON_PAYLOAD, payload);
164 requestObj->publish(error, result, 0, NULL);
166 return CONV_ERROR_NONE;
169 //callback function handles app control reply callback from callee application
170 static void _app_control_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data)
172 _D("app control reply received");
174 long long reply_id = (long long)user_data;
176 std::map<long long, app_control_cb_info_s>::iterator find_iter = app_control_cb_map.find(reply_id);
178 IF_FAIL_VOID_TAG(find_iter != app_control_cb_map.end(), _E, "No reply data");
180 app_control_cb_info_s cb_info = find_iter->second;
183 bundle* p_bundle_request;
184 iotcon_representation_h rep;
185 iotcon_representation_create(&rep);
186 iotcon_attributes_h attributes;
187 iotcon_attributes_create(&attributes);
189 app_control_export_as_bundle(reply, &p_bundle);
190 app_control_export_as_bundle(request, &p_bundle_request);
192 bundle_raw* p_bundle_raw;
193 bundle_raw* p_bundle_request_raw;
195 int len, len_request;
196 bundle_encode(p_bundle, &p_bundle_raw, &len);
197 char* bundle_raw = reinterpret_cast<char*>(p_bundle_raw);
199 bundle_encode(p_bundle_request, &p_bundle_request_raw, &len_request);
200 char* bundle_request_raw = reinterpret_cast<char*>(p_bundle_request_raw);
202 iotcon_attributes_add_str(attributes, CONV_JSON_APP_CONTROL_REPLY, bundle_raw);
203 iotcon_attributes_add_str(attributes, CONV_JSON_APP_CONTROL_REQUEST, bundle_request_raw);
204 iotcon_attributes_add_int(attributes, CONV_JSON_REQ_ID, cb_info.req_id);
205 iotcon_attributes_add_int(attributes, CONV_JSON_APP_CONTROL_RESULT, result);
207 iotcon_representation_set_attributes(rep, attributes);
209 _D("Send response to sender");
210 _send_response(cb_info.request_handle, rep, IOTCON_RESPONSE_OK);
213 bundle_free(p_bundle);
214 bundle_free(p_bundle_request);
215 app_control_cb_map.erase(find_iter);
218 #if !defined(_D2D_INTERNAL_ACL_)
219 static void __acl_state_callback(void *userdata, const rdm_device_s* pRdmDevice)
221 IF_FAIL_VOID_TAG(pRdmDevice, _E, "pRdmDevice is NULL");
222 _D("macAddress:%s aclState:%d", pRdmDevice->wifiMac, pRdmDevice->status);
224 conv::RemoteAppControlAclRequestInfo *aclInfo = reinterpret_cast<conv::RemoteAppControlAclRequestInfo*>(userdata);
227 IF_FAIL_VOID_TAG(aclInfo, _E, "aclInfo casting failed");
229 switch (pRdmDevice->status)
231 case RDM_STATUS_ALLOW: // permitted
233 policy = CONV_ACCESS_CONTROL_PERMITTED;
236 case RDM_STATUS_DENY: // denied
238 policy = CONV_ACCESS_CONTROL_DENIED;
241 case RDM_STATUS_UNDECIDED: // undecided
243 policy = CONV_ACCESS_CONTROL_DENIED;
246 case RDM_STATUS_REMOVED: // device removed
247 _D("Device Removed");
248 policy = CONV_ACCESS_CONTROL_DENIED;
252 policy = CONV_ACCESS_CONTROL_DENIED;
256 iotcon_response_result_e result;
257 result = IOTCON_RESPONSE_OK;
259 iotcon_representation_h representation;
260 iotcon_representation_create(&representation);
261 iotcon_attributes_h attributes;
262 iotcon_attributes_create(&attributes);
264 iotcon_attributes_add_str(attributes, CONV_JSON_ACCESS_REQUEST_RESULT, (char*)policy.c_str());
266 iotcon_representation_set_attributes(representation, attributes);
268 _send_response(aclInfo->request, representation, result);
270 iotcon_attributes_destroy(attributes);
271 iotcon_representation_destroy(representation);
273 rdm_callback_deregister(aclInfo->aclHandler);
280 static int __access_control(iotcon_request_h request, iotcon_attributes_h attributes)
282 _D("Access Request Handling");
287 int ret = iotcon_attributes_get_str(attributes, CONV_JSON_DEVICE_NAME, &deviceName);
288 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_representation_get_attributes() Fail(%d)", ret);
291 ret = iotcon_attributes_get_str(attributes, CONV_JSON_DEVICE_TYPE, &deviceType);
292 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_representation_get_attributes() Fail(%d)", ret);
295 ret = iotcon_request_get_host_address(request, &hostAddress);
296 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_request_get_host_address() Fail(%d)", ret);
298 string hostAddressString(hostAddress);
299 string ip = conv::util::getIpAddress(hostAddressString);
301 char macAddress[127] = {0, };
303 IF_FAIL_RETURN_TAG(conv::util::getPeerMac(ip, -1, macAddress), CONV_ERROR_INVALID_PARAMETER, _E, "getPeerMac failed");
305 _D("Device Name : %s, Device IP : %s, Mac : %s, DeviceType : %s", deviceName, ip.c_str(), macAddress, deviceType);
307 char *access_request_type = NULL;
308 ret = iotcon_attributes_get_str(attributes, CONV_JSON_ACCESS_REQUEST_TYPE, &access_request_type);
309 _D("Access Request : %s", access_request_type);
310 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_representation_get_attributes() Fail(%d)", ret);
312 if (!strcmp(CONV_ACCESS_CONTROL_REQUEST, access_request_type)) {
313 #if defined(_D2D_INTERNAL_ACL_)
314 ACManagerPolicy acManagerPolicy = ACMANAGER_POLICY_U;
315 IF_FAIL_RETURN_TAG(AddACLDevice(macAddress, deviceName, ip.c_str(), &acManagerPolicy) == ACLResult_OK, CONV_ERROR_INVALID_OPERATION, _E, "AddACLDevice failed");
317 if (acManagerPolicy == ACMANAGER_POLICY_P) {
319 policy = CONV_ACCESS_CONTROL_PERMITTED;
320 } else if (acManagerPolicy == ACMANAGER_POLICY_D) {
322 policy = CONV_ACCESS_CONTROL_DENIED;
323 } else if (acManagerPolicy == ACMANAGER_POLICY_U) {
325 policy = CONV_ACCESS_CONTROL_DENIED;
326 } else if (acManagerPolicy == ACMANAGER_POLICY_U2) {
328 conv::acl_manager::LaunchPasskeyShowPopup(deviceName);
329 policy = CONV_ACCESS_CONTROL_PASSKEY_REQUEST;
331 _D("acManagerPolicy:%d", acManagerPolicy);
333 rdm_device_s rdmDevice;
334 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");
336 ret = rdm_request_access(&rdmDevice);
338 if (ret == RDM_ERROR_SUCCESS) {
340 policy = CONV_ACCESS_CONTROL_PERMITTED;
341 } else if (ret == RDM_ERROR_DEVICE_IS_DENIED) {
343 policy = CONV_ACCESS_CONTROL_DENIED;
344 } else if (ret == RDM_ERROR_INPROGRESS){
346 conv::RemoteAppControlAclRequestInfo *aclRequest = new(std::nothrow) conv::RemoteAppControlAclRequestInfo();
347 aclRequest->request = request;
348 if (rdm_callback_register(__acl_state_callback, aclRequest, &aclRequest->aclHandler) == RDM_ERROR_SUCCESS) {
349 _D("Register callback for ACL");
350 return CONV_ERROR_NONE;
352 _D("Register callback failed");
353 policy = CONV_ACCESS_CONTROL_DENIED;
356 _D("rdm_request_access:%d", ret);
358 } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_RESPONSE, access_request_type)) {
359 #if defined(_D2D_INTERNAL_ACL_)
361 ret = iotcon_attributes_get_str(attributes, CONV_JSON_PASSKEY, &input_passkey);
362 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_attributes_get_str() Fail(%d)", ret);
364 ret = conv::acl_manager::PasskeyChecker(input_passkey);
365 if (ret == ACLResult_OK) {
366 policy = CONV_ACCESS_CONTROL_PASSKEY_RIGHT;
367 conv::acl_manager::SetDeviceInfoAndACL(macAddress, deviceType, deviceName, ip.c_str(), ACMANAGER_POLICY_P);
368 conv::acl_manager::LaunchAccessAllowedToast(deviceName);
369 } else if (ret == ACLResult_Error) {
370 policy = CONV_ACCESS_CONTROL_PASSKEY_WRONG;
371 } else if (ret == ACLResult_Close) {
372 policy = CONV_ACCESS_CONTROL_PASSKEY_REJECTED;
375 } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_CANCEL, access_request_type)) {
376 #if defined(_D2D_INTERNAL_ACL_)
377 _D("Access Cancel Handling");
378 policy = CONV_ACCESS_CONTROL_DENIED;
379 conv::acl_manager::LaunchPopupCancelToast();
383 iotcon_response_result_e result;
384 result = IOTCON_RESPONSE_OK;
386 iotcon_representation_h representation;
387 iotcon_representation_create(&representation);
388 iotcon_attributes_h attributesReply;
389 iotcon_attributes_create(&attributesReply);
391 iotcon_attributes_add_str(attributesReply, CONV_JSON_ACCESS_REQUEST_RESULT, (char*)policy.c_str());
393 iotcon_representation_set_attributes(representation, attributesReply);
395 _send_response(request, representation, result);
397 iotcon_attributes_destroy(attributesReply);
398 iotcon_representation_destroy(representation);
400 return CONV_ERROR_NONE;
403 static int __app_control_launch(iotcon_request_h request, iotcon_attributes_h attributes)
407 int ret = iotcon_request_get_host_address(request, &hostAddress);
408 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_request_get_host_address() Fail(%d)", ret);
409 string hostAddressString(hostAddress);
410 string ip = conv::util::getIpAddress(hostAddressString);
412 char macAddress[127] = {0, };
413 IF_FAIL_RETURN_TAG(conv::util::getPeerMac(ip, -1, macAddress), CONV_ERROR_INVALID_PARAMETER, _E, "getPeerMac failed");
415 _D("Device IP : %s, Mac : %s", ip.c_str(), macAddress);
417 #if defined(_D2D_INTERNAL_ACL_)
418 ACManagerPolicy acManagerPolicy = ACMANAGER_POLICY_U;
420 IF_FAIL_RETURN_TAG(GetACLState(macAddress, &acManagerPolicy) == ACLResult_OK, CONV_ERROR_INVALID_OPERATION, _E, "ACL check failed");
421 if (acManagerPolicy == ACMANAGER_POLICY_P) {
424 _D("Device is not permitted %d", acManagerPolicy);
425 return CONV_ERROR_INVALID_OPERATION;
428 rdm_status_e eStatus = RDM_STATUS_NONE;
429 ret = rdm_get_status(macAddress, RDM_TECH_IND_WIFI, &eStatus);
431 if (ret == RDM_ERROR_SUCCESS) {
432 if (eStatus == RDM_STATUS_ALLOW) {
435 _D("Device is not permitted %d", eStatus);
436 return CONV_ERROR_INVALID_OPERATION;
438 } else if (ret == RDM_ERROR_DEVICE_NOT_FOUND) {
439 _D("Device is not found");
440 return CONV_ERROR_INVALID_OPERATION;
442 _D("rdm_get_status failed (%d)", ret);
443 return CONV_ERROR_INVALID_OPERATION;
446 iotcon_attributes_get_int(attributes, CONV_JSON_REQ_ID, &req_id);
447 app_control_h app_control;
451 ret = iotcon_attributes_get_str(attributes, CONV_JSON_APP_CONTROL, &appctl_char);
452 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_attributes_get_str() Fail(%d)", ret);
454 bundle_raw* encoded = reinterpret_cast<unsigned char*>(appctl_char);
455 bundle* appctl_bundle = bundle_decode(encoded, strlen(appctl_char));
457 app_control_create(&app_control);
458 app_control_import_from_bundle(app_control, appctl_bundle);
460 iotcon_attributes_get_int(attributes, CONV_JSON_REPLY, &reply);
463 bool waiting_reply = false;
465 // check if it's already launched and waiting for app_control response
466 for(std::map<long long, app_control_cb_info_s>::iterator it = app_control_cb_map.begin(); it != app_control_cb_map.end(); it++) {
467 app_control_cb_info_s found_cb_info = it->second;
468 if(found_cb_info.request_handle == request) {
469 waiting_reply = true;
470 _D("app_control_send_launch_request is already called...waiting reply");
475 if (!waiting_reply) {
476 long long reply_id = get_req_id();
478 app_control_cb_info_s cb_info;
479 cb_info.req_id = req_id;
480 cb_info.request_handle = request;
481 app_control_cb_map[reply_id] = cb_info;
483 ret = app_control_send_launch_request(app_control, _app_control_cb, (void*)reply_id);
484 _D("app_control_send_launch_request with callback");
486 if (ret != APP_CONTROL_ERROR_NONE) {
487 _E("Launch request failed(%d)", ret);
488 iotcon_response_result_e result = IOTCON_RESPONSE_ERROR;
489 iotcon_attributes_h attr;
490 iotcon_representation_h rep;
491 iotcon_attributes_create(&attr);
492 iotcon_attributes_add_int(attr, CONV_JSON_REQ_ID, req_id);
493 iotcon_representation_create(&rep);
494 iotcon_representation_set_attributes(rep, attr);
495 _send_response(request, rep, result);
496 iotcon_representation_destroy(rep);
497 iotcon_attributes_destroy(attr);
498 app_control_cb_map.erase(reply_id);
502 bundle_free(appctl_bundle);
503 app_control_destroy(app_control);
505 _D("no waiting for reply. send response immediately");
506 iotcon_response_result_e result;
507 ret = app_control_send_launch_request(app_control, NULL, NULL);
509 if (ret != APP_CONTROL_ERROR_NONE) {
510 _E("Launch request failed(%d)", ret);
511 result = IOTCON_RESPONSE_ERROR;
513 _D("Launch request succeeded");
514 result = IOTCON_RESPONSE_OK;
516 bundle_free(appctl_bundle);
517 app_control_destroy(app_control);
519 iotcon_attributes_h attr;
520 iotcon_representation_h rep;
521 iotcon_attributes_create(&attr);
522 iotcon_attributes_add_int(attr, CONV_JSON_REQ_ID, req_id);
523 iotcon_representation_create(&rep);
524 iotcon_representation_set_attributes(rep, attr);
525 _send_response(request, rep, result);
526 iotcon_representation_destroy(rep);
527 iotcon_attributes_destroy(attr);
530 return CONV_ERROR_NONE;
533 //callback function handles put command for remote-app-control resource
534 static int __handle_request(iotcon_representation_h rep, iotcon_request_h request)
536 iotcon_attributes_h attributes;
539 int ret = iotcon_representation_get_attributes(rep, &attributes);
540 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_representation_get_attributes() Fail(%d)", ret);
542 // Handles Access Request
543 ret = iotcon_attributes_get_str(attributes, CONV_JSON_REQUEST_TYPE, &requestType);
544 IF_FAIL_RETURN_TAG(ret == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "iotcon_attributes_get_str() Fail(%d)", ret);
546 if (!strcmp(CONV_ACCESS_CONTROL_REQUEST, requestType)) {
547 return __access_control(request, attributes);
548 } else if (!strcmp(CONV_LAUNCH_REQUEST, requestType)) {
549 return __app_control_launch(request, attributes);
552 return CONV_ERROR_INVALID_PARAMETER;
555 //callback function handles requests for remote-app-control resource
556 void conv::RemoteAppControlServiceProvider::__iotcon_request_cb(iotcon_resource_h resource, iotcon_request_h request, void *user_data)
558 _D("request cb called");
561 iotcon_request_type_e type;
564 iotcon_representation_h reqRep = NULL;
566 IF_FAIL_VOID_TAG(request, _E, "request is NULL");
568 ret = iotcon_request_get_representation(request, &reqRep);
569 IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_response_get_representation() Failed(%d)", ret);
571 ret = iotcon_request_get_host_address(request, &hostAddress);
572 IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_request_get_host_address() Failed(%d)", ret);
574 _I("host_address : %s", hostAddress);
576 ret = iotcon_request_get_request_type(request, &type);
577 IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_request_get_request_type() Failed(%d)", ret);
578 _D("request type : %d", type);
580 if (IOTCON_REQUEST_PUT == type) {
582 IF_FAIL_CATCH_TAG(__handle_request(reqRep, request) == CONV_ERROR_NONE, _E, "__handle_request() Failed(%d)", ret);
586 iotcon_representation_destroy(reqRep);
593 iotcon_attributes_h attributes;
594 iotcon_representation_h responseRep;
595 iotcon_representation_create(&responseRep);
596 iotcon_attributes_h responseAttributes;
597 iotcon_attributes_create(&responseAttributes);
599 if (reqRep != NULL) {
600 ret = iotcon_representation_get_attributes(reqRep, &attributes);
601 if (ret == IOTCON_ERROR_NONE) {
602 iotcon_attributes_get_int(attributes, CONV_JSON_REQ_ID, &req_id);
606 iotcon_attributes_add_int(responseAttributes, CONV_JSON_REQ_ID, req_id);
607 iotcon_representation_set_attributes(responseRep, responseAttributes);
609 _send_response(request, responseRep, IOTCON_RESPONSE_ERROR);
612 iotcon_attributes_destroy(attributes);
615 if (responseAttributes) {
616 iotcon_attributes_destroy(responseAttributes);
617 responseAttributes = NULL;
620 iotcon_representation_destroy(reqRep);
624 iotcon_representation_destroy(responseRep);
629 int conv::RemoteAppControlServiceProvider::init()
631 if (iotcon_resource == NULL) {
634 iotcon_resource_interfaces_h resource_ifaces = NULL;
635 iotcon_resource_types_h resource_types = NULL;
638 properties = IOTCON_RESOURCE_DISCOVERABLE | IOTCON_RESOURCE_OBSERVABLE;
640 error = iotcon_resource_types_create(&resource_types);
641 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "rt creation failed");
643 iotcon_resource_types_add(resource_types, __resourceType.c_str());
645 error = iotcon_resource_interfaces_create(&resource_ifaces);
647 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "ri creation failed");
649 iotcon_resource_interfaces_add(resource_ifaces, IOTCON_INTERFACE_DEFAULT);
652 error = iotcon_resource_create(CONV_URI_REMOTE_APP_CONTROL, resource_types, resource_ifaces, properties, __iotcon_request_cb, NULL, &iotcon_resource);
653 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "resource creation failed");
655 iotcon_resource_types_destroy(resource_types);
656 iotcon_resource_interfaces_destroy(resource_ifaces);
658 _D("RemoteAppControlServiceProvider init done");
660 _D("RemoteAppControlServiceProvider is already initiated");
663 return CONV_ERROR_NONE;
666 int conv::RemoteAppControlServiceProvider::release()
668 if (iotcon_resource == NULL) {
669 _D("RemoteAppControlServiceProvider is already released");
671 // unregister resource
672 int error = iotcon_resource_destroy(iotcon_resource);
673 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "resource destroy failed");
674 iotcon_resource = NULL;
675 _D("RemoteAppControlServiceProvider release done");
678 return CONV_ERROR_NONE;
681 static void passkey_popup_callback(void *user_data, int result, char *passkey);
683 //callback function handles reply from access control request
684 static void __on_access_response(iotcon_remote_resource_h resource, iotcon_error_e err,
685 iotcon_request_type_e request_type, iotcon_response_h response, void *user_data)
687 _D("__on_access_response called");
689 iotcon_response_result_e response_result;
690 iotcon_representation_h repr;
692 conv::RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<conv::RemoteAppControlServiceInfo*>(user_data);
694 ret = iotcon_response_get_result(response, &response_result);
695 if (IOTCON_ERROR_NONE != ret) {
696 _E("iotcon_response_get_result() Fail(%d)", ret);
698 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
702 if (IOTCON_RESPONSE_RESOURCE_CHANGED != response_result) {
703 _E("_on_response_observe Response error(%d)", response_result);
705 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
709 ret = iotcon_response_get_representation(response, &repr);
711 char* accessControlResult;
712 iotcon_attributes_h attributes;
713 iotcon_representation_get_attributes(repr, &attributes);
714 ret = iotcon_attributes_get_str(attributes, CONV_JSON_ACCESS_REQUEST_RESULT, &accessControlResult);
715 if (IOTCON_ERROR_NONE != ret) {
716 _E("iotcon_attributes_get_str() Fail(%d)", ret);
718 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
722 if (!strcmp(CONV_ACCESS_CONTROL_PERMITTED, accessControlResult)) {
723 _D("__on_access_response PERMITTED");
725 svcInfo->accessControlState = ACCESS_CONTROL_STATE_PERMITTED;
726 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_NONE, svcInfo->registeredRequest);
728 } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_REQUEST, accessControlResult)) {
729 #if defined(_D2D_INTERNAL_ACL_)
730 _D("__on_access_response PASSKEY REQUEST");
731 conv::acl_manager::LaunchPasskeyInputPopup(passkey_popup_callback, svcInfo);
734 } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_RIGHT, accessControlResult)) {
735 #if defined(_D2D_INTERNAL_ACL_)
736 _D("__on_access_response PASSKEY RIGHT");
737 conv::acl_manager::LaunchAccessAllowedToast((char*)svcInfo->deviceName.c_str());
739 svcInfo->accessControlState = ACCESS_CONTROL_STATE_PERMITTED;
740 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_NONE, svcInfo->registeredRequest);
743 } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_WRONG, accessControlResult)) {
744 #if defined(_D2D_INTERNAL_ACL_)
745 _D("__on_access_response PASSKEY WRONG");
746 conv::acl_manager::LaunchPasskeyWrongToast();
749 } else if (!strcmp(CONV_ACCESS_CONTROL_PASSKEY_REJECTED, accessControlResult)) {
750 #if defined(_D2D_INTERNAL_ACL_)
751 _D("__on_access_response PASSKEY REJECTED");
752 conv::acl_manager::LaunchAccessRejectedToast();
754 svcInfo->accessControlState = ACCESS_CONTROL_STATE_DENIED;
755 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
759 _D("__on_access_response DENIED");
761 svcInfo->accessControlState = ACCESS_CONTROL_STATE_DENIED;
762 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
767 #if defined(_D2D_INTERNAL_ACL_)
768 static void passkey_popup_callback(void *user_data, int result, char *passkey)
770 conv::RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<conv::RemoteAppControlServiceInfo*>(user_data);
772 iotcon_representation_h representation;
773 iotcon_representation_create(&representation);
775 iotcon_attributes_h attributes;
776 iotcon_attributes_create(&attributes);
778 if (result == ACLResult_Cancel) {
779 iotcon_attributes_add_str(attributes, CONV_JSON_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_REQUEST);
780 iotcon_attributes_add_str(attributes, CONV_JSON_ACCESS_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_PASSKEY_CANCEL);
781 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_NAME, (char*)conv::util::getDeviceName().c_str());
782 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_TYPE, (char*)conv::util::getDeviceType().c_str());
784 } else if (result == ACLResult_Connect) {
785 iotcon_attributes_add_str(attributes, CONV_JSON_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_REQUEST);
786 iotcon_attributes_add_str(attributes, CONV_JSON_ACCESS_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_PASSKEY_RESPONSE);
787 iotcon_attributes_add_str(attributes, CONV_JSON_PASSKEY, passkey);
788 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_NAME, (char*)conv::util::getDeviceName().c_str());
789 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_TYPE, (char*)conv::util::getDeviceType().c_str());
792 iotcon_representation_set_attributes(representation, attributes);
793 svcInfo->iotconInfoObj.iotconRepresentationHandle = representation;
794 iotcon_attributes_destroy(attributes);
796 iotcon_remote_resource_put(svcInfo->iotconInfoObj.iotconResourceHandle, representation, NULL, __on_access_response, svcInfo);
800 int conv::RemoteAppControlServiceProvider::startRequest(Request* requestObj)
802 _D("communcation/start requested");
807 iotcon_resource_interfaces_h resource_ifaces = NULL;
808 iotcon_resource_types_h resource_types = NULL;
810 RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
812 if (svcInfo->iotconInfoObj.iotconResourceHandle != NULL) {
813 _D("already started");
814 sendResponse(result, CONV_JSON_ON_START, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
815 return CONV_ERROR_INVALID_OPERATION;
818 properties = IOTCON_RESOURCE_DISCOVERABLE | IOTCON_RESOURCE_OBSERVABLE;
820 error = iotcon_resource_types_create(&resource_types);
821 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "rt creation failed");
823 iotcon_resource_types_add(resource_types, svcInfo->iotconInfoObj.resourceType.c_str());
825 error = iotcon_resource_interfaces_create(&resource_ifaces);
827 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "ri creation failed");
829 iotcon_resource_interfaces_add(resource_ifaces, IOTCON_INTERFACE_DEFAULT);
831 error = iotcon_remote_resource_create(svcInfo->iotconInfoObj.address.c_str(), IOTCON_CONNECTIVITY_IP, svcInfo->iotconInfoObj.uri.c_str(), properties, resource_types, resource_ifaces,
832 &(svcInfo->iotconInfoObj.iotconResourceHandle));
834 _D("remote resource created : %s, %s", svcInfo->iotconInfoObj.address.c_str(), svcInfo->iotconInfoObj.uri.c_str());
836 IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "remote resource creation failed %s, %s", svcInfo->iotconInfoObj.address.c_str(), svcInfo->iotconInfoObj.uri.c_str());
838 iotcon_resource_types_destroy(resource_types);
839 iotcon_resource_interfaces_destroy(resource_ifaces);
841 //send message for access request
842 iotcon_representation_h representation;
843 iotcon_representation_create(&representation);
844 iotcon_attributes_h attributes;
845 iotcon_attributes_create(&attributes);
847 iotcon_attributes_add_str(attributes, CONV_JSON_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_REQUEST);
848 iotcon_attributes_add_str(attributes, CONV_JSON_ACCESS_REQUEST_TYPE, (char*)CONV_ACCESS_CONTROL_REQUEST);
849 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_NAME, (char*)conv::util::getDeviceName().c_str());
850 iotcon_attributes_add_str(attributes, CONV_JSON_DEVICE_TYPE, (char*)conv::util::getDeviceType().c_str());
852 iotcon_representation_set_attributes(representation, attributes);
853 svcInfo->iotconInfoObj.iotconRepresentationHandle = representation;
855 iotcon_attributes_destroy(attributes);
857 error = iotcon_remote_resource_put(svcInfo->iotconInfoObj.iotconResourceHandle, representation, NULL, __on_access_response, svcInfo);
859 return CONV_ERROR_NONE;
862 int conv::RemoteAppControlServiceProvider::stopRequest(Request* requestObj)
864 _D("communcation/stop requested");
867 RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
869 if (svcInfo->iotconInfoObj.iotconResourceHandle == NULL) {
870 _D("not even started");
871 sendResponse(result, CONV_JSON_ON_STOP, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
872 return CONV_ERROR_INVALID_OPERATION;
875 iotcon_remote_resource_destroy(svcInfo->iotconInfoObj.iotconResourceHandle);
876 svcInfo->iotconInfoObj.iotconResourceHandle = NULL;
877 sendResponse(result, CONV_JSON_ON_STOP, CONV_ERROR_NONE, svcInfo->registeredRequest);
879 return CONV_ERROR_NONE;
882 int conv::RemoteAppControlServiceProvider::readRequest(Request* requestObj)
884 return CONV_ERROR_NONE;
887 //callback function handles reply from publish request
888 static void __on_response(iotcon_remote_resource_h resource, iotcon_error_e err,
889 iotcon_request_type_e request_type, iotcon_response_h response, void *user_data)
892 int appcontrol_result = -1;
893 iotcon_response_result_e response_result;
894 iotcon_representation_h repr;
895 char* appctl_char = NULL;
896 char* appctl_request_char = NULL;
897 int appctl_result = -1;
899 iotcon_attributes_h attributes;
900 std::map<int, response_cb_info_s>::iterator find_iter = response_cb_map.end();
901 response_cb_info_s cb_info;
902 cb_info.requestObj = NULL;
904 ret = iotcon_response_get_representation(response, &repr);
905 IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_response_get_representation() Failed(%d)", ret);
907 iotcon_representation_get_attributes(repr, &attributes);
908 ret = iotcon_attributes_get_int(attributes, CONV_JSON_REQ_ID, &req_id);
909 IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_attributes_get_int() Failed(%d)", ret);
911 find_iter = response_cb_map.find(req_id);
912 IF_FAIL_CATCH_TAG(find_iter != response_cb_map.end(), _E, "No callback found for response");
913 cb_info = find_iter->second;
915 ret = iotcon_response_get_result(response, &response_result);
916 IF_FAIL_CATCH_TAG(ret == IOTCON_ERROR_NONE, _E, "iotcon_response_get_result() Failed(%d)", ret);
917 IF_FAIL_CATCH_TAG(response_result == IOTCON_RESPONSE_RESOURCE_CHANGED, _E, "not response of PUT method(%d)", response_result);
919 ret = iotcon_attributes_get_str(attributes, CONV_JSON_APP_CONTROL_REPLY, &appctl_char);
920 if (IOTCON_ERROR_NONE != ret) {
921 _E("iotcon_attributes_get_str() Fail(%d)", ret);
924 ret = iotcon_attributes_get_str(attributes, CONV_JSON_APP_CONTROL_REQUEST, &appctl_request_char);
925 if (IOTCON_ERROR_NONE != ret) {
926 _E("iotcon_attributes_get_str() Fail(%d)", ret);
929 appcontrol_result = iotcon_attributes_get_int(attributes, CONV_JSON_APP_CONTROL_RESULT, &appctl_result);
930 if (IOTCON_ERROR_NONE != appcontrol_result) {
931 _E("iotcon_attributes_get_int() Fail(%d)", appcontrol_result);
934 _D(RED("publishing_response"));
935 if (cb_info.requestObj) {
938 conv::Json description;
940 string resultStr = to_string(appctl_result);
941 payload.set(NULL, CONV_JSON_RESULT_TYPE, CONV_JSON_ON_PUBLISH);
943 payload.set(NULL, CONV_JSON_APP_CONTROL_REPLY, appctl_char);
945 if (appctl_request_char) {
946 payload.set(NULL, CONV_JSON_APP_CONTROL_REQUEST, appctl_request_char);
948 if (appcontrol_result == IOTCON_ERROR_NONE) {
949 payload.set(NULL, CONV_JSON_APP_CONTROL_RESULT, resultStr.c_str());
951 result.set(NULL, CONV_JSON_DESCRIPTION, cb_info.requestObj->getDescription());
952 result.set(NULL, CONV_JSON_PAYLOAD, payload);
954 cb_info.requestObj->publish(CONV_ERROR_NONE, result, 0, NULL);
955 _D("response published");
957 _D("request obj is NULL");
959 if (find_iter != response_cb_map.end()) {
960 response_cb_map.erase(find_iter);
964 if (cb_info.requestObj) {
967 conv::Json description;
969 string resultStr = to_string(appctl_result);
970 payload.set(NULL, CONV_JSON_RESULT_TYPE, CONV_JSON_ON_PUBLISH);
972 payload.set(NULL, CONV_JSON_APP_CONTROL_REPLY, appctl_char);
974 if (appctl_request_char) {
975 payload.set(NULL, CONV_JSON_APP_CONTROL_REQUEST, appctl_request_char);
977 if (appcontrol_result == IOTCON_ERROR_NONE) {
978 payload.set(NULL, CONV_JSON_APP_CONTROL_RESULT, resultStr.c_str());
980 payload.set(NULL, CONV_JSON_APP_CONTROL_RESULT, resultStr.c_str());
981 result.set(NULL, CONV_JSON_DESCRIPTION, cb_info.requestObj->getDescription());
982 result.set(NULL, CONV_JSON_PAYLOAD, payload);
984 cb_info.requestObj->publish(CONV_ERROR_INVALID_OPERATION, result, 0, NULL);
985 _D("response error published");
987 _D("request obj is NULL");
989 if (find_iter != response_cb_map.end()) {
990 response_cb_map.erase(find_iter);
995 int conv::RemoteAppControlServiceProvider::publishRequest(Request* requestObj)
997 RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
1000 IF_FAIL_RETURN_TAG(svcInfo->accessControlState == ACCESS_CONTROL_STATE_PERMITTED, CONV_ERROR_INVALID_OPERATION, _E, "Access to device is not permitted");
1002 requestObj->setCommunicationInfo(&(svcInfo->iotconInfoObj));
1004 iotcon_representation_h representation;
1005 iotcon_representation_create(&representation);
1008 requestObj->getPayloadFromDescription(&payload);
1013 payload.get(NULL, CONV_JSON_APP_CONTROL, &app_control);
1014 payload.get(NULL, CONV_JSON_REPLY, &reply);
1016 iotcon_attributes_h attributes;
1017 iotcon_attributes_create(&attributes);
1019 char* appControl = new char[app_control.size() + 1];
1021 memset(appControl, 0, app_control.size() + 1);
1022 strncpy(appControl, app_control.c_str(), app_control.size()+1);
1024 iotcon_attributes_add_str(attributes, CONV_JSON_APP_CONTROL, appControl);
1025 iotcon_attributes_add_int(attributes, CONV_JSON_REPLY, reply);
1026 iotcon_attributes_add_str(attributes, CONV_JSON_REQUEST_TYPE, (char *)CONV_LAUNCH_REQUEST);
1028 delete[] appControl;
1030 int req_id = get_req_id();
1031 iotcon_attributes_add_int(attributes, CONV_JSON_REQ_ID, req_id);
1033 response_cb_info_s cb_info;
1034 cb_info.req_id = req_id;
1035 cb_info.requestObj = svcInfo->registeredRequest;
1036 response_cb_map[req_id] = cb_info;
1038 iotcon_representation_set_attributes(representation, attributes);
1039 svcInfo->iotconInfoObj.iotconRepresentationHandle = representation;
1041 iotcon_attributes_destroy(attributes);
1043 error = iotcon_remote_resource_put(svcInfo->iotconInfoObj.iotconResourceHandle, representation, NULL, __on_response, NULL);
1045 if (error != IOTCON_ERROR_NONE) {
1046 _E("iotcon_remote_resource_put failed");
1047 response_cb_map.erase(req_id);
1049 sendResponse(result, CONV_JSON_ON_PUBLISH, CONV_ERROR_INVALID_OPERATION, svcInfo->registeredRequest);
1050 return CONV_ERROR_INVALID_OPERATION;
1053 return CONV_ERROR_NONE;
1056 int conv::RemoteAppControlServiceProvider::registerRequest(Request* requestObj)
1058 _D("communcation/recv requested");
1059 RemoteAppControlServiceInfo *svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(requestObj->getServiceInfo());
1061 switch (requestObj->getType()) {
1063 if (svcInfo->registeredRequest != NULL) {
1064 delete svcInfo->registeredRequest;
1066 svcInfo->registeredRequest = requestObj;
1067 requestObj->reply(CONV_ERROR_NONE);
1068 _D("subscribe requested");
1070 case REQ_UNSUBSCRIBE:
1071 svcInfo->registeredRequest = NULL;
1072 requestObj->reply(CONV_ERROR_NONE);
1076 requestObj->reply(CONV_ERROR_INVALID_OPERATION);
1078 return CONV_ERROR_INVALID_OPERATION;
1082 return CONV_ERROR_NONE;
1086 int conv::RemoteAppControlServiceProvider::loadServiceInfo(Request* requestObj)
1089 conv::ClientInfo* clientObj = NULL;
1091 client = requestObj->getSender();
1092 _D("client id : %s", client.c_str());
1093 clientObj = conv::client_manager::getClient(client);
1094 IF_FAIL_RETURN_TAG(clientObj, CONV_ERROR_OUT_OF_MEMORY, _E, "client info alloc failed");
1096 Json description = requestObj->getDescription();
1102 string deviceAddress;
1105 description.get(NULL, CONV_JSON_SERVICE, &service);
1106 description.get(NULL, CONV_JSON_DEVICE, &device);
1108 service.get(NULL, CONV_SERVICE_ID, &uri);
1110 device.get(NULL, CONV_DEVICE_ID, &deviceId);
1111 device.get(NULL, CONV_DEVICE_NAME, &deviceName);
1112 device.get(NULL, CONV_JSON_DEVICE_ADDRESS, &deviceAddress);
1114 RemoteAppControlServiceInfo *svcInfo = NULL;
1115 IServiceInfo* svcInfoBase = clientObj->getServiceInfo(__type, deviceId);
1117 if (svcInfoBase != NULL) {
1118 _D("service instance already exists");
1119 svcInfo = reinterpret_cast<RemoteAppControlServiceInfo*>(svcInfoBase);
1121 _D("allocating new service instance");
1122 svcInfo = new(std::nothrow) RemoteAppControlServiceInfo();
1123 IF_FAIL_RETURN_TAG(svcInfo, CONV_ERROR_OUT_OF_MEMORY, _E, "svcInfo alloc failed");
1125 svcInfo->deviceId = deviceId;
1126 svcInfo->deviceName = deviceName;
1127 svcInfo->deviceAddress = deviceAddress;
1129 svcInfo->iotconInfoObj.address = deviceAddress;
1130 svcInfo->iotconInfoObj.uri = CONV_URI_REMOTE_APP_CONTROL;
1131 svcInfo->iotconInfoObj.resourceType = __resourceType;
1132 svcInfo->iotconInfoObj.iotconResourceHandle = NULL;
1135 clientObj->addServiceInfo(__type, deviceId, (IServiceInfo*)svcInfo);
1137 _D("remote app control service is created");
1140 requestObj->setServiceInfo(svcInfo);
1141 return CONV_ERROR_NONE;
1144 int conv::RemoteAppControlServiceProvider::getServiceInfoForDiscovery(Json* jsonObj)
1146 jsonObj->set(NULL, CONV_JSON_DISCOVERY_SERVICE_TYPE, CONV_SERVICE_REMOTE_APP_CONTROL);
1148 // set data for service handle
1150 info.set(NULL, CONV_SERVICE_ID, __uri);
1151 info.set(NULL, CONV_SERVICE_VERSION, "1.0");
1153 jsonObj->set(NULL, CONV_JSON_DISCOVERY_SERVICE_INFO, info);
1155 return CONV_ERROR_NONE;