Go to hell and back to get valid frames off the wire, and keep track of error counts

This commit is contained in:
XANTRONIX Development 2015-07-15 21:59:08 -05:00
parent 6a427c4097
commit 9af63066b6
2 changed files with 43 additions and 20 deletions

View file

@ -31,6 +31,8 @@ patty_kiss_tnc *patty_kiss_tnc_open(const char *device, size_t bufsize);
void patty_kiss_tnc_close(patty_kiss_tnc *tnc);
int patty_kiss_tnc_errors(patty_kiss_tnc *tnc);
ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
void **frame, int *port);

View file

@ -17,6 +17,7 @@ enum kiss_flags {
struct _patty_kiss_tnc {
int fd;
int errors;
void * frame;
void * buf;
size_t bufsz;
@ -42,6 +43,7 @@ patty_kiss_tnc *patty_kiss_tnc_open(const char *device, size_t bufsz) {
goto error_open;
}
tnc->errors = 0;
tnc->bufsz = bufsz;
tnc->buflen = 0;
@ -113,7 +115,7 @@ static ssize_t tnc_decode(patty_kiss_tnc *tnc, void *frame, size_t *len, int *po
* Not all KISS TNCs will emit a type byte at the start of a frame
* to the host; if the low nybble has a value of zero, then presume
* the high nybble to be the radio port number from which the
* packet originated.
* frame originated.
*/
if (i == 1 && (c & 0x0f) == 0) {
*port = (c & 0xf0) >> 4;
@ -180,6 +182,18 @@ error_io:
return -1;
}
static void tnc_drop(patty_kiss_tnc *tnc) {
memset(tnc->buf, '\0', tnc->bufsz);
memset(tnc->frame, '\0', tnc->bufsz);
tnc->buflen = 0;
tnc->errors++;
}
int patty_kiss_tnc_errors(patty_kiss_tnc *tnc) {
return tnc->errors;
}
static void tnc_flush(patty_kiss_tnc *tnc, size_t len) {
/*
* Move everything from the buffer not processed up to this point, to the
@ -195,35 +209,42 @@ static void tnc_flush(patty_kiss_tnc *tnc, size_t len) {
}
ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc, void **frame, int *port) {
ssize_t decoded;
ssize_t buffered, decoded;
size_t framelen;
/*
* Fill the buffer with something to parse!
*/
if (tnc_buffer(tnc) < 0) {
goto error_io;
}
/*
* Initialize the frame to be returned to the caller.
*/
memset(tnc->frame, '\0', tnc->bufsz);
/*
* Try to decode the TNC buffer into the packet.
*/
if ((decoded = tnc_decode(tnc, tnc->frame, &framelen, port)) < 0) {
goto error_io;
}
do {
/*
* Fill the buffer with something to parse.
*/
if ((buffered = tnc_buffer(tnc)) < 0) {
goto error_io;
}
/*
* Try to decode the TNC buffer into the frame.
*/
if ((decoded = tnc_decode(tnc, tnc->frame, &framelen, port)) < 0) {
goto error_io;
}
/*
* If we can no longer buffer nor decode any data, then drop the whole
* frame.
*/
if (decoded == 0 && buffered == 0) {
tnc_drop(tnc);
}
} while (decoded == 0);
/*
* If we have decoded frame data, then flush the buffer up to the point of
* the next frame start, if present.
* Flush the buffer up to the point of the next frame start.
*/
if (decoded) {
tnc_flush(tnc, decoded);
}
tnc_flush(tnc, decoded);
*frame = tnc->frame;