/* strms_sess.c * * This implements a session of the strmsrv object. For general * comments, see header of strmsrv.c. * * Copyright 2007, 2008, 2009 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include "rsyslog.h" #include "dirty.h" #include "module-template.h" #include "net.h" #include "strmsrv.h" #include "strms_sess.h" #include "obj.h" #include "errmsg.h" #include "netstrm.h" #include "msg.h" #include "datetime.h" /* static data */ DEFobjStaticHelpers DEFobjCurrIf(glbl) DEFobjCurrIf(errmsg) DEFobjCurrIf(netstrm) DEFobjCurrIf(datetime) static int iMaxLine; /* maximum size of a single message */ /* forward definitions */ static rsRetVal Close(strms_sess_t *pThis); /* Standard-Constructor */ BEGINobjConstruct(strms_sess) /* be sure to specify the object type also in END macro! */ ENDobjConstruct(strms_sess) /* ConstructionFinalizer */ static rsRetVal strms_sessConstructFinalize(strms_sess_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, strms_sess); if(pThis->pSrv->OnSessConstructFinalize != NULL) { CHKiRet(pThis->pSrv->OnSessConstructFinalize(&pThis->pUsr)); } finalize_it: RETiRet; } /* destructor for the strms_sess object */ BEGINobjDestruct(strms_sess) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(strms_sess) if(pThis->pStrm != NULL) netstrm.Destruct(&pThis->pStrm); if(pThis->pSrv->pOnSessDestruct != NULL) { pThis->pSrv->pOnSessDestruct(&pThis->pUsr); } /* now destruct our own properties */ free(pThis->fromHost); free(pThis->fromHostIP); ENDobjDestruct(strms_sess) /* debugprint for the strms_sess object */ BEGINobjDebugPrint(strms_sess) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDebugPrint(strms_sess) ENDobjDebugPrint(strms_sess) /* set property functions */ /* set the hostname. Note that the caller *hands over* the string. That is, * the caller no longer controls it once SetHost() has received it. Most importantly, * the caller must not free it. -- rgerhards, 2008-04-24 */ static rsRetVal SetHost(strms_sess_t *pThis, uchar *pszHost) { DEFiRet; ISOBJ_TYPE_assert(pThis, strms_sess); free(pThis->fromHost); pThis->fromHost = pszHost; RETiRet; } /* set the remote host's IP. Note that the caller *hands over* the string. That is, * the caller no longer controls it once SetHostIP() has received it. Most importantly, * the caller must not free it. -- rgerhards, 2008-05-16 */ static rsRetVal SetHostIP(strms_sess_t *pThis, uchar *pszHostIP) { DEFiRet; ISOBJ_TYPE_assert(pThis, strms_sess); free(pThis->fromHostIP); pThis->fromHostIP = pszHostIP; RETiRet; } static rsRetVal SetStrm(strms_sess_t *pThis, netstrm_t *pStrm) { DEFiRet; ISOBJ_TYPE_assert(pThis, strms_sess); pThis->pStrm = pStrm; RETiRet; } /* set our parent, the strmsrv object */ static rsRetVal SetStrmsrv(strms_sess_t *pThis, strmsrv_t *pSrv) { DEFiRet; ISOBJ_TYPE_assert(pThis, strms_sess); ISOBJ_TYPE_assert(pSrv, strmsrv); pThis->pSrv = pSrv; RETiRet; } /* set our parent listener info*/ static rsRetVal SetLstnInfo(strms_sess_t *pThis, strmLstnPortList_t *pLstnInfo) { DEFiRet; ISOBJ_TYPE_assert(pThis, strms_sess); assert(pLstnInfo != NULL); pThis->pLstnInfo = pLstnInfo; RETiRet; } static rsRetVal SetUsrP(strms_sess_t *pThis, void *pUsr) { DEFiRet; pThis->pUsr = pUsr; RETiRet; } static void * GetUsrP(strms_sess_t *pThis) { return pThis->pUsr; } /* Closes a STRM session * No attention is paid to the return code * of close, so potential-double closes are not detected. */ static rsRetVal Close(strms_sess_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, strms_sess); netstrm.Destruct(&pThis->pStrm); free(pThis->fromHost); pThis->fromHost = NULL; /* not really needed, but... */ free(pThis->fromHostIP); pThis->fromHostIP = NULL; /* not really needed, but... */ RETiRet; } /* Processes the data received via a STRM session. If there * is no other way to handle it, data is discarded. * Input parameter data is the data received, iLen is its * len as returned from recv(). iLen must be 1 or more (that * is errors must be handled by caller!). iSTRMSess must be * the index of the STRM session that received the data. * rgerhards 2005-07-04 * And another change while generalizing. We now return either * RS_RET_OK, which means the session should be kept open * or anything else, which means it must be closed. * rgerhards, 2008-03-01 */ static rsRetVal DataRcvd(strms_sess_t *pThis, char *pData, size_t iLen) { DEFiRet; char *pEnd; ISOBJ_TYPE_assert(pThis, strms_sess); assert(pData != NULL); assert(iLen > 0); /* We now copy the message to the session buffer. */ pEnd = pData + iLen; /* this is one off, which is intensional */ while(pData < pEnd) { CHKiRet(pThis->pSrv->OnCharRcvd(pThis, (uchar)*pData++)); } finalize_it: RETiRet; } /* queryInterface function * rgerhards, 2008-02-29 */ BEGINobjQueryInterface(strms_sess) CODESTARTobjQueryInterface(strms_sess) if(pIf->ifVersion != strms_sessCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->DebugPrint = strms_sessDebugPrint; pIf->Construct = strms_sessConstruct; pIf->ConstructFinalize = strms_sessConstructFinalize; pIf->Destruct = strms_sessDestruct; pIf->Close = Close; pIf->DataRcvd = DataRcvd; pIf->SetUsrP = SetUsrP; pIf->GetUsrP = GetUsrP; pIf->SetStrmsrv = SetStrmsrv; pIf->SetLstnInfo = SetLstnInfo; pIf->SetHost = SetHost; pIf->SetHostIP = SetHostIP; pIf->SetStrm = SetStrm; finalize_it: ENDobjQueryInterface(strms_sess) /* exit our class * rgerhards, 2008-03-10 */ BEGINObjClassExit(strms_sess, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(strms_sess) /* release objects we no longer need */ objRelease(errmsg, CORE_COMPONENT); objRelease(netstrm, LM_NETSTRMS_FILENAME); objRelease(datetime, CORE_COMPONENT); ENDObjClassExit(strms_sess) /* Initialize our class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-29 */ BEGINObjClassInit(strms_sess, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */ /* request objects we use */ CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); iMaxLine = glbl.GetMaxLine(); /* get maximum size we currently support */ objRelease(glbl, CORE_COMPONENT); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, strms_sessDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, strms_sessConstructFinalize); ENDObjClassInit(strms_sess) /* vim:set ai: */