Check sequence number 01/263101/20
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 26 Aug 2021 06:41:09 +0000 (15:41 +0900)
committerHwanKyu Jhun <h.jhun@samsung.com>
Fri, 10 Sep 2021 04:49:32 +0000 (04:49 +0000)
When getting the result from the stub, the proxy checks whether the tag
exists or not. If it's existed, the proxy checks the sequence number.
If the sequence number is not matched, the proxy tries to get the parcel from
the port again.

Change-Id: I02b962cc54871ad31aadd74552c63255f8b7aa14
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
18 files changed:
idlc/gen/c_body_gen_base.cc
idlc/gen/c_body_gen_base.h
idlc/gen/c_body_gen_base_cb.h
idlc/gen/c_proxy_body_gen.cc
idlc/gen/c_proxy_body_gen_cb.h
idlc/gen/c_stub_body_gen.cc
idlc/gen/c_stub_body_gen_cb.h
idlc/gen/cpp_gen_base.cc
idlc/gen/cpp_gen_base.h
idlc/gen/cpp_gen_base_cb.h
idlc/gen/cpp_proxy_body_gen.cc
idlc/gen/cpp_proxy_body_gen_cb.h
idlc/gen/cpp_stub_body_gen.cc
idlc/gen/cpp_stub_body_gen_cb.h
idlc/gen/cs_proxy_gen.cc
idlc/gen/cs_proxy_gen_cb.h
idlc/gen/cs_stub_gen.cc
idlc/gen/cs_stub_gen_cb.h

index 478479777bba768106150e2205311b72b04ced4a..e1c3cf72a2f1b42ab80fb8deb35d5863c9b81fae 100644 (file)
@@ -82,6 +82,10 @@ void CBodyGeneratorBase::GenLogDefinition(std::ofstream& stream) {
   stream << SmartIndent(CB_LOG_DEF);
 }
 
+void CBodyGeneratorBase::GenVersionDefinition(std::ofstream& stream) {
+  stream << ReplaceAll(CB_VERSION_DEF, "<VERSION>", FULLVER);
+}
+
 void CBodyGeneratorBase::GenBaseDefinition(std::ofstream& stream) {
   stream << SmartIndent(CB_BASE_DEF);
 }
index c2e7ffa9b1e817a9709f592d87674830a146de4a..24bfeac192101d7573327daa7035d1c1e70f3440 100644 (file)
@@ -35,6 +35,7 @@ class CBodyGeneratorBase : public CGeneratorBase {
   void GenIncludeHeader(std::ofstream& stream);
   void GenLogTag(std::ofstream& stream, const std::string& log_tag);
   void GenLogDefinition(std::ofstream& stream);
+  void GenVersionDefinition(std::ofstream& stream);
   void GenBaseDefinition(std::ofstream& stream);
   const std::string& GetParcelType(const BaseType& type);
 
index a8f9a67b5808cce886325e49fe8a05777bfbe8ba..4cb55d61ef5e11505594789debd4315527875eff 100644 (file)
@@ -41,6 +41,16 @@ R"__c_cb(
 #define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 )__c_cb";
 
+/**
+ * <VERSION> Version of TIDL Compiler.
+ */
+constexpr const char CB_VERSION_DEF[] =
+R"__c_cb(
+#ifndef TIDL_VERSION
+#define TIDL_VERSION "<VERSION>"
+#endif
+)__c_cb";
+
 constexpr const char CB_BASE_DEF[] =
 R"__c_cb(
 #ifndef nullptr
index 5d15665384af74838d4c015db2dff6bc6e164d03..d24488dc6c3f5727b40a869417c8f1855681ee12 100644 (file)
@@ -33,6 +33,7 @@ void CProxyBodyGen::OnInitGen(std::ofstream& stream) {
   GenIncludeHeader(stream);
   GenLogTag(stream, std::string("RPC_PORT_PROXY"));
   GenLogDefinition(stream);
+  GenVersionDefinition(stream);
   GenBaseDefinition(stream);
   GenInterfaceDelegateCallback(stream);
   GenStructureDefs(stream);
index 305217544f82d98fd7be9897ebe5eb1ea7248856..fd103287f25cc9b789876f806d54e7e66a8f8246 100644 (file)
@@ -735,6 +735,8 @@ R"__c_cb(
 void <PREFIX>_<NAME>_invoke_<METHOD_NAME>(<PREFIX>_<NAME>_h h<METHOD_PARAMS>)
 {
   rpc_port_parcel_h parcel_;
+  rpc_port_parcel_header_h header_;
+  int seq_num_ = -1;
   int res_;
 
   if (h == nullptr<METHOD_PARAMS_CHECK>) {
@@ -759,6 +761,11 @@ void <PREFIX>_<NAME>_invoke_<METHOD_NAME>(<PREFIX>_<NAME>_h h<METHOD_PARAMS>)
     return;
   }
 
+  rpc_port_parcel_get_header(parcel_, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%d\", [Sequence] %d", TIDL_VERSION, seq_num_);
+
   rpc_port_parcel_write_int32(parcel_, <UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_<UPPERCASE_METHOD_NAME>);
 
   <METHOD_PARCEL_WRITE>
@@ -795,6 +802,11 @@ R"__c_cb(
 <RETURN_TYPE><PREFIX>_<NAME>_invoke_<METHOD_NAME>(<PREFIX>_<NAME>_h h<METHOD_PARAMS>)
 {
   rpc_port_parcel_h parcel_;
+  rpc_port_parcel_header_h header_;
+  int seq_num_ = -1;
+  int recv_seq_num_ = -1;
+  char *tag_ = nullptr;
+  bool done_ = false;
   int res_;
   <RETURN_TYPE>ret_ = <ERROR_VALUE>;
   <METHOD_ARGS>
@@ -821,6 +833,11 @@ R"__c_cb(
     return ret_;
   }
 
+  rpc_port_parcel_get_header(parcel_, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_);
+
   rpc_port_parcel_write_int32(parcel_, <UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_<UPPERCASE_METHOD_NAME>);
 
   <METHOD_PARCEL_WRITE>
@@ -844,9 +861,24 @@ R"__c_cb(
       break;
     }
 
+    rpc_port_parcel_get_header(parcel_, &header_);
+    rpc_port_parcel_header_get_tag(header_, &tag_);
+    if (tag_ && tag_[0] != '\0') {
+      _W("[Version] %s", tag_);
+      rpc_port_parcel_header_get_seq_num(header_, &recv_seq_num_);
+      if (recv_seq_num_ != seq_num_) {
+        _E("Invalid protocol. %d", recv_seq_num_);
+        free(tag_);
+        rpc_port_parcel_destroy(parcel_);
+        continue;
+      }
+    }
+    done_ = true;
+    free(tag_);
+
     <METHOD_PARCEL_READ>
     rpc_port_parcel_destroy(parcel_);
-  } while (0);
+  } while (!done_);
   g_rec_mutex_unlock(&h->mutex);
   set_last_result(res_);
 
index c0d68269db9f32177a679e6e24395db2113c3f2f..03a29b38235788106f31c4b3b45ced4a5e59c1b8 100644 (file)
@@ -33,6 +33,7 @@ void CStubBodyGen::OnInitGen(std::ofstream& stream) {
   GenIncludeHeader(stream);
   GenLogTag(stream, std::string("RPC_PORT_STUB"));
   GenLogDefinition(stream);
+  GenVersionDefinition(stream);
   GenBaseDefinition(stream);
   GenThreadEnableDefinition(stream);
   GenInterfaceMethodHandlerType(stream);
index a75a68bddac477a8ff8fc533b14aded205f9912d..4d253118e9c8dd8877e1b526ae34330b46ce2a55 100644 (file)
@@ -702,6 +702,8 @@ R"__c_cb(
 static int __<PREFIX>_<NAME>_method_<METHOD_NAME>_handler(rpc_port_h port, rpc_port_parcel_h parcel, void *user_data)
 {
   <PREFIX>_<NAME>_context_h context_ = user_data;
+  rpc_port_parcel_header_h header_;
+  int seq_num_ = -1;
   rpc_port_h callback_port_;
   int ret_;
   <METHOD_HANDLER_ARGS_DECL>
@@ -712,6 +714,10 @@ static int __<PREFIX>_<NAME>_method_<METHOD_NAME>_handler(rpc_port_h port, rpc_p
     goto out;
   }
 
+  rpc_port_parcel_get_header(parcel, &header_);
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Sequence] %d", seq_num_);
+
   <METHOD_HANDLER_PARCEL_READ>
   <METHOD_HANDLER_CALLBACK_INVOKE>
   <METHOD_HANDLER_PARCEL_WRITE>
@@ -823,6 +829,10 @@ if (ret_ != RPC_PORT_ERROR_NONE) {
   goto out;
 }
 
+rpc_port_parcel_get_header(parcel_, &header_);
+rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+rpc_port_parcel_header_set_seq_num(header_, seq_num_);
+
 rpc_port_parcel_write_int32(parcel_, RPC_PORT_STUB_<UPPERCASE_NAME>_METHOD_RESULT_);
 )__c_cb";
 
index f901eaf39664c28c913a38c5972923d29cea2075..83aaf1efb6acdf29600db594794d13cec5cff438 100644 (file)
@@ -747,4 +747,8 @@ void CppGeneratorBase::GenLogDefinition(std::ofstream& stream) {
   stream << CB_LOG_DEF;
 }
 
+void CppGeneratorBase::GenVersionDefinition(std::ofstream& stream) {
+  stream << ReplaceAll(CB_VERSION_DEF, "[VERSION]", FULLVER);
+}
+
 }  // namespace tidl
index fce6c56c72b10444ba4aa4857e92a110fc0a999e..4b575fc7266a7ab498509320156f552999624cf6 100644 (file)
@@ -60,6 +60,7 @@ class CppGeneratorBase : public Generator {
   std::string GetParameters(const Parameters& ps);
   void GenLogTag(std::ofstream& stream, std::string id);
   void GenLogDefinition(std::ofstream& stream);
+  void GenVersionDefinition(std::ofstream& stream);
 
  private:
   void GenSetter(std::ofstream& stream, const Element& ele);
index 46f58b2dc7c9ae906fadc275ffce69dce2cc13e3..84ef26943ed443d8965ee5d2f581e34a732a4350 100644 (file)
@@ -261,4 +261,14 @@ R"__cpp_cb(
 #define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 )__cpp_cb";
 
+/**
+ * [VERSION] Version of TIDL Compiler.
+ */
+constexpr const char CB_VERSION_DEF[] =
+R"__cpp_cb(
+#ifndef TIDL_VERSION
+#define TIDL_VERSION "[VERSION]"
+#endif
+)__cpp_cb";
+
 #endif  // IDLC_CPP_GEN_CPP_GEN_BASE_CB_H_
index 06a739dea1739ae578096133d69a2cbd89e8948f..7df3e8b94a3dd9db2ef4467bef030d8e9857ccb7 100644 (file)
@@ -42,6 +42,7 @@ void CppProxyBodyGen::OnInitGen(std::ofstream& stream) {
          << "#include \"" << header_file << "\"" << NLine(2);
   GenLogTag(stream, "RPC_PORT_PROXY");
   GenLogDefinition(stream);
+  GenVersionDefinition(stream);
   stream << NLine(1);
   GenNamespace(stream);
 }
@@ -155,22 +156,13 @@ void CppProxyBodyGen::GenInvocation(std::ofstream& stream,
   }
   stream << AddIndent(TAB_SIZE, m) << NLine(1);
 
-  if (decl.GetMethodType() == Declaration::MethodType::SYNC)
-    stream << Tab(1) << "rpc_port_parcel_h parcel_received;" << 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);
-    stream << CB_INVOCATION_MID << NLine(1);
-    if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
-      stream << Tab(2) << "// Receive" << NLine(1);
-      stream << Tab(2)
-             << "ConsumeCommand(&parcel_received, port_);" << NLine(1);
-    }
-  }, false, false);
-  stream << " while (false);" << NLine(1);
+  stream << Tab(1) << "std::lock_guard<std::recursive_mutex> lock(mutex_);"
+         << NLine(1);
+
+  if (!l.empty())
+    stream << AddIndent(TAB_SIZE, l);
+
+  stream << CB_INVOCATION_MID;
 
   // Deserialize
   if (decl.GetMethodType() == Declaration::MethodType::ASYNC) {
@@ -179,24 +171,29 @@ void CppProxyBodyGen::GenInvocation(std::ofstream& stream,
     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"));
-  }
+  auto parcel_read = [&]() -> std::string {
+        std::string code;
+        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 != "")
+            code += AddIndent(TAB_SIZE * 2, c);
+        }
+
+        if (decl.GetType().ToString() != "void") {
+          code += AddIndent(TAB_SIZE * 2,
+              ConvertTypeToDeserializer(decl.GetType(), "ret",
+                "parcel_received"));
+        }
+
+        return code;
+      };
+  stream << ReplaceAll(CB_INVOCATION_RECEIVE, "[PARCEL_READ]", parcel_read());
 
   stream << CB_INVOCATION_END;
 }
index 83a9f084c9eccff8fc1ca05b40ed3967e0ccafe9..96ba70890cc5c21e2a64ac3e92d3c07f3a2aae06 100644 (file)
@@ -33,31 +33,65 @@ R"__cpp_cb(  if (port_ == nullptr) {
 
   rpc_port_parcel_h p;
   rpc_port_parcel_create(&p);
+
+  rpc_port_parcel_header_h header_;
+  rpc_port_parcel_get_header(p, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  int seq_num_ = -1;
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_);
 )__cpp_cb";
 
 const char CB_INVOCATION_MID[] =
 R"__cpp_cb(
-    // Send
-    int r = rpc_port_parcel_send(p, port_);
-    if (r != RPC_PORT_ERROR_NONE) {
-      _E("Failed to send parcel. result(%d)", r);
-      rpc_port_parcel_destroy(p);
-      throw InvalidIOException();
-    }
+  // Send
+  int r = rpc_port_parcel_send(p, port_);
+  if (r != RPC_PORT_ERROR_NONE) {
+    _E("Failed to send parcel. result(%d)", r);
+    rpc_port_parcel_destroy(p);
+    throw InvalidIOException();
+  }
 )__cpp_cb";
 
+/**
+ * [PARCEL_READ] The implementation to read the data from the parcel.
+ */
 const char CB_INVOCATION_RECEIVE[] =
 R"__cpp_cb(
-  if (parcel_received == nullptr) {
-    _E("Invalid protocol");
-    throw InvalidProtocolException();
-  }
+  bool done_ = false;
+  do {
+    rpc_port_parcel_h parcel_received = nullptr;
+    // Receive
+    ConsumeCommand(&parcel_received, port_);
+    if (parcel_received == nullptr) {
+      _E("Invalid protocol");
+      throw InvalidProtocolException();
+    }
+
+    rpc_port_parcel_get_header(parcel_received, &header_);
+    char* tag_ = nullptr;
+    rpc_port_parcel_header_get_tag(header_, &tag_);
+    std::unique_ptr<char, decltype(std::free)*> tag_auto_(tag_, std::free);
+    if (tag_ && tag_[0] != '\0') {
+      _W("[Version] %s", tag_);
+      int seq_num_received_ = -1;
+      rpc_port_parcel_header_get_seq_num(header_, &seq_num_received_);
+      if (seq_num_received_ != seq_num_) {
+        _E("Invalid protocol. %d", seq_num_received_);
+        rpc_port_parcel_destroy(parcel_received);
+        continue;
+      }
+    }
+    done_ = true;
+
+[PARCEL_READ]
+    rpc_port_parcel_destroy(parcel_received);
+  } while (!done_);
 )__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";
index 3c840b70d736ac04539c4c3dfdc73b2a563f3482..e460964fc87ff45581993899b32b81f7c63ecfac 100644 (file)
@@ -44,6 +44,7 @@ void CppStubBodyGen::OnInitGen(std::ofstream& stream) {
          << "#include \"" << header_file << "\"" << NLine(2);
   GenLogTag(stream, "RPC_PORT_STUB");
   GenLogDefinition(stream);
+  GenVersionDefinition(stream);
   stream << NLine(1);
   GenNamespace(stream);
 }
@@ -132,13 +133,9 @@ void CppStubBodyGen::GenReceivedEvent(std::ofstream& stream,
         return iface.GetID();
       });
   } else {
-    GenTemplate(CB_ON_RECEIVED_CB_FRONT, stream,
-      [&]()->std::string {
-        return iface.GetID();
-      },
-      [&]()->std::string {
-        return iface.GetID();
-      });
+    std::string code = ReplaceAll(CB_ON_RECEIVED_CB_FRONT, "[NAME]",
+        iface.GetID());
+    stream << code;
   }
 
   for (auto& i : iface.GetDeclarations().GetDecls()) {
index 709ea4d2c6f921f94f45501ad0085c84f61b87d8..deea256ee14b5f1f20eca4e6059446acad5e1225 100644 (file)
@@ -101,13 +101,18 @@ void ##::ServiceBase::Dispatch(rpc_port_h port,
 
 )__cpp_cb";
 
+/**
+ * [NAME] The name of the interface.
+ */
 const char CB_ON_RECEIVED_CB_FRONT[] =
 R"__cpp_cb(
-int $$::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void *data)
+int [NAME]::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void *data)
 {
-  auto* cxt = static_cast<$$*>(data);
+  auto* cxt = static_cast<[NAME]*>(data);
   rpc_port_parcel_h p;
   rpc_port_parcel_h result;
+  rpc_port_parcel_h header;
+  int seq_num = -1;
   int cmd;
   int ret;
   std::shared_ptr<ServiceBase> b;
@@ -137,7 +142,15 @@ int $$::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port,
     return ret;
   }
 
+  rpc_port_parcel_get_header(p, &header);
+  rpc_port_parcel_header_get_seq_num(header, &seq_num);
+  _W("[Sequence] %d", seq_num);
+
   rpc_port_parcel_create(&result);
+  rpc_port_parcel_get_header(result, &header);
+  rpc_port_parcel_header_set_tag(header, TIDL_VERSION);
+  rpc_port_parcel_header_set_seq_num(header, seq_num);
+
   rpc_port_parcel_read_int32(p, &cmd);
 
   switch (cmd) {
index 51def89cb5d805bc02684304b9b17bfa95524111..8d8d88c391fc2acfdd0bdb7ec6c47b6dbc24f024 100644 (file)
@@ -66,7 +66,7 @@ void CsProxyGen::GenInterface(std::ofstream& stream, const Interface& iface) {
   stream << Tab(2) << "public class " << iface.GetID()
          << " : ProxyBase" << NLine(1);
   GenBrace(stream, TAB_SIZE * 2, [&]() {
-    stream << CB_DATA_MEMBERS;
+    stream << ReplaceAll(CB_DATA_MEMBERS, "<VERSION>", FULLVER);
     GenCallbacks(stream, iface, true);
     GenDelegateId(stream, iface);
     GenMethodId(stream, iface);
@@ -157,18 +157,12 @@ void CsProxyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
 
       st += AddIndent(TAB_SIZE * 5, m) + NLine(1);
 
-      if (decl.GetMethodType() == Declaration::MethodType::SYNC)
-        st += Tab(5) + "Parcel parcelReceived;" + NLine(1);
       st += Tab(5) + "lock (_lock)" + NLine(1);
       st += Tab(5) + "{" + NLine(1);
-        if (!l.empty())
-          st += AddIndent(TAB_SIZE * 6, l) + NLine(1);
-        st += CB_INVOCATION_MID + NLine(1);
-        if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
-          st += Tab(6) + "// Receive" + NLine(1);
-          st += Tab(6)
-             + "ConsumeCommand(out parcelReceived, Port);" + NLine(1);
-        }
+      if (!l.empty())
+        st += AddIndent(TAB_SIZE * 6, l) + NLine(1);
+
+      st += CB_INVOCATION_MID + NLine(1);
       st += Tab(5) + "}";
 
       // Deserialize
@@ -176,12 +170,8 @@ void CsProxyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
         return st;
       }
 
-      const char* receive_block =
-          "if (parcelReceived == null)\n" \
-          "{\n" \
-          "    throw new InvalidProtocolException();\n" \
-          "}\n";
-      st += NLine(1) + AddIndent(TAB_SIZE * 5, receive_block) + NLine(1);
+      st += NLine(1) + AddIndent(TAB_SIZE * 5, CB_INVOCATION_RECEIVE);
+      st += NLine(1);
 
       for (auto& i : decl.GetParameters().GetParams()) {
         if (i->GetParameterType().GetDirection() ==
index 21e25b9188caea14172477d71586f5637c0e03fb..b416f6bfe0dcc9e5a4475c28db25626451117b1f 100644 (file)
 #ifndef IDLC_CS_GEN_CS_PROXY_GEN_CB_H_
 #define IDLC_CS_GEN_CS_PROXY_GEN_CB_H_
 
+/**
+ * <VERSION> Version of TIDL Compiler.
+ */
 const char CB_DATA_MEMBERS[] =
 R"__cs_cb(            public event EventHandler Connected;
             public event EventHandler Disconnected;
             public event EventHandler Rejected;
 
+            private static readonly string _tidlVersion = "<VERSION>";
             private bool _online = false;
             private string _appId;
             private Object _lock = new Object();
@@ -167,6 +171,8 @@ R"__cs_cb(                if (!_online)
 
                 using (Parcel p = new Parcel())
                 {
+                    ParcelHeader header = p.GetHeader();
+                    header.SetTag(_tidlVersion);
 $$
                 }
 )__cs_cb";
@@ -189,4 +195,37 @@ R"__cs_cb(                        // Send
                         p.Send(Port);
 )__cs_cb";
 
+const char CB_INVOCATION_RECEIVE[] =
+R"__cs_cb(
+Parcel parcelReceived;
+bool done = false;
+do
+{
+    lock (_lock)
+    {
+        // Receive
+        ConsumeCommand(out parcelReceived, Port);
+    }
+
+    if (parcelReceived == null)
+    {
+        throw new InvalidProtocolException();
+    }
+
+    ParcelHeader headerReceived = parcelReceived.GetHeader();
+    if (!string.IsNullOrEmpty(headerReceived.GetTag()))
+    {
+        if (headerReceived.GetSequenceNumber() != header.GetSequenceNumber())
+        {
+            parcelReceived.Dispose();
+            parcelReceived = null;
+        }
+    }
+
+    if (parcelReceived != null)
+        done = true;
+}
+while (!done);
+)__cs_cb";
+
 #endif  // IDLC_CS_GEN_CS_PROXY_GEN_CB_H_
index 04b68b37120e1e3069ca64b1ee1346d4e6d7ef64..5cf40fda406ca66c2be8c51bcedc63abc99ef8b6 100644 (file)
@@ -65,7 +65,7 @@ void CsStubGen::GenInterface(std::ofstream& stream, const Interface& iface) {
   stream << Tab(2) << "public sealed class " << iface.GetID()
          << " : StubBase" << NLine(1);
   GenBrace(stream, TAB_SIZE * 2, [&]() {
-    stream << CB_DATA_MEMBERS;
+    stream << ReplaceAll(CB_DATA_MEMBERS, "<VERSION>", FULLVER);
     GenServiceBase(stream, iface);
     GenCallbacks(stream, iface, false);
     GenDelegateId(stream, iface);
@@ -168,7 +168,7 @@ void CsStubGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
     return;
 
   cnt = 0;
-  m = "result.WriteInt((int)MethodId.__Result);\n";
+  m = CB_INVOCATION_RESULT_PRE;
   for (auto& i : decl.GetParameters().GetParams()) {
     auto& pt = i->GetParameterType();
     cnt++;
index 3be382aae0b827397133fc98de077f7fbd990371..1eeb36e1f9736953520c8138a08887218c0bd8c9 100644 (file)
 #ifndef IDLC_CS_GEN_CS_STUB_GEN_CB_H_
 #define IDLC_CS_GEN_CS_STUB_GEN_CB_H_
 
+/**
+ * <VERSION> Version of TIDL Compiler.
+ */
 const char CB_DATA_MEMBERS[] =
 R"__cs_cb(            private List<ServiceBase> _services = new List<ServiceBase>();
             private Type _serviceType;
+            private static readonly string _tidlVersion = "<VERSION>";
 )__cs_cb";
 
 const char CB_SERVICE_BASE_FRONT[] =
@@ -184,4 +188,13 @@ R"__cs_cb(
             }
 )__cs_cb";
 
+constexpr const char CB_INVOCATION_RESULT_PRE[] =
+R"__cs_cb(
+ParcelHeader header = p.GetHeader();
+ParcelHeader resultHeader = result.GetHeader();
+resultHeader.SetTag(_tidlVersion);
+resultHeader.SetSequenceNumber(header.GetSequenceNumber());
+result.WriteInt((int)MethodId.__Result);
+)__cs_cb";
+
 #endif  // IDLC_CS_GEN_CS_STUB_GEN_CB_H_