/*! \file beepframe.h * \brief The BEEP frame object * * \note There are frames not belonging to messages! Curently, * this is the case for SEQ frames defined in RFC 3081. * * \author Rainer Gerhards * \date 2003-08-04 * * 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_BEEPFRAME_H_INCLUDED__ #define __LIB3195_BEEPFRAME_H_INCLUDED__ 1 #include "beepmessage.h" #include "beepchannel.h" #define sbFramCHECKVALIDOBJECT(x) {assert(x != NULL); assert(x->OID == OIDsbFram);} /** Session status */ enum sbFramState_ { /* RX flags */ sbFRAMSTATE_WAITING_HDR1, /**< waiting for the first HDR character */ sbFRAMSTATE_WAITING_HDR2, /**< waiting for the second HDR character */ sbFRAMSTATE_WAITING_HDR3, /**< waiting for the third HDR character */ sbFRAMSTATE_WAITING_SP_CHAN,/**< waiting for the SP before channo */ sbFRAMSTATE_IN_CHAN, /**< reading channo */ sbFRAMSTATE_WAITING_SP_MSGNO,/**< now the space before the next header */ sbFRAMSTATE_IN_MSGNO, /**< and the next (numeric) header */ sbFRAMSTATE_WAITING_SP_MORE,/**< now the space before the next header */ sbFRAMSTATE_IN_MORE, /**< and the next (char) header */ sbFRAMSTATE_WAITING_SP_SEQNO,/**< now the space before the next header */ sbFRAMSTATE_IN_SEQNO, /**< and the next (numeric) header */ sbFRAMSTATE_WAITING_SP_SIZE,/**< now the space before the next header */ sbFRAMSTATE_IN_SIZE, /**< and the next (numeric) header */ sbFRAMSTATE_WAITING_SP_ANSNO,/**< now the space before the next header */ sbFRAMSTATE_IN_ANSNO, /**< and the next (numeric) header */ sbFRAMSTATE_WAITING_SP_ACKNO,/**< now the space before the next header */ sbFRAMSTATE_IN_ACKNO, /**< and the next (char) header */ sbFRAMSTATE_WAITING_SP_WINDOW,/**< now the space before the next header */ sbFRAMSTATE_IN_WINDOW, /**< and the next (numeric) header */ sbFRAMSTATE_WAITING_HDRCR, /**< awaiting the HDR's CR */ sbFRAMSTATE_WAITING_HDRLF, /**< awaiting the HDR's LF */ sbFRAMSTATE_IN_PAYLOAD, /**< reading payload area */ sbFRAMSTATE_WAITING_END1, /**< waiting for the 1st HDR character */ sbFRAMSTATE_WAITING_END2, /**< waiting for the 2nd HDR character */ sbFRAMSTATE_WAITING_END3, /**< waiting for the 3rd HDR character */ sbFRAMSTATE_WAITING_END4, /**< waiting for the 4th HDR character */ sbFRAMSTATE_WAITING_END5, /**< waiting for the 5th HDR character */ sbFRAMSTATE_RECEIVED, /**< frame is fully received and ready for processing*/ /* TX flags */ sbFRAMSTATE_BEING_BUILD, /**< frame is currently being constructed */ sbFRAMSTATE_READY_TO_SEND, /**< frame is constructed and ready to send */ sbFRAMSTATE_SENDING, /**< frame is currently being send */ sbFRAMSTATE_SENT, /**< frame has been send and can be discarded */ sbFRAMSTATE_UNKNOWN = 0 /**< should never happen. Set after initialization. */ }; typedef enum sbFramState_ sbFramState; struct sbFramObject /** The BEEP frame object. Implemented via \ref beepframe.h and * \ref beepframe.c. */ { srObjID OID; /**< Object ID - to make code (more ;)) bulletproof */ struct sMesgObject* pMsg; /**< pointer to the message this frame belongs to. May be NULL * if the frame does NOT belong to a message (SEQ frame!) */ sbFramState iState; /**< status of this frame */ char* szRawBuf; /**< pointer to the complete frame text */ int iFrameLen; /**< size (in Bytes) of the complete frame */ BEEPHdrID idHdr; /**< the header id of this frame */ SBackno uAckno; /**< RFC 3081 ackno */ SBwindow uWindow; /**< RFC 3081 window */ SBchannel uChannel; /**< RFC 3080 channel */ SBmsgno uMsgno; /**< RFC 3080 msgno */ SBseqno uSeqno; /**< RFC 3080 seqno */ SBsize uSize; /**< RFC 3080 size */ char cMore; /**< RFC 3080 more */ SBansno uAnsno; /**< RFC 3080 ansno */ #if FEATURE_LISTENER == 1 unsigned uBytesSend; /**< number of bytes already send */ struct sbChanObject *pChan; /**< channel to send over (shortcut to save performance) */ struct sbStrBObject *pStrBuf;/**< work buffer for receiving frames */ unsigned uToReceive; /**< number of payload characters (still) to be recieved */ void (*OnFramDestroy)(struct sbFramObject*); /**< callback to be called when frame is destroyed */ void* pUsr; /**< user pointer to be passed to callback OnFramDestroy() */ #endif }; typedef struct sbFramObject sbFramObj; char* sbFramGetFrame(sbFramObj* pThis); /**< return frame content */ int sbFramGetFrameLen(sbFramObj* pThis); /**< return length of frame */ BEEPHdrID sbFramGetHdrID(sbFramObj *pThis); /**< Returns the header id of this BEEP frame. */ srRetVal sbFramDestroy(sbFramObj *pThis); /**< destroy a frame object */ /** Create a frame from a Message. * With the current implementation, there is * a one-to-one relationship between fram and mesg, so * this is faily simple ;) * * \param pChan [in/out] Channel object that this frame * will be sent on. Is updated with new SEQ number. * * \param pMesg [in] Pointer to the Mesg to be converted. This * buffer must not be modified by Mesg after * CreateFramFromMesg has been called! * * \param pszCmd [in] HDR-Command ("ANS", "MSG", ...) to be used. * * \param uAnso [in] if the HDR-Command is "ANS", this is the ansno * to be used. Ignored with any other HDR-Command. * * \retval Pointer to a newly created Frame object or NULL if * an error occured. */ sbFramObj* sbFramCreateFramFromMesg(sbChanObj* pChan, sbMesgObj* pMesg, char* pszCmd, SBansno uAnsno); /** * Actually receive a frame off the tcp stream. * Be sure to read \ref architecture.c for a full * explanation of what ActualRecvFram and its associated * methods do in an overall context. * * In detail, it receives a frame off the wire and * returns the resulting farme object to its caller. * It detects different frame formats (like SEQ frames). * * This is a BLOCKING method call. It blocks until the * frame is complete or a timeout occurs. * * \param pSess pointer to session object. This session * is to be used to receive the frame. * * \retval pointer to the received frame object or * NULL, if an error occured. */ sbFramObj* sbFramActualRecvFram(sbSessObj *pSess); /** * Logically receive a frame. This method uses the session object * to do the physical receive. See \ref architecture.c for a * full description of this interaction. * * This is just a slim wrapper to hide the implementation details. * * \param pChan [in/out] associated channel * \retval pointer to new frame object or NULL, if in error. */ sbFramObj* sbFramRecvFram(sbChanObj* pChan); /** * Send a frame on a channel (logical). This method does * not directly put the data on the wire but calls the * session object to initiate this. This sequence allows * for limited multiprocessing inside the stack. Please * see \ref architecture.c for a full description. * * This is just a very thin layer in this release. * * \param pChan the associated channel (where the frame * is to be sent). */ srRetVal sbFramSendFram(sbFramObj* pThis, sbChanObj*pChan); /** * Get the header ID for a given BEEP command header. This * is implemented in the sbFram object as sbFram ultimately * creaetes the frames and thus the IDs. One could argue * if a better place would be some util helper... * * \param psz [in] pointer to a BEEP header command ("MSG", ...) * \retval matching header id */ BEEPHdrID sbFramHdrID(char* szCmd); /** * Construct a frame. This builds the memory structure, only * but does not do anything to actually populate it. */ srRetVal sbFramConstruct(sbFramObj **ppThis); /** * Construct a SEQ frame for a given channel with a * given ackno. * * \param pChan Channel this SEQ is for. * \param uAckno ackno to use in the SEQ. Can not be 0. * \param uWindow Window to use in the SEQ. If 0, use BEEP default. */ srRetVal sbFramCreateSEQFram(sbFramObj **ppThis, sbChanObj* pChan, SBackno uAckno, SBwindow uWindow); /** * Register a callback handler to be called when the frame is sent and ready * to be destroyed. If there was already a handler set, it is REPLACED * with the new one. There is no "calling-queue" of multiple handlers. * * \param OnFramDestroy Pointer to Callback. Must not be NULL. * \param Pointer to user pointer (may be NULL) */ srRetVal sbFramSetOnDestroyEvent(sbFramObj *pThis, void (*OnFramDestroy)(struct sbFramObject *), void *pUsr); #endif