From: Inkyun Kil Date: Thu, 7 Oct 2021 08:24:45 +0000 (+0900) Subject: Implement C++ generator for cion X-Git-Tag: submit/tizen/20211028.054746~23^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=74bc2df904527a8c46deff23b222c9b85c64dd0c;p=platform%2Fcore%2Fappfw%2Ftidl.git Implement C++ generator for cion Change-Id: Ibce59d9424ad0ccf322c4c0babf9ae9446591098 Signed-off-by: Inkyun Kil --- diff --git a/idlc/gen_cion/cpp_cion_gen_base.cc b/idlc/gen_cion/cpp_cion_gen_base.cc new file mode 100644 index 00000000..96f428a7 --- /dev/null +++ b/idlc/gen_cion/cpp_cion_gen_base.cc @@ -0,0 +1,746 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "idlc/gen_cion/cpp_cion_gen_base.h" + +namespace { +#include "idlc/gen_cion/cpp_cion_gen_base_cb.h" +} + +namespace tidl { + +CppCionGeneratorBase::CppCionGeneratorBase(std::shared_ptr doc) + : Generator(doc) { + type_map_ = { + {"char", "char"}, {"int", "int"}, {"short", "short"}, + {"long", "long long"}, {"string", "std::string"}, {"bool", "bool"}, + {"list", "std::list"}, {"float", "float"}, {"double", "double"}, + {"file", "File"}, {"bundle", "Bundle"}, {"void", "void"}, + {"array", "std::vector"} + }; + + parcel_type_map_ = { + {"char", "byte"}, + {"int", "int32"}, + {"short", "int16"}, + {"long", "int64"}, + {"string", "string"}, + {"bool", "bool"}, + {"float", "float"}, + {"double", "double"}, + {"bundle", "bundle"}, + {"file", "string"}, + }; + + type_init_map_ = { + {"char", "0"}, + {"int", "0"}, + {"short", "0"}, + {"long", "0"}, + {"bool", "false"}, + {"float", "0.0f"}, + {"double", "0.0"}, + }; +} + +void CppCionGeneratorBase::GenStructuresForHeader(std::ofstream& stream) { + stream << CB_BUNDLE; + stream << CB_FILE; + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_STRUCTURE) + continue; + Structure& st = static_cast(*i); + GenStructureForHeader(stream, st); + stream << std::endl; + } +} + +void CppCionGeneratorBase::GenStructureForHeader(std::ofstream& stream, + const Structure& st) { + const char ctor[] = " $$();\n" \ + " $$($$);\n"; + const char variable[] = "$$\n"; + + stream << "class " << st.GetID() << " final "; + + GenBrace(stream, 0, [&]() { + stream << " public:" << NLine(1); + GenTemplate(ctor, stream, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + std::string str; + int n = 1; + for (auto& i : st.GetElements().GetElms()) { + if (n != 1) + str += ", "; + str += ConvertTypeToString(i->GetType()) + " " + i->GetID(); + n++; + } + return str; + }); + + stream << NLine(1); + for (auto& i : st.GetElements().GetElms()) { + GenSetter(stream, *i); + GenGetter(stream, *i); + stream << NLine(1); + } + + stream << " private:"; + GenTemplate(variable, stream, + [&]()->std::string { + std::string str; + for (auto& i : st.GetElements().GetElms()) { + str += NLine(1) + Tab(1) + + ConvertTypeToString(i->GetType()) + " " + + i->GetID() + "_"; + if (type_init_map_.find(i->GetType().ToString()) + == type_init_map_.end()) { + str += ";"; + } else { + str += " = " + type_init_map_[i->GetType().ToString()] + ";"; + } + } + str += NLine(1); + return str; + }); + }, false, false); + stream << ";" << NLine(1); +} + +void CppCionGeneratorBase::GenSetter(std::ofstream& stream, const Element& ele) { + const char setter[] = + "void Set$$($$ $$) {\n" \ + " $$_ = $$;\n" \ + "}\n"; + + GenTemplate(AddIndent(TAB_SIZE, setter, true), stream, + [&]()->std::string { + return ele.GetID(); + }, + [&]()->std::string { + return ConvertTypeToString(ele.GetType()); + }, + [&]()->std::string { + return ele.GetID(); + }, + [&]()->std::string { + return ele.GetID(); + }, + [&]()->std::string { + if (ele.GetType().IsUserDefinedType() || + ele.GetType().GetMetaType() != nullptr || + ele.GetType().ToString() == "string" || + ele.GetType().ToString() == "bundle" || + ele.GetType().ToString() == "file") { + return "std::move(" + ele.GetID() + ")"; + } + + return ele.GetID(); + }); + stream << NLine(1); +} + +void CppCionGeneratorBase::GenGetter(std::ofstream& stream, const Element& ele) { + const char getter[] = + "$$ Get$$() const {\n" \ + " return $$_;\n" \ + "}\n"; + + GenTemplate(AddIndent(TAB_SIZE, getter, true), stream, + [&]()->std::string { + if (ele.GetType().IsUserDefinedType() || + ele.GetType().GetMetaType() != nullptr || + ele.GetType().ToString() == "string" || + ele.GetType().ToString() == "bundle" || + ele.GetType().ToString() == "file") { + return "const " + ConvertTypeToString(ele.GetType()) + "&"; + } + + return ConvertTypeToString(ele.GetType()); + }, + [&]()->std::string { + return ele.GetID(); + }, + [&]()->std::string { + return ele.GetID(); + }); +} + +void CppCionGeneratorBase::GenStructuresForBody(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_STRUCTURE) + continue; + Structure& st = static_cast(*i); + GenStructureForBody(stream, st); + stream << std::endl; + } +} + +void CppCionGeneratorBase::GenStructureForBody(std::ofstream& stream, + const Structure& st) { + std::vector> v; + const char ctor[] = "##::##() {}\n\n" \ + "##::##($$)\n" \ + " : $$ {}"; + + for (auto& i : st.GetElements().GetElms()) { + std::pair p; + + p.first = ConvertTypeToString(i->GetType()); + p.second = i->GetID(); + v.push_back(p); + } + + GenTemplate(ReplaceAll(ctor, "##", st.GetID()), stream, + [&]()->std::string { + std::string str; + for (auto& i : v) { + str += i.first + " " + i.second; + + if (i != v.back()) + str += ", "; + } + return str; + }, + [&]()->std::string { + std::string str; + for (auto& i : v) { + str += i.second + "_(std::move(" + i.second + "))"; + + if (i != v.back()) + str += ", "; + } + return str; + }); + stream << NLine(2); +} + +void CppCionGeneratorBase::GenSerializer(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_STRUCTURE) + continue; + Structure& st = static_cast(*i); + GenSerializer(stream, st); + stream << NLine(1); + } +} + +void CppCionGeneratorBase::GenPrototype(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_STRUCTURE) + continue; + Structure& st = static_cast(*i); + GenSerializer(stream, st, true); + GenDeSerializer(stream, st, true); + } + GenListSerializer(stream, true); + stream << NLine(1); +} + +void CppCionGeneratorBase::GenSerializer(std::ofstream& stream, const Structure& st, + bool proto) { + const char parcel_str[] = "rpc_port_parcel_h"; + + stream << parcel_str << " operator << (" + << parcel_str << " h, const " << st.GetID() << "& param)"; + if (proto) { + stream << ";" << NLine(1); + return; + } + + stream << " "; + GenBrace(stream, 0, [&]() { + for (auto& i : st.GetElements().GetElms()) { + stream << AddIndent(TAB_SIZE, + ConvertTypeToSerializer(i->GetType(), + "param.Get" + i->GetID() + "()", "h")); + } + stream << Tab(1) << "return h;" << NLine(1); + }, false); +} + +void CppCionGeneratorBase::GenDeSerializer(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_STRUCTURE) + continue; + Structure& st = static_cast(*i); + GenDeSerializer(stream, st); + stream << std::endl; + } +} + +void CppCionGeneratorBase::GenDeSerializer(std::ofstream& stream, + const Structure& st, bool proto) { + const char parcel_str[] = "rpc_port_parcel_h"; + + stream << parcel_str << " operator >> (" + << parcel_str << " h, " << st.GetID() << "& param)"; + if (proto) { + stream << ";" << NLine(1); + return; + } + + stream << " "; + GenBrace(stream, 0, [&]() { + for (auto& i : st.GetElements().GetElms()) { + stream << AddIndent(TAB_SIZE, + ConvertTypeToDeserializer(i->GetType(), i->GetID(), "h")); + stream << Tab(1) << "param.Set" << i->GetID() << "(std::move(" + << i->GetID() << "));" << NLine(2); + } + stream << Tab(1) << "return h;" << NLine(1); + }, false); +} + +std::string CppCionGeneratorBase::ConvertTypeToString(const BaseType& type) { + if (type.IsUserDefinedType()) { + if (IsDelegateType(type)) { + return "std::unique_ptr<" + type.ToString() + ">"; + } + return type.ToString(); + } + + if (type.GetMetaType() != nullptr) + return type_map_[type.ToString()] + "<" + + ConvertTypeToString(*(type.GetMetaType())) + ">"; + + return type_map_[type.ToString()]; +} + +std::string CppCionGeneratorBase::Tab(int cnt) { + std::string t(cnt * 2, ' '); + + return t; +} + +std::string CppCionGeneratorBase::NLine(int cnt) { + std::string t(cnt, '\n'); + + return t; +} + +void CppCionGeneratorBase::AddSerializerList(const BaseType& type) { + if (type.GetMetaType() != nullptr) { + serializer_list_[ConvertTypeToString(type)] = &type; + AddSerializerList(*type.GetMetaType()); + } +} + +void CppCionGeneratorBase::GenListSerializer(std::ofstream& stream, + const BaseType& type, bool proto) { + stream << "rpc_port_parcel_h operator << (rpc_port_parcel_h h, const " + << ConvertTypeToString(type) << "& c)"; + + if (proto) { + stream << ";" << NLine(1); + stream << "rpc_port_parcel_h operator >> (rpc_port_parcel_h h, " + << ConvertTypeToString(type) << "& c);" << NLine(1); + return; + } + + stream << " "; + GenBrace(stream, 0, [&]() { + stream << Tab(1) + << "rpc_port_parcel_write_array_count(h, c.size());" + << NLine(1); + stream << Tab(1) << "for (const auto& i : c) "; + GenBrace(stream, TAB_SIZE, [&]() { + auto& mt = *type.GetMetaType(); + stream << AddIndent(TAB_SIZE * 2, ConvertTypeToSerializer(mt, "i", "h")); + }, false); + stream << Tab(1) << "return h;" << NLine(1); + }, false); + stream << NLine(1); + + stream << "rpc_port_parcel_h operator >> (rpc_port_parcel_h h, " + << ConvertTypeToString(type) << "& c) "; + GenBrace(stream, 0, [&]() { + stream << Tab(1) << "int l = 0;" << NLine(1); + stream << Tab(1) + << "rpc_port_parcel_read_array_count(h, &l);" << NLine(1); + stream << Tab(1) << "for (int i = 0; i < l; i++) "; + GenBrace(stream, TAB_SIZE, [&]() { + auto& mt = *type.GetMetaType(); + stream << AddIndent(TAB_SIZE * 2, + ConvertTypeToDeserializer(mt, "v", "h", true)); + stream << Tab(2) << "c.push_back(std::move(v));" << NLine(1); + }, false); + stream << Tab(1) << "return h;" << NLine(1); + }, false); +} + +void CppCionGeneratorBase::GenListSerializer(std::ofstream& stream, bool proto) { + serializer_list_.clear(); + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() == Block::TYPE_STRUCTURE) { + const Structure& st = static_cast(*i); + for (auto& j : st.GetElements().GetElms()) { + auto& t = j->GetType(); + AddSerializerList(t); + } + } else if (i->GetType() == Block::TYPE_INTERFACE) { + const Interface& iface = static_cast(*i); + for (auto& j : iface.GetDeclarations().GetDecls()) { + auto& t = j->GetType(); + AddSerializerList(t); + for (auto& k : j->GetParameters().GetParams()) { + auto& t1 = k->GetParameterType().GetBaseType(); + AddSerializerList(t1); + } + } + } + } + + for (auto& p : serializer_list_) { + const BaseType* t = p.second; + GenListSerializer(stream, *t, proto); + } +} + +void CppCionGeneratorBase::GenMethodId(std::ofstream& stream, + const Interface& iface) { + stream << Tab(1) << "enum class MethodId : int "; + GenBrace(stream, TAB_SIZE, [&]() { + int cnt = 2; + stream << Tab(2) << "__Result = 0," << NLine(1); + stream << Tab(2) << "__Callback = 1," << NLine(1); + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + stream << Tab(2) + << i->GetID() << " = " << cnt++ << "," << NLine(1); + } + }, false, false); + stream << ";" << NLine(2); +} + +void CppCionGeneratorBase::GenDelegateId(std::ofstream& stream, + const Interface& iface) { + stream << Tab(1) << "enum class DelegateId : int "; + GenBrace(stream, TAB_SIZE, [&]() { + int cnt = 1; + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + stream << Tab(2) + << i->GetID() << " = " << cnt++ << "," << NLine(1); + } + }, false, false); + stream << ";" << NLine(2); +} + +void CppCionGeneratorBase::GenParameters(std::ofstream& stream, + const Parameters& ps) { + stream << GetParameters(ps); +} + +std::string CppCionGeneratorBase::GetParameters(const Parameters& ps) { + bool first = true; + std::string ret; + for (auto& i : ps.GetParams()) { + if (!first) { + ret += ", "; + } + + std::string ref; + auto dir = i->GetParameterType().GetDirection(); + if (dir == ParameterType::Direction::OUT || + dir == ParameterType::Direction::REF) { + ref = "&"; + } + + ret += ConvertTypeToString(i->GetParameterType().GetBaseType()) + + ref + " " + i->GetID(); + first = false; + } + + return ret; +} + +void CppCionGeneratorBase::GenDeclaration(std::ofstream& stream, + const Interface& iface, + const Declaration& decl) { + stream << ConvertTypeToString(decl.GetType()) << " " << iface.GetID() << "::" + << decl.GetID() << "("; + GenParameters(stream, decl.GetParameters()); + stream << ") "; +} + +std::string CppCionGeneratorBase::GenPrivateSharingRequest(const BaseType& type, + std::string id) { + std::string ret; + if (type.GetMetaType() != nullptr && (type.GetMetaType()->GetFullName() == "file")) { + ret += std::string("for (const auto& i : " + id + ") {\n") + + std::string(" std::string name = i.GetFileName();\n") + + std::string(" FilePayloadSend(name, service_.lock()->GetPeer());\n") + + std::string("}\n"); + } else if (type.ToString() == "file") { + ret += std::string("std::string name = " + id + ".GetFileName();\n") + + std::string("FilePayloadSend(name, service_.lock()->GetPeer());\n"); + } + return ret; +} + +std::string CppCionGeneratorBase::ConvertTypeToSerializer( + const BaseType& type, std::string id, std::string parcel) { + std::string ret; + + if (type.ToString() == "string") { + ret += "rpc_port_parcel_write_" + + parcel_type_map_[type.ToString()] + + "(" + parcel + ", " + id + ".c_str());\n"; + } else if (type.ToString() == "file") { + ret += "rpc_port_parcel_write_" + + parcel_type_map_[type.ToString()] + + "(" + parcel + ", " + id + ".GetFileName()" + ".c_str());\n"; + } else if (type.ToString() == "bundle") { + ret += "rpc_port_parcel_write_bundle(" + parcel + ", " + + id + ".GetHandle());\n"; + } else if (type.GetMetaType() || type.IsUserDefinedType()) { + if (type.IsUserDefinedType() && IsDelegateType(type)) + ret += parcel + " << *" + id + ";\n"; + else + ret += parcel + " << " + id + ";\n"; + } else { + ret += "rpc_port_parcel_write_" + + parcel_type_map_[type.ToString()] + + "(" + parcel + ", " + id + ");\n"; + } + + return ret; +} + +std::string CppCionGeneratorBase::ConvertTypeToDeserializer( + const BaseType& type, std::string id, std::string parcel, + bool make_new_type) { + std::string ret; + + if (type.ToString() == "string") { + ret += "char* " + id + "_raw = nullptr;\n"; + ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()] + + "(" + parcel + ", &" + id + "_raw);\n"; + if (make_new_type) { + ret += "std::string " + id + "(" + id + "_raw);\n"; + } else { + ret += id + " = " + id + "_raw;\n"; + } + ret += "free(" + id + "_raw);\n"; + } else if (type.ToString() == "file") { + ret += "char* " + id + "_raw = nullptr;\n"; + ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()] + + "(" + parcel + ", &" + id + "_raw);\n"; + if (make_new_type) { + ret += "File " + id + "(" + id + "_raw);\n"; + } else { + ret += id + " = " + id + "_raw;\n" + + "free(" + id + "_raw);\n"; + } + } else if (type.ToString() == "bundle") { + ret += "bundle* " + id + "_raw = nullptr;\n"; + ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()] + + "(" + parcel + ", &" + id + "_raw);\n"; + if (make_new_type) { + ret += "Bundle " + id + "(" + id + "_raw);\n"; + } else { + ret += id + " = " + id + "_raw;\n"; + } + } else if (type.GetMetaType() != nullptr || type.IsUserDefinedType()) { + std::string n; + + if (type.GetMetaType() != nullptr || IsDelegateType(type)) + n = ConvertTypeToString(type); + else + n = type.ToString(); + + if (make_new_type) { + ret += n + " "; + if (IsDelegateType(type)) { + ret += id + "(new " + type.ToString() + + "(std::weak_ptr(b), stub->cion_server_));\n"; + } else { + ret += id + ";\n"; + } + } + if (IsDelegateType(type)) + ret += parcel + " >> *" + id + ";\n"; + else + ret += parcel + " >> " + id + ";\n"; + } else { + if (make_new_type) + ret += ConvertTypeToString(type) + " " + id + ";\n"; + ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()] + + "(" + parcel + ", &" + id + ");\n"; + } + + return ret; +} + +void CppCionGeneratorBase::GenBodyCallbacks(std::ofstream& stream, + const Interface& iface, bool is_proxy) { + stream << ReplaceAll(CB_CALLBACK_BASE, "##", iface.GetID()); + + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + GenBodyCallback(stream, iface, *i, is_proxy); + } +} + +void CppCionGeneratorBase::GenBodyCallback(std::ofstream& stream, + const Interface& iface, const Declaration& decl, bool is_proxy) { + if (!is_proxy) { + GenTemplate(CB_CALLBACK_FILE_PAYLOAD_SEND, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + }); + + GenTemplate(CB_CALLBACK_INVOKE_METHOD, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + }, + [&]()->std::string { + return GetParameters(decl.GetParameters()); + }, + [&]()->std::string { + std::string m; + for (auto& i : decl.GetParameters().GetParams()) { + auto& pt = i->GetParameterType(); + m += AddIndent(TAB_SIZE, + GenPrivateSharingRequest(pt.GetBaseType(), i->GetID())); + m += AddIndent(TAB_SIZE, + ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p")); + } + return m; + }); + } else { + GenTemplate(CB_CALLBACK_ON_RECEIVED_EVENT_METHOD, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return decl.GetID(); + }, + [&]()->std::string { + int cnt = 1; + std::string ret; + for (auto& i : decl.GetParameters().GetParams()) { + std::string v = "param" + std::to_string(cnt); + std::string c = ConvertTypeToDeserializer( + i->GetParameterType().GetBaseType(), v, "parcel"); + ret += AddIndent(TAB_SIZE, c) + NLine(1); + cnt++; + } + + cnt = 1; + ret += Tab(1) + "OnReceived("; + for (int i = 0; i < decl.GetParameters().GetParams().size(); i++) { + if (cnt != 1) { + ret += ", "; + } + ret += "std::move(param" + std::to_string(cnt) + ")"; + cnt++; + } + ret += ");"; + + return ret; + }); + } +} + +void CppCionGeneratorBase::GenHeaderCallbacks(std::ofstream& stream, + const Interface& iface, + bool is_proxy) { + stream << CB_CALLBACK_BASE_HEADER_FRONT; + if (is_proxy) { + stream << Tab(1) + << " virtual void OnReceivedEvent(rpc_port_parcel_h port) = 0;;" + << NLine(1); + } + stream << CB_CALLBACK_BASE_HEADER_BACK; + + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + GenHeaderCallback(stream, *i, is_proxy); + } +} + +void CppCionGeneratorBase::GenHeaderCallback(std::ofstream& stream, + const Declaration& decl, + bool is_proxy) { + stream << GenTemplateString(CB_CALLBACK_CLASS, + [&]()->std::string { + return decl.GetID(); + }, + [&]()->std::string { + return ReplaceAll( + is_proxy ? CB_CALLBACK_CTOR_PROXY : CB_CALLBACK_CTOR_STUB, + "##", decl.GetID()); + }, + [&]()->std::string { + std::string ret; + if (is_proxy) { + ret = Tab(2) + "virtual void OnReceived(" + + GetParameters(decl.GetParameters()) + + ") {}" + NLine(1); + } else { + ret = Tab(2) + "void Invoke(" + + GetParameters(decl.GetParameters()) + + ");" + NLine(1); + } + + return ret; + }, + [&]()->std::string { + return is_proxy ? CB_CALLBACK_PRIVATE_PROXY : CB_CALLBACK_PRIVATE_STUB; + }); +} + +void CppCionGeneratorBase::GenVersion(std::ofstream& stream) { + GenTemplate(CB_VERSION, stream, + [&]()->std::string { + return FULLVER; + }); +} + +void CppCionGeneratorBase::GenLogTag(std::ofstream& stream, std::string id) { + GenTemplate(CB_LOG_TAG, stream, + [&]()->std::string { + return id; + }); +} + +void CppCionGeneratorBase::GenLogDefinition(std::ofstream& stream) { + stream << CB_LOG_DEF; +} + +} // namespace tidl diff --git a/idlc/gen_cion/cpp_cion_gen_base.h b/idlc/gen_cion/cpp_cion_gen_base.h new file mode 100644 index 00000000..d710c77b --- /dev/null +++ b/idlc/gen_cion/cpp_cion_gen_base.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_GEN_BASE_H_ +#define IDLC_CPP_CION_GEN_CPP_GEN_BASE_H_ + +#include +#include +#include + +#include "idlc/ast/type.h" +#include "idlc/ast/structure.h" +#include "idlc/gen/generator.h" + +namespace tidl { + +class CppCionGeneratorBase : public Generator { + public: + explicit CppCionGeneratorBase(std::shared_ptr doc); + virtual ~CppCionGeneratorBase() = default; + + void GenVersion(std::ofstream& stream); + void GenStructuresForHeader(std::ofstream& stream); + void GenStructuresForBody(std::ofstream& stream); + void GenSerializer(std::ofstream& stream); + void GenDeSerializer(std::ofstream& stream); + void GenListSerializer(std::ofstream& stream, bool proto = false); + void GenPrototype(std::ofstream& stream); + void GenMethodId(std::ofstream& stream, const Interface& iface); + void GenDelegateId(std::ofstream& stream, const Interface& iface); + void GenParameters(std::ofstream& stream, const Parameters& ps); + void GenDeclaration(std::ofstream& stream, const Interface& iface, + const Declaration& decl); + void GenBodyCallbacks(std::ofstream& stream, const Interface& iface, + bool is_proxy); + void GenHeaderCallbacks(std::ofstream& stream, const Interface& iface, + bool is_proxy); + std::string ConvertTypeToString(const BaseType& type); + std::string Tab(int cnt); + std::string NLine(int cnt); + std::string ConvertTypeToDeserializer(const BaseType& type, + std::string id, std::string parcel, + bool make_new_type = true); + std::string ConvertTypeToSerializer(const BaseType& type, + std::string id, std::string parcel); + std::string GenPrivateSharingRequest(const BaseType& type, std::string id); + std::string GetParameters(const Parameters& ps); + void GenLogTag(std::ofstream& stream, std::string id); + void GenLogDefinition(std::ofstream& stream); + + private: + void GenSetter(std::ofstream& stream, const Element& ele); + void GenGetter(std::ofstream& stream, const Element& ele); + void AddSerializerList(const BaseType& type); + void GenListSerializer(std::ofstream& stream, const BaseType& type, + bool proto = false); + void GenDeSerializer(std::ofstream& stream, const Structure& st, + bool proto = false); + void GenSerializer(std::ofstream& stream, const Structure& st, + bool proto = false); + void GenStructureForHeader(std::ofstream& stream, const Structure& st); + void GenStructureForBody(std::ofstream& stream, const Structure& st); + void GenBodyCallback(std::ofstream& stream, const Interface& iface, + const Declaration& decl, bool is_proxy); + void GenHeaderCallback(std::ofstream& stream, const Declaration& decl, + bool is_proxy); + + protected: + const int TAB_SIZE = 2; + + private: + std::map type_map_; + std::map parcel_type_map_; + std::map type_init_map_; + std::map serializer_list_; +}; + +} // namespace tidl + +#endif // IDLC_CPP_CION_GEN_CPP_GEN_BASE_H_ diff --git a/idlc/gen_cion/cpp_cion_gen_base_cb.h b/idlc/gen_cion/cpp_cion_gen_base_cb.h new file mode 100644 index 00000000..ab9354d8 --- /dev/null +++ b/idlc/gen_cion/cpp_cion_gen_base_cb.h @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_GEN_BASE_CB_H_ +#define IDLC_CPP_CION_GEN_CPP_GEN_BASE_CB_H_ + +const char CB_BUNDLE[] = R"__cls_bundle(class Bundle final { + public: + Bundle() { + raw_ = bundle_create(); + } + + Bundle(bundle* b) { + raw_ = b; + } + + ~Bundle() { + if (raw_) + bundle_free(raw_); + } + + Bundle(Bundle&& b) : raw_(b.raw_) { + b.raw_ = nullptr; + } + + Bundle& operator = (Bundle&& b) { + if (this != &b) { + if (raw_) + bundle_free(raw_); + + raw_ = b.raw_; + b.raw_ = nullptr; + } + return *this; + } + + Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {} + + Bundle& operator = (const Bundle& b) { + if (this != &b) { + if (raw_) + bundle_free(raw_); + + raw_ = bundle_dup(b.GetHandle()); + } + return *this; + } + + bundle* GetHandle() const { + return raw_; + } + + private: + bundle* raw_; +}; + +)__cls_bundle"; + +const char CB_FILE[] = R"__cls_file(class File final { + public: + File() { + } + + File(std::string filename) { + filename_ = filename; + } + + std::string GetFileName() const { + return filename_; + } + + private: + std::string filename_; +}; + +)__cls_file"; + +const char CB_CALLBACK_BASE[] = +R"__cpp_cb( +std::atomic ##::CallbackBase::seq_num_ { 0 }; + +##::CallbackBase::CallbackBase(int delegate_id, bool once) + : id_(delegate_id), once_(once) { + seq_id_ = seq_num_++; +} + +int ##::CallbackBase::GetId() const { + return id_; +} + +int ##::CallbackBase::GetSeqId() const { + return seq_id_; +} + +bool ##::CallbackBase::IsOnce() const { + return once_; +} + +std::string ##::CallbackBase::GetTag() const { + return std::to_string(id_) + "::" + std::to_string(seq_id_); +} + +rpc_port_parcel_h operator << (rpc_port_parcel_h h, const ##::CallbackBase& cb) { + rpc_port_parcel_write_int32(h, cb.id_); + rpc_port_parcel_write_int32(h, cb.seq_id_); + rpc_port_parcel_write_bool(h, cb.once_); + + return h; +} + +rpc_port_parcel_h operator >> (rpc_port_parcel_h h, ##::CallbackBase& cb) { + rpc_port_parcel_read_int32(h, &cb.id_); + rpc_port_parcel_read_int32(h, &cb.seq_id_); + rpc_port_parcel_read_bool(h, &cb.once_); + + return h; +} +)__cpp_cb"; + +const char CB_VERSION[] = +R"__cpp_cb(/* + * Generated by tidlc $$. + */ +)__cpp_cb"; + +const char CB_CALLBACK_BASE_HEADER_FRONT[] = +R"__cpp_cb( + class CallbackBase { + public: + CallbackBase(int delegate_id, bool once); + virtual ~CallbackBase() = default; +)__cpp_cb"; + +const char CB_CALLBACK_BASE_HEADER_BACK[] = +R"__cpp_cb( + int GetId() const; + int GetSeqId() const; + bool IsOnce() const; + std::string GetTag() const; + + private: + friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb); + friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb); + + static std::atomic seq_num_; + int id_; + int seq_id_; + bool once_; + }; +)__cpp_cb"; + +const char CB_CALLBACK_CLASS[] = +R"__cpp_cb( + class $$ : public CallbackBase { + public:$$ +$$ + private:$$ + }; +)__cpp_cb"; + +const char CB_CALLBACK_CTOR_STUB[] = +R"__cpp_cb( + ##(std::weak_ptr service, cion_server_h cion_server) + : CallbackBase(static_cast(DelegateId::##), false) { + service_ = std::move(service); + cion_server_ = cion_server; + } +)__cpp_cb"; + +const char CB_CALLBACK_CTOR_PROXY[] = +R"__cpp_cb( + ##(bool once = false) + : CallbackBase(static_cast(DelegateId::##), once) {} +)__cpp_cb"; + +const char CB_CALLBACK_PRIVATE_PROXY[] = +R"__cpp_cb( + void OnReceivedEvent(rpc_port_parcel_h parcel) override; +)__cpp_cb"; + +const char CB_CALLBACK_PRIVATE_STUB[] = +R"__cpp_cb( + void FilePayloadSend(std::string path, cion_peer_info_h peer); + + std::weak_ptr service_; + bool valid_ = true; + cion_server_h cion_server_; +)__cpp_cb"; + +const char CB_CALLBACK_FILE_PAYLOAD_SEND[] = R"__cpp_cb( +void $$::$$::FilePayloadSend(std::string path, cion_peer_info_h peer) +{ + cion_payload_h pl; + int ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_FILE); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_create : %d", ret); + return; + } + + ret = cion_payload_set_file_path(pl, path.c_str()); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_set_file_path : %d - %s", ret, path.c_str()); + cion_payload_destroy(pl); + return; + } + + ret = cion_server_send_payload_async(cion_server_, peer, pl, nullptr, nullptr); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_send_payload_async : %d", ret); + cion_payload_destroy(pl); + return; + } + + cion_payload_destroy(pl); +} +)__cpp_cb"; + +const char CB_CALLBACK_INVOKE_METHOD[] = +R"__cpp_cb( +void $$::$$::Invoke($$) { + if (service_.lock().get() == nullptr) + throw NotConnectedSocketException(); + + if (IsOnce() && !valid_) + throw InvalidCallbackException(); + + rpc_port_parcel_h p; + rpc_port_parcel_create(&p); + rpc_port_parcel_write_int32(p, static_cast(MethodId::__Callback)); + p << *this; +$$ + // Send + unsigned int size; + char *data; + + int ret = rpc_port_parcel_get_raw(p, (void **)&data, &size); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to get raw. error(%d)", ret); + rpc_port_parcel_destroy(p); + throw InvalidIOException(); + } + + cion_payload_h pl; + ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_DATA); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_create : %d", ret); + rpc_port_parcel_destroy(p); + return; + } + + ret = cion_payload_set_data(pl, (const unsigned char*)data, size); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_set_data : %d", ret); + rpc_port_parcel_destroy(p); + cion_payload_destroy(pl); + return; + } + + ret = cion_server_send_payload_async(cion_server_, service_.lock()->GetPeer(), pl, nullptr, nullptr); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_client_send_payload_async : %d", ret); + rpc_port_parcel_destroy(p); + cion_payload_destroy(pl); + return; + } + + rpc_port_parcel_destroy(p); + cion_payload_destroy(pl); + valid_ = false; +} +)__cpp_cb"; + +const char CB_CALLBACK_ON_RECEIVED_EVENT_METHOD[] = +R"__cpp_cb( +void $$::$$::OnReceivedEvent(rpc_port_parcel_h parcel) { +$$ +} +)__cpp_cb"; + +const char CB_LOG_TAG[] = +R"__cpp_cb( +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "$$" +)__cpp_cb"; + +const char CB_LOG_DEF[] = +R"__cpp_cb( +#ifdef _E +#undef _E +#endif + +#ifdef _W +#undef _W +#endif + +#ifdef _I +#undef _I +#endif + +#ifdef _D +#undef _D +#endif + +#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__) +)__cpp_cb"; + +#endif // IDLC_CPP_CION_GEN_CPP_GEN_BASE_CB_H_ diff --git a/idlc/gen_cion/cpp_cion_proxy_body_gen.cc b/idlc/gen_cion/cpp_cion_proxy_body_gen.cc new file mode 100644 index 00000000..5ea467db --- /dev/null +++ b/idlc/gen_cion/cpp_cion_proxy_body_gen.cc @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "idlc/gen_cion/cpp_cion_proxy_body_gen.h" + +namespace { +#include "idlc/gen_cion/cpp_cion_proxy_body_gen_cb.h" +} + +namespace tidl { + +CppCionProxyBodyGen::CppCionProxyBodyGen(std::shared_ptr doc) + : CppCionGeneratorBase(doc) {} + +void CppCionProxyBodyGen::OnInitGen(std::ofstream& stream) { + std::string key(".cc"); + std::string header_file = FileName; + + std::size_t found = header_file.rfind(key); + if (found != std::string::npos) + header_file.replace(found, key.length(), ".h"); + + GenVersion(stream); + stream << NLine(1); + stream << "#include " << NLine(1) + << "#include " << NLine(1) + << "#include " << NLine(1) + << NLine(1) + << "#include \"" << header_file << "\"" << NLine(2); + GenLogTag(stream, "CION_PROXY"); + GenLogDefinition(stream); + stream << NLine(1); + GenNamespace(stream); +} + +void CppCionProxyBodyGen::OnFiniGen(std::ofstream& stream) { +} + +void CppCionProxyBodyGen::GenNamespace(std::ofstream& stream) { + stream << "namespace cion "; + GenBrace(stream, 0, [&]() { + stream << "namespace " << GetFileNamespace() << " "; + GenBrace(stream, 0, [&]() { + stream << NLine(1); + GenStructuresForBody(stream); + stream << "namespace proxy "; + GenBrace(stream, 0, [&]() { + GenPrototype(stream); + GenSerializer(stream); + GenDeSerializer(stream); + GenListSerializer(stream); + GenInterfaces(stream); + }, false, false); + stream << " // namespace proxy" + NLine(1); + }, false, false); + stream << " // namespace " + GetFileNamespace() + NLine(1); + }, false, false); + stream << " // namespace rpc_port" + NLine(1); +} + +void CppCionProxyBodyGen::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + Interface& iface = static_cast(*i); + GenInterface(stream, iface); + } +} + +void CppCionProxyBodyGen::GenInterface(std::ofstream& stream, + const Interface& iface) { + GenFilePayloadSend(stream, iface); + GenBodyCallbacks(stream, iface, true); + GenConstructor(stream, iface); + GenDestructor(stream, iface); + GenHelperMethods(stream, iface); + GenMethods(stream, iface); +} + +void CppCionProxyBodyGen::GenConstructor(std::ofstream& stream, + const Interface& iface) { + GenTemplate(CB_PROXY_INTERFACE_CTOR, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }); +} + +void CppCionProxyBodyGen::GenDestructor(std::ofstream& stream, + const Interface& iface) { + GenTemplate(CB_DTOR, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }); +} + +void CppCionProxyBodyGen::GenHelperMethods(std::ofstream& stream, + const Interface& iface) { + stream << ReplaceAll(CB_PROXY_HELPER_METHODS, "##", iface.GetID()) + << NLine(1); +} + +void CppCionProxyBodyGen::GenMethods(std::ofstream& stream, + const Interface& iface) { + auto& decls = iface.GetDeclarations(); + + for (auto& i : decls.GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + GenDeclaration(stream, iface, *i); + GenBrace(stream, 0, [&]() { + GenInvocation(stream, *i); + }, false); + stream << NLine(1); + } +} + +std::string CppCionProxyBodyGen::GenPrivateSharingRequestProxy(const BaseType& type, + std::string id) { + std::string ret; + if (type.GetMetaType() != nullptr && (type.GetMetaType()->GetFullName() == "file")) { + ret += std::string("for (const auto& i : " + id + ") {\n") + + std::string(" std::string name = i.GetFileName();\n") + + std::string(" FilePayloadSend(name);\n") + + std::string("}\n"); + } else if (type.ToString() == "file") { + ret += std::string("std::string name = " + id + ".GetFileName();\n") + + std::string("FilePayloadSend(name);\n"); + } + return ret; +} + +void CppCionProxyBodyGen::GenFilePayloadSend(std::ofstream& stream, + const Interface& iface) { + GenTemplate(CB_PROXY_FILE_PAYLOAD_SEND, stream, + [&]()->std::string { + return iface.GetID(); + }); +} + +void CppCionProxyBodyGen::GenInvocation(std::ofstream& stream, + const Declaration& decl) { + stream << CB_INVOCATION_PRE; + + // Serialize + stream << Tab(1) + << "rpc_port_parcel_write_int32(p, static_cast(MethodId::" + << decl.GetID() << "));" << NLine(1); + std::string m; + std::string l; + for (auto& i : decl.GetParameters().GetParams()) { + auto& pt = i->GetParameterType(); + if (pt.GetDirection() == ParameterType::Direction::OUT) + continue; + m += ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p"); + if (IsDelegateType(pt.GetBaseType())) { + l += "delegate_list_.emplace_back(" + i->GetID() + ".release());\n"; + } + } + stream << AddIndent(TAB_SIZE, m) << NLine(1); + + if (decl.GetMethodType() == Declaration::MethodType::SYNC) { + stream << Tab(1) << "unsigned char *return_data;" << NLine(1); + stream << Tab(1) << "unsigned int return_data_size = 0;" << NLine(1); + } + stream << Tab(1) << "do "; + GenBrace(stream, TAB_SIZE, [&]() { + stream << Tab(2) << "std::lock_guard lock(mutex_);" + << NLine(2); + if (!l.empty()) + stream << AddIndent(TAB_SIZE * 2, l); + if (decl.GetMethodType() == Declaration::MethodType::SYNC) + stream << CB_INVOCATION_SYNC_MID << NLine(1); + else if (decl.GetMethodType() == Declaration::MethodType::ASYNC) + stream << CB_INVOCATION_ASYNC_MID << NLine(1); + }, false, false); + stream << " while (false);" << NLine(1); + + // Deserialize + if (decl.GetMethodType() == Declaration::MethodType::ASYNC) { + stream << Tab(1) << "rpc_port_parcel_destroy(p);" + << NLine(1); + return; + } + + stream << CB_INVOCATION_RECEIVE << NLine(1); + for (auto& i : decl.GetParameters().GetParams()) { + if (i->GetParameterType().GetDirection() == ParameterType::Direction::IN) { + continue; + } + + std::string c = ConvertTypeToDeserializer( + i->GetParameterType().GetBaseType(), + i->GetID(), "parcel_received", false); + if (c != "") + stream << AddIndent(TAB_SIZE, c); + } + + if (decl.GetType().ToString() != "void") { + stream << AddIndent(TAB_SIZE, + ConvertTypeToDeserializer(decl.GetType(), + "ret", "parcel_received")); + } + + std::string f; + for (auto& i : decl.GetParameters().GetParams()) { + auto& pt = i->GetParameterType(); + if (pt.GetDirection() == ParameterType::Direction::OUT) + continue; + f += GenPrivateSharingRequestProxy(pt.GetBaseType(), i->GetID()); + } + stream << AddIndent(TAB_SIZE, f) << NLine(1); + + stream << CB_INVOCATION_END; +} + +} // namespace tidl diff --git a/idlc/gen_cion/cpp_cion_proxy_body_gen.h b/idlc/gen_cion/cpp_cion_proxy_body_gen.h new file mode 100644 index 00000000..da42e1a7 --- /dev/null +++ b/idlc/gen_cion/cpp_cion_proxy_body_gen.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_PROXY_BODY_GEN_H_ +#define IDLC_CPP_CION_GEN_CPP_PROXY_BODY_GEN_H_ + +#include +#include + +#include "idlc/gen_cion/cpp_cion_gen_base.h" + +namespace tidl { + +class CppCionProxyBodyGen : public CppCionGeneratorBase { + public: + explicit CppCionProxyBodyGen(std::shared_ptr doc); + virtual ~CppCionProxyBodyGen() = default; + + void OnInitGen(std::ofstream& stream) override; + void OnFiniGen(std::ofstream& stream) override; + + private: + void GenNamespace(std::ofstream& stream); + void GenStructures(std::ofstream& stream); + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + void GenConstructor(std::ofstream& stream, const Interface& iface); + void GenDestructor(std::ofstream& stream, const Interface& iface); + void GenHelperMethods(std::ofstream& stream, const Interface& iface); + void GenMethods(std::ofstream& stream, const Interface& iface); + void GenFilePayloadSend(std::ofstream& stream, const Interface& iface); + void GenInvocation(std::ofstream& stream, const Declaration& decl); + + std::string GenPrivateSharingRequestProxy(const BaseType& type, std::string id); +}; + +} // namespace tidl + +#endif // IDLC_CPP_CION_GEN_CPP_PROXY_BODY_GEN_H_ diff --git a/idlc/gen_cion/cpp_cion_proxy_body_gen_cb.h b/idlc/gen_cion/cpp_cion_proxy_body_gen_cb.h new file mode 100644 index 00000000..c95685f3 --- /dev/null +++ b/idlc/gen_cion/cpp_cion_proxy_body_gen_cb.h @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_GEN_CION_CPP_PROXY_BODY_GEN_CB_H_ +#define IDLC_CPP_GEN_CION_CPP_PROXY_BODY_GEN_CB_H_ + +const char CB_DTOR[] = +R"__cpp_cb( +$$::~$$() { +} +)__cpp_cb"; + +const char CB_INVOCATION_PRE[] = +R"__cpp_cb( rpc_port_parcel_h p; + rpc_port_parcel_create(&p); +)__cpp_cb"; + +const char CB_INVOCATION_SYNC_MID[] = +R"__cpp_cb( + // SendData(SYNC) + unsigned int size; + char *data; + + int ret = rpc_port_parcel_get_raw(p, (void **)&data, &size); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to get raw. error(%d)", ret); + rpc_port_parcel_destroy(p); + throw InvalidIOException(); + } + + ret = cion_client_send_data(cion_client_, (unsigned char *)data, size, + 100, &return_data, &return_data_size); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to cion_client_send_data : error(%d)", ret); + rpc_port_parcel_destroy(p); + throw InvalidIOException(); + } + +)__cpp_cb"; + +const char CB_INVOCATION_ASYNC_MID[] = +R"__cpp_cb( + // SendPayloadAsync + unsigned int size; + char *data; + + int ret = rpc_port_parcel_get_raw(p, (void **)&data, &size); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to get raw. error(%d)", ret); + rpc_port_parcel_destroy(p); + throw InvalidIOException(); + } + + cion_payload_h pl; + ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_DATA); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_create : %d", ret); + rpc_port_parcel_destroy(p); + throw InvalidIOException(); + } + + ret = cion_payload_set_data(pl, (const unsigned char*)data, size); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_set_data : %d", ret); + rpc_port_parcel_destroy(p); + cion_payload_destroy(pl); + throw InvalidIOException(); + } + + ret = cion_client_send_payload_async(cion_client_, pl, nullptr, nullptr); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_client_send_payload_async : %d", ret); + rpc_port_parcel_destroy(p); + cion_payload_destroy(pl); + throw InvalidIOException(); + } +)__cpp_cb"; + +const char CB_INVOCATION_RECEIVE[] = +R"__cpp_cb( + if (return_data_size == 0) { + _E("Invalid protocol"); + rpc_port_parcel_destroy(p); + throw InvalidProtocolException(); + } + + rpc_port_parcel_h parcel_received; + rpc_port_parcel_create_from_raw(&parcel_received, return_data, + return_data_size); + + int cmd; + rpc_port_parcel_read_int32(parcel_received, &cmd); + if (cmd != static_cast(MethodId::__Result)) { + _E("Invalid result cmd"); + rpc_port_parcel_destroy(p); + rpc_port_parcel_destroy(parcel_received); + throw InvalidProtocolException(); + } +)__cpp_cb"; + +const char CB_INVOCATION_END[] = +R"__cpp_cb( + rpc_port_parcel_destroy(p); + rpc_port_parcel_destroy(parcel_received); + + return ret; +)__cpp_cb"; + +const char CB_PROXY_FILE_PAYLOAD_SEND[] = R"__cpp_cb( +void $$::FilePayloadSend(std::string path) +{ + cion_payload_h pl; + int ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_FILE); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_create : %d", ret); + return; + } + + ret = cion_payload_set_file_path(pl, path.c_str()); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_set_file_path : %d - %s", ret, path.c_str()); + cion_payload_destroy(pl); + return; + } + + ret = cion_server_send_payload_async(cion_client_, peer_, pl, nullptr, nullptr); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_send_payload_async : %d", ret); + cion_payload_destroy(pl); + return; + } + + cion_payload_destroy(pl); +} +)__cpp_cb"; + +const char CB_PROXY_HELPER_METHODS[] = +R"__cpp_cb( +void ##::Connect() { + if (peer_) { + int ret = cion_client_connect(cion_client_, peer_); + if (ret != CION_ERROR_NONE) { + _E("Failed to connect to stub. error(%d)", ret); + return; + } + } + else { + _E("Not discovered"); + } +} + +void ##::DisposeCallback(const std::string& tag) { + for (auto& i : delegate_list_) { + if (i->GetTag() == tag) { + delegate_list_.remove(i); + return; + } + } +} + +void ##::ProcessReceivedEvent(rpc_port_parcel_h parcel) { + int id = 0; + int seq_id = 0; + bool once = false; + + rpc_port_parcel_read_int32(parcel, &id); + rpc_port_parcel_read_int32(parcel, &seq_id); + rpc_port_parcel_read_bool(parcel, &once); + + for (auto& i : delegate_list_) { + if (i->GetId() == id && i->GetSeqId() == seq_id) { + i->OnReceivedEvent(parcel); + if (i->IsOnce()) + delegate_list_.remove(i); + break; + } + } +} + +void ##::Disconnect() { +} + +void ##::Discovery() { + int ret = cion_client_try_discovery(cion_client_, OnDiscoveredCB, nullptr); + if (ret != CION_ERROR_NONE) { + _E("Failed to discovery to stub. error(%d)", ret); + return; + } +} + +void ##::StopDiscovery() { + int ret = cion_client_stop_discovery(cion_client_); + if (ret != CION_ERROR_NONE) { + _E("Failed to stop discovery. error(%d)", ret); + return; + } +} + +void ##::OnConnectionResultCB(const char *service_name, + const cion_peer_info_h peer_info, const cion_connection_result_h result, + void *user_data) { + ## *cl = static_cast<##*>(user_data); + cion_connection_status_e status; + int ret = cion_connection_result_get_status(result, &status); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_connection_result_get_status. error(%d)", ret); + return; + } + + if (status == CION_CONNECTION_STATUS_OK) + cl->listener_->OnConnected(); + else if (status == CION_CONNECTION_STATUS_REJECTED) + cl->listener_->OnRejected(); +} + +void ##::OnDisconnectedCB(const char *service_name, + const cion_peer_info_h peer_info, void *user_data) { + ## *cl = static_cast<##*>(user_data); + cl->delegate_list_.clear(); + cl->listener_->OnDisconnected(); +} + +void ##::OnDiscoveredCB(const char *service_name, + const cion_peer_info_h peer_info, void *user_data) { + ## *cl = static_cast<##*>(user_data); + char *app_id; + int ret = cion_peer_info_get_app_id(peer_info, &app_id); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_peer_info_get_app_id. error(%d)", ret); + return; + } + + if (std::string(app_id) == cl->target_appid_) { + ret = cion_peer_info_clone(peer_info, &cl->peer_); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_peer_info_clone. error(%d)", ret); + return; + } + + cl->listener_->OnDiscovered(); + } +} + +void ##::OnPayloadAsyncResultCB(const cion_payload_async_result_h result, + void *user_data) { + + } + +void ##::OnPayloadReceivedCB(const char *service_name, + const cion_peer_info_h peer_info, const cion_payload_h payload, + cion_payload_transfer_status_e status, + void *user_data) { + ## *cl = static_cast<##*>(user_data); + char *app_id; + int ret = cion_peer_info_get_app_id(peer_info, &app_id); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_peer_info_get_app_id. error(%d)", ret); + return; + } + + if (std::string(app_id) != cl->target_appid_) { + _E("peer is wrong"); + return; + } + + cion_payload_type_e type; + ret = cion_payload_get_type(payload, &type); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_get_type. error(%d)", ret); + return; + } + + if (type == CION_PAYLOAD_TYPE_FILE) { + cl->listener_->OnFileReceived(payload, peer_info, status); + return; + } + + unsigned char *data; + unsigned int size; + ret = cion_payload_get_data(payload, &data, &size); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_get_data. error(%d)", ret); + return; + } + + rpc_port_parcel_h parcel_received; + rpc_port_parcel_create_from_raw(&parcel_received, data, size); + + int cmd; + rpc_port_parcel_read_int32(parcel_received, &cmd); + if (cmd != static_cast(MethodId::__Callback)) { + rpc_port_parcel_destroy(parcel_received); + return; + } + + cl->ProcessReceivedEvent(parcel_received); + rpc_port_parcel_destroy(parcel_received); +} +)__cpp_cb"; + +const char CB_PROXY_INTERFACE_CTOR[] = +R"__cpp_cb( +$$::$$(IEventListener* listener, const std::string& service_name, + const std::string& target_appid) + : listener_(listener), service_name_(service_name), + target_appid_(target_appid) { + cion_security_h security; + int ret = cion_security_create(&security); + if (ret != CION_ERROR_NONE) { + _E("Failed to create security handle. error(%d)", ret); + throw InvalidIOException(); + } + + ret = cion_client_create(&cion_client_, service_name.c_str(), security); + if (ret != CION_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + throw InvalidIOException(); + } + + ret = cion_client_add_disconnected_cb(cion_client_, OnDisconnectedCB, + this); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_client_add_disconnected_cb. error(%d)", ret); + throw InvalidIOException(); + } + + + ret = cion_client_add_connection_result_cb(cion_client_, OnConnectionResultCB, + this); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_client_add_connection_result_cb. error(%d)", ret); + throw InvalidIOException(); + } + + ret = cion_client_add_payload_received_cb(cion_client_, OnPayloadReceivedCB, + this); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_client_add_payload_received_cb. error(%d)", ret); + throw InvalidIOException(); + } +} +)__cpp_cb"; + +#endif // IDLC_CPP_GEN_CION_CPP_PROXY_BODY_GEN_CB_H_ diff --git a/idlc/gen_cion/cpp_cion_proxy_header_gen.cc b/idlc/gen_cion/cpp_cion_proxy_header_gen.cc new file mode 100644 index 00000000..7006284b --- /dev/null +++ b/idlc/gen_cion/cpp_cion_proxy_header_gen.cc @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "idlc/gen_cion/cpp_cion_proxy_header_gen.h" + +namespace { +#include "idlc/gen_cion/cpp_cion_proxy_header_gen_cb.h" +} + +namespace tidl { + +CppCionProxyHeaderGen::CppCionProxyHeaderGen(std::shared_ptr doc) + : CppCionGeneratorBase(doc) {} + +void CppCionProxyHeaderGen::OnInitGen(std::ofstream& stream) { + GenVersion(stream); + stream << CB_HEADER; + GenNamespace(stream); +} + +void CppCionProxyHeaderGen::OnFiniGen(std::ofstream& stream) { +} + +void CppCionProxyHeaderGen::GenNamespace(std::ofstream& stream) { + stream << "namespace cion "; + GenBrace(stream, 0, [&]() { + stream << "namespace " << GetFileNamespace() << " "; + GenBrace(stream, 0, [&]() { + stream << NLine(1); + GenStructuresForHeader(stream); + stream << "namespace proxy "; + GenBrace(stream, 0, [&]() { + GenExceptions(stream); + GenInterfaces(stream); + }, false, false); + stream << " // namespace proxy" + NLine(1); + }, false, false); + stream << " // namespace " + GetFileNamespace() + NLine(1); + }, false, false); + stream << " // namespace cion" + NLine(1); +} + +void CppCionProxyHeaderGen::GenExceptions(std::ofstream& stream) { + stream << CB_EXCEPTIONS; +} + +void CppCionProxyHeaderGen::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + Interface& iface = static_cast(*i); + GenInterface(stream, iface); + } +} + +void CppCionProxyHeaderGen::GenInterface(std::ofstream& stream, + const Interface& iface) { + stream << NLine(1) << "class " << iface.GetID() << " final "; + GenBrace(stream, 0, [&]() { + stream << " public:" << NLine(1); + GenHeaderCallbacks(stream, iface, true); + GenTemplate(CB_PUBLIC_MEMBERS, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }); + GenMethods(stream, iface); + GenDelegateId(stream, iface); + stream << NLine(1) << " private:" << NLine(1); + GenMethodId(stream, iface); + stream << CB_PRIVATE_MEMBERS; + }, false, false); + stream << ";" << NLine(1); +} + +void CppCionProxyHeaderGen::GenMethods(std::ofstream& stream, + const Interface& iface) { + auto& decls = iface.GetDeclarations(); + + for (auto& i : decls.GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + GenDeclaration(stream, *i); + } +} + +void CppCionProxyHeaderGen::GenDeclaration(std::ofstream& stream, + const Declaration& decl) { + if (!decl.GetComments().empty()) + stream << NLine(1) << AddIndent(TAB_SIZE, decl.GetComments()); + + stream << Tab(1) << ConvertTypeToString(decl.GetType()) << " " + << decl.GetID() << "("; + GenParameters(stream, decl.GetParameters()); + stream << ");" << NLine(1); +} +} // namespace tidl diff --git a/idlc/gen_cion/cpp_cion_proxy_header_gen.h b/idlc/gen_cion/cpp_cion_proxy_header_gen.h new file mode 100644 index 00000000..c9eba7ca --- /dev/null +++ b/idlc/gen_cion/cpp_cion_proxy_header_gen.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_H_ +#define IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_H_ + +#include +#include + +#include "idlc/gen_cion/cpp_cion_gen_base.h" + +namespace tidl { + +class CppCionProxyHeaderGen : public CppCionGeneratorBase { + public: + explicit CppCionProxyHeaderGen(std::shared_ptr doc); + virtual ~CppCionProxyHeaderGen() = default; + + void OnInitGen(std::ofstream& stream) override; + void OnFiniGen(std::ofstream& stream) override; + + private: + void GenNamespace(std::ofstream& stream); + void GenExceptions(std::ofstream& stream); + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + void GenMethods(std::ofstream& stream, const Interface& iface); + void GenDeclaration(std::ofstream& stream, const Declaration& decl); +}; + +} // namespace tidl + +#endif // IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_H_ diff --git a/idlc/gen_cion/cpp_cion_proxy_header_gen_cb.h b/idlc/gen_cion/cpp_cion_proxy_header_gen_cb.h new file mode 100644 index 00000000..d09e7e1b --- /dev/null +++ b/idlc/gen_cion/cpp_cion_proxy_header_gen_cb.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_CB_H_ +#define IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_CB_H_ + +const char CB_EXCEPTIONS[] = +R"__cpp_cb( +class Exception {}; +class NotConnectedSocketException : public Exception {}; +class InvalidProtocolException : public Exception {}; +class InvalidIOException : public Exception {}; +class PermissionDeniedException : public Exception {}; +class InvalidIDException : public Exception {}; +)__cpp_cb"; + +const char CB_PUBLIC_MEMBERS[] = +R"__cpp_cb( + class IEventListener { + public: + /// + /// This method will be invoked when the client app is connected to the service app. + /// + virtual void OnConnected() = 0; + + /// + /// This method will be invoked after the client app was disconnected from the service app. + /// + virtual void OnDisconnected() = 0; + + /// + /// This method will be invoked when the service app rejects the client app. + /// + virtual void OnRejected() = 0; + + /// + /// This method will be invoked when the service app is discovered. + /// + virtual void OnDiscovered() = 0; + + /// + /// This method will be invoked when file receieved from service. + /// + virtual void OnFileReceived(cion_peer_info_h peer_info, + cion_payload_h file_payload, cion_payload_transfer_status_e status) = 0; + }; + + /// + /// Constructor for this class + /// + /// The service name for + explicit $$(IEventListener* listener, const std::string& service_name, + const std::string& target_appid); + + /// + /// Destructor for this class + /// + virtual ~$$(); + + /// + /// Connects to the service app. + /// + void Connect(); + + /// + /// Disconnects to the service app. + /// + void Disconnect(); + + void Discovery(); + void StopDiscovery(); + + /// + /// Disposes delegate objects in this interface + /// + /// The tag string from delegate object + void DisposeCallback(const std::string& tag); +)__cpp_cb"; + +const char CB_PRIVATE_MEMBERS[] = +R"__cpp_cb( void ProcessReceivedEvent(rpc_port_parcel_h parcel); + void FilePayloadSend(std::string path); + + static void OnConnectionResultCB(const char *service_name, + const cion_peer_info_h peer_info, const cion_connection_result_h result, + void *user_data); + static void OnDisconnectedCB(const char *service_name, + const cion_peer_info_h peer_info, void *user_data); + static void OnDiscoveredCB(const char *service_name, + const cion_peer_info_h peer_info, void *user_data); + static void OnPayloadAsyncResultCB(const cion_payload_async_result_h result, + void *user_data); + static void OnPayloadReceivedCB(const char *service_name, + const cion_peer_info_h peer_info, const cion_payload_h payload, + cion_payload_transfer_status_e status, + void *user_data); + + cion_client_h cion_client_; + cion_peer_info_h peer_; + IEventListener* listener_; + std::string service_name_; + std::string target_appid_; + std::recursive_mutex mutex_; + std::list> delegate_list_; +)__cpp_cb"; + +const char CB_HEADER[] = +R"__cpp_cb( +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +)__cpp_cb"; + +#endif // IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_CB_H_ diff --git a/idlc/gen_cion/cpp_cion_stub_body_gen.cc b/idlc/gen_cion/cpp_cion_stub_body_gen.cc new file mode 100644 index 00000000..56b90fbc --- /dev/null +++ b/idlc/gen_cion/cpp_cion_stub_body_gen.cc @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "idlc/gen_cion/cpp_cion_stub_body_gen.h" + +namespace { +#include "idlc/gen_cion/cpp_cion_stub_body_gen_cb.h" +} + +namespace tidl { + +CppCionStubBodyGen::CppCionStubBodyGen(std::shared_ptr doc, + std::shared_ptr options) + : CppCionGeneratorBase(doc), options_(options) {} + +void CppCionStubBodyGen::OnInitGen(std::ofstream& stream) { + std::string key(".cc"); + std::string header_file = FileName; + + std::size_t found = header_file.rfind(key); + if (found != std::string::npos) + header_file.replace(found, key.length(), ".h"); + + GenVersion(stream); + stream << NLine(1); + stream << "#include " << NLine(1) + << "#include " << NLine(1) + << "#include " << NLine(1) + << "#include " << NLine(1) + << NLine(1) + << "#include \"" << header_file << "\"" << NLine(2); + GenLogTag(stream, "CION_STUB"); + GenLogDefinition(stream); + stream << NLine(1); + GenNamespace(stream); +} + +void CppCionStubBodyGen::OnFiniGen(std::ofstream& stream) {} + +void CppCionStubBodyGen::GenNamespace(std::ofstream& stream) { + stream << "namespace cion "; + GenBrace(stream, 0, [&]() { + stream << "namespace " << GetFileNamespace() << " "; + GenBrace(stream, 0, [&]() { + stream << NLine(1); + GenStructuresForBody(stream); + stream << "namespace stub "; + GenBrace(stream, 0, [&]() { + GenPrototype(stream); + GenSerializer(stream); + GenDeSerializer(stream); + GenListSerializer(stream); + GenInterfaces(stream); + }, false, false); + stream << " // namespace stub" + NLine(1); + }, false, false); + stream << " // namespace " + GetFileNamespace() + NLine(1); + }, false, false); + stream << " // namespace cion" + NLine(1); +} + +void CppCionStubBodyGen::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + Interface& iface = static_cast(*i); + GenInterface(stream, iface); + } +} + +void CppCionStubBodyGen::GenInterface(std::ofstream& stream, + const Interface& iface) { + GenFilePayloadSend(stream, iface); + GenServiceBase(stream, iface); + GenBodyCallbacks(stream, iface, false); + GenDefaultMethods(stream, iface); + GenCionDataReceivedEvent(stream, iface); + GenCionPayloadReceivedEvent(stream, iface); +} + +void CppCionStubBodyGen::GenServiceBase(std::ofstream& stream, + const Interface& iface) { + GenTemplate(CB_CTOR_SERVICE_BASE, stream, + [&]()->std::string { + return iface.GetID(); + }); + stream << NLine(1); +} + +void CppCionStubBodyGen::GenConstructor(std::ofstream& stream, + const Interface& iface) { + stream << ReplaceAll(CB_CTOR_FRONT, "##", iface.GetID()); +} + +void CppCionStubBodyGen::GenDefaultMethods(std::ofstream& stream, + const Interface& iface) { + GenConstructor(stream, iface); + if (options_->IsThreadEnabled()) + stream << ReplaceAll(CB_DEFAULT_THREAD_METHODS, "##", iface.GetID()); + + stream << ReplaceAll(CB_DEFAULT_METHODS, "##", iface.GetID()); +} + +void CppCionStubBodyGen::GenCionDataReceivedEvent(std::ofstream& stream, + const Interface& iface) { + if (options_->IsThreadEnabled()) { + GenTemplate(CB_RUN_PENDING_JOB_FRONT, stream, + [&]()->std::string { + return iface.GetID(); + }); + } else { + GenTemplate(CB_CION_ON_DATA_RECEIVED_CB_FRONT, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }); + } + + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE || + i->GetMethodType() == Declaration::MethodType::ASYNC) + continue; + stream << Tab(2) << "case static_cast(MethodId::" + << i->GetID() << "): "; + GenBrace(stream, TAB_SIZE * 2, [&]() { + GenInvocation(stream, *i); + stream << Tab(3) << "break;" << NLine(1); + }, false); + stream << NLine(1); + } + + if (options_->IsThreadEnabled()) { + stream << CB_RUN_PENDING_JOB_BACK << NLine(1); + + GenTemplate(CB_ON_DATA_RECEIVED_CB, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }); + } else { + stream << CB_CION_ON_DATA_RECEIVED_CB_BACK << NLine(1); + } +} + +void CppCionStubBodyGen::GenCionPayloadReceivedEvent(std::ofstream& stream, + const Interface& iface) { + GenTemplate(CB_CION_ON_PAYLOAD_RECEIVED_CB_FRONT, stream, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }, + [&]()->std::string { + return iface.GetID(); + }); + + for (auto& i : iface.GetDeclarations().GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE || + i->GetMethodType() == Declaration::MethodType::SYNC) + continue; + stream << Tab(2) << "case static_cast(MethodId::" + << i->GetID() << "): "; + GenBrace(stream, TAB_SIZE * 2, [&]() { + GenInvocation(stream, *i); + stream << Tab(3) << "break;" << NLine(1); + }, false); + stream << NLine(1); + } + + stream << CB_CION_ON_PAYLOAD_RECEIVED_CB_BACK << NLine(1); +} + +std::string CppCionStubBodyGen::GenPrivateSharingRequestStub(const BaseType& type, + std::string id) { + std::string ret; + if (type.GetMetaType() != nullptr && (type.GetMetaType()->GetFullName() == "file")) { + ret += std::string("for (const auto& i : " + id + ") {\n") + + std::string(" std::string name = i.GetFileName();\n") + + std::string(" stub->FilePayloadSend(name, b->GetPeer());\n") + + std::string("}\n"); + } else if (type.ToString() == "file") { + ret += std::string("std::string name = " + id + ".GetFileName();\n") + + std::string("stub->FilePayloadSend(name, b->GetPeer());\n"); + } + return ret; +} + +void CppCionStubBodyGen::GenInvocation(std::ofstream& stream, + const Declaration& decl) { + int cnt = 1; + + // Deserialize + for (auto& i : decl.GetParameters().GetParams()) { + if (i->GetParameterType().GetDirection() == ParameterType::Direction::OUT) { + cnt++; + continue; + } + + std::string v = "param" + std::to_string(cnt); + std::string c = ConvertTypeToDeserializer( + i->GetParameterType().GetBaseType(), v, "p"); + stream << AddIndent(TAB_SIZE * 3, c); + cnt++; + } + + // Invoke + cnt = 1; + std::string m; + std::string d; + bool hasRet = false; + + if (decl.GetType().ToString() != "void") { + m += "auto retVal = "; + hasRet = true; + } + + m += "b->" + decl.GetID() + "("; + for (auto& i : decl.GetParameters().GetParams()) { + if (cnt != 1) { + m += ", "; + } + + std::string v = "param" + std::to_string(cnt); + auto& pt = i->GetParameterType(); + if (pt.GetDirection() == ParameterType::Direction::OUT) { + d += ConvertTypeToString(pt.GetBaseType()) + " " + v + ";\n"; + } + if (IsDelegateType(pt.GetBaseType())) { + m += "std::move("; + m += v; + m += ")"; + } else { + m += v; + } + cnt++; + } + + m += ");\n"; + stream << AddIndent(TAB_SIZE * 3, d); + stream << AddIndent(TAB_SIZE * 3, m); + + // Serialize + if (decl.GetMethodType() == Declaration::MethodType::ASYNC) + return; + + cnt = 0; + m = "rpc_port_parcel_write_int32(" \ + "result, static_cast(MethodId::__Result));\n"; + for (auto& i : decl.GetParameters().GetParams()) { + auto& pt = i->GetParameterType(); + cnt++; + if (pt.GetDirection() == ParameterType::Direction::IN) + continue; + m += GenPrivateSharingRequestStub(pt.GetBaseType(), "param" + std::to_string(cnt)); + m += ConvertTypeToSerializer(pt.GetBaseType(), + "param" + std::to_string(cnt), "result"); + } + + if (hasRet) { + m += GenPrivateSharingRequestStub(decl.GetType(), "retVal"); + m += ConvertTypeToSerializer(decl.GetType(), "retVal", "result"); + } + + //m += "_I(\"retVal(%d)\", retVal);\n"; + stream << AddIndent(TAB_SIZE * 3, m); +} + +void CppCionStubBodyGen::GenFilePayloadSend(std::ofstream& stream, + const Interface& iface) { + GenTemplate(CB_FILE_PAYLOAD_SEND, stream, + [&]()->std::string { + return iface.GetID(); + }); + stream << NLine(1); +} + +} // namespace tidl diff --git a/idlc/gen_cion/cpp_cion_stub_body_gen.h b/idlc/gen_cion/cpp_cion_stub_body_gen.h new file mode 100644 index 00000000..747aa68b --- /dev/null +++ b/idlc/gen_cion/cpp_cion_stub_body_gen.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_H_ +#define IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_H_ + +#include +#include + +#include "idlc/gen_cion/cpp_cion_gen_base.h" +#include "idlc/options.h" + +namespace tidl { + +class CppCionStubBodyGen : public CppCionGeneratorBase { + public: + explicit CppCionStubBodyGen(std::shared_ptr doc, std::shared_ptr options); + virtual ~CppCionStubBodyGen() = default; + + void OnInitGen(std::ofstream& stream) override; + void OnFiniGen(std::ofstream& stream) override; + + private: + void GenNamespace(std::ofstream& stream); + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + void GenServiceBase(std::ofstream& stream, const Interface& iface); + void GenDefaultMethods(std::ofstream& stream, const Interface& iface); + void GenCionDataReceivedEvent(std::ofstream& stream, const Interface& iface); + void GenCionPayloadReceivedEvent(std::ofstream& stream, const Interface& iface); + void GenInvocation(std::ofstream& stream, const Declaration& decl); + void GenConstructor(std::ofstream& stream, const Interface& iface); + void GenFilePayloadSend(std::ofstream& stream, const Interface& iface); + std::string GenPrivateSharingRequestStub(const BaseType& type, std::string id); + + private: + std::shared_ptr options_; +}; + +} // namespace tidl + +#endif // IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_H_ diff --git a/idlc/gen_cion/cpp_cion_stub_body_gen_cb.h b/idlc/gen_cion/cpp_cion_stub_body_gen_cb.h new file mode 100644 index 00000000..9a28cb53 --- /dev/null +++ b/idlc/gen_cion/cpp_cion_stub_body_gen_cb.h @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_CB_H_ +#define IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_CB_H_ + +const char CB_CTOR_FRONT[] = +R"__cpp_cb( +##::##(const std::string& service_name, const std::string& display_name) { + cion_security_h security; + int ret = cion_security_create(&security); + if (ret != CION_ERROR_NONE) { + _E("Failed to create security handle. error(%d)", ret); + throw InvalidIOException(); + } + + ret = cion_server_create(&cion_server_, service_name.c_str(), + display_name.c_str(), security); + if (ret != CION_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + throw InvalidIOException(); + } + + ret = cion_server_add_connection_result_cb(cion_server_, OnConnectionResultCB, + this); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_add_connection_result_cb. error(%d)", ret); + throw InvalidIOException(); + } + + ret = cion_server_add_payload_received_cb(cion_server_, OnPayloadReceivedCB, + this); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_add_payload_received_cb. error(%d)", ret); + throw InvalidIOException(); + } + + ret = cion_server_set_data_received_cb(cion_server_, OnDataReceivedCB, this); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_set_data_received_cb. error(%d)", ret); + throw InvalidIOException(); + } + + ret = cion_server_add_disconnected_cb(cion_server_, OnDisconnectedCB, this); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_add_disconnected_cb. error(%d)", ret); + throw InvalidIOException(); + } +} +)__cpp_cb"; + +const char CB_DEFAULT_METHODS[] = +R"__cpp_cb( +##::~##() { + for (auto& i : services_) { + i->OnTerminate(); + } +} + +void ##::Listen(std::shared_ptr<##::ServiceBase::Factory> service_factory) { + service_factory_ = std::move(service_factory); + int ret = cion_server_listen(cion_server_, OnConnectionRequestCB, nullptr); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_listen. error(%d)", ret); + throw InvalidIOException(); + } +} + +void ##::Accept(std::shared_ptr service) { + auto p = service->GetPeer(); + int ret = cion_server_accept(cion_server_, p); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_accept. error(%d)", ret); + throw InvalidIOException(); + } + + service->OnCreate(); + services_.emplace_back(std::move(service)); +} + +void ##::Reject(std::shared_ptr service, std::string reason) { + auto p = service->GetPeer(); + int ret = cion_server_reject(cion_server_, p, reason.c_str()); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_reject. error(%d)", ret); + throw InvalidIOException(); + } +} + +void ##::Disconnect(std::shared_ptr service) { + auto p = service->GetPeer(); + int ret = cion_server_disconnect(cion_server_, p); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_disconnect. error(%d)", ret); + throw InvalidIOException(); + } +} + +void ##::OnConnectionResultCB(const char *service_name, + const cion_peer_info_h peer_info, const cion_connection_result_h result, + void *user_data) { +} + +void ##::OnDisconnectedCB(const char *service_name, + const cion_peer_info_h peer_info, void *user_data) { + ##* stub = static_cast<##*>(user_data); + char *peer_app_id, *peer_uuid; + cion_peer_info_get_app_id(peer_info, &peer_app_id); + cion_peer_info_get_app_id(peer_info, &peer_uuid); + + for (auto s = stub->services_.begin(); + s != stub->services_.end(); s++) { + char *service_app_id, *service_uuid; + cion_peer_info_get_app_id(s->get()->GetPeer(), &service_app_id); + cion_peer_info_get_app_id(s->get()->GetPeer(), &service_uuid); + if (strcmp(peer_app_id, service_app_id) == 0 && + strcmp(peer_uuid, service_uuid)) { + stub->services_.erase(s); + return; + } + } +} + +void ##::OnConnectionRequestCB(const char *service_name, + const cion_peer_info_h peer_info, void *user_data) { + ##* stub = static_cast<##*>(user_data); + auto s = stub->service_factory_->CreateService(peer_info); + s->OnRequested(s); +} + +)__cpp_cb"; + +const char CB_DEFAULT_THREAD_METHODS[] = +R"__cpp_cb( +void ##::ServiceBase::Dispatch(rpc_port_h port, + rpc_port_h callback_port, + rpc_port_parcel_h parcel, + std::shared_ptr service) { + active_object_->Send( + std::shared_ptr( + new (std::nothrow) PendingJob( + port, callback_port, parcel, service))); +} + +##::PendingJob::PendingJob(rpc_port_h port, + rpc_port_h callback_port, + rpc_port_parcel_h parcel, + std::shared_ptr service) + : Job(this), + port_(port), + callback_port_(callback_port), + parcel_(parcel), + service_(std::move(service)) { +} + +)__cpp_cb"; + +const char CB_RUN_PENDING_JOB_FRONT[] = +R"__cpp_cb( +void $$::PendingJob::Run() { + rpc_port_parcel_h result; + int cmd; + int ret; + rpc_port_parcel_h p = parcel_; + std::shared_ptr b = service_; + rpc_port_h port = port_; + + rpc_port_parcel_create(&result); + rpc_port_parcel_read_int32(parcel_, &cmd); + + switch (cmd) { +)__cpp_cb"; + +const char CB_RUN_PENDING_JOB_BACK[] = +R"__cpp_cb( default: + _E("Unknown command(%d)", cmd); + rpc_port_parcel_destroy(parcel_); + rpc_port_parcel_destroy(result); + return; + } + + rpc_port_parcel_destroy(parcel_); + rpc_port_parcel_destroy(result); +} +)__cpp_cb"; + +const char CB_ON_DATA_RECEIVED_CB[] = +R"__cpp_cb( +int $$::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void *data) +{ + auto* cxt = static_cast<$$*>(data); + std::shared_ptr b; + rpc_port_parcel_h parcel; + rpc_port_h callback_port; + + for (auto& i : cxt->services_) { + if (i->GetInstance() == instance) { + b = i; + break; + } + } + + if (b.get() == nullptr) { + _E("Failed to find $$ context(%s)", instance); + return -1; + } + + int ret = rpc_port_stub_get_port(cxt->stub_, RPC_PORT_PORT_CALLBACK, instance, + &callback_port); + if (ret != 0) { + _E("Failed to get callback port"); + } + + ret = rpc_port_parcel_create_from_port(&parcel, port); + if (ret != 0) { + _E("Failed to create parcel from port"); + return ret; + } + b->Dispatch(port, callback_port, parcel, b); + + return ret; +} +)__cpp_cb"; + +const char CB_CTOR_SERVICE_BASE[] = +R"__cpp_cb($$::ServiceBase::ServiceBase(cion_peer_info_h peer) + : active_object_(new ActiveObject()) { + int ret = cion_peer_info_clone(peer, &peer_); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_peer_info_clone. error(%d)", ret); + return; + } +})__cpp_cb"; + + +const char CB_FILE_PAYLOAD_SEND[] = R"__cpp_cb( +void $$::FilePayloadSend(std::string path, cion_peer_info_h peer) +{ + cion_payload_h pl; + int ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_FILE); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_create : %d", ret); + return; + } + + ret = cion_payload_set_file_path(pl, path.c_str()); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_set_file_path : %d - %s", ret, path.c_str()); + cion_payload_destroy(pl); + return; + } + + ret = cion_server_send_payload_async(cion_server_, peer, pl, nullptr, nullptr); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_server_send_payload_async : %d", ret); + cion_payload_destroy(pl); + return; + } + + cion_payload_destroy(pl); +} +)__cpp_cb"; + +const char CB_CION_ON_PAYLOAD_RECEIVED_CB_FRONT[] = +R"__cpp_cb( +void $$::OnPayloadReceivedCB(const char *service_name, + const cion_peer_info_h peer_info, const cion_payload_h payload, + cion_payload_transfer_status_e status, + void *user_data) { + $$* stub = static_cast<$$*>(user_data); + std::shared_ptr b; + rpc_port_parcel_h p; + char *peer_app_id, *peer_uuid; + cion_peer_info_get_app_id(peer_info, &peer_app_id); + cion_peer_info_get_app_id(peer_info, &peer_uuid); + + for (auto& s : stub->services_) { + char *service_app_id, *service_uuid; + cion_peer_info_get_app_id(s->GetPeer(), &service_app_id); + cion_peer_info_get_app_id(s->GetPeer(), &service_uuid); + if (strcmp(peer_app_id, service_app_id) == 0 && + strcmp(peer_uuid, service_uuid)) { + b = s; + break; + } + } + + if (b.get() == nullptr) { + _E("Failed to find service base(%s)", peer_app_id); + return; + } + + cion_payload_type_e type; + int ret = cion_payload_get_type(payload, &type); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_get_type. error(%d)", ret); + return; + } + + if (type == CION_PAYLOAD_TYPE_FILE) { + b->OnFileReceived(payload, peer_info, status); + return; + } + + unsigned char *data; + unsigned int size; + ret = cion_payload_get_data(payload, &data, &size); + if (ret != CION_ERROR_NONE) { + _E("Failed to cion_payload_get_data. error(%d)", ret); + return; + } + + ret = rpc_port_parcel_create_from_raw(&p, data, size); + if (ret != 0) { + _E("Failed to create parcel from port"); + return; + } + + int cmd; + rpc_port_parcel_read_int32(p, &cmd); + + switch (cmd) { +)__cpp_cb"; + +const char CB_CION_ON_PAYLOAD_RECEIVED_CB_BACK[] = +R"__cpp_cb( default: + _E("Unknown command(%d)", cmd); + rpc_port_parcel_destroy(p); + } + + rpc_port_parcel_destroy(p); + +} +)__cpp_cb"; + +const char CB_CION_ON_DATA_RECEIVED_CB_FRONT[] = +R"__cpp_cb( +void $$::OnDataReceivedCB(const char *service_name, + const cion_peer_info_h peer_info, const unsigned char *data, + unsigned int data_size, unsigned char **return_data, + unsigned int *return_data_size, void *user_data) { + $$* stub = static_cast<$$*>(user_data); + std::shared_ptr b; + rpc_port_parcel_h p; + char *peer_app_id, *peer_uuid; + cion_peer_info_get_app_id(peer_info, &peer_app_id); + cion_peer_info_get_app_id(peer_info, &peer_uuid); + + for (auto& s : stub->services_) { + char *service_app_id, *service_uuid; + cion_peer_info_get_app_id(s->GetPeer(), &service_app_id); + cion_peer_info_get_app_id(s->GetPeer(), &service_uuid); + if (strcmp(peer_app_id, service_app_id) == 0 && + strcmp(peer_uuid, service_uuid)) { + b = s; + break; + } + } + + int ret = rpc_port_parcel_create_from_raw(&p, data, data_size); + if (ret != 0) { + _E("Failed to create parcel from port"); + return; + } + + int cmd; + rpc_port_parcel_read_int32(p, &cmd); + + rpc_port_parcel_h result = nullptr; + rpc_port_parcel_create(&result); + switch (cmd) { +)__cpp_cb"; + +const char CB_CION_ON_DATA_RECEIVED_CB_BACK[] = +R"__cpp_cb( default: + _E("Unknown command(%d)", cmd); + rpc_port_parcel_destroy(p); + rpc_port_parcel_destroy(result); + return; + } + + ret = rpc_port_parcel_get_raw(result, (void **)return_data, return_data_size); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to get raw. error(%d)", ret); + rpc_port_parcel_destroy(p); + rpc_port_parcel_destroy(result); + return; + } + + rpc_port_parcel_destroy(p); + rpc_port_parcel_destroy(result); +} +)__cpp_cb"; + +#endif // IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_CB_H_ diff --git a/idlc/gen_cion/cpp_cion_stub_header_gen.cc b/idlc/gen_cion/cpp_cion_stub_header_gen.cc new file mode 100644 index 00000000..389a673e --- /dev/null +++ b/idlc/gen_cion/cpp_cion_stub_header_gen.cc @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "idlc/gen_cion/cpp_cion_stub_header_gen.h" + +namespace { +#include "idlc/gen_cion/cpp_cion_stub_header_gen_cb.h" +} + +namespace tidl { + +CppCionStubHeaderGen::CppCionStubHeaderGen(std::shared_ptr doc, + std::shared_ptr options) + : CppCionGeneratorBase(doc), options_(options) {} + +void CppCionStubHeaderGen::OnInitGen(std::ofstream& stream) { + GenVersion(stream); + stream << CB_HEADER; + GenNamespace(stream); +} + +void CppCionStubHeaderGen::OnFiniGen(std::ofstream& stream) { +} + +void CppCionStubHeaderGen::GenNamespace(std::ofstream& stream) { + stream << "namespace cion "; + GenBrace(stream, 0, [&]() { + stream << "namespace " << GetFileNamespace() << " "; + GenBrace(stream, 0, [&]() { + stream << NLine(1); + GenStructuresForHeader(stream); + stream << "namespace stub "; + GenBrace(stream, 0, [&]() { + GenExceptions(stream); + stream << CB_JOB; + stream << CB_SHARED_QUEUE; + stream << CB_ACTIVE_OBJECT; + GenInterfaces(stream); + }, false, false); + stream << " // namespace stub" + NLine(1); + }, false, false); + stream << " // namespace " + GetFileNamespace() + NLine(1); + }, false, false); + stream << " // namespace cion" + NLine(1); +} + +void CppCionStubHeaderGen::GenExceptions(std::ofstream& stream) { + stream << CB_EXCEPTIONS; +} + +void CppCionStubHeaderGen::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + Interface& iface = static_cast(*i); + GenInterface(stream, iface); + } +} + +void CppCionStubHeaderGen::GenInterface(std::ofstream& stream, + const Interface& iface) { + stream << NLine(1) << "class " << iface.GetID() << " final "; + GenBrace(stream, 0, [&]() { + GenPublic(stream, iface); + GenPrivate(stream, iface); + }, false, false); + stream << ";" << NLine(1); +} + +void CppCionStubHeaderGen::GenPublic(std::ofstream& stream, + const Interface& iface) { + stream << " public:" << NLine(1); + stream << " class ServiceBase;" << NLine(1); + GenHeaderCallbacks(stream, iface, false); + if (options_->IsThreadEnabled()) + stream << CB_PENDING_JOB << NLine(1); + GenServiceBase(stream, iface); + GenPublicMethods(stream, iface); +} + +void CppCionStubHeaderGen::GenPrivate(std::ofstream& stream, + const Interface& iface) { + stream << " private:" << NLine(1); + GenMethodId(stream, iface); + GenDelegateId(stream, iface); + stream << CB_PRIVATE_MEMBERS; +} + +void CppCionStubHeaderGen::GenServiceBase(std::ofstream& stream, + const Interface& iface) { + stream << CB_SERVICE_BASE_FRONT; + auto& decls = iface.GetDeclarations(); + + for (auto& i : decls.GetDecls()) { + if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + if (!i->GetComments().empty()) + stream << NLine(1) << AddIndent(TAB_SIZE * 2, i->GetComments()); + stream << Tab(2) << "virtual " << ConvertTypeToString(i->GetType()) + << " " << i->GetID() << "("; + GenParameters(stream, i->GetParameters()); + stream << ") = 0;" << NLine(1); + } + + stream << CB_SERVICE_BASE_BACK << NLine(2); +} + +void CppCionStubHeaderGen::GenPublicMethods(std::ofstream& stream, + const Interface& iface) { + stream << ReplaceAll(CB_PUBLIC_METHODS, "##", iface.GetID()); +} + +} // namespace tidl diff --git a/idlc/gen_cion/cpp_cion_stub_header_gen.h b/idlc/gen_cion/cpp_cion_stub_header_gen.h new file mode 100644 index 00000000..634217bf --- /dev/null +++ b/idlc/gen_cion/cpp_cion_stub_header_gen.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_H_ +#define IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_H_ + +#include +#include + +#include "idlc/gen_cion/cpp_cion_gen_base.h" +#include "idlc/options.h" + +namespace tidl { + +class CppCionStubHeaderGen : public CppCionGeneratorBase { + public: + explicit CppCionStubHeaderGen(std::shared_ptr doc, + std::shared_ptr options); + virtual ~CppCionStubHeaderGen() = default; + + void OnInitGen(std::ofstream& stream) override; + void OnFiniGen(std::ofstream& stream) override; + + private: + void GenExceptions(std::ofstream& stream); + void GenNamespace(std::ofstream& stream); + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + void GenPublic(std::ofstream& stream, const Interface& iface); + void GenPrivate(std::ofstream& stream, const Interface& iface); + void GenServiceBase(std::ofstream& stream, const Interface& iface); + void GenPublicMethods(std::ofstream& stream, const Interface& iface); + + private: + std::shared_ptr options_; +}; + +} // namespace tidl + +#endif // IDLC_CPP_GEN_CPP_STUB_HEADER_GEN_H_ diff --git a/idlc/gen_cion/cpp_cion_stub_header_gen_cb.h b/idlc/gen_cion/cpp_cion_stub_header_gen_cb.h new file mode 100644 index 00000000..5cb1e344 --- /dev/null +++ b/idlc/gen_cion/cpp_cion_stub_header_gen_cb.h @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_CB_H_ +#define IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_CB_H_ + +const char CB_EXCEPTIONS[] = +R"__cpp_cb( +class Exception {}; +class NotConnectedSocketException : public Exception {}; +class InvalidProtocolException : public Exception {}; +class InvalidIOException : public Exception {}; +class InvalidCallbackException : public Exception {}; +)__cpp_cb"; + +const char CB_PRIVATE_MEMBERS[] = +R"__cpp_cb( + void FilePayloadSend(std::string path, cion_peer_info_h peer); + + static void OnConnectionResultCB(const char *service_name, + const cion_peer_info_h peer_info, const cion_connection_result_h result, + void *user_data); + static void OnDisconnectedCB(const char *service_name, + const cion_peer_info_h peer_info, void *user_data); + static void OnConnectionRequestCB(const char *service_name, + const cion_peer_info_h peer_info, void *user_data); + static void OnDataReceivedCB(const char *service_name, + const cion_peer_info_h peer_info, const unsigned char *data, + unsigned int data_size, unsigned char **return_data, + unsigned int *return_data_size, void *user_data); + static void OnPayloadReceivedCB(const char *service_name, + const cion_peer_info_h peer_info, const cion_payload_h payload, + cion_payload_transfer_status_e status, + void *user_data); + + std::shared_ptr service_factory_; + std::list> services_; + cion_server_h cion_server_; +)__cpp_cb"; + +const char CB_SERVICE_BASE_FRONT[] = +R"__cpp_cb( + class ServiceBase { + public: + class Factory { + public: + /// + /// The method for making service instances + /// + /// The client peer info + virtual std::shared_ptr CreateService(cion_peer_info_h peer) = 0; + }; + + virtual ~ServiceBase() = default; + + /// + /// Gets peer info + /// + const cion_peer_info_h GetPeer() const { + return peer_; + } + + /// + /// This method will be called when file receieved from client app + /// + virtual void OnFileReceived(cion_peer_info_h peer_info, + cion_payload_h file_payload, cion_payload_transfer_status_e status) = 0; + + /// + /// This method will be called when the client is connection requested + /// + virtual void OnRequested(std::shared_ptr s) = 0; + + /// + /// This method will be called when the client is connected + /// + virtual void OnCreate() = 0; + + /// + /// This method will be called when the client is disconnected + /// + virtual void OnTerminate() = 0; + + void Dispatch(rpc_port_h port, rpc_port_h callback_port, + rpc_port_parcel_h parcel, std::shared_ptr service); + +)__cpp_cb"; + +const char CB_SERVICE_BASE_BACK[] = +R"__cpp_cb( + protected: + ServiceBase(cion_peer_info_h peer); + + private: + cion_peer_info_h peer_; + std::unique_ptr active_object_; + };)__cpp_cb"; + +const char CB_PENDING_JOB[] = +R"__cpp_cb( + class PendingJob : public Job, Job::IEvent { + public: + PendingJob(rpc_port_h port, rpc_port_h callback_port, + rpc_port_parcel_h parcel, std::shared_ptr service_); + + private: + void Run() override; + + private: + rpc_port_h port_; + rpc_port_h callback_port_; + rpc_port_parcel_h parcel_; + std::shared_ptr service_; + }; +)__cpp_cb"; + +const char CB_PUBLIC_METHODS[] = +R"__cpp_cb( ##(const std::string& service_name, const std::string& display_name); + ~##(); + + /// + /// Listens to client apps + /// + /// The factory object for making service instances + /// + /// Thrown when internal I/O error happen. + /// + void Listen(std::shared_ptr service_factory); + + /// + /// Accepts client apps + /// + void Accept(std::shared_ptr service); + + /// + /// Rejects client apps + /// + void Reject(std::shared_ptr service, std::string reason); + + /// + /// Disconnects client apps + /// + void Disconnect(std::shared_ptr service); + + /// + /// Gets service objects which are connected + /// + /// The list of service objects which are connected + const std::list>& GetServices() const { + return services_; + } + +)__cpp_cb"; + + +const char CB_JOB[] = R"__cls_job(class Job { + public: + class IEvent { + public: + virtual void Run() = 0; + }; + + Job() : handler_(nullptr) { + } + + Job(IEvent* handler) : handler_(handler) { + } + virtual ~Job() = default; + + Job(const Job& job) { + handler_ = job.handler_; + } + + Job& operator = (const Job& job) { + if (this != &job) + handler_ = job.handler_; + return *this; + } + Job(Job&& job) noexcept { + handler_ = job.handler_; + job.handler_ = nullptr; + } + + Job& operator = (Job&& job) noexcept { + if (this != &job) { + handler_ = job.handler_; + job.handler_ = nullptr; + } + return *this; + } + + void Invoke() { + if (handler_) + handler_->Run(); + } + + private: + IEvent* handler_; +}; + +)__cls_job"; + +const char CB_SHARED_QUEUE[] = R"__cls_shared_que( +template +class SharedQueue { + public: + SharedQueue() = default; + virtual ~SharedQueue() = default; + + void Push(T item) { + std::lock_guard lock(mutex_); + queue_.push_back(item); + cond_var_.notify_one(); + } + + void PushFront(T item) { + std::lock_guard lock(mutex_); + queue_.push_front(item); + cond_var_.notify_one(); + } + + bool TryAndPop(T& item) { + std::lock_guard lock(mutex_); + if (queue_.empty()) + return false; + + item = queue_.front(); + queue_.pop_front(); + + return true; + } + + void WaitAndPop(T& item) { + std::unique_lock lock(mutex_); + while (queue_.empty()) + cond_var_.wait(lock); + + item = queue_.front(); + queue_.pop_front(); + } + + bool Empty() { + std::lock_guard lock(mutex_); + return queue_.empty(); + } + + int Size() { + std::lock_guard lock(mutex_); + return queue_.size(); + } + + private: + std::deque queue_; + mutable std::mutex mutex_; + std::condition_variable cond_var_; +}; + +)__cls_shared_que"; + +const char CB_ACTIVE_OBJECT[] = R"__cls_active_obj(class ActiveObject : public Job::IEvent { + public: + ActiveObject() { + thread_ = std::thread([&]{ + do { + std::shared_ptr item; + queue_.WaitAndPop(item); + item->Invoke(); + } while (!done_); + }); + } + virtual ~ActiveObject() { + Quit(); + thread_.join(); + } + + public: + void Send(std::shared_ptr job) { + queue_.Push(std::move(job)); + } + + private: + void Quit() { + Send(std::shared_ptr(new (std::nothrow) Job(this))); + } + void Run() override { + done_ = true; + } + + private: + std::thread thread_; + bool done_ = false; + SharedQueue> queue_; +}; + +)__cls_active_obj"; + +const char CB_HEADER[] = +R"__cpp_cb( +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +)__cpp_cb"; + +#endif // IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_CB_H_ diff --git a/idlc/main.cc b/idlc/main.cc index 6020d65a..5b9c4fe2 100644 --- a/idlc/main.cc +++ b/idlc/main.cc @@ -37,7 +37,10 @@ #include "idlc/gen_cion/c_cion_stub_body_gen.h" #include "idlc/gen_cion/cs_cion_proxy_gen.h" #include "idlc/gen_cion/cs_cion_stub_gen.h" - +#include "idlc/gen_cion/cpp_cion_proxy_header_gen.h" +#include "idlc/gen_cion/cpp_cion_proxy_body_gen.h" +#include "idlc/gen_cion/cpp_cion_stub_header_gen.h" +#include "idlc/gen_cion/cpp_cion_stub_body_gen.h" #include "idlc/options.h" void GenerateStubCodes(std::shared_ptr options, @@ -57,7 +60,13 @@ void GenerateStubCodes(std::shared_ptr options, break; } case tidl::Options::LANGUAGE_TYPE_CPP: + { + tidl::CppCionStubHeaderGen stub_header(ps.GetDoc(), options); + stub_header.Run(options->GetOutput() + ".h"); + tidl::CppCionStubBodyGen stub_body(ps.GetDoc(), options); + stub_body.Run(options->GetOutput() + ".cc"); break; + } case tidl::Options::LANGUAGE_TYPE_CSHARP: { tidl::CsCionStubGen stub(ps.GetDoc()); @@ -126,6 +135,13 @@ void GenerateProxyCodes(std::shared_ptr options, break; } case tidl::Options::LANGUAGE_TYPE_CPP: + { + tidl::CppCionProxyHeaderGen proxy_header(ps.GetDoc()); + proxy_header.Run(options->GetOutput() + ".h"); + tidl::CppCionProxyBodyGen proxy_body(ps.GetDoc()); + proxy_body.Run(options->GetOutput() + ".cc"); + break; + } break; case tidl::Options::LANGUAGE_TYPE_CSHARP: {