Extended mbus_recv_frame() error codes, improved collision handling

- handling TCP connection reset and read(2) timeout
This commit is contained in:
jakubovsky
2012-07-03 14:35:07 +02:00
parent 82aec2ff97
commit 5d079254cc
10 changed files with 78 additions and 82 deletions

2
bin/mbus-serial-request-data.c Normal file → Executable file
View File

@ -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"); fprintf(stderr, "Failed to receive M-Bus response frame.\n");
return 1; return 1;

13
bin/mbus-serial-scan.c Normal file → Executable file
View File

@ -97,7 +97,7 @@ main(int argc, char **argv)
ret = mbus_recv_frame(handle, &reply); ret = mbus_recv_frame(handle, &reply);
if (ret == -1) if (ret == -3)
{ {
continue; continue;
} }
@ -108,22 +108,15 @@ main(int argc, char **argv)
if (ret == -2) if (ret == -2)
{ {
/* check for more data (collision) */ /* check for more data (collision) */
while (mbus_recv_frame(handle, &reply) != -1); mbus_recv_frame_dummy(handle);
printf("Collision at address %d\n", address); printf("Collision at address %d\n", address);
continue; continue;
} }
if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK) if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK)
{ {
/* check for more data (collision) */ /* check for more data (collision) */
while (mbus_recv_frame(handle, &reply) != -1) if (mbus_recv_frame_dummy(handle))
{
ret = -2;
}
if (ret == -2)
{ {
printf("Collision at address %d\n", address); printf("Collision at address %d\n", address);

4
bin/mbus-serial-select-secondary.c Normal file → Executable file
View File

@ -73,7 +73,7 @@ main(int argc, char **argv)
ret = mbus_recv_frame(handle, &reply); 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()); printf("No reply from device with secondary address %s: %s\n", argv[2], mbus_error_str());
return 1; return 1;
@ -93,7 +93,7 @@ main(int argc, char **argv)
return 1; 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()); printf("Failed to recieve reply from selected secondary device: %s\n", mbus_error_str());
return 1; return 1;

2
bin/mbus-serial-switch-baudrate.c Normal file → Executable file
View File

@ -72,7 +72,7 @@ main(int argc, char **argv)
ret = mbus_recv_frame(handle, &reply); ret = mbus_recv_frame(handle, &reply);
if (ret == -1) if (ret == -3)
{ {
printf("No reply from device\n"); printf("No reply from device\n");
return 1; return 1;

4
bin/mbus-tcp-request-data.c Normal file → Executable file
View File

@ -111,9 +111,9 @@ 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; return 1;
} }

15
bin/mbus-tcp-scan.c Normal file → Executable file
View File

@ -17,7 +17,6 @@
#include <stdio.h> #include <stdio.h>
#include <mbus/mbus.h> #include <mbus/mbus.h>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Execution starts here: // Execution starts here:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -81,7 +80,7 @@ main(int argc, char **argv)
ret = mbus_recv_frame(handle, &reply); ret = mbus_recv_frame(handle, &reply);
if (ret == -1) if (ret == -3)
{ {
continue; continue;
} }
@ -92,25 +91,17 @@ main(int argc, char **argv)
if (ret == -2) if (ret == -2)
{ {
/* check for more data (collision) */ /* check for more data (collision) */
while (mbus_recv_frame(handle, &reply) != -1); mbus_recv_frame_dummy(handle);
printf("Collision at address %d\n", address); printf("Collision at address %d\n", address);
continue; continue;
} }
if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK) if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK)
{ {
/* check for more data (collision) */ /* check for more data (collision) */
while (mbus_recv_frame(handle, &reply) != -1) if (mbus_recv_frame_dummy(handle))
{
ret = -2;
}
if (ret == -2)
{ {
printf("Collision at address %d\n", address); printf("Collision at address %d\n", address);
continue; continue;
} }

4
bin/mbus-tcp-select-secondary.c Normal file → Executable file
View File

@ -59,7 +59,7 @@ main(int argc, char **argv)
ret = mbus_recv_frame(handle, &reply); 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()); printf("No reply from device with secondary address %s: %s\n", argv[3], mbus_error_str());
return 1; return 1;
@ -79,7 +79,7 @@ main(int argc, char **argv)
return 1; 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()); printf("Failed to recieve reply from selected secondary device: %s\n", mbus_error_str());
return 1; return 1;

36
mbus/mbus-protocol-aux.c Normal file → Executable file
View File

@ -1407,6 +1407,24 @@ mbus_recv_frame(mbus_handle * handle, mbus_frame *frame)
return result; 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 int
mbus_send_frame(mbus_handle * handle, mbus_frame *frame) 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) if (debug)
printf("%s: debug: receiving response frame #%d\n", __PRETTY_FUNCTION__, frame_count); 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__); MBUS_ERROR("%s: Failed to receive M-Bus response frame.\n", __PRETTY_FUNCTION__);
retval = 1; retval = 1;
@ -1743,7 +1761,7 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask)
ret = mbus_recv_frame(handle, &reply); ret = mbus_recv_frame(handle, &reply);
if (ret == -1) if (ret == -3)
{ {
return MBUS_PROBE_NOTHING; return MBUS_PROBE_NOTHING;
} }
@ -1751,20 +1769,14 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask)
if (ret == -2) if (ret == -2)
{ {
/* check for more data (collision) */ /* check for more data (collision) */
while (mbus_recv_frame(handle, &reply) != -1); mbus_recv_frame_dummy(handle);
return MBUS_PROBE_COLLISION; return MBUS_PROBE_COLLISION;
} }
if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK) if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK)
{ {
/* check for more data (collision) */ /* check for more data (collision) */
while (mbus_recv_frame(handle, &reply) != -1) if (mbus_recv_frame_dummy(handle))
{
ret = -2;
}
if (ret == -2)
{ {
return MBUS_PROBE_COLLISION; 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); ret = mbus_recv_frame(handle, &reply);
if (ret == -1) if (ret == -3)
{ {
return MBUS_PROBE_NOTHING; 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", MBUS_ERROR("%s: Failed to receive M-Bus response frame.\n",
__PRETTY_FUNCTION__); __PRETTY_FUNCTION__);

9
mbus/mbus-protocol-aux.h Normal file → Executable file
View File

@ -178,6 +178,15 @@ int mbus_disconnect(mbus_handle * handle);
*/ */
int mbus_recv_frame(mbus_handle * handle, mbus_frame *frame); 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 * Sends frame using "unified" handle
* *

55
mbus/mbus-tcp.c Normal file → Executable file
View File

@ -21,6 +21,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <errno.h>
#include <mbus/mbus.h> #include <mbus/mbus.h>
#include <mbus/mbus-tcp.h> #include <mbus/mbus-tcp.h>
@ -161,65 +162,54 @@ mbus_tcp_send_frame(mbus_tcp_handle *handle, mbus_frame *frame)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// //
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int int mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame)
mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame)
{ {
char buff[PACKET_BUFF_SIZE]; char buff[PACKET_BUFF_SIZE];
int len, remaining, nread, timeouts; int len, remaining, nread;
if (handle == NULL || frame == NULL) if (handle == NULL || frame == NULL) {
{
fprintf(stderr, "%s: Invalid parameter.\n", __PRETTY_FUNCTION__); fprintf(stderr, "%s: Invalid parameter.\n", __PRETTY_FUNCTION__);
return -1; return -1;
} }
memset((void *)buff, 0, sizeof(buff)); memset((void *) buff, 0, sizeof(buff));
// //
// read data until a packet is received // read data until a packet is received
// //
remaining = 1; // start by reading 1 byte remaining = 1; // start by reading 1 byte
len = 0; len = 0;
timeouts = 0;
do { do {
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;
}
if ((nread = read(handle->sock, &buff[len], remaining)) == -1)
{
mbus_error_str_set("M-Bus tcp transport layer failed to read data."); mbus_error_str_set("M-Bus tcp transport layer failed to read data.");
return -1; 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); } 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 // call the receive event function, if the callback function is registered
// //
if (_mbus_recv_event) if (_mbus_recv_event)
_mbus_recv_event(MBUS_HANDLE_TYPE_TCP, buff, len); _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."); mbus_error_str_set("M-Bus layer failed to parse data.");
return -2; return -2;
} }
@ -227,3 +217,4 @@ mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame)
return 0; return 0;
} }