//
// Functions that handle communication with a Citadel Server
//
-// Copyright (c) 1987-2018 by the citadel.org team
+// Copyright (c) 1987-2022 by the citadel.org team
//
// This program is open source software. It runs great on the
// Linux operating system (and probably elsewhere). You can use,
pthread_mutex_t cpool_mutex = PTHREAD_MUTEX_INITIALIZER; // Lock it before modifying
-/*
- * Read a specific number of bytes of binary data from the Citadel server.
- * Returns the number of bytes read or -1 for error.
- */
-int ctdl_read_binary(struct ctdlsession *ctdl, char *buf, int bytes_requested)
-{
+// Read a specific number of bytes of binary data from the Citadel server.
+// Returns the number of bytes read or -1 for error.
+int ctdl_read_binary(struct ctdlsession *ctdl, char *buf, int bytes_requested) {
int bytes_read = 0;
int c = 0;
}
-/*
- * Read a newline-terminated line of text from the Citadel server.
- * Returns the string length or -1 for error.
- */
-int ctdl_readline(struct ctdlsession *ctdl, char *buf, int maxbytes)
-{
+// Read a newline-terminated line of text from the Citadel server.
+// Returns the string length or -1 for error.
+int ctdl_readline(struct ctdlsession *ctdl, char *buf, int maxbytes) {
int len = 0;
int c = 0;
--len;
}
buf[len] = 0;
- // syslog(LOG_DEBUG, "\033[33m[ %s\033[0m", buf);
+ syslog(LOG_DEBUG, "\033[32m[ %s\033[0m", buf);
return (len);
}
++len;
}
- // syslog(LOG_DEBUG, "\033[33m[ %s\033[0m", buf);
+ syslog(LOG_DEBUG, "\033[32m[ %s\033[0m", buf);
return (len);
}
-/*
- * Read lines of text from the Citadel server until a 000 terminator is received.
- * Implemented in terms of ctdl_readline() and is therefore transparent...
- * Returns a newly allocated StrBuf or NULL for error.
- */
-StrBuf *ctdl_readtextmsg(struct ctdlsession * ctdl)
-{
+// Read lines of text from the Citadel server until a 000 terminator is received.
+// Implemented in terms of ctdl_readline() and is therefore transparent...
+// Returns a newly allocated StrBuf or NULL for error.
+StrBuf *ctdl_readtextmsg(struct ctdlsession * ctdl) {
char buf[1024];
StrBuf *sj = NewStrBuf();
if (!sj) {
}
-/*
- * Write to the Citadel server. For now we're just wrapping write() in case we
- * need to add anything else later.
- */
-ssize_t ctdl_write(struct ctdlsession * ctdl, const void *buf, size_t count)
-{
+// Write to the Citadel server. For now we're just wrapping write() in case we
+// need to add anything else later.
+ssize_t ctdl_write(struct ctdlsession * ctdl, const void *buf, size_t count) {
return write(ctdl->sock, buf, count);
}
-/*
- * printf() type function to send data to the Citadel Server.
- */
-void ctdl_printf(struct ctdlsession *ctdl, const char *format, ...)
-{
+// printf() type function to send data to the Citadel Server.
+void ctdl_printf(struct ctdlsession *ctdl, const char *format, ...) {
va_list arg_ptr;
StrBuf *Buf = NewStrBuf();
}
-/*
- * Client side - connect to a unix domain socket
- */
-int uds_connectsock(char *sockpath)
-{
+// Client side - connect to a unix domain socket
+int uds_connectsock(char *sockpath) {
struct sockaddr_un addr;
int s;
}
-/*
- * TCP client - connect to a host/port
- */
-int tcp_connectsock(char *host, char *service)
-{
- struct in6_addr serveraddr;
- struct addrinfo hints;
- struct addrinfo *res = NULL;
- struct addrinfo *ai = NULL;
- int rc = (-1);
- int s = (-1);
-
- if ((host == NULL) || IsEmptyStr(host))
- return (-1);
- if ((service == NULL) || IsEmptyStr(service))
- return (-1);
-
- syslog(LOG_DEBUG, "tcp_connectsock(%s,%s)", host, service);
-
- memset(&hints, 0x00, sizeof(hints));
- hints.ai_flags = AI_NUMERICSERV;
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-
- /*
- * Handle numeric IPv4 and IPv6 addresses
- */
- rc = inet_pton(AF_INET, host, &serveraddr);
- if (rc == 1) { /* dotted quad */
- hints.ai_family = AF_INET;
- hints.ai_flags |= AI_NUMERICHOST;
- } else {
- rc = inet_pton(AF_INET6, host, &serveraddr);
- if (rc == 1) { /* IPv6 address */
- hints.ai_family = AF_INET6;
- hints.ai_flags |= AI_NUMERICHOST;
- }
- }
-
- /* Begin the connection process */
-
- rc = getaddrinfo(host, service, &hints, &res);
- if (rc != 0) {
- syslog(LOG_DEBUG, "%s: %s", host, gai_strerror(rc));
- freeaddrinfo(res);
- return (-1);
- }
-
- /*
- * Try all available addresses until we connect to one or until we run out.
- */
- for (ai = res; ai != NULL; ai = ai->ai_next) {
-
- if (ai->ai_family == AF_INET)
- syslog(LOG_DEBUG, "Trying IPv4");
- else if (ai->ai_family == AF_INET6)
- syslog(LOG_DEBUG, "Trying IPv6");
- else
- syslog(LOG_WARNING, "This is going to fail.");
-
- s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (s < 0) {
- syslog(LOG_WARNING, "socket() failed: %s", strerror(errno));
- freeaddrinfo(res);
- return (-1);
- }
- rc = connect(s, ai->ai_addr, ai->ai_addrlen);
- if (rc >= 0) {
- int fdflags;
- freeaddrinfo(res);
-
- fdflags = fcntl(rc, F_GETFL);
- if (fdflags < 0) {
- syslog(LOG_ERR, "unable to get socket %d flags! %s", rc, strerror(errno));
- close(rc);
- return -1;
- }
- fdflags = fdflags | O_NONBLOCK;
- if (fcntl(rc, F_SETFL, fdflags) < 0) {
- syslog(LOG_ERR, "unable to set socket %d nonblocking flags! %s", rc, strerror(errno));
- close(s);
- return -1;
- }
-
- return (s);
- } else {
- syslog(LOG_WARNING, "connect() failed: %s", strerror(errno));
- close(s);
- }
- }
- freeaddrinfo(res);
- return (-1);
-}
-
-
-/*
- * Extract from the headers, the username and password the client is attempting to use.
- * This could be HTTP AUTH or it could be in the cookies.
- */
-void extract_auth(struct http_transaction *h, char *authbuf, int authbuflen)
-{
+// Extract from the headers, the username and password the client is attempting to use.
+// This could be HTTP AUTH or it could be in the cookies.
+void extract_auth(struct http_transaction *h, char *authbuf, int authbuflen) {
if (authbuf == NULL)
return;
authbuf[0] = 0;
}
-/*
- * Log in to the Citadel server. Returns 0 on success or nonzero on error.
- *
- * 'auth' should be a base64-encoded "username:password" combination (like in http-auth)
- *
- * If 'resultbuf' is not NULL, it should be a buffer of at least 1024 characters,
- * and will be filled with the result from a Citadel server command.
- */
-int login_to_citadel(struct ctdlsession *c, char *auth, char *resultbuf)
-{
+// Log in to the Citadel server. Returns 0 on success or nonzero on error.
+//
+// 'auth' should be a base64-encoded "username:password" combination (like in http-auth)
+//
+// If 'resultbuf' is not NULL, it should be a buffer of at least 1024 characters,
+// and will be filled with the result from a Citadel server command.
+int login_to_citadel(struct ctdlsession *c, char *auth, char *resultbuf) {
char localbuf[1024];
char *buf;
int buflen;
if (resultbuf != NULL) {
buf = resultbuf;
- } else {
+ }
+ else {
buf = localbuf;
}
}
-/*
- * Hunt for, or create, a connection to our Citadel Server
- */
-struct ctdlsession *connect_to_citadel(struct http_transaction *h)
-{
+// Hunt for, or create, a connection to our Citadel Server
+struct ctdlsession *connect_to_citadel(struct http_transaction *h) {
struct ctdlsession *cptr = NULL;
struct ctdlsession *my_session = NULL;
int is_new_session = 0;
if (my_session->sock < 3) {
is_new_session = 1;
- } else { // make sure our Citadel session is still good
+ }
+ else { // make sure our Citadel session is still good
int test_conn;
test_conn = ctdl_write(my_session, HKEY("NOOP\n"));
if (test_conn < 5) {
close(my_session->sock);
my_session->sock = 0;
is_new_session = 1;
- } else {
+ }
+ else {
test_conn = ctdl_readline(my_session, buf, sizeof(buf));
if (test_conn < 1) {
syslog(LOG_DEBUG, "Citadel session is broken , must reconnect");
if (is_new_session) {
strcpy(my_session->room, "");
- my_session->sock = tcp_connectsock(ctdlhost, ctdlport);
+ static char *ctdl_sock_path = NULL;
+ if (!ctdl_sock_path) {
+ ctdl_sock_path = malloc(PATH_MAX);
+ snprintf(ctdl_sock_path, PATH_MAX, "%s/citadel.socket", ctdl_dir);
+ }
+ my_session->sock = uds_connectsock(ctdl_sock_path);
ctdl_readline(my_session, buf, sizeof(buf)); // skip past the server greeting banner
if (!IsEmptyStr(auth)) { // do we need to log in to Citadel?
}
-/*
- * Release our Citadel Server connection back into the pool.
- */
-void disconnect_from_citadel(struct ctdlsession *ctdl)
-{
+// Release our Citadel Server connection back into the pool.
+void disconnect_from_citadel(struct ctdlsession *ctdl) {
pthread_mutex_lock(&cpool_mutex);
ctdl->is_bound = 0;
pthread_mutex_unlock(&cpool_mutex);