Пример #1
0
        private void Pbx_OnChannelDestroyedEvent(IAriClient sender, ChannelDestroyedEvent e)
        {
            ProtocolMessages.Message msg = null;
            try
            {
                lock (_locker)
                {
                    //si aun existe el callhandler manejo el evento
                    if (callHandlerCache.GetByChannelId(e.Channel.Id) != null)
                    {
                        msg = callHandlerCache.GetByChannelId(e.Channel.Id).ChannelDestroyEvent(e.Channel.Id, e.Cause, e.Cause_txt);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Debug("Error en Pbx_OnChannelDestroyedEvent - " + ex.Message);
            }

            if (msg != null)
            {
                actorPbxProxy.Send(msg);
            }
            else
            {
                Log.Logger.Debug("Channel Destroy: " + e.Channel.Id + " el callhandler devolvió msg = null");
            }
            lock (_locker)
            {
                callHandlerCache.RemoveChannel(e.Channel.Id);
            }
            Log.Logger.Debug("Channel Destroy: " + e.Channel.Id + " remuevo channel del callhandler");
        }
Пример #2
0
        /// <summary>
        /// This event fires every time that a call has timeout waiting on the queue
        /// </summary>
        /// <param name="callTimeOut">Holds the call id and the timeout</param>
        private void CallTimeOutHandler_CallTimeOutEvent(CallTimeOut callTimeOut)
        {
            ProtocolMessages.Message msg = null;
            try
            {
                //TODO: no olvidar manerjar la concurrencia sobre el callHandlerCache !!! sobre ese objeto trabajan el thread del timeouthandler, el de los evenntos del ari, y uno mas de los eventos del pbxproxy!
                //TODO: ver como hago que la llamada continue y enviar el msg adecuado al callditributor
                //Esto deberia generar un mensaje EXIT WITH TIMEOUT
                lock (_locker)
                {
                    CallHandler callHandler = callHandler = callHandlerCache.GetByCallHandlerlId(callTimeOut.CallHandlerId);
                    if (callHandler != null)
                    {
                        msg = callHandler.CancelCall();
                        callHandlerCache.RemoveCallHandler(callHandler.Id); //lo hago aca, o dejo que lo haga el stasisend?
                        pbx.Channels.ContinueInDialplan(callHandler.Caller.Id);
                    }
                }
                Log.Logger.Debug("La LLamada: " + callTimeOut.CallHandlerId + " Expiro!, remuevo el callhandler");
            }
            catch (Exception ex)
            {
                Log.Logger.Debug("CallTimeOut: ERROR! " + callTimeOut.CallHandlerId + ", Mensaje: " + ex.Message);
            }

            if (msg != null)
            {
                actorPbxProxy.Send(msg);
            }
            else
            {
                Log.Logger.Debug("CallTimeOut: " + callTimeOut.CallHandlerId + " el callhandler devolvió msg = null");
            }
        }
Пример #3
0
        private void Pbx_OnChannelStateChangeEvent(IAriClient sender, ChannelStateChangeEvent e)
        {
            ProtocolMessages.Message msg = null;
            //track channel state changes
            try
            {
                lock (_locker)
                {
                    msg = callHandlerCache.GetByChannelId(e.Channel.Id).ChannelStateChangedEvent(e.Channel.Id, e.Channel.State);
                }
                if (msg != null)
                {
                    actorPbxProxy.Send(msg);
                }
                else
                {
                    Log.Logger.Debug("Channel State Change: " + e.Channel.Id + " el callhandler devolvió msg = null");
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Debug("ERROR!!: Pbx_OnChannelStateChangeEvent chan:" + e.Channel.Id + ", error: " + ex.Message);
            }

            //log to console
            Log.Logger.Debug("El canal: " + e.Channel.Id + " cambio su estado a: " + e.Channel.State.ToString());
        }
Пример #4
0
        private void Pbx_OnChannelUnholdEvent(IAriClient sender, ChannelUnholdEvent e)
        {
            ProtocolMessages.Message msg = null;
            try
            {
                lock (_locker)
                {
                    msg = callHandlerCache.GetByChannelId(e.Channel.Id).ChannelUnHoldEvent(e.Channel.Id);
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Debug("Channel UnHold: ERROR " + ex.Message + "\n" + ex.StackTrace);
            }

            if (msg != null)
            {
                actorPbxProxy.Send(msg);
            }
            else
            {
                Log.Logger.Debug("Channel UnHold: " + e.Channel.Id + " el callhandler devolvió msg = null");
            }
            Log.Logger.Debug("Channel UnHold: " + e.Channel.Id);
        }
Пример #5
0
 private void Pbx_OnBridgeBlindTransferEvent(IAriClient sender, BridgeBlindTransferEvent e)
 {
     ProtocolMessages.Message msg = null;
     lock (_locker)
     {
         CallHandler callHandler = callHandlerCache.GetByChannelId(e.Transferee.Id);
         if (callHandler == null)
         {
             callHandler = callHandlerCache.GetByChannelId(e.Replace_channel.Id);
         }
         if (callHandler != null)
         {
             msg = callHandler.AttendedTransferEvent(e.Transferee, e.Replace_channel);
         }
     }
     //Mando el mensaje
     if (msg != null)
     {
         actorPbxProxy.Send(msg);
     }
     else
     {
         Log.Logger.Debug("UnAttTransfer devolvió msg = null");
     }
 }
Пример #6
0
 private void Pbx_OnBridgeAttendedTransferEvent(IAriClient sender, BridgeAttendedTransferEvent e)
 {
     ProtocolMessages.Message msg = null;
     lock (_locker)
     {
         //Este evento trae muchisima info, requiere de mayor estudio/prueba
         //ver como queda el canal del caller, seguro hay un rename por ahi
         CallHandler callHandler = callHandlerCache.GetByChannelId(e.Transferee.Id);
         if (callHandler == null)
         {
             callHandler = callHandlerCache.GetByChannelId(e.Transfer_target.Id);
         }
         if (callHandler != null)
         {
             msg = callHandler.AttendedTransferEvent(e.Transferee, e.Transfer_target);
         }
     }
     //Mando el mensaje
     if (msg != null)
     {
         actorPbxProxy.Send(msg);
     }
     else
     {
         Log.Logger.Debug("AttTransfer devolvió msg = null");
     }
 }
Пример #7
0
        public ProtocolMessages.Message ChannelStateChangedEvent(string channelId, string newState)
        {
            ProtocolMessages.Message msg = null;

            if (channelId == caller.Id)
            {
                caller.State = newState;
            }
            else if (channelId == agent.Id)
            {
                agent.State = newState;
                if (newState == "Up") //Esto indica que el canal es de un agente y atendió la llamada
                {
                    int holdTime = chronometer.CallToSuccess();
                    msg = new MessageCallToSuccess()
                    {
                        From = source, CallHandlerId = this.id, QueueId = currentQueue, HoldTime = holdTime
                    };
                    callState = CallState.AGENT_ANSWERED;
                }
            }
            else
            {
                Log.Logger.Debug("Callhandler: El canal " + caller.Id + " no está en la llamada: " + this.id);
            }

            return(msg);
        }
Пример #8
0
        //Este método lo llamo para cancelar la llamada, no hace hangup del canal del caller porque lo dejo continuar
        //en el dialplan, lo que hace es terminar el callto si se originó, y genera el mensaje para el callditributor
        public ProtocolMessages.Message CancelCall()
        {
            ProtocolMessages.Message msg = null;

            if (agent != null)
            {
                pbx.Channels.Hangup(agent.Id);
            }

            callState = CallState.TERMINATED;

            msg = new MessageCallerExitWithTimeOut {
                From          = source,
                CallHandlerId = this.id,
                QueueId       = currentQueue,
                TimeOut       = timeOut
            };
            try
            {
                pbx.Channels.ContinueInDialplan(Id);
            }
            catch (Exception ex)
            {
                Log.Logger.Debug("CallHandler: Error continue dialplan action. " + ex.Message);
            }

            return(msg);
        }
Пример #9
0
        //por lo que pude relevar el evento channelHangup solo llega si el canal no atendido
        //hay que ver bien cause que valores toma en los casos de una llamada terminada por falla
        //basado en lo que dije en las lineas anteriores, aca debería llegar por un canal de caller que corta, ya que al entrar en stasis
        //debería haber sido atendido. o bien por un agente que corta
        public ProtocolMessages.Message ChannelHangupEvent(string channelId, int cause, string causeText)
        {
            ProtocolMessages.Message msg = null;
            //Hay que pulir la lógica del hangup, también hay que tener en cuenta los transfer
            if (channelId == caller.Id && callState != CallState.TERMINATED && callState != CallState.TRANSFERRED)
            {
                int x = chronometer.CallEnd();
                msg = new MessageCallerHangup()
                {
                    From          = source,
                    CallHandlerId = this.id,
                    QueueId       = currentQueue,
                    HangUpCode    = cause.ToString(),
                    HangUpReason  = causeText,
                    WatingTime    = chronometer.WaitingTime,
                    HoldingTime   = chronometer.HoldingTime,
                    //ConnectedTime = chronometer.ConnectedTime,
                    TalkingTime = chronometer.TalkingTime
                };
                TerminateAgent();
                callState = CallState.TERMINATED;
            }
            else if (channelId == agent.Id)
            {
                //prevengo que si la llamada fue transferida le corte al que llamó
                if (callState != CallState.TRANSFERRED && callState != CallState.TERMINATED)
                {
                    int x = chronometer.CallEnd();
                    msg = new MessageAgentHangup()
                    {
                        From          = source,
                        CallHandlerId = this.id,
                        QueueId       = currentQueue,
                        HangUpCode    = cause.ToString(),
                        HangUpReason  = causeText,
                        WatingTime    = chronometer.WaitingTime,
                        HoldingTime   = chronometer.HoldingTime,
                        //ConnectedTime = chronometer.ConnectedTime,
                        TalkingTime = chronometer.TalkingTime
                    };
                    TerminateCaller();
                    callState = CallState.TERMINATED;
                }
                //else
                //{
                //    msg = new MessageCallTransfer() { CallHandlerId = this.id, TargetId = transferTarget.Id, TargetName = transferTarget.Name };
                //}
            }
            else
            {
                Log.Logger.Debug("Callhandler: El canal " + caller.Id + " no está en la llamada: " + this.id);
            }

            return(msg);
        }
Пример #10
0
        //TODO: esto es una versión muy simplificada, el evento de transferencia atendida requiere mayor estudio
        public ProtocolMessages.Message AttendedTransferEvent(Channel ch1, Channel ch2)
        {
            ProtocolMessages.Message msg = null;
            if (ch1.Id == caller.Id)
            {
                msg = TransferTo(ch2);
            }

            if (ch2.Id == caller.Id)
            {
                msg = TransferTo(ch1);
            }

            return(msg);
        }
Пример #11
0
        public ProtocolMessages.Message ChannelHoldEvent(string channelId)
        {
            ProtocolMessages.Message msg = null;

            chronometer.CallHoldStart();

            msg = new MessageCallHold()
            {
                From          = source,
                CallHandlerId = this.id,
                QueueId       = currentQueue
            };

            return(msg);
        }
Пример #12
0
        private void Pbx_OnChannelHangupRequestEvent(IAriClient sender, ChannelHangupRequestEvent e)
        {
            ProtocolMessages.Message msg = null;
            try
            {
                lock (_locker)
                {
                    msg = callHandlerCache.GetByChannelId(e.Channel.Id).ChannelHangupEvent(e.Channel.Id, e.Cause, "");
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Debug("Channel HangUpReques: ERROR " + ex.Message + "\n" + ex.StackTrace);
            }

            if (msg != null)
            {
                actorPbxProxy.Send(msg);
            }
            else
            {
                Log.Logger.Debug("Channel HangUpReques: " + e.Channel.Id + " el callhandler devolvió msg = null");
            }
            //TODO:Revisar este lock, verificar si lo que está adentro lo estoy ejecutando
            lock (_locker)
            {
                //si la llamada finalizó remuevo todo
                CallHandler callHandler = callHandlerCache.GetByChannelId(e.Channel.Id);
                if (callHandler != null && callHandler.IsCallTerminated())
                {
                    Log.Logger.Debug("Channel HangUpRequest: " + e.Channel.Id + ", call TERMINATED remuevo todo el callhandler: " + callHandler);
                    callHandlerCache.RemoveCallHandler(callHandler.Id);

                    Log.Logger.Debug("Channel HangUpRequest: el bridge: " + callHandler.Bridge.Id + " lo marco como free");
                    bridgesList.SetFreeBridge(callHandler.Bridge.Id);
                }
                else // hago lo mismo que el channel destroy
                {
                    callHandlerCache.RemoveChannel(e.Channel.Id);
                    Log.Logger.Debug("Channel HangUpRequest: " + e.Channel.Id + " remuevo channel del callhandler");
                }
            }
        }
Пример #13
0
        //por lo que pude relevar el evento channelDestry solo llega si el canal no fué atendido
        //hay que ver bien cause que valores toma en los casos de una llamada terminada por timeout, o por falla
        //basado en lo que dije en las lineas anteriores, no debería llegar aca por un canal de caller, ya que al entrar en stasis
        //debería haber sido atendido. Si pasa con las llamadas que inicio hacia los agentes
        public ProtocolMessages.Message ChannelDestroyEvent(string channelId, int cause, string causeText)
        {
            ProtocolMessages.Message msg = null;
            //Hay que pulir la lógica del hangup, también hay que tener en cuenta los transfer
            if (channelId == caller.Id && callState != CallState.TERMINATED)
            {
                int x = chronometer.CallEnd();
                msg = new MessageCallerHangup()
                {
                    From          = source,
                    CallHandlerId = this.id,
                    QueueId       = currentQueue,
                    HangUpCode    = cause.ToString(),
                    HangUpReason  = causeText,
                    WatingTime    = chronometer.WaitingTime,
                    HoldingTime   = chronometer.HoldingTime,
                    //ConnectedTime = chronometer.ConnectedTime,
                    TalkingTime = chronometer.TalkingTime
                };
                callState = CallState.TERMINATED;
            }
            else if (channelId == agent.Id)
            {
                int ringingTime = chronometer.CallToEndFailed();
                msg = new MessageCallToFailed()
                {
                    From = source, CallHandlerId = this.id, QueueId = currentQueue, Code = cause, Reason = causeText, RingingTime = ringingTime
                };
                callState = CallState.CONNECT_FAILDED;
            }
            else
            {
                Log.Logger.Debug("Callhandler: El canal " + caller.Id + " no está en la llamada: " + this.id);
            }

            return(msg);
        }
Пример #14
0
        private void Pbx_OnStasisStartEvent(IAriClient sender, StasisStartEvent e)
        {
            lock (_locker)                     //Refinar esto, estoy bloqueando durante todo el evento
            {
                if (e.Replace_channel != null) //esto me indica si no es null que hubo un rename, por ejemplo por un transfer
                {
                    CallHandler callHandler = callHandlerCache.GetByChannelId(e.Replace_channel.Id);
                    if (callHandler != null)
                    {
                        //Lo comento porque si remplazo el canal, el nuevo canal no esta en stasis y nunca detecto el hangup
                        //para poder hacer esto debería recibir los eventos de todos los canales osea pbx.Applications.Subscribe(appName, "channel:");
                        callHandler.ChannelReplace(e.Replace_channel, e.Channel);
                    }
                }
                else
                {
                    //TODO: si e.Replace_channel != null (rename) es un nuevo canal que reemplaza a otro, hasta ahora solo me pasa con las transferencias atendidas, debo buscar el callhandler que tiene el e.Replace_channel y reemplazarlo por el nuevo channel
                    //Verifico: si el canal es de una llamada que ya existe no creo nada. Esto es para el caso en que hago un originate al agente, ya tengo un callhandler creado por el caller que llamó inicialmente
                    if (callHandlerCache.GetByChannelId(e.Channel.Id) == null)
                    {
                        Log.Logger.Debug("El canal: " + e.Channel.Id + " entró a la app: " + e.Application);
                        Bridge bridge = bridgesList.GetFreeBridge();
                        if (bridge == null) //si no hay un bridge libre creo uno y lo agrego a la lista
                        {
                            bridge = pbx.Bridges.Create("mixing", Guid.NewGuid().ToString());
                            bridgesList.AddNewBridge(bridge);
                            Log.Logger.Debug("Se crea un Bridge: " + bridge.Id);
                        }
                        else
                        {
                            Log.Logger.Debug("Se usa un Bridge existente: " + bridge.Id);
                        }

                        CallHandler callHandler = new CallHandler(source, appName, pbx, bridge, e.Channel);
                        callHandlerCache.AddCallHandler(callHandler);
                        Log.Logger.Debug("Se crea un callhandler: " + callHandler.Id + " para el canal: " + e.Channel.Id);

                        //Agrego el canal al bridge
                        try
                        {
                            //Seteo la variabl callhandlerid del canal para identificarlo, esto solo para el caller
                            //ver que pasa cuando se hace un transfer a una cola, deberia cambiar el callhandlerid?
                            //En el hangup pregunto por esta variable y si la encuentro, libero la llamada y marco el bridge como libre
                            pbx.Channels.SetChannelVar(e.Channel.Id, "cq_callhandlerid", callHandler.Id);
                            //agrego el canal al bridge, controlar que pasa si falla el originate
                            pbx.Bridges.AddChannel(callHandler.Bridge.Id, e.Channel.Id, null);
                        }
                        catch (Exception ex)
                        {
                            Log.Logger.Debug("No se pudo agregar el canal: " + e.Channel.Id + " al bridge: " + callHandler.Bridge.Id + " Error: " + ex.Message);
                        }

                        //supongo que aca debo avisar a akka que cree el manejador para esta llamada y me mande el mesajito para que atienda
                        //TODO: si este parametro no existe no entrar al evento stasisstart
                        var queueId = e.Args[0];
                        if (e.Args.Count >= 1)
                        {
                            callHandler.SetTimeOut(e.Args[1]);
                        }
                        ProtocolMessages.Message msg = null;
                        msg = callHandler.SetCurrentQueue(queueId);
                        if (msg != null)
                        {
                            actorPbxProxy.Send(msg);
                        }
                    }
                    else //si no es null entonces el canal lo agregé yo cuando hice el CallTo
                    {
                        CallHandler callHandler = callHandlerCache.GetByChannelId(e.Channel.Id);
                        try
                        {
                            //lo conecte a un member, asi que temuevo el timeout
                            callTimeOutHandler.CancelCallTimOut(callHandler.Id);
                            //Le digo al callhandler que el canal generado en el callto ya está en el dial plan, cuando el estado pasa a Up es que contestó el agente
                            callHandler.CallToSuccess(e.Channel.Id);
                        }
                        catch (Exception ex)
                        {
                            Log.Logger.Debug("No se pudo agregar el canal: " + e.Channel.Id + " al bridge: " + callHandler.Bridge.Id + " Error: " + ex.Message);
                        }
                    }
                }
            }
        }
Пример #15
0
 private void ActorPbxProxy_Receive(object sender, ProtocolMessages.Message message)
 {
     //Aca entran todos los eventos del sistema de actores
 }