Пример #1
0
        public static DuplexStreamMessage CreateSubscribeResponse(DuplexCallbackId id, int clientSubscriptionId, StreamQbservableProtocol protocol)
        {
            Contract.Requires(protocol != null);
            Contract.Ensures(Contract.Result <DuplexStreamMessage>() != null);

            return(new DuplexStreamMessage(QbservableProtocolMessageKind.DuplexSubscribeResponse, id, clientSubscriptionId, Serialize(id, clientSubscriptionId, protocol)));
        }
        public virtual async void SendOnNext(string name, DuplexCallbackId id, object value)
        {
#if TRACE
            var sourceId = GetSourceId(id);

            Log.OnNext(name, value, false, false, sourceId, LogMessages.Sending);
#endif

            try
            {
                await Protocol.SendMessageSafeAsync(CreateOnNext(id, value)).ConfigureAwait(false);
            }
            catch (SerializationException ex)
            {
                SendOnError(name, id, ExceptionDispatchInfo.Capture(ex));
            }
            catch (Exception ex)
            {
                if (Protocol.ServiceOptions.SendServerErrorsToClients)
                {
                    SendOnError(name, id, ExceptionDispatchInfo.Capture(ex));
                }
                else
                {
                    Fail(ExceptionDispatchInfo.Capture(ex));
                }
            }
        }
Пример #3
0
        public static DuplexStreamMessage CreateOnCompleted(DuplexCallbackId id, StreamQbservableProtocol protocol)
        {
            Contract.Requires(protocol != null);
            Contract.Ensures(Contract.Result <DuplexStreamMessage>() != null);

            return(CreateWithoutValue(QbservableProtocolMessageKind.DuplexOnCompleted, id, protocol));
        }
Пример #4
0
        protected void MoveNext(DuplexCallbackId id)
        {
            var enumerator = GetEnumerator(id.ClientId);

            object current;
            bool   result;

            try
            {
                if (enumerator != null && enumerator.MoveNext())
                {
                    result  = true;
                    current = enumerator.Current;
                }
                else
                {
                    result  = false;
                    current = null;
                }
            }
            catch (Exception ex)
            {
                SendEnumeratorError(id, ex);
                return;
            }

            SendEnumeratorResponse(id, result, current);
        }
        public Tuple <DuplexCallbackId, IDisposable> RegisterObservableCallbacks(int clientId, Action <object> onNext, Action <Exception> onError, Action onCompleted, Action <int> dispose)
        {
            var serverId = Interlocked.Increment(ref lastObservableId);

            var id = new DuplexCallbackId(clientId, serverId);

            var actions = Tuple.Create(onNext, onError, onCompleted, dispose);

            if (!observableCallbacks.TryAdd(id, actions))
            {
                throw new InvalidOperationException(Errors.ProtocolDuplicateDuplexIdForObservable);
            }

            return(Tuple.Create(
                       id,
                       Disposable.Create(() =>
            {
                lock (actions)
                {
                    int?clientSubscriptionId = null;

                    if (TryGetOrAddSubscriptionOneTime(id, ref clientSubscriptionId))
                    {
                        Contract.Assume(clientSubscriptionId.HasValue); // Disposable.Create ensures that this code only runs once

                        actions.Item4(clientSubscriptionId.Value);
                    }
                }
            })));
        }
        protected void GetEnumerator(DuplexCallbackId id)
        {
            var enumerable = GetEnumerable(id.ClientId);

#if TRACE
            var sourceId = GetSourceId(id);

            Log.Enumerating(enumerable.Name, false, sourceId, LogMessages.Received);
#endif

            IEnumerator enumerator;
            try
            {
                enumerator = enumerable.GetEnumerator();
            }
            catch (Exception ex)
            {
                SendGetEnumeratorError(id, ExceptionDispatchInfo.Capture(ex));
                return;
            }

            var enumeratorId = RegisterEnumerator(new NamedEnumerator(enumerable.Name, enumerator));

            SendGetEnumeratorResponse(id, enumeratorId);
        }
Пример #7
0
        public static DuplexStreamMessage CreateInvoke(DuplexCallbackId id, object[] arguments, StreamQbservableProtocol protocol)
        {
            Contract.Requires(protocol != null);
            Contract.Ensures(Contract.Result <DuplexStreamMessage>() != null);

            return(new DuplexStreamMessage(QbservableProtocolMessageKind.DuplexInvoke, id, arguments, Serialize(id, arguments, protocol)));
        }
        public void SendOnError(string name, DuplexCallbackId id, ExceptionDispatchInfo error)
        {
#if TRACE
            Contract.Requires(!string.IsNullOrEmpty(name));
#endif
            Contract.Requires(error != null);
        }
Пример #9
0
        protected void Subscribe(DuplexCallbackId id)
        {
            Func <int, IDisposable> subscribe;

            if (!obsevableCallbacks.TryGetValue(id.ClientId, out subscribe))
            {
                throw new InvalidOperationException(Errors.ProtocolInvalidDuplexId);
            }

            var subscription = new SingleAssignmentDisposable();

            var subscriptionId = RegisterSubscription(subscription);

            try
            {
                subscription.Disposable = subscribe(id.ServerId);
            }
            catch (Exception ex)
            {
                SendOnError(id, ex);
                return;
            }

            SendSubscribeResponse(id, subscriptionId);
        }
Пример #10
0
        public static DuplexStreamMessage CreateOnNext(DuplexCallbackId id, object value, StreamQbservableProtocol protocol)
        {
            Contract.Requires(protocol != null);
            Contract.Ensures(Contract.Result <DuplexStreamMessage>() != null);

            return(new DuplexStreamMessage(QbservableProtocolMessageKind.DuplexOnNext, id, value, Serialize(id, value, protocol)));
        }
Пример #11
0
        private DuplexStreamMessage(QbservableProtocolMessageKind kind, DuplexCallbackId id, ExceptionDispatchInfo error, byte[] data)
            : base(kind, data, data.Length)
        {
            Contract.Requires(error != null);

            Id    = id;
            Error = error;
        }
Пример #12
0
        public static DuplexStreamMessage CreateOnError(DuplexCallbackId id, ExceptionDispatchInfo error, StreamQbservableProtocol protocol)
        {
            Contract.Requires(error != null);
            Contract.Requires(protocol != null);
            Contract.Ensures(Contract.Result <DuplexStreamMessage>() != null);

            return(new DuplexStreamMessage(QbservableProtocolMessageKind.DuplexOnError, id, error, Serialize(id, error.SourceException, protocol)));
        }
Пример #13
0
        public static DuplexStreamMessage CreateEnumeratorResponse(DuplexCallbackId id, bool result, object current, StreamQbservableProtocol protocol)
        {
            Contract.Requires(protocol != null);
            Contract.Ensures(Contract.Result <DuplexStreamMessage>() != null);

            var value = Tuple.Create(result, current);

            return(new DuplexStreamMessage(QbservableProtocolMessageKind.DuplexEnumeratorResponse, id, value, Serialize(id, value, protocol)));
        }
Пример #14
0
        private DuplexStreamMessage(QbservableProtocolMessageKind kind, DuplexCallbackId id, object value, byte[] data, long length)
            : base(kind, data, length)
        {
            Contract.Requires(length >= 0);
            Contract.Requires(length == 0 || data != null);
            Contract.Requires(length == 0 || data.Length >= length);

            Id    = id;
            Value = value;
        }
        private Tuple <Action <object>, Action <Exception> > GetEnumeratorCallbacks(DuplexCallbackId id)
        {
            Tuple <Action <object>, Action <Exception> > actions;

            if (!enumeratorCallbacks.TryGetValue(id, out actions))
            {
                throw new InvalidOperationException(Errors.ProtocolInvalidDuplexIdForEnumerator);
            }

            return(actions);
        }
 protected virtual async void SendError(DuplexCallbackId id, ExceptionDispatchInfo error)
 {
     try
     {
         await Protocol.SendMessageSafeAsync(CreateErrorResponse(id, error)).ConfigureAwait(false);
     }
     catch (Exception ex)
     {
         Fail(ExceptionDispatchInfo.Capture(ex));
     }
 }
 protected virtual async void SendEnumeratorResponse(DuplexCallbackId id, bool result, object current)
 {
     try
     {
         await Protocol.SendMessageSafeAsync(CreateEnumeratorResponse(id, result, current)).ConfigureAwait(false);
     }
     catch (Exception ex)
     {
         Fail(ExceptionDispatchInfo.Capture(ex));
     }
 }
 protected virtual async void SendGetEnumeratorResponse(DuplexCallbackId id, int clientEnumeratorId)
 {
     try
     {
         await Protocol.SendMessageSafeAsync(CreateGetEnumeratorResponse(id, clientEnumeratorId)).ConfigureAwait(false);
     }
     catch (Exception ex)
     {
         Fail(ExceptionDispatchInfo.Capture(ex));
     }
 }
        public DuplexCallbackId RegisterEnumeratorCallback(int clientId, Action <object> callback, Action <Exception> onError)
        {
            var serverId = Interlocked.Increment(ref lastEnumeratorId);

            var id = new DuplexCallbackId(clientId, serverId);

            if (!enumeratorCallbacks.TryAdd(id, Tuple.Create(callback, onError)))
            {
                throw new InvalidOperationException(Errors.ProtocolDuplicateDuplexIdForEnumerator);
            }

            return(id);
        }
Пример #20
0
        protected void ResetEnumerator(DuplexCallbackId id)
        {
            var enumerator = GetEnumerator(id.ClientId);

            try
            {
                enumerator.Reset();
            }
            catch (Exception ex)
            {
                SendEnumeratorError(id, ex);
            }
        }
        protected virtual async void SendEnumeratorError(DuplexCallbackId id, ExceptionDispatchInfo error)
        {
            Contract.Requires(error != null);

            try
            {
                await Protocol.SendMessageSafeAsync(CreateEnumeratorError(id, error)).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Fail(ExceptionDispatchInfo.Capture(ex));
            }
        }
Пример #22
0
        private static byte[] Serialize(DuplexCallbackId id, object value, QbservableProtocol protocol)
        {
            var idData = BitConverter.GetBytes(id);

            long serializedDataLength;
            var  serializedData = protocol.Serialize(value, out serializedDataLength);

            var data = new byte[idData.Length + serializedDataLength];

            Array.Copy(idData, data, idData.Length);
            Array.Copy(serializedData, 0, data, idData.Length, serializedDataLength);

            return(data);
        }
        private void TryInvokeObservableCallback(
            DuplexCallbackId id,
            Action <Tuple <Action <object>, Action <Exception>, Action, Action <int> > > action)
        {
            Tuple <Action <object>, Action <Exception>, Action, Action <int> > callbacks;

            if (observableCallbacks.TryGetValue(id, out callbacks))
            {
                action(callbacks);
            }

            /* It's acceptable for the callbacks to be missing due to a race condition between the
             * client sending notifications and the server disposing of the subscription, which causes
             * the callbacks to be removed.
             */
        }
Пример #24
0
        private static byte[] Serialize(DuplexCallbackId id, object value, StreamQbservableProtocol protocol)
        {
            Contract.Requires(protocol != null);
            Contract.Ensures(Contract.Result <byte[]>() != null);

            var idData = BitConverter.GetBytes(id);

            long serializedDataLength;
            var  serializedData = protocol.Serialize(value, out serializedDataLength);

            var data = new byte[idData.Length + serializedDataLength];

            Array.Copy(idData, data, idData.Length);
            Array.Copy(serializedData, 0, data, idData.Length, serializedDataLength);

            return(data);
        }
        protected void DisposeEnumerator(DuplexCallbackId id)
        {
            var enumerator = GetEnumerator(id.ClientId);

#if TRACE
            var sourceId = GetSourceId(id);

            Log.Enumerated(enumerator.Name, false, sourceId, LogMessages.Received);
#endif

            var disposable = enumerator.Decorated as IDisposable;

            if (disposable != null)
            {
                disposable.Dispose();
            }
        }
        public virtual async void SendOnCompleted(string name, DuplexCallbackId id)
        {
#if TRACE
            var sourceId = GetSourceId(id);

            Log.OnCompleted(name, false, false, sourceId, LogMessages.Sending);
#endif

            try
            {
                await Protocol.SendMessageSafeAsync(CreateOnCompleted(id)).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Fail(ExceptionDispatchInfo.Capture(ex));
            }
        }
        private bool TryGetOrAddSubscriptionOneTime(DuplexCallbackId id, ref int?clientSubscriptionId)
        {
            int?s;

            if (subscriptions.TryGetValue(id, out s))
            {
                subscriptions.Remove(id);

                clientSubscriptionId = s;
                return(true);
            }
            else
            {
                subscriptions.Add(id, clientSubscriptionId);
            }

            return(false);
        }
        protected void MoveNext(DuplexCallbackId id)
        {
            var enumerator = GetEnumerator(id.ClientId);

#if TRACE
            var sourceId = GetSourceId(id);

            if (enumerator != null)
            {
                Log.MoveNext(enumerator.Name, false, sourceId, LogMessages.Received);
            }
#endif

            object current;
            bool   result;
            try
            {
                if (enumerator != null && enumerator.MoveNext())
                {
                    result  = true;
                    current = enumerator.Current;
                }
                else
                {
                    result  = false;
                    current = null;
                }
            }
            catch (Exception ex)
            {
                SendEnumeratorError(id, ExceptionDispatchInfo.Capture(ex));
                return;
            }

#if TRACE
            if (result)
            {
                Log.Current(enumerator.Name, current, false, sourceId, LogMessages.Sending);
            }
#endif

            SendEnumeratorResponse(id, result, current);
        }
Пример #29
0
        protected void GetEnumerator(DuplexCallbackId id)
        {
            var enumerable = GetEnumerable(id.ClientId);

            IEnumerator enumerator;

            try
            {
                enumerator = enumerable();
            }
            catch (Exception ex)
            {
                SendGetEnumeratorError(id, ex);
                return;
            }

            var enumeratorId = RegisterEnumerator(enumerator);

            SendGetEnumeratorResponse(id, enumeratorId);
        }
        protected void Invoke(DuplexCallbackId id, object[] arguments)
        {
            Contract.Requires(arguments != null);

            IInvokeDuplexCallback callback;

            if (!invokeCallbacks.TryGetValue(id.ClientId, out callback))
            {
                throw new InvalidOperationException(Errors.ProtocolInvalidDuplexId);
            }

#if TRACE
            var sourceId = GetSourceId(id);

            Log.Invoking(callback.Name, arguments, false, sourceId, LogMessages.Received);
#endif

            object result;
            try
            {
                result = callback.Invoke(arguments);
            }
            catch (Exception ex)
            {
                SendError(id, ExceptionDispatchInfo.Capture(ex));
                return;
            }

            var duplex = result as DuplexCallback;

            if (duplex != null)
            {
                duplex.SetClientProtocol(Protocol);
            }

#if TRACE
            Log.Invoked(callback.Name, arguments, result, false, sourceId, LogMessages.Sending);
#endif

            SendResponse(id, result);
        }