anntp

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

commit ee7621ad8828e7cf9948848f9ff93ff4f630a7f6
parent 708db91e9975228bedb5b29d86312f90eddb922d
Author: Mario Rosell R. Martinez <mario@mariorosell.es>
Date:   Sat, 28 Mar 2026 21:35:38 +0100

anntp_article: Add anntp_article_cb

Diffstat:
Manntp.h | 57++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/anntp.h b/anntp.h @@ -195,6 +195,7 @@ ANNTP_API ssize_t anntp_write(AnntpConnection* conn, const uchar_t* buf ANNTP_API int anntp_group(AnntpConnection* conn, const char* group, AnntpGroup* out_group); ANNTP_API ssize_t anntp_article(AnntpConnection*, size_t num, AnntpArticle* out_art); ANNTP_API void anntp_article_free(AnntpArticle* art); +ANNTP_API int anntp_article_cb(AnntpConnection*, size_t n, AnntpLineCb cb, void* extra); ANNTP_API ssize_t anntp_write_all(AnntpConnection* conn, const uchar_t* buf, size_t bufsize); ANNTP_API ssize_t anntp_writeline(AnntpConnection* conn, const char* buf); ANNTP_API ssize_t anntp_readline(AnntpConnection* conn, char* buf, size_t maxlen); @@ -394,7 +395,7 @@ error: return ANNTPE(ANE_IO); } -ANNTP_API void +void anntp_article_free(AnntpArticle* art) { if (!art) @@ -423,6 +424,60 @@ anntp_article_free(AnntpArticle* art) art->n = 0; } +int +anntp_article_cb(AnntpConnection* cv, size_t n, AnntpLineCb cb, void* extra) +{ + if (!cv || !cb) + return ANE_PARAMS; + + char cmd[ANNTP_BUFSIZE]; + char line[ANNTP_BUFSIZE]; + + snprintf(cmd, sizeof(cmd), "ARTICLE %zu", n); + + if (anntp_writeline(cv, cmd) <= 0) + return ANE_IO; + + ssize_t r = anntp_readline(cv, line, sizeof(line)); + if (r <= 0) + return ANE_IO; + + if (strncmp(line, "220", 3) != 0) + return ANE_PROTO; + + /* stream dot-terminated response */ + int in_headers = 1; + + for (;;) { + r = anntp_readline(cv, line, sizeof(line)); + if (r <= 0) + return ANE_IO; + + /* end of article */ + if (strcmp(line, ".\r\n") == 0) + break; + + /* dot-stuffing removal */ + char* out = line; + if (out[0] == '.' && out[1] == '.') + out++; + + /* header/body split */ + if (in_headers) { + if (out[0] == '\r' || out[0] == '\n') { + in_headers = 0; + continue; + } + } + + /* callback */ + if (cb(out, extra) != 0) + return ANE_OK; + } + + return ANE_OK; +} + void anntp_freeconn(AnntpConnection* cv) {