Refactor patty_kiss_tnc_recv()

Refactor patty_kiss_tnc_recv() to always read a fixed number of bytes
into a circular buffer

Other changes:

    * Avoid needing memmove() per packet processed

    * Allow processing packets larger than the internal read buffer
This commit is contained in:
XANTRONIX Development 2020-05-28 17:53:26 -04:00 committed by XANTRONIX Industrial
parent 153dc17c7b
commit 750ab452d2

View file

@ -24,8 +24,13 @@ struct _patty_kiss_tnc {
*frame;
size_t bufsz,
buflen,
offset,
dropped;
ssize_t readlen,
left;
int eof;
};
patty_kiss_tnc *patty_kiss_tnc_open_fd(int fd) {
@ -41,8 +46,11 @@ patty_kiss_tnc *patty_kiss_tnc_open_fd(int fd) {
tnc->fd = fd;
tnc->bufsz = PATTY_KISS_BUFSZ;
tnc->buflen = 0;
tnc->offset = 0;
tnc->dropped = 0;
tnc->readlen = 0;
tnc->left = 0;
tnc->eof = 0;
return tnc;
@ -84,36 +92,11 @@ void patty_kiss_tnc_close(patty_kiss_tnc *tnc) {
free(tnc);
}
static ssize_t tnc_buffer(patty_kiss_tnc *tnc) {
ssize_t readlen;
if (tnc->buflen == tnc->bufsz) {
goto full;
}
if ((readlen = read(tnc->fd, tnc->buf, tnc->bufsz - tnc->buflen)) < 0) {
goto error_read;
}
tnc->buflen += readlen;
return readlen;
full:
return 0;
error_read:
return -1;
}
static void tnc_flush(patty_kiss_tnc *tnc, size_t len) {
memmove(tnc->buf, ((uint8_t *)tnc->buf) + len, tnc->buflen - len);
tnc->buflen -= len;
}
static void tnc_drop(patty_kiss_tnc *tnc) {
tnc->buflen = 0;
tnc->offset = 0;
tnc->readlen = 0;
tnc->left = 0;
tnc->eof = 0;
tnc->dropped++;
}
@ -125,17 +108,46 @@ ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
void *buf,
size_t len,
int *port) {
size_t i = 0,
b = 0;
size_t r = 0, /* Number of bytes read */
w = 0; /* Number of bytes written to buf */
enum kiss_flags flags = KISS_NONE;
if (tnc_buffer(tnc) < 0) {
goto error_io;
if (tnc->eof) {
return 0;
}
while (i < tnc->buflen && b < len) {
uint8_t c = ((uint8_t *)tnc->buf)[i++];
while (1) {
uint8_t c;
r++;
if (w == len) {
tnc_drop(tnc);
flags &= ~KISS_FRAME;
w = 0;
}
if (tnc->offset == 0) {
if ((tnc->readlen = read(tnc->fd, tnc->buf, tnc->bufsz)) < 0) {
goto error_io;
} else if (tnc->readlen == 0) {
if (errno) {
goto error_io;
}
goto done;
}
tnc->left = tnc->readlen;
}
c = ((uint8_t *)tnc->buf)[tnc->offset++];
if (tnc->offset == tnc->bufsz) {
tnc->offset = 0;
}
if (!(flags & KISS_FRAME)) {
if (c == PATTY_KISS_FEND) {
@ -149,7 +161,7 @@ ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
}
} else {
if (c == PATTY_KISS_FEND) {
if (b > 0) {
if (w > 0) {
flags &= ~KISS_FRAME;
goto done;
@ -182,12 +194,12 @@ ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
} else {
switch (c) {
case PATTY_KISS_TFEND:
((uint8_t *)buf)[b++] = PATTY_KISS_FEND;
((uint8_t *)buf)[w++] = PATTY_KISS_FEND;
flags &= ~KISS_ESCAPE;
continue;
case PATTY_KISS_TFESC:
((uint8_t *)buf)[b++] = PATTY_KISS_FESC;
((uint8_t *)buf)[w++] = PATTY_KISS_FESC;
flags &= ~KISS_ESCAPE;
continue;
@ -198,17 +210,23 @@ ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
}
}
((uint8_t *)buf)[b++] = c;
((uint8_t *)buf)[w++] = c;
}
done:
if (flags & KISS_FRAME) {
tnc_drop(tnc);
} else {
tnc_flush(tnc, i);
return 0;
}
return (ssize_t)b;
tnc->left -= r;
if (tnc->readlen < tnc->bufsz && tnc->left == 0) {
tnc->eof = 1;
}
return (ssize_t)w;
error_io:
return -1;