Exemplo n.º 1
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposed != null && !disposed.EnsureCalledOnce())
            {
                if (disposing)
                {
                    SafeLog(LogLevel.Trace, () => "Disposing {0} (disposing:{1})".Fmt(GetType(), disposing));
                }

                if (IsConnected)
                {
                    if (tcpClient != null)
                    {
                        tcpClient.Close();
                        tcpClient = null;

                        SafeLog(LogLevel.Trace, () => "TcpClient closed");
                    }
                }

                var localCopy = Disposed;
                if (localCopy != null)
                {
                    localCopy(this, EventArgs.Empty);
                }


                SafeLog(LogLevel.Debug, () => "{0} ({1}) Disposed".Fmt(GetType(), id));
            }
        }
Exemplo n.º 2
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposed != null && !disposed.EnsureCalledOnce())
            {
                if (disposing)
                {
                    SafeLog(LogLevel.Trace, "Disposing {0} (disposing:{1})".Fmt(GetType(), disposing));
                }

                if (IsConnected)
                {
                    readCancellationToken.Cancel();

                    if (tcpClient != null)
                    {
                        tcpClient.Close();
                        tcpClient = null;

                        SafeLog(LogLevel.Trace, "TcpClient closed");
                    }
                }

                var localCopy = Disposed;
                localCopy?.Invoke(this, EventArgs.Empty);

                SafeLog(LogLevel.Debug, "{0} ({1}) Disposed".Fmt(GetType(), id));
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Starts observing commits and dispatching them..
        /// </summary>
        /// <returns></returns>
        public async Task Start()
        {
            if (_isStarted.EnsureCalledOnce())
            {
                return;
            }

            string checkpointToken = await _checkpointRepository.Get();

            /* string checkpointToken = null;
             * await _retryPolicy.Retry(async () => checkpointToken = await _checkpointRepository.Get(), _disposed.Token); //TODO should have different retry policy? */
            _subscription = _eventStoreClient.Subscribe(checkpointToken, async commit =>
            {
                try
                {
                    await _retryPolicy.Retry(() => _dispatchCommit(commit, _disposed.Token), _disposed.Token);
                    await _retryPolicy.Retry(() => _checkpointRepository.Put(commit.CheckpointToken), _disposed.Token);
                }
                catch (Exception ex)
                {
                    Logger.ErrorException(
                        Messages.ExceptionHasOccuredWhenDispatchingACommit.FormatWith(commit.ToString()),
                        ex);
                    _projectedCommits.OnError(ex);
                    throw;
                }
                _projectedCommits.OnNext(commit);
            });
        }
Exemplo n.º 4
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposed != null && !disposed.EnsureCalledOnce())
            {
                if (disposing)
                {
                    Console.WriteLine("Disposing {0} (disposing:{1})".Fmt(GetType(), disposing));
                }

                if (IsConnected)
                {
                    readCancellationToken.Cancel();

                    if (tcpClient != null)
                    {
                        tcpClient.Close();
                        tcpClient = null;

                        Console.WriteLine("TcpClient closed");
                    }
                }

                var localCopy = Disposed;
                if (localCopy != null)
                {
                    localCopy(this, EventArgs.Empty);
                }


                Console.WriteLine("{0} ({1}) Disposed".Fmt(GetType(), id));
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Starts observing commits and dispatching them..
        /// </summary>
        /// <returns></returns>
        public async Task Start()
        {
            if (_isStarted.EnsureCalledOnce())
            {
                return;
            }

            string checkpointToken = await _checkpointRepository.Get();

            _subscription = _eventStoreClient.Subscribe(checkpointToken, async commit =>
            {
                try
                {
                    await _dispatchCommit(commit, _disposed.Token);
                    await _checkpointRepository.Put(commit.CheckpointToken);
                }
                catch (Exception ex)
                {
                    Logger.ErrorException(
                        ExtensionMethods.FormatWith(Messages.ExceptionHasOccuredWhenDispatchingACommit, new[] { commit.ToString() }),
                        ex);
                    _projectedCommits.OnError(ex);
                    throw;
                }
                _projectedCommits.OnNext(commit);
            });
        }
Exemplo n.º 6
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposed != null && !disposed.EnsureCalledOnce())
            {
                if (disposing)
                {
                    if (!Disposables.IsDisposed)
                    {
                        Disposables.Dispose();
                    }

                    OtherLeg?.Dispose();
                    bridgedChannelsSubject.Dispose();
                }

                if (eventSocket != null && eventSocket is OutboundSocket)
                {
                    // todo: should we close the socket associated with the channel here?
                    eventSocket.Dispose();
                }

                eventSocket = null;

                Log.Debug(() => "Channel Disposed.");
            }

            base.Dispose(disposing);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources.
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposed != null && !disposed.EnsureCalledOnce())
            {
                log.LogTrace("Disposing (disposing:{0})".Fmt(disposing));

                if (disposing)
                {
                    listenerTermination.OnNext(Unit.Default);
                    listenerTermination.Dispose();

                    if (subscription != null)
                    {
                        subscription.Dispose();
                        subscription = null;
                    }

                    disposables.Dispose();
                    connections?.ToList().ForEach(connection => connection?.Dispose());

                    observable.OnCompleted();
                    observable.Dispose();

                    if (tcpListener != null)
                    {
                        tcpListener.Stop();
                        tcpListener = null;
                    }
                }

                log.LogTrace("Disposed");
            }
        }
Exemplo n.º 8
0
 public void Dispose()
 {
     if (_isDisposed.EnsureCalledOnce())
     {
         return;
     }
     _durableCommitDispatcher.Dispose();
     _storeEvents.Dispose();
 }
Exemplo n.º 9
0
 protected virtual void Dispose(bool disposing)
 {
     if (disposed != null && !disposed.EnsureCalledOnce())
     {
         if (buffer != null)
         {
             StringBuilderPool.Free(buffer);
             buffer = null;
         }
     }
 }
Exemplo n.º 10
0
        private static void PreventThreadPoolStarvationWhenRunningTestsInParallel()
        {
            if (Initialized.EnsureCalledOnce())
            {
                return;
            }

            // doing this to avoid thread starvation when running tests in parallel eg. nCrunch, AppVeyor
            int maxThreads;
            int maxIoPorts;

            System.Threading.ThreadPool.GetMaxThreads(out maxThreads, out maxIoPorts);
            System.Threading.ThreadPool.SetMaxThreads(maxThreads * 2, maxIoPorts * 2);
        }
Exemplo n.º 11
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposed != null && disposed.EnsureCalledOnce())
            {
                if (disposing)
                {
                    if (Disposables != null)
                    {
                        Disposables.Dispose();
                    }
                }

                Log.Debug(() => "BasicChannel Disposed.");
            }
        }
Exemplo n.º 12
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposed != null && disposed.EnsureCalledOnce())
            {
                if (disposing)
                {
                    if (Disposables != null)
                    {
                        Disposables.Dispose();
                    }
                }

                Console.WriteLine("BasicChannel Disposed.");
            }
        }
Exemplo n.º 13
0
        private void UpdateTokens()
        {
            if (_updatingTokens.EnsureCalledOnce())
            {
                return;
            }
            var currentTime = _getUtcNow().Ticks;

            if (currentTime >= _nextRefillTime)
            {
                Interlocked.Exchange(ref _tokens, _getBucketTokenCapacty());
                _nextRefillTime = currentTime + _refillIntervalTicks;
            }

            _updatingTokens.Set(false);
        }
Exemplo n.º 14
0
        protected override void Dispose(bool disposing)
        {
            if (disposed != null && !disposed.EnsureCalledOnce())
            {
                if (disposing)
                {
                    // cancel any outgoing network sends
                    if (cts != null)
                    {
                        cts.Cancel();
                    }
                }
            }

            base.Dispose(disposing);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ObservableSocket"/> class.
        /// </summary>
        /// <param name="tcpClient">The TCP client to wrap.</param>
        protected ObservableSocket(TcpClient tcpClient)
        {
            id = Interlocked.Increment(ref IdCounter);

            this.tcpClient = tcpClient;

            subject = new Subject <byte[]>();

            receiver = Observable.Defer(
                () =>
            {
                if (isStarted.EnsureCalledOnce())
                {
                    return(subject.AsObservable());
                }

                Task.Run(
                    async() =>
                {
                    Console.WriteLine("{0} Worker Thread {1} started".Fmt(GetType(), id));

                    int bytesRead = 1;
                    var stream    = tcpClient.GetStream();
                    byte[] buffer = SharedPools.ByteArray.Allocate();
                    try
                    {
                        while (bytesRead > 0)
                        {
                            bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, readCancellationToken.Token);
                            if (bytesRead > 0)
                            {
                                if (bytesRead == buffer.Length)
                                {
                                    subject.OnNext(buffer);
                                }
                                else
                                {
                                    subject.OnNext(buffer.Take(bytesRead).ToArray());
                                }
                            }
                            else
                            {
                                subject.OnCompleted();
                            }
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        //expected - normal shutdown
                        subject.OnCompleted();
                    }
                    catch (TaskCanceledException)
                    {
                        //expected - normal shutdown
                        subject.OnCompleted();
                    }
                    catch (IOException ex)
                    {
                        if (ex.InnerException is ObjectDisposedException)
                        {
                            //expected - normal shutdown
                            subject.OnCompleted();
                        }
                        else
                        {
                            //socket comms interrupted - propogate the error up the layers
                            Console.WriteLine("IO Error reading from stream", ex);
                            subject.OnError(ex);
                        }
                    }
                    catch (SocketException ex)
                    {
                        //socket comms interrupted - propogate the error up the layers
                        Console.WriteLine("Socket Error reading from stream", ex);
                        subject.OnError(ex);
                    }
                    catch (Exception ex)
                    {
                        //unexpected error
                        Console.WriteLine("Unexpected Error reading from stream", ex);
                        subject.OnError(ex);
                    }
                    finally
                    {
                        SharedPools.ByteArray.Free(buffer);

                        Console.WriteLine("{0} Worker Thread {1} completed".Fmt(GetType(), id));
                        Dispose();
                    }
                });

                return(subject.AsObservable());
            });
        }
Exemplo n.º 16
0
        private void InitializeSubscriptions()
        {
            if (initialized.EnsureCalledOnce())
            {
                Log.Warn(() => "Channel already initialized");
                return;
            }

            Disposables.Add(
                eventSocket.ChannelEvents.Where(x => x.UUID == UUID &&
                                                x.EventName == EventName.ChannelBridge &&
                                                x.OtherLegUUID != bridgedUUID)
                .Subscribe(
                    async x =>
            {
                Log.Info(() => "Channel [{0}] Bridged to [{1}] CHANNEL_BRIDGE".Fmt(UUID, x.GetHeader(HeaderNames.OtherLegUniqueId)));

                var apiResponse = await eventSocket.Api("uuid_dump", x.OtherLegUUID);

                if (apiResponse.Success && apiResponse.BodyText != "+OK")
                {
                    var eventMessage = new ChannelEvent(apiResponse);
                    bridgedChannelsSubject.OnNext(new BridgedChannel(eventMessage, eventSocket));
                }
                else
                {
                    Log.Error(() => "Unable to get CHANNEL_DATA info from 'api uuid_dump {0}' - received '{1}'.".Fmt(x.OtherLegUUID, apiResponse.BodyText));
                }
            }));

            Disposables.Add(
                eventSocket.ChannelEvents.Where(x =>
                                                x.UUID == UUID &&
                                                x.EventName == EventName.ChannelUnbridge &&
                                                x.GetVariable("bridge_hangup_cause") != null)
                .Subscribe(
                    x =>
            {
                /* side effects:
                 * the att_xfer application is evil
                 * if after speaking to C, B presses '#' to cancel,
                 * the A channel fires an unbridge event, even though it is still bridged to B
                 * in this case, bridge_hangup_cause will be empty so we'll ignore those events
                 * however, this may break if this channel has had any completed bridges before this. */

                Log.Info(
                    () =>
                    "Channel [{0}] Unbridged from [{1}] {2}".Fmt(
                        UUID,
                        x.GetVariable("last_bridge_to"),
                        x.GetVariable("bridge_hangup_cause")));

                bridgedChannelsSubject.OnNext(null);                    //clears out OtherLeg
            }));

            Disposables.Add(BridgedChannels.Subscribe(
                                async b =>
            {
                if (bridgedUUID != null && bridgedUUID != b.UUID)
                {
                    await eventSocket.FilterDelete(HeaderNames.UniqueId, bridgedUUID).ConfigureAwait(false);
                    await eventSocket.FilterDelete(HeaderNames.OtherLegUniqueId, bridgedUUID).ConfigureAwait(false);
                    await eventSocket.FilterDelete(HeaderNames.ChannelCallUniqueId, bridgedUUID).ConfigureAwait(false);
                }

                bridgedUUID = b.UUID;

                await eventSocket.Filter(HeaderNames.UniqueId, bridgedUUID).ConfigureAwait(false);
                await eventSocket.Filter(HeaderNames.OtherLegUniqueId, bridgedUUID).ConfigureAwait(false);
                await eventSocket.Filter(HeaderNames.ChannelCallUniqueId, bridgedUUID).ConfigureAwait(false);

                Log.Trace(() => "Channel [{0}] setting OtherLeg to [{1}]".Fmt(UUID, b.UUID));
            }));

            Disposables.Add(
                eventSocket.ChannelEvents.Where(
                    x =>
                    x.EventName == EventName.ChannelBridge &&
                    x.UUID != UUID &&
                    x.GetHeader(HeaderNames.OtherLegUniqueId) == UUID &&
                    x.UUID != bridgedUUID)
                .Subscribe(
                    x =>
            {
                //there is another channel out there that has bridged to us but we didn't get the CHANNEL_BRIDGE event on this channel
                Log.Info(() => "Channel [{0}] bridged to [{1}]] on CHANNEL_BRIDGE received on other channel".Fmt(UUID, x.UUID));
                bridgedChannelsSubject.OnNext(new BridgedChannel(x, eventSocket));
            }));


            if (eventSocket is OutboundSocket)
            {
                Disposables.Add(
                    eventSocket.ChannelEvents.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelHangupComplete)
                    .Subscribe(
                        async e =>
                {
                    if (ExitOnHangup)
                    {
                        //give event subscribers time to complete
                        if (LingerTime > 0)
                        {
                            Log.Debug(() => "Channel[{0}] will exit in {1} seconds...".Fmt(UUID, LingerTime));
                            await Task.Delay(LingerTime * 1000);
                        }

                        if (eventSocket != null)
                        {
                            Log.Info(() => "Channel [{0}] exiting".Fmt(UUID));
                            await eventSocket.Exit().ConfigureAwait(false);
                        }

                        Dispose();
                    }
                }));
            }

            Log.Trace(() => "Channel [{0}] subscriptions initialized".Fmt(UUID));
        }
Exemplo n.º 17
0
        private void InitializeSubscriptions()
        {
            if (initialized.EnsureCalledOnce())
            {
                Log.Warn(() => "Channel already initialized");
                return;
            }

            Disposables.Add(
                eventSocket.Events.Where(x => x.UUID == UUID &&
                                         x.EventName == EventName.ChannelBridge &&
                                         x.OtherLegUUID != bridgedUUID)
                .Subscribe(
                    async x =>
            {
                Log.Info(() => "Channel [{0}] Bridged to [{1}] CHANNEL_BRIDGE".Fmt(UUID, x.GetHeader(HeaderNames.OtherLegUniqueId)));

                var apiResponse = await eventSocket.Api("uuid_dump", x.OtherLegUUID);

                if (apiResponse.Success && apiResponse.BodyText != "+OK")
                {
                    var eventMessage = new EventMessage(apiResponse);
                    bridgedChannels.OnNext(new BridgedChannel(eventMessage, eventSocket));
                }
                else
                {
                    Log.Error(() => "Unable to get CHANNEL_DATA info from 'api uuid_dump {0}' - received '{1}'.".Fmt(x.OtherLegUUID, apiResponse.BodyText));
                }
            }));

            Disposables.Add(
                eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelUnbridge)
                .Subscribe(x => Log.Info(() => "Channel [{0}] Unbridged from [{1}] {2}".Fmt(UUID, x.GetVariable("last_bridge_to"), x.GetVariable("bridge_hangup_cause")))));

            Disposables.Add(bridgedChannels.Subscribe(
                                async b =>
            {
                if (bridgedUUID != null && bridgedUUID != b.UUID)
                {
                    await eventSocket.FilterDelete(HeaderNames.UniqueId, bridgedUUID).ConfigureAwait(false);
                    await eventSocket.FilterDelete(HeaderNames.OtherLegUniqueId, bridgedUUID).ConfigureAwait(false);
                    await eventSocket.FilterDelete(HeaderNames.ChannelCallUniqueId, bridgedUUID).ConfigureAwait(false);
                }

                bridgedUUID = b.UUID;

                await eventSocket.Filter(HeaderNames.UniqueId, bridgedUUID).ConfigureAwait(false);
                await eventSocket.Filter(HeaderNames.OtherLegUniqueId, bridgedUUID).ConfigureAwait(false);
                await eventSocket.Filter(HeaderNames.ChannelCallUniqueId, bridgedUUID).ConfigureAwait(false);

                this.OtherLeg = b;
            }));

            Disposables.Add(
                eventSocket.Events.Where(
                    x =>
                    x.EventName == EventName.ChannelBridge &&
                    x.UUID != UUID &&
                    x.GetHeader(HeaderNames.OtherLegUniqueId) == UUID &&
                    x.UUID != bridgedUUID)
                .Subscribe(
                    x =>
            {
                //there is another channel out there that has bridged to us but we didn't get the CHANNEL_BRIDGE event on this channel
                Log.Info(() => "Channel [{0}] bridged to [{1}]] on CHANNEL_BRIDGE received on other channel".Fmt(UUID, x.UUID));
                bridgedChannels.OnNext(new BridgedChannel(x, eventSocket));
            }));


            if (eventSocket is OutboundSocket)
            {
                Disposables.Add(
                    eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelHangup)
                    .Subscribe(
                        async e =>
                {
                    if (ExitOnHangup)
                    {
                        //give event subscribers time to complete
                        if (LingerTime > 0)
                        {
                            await Task.Delay(LingerTime * 1000);
                        }

                        Log.Info(() => "Channel [{0}] exiting".Fmt(UUID));
                        await eventSocket.Exit().ConfigureAwait(false);
                    }
                }));
            }

            Log.Trace(() => "Channel [{0}] subscriptions initialized".Fmt(UUID));
        }
Exemplo n.º 18
0
        /// <summary>
        /// Starts the Listener
        /// </summary>
        public void Start()
        {
            if (disposed.Value)
            {
                throw new ObjectDisposedException(ToString());
            }

            if (isStarted.EnsureCalledOnce())
            {
                return;
            }

            tcpListener = new TcpListener(IPAddress.Any, port);

            tcpListener.Start();

            log.LogTrace("Listener Started on Port {0}".Fmt(Port));

            subscription = Observable.FromAsync(tcpListener.AcceptTcpClientAsync)
                           .Repeat()
                           .TakeUntil(listenerTermination)
                           .Do(connection => log.LogTrace("New Connection from {0}".Fmt(connection.Client.RemoteEndPoint)))
                           .Select(
                tcpClient =>
            {
                try
                {
                    return(observableSocketFactory(tcpClient));
                }
                catch (Exception ex)
                {
                    //race condition - socket might shut down before we can initialize
                    log.LogError(ex, "Unable to create observableSocket");
                    return(null);
                }
            })
                           .Where(x => x != null)
                           .Subscribe(
                connection =>
            {
                if (connection != null)
                {
                    connections.Add(connection);
                    observable.OnNext(connection);

                    disposables.Add(
                        Observable.FromEventPattern(h => connection.Disposed += h, h => connection.Disposed -= h)
                        .FirstAsync()
                        .Subscribe(
                            _ =>
                    {
                        log.LogTrace("Connection Disposed");
                        connections.Remove(connection);
                    }));
                }
            },
                ex =>
            {
                //ObjectDisposedException is thrown by TcpListener when Stop() is called before EndAcceptTcpClient()
                if (!(ex is ObjectDisposedException))
                {
                    log.LogError(ex, "Error handling inbound connection");
                }
            },
                () => isStarted.Set(false));
        }
Exemplo n.º 19
0
        private void InitializeSubscriptions()
        {
            if (initialized.EnsureCalledOnce())
            {
                Log.Warn(() => "Channel already initialized");
                return;
            }

            Disposables.Add(
                eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelBridge).Subscribe(
                    x =>
            {
                Log.Trace(
                    () =>
                    "Channel [{0}] Bridged to [{1}]".Fmt(UUID, x.GetHeader(HeaderNames.OtherLegUniqueId)));

                if (Bridge.Channel != null &&
                    x.GetHeader(HeaderNames.OtherLegUniqueId) != Bridge.Channel.UUID)
                {
                    //possibly changed bridge partner as part of att_xfer
                    Log.Warn(
                        () =>
                        "Channel [{0}] was Bridged to [{1}] but now changed to [{2}]".Fmt(
                            UUID, Bridge.Channel.UUID, x.UUID));

                    Bridge.Channel.Dispose();
                    Bridge = new BridgeStatus(true, "TRANSFERRED", new BridgedChannel(x, eventSocket));
                }
            }));

            Disposables.Add(
                eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelUnbridge)
                .Subscribe(
                    x =>
                    Log.Trace(
                        () =>
                        "Channel [{0}] Unbridged from [{1}] {2}".Fmt(
                            UUID, Bridge.Channel.UUID, x.GetVariable("bridge_hangup_cause")))));

            Disposables.Add(
                eventSocket.Events.Where(
                    x =>
                    x.EventName == EventName.ChannelBridge && x.UUID != UUID &&
                    x.GetHeader(HeaderNames.OtherLegUniqueId) == UUID &&
                    (Bridge.Channel != null && x.UUID != Bridge.Channel.UUID)).Subscribe(
                    x =>
            {
                //there is another channel out there that has bridged to us but we didn't get the CHANNEL_BRIDGE event on this channel
                //possibly an attended transfer. We'll swap our bridge partner so we can get its events

                Log.Warn(
                    () =>
                    "Channel [{0}] was Bridged to [{1}] but now changed to [{2}]".Fmt(
                        UUID, Bridge.Channel.UUID, x.UUID));

                Bridge.Channel.Dispose();
                Bridge = new BridgeStatus(true, "TRANSFERRED", new BridgedChannel(x, eventSocket));
            }));

            if (this.eventSocket is OutboundSocket)
            {
                Disposables.Add(
                    eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelHangup)
                    .Subscribe(
                        e =>
                {
                    if (ExitOnHangup)
                    {
                        Log.Info(() => "Channel [{0}] exiting".Fmt(UUID));
                        eventSocket.Exit();                    //don't care about the result, no need to wait
                    }
                }));
            }

            Log.Trace(() => "Channel [{0}] subscriptions initialized".Fmt(UUID));
        }