From ff25103f77ff7e077014c4cf3ee7ff27ff85d761 Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Wed, 9 Jan 2013 23:08:09 +0100 Subject: [PATCH] NETCFG: make basic parsing - add hook to module init; make shure its run last, so everyone registered his config parsers - make rss hooks at the right time - implement generic parser that works for most of the configs by simply splitting the lines --- citadel/include/ctdl_module.h | 8 +- citadel/modules/network/serv_netspool.c | 79 ++++----- citadel/modules/pop3client/serv_pop3client.c | 2 +- citadel/modules/rssclient/serv_rssclient.c | 9 +- citadel/netconfig.c | 173 +++++++++++++++++-- citadel/scripts/mk_module_init.sh | 6 + 6 files changed, 204 insertions(+), 73 deletions(-) diff --git a/citadel/include/ctdl_module.h b/citadel/include/ctdl_module.h index 7dad38745..25a00fa70 100644 --- a/citadel/include/ctdl_module.h +++ b/citadel/include/ctdl_module.h @@ -393,11 +393,13 @@ struct CfgLineType { CfgLineDeAllocator DeAllocator; ConstStr Str; int IsSingleLine; + int nSegments; }; struct RoomNetCfgLine { RoomNetCfgLine *next; - StrBuf *Value; + int nValues; + StrBuf **Value; }; struct OneRoomNetCfg { @@ -409,8 +411,8 @@ struct OneRoomNetCfg { }; -#define CtdlREGISTERRoomCfgType(a, p, uniq, s, d) RegisterRoomCfgType(#a, sizeof(#a) - 1, a, p, uniq, s, d); -void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLineParser p, int uniq, CfgLineSerializer s, CfgLineDeAllocator d); +#define CtdlREGISTERRoomCfgType(a, p, uniq, nSegs, s, d) RegisterRoomCfgType(#a, sizeof(#a) - 1, a, p, uniq, nSegs, s, d); +void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLineParser p, int uniq, int nSegments, CfgLineSerializer s, CfgLineDeAllocator d); void ParseGeneric(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *sc); void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *sc, RoomNetCfgLine *data); void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data); diff --git a/citadel/modules/network/serv_netspool.c b/citadel/modules/network/serv_netspool.c index 1da98f807..f2ad74dde 100644 --- a/citadel/modules/network/serv_netspool.c +++ b/citadel/modules/network/serv_netspool.c @@ -94,21 +94,14 @@ #endif -void ParseLastSent(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *rncfg) +void ParseLastSent(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG) { - rncfg->lastsent = extract_long(LinePos, 0); -} -void ParseIgnetPushShare(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *rncfg) -{ -/* - extract_token(nodename, LinePos, 0, '|', sizeof nodename); - extract_token(roomname, LinePos, 1, '|', sizeof roomname); - mptr = (maplist *) malloc(sizeof(maplist)); - mptr->next = rncfg->RNCfg->ignet_push_shares; - strcpy(mptr->remote_nodename, nodename); - strcpy(mptr->remote_roomname, roomname); - rncfg->RNCfg->ignet_push_shares = mptr; -*/ + RoomNetCfgLine *nptr; + nptr = (RoomNetCfgLine *) + malloc(sizeof(RoomNetCfgLine)); + + OneRNCFG->lastsent = extract_long(LinePos, 0); + OneRNCFG->NetConfigs[ThisOne->C] = nptr; } void ParseRoomAlias(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *rncfg) @@ -121,24 +114,19 @@ void ParseRoomAlias(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePo */ } -void ParseSubPendingLine(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *rncfg) +void ParseSubPendingLine(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG) { + if (time(NULL) - extract_long(LinePos, 3) > EXP) + return; /* expired subscription... */ - if (time(NULL) - extract_long(LinePos, 3) > EXP) { - // skipthisline = 1; - } - else - { - } - + ParseGeneric(ThisOne, Line, LinePos, OneRNCFG); } -void ParseUnSubPendingLine(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *rncfg) +void ParseUnSubPendingLine(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG) { - ///int skipthisline = 0; - if (time(NULL) - extract_long(LinePos, 2) > EXP) { - // skipthisline = 1; - } + if (time(NULL) - extract_long(LinePos, 2) > EXP) + return; /* expired subscription... */ + ParseGeneric(ThisOne, Line, LinePos, OneRNCFG); } @@ -148,24 +136,15 @@ void SerializeLastSent(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoom StrBufAppendPrintf(OutputBuffer, "|%ld\n", RNCfg->lastsent); } -void SerializeIgnetPushShare(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *RNCfg, RoomNetCfgLine *data) +void DeleteLastSent(const CfgLineType *ThisOne, RoomNetCfgLine **data) { - StrBufAppendBufPlain(OutputBuffer, CKEY(ThisOne->Str), 0); -/* - StrBufAppendPrintf(Cfg, "ignet_push_share|%s", RNCfg->ignet_push_shares->remote_nodename); - if (!IsEmptyStr(RNCfg->ignet_push_shares->remote_roomname)) { - StrBufAppendPrintf(Cfg, "|%s", RNCfg->ignet_push_shares->remote_roomname); - } - StrBufAppendPrintf(Cfg, "\n"); - mptr = RNCfg->ignet_push_shares->next; - free(RNCfg->ignet_push_shares); - RNCfg->ignet_push_shares = mptr; -*/ - StrBufAppendBuf(OutputBuffer, data->Value, 0); - StrBufAppendBufPlain(OutputBuffer, HKEY("\n"), 0); + free(*data); + *data = NULL; } + + /* * Batch up and send all outbound traffic from the current room */ @@ -192,7 +171,7 @@ void network_spoolout_room(RoomProcList *room_to_spool, begin_critical_section(S_NETCONFIGS); /* Only do net processing for rooms that have netconfigs */ - if (!read_spoolcontrol_file(&sc, filename)) + if (!ReadRoomNetConfigFile(&sc, filename)) { end_critical_section(S_NETCONFIGS); return; @@ -895,14 +874,14 @@ CTDL_MODULE_INIT(network_spool) { if (!threading) { -// CtdlREGISTERRoomCfgType(subpending, ParseSubPendingLine, 0, SerializeSubPendingLine, DeleteSubPendingLine); /// todo: move this to mailinglist manager -// CtdlREGISTERRoomCfgType(unsubpending, ParseUnSubPendingLine0, SerializeUnSubPendingLine, DeleteUnSubPendingLine); /// todo: move this to mailinglist manager -// CtdlREGISTERRoomCfgType(lastsent, ParseLastSent, 1, SerializeLastSent, DeleteLastSent); -/// CtdlREGISTERRoomCfgType(ignet_push_share, ParseIgnetPushShare, 0, SerializeIgnetPushShare, DeleteIgnetPushShare); // todo: move this to the ignet client - CtdlREGISTERRoomCfgType(listrecp, ParseGeneric, 0, SerializeGeneric, DeleteGenericCfgLine); - CtdlREGISTERRoomCfgType(digestrecp, ParseGeneric, 0, SerializeGeneric, DeleteGenericCfgLine); - CtdlREGISTERRoomCfgType(participate, ParseGeneric, 0, SerializeGeneric, DeleteGenericCfgLine); - CtdlREGISTERRoomCfgType(roommailalias, ParseRoomAlias, 0, SerializeGeneric, DeleteGenericCfgLine); + CtdlREGISTERRoomCfgType(subpending, ParseSubPendingLine, 0, 5, SerializeGeneric, DeleteGenericCfgLine); /// todo: move this to mailinglist manager + CtdlREGISTERRoomCfgType(unsubpending, ParseUnSubPendingLine, 0, 4, SerializeGeneric, DeleteGenericCfgLine); /// todo: move this to mailinglist manager + CtdlREGISTERRoomCfgType(lastsent, ParseLastSent, 1, 1, SerializeLastSent, DeleteLastSent); + CtdlREGISTERRoomCfgType(ignet_push_share, ParseGeneric, 0, 2, SerializeGeneric, DeleteGenericCfgLine); // [remotenode|remoteroomname (optional)]// todo: move this to the ignet client + CtdlREGISTERRoomCfgType(listrecp, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine); + CtdlREGISTERRoomCfgType(digestrecp, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine); + CtdlREGISTERRoomCfgType(participate, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine); + CtdlREGISTERRoomCfgType(roommailalias, ParseRoomAlias, 0, 1, SerializeGeneric, DeleteGenericCfgLine); create_spool_dirs(); //////todo CtdlRegisterCleanupHook(destroy_network_queue_room); diff --git a/citadel/modules/pop3client/serv_pop3client.c b/citadel/modules/pop3client/serv_pop3client.c index 0672919bf..63451ed05 100644 --- a/citadel/modules/pop3client/serv_pop3client.c +++ b/citadel/modules/pop3client/serv_pop3client.c @@ -1263,7 +1263,7 @@ CTDL_MODULE_INIT(pop3client) if (!threading) { CtdlFillSystemContext(&pop3_client_CC, "POP3aggr"); - CtdlREGISTERRoomCfgType(pop3client, ParseGeneric, 0, SerializeGeneric, DeleteGenericCfgLine);/// todo: implement pop3 specific parser + CtdlREGISTERRoomCfgType(pop3client, ParseGeneric, 0, 3, SerializeGeneric, DeleteGenericCfgLine); pthread_mutex_init(&POP3QueueMutex, NULL); POP3QueueRooms = NewHash(1, lFlathash); POP3FetchUrls = NewHash(1, NULL); diff --git a/citadel/modules/rssclient/serv_rssclient.c b/citadel/modules/rssclient/serv_rssclient.c index 0c8265060..29c3efea2 100644 --- a/citadel/modules/rssclient/serv_rssclient.c +++ b/citadel/modules/rssclient/serv_rssclient.c @@ -797,10 +797,9 @@ void LogDebugEnableRSSClient(const int n) CTDL_MODULE_INIT(rssclient) { - if (threading) + if (!threading) { - CtdlREGISTERRoomCfgType(rssclient, ParseGeneric, 0, SerializeGeneric, DeleteGenericCfgLine); /// todo: implement rss specific parser - CtdlFillSystemContext(&rss_CC, "rssclient"); + CtdlREGISTERRoomCfgType(rssclient, ParseGeneric, 0, 1, SerializeGeneric, DeleteGenericCfgLine); /// todo: implement rss specific parser pthread_mutex_init(&RSSQueueMutex, NULL); RSSQueueRooms = NewHash(1, lFlathash); RSSFetchUrls = NewHash(1, NULL); @@ -809,5 +808,9 @@ CTDL_MODULE_INIT(rssclient) CtdlRegisterEVCleanupHook(rss_cleanup); CtdlRegisterDebugFlagHook(HKEY("rssclient"), LogDebugEnableRSSClient, &RSSClientDebugEnabled); } + else + { + CtdlFillSystemContext(&rss_CC, "rssclient"); + } return "rssclient"; } diff --git a/citadel/netconfig.c b/citadel/netconfig.c index 6137bd3d4..984f97a28 100644 --- a/citadel/netconfig.c +++ b/citadel/netconfig.c @@ -24,16 +24,17 @@ # include # endif #endif +#include #include #include "include/ctdl_module.h" HashList *CfgTypeHash = NULL; - +HashList *RoomConfigs = NULL; /*-----------------------------------------------------------------------------* * Per room network configs * *-----------------------------------------------------------------------------*/ -void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLineParser p, int uniq, CfgLineSerializer s, CfgLineDeAllocator d) +void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLineParser p, int uniq, int nSegments, CfgLineSerializer s, CfgLineDeAllocator d) { CfgLineType *pCfg; @@ -44,7 +45,7 @@ void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLinePar pCfg->Str.Key = Name; pCfg->Str.len = len; pCfg->IsSingleLine = uniq; - + pCfg->nSegments = nSegments; if (CfgTypeHash == NULL) CfgTypeHash = NewHash(1, NULL); Put(CfgTypeHash, Name, len, pCfg, NULL); @@ -84,28 +85,53 @@ const CfgLineType *GetCfgTypeByEnum(RoomNetCfg eCfg, HashPos *It) void ParseGeneric(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG) { RoomNetCfgLine *nptr; + int i; nptr = (RoomNetCfgLine *) malloc(sizeof(RoomNetCfgLine)); nptr->next = OneRNCFG->NetConfigs[ThisOne->C]; - nptr->Value = NewStrBufPlain(LinePos, StrLength(Line) - ( LinePos - ChrPtr(Line)) ); + nptr->Value = malloc(sizeof(StrBuf*) * ThisOne->nSegments); + memset(nptr->Value, 0, sizeof(StrBuf*) * ThisOne->nSegments); + if (ThisOne->nSegments == 1) + { + nptr->Value[0] = NewStrBufPlain(LinePos, StrLength(Line) - ( LinePos - ChrPtr(Line)) ); + } + else for (i = 0; i < ThisOne->nSegments; i++) + { + nptr->Value[i] = NewStrBufPlain(NULL, StrLength(Line) - ( LinePos - ChrPtr(Line)) ); + StrBufExtract_NextToken(nptr->Value[i], Line, &LinePos, '|'); + } + OneRNCFG->NetConfigs[ThisOne->C] = nptr; } void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *OneRNCFG, RoomNetCfgLine *data) { + int i; + StrBufAppendBufPlain(OutputBuffer, CKEY(ThisOne->Str), 0); - StrBufAppendBuf(OutputBuffer, data->Value, 0); + for (i = 0; i < ThisOne->nSegments; i++) + { + StrBufAppendBuf(OutputBuffer, data->Value[i], 0); + if (i + 1 < ThisOne->nSegments) + StrBufAppendBufPlain(OutputBuffer, HKEY("|"), 0); + } StrBufAppendBufPlain(OutputBuffer, HKEY("\n"), 0); } void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data) { - FreeStrBuf(&(*data)->Value); + int i; + + for (i = 0; i < ThisOne->nSegments; i++) + { + FreeStrBuf(&(*data)->Value[i]); + } + free ((*data)->Value); free(*data); *data = NULL; } -int read_spoolcontrol_file(OneRoomNetCfg **pOneRNCFG, char *filename) +int ReadRoomNetConfigFile(OneRoomNetCfg **pOneRNCFG, char *filename) { int fd; const char *ErrStr = NULL; @@ -123,6 +149,7 @@ int read_spoolcontrol_file(OneRoomNetCfg **pOneRNCFG, char *filename) OneRNCFG = malloc(sizeof(OneRoomNetCfg)); memset(OneRNCFG, 0, sizeof(OneRoomNetCfg)); *pOneRNCFG = OneRNCFG; + Line = NewStrBuf(); while (StrBufTCP_read_line(Line, &fd, 0, &ErrStr) >= 0) { if (StrLength(Line) == 0) @@ -157,7 +184,7 @@ int read_spoolcontrol_file(OneRoomNetCfg **pOneRNCFG, char *filename) return 1; } -int save_spoolcontrol_file(OneRoomNetCfg *OneRNCFG, char *filename) +int SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCFG, char *filename) { RoomNetCfg eCfg; StrBuf *Cfg; @@ -245,14 +272,13 @@ int save_spoolcontrol_file(OneRoomNetCfg *OneRNCFG, char *filename) } - -void free_spoolcontrol_struct(OneRoomNetCfg **pOneRNCFG) +void vFreeRoomNetworkStruct(void *vOneRoomNetCfg) { RoomNetCfg eCfg; HashPos *CfgIt; OneRoomNetCfg *OneRNCFG; - OneRNCFG = *pOneRNCFG; + OneRNCFG = (OneRoomNetCfg*)vOneRoomNetCfg; CfgIt = GetNewHashPos(CfgTypeHash, 1); for (eCfg = subpending; eCfg < maxRoomNetCfg; eCfg ++) { @@ -274,10 +300,123 @@ void free_spoolcontrol_struct(OneRoomNetCfg **pOneRNCFG) FreeStrBuf(&OneRNCFG->RoomInfo); FreeStrBuf(&OneRNCFG->misc); free(OneRNCFG); +} +void FreeRoomNetworkStruct(OneRoomNetCfg **pOneRNCFG) +{ + vFreeRoomNetworkStruct(*pOneRNCFG); *pOneRNCFG=NULL; } +void LoadAllNetConfigs(void) +{ + DIR *filedir = NULL; + struct dirent *d; + struct dirent *filedir_entry; + int d_type = 0; + int d_namelen; + long RoomNumber; + OneRoomNetCfg *OneRNCFG; + int IsNumOnly; + const char *pch; + char path[PATH_MAX]; + + RoomConfigs = NewHash(1, NULL); + filedir = opendir (ctdl_netcfg_dir); + if (filedir == NULL) { + return ; /// todo: panic! + } + + d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1); + if (d == NULL) { + closedir(filedir); + return ; + } + + while ((readdir_r(filedir, d, &filedir_entry) == 0) && + (filedir_entry != NULL)) + { +#ifdef _DIRENT_HAVE_D_NAMLEN + d_namelen = filedir_entry->d_namelen; +#else + d_namelen = strlen(filedir_entry->d_name); +#endif + +#ifdef _DIRENT_HAVE_D_TYPE + d_type = filedir_entry->d_type; +#else + +#ifndef DT_UNKNOWN +#define DT_UNKNOWN 0 +#define DT_DIR 4 +#define DT_REG 8 +#define DT_LNK 10 + +#define IFTODT(mode) (((mode) & 0170000) >> 12) +#define DTTOIF(dirtype) ((dirtype) << 12) +#endif + d_type = DT_UNKNOWN; +#endif + if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~') + continue; /* Ignore backup files... */ + + if ((d_namelen == 1) && + (filedir_entry->d_name[0] == '.')) + continue; + + if ((d_namelen == 2) && + (filedir_entry->d_name[0] == '.') && + (filedir_entry->d_name[1] == '.')) + continue; + + snprintf(path, PATH_MAX, "%s/%s", + ctdl_netcfg_dir, filedir_entry->d_name); + + if (d_type == DT_UNKNOWN) { + struct stat s; + if (lstat(path, &s) == 0) { + d_type = IFTODT(s.st_mode); + } + } + + switch (d_type) + { + case DT_DIR: + break; + case DT_LNK: /* TODO: check whether its a file or a directory */ + case DT_REG: + IsNumOnly = 1; + pch = filedir_entry->d_name; + while (*pch != '\0') + { + if (!isdigit(*pch)) + { + IsNumOnly = 0; + } + pch ++; + } + if (IsNumOnly) + { + RoomNumber = atol(filedir_entry->d_name); + ReadRoomNetConfigFile(&OneRNCFG, path); + + if (OneRNCFG != NULL) + Put(RoomConfigs, LKEY(RoomNumber), OneRNCFG, vFreeRoomNetworkStruct); + + /* syslog(9, "[%s | %s]\n", ChrPtr(OneWebName), ChrPtr(FileName)); */ + } + break; + default: + break; + } + + + } + free(d); + closedir(filedir); +} + + /*-----------------------------------------------------------------------------* * Per room network configs : exchange with client * *-----------------------------------------------------------------------------*/ @@ -574,8 +713,8 @@ int is_recipient(OneRoomNetCfg *RNCfg, const char *Name) while (nptr != NULL) { - if ((StrLength(nptr->Value) == len) && - (!strcmp(Name, ChrPtr(nptr->Value)))) + if ((StrLength(nptr->Value[0]) == len) && + (!strcmp(Name, ChrPtr(nptr->Value[0])))) { return 1; } @@ -604,7 +743,7 @@ int CtdlNetconfigCheckRoomaccess( assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); begin_critical_section(S_NETCONFIGS); - if (!read_spoolcontrol_file(&RNCfg, filename)) + if (!ReadRoomNetConfigFile(&RNCfg, filename)) { end_critical_section(S_NETCONFIGS); snprintf(errmsgbuf, n, @@ -613,7 +752,7 @@ int CtdlNetconfigCheckRoomaccess( } end_critical_section(S_NETCONFIGS); found = is_recipient (RNCfg, RemoteIdentifier); - free_spoolcontrol_struct(&RNCfg); + vFreeRoomNetworkStruct(&RNCfg); if (found) { return (0); } @@ -906,6 +1045,8 @@ int CtdlIsValidNode(const StrBuf **nexthop, } + + /* * Module entry point */ @@ -913,7 +1054,7 @@ CTDL_MODULE_INIT(netconfig) { if (!threading) { - + LoadAllNetConfigs (); CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config"); CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config"); CtdlRegisterProtoHook(cmd_netp, "NETP", "Identify as network poller"); diff --git a/citadel/scripts/mk_module_init.sh b/citadel/scripts/mk_module_init.sh index 7939cd7fa..bbf19b783 100755 --- a/citadel/scripts/mk_module_init.sh +++ b/citadel/scripts/mk_module_init.sh @@ -171,6 +171,7 @@ void upgrade_modules(void); CTDL_MODULE_INIT(msgbase); CTDL_MODULE_INIT(room_ops); CTDL_MODULE_INIT(user_ops); + CTDL_MODULE_INIT(netconfig); EOF for i in serv_*.c @@ -318,6 +319,11 @@ fi cd $CUR_DIR +# this one has to be called last, else it will not find all hooks registered. +cat <> $C_FILE + pMod = CTDL_INIT_CALL(netconfig); + MOD_syslog(LOG_DEBUG, "Loaded module: %s\n", pMod); +EOF /usr/bin/printf "\n\n" >> $C_FILE /usr/bin/printf "\tfor (filter = 1; filter != 0; filter = filter << 1)\n" >> $C_FILE /usr/bin/printf "\t\tif ((filter & DetailErrorFlags) != 0)\n" >> $C_FILE -- 2.30.2