Files
MARTe-Integrated-Components/Source/Applications/StreamHub/WSFrame.h
T
2026-06-12 15:25:13 +02:00

143 lines
4.5 KiB
C++

/**
* @file WSFrame.h
* @brief WebSocket frame constants, opcode definitions, and frame-building helpers.
*
* RFC 6455 WebSocket framing layer utilities.
*/
#ifndef STREAMHUB_WSFRAME_H_
#define STREAMHUB_WSFRAME_H_
#include "CompilerTypes.h"
#include <string.h>
namespace StreamHub {
using MARTe::uint8;
using MARTe::uint16;
using MARTe::uint32;
using MARTe::uint64;
/*---------------------------------------------------------------------------*/
/* Opcodes */
/*---------------------------------------------------------------------------*/
static const uint8 WS_OPCODE_CONTINUATION = 0x00u;
static const uint8 WS_OPCODE_TEXT = 0x01u;
static const uint8 WS_OPCODE_BINARY = 0x02u;
static const uint8 WS_OPCODE_CLOSE = 0x08u;
static const uint8 WS_OPCODE_PING = 0x09u;
static const uint8 WS_OPCODE_PONG = 0x0Au;
static const uint8 WS_FIN_BIT = 0x80u;
static const uint8 WS_MASK_BIT = 0x80u;
/*---------------------------------------------------------------------------*/
/* Frame encoder (server → client, no masking) */
/*---------------------------------------------------------------------------*/
/**
* @brief Encode a WebSocket frame header into @p buf.
* @param buf Output buffer (must have at least 10 bytes available).
* @param opcode WS_OPCODE_TEXT or WS_OPCODE_BINARY.
* @param payloadLen Number of payload bytes that follow the header.
* @return Number of header bytes written (2, 4, or 10).
*/
inline uint32 WSEncodeHeader(uint8 *buf, uint8 opcode, uint64 payloadLen) {
buf[0] = WS_FIN_BIT | opcode;
if (payloadLen < 126u) {
buf[1] = static_cast<uint8>(payloadLen);
return 2u;
} else if (payloadLen < 65536u) {
buf[1] = 126u;
buf[2] = static_cast<uint8>((payloadLen >> 8u) & 0xFFu);
buf[3] = static_cast<uint8>(payloadLen & 0xFFu);
return 4u;
} else {
buf[1] = 127u;
for (int i = 7; i >= 0; i--) {
buf[2 + i] = static_cast<uint8>(payloadLen & 0xFFu);
payloadLen >>= 8u;
}
return 10u;
}
}
/*---------------------------------------------------------------------------*/
/* Frame decoder (client → server, with masking) */
/*---------------------------------------------------------------------------*/
/**
* @brief Parsed fields from a received WebSocket frame header.
*/
struct WSFrameHeader {
bool fin;
uint8 opcode;
bool masked;
uint64 payloadLen;
uint8 maskKey[4];
uint32 headerSize; ///< Total header byte count (2 + 0|2|8 length + 0|4 mask)
};
/**
* @brief Try to parse a WebSocket frame header from @p buf (bufLen available bytes).
* @param buf Received bytes.
* @param bufLen Number of bytes available.
* @param hdr Output: parsed header fields.
* @return true if a complete header was parsed; false if more bytes are needed.
*/
inline bool WSParseHeader(const uint8 *buf, uint32 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 hdrSize = 2u;
uint64 plen = static_cast<uint64>(buf[1] & 0x7Fu);
if (plen == 126u) {
if (bufLen < 4u) { return false; }
plen = (static_cast<uint64>(buf[2]) << 8u) | static_cast<uint64>(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>(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;
}
/**
* @brief XOR-unmask a masked WebSocket payload in place.
* @param payload Payload buffer.
* @param len Payload length.
* @param mask 4-byte masking key.
*/
inline void WSUnmask(uint8 *payload, uint32 len, const uint8 mask[4]) {
for (uint32 i = 0u; i < len; i++) {
payload[i] ^= mask[i % 4u];
}
}
} /* namespace StreamHub */
#endif /* STREAMHUB_WSFRAME_H_ */