Implemented new C++ logic
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @file WSFrame_client.h
|
||||
* @brief WebSocket frame helpers for the ImGui client (no MARTe2 dependency).
|
||||
*
|
||||
* Mirrors WSFrame.h from Source/Applications/StreamHub/ using standard C++ types.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace StreamHubClient {
|
||||
|
||||
static const uint8_t WS_OPCODE_CONTINUATION = 0x00u;
|
||||
static const uint8_t WS_OPCODE_TEXT = 0x01u;
|
||||
static const uint8_t WS_OPCODE_BINARY = 0x02u;
|
||||
static const uint8_t WS_OPCODE_CLOSE = 0x08u;
|
||||
static const uint8_t WS_OPCODE_PING = 0x09u;
|
||||
static const uint8_t WS_OPCODE_PONG = 0x0Au;
|
||||
|
||||
static const uint8_t WS_FIN_BIT = 0x80u;
|
||||
static const uint8_t WS_MASK_BIT = 0x80u;
|
||||
|
||||
/** @brief Encode a WebSocket frame header (server→client, no masking).
|
||||
* @return Number of header bytes written (2, 4, or 10). */
|
||||
inline uint32_t WSEncodeHeader(uint8_t* buf, uint8_t opcode, uint64_t payloadLen) {
|
||||
buf[0] = WS_FIN_BIT | opcode;
|
||||
if (payloadLen < 126u) {
|
||||
buf[1] = static_cast<uint8_t>(payloadLen);
|
||||
return 2u;
|
||||
} else if (payloadLen < 65536u) {
|
||||
buf[1] = 126u;
|
||||
buf[2] = static_cast<uint8_t>((payloadLen >> 8u) & 0xFFu);
|
||||
buf[3] = static_cast<uint8_t>(payloadLen & 0xFFu);
|
||||
return 4u;
|
||||
} else {
|
||||
buf[1] = 127u;
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
buf[2 + i] = static_cast<uint8_t>(payloadLen & 0xFFu);
|
||||
payloadLen >>= 8u;
|
||||
}
|
||||
return 10u;
|
||||
}
|
||||
}
|
||||
|
||||
struct WSFrameHeader {
|
||||
bool fin;
|
||||
uint8_t opcode;
|
||||
bool masked;
|
||||
uint64_t payloadLen;
|
||||
uint8_t maskKey[4];
|
||||
uint32_t headerSize;
|
||||
};
|
||||
|
||||
inline bool WSParseHeader(const uint8_t* buf, uint32_t bufLen, WSFrameHeader& hdr) {
|
||||
if (bufLen < 2u) { return false; }
|
||||
|
||||
hdr.fin = (buf[0] & WS_FIN_BIT) != 0u;
|
||||
hdr.opcode = buf[0] & 0x0Fu;
|
||||
hdr.masked = (buf[1] & WS_MASK_BIT) != 0u;
|
||||
|
||||
uint32_t hdrSize = 2u;
|
||||
uint64_t plen = static_cast<uint64_t>(buf[1] & 0x7Fu);
|
||||
|
||||
if (plen == 126u) {
|
||||
if (bufLen < 4u) { return false; }
|
||||
plen = (static_cast<uint64_t>(buf[2]) << 8u) | static_cast<uint64_t>(buf[3]);
|
||||
hdrSize += 2u;
|
||||
} else if (plen == 127u) {
|
||||
if (bufLen < 10u) { return false; }
|
||||
plen = 0u;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
plen = (plen << 8u) | static_cast<uint64_t>(buf[2 + i]);
|
||||
}
|
||||
hdrSize += 8u;
|
||||
}
|
||||
|
||||
if (hdr.masked) {
|
||||
if (bufLen < hdrSize + 4u) { return false; }
|
||||
hdr.maskKey[0] = buf[hdrSize];
|
||||
hdr.maskKey[1] = buf[hdrSize + 1u];
|
||||
hdr.maskKey[2] = buf[hdrSize + 2u];
|
||||
hdr.maskKey[3] = buf[hdrSize + 3u];
|
||||
hdrSize += 4u;
|
||||
} else {
|
||||
hdr.maskKey[0] = hdr.maskKey[1] = hdr.maskKey[2] = hdr.maskKey[3] = 0u;
|
||||
}
|
||||
|
||||
hdr.payloadLen = plen;
|
||||
hdr.headerSize = hdrSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void WSUnmask(uint8_t* payload, uint32_t len, const uint8_t mask[4]) {
|
||||
for (uint32_t i = 0u; i < len; i++) {
|
||||
payload[i] ^= mask[i % 4u];
|
||||
}
|
||||
}
|
||||
|
||||
/* ── SHA-1 (for WebSocket handshake) ──────────────────────────────────────── */
|
||||
|
||||
inline void WS_SHA1(const uint8_t* data, uint32_t len, uint8_t digest[20]) {
|
||||
/* FIPS 180-4 SHA-1 — sufficient for a 60-byte input (key+GUID) */
|
||||
uint32_t h0 = 0x67452301u, h1 = 0xEFCDAB89u, h2 = 0x98BADCFEu,
|
||||
h3 = 0x10325476u, h4 = 0xC3D2E1F0u;
|
||||
|
||||
auto rot32 = [](uint32_t v, int n) -> uint32_t {
|
||||
return (v << n) | (v >> (32 - n));
|
||||
};
|
||||
|
||||
/* Build padded message */
|
||||
uint32_t bitLen = len * 8u;
|
||||
uint32_t padLen = (len % 64u < 56u) ? (56u - len % 64u) : (120u - len % 64u);
|
||||
uint32_t msgLen = len + padLen + 8u;
|
||||
uint8_t* msg = new uint8_t[msgLen]();
|
||||
memcpy(msg, data, len);
|
||||
msg[len] = 0x80u;
|
||||
/* Big-endian bit-length at end */
|
||||
msg[msgLen - 4] = static_cast<uint8_t>((bitLen >> 24) & 0xFF);
|
||||
msg[msgLen - 3] = static_cast<uint8_t>((bitLen >> 16) & 0xFF);
|
||||
msg[msgLen - 2] = static_cast<uint8_t>((bitLen >> 8) & 0xFF);
|
||||
msg[msgLen - 1] = static_cast<uint8_t>( bitLen & 0xFF);
|
||||
|
||||
for (uint32_t blk = 0u; blk < msgLen; blk += 64u) {
|
||||
uint32_t w[80];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
w[i] = (static_cast<uint32_t>(msg[blk + i*4]) << 24)
|
||||
| (static_cast<uint32_t>(msg[blk + i*4+1]) << 16)
|
||||
| (static_cast<uint32_t>(msg[blk + i*4+2]) << 8)
|
||||
| static_cast<uint32_t>(msg[blk + i*4+3]);
|
||||
}
|
||||
for (int i = 16; i < 80; i++) {
|
||||
w[i] = rot32(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
|
||||
}
|
||||
uint32_t a=h0,b=h1,c=h2,d=h3,e=h4,f,k,t;
|
||||
for (int i = 0; i < 80; i++) {
|
||||
if (i < 20) { f=( b & c)|((~b)& d); k=0x5A827999u; }
|
||||
else if (i < 40) { f= b ^ c ^ d; k=0x6ED9EBA1u; }
|
||||
else if (i < 60) { f=(b&c)|(b&d)|(c&d); k=0x8F1BBCDCu; }
|
||||
else { f= b ^ c ^ d; k=0xCA62C1D6u; }
|
||||
t = rot32(a,5) + f + e + k + w[i];
|
||||
e=d; d=c; c=rot32(b,30); b=a; a=t;
|
||||
}
|
||||
h0+=a; h1+=b; h2+=c; h3+=d; h4+=e;
|
||||
}
|
||||
delete[] msg;
|
||||
|
||||
auto put32 = [&](uint8_t* p, uint32_t v) {
|
||||
p[0]=v>>24; p[1]=(v>>16)&0xFF; p[2]=(v>>8)&0xFF; p[3]=v&0xFF;
|
||||
};
|
||||
put32(digest, h0); put32(digest+4, h1);
|
||||
put32(digest+8, h2); put32(digest+12, h3);
|
||||
put32(digest+16, h4);
|
||||
}
|
||||
|
||||
/* ── Base64 encode (for WebSocket handshake) ─────────────────────────────── */
|
||||
|
||||
inline uint32_t WS_Base64Encode(const uint8_t* in, uint32_t inLen, char* out) {
|
||||
static const char tbl[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
uint32_t o = 0;
|
||||
for (uint32_t i = 0; i < inLen; ) {
|
||||
uint32_t b = static_cast<uint32_t>(in[i++]) << 16;
|
||||
int have = 1;
|
||||
if (i < inLen) { b |= static_cast<uint32_t>(in[i++]) << 8; have++; }
|
||||
if (i < inLen) { b |= static_cast<uint32_t>(in[i++]); have++; }
|
||||
out[o++] = tbl[(b >> 18) & 0x3F];
|
||||
out[o++] = tbl[(b >> 12) & 0x3F];
|
||||
out[o++] = (have >= 2) ? tbl[(b >> 6) & 0x3F] : '=';
|
||||
out[o++] = (have >= 3) ? tbl[ b & 0x3F] : '=';
|
||||
}
|
||||
out[o] = '\0';
|
||||
return o;
|
||||
}
|
||||
|
||||
} /* namespace StreamHubClient */
|
||||
Reference in New Issue
Block a user