From eb7256a6a4a56d633624f788d8e0fd2008a6ea71 Mon Sep 17 00:00:00 2001 From: InGeol Baek Date: Sun, 9 Aug 2026 13:28:08 +0900 Subject: [PATCH 1/4] fix: return success status when 0x0000 System Error frame is produced and bump version to 0.1.1 --- pyproject.toml | 2 +- tests/test_c_rpc_flat.c | 2 +- windrpc/__init__.py | 2 +- windrpc/core_spec.yml | 4 ++-- windrpc/server/generator.py | 2 +- windrpc/server/templates/windrpc.c | 14 +++++--------- windrpc/server/templates/windrpc_common.h | 4 ++-- 7 files changed, 13 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7664fb3..63b584d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "windrpc" -version = "0.1.0" +version = "0.1.1" description = "Micro Interconnect & Network Dispatch RPC framework using Protocol Buffers and NanoPB" readme = "README.md" authors = [ diff --git a/tests/test_c_rpc_flat.c b/tests/test_c_rpc_flat.c index ffaf755..52761fb 100644 --- a/tests/test_c_rpc_flat.c +++ b/tests/test_c_rpc_flat.c @@ -104,7 +104,7 @@ int main(void) { txn.buffer.bytes_written = 6; int32_t err_unknown = windrpc_handle(&txn); - assert(err_unknown == -1); + assert(err_unknown == 0); assert(txn.buffer.bytes_written >= 6); assert(tx_buf[0] == 0x00 && tx_buf[1] == 0x00); // System Error RPC ID = 0x0000 assert(tx_buf[2] == 0x07 && tx_buf[3] == 0x00); // seq_id = 7 diff --git a/windrpc/__init__.py b/windrpc/__init__.py index b794fd4..df9144c 100644 --- a/windrpc/__init__.py +++ b/windrpc/__init__.py @@ -1 +1 @@ -__version__ = '0.1.0' +__version__ = '0.1.1' diff --git a/windrpc/core_spec.yml b/windrpc/core_spec.yml index 6dbf8aa..e43ded4 100644 --- a/windrpc/core_spec.yml +++ b/windrpc/core_spec.yml @@ -1,6 +1,6 @@ info: - version_code: 100 - version_name: "0.1.0" + version_code: 101 + version_name: "0.1.1" types: diff --git a/windrpc/server/generator.py b/windrpc/server/generator.py index 2eab807..f8de468 100644 --- a/windrpc/server/generator.py +++ b/windrpc/server/generator.py @@ -322,7 +322,7 @@ def _generate_common_header_content(spec_data, package_name): # Resolve core version from core_info (populated by merge_specs from core_spec.yml info) core_info = spec_data.get('core_info', {}) - core_ver_name = core_info.get('version_name') or core_info.get('version') or '0.1.0' + core_ver_name = core_info.get('version_name') or core_info.get('version') or '0.1.1' core_ver_code = core_info.get('version_code') if core_ver_code is None: try: diff --git a/windrpc/server/templates/windrpc.c b/windrpc/server/templates/windrpc.c index 67ace6c..bdefce0 100644 --- a/windrpc/server/templates/windrpc.c +++ b/windrpc/server/templates/windrpc.c @@ -146,8 +146,7 @@ int32_t windrpc_handle(struct windrpc_transaction* txn) { LOG_ERR("Unknown RPC ID: 0x%04X", rpc_id); ctx->status_code = (int32_t)WINDRPC_STATUS_CODE(UNIMPLEMENTED); snprintf(ctx->status_message, WINDRPC_STATUS_MESSAGE_MAX_LEN, "RPC ID 0x%04X not found", rpc_id); - send_flat_error_response(buffer, seq_id, ctx->status_code, ctx->status_message); - return -1; + return send_flat_error_response(buffer, seq_id, ctx->status_code, ctx->status_message); } ctx->handler = handler; @@ -160,8 +159,7 @@ int32_t windrpc_handle(struct windrpc_transaction* txn) { LOG_ERR("Failed to decode payload for RPC ID 0x%04X: %s", rpc_id, PB_GET_ERROR(&istream)); ctx->status_code = (int32_t)WINDRPC_STATUS_CODE(INVALID_DATA_FORMAT); snprintf(ctx->status_message, WINDRPC_STATUS_MESSAGE_MAX_LEN, "Invalid data format"); - send_flat_error_response(buffer, seq_id, ctx->status_code, ctx->status_message); - return -1; + return send_flat_error_response(buffer, seq_id, ctx->status_code, ctx->status_message); } } @@ -172,8 +170,7 @@ int32_t windrpc_handle(struct windrpc_transaction* txn) { LOG_WRN("Execution failed with application error: %d", status); ctx->status_code = status; const char* msg = (ctx->status_message[0] != '\0') ? ctx->status_message : windrpc_strerror(status); - send_flat_error_response(buffer, seq_id, status, msg); - return status; + return send_flat_error_response(buffer, seq_id, status, msg); } // REQUEST_ONLY pattern: skip TX response @@ -200,8 +197,7 @@ int32_t windrpc_handle(struct windrpc_transaction* txn) { if (handler->res_fields && res_ptr) { if (!pb_encode(&ostream, handler->res_fields, res_ptr)) { LOG_ERR("Failed to encode response for RPC ID 0x%04X", rpc_id); - send_flat_error_response(buffer, seq_id, WINDRPC_STATUS_CODE(INTERNAL), "Failed to encode response"); - return -1; + return send_flat_error_response(buffer, seq_id, WINDRPC_STATUS_CODE(INTERNAL), "Failed to encode response"); } } @@ -233,7 +229,7 @@ int32_t windrpc_process_packet(const uint8_t* rx_packet, uint16_t rx_len, int32_t err = windrpc_handle(&txn); - if (!err && txn.buffer.bytes_written > 0 && out_resp_buf && out_resp_len) { + if (txn.buffer.bytes_written > 0 && out_resp_buf && out_resp_len) { uint16_t copy_len = (txn.buffer.bytes_written < max_resp_len) ? txn.buffer.bytes_written : max_resp_len; memcpy(out_resp_buf, txn.buffer.tx_data, copy_len); *out_resp_len = copy_len; diff --git a/windrpc/server/templates/windrpc_common.h b/windrpc/server/templates/windrpc_common.h index d0facae..5d4b33b 100644 --- a/windrpc/server/templates/windrpc_common.h +++ b/windrpc/server/templates/windrpc_common.h @@ -62,11 +62,11 @@ #define WINDRPC_CAT6(a, b, c, d, e, f) WINDRPC_CAT6_IMPL(a, b, c, d, e, f) #ifndef WINDRPC_CORE_VERSION_CODE -#define WINDRPC_CORE_VERSION_CODE 100 +#define WINDRPC_CORE_VERSION_CODE 101 #endif #ifndef WINDRPC_CORE_VERSION_NAME -#define WINDRPC_CORE_VERSION_NAME "0.1.0" +#define WINDRPC_CORE_VERSION_NAME "0.1.1" #endif #define WINDRPC_STATUS_CODE(name) \ From a0747ca05b75299bfb7b5583930dcc2111cb868d Mon Sep 17 00:00:00 2001 From: InGeol Baek Date: Sun, 9 Aug 2026 13:35:18 +0900 Subject: [PATCH 2/4] docs: add Doxygen comments and manual notes for windrpc_handle return semantics --- docs/windrpc_manual.KR.md | 4 ++++ docs/windrpc_manual.md | 4 ++++ windrpc/server/templates/windrpc.h | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/docs/windrpc_manual.KR.md b/docs/windrpc_manual.KR.md index b1b96a4..6b6a1a3 100644 --- a/docs/windrpc_manual.KR.md +++ b/docs/windrpc_manual.KR.md @@ -277,6 +277,10 @@ void process_incoming_packet(uint8_t *data, size_t len) { } ``` +> [!NOTE] +> **`windrpc_handle(&txn)` 반환값 시맨틱** +> `windrpc_handle`이 `0`을 반환하는 것은 "송신 채널로 보낼 응답 패킷(정상 응답 또는 `0x0000` 시스템 에러 패킷)이 `tx_data`에 정상 생성됨"을 의미합니다. 음수(`-1`) 반환은 버퍼 크기 부족 등 패킷 생성이 불가능한 치명적 시스템 오류 발생 시에만 리턴됩니다. 애플리케이션 수준의 에러 코드는 `txn.context.status_code` 및 패킷 페이로드에 저장되어 전송됩니다. + ### 4.3 빌드 및 멀티스레드 주의사항 - `prj.conf` 설정: diff --git a/docs/windrpc_manual.md b/docs/windrpc_manual.md index 4b45f08..a7c9ec7 100644 --- a/docs/windrpc_manual.md +++ b/docs/windrpc_manual.md @@ -274,6 +274,10 @@ void process_incoming_packet(uint8_t *data, size_t len) { } ``` +> [!NOTE] +> **`windrpc_handle(&txn)` Return Value Semantics** +> Returning `0` from `windrpc_handle` signifies that a response packet (either a normal RPC response or a `0x0000` System Error response) was successfully generated into `tx_data` for transmission. A negative return value (`-1`) indicates a fatal framing or buffer size failure where no response packet could be produced. Application-level RPC error codes are stored in `txn.context.status_code`. + ### 4.3 Build Rules & Concurrency - `prj.conf` settings: diff --git a/windrpc/server/templates/windrpc.h b/windrpc/server/templates/windrpc.h index 1d1fe7b..7936a42 100644 --- a/windrpc/server/templates/windrpc.h +++ b/windrpc/server/templates/windrpc.h @@ -35,11 +35,30 @@ struct windrpc_transaction { }; int32_t windrpc_init(struct windrpc_device_info* device_info); + +/** + * @brief Dispatch incoming RPC packet and generate response frame into txn->buffer.tx_data. + * + * @param txn Pointer to the RPC transaction structure. + * @return 0 If frame processing completed and a response packet (either normal success response + * or 0x0000 System Error packet) was written to txn->buffer.tx_data ready for transmission + * (or 0 bytes written for REQUEST_ONLY RPCs). + * -1 If a fatal internal error occurred (e.g. input buffer < 6 bytes, NULL tx_data) + * where no response frame could be generated. + * + * @note Application-level status code is stored in txn->context.status_code. + */ int32_t windrpc_handle(struct windrpc_transaction* txn); + int32_t windrpc_notify(struct windrpc_transaction* txn); const char* windrpc_strerror(int32_t code); void windrpc_set_error(struct windrpc_context* ctx, int32_t code, const char* message); +/** + * @brief Transport-agnostic helper to process raw packet bytes and copy response frame. + * + * @return 0 on successful frame production, non-zero on fatal internal error. + */ int32_t windrpc_process_packet(const uint8_t* rx_packet, uint16_t rx_len, uint8_t* out_resp_buf, uint16_t max_resp_len, uint16_t* out_resp_len); From 9d02bd098c52f6fc017612c50f0940b2468489d2 Mon Sep 17 00:00:00 2001 From: InGeol Baek Date: Sun, 9 Aug 2026 13:39:53 +0900 Subject: [PATCH 3/4] docs: clarify windrpc_process_packet docstring regarding system error frames --- windrpc/server/templates/windrpc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/windrpc/server/templates/windrpc.h b/windrpc/server/templates/windrpc.h index 7936a42..52220d6 100644 --- a/windrpc/server/templates/windrpc.h +++ b/windrpc/server/templates/windrpc.h @@ -57,7 +57,8 @@ void windrpc_set_error(struct windrpc_context* ctx, int32_t code, const char* me /** * @brief Transport-agnostic helper to process raw packet bytes and copy response frame. * - * @return 0 on successful frame production, non-zero on fatal internal error. + * @return 0 on successful response frame production (including normal responses and 0x0000 System Error frames), + * non-zero on fatal internal error where no response frame could be generated. */ int32_t windrpc_process_packet(const uint8_t* rx_packet, uint16_t rx_len, uint8_t* out_resp_buf, uint16_t max_resp_len, uint16_t* out_resp_len); From 8281b4075ef30170501c493e50e7b8a64684d5f5 Mon Sep 17 00:00:00 2001 From: InGeol Baek Date: Sun, 9 Aug 2026 13:41:09 +0900 Subject: [PATCH 4/4] docs: add @note mirrors windrpc_handle return semantics to windrpc_process_packet --- windrpc/server/templates/windrpc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/windrpc/server/templates/windrpc.h b/windrpc/server/templates/windrpc.h index 52220d6..53259d0 100644 --- a/windrpc/server/templates/windrpc.h +++ b/windrpc/server/templates/windrpc.h @@ -59,6 +59,8 @@ void windrpc_set_error(struct windrpc_context* ctx, int32_t code, const char* me * * @return 0 on successful response frame production (including normal responses and 0x0000 System Error frames), * non-zero on fatal internal error where no response frame could be generated. + * + * @note Mirrors the return semantics of windrpc_handle(). */ int32_t windrpc_process_packet(const uint8_t* rx_packet, uint16_t rx_len, uint8_t* out_resp_buf, uint16_t max_resp_len, uint16_t* out_resp_len);