From 5d079254cc714864cc864ba9cb30a238f3784a52 Mon Sep 17 00:00:00 2001 From: jakubovsky Date: Tue, 3 Jul 2012 14:35:07 +0200 Subject: [PATCH] Extended mbus_recv_frame() error codes, improved collision handling - handling TCP connection reset and read(2) timeout --- bin/mbus-serial-request-data.c | 2 +- bin/mbus-serial-scan.c | 13 ++---- bin/mbus-serial-select-secondary.c | 4 +- bin/mbus-serial-switch-baudrate.c | 2 +- bin/mbus-tcp-request-data.c | 6 +-- bin/mbus-tcp-scan.c | 17 ++------ bin/mbus-tcp-select-secondary.c | 4 +- mbus/mbus-protocol-aux.c | 36 ++++++++++------ mbus/mbus-protocol-aux.h | 9 ++++ mbus/mbus-tcp.c | 67 +++++++++++++----------------- 10 files changed, 78 insertions(+), 82 deletions(-) mode change 100644 => 100755 bin/mbus-serial-request-data.c mode change 100644 => 100755 bin/mbus-serial-scan.c mode change 100644 => 100755 bin/mbus-serial-select-secondary.c mode change 100644 => 100755 bin/mbus-serial-switch-baudrate.c mode change 100644 => 100755 bin/mbus-tcp-request-data.c mode change 100644 => 100755 bin/mbus-tcp-scan.c mode change 100644 => 100755 bin/mbus-tcp-select-secondary.c mode change 100644 => 100755 mbus/mbus-protocol-aux.c mode change 100644 => 100755 mbus/mbus-protocol-aux.h mode change 100644 => 100755 mbus/mbus-tcp.c diff --git a/bin/mbus-serial-request-data.c b/bin/mbus-serial-request-data.c old mode 100644 new mode 100755 index d60a777..219a49d --- a/bin/mbus-serial-request-data.c +++ b/bin/mbus-serial-request-data.c @@ -126,7 +126,7 @@ main(int argc, char **argv) } } - if (mbus_recv_frame(handle, &reply) == -1) + if (mbus_recv_frame(handle, &reply) != 0) { fprintf(stderr, "Failed to receive M-Bus response frame.\n"); return 1; diff --git a/bin/mbus-serial-scan.c b/bin/mbus-serial-scan.c old mode 100644 new mode 100755 index 3d7c8bf..cfd325a --- a/bin/mbus-serial-scan.c +++ b/bin/mbus-serial-scan.c @@ -97,7 +97,7 @@ main(int argc, char **argv) ret = mbus_recv_frame(handle, &reply); - if (ret == -1) + if (ret == -3) { continue; } @@ -108,22 +108,15 @@ main(int argc, char **argv) if (ret == -2) { /* check for more data (collision) */ - while (mbus_recv_frame(handle, &reply) != -1); - + mbus_recv_frame_dummy(handle); printf("Collision at address %d\n", address); - continue; } if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK) { /* check for more data (collision) */ - while (mbus_recv_frame(handle, &reply) != -1) - { - ret = -2; - } - - if (ret == -2) + if (mbus_recv_frame_dummy(handle)) { printf("Collision at address %d\n", address); diff --git a/bin/mbus-serial-select-secondary.c b/bin/mbus-serial-select-secondary.c old mode 100644 new mode 100755 index a5b7067..6fe462b --- a/bin/mbus-serial-select-secondary.c +++ b/bin/mbus-serial-select-secondary.c @@ -73,7 +73,7 @@ main(int argc, char **argv) ret = mbus_recv_frame(handle, &reply); - if (ret == -1) + if (ret == -3) { printf("No reply from device with secondary address %s: %s\n", argv[2], mbus_error_str()); return 1; @@ -93,7 +93,7 @@ main(int argc, char **argv) return 1; } - if (mbus_recv_frame(handle, &reply) == -1) + if (mbus_recv_frame(handle, &reply) != 0) { printf("Failed to recieve reply from selected secondary device: %s\n", mbus_error_str()); return 1; diff --git a/bin/mbus-serial-switch-baudrate.c b/bin/mbus-serial-switch-baudrate.c old mode 100644 new mode 100755 index 4a0d91e..249f5d5 --- a/bin/mbus-serial-switch-baudrate.c +++ b/bin/mbus-serial-switch-baudrate.c @@ -72,7 +72,7 @@ main(int argc, char **argv) ret = mbus_recv_frame(handle, &reply); - if (ret == -1) + if (ret == -3) { printf("No reply from device\n"); return 1; diff --git a/bin/mbus-tcp-request-data.c b/bin/mbus-tcp-request-data.c old mode 100644 new mode 100755 index 7b40f28..6024f4b --- a/bin/mbus-tcp-request-data.c +++ b/bin/mbus-tcp-request-data.c @@ -111,11 +111,11 @@ main(int argc, char **argv) } } - if (mbus_recv_frame(handle, &reply) == -1) + if (mbus_recv_frame(handle, &reply) != 0) { - fprintf(stderr, "Failed to receive M-Bus response frame.\n"); + fprintf(stderr, "Failed to receive M-Bus response frame: %s\n", mbus_error_str()); return 1; - } + } // // parse data and print in XML format diff --git a/bin/mbus-tcp-scan.c b/bin/mbus-tcp-scan.c old mode 100644 new mode 100755 index d6dcee4..4de525e --- a/bin/mbus-tcp-scan.c +++ b/bin/mbus-tcp-scan.c @@ -17,7 +17,6 @@ #include #include - //------------------------------------------------------------------------------ // Execution starts here: //------------------------------------------------------------------------------ @@ -81,7 +80,7 @@ main(int argc, char **argv) ret = mbus_recv_frame(handle, &reply); - if (ret == -1) + if (ret == -3) { continue; } @@ -92,28 +91,20 @@ main(int argc, char **argv) if (ret == -2) { /* check for more data (collision) */ - while (mbus_recv_frame(handle, &reply) != -1); - + mbus_recv_frame_dummy(handle); printf("Collision at address %d\n", address); - continue; } if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK) { /* check for more data (collision) */ - while (mbus_recv_frame(handle, &reply) != -1) - { - ret = -2; - } - - if (ret == -2) + if (mbus_recv_frame_dummy(handle)) { printf("Collision at address %d\n", address); - continue; } - + printf("Found a M-Bus device at address %d\n", address); } } diff --git a/bin/mbus-tcp-select-secondary.c b/bin/mbus-tcp-select-secondary.c old mode 100644 new mode 100755 index 712abe2..698ef9d --- a/bin/mbus-tcp-select-secondary.c +++ b/bin/mbus-tcp-select-secondary.c @@ -59,7 +59,7 @@ main(int argc, char **argv) ret = mbus_recv_frame(handle, &reply); - if (ret == -1) + if (ret == -3) { printf("No reply from device with secondary address %s: %s\n", argv[3], mbus_error_str()); return 1; @@ -79,7 +79,7 @@ main(int argc, char **argv) return 1; } - if (mbus_recv_frame(handle, &reply) == -1) + if (mbus_recv_frame(handle, &reply) != 0) { printf("Failed to recieve reply from selected secondary device: %s\n", mbus_error_str()); return 1; diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c old mode 100644 new mode 100755 index 2323bec..fa06bb5 --- a/mbus/mbus-protocol-aux.c +++ b/mbus/mbus-protocol-aux.c @@ -1407,6 +1407,24 @@ mbus_recv_frame(mbus_handle * handle, mbus_frame *frame) return result; } +int mbus_recv_frame_dummy(mbus_handle *handle) +{ + int err, received; + mbus_frame reply; + + received = 0; + while (1) + { + err = mbus_recv_frame(handle, &reply); + if (err != -2 && err != 0) + break; + + received = 1; + } + + return received; +} + int mbus_send_frame(mbus_handle * handle, mbus_frame *frame) { @@ -1601,7 +1619,7 @@ mbus_sendrecv_request(mbus_handle *handle, int address, mbus_frame *reply, int m if (debug) printf("%s: debug: receiving response frame #%d\n", __PRETTY_FUNCTION__, frame_count); - if (mbus_recv_frame(handle, next_frame) == -1) + if (mbus_recv_frame(handle, next_frame) != 0) { MBUS_ERROR("%s: Failed to receive M-Bus response frame.\n", __PRETTY_FUNCTION__); retval = 1; @@ -1743,7 +1761,7 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask) ret = mbus_recv_frame(handle, &reply); - if (ret == -1) + if (ret == -3) { return MBUS_PROBE_NOTHING; } @@ -1751,20 +1769,14 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask) if (ret == -2) { /* check for more data (collision) */ - while (mbus_recv_frame(handle, &reply) != -1); - + mbus_recv_frame_dummy(handle); return MBUS_PROBE_COLLISION; } if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK) { /* check for more data (collision) */ - while (mbus_recv_frame(handle, &reply) != -1) - { - ret = -2; - } - - if (ret == -2) + if (mbus_recv_frame_dummy(handle)) { return MBUS_PROBE_COLLISION; } @@ -1809,7 +1821,7 @@ mbus_probe_secondary_address(mbus_handle * handle, const char *mask, char *match ret = mbus_recv_frame(handle, &reply); - if (ret == -1) + if (ret == -3) { return MBUS_PROBE_NOTHING; } @@ -1905,7 +1917,7 @@ int mbus_read_slave(mbus_handle * handle, mbus_address *address, mbus_frame * re } } - if (mbus_recv_frame(handle, reply) == -1) + if (mbus_recv_frame(handle, reply) != 0) { MBUS_ERROR("%s: Failed to receive M-Bus response frame.\n", __PRETTY_FUNCTION__); diff --git a/mbus/mbus-protocol-aux.h b/mbus/mbus-protocol-aux.h old mode 100644 new mode 100755 index 39cc454..f5be172 --- a/mbus/mbus-protocol-aux.h +++ b/mbus/mbus-protocol-aux.h @@ -179,6 +179,15 @@ int mbus_disconnect(mbus_handle * handle); int mbus_recv_frame(mbus_handle * handle, mbus_frame *frame); /** + * Used for handling collisions. Blocks as long as receiving frames or corrupted data. + * + * @param handle Initialized handle + * + * @return Zero when nothing received, one otherwise. + */ +int mbus_recv_frame_dummy(mbus_handle * handle); + +/** * Sends frame using "unified" handle * * @param handle Initialized handle diff --git a/mbus/mbus-tcp.c b/mbus/mbus-tcp.c old mode 100644 new mode 100755 index f29e8ce..cc14b18 --- a/mbus/mbus-tcp.c +++ b/mbus/mbus-tcp.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -161,69 +162,59 @@ mbus_tcp_send_frame(mbus_tcp_handle *handle, mbus_frame *frame) //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ -int -mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame) +int mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame) { char buff[PACKET_BUFF_SIZE]; - int len, remaining, nread, timeouts; - - if (handle == NULL || frame == NULL) - { + int len, remaining, nread; + + if (handle == NULL || frame == NULL) { fprintf(stderr, "%s: Invalid parameter.\n", __PRETTY_FUNCTION__); return -1; } - memset((void *)buff, 0, sizeof(buff)); + memset((void *) buff, 0, sizeof(buff)); // // read data until a packet is received // remaining = 1; // start by reading 1 byte len = 0; - timeouts = 0; do { - - if ((nread = read(handle->sock, &buff[len], remaining)) == -1) - { +retry: + nread = read(handle->sock, &buff[len], remaining); + switch (nread) { + case -1: + if (errno == EINTR) + goto retry; + + if (errno == EAGAIN || errno == EWOULDBLOCK) { + mbus_error_str_set("M-Bus tcp transport layer timeout has been reached."); + return -3; + } + mbus_error_str_set("M-Bus tcp transport layer failed to read data."); return -1; + case 0: + mbus_error_str_set("M-Bus tcp transport layer connection closed by remote host."); + return -4; + default: + len += nread; } - - if (nread == 0) - { - timeouts++; - - if (timeouts >= 3) - { - // abort to avoid endless loop - fprintf(stderr, "%s: Timeout\n", __PRETTY_FUNCTION__); - break; - } - } - - len += nread; - } while ((remaining = mbus_parse(frame, buff, len)) > 0); - - if (len == 0) - { - // No data received - return -1; - } - + // // call the receive event function, if the callback function is registered - // + // if (_mbus_recv_event) _mbus_recv_event(MBUS_HANDLE_TYPE_TCP, buff, len); - - if (remaining != 0) - { + + if (remaining < 0) { mbus_error_str_set("M-Bus layer failed to parse data."); return -2; } - + return 0; } +