Пример #1
0
        private void OnJsonRpcDisconnected(JsonRpcDisconnectedEventArgs eventArgs)
        {
            EventHandler <JsonRpcDisconnectedEventArgs> handlersToInvoke = null;

            lock (this.disconnectedEventLock)
            {
                if (!this.hasDisconnectedEventBeenRaised)
                {
                    this.hasDisconnectedEventBeenRaised = true;
                    handlersToInvoke    = this.onDisconnected;
                    this.onDisconnected = null;
                }
            }

            try
            {
                // Fire the event first so that subscribers can interact with a non-disposed stream
                handlersToInvoke?.Invoke(this, eventArgs);
            }
            finally
            {
                // Dispose the stream and cancel pending requests in the finally block
                // So this is executed even if Disconnected event handler throws.
                this.disposeCts.Cancel();
                this.MessageHandler.Dispose();
                this.CancelPendingRequests();
            }
        }
Пример #2
0
 /// <summary>
 /// Disposes managed and native resources held by this instance.
 /// </summary>
 /// <param name="disposing"><c>true</c> if being disposed; <c>false</c> if being finalized.</param>
 protected virtual void Dispose(bool disposing)
 {
     if (!this.disposed)
     {
         this.disposed = true;
         if (disposing)
         {
             var disconnectedEventArgs = new JsonRpcDisconnectedEventArgs(Resources.StreamDisposed, DisconnectedReason.Disposed);
             this.OnJsonRpcDisconnected(disconnectedEventArgs);
         }
     }
 }
Пример #3
0
        private async Task HandleRpcAsync(string json)
        {
            JsonRpcMessage rpc;

            try
            {
                rpc = JsonRpcMessage.FromJson(json, this.MessageJsonDeserializerSettings);
            }
            catch (JsonException exception)
            {
                var e = new JsonRpcDisconnectedEventArgs(string.Format(CultureInfo.CurrentCulture, Resources.FailureDeserializingJsonRpc, json, exception.Message),
                                                         DisconnectedReason.ParseError,
                                                         json,
                                                         exception);

                // Fatal error. Raise disconnected event.
                this.OnJsonRpcDisconnected(e);
                return;
            }

            if (rpc.IsRequest)
            {
                // We can't accept a request that requires a response if we can't write.
                Verify.Operation(rpc.IsNotification || this.MessageHandler.CanWrite, Resources.StreamMustBeWriteable);

                if (rpc.IsNotification && rpc.Method == CancelRequestSpecialMethod)
                {
                    this.HandleCancellationNotification(rpc);
                    return;
                }

                JsonRpcMessage result = await this.DispatchIncomingRequestAsync(rpc, this.JsonSerializer).ConfigureAwait(false);

                if (!rpc.IsNotification)
                {
                    try
                    {
                        await this.TransmitAsync(result, this.disposeCts.Token).ConfigureAwait(false);
                    }
                    catch (OperationCanceledException)
                    {
                    }
                    catch (ObjectDisposedException)
                    {
                    }
                    catch (Exception exception)
                    {
                        var e = new JsonRpcDisconnectedEventArgs(string.Format(CultureInfo.CurrentCulture, Resources.ErrorWritingJsonRpcResult, exception.GetType().Name, exception.Message),
                                                                 DisconnectedReason.StreamError,
                                                                 exception);

                        // Fatal error. Raise disconnected event.
                        this.OnJsonRpcDisconnected(e);
                    }
                }

                return;
            }

            if (rpc.IsResponse)
            {
                OutstandingCallData data = null;
                lock (this.dispatcherMapLock)
                {
                    int id = (int)rpc.Id;
                    if (this.resultDispatcherMap.TryGetValue(id, out data))
                    {
                        this.resultDispatcherMap.Remove(id);
                    }
                }

                if (data != null)
                {
                    data.CompletionHandler(rpc);
                }

                return;
            }

            // Not a request or return. Raise disconnected event.
            this.OnJsonRpcDisconnected(new JsonRpcDisconnectedEventArgs(
                                           string.Format(CultureInfo.CurrentCulture, Resources.UnrecognizedIncomingJsonRpc, json),
                                           DisconnectedReason.ParseError,
                                           json));
        }
Пример #4
0
        private async Task ReadAndHandleRequestsAsync()
        {
            JsonRpcDisconnectedEventArgs disconnectedEventArgs = null;

            try
            {
                while (!this.disposed)
                {
                    string json = null;
                    try
                    {
                        json = await this.MessageHandler.ReadAsync(this.disposeCts.Token).ConfigureAwait(false);
                    }
                    catch (OperationCanceledException)
                    {
                    }
                    catch (ObjectDisposedException)
                    {
                    }
                    catch (Exception exception)
                    {
                        var e = new JsonRpcDisconnectedEventArgs(string.Format(CultureInfo.CurrentCulture, Resources.ReadingJsonRpcStreamFailed, exception.GetType().Name, exception.Message),
                                                                 DisconnectedReason.StreamError,
                                                                 exception);

                        // Fatal error. Raise disconnected event.
                        this.OnJsonRpcDisconnected(e);
                        break;
                    }

                    if (json == null)
                    {
                        // End of stream reached
                        disconnectedEventArgs = new JsonRpcDisconnectedEventArgs(Resources.ReachedEndOfStream, DisconnectedReason.Disposed);
                        break;
                    }

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

                    Task.Run(async delegate
                    {
                        try
                        {
                            await this.HandleRpcAsync(json).ConfigureAwait(false);
                        }
                        catch (Exception exception)
                        {
                            var eventArgs = new JsonRpcDisconnectedEventArgs(
                                string.Format(CultureInfo.CurrentCulture, Resources.UnexpectedErrorProcessingJsonRpc, json, exception.Message),
                                DisconnectedReason.ParseError,
                                json,
                                exception);

                            // Fatal error. Raise disconnected event.
                            this.OnJsonRpcDisconnected(eventArgs);
                        }
                    }, this.disposeCts.Token);

#pragma warning restore CS4014
                }
            }
            finally
            {
                if (disconnectedEventArgs == null)
                {
                    disconnectedEventArgs = new JsonRpcDisconnectedEventArgs(Resources.StreamDisposed, DisconnectedReason.Disposed);
                }

                this.OnJsonRpcDisconnected(disconnectedEventArgs);
            }
        }