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