private PushChannel AChannel(int queuedEventCount) { var channelEvents = new ChannelEvents(); var theChannel = Substitute.For<PushChannel>(); theChannel.Events.Returns(channelEvents); theChannel.QueuedNotificationCount.Returns(queuedEventCount); return theChannel; }
/// <summary> /// Bridge a new channel to the existing one. Generally used to route an incoming call to one or more endpoints. /// </summary> /// <remarks> /// See https://freeswitch.org/confluence/display/FREESWITCH/bridge /// </remarks> /// <param name="uuid">The UUID of the channel to bridge (the A-Leg).</param> /// <param name="endpoint">The destination to dial.</param> /// <param name="options">(Optional) Any <seealso cref="BridgeOptions"/> to configure the bridge.</param> /// <returns>A Task of <seealso cref="BridgeResult"/>.</returns> public async Task <BridgeResult> Bridge(string uuid, string endpoint, BridgeOptions options = null) { if (options == null) { options = new BridgeOptions(); } if (string.IsNullOrEmpty(options.UUID)) { options.UUID = Guid.NewGuid().ToString(); } var bridgeString = string.Format("{0}{1}", options, endpoint); // some bridge options need to be set in channel vars if (options.ChannelVariables.Any()) { await this.SetMultipleChannelVariables( uuid, options.ChannelVariables.Select(kvp => kvp.Key + "='" + kvp.Value + "'").ToArray()).ConfigureAwait(false); } /* If the bridge fails to connect we'll get a CHANNEL_EXECUTE_COMPLETE event with a failure message and the Execute task will complete. * If the bridge succeeds, that event won't arrive until after the bridged leg hangs up and completes the call. * In this case, we want to return a result as soon as the b-leg picks up and connects so we'll merge with the CHANNEL_BRIDGE event * observable.Amb(otherObservable) will propogate the first sequence to produce a result. */ await SubscribeEvents(EventName.ChannelBridge, EventName.ChannelHangup).ConfigureAwait(false); var bridgedOrHungupEvent = ChannelEvents.FirstOrDefaultAsync(x => x.UUID == uuid && (x.EventName == EventName.ChannelBridge || x.EventName == EventName.ChannelHangup)) .Do( e => { if (e != null) { switch (e.EventName) { case EventName.ChannelBridge: Console.WriteLine("Bridge [{0} - {1}] complete - {2}".Fmt(uuid, options.UUID, e.Headers[HeaderNames.OtherLegUniqueId])); break; case EventName.ChannelHangup: Console.WriteLine("Bridge [{0} - {1}] aborted, channel hangup [{2}]".Fmt(uuid, options.UUID, e.Headers[HeaderNames.HangupCause])); break; } } }); return (await ExecuteApplication(uuid, "bridge", bridgeString) .ToObservable() .Amb(bridgedOrHungupEvent) .Select(x => new BridgeResult(x)) .ToTask() .ConfigureAwait(false)); }
public void VirtualChannelOpenEvent(int openHandle, ChannelEvents Event, IntPtr pData, int dataLength, uint totalLength, ChannelFlags dataFlags) { Debug.Print(DateTime.Now + " " + Environment.MachineName + ": VirtualChannelOpenEvent: " + Event); switch (Event) { case ChannelEvents.DataReceived: var data = new byte[dataLength]; Marshal.Copy(pData, data, 0, dataLength); switch (dataFlags & ChannelFlags.Only) { case ChannelFlags.Only: MessageReceived(ChannelMessage.FromByteArray(data)); break; case ChannelFlags.First: memoryStream = new MemoryStream((int)totalLength); memoryStream.Write(data, 0, data.Length); break; case ChannelFlags.Middle: if (memoryStream != null) { memoryStream.Write(data, 0, data.Length); } break; case ChannelFlags.Last: if (memoryStream != null) { memoryStream.Write(data, 0, data.Length); memoryStream.Position = 0; MessageReceived(ChannelMessage.FromStream(memoryStream)); memoryStream = null; } break; } break; case ChannelEvents.WriteCanceled: case ChannelEvents.WriteComplete: /* * The VirtualChannelWrite function is asynchronous. When the write operation has been completed, * your VirtualChannelOpenEvent function receives a CHANNEL_EVENT_WRITE_COMPLETE notification. * Until that notification is received, the caller must not free or reuse the pData buffer passed to VirtualChannelWrite */ Marshal.FreeHGlobal(pData); break; } }
public void GivenAQueueBalancer() { var channelEvents = new ChannelEvents(); this.eventsProxy = new ChannelEvents(); this.eventsProxy.OnChannelCreated += this.eventsProxyOnChannelCreated; var channelFactory = Substitute.For<ChannelFactory>(); var channel = Substitute.For<PushChannel>(); channel.Events.Returns(channelEvents); channelFactory.Create().Returns(channel); this.balancer = new QueueLengthLoadBalancer(channelFactory, this.eventsProxy, PlatformType.None); this.balancer.AddChannels(5); }
public void WhenBalancerIsShutdown() { var channelEvents = new ChannelEvents(); this.eventsProxy = new ChannelEvents(); var channelFactory = Substitute.For<ChannelFactory>(); this.theChannel = Substitute.For<PushChannel>(); this.theChannel.Events.Returns(channelEvents); channelFactory.Create().Returns(this.theChannel); this.balancer = new QueueLengthLoadBalancer(channelFactory, this.eventsProxy, PlatformType.None); this.balancer.AddChannels(1); this.balancer.ShutdownAll(true); }
public void WhenTwoChannelsAreRemoved() { var channelEvents = new ChannelEvents(); this.eventsProxy = new ChannelEvents(); this.eventsProxy.OnChannelDestroyed += this.EventsProxyOnChannelDestroyed; var channelFactory = Substitute.For<ChannelFactory>(); var channel = Substitute.For<PushChannel>(); channel.Events.Returns(channelEvents); channelFactory.Create().Returns(channel); this.balancer = new QueueLengthLoadBalancer(channelFactory, this.eventsProxy, PlatformType.None); this.balancer.AddChannels(3); this.balancer.RemoveChannels(5); }
public void VirtualChannelOpenEvent(int openHandle, ChannelEvents Event, byte[] data, int dataLength, uint totalLength, ChannelFlags dataFlags) { DataChannelEventArgs args = new DataChannelEventArgs() { Data = data, DataFlags = dataFlags, DataLength = dataLength, Event = Event, OpenHandle = openHandle, TotalLength = totalLength }; OnDataChannelEvent(args); }
public Base(Negotiation.Base parent, Message.Negotiation.Parameters parameters, UnityAction <Base> disconnection_handler) { this.parent = parent; this.parameters = parameters; events = new ChannelEvents(); events.onDisconnectedHandler = new ChannelEvents.DisonnectionHandlerCallback(); events.onDisconnectedHandler.AddListener(disconnection_handler); sendResult = null; sendQueue = new Queue <Threads.Task>(); stopEvent = new ManualResetEvent(false); addEvent = new ManualResetEvent(false); worker = new Threads.Thread(Worker); }
public void WhenBalancerIsShutdown() { this.eventsProxy = new ChannelEvents(); var channelFactory = Substitute.For<ChannelFactory>(); this.GivenAnEmptyChannel(); this.GivenABusyChannel(); channelFactory.Create().Returns(this.theEmptyChannel, theBusyChannel); this.balancer = new QueueLengthLoadBalancer(channelFactory, this.eventsProxy, PlatformType.None); this.theNotification = Substitute.For<Notification>(); this.balancer.AddChannels(2); this.balancer.Distribute(this.theNotification); }
private void VirtualChannelInitEventProc(IntPtr initHandle, ChannelEvents Event, byte[] data, int dataLength) { Debug.Print(DateTime.Now + " " + Environment.MachineName + ": VirtualChannelInitEventProc: " + Event); switch (Event) { case ChannelEvents.Initialized: break; case ChannelEvents.Connected: var ret = entryPoints.VirtualChannelOpen(initHandle, ref OpenChannel, ChannelMessage.ChannelName, channelOpenEventDelegate); if (ret != ChannelReturnCodes.Ok) { MessageBox.Show("TSTunnels: Open of RDP virtual channel failed.\n" + ret, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { /*main = new frmMain(entryPoints, OpenChannel); * main.Show(); * main.Hide(); * string servername = System.Text.Encoding.Unicode.GetString(data); * servername = servername.Substring(0, servername.IndexOf('\0')); * main.Text = "TS addin in C#: " + servername;*/ } break; case ChannelEvents.V1Connected: MessageBox.Show("TSTunnels: Connecting to a non Windows 2000 Terminal Server.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); break; case ChannelEvents.Disconnected: //main.RealClosing = true; //main.Close(); break; case ChannelEvents.Terminated: break; } }
public void VirtualChannelInitEventProc(IntPtr initHandle, ChannelEvents Event, byte[] data, int dataLength) { switch (Event) { case ChannelEvents.Initialized: break; case ChannelEvents.Connected: ChannelReturnCodes ret = _entryPoints.VirtualChannelOpen( initHandle, ref _openChannel, _channelName, _channelOpenEventDelegate); if (ret != ChannelReturnCodes.Ok) { throw new VirtualChannelException(String.Format("TsClientAddIn ({0}): Couldn't open communcation channel for battery monitor.", _channelName)); } else { string servername = System.Text.Encoding.Unicode.GetString(data); _serverName = servername.Substring(0, servername.IndexOf('\0')); } break; case ChannelEvents.V1Connected: throw new VirtualChannelException(String.Format("TsClientAddIn ({0}): Connecting to a Terminal Server that doesn't support data communication.", _channelName)); case ChannelEvents.Disconnected: break; case ChannelEvents.Terminated: GC.KeepAlive(_channelInitEventDelegate); GC.KeepAlive(_channelOpenEventDelegate); GC.KeepAlive(_entryPoints); GC.Collect(); GC.WaitForPendingFinalizers(); break; } }
public PushService() { this.Events = new ChannelEvents(); }
/// <summary> /// Register a callback to be invoked when the given Channel UUID hangs up. /// </summary> /// <param name="uuid">The Channel UUID.</param> /// <param name="action">A Callback to be invoked on hangup.</param> public void OnHangup(string uuid, Action <EventMessage> action) { ChannelEvents.Where(x => x.UUID == uuid && x.EventName == EventName.ChannelHangup).Take(1).Subscribe(action); }
/// <summary> /// Asynchronously executes a dialplan application on the given channel. /// </summary> /// <remarks> /// See https://freeswitch.org/confluence/display/FREESWITCH/mod_dptools /// </remarks> /// <param name="uuid">The channel UUID.</param> /// <param name="application">The dialplan application to execute.</param> /// <param name="applicationArguments">(Optional) arguments to pass to the application.</param> /// <param name="eventLock">(Default: false) Whether to block the socket until the application completes before processing further. /// (see https://wiki.freeswitch.org/wiki/Event_Socket_Outbound#Q:_Ordering_and_async_keyword )</param> /// <param name="async">(Default: false) Whether to return control from the application immediately. /// (see https://wiki.freeswitch.org/wiki/Event_Socket_Outbound#Q:_Should_I_use_sync_mode_or_async_mode.3F) /// </param> /// <param name="loops">(Optional) How many times to repeat the application.</param> /// <returns> /// A Task of <seealso cref="EventMessage"/> that wraps the ChannelExecuteComplete event if the application completes successfully. /// The Task result will be null if the application did not execute, for example, the socket disconnected or the channel was hung up. /// </returns> public Task <ChannelEvent> ExecuteApplication( string uuid, string application, string applicationArguments = null, bool eventLock = false, bool async = false, int loops = 1) { if (uuid == null) { throw new ArgumentNullException("uuid"); } if (application == null) { throw new ArgumentNullException("application"); } //lists.freeswitch.org/pipermail/freeswitch-users/2013-May/095329.html var applicationUUID = Guid.NewGuid().ToString(); var sb = StringBuilderPool.Allocate(); sb.AppendFormat("sendmsg {0}\nEvent-UUID: {1}\ncall-command: execute\nexecute-app-name: {2}\n", uuid, applicationUUID, application); if (eventLock) { sb.Append("event-lock: true\n"); } if (loops > 1) { sb.Append("loops: " + loops + "\n"); } if (async) { sb.Append("async: true\n"); } if (applicationArguments != null) { sb.AppendFormat("content-type: text/plain\ncontent-length: {0}\n\n{1}\n", applicationArguments.Length, applicationArguments); } var tcs = new TaskCompletionSource <ChannelEvent>(); var subscriptions = new CompositeDisposable(); if (cts.Token.CanBeCanceled) { subscriptions.Add(cts.Token.Register(() => tcs.TrySetCanceled())); } subscriptions.Add( ChannelEvents.Where( x => x.EventName == EventName.ChannelExecuteComplete && x.Headers["Application-UUID"] == applicationUUID) .Take(1) .Subscribe( executeCompleteEvent => { if (executeCompleteEvent != null) { Console.WriteLine("{0} ChannelExecuteComplete [{1} {2} {3}]".Fmt( executeCompleteEvent.UUID, executeCompleteEvent.AnswerState, executeCompleteEvent.Headers[HeaderNames.Application], executeCompleteEvent.Headers[HeaderNames.ApplicationResponse])); } else { Console.WriteLine("No ChannelExecuteComplete event received for {0}".Fmt(application)); } tcs.TrySetResult(executeCompleteEvent); }, ex => tcs.TrySetException(ex), subscriptions.Dispose)); SubscribeEvents(EventName.ChannelExecuteComplete).ContinueWith(t => { if (t.IsCompleted) { SendCommand(StringBuilderPool.ReturnAndFree(sb)) .Then(reply => { if (!reply.Success) { tcs.TrySetResult(null); } }) .ContinueOnFaultedOrCancelled(tcs, subscriptions.Dispose); } else { tcs.TrySetException(t.Exception); } }); return(tcs.Task); }