From: Pawel Andruszkiewicz Date: Thu, 11 Feb 2016 07:48:07 +0000 (+0100) Subject: [iotcon] Implementation of Response.send(). X-Git-Tag: submit/tizen/20160222.104327^2~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=02fd865a58307ce45b20b474e2f0e1dd1dcbf228;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [iotcon] Implementation of Response.send(). Change-Id: Idced64c3cf411aaf2c217b3ddd9c2c34a194cb5b Signed-off-by: Pawel Andruszkiewicz --- diff --git a/src/iotcon/iotcon_api.js b/src/iotcon/iotcon_api.js index cee73089..288447b9 100644 --- a/src/iotcon/iotcon_api.js +++ b/src/iotcon/iotcon_api.js @@ -496,11 +496,18 @@ function Response(request) { } Response.prototype.send = function() { + var args = validator.validateMethod(arguments, [{ + name: 'iface', + type: types.ENUM, + values: T.getValues(ResourceInterface) + }]); + var callArgs = {}; callArgs.id = this.request[kIdKey]; callArgs.result = this.result; callArgs.representation = this.representation; callArgs.options = this.options; + callArgs.iface = args.iface; var result = native.callSync('IotconResponse_send', callArgs); diff --git a/src/iotcon/iotcon_instance.cc b/src/iotcon/iotcon_instance.cc index ae913dff..3f024f64 100644 --- a/src/iotcon/iotcon_instance.cc +++ b/src/iotcon/iotcon_instance.cc @@ -65,6 +65,7 @@ const std::string kQos = "qos"; const std::string kChildId = "childId"; const std::string kType = "type"; const std::string kInterface = "iface"; +const std::string kResult = "result"; const std::string kTimeout = "timeout"; } // namespace @@ -422,7 +423,79 @@ common::TizenResult IotconInstance::ResourceUnsetRequestListener(const picojson: common::TizenResult IotconInstance::ResponseSend(const picojson::object& args) { ScopeLogger(); - return common::UnknownError("Not implemented"); + + CHECK_EXIST(args, kId); + CHECK_EXIST(args, kResult); + CHECK_EXIST(args, kRepresentation); + CHECK_EXIST(args, kOptions); + CHECK_EXIST(args, kInterface); + + ResponsePtr response = nullptr; + auto result = IotconServerManager::GetInstance().GetResponseById(GetId(args), &response); + if (!result) { + LogAndReturnTizenError(result, ("GetResponseById() failed")); + } + + { + const auto& js_response_result = GetArg(args, kResult); + if (!js_response_result.is()) { + return LogAndCreateTizenError(TypeMismatchError, "ResponseResult should be a string"); + } + iotcon_response_result_e response_result = IotconUtils::ToResponseResult(js_response_result.get()); + + result = IotconUtils::ConvertIotconError(iotcon_response_set_result(response.get(), response_result)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_response_set_result() failed")); + } + } + + { + const auto& js_representation = GetArg(args, kRepresentation); + if (!js_representation.is()) { + return LogAndCreateTizenError(TypeMismatchError, "Representation should be an object"); + } + iotcon_representation_h representation = nullptr; + result = IotconUtils::RepresentationFromJson(js_representation.get(), &representation); + if (!result) { + LogAndReturnTizenError(result, ("RepresentationFromJson() failed")); + } + SCOPE_EXIT { + iotcon_representation_destroy(representation); + }; + + result = IotconUtils::ConvertIotconError(iotcon_response_set_representation(response.get(), IotconUtils::ToInterface(GetArg(args, kInterface).get()), representation)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_response_set_representation() failed")); + } + } + + { + const auto& js_options = GetArg(args, kOptions); + + if (js_options.is()) { + iotcon_options_h options = nullptr; + + result = IotconUtils::OptionsFromJson(js_options.get(), &options); + if (!result) { + LogAndReturnTizenError(result, ("OptionsFromJson() failed")); + } + SCOPE_EXIT { + iotcon_options_destroy(options); + }; + + result = IotconUtils::ConvertIotconError(iotcon_response_set_options(response.get(), options)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_response_set_options() failed")); + } + } + } + + result = IotconUtils::ConvertIotconError(iotcon_response_send(response.get())); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_response_send() failed")); + } + + return common::TizenSuccess(); } common::TizenResult IotconInstance::RemoteResourceGetCachedRepresentation(const picojson::object& args) { diff --git a/src/iotcon/iotcon_server_manager.cc b/src/iotcon/iotcon_server_manager.cc index 9a1144eb..079e7832 100644 --- a/src/iotcon/iotcon_server_manager.cc +++ b/src/iotcon/iotcon_server_manager.cc @@ -161,7 +161,7 @@ void IotconServerManager::RequestHandler(iotcon_resource_h resource, // store data long long id = GetNextId(); obj.insert(std::make_pair(kId, picojson::value{static_cast(id)})); - r->unhandled_responses.insert(std::make_pair(id, response)); + r->pending_responses.insert(std::make_pair(id, ResponsePtr{response, &iotcon_response_destroy})); // call listener r->request_listener(TizenSuccess(), value); @@ -264,5 +264,19 @@ common::TizenResult IotconServerManager::GetResourceByHandle( return TizenSuccess(); } +common::TizenResult IotconServerManager::GetResponseById(long long id, ResponsePtr* out) const { + ScopeLogger(); + + for (const auto& resource : resource_map_) { + const auto& it = resource.second->pending_responses.find(id); + if (resource.second->pending_responses.end() != it) { + *out = it->second; + return TizenSuccess(); + } + } + + return LogAndCreateTizenError(NotFoundError, "Response with specified ID does not exist"); +} + } // namespace iotcon } // namespace extension diff --git a/src/iotcon/iotcon_server_manager.h b/src/iotcon/iotcon_server_manager.h index b15e362f..3f9d8ef8 100644 --- a/src/iotcon/iotcon_server_manager.h +++ b/src/iotcon/iotcon_server_manager.h @@ -44,6 +44,7 @@ class IotconServerManager { common::TizenResult GetResourceById(long long id, ResourceInfoPtr* res_pointer) const; common::TizenResult DestroyResource(long long id); common::TizenResult GetResourceByHandle(iotcon_resource_h resource, ResourceInfoPtr* res_pointer) const; + common::TizenResult GetResponseById(long long id, ResponsePtr* out) const; private: IotconServerManager() = default; diff --git a/src/iotcon/iotcon_utils.cc b/src/iotcon/iotcon_utils.cc index 88c8a711..6f2a99f9 100644 --- a/src/iotcon/iotcon_utils.cc +++ b/src/iotcon/iotcon_utils.cc @@ -76,6 +76,15 @@ namespace { X(IOTCON_PRESENCE_RESOURCE_UPDATED, "UPDATED") \ XD(IOTCON_PRESENCE_RESOURCE_DESTROYED, "DESTROYED") +#define IOTCON_RESPONSE_RESULT_E \ + X(IOTCON_RESPONSE_OK, "SUCCESS") \ + X(IOTCON_RESPONSE_ERROR, "ERROR") \ + X(IOTCON_RESPONSE_RESOURCE_CREATED, "RESOURCE_CREATED") \ + X(IOTCON_RESPONSE_RESOURCE_DELETED, "RESOURCE_DELETED") \ + X(IOTCON_RESPONSE_SLOW, "SLOW") \ + X(IOTCON_RESPONSE_FORBIDDEN, "FORBIDDEN") \ + XD(IOTCON_RESPONSE_ERROR, "unknown") + } // namespace const std::string kIsDiscoverable = "isDiscoverable"; @@ -1338,6 +1347,155 @@ common::TizenResult IotconUtils::ExtractFromPresenceEvent(const PresenceEventPtr return TizenSuccess(); } +common::TizenResult IotconUtils::OptionsFromJson(const picojson::array& o, + iotcon_options_h* out) { + ScopeLogger(); + + iotcon_options_h options = nullptr; + + auto result = ConvertIotconError(iotcon_options_create(&options)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_options_create() failed")); + } + + std::unique_ptr::type, void(*)(iotcon_options_h)> ptr{options, &iotcon_options_destroy}; + + // we ignore values with incorrect types + // TODO: should we convert them in JS? + for (const auto& option : o) { + if (option.is()) { + const auto& js_id = option.get(kOptionsId); + const auto& js_data = option.get(kOptionsData); + + if (js_id.is() && js_data.is()) { + result = ConvertIotconError(iotcon_options_add(options, js_id.get(), js_data.get().c_str())); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_options_add() failed")); + } + } + } + } + + *out = ptr.release(); + return TizenSuccess(); +} + +common::TizenResult IotconUtils::RepresentationFromJson(const picojson::object& r, + iotcon_representation_h* out) { + ScopeLogger(); + + iotcon_representation_h representation = nullptr; + + auto result = ConvertIotconError(iotcon_representation_create(&representation)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_representation_create() failed")); + } + + std::unique_ptr::type, void(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy}; + + { + const auto& uri_path = r.find(kUriPath); + if (r.end() != uri_path && uri_path->second.is()) { + result = ConvertIotconError(iotcon_representation_set_uri_path(representation, uri_path->second.get().c_str())); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_representation_set_uri_path() failed")); + } + } else { + return LogAndCreateTizenError(TypeMismatchError, "Representation object needs to have an uriPath attribute which is a string."); + } + } + + { + const auto& resource_types = r.find(kResourceTypes); + if (r.end() != resource_types && resource_types->second.is()) { + iotcon_resource_types_h types = nullptr; + + result = ArrayToTypes(resource_types->second.get(), &types); + if (!result) { + LogAndReturnTizenError(result, ("ArrayToTypes() failed")); + } + SCOPE_EXIT { + iotcon_resource_types_destroy(types); + }; + + result = ConvertIotconError(iotcon_representation_set_resource_types(representation, types)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_representation_set_resource_types() failed")); + } + } else { + return LogAndCreateTizenError(TypeMismatchError, "Representation object needs to have a resourceTypes attribute which is an array."); + } + } + + { + const auto& resource_interfaces = r.find(kResourceInterfaces); + if (r.end() != resource_interfaces && resource_interfaces->second.is()) { + int interfaces = IOTCON_INTERFACE_NONE; + + result = ArrayToInterfaces(resource_interfaces->second.get(), &interfaces); + if (!result) { + LogAndReturnTizenError(result, ("ArrayToInterfaces() failed")); + } + + result = ConvertIotconError(iotcon_representation_set_resource_interfaces(representation, interfaces)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_representation_set_resource_interfaces() failed")); + } + } else { + return LogAndCreateTizenError(TypeMismatchError, "Representation object needs to have a resourceInterfaces attribute which is an array."); + } + } + + { + const auto& states = r.find(kStates); + if (r.end() != states && states->second.is()) { + iotcon_state_h s = nullptr; + + result = StateFromJson(states->second.get(), &s); + if (!result) { + LogAndReturnTizenError(result, ("StateFromJson() failed")); + } + SCOPE_EXIT { + iotcon_state_destroy(s); + }; + + result = ConvertIotconError(iotcon_representation_set_state(representation, s)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_representation_set_state() failed")); + } + } + } + + { + const auto& representations = r.find(kRepresentations); + if (r.end() != representations && representations->second.is()) { + for (const auto& js_child : representations->second.get()) { + if (js_child.is()) { + iotcon_representation_h child = nullptr; + + result = RepresentationFromJson(js_child.get(), &child); + if (!result) { + LogAndReturnTizenError(result, ("RepresentationFromJson() failed")); + } + SCOPE_EXIT { + iotcon_representation_destroy(child); + }; + + result = ConvertIotconError(iotcon_representation_add_child(representation, child)); + if (!result) { + LogAndReturnTizenError(result, ("iotcon_representation_add_child() failed")); + } + } else { + return LogAndCreateTizenError(TypeMismatchError, "The Representation.representations attribute needs to be an array of Representation objects."); + } + } + } + } + + *out = ptr.release(); + return TizenSuccess(); +} + common::TizenResult IotconUtils::PlatformInfoGetProperty(iotcon_platform_info_h platform, iotcon_platform_info_e property_e, const std::string& name, @@ -1641,6 +1799,10 @@ iotcon_connectivity_type_e IotconUtils::ToConnectivityType(const std::string& e) IOTCON_CONNECTIVITY_TYPE_E } +iotcon_response_result_e IotconUtils::ToResponseResult(const std::string& e) { + IOTCON_RESPONSE_RESULT_E +} + #undef X #undef XD diff --git a/src/iotcon/iotcon_utils.h b/src/iotcon/iotcon_utils.h index b8fb9345..e171dcfe 100644 --- a/src/iotcon/iotcon_utils.h +++ b/src/iotcon/iotcon_utils.h @@ -50,6 +50,8 @@ extern const std::string kDeviceId; extern const std::string kHostAddress; extern const std::string kConnectivityType; extern const std::string kResourceType; +extern const std::string kRepresentation; +extern const std::string kOptions; class ResourceInfo; class PresenceEvent; @@ -59,12 +61,14 @@ typedef std::map ResourceInfoMap; typedef std::shared_ptr PresenceEventPtr; typedef std::map PresenceMap; +using ResponsePtr = std::shared_ptr::type>; + struct ResourceInfo { long long id; iotcon_resource_h handle; std::set observers; common::PostCallback request_listener; - std::unordered_map unhandled_responses; + std::unordered_map pending_responses; std::set children; std::set parents; @@ -72,9 +76,6 @@ struct ResourceInfo { id(0), handle(nullptr) {} ~ResourceInfo() { iotcon_resource_destroy(handle); - for (auto& it : unhandled_responses) { - iotcon_response_destroy(it.second); - } } }; @@ -161,6 +162,10 @@ class IotconUtils { iotcon_state_h* out); static common::TizenResult StateListFromJson(const picojson::array& list, iotcon_list_h* out); + static common::TizenResult OptionsFromJson(const picojson::array& options, + iotcon_options_h* out); + static common::TizenResult RepresentationFromJson(const picojson::object& representation, + iotcon_representation_h* out); static common::TizenResult ConvertIotconError(int error); static std::string FromConnectivityType(iotcon_connectivity_type_e e); @@ -173,6 +178,7 @@ class IotconUtils { static iotcon_interface_e ToInterface(const std::string& e); static iotcon_connectivity_type_e ToConnectivityType(const std::string& e); static iotcon_qos_e ToQos(const std::string& e); + static iotcon_response_result_e ToResponseResult(const std::string& e); }; } // namespace iotcon