summaryrefslogtreecommitdiff
path: root/protocols/Facebook/src/thrift.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2019-12-23 19:46:00 +0300
committerGeorge Hazan <ghazan@miranda.im>2019-12-23 19:46:00 +0300
commit22a846c74f1903eb9b881b0d3b4615b249960be9 (patch)
tree56d18d9d6cc94a252a1f12703388f2b3e258499b /protocols/Facebook/src/thrift.cpp
parente016a7802692a2ccfba34c2505dbd4b14a39d715 (diff)
Facebook: presence packet parsing
Diffstat (limited to 'protocols/Facebook/src/thrift.cpp')
-rw-r--r--protocols/Facebook/src/thrift.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/protocols/Facebook/src/thrift.cpp b/protocols/Facebook/src/thrift.cpp
new file mode 100644
index 0000000000..aefc7143a9
--- /dev/null
+++ b/protocols/Facebook/src/thrift.cpp
@@ -0,0 +1,306 @@
+/*
+
+Facebook plugin for Miranda NG
+Copyright © 2019 Miranda NG team
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// FbThrift class members
+
+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;
+ }
+}
+
+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);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// FbThriftReader class members
+
+uint8_t FbThriftReader::decodeType(int type)
+{
+ switch (type) {
+ case 0:
+ return FB_THRIFT_TYPE_STOP;
+ case 1:
+ m_lastBval = m_lastBool = true;
+ return FB_THRIFT_TYPE_BOOL;
+ case 2:
+ m_lastBool = true;
+ m_lastBval = false;
+ return FB_THRIFT_TYPE_BOOL;
+ case 3:
+ return FB_THRIFT_TYPE_BYTE;
+ case 4:
+ return FB_THRIFT_TYPE_I16;
+ case 5:
+ return FB_THRIFT_TYPE_I32;
+ case 6:
+ return FB_THRIFT_TYPE_I64;
+ case 7:
+ return FB_THRIFT_TYPE_DOUBLE;
+ case 8:
+ return FB_THRIFT_TYPE_STRING;
+ case 9:
+ return FB_THRIFT_TYPE_LIST;
+ case 10:
+ return FB_THRIFT_TYPE_SET;
+ case 11:
+ return FB_THRIFT_TYPE_MAP;
+ case 12:
+ return FB_THRIFT_TYPE_STRUCT;
+ default:
+ return 0;
+ }
+}
+
+bool FbThriftReader::isStop()
+{
+ byte b;
+ if (!readByte(b))
+ return false;
+
+ offset--;
+ return b == FB_THRIFT_TYPE_STOP;
+}
+
+bool FbThriftReader::readBool(bool &bVal)
+{
+ if (m_lastBool) {
+ bVal = m_lastBval;
+ m_lastBool = false;
+ return true;
+ }
+
+ byte b;
+ if (!readByte(b))
+ return false;
+
+ bVal = b == 0x11;
+ return true;
+}
+
+bool FbThriftReader::readByte(uint8_t &b)
+{
+ if (offset >= size())
+ return false;
+
+ b = *((uint8_t *)data() + offset);
+ offset++;
+ return true;
+}
+
+bool FbThriftReader::readField(uint8_t &type, uint16_t &id)
+{
+ byte b;
+ if (!readByte(b))
+ return false;
+
+ type = decodeType(b & 0x0F);
+ id = (b >> 4);
+ return (id == 0) ? readInt16(id) : true;
+}
+
+bool FbThriftReader::readIntV(uint64_t &val)
+{
+ uint8_t b;
+ unsigned i = 0;
+ val = 0;
+
+ do {
+ if (!readByte(b))
+ return false;
+
+ val |= ((b & 0x7F) << i);
+ i += 7;
+ } while ((b & 0x80) != 0);
+
+ return true;
+}
+
+bool FbThriftReader::readList(uint8_t &type, uint32_t &size)
+{
+ byte b;
+ if (!readByte(b))
+ return false;
+
+ type = decodeType(b & 0x0F);
+ size = b >> 4;
+ if (size == 0x0F) {
+ uint64_t tmp;
+ if (!readIntV(tmp))
+ return false;
+ size = (uint32_t)tmp;
+ }
+ return true;
+}
+
+bool FbThriftReader::readStr(char *&val)
+{
+ uint64_t tmp;
+ if (!readIntV(tmp))
+ return false;
+
+ uint32_t cbLen = (uint32_t)tmp;
+ if (offset + cbLen >= size())
+ return false;
+
+ if (cbLen > 0) {
+ val = mir_strndup((char *)data() + offset, cbLen);
+ offset += cbLen;
+ }
+ else val = nullptr;
+ return true;
+}
+
+bool FbThriftReader::readInt16(uint16_t &val)
+{
+ if (offset + 2 >= size())
+ return false;
+
+ val = ntohs(*(u_short *)((char *)data() + offset));
+ offset += 2;
+ return true;
+}
+
+bool FbThriftReader::readInt32(uint32_t &val)
+{
+ uint64_t tmp;
+ if (!readIntV(tmp))
+ return false;
+
+ val = (uint32_t )tmp;
+ return true;
+}
+
+bool FbThriftReader::readInt64(uint64_t &val)
+{
+ uint64_t tmp;
+ if (!readIntV(tmp))
+ return false;
+
+ val = (tmp >> 0x01) ^ -(tmp & 0x01);
+ return true;
+}