summaryrefslogtreecommitdiff
path: root/protocols/WhatsAppWeb
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-09-28 21:26:25 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-09-28 21:26:25 +0300
commitcd30b43a4da9327cb5d7cb054b889350aedcf7e7 (patch)
tree24885fd24c0ecb77fe7f1bb782bd71f0549d62dc /protocols/WhatsAppWeb
parent96b7e711d06d0a673daf76a12c2bff4de14b0502 (diff)
code cleaning
Diffstat (limited to 'protocols/WhatsAppWeb')
-rw-r--r--protocols/WhatsAppWeb/src/proto.cpp2
-rw-r--r--protocols/WhatsAppWeb/src/proto.h4
-rw-r--r--protocols/WhatsAppWeb/src/server.cpp4
-rw-r--r--protocols/WhatsAppWeb/src/utils.cpp39
-rw-r--r--protocols/WhatsAppWeb/src/utils.h11
-rw-r--r--protocols/WhatsAppWeb/src/wareader.cpp104
6 files changed, 89 insertions, 75 deletions
diff --git a/protocols/WhatsAppWeb/src/proto.cpp b/protocols/WhatsAppWeb/src/proto.cpp
index c21b6e24c7..65b449807b 100644
--- a/protocols/WhatsAppWeb/src/proto.cpp
+++ b/protocols/WhatsAppWeb/src/proto.cpp
@@ -253,7 +253,7 @@ int WhatsAppProto::SendMsg(MCONTACT hContact, int, const char *pszMsg)
payLoad.addAttr("type", "relay");
payLoad.content.assign(pBuf, cbBinaryLen);
- int pktId = WSSendNode(0, payLoad);
+ int pktId = WSSendNode(payLoad);
mir_cslock lck(m_csOwnMessages);
m_arOwnMsgs.insert(new WAOwnMessage(pktId, hContact, szMsgId));
diff --git a/protocols/WhatsAppWeb/src/proto.h b/protocols/WhatsAppWeb/src/proto.h
index 54ec389933..3383ee6306 100644
--- a/protocols/WhatsAppWeb/src/proto.h
+++ b/protocols/WhatsAppWeb/src/proto.h
@@ -8,6 +8,7 @@ Copyright © 2019-22 George Hazan
#if !defined(PROTO_H)
#define PROTO_H
+#define S_WHATSAPP_NET "@s.whatsapp.net"
#define APP_VERSION "2.2230.15"
#define KEY_BUNDLE_TYPE "\x05"
@@ -159,7 +160,6 @@ class WhatsAppProto : public PROTO<WhatsAppProto>
/// Network ////////////////////////////////////////////////////////////////////////////
- int m_iPktNumber;
time_t m_iLoginTime;
HNETLIBCONN m_hServerConn;
@@ -168,7 +168,7 @@ class WhatsAppProto : public PROTO<WhatsAppProto>
bool WSReadPacket(const WSHeader &hdr, MBinBuffer &buf);
int WSSend(const MessageLite &msg, WA_PKT_HANDLER = nullptr, void *pUserIndo = nullptr);
- int WSSendNode(int flags, WANode &node, WA_PKT_HANDLER = nullptr);
+ int WSSendNode(WANode &node, WA_PKT_HANDLER = nullptr);
void OnLoggedIn(void);
void OnLoggedOut(void);
diff --git a/protocols/WhatsAppWeb/src/server.cpp b/protocols/WhatsAppWeb/src/server.cpp
index 1ffa435579..192e203521 100644
--- a/protocols/WhatsAppWeb/src/server.cpp
+++ b/protocols/WhatsAppWeb/src/server.cpp
@@ -70,6 +70,9 @@ void WhatsAppProto::ShutdownSession()
void WhatsAppProto::OnStartSession(const WANode &node)
{
+ WANode reply("iq");
+ reply << CHAR_PARAM("to", S_WHATSAPP_NET) << CHAR_PARAM("type", "result") << CHAR_PARAM("id", node.getAttr("id"));
+ WSSendNode(reply);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -256,7 +259,6 @@ bool WhatsAppProto::ServerThreadWorker()
debugLogA("Server connection succeeded");
m_hServerConn = pReply->nlc;
m_iLoginTime = time(0);
- m_iPktNumber = 0;
m_szClientToken = getMStringA(DBKEY_CLIENT_TOKEN);
auto &pubKey = m_noise->ephemeral.pub;
diff --git a/protocols/WhatsAppWeb/src/utils.cpp b/protocols/WhatsAppWeb/src/utils.cpp
index 9d62432a10..85c545273a 100644
--- a/protocols/WhatsAppWeb/src/utils.cpp
+++ b/protocols/WhatsAppWeb/src/utils.cpp
@@ -76,46 +76,27 @@ int WhatsAppProto::WSSend(const MessageLite &msg, WA_PKT_HANDLER pHandler, void
static char zeroData[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int WhatsAppProto::WSSendNode(int flags, WANode &node, WA_PKT_HANDLER pHandler)
+int WhatsAppProto::WSSendNode(WANode &node, WA_PKT_HANDLER pHandler)
{
if (m_hServerConn == nullptr)
return 0;
- {
- char str[100];
- _i64toa(_time64(0), str, 10);
- node.addAttr("epoch", str);
-
- CMStringA szText;
- node.print(szText);
- debugLogA("Sending binary node: %s", szText.c_str());
- }
+ CMStringA szText;
+ node.print(szText);
+ debugLogA("Sending binary node: %s", szText.c_str());
WAWriter writer;
writer.writeNode(&node);
- // AES block size = 16 bytes, let's expand data to block size boundary
- size_t rest = writer.body.length() % 16;
- if (rest != 0)
- writer.body.append(zeroData, 16 - rest);
-
- BYTE iv[16];
- Utils_GetRandom(iv, sizeof(iv));
-
- int pktId = ++m_iPktNumber;
-
if (pHandler != nullptr) {
mir_cslock lck(m_csPacketQueue);
m_arPacketQueue.insert(new WARequest(pHandler));
}
- char postPrefix[3] = {',', 0, (char)flags};
-
- MBinBuffer ret;
- ret.append(postPrefix, sizeof(postPrefix));
- WebSocket_SendBinary(m_hServerConn, ret.data(), ret.length());
-
- return pktId;
+ MBinBuffer encData = m_noise->encrypt(writer.body.data(), writer.body.length());
+ MBinBuffer payload = m_noise->encodeFrame(encData.data(), encData.length());
+ WebSocket_SendBinary(m_hServerConn, payload.data(), payload.length());
+ return 1;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -124,6 +105,10 @@ int WhatsAppProto::WSSendNode(int flags, WANode &node, WA_PKT_HANDLER pHandler)
WANode::WANode()
{}
+WANode::WANode(const char *pszTitle) :
+ title(pszTitle)
+{}
+
WANode::~WANode()
{
for (auto &p: attrs)
diff --git a/protocols/WhatsAppWeb/src/utils.h b/protocols/WhatsAppWeb/src/utils.h
index 72d69c96f0..dfa98705c6 100644
--- a/protocols/WhatsAppWeb/src/utils.h
+++ b/protocols/WhatsAppWeb/src/utils.h
@@ -41,6 +41,7 @@ class WANode // kinda XML
public:
WANode();
+ WANode(const char *pszTitle);
~WANode();
void addAttr(const char *pszName, const char *pszValue);
@@ -53,6 +54,12 @@ public:
std::list<WANode*> children;
};
+__forceinline WANode& operator<<(WANode &node, const CHAR_PARAM &param)
+{
+ node.addAttr(param.szName, param.szValue);
+ return node;
+}
+
class WAReader
{
const BYTE *m_buf, *m_limit;
@@ -91,8 +98,8 @@ class WAWriter
void writeInt20(int value);
void writeLength(int value);
void writeListSize(int tag);
- void writePacked(const CMStringA &str);
- void writeString(const char *str, bool bRaw = false);
+ void writePacked(const CMStringA &str, int tag);
+ void writeString(const char *str);
bool writeToken(const char *str);
public:
diff --git a/protocols/WhatsAppWeb/src/wareader.cpp b/protocols/WhatsAppWeb/src/wareader.cpp
index 0f6df4b31a..30d9aab7c0 100644
--- a/protocols/WhatsAppWeb/src/wareader.cpp
+++ b/protocols/WhatsAppWeb/src/wareader.cpp
@@ -190,18 +190,27 @@ CMStringA WAReader::readPacked(int tag)
CMStringA WAReader::readString(int tag)
{
- if (tag >= 1 && tag < _countof(SingleByteTokens)) {
- CMStringA ret = SingleByteTokens[tag];
- if (ret == "s.whatsapp.net")
- return "c.us";
- return ret;
- }
+ if (tag >= 1 && tag < _countof(SingleByteTokens))
+ return SingleByteTokens[tag];
+ int idx;
switch (tag) {
- case DICTIONARY_0: return dict0[readInt8()];
- case DICTIONARY_1: return dict1[readInt8()];
- case DICTIONARY_2: return dict2[readInt8()];
- case DICTIONARY_3: return dict3[readInt8()];
+ case DICTIONARY_0:
+ idx = readInt8();
+ return (idx < _countof(dict0)) ? dict0[idx] : "";
+
+ case DICTIONARY_1:
+ idx = readInt8();
+ return (idx < _countof(dict1)) ? dict1[idx] : "";
+
+ case DICTIONARY_2:
+ idx = readInt8();
+ return (idx < _countof(dict2)) ? dict2[idx] : "";
+
+ case DICTIONARY_3:
+ idx = readInt8();
+ return (idx < _countof(dict3)) ? dict3[idx] : "";
+
case LIST_EMPTY:
return "";
@@ -302,6 +311,9 @@ void WAWriter::writeListSize(int length)
void WAWriter::writeNode(const WANode *pNode)
{
+ // we never send zipped content
+ writeByte(0);
+
int numAttrs = (int)pNode->attrs.size();
int hasContent = pNode->content.length() != 0;
writeListSize(2 * numAttrs + 1 + hasContent);
@@ -331,32 +343,6 @@ void WAWriter::writeNode(const WANode *pNode)
}
}
-void WAWriter::writeString(const char *str, bool bRaw)
-{
- if (!bRaw && !mir_strcmp(str, "c.us")) {
- writeToken("s.whatsapp.net");
- return;
- }
-
- if (writeToken(str))
- return;
-
- auto *pszDelimiter = strchr(str, '@');
- if (pszDelimiter) {
- writeByte(JID_PAIR);
-
- if (pszDelimiter == str) // empty jid
- writeByte(LIST_EMPTY);
- else
- writePacked(CMStringA(str, int(pszDelimiter - str)));
- }
- else {
- int len = (int)strlen(str);
- writeLength(len);
- body.append(str, len);
- }
-}
-
bool WAWriter::writeToken(const char *str)
{
for (auto &it : SingleByteTokens)
@@ -408,22 +394,56 @@ static BYTE packPair(int type, char c1, char c2)
return (b1 << 4) + b2;
}
-void WAWriter::writePacked(const CMStringA &str)
+static bool isNibble(const CMStringA &str)
+{
+ return strspn(str, "0123456789-.") == str.GetLength();
+}
+
+static bool isHex(const CMStringA &str)
+{
+ return strspn(str, "0123456789abcdefABCDEF-.") == str.GetLength();
+}
+
+void WAWriter::writePacked(const CMStringA &str, int tag)
{
if (str.GetLength() > 254)
return;
- // all symbols of str can be a nibble?
- int type = (strspn(str, "0123456789-.") == str.GetLength()) ? NIBBLE_8 : HEX_8;
-
int len = str.GetLength() / 2;
BYTE firstByte = (len % 2) == 0 ? 0 : 0x80;
writeByte(firstByte | len);
const char *p = str;
for (int i = 0; i < len; i++, p += 2)
- writeByte(packPair(type, p[0], p[1]));
+ writeByte(packPair(tag, p[0], p[1]));
if (firstByte != 0)
- writeByte(packPair(type, p[0], 0));
+ writeByte(packPair(tag, p[0], 0));
+}
+
+void WAWriter::writeString(const char *str)
+{
+ if (writeToken(str))
+ return;
+
+ auto *pszDelimiter = strchr(str, '@');
+ if (pszDelimiter) {
+ writeByte(JID_PAIR);
+
+ if (pszDelimiter == str) // empty jid
+ writeByte(LIST_EMPTY);
+ else
+ writeString(CMStringA(str, int(pszDelimiter - str)));
+ }
+ else {
+ CMStringA buf(str);
+ if (isNibble(buf))
+ writePacked(buf, NIBBLE_8);
+ else if (isHex(buf))
+ writePacked(buf, HEX_8);
+ else {
+ writeLength(buf.GetLength());
+ body.append(buf, buf.GetLength());
+ }
+ }
}