Пример #1
0
 internal static void TraceFrame(Communicator communicator, ReadOnlySpan <byte> header,
                                 IncomingResponseFrame frame) =>
 TraceResponse(
     "received response",
     communicator,
     header[8],                                // Message Type
     header[9],                                // Compression Status
     InputStream.ReadInt(header.Slice(10, 4)), // Request size
     InputStream.ReadInt(header.Slice(14, 4)), // Request-Id,
     frame.ReplyStatus,
     frame.Encoding);
Пример #2
0
 internal static void TraceCollocatedFrame(Communicator communicator, byte messageType, int requestId,
                                           IncomingResponseFrame frame) =>
 TraceResponse(
     "received response",
     communicator,
     messageType,
     0,
     frame.Size + Ice1Definitions.HeaderSize + 4,
     requestId,
     frame.ReplyStatus,
     frame.Encoding);
Пример #3
0
 internal static void TraceFrame(
     Communicator communicator,
     ReadOnlySpan <byte> header,
     IncomingResponseFrame frame) =>
 TraceResponse(
     "received response",
     communicator,
     frame.Protocol,
     header[8],                                                                          // Frame type
     header[9],                                                                          // Compression Status
     InputStream.ReadFixedLengthSize(frame.Protocol.GetEncoding(), header.Slice(10, 4)), // Request size
     InputStream.ReadInt(header.Slice(14, 4)),                                           // Request-Id,
     frame.ReplyStatus,
     frame.Encoding);
Пример #4
0
        /// <summary>Forwards an incoming request to another Ice object.</summary>
        /// <param name="proxy">The proxy for the target Ice object.</param>
        /// <param name="oneway">When true, the request is sent as a oneway request. When false, it is sent as a
        /// two-way request.</param>
        /// <param name="request">The incoming request frame.</param>
        /// <param name="progress">Sent progress provider.</param>
        /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
        /// <returns>A task holding the response frame.</returns>
        public static async ValueTask <OutgoingResponseFrame> ForwardAsync(this IObjectPrx proxy,
                                                                           bool oneway,
                                                                           IncomingRequestFrame request,
                                                                           IProgress <bool>?progress = null,
                                                                           CancellationToken cancel  = default)
        {
            var forwardedRequest = new OutgoingRequestFrame(proxy, request.Operation, request.IsIdempotent,
                                                            request.Context, request.Payload);
            IncomingResponseFrame response =
                await proxy.InvokeAsync(forwardedRequest, oneway : oneway, progress, cancel)
                .ConfigureAwait(false);

            return(new OutgoingResponseFrame(request.Encoding, response.Payload));
        }
Пример #5
0
        internal async virtual ValueTask <IncomingResponseFrame> ReceiveResponseFrameAsync(CancellationToken cancel)
        {
            ArraySegment <byte> data;

            try
            {
                byte frameType = _socket.Endpoint.Protocol == Protocol.Ice1 ?
                                 (byte)Ice1FrameType.Reply : (byte)Ice2FrameType.Response;

                data = await ReceiveFrameAsync(frameType, cancel).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                if (_socket.Endpoint.Protocol != Protocol.Ice1)
                {
                    await ResetAsync((long)StreamResetErrorCode.RequestCanceled).ConfigureAwait(false);
                }
                throw;
            }

            IncomingResponseFrame response;

            if (ReceivedEndOfStream)
            {
                response = new IncomingResponseFrame(_socket.Endpoint.Protocol, data, _socket.IncomingFrameMaxSize, null);
            }
            else
            {
                // Increment the use count of this stream to ensure it's not going to be disposed before the
                // stream parameter data is disposed.
                Interlocked.Increment(ref UseCount);
                response = new IncomingResponseFrame(_socket.Endpoint.Protocol, data, _socket.IncomingFrameMaxSize, this);
            }

            if (_socket.Endpoint.Communicator.TraceLevels.Protocol >= 1)
            {
                TraceFrame(response);
            }

            return(response);
        }
Пример #6
0
        /// <summary>Forwards an incoming request to another Ice object represented by the <paramref name="proxy"/>
        /// parameter.</summary>
        /// <remarks>When the incoming request frame's protocol and proxy's protocol are different, this method
        /// automatically bridges between these two protocols. When proxy's protocol is ice1, the resulting outgoing
        /// request frame is never compressed.</remarks>
        /// <param name="proxy">The proxy for the target Ice object.</param>
        /// <param name="request">The incoming request frame to forward to proxy's target.</param>
        /// <param name="oneway">When true, the request is sent as a oneway request. When false, it is sent as a
        /// two-way request.</param>
        /// <param name="progress">Sent progress provider.</param>
        /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
        /// <returns>A task holding the response frame.</returns>
        public static async ValueTask <OutgoingResponseFrame> ForwardAsync(
            this IObjectPrx proxy,
            IncomingRequestFrame request,
            bool oneway,
            IProgress <bool>?progress = null,
            CancellationToken cancel  = default)
        {
            var forwardedRequest = new OutgoingRequestFrame(proxy, request, cancel: cancel);

            try
            {
                // TODO: add support for stream data forwarding.
                using IncomingResponseFrame response =
                          await Reference.InvokeAsync(proxy, forwardedRequest, oneway, progress).ConfigureAwait(false);

                return(new OutgoingResponseFrame(request, response));
            }
            catch (LimitExceededException exception)
            {
                return(new OutgoingResponseFrame(request, new ServerException(exception.Message, exception)));
            }
        }
Пример #7
0
        public async Task <IncomingResponseFrame> SendRequestAsync(
            OutgoingRequestFrame outgoingRequest,
            bool oneway,
            bool synchronous,
            IInvocationObserver?observer,
            IProgress <bool> progress,
            CancellationToken cancel)
        {
            cancel.ThrowIfCancellationRequested();

            IChildInvocationObserver?childObserver = null;
            int requestId = 0;

            // The CollocatedRequestHandler is an internal object so it's safe to lock (this) as long as our
            // code doesn't use the collocated request handler as a lock. The lock here is useful to ensure
            // the protocol trace and observer call is output or called in the same order as the request ID
            // is allocated.
            lock (_mutex)
            {
                if (!oneway)
                {
                    requestId = ++_requestId;
                }

                if (observer != null)
                {
                    childObserver = observer.GetCollocatedObserver(_adapter, requestId, outgoingRequest.Size);
                    childObserver?.Attach();
                }

                if (_adapter.Communicator.TraceLevels.Protocol >= 1)
                {
                    ProtocolTrace.TraceFrame(_adapter.Communicator, requestId, outgoingRequest);
                }
            }

            Task <OutgoingResponseFrame> task;

            if (_adapter.TaskScheduler != null ||
                !synchronous ||
                oneway ||
                cancel != CancellationToken.None)
            {
                // Don't invoke from the user thread if async or cancellation token is set. We also don't dispatch
                // oneway from the user thread to match the non-collocated behavior where the oneway synchronous
                // request returns as soon as it's sent over the transport.
                task = Task.Factory.StartNew(() =>
                {
                    progress.Report(false);
                    return(DispatchAsync(outgoingRequest, requestId, cancel));
                },
                                             cancel,
                                             TaskCreationOptions.None,
                                             _adapter.TaskScheduler ?? TaskScheduler.Default).Unwrap();

                if (oneway)
                {
                    childObserver?.Detach();
                    return(IncomingResponseFrame.WithVoidReturnValue(outgoingRequest.Protocol,
                                                                     outgoingRequest.Encoding));
                }
            }
            else // Optimization: directly call DispatchAsync
            {
                progress.Report(false);
                task = DispatchAsync(outgoingRequest, requestId, cancel);
            }

            Debug.Assert(!oneway);
            try
            {
                OutgoingResponseFrame outgoingResponseFrame = await task.WaitAsync(cancel).ConfigureAwait(false);

                var incomingResponse = new IncomingResponseFrame(
                    outgoingRequest.Protocol,
                    outgoingResponseFrame.Data.AsArraySegment(),
                    _adapter.IncomingFrameSizeMax);

                if (_adapter.Communicator.TraceLevels.Protocol >= 1)
                {
                    ProtocolTrace.TraceFrame(_adapter.Communicator, requestId, incomingResponse);
                }

                childObserver?.Reply(incomingResponse.Size);
                return(incomingResponse);
            }
            catch (Exception ex)
            {
                childObserver?.Failed(ex.GetType().FullName ?? "System.Exception");
                throw;
            }
            finally
            {
                childObserver?.Detach();
            }
        }
Пример #8
0
 public virtual bool Response(IncomingResponseFrame responseFrame)
 {
     Debug.Assert(false); // Must be overridden by request that can handle responses
     return(false);
 }
Пример #9
0
 /// <summary>The <see cref="ResponseReader{T}"/> reader for the return type of operation ice_isA.
 /// </summary>
 public static bool IceIsA(IObjectPrx proxy, IncomingResponseFrame response) =>
 response.ReadReturnValue(proxy, InputStream.IceReaderIntoBool);
Пример #10
0
 /// <summary>The <see cref="ResponseReader{T}"/> reader for the return type of operation ice_ids.
 /// </summary>
 public static string[] IceIds(IObjectPrx proxy, IncomingResponseFrame response) =>
 response.ReadReturnValue(
     proxy, istr => istr.ReadArray(minElementSize: 1, InputStream.IceReaderIntoString));
Пример #11
0
 /// <summary>The <see cref="ResponseReader{T}"/> reader for the return type of operation ice_id.
 /// </summary>
 public static string IceId(IObjectPrx proxy, IncomingResponseFrame response) =>
 response.ReadReturnValue(proxy, InputStream.IceReaderIntoString);