diff options
author | George Hazan <ghazan@miranda.im> | 2019-12-23 19:46:00 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-12-23 19:46:00 +0300 |
commit | 22a846c74f1903eb9b881b0d3b4615b249960be9 (patch) | |
tree | 56d18d9d6cc94a252a1f12703388f2b3e258499b /protocols/Facebook/src/mqtt.cpp | |
parent | e016a7802692a2ccfba34c2505dbd4b14a39d715 (diff) |
Facebook: presence packet parsing
Diffstat (limited to 'protocols/Facebook/src/mqtt.cpp')
-rw-r--r-- | protocols/Facebook/src/mqtt.cpp | 170 |
1 files changed, 41 insertions, 129 deletions
diff --git a/protocols/Facebook/src/mqtt.cpp b/protocols/Facebook/src/mqtt.cpp index 72ed222079..c80544176b 100644 --- a/protocols/Facebook/src/mqtt.cpp +++ b/protocols/Facebook/src/mqtt.cpp @@ -20,36 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "stdafx.h" -static uint8_t encodeType(int type) -{ - switch (type) { - case FB_THRIFT_TYPE_BOOL: - return 2; - case FB_THRIFT_TYPE_BYTE: - return 3; - case FB_THRIFT_TYPE_I16: - return 4; - case FB_THRIFT_TYPE_I32: - return 5; - case FB_THRIFT_TYPE_I64: - return 6; - case FB_THRIFT_TYPE_DOUBLE: - return 7; - case FB_THRIFT_TYPE_STRING: - return 8; - case FB_THRIFT_TYPE_LIST: - return 9; - case FB_THRIFT_TYPE_SET: - return 10; - case FB_THRIFT_TYPE_MAP: - return 11; - case FB_THRIFT_TYPE_STRUCT: - return 12; - default: - return 0; - } -} - uint8_t *FacebookProto::doZip(size_t cbData, const void *pData, size_t &cbRes) { size_t dataSize = cbData + 100; @@ -101,91 +71,7 @@ uint8_t *FacebookProto::doUnzip(size_t cbData, const void *pData, size_t &cbRes) } ///////////////////////////////////////////////////////////////////////////////////////// - -FbThrift& FbThrift::operator<<(uint8_t value) -{ - m_buf.append(&value, 1); - return *this; -} - -FbThrift& FbThrift::operator<<(const char *str) -{ - size_t len = mir_strlen(str); - writeIntV(len); - m_buf.append((void*)str, len); - return *this; -} - -void FbThrift::writeBool(bool bValue) -{ - uint8_t b = (bValue) ? 0x11 : 0x12; - m_buf.append(&b, 1); -} - -void FbThrift::writeBuf(const void *pData, size_t cbLen) -{ - m_buf.append((void*)pData, cbLen); -} - -void FbThrift::writeField(int iType) -{ - uint8_t type = encodeType(iType) + 0x10; - m_buf.append(&type, 1); -} - -void FbThrift::writeField(int iType, int id, int lastid) -{ - uint8_t type = encodeType(iType); - uint8_t diff = uint8_t(id - lastid); - if (diff > 0x0F) { - m_buf.append(&type, 1); - writeInt64(id); - } - else { - type += (diff << 4); - m_buf.append(&type, 1); - } -} - -void FbThrift::writeList(int iType, int size) -{ - uint8_t type = encodeType(iType); - if (size > 14) { - writeIntV(size); - *this << (type | 0xF0); - } - else *this << (type | (size << 4)); -} - -void FbThrift::writeInt16(uint16_t value) -{ - value = htons(value); - m_buf.append(&value, sizeof(value)); -} - -void FbThrift::writeInt32(int32_t value) -{ - writeIntV((value << 1) ^ (value >> 31)); -} - -void FbThrift::writeInt64(int64_t value) -{ - writeIntV((value << 1) ^ (value >> 63)); -} - -void FbThrift::writeIntV(uint64_t value) -{ - bool bLast; - do { - bLast = (value & ~0x7F) == 0; - uint8_t b = value & 0x7F; - if (!bLast) { - b |= 0x80; - value >>= 7; - } - m_buf.append(&b, 1); - } while (!bLast); -} +// MqttMessage class members MqttMessage::MqttMessage() : m_leadingByte(0) @@ -197,6 +83,19 @@ MqttMessage::MqttMessage(FbMqttMessageType type, uint8_t flags) m_leadingByte = ((type & 0x0F) << 4) | (flags & 0x0F); } +char* MqttMessage::readStr(const uint8_t *&pData) const +{ + u_short len = ntohs(*(u_short *)pData); pData += sizeof(u_short); + if (len == 0) + return nullptr; + + char *res = (char*)mir_alloc(len + 1); + memcpy(res, pData, len); + res[len] = 0; + pData += len; + return res; +} + void MqttMessage::writeStr(const char *str) { size_t len = mir_strlen(str); @@ -224,7 +123,9 @@ bool FacebookProto::MqttConnect() bool FacebookProto::MqttParse(const MqttMessage &payload) { - auto *pData = (const uint8_t *)payload.data(); + auto *pData = (const uint8_t *)payload.data(), *pBeg = pData; + int flags = payload.getFlags(); + uint16_t mid; switch (payload.getType()) { case FB_MQTT_MESSAGE_TYPE_CONNACK: @@ -236,6 +137,30 @@ bool FacebookProto::MqttParse(const MqttMessage &payload) OnLoggedIn(); MqttPing(); break; + + case FB_MQTT_MESSAGE_TYPE_PUBREL: + mid = ntohs(*(u_short *)pData); + { + MqttMessage reply(FB_MQTT_MESSAGE_TYPE_PUBCOMP); + reply << mid; + MqttSend(reply); + } + break; + + case FB_MQTT_MESSAGE_TYPE_PUBLISH: + char *str = payload.readStr(pData); + + if ((flags & FB_MQTT_MESSAGE_FLAG_QOS1) || (flags & FB_MQTT_MESSAGE_FLAG_QOS2)) { + mid = ntohs(*(u_short *)pData); + + MqttMessage reply((flags & FB_MQTT_MESSAGE_FLAG_QOS1) ? FB_MQTT_MESSAGE_TYPE_PUBACK : FB_MQTT_MESSAGE_TYPE_PUBREC); + reply << mid; + MqttSend(reply); + } + + OnPublish(str, pData, payload.size() - (pData - pBeg)); + mir_free(str); + break; } return true; @@ -271,19 +196,6 @@ bool FacebookProto::MqttRead(MqttMessage &payload) payload.writeBuf(buf, res); remainingBytes -= res; } - - // that might be a zipped buffer - if (payload.size() >= 2) { - auto *p = (const uint8_t *)payload.data(); - if ((((p[0] << 8) | p[1]) % 31) == 0 && (p[0] & 0x0F) == 8) { // zip header ok - size_t dataSize; - void *pData = doUnzip(payload.size(), payload.data(), dataSize); - if (pData != nullptr) { - payload.reset(dataSize, pData); - mir_free(pData); - } - } - } } return true; |