From ec7725347e80a9635cb3ce7a19426dc415b7eb37 Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Sun, 20 Jan 2013 13:50:45 +0100 Subject: [PATCH] NETCFG: more work on details - set configured roomalias instead of room_%s@... as mailadress - remove concurency check, the houseworker is just run once. - we don't need the 'RoomsInterestedIn' hash anymore. - only process rooms for network spooling that actualy _have_ a netspool config like list/digest/participate/ignet push --- citadel/citserver.h | 2 +- citadel/include/ctdl_module.h | 1 + citadel/modules/network/netspool.h | 2 +- citadel/modules/network/serv_netmail.c | 270 ++++++++++++------------ citadel/modules/network/serv_netspool.c | 86 +++++--- citadel/modules/network/serv_network.c | 37 ++-- 6 files changed, 204 insertions(+), 194 deletions(-) diff --git a/citadel/citserver.h b/citadel/citserver.h index b4b48c716..59660496c 100644 --- a/citadel/citserver.h +++ b/citadel/citserver.h @@ -18,7 +18,7 @@ typedef struct RoomProcList RoomProcList; struct RoomProcList { struct RoomProcList *next; - const OneRoomNetCfg *OneRNCFG; + OneRoomNetCfg *OneRNCfg; char name[ROOMNAMELEN]; char lcname[ROOMNAMELEN]; long namelen; diff --git a/citadel/include/ctdl_module.h b/citadel/include/ctdl_module.h index 6b1e6c007..e4ca40083 100644 --- a/citadel/include/ctdl_module.h +++ b/citadel/include/ctdl_module.h @@ -408,6 +408,7 @@ struct RoomNetCfgLine { struct OneRoomNetCfg { long lastsent; + long changed; StrBuf *Sender; StrBuf *RoomInfo; RoomNetCfgLine *NetConfigs[maxRoomNetCfg]; diff --git a/citadel/modules/network/netspool.h b/citadel/modules/network/netspool.h index 2caecf372..0fcb1808b 100644 --- a/citadel/modules/network/netspool.h +++ b/citadel/modules/network/netspool.h @@ -30,7 +30,7 @@ typedef struct SpoolControl SpoolControl; struct SpoolControl { - RoomNetCfgLine *NetConfigs[maxRoomNetCfg]; + OneRoomNetCfg *RNCfg; FILE *digestfp; int num_msgs_spooled; long lastsent; diff --git a/citadel/modules/network/serv_netmail.c b/citadel/modules/network/serv_netmail.c index 9bc9df123..ea324a590 100644 --- a/citadel/modules/network/serv_netmail.c +++ b/citadel/modules/network/serv_netmail.c @@ -150,7 +150,7 @@ void network_deliver_digest(SpoolControl *sc) { /* * Figure out how big a buffer we need to allocate */ - for (nptr = sc->NetConfigs[digestrecp]; nptr != NULL; nptr = nptr->next) { + for (nptr = sc->RNCfg->NetConfigs[digestrecp]; nptr != NULL; nptr = nptr->next) { recps_len = recps_len + StrLength(nptr->Value[0]) + 2; } @@ -164,8 +164,8 @@ void network_deliver_digest(SpoolControl *sc) { } /* Each recipient */ - for (nptr = sc->NetConfigs[digestrecp]; nptr != NULL; nptr = nptr->next) { - if (nptr != sc->NetConfigs[digestrecp]) { + for (nptr = sc->RNCfg->NetConfigs[digestrecp]; nptr != NULL; nptr = nptr->next) { + if (nptr != sc->RNCfg->NetConfigs[digestrecp]) { StrBufAppendBufPlain(recps, HKEY(","), 0); } StrBufAppendBuf(recps, nptr->Value[0], 0); @@ -203,14 +203,14 @@ void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char char bounce_to[256]; /* Don't do this if there were no recipients! */ - if (sc->NetConfigs[listrecp] == NULL) return; + if (sc->RNCfg->NetConfigs[listrecp] == NULL) return; /* Now generate the delivery instructions */ /* * Figure out how big a buffer we need to allocate */ - for (nptr = sc->NetConfigs[listrecp]; nptr != NULL; nptr = nptr->next) { + for (nptr = sc->RNCfg->NetConfigs[listrecp]; nptr != NULL; nptr = nptr->next) { recps_len = recps_len + StrLength(nptr->Value[0]) + 2; } @@ -224,8 +224,8 @@ void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char } /* Each recipient */ - for (nptr = sc->NetConfigs[listrecp]; nptr != NULL; nptr = nptr->next) { - if (nptr != sc->NetConfigs[listrecp]) { + for (nptr = sc->RNCfg->NetConfigs[listrecp]; nptr != NULL; nptr = nptr->next) { + if (nptr != sc->RNCfg->NetConfigs[listrecp]) { StrBufAppendBufPlain(recps, HKEY(","), 0); } StrBufAppendBuf(recps, nptr->Value[0], 0); @@ -279,7 +279,7 @@ void network_spool_msg(long msgnum, /* * Process mailing list recipients */ - if (sc->NetConfigs[listrecp] != NULL) { + if (sc->RNCfg->NetConfigs[listrecp] != NULL) { /* Fetch the message. We're going to need to modify it * in order to insert the [list name] in it, etc. */ @@ -392,7 +392,7 @@ void network_spool_msg(long msgnum, /* * Process digest recipients */ - if ((sc->NetConfigs[digestrecp] != NULL) && (sc->digestfp != NULL)) { + if ((sc->RNCfg->NetConfigs[digestrecp] != NULL) && (sc->digestfp != NULL)) { msg = CtdlFetchMessage(msgnum, 1); if (msg != NULL) { fprintf(sc->digestfp, @@ -448,7 +448,7 @@ void network_spool_msg(long msgnum, /* * Process client-side list participations for this room */ - if (sc->NetConfigs[participate] != NULL) { + if (sc->RNCfg->NetConfigs[participate] != NULL) { msg = CtdlFetchMessage(msgnum, 1); if (msg != NULL) { @@ -497,7 +497,7 @@ void network_spool_msg(long msgnum, /* * Figure out how big a buffer we need to alloc */ - for (nptr = sc->NetConfigs[participate]; + for (nptr = sc->RNCfg->NetConfigs[participate]; nptr != NULL; nptr = nptr->next) { @@ -518,143 +518,145 @@ void network_spool_msg(long msgnum, } } - /* - * Process IGnet push shares - */ - msg = CtdlFetchMessage(msgnum, 1); - if (msg != NULL) { - size_t newpath_len; - - /* Prepend our node name to the Path field whenever - * sending a message to another IGnet node - */ - if (msg->cm_fields['P'] == NULL) { - msg->cm_fields['P'] = strdup("username"); - } - newpath_len = strlen(msg->cm_fields['P']) + - strlen(config.c_nodename) + 2; - newpath = malloc(newpath_len); - snprintf(newpath, newpath_len, "%s!%s", - config.c_nodename, msg->cm_fields['P']); - free(msg->cm_fields['P']); - msg->cm_fields['P'] = newpath; - + if (sc->RNCfg->NetConfigs[ignet_push_share] != NULL) + { /* - * Determine if this message is set to be deleted - * after sending out on the network + * Process IGnet push shares */ - if (msg->cm_fields['S'] != NULL) { - if (!strcasecmp(msg->cm_fields['S'], "CANCEL")) { - delete_after_send = 1; - } - } - - /* Now send it to every node */ - if (sc->NetConfigs[ignet_push_share] != NULL) - for (mptr = sc->NetConfigs[ignet_push_share]; mptr != NULL; - mptr = mptr->next) { - - send = 1; - NewStrBufDupAppendFlush(&Buf, mptr->Value[0], NULL, 1); - - /* Check for valid node name */ - if (CtdlIsValidNode(NULL, - NULL, - Buf, - sc->working_ignetcfg, - sc->the_netmap) != 0) - { - QN_syslog(LOG_ERR, - "Invalid node <%s>\n", - ChrPtr(mptr->Value[0])); + msg = CtdlFetchMessage(msgnum, 1); + if (msg != NULL) { + size_t newpath_len; - send = 0; + /* Prepend our node name to the Path field whenever + * sending a message to another IGnet node + */ + if (msg->cm_fields['P'] == NULL) { + msg->cm_fields['P'] = strdup("username"); } - - /* Check for split horizon */ - QN_syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields['P']); - bang = num_tokens(msg->cm_fields['P'], '!'); - if (bang > 1) { - for (i=0; i<(bang-1); ++i) { - extract_token(buf, - msg->cm_fields['P'], - i, '!', - sizeof buf); - - QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n", - buf, ChrPtr(mptr->Value[0])) ; - if (!strcasecmp(buf, ChrPtr(mptr->Value[0]))) { - send = 0; - break; - } + newpath_len = strlen(msg->cm_fields['P']) + + strlen(config.c_nodename) + 2; + newpath = malloc(newpath_len); + snprintf(newpath, newpath_len, "%s!%s", + config.c_nodename, msg->cm_fields['P']); + free(msg->cm_fields['P']); + msg->cm_fields['P'] = newpath; + + /* + * Determine if this message is set to be deleted + * after sending out on the network + */ + if (msg->cm_fields['S'] != NULL) { + if (!strcasecmp(msg->cm_fields['S'], "CANCEL")) { + delete_after_send = 1; } - - QN_syslog(LOG_INFO, - "%sSending to %s\n", - (send)?"":"Not ", - ChrPtr(mptr->Value[0])); } - /* Send the message */ - if (send == 1) - { - /* - * Force the message to appear in the correct - * room on the far end by setting the C field - * correctly - */ - if (msg->cm_fields['C'] != NULL) { - free(msg->cm_fields['C']); - } - if (StrLength(mptr->Value[0]) > 0) { - msg->cm_fields['C'] = - strdup(ChrPtr(mptr->Value[0])); - } - else { - msg->cm_fields['C'] = - strdup(CC->room.QRname); - } + /* Now send it to every node */ + if (sc->RNCfg->NetConfigs[ignet_push_share] != NULL) + for (mptr = sc->RNCfg->NetConfigs[ignet_push_share]; mptr != NULL; + mptr = mptr->next) { + + send = 1; + NewStrBufDupAppendFlush(&Buf, mptr->Value[0], NULL, 1); + + /* Check for valid node name */ + if (CtdlIsValidNode(NULL, + NULL, + Buf, + sc->working_ignetcfg, + sc->the_netmap) != 0) + { + QN_syslog(LOG_ERR, + "Invalid node <%s>\n", + ChrPtr(mptr->Value[0])); - /* serialize it for transmission */ - serialize_message(&sermsg, msg); - if (sermsg.len > 0) { - - /* write it to a spool file */ - snprintf(filename, - sizeof(filename), - "%s/%s@%lx%x", - ctdl_netout_dir, - ChrPtr(mptr->Value[0]), - time(NULL), - rand() - ); - - QN_syslog(LOG_DEBUG, - "Appending to %s\n", - filename); - - fp = fopen(filename, "ab"); - if (fp != NULL) { - fwrite(sermsg.ser, - sermsg.len, 1, fp); - fclose(fp); + send = 0; } - else { - QN_syslog(LOG_ERR, - "%s: %s\n", - filename, - strerror(errno)); + + /* Check for split horizon */ + QN_syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields['P']); + bang = num_tokens(msg->cm_fields['P'], '!'); + if (bang > 1) { + for (i=0; i<(bang-1); ++i) { + extract_token(buf, + msg->cm_fields['P'], + i, '!', + sizeof buf); + + QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n", + buf, ChrPtr(mptr->Value[0])) ; + if (!strcasecmp(buf, ChrPtr(mptr->Value[0]))) { + send = 0; + break; + } + } + + QN_syslog(LOG_INFO, + "%sSending to %s\n", + (send)?"":"Not ", + ChrPtr(mptr->Value[0])); } - /* free the serialized version */ - free(sermsg.ser); - } + /* Send the message */ + if (send == 1) + { + /* + * Force the message to appear in the correct + * room on the far end by setting the C field + * correctly + */ + if (msg->cm_fields['C'] != NULL) { + free(msg->cm_fields['C']); + } + if (StrLength(mptr->Value[0]) > 0) { + msg->cm_fields['C'] = + strdup(ChrPtr(mptr->Value[0])); + } + else { + msg->cm_fields['C'] = + strdup(CC->room.QRname); + } + + /* serialize it for transmission */ + serialize_message(&sermsg, msg); + if (sermsg.len > 0) { + + /* write it to a spool file */ + snprintf(filename, + sizeof(filename), + "%s/%s@%lx%x", + ctdl_netout_dir, + ChrPtr(mptr->Value[0]), + time(NULL), + rand() + ); + + QN_syslog(LOG_DEBUG, + "Appending to %s\n", + filename); + + fp = fopen(filename, "ab"); + if (fp != NULL) { + fwrite(sermsg.ser, + sermsg.len, 1, fp); + fclose(fp); + } + else { + QN_syslog(LOG_ERR, + "%s: %s\n", + filename, + strerror(errno)); + } + + /* free the serialized version */ + free(sermsg.ser); + } - } + } + } + CtdlFreeMessage(msg); } - CtdlFreeMessage(msg); } - /* update lastsent */ ///sc->lastsent = msgnum; ////// TODO diff --git a/citadel/modules/network/serv_netspool.c b/citadel/modules/network/serv_netspool.c index edf974a4d..659f8e259 100644 --- a/citadel/modules/network/serv_netspool.c +++ b/citadel/modules/network/serv_netspool.c @@ -152,66 +152,86 @@ void network_spoolout_room(RoomProcList *room_to_spool, HashList *working_ignetcfg, HashList *the_netmap) { + struct CitContext *CCC = CC; char buf[SIZ]; - char filename[PATH_MAX]; - SpoolControl *sc; + SpoolControl sc; int i; + if ((sc.RNCfg->NetConfigs[listrecp] == NULL) && + (sc.RNCfg->NetConfigs[digestrecp] == NULL) && + (sc.RNCfg->NetConfigs[participate] == NULL) && + (sc.RNCfg->NetConfigs[ignet_push_share] == NULL)) + { + /* nothing to do for this room... */ + return; + } + /* * 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 (CtdlGetRoom(&CC->room, room_to_spool->name) != 0) { + if (CtdlGetRoom(&CCC->room, room_to_spool->name) != 0) { syslog(LOG_CRIT, "ERROR: cannot load <%s>\n", room_to_spool->name); return; } - assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); - begin_critical_section(S_NETCONFIGS); - - /* Only do net processing for rooms that have netconfigs */ - if (!ReadRoomNetConfigFile(&sc, filename)) - { - end_critical_section(S_NETCONFIGS); - return; - } - syslog(LOG_INFO, "Networking started for <%s>\n", CC->room.QRname); - - sc->working_ignetcfg = working_ignetcfg; - sc->the_netmap = the_netmap; + + syslog(LOG_INFO, "Networking started for <%s>\n", CCC->room.QRname); + sc.RNCfg = room_to_spool->OneRNCfg; + sc.lastsent = room_to_spool->OneRNCfg->lastsent; + sc.working_ignetcfg = working_ignetcfg; + sc.the_netmap = the_netmap; /* If there are digest recipients, we have to build a digest */ - if (sc->NetConfigs[digestrecp] != NULL) { - sc->digestfp = tmpfile(); - fprintf(sc->digestfp, "Content-type: text/plain\n\n"); + if (sc.RNCfg->NetConfigs[digestrecp] != NULL) { + sc.digestfp = tmpfile(); + fprintf(sc.digestfp, "Content-type: text/plain\n\n"); } /* Do something useful */ - CtdlForEachMessage(MSGS_GT, sc->lastsent, NULL, NULL, NULL, - network_spool_msg, sc); + CtdlForEachMessage(MSGS_GT, sc.lastsent, NULL, NULL, NULL, + 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); + if (StrLength(sc.RNCfg->Sender) > 0) + { + long len; + len = StrLength(sc.RNCfg->Sender); + if (len + 1 > sizeof(buf)) + len = sizeof(buf) - 1; + memcpy(buf, ChrPtr(sc.RNCfg->Sender), len); + buf[len] = '\0'; + } + else + { + snprintf(buf, sizeof buf, "room_%s@%s", + CCC->room.QRname, config.c_fqdn); + } + for (i=0; buf[i]; ++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" - "To post to the list: %s\n", - CC->room.QRname, buf + if (sc.digestfp != NULL) { + fprintf(sc.digestfp, + " -----------------------------------" + "------------------------------------" + "-------\n" + "You are subscribed to the '%s' " + "list.\n" + "To post to the list: %s\n", + CCC->room.QRname, buf ); - network_deliver_digest(sc); /* deliver and close */ + network_deliver_digest(&sc); /* deliver and close */ } /* Now rewrite the config file */ - //// todo writenfree_spoolcontrol_file(&sc, filename); + if (sc.lastsent != room_to_spool->OneRNCfg->lastsent) + { + room_to_spool->OneRNCfg->lastsent = sc.lastsent; + room_to_spool->OneRNCfg->changed = 1; + } end_critical_section(S_NETCONFIGS); } diff --git a/citadel/modules/network/serv_network.c b/citadel/modules/network/serv_network.c index 6dda50363..65645d9ab 100644 --- a/citadel/modules/network/serv_network.c +++ b/citadel/modules/network/serv_network.c @@ -88,7 +88,6 @@ extern uint32_t hashlittle( const void *key, size_t length, uint32_t initval); typedef struct __roomlists { RoomProcList *rplist; - HashList *RoomsInterestedIn; }roomlists; /* * When we do network processing, it's accomplished in two passes; one to @@ -159,21 +158,22 @@ int network_usetable(struct CtdlMessage *msg) int network_sync_to(char *target_node, long len) { struct CitContext *CCC = CC; - const OneRoomNetCfg *OneRNCFG; + OneRoomNetCfg OneRNCFG; + OneRoomNetCfg *pRNCFG; const RoomNetCfgLine *pCfgLine; SpoolControl sc; int num_spooled = 0; /* Grab the configuration line we're looking for */ begin_critical_section(S_NETCONFIGS); - OneRNCFG = CtdlGetNetCfgForRoom(CCC->room.QRnumber); - if ((OneRNCFG == NULL) || - (OneRNCFG->NetConfigs[ignet_push_share] == NULL)) + pRNCFG = CtdlGetNetCfgForRoom(CCC->room.QRnumber); + if ((pRNCFG == NULL) || + (pRNCFG->NetConfigs[ignet_push_share] == NULL)) { return -1; } - pCfgLine = OneRNCFG->NetConfigs[ignet_push_share]; + pCfgLine = pRNCFG->NetConfigs[ignet_push_share]; while (pCfgLine != NULL) { if (strcmp(ChrPtr(pCfgLine->Value[0]), target_node)) @@ -185,8 +185,9 @@ int network_sync_to(char *target_node, long len) return -1; } memset(&sc, 0, sizeof(SpoolControl)); - - sc.NetConfigs[ignet_push_share] = DuplicateOneGenericCfgLine(pCfgLine); + memset(&OneRNCFG, 0, sizeof(OneRoomNetCfg)); + sc.RNCfg = &OneRNCFG; + sc.RNCfg->NetConfigs[ignet_push_share] = DuplicateOneGenericCfgLine(pCfgLine); end_critical_section(S_NETCONFIGS); @@ -198,7 +199,7 @@ int network_sync_to(char *target_node, long len) network_spool_msg, &sc); /* Concise cleanup because we know there's only one node in the sc */ - DeleteGenericCfgLine(NULL/*TODO*/, &sc.NetConfigs[ignet_push_share]); + DeleteGenericCfgLine(NULL/*TODO*/, &sc.RNCfg->NetConfigs[ignet_push_share]); DeleteHash(&sc.working_ignetcfg); DeleteHash(&sc.the_netmap); @@ -253,7 +254,7 @@ RoomProcList *CreateRoomProcListEntry(struct ctdlroom *qrbuf, const OneRoomNetCf ptr->lcname[ptr->namelen] = '\0'; ptr->key = hashlittle(ptr->lcname, ptr->namelen, 9872345); - ptr->OneRNCFG = OneRNCFG; + ptr->OneRNCfg = OneRNCFG; return ptr; } @@ -440,7 +441,6 @@ void network_bounce(struct CtdlMessage *msg, char *reason) void network_do_queue(void) { struct CitContext *CCC = CC; - static int doing_queue = 0; static time_t last_run = 0L; int full_processing = 1; HashList *working_ignetcfg; @@ -459,17 +459,6 @@ void network_do_queue(void) ); } - /* - * This is a simple concurrency check to make sure only one queue run - * is done at a time. We could do this with a mutex, but since we - * don't really require extremely fine granularity here, we'll do it - * with a static variable instead. - */ - if (doing_queue) { - return; - } - doing_queue = 1; - become_session(&networker_spool_CC); begin_critical_section(S_RPLIST); RL.rplist = rplist; @@ -506,7 +495,7 @@ void network_do_queue(void) while (ptr != NULL && !server_shutting_down) { cmp = ptr->next; - + /* filter duplicates from the list... */ while (cmp != NULL) { if ((cmp->namelen > 0) && (cmp->key == ptr->key) && @@ -557,9 +546,7 @@ void network_do_queue(void) if (full_processing) { last_run = time(NULL); } - DeleteHash(&RL.RoomsInterestedIn); destroy_network_queue_room(RL.rplist); - doing_queue = 0; } -- 2.30.2