]> code.citadel.org Git - citadel.git/blobdiff - citadel/serv_network.c
* if the message is not valid, try to free the message pointer in message_free
[citadel.git] / citadel / serv_network.c
index b7a68ef9afb5476b63c0331a382f94d236307a59..fb18445ed23c0e575454542ff0dfbfb78bd556de 100644 (file)
@@ -77,8 +77,7 @@ static int doing_queue = 0;
 /*
  * When we do network processing, it's accomplished in two passes; one to
  * gather a list of rooms and one to actually do them.  It's ok that rplist
- * is global; this process *only* runs as part of the housekeeping loop and
- * therefore only one will run at a time.
+ * is global; we have a mutex that keeps it safe.
  */
 struct RoomProcList *rplist = NULL;
 
@@ -426,12 +425,12 @@ void cmd_snet(char *argbuf) {
 void network_deliver_digest(struct SpoolControl *sc) {
        char buf[SIZ];
        int i;
-       struct CtdlMessage *msg;
+       struct CtdlMessage *msg = NULL;
        long msglen;
        long msgnum;
        char *instr = NULL;
        size_t instr_len = SIZ;
-       struct CtdlMessage *imsg;
+       struct CtdlMessage *imsg = NULL;
        struct namelist *nptr;
 
        if (sc->num_msgs_spooled < 1) {
@@ -531,7 +530,7 @@ void network_deliver_list(struct CtdlMessage *msg, struct SpoolControl *sc) {
        long msgnum;
        char *instr = NULL;
        size_t instr_len = SIZ;
-       struct CtdlMessage *imsg;
+       struct CtdlMessage *imsg = NULL;
        struct namelist *nptr;
 
        /* Don't do this if there were no recipients! */
@@ -785,8 +784,7 @@ void network_spool_msg(long msgnum, void *userdata) {
                 * after sending out on the network
                 */
                if (msg->cm_fields['S'] != NULL) {
-                       if (!strcasecmp(msg->cm_fields['S'],
-                          "CANCEL")) {
+                       if (!strcasecmp(msg->cm_fields['S'], "CANCEL")) {
                                delete_after_send = 1;
                        }
                }
@@ -835,27 +833,30 @@ void network_spool_msg(long msgnum, void *userdata) {
 
                                /* serialize it for transmission */
                                serialize_message(&sermsg, msg);
-
-                               /* write it to the spool file */
-                               snprintf(filename, sizeof filename,"%s/%s",
-                                                ctdl_netout_dir,
-                                                mptr->remote_nodename);
-                               lprintf(CTDL_DEBUG, "Appending to %s\n", filename);
-                               fp = fopen(filename, "ab");
-                               if (fp != NULL) {
-                                       fwrite(sermsg.ser,
-                                               sermsg.len, 1, fp);
-                                       fclose(fp);
-                               }
-                               else {
-                                       lprintf(CTDL_ERR, "%s: %s\n", filename, strerror(errno));
+                               if (sermsg.len > 0) {
+
+                                       /* write it to the spool file */
+                                       snprintf(filename, sizeof filename,"%s/%s",
+                                                       ctdl_netout_dir,
+                                                       mptr->remote_nodename);
+                                       lprintf(CTDL_DEBUG, "Appending to %s\n", filename);
+                                       fp = fopen(filename, "ab");
+                                       if (fp != NULL) {
+                                               fwrite(sermsg.ser,
+                                                       sermsg.len, 1, fp);
+                                               fclose(fp);
+                                       }
+                                       else {
+                                               lprintf(CTDL_ERR, "%s: %s\n", filename, strerror(errno));
+                                       }
+       
+                                       /* free the serialized version */
+                                       free(sermsg.ser);
                                }
 
-                               /* free the serialized version */
-                               free(sermsg.ser);
                        }
-                       CtdlFreeMessage(msg);
                }
+               CtdlFreeMessage(msg);
        }
 
        /* update lastsent */
@@ -863,7 +864,7 @@ void network_spool_msg(long msgnum, void *userdata) {
 
        /* Delete this message if delete-after-send is set */
        if (delete_after_send) {
-               CtdlDeleteMessages(CC->room.QRname, msgnum, "", 0);
+               CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, "");
        }
 
 }
@@ -888,6 +889,11 @@ void network_spoolout_room(char *room_to_spool) {
        int skipthisline = 0;
        int i;
 
+       /*
+        * If the room doesn't exist, don't try to perform its networking tasks.
+        * Normally this should never happen, but once in a while maybe a room gets
+        * queued for networking and then deleted before it can happen.
+        */
        if (getroom(&CC->room, room_to_spool) != 0) {
                lprintf(CTDL_CRIT, "ERROR: cannot load <%s>\n", room_to_spool);
                return;
@@ -898,6 +904,7 @@ void network_spoolout_room(char *room_to_spool) {
 
        begin_critical_section(S_NETCONFIGS);
 
+       /* Only do net processing for rooms that have netconfigs */
        fp = fopen(filename, "r");
        if (fp == NULL) {
                end_critical_section(S_NETCONFIGS);
@@ -990,7 +997,7 @@ void network_spoolout_room(char *room_to_spool) {
        }
 
        /* Do something useful */
-       CtdlForEachMessage(MSGS_GT, sc.lastsent, NULL, NULL,
+       CtdlForEachMessage(MSGS_GT, sc.lastsent, NULL, NULL, NULL,
                network_spool_msg, &sc);
 
        /* If we wrote a digest, deliver it and then close it */
@@ -1125,7 +1132,7 @@ int network_sync_to(char *target_node) {
        if (!found_node) return(-1);
 
        /* Send ALL messages */
-       num_spooled = CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL,
+       num_spooled = CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL,
                network_spool_msg, &sc);
 
        /* Concise cleanup because we know there's only one node in the sc */
@@ -1169,8 +1176,10 @@ void network_queue_room(struct ctdlroom *qrbuf, void *data) {
        if (ptr == NULL) return;
 
        safestrncpy(ptr->name, qrbuf->QRname, sizeof ptr->name);
+       begin_critical_section(S_RPLIST);
        ptr->next = rplist;
        rplist = ptr;
+       end_critical_section(S_RPLIST);
 }
 
 
@@ -1319,7 +1328,7 @@ void network_bounce(struct CtdlMessage *msg, char *reason) {
  * from the inbound queue 
  */
 void network_process_buffer(char *buffer, long size) {
-       struct CtdlMessage *msg;
+       struct CtdlMessage *msg = NULL;
        long pos;
        int field;
        struct recptypes *recp = NULL;
@@ -1947,13 +1956,31 @@ void network_do_queue(void) {
        if (full_processing) {
                lprintf(CTDL_DEBUG, "network: loading outbound queue\n");
                ForEachRoom(network_queue_room, NULL);
+       }
 
+       if (rplist != NULL) {
                lprintf(CTDL_DEBUG, "network: running outbound queue\n");
                while (rplist != NULL) {
-                       network_spoolout_room(rplist->name);
+                       char spoolroomname[ROOMNAMELEN];
+                       safestrncpy(spoolroomname, rplist->name, sizeof spoolroomname);
+                       begin_critical_section(S_RPLIST);
+
+                       /* pop this record off the list */
                        ptr = rplist;
                        rplist = rplist->next;
                        free(ptr);
+
+                       /* invalidate any duplicate entries to prevent double processing */
+                       for (ptr=rplist; ptr!=NULL; ptr=ptr->next) {
+                               if (!strcasecmp(ptr->name, spoolroomname)) {
+                                       ptr->name[0] = 0;
+                               }
+                       }
+
+                       end_critical_section(S_RPLIST);
+                       if (spoolroomname[0] != 0) {
+                               network_spoolout_room(spoolroomname);
+                       }
                }
        }