--- /dev/null
+/*
+ * 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 <ctime>
+#include <vector>
+#include <utility>
+
+#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<Document> 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<Structure&>(*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<Structure&>(*i);
+ GenStructureForBody(stream, st);
+ stream << std::endl;
+ }
+}
+
+void CppCionGeneratorBase::GenStructureForBody(std::ofstream& stream,
+ const Structure& st) {
+ std::vector<std::pair<std::string, std::string>> v;
+ const char ctor[] = "##::##() {}\n\n" \
+ "##::##($$)\n" \
+ " : $$ {}";
+
+ for (auto& i : st.GetElements().GetElms()) {
+ std::pair<std::string, std::string> 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<Structure&>(*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<Structure&>(*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<Structure&>(*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<const Structure&>(*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<const Interface&>(*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<ServiceBase>(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
--- /dev/null
+/*
+ * 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 <memory>
+#include <string>
+#include <map>
+
+#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<Document> 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<std::string, std::string> type_map_;
+ std::map<std::string, std::string> parcel_type_map_;
+ std::map<std::string, std::string> type_init_map_;
+ std::map<std::string, const BaseType*> serializer_list_;
+};
+
+} // namespace tidl
+
+#endif // IDLC_CPP_CION_GEN_CPP_GEN_BASE_H_
--- /dev/null
+/*
+ * 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<int> ##::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<int> 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<ServiceBase> service, cion_server_h cion_server)
+ : CallbackBase(static_cast<int>(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<int>(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<ServiceBase> 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<int>(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<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+)__cpp_cb";
+
+#endif // IDLC_CPP_CION_GEN_CPP_GEN_BASE_CB_H_
--- /dev/null
+/*
+ * 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<Document> 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 <stdlib.h>" << NLine(1)
+ << "#include <assert.h>" << NLine(1)
+ << "#include <dlog.h>" << 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<Interface&>(*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<int>(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<std::recursive_mutex> 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
--- /dev/null
+/*
+ * 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 <memory>
+#include <string>
+
+#include "idlc/gen_cion/cpp_cion_gen_base.h"
+
+namespace tidl {
+
+class CppCionProxyBodyGen : public CppCionGeneratorBase {
+ public:
+ explicit CppCionProxyBodyGen(std::shared_ptr<Document> 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_
--- /dev/null
+/*
+ * 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<int>(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<int>(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_
--- /dev/null
+/*
+ * 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<Document> 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<Interface&>(*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
--- /dev/null
+/*
+ * 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 <memory>
+#include <string>
+
+#include "idlc/gen_cion/cpp_cion_gen_base.h"
+
+namespace tidl {
+
+class CppCionProxyHeaderGen : public CppCionGeneratorBase {
+ public:
+ explicit CppCionProxyHeaderGen(std::shared_ptr<Document> 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_
--- /dev/null
+/*
+ * 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:
+ /// <summary>
+ /// This method will be invoked when the client app is connected to the service app.
+ /// </summary>
+ virtual void OnConnected() = 0;
+
+ /// <summary>
+ /// This method will be invoked after the client app was disconnected from the service app.
+ /// </summary>
+ virtual void OnDisconnected() = 0;
+
+ /// <summary>
+ /// This method will be invoked when the service app rejects the client app.
+ /// </summary>
+ virtual void OnRejected() = 0;
+
+ /// <summary>
+ /// This method will be invoked when the service app is discovered.
+ /// </summary>
+ virtual void OnDiscovered() = 0;
+
+ /// <summary>
+ /// This method will be invoked when file receieved from service.
+ /// </summary>
+ virtual void OnFileReceived(cion_peer_info_h peer_info,
+ cion_payload_h file_payload, cion_payload_transfer_status_e status) = 0;
+ };
+
+ /// <summary>
+ /// Constructor for this class
+ /// </summary>
+ /// <param name="service_name">The service name for </param>
+ explicit $$(IEventListener* listener, const std::string& service_name,
+ const std::string& target_appid);
+
+ /// <summary>
+ /// Destructor for this class
+ /// </summary>
+ virtual ~$$();
+
+ /// <summary>
+ /// Connects to the service app.
+ /// </summary>
+ void Connect();
+
+ /// <summary>
+ /// Disconnects to the service app.
+ /// </summary>
+ void Disconnect();
+
+ void Discovery();
+ void StopDiscovery();
+
+ /// <summary>
+ /// Disposes delegate objects in this interface
+ /// </summary>
+ /// <param name="tag">The tag string from delegate object</param>
+ 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<std::unique_ptr<CallbackBase>> delegate_list_;
+)__cpp_cb";
+
+const char CB_HEADER[] =
+R"__cpp_cb(
+#pragma once
+
+#include <cion.h>
+#include <rpc-port-parcel.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <atomic>
+
+)__cpp_cb";
+
+#endif // IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_CB_H_
--- /dev/null
+/*
+ * 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<Document> doc,
+ std::shared_ptr<Options> 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 <stdlib.h>" << NLine(1)
+ << "#include <assert.h>" << NLine(1)
+ << "#include <libgen.h>" << NLine(1)
+ << "#include <dlog.h>" << 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<Interface&>(*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<int>(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<int>(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<int>(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
--- /dev/null
+/*
+ * 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 <memory>
+#include <string>
+
+#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<Document> doc, std::shared_ptr<Options> 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> options_;
+};
+
+} // namespace tidl
+
+#endif // IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_H_
--- /dev/null
+/*
+ * 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<ServiceBase> 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<ServiceBase> 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<ServiceBase> 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<ServiceBase> service) {
+ active_object_->Send(
+ std::shared_ptr<Job>(
+ 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<ServiceBase> 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<ServiceBase> 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<ServiceBase> 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<ServiceBase> 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<ServiceBase> 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_
--- /dev/null
+/*
+ * 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<Document> doc,
+ std::shared_ptr<Options> 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<Interface&>(*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
--- /dev/null
+/*
+ * 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 <memory>
+#include <string>
+
+#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<Document> doc,
+ std::shared_ptr<Options> 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> options_;
+};
+
+} // namespace tidl
+
+#endif // IDLC_CPP_GEN_CPP_STUB_HEADER_GEN_H_
--- /dev/null
+/*
+ * 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<ServiceBase::Factory> service_factory_;
+ std::list<std::shared_ptr<ServiceBase>> services_;
+ cion_server_h cion_server_;
+)__cpp_cb";
+
+const char CB_SERVICE_BASE_FRONT[] =
+R"__cpp_cb(
+ class ServiceBase {
+ public:
+ class Factory {
+ public:
+ /// <summary>
+ /// The method for making service instances
+ /// </summary>
+ /// <param name="peer">The client peer info</param>
+ virtual std::shared_ptr<ServiceBase> CreateService(cion_peer_info_h peer) = 0;
+ };
+
+ virtual ~ServiceBase() = default;
+
+ /// <summary>
+ /// Gets peer info
+ /// </summary>
+ const cion_peer_info_h GetPeer() const {
+ return peer_;
+ }
+
+ /// <summary>
+ /// This method will be called when file receieved from client app
+ /// </summary>
+ virtual void OnFileReceived(cion_peer_info_h peer_info,
+ cion_payload_h file_payload, cion_payload_transfer_status_e status) = 0;
+
+ /// <summary>
+ /// This method will be called when the client is connection requested
+ /// </summary>
+ virtual void OnRequested(std::shared_ptr<ServiceBase> s) = 0;
+
+ /// <summary>
+ /// This method will be called when the client is connected
+ /// </summary>
+ virtual void OnCreate() = 0;
+
+ /// <summary>
+ /// This method will be called when the client is disconnected
+ /// </summary>
+ virtual void OnTerminate() = 0;
+
+ void Dispatch(rpc_port_h port, rpc_port_h callback_port,
+ rpc_port_parcel_h parcel, std::shared_ptr<ServiceBase> 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<ActiveObject> 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<ServiceBase> service_);
+
+ private:
+ void Run() override;
+
+ private:
+ rpc_port_h port_;
+ rpc_port_h callback_port_;
+ rpc_port_parcel_h parcel_;
+ std::shared_ptr<ServiceBase> service_;
+ };
+)__cpp_cb";
+
+const char CB_PUBLIC_METHODS[] =
+R"__cpp_cb( ##(const std::string& service_name, const std::string& display_name);
+ ~##();
+
+ /// <summary>
+ /// Listens to client apps
+ /// </summary>
+ /// <param name="service_factory">The factory object for making service instances</param>
+ /// <exception cref="InvalidIOException">
+ /// Thrown when internal I/O error happen.
+ /// </exception>
+ void Listen(std::shared_ptr<ServiceBase::Factory> service_factory);
+
+ /// <summary>
+ /// Accepts client apps
+ /// </summary>
+ void Accept(std::shared_ptr<ServiceBase> service);
+
+ /// <summary>
+ /// Rejects client apps
+ /// </summary>
+ void Reject(std::shared_ptr<ServiceBase> service, std::string reason);
+
+ /// <summary>
+ /// Disconnects client apps
+ /// </summary>
+ void Disconnect(std::shared_ptr<ServiceBase> service);
+
+ /// <summary>
+ /// Gets service objects which are connected
+ /// </summary>
+ /// <returns>The list of service objects which are connected</returns>
+ const std::list<std::shared_ptr<ServiceBase>>& 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 T>
+class SharedQueue {
+ public:
+ SharedQueue() = default;
+ virtual ~SharedQueue() = default;
+
+ void Push(T item) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ queue_.push_back(item);
+ cond_var_.notify_one();
+ }
+
+ void PushFront(T item) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ queue_.push_front(item);
+ cond_var_.notify_one();
+ }
+
+ bool TryAndPop(T& item) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (queue_.empty())
+ return false;
+
+ item = queue_.front();
+ queue_.pop_front();
+
+ return true;
+ }
+
+ void WaitAndPop(T& item) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ while (queue_.empty())
+ cond_var_.wait(lock);
+
+ item = queue_.front();
+ queue_.pop_front();
+ }
+
+ bool Empty() {
+ std::lock_guard<std::mutex> lock(mutex_);
+ return queue_.empty();
+ }
+
+ int Size() {
+ std::lock_guard<std::mutex> lock(mutex_);
+ return queue_.size();
+ }
+
+ private:
+ std::deque<T> 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<Job> item;
+ queue_.WaitAndPop(item);
+ item->Invoke();
+ } while (!done_);
+ });
+ }
+ virtual ~ActiveObject() {
+ Quit();
+ thread_.join();
+ }
+
+ public:
+ void Send(std::shared_ptr<Job> job) {
+ queue_.Push(std::move(job));
+ }
+
+ private:
+ void Quit() {
+ Send(std::shared_ptr<Job>(new (std::nothrow) Job(this)));
+ }
+ void Run() override {
+ done_ = true;
+ }
+
+ private:
+ std::thread thread_;
+ bool done_ = false;
+ SharedQueue<std::shared_ptr<Job>> queue_;
+};
+
+)__cls_active_obj";
+
+const char CB_HEADER[] =
+R"__cpp_cb(
+#pragma once
+
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+#include <cion.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <list>
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <deque>
+#include <thread>
+
+)__cpp_cb";
+
+#endif // IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_CB_H_
#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<tidl::Options> 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());
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:
{