From de84a12f8a5f140c0f7b8e00f4cac92ef13cd866 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 29 Jun 2009 16:53:26 +0200 Subject: introduced the idea of detached properties some things inside the message can be used over a large number of messages and need to to be allocated and re-written every time. I now begin to implement this as a "prop_t" object, first use for the inputName. Some input modules are already converted, some others to go. Will do a little performance check on the new method before I go further. Also, this commit has some cleanup and a few bug fixes that prevented compiliation in debug mode (I overlooked this as I did not compile for debug, what I normally do, and the automatted test also does not do that) --- plugins/imdiag/imdiag.c | 2 +- plugins/imfile/imfile.c | 2 +- plugins/imklog/imklog.c | 2 +- plugins/imklog/linux.c | 7 ++-- plugins/imudp/imudp.c | 16 ++++++++- runtime/datetime.c | 5 --- runtime/datetime.h | 2 -- runtime/msg.c | 91 +++++++++++++++++++++++++++++++++++-------------- runtime/msg.h | 11 ++++-- runtime/prop.c | 63 ++++++++++++++++++++++++++++++++++ runtime/prop.h | 11 +++++- runtime/rsyslog.c | 3 ++ runtime/rsyslog.h | 1 + runtime/stringbuf.h | 2 +- tcps_sess.c | 8 +++-- tcpsrv.c | 15 ++++++-- tcpsrv.h | 4 +-- tests/nettester.c | 5 +-- tools/syslogd.c | 5 +-- 19 files changed, 200 insertions(+), 55 deletions(-) diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c index bfb4a2e5..4b004bc4 100644 --- a/plugins/imdiag/imdiag.c +++ b/plugins/imdiag/imdiag.c @@ -206,7 +206,7 @@ doInjectMsg(int iNum) /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime)); MsgSetRawMsg(pMsg, (char*) szMsg, ustrlen(szMsg)); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imdiag"), sizeof("imdiag")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imdiag"), sizeof("imdiag")-1); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 631d02ff..fdd0c5f0 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -97,7 +97,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index ab806183..21744c4b 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -97,7 +97,7 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imklog"), sizeof("imklog")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imklog"), sizeof("imklog")-1); MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetRcvFrom(pMsg, glbl.GetLocalHostName()); diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c index fcd9d6cd..977395ea 100644 --- a/plugins/imklog/linux.c +++ b/plugins/imklog/linux.c @@ -37,6 +37,7 @@ #include "msg.h" #include "module-template.h" #include "imklog.h" +#include "unicode-helper.h" /* Includes. */ @@ -86,7 +87,7 @@ extern int ksyslog(int type, char *buf, int len); static uchar *GetPath(void) { - return pszPath ? pszPath : _PATH_KLOG; + return pszPath ? pszPath : UCHAR_CONSTANT(_PATH_KLOG); } static void CloseLogSrc(void) @@ -140,7 +141,7 @@ static enum LOGSRC GetKernelLogSrc(void) * file system is available to get kernel messages from. */ if ( use_syscall || - ((stat(GetPath(), &sb) < 0) && (errno == ENOENT)) ) + ((stat((char*)GetPath(), &sb) < 0) && (errno == ENOENT)) ) { /* Initialize kernel logging. */ ksyslog(1, NULL, 0); @@ -149,7 +150,7 @@ static enum LOGSRC GetKernelLogSrc(void) return(kernel); } - if ( (kmsg = open(GetPath(), O_RDONLY|O_CLOEXEC)) < 0 ) + if ( (kmsg = open((char*)GetPath(), O_RDONLY|O_CLOEXEC)) < 0 ) { imklogLogIntMsg(LOG_ERR, "imklog: Cannot open proc file system, %d.\n", errno); ksyslog(7, NULL, 0); /* TODO: check this, implement more */ diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index 2340aac4..828b9636 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -43,6 +43,7 @@ #include "msg.h" #include "parser.h" #include "datetime.h" +#include "prop.h" #include "unicode-helper.h" MODULE_TYPE_INPUT @@ -55,6 +56,7 @@ DEFobjCurrIf(errmsg) DEFobjCurrIf(glbl) DEFobjCurrIf(net) DEFobjCurrIf(datetime) +DEFobjCurrIf(prop) static int iMaxLine; /* maximum UDP message size supported */ static time_t ttLastDiscard = 0; /* timestamp when a message from a non-permitted sender was last discarded @@ -68,6 +70,7 @@ static uchar *pRcvBuf = NULL; /* receive buffer (for a single packet). We use a * it so that we can check available memory in willRun() and request * termination if we can not get it. -- rgerhards, 2007-12-27 */ +static prop_t *pInputName = NULL; /* our inputName currently is always "imudp", and this will hold it */ // TODO: static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */ #define TIME_REQUERY_DFLT 2 static int iTimeRequery = TIME_REQUERY_DFLT;/* how often is time to be queried inside tight recv loop? 0=always */ @@ -242,7 +245,8 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime)); MsgSetRawMsg(pMsg, (char*)pRcvBuf, lenRcvBuf); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imudp"), sizeof("imudp")-1); + prop.AddRef(pInputName); + MsgSetInputName(pMsg, pInputName); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; @@ -338,6 +342,12 @@ ENDrunInput /* initialize and return if will run or not */ BEGINwillRun CODESTARTwillRun + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imudp"), sizeof("imudp") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + prop.AddRef(pInputName); + net.PrintAllowedSenders(1); /* UDP */ /* if we could not set up any listners, there is no point in running... */ @@ -365,6 +375,8 @@ CODESTARTafterRun free(pRcvBuf); pRcvBuf = NULL; } + if(pInputName != NULL) + prop.Destruct(&pInputName); ENDafterRun @@ -374,6 +386,7 @@ CODESTARTmodExit objRelease(errmsg, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); objRelease(net, LM_NET_FILENAME); ENDmodExit @@ -405,6 +418,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); /* register config file handlers */ diff --git a/runtime/datetime.c b/runtime/datetime.c index e0f3f5fa..ea67eec5 100644 --- a/runtime/datetime.c +++ b/runtime/datetime.c @@ -556,7 +556,6 @@ int formatTimestampToMySQL(struct syslogTime *ts, char* pBuf) */ assert(ts != NULL); assert(pBuf != NULL); - assert(iLenDst >= 15); pBuf[0] = (ts->year / 1000) % 10 + '0'; pBuf[1] = (ts->year / 100) % 10 + '0'; @@ -582,7 +581,6 @@ int formatTimestampToPgSQL(struct syslogTime *ts, char *pBuf) /* see note in formatTimestampToMySQL, applies here as well */ assert(ts != NULL); assert(pBuf != NULL); - assert(iLenDst >= 20); pBuf[0] = (ts->year / 1000) % 10 + '0'; pBuf[1] = (ts->year / 100) % 10 + '0'; @@ -665,7 +663,6 @@ int formatTimestamp3339(struct syslogTime *ts, char* pBuf) BEGINfunc assert(ts != NULL); assert(pBuf != NULL); - assert(iLenBuf >= 33); /* start with fixed parts */ /* year yyyy */ @@ -740,8 +737,6 @@ int formatTimestamp3164(struct syslogTime *ts, char* pBuf) assert(ts != NULL); assert(pBuf != NULL); - assert(iLenBuf >= 16); - pBuf[0] = monthNames[(ts->month - 1)% 12][0]; pBuf[1] = monthNames[(ts->month - 1) % 12][1]; pBuf[2] = monthNames[(ts->month - 1) % 12][2]; diff --git a/runtime/datetime.h b/runtime/datetime.h index 79a86d05..58f368e7 100644 --- a/runtime/datetime.h +++ b/runtime/datetime.h @@ -23,8 +23,6 @@ #ifndef INCLUDED_DATETIME_H #define INCLUDED_DATETIME_H -#include "datetime.h" - /* TODO: define error codes */ #define NO_ERRCODE -1 diff --git a/runtime/msg.c b/runtime/msg.c index c4ba18df..47b4ed85 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -48,6 +48,7 @@ #include "atomic.h" #include "unicode-helper.h" #include "ruleset.h" +#include "prop.h" /* static data */ DEFobjStaticHelpers @@ -55,6 +56,7 @@ DEFobjCurrIf(var) DEFobjCurrIf(datetime) DEFobjCurrIf(glbl) DEFobjCurrIf(regexp) +DEFobjCurrIf(prop) static struct { uchar *pszName; @@ -273,12 +275,26 @@ static char *syslog_number_names[24] = { "0", "1", "2", "3", "4", "5", "6", "7", /* some forward declarations */ static int getAPPNAMELen(msg_t *pM, bool bLockMutex); + static inline int getProtocolVersion(msg_t *pM) { return(pM->iProtocolVersion); } +static inline void +getInputName(msg_t *pM, uchar **ppsz, int *plen) +{ + BEGINfunc + if(pM == NULL) { + *ppsz = UCHAR_CONSTANT(""); + *plen = 0; + } else { + prop.GetString(pM->pInputName, ppsz, plen); + } + ENDfunc +} + /* The following functions will support advanced output module * multithreading, once this is implemented. Currently, we * include them as hooks only. The idea is that we need to guard @@ -431,7 +447,6 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) pM->iFacility = -1; pM->offAfterPRI = 0; pM->offMSG = -1; - pM->iLenInputName = 0; pM->iProtocolVersion = 0; pM->msgFlags = 0; pM->iLenRawMsg = 0; @@ -444,7 +459,6 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) pM->pszHOSTNAME = NULL; pM->pszRcvFrom = NULL; pM->pszRcvFromIP = NULL; - pM->pszInputName = NULL; pM->pszRcvdAt3164 = NULL; pM->pszRcvdAt3339 = NULL; pM->pszRcvdAt_MySQL = NULL; @@ -458,6 +472,7 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) pM->pCSAPPNAME = NULL; pM->pCSPROCID = NULL; pM->pCSMSGID = NULL; + pM->pInputName = NULL; pM->pRuleset = NULL; memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt)); memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP)); @@ -556,7 +571,8 @@ CODESTARTobjDestruct(msg) free(pThis->pszRawMsg); freeTAG(pThis); freeHOSTNAME(pThis); - free(pThis->pszInputName); + if(pThis->pInputName != NULL) + prop.Destruct(&pThis->pInputName); free(pThis->pszRcvFrom); free(pThis->pszRcvFromIP); free(pThis->pszRcvdAt3164); @@ -719,11 +735,16 @@ msg_t* MsgDup(msg_t* pOld) */ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm) { + uchar *psz; + int len; DEFiRet; assert(pThis != NULL); assert(pStrm != NULL); + /* "pump" some property values into strings */ + + /* then serialize elements */ CHKiRet(obj.BeginSerialize(pStrm, (obj_t*) pThis)); objSerializeSCALAR(pStrm, iProtocolVersion, SHORT); objSerializeSCALAR(pStrm, iSeverity, SHORT); @@ -743,7 +764,9 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm) objSerializePTR(pStrm, pszRawMsg, PSZ); objSerializePTR(pStrm, pszHOSTNAME, PSZ); - objSerializePTR(pStrm, pszInputName, PSZ); + getInputName(pThis, &psz, &len); + objSerializeSCALAR_VAR(pStrm, "pszInputName", PSZ, psz); + //objSerializePTR(pStrm, pszInputName, PSZ); objSerializePTR(pStrm, pszRcvFrom, PSZ); objSerializePTR(pStrm, pszRcvFromIP, PSZ); @@ -1427,18 +1450,6 @@ char *getHOSTNAME(msg_t *pM) } -static uchar *getInputName(msg_t *pM) -{ - if(pM == NULL) - return (uchar*) ""; - else - if(pM->pszInputName == NULL) - return (uchar*) ""; - else - return pM->pszInputName; -} - - uchar *getRcvFrom(msg_t *pM) { if(pM == NULL) @@ -1598,14 +1609,31 @@ static int getAPPNAMELen(msg_t *pM, bool bLockMutex) /* rgerhards 2008-09-10: set pszInputName in msg object * rgerhards, 2009-06-16 */ -void MsgSetInputName(msg_t *pMsg, uchar* pszInputName, size_t lenInputName) +void MsgSetInputName(msg_t *pThis, prop_t *inputName) { - assert(pMsg != NULL); - free(pMsg->pszInputName); - pMsg->iLenInputName = lenInputName; - if((pMsg->pszInputName = malloc(pMsg->iLenInputName + 1)) != NULL) { - memcpy(pMsg->pszInputName, pszInputName, pMsg->iLenInputName + 1); - } + assert(pThis != NULL); + + if(pThis->pInputName != NULL) + prop.Destruct(&pThis->pInputName); + pThis->pInputName = inputName; +} + +/* to be removed soon: work-around for those tht can not natively generate an + * input name. + * rgerhards, 2009-06-29 + */ +void MsgSetInputNameStr(msg_t *pThis, uchar *psz, int len) +{ + prop_t *pProp; + assert(pThis != NULL); + + /* we need to create a property */ + prop.Construct(&pProp); + prop.SetString(pProp, psz, len); + prop.ConstructFinalize(pProp); + prop.AddRef(pProp); + MsgSetInputName(pThis, pProp); + prop.Destruct(&pProp); } /* rgerhards 2004-11-16: set pszRcvFrom in msg object @@ -1875,6 +1903,7 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, short iOffs; BEGINfunc +dbgprintf("XXXX: msgGetProp for %d\n", propID); assert(pMsg != NULL); assert(pbMustBeFreed != NULL); @@ -1910,7 +1939,10 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, break; */ case PROP_INPUTNAME: - pRes = (char*) getInputName(pMsg); +RUNLOG; + getInputName(pMsg, ((uchar**) &pRes), &bufLen); +RUNLOG; +RUNLOG_VAR("%p", pRes); break; case PROP_FROMHOST: pRes = (char*) getRcvFrom(pMsg); @@ -2738,6 +2770,7 @@ rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID) #define isProp(name) !rsCStrSzStrCmp(pProp->pcsName, (uchar*) name, sizeof(name) - 1) rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp) { + prop_t *myProp; DEFiRet; ISOBJ_TYPE_assert(pThis, msg); @@ -2765,7 +2798,13 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp) } else if(isProp("pszTAG")) { MsgSetTAG(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), cstrLen(pProp->val.pStr)); } else if(isProp("pszInputName")) { - MsgSetInputName(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr)); + /* we need to create a property */ + CHKiRet(prop.Construct(&myProp)); + CHKiRet(prop.SetString(myProp, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr))); + CHKiRet(prop.ConstructFinalize(myProp)); + prop.AddRef(myProp); + MsgSetInputName(pThis, myProp); + prop.Destruct(&myProp); } else if(isProp("pszRcvFromIP")) { MsgSetRcvFromIP(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr)); } else if(isProp("pszRcvFrom")) { @@ -2790,6 +2829,7 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp) dbgprintf("no longer supported property pszMSG silently ignored\n"); } +finalize_it: RETiRet; } #undef isProp @@ -2833,6 +2873,7 @@ BEGINObjClassInit(msg, 1, OBJ_IS_CORE_MODULE) CHKiRet(objUse(var, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); /* set our own handlers */ OBJSetMethodHandler(objMethod_SERIALIZE, MsgSerialize); diff --git a/runtime/msg.h b/runtime/msg.h index e6b25e6c..a1fc535b 100644 --- a/runtime/msg.h +++ b/runtime/msg.h @@ -72,7 +72,6 @@ struct msg { short iFacility; /* Facility code 0 .. 23*/ short offAfterPRI; /* offset, at which raw message WITHOUT PRI part starts in pszRawMsg */ short offMSG; /* offset at which the MSG part starts in pszRawMsg */ - short iLenInputName; /* Length of pszInputName */ short iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */ int msgFlags; /* flags associated with this message */ int iLenRawMsg; /* length of raw message */ @@ -86,7 +85,6 @@ struct msg { uchar *pszHOSTNAME; /* HOSTNAME from syslog message */ uchar *pszRcvFrom; /* System message was received from */ uchar *pszRcvFromIP; /* IP of system message was received from */ - uchar *pszInputName; /* name of the input module that submitted this message */ char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 charcters) */ char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 charcters at most) */ char *pszRcvdAt_MySQL; /* rcvdAt as MySQL formatted string (always 14 charcters) */ @@ -100,6 +98,7 @@ struct msg { cstr_t *pCSAPPNAME; /* APP-NAME */ cstr_t *pCSPROCID; /* PROCID */ cstr_t *pCSMSGID; /* MSGID */ + prop_t *pInputName; /* input name property */ ruleset_t *pRuleset; /* ruleset to be used for processing this message */ time_t ttGenTime; /* time msg object was generated, same as tRcvdAt, but a Unix timestamp. While this field looks redundant, it is required because a Unix timestamp @@ -144,7 +143,7 @@ rsRetVal msgDestruct(msg_t **ppM); msg_t* MsgDup(msg_t* pOld); msg_t *MsgAddRef(msg_t *pM); void setProtocolVersion(msg_t *pM, int iNewVersion); -void MsgSetInputName(msg_t *pMsg, uchar*, size_t); +void MsgSetInputName(msg_t *pMsg, prop_t*); rsRetVal MsgSetAPPNAME(msg_t *pMsg, char* pszAPPNAME); rsRetVal MsgSetPROCID(msg_t *pMsg, char* pszPROCID); rsRetVal MsgSetMSGID(msg_t *pMsg, char* pszMSGID); @@ -166,6 +165,12 @@ char *textpri(char *pRes, size_t pResLen, int pri); rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar); rsRetVal MsgEnableThreadSafety(void); + +// REMOVE: +void MsgSetInputNameStr(msg_t *pThis, uchar *psz, int len); + + + /* TODO: remove these five (so far used in action.c) */ char *getMSG(msg_t *pM); char *getHOSTNAME(msg_t *pM); diff --git a/runtime/prop.c b/runtime/prop.c index 02be315f..989657dd 100644 --- a/runtime/prop.c +++ b/runtime/prop.c @@ -36,9 +36,12 @@ #include "config.h" #include #include +#include #include "rsyslog.h" #include "obj.h" +#include "obj-types.h" +#include "atomic.h" #include "prop.h" /* static data */ @@ -48,8 +51,45 @@ DEFobjStaticHelpers /* Standard-Constructor */ BEGINobjConstruct(prop) /* be sure to specify the object type also in END macro! */ + pThis->iRefCount = 1; ENDobjConstruct(prop) +/* set string, we make our own private copy! This MUST only be called BEFORE + * ConstructFinalize()! + */ +static rsRetVal SetString(prop_t *pThis, uchar *psz, int len) +{ + DEFiRet; + ISOBJ_TYPE_assert(pThis, prop); + if(pThis->len >= CONF_PROP_BUFSIZE) + free(pThis->szVal.psz); + pThis->len = len; + if(len < CONF_PROP_BUFSIZE) { + memcpy(pThis->szVal.sz, psz, len + 1); + } else { + CHKmalloc(pThis->szVal.psz = malloc(len + 1)); + memcpy(pThis->szVal.sz, psz, len + 1); + } + +finalize_it: + RETiRet; +} + + +/* get string */ +static rsRetVal GetString(prop_t *pThis, uchar **ppsz, int *plen) +{ + BEGINfunc + ISOBJ_TYPE_assert(pThis, prop); + if(pThis->len < CONF_PROP_BUFSIZE) + *ppsz = pThis->szVal.sz; + else + *ppsz = pThis->szVal.psz; + *plen = pThis->len; + ENDfunc + return RS_RET_OK; +} + /* ConstructionFinalizer * rgerhards, 2008-01-09 @@ -63,9 +103,29 @@ propConstructFinalize(prop_t __attribute__((unused)) *pThis) } +/* add a new reference. It is VERY IMPORTANT to call this function whenever + * the property is handed over to some entitiy that later call Destruct() on it. + */ +static rsRetVal AddRef(prop_t *pThis) +{ + ATOMIC_INC(pThis->iRefCount); + return RS_RET_OK; +} + + /* destructor for the prop object */ BEGINobjDestruct(prop) /* be sure to specify the object type also in END and CODESTART macros! */ + int currRefCount; CODESTARTobjDestruct(prop) + currRefCount = ATOMIC_DEC_AND_FETCH(pThis->iRefCount); + if(currRefCount == 0) { + /* (only) in this case we need to actually destruct the object */ +dbgprintf("XXXXX: propDestruct: ptr %p, pThis %p, len %d\n", pThis->szVal.psz, pThis, pThis->len); + if(pThis->len >= CONF_PROP_BUFSIZE) + free(pThis->szVal.psz); + } else { + pThis = NULL; /* tell framework NOT to destructing the object! */ + } ENDobjDestruct(prop) @@ -94,6 +154,9 @@ CODESTARTobjQueryInterface(prop) pIf->ConstructFinalize = propConstructFinalize; pIf->Destruct = propDestruct; pIf->DebugPrint = propDebugPrint; + pIf->SetString = SetString; + pIf->GetString = GetString; + pIf->AddRef = AddRef; finalize_it: ENDobjQueryInterface(prop) diff --git a/runtime/prop.h b/runtime/prop.h index 7fc466b5..1d18c650 100644 --- a/runtime/prop.h +++ b/runtime/prop.h @@ -28,14 +28,23 @@ /* the prop object */ struct prop_s { BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ + int iRefCount; /* reference counter */ + union { + uchar *psz; /* stored string */ + uchar sz[CONF_PROP_BUFSIZE]; + } szVal; + int len; /* we use int intentionally, otherwise we may get some troubles... */ }; /* interfaces */ BEGINinterface(prop) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(prop); rsRetVal (*Construct)(prop_t **ppThis); - rsRetVal (*ConstructFinalize)(prop_t __attribute__((unused)) *pThis); + rsRetVal (*ConstructFinalize)(prop_t *pThis); rsRetVal (*Destruct)(prop_t **ppThis); + rsRetVal (*SetString)(prop_t *pThis, uchar* psz, int len); + rsRetVal (*GetString)(prop_t *pThis, uchar** ppsz, int *plen); + rsRetVal (*AddRef)(prop_t *pThis); ENDinterface(prop) #define propCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c index 6f732f0e..faa74427 100644 --- a/runtime/rsyslog.c +++ b/runtime/rsyslog.c @@ -77,6 +77,7 @@ #include "conf.h" #include "glbl.h" #include "errmsg.h" +#include "prop.h" #include "rule.h" #include "ruleset.h" @@ -150,6 +151,8 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF) CHKiRet(glblClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "datetime"; CHKiRet(datetimeClassInit(NULL)); + if(ppErrObj != NULL) *ppErrObj = "prop"; + CHKiRet(propClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "msg"; CHKiRet(msgClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "ctok_token"; diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 4e0f6e6c..8a043dde 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -39,6 +39,7 @@ #define CONF_RAWMSG_BUFSIZE 101 #define CONF_TAG_BUFSIZE 32 #define CONF_HOSTNAME_BUFSIZE 32 +#define CONF_PROP_BUFSIZE 16 /* should be close to sizeof(ptr) or lighly above it */ /* ############################################################# * diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h index 400c74eb..c5130238 100644 --- a/runtime/stringbuf.h +++ b/runtime/stringbuf.h @@ -35,6 +35,7 @@ #ifndef _STRINGBUF_H_INCLUDED__ #define _STRINGBUF_H_INCLUDED__ 1 +#include /** * The dynamic string buffer object. @@ -48,7 +49,6 @@ typedef struct cstr_s uchar *pszBuf; /**< pointer to the sz version of the string (after it has been created )*/ size_t iBufSize; /**< current maximum size of the string buffer */ size_t iStrLen; /**< length of the string in characters. */ - bool bIsForeignBuf; /**< is pBuf a buffer provided by someone else? */ } cstr_t; diff --git a/tcps_sess.c b/tcps_sess.c index e0bec949..4786e154 100644 --- a/tcps_sess.c +++ b/tcps_sess.c @@ -45,6 +45,7 @@ #include "netstrm.h" #include "msg.h" #include "datetime.h" +#include "prop.h" /* static data */ @@ -52,6 +53,7 @@ DEFobjStaticHelpers DEFobjCurrIf(glbl) DEFobjCurrIf(errmsg) DEFobjCurrIf(netstrm) +DEFobjCurrIf(prop) DEFobjCurrIf(datetime) static int iMaxLine; /* maximum size of a single message */ @@ -234,9 +236,9 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime)); -dbgprintf("defaultDoSubmit, iMsg %d\n", pThis->iMsg); MsgSetRawMsg(pMsg, (char*)pThis->pMsg, pThis->iMsg); - MsgSetInputName(pMsg, pThis->pLstnInfo->pszInputName, pThis->pLstnInfo->lenInputName); + prop.AddRef(pThis->pLstnInfo->pInputName); + MsgSetInputName(pMsg, pThis->pLstnInfo->pInputName); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; @@ -520,6 +522,7 @@ CODESTARTObjClassExit(tcps_sess) objRelease(errmsg, CORE_COMPONENT); objRelease(netstrm, LM_NETSTRMS_FILENAME); objRelease(datetime, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); ENDObjClassExit(tcps_sess) @@ -532,6 +535,7 @@ BEGINObjClassInit(tcps_sess, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE c CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME)); CHKiRet(objUse(datetime, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); iMaxLine = glbl.GetMaxLine(); /* get maximum size we currently support */ diff --git a/tcpsrv.c b/tcpsrv.c index 119aea91..e8ea2b98 100644 --- a/tcpsrv.c +++ b/tcpsrv.c @@ -89,6 +89,7 @@ DEFobjCurrIf(net) DEFobjCurrIf(netstrms) DEFobjCurrIf(netstrm) DEFobjCurrIf(nssel) +DEFobjCurrIf(prop) /* add new listener port to listener port list @@ -107,8 +108,11 @@ addNewLstnPort(tcpsrv_t *pThis, uchar *pszPort) pEntry->pszPort = pszPort; pEntry->pSrv = pThis; pEntry->pRuleset = pThis->pRuleset; - CHKmalloc(pEntry->pszInputName = ustrdup(pThis->pszInputName)); - pEntry->lenInputName = ustrlen(pEntry->pszInputName); + + /* we need to create a property */ + CHKiRet(prop.Construct(&pEntry->pInputName)); + CHKiRet(prop.SetString(pEntry->pInputName, pThis->pszInputName, ustrlen(pThis->pszInputName))); + CHKiRet(prop.ConstructFinalize(pEntry->pInputName)); /* and add to list */ pEntry->pNext = pThis->pLstnPorts; @@ -250,7 +254,7 @@ static void deinit_tcp_listener(tcpsrv_t *pThis) pEntry = pThis->pLstnPorts; while(pEntry != NULL) { free(pEntry->pszPort); - free(pEntry->pszInputName); + prop.Destruct(&pEntry->pInputName); pDel = pEntry; pEntry = pEntry->pNext; free(pDel); @@ -477,6 +481,7 @@ Run(tcpsrv_t *pThis) * this thread. Thus, we also need to instantiate a cancel cleanup handler * to prevent us from leaking anything. -- rgerharsd, 20080-04-24 */ +RUNLOG_STR("XXXX: tcp server runs\n"); pthread_cleanup_push(RunCancelCleanup, (void*) &pSel); while(1) { CHKiRet(nssel.Construct(&pSel)); @@ -497,6 +502,7 @@ Run(tcpsrv_t *pThis) iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); } +RUNLOG_STR("XXXX: tcp server select\n"); /* wait for io to become ready */ CHKiRet(nssel.Wait(pSel, &nfds)); @@ -508,6 +514,7 @@ Run(tcpsrv_t *pThis) --nfds; /* indicate we have processed one */ } } +RUNLOG_STR("XXXX: tcp server post select\n"); /* now check the sessions */ iTCPSess = TCPSessGetNxtSess(pThis, -1); @@ -883,6 +890,7 @@ CODESTARTObjClassExit(tcpsrv) /* release objects we no longer need */ objRelease(tcps_sess, DONT_LOAD_LIB); objRelease(conf, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); @@ -908,6 +916,7 @@ BEGINObjClassInit(tcpsrv, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE CHKiRet(objUse(conf, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, tcpsrvDebugPrint); diff --git a/tcpsrv.h b/tcpsrv.h index e2170bef..70682398 100644 --- a/tcpsrv.h +++ b/tcpsrv.h @@ -23,6 +23,7 @@ #define INCLUDED_TCPSRV_H #include "obj.h" +#include "prop.h" #include "tcps_sess.h" /* support for framing anomalies */ @@ -36,8 +37,7 @@ typedef enum ETCPsyslogFramingAnomaly { /* list of tcp listen ports */ struct tcpLstnPortList_s { uchar *pszPort; /**< the ports the listener shall listen on */ - uchar *pszInputName; /**< value to be used as input name */ - size_t lenInputName; /**< length of inputName */ + prop_t *pInputName; tcpsrv_t *pSrv; /**< pointer to higher-level server instance */ ruleset_t *pRuleset; /**< associated ruleset */ tcpLstnPortList_t *pNext; /**< next port or NULL */ diff --git a/tests/nettester.c b/tests/nettester.c index c9a978c5..dbfb4db3 100644 --- a/tests/nettester.c +++ b/tests/nettester.c @@ -128,11 +128,12 @@ tcpSend(char *buf, int lenBuf) if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) { break; } else { - if(retries++ == 3) { + if(retries++ == 30) { + ++iFailed; fprintf(stderr, "connect() failed\n"); return(1); } else { - sleep(1); + usleep(100); } } } diff --git a/tools/syslogd.c b/tools/syslogd.c index 3204d94e..2fe949ac 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -580,7 +580,7 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime)); } if(pszInputName != NULL) - MsgSetInputName(pMsg, pszInputName, ustrlen(pszInputName)); + MsgSetInputNameStr(pMsg, pszInputName, ustrlen(pszInputName)); MsgSetFlowControlType(pMsg, flowCtlType); MsgSetRawMsgWOSize(pMsg, (char*)msg); @@ -881,7 +881,7 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags) DEFiRet; CHKiRet(msgConstruct(&pMsg)); - MsgSetInputName(pMsg, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd")-1); MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetRcvFrom(pMsg, glbl.GetLocalHostName()); @@ -2089,6 +2089,7 @@ runInputModules(void) { modInfo_t *pMod; + BEGINfunc /* loop through all modules and activate them (brr...) */ pMod = module.GetNxtType(NULL, eMOD_IN); while(pMod != NULL) { -- cgit