commit ccbb30dd2e6c844c9333a1bf3307e8f559717dee
parent 9d48529167584efb233efa581dcdab6b52f961a6
Author: Mario Rosell R. Martinez <mario@mariorosell.es>
Date: Wed, 18 Mar 2026 19:56:44 +0100
Add anntp_write and TSLing...
Diffstat:
| M | anntp.h | | | 181 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
1 file changed, 132 insertions(+), 49 deletions(-)
diff --git a/anntp.h b/anntp.h
@@ -5,40 +5,36 @@
#ifndef ANNTP_H
#define ANNTP_H
-#include <arpa/inet.h> /* for inet_ntoa */
-#include <netdb.h> /* for gethostbyname */
-#include <netinet/in.h> /* for struct in_addr */
-#include <stddef.h> /* for size_t */
-#include <stdio.h> /* for fprintf, perror, stderr */
-#include <stdlib.h> /* for malloc, free */
-#include <string.h> /* for memset, memcpy, strdup */
-#include <sys/socket.h> /* for socket */
-#include <unistd.h> /* for close */
-
-/*** config ***/
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
#ifdef _WIN32
-# error This project uses the Anntp library, which is not compatible with Windows, sorry :(
+# error This project uses the Anntp library, which is not compatible with Windows
#endif
#ifndef ANNTP_MALLOC
-# define ANNTP_MALLOC malloc
+# define ANNTP_MALLOC malloc
#endif
#ifndef ANNTP_FREE
-# define ANNTP_FREE free
+# define ANNTP_FREE free
#endif
#ifndef ANNTP_BUFSIZE
-# define ANNTP_BUFSIZE 0x1000
+# define ANNTP_BUFSIZE 0x1000
#endif
#ifndef ANNTP_API
-# define ANNTP_API extern
+# define ANNTP_API extern
#endif
-/*** defs ***/
-
#define Bool int
#define true 1
#define false 0
@@ -54,86 +50,173 @@ enum anntp_state {
typedef enum anntp_state AnntpState;
-typedef struct anntp_connection AnntpConnection;
-
struct anntp_connection {
- int fd; /* socket file descriptor */
- AnntpState state; /* current connection state */
- Bool use_tls; /* whether to use TLS */
- char* host; /* hostname string */
- struct hostent* host_he; /* resolved host entry from gethostbyname/gethostbyaddr */
- struct in_addr addr; /* resolved IP address */
- uchar_t read_buffer[ANNTP_BUFSIZE]; /* read buffer */
- size_t read_len; /* current length of data in buffer */
+ int fd;
+ AnntpState state;
+ Bool use_tls;
+#ifdef ANNTP_TLS
+ void* ssl;
+ void* ssl_ctx;
+#endif
+ char* host;
+ struct in_addr addr;
+ uchar_t rbuf[ANNTP_BUFSIZE];
+ size_t rbuf_elen;
};
-ANNTP_API AnntpConnection* anntp_mkconn(const char* host, char* port, Bool tls);
-ANNTP_API void anntp_freeconn(AnntpConnection* conn);
-ANNTP_API int anntp_connect(AnntpConnection* conn);
-ANNTP_API ssize_t anntp_read(AnntpConnection* conn, uchar_t* buf, size_t bufsize);
-ANNTP_API ssize_t anntp_write(AnntpConnection* conn, const uchar_t* buf, size_t bufsize);
+typedef struct anntp_connection AnntpConnection;
+
+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);
+ANNTP_API ssize_t anntp_write(AnntpConnection* conn, const uchar_t* buf, size_t bufsize);
#endif /* ANNTP_H */
#ifdef ANNTP_IMPLEMENTATION
+#ifdef ANNTP_TLS
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
+
void
anntp_init(void)
{
- /*
- * for now, there is nothing to do here...
- */
+#ifdef ANNTP_TLS
+ SSL_library_init();
+ SSL_load_error_strings();
+ OpenSSL_add_all_algorithms();
+#endif
}
AnntpConnection*
-anntp_mkconn(const char* host, char* port, Bool tls)
+anntp_mkconn(const char* host, const char* port, Bool tls)
{
- /* do some initting */
AnntpConnection* cv = (AnntpConnection*)ANNTP_MALLOC(sizeof(AnntpConnection));
if (!cv)
- return NULL; /* check errno */
+ return NULL;
memset(cv, 0, sizeof(*cv));
cv->host = strdup(host);
cv->use_tls = tls;
cv->state = ANS_OFF;
- /* first, we get a nice nonblocking two-way socket over TCP from the kernel... */
cv->fd = socket(AF_INET, SOCK_STREAM, 0);
if (cv->fd < 0) {
- perror("anntp - making connection socket");
+ perror("anntp - socket");
goto cleanup;
}
- /* now resolve the host name... */
struct addrinfo hints, *res = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
- /* look mom! i made go in c! */
int err = getaddrinfo(host, port, &hints, &res);
if (err != 0) {
- fprintf(stderr, "anntp - cant resolve host `%s': %s", host, gai_strerror(err)); /* if you find whoever made this function of *HELL*, tell him how much i hate him */
+ fprintf(stderr, "anntp - cant resolve host `%s': %s\n", host, gai_strerror(err));
close(cv->fd);
goto cleanup;
}
- if (res) {
- struct sockaddr_in* sa = (struct sockaddr_in*)res->ai_addr;
- cv->addr = sa->sin_addr;
+ struct sockaddr_in* sa = (struct sockaddr_in*)res->ai_addr;
+ cv->addr = sa->sin_addr;
+
+ if (connect(cv->fd, (struct sockaddr*)sa, sizeof(*sa)) < 0) {
+ perror("anntp - connect");
+ close(cv->fd);
+ freeaddrinfo(res);
+ goto cleanup;
}
freeaddrinfo(res);
- cv->state = ANS_CONNECTING;
+#ifdef ANNTP_TLS
+ if (tls) {
+ SSL_CTX* ctx = SSL_CTX_new(TLS_client_method());
+ if (!ctx) {
+ fprintf(stderr, "anntp - SSL_CTX_new failed\n");
+ goto cleanup;
+ }
+
+ SSL* ssl = SSL_new(ctx);
+ if (!ssl) {
+ fprintf(stderr, "anntp - SSL_new failed\n");
+ SSL_CTX_free(ctx);
+ goto cleanup;
+ }
+
+ SSL_set_fd(ssl, cv->fd);
+ if (SSL_connect(ssl) <= 0) {
+ ERR_print_errors_fp(stderr);
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ goto cleanup;
+ }
+
+ cv->ssl = ssl;
+ cv->ssl_ctx = ctx;
+ }
+#endif
+
+ cv->state = ANS_CONNECTING;
return cv;
cleanup:
- ANNTP_FREE(cv->host);
+#ifdef ANNTP_TLS
+ if (cv->ssl) SSL_free((SSL*)cv->ssl);
+ if (cv->ssl_ctx) SSL_CTX_free((SSL_CTX*)cv->ssl_ctx);
+#endif
+ if (cv->fd >= 0) close(cv->fd);
+ if (cv->host) ANNTP_FREE(cv->host);
ANNTP_FREE(cv);
return NULL;
}
+void
+anntp_freeconn(AnntpConnection* cv)
+{
+ if (!cv) return;
+
+#ifdef ANNTP_TLS
+ if (cv->ssl) SSL_shutdown((SSL*)cv->ssl);
+ if (cv->ssl) SSL_free((SSL*)cv->ssl);
+ if (cv->ssl_ctx) SSL_CTX_free((SSL_CTX*)cv->ssl_ctx);
+#endif
+
+ if (cv->fd >= 0) close(cv->fd);
+ if (cv->host) ANNTP_FREE(cv->host);
+ ANNTP_FREE(cv);
+}
+
+ssize_t
+anntp_write(AnntpConnection* conn, const uchar_t* bytes, size_t len)
+{
+ if (!conn || !bytes)
+ return -1; /* idiot-proofing */
+
+ size_t total = 0;
+
+ while (total < len) {
+ ssize_t n = 0;
+
+#ifdef ANNTP_TLS
+ if (conn->use_tls)
+ n = SSL_write((SSL*)conn->ssl, bytes + total, (int)(len - total));
+ else
+#endif
+ n = write(conn->fd, bytes + total, len - total);
+
+ if (n <= 0) {
+ /* an error happened */
+ return n;
+ }
+
+ total += n;
+ }
+}
+
#endif /* ANNTP_IMPLEMENTATION */