protected Task ShutdownAsync(QbservableProtocolShutdownReason reason) { Contract.Ensures(Contract.Result <Task>() != null); ShutdownReason |= reason; return(ShutdownCoreAsync()); }
private TcpClientTermination(SerializationInfo info, StreamingContext context) { localEndPoint = (EndPoint)info.GetValue("localEndPoint", typeof(EndPoint)); remoteEndPoint = (EndPoint)info.GetValue("remoteEndPoint", typeof(EndPoint)); duration = (TimeSpan)info.GetValue("duration", typeof(TimeSpan)); reason = (QbservableProtocolShutdownReason)info.GetValue("reason", typeof(QbservableProtocolShutdownReason)); exceptions = ((List <Exception>)info.GetValue("rawExceptions", typeof(List <Exception>))) .Select(ExceptionDispatchInfo.Capture) .ToList() .AsReadOnly(); }
public void CancelAllCommunication(ExceptionDispatchInfo exception) { exceptions.Add(exception); if (!protocolCancellation.IsCancellationRequested) { ShutdownReason |= QbservableProtocolShutdownReason.ServerError; CancelAllCommunication(); } }
public WebSocketClientTermination( Uri uri, string origin, TimeSpan duration, QbservableProtocolShutdownReason reason, IEnumerable <ExceptionDispatchInfo> exceptions) : base(duration, reason, exceptions) { Contract.Requires(uri != null); Contract.Requires(duration >= TimeSpan.Zero); Uri = uri; Origin = origin; }
public ClientTermination( TimeSpan duration, QbservableProtocolShutdownReason reason, IEnumerable <ExceptionDispatchInfo> exceptions) { Contract.Requires(duration >= TimeSpan.Zero); Duration = duration; Reason = reason; Exceptions = (exceptions ?? Enumerable.Empty <ExceptionDispatchInfo>()) .Distinct(ExceptionDispatchInfoEqualityComparer.Instance) .ToList() .AsReadOnly(); }
public TcpClientTermination( EndPoint localEndPoint, EndPoint remoteEndPoint, TimeSpan duration, QbservableProtocolShutdownReason reason, IEnumerable <ExceptionDispatchInfo> exceptions) : base(duration, reason, exceptions) { Contract.Requires(localEndPoint != null); Contract.Requires(remoteEndPoint != null); Contract.Requires(duration >= TimeSpan.Zero); LocalEndPoint = localEndPoint; RemoteEndPoint = remoteEndPoint; }
public TcpClientTermination( EndPoint localEndPoint, EndPoint remoteEndPoint, TimeSpan duration, QbservableProtocolShutdownReason reason, IEnumerable <ExceptionDispatchInfo> exceptions) { this.localEndPoint = localEndPoint; this.remoteEndPoint = remoteEndPoint; this.duration = duration; this.reason = reason; this.exceptions = (exceptions ?? Enumerable.Empty <ExceptionDispatchInfo>()) .Distinct(ExceptionDispatchInfoEqualityComparer.Instance) .ToList() .AsReadOnly(); }
private async void Shutdown(WebSocket socket, QbservableProtocolShutdownReason reason, object id = null) { Contract.Requires(socket != null); try { if (IsConnectedSafe(socket)) { if (IsServer) { Disconnecting(idOverride: id); await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, reason.ToString(), CancellationToken.None).ConfigureAwait(false); } else { Stopping(); await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, reason.ToString(), CancellationToken.None).ConfigureAwait(false); } } } catch (ObjectDisposedException) { } catch (WebSocketException ex) { QactiveTraceSources.Qactive.TraceEvent(TraceEventType.Warning, 0, Id + " - " + ex); } finally { socket.Dispose(); if (IsServer) { Disconnected(idOverride: id); } else { Stopped(); } } }
protected async Task ShutdownAsync(QbservableProtocolShutdownReason reason) { ShutdownReason = reason; await ShutdownCoreAsync().ConfigureAwait(false); }
protected override QbservableProtocolShutdownReason GetShutdownReason(TestMessage message, QbservableProtocolShutdownReason defaultReason) => defaultReason;
private static QbservableProtocolShutdownReason GetShutdownReason(QbservableMessage message, QbservableProtocolShutdownReason defaultReason) { if (message.Data.Length > 0) { return((QbservableProtocolShutdownReason)message.Data[0]); } else { return(defaultReason); } }
protected void ShutdownWithoutResponse(QbservableProtocolShutdownReason reason) { ShutdownReason |= reason; CancelAllCommunication(); }
protected abstract QbservableProtocolShutdownReason GetShutdownReason(TMessage message, QbservableProtocolShutdownReason defaultReason);
private async Task SendObservableAsync(object untypedObservable, Type dataType, bool sendServerErrorsToClients, CancellationToken cancel) { Contract.Requires(untypedObservable != null); Contract.Requires(dataType != null); var networkErrors = new ConcurrentBag <ExceptionDispatchInfo>(); ExceptionDispatchInfo expressionSecurityError = null; ExceptionDispatchInfo qbservableSubscriptionError = null; ExceptionDispatchInfo qbservableError = null; var terminationKind = NotificationKind.OnCompleted; try { var cancelSubscription = new CancellationTokenSource(); cancel.Register(cancelSubscription.Cancel); IObservable <object> observable; #if CAS new PermissionSet(PermissionState.Unrestricted).Assert(); #endif try { observable = dataType.UpCast(untypedObservable); } finally { #if CAS PermissionSet.RevertAssert(); #endif } await observable .TraceSubscriptions(ServiceObservableName, true, true, ClientId) .TraceNotifications(ServiceObservableName, true, true, ClientId) .ForEachAsync( async data => { try { await ServerSendAsync(NotificationKind.OnNext, data).ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { /* Collecting exceptions handles a possible race condition. Since this code is using a fire-and-forget model to * subscribe to the observable, due to the async OnNext handler, it's possible that more than one SendAsync task * can be executing concurrently. As a result, canceling the cancelSubscription below does not guarantee that * this catch block won't run again. */ networkErrors.Add(ExceptionDispatchInfo.Capture(ex)); cancelSubscription.Cancel(); } }, cancelSubscription.Token) .ConfigureAwait(false); } catch (OperationCanceledException) { if (cancel.IsCancellationRequested && networkErrors.Count == 0) { throw; } } catch (ExpressionSecurityException ex) { ShutdownReason = QbservableProtocolShutdownReason.ExpressionSecurityViolation; expressionSecurityError = ExceptionDispatchInfo.Capture(ex); } catch (QbservableSubscriptionException ex) { ShutdownReason = QbservableProtocolShutdownReason.ExpressionSubscriptionException; qbservableSubscriptionError = ExceptionDispatchInfo.Capture(ex.InnerException ?? ex); } catch (TargetInvocationException ex) { if (ex.InnerException is QbservableSubscriptionException) { ShutdownReason = QbservableProtocolShutdownReason.ExpressionSubscriptionException; qbservableSubscriptionError = ExceptionDispatchInfo.Capture(ex.InnerException.InnerException ?? ex.InnerException); } else { qbservableSubscriptionError = ExceptionDispatchInfo.Capture(ex); } } catch (Exception ex) { terminationKind = NotificationKind.OnError; qbservableError = ExceptionDispatchInfo.Capture(ex); } var error = expressionSecurityError ?? qbservableSubscriptionError; if (error != null) { if (networkErrors.Count > 0) { // It's not technically a network error, but since the client can't receive it anyway add it so that it's thrown later networkErrors.Add(error); } else { if (sendServerErrorsToClients || expressionSecurityError != null) { var exception = expressionSecurityError == null ? error.SourceException : new SecurityException(error.SourceException.Message); // Remove stack trace await ServerSendAsync(NotificationKind.OnError, exception).ConfigureAwait(false); } error.Throw(); } } /* There's an acceptable race condition here whereby ForEachAsync is canceled by the external cancellation token though * it's still executing a fire-and-forget task. It's possible for the fire-and-forget task to throw before seeing the * cancellation, yet after the following code has already executed. In that case, since the cancellation was requested * externally, it's acceptable for the cancellation to simply beat the send error, thus the error can safely be ignored. */ if (networkErrors.Count > 0) { throw new AggregateException(networkErrors.Select(e => e.SourceException)); } else { try { await ServerSendAsync(terminationKind, (qbservableError == null ? null : qbservableError.SourceException)).ConfigureAwait(false); } catch (OperationCanceledException) { } if (qbservableError != null) { qbservableError.Throw(); } } }
public async Task ExecuteServerAsync(IQbservableProvider provider) { Task receivingAsync = null; ExceptionDispatchInfo fatalException = null; try { await InitializeSinksAsync().ConfigureAwait(false); var input = await ServerReceiveQueryAsync().ConfigureAwait(false); receivingAsync = ServerReceiveAsync(); try { await ExecuteServerQueryAsync(input, provider).ConfigureAwait(false); } catch (OperationCanceledException) { throw; } catch (Exception ex) { ShutdownReason |= QbservableProtocolShutdownReason.BadClientRequest; fatalException = ExceptionDispatchInfo.Capture(ex); CancelAllCommunication(fatalException); } } catch (OperationCanceledException ex) { var exception = TryRollupExceptions(); if (exception != null) { ShutdownReason |= QbservableProtocolShutdownReason.ServerError; fatalException = exception; } ShutdownReason |= QbservableProtocolShutdownReason.ClientTerminated; fatalException = ExceptionDispatchInfo.Capture(ex); } catch (Exception ex) { fatalException = ExceptionDispatchInfo.Capture(ex); CancelAllCommunication(fatalException); } if (receivingAsync != null) { try { await receivingAsync.ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { AddError(ExceptionDispatchInfo.Capture(ex)); } } if (fatalException != null) { fatalException.Throw(); } }
protected override QbservableProtocolShutdownReason GetShutdownReason(TMessage message, QbservableProtocolShutdownReason defaultReason) { Contract.Requires(message != null); return(default(QbservableProtocolShutdownReason)); }
protected override QbservableProtocolShutdownReason GetShutdownReason(StreamMessage message, QbservableProtocolShutdownReason defaultReason) => message.Data.Length > 0 ? (QbservableProtocolShutdownReason)message.Data[0] : defaultReason;