/*! \file beepsession.h * \brief The BEEP Session Object * * \note The current implementation only supports 2 channels - * the control channel plus 1 payload channel. * * \author Rainer Gerhards * \date 2003-08-04 * 0.1 version created. * * \date 2003-08-07 * name value list for channnels added. * * Copyright 2002-2003 * Rainer Gerhards and Adiscon GmbH. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * * Neither the name of Adiscon GmbH or Rainer Gerhards * nor the names of its contributors may be used to * endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __LIB3195_BEEPSESSION_H_INCLUDED__ #define __LIB3195_BEEPSESSION_H_INCLUDED__ 1 #define sbSessCHECKVALIDOBJECT(x) {assert((x) != NULL); assert((x)->OID == OIDsbSess);} struct sbMesgObject; #include "beepchannel.h" #include "beepprofile.h" #if FEATURE_LISTENER == 1 /** Session status */ enum sbSessState_ { sbSESSSTATE_OPEN, sbSESSSTATE_CLOSED, /**< session is closed and ready to be removed from ** whatever queues it is in. **/ sbSESSSTATE_UNKNOWN = 0 /**< should never happen. Set after initialization. */ }; typedef enum sbSessState_ sbSessState; enum sbSessTXState_ { sbSESSTXSTATE_NO_TX_PENDING, /**< no transmit pending */ sbSESSTXSTATE_IN_TX, /**< data is currently being send */ sbSESSTXSTATE_UNKNOWN = 0 /**< should never happen. Set after initialization. */ }; typedef enum sbSessTXState_ sbSessTXState; #endif struct sbChanObject; struct sbChanObject; struct sbFramObject; struct sbNVTRObject; struct sbSessObject /** The session object. Implemented via \ref beepsession.h and * \ref beepsession.c. */ { srObjID OID; /**< object ID */ srRetVal iLastErr; /**< last error occured */ struct sbSockObject *pSock; /**< underlying socket */ struct sbChanObject *pChan0; /**< the control channel. This is stored in a separate variable for ** performance reasons. It also has an entry in pChannels. */ struct sbNVTRObject *pChannels; /**< pointer to a name value list with the channels. */ struct sbNVTRObject* pRXQue; /**< receive frame queue */ struct sbNVTRObject *pRemoteProfiles; /**< linked list of profiles supported by remote peer. Constructed based on greeting. */ srRetVal (*SendFramMethod)(struct sbSessObject *, struct sbFramObject *, struct sbChanObject *); /**< method to be used for sending the frame. Is different for client and server implementations */ struct sbNVTRObject *pProfilesSupported;/**< the list of profiles supported at the time of session connection. */ #if FEATURE_LISTENER == 1 sbSessState iState; /**< this session's current status */ sbSessTXState iTXState; /**< session transmit status */ struct sbNVTRObject *pSendQue; /**< queue of data to be send */ struct sbFramObject *pRecvFrame; /**< frame currently being received */ int bNeedData; /**< TRUE = can NOT send, because data (SEQ frame) needs to arrive first */ #endif }; typedef struct sbSessObject sbSessObj; /** Open a BEEP session. * The initial greeting is sent and the remote peers initial greeting * is accepted. Channel 0 is initialized and brought into operation. * * \param pszRemotePeer name or IP address of the peer to connect to * \param iPort TCP port the remote peer is listening to * \retval pointer to the new session object or NULL, if an error * occured. */ sbSessObj* sbSessOpenSession(char* pszRemotePeer, int iPort, struct sbNVTRObject *pProfSupported); srRetVal sbSessCloseSession(sbSessObj *pThis); /* The following three macros could also be inline code. * For now, I have kept them to be macros to make * facilitate porting. */ /** Getthe last error for this module */ #define sbSessGetLastError(pThis) pThis->iLastErr /** Set the last error for this module */ #define sbSessSetLastError(pThis, iRet) pThis->iLastErr = iRet /** reset the last error for this module */ #define sbSessResetLastError(pThis) pThis->iLastErr = SR_RET_OK /** * Retrieve the channel object associated with the channel number. * This method allows to retrieve a channel number based on the * actual channel. * * \param uChanNo channel number * \retval pointer to channel object or NULL, if uChanNo could * not be found. */ struct sbChanObject* sbSessRetrChanObj(sbSessObj *pThis, SBchannel uChanNo); /** * Receive a frame for a specified channel from the tcp stream. * This method handles intermixed frames from other channels. It * calls back into the frame object to do the actual frame read * (if no frame is buffered). * * See \ref architecture.c for a full description. * * \param pChan the associated channel * \retval pointer to the new frame object or NULL, if an error * occured. */ struct sbFramObject* sbSessRecvFram(sbSessObj* pThis, struct sbChanObject *pChan); /** * Open a BEEP channel on an established session. * The method carries out all channel 0 management functions * to open up a new channel. * * When the method returns without error, the channel is ready * for data transmission. If the remote peer send a (profile payload) * frame as part of the channel creation, this frame is probably * available for retrieval. * * \param pProfsSupported [in] pointer to the profile supporeted for this session. */ struct sbChanObject* sbSessOpenChan(sbSessObj* pThis); /** * Close a channel. * This is a very partial implementation of RFC 3080. For syslog-raw, * I honestly and strongly beliefe it works. However, there may be * implementations of syslog raw where it will not work or at least * not work fully correctly. * * \todo This method (and some of the plumbing behind) must be * updated to be fully compliant to RFC 3080. * * Issues are: * - we do not expect other messages to come in during the * session * - if the remote peer closes the session before us, we * may be in trouble * * \param pChan [in] Channel to be closed. Will be destroyed * at the end of the execution and thus can * no longer be used after this method call! */ srRetVal sbSessCloseChan(sbSessObj *pThis, struct sbChanObject *pChan); /** * Closes the BEEP session. First, the management channel (channel 0) * is taken down and then the TCP stream is closed. * This function can only be called after all sessions have been closed. * Once the function returns, the session object is no longer valid * and can no longer be used. */ srRetVal sbSessCloseSession(sbSessObj *pThis); /** * Receive frames off the tcp stream. SEQ frames * are processed as they arrive. Other frames are * buffered in the respective in-memory queue. This is * a helper to sbSessRecvFram() and sbSessSendFram(). * * \param bMustRcvPayloadFrame A boolean indicating if an * actual payload frame must be received. If set to * TRUE, the method blocks until a payload frame is * received. All interim SEQ frames are processed, but * will not make this method to return. * If FALSE, the method will block until anything is received, * including a SEQ. If a SEQ is received, it will be processed * and the method returns. */ srRetVal sbSessDoReceive(sbSessObj *pThis, int bMustRcvPayloadFrame); /** * Send the provided frame on the provided channel. While sending, * concurrently incoming frames are buffered and SEQ frames are * processed. This method blocks until pFram could be sent (this * means it may need to wait for the proper SEQ frame). * * See \ref architecture.c for full details on how this * method "drives the BEEP stack". * * \param pFram [in] frame to be send * \param pChan [in] channel where pFram is to be sent over */ srRetVal sbSessSendFram(sbSessObj *pThis, struct sbFramObject *pFram, struct sbChanObject *pChan); /** Destructor. pThis is invalid * when this function returns. The caller can no longer use * it. The caller is also not allowed to free it - this is * already done in this method. */ void sbSessDestroy(sbSessObj *pThis); /** * Open a BEEP session. This method is called * if a REMOTE peer requests an session open. As such, * it does only the most pressing initialization work and * then returns back to the caller. */ srRetVal sbSessRemoteOpen(sbSessObj **pThis, sbSockObj *pSock, struct sbNVTRObject *pProfSupported); /** * Close a session without any further communication. Can * be used to abort a connection if * - the remote peer broke it * - we have a protocol error and we need to break it * * This method is void, because it *must* complete, no matter * which errors it encounters. Furthermore, it is primarily * intended to be called from destructors which are also void. * Consider it to be an extended desctrutor. */ void sbSessAbort(sbSessObj *pThis); /** * Process the remote peer's greeting message. Most importantly, * the list of profiles is extracted and stored in the session * object. * * \param pMesg The message containing the Greeting. Must not be NULL. */ srRetVal sbSessProcessGreeting(struct sbSessObject *pThis, struct sbMesgObject *pMesg); /** * Send a greeting message based on the currently registered * profiles. * * We generate the greeting via a simple stringbuf, not with * an XML parser. This saves execution time and is as good * as the XML thing... * * \param pProfsSupported Pointer to a linked list of supported * profiles (which should be specified in the greeting. */ srRetVal sbSessSendGreeting(struct sbSessObject* pSess, struct sbNVTRObject *pProfsSupported); #endif