Beispiel #1
0
        public async Task Stopping_the_listener_does_not_dispose_any_connected_clients()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;
                bool disposed  = false;

                listener.Connections.Subscribe((socket) =>
                {
                    connected        = true;
                    socket.Disposed += (o, e) => disposed = true;
                });

                var _ = new FakeFreeSwitchSocket(listener.Port);

                await Wait.Until(() => connected);

                listener.Stop();

                Assert.False(disposed);

                listener.Dispose();
                Assert.True(disposed);
            }
        }
        public async Task Calling_Connect_on_a_new_OutboundSocket_should_populate_the_ChannelData()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                ChannelEvent channelData = null;

                listener.Connections.Subscribe(
                    async(socket) =>
                {
                    channelData = await socket.Connect();
                });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                    .Subscribe(async _ => await freeSwitch.SendChannelDataEvent());

                    await Wait.Until(() => channelData != null);

                    Assert.NotNull(channelData);
                    Assert.Equal(ChannelState.Execute, channelData.ChannelState);
                    Assert.Equal("RINGING", channelData.Headers["Channel-Call-State"]);
                }
            }
        }
        public async Task When_FreeSwitch_disconnects_it_completes_the_message_observables()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;
                bool disposed = true;
                bool messagesObservableCompleted = false;
                bool eventsObservableCompleted = false;

                listener.Connections.Subscribe(connection =>
                {
                    connected = true;
                    connection.Messages.Subscribe(_ => { }, () => messagesObservableCompleted = true);
                    connection.Events.Subscribe(_ => { }, () => eventsObservableCompleted = true);
                    connection.Disposed += (o, e) => disposed = true;
                });

                using (var client = new FakeFreeSwitchSocket(listener.Port))
                {
                    await Wait.Until(() => connected);
                    client.Dispose();

                    await Wait.Until(() => messagesObservableCompleted);
                    await Wait.Until(() => eventsObservableCompleted);

                    Assert.True(connected, "Expect a connection to have been made.");
                    Assert.True(disposed, "Expect the socket to have been disposed.");
                    Assert.True(messagesObservableCompleted, "Expect the BasicMessage observable to be completed");
                    Assert.True(eventsObservableCompleted, "Expect the EventMessage observable to be completed");
                }
            }
        }
        public async Task Calling_Exit_on_a_disconnected_OutboundSocket_should_close_gracefully()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                EventMessage channelData = null;
                bool         exited      = false;

                listener.Connections.Subscribe(
                    async(socket) =>
                {
                    channelData = await socket.Connect();
                    await socket.Exit();
                    exited = true;
                });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                    .Subscribe(async _ =>
                    {
                        await freeSwitch.SendChannelDataEvent();
                        await Task.Delay(500);
                        freeSwitch.Dispose();
                    });

                    await Wait.Until(() => channelData != null);

                    await Wait.Until(() => exited);

                    Assert.True(exited);
                }
            }
        }
Beispiel #5
0
 public async Task IsStarted_is_false_when_initialized()
 {
     using (var listener = new OutboundListener(0))
     {
         Assert.False(listener.IsStarted);
     }
 }
Beispiel #6
0
        public async Task Can_restart_the_listener_after_stopping()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                int counter = 0;

                listener.Connections.Subscribe((socket) =>
                {
                    counter++;
                });

                new FakeFreeSwitchSocket(listener.Port);
                await Wait.Until(() => counter == 1);

                listener.Stop();

                //not listening
                Assert.Throws <SocketException>(() => new FakeFreeSwitchSocket(listener.Port));

                listener.Start();
                new FakeFreeSwitchSocket(listener.Port);
                await Wait.Until(() => counter == 2);
            }
        }
Beispiel #7
0
 public async Task IsStarted_is_true_when_started()
 {
     using (var listener = new OutboundListener(0))
     {
         listener.Start();
         Assert.True(listener.IsStarted);
     }
 }
Beispiel #8
0
 public async Task Starting_should_be_idempotent()
 {
     using (var listener = new OutboundListener(0))
     {
         listener.Start();
         listener.Start();
         Assert.True(listener.IsStarted);
     }
 }
Beispiel #9
0
        public async Task IsStarted_is_false_when_disposed()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                listener.Dispose();
                await Wait.Until(() => listener.IsStarted == false);
            }
        }
        public void Disposing_the_listener_completes_the_connections_observable()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool completed = false;

                listener.Connections.Subscribe(_ => { }, () => completed = true);

                listener.Dispose();

                Assert.True(completed);
            }
        }
Beispiel #11
0
        public void Disposing_the_listener_completes_the_connections_observable()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool completed = false;

                listener.Connections.Subscribe(_ => { }, () => completed = true);

                listener.Dispose();

                Assert.True(completed);
            }
        }
        public async Task a_new_connection_produces_an_outbound_socket()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;

                listener.Connections.Subscribe((socket) => connected = true);

                var client = new FakeFreeSwitchSocket(listener.Port);

                await Wait.Until(() => connected);
                Assert.True(connected);
            }
        }
Beispiel #13
0
        static void Main(string[] args)
        {
            using (var listener = new OutboundListener(8084))
            {
                listener.Connections.Subscribe(
                    async socket =>
                {
                    await socket.Connect();

                    //after calling .Connect(), socket.ChannelData
                    //is populated with all the headers and variables of the channel

                    var uuid = socket.ChannelData.Headers[HeaderNames.UniqueId];
                    Console.WriteLine("OutboundSocket connected for channel " + uuid);

                    await socket.SubscribeEvents(EventName.ChannelHangup);

                    socket.ChannelEvents
                    .Where(x => x.EventName == EventName.ChannelHangup && x.UUID == uuid)
                    .Take(1)
                    .Subscribe(async x =>
                    {
                        Console.WriteLine("Hangup Detected on " + x.UUID);
                        await socket.Exit();
                    });


                    //if we use 'full' in our FS dialplan, we'll get events for ALL channels in FreeSwitch
                    //this is not desirable here - so we'll filter in for our unique id only
                    //cases where this is desirable is in the channel api where we want to catch other channels bridging to us
                    await socket.Filter(HeaderNames.UniqueId, uuid);

                    //tell FreeSwitch not to end the socket on hangup, we'll catch the hangup event and .Exit() ourselves
                    await socket.Linger();

                    await socket.ExecuteApplication(uuid, "answer");
                    await socket.Play(uuid, "https://s3-ap-southeast-2.amazonaws.com/talkingtech-voip/Greeting.wav");
                    await socket.Hangup(uuid, HangupCause.NormalClearing);
                });

                listener.Start();

                Console.WriteLine("Press [Enter] to exit.");
                Console.ReadLine();
            }
        }
Beispiel #14
0
        public async Task a_new_connection_produces_an_outbound_socket()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;

                listener.Connections.Subscribe((socket) => connected = true);

                var client = new FakeFreeSwitchSocket(listener.Port);

                await Wait.Until(() => connected);

                Assert.True(connected);
            }
        }
        public async Task can_send_multple_commands()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool         commandRequestReceived = false;
                CommandReply commandReply           = null;

                listener.Connections.Subscribe(
                    async(socket) =>
                {
                    await socket.Connect();

                    commandReply = await socket.Linger();

                    commandReply = await socket.NoLinger();
                });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                    .Subscribe(async _ => await freeSwitch.SendChannelDataEvent());

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("linger"))
                    .Subscribe(async _ =>
                    {
                        await freeSwitch.SendCommandReplyOk();
                    });

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("nolinger"))
                    .Subscribe(async _ =>
                    {
                        await freeSwitch.SendCommandReplyError("FAILED");
                        commandRequestReceived = true;
                    });

                    await Wait.Until(() => commandRequestReceived);

                    Assert.True(commandRequestReceived);
                    Assert.NotNull(commandReply);
                    Assert.False(commandReply.Success);
                }
            }
        }
        public async Task Channel_connect_errors_should_not_cause_subsequent_connections_to_fail()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                bool channelCallbackCalled    = false;
                bool firstConnectionReceived  = false;
                bool secondConnectionReceived = false;

                listener.Channels.Subscribe(channel => { channelCallbackCalled = true; });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ =>
                    {
                        freeSwitch.Dispose();
                        firstConnectionReceived = true;
                    });

                    await Wait.Until(() => firstConnectionReceived);

                    Assert.False(channelCallbackCalled);
                }

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(async _ =>
                    {
                        await freeSwitch.SendChannelDataEvent();
                        secondConnectionReceived = true;
                    });

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("linger") || m.StartsWith("event") || m.StartsWith("filter"))
                    .Subscribe(async _ =>
                    {
                        await freeSwitch.SendCommandReplyOk("sending OK for linger, event and filter commands");
                    });


                    await Wait.Until(() => secondConnectionReceived);

                    Assert.True(channelCallbackCalled);
                }
            }
        }
        public async Task Calling_Connect_on_a_OutboundSocket_that_was_disconnected_should_throw_OperationCanceledException()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                Exception ex = null;

                listener.Connections.Subscribe((socket) => ex = Record.Exception(() => socket.Connect().Wait()));

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ => freeSwitch.Dispose());

                    await Wait.Until(() => ex != null);

                    Assert.IsType <TaskCanceledException>(ex.InnerException);
                }
            }
        }
Beispiel #18
0
        private static void OutboundSocketTest()
        {
            var listener = new OutboundListener(8084);

            listener.Connections.Subscribe(
                async connection =>
            {
                await connection.Connect();
                Console.WriteLine("New Socket connected");

                connection.Events.Where(x => x.EventName == EventName.ChannelHangup).Take(1).Subscribe(
                    e =>
                {
                    ColorConsole.WriteLine("Hangup Detected on A-Leg ".Red(),
                                           e.Headers[HeaderNames.CallerUniqueId],
                                           " ",
                                           e.Headers[HeaderNames.HangupCause]);

                    connection.Exit();
                });

                var uuid = connection.ChannelData.Headers[HeaderNames.UniqueId];

                await
                connection.SubscribeEvents(
                    EventName.Dtmf);

                await connection.Linger();
                await connection.ExecuteApplication(uuid, "answer", null, true, false);

                var result =
                    await
                    connection.Play(
                        uuid,
                        "$${base_dir}/sounds/en/us/callie/misc/8000/misc-freeswitch_is_state_of_the_art.wav");

                //await connection.ExecuteAppAsync(uuid, "conference", "test+1234");
                //if (result.ChannelData.AnswerState != AnswerState.Hangup) await connection.Hangup(uuid, "NORMAL_CLEARING");
            });

            listener.Start();
        }
        public Task Run(CancellationToken cancellationToken)
        {
            listener = new OutboundListener(8084);

            listener.Connections.Subscribe(
                async connection =>
            {
                await connection.Connect();
                Console.WriteLine("New Socket connected");

                connection.ChannelEvents.Where(x => x.UUID == connection.ChannelData.UUID && x.EventName == EventName.ChannelHangup)
                .Take(1)
                .Subscribe(
                    e =>
                {
                    ColorConsole.WriteLine(
                        "Hangup Detected on A-Leg ".Red(),
                        e.Headers[HeaderNames.CallerUniqueId],
                        " ",
                        e.Headers[HeaderNames.HangupCause]);

                    connection.Exit();
                });

                var uuid = connection.ChannelData.Headers[HeaderNames.UniqueId];

                await connection.SubscribeEvents(EventName.Dtmf, EventName.ChannelHangup);

                await connection.Linger();
                await connection.ExecuteApplication(uuid, "answer", null, true, false);

                var result =
                    await connection.Play(uuid, "$${base_dir}/sounds/en/us/callie/misc/8000/misc-freeswitch_is_state_of_the_art.wav");
            });

            listener.Start();

            Console.WriteLine("Listener started on 8084. Press [Enter] to exit");
            Console.ReadLine();

            return(Task.FromResult(0));
        }
        public async Task Disposing_the_listener_completes_the_message_observables()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;
                bool messagesObservableCompleted = false;
                bool eventsObservableCompleted   = false;
                bool channelDataReceived         = false;

                listener.Connections.Subscribe(async(connection) =>
                {
                    connected = true;
                    connection.Messages.Subscribe(_ => { }, () => messagesObservableCompleted = true);
                    connection.Events.Subscribe(_ => { }, () => eventsObservableCompleted     = true);
                    await connection.Connect();

                    channelDataReceived = connection.ChannelData != null;
                    Assert.True(channelDataReceived);
                });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                    .Subscribe(async _ => await freeSwitch.SendChannelDataEvent());

                    await Wait.Until(() => channelDataReceived);

                    listener.Dispose(); // will dispose the socket

                    await Wait.Until(() => messagesObservableCompleted);

                    await Wait.Until(() => eventsObservableCompleted);

                    Assert.True(connected, "Expect a connection to have been made.");
                    Assert.True(messagesObservableCompleted, "Expect the BasicMessage observable to be completed");
                    Assert.True(eventsObservableCompleted, "Expect the EventMessage observable to be completed");
                }
            }
        }
Beispiel #21
0
        public async Task each_new_connection_produces_a_new_outbound_socket_from_the_Connections_observable()
        {
            const int NumberOfConnections = 3;

            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                var connected = 0;

                listener.Connections.Subscribe((socket) => connected++);

                for (int i = 0; i < NumberOfConnections; i++)
                {
                    var client = new FakeFreeSwitchSocket(listener.Port);
                }

                await Wait.Until(() => connected == NumberOfConnections);

                Assert.Equal(NumberOfConnections, connected);
            }
        }
        public async Task can_send_api()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool        apiRequestReceived = false;
                ApiResponse apiResponse        = null;

                listener.Connections.Subscribe(
                    async(socket) =>
                {
                    await socket.Connect();

                    apiResponse = await socket.SendApi("status");
                });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                    .Subscribe(async _ => await freeSwitch.SendChannelDataEvent());

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("api")).Subscribe(
                        async _ =>
                    {
                        apiRequestReceived = true;
                        await freeSwitch.SendApiResponseOk();
                    });

                    await Wait.Until(() => apiRequestReceived);

                    await Wait.Until(() => apiResponse != null);

                    Assert.True(apiRequestReceived);
                    Assert.NotNull(apiResponse);
                    Assert.True(apiResponse.Success);
                }
            }
        }
        public async Task Disposing_the_listener_completes_the_message_observables()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;
                bool messagesObservableCompleted = false;
                bool eventsObservableCompleted = false;
                bool channelDataReceived = false;

                listener.Connections.Subscribe(async (connection) =>
                {
                    connected = true;
                    connection.Messages.Subscribe(_ => { }, () => messagesObservableCompleted = true);
                    connection.Events.Subscribe(_ => { }, () => eventsObservableCompleted = true);
                    await connection.Connect();

                    channelDataReceived = connection.ChannelData != null;
                    Assert.True(channelDataReceived);
                });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                          .Subscribe(async _ => await freeSwitch.SendChannelDataEvent());

                    await Wait.Until(() => channelDataReceived);
                    listener.Dispose(); // will dispose the socket

                    await Wait.Until(() => messagesObservableCompleted);
                    await Wait.Until(() => eventsObservableCompleted);

                    Assert.True(connected, "Expect a connection to have been made.");
                    Assert.True(messagesObservableCompleted, "Expect the BasicMessage observable to be completed");
                    Assert.True(eventsObservableCompleted, "Expect the EventMessage observable to be completed");
                }
            }
        }
        public async Task Disposing_the_listener_disposes_any_connected_clients()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;
                bool disposed = false;

                listener.Connections.Subscribe((socket) =>
                {
                    connected = true;
                    socket.Disposed += (o, e) => disposed = true;
                });

               var client = new FakeFreeSwitchSocket(listener.Port);

                await Wait.Until(() => connected);
                listener.Dispose();

                Assert.True(disposed);
            }
        }
        public async Task When_FreeSwitch_disconnects_it_completes_the_message_observables()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool connected = false;
                bool disposed  = true;
                bool messagesObservableCompleted = false;
                bool eventsObservableCompleted   = false;

                listener.Connections.Subscribe(connection =>
                {
                    connected = true;
                    connection.Messages.Subscribe(_ => { }, () => messagesObservableCompleted = true);
                    connection.Events.Subscribe(_ => { }, () => eventsObservableCompleted     = true);
                    connection.Disposed += (o, e) => disposed = true;
                });

                using (var client = new FakeFreeSwitchSocket(listener.Port))
                {
                    await Wait.Until(() => connected);

                    client.Dispose();

                    await Wait.Until(() => messagesObservableCompleted);

                    await Wait.Until(() => eventsObservableCompleted);

                    Assert.True(connected, "Expect a connection to have been made.");
                    Assert.True(disposed, "Expect the socket to have been disposed.");
                    Assert.True(messagesObservableCompleted, "Expect the BasicMessage observable to be completed");
                    Assert.True(eventsObservableCompleted, "Expect the EventMessage observable to be completed");
                }
            }
        }
        public async Task Channel_listener_should_handle_where_FS_disconnects_before_channelData_event_received()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                bool channelCallbackCalled   = false;
                bool firstConnectionReceived = false;

                listener.Channels.Subscribe(channel => { channelCallbackCalled = true; });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ =>
                    {
                        firstConnectionReceived = true;
                        freeSwitch.Dispose();
                    });

                    await Wait.Until(() => firstConnectionReceived);

                    Assert.False(channelCallbackCalled);
                }
            }
        }
        public async Task Calling_Exit_on_a_disconnected_OutboundSocket_should_close_gracefully()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                EventMessage channelData = null;
                bool exited = false;

                listener.Connections.Subscribe(
                    async (socket) =>
                    {
                        channelData = await socket.Connect();
                        await socket.Exit();
                        exited = true;
                    });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                          .Subscribe(async _ =>
                              { 
                                  await freeSwitch.SendChannelDataEvent();
                                  await Task.Delay(500);
                                  freeSwitch.Dispose();
                              });

                    await Wait.Until(() => channelData != null);
                    await Wait.Until(() => exited);

                    Assert.True(exited);
                }
            }
        }
        public async Task Calling_Connect_on_a_OutboundSocket_that_was_disconnected_should_throw_OperationCanceledException()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                Exception ex = null;

                listener.Connections.Subscribe((socket) => ex = Record.Exception(() => socket.Connect().Wait()));

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ => freeSwitch.Dispose());

                    await Wait.Until(() => ex != null);
                    Assert.IsType<TaskCanceledException>(ex.InnerException);
                }
            }
        }
        public async Task Channel_listener_should_handle_where_FS_disconnects_before_channelData_event_received()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                bool channelCallbackCalled = false;
                bool firstConnectionReceived = false;

                listener.Channels.Subscribe(channel => { channelCallbackCalled = true; });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ =>
                        { 
                            firstConnectionReceived = true;
                            freeSwitch.Dispose();
                        });

                    await Wait.Until(() => firstConnectionReceived);
                    Assert.False(channelCallbackCalled);
                }
            }
        }
        public async Task can_send_api()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool apiRequestReceived = false;
                ApiResponse apiResponse = null;

                listener.Connections.Subscribe(
                    async (socket) =>
                        {
                            await socket.Connect();

                            apiResponse = await socket.SendApi("status");
                        });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                              .Subscribe(async _ => await freeSwitch.SendChannelDataEvent());

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("api")).Subscribe(
                        async _ =>
                            {
                                apiRequestReceived = true;
                                await freeSwitch.SendApiResponseOk();
                            });

                    await Wait.Until(() => apiRequestReceived);

                    Assert.True(apiRequestReceived);
                    Assert.NotNull(apiResponse);
                    Assert.True(apiResponse.Success);
                }
            }
        }
        public async Task Channel_connect_errors_should_not_cause_subsequent_connections_to_fail()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                bool channelCallbackCalled = false;
                bool firstConnectionReceived = false;
                bool secondConnectionReceived = false;

                listener.Channels.Subscribe(channel => { channelCallbackCalled = true; });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(_ =>
                        {
                            freeSwitch.Dispose();
                            firstConnectionReceived = true;
                        });

                    await Wait.Until(() => firstConnectionReceived);
                    Assert.False(channelCallbackCalled);
                }

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect")).Subscribe(async _ =>
                        {
                            await freeSwitch.SendChannelDataEvent();
                            secondConnectionReceived = true;
                        });

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("linger") || m.StartsWith("event") || m.StartsWith("filter"))
                        .Subscribe(async _ =>
                        {
                            await freeSwitch.SendCommandReplyOk("sending OK for linger, event and filter commands");
                        });


                    await Wait.Until(() => secondConnectionReceived);
                    Assert.True(channelCallbackCalled);
                }
            }
        }
Beispiel #32
0
        private static void OutboundSocketTest()
        {
            var listener = new OutboundListener(8084);

            listener.Connections.Subscribe(
                async connection =>
                    {
                        await connection.Connect();
                        Console.WriteLine("New Socket connected");
                        
                        connection.Events.Where(x => x.EventName == EventName.ChannelHangup).Take(1).Subscribe(
                            e =>
                                {
                                    ColorConsole.WriteLine("Hangup Detected on A-Leg ".Red(),
                                                        e.Headers[HeaderNames.CallerUniqueId],
                                                        " ",
                                                        e.Headers[HeaderNames.HangupCause]);

                                    connection.Exit();
                                });

                        var uuid = connection.ChannelData.Headers[HeaderNames.UniqueId];

                        await
                            connection.SubscribeEvents(
                                EventName.Dtmf);

                        await connection.Linger();
                        await connection.ExecuteApplication(uuid, "answer", null, true, false);

                        var result =
                            await
                            connection.Play(
                                uuid, 
                                "$${base_dir}/sounds/en/us/callie/misc/8000/misc-freeswitch_is_state_of_the_art.wav");
                        
                        //await connection.ExecuteAppAsync(uuid, "conference", "test+1234");
                        //if (result.ChannelData.AnswerState != AnswerState.Hangup) await connection.Hangup(uuid, "NORMAL_CLEARING");
                    });

            listener.Start();
        }
Beispiel #33
0
        public void Run()
        {
            var listener = new OutboundListener(8084);

            listener.Channels.Subscribe(
                async channel =>
            {
                try
                {
                    channel.HangupCallBack = (e) =>
                    {
                        ColorConsole.WriteLine("Hangup Detected on A-Leg {0} {1}".Fmt(e.Headers[HeaderNames.CallerUniqueId], e.Headers[HeaderNames.HangupCause]).Red());
                        ColorConsole.WriteLine("Aleg bridge {0}".Fmt(channel.Bridge.HangupCause).OnRed());

                        ColorConsole.WriteLine(e.ToString().DarkGreen());
                    };

                    await channel.Answer();
                    await channel.StartDetectingInbandDtmf();

                    var bridgeOptions = new BridgeOptions()
                    {
                        UUID             = Guid.NewGuid().ToString(),
                        IgnoreEarlyMedia = true,
                        RingBack         =
                            "tone_stream://%(400,200,400,450);%(400,2000,400,450);loops=-1",
                        ContinueOnFail    = true,
                        HangupAfterBridge = true,
                        TimeoutSeconds    = 60,
                        CallerIdName      = channel["effective_caller_id_name"],
                        CallerIdNumber    = channel["effective_caller_id_number"],
                    };

                    bridgeOptions.ChannelVariables.Add("bridge_filter_dtmf", "true");

                    await channel.BridgeTo("user/1003", bridgeOptions, (e) => ColorConsole.WriteLine("Bridge Progress Ringing...".DarkGreen()));

                    if (!channel.Bridge.IsBridged)
                    {
                        ColorConsole.WriteLine("Bridge Failed - {0}".Fmt(channel.Bridge.HangupCause).Red());
                        await channel.PlayFile("ivr/8000/ivr-call_rejected.wav");
                        await channel.Hangup(HangupCause.NormalTemporaryFailure);
                    }
                    else
                    {
                        ColorConsole.WriteLine("Bridge success - {0}".Fmt(channel.Bridge.ResponseText).DarkGreen());

                        channel.Bridge.Channel.HangupCallBack = (e) => ColorConsole.WriteLine("Hangup Detected on B-Leg {0} {1}".Fmt(e.Headers[HeaderNames.CallerUniqueId], e.Headers[HeaderNames.HangupCause]).Red());

                        ColorConsole.WriteLine("Enabling feature codes on the B-Leg: ".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#7".Yellow(), " to Start Recording".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#8".Yellow(), " to Stop Recording".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#4".Yellow(), " to Pause Recording".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#5".Yellow(), " to Resume Recording".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#9".Yellow(), " for attended transfer".DarkGreen());

                        await channel.SetChannelVariable("RECORD_STEREO", "true");
                        var recordingPath = "{0}.wav".Fmt(channel.UUID);

                        channel.Bridge.Channel.FeatureCodes("#").Subscribe(
                            async x =>
                        {
                            try
                            {
                                ColorConsole.WriteLine("Detected Feature Code: ".DarkYellow(), x);
                                switch (x)
                                {
                                case "#4":
                                    ColorConsole.WriteLine("Mask recording".Yellow());
                                    await channel.MaskRecording();
                                    await channel.PlayFile("ivr/8000/ivr-recording_paused.wav", Leg.BLeg);
                                    break;

                                case "#5":
                                    ColorConsole.WriteLine("Unmask recording".Yellow());
                                    await channel.UnmaskRecording();
                                    await channel.PlayFile("ivr/8000/ivr-begin_recording.wav", Leg.BLeg);
                                    break;

                                case "#8":
                                    ColorConsole.WriteLine("Stop recording".Yellow());
                                    await channel.StopRecording();
                                    await channel.PlayFile(
                                        "ivr/8000/ivr-recording_stopped.wav", Leg.Both);
                                    break;

                                case "#7":
                                    ColorConsole.WriteLine("Start recording".Yellow());
                                    await channel.StartRecording(recordingPath);
                                    await channel.PlayFile("ivr/8000/ivr-begin_recording.wav", Leg.Both);
                                    break;

                                case "#9":
                                    ColorConsole.WriteLine("Attended x-fer".Yellow());
                                    await
                                    Task.WhenAll(
                                        channel.PlayFile("ivr/8000/ivr-call_being_transferred.wav"),
                                        channel.Bridge.Channel.PlayFile("misc/8000/transfer1.wav"));

                                    var digits = await channel.Bridge.Channel.Read(new ReadOptions {
                                        MinDigits = 3, MaxDigits = 4, Prompt = "tone_stream://%(10000,0,350,440)", TimeoutMs = 30000, Terminators = "#"
                                    });
                                    if (digits.Result == ReadResultStatus.Success && digits.Digits.Length == 4)
                                    {
                                        await channel.Bridge.Channel.SetChannelVariable("recording_follow_attxfer", "true");
                                        await channel.Bridge.Channel.SetChannelVariable("origination_cancel_key", "#");
                                        await channel.Bridge.Channel.SetChannelVariable("transfer_ringback", "tone_stream://%(400,200,400,450);%(400,2000,400,450);loops=-1");

                                        await channel.Bridge.Channel.PlayFile("ivr/8000/ivr-please_hold_while_party_contacted.wav");

                                        //todo: push this logic into the channel itself?

                                        channel.ExitOnHangup = false;                    //we might want to notify b+c parties if the transfer failed
                                        var xfer             = await channel.Bridge.Channel.AttendedTransfer("user/{0}".Fmt(digits));
                                        channel.ExitOnHangup = true;                     //re enable exit on hangup

                                        ColorConsole.WriteLine("XFER: {0} {1}".Fmt(xfer.Status, xfer.HangupCause).Yellow());

                                        if (xfer.Status != AttendedTransferResultStatus.Failed)
                                        {
                                            await channel.PlayFile("misc/8000/transfer2.wav", Leg.Both);
                                        }
                                        else
                                        {
                                            if (!channel.IsAnswered && channel.Bridge.Channel.IsAnswered)
                                            {
                                                await channel.Bridge.Channel.PlayFile("ivr/8000/ivr-call_attempt_aborted.wav", Leg.Both);

                                                //as a-leg has disconnected, we'll close the socket when b-leg hangs up
                                                //todo: what if it's a three-way?!
                                                channel.Bridge.Channel.HangupCallBack = async _ => await channel.Exit();

                                                return;
                                            }

                                            if (xfer.HangupCause == HangupCause.CallRejected)
                                            {
                                                await channel.Bridge.Channel.PlayFile("ivr/8000/ivr-call_rejected.wav");
                                            }
                                            else if (xfer.HangupCause == HangupCause.NoUserResponse ||
                                                     xfer.HangupCause == HangupCause.NoAnswer)
                                            {
                                                await
                                                channel.Bridge.Channel.PlayFile(
                                                    "ivr/8000/ivr-no_user_response.wav");
                                            }
                                            else if (xfer.HangupCause == HangupCause.UserBusy)
                                            {
                                                await channel.Bridge.Channel.PlayFile("ivr/8000/ivr-user_busy.wav");
                                            }
                                            else
                                            {
                                                await
                                                channel.Bridge.Channel.PlayFile(
                                                    "ivr/8000/ivr-call_cannot_be_completed_as_dialed.wav");
                                            }
                                        }
                                    }

                                    break;
                                }
                            }
                            catch (OperationCanceledException ex)
                            {
                                ColorConsole.WriteLine("TaskCancelled - shutting down\r\n{0}".Fmt(ex.ToString()).OnRed());
                                ColorConsole.WriteLine("Channel {0} is {1}".Fmt(channel.UUID, channel.Answered).OnRed());
                            }
                        });
                    }
                }
                catch (OperationCanceledException ex)
                {
                    ColorConsole.WriteLine("TaskCancelled - shutting down\r\n{0}".Fmt(ex.ToString()).OnRed());
                    ColorConsole.WriteLine("Channel {0} is {1}".Fmt(channel.UUID, channel.Answered).OnRed());
                }
            });

            listener.Start();
        }
        public void Run()
        {
            const string TempFolder = "C:/temp/";
            const string ConferenceId = "my-test-conference";
            const string ConferencePin = "1234";
            const string ConferenceArgs = ConferenceId;// +"+" + ConferencePin;

            var listener = new OutboundListener(8084);
            string conferenceServerIp = null;
            bool conferenceIsStarted = false;

            listener.Channels.Subscribe(
                async channel =>
                {
                    try
                    {
                        var serverIpAddress = channel.Advanced.GetHeader("FreeSWITCH-IPv4");
                        var destinationNumber = channel.Advanced.GetHeader("Channel-Destination-Number");

                        ColorConsole.WriteLine("Connection from server ", serverIpAddress.Blue(), " for number", destinationNumber.Blue());

                        if (conferenceServerIp != null && conferenceServerIp != serverIpAddress)
                        {
                            //the conference has started on a different server, redirect to that server
                            await channel.Execute("redirect", "sip:" + destinationNumber + "@" + conferenceServerIp);
                        }
                        else
                        {
                            //either conference has not started yet or it has started on this server
                            await channel.Answer();
                            await channel.Sleep(400);
                            await channel.PlayFile("ivr/ivr-welcome_to_freeswitch.wav");

                            if (conferenceIsStarted)
                            {
                                //prompt user for their name

                                var nameFile = string.Concat(TempFolder, channel.UUID, ".wav");
                                ColorConsole.WriteLine("Recording name file to ", nameFile.Blue());


                                await channel.PlayFile("ivr/ivr-say_name.wav");
                                await channel.PlayFile("tone_stream://%(500,0,500)");
                                await channel.Advanced.Socket.ExecuteApplication(channel.UUID, "record", nameFile + " 10 200 1");

                                //when this member enters the conference, play the announcement
                                channel.Advanced.Socket.ConferenceEvents.FirstAsync(x => x.Action == ConferenceAction.AddMember)
                                       .Subscribe(
                                           _ => channel.Advanced.Socket.Api("conference {0} play file_string://{1}!conference/conf-has_joined.wav"
                                                    .Fmt(ConferenceId, nameFile)));
                            }
                            else
                            {
                                //first person in the conference, no need to record their name
                                conferenceIsStarted = true;
                                conferenceServerIp = serverIpAddress;
                            }

                            channel.Advanced.Socket.ConferenceEvents
                                .Subscribe(x =>
                                    {
                                        ColorConsole.WriteLine("Got conf event ".DarkYellow(), x.Action.ToString().Yellow());
                                        switch (x.Action)
                                        {
                                            case ConferenceAction.StartTalking:
                                                ColorConsole.WriteLine(
                                                    "Channel ".DarkGreen(), x.UUID.Green(), " started talking".DarkGreen());
                                                break;
                                            case ConferenceAction.StopTalking:
                                                ColorConsole.WriteLine("Channel ".DarkRed(), x.UUID.Red(), " stopped talking".DarkRed());
                                                break;
                                        }
                                    });

                            //if we await the result of this, we'll get OperationCanceledException on hangup
                            await channel.Advanced.Socket.ExecuteApplication(channel.UUID, "conference", ConferenceArgs);
                        }
                    }
                    catch (OperationCanceledException ex)
                    {
                        ColorConsole.WriteLine("TaskCancelled - shutting down\r\n{0}".Fmt(ex.ToString()).OnRed());
                        ColorConsole.WriteLine("Channel {0} is {1}".Fmt(channel.UUID, channel.Answered).OnRed());
                    }
                });

            listener.Start();
        }
Beispiel #35
0
        public void Run()
        {
            const string TempFolder     = "C:/temp/";
            const string ConferenceId   = "my-test-conference";
            const string ConferencePin  = "1234";
            const string ConferenceArgs = ConferenceId;// +"+" + ConferencePin;

            var    listener            = new OutboundListener(8084);
            string conferenceServerIp  = null;
            bool   conferenceIsStarted = false;

            listener.Channels.Subscribe(
                async channel =>
            {
                try
                {
                    var serverIpAddress   = channel.Advanced.GetHeader("FreeSWITCH-IPv4");
                    var destinationNumber = channel.Advanced.GetHeader("Channel-Destination-Number");

                    ColorConsole.WriteLine("Connection from server ", serverIpAddress.Blue(), " for number", destinationNumber.Blue());

                    if (conferenceServerIp != null && conferenceServerIp != serverIpAddress)
                    {
                        //the conference has started on a different server, redirect to that server
                        await channel.Execute("redirect", "sip:" + destinationNumber + "@" + conferenceServerIp);
                    }
                    else
                    {
                        //either conference has not started yet or it has started on this server
                        await channel.Answer();
                        await channel.Sleep(400);
                        await channel.PlayFile("ivr/ivr-welcome_to_freeswitch.wav");

                        if (conferenceIsStarted)
                        {
                            //prompt user for their name

                            var nameFile = string.Concat(TempFolder, channel.UUID, ".wav");
                            ColorConsole.WriteLine("Recording name file to ", nameFile.Blue());


                            await channel.PlayFile("ivr/ivr-say_name.wav");
                            await channel.PlayFile("tone_stream://%(500,0,500)");
                            await channel.Advanced.Socket.ExecuteApplication(channel.UUID, "record", nameFile + " 10 200 1");

                            //when this member enters the conference, play the announcement
                            channel.Advanced.Socket.ConferenceEvents.FirstAsync(x => x.Action == ConferenceAction.AddMember)
                            .Subscribe(
                                _ => channel.Advanced.Socket.Api("conference {0} play file_string://{1}!conference/conf-has_joined.wav"
                                                                 .Fmt(ConferenceId, nameFile)));
                        }
                        else
                        {
                            //first person in the conference, no need to record their name
                            conferenceIsStarted = true;
                            conferenceServerIp  = serverIpAddress;
                        }

                        channel.Advanced.Socket.ConferenceEvents
                        .Subscribe(x =>
                        {
                            ColorConsole.WriteLine("Got conf event ".DarkYellow(), x.Action.ToString().Yellow());
                            switch (x.Action)
                            {
                            case ConferenceAction.StartTalking:
                                ColorConsole.WriteLine(
                                    "Channel ".DarkGreen(), x.UUID.Green(), " started talking".DarkGreen());
                                break;

                            case ConferenceAction.StopTalking:
                                ColorConsole.WriteLine("Channel ".DarkRed(), x.UUID.Red(), " stopped talking".DarkRed());
                                break;
                            }
                        });

                        //if we await the result of this, we'll get OperationCanceledException on hangup
                        await channel.Advanced.Socket.ExecuteApplication(channel.UUID, "conference", ConferenceArgs);
                    }
                }
                catch (OperationCanceledException ex)
                {
                    ColorConsole.WriteLine("TaskCancelled - shutting down\r\n{0}".Fmt(ex.ToString()).OnRed());
                    ColorConsole.WriteLine("Channel {0} is {1}".Fmt(channel.UUID, channel.Answered).OnRed());
                }
            });

            listener.Start();
        }
Beispiel #36
0
        public void Run()
        {
            var listener = new OutboundListener(8084);

            listener.Channels.Subscribe(
                async channel =>
                    {
                        try
                        {
                            channel.HangupCallBack = (e) =>
                                {
                                    ColorConsole.WriteLine("Hangup Detected on A-Leg {0} {1}".Fmt(e.Headers[HeaderNames.CallerUniqueId], e.Headers[HeaderNames.HangupCause]).Red());
                                    ColorConsole.WriteLine("Aleg bridge {0}".Fmt(channel.Bridge.HangupCause).OnRed());

                                    ColorConsole.WriteLine(e.ToString().DarkGreen());
                                };

                            await channel.Answer();
                            await channel.StartDetectingInbandDtmf();

                            var bridgeOptions = new BridgeOptions()
                                                    {
                                                        UUID = Guid.NewGuid().ToString(),
                                                        IgnoreEarlyMedia = true,
                                                        RingBack =
                                                            "tone_stream://%(400,200,400,450);%(400,2000,400,450);loops=-1",
                                                        ContinueOnFail = true,
                                                        HangupAfterBridge = true,
                                                        TimeoutSeconds = 60,
                                                        CallerIdName = channel.Advanced.GetVariable("effective_caller_id_name"),
                                                        CallerIdNumber = channel.Advanced.GetVariable("effective_caller_id_number"),
                                                    };

                            bridgeOptions.ChannelVariables.Add("bridge_filter_dtmf", "true");

                            await channel.BridgeTo("user/1003", bridgeOptions, (e) => ColorConsole.WriteLine("Bridge Progress Ringing...".DarkGreen()));

                            if (!channel.Bridge.IsBridged)
                            {
                                ColorConsole.WriteLine("Bridge Failed - {0}".Fmt(channel.Bridge.HangupCause).Red());
                                await channel.PlayFile("ivr/8000/ivr-call_rejected.wav");
                                await channel.Hangup(HangupCause.NormalTemporaryFailure);
                            }
                            else
                            {
                                ColorConsole.WriteLine("Bridge success - {0}".Fmt(channel.Bridge.ResponseText).DarkGreen());

                                channel.Bridge.Channel.HangupCallBack = (e) => ColorConsole.WriteLine("Hangup Detected on B-Leg {0} {1}".Fmt(e.Headers[HeaderNames.CallerUniqueId], e.Headers[HeaderNames.HangupCause]).Red());

                                ColorConsole.WriteLine("Enabling feature codes on the B-Leg: ".DarkGreen());
                                ColorConsole.WriteLine("Press ".DarkGreen(), "#7".Yellow(), " to Start Recording".DarkGreen());
                                ColorConsole.WriteLine("Press ".DarkGreen(), "#8".Yellow(), " to Stop Recording".DarkGreen());
                                ColorConsole.WriteLine("Press ".DarkGreen(), "#4".Yellow(), " to Pause Recording".DarkGreen());
                                ColorConsole.WriteLine("Press ".DarkGreen(), "#5".Yellow(), " to Resume Recording".DarkGreen());
                                ColorConsole.WriteLine("Press ".DarkGreen(), "#9".Yellow(), " for attended transfer".DarkGreen());

                                await channel.SetChannelVariable("RECORD_STEREO", "true");
                                var recordingPath = "{0}.wav".Fmt(channel.UUID);

                                channel.Bridge.Channel.FeatureCodes("#").Subscribe(
                                    async x =>
                                        {
                                            try
                                            {
                                                ColorConsole.WriteLine("Detected Feature Code: ".DarkYellow(), x);
                                                switch (x)
                                                {
                                                    case "#4":
                                                        ColorConsole.WriteLine("Mask recording".Yellow());
                                                        await channel.MaskRecording();
                                                        await channel.PlayFile("ivr/8000/ivr-recording_paused.wav", Leg.BLeg);
                                                        break;
                                                    case "#5":
                                                        ColorConsole.WriteLine("Unmask recording".Yellow());
                                                        await channel.UnmaskRecording();
                                                        await channel.PlayFile("ivr/8000/ivr-begin_recording.wav", Leg.BLeg);
                                                        break;
                                                    case "#8":
                                                        ColorConsole.WriteLine("Stop recording".Yellow());
                                                        await channel.StopRecording();
                                                        await channel.PlayFile(
                                                            "ivr/8000/ivr-recording_stopped.wav", Leg.Both);
                                                        break;
                                                    case "#7":
                                                        ColorConsole.WriteLine("Start recording".Yellow());
                                                        await channel.StartRecording(recordingPath);
                                                        await channel.PlayFile("ivr/8000/ivr-begin_recording.wav", Leg.Both);
                                                        break;
                                                    case "#9":
                                                        ColorConsole.WriteLine("Attended x-fer".Yellow());
                                                        await
                                                            Task.WhenAll(
                                                                channel.PlayFile("ivr/8000/ivr-call_being_transferred.wav"),
                                                                channel.Bridge.Channel.PlayFile("misc/8000/transfer1.wav"));

                                                        var digits = await channel.Bridge.Channel.Read(new ReadOptions { MinDigits = 3, MaxDigits = 4, Prompt = "tone_stream://%(10000,0,350,440)", TimeoutMs = 30000, Terminators = "#" });
                                                        if (digits.Result == ReadResultStatus.Success && digits.Digits.Length == 4)
                                                        {
                                                            await channel.Bridge.Channel.SetChannelVariable("recording_follow_attxfer", "true");
                                                            await channel.Bridge.Channel.SetChannelVariable("origination_cancel_key", "#");
                                                            await channel.Bridge.Channel.SetChannelVariable("transfer_ringback", "tone_stream://%(400,200,400,450);%(400,2000,400,450);loops=-1");

                                                            await channel.Bridge.Channel.PlayFile("ivr/8000/ivr-please_hold_while_party_contacted.wav");

                                                            //todo: push this logic into the channel itself?

                                                            channel.ExitOnHangup = false; //we might want to notify b+c parties if the transfer failed
                                                            var xfer = await channel.Bridge.Channel.AttendedTransfer("user/{0}".Fmt(digits));
                                                            channel.ExitOnHangup = true; //re enable exit on hangup

                                                            ColorConsole.WriteLine("XFER: {0} {1}".Fmt(xfer.Status, xfer.HangupCause).Yellow());

                                                            if (xfer.Status != AttendedTransferResultStatus.Failed)
                                                            {
                                                                await channel.PlayFile("misc/8000/transfer2.wav", Leg.Both);
                                                            }
                                                            else
                                                            {
                                                                if (!channel.IsAnswered && channel.Bridge.Channel.IsAnswered)
                                                                {
                                                                    await channel.Bridge.Channel.PlayFile("ivr/8000/ivr-call_attempt_aborted.wav", Leg.Both);

                                                                    //as a-leg has disconnected, we'll close the socket when b-leg hangs up
                                                                    //todo: what if it's a three-way?!
                                                                    channel.Bridge.Channel.HangupCallBack = async _ => await channel.Exit();

                                                                    return;
                                                                }

                                                                if (xfer.HangupCause == HangupCause.CallRejected)
                                                                {
                                                                    await channel.Bridge.Channel.PlayFile("ivr/8000/ivr-call_rejected.wav");
                                                                }
                                                                else if (xfer.HangupCause == HangupCause.NoUserResponse
                                                                         || xfer.HangupCause == HangupCause.NoAnswer)
                                                                {
                                                                    await
                                                                        channel.Bridge.Channel.PlayFile(
                                                                            "ivr/8000/ivr-no_user_response.wav");
                                                                }
                                                                else if (xfer.HangupCause == HangupCause.UserBusy)
                                                                {
                                                                    await channel.Bridge.Channel.PlayFile("ivr/8000/ivr-user_busy.wav");
                                                                }
                                                                else
                                                                {
                                                                    await
                                                                        channel.Bridge.Channel.PlayFile(
                                                                            "ivr/8000/ivr-call_cannot_be_completed_as_dialed.wav");
                                                                }
                                                            }
                                                        }

                                                        break;
                                                }
                                            }
                                            catch (OperationCanceledException ex)
                                            {
                                                ColorConsole.WriteLine("TaskCancelled - shutting down\r\n{0}".Fmt(ex.ToString()).OnRed());
                                                ColorConsole.WriteLine("Channel {0} is {1}".Fmt(channel.UUID, channel.Answered).OnRed());
                                            }
                                        });
                            }
                        }
                        catch (OperationCanceledException ex)
                        {
                            ColorConsole.WriteLine("TaskCancelled - shutting down\r\n{0}".Fmt(ex.ToString()).OnRed());
                            ColorConsole.WriteLine("Channel {0} is {1}".Fmt(channel.UUID, channel.Answered).OnRed());
                        }
                    });

            listener.Start();
        }
        public async Task each_new_connection_produces_a_new_outbound_socket_from_the_Connections_observable()
        {
            const int NumberOfConnections = 3;

            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                var connected = 0;

                listener.Connections.Subscribe((socket) => connected++);

                for (int i = 0; i < NumberOfConnections; i++)
                {
                    var client = new FakeFreeSwitchSocket(listener.Port);
                }

                await Wait.Until(() => connected == NumberOfConnections);
                Assert.Equal(NumberOfConnections, connected);
            }
        }
        public Task Run(CancellationToken cancellationToken)
        {
            const string MusicOnHold = "local_stream://moh";

            const string AgentEndPoint = "user/1003";
            const string RingTone      = "tone_stream://%(400,200,400,450);%(400,2000,400,450);loops=-1"; // uk ring
            const string DialTone      = "tone_stream://%(10000,0,350,440)";
            const string RecordingPath = "/var/tmp/";

            listener = new OutboundListener(8084);

            listener.Channels.Subscribe(
                async channel =>
            {
                try
                {
                    channel.BridgedChannels.Subscribe(
                        async bridgedChannel =>
                    {
                        ColorConsole.WriteLine("New Bridged Channel  [{0}]".Fmt(bridgedChannel.Uuid).DarkGreen());

                        bridgedChannel.HangupCallBack =
                            (e) =>
                            ColorConsole.WriteLine(
                                "Hangup Detected on B-Leg {0} {1}".Fmt(
                                    e.Headers[HeaderNames.CallerUniqueId],
                                    e.Headers[HeaderNames.HangupCause]).Red());

                        ColorConsole.WriteLine("Enabling feature codes on the B-Leg: ".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#1".Yellow(), " to Play to both Legs".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#2".Yellow(), " to Play to A Leg".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#3".Yellow(), " to Play to B Leg".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#7".Yellow(), " to Start Recording".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#8".Yellow(), " to Stop Recording".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#4".Yellow(), " to Pause Recording".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#5".Yellow(), " to Resume Recording".DarkGreen());
                        ColorConsole.WriteLine("Press ".DarkGreen(), "#9".Yellow(), " for attended transfer".DarkGreen());

                        await channel.SetChannelVariable("RECORD_STEREO", "true");
                        var recordingPath = RecordingPath + channel.Uuid + ".wav";

                        bridgedChannel.FeatureCodes("#").Subscribe(
                            async x =>
                        {
                            try
                            {
                                ColorConsole.WriteLine("Detected Feature Code: ".DarkYellow(), x);
                                switch (x)
                                {
                                case "#1":
                                    await channel.Play("ivr/ivr-welcome_to_freeswitch.wav", Leg.Both);
                                    break;

                                case "#2":
                                    await channel.Play("ivr/ivr-welcome_to_freeswitch.wav", Leg.ALeg);
                                    break;

                                case "#3":
                                    await channel.Play("ivr/ivr-welcome_to_freeswitch.wav", Leg.BLeg);
                                    break;

                                case "#4":
                                    ColorConsole.WriteLine("Mask recording".Yellow());
                                    await channel.MaskRecording();
                                    await channel.Play("ivr/ivr-recording_paused.wav", Leg.BLeg);
                                    break;

                                case "#5":
                                    ColorConsole.WriteLine("Unmask recording".Yellow());
                                    await channel.UnmaskRecording();
                                    await channel.Play("ivr/ivr-begin_recording.wav", Leg.BLeg);
                                    break;

                                case "#8":
                                    ColorConsole.WriteLine("Stop recording".Yellow());
                                    await channel.StopRecording();
                                    await channel.Play("ivr/ivr-recording_stopped.wav", Leg.Both);
                                    break;

                                case "#7":
                                    ColorConsole.WriteLine("Start recording".Yellow());
                                    await channel.StartRecording(recordingPath);
                                    await channel.Play("ivr/ivr-begin_recording.wav", Leg.Both);
                                    break;

                                case "#9":
                                    ColorConsole.WriteLine("Attended x-fer".Yellow());
                                    await
                                    Task.WhenAll(
                                        channel.Play("ivr/ivr-call_being_transferred.wav"),
                                        bridgedChannel.Play("misc/transfer1.wav"));

                                    var holdMusic = await channel.PlayUntilCancelled(MusicOnHold);

                                    var digits =
                                        await
                                        bridgedChannel.Read(
                                            new ReadOptions
                                    {
                                        MinDigits   = 3,
                                        MaxDigits   = 4,
                                        Prompt      = DialTone,
                                        TimeoutMs   = 30000,
                                        Terminators = "#"
                                    });

                                    if (digits.Result != ReadResultStatus.Success || digits.Digits.Length != 4)
                                    {
                                        holdMusic.Dispose();
                                    }
                                    else
                                    {
                                        await bridgedChannel.SetChannelVariable("recording_follow_attxfer", "true");
                                        await bridgedChannel.SetChannelVariable("origination_cancel_key", "#");
                                        await bridgedChannel.SetChannelVariable("transfer_ringback", RingTone);

                                        var xfer = await bridgedChannel.AttendedTransfer("user/{0}".Fmt(digits));
                                        holdMusic.Dispose();

                                        ColorConsole.WriteLine(
                                            "Xfer ".Yellow(),
                                            xfer.Status.ToString().DarkYellow(),
                                            " ",
                                            xfer.HangupCause.GetValueOrDefault().ToString());


                                        if (xfer.Status != AttendedTransferResultStatus.Failed)
                                        {
                                            await channel.Play("misc/transfer2.wav", Leg.Both);
                                        }
                                        else
                                        {
                                            if (xfer.HangupCause == HangupCause.CallRejected)
                                            {
                                                await bridgedChannel.Play("ivr/ivr-call_rejected.wav");
                                            }
                                            else if (xfer.HangupCause == HangupCause.NoUserResponse ||
                                                     xfer.HangupCause == HangupCause.NoAnswer)
                                            {
                                                await bridgedChannel.Play("ivr/ivr-no_user_response.wav");
                                            }
                                            else if (xfer.HangupCause == HangupCause.UserBusy)
                                            {
                                                await bridgedChannel.Play("ivr/ivr-user_busy.wav");
                                            }
                                            else
                                            {
                                                await
                                                bridgedChannel.Play(
                                                    "ivr/ivr-call_cannot_be_completed_as_dialed.wav");
                                            }
                                        }
                                    }

                                    break;
                                }
                            }
                            catch (OperationCanceledException ex)
                            {
                                ColorConsole.WriteLine("TaskCancelled - shutting down\r\n{0}".Fmt(ex.ToString()).OnRed());
                                ColorConsole.WriteLine("Channel {0} is {1}".Fmt(channel.Uuid, channel.Answered).OnRed());
                            }
                        });
                    });

                    channel.HangupCallBack = (e) =>
                    {
                        ColorConsole.WriteLine("Hangup Detected on A-Leg {0} {1}".Fmt(e.Headers[HeaderNames.CallerUniqueId], e.Headers[HeaderNames.HangupCause]).Red());
                        ColorConsole.WriteLine("Aleg bridge {0}".Fmt(channel.GetVariable("last_bridge_hangup_cause")).OnRed());
                    };

                    await channel.Answer();

                    var queueHoldMusic = await channel.PlayUntilCancelled(MusicOnHold);

                    await Task.Delay(5000);

                    await channel.Play(new[]
                    {
                        "ivr/ivr-you_are_number.wav",
                        123456.ToFileString(),
                        "ivr/ivr-in_line.wav"
                    });

                    await Task.Delay(5000);

                    queueHoldMusic.Dispose();

                    var bridgeOptions = new BridgeOptions()
                    {
                        UUID              = Guid.NewGuid().ToString(),
                        IgnoreEarlyMedia  = true,
                        RingBack          = RingTone,
                        ContinueOnFail    = true,
                        HangupAfterBridge = true,
                        TimeoutSeconds    = 10,
                        CallerIdName      = channel.GetVariable("effective_caller_id_name"),
                        CallerIdNumber    =
                            channel.GetVariable("effective_caller_id_number"),
                    };


                    await channel.SetChannelVariable(
                        "transfer_ringback",
                        "tone_stream://%(400,200,400,450);%(400,2000,400,450);loops=-1");


                    await channel.BridgeTo(AgentEndPoint, bridgeOptions, (e) => ColorConsole.WriteLine("Bridge Progress Ringing...".DarkGreen()));

                    if (!channel.IsBridged)
                    {
                        ColorConsole.WriteLine("Bridge Failed - {0}".Fmt(channel.Variables.BridgeHangupCause).Red());
                        await channel.Play("ivr/ivr-call_rejected.wav");
                        await channel.Hangup(HangupCause.NormalTemporaryFailure);
                    }
                }
                catch (OperationCanceledException ex)
                {
                    ColorConsole.WriteLine("TaskCancelled - shutting down\r\n{0}".Fmt(ex.ToString()).OnRed());
                    ColorConsole.WriteLine("Channel {0} is {1}".Fmt(channel.Uuid, channel.Answered).OnRed());
                }
            });

            listener.Start();

            Console.WriteLine("Listener started. Press [Enter] to stop");
            Console.ReadLine();

            return(Task.FromResult(0));
        }
        public async Task Calling_Connect_on_a_new_OutboundSocket_should_populate_the_ChannelData()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();
                EventMessage channelData = null;

                listener.Connections.Subscribe(
                    async (socket) =>
                    {
                        channelData = await socket.Connect();
                    });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                          .Subscribe(async _ => await freeSwitch.SendChannelDataEvent());

                    await Wait.Until(() => channelData != null);

                    Assert.NotNull(channelData);
                    Assert.Equal(ChannelState.Execute, channelData.ChannelState);
                    Assert.Equal("RINGING", channelData.Headers["Channel-Call-State"]);
                }
            }
        }
        public async Task can_send_multple_commands()
        {
            using (var listener = new OutboundListener(0))
            {
                listener.Start();

                bool commandRequestReceived = false;
                CommandReply commandReply = null;

                listener.Connections.Subscribe(
                    async (socket) =>
                    {
                        await socket.Connect();

                        commandReply = await socket.Linger();

                        commandReply = await socket.NoLinger();
                    });

                using (var freeSwitch = new FakeFreeSwitchSocket(listener.Port))
                {
                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("connect"))
                          .Subscribe(async _ => await freeSwitch.SendChannelDataEvent());

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("linger"))
                          .Subscribe(async _ =>
                          {
                              await freeSwitch.SendCommandReplyOk();
                          });

                    freeSwitch.MessagesReceived.FirstAsync(m => m.StartsWith("nolinger"))
                          .Subscribe(async _ =>
                          {
                              await freeSwitch.SendCommandReplyError("FAILED");
                              commandRequestReceived = true;
                          });

                    await Wait.Until(() => commandRequestReceived);

                    Assert.True(commandRequestReceived);
                    Assert.NotNull(commandReply);
                    Assert.False(commandReply.Success);
                }
            }
        }
Beispiel #41
0
        public Task Run(CancellationToken cancellationToken)
        {
            listener  = new OutboundListener(8084);
            listener2 = new OutboundListener(8085);

            /* this example demonstrates forwarding an outbound connection from one listener to another.
             * FS Dialplan is configured to hit localhost:8084
             * By parking the call then using sched_api to schedule a transfer, we can disconnect the socket on localhost:8084
             * and allow  transfer the call to localhost:8085 without hanging up the call when the first socket disconnects. */

            listener.Connections.Subscribe(
                async connection =>
            {
                try
                {
                    await connection.Connect();
                    await connection.ExecuteApplication(connection.ChannelData.UUID, "pre_answer");

                    //let's pretend we did a database or service registry lookup to find the socket server we want to route to - localhost:8085 in this example

                    await connection.Api("uuid_park", connection.ChannelData.UUID);
                    await connection.Api("sched_api +0.01 none uuid_transfer {0} 'socket:127.0.0.1:8085 async full' inline".Fmt(connection.ChannelData.UUID));
                    await connection.Exit();
                }
                catch (OperationCanceledException)
                {
                }
            });

            listener2.Connections.Subscribe(
                async connection =>
            {
                try
                {
                    await connection.Connect();

                    Console.WriteLine("New Socket connected");

                    await connection.ExecuteApplication(connection.ChannelData.UUID, "answer");

                    connection.Events.Where(x => x.UUID == connection.ChannelData.UUID && x.EventName == EventName.ChannelHangup)
                    .Take(1)
                    .Subscribe(
                        async e =>
                    {
                        ColorConsole.WriteLine(
                            "Hangup Detected on A-Leg ".Red(),
                            e.Headers[HeaderNames.CallerUniqueId],
                            " ",
                            e.Headers[HeaderNames.HangupCause]);

                        await connection.Exit();
                    });


                    connection.Events.Where(x => x.UUID == connection.ChannelData.UUID && x.EventName == EventName.Dtmf)
                    .Subscribe(
                        async e =>
                    {
                        ColorConsole.WriteLine(
                            "DTMF Detected on A-Leg ".Red(),
                            e.Headers[HeaderNames.CallerUniqueId].Yellow(),
                            " ",
                            e.Headers[HeaderNames.DtmfDigit].Red());

                        await connection.Play(connection.ChannelData.UUID, "ivr/ivr-you_entered.wav");

                        await
                        connection.Say(
                            connection.ChannelData.UUID,
                            new SayOptions()
                        {
                            Gender = SayGender.Feminine,
                            Method = SayMethod.Iterated,
                            Text   = e.Headers[HeaderNames.DtmfDigit],
                            Type   = SayType.Number
                        });
                    });

                    var uuid = connection.ChannelData.Headers[HeaderNames.UniqueId];

                    await connection.SubscribeEvents(EventName.Dtmf, EventName.ChannelHangup);

                    await connection.Linger();
                    await connection.ExecuteApplication(uuid, "answer", null, true, false);

                    await connection.Play(uuid, "misc/misc-freeswitch_is_state_of_the_art.wav");
                }
                catch (OperationCanceledException)
                {
                }
            });

            listener.Start();

            listener2.Start();

            Console.WriteLine("Listener started on 8084 and 8085. Press [Enter] to exit");
            Console.ReadLine();

            return(Task.FromResult(0));
        }
Beispiel #42
0
        public async Task Run(CancellationToken cancellationToken)
        {
            //cancellationToken is cancelled when Ctrl+C is pressed
            //we'll use our own inner cancellationToken in our business logic
            //and link it to the outer one that is provided.
            var ourCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

            using (var client = await InboundSocket.Connect())
            {
                Console.WriteLine("Authenticated!");

                await client.SubscribeEvents(EventName.ChannelHangup, EventName.BackgroundJob);

                client.ChannelEvents.Where(x => x.EventName == EventName.ChannelHangup && x.HangupCause != HangupCause.NormalClearing)
                .Subscribe(x => { Console.WriteLine("Hangup Detected : {0} {1}", x.GetVariable("mobile_no"), x.HangupCause); });

                using (var listener = new OutboundListener(8084))
                {
                    listener.Connections.Subscribe(
                        async socket =>
                    {
                        try
                        {
                            await socket.Connect();
                            await socket.Filter(HeaderNames.UniqueId, socket.ChannelData.UUID);

                            var uuid = socket.ChannelData.Headers[HeaderNames.UniqueId];
                            Console.WriteLine(
                                "OutboundSocket connected for channel {0} {1}",
                                uuid,
                                socket.ChannelData.GetVariable("mobile_no"));

                            await socket.Play(uuid, "misc/8000/misc-learn_more_about_freeswitch_solutions.wav");
                            await socket.Play(uuid, "misc/8000/misc-freeswitch_is_state_of_the_art.wav");
                            await socket.ExecuteApplication(uuid, "sleep", "1000");         //wait for audio to go out to the network
                            await socket.Hangup(uuid, HangupCause.NormalClearing);
                        }
                        catch (OperationCanceledException)
                        {
                            //hangup - freeswitch disconnected from us
                        }
                    });

                    listener.Start();

                    var checkCallCount = new Task(
                        async() =>
                    {
                        try
                        {
                            while (!ourCancellationToken.IsCancellationRequested)
                            {
                                var res = await client.SendApi("show calls count");
                                Console.WriteLine("Current Calls Count " + Convert.ToInt32(res.BodyText.Split(' ')[0]));
                                currentCallCount = Convert.ToInt32(res.BodyText.Split(' ')[0]);
                                await Task.Delay(2000);
                            }
                        }
                        catch (OperationCanceledException)
                        {
                            //shutdown
                        }
                    });

                    checkCallCount.Start();

                    Task.Run(
                        async() =>
                    {
                        try
                        {
                            await Dialler(client, ourCancellationToken.Token);
                        }
                        catch (OperationCanceledException)
                        {
                            //shutdown
                        }
                    });

                    ColorConsole.WriteLine("Press [Enter] to exit.".Green());
                    await Util.WaitForEnterKeyPress(cancellationToken);

                    ourCancellationToken.Cancel();

                    listener.Dispose();
                }
            }
        }