diff --git a/src/bacnet/abort.c b/src/bacnet/abort.c index 41f9d6d4..7690a133 100644 --- a/src/bacnet/abort.c +++ b/src/bacnet/abort.c @@ -38,10 +38,17 @@ #include "bacnet/abort.h" /** @file abort.c Abort Encoding/Decoding */ -/* Helper function to avoid needing additional entries in service data + +/** + * @brief Convert error-code into abort-reason + * + * Helper function to avoid needing additional entries in service data * structures when passing back abort status. Convert from error code to abort - * code. Anything not defined converts to ABORT_REASON_OTHER. Will need - * reworking if it is required to return proprietary abort codes. + * code. Anything not defined converts to ABORT_REASON_OTHER. Alternate + * methods are required to return proprietary abort codes. + * + * @param error_code - BACnet Error Code to convert + * @return abort code or ABORT_REASON_OTHER if not found */ BACNET_ABORT_REASON abort_convert_error_code(BACNET_ERROR_CODE error_code) { @@ -60,6 +67,12 @@ BACNET_ABORT_REASON abort_convert_error_code(BACNET_ERROR_CODE error_code) case ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED: abort_code = ABORT_REASON_SEGMENTATION_NOT_SUPPORTED; break; + case ERROR_CODE_ABORT_SECURITY_ERROR: + abort_code = ABORT_REASON_SECURITY_ERROR; + break; + case ERROR_CODE_ABORT_INSUFFICIENT_SECURITY: + abort_code = ABORT_REASON_INSUFFICIENT_SECURITY; + break; case ERROR_CODE_ABORT_PROPRIETARY: abort_code = ABORT_REASON_PROPRIETARY_FIRST; break; @@ -72,6 +85,54 @@ BACNET_ABORT_REASON abort_convert_error_code(BACNET_ERROR_CODE error_code) return (abort_code); } +/** + * @brief Convert error-code from abort-reason + * + * Helper function to avoid needing additional entries in service data + * structures when passing back abort status. Converts to error code from + * abort code. Anything not defined converts to ABORT_REASON_OTHER. + * Alternate methods are required to return proprietary abort codes. + * + * @param abort_code - BACnet Error Code to convert + * @return error code or ERROR_CODE_ABORT_OTHER if not found + */ +BACNET_ERROR_CODE abort_convert_to_error_code(BACNET_ABORT_REASON abort_code) +{ + BACNET_ERROR_CODE error_code = ERROR_CODE_ABORT_OTHER; + + switch (abort_code) { + case ABORT_REASON_BUFFER_OVERFLOW: + error_code = ERROR_CODE_ABORT_BUFFER_OVERFLOW; + break; + case ABORT_REASON_INVALID_APDU_IN_THIS_STATE: + error_code = ERROR_CODE_ABORT_INVALID_APDU_IN_THIS_STATE; + break; + case ABORT_REASON_PREEMPTED_BY_HIGHER_PRIORITY_TASK: + error_code = ERROR_CODE_ABORT_PREEMPTED_BY_HIGHER_PRIORITY_TASK; + break; + case ABORT_REASON_SEGMENTATION_NOT_SUPPORTED: + error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; + break; + case ABORT_REASON_SECURITY_ERROR: + error_code = ERROR_CODE_ABORT_SECURITY_ERROR; + break; + case ABORT_REASON_INSUFFICIENT_SECURITY: + error_code = ERROR_CODE_ABORT_INSUFFICIENT_SECURITY; + break; + case ABORT_REASON_OTHER: + error_code = ERROR_CODE_ABORT_OTHER; + break; + default: + if ((abort_code >= ABORT_REASON_PROPRIETARY_FIRST) && + (abort_code <= ABORT_REASON_PROPRIETARY_LAST)) { + error_code = ERROR_CODE_ABORT_PROPRIETARY; + } + break; + } + + return (error_code); +} + /* encode service */ int abort_encode_apdu( uint8_t *apdu, uint8_t invoke_id, uint8_t abort_reason, bool server) @@ -118,7 +179,7 @@ int abort_decode_service_request( #include "ctest.h" /* decode the whole APDU - mainly used for unit testing */ -int abort_decode_apdu(uint8_t *apdu, +static int abort_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id, uint8_t *abort_reason, @@ -145,7 +206,7 @@ int abort_decode_apdu(uint8_t *apdu, return len; } -void testAbortAPDU( +static void testAbortAPDU( Test *pTest, uint8_t invoke_id, uint8_t abort_reason, bool server) { uint8_t apdu[480] = { 0 }; @@ -168,7 +229,7 @@ void testAbortAPDU( return; } -void testAbort(Test *pTest) +static void testAbortEncodeDecode(Test *pTest) { uint8_t apdu[480] = { 0 }; int len = 0; @@ -215,6 +276,32 @@ void testAbort(Test *pTest) } } +static void testAbortError(Test *pTest) +{ + int i; + BACNET_ERROR_CODE error_code; + BACNET_ABORT_REASON abort_code; + BACNET_ABORT_REASON test_abort_code; + + for (i = 0; i < MAX_BACNET_ABORT_REASON; i++) { + abort_code = (BACNET_ABORT_REASON)i; + error_code = abort_convert_to_error_code(abort_code); + test_abort_code = abort_convert_error_code(error_code); + if (test_abort_code != abort_code) { + printf("Abort: result=%u abort-code=%u\n", + test_abort_code, + abort_code); + } + ct_test(pTest, test_abort_code == abort_code); + } +} + +void testAbort(Test *pTest) +{ + testAbortEncodeDecode(pTest); + testAbortError(pTest); +} + #ifdef TEST_ABORT int main(void) { diff --git a/src/bacnet/abort.h b/src/bacnet/abort.h index fc797b71..4930c1fc 100644 --- a/src/bacnet/abort.h +++ b/src/bacnet/abort.h @@ -34,6 +34,8 @@ extern "C" { BACNET_ABORT_REASON abort_convert_error_code( BACNET_ERROR_CODE error_code); + BACNET_ERROR_CODE abort_convert_to_error_code( + BACNET_ABORT_REASON abort_code); int abort_encode_apdu( uint8_t * apdu, @@ -49,13 +51,6 @@ extern "C" { #ifdef TEST #include "ctest.h" - int abort_decode_apdu( - uint8_t * apdu, - unsigned apdu_len, - uint8_t * invoke_id, - uint8_t * abort_reason, - bool * server); - void testAbort( Test * pTest); #endif diff --git a/src/bacnet/bactext.c b/src/bacnet/bactext.c index 886efc6e..27c2ba66 100644 --- a/src/bacnet/bactext.c +++ b/src/bacnet/bactext.c @@ -970,6 +970,8 @@ INDTEXT_DATA bacnet_abort_reason_names[] = { { ABORT_REASON_OTHER, "Other" }, { ABORT_REASON_PREEMPTED_BY_HIGHER_PRIORITY_TASK, "Preempted by Higher Priority Task" }, { ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, "Segmentation Not Supported" }, + { ABORT_REASON_SECURITY_ERROR, "Security Error" }, + { ABORT_REASON_INSUFFICIENT_SECURITY, "Insufficient Security" }, { ABORT_REASON_PROPRIETARY_FIRST, "Proprietary" }, { 0, NULL } }; const char *bactext_abort_reason_name(unsigned index)