blob: 338121ef5741c226707464dfa69628daa6f66275 [file]
/**
* Copyright (C) 2013 kangliqiang ,kangliq@163.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "MessageDecoder.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include "MessageExt.h"
#include "MessageSysFlag.h"
#include "UtilAll.h"
namespace rmq
{
const char MessageDecoder::NAME_VALUE_SEPARATOR = 1;
const char MessageDecoder::PROPERTY_SEPARATOR = 2;
const int MessageDecoder::MSG_ID_LENGTH = 8 + 8;
int MessageDecoder::MessageMagicCodePostion = 4;
int MessageDecoder::MessageFlagPostion = 16;
int MessageDecoder::MessagePhysicOffsetPostion = 28;
int MessageDecoder::MessageStoreTimestampPostion = 56;
std::string MessageDecoder::createMessageId(sockaddr& addr, long long offset)
{
struct sockaddr_in sa;
memcpy(&sa, &addr, sizeof(sockaddr));
sa.sin_family = AF_INET;
int port = ntohs(sa.sin_port);
port = htonl(port);
int ip = sa.sin_addr.s_addr;
unsigned char* buf = new unsigned char[MSG_ID_LENGTH];
offset = h2nll(offset);
memcpy(buf, &ip, 4);
memcpy(buf + 4, &port, 4);
memcpy(buf + 8, &offset, 8);
char* str = new char[2 * MSG_ID_LENGTH + 1];
memset(str, 0, 2 * MSG_ID_LENGTH + 1);
for (int i = 0; i < MSG_ID_LENGTH; i++)
{
char tmp[3];
tmp[2] = 0;
snprintf(tmp, sizeof(tmp), "%02X", buf[i]);
strncat(str, tmp, sizeof(tmp));
}
std::string ret = str;
delete[] buf;
delete[] str;
return ret;
}
MessageId MessageDecoder::decodeMessageId(const std::string& msgId)
{
std::string ipstr = msgId.substr(0, 8);
std::string portstr = msgId.substr(8, 8);
std::string offsetstr = msgId.substr(16);
char* end;
int ipint = strtoul(ipstr.c_str(), &end, 16);
int portint = strtoul(portstr.c_str(), &end, 16);
long long offset = UtilAll::hexstr2ull(offsetstr.c_str());
offset = n2hll(offset);
portint = ntohl(portint);
short port = portint;
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = ipint;
sockaddr addr;
memcpy(&addr, &sa, sizeof(sockaddr));
MessageId id(addr, offset);
return id;
}
MessageExt* MessageDecoder::decode(const char* pData, int len, int& offset)
{
return decode(pData, len, offset, true);
}
MessageExt* MessageDecoder::decode(const char* pData, int len, int& offset, bool readBody)
{
MessageExt* msgExt = NULL;
try
{
msgExt = new MessageExt();
// 1 TOTALSIZE
int storeSize;
memcpy(&storeSize, pData, 4);
storeSize = ntohl(storeSize);
msgExt->setStoreSize(storeSize);
// 2 MAGICCODE sizeof(int)
// 3 BODYCRC
int bodyCRC;
memcpy(&bodyCRC, pData + 2 * sizeof(int), 4);
bodyCRC = ntohl(bodyCRC);
msgExt->setBodyCRC(bodyCRC);
// 4 QUEUEID
int queueId;
memcpy(&queueId, pData + 3 * sizeof(int), 4);
queueId = ntohl(queueId);
msgExt->setQueueId(queueId);
// 5 FLAG
int flag ;
memcpy(&flag, pData + 4 * sizeof(int), 4);
flag = ntohl(flag);
msgExt->setFlag(flag);
// 6 QUEUEOFFSET
long long queueOffset;
memcpy(&queueOffset, pData + 5 * sizeof(int), 8);
queueOffset = n2hll(queueOffset);
msgExt->setQueueOffset(queueOffset);
// 7 PHYSICALOFFSET
long long physicOffset;
memcpy(&physicOffset, pData + 7 * sizeof(int), 8);
physicOffset = n2hll(physicOffset);
msgExt->setCommitLogOffset(physicOffset);
// 8 SYSFLAG
int sysFlag;
memcpy(&sysFlag, pData + 9 * sizeof(int), 4);
sysFlag = ntohl(sysFlag);
msgExt->setSysFlag(sysFlag);
// 9 BORNTIMESTAMP
long long bornTimeStamp;
memcpy(&bornTimeStamp, pData + 10 * sizeof(int), 8);
bornTimeStamp = n2hll(bornTimeStamp);
msgExt->setBornTimestamp(bornTimeStamp);
// 10 BORNHOST
int bornHost;//c0 a8 00 68 192.168.0.104 c0 a8 00 68 00 00 c4 04
memcpy(&bornHost, pData + 12 * sizeof(int), 4);
int port;
memcpy(&port, pData + 13 * sizeof(int), 4);
port = ntohl(port);
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = bornHost;
sockaddr bornAddr;
memcpy(&bornAddr, &sa, sizeof(sockaddr));
msgExt->setBornHost(bornAddr);
// 11 STORETIMESTAMP
long long storeTimestamp;
memcpy(&storeTimestamp, pData + 14 * sizeof(int), 8);
storeTimestamp = n2hll(storeTimestamp);
msgExt->setStoreTimestamp(storeTimestamp);
// 12 STOREHOST
int storeHost;
memcpy(&storeHost, pData + 16 * sizeof(int), 4);
memcpy(&port, pData + 17 * sizeof(int), 4);
port = ntohl(port);
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = storeHost;
sockaddr storeAddr;
memcpy(&storeAddr, &sa, sizeof(sockaddr));
msgExt->setStoreHost(storeAddr);
// 13 RECONSUMETIMES
int reconsumeTimes;
memcpy(&reconsumeTimes, pData + 18 * sizeof(int), 4);
reconsumeTimes = ntohl(reconsumeTimes);
msgExt->setReconsumeTimes(reconsumeTimes);
// 14 Prepared Transaction Offset
long long preparedTransactionOffset;
memcpy(&preparedTransactionOffset, pData + 19 * sizeof(int), 8);
preparedTransactionOffset = n2hll(preparedTransactionOffset);
msgExt->setPreparedTransactionOffset(preparedTransactionOffset);
// 15 BODY
int bodyLen = 0;
memcpy(&bodyLen, pData + 21 * sizeof(int), 4);
bodyLen = ntohl(bodyLen);
if (bodyLen > 0)
{
if (readBody)
{
const char* body = pData + 22 * sizeof(int);
int newBodyLen = bodyLen;
// uncompress body
if ((sysFlag & MessageSysFlag::CompressedFlag) == MessageSysFlag::CompressedFlag)
{
unsigned char* pOut;
int outLen;
if (UtilAll::decompress(body, bodyLen, &pOut, &outLen))
{
msgExt->setBody((char*)pOut, outLen);
free(pOut);
}
else
{
msgExt->setBody(body, newBodyLen);
}
}
else
{
msgExt->setBody(body, newBodyLen);
}
}
else
{
}
}
// 16 TOPIC
int topicLen = *(pData + 22 * sizeof(int) + bodyLen);
char* tmp = new char[topicLen + 1];
memcpy(tmp, pData + 22 * sizeof(int) + bodyLen + 1, topicLen);
tmp[topicLen] = 0;
std::string topic = tmp;
delete[] tmp;
msgExt->setTopic(topic);
// 17 properties
short propertiesLength;
memcpy(&propertiesLength, pData + 22 * sizeof(int) + bodyLen + 1 + topicLen, 2);
propertiesLength = ntohs(propertiesLength);
if (propertiesLength > 0)
{
char* properties = new char[propertiesLength + 1];
memcpy(properties, pData + 22 * sizeof(int) + bodyLen + 1 + topicLen + 2, propertiesLength);
properties[propertiesLength] = 0;
std::string propertiesString = properties;
std::map<std::string, std::string> map;
string2messageProperties(map, propertiesString);
msgExt->setProperties(map);
delete[] properties;
}
offset = 22 * sizeof(int) + bodyLen + 1 + topicLen + 2 + propertiesLength;
// ÏûÏ¢ID
std::string msgId = createMessageId(storeAddr, physicOffset);
msgExt->setMsgId(msgId);
return msgExt;
}
catch (...)
{
RMQ_ERROR("decode exception");
if (msgExt)
{
delete msgExt;
msgExt = NULL;
}
}
return NULL;
}
std::list<MessageExt*> MessageDecoder::decodes(const char* pData, int len)
{
return decodes(pData, len, true);
}
std::list<MessageExt*> MessageDecoder::decodes(const char* pData, int len, bool readBody)
{
std::list<MessageExt*> list;
int offset = 0;
while (offset < len)
{
int tmp;
MessageExt* msg = decode(pData + offset, len, tmp);
list.push_back(msg);
offset += tmp;
}
return list;
}
std::string MessageDecoder::messageProperties2String(const std::map<std::string, std::string>& properties)
{
std::stringstream ss;
std::map<std::string, std::string>::const_iterator it = properties.begin();
for (; it != properties.end(); it++)
{
ss << it->first << NAME_VALUE_SEPARATOR << it->second << PROPERTY_SEPARATOR;
}
return ss.str();
}
void MessageDecoder::string2messageProperties(std::map<std::string, std::string>& properties,
std::string& propertiesString)
{
std::vector<std::string> out;
UtilAll::Split(out, propertiesString, PROPERTY_SEPARATOR);
for (size_t i = 0; i < out.size(); i++)
{
std::vector<std::string> outValue;
UtilAll::Split(outValue, out[i], NAME_VALUE_SEPARATOR);
if (outValue.size() == 2)
{
properties[outValue[0]] = outValue[1];
}
}
}
}