]> code.citadel.org Git - citadel.git/blobdiff - citadel/serv_network.c
* Killed off CtdlGetDynamicSymbol() and just put all the symbols in server.h
[citadel.git] / citadel / serv_network.c
index f40c79829a140c2d305bfcf2e7cfa9f2855bbe97..3088de2debfa478e8d89535cecee6fbe18c50753 100644 (file)
@@ -7,12 +7,20 @@
  * Copyright (C) 2000-2002 by Art Cancro and others.
  * This code is released under the terms of the GNU General Public License.
  *
+ * ** NOTE **   A word on the S_NETCONFIGS semaphore:
+ * This is a fairly high-level type of critical section.  It ensures that no
+ * two threads work on the netconfigs files at the same time.  Since we do
+ * so many things inside these, here are the rules:
+ *  1. begin_critical_section(S_NETCONFIGS) *before* begin_ any others.
+ *  2. Do *not* perform any I/O with the client during these sections.
+ *
  */
 
 /*
- * FIXME
- * Don't allow polls during network processing
+ * Duration of time (in seconds) after which pending list subscribe/unsubscribe
+ * requests that have not been confirmed will be deleted.
  */
+#define EXP    259200  /* three days */
 
 #include "sysdep.h"
 #include <stdlib.h>
@@ -45,7 +53,7 @@
 #include "citserver.h"
 #include "support.h"
 #include "config.h"
-#include "dynloader.h"
+#include "serv_extensions.h"
 #include "room_ops.h"
 #include "user_ops.h"
 #include "policy.h"
@@ -61,6 +69,8 @@
 #include "snprintf.h"
 #endif
 
+/* Nonzero while we are doing outbound network processing */
+static int doing_queue = 0;
 
 /*
  * When we do network processing, it's accomplished in two passes; one to
@@ -324,10 +334,10 @@ void cmd_gnet(char *argbuf) {
        FILE *fp;
 
        if (CtdlAccessCheck(ac_room_aide)) return;
-       assoc_file_name(filename, sizeof filename, &CC->quickroom, "netconfigs");
+       assoc_file_name(filename, sizeof filename, &CC->room, "netconfigs");
        cprintf("%d Network settings for room #%ld <%s>\n",
                LISTING_FOLLOWS,
-               CC->quickroom.QRnumber, CC->quickroom.QRname);
+               CC->room.QRnumber, CC->room.QRname);
 
        fp = fopen(filename, "r");
        if (fp != NULL) {
@@ -350,7 +360,7 @@ void cmd_snet(char *argbuf) {
 
        if (CtdlAccessCheck(ac_room_aide)) return;
        safestrncpy(tempfilename, tmpnam(NULL), sizeof tempfilename);
-       assoc_file_name(filename, sizeof filename, &CC->quickroom, "netconfigs");
+       assoc_file_name(filename, sizeof filename, &CC->room, "netconfigs");
 
        fp = fopen(tempfilename, "w");
        if (fp == NULL) {
@@ -372,7 +382,9 @@ void cmd_snet(char *argbuf) {
         */
        unlink(filename);
        snprintf(buf, sizeof buf, "/bin/mv %s %s", tempfilename, filename);
+       begin_critical_section(S_NETCONFIGS);
        system(buf);
+       end_critical_section(S_NETCONFIGS);
 }
 
 
@@ -496,7 +508,7 @@ void network_spool_msg(long msgnum, void *userdata) {
                        if (msg->cm_fields['C'] != NULL) {
                                phree(msg->cm_fields['C']);
                        }
-                       msg->cm_fields['C'] = strdoop(CC->quickroom.QRname);
+                       msg->cm_fields['C'] = strdoop(CC->room.QRname);
 
                        /*
                         * Determine if this message is set to be deleted
@@ -561,7 +573,7 @@ void network_spool_msg(long msgnum, void *userdata) {
 
        /* Delete this message if delete-after-send is set */
        if (delete_after_send) {
-               CtdlDeleteMessages(CC->quickroom.QRname, msgnum, "");
+               CtdlDeleteMessages(CC->room.QRname, msgnum, "");
        }
 
 }
@@ -595,9 +607,9 @@ void network_deliver_digest(struct SpoolControl *sc) {
 
        sprintf(buf, "%ld", time(NULL));
        msg->cm_fields['T'] = strdoop(buf);
-       msg->cm_fields['A'] = strdoop(CC->quickroom.QRname);
-       msg->cm_fields['U'] = strdoop(CC->quickroom.QRname);
-       sprintf(buf, "room_%s@%s", CC->quickroom.QRname, config.c_fqdn);
+       msg->cm_fields['A'] = strdoop(CC->room.QRname);
+       msg->cm_fields['U'] = strdoop(CC->room.QRname);
+       sprintf(buf, "room_%s@%s", CC->room.QRname, config.c_fqdn);
        for (i=0; i<strlen(buf); ++i) {
                if (isspace(buf[i])) buf[i]='_';
                buf[i] = tolower(buf[i]);
@@ -676,25 +688,29 @@ void network_spoolout_room(char *room_to_spool) {
        FILE *fp;
        struct SpoolControl sc;
        struct namelist *nptr;
+       size_t miscsize = 0;
+       size_t linesize = 0;
+       int skipthisline = 0;
+       int i;
 
-       lprintf(7, "Spooling <%s>\n", room_to_spool);
-       if (getroom(&CC->quickroom, room_to_spool) != 0) {
+       if (getroom(&CC->room, room_to_spool) != 0) {
                lprintf(1, "ERROR: cannot load <%s>\n", room_to_spool);
                return;
        }
 
        memset(&sc, 0, sizeof(struct SpoolControl));
-       assoc_file_name(filename, sizeof filename, &CC->quickroom, "netconfigs");
+       assoc_file_name(filename, sizeof filename, &CC->room, "netconfigs");
+
+       begin_critical_section(S_NETCONFIGS);
+       end_critical_section(S_NETCONFIGS);
 
        fp = fopen(filename, "r");
        if (fp == NULL) {
-               lprintf(7, "Outbound batch processing skipped for <%s>\n",
-                       CC->quickroom.QRname);
+               end_critical_section(S_NETCONFIGS);
                return;
        }
 
-       lprintf(5, "Outbound batch processing started for <%s>\n",
-               CC->quickroom.QRname);
+       lprintf(5, "Networking started for <%s>\n", CC->room.QRname);
 
        while (fgets(buf, sizeof buf, fp) != NULL) {
                buf[strlen(buf)-1] = 0;
@@ -724,6 +740,31 @@ void network_spoolout_room(char *room_to_spool) {
                        extract(nptr->name, buf, 1);
                        sc.ignet_push_shares = nptr;
                }
+               else {
+                       /* Preserve 'other' lines ... *unless* they happen to
+                        * be subscribe/unsubscribe pendings with expired
+                        * timestamps.
+                        */
+                       skipthisline = 0;
+                       if (!strncasecmp(buf, "subpending|", 11)) {
+                               if (time(NULL) - extract_long(buf, 4) > EXP) {
+                                       skipthisline = 1;
+                               }
+                       }
+                       if (!strncasecmp(buf, "unsubpending|", 13)) {
+                               if (time(NULL) - extract_long(buf, 3) > EXP) {
+                                       skipthisline = 1;
+                               }
+                       }
+
+                       if (skipthisline == 0) {
+                               linesize = strlen(buf);
+                               sc.misc = realloc(sc.misc,
+                                       (miscsize + linesize + 2) );
+                               sprintf(&sc.misc[miscsize], "%s\n", buf);
+                               miscsize = miscsize + linesize + 1;
+                       }
+               }
 
 
        }
@@ -740,13 +781,20 @@ void network_spoolout_room(char *room_to_spool) {
                network_spool_msg, &sc);
 
        /* If we wrote a digest, deliver it and then close it */
+       snprintf(buf, sizeof buf, "room_%s@%s",
+               CC->room.QRname, config.c_fqdn);
+       for (i=0; i<strlen(buf); ++i) {
+               buf[i] = tolower(buf[i]);
+               if (isspace(buf[i])) buf[i] = '_';
+       }
        if (sc.digestfp != NULL) {
                fprintf(sc.digestfp,    " -----------------------------------"
                                        "------------------------------------"
                                        "-------\n"
                                        "You are subscribed to the '%s' "
-                                       "list.\n",
-                                       CC->quickroom.QRname
+                                       "list.\n"
+                                       "To post to the list: %s\n",
+                                       CC->room.QRname, buf
                );
                network_deliver_digest(&sc);    /* deliver and close */
        }
@@ -783,19 +831,21 @@ void network_spoolout_room(char *room_to_spool) {
                        phree(sc.ignet_push_shares);
                        sc.ignet_push_shares = nptr;
                }
+               if (sc.misc != NULL) {
+                       fwrite(sc.misc, strlen(sc.misc), 1, fp);
+               }
+               phree(sc.misc);
 
                fclose(fp);
        }
-
-       lprintf(5, "Outbound batch processing finished for <%s>\n",
-               CC->quickroom.QRname);
+       end_critical_section(S_NETCONFIGS);
 }
 
 
 /*
  * Batch up and send all outbound traffic from the current room
  */
-void network_queue_room(struct quickroom *qrbuf, void *data) {
+void network_queue_room(struct ctdlroom *qrbuf, void *data) {
        struct RoomProcList *ptr;
 
        ptr = (struct RoomProcList *) mallok(sizeof (struct RoomProcList));
@@ -1411,7 +1461,6 @@ void network_poll_other_citadel_nodes(void) {
  * Run through the rooms doing various types of network stuff.
  */
 void network_do_queue(void) {
-       static int doing_queue = 0;
        static time_t last_run = 0L;
        struct RoomProcList *ptr;
 
@@ -1482,6 +1531,11 @@ void cmd_netp(char *cmdbuf)
        char secret[SIZ];
        char nexthop[SIZ];
 
+       if (doing_queue) {
+               cprintf("%d spooling - try again in a few minutes\n", ERROR);
+               return;
+       }
+
        extract(node, cmdbuf, 0);
        extract(pass, cmdbuf, 1);
 
@@ -1513,7 +1567,7 @@ void cmd_netp(char *cmdbuf)
 /*
  * Module entry point
  */
-char *Dynamic_Module_Init(void)
+char *serv_network_init(void)
 {
        CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
        CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");