public ValueTask <Task <IncomingResponseFrame>?> SendRequestAsync( OutgoingRequestFrame outgoingRequestFrame, bool oneway, bool synchronous, IInvocationObserver?observer, CancellationToken cancel) => _connection.SendRequestAsync(outgoingRequestFrame, oneway, _compress, synchronous, observer, cancel);
public ValueTask <Task <IncomingResponseFrame>?> SendRequestAsync( OutgoingRequestFrame outgoingRequestFrame, bool oneway, bool synchronous, IInvocationObserver?observer, CancellationToken cancel) { cancel.ThrowIfCancellationRequested(); // // Increase the direct count to prevent the thread pool from being destroyed before // invokeAll is called. This will also throw if the object adapter has been deactivated. // _adapter.IncDirectCount(); 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, outgoingRequestFrame.Size); childObserver?.Attach(); } if (_adapter.Communicator.TraceLevels.Protocol >= 1) { ProtocolTrace.TraceCollocatedFrame(_adapter.Communicator, (byte)Ice1Definitions.FrameType.Request, requestId, outgoingRequestFrame); } } Task <IncomingResponseFrame?> task; if (_adapter.TaskScheduler != null || !synchronous || oneway || _reference.InvocationTimeout > 0) { // Don't invoke from the user thread if async or invocation timeout 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(() => InvokeAllAsync(outgoingRequestFrame, requestId, cancel), cancel, TaskCreationOptions.None, _adapter.TaskScheduler ?? TaskScheduler.Default).Unwrap(); if (oneway) { childObserver?.Detach(); return(default);
/// <summary>Creates a new <see cref="OutgoingRequestFrame"/> for an operation with a single non-struct /// parameter.</summary> /// <typeparam name="T">The type of the operation's parameter.</typeparam> /// <param name="proxy">A proxy to the target Ice object. This method uses the communicator, identity, facet, /// encoding and context of this proxy to create the request frame.</param> /// <param name="operation">The operation to invoke on the target Ice object.</param> /// <param name="idempotent">True when operation is idempotent, otherwise false.</param> /// <param name="compress">True if the request should be compressed, false otherwise.</param> /// <param name="format">The format to use when writing class instances in case <c>args</c> contains class /// instances.</param> /// <param name="context">An optional explicit context. When non null, it overrides both the context of the /// proxy and the communicator's current context (if any).</param> /// <param name="args">The argument(s) to write into the frame.</param> /// <param name="writer">The <see cref="OutputStreamWriter{T}"/> that writes the arguments into the frame. /// </param> /// <returns>A new OutgoingRequestFrame.</returns> public static OutgoingRequestFrame WithArgs <T>( IObjectPrx proxy, string operation, bool idempotent, bool compress, FormatType format, IReadOnlyDictionary <string, string>?context, T args, OutputStreamWriter <T> writer) { var request = new OutgoingRequestFrame(proxy, operation, idempotent, compress, context); var ostr = new OutputStream(proxy.Protocol.GetEncoding(), request.Data, request.PayloadStart, request.Encoding, format); writer(ostr, args); request.PayloadEnd = ostr.Finish(); if (compress && proxy.Encoding == Encoding.V20) { request.CompressPayload(); } return(request); }
private protected Task <TReturnValue> InvokeAsync(IObjectPrx prx, OutgoingRequestFrame request, IProgress <bool>?progress, CancellationToken cancel) { return(ReadReturnValueAsync(prx.InvokeAsync(request, oneway: false, progress, cancel), prx.Communicator, _reader));
public OutgoingAsync(IObjectPrx prx, IOutgoingAsyncCompletionCallback completionCallback, OutgoingRequestFrame requestFrame, bool oneway = false) : base(prx, completionCallback, requestFrame) { Encoding = Proxy.Encoding; Synchronous = false; IsOneway = oneway; IsIdempotent = requestFrame.IsIdempotent; }
protected ProxyOutgoingAsyncBase(IObjectPrx prx, IOutgoingAsyncCompletionCallback completionCallback, OutgoingRequestFrame requestFrame) : base(prx.Communicator, completionCallback) { Proxy = prx; IsOneway = false; _cnt = 0; _sent = false; RequestFrame = requestFrame; }
/// <summary>Sends a request asynchronously.</summary> /// <param name="proxy">The proxy for the target Ice object.</param> /// <param name="request">The outgoing request frame for this invocation. Usually this request frame should have /// been created using the same proxy, however some differences are acceptable, for example proxy can have /// different endpoints.</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 Task <IncomingResponseFrame> InvokeAsync(this IObjectPrx proxy, OutgoingRequestFrame request, bool oneway = false, IProgress <bool>?progress = null, CancellationToken cancel = default) { var completed = new IObjectPrx.InvokeTaskCompletionCallback(progress, cancel); new OutgoingAsync(proxy, completed, request, oneway: oneway).Invoke(request.Operation, request.Context, synchronous: false); return(completed.Task); }
/// <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 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); ValueTask <IncomingResponseFrame> task = proxy.InvokeAsync(forwardedRequest, oneway: oneway, progress, cancel); return(WaitResponseAsync(request, task));
/// <summary>Sends a request synchronously.</summary> /// <param name="proxy">The proxy for the target Ice object.</param> /// <param name="request">The outgoing request frame for this invocation. Usually this request frame should have /// been created using the same proxy, however some differences are acceptable, for example proxy can have /// different endpoints.</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> /// <returns>The response frame.</returns> public static IncomingResponseFrame Invoke(this IObjectPrx proxy, OutgoingRequestFrame request, bool oneway = false) { try { return(InvokeAsync(proxy, request, oneway, synchronous: true).Result); } catch (AggregateException ex) { Debug.Assert(ex.InnerException != null); throw ex.InnerException; } }
/// <summary>Creates an <see cref="OutgoingRequestFrame"/> for operation ice_isA.</summary> /// <param name="proxy">Proxy to the target Ice Object.</param> /// <param name="id">The type ID argument to write into the request.</param> /// <param name="context">The context to write into the request.</param> /// <returns>A new <see cref="OutgoingRequestFrame"/>.</returns> public static OutgoingRequestFrame IceIsA( IObjectPrx proxy, string id, IReadOnlyDictionary <string, string>?context) => OutgoingRequestFrame.WithArgs( proxy, "ice_isA", idempotent: true, compress: false, format: default, context, id, OutputStream.IceWriterFromString);
/// <summary>Create a new OutgoingRequestFrame.</summary> /// <param name="proxy">A proxy to the target Ice object. This method uses the communicator, identity, facet, /// encoding and context of this proxy to create the request frame.</param> /// <param name="operation">The operation to invoke on the target Ice object.</param> /// <param name="idempotent">True when operation is idempotent, otherwise false.</param> /// <param name="format">The format type used to marshal classes and exceptions, when this parameter is null /// the communicator's default format is used.</param> /// <param name="context">An optional explicit context. When non null, it overrides both the context of the /// proxy and the communicator's current context (if any).</param> /// <param name="value">The parameter to marshal in the frame.</param> /// <param name="writer">The delegate into marshal the parameter to the frame.</param> /// <returns>A new OutgoingRequestFrame</returns> public static OutgoingRequestFrame WithParamList <T>( IObjectPrx proxy, string operation, bool idempotent, FormatType?format, IReadOnlyDictionary <string, string>?context, T value, OutputStreamWriter <T> writer) { var request = new OutgoingRequestFrame(proxy, operation, idempotent, context); var ostr = new OutputStream(proxy.Protocol.GetEncoding(), request.Data, request._payloadStart, request.Encoding, format ?? proxy.Communicator.DefaultFormat); writer(ostr, value); request.Finish(ostr.Save()); return(request); }
/// <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)); }
internal static void TraceFrame(Communicator communicator, ReadOnlySpan <byte> header, OutgoingRequestFrame frame) => TraceRequest( "sending request", 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.Identity, frame.Facet, frame.Operation, frame.IsIdempotent, frame.Context, frame.Encoding);
internal static void TraceCollocatedFrame(Communicator communicator, byte messageType, int requestId, OutgoingRequestFrame frame) => TraceRequest( "sending request", communicator, messageType, 0, frame.Size + Ice1Definitions.HeaderSize + 4, requestId, frame.Identity, frame.Facet, frame.Operation, frame.IsIdempotent, frame.Context, frame.Encoding);
/// <summary>Creates a new <see cref="OutgoingRequestFrame"/> for an operation with a single non-struct /// parameter.</summary> /// <typeparam name="T">The type of the operation's parameter.</typeparam> /// <param name="proxy">A proxy to the target Ice object. This method uses the communicator, identity, facet, /// encoding and context of this proxy to create the request frame.</param> /// <param name="operation">The operation to invoke on the target Ice object.</param> /// <param name="idempotent">True when operation is idempotent, otherwise false.</param> /// <param name="compress">True if the request should be compressed, false otherwise.</param> /// <param name="format">The format to use when writing class instances in case <c>args</c> contains class /// instances.</param> /// <param name="context">An optional explicit context. When non null, it overrides both the context of the /// proxy and the communicator's current context (if any).</param> /// <param name="args">The argument(s) to write into the frame.</param> /// <param name="writer">The <see cref="OutputStreamWriter{T}"/> that writes the arguments into the frame. /// </param> /// <param name="cancel">A cancellation token that receives the cancellation requests.</param> /// <returns>A new OutgoingRequestFrame.</returns> public static OutgoingRequestFrame WithArgs <T>( IObjectPrx proxy, string operation, bool idempotent, bool compress, FormatType format, IReadOnlyDictionary <string, string>?context, T args, OutputStreamWriter <T> writer, CancellationToken cancel = default) { var request = new OutgoingRequestFrame(proxy, operation, idempotent, compress, context, cancel); var ostr = new OutputStream(proxy.Protocol.GetEncoding(), request.Payload, startAt: default,
internal static List <ArraySegment <byte> > GetRequestData(OutgoingRequestFrame frame, int requestId) { byte[] headerData = new byte[HeaderSize + 4]; RequestHeader.CopyTo(headerData.AsSpan()); OutputStream.WriteInt(frame.Size + HeaderSize + 4, headerData.AsSpan(10, 4)); OutputStream.WriteInt(requestId, headerData.AsSpan(HeaderSize, 4)); var data = new List <ArraySegment <byte> >() { headerData }; data.AddRange(frame.Data); return(data); }
/// <summary>Sends a request synchronously.</summary> /// <param name="proxy">The proxy for the target Ice object.</param> /// <param name="request">The outgoing request frame for this invocation. Usually this request frame should have /// been created using the same proxy, however some differences are acceptable, for example proxy can have /// different endpoints.</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> /// <returns>The response frame.</returns> public static IncomingResponseFrame Invoke(this IObjectPrx proxy, OutgoingRequestFrame request, bool oneway = false) { try { var completed = new IObjectPrx.InvokeTaskCompletionCallback(null, default); new OutgoingAsync(proxy, completed, request, oneway: oneway).Invoke(request.Operation, request.Context, synchronous: true); return(completed.Task.Result); } catch (AggregateException ex) { Debug.Assert(ex.InnerException != null); throw ex.InnerException; } }
internal static List <ArraySegment <byte> > GetRequestData(OutgoingRequestFrame frame, long streamId) { byte[] headerData = new byte[HeaderSize + 4]; RequestHeader.CopyTo(headerData.AsSpan()); OutputStream.WriteSize20(frame.Size + HeaderSize + 4, headerData.AsSpan(10, 4)); // TODO: Fix to support long streamId OutputStream.WriteInt((int)streamId, headerData.AsSpan(HeaderSize, 4)); var data = new List <ArraySegment <byte> >() { headerData }; data.AddRange(frame.Data); return(data); }
internal static void TraceFrame( Communicator communicator, ReadOnlySpan <byte> header, OutgoingRequestFrame frame) => TraceRequest( "sending request", communicator, frame.Protocol, header[8], // Frame type header[9], // Compression Status header.Slice(10, 4).ReadFixedLengthSize(frame.Protocol.GetEncoding()), // Request size header.Slice(14, 4).ReadInt(), // Request-Id frame.Identity, frame.Facet, frame.Operation, frame.IsIdempotent, frame.Context, frame.Encoding);
internal static void TraceCollocatedFrame( Communicator communicator, byte frameType, int requestId, OutgoingRequestFrame frame) => TraceRequest( "sending request", communicator, frame.Protocol, frameType, 0, frame.Size + Ice1Definitions.HeaderSize + 4, // TODO: where is this size coming from? requestId, frame.Identity, frame.Facet, frame.Operation, frame.IsIdempotent, frame.Context, frame.Encoding);
private async Task <OutgoingResponseFrame> DispatchAsync( OutgoingRequestFrame outgoingRequest, int requestId, CancellationToken cancel) { // Increase the direct count to prevent the object adapter from being destroyed while the dispatch is in // progress. This will also throw if the object adapter has been deactivated. _adapter.IncDirectCount(); try { var incomingRequest = new IncomingRequestFrame(outgoingRequest, _adapter.IncomingFrameSizeMax); var current = new Current(_adapter, incomingRequest, oneway: requestId == 0, cancel); return(await _adapter.DispatchAsync(incomingRequest, requestId, current).ConfigureAwait(false)); } finally { _adapter.DecDirectCount(); } }
/// <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))); } }
/// <summary>Creates an <see cref="OutgoingRequestFrame"/> for operation ice_ids.</summary> /// <param name="proxy">Proxy to the target Ice Object.</param> /// <param name="context">The context to write into the request.</param> /// <returns>A new <see cref="OutgoingRequestFrame"/>.</returns> public static OutgoingRequestFrame IceIds(IObjectPrx proxy, IReadOnlyDictionary <string, string>?context) => OutgoingRequestFrame.WithEmptyArgs(proxy, "ice_ids", idempotent: true, context);
// TODO avoid copy payload (ToArray) creates a copy, that should be possible when // the frame has a single segment. internal IncomingRequestFrame(OutgoingRequestFrame frame) : this(frame.Protocol, VectoredBufferExtensions.ToArray(frame.Data)) { }
/// <summary>Invokes a request on a proxy.</summary> /// <remarks>request.CancellationToken holds the cancellation token.</remarks> /// <param name="proxy">The proxy for the target Ice object.</param> /// <param name="request">The request frame.</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> /// <returns>A task holding the response frame.</returns> public static Task <IncomingResponseFrame> InvokeAsync( this IObjectPrx proxy, OutgoingRequestFrame request, bool oneway = false, IProgress <bool>?progress = null) => Reference.InvokeAsync(proxy, request, oneway, progress);
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(); } }
internal IncomingRequestFrame(OutgoingRequestFrame frame, int sizeMax) : this(frame.Protocol, frame.Data.AsArraySegment(), sizeMax) { }
private async Task <OutgoingResponseFrame> DispatchAsync( OutgoingRequestFrame outgoingRequest, int requestId, CancellationToken cancel) { // Increase the direct count to prevent the object adapter from being destroyed while the dispatch is in // progress. This will also throw if the object adapter has been deactivated. _adapter.IncDirectCount(); IDispatchObserver?dispatchObserver = null; try { var incomingRequest = new IncomingRequestFrame(outgoingRequest, _adapter.IncomingFrameSizeMax); var current = new Current(_adapter, incomingRequest, oneway: requestId == 0, cancel); // Then notify and set dispatch observer, if any. ICommunicatorObserver?communicatorObserver = _adapter.Communicator.Observer; if (communicatorObserver != null) { dispatchObserver = communicatorObserver.GetDispatchObserver(current, requestId, incomingRequest.Size); dispatchObserver?.Attach(); } OutgoingResponseFrame?outgoingResponseFrame = null; try { IObject?servant = current.Adapter.Find(current.Identity, current.Facet); if (servant == null) { throw new ObjectNotExistException(current.Identity, current.Facet, current.Operation); } ValueTask <OutgoingResponseFrame> vt = servant.DispatchAsync(incomingRequest, current); if (requestId != 0) { // We don't use the cancelable WaitAsync for the await here. The asynchronous dispatch is // not completed yet and we want to make sure the observer is detached only when the dispatch // completes, not when the caller cancels the request. outgoingResponseFrame = await vt.ConfigureAwait(false); outgoingResponseFrame.Finish(); dispatchObserver?.Reply(outgoingResponseFrame.Size); } } catch (Exception ex) { RemoteException actualEx; if (ex is RemoteException remoteEx && !remoteEx.ConvertToUnhandled) { actualEx = remoteEx; } else { actualEx = new UnhandledException(current.Identity, current.Facet, current.Operation, ex); } Incoming.ReportException(actualEx, dispatchObserver, current); if (requestId != 0) { outgoingResponseFrame = new OutgoingResponseFrame(incomingRequest, actualEx); outgoingResponseFrame.Finish(); dispatchObserver?.Reply(outgoingResponseFrame.Size); } }
/// <summary>Creates an <see cref="OutgoingRequestFrame"/> for operation ice_ping.</summary> /// <param name="proxy">Proxy to the target Ice Object.</param> /// <param name="context">The context to write into the request.</param> /// <param name="cancel">A cancellation token that receives the cancellation requests.</param> /// <returns>A new <see cref="OutgoingRequestFrame"/>.</returns> public static OutgoingRequestFrame IcePing( IObjectPrx proxy, IReadOnlyDictionary <string, string>?context, CancellationToken cancel) => OutgoingRequestFrame.WithEmptyArgs(proxy, "ice_ping", idempotent: true, context, cancel);
private protected TReturnValue Invoke(IObjectPrx prx, OutgoingRequestFrame request) => prx.Invoke(request, oneway: false).ReadReturnValue(prx.Communicator, _reader);