protected QbservableProtocol(QbservableServiceOptions serviceOptions, CancellationToken cancel) { Contract.Requires(serviceOptions != null); Contract.Ensures(!IsClient); ServiceOptions = serviceOptions; cancel.Register(protocolCancellation.Cancel, useSynchronizationContext: false); }
internal QbservableProtocol(NetworkStream stream, IRemotingFormatter formatter, QbservableServiceOptions serviceOptions, CancellationToken cancel) : this(stream, formatter, cancel) { Contract.Ensures(!IsClient); this.serviceOptions = serviceOptions; this.isClient = false; }
public static IObservable <TcpClientTermination> CreateService <TSource, TResult>( IPEndPoint endPoint, IRemotingFormatter formatter, QbservableServiceOptions options, Func <IObservable <TSource>, IQbservable <TResult> > service) { return(CreateService <TSource, TResult>(endPoint, () => formatter, options, service)); }
internal QbservableProtocol(TSource source, QbservableServiceOptions serviceOptions, CancellationToken cancel) : base(serviceOptions, cancel) { Contract.Requires(source != null); Contract.Requires(serviceOptions != null); Contract.Ensures(!IsClient); Source = source; }
public TcpServerQbservableProvider( QbservableProtocol protocol, QbservableServiceOptions options, Func <object, IQbservable <TSource> > sourceSelector) { this.protocol = protocol; this.options = options; this.sourceSelector = sourceSelector; }
public static IObservable <TcpClientTermination> CreateService <TSource, TResult>( AppDomainSetup appDomainSetup, IPEndPoint endPoint, QbservableServiceOptions options, Func <IObservable <TSource>, IQbservable <TResult> > service, [CallerMemberName] string appDomainBaseName = null, params Assembly[] fullTrustAssemblies) { return(CreateService <TSource, TResult>(appDomainSetup, endPoint, CreateDefaultFormatter, options, service, appDomainBaseName, fullTrustAssemblies)); }
public QbservableServiceOptions(QbservableServiceOptions clone) { Contract.Requires(clone != null); Contract.Ensures(!IsFrozen); sendServerErrorsToClients = clone.sendServerErrorsToClients; enableDuplex = clone.enableDuplex; allowExpressionsUnrestricted = clone.allowExpressionsUnrestricted; expressionOptions = clone.expressionOptions; evaluationContext = clone.evaluationContext; }
public static IObservable <TcpClientTermination> CreateService <TSource, TResult>( AppDomainSetup appDomainSetup, IPEndPoint endPoint, Func <IRemotingFormatter> formatterFactory, QbservableServiceOptions options, Func <IObservable <TSource>, IObservable <TResult> > service, [CallerMemberName] string appDomainBaseName = null, params Assembly[] fullTrustAssemblies) { return(CreateService <TSource, TResult>(appDomainSetup, endPoint, formatterFactory, options, new QbservableServiceConverter <TSource, TResult>(service).Convert, appDomainBaseName, fullTrustAssemblies)); }
public IObservable <TcpClientTermination> CreateService( IPEndPoint endPoint, QbservableServiceOptions options, CreateServiceProxyDelegates <TSource, TResult> delegates) { new PermissionSet(PermissionState.Unrestricted).Assert(); try { InitializeInFullTrust(); } finally { PermissionSet.RevertAssert(); } Func <IRemotingFormatter> formatterFactory; Func <IObservable <TSource>, IQbservable <TResult> > service; /* Retrieving a cross-domain delegate always fails with a SecurityException due to * a Demand for ReflectionPermission, regardless of whether that permission is asserted * here or even whether full trust is asserted (commented line). It is unclear why the * assertions don't work. The only solution appears to be that the delegates must * point to public members. * * (Alternatively, adding the ReflectionPermission to the minimum permission set of the * AppDomain works as well, but it's more secure to disallow it entirely to prevent * reflection from executing within clients' expression trees, just in case the host * relaxes the service options to allow unrestricted expressions constrained only by * the minimum AppDomain permissions; i.e., The Principle of Least Surprise.) * * new PermissionSet(PermissionState.Unrestricted).Assert(); */ try { formatterFactory = delegates.FormatterFactory; service = delegates.Service; } catch (SecurityException ex) { throw new ArgumentException(Errors.CreateServiceDelegatesNotPublic, ex); } finally { /* This line is unnecessary - see comments above. * PermissionSet.RevertAssert(); */ } return(QbservableTcpServer .CreateService(endPoint, formatterFactory, options, service) .RemotableWithoutConfiguration()); }
public static IObservable <ClientTermination> CreateService <TSource, TResult>( IQactiveProvider provider, QbservableServiceOptions options, Func <IObservable <TSource>, IObservable <TResult> > service) { Contract.Requires(provider != null); Contract.Requires(options != null); Contract.Requires(service != null); Contract.Ensures(Contract.Result <IObservable <ClientTermination> >() != null); return(CreateService <TSource, TResult>(provider, options, request => service(request).AsQbservable())); }
public static IObservable <ClientTermination> ServeTcp <TSource>( this IQbservable <TSource> source, IPEndPoint endPoint, QbservableServiceOptions options) { Contract.Requires(source != null); Contract.Requires(endPoint != null); Contract.Requires(options != null); Contract.Ensures(Contract.Result <IObservable <ClientTermination> >() != null); return(TcpQbservableServer.CreateService <object, TSource>(endPoint, options, _ => source)); }
public static IObservable <ClientTermination> CreateService <TSource, TResult>( Uri uri, QbservableServiceOptions options, Func <IObservable <TSource>, IQbservable <TResult> > service) { Contract.Requires(uri != null); Contract.Requires(options != null); Contract.Requires(service != null); Contract.Ensures(Contract.Result <IObservable <ClientTermination> >() != null); return(QbservableServer.CreateService(WebSocketQactiveProvider.Server(uri), options, service)); }
public static IObservable <ClientTermination> CreateService <TSource, TResult>( IPEndPoint endPoint, QbservableServiceOptions options, Func <IObservable <TSource>, IQbservable <TResult> > service) { Contract.Requires(endPoint != null); Contract.Requires(options != null); Contract.Requires(service != null); Contract.Ensures(Contract.Result <IObservable <ClientTermination> >() != null); return(QbservableServer.CreateService(TcpQactiveProvider.Server(endPoint), options, service)); }
public static IObservable <ClientTermination> ServeWebSocket <TSource>( this IQbservable <TSource> source, Uri uri, QbservableServiceOptions options) { Contract.Requires(source != null); Contract.Requires(uri != null); Contract.Requires(options != null); Contract.Ensures(Contract.Result <IObservable <ClientTermination> >() != null); return(WebSocketQbservableServer.CreateService <object, TSource>(uri, options, _ => source)); }
public StreamQbservableProtocol(Stream stream, IRemotingFormatter formatter, QbservableServiceOptions serviceOptions, CancellationToken cancel) : base(stream, serviceOptions, cancel) { Contract.Requires(stream != null); Contract.Requires(formatter != null); Contract.Requires(serviceOptions != null); this.formatter = formatter; sendQ.UnhandledExceptions.Subscribe(AddError); receiveQ.UnhandledExceptions.Subscribe(AddError); }
public static IObservable <TcpClientTermination> CreateService <TSource, TResult>( AppDomainSetup appDomainSetup, PermissionSet permissions, IPEndPoint endPoint, Func <IRemotingFormatter> formatterFactory, QbservableServiceOptions options, Func <IObservable <TSource>, IQbservable <TResult> > service, [CallerMemberName] string appDomainBaseName = null, params Assembly[] fullTrustAssemblies) { var minimumPermissions = new PermissionSet(PermissionState.None); minimumPermissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); minimumPermissions.AddPermission(new SocketPermission(NetworkAccess.Accept, TransportType.Tcp, endPoint.Address.ToString(), endPoint.Port)); var entryAssembly = Assembly.GetEntryAssembly(); var domain = AppDomain.CreateDomain( Interlocked.Increment(ref appDomainNumber) + ':' + appDomainBaseName, null, appDomainSetup, minimumPermissions.Union(permissions), new[] { typeof(QbservableTcpServer).Assembly.Evidence.GetHostEvidence <StrongName>(), typeof(System.Reactive.Linq.Observable).Assembly.Evidence.GetHostEvidence <StrongName>(), typeof(System.Reactive.Linq.Qbservable).Assembly.Evidence.GetHostEvidence <StrongName>(), typeof(System.Reactive.Notification).Assembly.Evidence.GetHostEvidence <StrongName>(), typeof(System.Reactive.IEventPattern <,>).Assembly.Evidence.GetHostEvidence <StrongName>(), typeof(System.Reactive.Concurrency.TaskPoolScheduler).Assembly.Evidence.GetHostEvidence <StrongName>() } .Concat(entryAssembly == null ? new StrongName[0] : new[] { entryAssembly.Evidence.GetHostEvidence <StrongName>() }) .Concat(fullTrustAssemblies.Select(assembly => assembly.Evidence.GetHostEvidence <StrongName>())) .ToArray()); try { var handle = Activator.CreateInstanceFrom( domain, typeof(CreateServiceProxy <TSource, TResult>).Assembly.ManifestModule.FullyQualifiedName, typeof(CreateServiceProxy <TSource, TResult>).FullName); var proxy = (CreateServiceProxy <TSource, TResult>)handle.Unwrap(); return(proxy.CreateService(endPoint, options, new CreateServiceProxyDelegates <TSource, TResult>(formatterFactory, service)) .Finally(() => AppDomain.Unload(domain))); } catch { AppDomain.Unload(domain); throw; } }
public ServerQbservableProvider( IQbservableProtocol protocol, QbservableServiceOptions options, Func <object, IQbservable <TSource> > sourceSelector) { Contract.Requires(protocol != null); Contract.Requires(options != null); Contract.Requires(sourceSelector != null); Protocol = protocol; Options = options; this.sourceSelector = sourceSelector; }
public static IObservable <TcpClientTermination> CreateService <TSource, TResult>( AppDomainSetup appDomainSetup, IPEndPoint endPoint, Func <IRemotingFormatter> formatterFactory, QbservableServiceOptions options, Func <IObservable <TSource>, IQbservable <TResult> > service, [CallerMemberName] string appDomainBaseName = null, params Assembly[] fullTrustAssemblies) { var permissions = new PermissionSet(PermissionState.None); return(CreateService <TSource, TResult>(appDomainSetup, permissions, endPoint, formatterFactory, options, service, appDomainBaseName, fullTrustAssemblies)); }
public static IObservable <ClientTermination> ServeQbservableTcp <TSource>( this IObservable <TSource> source, IPEndPoint endPoint, ITcpQactiveProviderTransportInitializer transportInitializer, QbservableServiceOptions options) { Contract.Requires(source != null); Contract.Requires(endPoint != null); Contract.Requires(transportInitializer != null); Contract.Requires(options != null); Contract.Ensures(Contract.Result <IObservable <ClientTermination> >() != null); return(TcpQbservableServer.CreateService <object, TSource>(endPoint, transportInitializer, options, _ => source)); }
public static IObservable <ClientTermination> ServeQbservableWebSocket <TSource>( this IObservable <TSource> source, Uri uri, IWebSocketQactiveProviderTransportInitializer transportInitializer, QbservableServiceOptions options) { Contract.Requires(source != null); Contract.Requires(uri != null); Contract.Requires(transportInitializer != null); Contract.Requires(options != null); Contract.Ensures(Contract.Result <IObservable <ClientTermination> >() != null); return(WebSocketQbservableServer.CreateService <object, TSource>(uri, transportInitializer, options, _ => source)); }
public override IObservable <ClientTermination> Listen(QbservableServiceOptions options, Func <IQbservableProtocol, IParameterizedQbservableProvider> providerFactory) { var l = new HttpListener() { Prefixes = { Uri.ToString() } }; return(from listener in Observable.Return(l) .Do(listener => { Starting(); listener.Start(); if (transportInitializer != null) { transportInitializer.StartedListener(serverNumber.Value, Uri); } Started(); }) from context in Observable.FromAsync(listener.GetContextAsync) .SelectMany(context => context.AcceptWebSocketAsync(protocol)) .Repeat() .Finally(() => { Stopping(); listener.Stop(); if (transportInitializer != null) { transportInitializer.StoppedListener(serverNumber.Value, Uri); } Stopped(); }) let capturedId = new CapturedId(Id + " C" + Interlocked.Increment(ref lastServerClientNumber) + " " + context.Origin) let capturedShutdownReason = new CapturedShutdownReason() from termination in Observable.StartAsync(cancel => AcceptAsync(context, capturedId, capturedShutdownReason, options, providerFactory, cancel)) .Finally(() => Shutdown(context.WebSocket, capturedShutdownReason.Value, capturedId.Value)) select termination); }
public static IObservable <ClientTermination> CreateService <TSource, TResult>( IQactiveProvider provider, QbservableServiceOptions options, Func <IObservable <TSource>, IQbservable <TResult> > service) { Contract.Requires(provider != null); Contract.Requires(options != null); Contract.Requires(service != null); Contract.Ensures(Contract.Result <IObservable <ClientTermination> >() != null); return(provider.Listen( options, protocol => new ServerQbservableProvider <TResult>( protocol, options, argument => argument == null && typeof(TSource).GetIsValueType() ? service(Observable.Return(default(TSource))) : service(Observable.Return((TSource)argument))))); }
public SecurityExpressionVisitor(QbservableServiceOptions serviceOptions) { this.options = serviceOptions.ExpressionOptions; this.context = serviceOptions.EvaluationContext; if (options.HasFlag(ExpressionOptions.AllowTypeTests) && options.HasFlag(ExpressionOptions.AllowExplicitConversions)) { context.EnsureHasKnownOperator("Cast"); context.EnsureHasKnownOperator("OfType"); } if (options.HasFlag(ExpressionOptions.AllowCatchBlocks)) { context.EnsureHasKnownOperator("Catch"); context.EnsureHasKnownOperator("OnErrorResumeNext"); context.EnsureHasKnownOperator("Retry"); } }
public SecurityExpressionVisitor(QbservableServiceOptions serviceOptions) { Contract.Requires(serviceOptions != null); Options = serviceOptions.ExpressionOptions; Context = serviceOptions.EvaluationContext; if (Options.HasFlag(ExpressionOptions.AllowTypeTests) && Options.HasFlag(ExpressionOptions.AllowExplicitConversions)) { Context.EnsureHasKnownOperator("Cast"); Context.EnsureHasKnownOperator("OfType"); } if (Options.HasFlag(ExpressionOptions.AllowCatchBlocks)) { Context.EnsureHasKnownOperator("Catch"); Context.EnsureHasKnownOperator("OnErrorResumeNext"); Context.EnsureHasKnownOperator("Retry"); } }
public override IObservable <ClientTermination> Listen(QbservableServiceOptions options, Func <IQbservableProtocol, IParameterizedQbservableProvider> providerFactory) { return(from listener in Observable.Return(new TcpListener(EndPoint)) .Do(listener => { Starting(); listener.Start(); if (transportInitializer != null) { transportInitializer.StartedListener(serverNumber.Value, listener.LocalEndpoint); } Started(); }) from client in Observable.FromAsync(listener.AcceptTcpClientAsync).Repeat() .Finally(() => { Stopping(); var endPoint = listener.LocalEndpoint; listener.Stop(); if (transportInitializer != null) { transportInitializer.StoppedListener(serverNumber.Value, endPoint); } Stopped(); }) let capturedId = new CapturedId(Id + " C" + Interlocked.Increment(ref lastServerClientNumber) + " " + client.Client.RemoteEndPoint) from termination in Observable.StartAsync(cancel => AcceptAsync(client, capturedId, options, providerFactory, cancel)) .Finally(() => Shutdown(client.Client, capturedId.Value)) select termination); }
protected QbservableProtocol(NetworkStream stream, IRemotingFormatter formatter, QbservableServiceOptions serviceOptions, CancellationToken cancel) : base(stream, formatter, serviceOptions, cancel) { Contract.Ensures(!IsClient); }
private static async Task <IStreamQbservableProtocol> NegotiateServerAsync(object baseId, Stream stream, IRemotingFormatter formatter, QbservableServiceOptions serviceOptions, CancellationToken cancel) { Contract.Requires(stream != null); Contract.Requires(formatter != null); Contract.Requires(serviceOptions != null); var protocol = StreamQbservableProtocolFactory.CreateServer(stream, formatter, serviceOptions, cancel); var lengthBuffer = new byte[4]; await protocol.ReceiveAsync(lengthBuffer, 0, 4).ConfigureAwait(false); var length = BitConverter.ToInt32(lengthBuffer, 0); if (length <= 0 || length > 255) { throw new InvalidOperationException("Invalid client ID received. (" + length + " bytes)"); } var clientIdBuffer = new byte[length]; await protocol.ReceiveAsync(clientIdBuffer, 0, clientIdBuffer.Length).ConfigureAwait(false); var clientId = Encoding.ASCII.GetString(clientIdBuffer); if (clientId == null || string.IsNullOrWhiteSpace(clientId)) { throw new InvalidOperationException("Invalid client ID received (empty or only whitespace)."); } await protocol.SendAsync(clientIdBuffer, 0, clientIdBuffer.Length).ConfigureAwait(false); protocol.ClientId = baseId + " (" + clientId + ")"; return(protocol); }
private async Task <TcpClientTermination> AcceptAsync( TcpClient client, CapturedId capturedId, QbservableServiceOptions options, Func <IQbservableProtocol, IParameterizedQbservableProvider> providerFactory, CancellationToken cancel) { Contract.Requires(client != null); Contract.Requires(capturedId != null); Contract.Requires(options != null); Contract.Requires(providerFactory != null); ReceivingConnection(idOverride: capturedId.Value); // These default settings enable a proper graceful shutdown. DisconnectAsync is used instead of Close on the server-side to request // that the client terminates the connection ASAP. This is important because it prevents the server-side socket from going into a // TIME_WAIT state rather than the client. The linger option is meant to ensure that any outgoing data, such as an exception, is // completely transmitted to the client before the socket terminates. The seconds specified is arbitrary, though chosen to be large // enough to transfer any remaining data successfully and small enough to cause a timely disconnection. A custom prepareSocket // implementation can always change it via SetSocketOption, if necessary. // // https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.disconnect(v=vs.110).aspx client.LingerState.Enabled = true; client.LingerState.LingerTime = LingerTimeInSeconds; prepareSocket(client.Client); var watch = Stopwatch.StartNew(); var localEndPoint = client.Client.LocalEndPoint; var remoteEndPoint = client.Client.RemoteEndPoint; var exceptions = new List <ExceptionDispatchInfo>(); var shutdownReason = QbservableProtocolShutdownReason.None; try { using (var stream = new NetworkStream(client.Client, ownsSocket: false)) using (var protocol = await NegotiateServerAsync(capturedId.Value, stream, formatterFactory(), options, cancel).ConfigureAwait(false)) { capturedId.Value = protocol.ClientId; var provider = providerFactory(protocol); ReceivedConnection(idOverride: capturedId.Value); try { await protocol.ExecuteServerAsync(provider).ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { exceptions.Add(ExceptionDispatchInfo.Capture(ex)); } finally { shutdownReason = protocol.ShutdownReason; } var protocolExceptions = protocol.Exceptions; if (protocolExceptions != null) { foreach (var exception in protocolExceptions) { exceptions.Add(exception); } } } } catch (OperationCanceledException) { shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationCanceled; } catch (Exception ex) { shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationError; exceptions.Add(ExceptionDispatchInfo.Capture(ex)); } return(new TcpClientTermination(localEndPoint, remoteEndPoint, watch.Elapsed, shutdownReason, exceptions)); }
public TestQbservableProtocol(object clientId, IObservable <TestMessage> source, IObserver <TestMessage> other, QbservableServiceOptions serviceOptions) : base(source, serviceOptions, CancellationToken.None) { this.other = other; ClientId = clientId; }
private async Task <WebSocketClientTermination> AcceptAsync( HttpListenerWebSocketContext context, CapturedId capturedId, CapturedShutdownReason capturedShutdownReason, QbservableServiceOptions options, Func <IQbservableProtocol, IParameterizedQbservableProvider> providerFactory, CancellationToken cancel) { Contract.Requires(context != null); Contract.Requires(capturedId != null); Contract.Requires(capturedShutdownReason != null); Contract.Requires(options != null); Contract.Requires(providerFactory != null); ReceivingConnection(idOverride: capturedId.Value); prepareSocket(context.WebSocket); var watch = Stopwatch.StartNew(); var exceptions = new List <ExceptionDispatchInfo>(); var shutdownReason = QbservableProtocolShutdownReason.None; try { using (var stream = new WebSocketStream(context.WebSocket)) using (var protocol = await NegotiateServerAsync(capturedId.Value, stream, formatterFactory(), options, cancel).ConfigureAwait(false)) { capturedId.Value = protocol.ClientId; var provider = providerFactory(protocol); ReceivedConnection(idOverride: capturedId.Value); try { await protocol.ExecuteServerAsync(provider).ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { exceptions.Add(ExceptionDispatchInfo.Capture(ex)); } finally { shutdownReason = protocol.ShutdownReason; } var protocolExceptions = protocol.Exceptions; if (protocolExceptions != null) { foreach (var exception in protocolExceptions) { exceptions.Add(exception); } } } } catch (OperationCanceledException) { shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationCanceled; } catch (Exception ex) { shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationError; exceptions.Add(ExceptionDispatchInfo.Capture(ex)); } finally { capturedShutdownReason.Value = shutdownReason; } return(new WebSocketClientTermination(Uri, context.Origin, watch.Elapsed, shutdownReason, exceptions)); }