| | 1 | | // Copyright (c) ZeroC, Inc. |
| | 2 | |
|
| | 3 | | namespace IceRpc.Internal; |
| | 4 | |
|
| | 5 | | // Definitions for the ice protocol. |
| | 6 | | internal static class IceDefinitions |
| | 7 | | { |
| | 8 | | // Size of an ice frame prologue: |
| | 9 | | // Magic number (4 bytes) |
| | 10 | | // Protocol bytes (4 bytes) |
| | 11 | | // Frame type (Byte) |
| | 12 | | // Compression status (Byte) |
| | 13 | | // Frame size (Int - 4 bytes) |
| | 14 | | internal const int PrologueSize = 14; |
| | 15 | |
|
| | 16 | | // The magic number at the front of each frame. |
| 3 | 17 | | internal static readonly byte[] Magic = "IceP"u8.ToArray(); // 'I', 'c', 'e', 'P' |
| | 18 | |
|
| | 19 | | // 4-bytes after magic that provide the protocol version (always 1.0 for an ice frame) and the encoding of the |
| | 20 | | // frame header (always set to 1.0 with an ice frame, even though we use Slice1). |
| 3 | 21 | | internal static readonly byte[] ProtocolBytes = new byte[] { 1, 0, 1, 0 }; |
| | 22 | |
|
| 3 | 23 | | internal static readonly IcePrologue CloseConnectionFrame = new( |
| 3 | 24 | | Magic[0], |
| 3 | 25 | | Magic[1], |
| 3 | 26 | | Magic[2], |
| 3 | 27 | | Magic[3], |
| 3 | 28 | | ProtocolBytes[0], |
| 3 | 29 | | ProtocolBytes[1], |
| 3 | 30 | | ProtocolBytes[2], |
| 3 | 31 | | ProtocolBytes[3], |
| 3 | 32 | | IceFrameType.CloseConnection, |
| 3 | 33 | | compressionStatus: 0, |
| 3 | 34 | | PrologueSize); |
| | 35 | |
|
| 3 | 36 | | internal static readonly byte[] FramePrologue = new byte[] |
| 3 | 37 | | { |
| 3 | 38 | | Magic[0], Magic[1], Magic[2], Magic[3], |
| 3 | 39 | | ProtocolBytes[0], ProtocolBytes[1], ProtocolBytes[2], ProtocolBytes[3], |
| 3 | 40 | | }; |
| | 41 | |
|
| 3 | 42 | | internal static readonly IcePrologue ValidateConnectionFrame = new( |
| 3 | 43 | | Magic[0], |
| 3 | 44 | | Magic[1], |
| 3 | 45 | | Magic[2], |
| 3 | 46 | | Magic[3], |
| 3 | 47 | | ProtocolBytes[0], |
| 3 | 48 | | ProtocolBytes[1], |
| 3 | 49 | | ProtocolBytes[2], |
| 3 | 50 | | ProtocolBytes[3], |
| 3 | 51 | | IceFrameType.ValidateConnection, |
| 3 | 52 | | compressionStatus: 0, |
| 3 | 53 | | PrologueSize); |
| | 54 | |
|
| | 55 | | // Verify that the first 8 bytes correspond to Magic + ProtocolBytes |
| | 56 | | internal static void CheckPrologue(IcePrologue prologue) |
| 5616 | 57 | | { |
| 5616 | 58 | | if (prologue.Magic1 != Magic[0] || |
| 5616 | 59 | | prologue.Magic2 != Magic[1] || |
| 5616 | 60 | | prologue.Magic3 != Magic[2] || |
| 5616 | 61 | | prologue.Magic4 != Magic[3]) |
| 4 | 62 | | { |
| 4 | 63 | | byte[] magic = new byte[] { prologue.Magic1, prologue.Magic2, prologue.Magic3, prologue.Magic4 }; |
| 4 | 64 | | throw new InvalidDataException( |
| 4 | 65 | | $"Received incorrect magic bytes in the prologue of an ice frame: '{BytesToString(magic)}'."); |
| | 66 | | } |
| | 67 | |
|
| 5612 | 68 | | if (prologue.ProtocolMajor != ProtocolBytes[0] || prologue.ProtocolMinor != ProtocolBytes[1]) |
| 0 | 69 | | { |
| 0 | 70 | | throw new InvalidDataException( |
| 0 | 71 | | $"Received unexpected protocol in the prologue of an ice frame: '{prologue.ProtocolMajor}.{prologue.Prot |
| | 72 | | } |
| | 73 | |
|
| 5612 | 74 | | if (prologue.EncodingMajor != ProtocolBytes[2] || prologue.EncodingMinor != ProtocolBytes[3]) |
| 0 | 75 | | { |
| 0 | 76 | | throw new InvalidDataException( |
| 0 | 77 | | $"Received unexpected protocol encoding in the prologue of an ice frame: '{prologue.EncodingMajor}.{prol |
| | 78 | | } |
| 5612 | 79 | | } |
| | 80 | |
|
| 4 | 81 | | private static string BytesToString(ReadOnlySpan<byte> bytes) => BitConverter.ToString(bytes.ToArray()); |
| | 82 | | } |