anntp

a nntp implementation in pure C99
Log | Files | Refs | README | LICENSE

commit d040472e70970fdbbabaee795dacb328a439b650
parent d6db399d7593abedb6569d335a7f337c32b25e42
Author: Mario Rosell R. Martinez <mario@mariorosell.es>
Date:   Thu, 19 Mar 2026 21:40:44 +0100

Buffer reads

One syscall per byte read was a lot, and more with TLS :). Now it buffers 4kb,
or whatever ANNTP_BUFSIZE is.

Diffstat:
D.anntp.h.swo | 0
Manntp.h | 51+++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/.anntp.h.swo b/.anntp.h.swo Binary files differ. diff --git a/anntp.h b/anntp.h @@ -68,6 +68,7 @@ struct anntp_connection { struct hostent* host_he; /* resolved host entry */ struct in_addr addr; /* resolved IP address */ uchar_t read_buffer[ANNTP_BUFSIZE]; /* read buffer */ + size_t read_pos; /* used for buffering */ size_t read_len; /* length of data in buffer */ #ifdef ANNTP_TLS SSL* ssl; /* TLS session */ @@ -80,7 +81,7 @@ typedef int (*AnntpLineCb)(const char* line, void* extra); /*** function declarations ***/ -ANNTP_API void anntp_init(void); +ANNTP_API void anntp_init(void); ANNTP_API AnntpConnection* anntp_mkconn(const char* host, const char* port, Bool tls); ANNTP_API void anntp_freeconn(AnntpConnection* conn); ANNTP_API ssize_t anntp_read(AnntpConnection* conn, uchar_t* buf, size_t bufsize); @@ -96,6 +97,8 @@ ANNTP_API int anntp_auth(AnntpConnection* conn, const char* login, c #ifdef ANNTP_IMPLEMENTATION +static ssize_t _afillbuf(AnntpConnection* c); + void anntp_init(void) { @@ -117,6 +120,7 @@ anntp_mkconn(const char* host, const char* port, Bool tls) cv->host = strdup(host); cv->use_tls = tls; cv->state = ANS_OFF; + cv->fd = -1; /* create socket */ cv->fd = socket(AF_INET, SOCK_STREAM, 0); @@ -244,16 +248,22 @@ anntp_readline(AnntpConnection* cv, char* buf, size_t maxlen) if (!cv || !buf || maxlen == 0) return -1; size_t pos = 0; + while (pos < maxlen - 1) { - uchar_t c; - ssize_t n = anntp_read(cv, &c, 1); - if (n <= 0) { - if (pos == 0) return n; - break; + /* refill buffer if empty */ + if (cv->read_pos >= cv->read_len) { + ssize_t n = _afillbuf(cv); + if (n <= 0) { + if (pos == 0) return n; + break; + } } - buf[pos++] = c; - if (c == '\n') break; + char ch = (char)cv->read_buffer[cv->read_pos++]; + buf[pos++] = ch; + + if (ch == '\n') + break; } buf[pos] = '\0'; @@ -336,6 +346,8 @@ anntp_readdot_cb(AnntpConnection* cv, AnntpLineCb cb, void* extra) if (cb(out, extra) != 0) return 1; /* user aborted */ } + + return 0; } /* NOTE: I have a gut feeling this auth mechanism is probably a bit insecure... */ @@ -402,5 +414,28 @@ anntp_auth(AnntpConnection* cv, const char* user, const char* pass) return -1; } +/* fill read buffer with data */ +static ssize_t +_afillbuf(AnntpConnection* c) +{ + ssize_t n; + +#ifdef ANNTP_TLS + if (c->use_tls && c->ssl) + n = SSL_read(c->ssl, c->read_buffer, ANNTP_BUFSIZE); + else +#endif + n = read(c->fd, c->read_buffer, ANNTP_BUFSIZE); + + if (n > 0) { + c->read_len = (size_t)n; + c->read_pos = 0; + } else { + c->read_len = 0; + } + + return n; +} + #endif /* ANNTP_IMPLEMENTATION */