private static async Task <OriginateResult> InternalOriginate(EventSocket socket, string endpoint, string destination, OriginateOptions options = null) { if (options == null) { options = new OriginateOptions(); } // if no UUID provided, we'll set one now and use that to filter for the correct channel events // this way, one inbound socket can originate many calls and we can complete the correct // TaskCompletionSource for each originated call. if (string.IsNullOrEmpty(options.UUID)) { options.UUID = Guid.NewGuid().ToString(); } await socket.SubscribeEvents(EventName.ChannelAnswer, EventName.ChannelHangup, EventName.ChannelProgress).ConfigureAwait(false); var originateString = string.Format("{0}{1} {2}", options, endpoint, destination); return (await socket.BackgroundJob("originate", originateString) .ToObservable() .Merge( socket.ChannelEvents.FirstAsync( x => x.UUID == options.UUID && (x.EventName == EventName.ChannelAnswer || x.EventName == EventName.ChannelHangup || (options.ReturnRingReady && x.EventName == EventName.ChannelProgress))).Cast <BasicMessage>()) .FirstAsync(x => (x is BackgroundJobResult && !((BackgroundJobResult)x).Success) || x is ChannelEvent) .Select(OriginateResult.FromBackgroundJobResultOrChannelEvent) // pattern matching, my kingdom for pattern matching .ToTask() .ConfigureAwait(false)); }
protected Channel(EventMessage eventMessage, EventSocket eventSocket) : base(eventMessage, eventSocket) { eventSocket.SubscribeEvents(EventName.ChannelCreate).Wait(); Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelBridge).Subscribe( x => { Log.Trace(() => "Channel [{0}] Bridged to [{1}]".Fmt(UUID, x.GetHeader(HeaderNames.OtherLegUniqueId))); if (Bridge.Channel != null && x.GetHeader(HeaderNames.OtherLegUniqueId) != Bridge.Channel.UUID) { //possibly changed bridge partner as part of att_xfer Log.Warn(() => "Channel [{0}] was Bridged to [{1}] but now changed to [{2}]".Fmt(UUID, Bridge.Channel.UUID, x.UUID)); Bridge.Channel.Dispose(); Bridge = new BridgeStatus(true, "TRANSFERRED", new BridgedChannel(x, eventSocket)); } })); Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelUnbridge).Subscribe( x => Log.Trace(() => "Channel [{0}] Unbridged from [{1}] {2}".Fmt(UUID, Bridge.Channel.UUID, x.GetVariable("bridge_hangup_cause"))))); Disposables.Add( eventSocket.Events.Where(x => x.EventName == EventName.ChannelBridge && x.UUID != UUID && x.GetHeader(HeaderNames.OtherLegUniqueId) == UUID && (Bridge.Channel != null && x.UUID != Bridge.Channel.UUID)) .Subscribe(x => { //there is another channel out there that has bridged to us but we didn't get the CHANNEL_BRIDGE event on this channel //possibly an attended transfer. We'll swap our bridge partner so we can get its events Log.Warn(() => "Channel [{0}] was Bridged to [{1}] but now changed to [{2}]".Fmt(UUID, Bridge.Channel.UUID, x.UUID)); Bridge.Channel.Dispose(); Bridge = new BridgeStatus(true, "TRANSFERRED", new BridgedChannel(x, eventSocket)); })); if (this.eventSocket is OutboundSocket) { Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelHangup) .Subscribe(async e => { if (ExitOnHangup) { await eventSocket.Exit(); Log.Info(() => "Channel [{0}] exited".Fmt(UUID)); } })); } //populate empty bridge status Bridge = new BridgeStatus(false, null); ExitOnHangup = true; }
public Task StartDetectingInbandDtmf() { return(RunIfAnswered( async() => { await eventSocket.SubscribeEvents(EventName.Dtmf).ConfigureAwait(false); await eventSocket.StartDtmf(UUID).ConfigureAwait(false); })); }
public async Task StartDetectingInbandDtmf() { if (!IsAnswered) { return; } await eventSocket.SubscribeEvents(EventName.Dtmf); await eventSocket.StartDtmf(UUID); }
private static async Task <OriginateResult> InternalOriginate(EventSocket socket, string endpoint, string destination, OriginateOptions options = null) { if (options == null) { options = new OriginateOptions(); } var originateString = $"{options}{endpoint} {destination}"; await socket.SubscribeEvents(EventName.BackgroundJob).ConfigureAwait(false); return (await socket.BackgroundJob("originate", originateString) .ToObservable() .Select(OriginateResult.FromBackgroundJobResultOrChannelEvent) .ToTask() .ConfigureAwait(false)); }
protected Channel(EventMessage eventMessage, EventSocket eventSocket) : base(eventMessage, eventSocket) { //populate empty bridge status Bridge = new BridgeStatus(false, null); ExitOnHangup = true; Task.WhenAll( new[] { eventSocket.SubscribeEvents(), //subscribe to minimum events eventSocket.Filter(HeaderNames.UniqueId, UUID), //filter for our unique id (in case using full socket mode) eventSocket.Filter(HeaderNames.OtherLegUniqueId, UUID) //filter for channels bridging to our unique id }).ContinueWith( t => { if (t.IsFaulted && t.Exception != null) { Log.ErrorException("Channel [{0}] - failed to configure outbound socket for Channel usage".Fmt(UUID), t.Exception.InnerException); return; } this.InitializeSubscriptions(); }); }