blob: 2d90b6fa1873c62429af7693c7bc90c1a4c6abfa (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include <zenhttp/websocket.h>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <vector>
namespace zen {
/**
* Result of attempting to parse a single WebSocket frame from a byte buffer
*/
struct WsFrameParseResult
{
bool IsValid = false; // true if a complete frame was successfully parsed
size_t BytesConsumed = 0; // number of bytes consumed from the input buffer
WebSocketOpcode Opcode = WebSocketOpcode::kText;
bool Fin = false;
std::vector<uint8_t> Payload;
};
/**
* RFC 6455 WebSocket frame codec
*
* Provides static helpers for parsing client-to-server frames (which are
* always masked) and building server-to-client frames (which are never masked).
*/
struct WsFrameCodec
{
/**
* Try to parse one complete frame from the front of the buffer.
*
* Returns a result with IsValid == false and BytesConsumed == 0 when
* there is not enough data yet. The caller should accumulate more data
* and retry.
*/
static WsFrameParseResult TryParseFrame(const uint8_t* Data, size_t Size);
/**
* Build a server-to-client frame (no masking)
*/
static std::vector<uint8_t> BuildFrame(WebSocketOpcode Opcode, std::span<const uint8_t> Payload);
/**
* Build a close frame with a status code and optional reason string
*/
static std::vector<uint8_t> BuildCloseFrame(uint16_t Code, std::string_view Reason = {});
/**
* Build a client-to-server frame (with masking per RFC 6455)
*/
static std::vector<uint8_t> BuildMaskedFrame(WebSocketOpcode Opcode, std::span<const uint8_t> Payload);
/**
* Build a masked close frame with status code and optional reason
*/
static std::vector<uint8_t> BuildMaskedCloseFrame(uint16_t Code, std::string_view Reason = {});
/**
* Compute the Sec-WebSocket-Accept value per RFC 6455 section 4.2.2
*
* accept = Base64(SHA1(clientKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
*/
static std::string ComputeAcceptKey(std::string_view ClientKey);
};
} // namespace zen
|