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:
parent
153dc17c7b
commit
750ab452d2
1 changed files with 62 additions and 44 deletions
104
src/kiss.c
104
src/kiss.c
|
@ -24,8 +24,13 @@ struct _patty_kiss_tnc {
|
||||||
*frame;
|
*frame;
|
||||||
|
|
||||||
size_t bufsz,
|
size_t bufsz,
|
||||||
buflen,
|
offset,
|
||||||
dropped;
|
dropped;
|
||||||
|
|
||||||
|
ssize_t readlen,
|
||||||
|
left;
|
||||||
|
|
||||||
|
int eof;
|
||||||
};
|
};
|
||||||
|
|
||||||
patty_kiss_tnc *patty_kiss_tnc_open_fd(int fd) {
|
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->fd = fd;
|
||||||
tnc->bufsz = PATTY_KISS_BUFSZ;
|
tnc->bufsz = PATTY_KISS_BUFSZ;
|
||||||
tnc->buflen = 0;
|
tnc->offset = 0;
|
||||||
tnc->dropped = 0;
|
tnc->dropped = 0;
|
||||||
|
tnc->readlen = 0;
|
||||||
|
tnc->left = 0;
|
||||||
|
tnc->eof = 0;
|
||||||
|
|
||||||
return tnc;
|
return tnc;
|
||||||
|
|
||||||
|
@ -84,36 +92,11 @@ void patty_kiss_tnc_close(patty_kiss_tnc *tnc) {
|
||||||
free(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) {
|
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++;
|
tnc->dropped++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,17 +108,46 @@ ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
|
||||||
void *buf,
|
void *buf,
|
||||||
size_t len,
|
size_t len,
|
||||||
int *port) {
|
int *port) {
|
||||||
size_t i = 0,
|
size_t r = 0, /* Number of bytes read */
|
||||||
b = 0;
|
w = 0; /* Number of bytes written to buf */
|
||||||
|
|
||||||
enum kiss_flags flags = KISS_NONE;
|
enum kiss_flags flags = KISS_NONE;
|
||||||
|
|
||||||
if (tnc_buffer(tnc) < 0) {
|
if (tnc->eof) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 error_io;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i < tnc->buflen && b < len) {
|
goto done;
|
||||||
uint8_t c = ((uint8_t *)tnc->buf)[i++];
|
}
|
||||||
|
|
||||||
|
tnc->left = tnc->readlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = ((uint8_t *)tnc->buf)[tnc->offset++];
|
||||||
|
|
||||||
|
if (tnc->offset == tnc->bufsz) {
|
||||||
|
tnc->offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(flags & KISS_FRAME)) {
|
if (!(flags & KISS_FRAME)) {
|
||||||
if (c == PATTY_KISS_FEND) {
|
if (c == PATTY_KISS_FEND) {
|
||||||
|
@ -149,7 +161,7 @@ ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (c == PATTY_KISS_FEND) {
|
if (c == PATTY_KISS_FEND) {
|
||||||
if (b > 0) {
|
if (w > 0) {
|
||||||
flags &= ~KISS_FRAME;
|
flags &= ~KISS_FRAME;
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -182,12 +194,12 @@ ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc,
|
||||||
} else {
|
} else {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case PATTY_KISS_TFEND:
|
case PATTY_KISS_TFEND:
|
||||||
((uint8_t *)buf)[b++] = PATTY_KISS_FEND;
|
((uint8_t *)buf)[w++] = PATTY_KISS_FEND;
|
||||||
flags &= ~KISS_ESCAPE;
|
flags &= ~KISS_ESCAPE;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case PATTY_KISS_TFESC:
|
case PATTY_KISS_TFESC:
|
||||||
((uint8_t *)buf)[b++] = PATTY_KISS_FESC;
|
((uint8_t *)buf)[w++] = PATTY_KISS_FESC;
|
||||||
flags &= ~KISS_ESCAPE;
|
flags &= ~KISS_ESCAPE;
|
||||||
continue;
|
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:
|
done:
|
||||||
if (flags & KISS_FRAME) {
|
if (flags & KISS_FRAME) {
|
||||||
tnc_drop(tnc);
|
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:
|
error_io:
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Add table
Reference in a new issue