diff --git a/include/patty/kiss.h b/include/patty/kiss.h index 9b4b7ae..0fa8bd6 100644 --- a/include/patty/kiss.h +++ b/include/patty/kiss.h @@ -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); diff --git a/src/kiss.c b/src/kiss.c index 68a1e3a..1cac0ed 100644 --- a/src/kiss.c +++ b/src/kiss.c @@ -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;