internal virtual async ValueTask ReceiveInitializeFrameAsync(CancellationToken cancel) { byte frameType = _socket.Endpoint.Protocol == Protocol.Ice1 ? (byte)Ice1FrameType.ValidateConnection : (byte)Ice2FrameType.Initialize; ArraySegment <byte> data = await ReceiveFrameAsync(frameType, cancel).ConfigureAwait(false); if (ReceivedEndOfStream) { throw new InvalidDataException($"received unexpected end of stream after initialize frame"); } if (_socket.Endpoint.Communicator.TraceLevels.Protocol >= 1) { TraceFrame(data, frameType); } if (_socket.Endpoint.Protocol == Protocol.Ice1) { if (data.Count > 0) { throw new InvalidDataException( @$ "received an ice1 frame with validate connection type and a size of `{data.Count}' bytes"); } } else { // Read the protocol parameters which are encoded with the binary context encoding. var istr = new InputStream(data, Ice2Definitions.Encoding); int dictionarySize = istr.ReadSize(); for (int i = 0; i < dictionarySize; ++i) { (int key, ReadOnlyMemory <byte> value) = istr.ReadBinaryContextEntry(); if (key == (int)Ice2ParameterKey.IncomingFrameMaxSize) { checked { _socket.PeerIncomingFrameMaxSize = (int)value.Span.ReadVarULong().Value; } if (_socket.PeerIncomingFrameMaxSize < 1024) { throw new InvalidDataException($@"the peer's IncomingFrameMaxSize ({ _socket.PeerIncomingFrameMaxSize} bytes) value is inferior to 1KB"); } } else { // Ignore unsupported parameters. } } if (_socket.PeerIncomingFrameMaxSize == null) { throw new InvalidDataException("missing IncomingFrameMaxSize Ice2 connection parameter"); } } }
/// <summary>Reads a binary context from the stream.</summary> /// <param name="istr">The input stream.</param> /// <returns>The binary context as an immutable dictionary.</returns> /// <remarks>The values of the dictionary reference memory in the stream's underlying buffer.</remarks> public static ImmutableDictionary <int, ReadOnlyMemory <byte> > ReadBinaryContext(this InputStream istr) { Debug.Assert(istr.Encoding == Encoding.V20); int size = istr.ReadSize(); if (size == 0) { return(ImmutableDictionary <int, ReadOnlyMemory <byte> > .Empty); } else { var builder = ImmutableDictionary.CreateBuilder <int, ReadOnlyMemory <byte> >(); for (int i = 0; i < size; ++i) { (int key, ReadOnlyMemory <byte> value) = istr.ReadBinaryContextEntry(); builder.Add(key, value); } return(builder.ToImmutable()); } }