/// <summary>Constructs an incoming request frame.</summary> /// <param name="protocol">The Ice protocol.</param> /// <param name="data">The frame data as an array segment.</param> /// <param name="maxSize">The maximum payload size, checked during decompression.</param> /// <param name="socketStream">The optional socket stream. The stream is non-null if there's still data to /// read on the stream after the reading the request frame.</param> internal IncomingRequestFrame( Protocol protocol, ArraySegment <byte> data, int maxSize, SocketStream?socketStream) : base(protocol, maxSize) { SocketStream = socketStream; var istr = new InputStream(data, Protocol.GetEncoding()); if (Protocol == Protocol.Ice1) { var requestHeader = new Ice1RequestHeader(istr); Identity = requestHeader.Identity; Facet = Ice1Definitions.GetFacet(requestHeader.FacetPath); Location = Array.Empty <string>(); Operation = requestHeader.Operation; IsIdempotent = requestHeader.OperationMode != OperationMode.Normal; Context = requestHeader.Context; Priority = default; Deadline = DateTime.MaxValue; } else { int headerSize = istr.ReadSize(); int startPos = istr.Pos; // We use the generated code for the header body and read the rest of the header "by hand". var requestHeaderBody = new Ice2RequestHeaderBody(istr); Identity = requestHeaderBody.Identity; Facet = requestHeaderBody.Facet ?? ""; Location = requestHeaderBody.Location ?? Array.Empty <string>(); Operation = requestHeaderBody.Operation; IsIdempotent = requestHeaderBody.Idempotent ?? false; Priority = requestHeaderBody.Priority ?? default; if (requestHeaderBody.Deadline < -1 || requestHeaderBody.Deadline == 0) { throw new InvalidDataException($"received invalid deadline value {requestHeaderBody.Deadline}"); } // The infinite deadline is encoded as -1 and converted to DateTime.MaxValue Deadline = requestHeaderBody.Deadline == -1 ? DateTime.MaxValue : DateTime.UnixEpoch + TimeSpan.FromMilliseconds(requestHeaderBody.Deadline); Context = requestHeaderBody.Context ?? new SortedDictionary <string, string>(); BinaryContext = istr.ReadBinaryContext(); if (istr.Pos - startPos != headerSize) { throw new InvalidDataException( @$ "received invalid request header: expected {headerSize} bytes but read {istr.Pos - startPos } bytes"); } if (Location.Any(segment => segment.Length == 0)) { throw new InvalidDataException("received request with an empty location segment"); } }
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"); } } }
// Constructor for unmarshaling. internal WSEndpoint(InputStream istr, Transport transport, Protocol protocol) : base(istr, transport, protocol, mostDerived: false) { if (protocol == Protocol.Ice1) { _resource = istr.ReadString(); } else { int optionCount = istr.ReadSize(); if (optionCount > 0) { _resource = istr.ReadString(); optionCount--; SkipUnknownOptions(istr, optionCount); } } }
// Constructor for unmarshaling internal TcpEndpoint( InputStream istr, Communicator communicator, Transport transport, Protocol protocol, bool mostDerived = true) : base(istr, communicator, protocol) { Transport = transport; if (protocol == Protocol.Ice1) { Timeout = TimeSpan.FromMilliseconds(istr.ReadInt()); HasCompressionFlag = istr.ReadBool(); } else if (mostDerived) { SkipUnknownOptions(istr, istr.ReadSize()); } }
/// <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()); } }