/**
 * Decode the received message flatbuffer and ensure messages are processed in
 * order
 *
 * @param eventData
 * @param rawbuf
 * @param receivedDataStats
 */
void NexusSubscriber::decodeMessage(
    std::shared_ptr<EventData> eventData, const std::string &rawbuf,
    std::shared_ptr<ReceivedDataStats> receivedDataStats) {
  // if the message is in order or is the first message then go ahead and decode
  // it
  auto currentMessageID = getMessageID(rawbuf);
  if (currentMessageID == receivedDataStats->previousMessageID + 1 ||
      receivedDataStats->previousMessageID ==
          std::numeric_limits<uint64_t>::max()) {
    eventData->decodeMessage(reinterpret_cast<const uint8_t *>(rawbuf.c_str()));
    processMessage(eventData, rawbuf, receivedDataStats);
    receivedDataStats->previousMessageID = currentMessageID;

    // if this was a message in the map then remove it
    if (m_futureMessages.count(currentMessageID) > 0) {
      m_futureMessages.erase(currentMessageID);
    }

    // if the next messageID is a key in the map then decode it
    if (m_futureMessages.count(currentMessageID + 1) > 0) {
      decodeMessage(eventData, m_futureMessages[currentMessageID + 1],
                    receivedDataStats);
    }
  } else {
    // message is out of order so add it to map to go back to listening
    m_futureMessages[currentMessageID] = rawbuf;
  }
}
Exemple #2
0
int SendTextIMPacket::putContents(unsigned char *buf) 
{
	int pos=0;

	//multi-fragment information
	buf[pos++] = numFragments;
	buf[pos++] = seqFragments;
	memcpy(buf+pos, &messageID, 2);
	pos+=2;
	
	bool hasImage = false;
	std::string str2send = EvaUtil::convertToSend(message, &hasImage);

	buf[pos++] = hasImage?QQ_IM_IMAGE_REPLY:replyType; // auto-reply or not

	memcpy(buf+pos, str2send.c_str(), str2send.length());
	pos += str2send.length();

	if (getNumFragments() == (getSeqOfFragments() + 1))
	{
		buf[pos++] = 0x20; //  a space, witch is needed in the last fragment
		setMessageID(getMessageID() + 1);
	}
	buf[pos++] = 0x00;    //  C style string terminator
	
	buf[pos++] = fontFlag;
	buf[pos++] = red;
	buf[pos++] = green;
	buf[pos++] = blue;
	
	buf[pos++] = 0;
	
	short tmpEncoding = htons(encoding);  // encoding for text
	memcpy(buf+pos,&tmpEncoding, 2);
	pos+=2;
	
	int len = fontName.length();     // font name
	memcpy(buf+pos, fontName.c_str(), len);
        pos+=len;
 
	buf[pos++] = 0x0D;   // an Enter
	
	return pos;
}
void MessageQueueBase::removeRepetitions()
{
  ASSERT(!messageIndex);
  unsigned short messagesPerType[5][numOfMessageIDs];
  unsigned char numberOfProcesses = 0,
                processes[26],
                currentProcess = 0;

  memset(messagesPerType, 0, sizeof(messagesPerType));
  memset(processes, 255, sizeof(processes));
  selectedMessageForReadingPosition = 0;

  for(int i = 0; i < numberOfMessages; ++i)
  {
    if(getMessageID() == idProcessBegin)
    {
      unsigned char process = getData()[0] - 'a';
      if(processes[process] == 255)
        processes[process] = numberOfProcesses++;
      currentProcess = processes[process];
    }
    ++messagesPerType[currentProcess][getMessageID()];
    selectedMessageForReadingPosition += getMessageSize() + headerSize;
  }

  selectedMessageForReadingPosition = 0;
  usedSize = 0;
  int numOfDeleted = 0;
  int frameBegin = -1;
  bool frameEmpty = true;

  for(int i = 0; i < numberOfMessages; ++i)
  {
    int mlength = getMessageSize() + headerSize;
    bool copy;
    switch(getMessageID())
    {
      // accept up to 20 times, process id is not important
      case idText:
        copy = --messagesPerType[currentProcess][idText] <= 20;
        break;

      // accept always, process id is not important
      case idDebugRequest:
      case idDebugResponse:
      case idDebugDataResponse:
      case idPlot:
      case idConsole:
      case idAudioData:
      case idAnnotation:
      case idLogResponse:
        copy = true;
        break;

      // data only from latest frame
      case idStopwatch:
      case idDebugImage:
      case idDebugJPEGImage:
      case idDebugDrawing:
      case idDebugDrawing3D:
        copy = messagesPerType[currentProcess][idProcessFinished] == 1;
        break;

      // always accept, but may be reverted later
      case idProcessBegin:
        if(frameBegin != -1) // nothing between last idProcessBegin and this one, so remove idProcessBegin as well
        {
          usedSize = frameBegin;
          ++numOfDeleted;
        }
        currentProcess = processes[getData()[0] - 'a'];
        copy = true;
        break;

      case idProcessFinished:
        ASSERT(currentProcess == processes[getData()[0] - 'a']);
        copy = !frameEmpty; // nothing since last idProcessBegin or idProcessFinished, no new idProcessFinished required
        --messagesPerType[currentProcess][idProcessFinished];
        break;

      default:
        if(getMessageID() < numOfDataMessageIDs) // data only from latest frame
          copy = messagesPerType[currentProcess][idProcessFinished] == 1;
        else // only the latest other messages
          copy = --messagesPerType[currentProcess][getMessageID()] == 0;
    }

    if(copy)
    {
      // Remember position of begin of frame, but forget it, when another message was copied.
      // So idProcessBegin idProcessFinished+ will be removed.
      if(getMessageID() == idProcessBegin) // remember begin of frame
      {
        frameBegin = usedSize;
        frameEmpty = true; // assume next frame as empty
      }
      else if(getMessageID() == idProcessFinished)
        frameEmpty = true; // assume next frame as empty
      else // we copy a message within a frame so the idProcessBegin/Finished must stay
      {
        frameBegin = -1;
        frameEmpty = false;
      }

      //this message is important, it shall be copied
      if(usedSize != selectedMessageForReadingPosition)
        memmove(buf + usedSize, buf + selectedMessageForReadingPosition, mlength);
      usedSize += mlength;
    }
    else
      ++numOfDeleted;
    selectedMessageForReadingPosition += mlength;
  }
  numberOfMessages -= numOfDeleted;
  readPosition = 0;
  selectedMessageForReadingPosition = 0;
  lastMessage = 0;
}