Implemented new C++ logic

This commit is contained in:
Martino Ferrari
2026-06-12 15:25:13 +02:00
parent 617b5bd712
commit f25bd7f08e
220 changed files with 39185 additions and 850 deletions
+177
View File
@@ -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 */