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:
| M | anntp.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)
{