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");
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);
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);

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);
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;

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);
if (ret == -1)
if (ret == -3)
{
printf("No reply from device\n");
return 1;

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

@ -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

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

@ -17,7 +17,6 @@
#include <stdio.h>
#include <mbus/mbus.h>
//------------------------------------------------------------------------------
// 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);
}
}

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);
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;

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;
}
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__);

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

@ -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

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

@ -21,6 +21,7 @@
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <mbus/mbus.h>
#include <mbus/mbus-tcp.h>
@ -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;
}