namespace NATS.Server.WebSocket; /// /// WebSocket protocol constants (RFC 6455). /// Ported from golang/nats-server/server/websocket.go lines 41-106. /// public static class WsConstants { // Opcodes (RFC 6455 Section 5.2) public const int TextMessage = 1; public const int BinaryMessage = 2; public const int CloseMessage = 8; public const int PingMessage = 9; public const int PongMessage = 10; public const int ContinuationFrame = 0; // Frame header bits public const byte FinalBit = 0x80; // 1 << 7 public const byte Rsv1Bit = 0x40; // 1 << 6 (compression, RFC 7692) public const byte Rsv2Bit = 0x20; // 1 << 5 public const byte Rsv3Bit = 0x10; // 1 << 4 public const byte MaskBit = 0x80; // 1 << 7 (in second byte) // Frame size limits public const int MaxFrameHeaderSize = 14; public const int MaxControlPayloadSize = 125; public const int FrameSizeForBrowsers = 4096; public const int CompressThreshold = 64; public const int CloseStatusSize = 2; // Close status codes (RFC 6455 Section 11.7) public const int CloseStatusNormalClosure = 1000; public const int CloseStatusGoingAway = 1001; public const int CloseStatusProtocolError = 1002; public const int CloseStatusUnsupportedData = 1003; public const int CloseStatusNoStatusReceived = 1005; public const int CloseStatusInvalidPayloadData = 1007; public const int CloseStatusPolicyViolation = 1008; public const int CloseStatusMessageTooBig = 1009; public const int CloseStatusInternalSrvError = 1011; public const int CloseStatusTlsHandshake = 1015; // Compression constants (RFC 7692) public const string PmcExtension = "permessage-deflate"; public const string PmcSrvNoCtx = "server_no_context_takeover"; public const string PmcCliNoCtx = "client_no_context_takeover"; public static readonly string PmcReqHeaderValue = $"{PmcExtension}; {PmcSrvNoCtx}; {PmcCliNoCtx}"; public static readonly string PmcFullResponse = $"Sec-WebSocket-Extensions: {PmcExtension}; {PmcSrvNoCtx}; {PmcCliNoCtx}\r\n"; // Header names public const string NoMaskingHeader = "Nats-No-Masking"; public const string NoMaskingValue = "true"; public static readonly string NoMaskingFullResponse = $"{NoMaskingHeader}: {NoMaskingValue}\r\n"; public const string XForwardedForHeader = "X-Forwarded-For"; // Path routing public const string ClientPath = "/"; public const string LeafNodePath = "/leafnode"; public const string MqttPath = "/mqtt"; // Decompression trailer appended before decompressing (RFC 7692 Section 7.2.2) public static readonly byte[] DecompressTrailer = [0x00, 0x00, 0xff, 0xff]; public static bool IsControlFrame(int opcode) => opcode >= CloseMessage; } public enum WsClientKind { Client, Leaf, Mqtt, }