You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2026/10/12 10:47:09 UTC

(plc4x) 04/05: fix(plc4c/plc4x): report the proxy's response code instead of INTERNAL_ERROR

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit a0d3378bbe26c30c8022ae9d3b06fb814255317d
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Oct 12 12:37:05 2026 +0200

    fix(plc4c/plc4x): report the proxy's response code instead of INTERNAL_ERROR
    
    The plc4x proxy driver turned every response code other than OK into
    INTERNAL_ERROR, for reads and writes alike, so a C caller couldn't tell a
    missing tag, a denied access or a timeout apart. The code is now mapped to the
    matching plc4c one where plc4c has it (OK, NOT_FOUND, ACCESS_DENIED,
    INVALID_ADDRESS, INVALID_DATATYPE, RESPONSE_PENDING, REQUEST_TIMEOUT); the
    codes plc4c has no counterpart for are still INTERNAL_ERROR.
    
    The test covers every wire code and fails when one is added without deciding
    its mapping.
---
 .../plc4x/include/plc4c/driver_plc4x_packets.h     | 10 ++++++
 plc4c/drivers/plc4x/src/driver_plc4x_packets.c     | 24 +++++++++++++++
 plc4c/drivers/plc4x/src/driver_plc4x_sm_read.c     |  7 ++---
 plc4c/drivers/plc4x/src/driver_plc4x_sm_write.c    |  8 ++---
 plc4c/drivers/plc4x/test/plc4x_test.c              | 36 ++++++++++++++++++++++
 5 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/plc4c/drivers/plc4x/include/plc4c/driver_plc4x_packets.h b/plc4c/drivers/plc4x/include/plc4c/driver_plc4x_packets.h
index 1a62daa59e..70f3d6e635 100644
--- a/plc4c/drivers/plc4x/include/plc4c/driver_plc4x_packets.h
+++ b/plc4c/drivers/plc4x/include/plc4c/driver_plc4x_packets.h
@@ -53,6 +53,16 @@ plc4c_return_code plc4c_driver_plc4x_create_plc4x_write_request(
 void plc4c_driver_plc4x_destroy_plc4x_write_request(
     plc4c_plc4x_read_write_plc4x_message* packet);
 
+/**
+ * Translates a response code received from the proxy into the one plc4c reports for the tag.
+ * Codes plc4c has no counterpart for are reported as PLC4C_RESPONSE_CODE_INTERNAL_ERROR.
+ *
+ * @param response_code the code as it came over the wire.
+ * @return the code to report to the caller.
+ */
+plc4c_response_code plc4c_driver_plc4x_map_response_code(
+    plc4c_plc4x_read_write_plc4x_response_code response_code);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/plc4c/drivers/plc4x/src/driver_plc4x_packets.c b/plc4c/drivers/plc4x/src/driver_plc4x_packets.c
index 2acee6d51d..7ebf1f143e 100644
--- a/plc4c/drivers/plc4x/src/driver_plc4x_packets.c
+++ b/plc4c/drivers/plc4x/src/driver_plc4x_packets.c
@@ -329,3 +329,27 @@ void plc4c_driver_plc4x_destroy_plc4x_write_request(plc4c_plc4x_read_write_plc4x
 
 
 
+
+plc4c_response_code plc4c_driver_plc4x_map_response_code(
+    plc4c_plc4x_read_write_plc4x_response_code response_code) {
+  switch (response_code) {
+    case plc4c_plc4x_read_write_plc4x_response_code_OK:
+      return PLC4C_RESPONSE_CODE_OK;
+    case plc4c_plc4x_read_write_plc4x_response_code_NOT_FOUND:
+      return PLC4C_RESPONSE_CODE_NOT_FOUND;
+    case plc4c_plc4x_read_write_plc4x_response_code_ACCESS_DENIED:
+      return PLC4C_RESPONSE_CODE_ACCESS_DENIED;
+    case plc4c_plc4x_read_write_plc4x_response_code_INVALID_ADDRESS:
+      return PLC4C_RESPONSE_CODE_INVALID_ADDRESS;
+    case plc4c_plc4x_read_write_plc4x_response_code_INVALID_DATATYPE:
+      return PLC4C_RESPONSE_CODE_INVALID_DATATYPE;
+    case plc4c_plc4x_read_write_plc4x_response_code_RESPONSE_PENDING:
+      return PLC4C_RESPONSE_CODE_RESPONSE_PENDING;
+    case plc4c_plc4x_read_write_plc4x_response_code_REQUEST_TIMEOUT:
+      return PLC4C_RESPONSE_CODE_REQUEST_TIMEOUT;
+    default:
+      // INVALID_DATA, REMOTE_BUSY, REMOTE_ERROR, UNSUPPORTED, NOT_READY and OUT_OF_RANGE have no
+      // plc4c counterpart (yet), and INTERNAL_ERROR maps onto itself.
+      return PLC4C_RESPONSE_CODE_INTERNAL_ERROR;
+  }
+}
diff --git a/plc4c/drivers/plc4x/src/driver_plc4x_sm_read.c b/plc4c/drivers/plc4x/src/driver_plc4x_sm_read.c
index f0a0d177e2..b1d65d37de 100644
--- a/plc4c/drivers/plc4x/src/driver_plc4x_sm_read.c
+++ b/plc4c/drivers/plc4x/src/driver_plc4x_sm_read.c
@@ -216,11 +216,8 @@ plc4c_return_code plc4c_driver_plc4x_parse_read_response(
 
     response_value_item->item = request_item;
 
-    if (payload_item->response_code == plc4c_plc4x_read_write_plc4x_response_code_OK) {
-      response_value_item->response_code = PLC4C_RESPONSE_CODE_OK;
-    } else {
-      response_value_item->response_code = PLC4C_RESPONSE_CODE_INTERNAL_ERROR;
-    }
+    response_value_item->response_code =
+        plc4c_driver_plc4x_map_response_code(payload_item->response_code);
     
     response_value_item->value = payload_item->value;
 
diff --git a/plc4c/drivers/plc4x/src/driver_plc4x_sm_write.c b/plc4c/drivers/plc4x/src/driver_plc4x_sm_write.c
index 1aae8c796d..65595eb386 100644
--- a/plc4c/drivers/plc4x/src/driver_plc4x_sm_write.c
+++ b/plc4c/drivers/plc4x/src/driver_plc4x_sm_write.c
@@ -215,12 +215,8 @@ plc4c_return_code plc4c_driver_plc4x_parse_write_response(
     }
     response_item->item = request_item->item;
 
-    // TODO: better map transport error codes to response error codes
-    if (plc4x_payload_item->response_code == plc4c_plc4x_read_write_plc4x_response_code_OK) {
-      response_item->response_code = PLC4C_RESPONSE_CODE_OK;
-    } else {
-      response_item->response_code = PLC4C_RESPONSE_CODE_INTERNAL_ERROR;
-    }
+    response_item->response_code =
+        plc4c_driver_plc4x_map_response_code(plc4x_payload_item->response_code);
 
     plc4c_utils_list_insert_head_value(execution->write_response->response_items, response_item);
 
diff --git a/plc4c/drivers/plc4x/test/plc4x_test.c b/plc4c/drivers/plc4x/test/plc4x_test.c
index 3e8056d2c1..52145875a0 100644
--- a/plc4c/drivers/plc4x/test/plc4x_test.c
+++ b/plc4c/drivers/plc4x/test/plc4x_test.c
@@ -18,17 +18,53 @@
  */
 #include <unity.h>
 
+#include "plc4c/driver_plc4x_packets.h"
+
 void parser_serializer_test_plc4x_read_write();
 
 void setUp(void) {}
 
 void tearDown(void) {}
 
+// Every code the proxy can put on the wire, and what a plc4c caller sees for it: the one plc4c
+// has where it has one, INTERNAL_ERROR where it doesn't.
+void test_plc4x_response_code_mapping(void) {
+  struct {
+    plc4c_plc4x_read_write_plc4x_response_code wire;
+    plc4c_response_code expected;
+  } cases[] = {
+      {plc4c_plc4x_read_write_plc4x_response_code_OK, PLC4C_RESPONSE_CODE_OK},
+      {plc4c_plc4x_read_write_plc4x_response_code_NOT_FOUND, PLC4C_RESPONSE_CODE_NOT_FOUND},
+      {plc4c_plc4x_read_write_plc4x_response_code_ACCESS_DENIED, PLC4C_RESPONSE_CODE_ACCESS_DENIED},
+      {plc4c_plc4x_read_write_plc4x_response_code_INVALID_ADDRESS, PLC4C_RESPONSE_CODE_INVALID_ADDRESS},
+      {plc4c_plc4x_read_write_plc4x_response_code_INVALID_DATATYPE, PLC4C_RESPONSE_CODE_INVALID_DATATYPE},
+      {plc4c_plc4x_read_write_plc4x_response_code_INVALID_DATA, PLC4C_RESPONSE_CODE_INTERNAL_ERROR},
+      {plc4c_plc4x_read_write_plc4x_response_code_INTERNAL_ERROR, PLC4C_RESPONSE_CODE_INTERNAL_ERROR},
+      {plc4c_plc4x_read_write_plc4x_response_code_REMOTE_BUSY, PLC4C_RESPONSE_CODE_INTERNAL_ERROR},
+      {plc4c_plc4x_read_write_plc4x_response_code_REMOTE_ERROR, PLC4C_RESPONSE_CODE_INTERNAL_ERROR},
+      {plc4c_plc4x_read_write_plc4x_response_code_UNSUPPORTED, PLC4C_RESPONSE_CODE_INTERNAL_ERROR},
+      {plc4c_plc4x_read_write_plc4x_response_code_RESPONSE_PENDING, PLC4C_RESPONSE_CODE_RESPONSE_PENDING},
+      {plc4c_plc4x_read_write_plc4x_response_code_NOT_READY, PLC4C_RESPONSE_CODE_INTERNAL_ERROR},
+      {plc4c_plc4x_read_write_plc4x_response_code_OUT_OF_RANGE, PLC4C_RESPONSE_CODE_INTERNAL_ERROR},
+      {plc4c_plc4x_read_write_plc4x_response_code_REQUEST_TIMEOUT, PLC4C_RESPONSE_CODE_REQUEST_TIMEOUT},
+  };
+  int num_cases = sizeof(cases) / sizeof(cases[0]);
+
+  // A code added to the wire enum has to be added here, so that its mapping is a decision.
+  TEST_ASSERT_EQUAL_INT(plc4c_plc4x_read_write_plc4x_response_code_num_values(), num_cases);
+  for (int i = 0; i < num_cases; i++) {
+    TEST_ASSERT_EQUAL_INT_MESSAGE(cases[i].expected,
+        plc4c_driver_plc4x_map_response_code(cases[i].wire),
+        plc4c_response_code_to_message(cases[i].expected));
+  }
+}
+
 int main(void) {
   UNITY_BEGIN();
 
   // Execute the auto-generated serializer/parser tests.
   parser_serializer_test_plc4x_read_write();
+  RUN_TEST(test_plc4x_response_code_mapping);
 
   return UNITY_END();
 }
\ No newline at end of file