"Fossies" - the Fresh Open Source Software Archive

Member "muscle/minimessage/MiniMessageGateway.c" (28 Nov 2019, 7673 Bytes) of package /linux/privat/muscle7.52.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "MiniMessageGateway.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 7.13_vs_7.20.

    1 #include <string.h>  // for memcpy()
    2 #include "minimessage/MiniMessageGateway.h"
    3 
    4 #ifdef __cplusplus
    5 extern "C" {
    6 #endif
    7 
    8 struct _MMessageGateway {
    9    MByteBuffer * _curInput;   /* We receive data into this buffer           */
   10    MByteBuffer * _curOutput;  /* The head of our output-buffers linked list */
   11    MByteBuffer * _outputTail; /* The tail of our output-buffers linked list */ 
   12    uint32 _curInputPos;       /* Index of next byte to receive in _curInput */
   13    uint32 _maxInputPos;       /* Index of last byte to receive in _curInput */
   14    uint32 _curOutputPos;      /* Index of next byte to send in _curOutput   */
   15 };
   16 
   17 static inline MByteBuffer * GetNextPointer(const MByteBuffer * buf)
   18 {
   19    return *((MByteBuffer **)(&buf->bytes));
   20 }
   21 
   22 static inline void SetNextPointer(MByteBuffer * buf, const MByteBuffer * next)
   23 {
   24    *((const MByteBuffer **)(&buf->bytes)) = next;
   25 }
   26 
   27 MMessageGateway * MGAllocMessageGateway()
   28 {
   29    MMessageGateway * ret = MMalloc(sizeof(MMessageGateway));
   30    if (ret)
   31    {
   32       ret->_outputTail   = NULL;
   33       ret->_curInputPos  = 0;                        /* input buffer doesn't have a next pointer */
   34       ret->_curOutputPos = sizeof(MByteBuffer *); /* start sending after the next pointer */
   35       ret->_maxInputPos  = (2*sizeof(uint32));       /* start by reading the fixed-size header fields */
   36       ret->_curOutput    = NULL;
   37       ret->_curInput     = MBAllocByteBuffer(ret->_maxInputPos, false);
   38       if (ret->_curInput == NULL)
   39       {
   40          MFree(ret);
   41          ret = NULL;
   42       }
   43    }
   44    return ret;
   45 }
   46 
   47 void MGFreeMessageGateway(MMessageGateway * gw)
   48 {
   49    if (gw)
   50    {
   51       MBFreeByteBuffer(gw->_curInput);
   52       while(gw->_curOutput)
   53       {
   54          MByteBuffer * next = GetNextPointer(gw->_curOutput);
   55          MBFreeByteBuffer(gw->_curOutput);
   56          gw->_curOutput = next;
   57       }
   58       MFree(gw);
   59    }
   60 }
   61 
   62 static const uint32 _MUSCLE_MESSAGE_ENCODING_DEFAULT = 1164862256; /* 'Enc0' -- vanilla encoding */
   63 
   64 c_status_t MGAddOutgoingMessage(MMessageGateway * gw, const MMessage * msg)
   65 {
   66    const uint32 flatSize = MMGetFlattenedSize(msg);
   67    MByteBuffer * buf = MBAllocByteBuffer(sizeof(MMessage *) + (2*sizeof(uint32)) + flatSize, false);
   68    if (buf) 
   69    {
   70       uint32 * h = (uint32 *)(((MMessage **)(&buf->bytes))+1);
   71 
   72       SetNextPointer(buf, NULL);
   73       h[0] = B_HOST_TO_LENDIAN_INT32(flatSize);
   74       h[1] = B_HOST_TO_LENDIAN_INT32(_MUSCLE_MESSAGE_ENCODING_DEFAULT);
   75       MMFlattenMessage(msg, (uint8 *) &h[2]);
   76 
   77       if (gw->_outputTail)
   78       {
   79          SetNextPointer(gw->_outputTail, buf);
   80          gw->_outputTail = buf;
   81       }
   82       else gw->_curOutput = gw->_outputTail = buf;
   83        
   84       return CB_NO_ERROR;
   85    }
   86    else return CB_ERROR;
   87 }
   88 
   89 MBool MGHasBytesToOutput(const MMessageGateway * gw)
   90 {
   91    return (gw->_curOutput != NULL);
   92 }
   93 
   94 int32 MGDoOutput(MMessageGateway * gw, uint32 maxBytes, MGSendFunc sendFunc, void * arg)
   95 {
   96    int32 totalSent = 0;
   97    while(gw->_curOutput != NULL)
   98    {
   99       int32 bytesSent;
  100 
  101       uint32 bytesToSend = gw->_curOutput->numBytes - gw->_curOutputPos;
  102       if (bytesToSend > maxBytes) bytesToSend = maxBytes;
  103       
  104       bytesSent = sendFunc((&gw->_curOutput->bytes)+(gw->_curOutputPos), bytesToSend, arg);
  105       if (bytesSent < 0) return -1;  /* error! */
  106       else
  107       {
  108          totalSent += bytesSent;
  109          maxBytes  -= bytesSent;
  110          gw->_curOutputPos += bytesSent;
  111          if (gw->_curOutputPos == gw->_curOutput->numBytes)
  112          {
  113             MByteBuffer * next = GetNextPointer(gw->_curOutput);
  114             if (next == NULL) gw->_outputTail = NULL;
  115             MBFreeByteBuffer(gw->_curOutput);
  116             gw->_curOutput = next;
  117             gw->_curOutputPos = sizeof(MByteBuffer *);  /* send all data after the next-pointer */
  118          }
  119       }
  120       if (bytesSent < bytesToSend) break;  /* short write indicates that the output buffer is full for now */
  121    }
  122    return totalSent;
  123 }
  124 
  125 int32 MGDoInput(MMessageGateway * gw, uint32 maxBytes, MGReceiveFunc recvFunc, void * arg, MMessage ** optRetMsg)
  126 {
  127    int32 totalRecvd = 0;
  128 
  129    if (optRetMsg) *optRetMsg = NULL;
  130    while(true) 
  131    {
  132       int32 bytesReceived;
  133       uint32 bytesToRecv = gw->_maxInputPos - gw->_curInputPos;
  134       if (bytesToRecv > maxBytes) bytesToRecv = maxBytes;
  135 
  136       bytesReceived = recvFunc((&gw->_curInput->bytes)+gw->_curInputPos, bytesToRecv, arg);
  137       if (bytesReceived < 0) return -1;  /* error */
  138       else
  139       {
  140          totalRecvd += bytesReceived;
  141          maxBytes   -= bytesReceived;
  142          gw->_curInputPos += bytesReceived;
  143          if (gw->_curInputPos == gw->_maxInputPos)
  144          {
  145             if (gw->_curInputPos > (2*sizeof(uint32)))
  146             {
  147                /* We have received the Message body and we are ready to unflatten! */
  148                MMessage * msg = MMAllocMessage(0);
  149                if (msg == NULL) return -1;  /* out of memory */
  150 
  151                if (MMUnflattenMessage(msg, (&gw->_curInput->bytes)+(2*sizeof(uint32)), gw->_maxInputPos-(2*sizeof(uint32))) == CB_NO_ERROR)
  152                {
  153                   /* set parser up for the next go-round */
  154                   gw->_curInputPos = 0;
  155                   gw->_maxInputPos = 2*(sizeof(uint32));
  156 
  157                   /* For input buffers over 64KB, it's better to reclaim the extra space than avoid reallocating */
  158                   if (gw->_curInput->numBytes > 64*1024)
  159                   {
  160                      MByteBuffer * smallBuf = MBAllocByteBuffer(64*1024, false);
  161                      if (smallBuf == NULL) 
  162                      {
  163                         MMFreeMessage(msg);
  164                         return -1;
  165                      }
  166 
  167                      MBFreeByteBuffer(gw->_curInput);
  168                      gw->_curInput = smallBuf;
  169                   }
  170 
  171                   if (optRetMsg)
  172                   {
  173                      *optRetMsg = msg;
  174                      break;  /* If we have a Message for the user, return it to him now */
  175                   }
  176                   else MMFreeMessage(msg);  /* User doesn't want it, so just throw it away */
  177                }
  178                else
  179                {
  180                   MMFreeMessage(msg);
  181                   return -1;   /* parse error! */
  182                }
  183             }
  184             else
  185             {
  186                /* We have our fixed-size headers, now prepare to receive the actual Message body! */
  187                const uint32 * h = (const uint32 *)(&gw->_curInput->bytes);
  188                uint32 bodySize = B_LENDIAN_TO_HOST_INT32(h[0]);
  189                if ((bodySize == 0)||(B_LENDIAN_TO_HOST_INT32(h[1]) != _MUSCLE_MESSAGE_ENCODING_DEFAULT)) return -1;  /* unsupported encoding! */
  190 
  191                bodySize += (2*sizeof(uint32));  /* we'll include the fixed headers in our body buffer too */
  192                if (bodySize > gw->_curInput->numBytes)
  193                {
  194                   /** Gotta trade up for a larger buffer, so that all our data will fit! */
  195                   MByteBuffer * bigBuf = MBAllocByteBuffer(2*bodySize, false);  /* might as well alloc some extra space too */
  196                   if (bigBuf == NULL) return -1;  /* out of memory! */
  197 
  198                   memcpy(&bigBuf->bytes, &gw->_curInput->bytes, gw->_curInputPos);  /* not strictly necessary, but for form's sake... */
  199                   MBFreeByteBuffer(gw->_curInput);  /* dispose of the too-small old input buffer */
  200                   gw->_curInput = bigBuf;
  201                }
  202                gw->_maxInputPos = bodySize;
  203             }
  204          }
  205       }
  206       if (bytesReceived < bytesToRecv) break;  /* short read indicates that the input buffer is empty for now */
  207    }
  208    return totalRecvd;
  209 }
  210 
  211 #ifdef __cplusplus
  212 };
  213 #endif