diff --git a/src/ca/comQueSend.cpp b/src/ca/comQueSend.cpp index be0949c23..32422b93c 100644 --- a/src/ca/comQueSend.cpp +++ b/src/ca/comQueSend.cpp @@ -64,6 +64,13 @@ #include "virtualCircuit.h" #include "db_access.h" // for dbr_short_t etc +// nill message alignment pad bytes +const char cacNillBytes [] = +{ + 0, 0, 0, 0, + 0, 0, 0, 0 +}; + comQueSend::comQueSend ( wireSendAdapter & wireIn ) : wire ( wireIn ), nBytesPending ( 0u ) { @@ -102,32 +109,32 @@ void comQueSend::clearUncommitted () void comQueSend::copy_dbr_string ( const void *pValue, unsigned nElem ) { - this->copyIn ( static_cast ( pValue ), nElem ); + this->push ( static_cast ( pValue ), nElem ); } void comQueSend::copy_dbr_short ( const void *pValue, unsigned nElem ) { - this->copyIn ( static_cast ( pValue ), nElem ); + this->push ( static_cast ( pValue ), nElem ); } void comQueSend::copy_dbr_float ( const void *pValue, unsigned nElem ) { - this->copyIn ( static_cast ( pValue ), nElem ); + this->push ( static_cast ( pValue ), nElem ); } void comQueSend::copy_dbr_char ( const void *pValue, unsigned nElem ) { - this->copyIn ( static_cast ( pValue ), nElem ); + this->push ( static_cast ( pValue ), nElem ); } void comQueSend::copy_dbr_long ( const void *pValue, unsigned nElem ) { - this->copyIn ( static_cast ( pValue ), nElem ); + this->push ( static_cast ( pValue ), nElem ); } void comQueSend::copy_dbr_double ( const void *pValue, unsigned nElem ) { - this->copyIn ( static_cast ( pValue ), nElem ); + this->push ( static_cast ( pValue ), nElem ); } const comQueSend::copyFunc_t comQueSend::dbrCopyVector [39] = { @@ -198,3 +205,90 @@ void comQueRecv::popString ( epicsOldString *pStr ) pStr[0][i] = this->popInt8 (); } } + +void comQueSend::commitMsg () +{ + while ( this->pFirstUncommited.valid() ) { + this->nBytesPending += this->pFirstUncommited->uncommittedBytes (); + this->pFirstUncommited->commitIncomming (); + this->pFirstUncommited++; + } +} + +void comQueSend::insertRequestHeader ( + ca_uint16_t request, ca_uint32_t payloadSize, + ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, + ca_uint32_t requestDependent, bool v49Ok ) +{ + this->beginMsg (); + if ( payloadSize < 0xffff && nElem < 0xffff ) { + this->pushUInt16 ( request ); + this->pushUInt16 ( static_cast < ca_uint16_t > ( payloadSize ) ); + this->pushUInt16 ( dataType ); + this->pushUInt16 ( static_cast < ca_uint16_t > ( nElem ) ); + this->pushUInt32 ( cid ); + this->pushUInt32 ( requestDependent ); + } + else if ( v49Ok ) { + this->pushUInt16 ( request ); + this->pushUInt16 ( 0xffff ); + this->pushUInt16 ( dataType ); + this->pushUInt16 ( 0u ); + this->pushUInt32 ( cid ); + this->pushUInt32 ( requestDependent ); + this->pushUInt32 ( payloadSize ); + this->pushUInt32 ( nElem ); + } + else { + throw cacChannel::outOfBounds (); + } +} + +void comQueSend::insertRequestWithPayLoad ( + ca_uint16_t request, unsigned dataType, ca_uint32_t nElem, + ca_uint32_t cid, ca_uint32_t requestDependent, const void * pPayload, + bool v49Ok ) +{ + if ( ! this->dbr_type_ok ( dataType ) ) { + throw cacChannel::badType(); + } + ca_uint32_t size; + bool stringOptim; + if ( dataType == DBR_STRING && nElem == 1 ) { + const char *pStr = static_cast < const char * > ( pPayload ); + size = strlen ( pStr ) + 1u; + if ( size > MAX_STRING_SIZE ) { + throw cacChannel::outOfBounds(); + } + stringOptim = true; + } + else { + unsigned maxBytes; + if ( v49Ok ) { + maxBytes = 0xffffffff; + } + else { + maxBytes = MAX_TCP - 16u; // allow space for protocol header + } + unsigned maxElem = ( maxBytes - dbr_size[dataType] ) / dbr_value_size[dataType]; + if ( nElem >= maxElem ) { + throw cacChannel::outOfBounds(); + } + size = dbr_size_n ( dataType, nElem ); + stringOptim = false; + } + ca_uint32_t payloadSize = CA_MESSAGE_ALIGN ( size ); + this->insertRequestHeader ( request, payloadSize, + static_cast ( dataType ), + nElem, cid, requestDependent, v49Ok ); + if ( stringOptim ) { + this->pushString ( static_cast < const char * > ( pPayload ), size ); + } + else { + this->push_dbr_type ( dataType, pPayload, nElem ); + } + // set pad bytes to nill + this->pushString ( cacNillBytes, payloadSize - size ); + this->commitMsg (); +} + diff --git a/src/ca/comQueSend.h b/src/ca/comQueSend.h index 147b8a836..7f294cd5f 100644 --- a/src/ca/comQueSend.h +++ b/src/ca/comQueSend.h @@ -44,6 +44,14 @@ public: void pushUInt32 ( const ca_uint32_t value ); void pushFloat32 ( const ca_float32_t value ); void pushString ( const char *pVal, unsigned nChar ); + void insertRequestHeader ( + ca_uint16_t request, ca_uint32_t payloadSize, + ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, + ca_uint32_t requestDependent, bool v49Ok ); + void insertRequestWithPayLoad ( + ca_uint16_t request, unsigned dataType, ca_uint32_t nElem, + ca_uint32_t cid, ca_uint32_t requestDependent, const void * pPayload, + bool v49Ok ); void push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ); comBuf * popNextComBufToSend (); private: @@ -68,19 +76,19 @@ private: // class member template function definition // template < class T > - inline void copyIn ( const T *pVal, const unsigned nElem ) + inline void push ( const T *pVal, const unsigned nElem ) { comBuf * pLastBuf = this->bufs.last (); unsigned nCopied; if ( pLastBuf ) { - nCopied = pLastBuf->copyIn ( pVal, nElem ); + nCopied = pLastBuf->push ( pVal, nElem ); } else { nCopied = 0u; } while ( nElem > nCopied ) { comBuf * pComBuf = new comBuf; - unsigned nNew = pComBuf->copyIn ( &pVal[nCopied], nElem - nCopied ); + unsigned nNew = pComBuf->push ( &pVal[nCopied], nElem - nCopied ); nCopied += nNew; this->bufs.add ( *pComBuf ); if ( ! this->pFirstUncommited.valid() ) { @@ -94,26 +102,27 @@ private: // class member template function definition // template < class T > - inline void copyIn ( const T &val ) + inline void push ( const T & val ) { - comBuf *pComBuf = this->bufs.last (); + comBuf * pComBuf = this->bufs.last (); if ( pComBuf ) { - if ( pComBuf->copyIn ( &val, 1u ) >= 1u ) { + if ( pComBuf->push ( val ) ) { return; } } pComBuf = new comBuf; - assert ( pComBuf->copyIn ( &val, 1u ) == 1u ); + assert ( pComBuf->push ( val ) ); this->bufs.add ( *pComBuf ); if ( ! this->pFirstUncommited.valid() ) { this->pFirstUncommited = this->bufs.lastIter (); } - return; } comQueSend ( const comQueSend & ); comQueSend & operator = ( const comQueSend & ); }; +extern const char cacNillBytes[]; + inline bool comQueSend::dbr_type_ok ( unsigned type ) { if ( type >= ( sizeof ( this->dbrCopyVector ) / sizeof ( this->dbrCopyVector[0] ) ) ) { @@ -127,22 +136,22 @@ inline bool comQueSend::dbr_type_ok ( unsigned type ) inline void comQueSend::pushUInt16 ( const ca_uint16_t value ) { - this->copyIn ( value ); + this->push ( value ); } inline void comQueSend::pushUInt32 ( const ca_uint32_t value ) { - this->copyIn ( value ); + this->push ( value ); } inline void comQueSend::pushFloat32 ( const ca_float32_t value ) { - this->copyIn ( value ); + this->push ( value ); } inline void comQueSend::pushString ( const char *pVal, unsigned nChar ) { - this->copyIn ( pVal, nChar ); + this->push ( pVal, nChar ); } // it is assumed that dbr_type_ok() was called prior to calling this routine @@ -175,13 +184,4 @@ inline void comQueSend::beginMsg () this->pFirstUncommited = this->bufs.lastIter (); } -inline void comQueSend::commitMsg () -{ - while ( this->pFirstUncommited.valid() ) { - this->nBytesPending += this->pFirstUncommited->uncommittedBytes (); - this->pFirstUncommited->commitIncomming (); - this->pFirstUncommited++; - } -} - #endif // ifndef comQueSendh