From 5e738cdd3cf5f95e00b2dae1c729d6cedb90d9d4 Mon Sep 17 00:00:00 2001 From: zsender Date: Wed, 5 Apr 2017 08:32:55 +0300 Subject: [PATCH 1/8] Used EventHandler delegate because the event signature is the same for all. Changed the call of the event so that the indexes are not used. Action allows you to use the delegate value at the current real time --- .../Asterisk.NET.Test/Program.cs | 10 +- .../Asterisk.NET.WinForm/FormMain.cs | 2 +- Asterisk.2013/Asterisk.NET/Helper.cs | 11 +- .../Asterisk.NET/Manager/ManagerConnection.cs | 3709 +++++++---------- 4 files changed, 1545 insertions(+), 2187 deletions(-) diff --git a/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs b/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs index e47cda1..d39c86e 100644 --- a/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs +++ b/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs @@ -138,13 +138,13 @@ Ctrl-C to exit"); manager.RegisterUserEventClass(typeof(UserAgentLoginEvent)); // Add or Remove events - manager.UserEvents += new UserEventHandler(dam_UserEvents); + manager.UserEvents += dam_UserEvents; // Dont't display this event - manager.NewExten += new NewExtenEventHandler(manager_IgnoreEvent); + manager.NewExten += manager_IgnoreEvent; // Display all other - manager.UnhandledEvent += new ManagerEventHandler(dam_Events); + manager.UnhandledEvent += dam_Events; // +++ Only to debug purpose manager.FireAllEvents = true; @@ -288,7 +288,7 @@ Ctrl-C to exit"); Console.WriteLine("Redirect Call from " + ORIGINATE_CHANNEL + " to " + ORIGINATE_EXTRA_CHANNEL + " or press ESC."); // Wait for Dial Event from ORIGINATE_CHANNEL - DialEventHandler de = new DialEventHandler(dam_Dial); + EventHandler de = dam_Dial; manager.Dial += de; while (transferChannel == null) { @@ -323,7 +323,7 @@ Ctrl-C to exit"); // Link event used to define monitor channel Console.WriteLine("Monitor call. Please call " + ORIGINATE_CHANNEL + " and answer or press ESC."); // Wait for Link event - LinkEventHandler le = new LinkEventHandler(dam_Link); + EventHandler le = dam_Link; manager.Link += le; while (monitorChannel == null) { diff --git a/Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs b/Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs index 0ebcbb5..89dcec4 100644 --- a/Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs +++ b/Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs @@ -28,7 +28,7 @@ namespace AsterNET.WinForm btnConnect.Enabled = false; manager = new ManagerConnection(address, port, user, password); - manager.UnhandledEvent += new ManagerEventHandler(manager_Events); + manager.UnhandledEvent += manager_Events; try { // Uncomment next 2 line comments to Disable timeout (debug mode) diff --git a/Asterisk.2013/Asterisk.NET/Helper.cs b/Asterisk.2013/Asterisk.NET/Helper.cs index 80c9830..8d2ff60 100644 --- a/Asterisk.2013/Asterisk.NET/Helper.cs +++ b/Asterisk.2013/Asterisk.NET/Helper.cs @@ -872,14 +872,15 @@ namespace AsterNET #endregion - #region RegisterEventHandler(Dictionary list, int index, Type eventType) + #region RegisterEventHandler(Dictionary> list, Type eventType, Action action) - internal static void RegisterEventHandler(Dictionary list, int index, Type eventType) + internal static void RegisterEventHandler(Dictionary> list, Type eventType, Action action) { - int eventHash = eventType.Name.GetHashCode(); + var eventTypeName = eventType.Name; + int eventHash = eventTypeName.GetHashCode(); if (list.ContainsKey(eventHash)) - throw new ArgumentException("Event class already registered : " + eventType.Name); - list.Add(eventHash, index); + throw new ArgumentException("Event class already registered : " + eventTypeName); + list.Add(eventHash, action); } #endregion diff --git a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs index cd594b1..d3dd4be 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs @@ -15,1566 +15,917 @@ using AsterNET.Util; namespace AsterNET.Manager { - #region Event delegate - - public delegate void ManagerEventHandler(object sender, ManagerEvent e); - public delegate void AgentCallbackLoginEventHandler(object sender, Event.AgentCallbackLoginEvent e); - public delegate void AgentCallbackLogoffEventHandler(object sender, Event.AgentCallbackLogoffEvent e); - public delegate void AgentCalledEventHandler(object sender, Event.AgentCalledEvent e); - public delegate void AgentCompleteEventHandler(object sender, Event.AgentCompleteEvent e); - public delegate void AgentConnectEventHandler(object sender, Event.AgentConnectEvent e); - public delegate void AgentDumpEventHandler(object sender, Event.AgentDumpEvent e); - public delegate void AgentLoginEventHandler(object sender, Event.AgentLoginEvent e); - public delegate void AgentLogoffEventHandler(object sender, Event.AgentLogoffEvent e); - public delegate void AgentsCompleteEventHandler(object sender, Event.AgentsCompleteEvent e); - public delegate void AgentsEventHandler(object sender, Event.AgentsEvent e); - public delegate void AlarmClearEventHandler(object sender, Event.AlarmClearEvent e); - public delegate void AlarmEventHandler(object sender, Event.AlarmEvent e); - public delegate void BridgeEventHandler(object sender, Event.BridgeEvent e); - public delegate void CdrEventHandler(object sender, Event.CdrEvent e); - public delegate void DBGetResponseEventHandler(object sender, Event.DBGetResponseEvent e); - public delegate void DialEventHandler(object sender, Event.DialEvent e); - public delegate void DTMFEventHandler(object sender, Event.DTMFEvent e); - public delegate void DNDStateEventHandler(object sender, Event.DNDStateEvent e); - public delegate void ExtensionStatusEventHandler(object sender, Event.ExtensionStatusEvent e); - public delegate void HangupEventHandler(object sender, Event.HangupEvent e); - public delegate void HoldedCallEventHandler(object sender, Event.HoldedCallEvent e); - public delegate void HoldEventHandler(object sender, Event.HoldEvent e); - public delegate void JoinEventHandler(object sender, Event.JoinEvent e); - public delegate void LeaveEventHandler(object sender, Event.LeaveEvent e); - public delegate void LinkEventHandler(object sender, Event.LinkEvent e); - public delegate void LogChannelEventHandler(object sender, Event.LogChannelEvent e); - public delegate void MeetMeJoinEventHandler(object sender, Event.MeetmeJoinEvent e); - public delegate void MeetMeLeaveEventHandler(object sender, Event.MeetmeLeaveEvent e); - public delegate void MeetMeTalkingEventHandler(object sender, Event.MeetmeTalkingEvent e); - public delegate void MessageWaitingEventHandler(object sender, Event.MessageWaitingEvent e); - public delegate void NewCallerIdEventHandler(object sender, Event.NewCallerIdEvent e); - public delegate void NewChannelEventHandler(object sender, Event.NewChannelEvent e); - public delegate void NewExtenEventHandler(object sender, Event.NewExtenEvent e); - public delegate void NewStateEventHandler(object sender, Event.NewStateEvent e); - public delegate void OriginateResponseEventHandler(object sender, Event.OriginateResponseEvent e); - public delegate void ParkedCallEventHandler(object sender, Event.ParkedCallEvent e); - public delegate void ParkedCallGiveUpEventHandler(object sender, Event.ParkedCallGiveUpEvent e); - public delegate void ParkedCallsCompleteEventHandler(object sender, Event.ParkedCallsCompleteEvent e); - public delegate void ParkedCallTimeOutEventHandler(object sender, Event.ParkedCallTimeOutEvent e); - public delegate void PeerEntryEventHandler(object sender, Event.PeerEntryEvent e); - public delegate void PeerlistCompleteEventHandler(object sender, Event.PeerlistCompleteEvent e); - public delegate void PeerStatusEventHandler(object sender, Event.PeerStatusEvent e); - public delegate void QueueEntryEventHandler(object sender, Event.QueueEntryEvent e); - public delegate void QueueMemberAddedEventHandler(object sender, Event.QueueMemberAddedEvent e); - public delegate void QueueMemberEventHandler(object sender, Event.QueueMemberEvent e); - public delegate void QueueMemberPausedEventHandler(object sender, Event.QueueMemberPausedEvent e); - public delegate void QueueMemberRemovedEventHandler(object sender, Event.QueueMemberRemovedEvent e); - public delegate void QueueMemberStatusEventHandler(object sender, Event.QueueMemberStatusEvent e); - public delegate void QueueParamsEventHandler(object sender, Event.QueueParamsEvent e); - public delegate void QueueStatusCompleteEventHandler(object sender, Event.QueueStatusCompleteEvent e); - public delegate void RegistryEventHandler(object sender, Event.RegistryEvent e); - public delegate void RenameEventHandler(object sender, Event.RenameEvent e); - public delegate void TransferEventHandler(object sender, Event.TransferEvent e); - public delegate void StatusCompleteEventHandler(object sender, Event.StatusCompleteEvent e); - public delegate void StatusEventHandler(object sender, Event.StatusEvent e); - public delegate void UnholdEventHandler(object sender, Event.UnholdEvent e); - public delegate void UnlinkEventHandler(object sender, Event.UnlinkEvent e); - public delegate void UnparkedCallEventHandler(object sender, Event.UnparkedCallEvent e); - public delegate void UserEventHandler(object sender, Event.UserEvent e); - public delegate void QueueCallerAbandonEventHandler(object sender, Event.QueueCallerAbandonEvent e); - public delegate void ZapShowChannelsCompleteEventHandler(object sender, Event.ZapShowChannelsCompleteEvent e); - public delegate void ZapShowChannelsEventHandler(object sender, Event.ZapShowChannelsEvent e); - public delegate void ConnectionStateEventHandler(object sender, Event.ConnectionStateEvent e); - public delegate void VarSetEventHandler(object sender, Event.VarSetEvent e); - public delegate void AGIExecHandler(object sender, Event.AGIExecEvent e); - public delegate void ConfbridgeStartEventHandler(object sender, Event.ConfbridgeStartEvent e); - public delegate void ConfbridgeJoinEventHandler(object sender, Event.ConfbridgeJoinEvent e); - public delegate void ConfbridgeLeaveEventHandler(object sender, Event.ConfbridgeLeaveEvent e); - public delegate void ConfbridgeEndEventHandler(object sender, Event.ConfbridgeEndEvent e); - public delegate void ConfbridgeTalkingEventHandler(object sender, Event.ConfbridgeTalkingEvent e); - public delegate void FailedACLEventHandler(object sender, Event.FailedACLEvent e); - public delegate void AttendedTransferEventHandler(object sender, Event.AttendedTransferEvent e); - public delegate void BlindTransferEventHandler(object sender, Event.BlindTransferEvent e); - public delegate void BridgeCreateEventHandler(object sender, Event.BridgeCreateEvent e); - public delegate void BridgeDestroyEventHandler(object sender, Event.BridgeDestroyEvent e); - public delegate void BridgeEnterEventHandler(object sender, Event.BridgeEnterEvent e); - public delegate void BridgeLeaveEventHandler(object sender, Event.BridgeLeaveEvent e); - public delegate void DialBeginEventHandler(object sender, Event.DialBeginEvent e); - public delegate void DialEndEventHandler(object sender, Event.DialEndEvent e); - public delegate void QueueCallerJoinEventHandler(object sender, Event.QueueCallerJoinEvent e); - public delegate void QueueCallerLeaveEventHandler(object sender, Event.QueueCallerLeaveEvent e); - public delegate void QueueMemberPauseEventHandler(object sender, Event.QueueMemberPauseEvent e); - - - - #endregion - /// /// Default implemention of the ManagerConnection interface. /// public class ManagerConnection - { - #region Variables + { + #region Variables #if LOGGER - private Logger logger = Logger.Instance(); + private Logger logger = Logger.Instance(); #endif - private long actionIdCount = 0; - private string hostname; - private int port; - private string username; - private string password; + private long actionIdCount = 0; + private string hostname; + private int port; + private string username; + private string password; - private SocketConnection mrSocket; - private Thread mrReaderThread; - private ManagerReader mrReader; + private SocketConnection mrSocket; + private Thread mrReaderThread; + private ManagerReader mrReader; - private int defaultResponseTimeout = 2000; - private int defaultEventTimeout = 5000; - private int sleepTime = 50; - private bool keepAlive = true; - private bool keepAliveAfterAuthenticationFailure = false; - private string protocolIdentifier; - private AsteriskVersion asteriskVersion; - private Dictionary responseHandlers; - private Dictionary pingHandlers; - private Dictionary responseEventHandlers; - private int pingInterval = 10000; + private int defaultResponseTimeout = 2000; + private int defaultEventTimeout = 5000; + private int sleepTime = 50; + private bool keepAlive = true; + private bool keepAliveAfterAuthenticationFailure = false; + private string protocolIdentifier; + private AsteriskVersion asteriskVersion; + private Dictionary responseHandlers; + private Dictionary pingHandlers; + private Dictionary responseEventHandlers; + private int pingInterval = 10000; - private object lockSocket = new object(); - private object lockHandlers = new object(); + private object lockSocket = new object(); + private object lockHandlers = new object(); - private bool enableEvents = true; - private string version = string.Empty; - private Encoding socketEncoding = Encoding.ASCII; - private bool reconnected = false; - private bool reconnectEnable = false; - private int reconnectCount; + private bool enableEvents = true; + private string version = string.Empty; + private Encoding socketEncoding = Encoding.ASCII; + private bool reconnected = false; + private bool reconnectEnable = false; + private int reconnectCount; - private Dictionary registeredEventClasses; - private Dictionary registeredEventHandlers; - private event ManagerEventHandler internalEvent; - private bool fireAllEvents = false; - private Thread callerThread; + private Dictionary registeredEventClasses; + //private Dictionary registeredEventHandlers; + private Dictionary> registeredEventHandlers; + private event EventHandler internalEvent; + private bool fireAllEvents = false; + private Thread callerThread; - /// Default Fast Reconnect retry counter. - private int reconnectRetryFast = 5; - /// Default Maximum Reconnect retry counter. - private int reconnectRetryMax = 10; - /// Default Fast Reconnect interval in milliseconds. - private int reconnectIntervalFast = 5000; - /// Default Slow Reconnect interval in milliseconds. - private int reconnectIntervalMax = 10000; + /// Default Fast Reconnect retry counter. + private int reconnectRetryFast = 5; + /// Default Maximum Reconnect retry counter. + private int reconnectRetryMax = 10; + /// Default Fast Reconnect interval in milliseconds. + private int reconnectIntervalFast = 5000; + /// Default Slow Reconnect interval in milliseconds. + private int reconnectIntervalMax = 10000; public char[] VAR_DELIMITER = { '|' }; - #endregion + #endregion /// /// Allows you to specifiy how events are fired. If false (default) then /// events will be fired in order. Otherwise events will be fired as they arrive and /// control logic in your application will need to handle synchronization. /// - public bool UseASyncEvents = false; + public bool UseASyncEvents = false; - #region Events + #region Events - /// - /// An UnhandledEvent is triggered on unknown event. - /// - public event ManagerEventHandler UnhandledEvent; - /// - /// An AgentCallbackLogin is triggered when an agent is successfully logged in. - /// - public event AgentCallbackLoginEventHandler AgentCallbackLogin; - /// - /// An AgentCallbackLogoff is triggered when an agent that previously logged in is logged of.
- ///
- public event AgentCallbackLogoffEventHandler AgentCallbackLogoff; - /// - /// An AgentCalled is triggered when an agent is ring.
- /// To enable AgentCalled you have to set eventwhencalled = yes in queues.conf.
- ///
- public event AgentCalledEventHandler AgentCalled; - /// - /// An AgentCompleteEvent is triggered when at the end of a call if the caller was connected to an agent. - /// - public event AgentCompleteEventHandler AgentComplete; - /// - /// An AgentConnectEvent is triggered when a caller is connected to an agent. - /// - public event AgentConnectEventHandler AgentConnect; - /// - /// An AgentDumpEvent is triggered when an agent dumps the caller while listening to the queue announcement. - /// - public event AgentDumpEventHandler AgentDump; - /// - /// An AgentLoginEvent is triggered when an agent is successfully logged in using AgentLogin. - /// - public event AgentLoginEventHandler AgentLogin; - /// - /// An AgentCallbackLogoffEvent is triggered when an agent that previously logged in using AgentLogin is logged of. - /// - public event AgentLogoffEventHandler AgentLogoff; - /// - /// An AgentsCompleteEvent is triggered after the state of all agents has been reported in response to an AgentsAction. - /// - public event AgentsCompleteEventHandler AgentsComplete; - /// - /// An AgentsEvent is triggered for each agent in response to an AgentsAction. - /// - public event AgentsEventHandler Agents; - /// - /// An AlarmEvent is triggered when a Zap channel leaves alarm state. - /// - public event AlarmClearEventHandler AlarmClear; - /// - /// - /// - public event BridgeEventHandler Bridge; - /// - /// An AlarmEvent is triggered when a Zap channel enters or changes alarm state. - /// - public event AlarmEventHandler Alarm; - /// - /// A CdrEvent is triggered when a call detail record is generated, usually at the end of a call. - /// - public event CdrEventHandler Cdr; - public event DBGetResponseEventHandler DBGetResponse; - /// - /// A Dial is triggered whenever a phone attempts to dial someone.
- ///
- public event DialEventHandler Dial; - public event DTMFEventHandler DTMF; - /// - /// A DNDStateEvent is triggered by the Zap channel driver when a channel enters or leaves DND (do not disturb) state. - /// - public event DNDStateEventHandler DNDState; - /// - /// An ExtensionStatus is triggered when the state of an extension changes.
- ///
- public event ExtensionStatusEventHandler ExtensionStatus; - /// - /// A Hangup is triggered when a channel is hung up.
- ///
- public event HangupEventHandler Hangup; - /// - /// A HoldedCall is triggered when a channel is put on hold.
- ///
- public event HoldedCallEventHandler HoldedCall; - /// - /// A Hold is triggered by the SIP channel driver when a channel is put on hold.
- ///
- public event HoldEventHandler Hold; - /// - /// A Join is triggered when a channel joines a queue.
- ///
- public event JoinEventHandler Join; - /// - /// A Leave is triggered when a channel leaves a queue.
- ///
- public event LeaveEventHandler Leave; - /// - /// A Link is triggered when two voice channels are linked together and voice data exchange commences.
- /// Several Link events may be seen for a single call. This can occur when Asterisk fails to setup a - /// native bridge for the call.This is when Asterisk must sit between two telephones and perform - /// CODEC conversion on their behalf. - ///
- public event LinkEventHandler Link; - /// - /// A LogChannel is triggered when logging is turned on or off.
- ///
- public event LogChannelEventHandler LogChannel; - /// - /// A MeetMeJoin is triggered if a channel joins a meet me conference.
- ///
- public event MeetMeJoinEventHandler MeetMeJoin; - /// - /// A MeetMeLeave is triggered if a channel leaves a meet me conference.
- ///
- public event MeetMeLeaveEventHandler MeetMeLeave; - // public event MeetMeStopTalkingEventHandler MeetMeStopTalking; - /// - /// A MeetMeTalkingEvent is triggered when a user starts talking in a meet me conference.
- /// To enable talker detection you must pass the option 'T' to the MeetMe application. - ///
- public event MeetMeTalkingEventHandler MeetMeTalking; - /// - /// A MessageWaiting is triggered when someone leaves voicemail.
- ///
- public event MessageWaitingEventHandler MessageWaiting; - /// - /// A NewCallerId is triggered when the caller id of a channel changes.
- ///
- public event NewCallerIdEventHandler NewCallerId; - /// - /// A NewChannel is triggered when a new channel is created.
- ///
- public event NewChannelEventHandler NewChannel; - /// - /// A NewExten is triggered when a channel is connected to a new extension.
- ///
- public event NewExtenEventHandler NewExten; - /// - /// A NewState is triggered when the state of a channel has changed.
- ///
- public event NewStateEventHandler NewState; - // public event OriginateEventHandler Originate; - /// - /// An OriginateFailure is triggered when the execution of an OriginateAction failed. - /// - // public event OriginateFailureEventHandler OriginateFailure; - /// - /// An OriginateSuccess is triggered when the execution of an OriginateAction succeeded. - /// - // public event OriginateSuccessEventHandler OriginateSuccess; - /// - /// An OriginateResponse is triggered when the execution of an Originate. - /// - public event OriginateResponseEventHandler OriginateResponse; - /// - /// A ParkedCall is triggered when a channel is parked (in this case no - /// action id is set) and in response to a ParkedCallsAction.
- ///
- public event ParkedCallEventHandler ParkedCall; - /// - /// A ParkedCallGiveUp is triggered when a channel that has been parked is hung up.
- ///
- public event ParkedCallGiveUpEventHandler ParkedCallGiveUp; - /// - /// A ParkedCallsComplete is triggered after all parked calls have been reported in response to a ParkedCallsAction. - /// - public event ParkedCallsCompleteEventHandler ParkedCallsComplete; - /// - /// A ParkedCallTimeOut is triggered when call parking times out for a given channel.
- ///
- public event ParkedCallTimeOutEventHandler ParkedCallTimeOut; - /// - /// A PeerEntry is triggered in response to a SIPPeersAction or SIPShowPeerAction and contains information about a peer.
- ///
- public event PeerEntryEventHandler PeerEntry; - /// - /// A PeerlistComplete is triggered after the details of all peers has been reported in response to an SIPPeersAction or SIPShowPeerAction.
- ///
- public event PeerlistCompleteEventHandler PeerlistComplete; - /// - /// A PeerStatus is triggered when a SIP or IAX client attempts to registrer at this asterisk server.
- ///
- public event PeerStatusEventHandler PeerStatus; - /// - /// A QueueEntryEvent is triggered in response to a QueueStatusAction and contains information about an entry in a queue. - /// - public event QueueCallerAbandonEventHandler QueueCallerAbandon; - /// - /// A QueueEntryEvent is triggered in response to a QueueStatusAction and contains information about an entry in a queue. - /// - public event QueueEntryEventHandler QueueEntry; - /// - /// A QueueMemberAddedEvent is triggered when a queue member is added to a queue. - /// - public event QueueMemberAddedEventHandler QueueMemberAdded; - /// - /// A QueueMemberEvent is triggered in response to a QueueStatusAction and contains information about a member of a queue. - /// - public event QueueMemberEventHandler QueueMember; + /// + /// An UnhandledEvent is triggered on unknown event. + /// + public event EventHandler UnhandledEvent; + /// + /// An AgentCallbackLogin is triggered when an agent is successfully logged in. + /// + public event EventHandler AgentCallbackLogin; + /// + /// An AgentCallbackLogoff is triggered when an agent that previously logged in is logged of.
+ ///
+ public event EventHandler AgentCallbackLogoff; + /// + /// An AgentCalled is triggered when an agent is ring.
+ /// To enable AgentCalled you have to set eventwhencalled = yes in queues.conf.
+ ///
+ public event EventHandler AgentCalled; + /// + /// An AgentCompleteEvent is triggered when at the end of a call if the caller was connected to an agent. + /// + public event EventHandler AgentComplete; + /// + /// An AgentConnectEvent is triggered when a caller is connected to an agent. + /// + public event EventHandler AgentConnect; + /// + /// An AgentDumpEvent is triggered when an agent dumps the caller while listening to the queue announcement. + /// + public event EventHandler AgentDump; + /// + /// An AgentLoginEvent is triggered when an agent is successfully logged in using AgentLogin. + /// + public event EventHandler AgentLogin; + /// + /// An AgentCallbackLogoffEvent is triggered when an agent that previously logged in using AgentLogin is logged of. + /// + public event EventHandler AgentLogoff; + /// + /// An AgentsCompleteEvent is triggered after the state of all agents has been reported in response to an AgentsAction. + /// + public event EventHandler AgentsComplete; + /// + /// An AgentsEvent is triggered for each agent in response to an AgentsAction. + /// + public event EventHandler Agents; + /// + /// An AlarmEvent is triggered when a Zap channel leaves alarm state. + /// + public event EventHandler AlarmClear; + /// + /// + /// + public event EventHandler Bridge; + /// + /// An AlarmEvent is triggered when a Zap channel enters or changes alarm state. + /// + public event EventHandler Alarm; + /// + /// A CdrEvent is triggered when a call detail record is generated, usually at the end of a call. + /// + public event EventHandler Cdr; + public event EventHandler DBGetResponse; + /// + /// A Dial is triggered whenever a phone attempts to dial someone.
+ ///
+ public event EventHandler Dial; + public event EventHandler DTMF; + /// + /// A DNDStateEvent is triggered by the Zap channel driver when a channel enters or leaves DND (do not disturb) state. + /// + public event EventHandler DNDState; + /// + /// An ExtensionStatus is triggered when the state of an extension changes.
+ ///
+ public event EventHandler ExtensionStatus; + /// + /// A Hangup is triggered when a channel is hung up.
+ ///
+ public event EventHandler Hangup; + /// + /// A HoldedCall is triggered when a channel is put on hold.
+ ///
+ public event EventHandler HoldedCall; + /// + /// A Hold is triggered by the SIP channel driver when a channel is put on hold.
+ ///
+ public event EventHandler Hold; + /// + /// A Join is triggered when a channel joines a queue.
+ ///
+ public event EventHandler Join; + /// + /// A Leave is triggered when a channel leaves a queue.
+ ///
+ public event EventHandler Leave; + /// + /// A Link is triggered when two voice channels are linked together and voice data exchange commences.
+ /// Several Link events may be seen for a single call. This can occur when Asterisk fails to setup a + /// native bridge for the call.This is when Asterisk must sit between two telephones and perform + /// CODEC conversion on their behalf. + ///
+ public event EventHandler Link; + /// + /// A LogChannel is triggered when logging is turned on or off.
+ ///
+ public event EventHandler LogChannel; + /// + /// A MeetMeJoin is triggered if a channel joins a meet me conference.
+ ///
+ public event EventHandler MeetMeJoin; + /// + /// A MeetMeLeave is triggered if a channel leaves a meet me conference.
+ ///
+ public event EventHandler MeetMeLeave; + // public event MeetMeStopTalkingEventHandler MeetMeStopTalking; + /// + /// A MeetMeTalkingEvent is triggered when a user starts talking in a meet me conference.
+ /// To enable talker detection you must pass the option 'T' to the MeetMe application. + ///
+ public event EventHandler MeetMeTalking; + /// + /// A MessageWaiting is triggered when someone leaves voicemail.
+ ///
+ public event EventHandler MessageWaiting; + /// + /// A NewCallerId is triggered when the caller id of a channel changes.
+ ///
+ public event EventHandler NewCallerId; + /// + /// A NewChannel is triggered when a new channel is created.
+ ///
+ public event EventHandler NewChannel; + /// + /// A NewExten is triggered when a channel is connected to a new extension.
+ ///
+ public event EventHandler NewExten; + /// + /// A NewState is triggered when the state of a channel has changed.
+ ///
+ public event EventHandler NewState; + // public event OriginateEventHandler Originate; + /// + /// An OriginateFailure is triggered when the execution of an OriginateAction failed. + /// + // public event OriginateFailureEventHandler OriginateFailure; + /// + /// An OriginateSuccess is triggered when the execution of an OriginateAction succeeded. + /// + // public event OriginateSuccessEventHandler OriginateSuccess; + /// + /// An OriginateResponse is triggered when the execution of an Originate. + /// + public event EventHandler OriginateResponse; + /// + /// A ParkedCall is triggered when a channel is parked (in this case no + /// action id is set) and in response to a ParkedCallsAction.
+ ///
+ public event EventHandler ParkedCall; + /// + /// A ParkedCallGiveUp is triggered when a channel that has been parked is hung up.
+ ///
+ public event EventHandler ParkedCallGiveUp; + /// + /// A ParkedCallsComplete is triggered after all parked calls have been reported in response to a ParkedCallsAction. + /// + public event EventHandler ParkedCallsComplete; + /// + /// A ParkedCallTimeOut is triggered when call parking times out for a given channel.
+ ///
+ public event EventHandler ParkedCallTimeOut; + /// + /// A PeerEntry is triggered in response to a SIPPeersAction or SIPShowPeerAction and contains information about a peer.
+ ///
+ public event EventHandler PeerEntry; + /// + /// A PeerlistComplete is triggered after the details of all peers has been reported in response to an SIPPeersAction or SIPShowPeerAction.
+ ///
+ public event EventHandler PeerlistComplete; + /// + /// A PeerStatus is triggered when a SIP or IAX client attempts to registrer at this asterisk server.
+ ///
+ public event EventHandler PeerStatus; + /// + /// A QueueEntryEvent is triggered in response to a QueueStatusAction and contains information about an entry in a queue. + /// + public event EventHandler QueueCallerAbandon; + /// + /// A QueueEntryEvent is triggered in response to a QueueStatusAction and contains information about an entry in a queue. + /// + public event EventHandler QueueEntry; + /// + /// A QueueMemberAddedEvent is triggered when a queue member is added to a queue. + /// + public event EventHandler QueueMemberAdded; + /// + /// A QueueMemberEvent is triggered in response to a QueueStatusAction and contains information about a member of a queue. + /// + public event EventHandler QueueMember; /// /// A QueueMemberPausedEvent is triggered when a queue member is paused or unpaused. /// Replaced by : since Asterisk 12.
/// Removed since : Asterisk 13.
///
- public event QueueMemberPausedEventHandler QueueMemberPaused; - /// - /// A QueueMemberRemovedEvent is triggered when a queue member is removed from a queue. - /// - public event QueueMemberRemovedEventHandler QueueMemberRemoved; - /// - /// A QueueMemberStatusEvent shows the status of a QueueMemberEvent. - /// - public event QueueMemberStatusEventHandler QueueMemberStatus; - /// - /// A QueueParamsEvent is triggered in response to a QueueStatusAction and contains the parameters of a queue. - /// - public event QueueParamsEventHandler QueueParams; - /// - /// A QueueStatusCompleteEvent is triggered after the state of all queues has been reported in response to a QueueStatusAction. - /// - public event QueueStatusCompleteEventHandler QueueStatusComplete; - /// - /// A Registry is triggered when this asterisk server attempts to register - /// as a client at another SIP or IAX server.
- ///
- public event RegistryEventHandler Registry; - /// - /// A RenameEvent is triggered when the name of a channel is changed. - /// - public event RenameEventHandler Rename; - /// - /// A StatusCompleteEvent is triggered after the state of all channels has been reported in response to a StatusAction. - /// - public event StatusCompleteEventHandler StatusComplete; - /// - /// A StatusEvent is triggered for each active channel in response to a StatusAction. - /// - public event StatusEventHandler Status; - /// - /// - /// - public event TransferEventHandler Transfer; - /// - /// An UnholdEvent is triggered by the SIP channel driver when a channel is no longer put on hold. - /// - public event UnholdEventHandler Unhold; - /// - /// An UnlinkEvent is triggered when a link between two voice channels is discontinued, for example, just before call completion. - /// - public event UnlinkEventHandler Unlink; - /// - /// A UnparkedCallEvent is triggered when a channel that has been parked is resumed. - /// - public event UnparkedCallEventHandler UnparkedCall; - /// - /// A ZapShowChannelsEvent is triggered on UserEvent in dialplan. - /// - public event UserEventHandler UserEvents; - /// - /// A ZapShowChannelsCompleteEvent is triggered after the state of all zap channels has been reported in response to a ZapShowChannelsAction. - /// - public event ZapShowChannelsCompleteEventHandler ZapShowChannelsComplete; - /// - /// A ZapShowChannelsEvent is triggered in response to a ZapShowChannelsAction and shows the state of a zap channel. - /// - public event ZapShowChannelsEventHandler ZapShowChannels; - /// - /// A ConnectionState is triggered after Connect/Disconnect/Reload/Shutdown events. - /// - public event ConnectionStateEventHandler ConnectionState; + public event EventHandler QueueMemberPaused; + /// + /// A QueueMemberRemovedEvent is triggered when a queue member is removed from a queue. + /// + public event EventHandler QueueMemberRemoved; + /// + /// A QueueMemberStatusEvent shows the status of a QueueMemberEvent. + /// + public event EventHandler QueueMemberStatus; + /// + /// A QueueParamsEvent is triggered in response to a QueueStatusAction and contains the parameters of a queue. + /// + public event EventHandler QueueParams; + /// + /// A QueueStatusCompleteEvent is triggered after the state of all queues has been reported in response to a QueueStatusAction. + /// + public event EventHandler QueueStatusComplete; + /// + /// A Registry is triggered when this asterisk server attempts to register + /// as a client at another SIP or IAX server.
+ ///
+ public event EventHandler Registry; + /// + /// A RenameEvent is triggered when the name of a channel is changed. + /// + public event EventHandler Rename; + /// + /// A StatusCompleteEvent is triggered after the state of all channels has been reported in response to a StatusAction. + /// + public event EventHandler StatusComplete; + /// + /// A StatusEvent is triggered for each active channel in response to a StatusAction. + /// + public event EventHandler Status; + /// + /// + /// + public event EventHandler Transfer; + /// + /// An UnholdEvent is triggered by the SIP channel driver when a channel is no longer put on hold. + /// + public event EventHandler Unhold; + /// + /// An UnlinkEvent is triggered when a link between two voice channels is discontinued, for example, just before call completion. + /// + public event EventHandler Unlink; + /// + /// A UnparkedCallEvent is triggered when a channel that has been parked is resumed. + /// + public event EventHandler UnparkedCall; + /// + /// A ZapShowChannelsEvent is triggered on UserEvent in dialplan. + /// + public event EventHandler UserEvents; + /// + /// A ZapShowChannelsCompleteEvent is triggered after the state of all zap channels has been reported in response to a ZapShowChannelsAction. + /// + public event EventHandler ZapShowChannelsComplete; + /// + /// A ZapShowChannelsEvent is triggered in response to a ZapShowChannelsAction and shows the state of a zap channel. + /// + public event EventHandler ZapShowChannels; + /// + /// A ConnectionState is triggered after Connect/Disconnect/Reload/Shutdown events. + /// + public event EventHandler ConnectionState; - /// - /// When a variable is set - /// - public event VarSetEventHandler VarSet; + /// + /// When a variable is set + /// + public event EventHandler VarSet; - /// - /// AgiExec is execute - /// - public event AGIExecHandler AGIExec; + /// + /// AgiExec is execute + /// + public event EventHandler AGIExec; - /// - /// This event is sent when the first user requests a conference and it is instantiated - /// - public event ConfbridgeStartEventHandler ConfbridgeStart; + /// + /// This event is sent when the first user requests a conference and it is instantiated + /// + public event EventHandler ConfbridgeStart; - /// - /// This event is sent when a user joins a conference - either one already in progress or as the first user to join a newly instantiated bridge. - /// - public event ConfbridgeJoinEventHandler ConfbridgeJoin; + /// + /// This event is sent when a user joins a conference - either one already in progress or as the first user to join a newly instantiated bridge. + /// + public event EventHandler ConfbridgeJoin; - /// - /// This event is sent when a user leaves a conference. - /// - public event ConfbridgeLeaveEventHandler ConfbridgeLeave; + /// + /// This event is sent when a user leaves a conference. + /// + public event EventHandler ConfbridgeLeave; - /// - /// This event is sent when the last user leaves a conference and it is torn down. - /// - public event ConfbridgeEndEventHandler ConfbridgeEnd; + /// + /// This event is sent when the last user leaves a conference and it is torn down. + /// + public event EventHandler ConfbridgeEnd; - /// - /// This event is sent when the conference detects that a user has either begin or stopped talking. - /// - public event ConfbridgeTalkingEventHandler ConfbridgeTalking; + /// + /// This event is sent when the conference detects that a user has either begin or stopped talking. + /// + public event EventHandler ConfbridgeTalking; /// /// /// - public event FailedACLEventHandler FailedACL; + public event EventHandler FailedACL; - public event AttendedTransferEventHandler AttendedTransfer; - public event BlindTransferEventHandler BlindTransfer; + public event EventHandler AttendedTransfer; + public event EventHandler BlindTransfer; - public event BridgeCreateEventHandler BridgeCreate; - public event BridgeDestroyEventHandler BridgeDestroy; - public event BridgeEnterEventHandler BridgeEnter; - public event BridgeLeaveEventHandler BridgeLeave; + public event EventHandler BridgeCreate; + public event EventHandler BridgeDestroy; + public event EventHandler BridgeEnter; + public event EventHandler BridgeLeave; /// /// Raised when a dial action has started.
///
- public event DialBeginEventHandler DialBegin; + public event EventHandler DialBegin; /// /// Raised when a dial action has completed.
///
- public event DialEndEventHandler DialEnd; + public event EventHandler DialEnd; /// /// Raised when a caller joins a Queue.
///
- public event QueueCallerJoinEventHandler QueueCallerJoin; + public event EventHandler QueueCallerJoin; /// /// Raised when a caller leaves a Queue.
///
- public event QueueCallerLeaveEventHandler QueueCallerLeave; + public event EventHandler QueueCallerLeave; /// /// A QueueMemberPauseEvent is triggered when a queue member is paused or unpaused.
/// Available since : Asterisk 12. ///
- public event QueueMemberPauseEventHandler QueueMemberPause; + public event EventHandler QueueMemberPause; #endregion #region Constructor - ManagerConnection() /// Creates a new instance. public ManagerConnection() - { - callerThread = Thread.CurrentThread; + { + callerThread = Thread.CurrentThread; - socketEncoding = Encoding.ASCII; + socketEncoding = Encoding.ASCII; - responseHandlers = new Dictionary(); - pingHandlers = new Dictionary(); - responseEventHandlers = new Dictionary(); - registeredEventClasses = new Dictionary(); + responseHandlers = new Dictionary(); + pingHandlers = new Dictionary(); + responseEventHandlers = new Dictionary(); + registeredEventClasses = new Dictionary(); - Helper.RegisterBuiltinEventClasses(registeredEventClasses); + Helper.RegisterBuiltinEventClasses(registeredEventClasses); - registeredEventHandlers = new Dictionary(); + registeredEventHandlers = new Dictionary>(); - #region Event mapping table - Helper.RegisterEventHandler(registeredEventHandlers, 0, typeof(AgentCallbackLoginEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 1, typeof(AgentCallbackLogoffEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 2, typeof(AgentCalledEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 3, typeof(AgentCompleteEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 4, typeof(AgentConnectEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 5, typeof(AgentDumpEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 6, typeof(AgentLoginEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 7, typeof(AgentLogoffEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 8, typeof(AgentsCompleteEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 9, typeof(AgentsEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 10, typeof(AlarmClearEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 11, typeof(AlarmEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 12, typeof(CdrEvent)); + #region Event mapping table + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentCallbackLoginEvent), arg => fireEvent(AgentCallbackLogin, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentCallbackLogoffEvent), arg => fireEvent(AgentCallbackLogoff, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentCalledEvent), arg => fireEvent(AgentCalled, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentCompleteEvent), arg => fireEvent(AgentComplete, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentConnectEvent), arg => fireEvent(AgentConnect, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentDumpEvent), arg => fireEvent(AgentDump, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentLoginEvent), arg => fireEvent(AgentLogin, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentLogoffEvent), arg => fireEvent(AgentLogoff, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentsCompleteEvent), arg => fireEvent(AgentsComplete, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentsEvent), arg => fireEvent(Agents, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AlarmClearEvent), arg => fireEvent(AlarmClear, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AlarmEvent), arg => fireEvent(Alarm, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(CdrEvent), arg => fireEvent(Cdr, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 14, typeof(DBGetResponseEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 15, typeof(DialEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(DBGetResponseEvent), arg => fireEvent(DBGetResponse, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(DialEvent), arg => fireEvent(Dial, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 17, typeof(DNDStateEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 18, typeof(ExtensionStatusEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 19, typeof(HangupEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 20, typeof(HoldedCallEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 21, typeof(HoldEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 22, typeof(JoinEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 23, typeof(LeaveEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 24, typeof(LinkEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 25, typeof(LogChannelEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 26, typeof(MeetmeJoinEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 27, typeof(MeetmeLeaveEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 28, typeof(MeetmeTalkingEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 29, typeof(MessageWaitingEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 30, typeof(NewCallerIdEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 31, typeof(NewChannelEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 32, typeof(NewExtenEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 33, typeof(NewStateEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 34, typeof(OriginateResponseEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 35, typeof(ParkedCallEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 36, typeof(ParkedCallGiveUpEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 37, typeof(ParkedCallsCompleteEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 38, typeof(ParkedCallTimeOutEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 39, typeof(PeerEntryEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 40, typeof(PeerlistCompleteEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 41, typeof(PeerStatusEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 42, typeof(QueueEntryEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 43, typeof(QueueMemberAddedEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 44, typeof(QueueMemberEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 45, typeof(QueueMemberPausedEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 46, typeof(QueueMemberRemovedEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 47, typeof(QueueMemberStatusEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 48, typeof(QueueParamsEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 49, typeof(QueueStatusCompleteEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 50, typeof(RegistryEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 51, typeof(QueueCallerAbandonEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 52, typeof(RenameEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(DNDStateEvent), arg => fireEvent(DNDState, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ExtensionStatusEvent), arg => fireEvent(ExtensionStatus, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(HangupEvent), arg => fireEvent(Hangup, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(HoldedCallEvent), arg => fireEvent(HoldedCall, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(HoldEvent), arg => fireEvent(Hold, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(JoinEvent), arg => fireEvent(Join, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(LeaveEvent), arg => fireEvent(Leave, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(LinkEvent), arg => fireEvent(Link, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(LogChannelEvent), arg => fireEvent(LogChannel, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(MeetmeJoinEvent), arg => fireEvent(MeetMeJoin, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(MeetmeLeaveEvent), arg => fireEvent(MeetMeLeave, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(MeetmeTalkingEvent), arg => fireEvent(MeetMeTalking, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(MessageWaitingEvent), arg => fireEvent(MessageWaiting, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(NewCallerIdEvent), arg => fireEvent(NewCallerId, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(NewChannelEvent), arg => fireEvent(NewChannel, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(NewExtenEvent), arg => fireEvent(NewExten, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(NewStateEvent), arg => fireEvent(NewState, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(OriginateResponseEvent), arg => fireEvent(OriginateResponse, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallEvent), arg => fireEvent(ParkedCall, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallGiveUpEvent), arg => fireEvent(ParkedCallGiveUp, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallsCompleteEvent), arg => fireEvent(ParkedCallsComplete, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallTimeOutEvent), arg => fireEvent(ParkedCallsComplete, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(PeerEntryEvent), arg => fireEvent(ParkedCallTimeOut, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(PeerlistCompleteEvent), arg => fireEvent(PeerlistComplete, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(PeerStatusEvent), arg => fireEvent(PeerStatus, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueEntryEvent), arg => fireEvent(QueueEntry, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueMemberAddedEvent), arg => fireEvent(QueueMemberAdded, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueMemberEvent), arg => fireEvent(QueueMember, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueMemberPausedEvent), arg => fireEvent(QueueMemberPaused, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueMemberRemovedEvent), arg => fireEvent(QueueMemberRemoved, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueMemberStatusEvent), arg => fireEvent(QueueMemberStatus, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueParamsEvent), arg => fireEvent(QueueParams, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueStatusCompleteEvent), arg => fireEvent(QueueStatusComplete, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(RegistryEvent), arg => fireEvent(Registry, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueCallerAbandonEvent), arg => fireEvent(QueueCallerAbandon, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(RenameEvent), arg => fireEvent(Rename, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 54, typeof(StatusCompleteEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 55, typeof(StatusEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 56, typeof(UnholdEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 57, typeof(UnlinkEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 58, typeof(UnparkedCallEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 59, typeof(UserEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 60, typeof(ZapShowChannelsCompleteEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 61, typeof(ZapShowChannelsEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(StatusCompleteEvent), arg => fireEvent(StatusComplete, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(StatusEvent), arg => fireEvent(Status, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(UnholdEvent), arg => fireEvent(Unhold, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(UnlinkEvent), arg => fireEvent(Unlink, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(UnparkedCallEvent), arg => fireEvent(UnparkedCall, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(UserEvent), arg => fireEvent(UserEvents, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ZapShowChannelsCompleteEvent), arg => fireEvent(ZapShowChannelsComplete, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ZapShowChannelsEvent), arg => fireEvent(ZapShowChannels, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(ConnectEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(DisconnectEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(ReloadEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(ShutdownEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ConnectEvent), arg => fireEvent(ConnectionState, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(DisconnectEvent), arg => fireEvent(ConnectionState, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ReloadEvent), arg => fireEvent(ConnectionState, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ShutdownEvent), arg => fireEvent(ConnectionState, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 63, typeof(BridgeEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 64, typeof(TransferEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 65, typeof(DTMFEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(BridgeEvent), arg => fireEvent(Bridge, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(TransferEvent), arg => fireEvent(Transfer, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(DTMFEvent), arg => fireEvent(DTMF, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 70, typeof(VarSetEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 80, typeof(AGIExecEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(VarSetEvent), arg => fireEvent(VarSet, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AGIExecEvent), arg => fireEvent(AGIExec, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 81, typeof(ConfbridgeStartEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 82, typeof(ConfbridgeJoinEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 83, typeof(ConfbridgeLeaveEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 84, typeof(ConfbridgeEndEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 85, typeof(ConfbridgeTalkingEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ConfbridgeStartEvent), arg => fireEvent(ConfbridgeStart, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ConfbridgeJoinEvent), arg => fireEvent(ConfbridgeJoin, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ConfbridgeLeaveEvent), arg => fireEvent(ConfbridgeLeave, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ConfbridgeEndEvent), arg => fireEvent(ConfbridgeEnd, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ConfbridgeTalkingEvent), arg => fireEvent(ConfbridgeTalking, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 86, typeof(FailedACLEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(FailedACLEvent), arg => fireEvent(FailedACL, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, 87, typeof(AttendedTransferEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 88, typeof(BridgeCreateEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 89, typeof(BridgeDestroyEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 90, typeof(BridgeEnterEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 91, typeof(BridgeLeaveEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 92, typeof(BlindTransferEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 93, typeof(DialBeginEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 94, typeof(DialEndEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 95, typeof(QueueCallerJoinEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 96, typeof(QueueCallerLeaveEvent)); - Helper.RegisterEventHandler(registeredEventHandlers, 97, typeof(QueueMemberPauseEvent)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(AttendedTransferEvent), arg => fireEvent(AttendedTransfer, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(BridgeCreateEvent), arg => fireEvent(BridgeCreate, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(BridgeDestroyEvent), arg => fireEvent(BridgeDestroy, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(BridgeEnterEvent), arg => fireEvent(BridgeEnter, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(BridgeLeaveEvent), arg => fireEvent(BridgeLeave, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(BlindTransferEvent), arg => fireEvent(BlindTransfer, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(DialBeginEvent), arg => fireEvent(DialBegin, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(DialEndEvent), arg => fireEvent(DialEnd, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueCallerJoinEvent), arg => fireEvent(QueueCallerJoin, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueCallerLeaveEvent), arg => fireEvent(QueueCallerLeave, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueMemberPauseEvent), arg => fireEvent(QueueMemberPause, arg)); #endregion - this.internalEvent += new ManagerEventHandler(internalEventHandler); - } - #endregion + this.internalEvent += new EventHandler(internalEventHandler); - #region Constructor - ManagerConnection(hostname, port, username, password) - /// - /// Creates a new instance with the given connection parameters. - /// - /// the hosname of the Asterisk server to connect to. - /// the port where Asterisk listens for incoming Manager API connections, usually 5038. - /// the username to use for login - /// the password to use for login - public ManagerConnection(string hostname, int port, string username, string password) - : this() - { - this.hostname = hostname; - this.port = port; - this.username = username; - this.password = password; - } - #endregion + } + #endregion - #region Constructor - ManagerConnection(hostname, port, username, password, Encoding socketEncoding) - /// - /// Creates a new instance with the given connection parameters. - /// - /// the hosname of the Asterisk server to connect to. - /// the port where Asterisk listens for incoming Manager API connections, usually 5038. - /// the username to use for login - /// the password to use for login - /// text encoding to asterisk input/output stream - public ManagerConnection(string hostname, int port, string username, string password, Encoding encoding) - : this() - { - this.hostname = hostname; - this.port = port; - this.username = username; - this.password = password; - this.socketEncoding = encoding; - } - #endregion + #region Constructor - ManagerConnection(hostname, port, username, password) + /// + /// Creates a new instance with the given connection parameters. + /// + /// the hosname of the Asterisk server to connect to. + /// the port where Asterisk listens for incoming Manager API connections, usually 5038. + /// the username to use for login + /// the password to use for login + public ManagerConnection(string hostname, int port, string username, string password) + : this() + { + this.hostname = hostname; + this.port = port; + this.username = username; + this.password = password; + } + #endregion - /// - /// Default Fast Reconnect retry counter. - /// - public int ReconnectRetryFast - { - get { return reconnectRetryFast; } - set { reconnectRetryFast = value; } - } - /// Default Maximum Reconnect retry counter. - public int ReconnectRetryMax - { - get { return reconnectRetryMax; } - set { reconnectRetryMax = value; } - } - /// Default Fast Reconnect interval in milliseconds. - public int ReconnectIntervalFast - { - get { return reconnectIntervalFast; } - set { reconnectIntervalFast = value; } - } - /// Default Slow Reconnect interval in milliseconds. - public int ReconnectIntervalMax - { - get { return reconnectIntervalMax; } - set { reconnectIntervalMax = value; } - } + #region Constructor - ManagerConnection(hostname, port, username, password, Encoding socketEncoding) + /// + /// Creates a new instance with the given connection parameters. + /// + /// the hosname of the Asterisk server to connect to. + /// the port where Asterisk listens for incoming Manager API connections, usually 5038. + /// the username to use for login + /// the password to use for login + /// text encoding to asterisk input/output stream + public ManagerConnection(string hostname, int port, string username, string password, Encoding encoding) + : this() + { + this.hostname = hostname; + this.port = port; + this.username = username; + this.password = password; + this.socketEncoding = encoding; + } + #endregion - #region CallerThread - internal Thread CallerThread - { - get { return callerThread; } - } - #endregion + /// + /// Default Fast Reconnect retry counter. + /// + public int ReconnectRetryFast + { + get { return reconnectRetryFast; } + set { reconnectRetryFast = value; } + } + /// Default Maximum Reconnect retry counter. + public int ReconnectRetryMax + { + get { return reconnectRetryMax; } + set { reconnectRetryMax = value; } + } + /// Default Fast Reconnect interval in milliseconds. + public int ReconnectIntervalFast + { + get { return reconnectIntervalFast; } + set { reconnectIntervalFast = value; } + } + /// Default Slow Reconnect interval in milliseconds. + public int ReconnectIntervalMax + { + get { return reconnectIntervalMax; } + set { reconnectIntervalMax = value; } + } - #region internalEventHandler(object sender, ManagerEvent e) - private void internalEventHandler(object sender, ManagerEvent e) - { - int eventHash = e.GetType().Name.GetHashCode(); - if (registeredEventHandlers.ContainsKey(eventHash)) - { - switch (registeredEventHandlers[eventHash]) - { - #region A-C - case 0: - if (AgentCallbackLogin != null) - { - AgentCallbackLogin(this, (AgentCallbackLoginEvent)e); - return; - } - break; - case 1: - if (AgentCallbackLogoff != null) - { - AgentCallbackLogoff(this, (AgentCallbackLogoffEvent)e); - return; - } - break; - case 2: - if (AgentCalled != null) - { - AgentCalled(this, (Event.AgentCalledEvent)e); - return; - } - break; - case 3: - if (AgentComplete != null) - { - AgentComplete(this, (Event.AgentCompleteEvent)e); - return; - } - break; - case 4: - if (AgentConnect != null) - { - AgentConnect(this, (Event.AgentConnectEvent)e); - return; - } - break; - case 5: - if (AgentDump != null) - { - AgentDump(this, (Event.AgentDumpEvent)e); - return; - } - break; - case 6: - if (AgentLogin != null) - { - AgentLogin(this, (Event.AgentLoginEvent)e); - return; - } - break; - case 7: - if (AgentLogoff != null) - { - AgentLogoff(this, (Event.AgentLogoffEvent)e); - return; - } - break; - case 8: - if (AgentsComplete != null) - { - AgentsComplete(this, (AgentsCompleteEvent)e); - return; - } - break; - case 9: - if (Agents != null) - { - Agents(this, (AgentsEvent)e); - return; - } - break; - case 10: - if (AlarmClear != null) - { - AlarmClear(this, (AlarmClearEvent)e); - return; - } - break; - case 11: - if (Alarm != null) - { - Alarm(this, (AlarmEvent)e); - return; - } - break; - case 12: - if (Cdr != null) - { - Cdr(this, (CdrEvent)e); - return; - } - break; - #endregion - #region D-L - case 14: - if (DBGetResponse != null) - { - DBGetResponse(this, (DBGetResponseEvent)e); - return; - } - break; - case 15: - if (Dial != null) - { - Dial(this, (DialEvent)e); - return; - } - break; - case 17: - if (DNDState != null) - { - DNDState(this, (DNDStateEvent)e); - return; - } - break; - case 18: - if (ExtensionStatus != null) - { - ExtensionStatus(this, (ExtensionStatusEvent)e); - return; - } - break; - case 19: - if (Hangup != null) - { - Hangup(this, (HangupEvent)e); - return; - } - break; - case 20: - if (HoldedCall != null) - { - HoldedCall(this, (HoldedCallEvent)e); - return; - } - break; - case 21: - if (Hold != null) - { - Hold(this, (HoldEvent)e); - return; - } - break; - case 22: - if (Join != null) - { - Join(this, (JoinEvent)e); - return; - } - break; - case 23: - if (Leave != null) - { - Leave(this, (LeaveEvent)e); - return; - } - break; - case 24: - if (Link != null) - { - Link(this, (LinkEvent)e); - return; - } - break; - case 25: - if (LogChannel != null) - { - LogChannel(this, (LogChannelEvent)e); - return; - } - break; - #endregion - #region M-P - case 26: - if (MeetMeJoin != null) - { - MeetMeJoin(this, (MeetmeJoinEvent)e); - return; - } - break; - case 27: - if (MeetMeLeave != null) - { - MeetMeLeave(this, (MeetmeLeaveEvent)e); - return; - } - break; - case 28: - if (MeetMeTalking != null) - { - MeetMeTalking(this, (MeetmeTalkingEvent)e); - return; - } - break; - case 29: - if (MessageWaiting != null) - { - MessageWaiting(this, (MessageWaitingEvent)e); - return; - } - break; - case 30: - if (NewCallerId != null) - { - NewCallerId(this, (NewCallerIdEvent)e); - return; - } - break; - case 31: - if (NewChannel != null) - { - NewChannel(this, (NewChannelEvent)e); - return; - } - break; - case 32: - if (NewExten != null) - { - NewExten(this, (NewExtenEvent)e); - return; - } - break; - case 33: - if (NewState != null) - { - NewState(this, (NewStateEvent)e); - return; - } - break; - case 34: - if (OriginateResponse != null) - { - OriginateResponse(this, (OriginateResponseEvent)e); - return; - } - break; - case 35: - if (ParkedCall != null) - { - ParkedCall(this, (ParkedCallEvent)e); - return; - } - break; - case 36: - if (ParkedCallGiveUp != null) - { - ParkedCallGiveUp(this, (ParkedCallGiveUpEvent)e); - return; - } - break; - case 37: - if (ParkedCallsComplete != null) - { - ParkedCallsComplete(this, (ParkedCallsCompleteEvent)e); - return; - } - break; - case 38: - if (ParkedCallTimeOut != null) - { - ParkedCallTimeOut(this, (ParkedCallTimeOutEvent)e); - return; - } - break; - case 39: - if (PeerEntry != null) - { - PeerEntry(this, (PeerEntryEvent)e); - return; - } - break; - case 40: - if (PeerlistComplete != null) - { - PeerlistComplete(this, (PeerlistCompleteEvent)e); - return; - } - break; - case 41: - if (PeerStatus != null) - { - PeerStatus(this, (PeerStatusEvent)e); - return; - } - break; - #endregion - #region Q-Z - case 42: - if (QueueEntry != null) - { - QueueEntry(this, (QueueEntryEvent)e); - return; - } - break; - case 43: - if (QueueMemberAdded != null) - { - QueueMemberAdded(this, (QueueMemberAddedEvent)e); - return; - } - break; - case 44: - if (QueueMember != null) - { - QueueMember(this, (QueueMemberEvent)e); - return; - } - break; - case 45: - if (QueueMemberPaused != null) - { - QueueMemberPaused(this, (QueueMemberPausedEvent)e); - return; - } - break; - case 46: - if (QueueMemberRemoved != null) - { - QueueMemberRemoved(this, (QueueMemberRemovedEvent)e); - return; - } - break; - case 47: - if (QueueMemberStatus != null) - { - QueueMemberStatus(this, (QueueMemberStatusEvent)e); - return; - } - break; - case 48: - if (QueueParams != null) - { - QueueParams(this, (QueueParamsEvent)e); - return; - } - break; - case 49: - if (QueueStatusComplete != null) - { - QueueStatusComplete(this, (QueueStatusCompleteEvent)e); - return; - } - break; - case 50: - if (Registry != null) - { - Registry(this, (RegistryEvent)e); - return; - } - break; - case 51: - if (QueueCallerAbandon != null) - { - QueueCallerAbandon(this, (QueueCallerAbandonEvent)e); - return; - } - break; - case 52: - if (Rename != null) - { - Rename(this, (RenameEvent)e); - return; - } - break; - case 54: - if (StatusComplete != null) - { - StatusComplete(this, (StatusCompleteEvent)e); - return; - } - break; - case 55: - if (Status != null) - { - Status(this, (StatusEvent)e); - return; - } - break; - case 56: - if (Unhold != null) - { - Unhold(this, (UnholdEvent)e); - return; - } - break; - case 57: - if (Unlink != null) - { - Unlink(this, (UnlinkEvent)e); - return; - } - break; - case 58: - if (UnparkedCall != null) - { - UnparkedCall(this, (UnparkedCallEvent)e); - return; - } - break; - case 59: - if (UserEvents != null) - { - UserEvents(this, (UserEvent)e); - return; - } - break; - case 60: - if (ZapShowChannelsComplete != null) - { - ZapShowChannelsComplete(this, (ZapShowChannelsCompleteEvent)e); - return; - } - break; - case 61: - if (ZapShowChannels != null) - { - ZapShowChannels(this, (ZapShowChannelsEvent)e); - return; - } - break; - #endregion + #region CallerThread + internal Thread CallerThread + { + get { return callerThread; } + } + #endregion - case 62: - if (ConnectionState != null) - { - ConnectionState(this, (ConnectionStateEvent)e); - return; - } - break; - case 63: - if (Bridge != null) - { - Bridge(this, (BridgeEvent)e); - } - break; - case 64: - if (Transfer != null) - { - Transfer(this, (TransferEvent)e); - } - break; - case 65: - if (DTMF != null) - { - DTMF(this, (DTMFEvent)e); - } - break; - case 70: - if (VarSet != null) - { - VarSet(this, (VarSetEvent)e); - } - break; - case 80: - if (AGIExec != null) - { - AGIExec(this, (AGIExecEvent)e); - } - break; - case 81: - if (ConfbridgeStart != null) - { - ConfbridgeStart(this, (ConfbridgeStartEvent)e); - } - break; - case 82: - if (ConfbridgeJoin != null) - { - ConfbridgeJoin(this, (ConfbridgeJoinEvent)e); - } - break; - case 83: - if (ConfbridgeLeave != null) - { - ConfbridgeLeave(this, (ConfbridgeLeaveEvent)e); - } - break; - case 84: - if (ConfbridgeEnd != null) - { - ConfbridgeEnd(this, (ConfbridgeEndEvent)e); - } - break; - case 85: - if (ConfbridgeTalking != null) - { - ConfbridgeTalking(this, (ConfbridgeTalkingEvent)e); - } - break; - case 86: - if (FailedACL != null) - { - FailedACL(this, (FailedACLEvent)e); - } - break; - case 87: - if (AttendedTransfer != null) - { - AttendedTransfer(this, (AttendedTransferEvent) e); - } - break; - case 88: - if (BridgeCreate != null) - { - BridgeCreate(this, (BridgeCreateEvent) e); - } - break; - case 89: - if (BridgeDestroy != null) - { - BridgeDestroy(this, (BridgeDestroyEvent)e); - } - break; - case 90: - if (BridgeEnter != null) - { - BridgeEnter(this, (BridgeEnterEvent)e); - } - break; - case 91: - if (BridgeLeave != null) - { - BridgeLeave(this, (BridgeLeaveEvent)e); - } - break; - case 92: - if (BlindTransfer != null) - { - BlindTransfer(this, (BlindTransferEvent)e); - } - break; - case 93: - if (DialBegin != null) - { - DialBegin(this, (DialBeginEvent)e); - } - break; - case 94: - if (DialEnd != null) - { - DialEnd(this, (DialEndEvent)e); - } - break; - case 95: - if (QueueCallerJoin != null) - { - QueueCallerJoin(this, (QueueCallerJoinEvent)e); - } - break; - case 96: - if (QueueCallerLeave != null) - { - QueueCallerLeave(this, (QueueCallerLeaveEvent)e); - } - break; - case 97: - if (QueueMemberPause != null) - { - QueueMemberPause(this, (QueueMemberPauseEvent)e); - } - break; - default: - if (UnhandledEvent != null) - UnhandledEvent(this, e); - return; - } - } - if (fireAllEvents && UnhandledEvent != null) - UnhandledEvent(this, e); - } - #endregion + #region internalEventHandler(object sender, ManagerEvent e) + private void internalEventHandler(object sender, ManagerEvent e) + { + int eventHash = e.GetType().Name.GetHashCode(); + if (registeredEventHandlers.ContainsKey(eventHash)) + { + var currentEvent = registeredEventHandlers[eventHash]; + currentEvent(e); + } + else + { + fireEvent(UnhandledEvent, e); + } - #region FireAllEvents - /// - /// If this property set to true then ManagerConnection send all unassigned events to UnhandledEvent handler,
- /// if set to false then all unassgned events lost and send only UnhandledEvent.
- /// Default: false - ///
- public bool FireAllEvents - { - get { return this.fireAllEvents; } - set { this.fireAllEvents = value; } - } - #endregion + if (fireAllEvents) + fireEvent(UnhandledEvent, e); + } + #endregion - #region PingInterval - /// - /// Timeout from Ping to Pong. If no Pong received send Disconnect event. Set to zero to disable. - /// - public int PingInterval - { - get { return pingInterval; } - set { pingInterval = value; } - } - #endregion + #region FireAllEvents + /// + /// If this property set to true then ManagerConnection send all unassigned events to UnhandledEvent handler,
+ /// if set to false then all unassgned events lost and send only UnhandledEvent.
+ /// Default: false + ///
+ public bool FireAllEvents + { + get { return this.fireAllEvents; } + set { this.fireAllEvents = value; } + } + #endregion - #region Hostname - /// Sets the hostname of the asterisk server to connect to.
- /// Default is localhost. - ///
- public string Hostname - { - get { return hostname; } - set { hostname = value; } - } - #endregion + #region PingInterval + /// + /// Timeout from Ping to Pong. If no Pong received send Disconnect event. Set to zero to disable. + /// + public int PingInterval + { + get { return pingInterval; } + set { pingInterval = value; } + } + #endregion - #region Port - /// - /// Sets the port to use to connect to the asterisk server. This is the port - /// specified in asterisk's manager.conf file.
- /// Default is 5038. - ///
- public int Port - { - get { return port; } - set { port = value; } - } - #endregion + #region Hostname + /// Sets the hostname of the asterisk server to connect to.
+ /// Default is localhost. + ///
+ public string Hostname + { + get { return hostname; } + set { hostname = value; } + } + #endregion - #region UserName - /// - /// Sets the username to use to connect to the asterisk server. This is the - /// username specified in asterisk's manager.conf file. - /// - public string Username - { - get { return username; } - set { username = value; } - } - #endregion + #region Port + /// + /// Sets the port to use to connect to the asterisk server. This is the port + /// specified in asterisk's manager.conf file.
+ /// Default is 5038. + ///
+ public int Port + { + get { return port; } + set { port = value; } + } + #endregion - #region Password - /// - /// Sets the password to use to connect to the asterisk server. This is the - /// password specified in asterisk's manager.conf file. - /// - public string Password - { - get { return password; } - set { password = value; } - } - #endregion + #region UserName + /// + /// Sets the username to use to connect to the asterisk server. This is the + /// username specified in asterisk's manager.conf file. + /// + public string Username + { + get { return username; } + set { username = value; } + } + #endregion - #region DefaultResponseTimeout - /// Sets the time in milliseconds the synchronous method - /// will wait for a response before throwing a TimeoutException.
- /// Default is 2000. - ///
- public int DefaultResponseTimeout - { - get { return defaultResponseTimeout; } - set { defaultResponseTimeout = value; } - } - #endregion + #region Password + /// + /// Sets the password to use to connect to the asterisk server. This is the + /// password specified in asterisk's manager.conf file. + /// + public string Password + { + get { return password; } + set { password = value; } + } + #endregion - #region DefaultEventTimeout - /// Sets the time in milliseconds the synchronous method - /// will wait for a response and the last response event before throwing a TimeoutException.
- /// Default is 5000. - ///
- public int DefaultEventTimeout - { - get { return defaultEventTimeout; } - set { defaultEventTimeout = value; } - } - #endregion + #region DefaultResponseTimeout + /// Sets the time in milliseconds the synchronous method + /// will wait for a response before throwing a TimeoutException.
+ /// Default is 2000. + ///
+ public int DefaultResponseTimeout + { + get { return defaultResponseTimeout; } + set { defaultResponseTimeout = value; } + } + #endregion - #region SleepTime - /// Sets the time in milliseconds the synchronous methods - /// SendAction(Action.ManagerAction) and - /// SendAction(Action.ManagerAction, long) will sleep between two checks - /// for the arrival of a response. This value should be rather small.
- /// The sleepTime attribute is also used when checking for the protocol - /// identifer.
- /// Default is 50. - ///
- /// this has been replaced by an interrupt based response checking approach. - public int SleepTime - { - get { return sleepTime; } - set { sleepTime = value; } - } - #endregion + #region DefaultEventTimeout + /// Sets the time in milliseconds the synchronous method + /// will wait for a response and the last response event before throwing a TimeoutException.
+ /// Default is 5000. + ///
+ public int DefaultEventTimeout + { + get { return defaultEventTimeout; } + set { defaultEventTimeout = value; } + } + #endregion - #region KeepAliveAfterAuthenticationFailure - /// Set to true to try reconnecting to ther asterisk serve - /// even if the reconnection attempt threw an AuthenticationFailedException.
- /// Default is false. - ///
- public bool KeepAliveAfterAuthenticationFailure - { - set { keepAliveAfterAuthenticationFailure = value; } - get { return keepAliveAfterAuthenticationFailure; } - } - #endregion + #region SleepTime + /// Sets the time in milliseconds the synchronous methods + /// SendAction(Action.ManagerAction) and + /// SendAction(Action.ManagerAction, long) will sleep between two checks + /// for the arrival of a response. This value should be rather small.
+ /// The sleepTime attribute is also used when checking for the protocol + /// identifer.
+ /// Default is 50. + ///
+ /// this has been replaced by an interrupt based response checking approach. + public int SleepTime + { + get { return sleepTime; } + set { sleepTime = value; } + } + #endregion - #region KeepAlive - /// - /// Should we attempt to reconnect when the connection is lost?
- /// This is set to true after successful login and to false after logoff or after an authentication failure when keepAliveAfterAuthenticationFailure is false. - ///
- public bool KeepAlive - { - get { return keepAlive; } - set { keepAlive = value; } - } - #endregion + #region KeepAliveAfterAuthenticationFailure + /// Set to true to try reconnecting to ther asterisk serve + /// even if the reconnection attempt threw an AuthenticationFailedException.
+ /// Default is false. + ///
+ public bool KeepAliveAfterAuthenticationFailure + { + set { keepAliveAfterAuthenticationFailure = value; } + get { return keepAliveAfterAuthenticationFailure; } + } + #endregion - #region SocketEncoding - /// - /// Socket Encoding - default ASCII - /// - public Encoding SocketEncoding - { - get { return socketEncoding; } - set { socketEncoding = value; } - } - #endregion + #region KeepAlive + /// + /// Should we attempt to reconnect when the connection is lost?
+ /// This is set to true after successful login and to false after logoff or after an authentication failure when keepAliveAfterAuthenticationFailure is false. + ///
+ public bool KeepAlive + { + get { return keepAlive; } + set { keepAlive = value; } + } + #endregion - #region Version - public string Version - { - get { return version; } - } - #endregion + #region SocketEncoding + /// + /// Socket Encoding - default ASCII + /// + public Encoding SocketEncoding + { + get { return socketEncoding; } + set { socketEncoding = value; } + } + #endregion - #region AsteriskVersion - public AsteriskVersion AsteriskVersion - { - get { return asteriskVersion; } - } - #endregion + #region Version + public string Version + { + get { return version; } + } + #endregion - #region login(timeout) - /// - /// Does the real login, following the steps outlined below.
- /// Connects to the asterisk server by calling connect() if not already connected
- /// Waits until the protocol identifier is received. This is checked every sleepTime ms but not longer than timeout ms in total.
- /// Sends a ChallengeAction requesting a challenge for authType MD5.
- /// When the ChallengeResponse is received a LoginAction is sent using the calculated key (MD5 hash of the password appended to the received challenge).
- ///
- /// the maximum time to wait for the protocol identifier (in ms) - /// - /// AuthenticationFailedException if username or password are incorrect and the login action returns an error or if the MD5 - /// hash cannot be computed. The connection is closed in this case. - /// - /// - /// TimeoutException if a timeout occurs either while waiting for the - /// protocol identifier or when sending the challenge or login - /// action. The connection is closed in this case. - /// - private void login(int timeout) - { - enableEvents = false; - if (reconnected) - { + #region AsteriskVersion + public AsteriskVersion AsteriskVersion + { + get { return asteriskVersion; } + } + #endregion + + #region login(timeout) + /// + /// Does the real login, following the steps outlined below.
+ /// Connects to the asterisk server by calling connect() if not already connected
+ /// Waits until the protocol identifier is received. This is checked every sleepTime ms but not longer than timeout ms in total.
+ /// Sends a ChallengeAction requesting a challenge for authType MD5.
+ /// When the ChallengeResponse is received a LoginAction is sent using the calculated key (MD5 hash of the password appended to the received challenge).
+ ///
+ /// the maximum time to wait for the protocol identifier (in ms) + /// + /// AuthenticationFailedException if username or password are incorrect and the login action returns an error or if the MD5 + /// hash cannot be computed. The connection is closed in this case. + /// + /// + /// TimeoutException if a timeout occurs either while waiting for the + /// protocol identifier or when sending the challenge or login + /// action. The connection is closed in this case. + /// + private void login(int timeout) + { + enableEvents = false; + if (reconnected) + { #if LOGGER - logger.Error("Login during reconnect state."); + logger.Error("Login during reconnect state."); #endif - throw new AuthenticationFailedException("Unable login during reconnect state."); - } + throw new AuthenticationFailedException("Unable login during reconnect state."); + } - reconnectEnable = false; - DateTime start = DateTime.Now; - do - { - if (connect()) - { - // Increase delay after connection up to 500 ms - Thread.Sleep(10 * sleepTime); // 200 milliseconds delay - } - try - { - Thread.Sleep(4 * sleepTime); // 200 milliseconds delay - } - catch - { } + reconnectEnable = false; + DateTime start = DateTime.Now; + do + { + if (connect()) + { + // Increase delay after connection up to 500 ms + Thread.Sleep(10 * sleepTime); // 200 milliseconds delay + } + try + { + Thread.Sleep(4 * sleepTime); // 200 milliseconds delay + } + catch + { } - if (string.IsNullOrEmpty(protocolIdentifier) && timeout > 0 && Helper.GetMillisecondsFrom(start) > timeout) - { - disconnect(true); - throw new TimeoutException("Timeout waiting for protocol identifier"); - } - } while (string.IsNullOrEmpty(protocolIdentifier)); + if (string.IsNullOrEmpty(protocolIdentifier) && timeout > 0 && Helper.GetMillisecondsFrom(start) > timeout) + { + disconnect(true); + throw new TimeoutException("Timeout waiting for protocol identifier"); + } + } while (string.IsNullOrEmpty(protocolIdentifier)); - ChallengeAction challengeAction = new ChallengeAction(); - Response.ManagerResponse response = SendAction(challengeAction, defaultResponseTimeout * 2); - if (response is ChallengeResponse) - { - ChallengeResponse challengeResponse = (ChallengeResponse)response; - string key, challenge = challengeResponse.Challenge; - try - { - Util.MD5Support md = Util.MD5Support.GetInstance(); - if (challenge != null) - md.Update(UTF8Encoding.UTF8.GetBytes(challenge)); - if (password != null) - md.Update(UTF8Encoding.UTF8.GetBytes(password)); - key = Helper.ToHexString(md.DigestData); - } - catch (Exception ex) - { - disconnect(true); + ChallengeAction challengeAction = new ChallengeAction(); + Response.ManagerResponse response = SendAction(challengeAction, defaultResponseTimeout * 2); + if (response is ChallengeResponse) + { + ChallengeResponse challengeResponse = (ChallengeResponse)response; + string key, challenge = challengeResponse.Challenge; + try + { + Util.MD5Support md = Util.MD5Support.GetInstance(); + if (challenge != null) + md.Update(UTF8Encoding.UTF8.GetBytes(challenge)); + if (password != null) + md.Update(UTF8Encoding.UTF8.GetBytes(password)); + key = Helper.ToHexString(md.DigestData); + } + catch (Exception ex) + { + disconnect(true); #if LOGGER - logger.Error("Unable to create login key using MD5 Message Digest.", ex); + logger.Error("Unable to create login key using MD5 Message Digest.", ex); #endif - throw new AuthenticationFailedException("Unable to create login key using MD5 Message Digest.", ex); - } + throw new AuthenticationFailedException("Unable to create login key using MD5 Message Digest.", ex); + } - Action.LoginAction loginAction = new Action.LoginAction(username, "MD5", key); - Response.ManagerResponse loginResponse = SendAction(loginAction); - if (loginResponse is Response.ManagerError) - { - disconnect(true); - throw new AuthenticationFailedException(loginResponse.Message); - } + Action.LoginAction loginAction = new Action.LoginAction(username, "MD5", key); + Response.ManagerResponse loginResponse = SendAction(loginAction); + if (loginResponse is Response.ManagerError) + { + disconnect(true); + throw new AuthenticationFailedException(loginResponse.Message); + } - // successfully logged in so assure that we keep trying to reconnect when disconnected - reconnectEnable = keepAlive; + // successfully logged in so assure that we keep trying to reconnect when disconnected + reconnectEnable = keepAlive; #if LOGGER - logger.Info("Successfully logged in"); + logger.Info("Successfully logged in"); #endif - asteriskVersion = determineVersion(); + asteriskVersion = determineVersion(); #if LOGGER - logger.Info("Determined Asterisk version: " + asteriskVersion); + logger.Info("Determined Asterisk version: " + asteriskVersion); #endif - enableEvents = true; - ConnectEvent ce = new ConnectEvent(this); - ce.ProtocolIdentifier = this.protocolIdentifier; - DispatchEvent(ce); - } - else if (response is ManagerError) - throw new ManagerException("Unable login to Asterisk - " + response.Message); - else - throw new ManagerException("Unknown response during login to Asterisk - " + response.GetType().Name + " with message " + response.Message); + enableEvents = true; + ConnectEvent ce = new ConnectEvent(this); + ce.ProtocolIdentifier = this.protocolIdentifier; + DispatchEvent(ce); + } + else if (response is ManagerError) + throw new ManagerException("Unable login to Asterisk - " + response.Message); + else + throw new ManagerException("Unknown response during login to Asterisk - " + response.GetType().Name + " with message " + response.Message); - } - #endregion + } + #endregion - #region determineVersion() - protected internal AsteriskVersion determineVersion() - { - Response.ManagerResponse response; - response = SendAction(new Action.CommandAction("core show version"), defaultResponseTimeout * 2); - if (response is Response.CommandResponse) - { - foreach (string line in ((Response.CommandResponse)response).Result) - { - foreach (Match m in Common.ASTERISK_VERSION.Matches(line)) - { - if (m.Groups.Count >= 2) - { - version = m.Groups[1].Value; + #region determineVersion() + protected internal AsteriskVersion determineVersion() + { + Response.ManagerResponse response; + response = SendAction(new Action.CommandAction("core show version"), defaultResponseTimeout * 2); + if (response is Response.CommandResponse) + { + foreach (string line in ((Response.CommandResponse)response).Result) + { + foreach (Match m in Common.ASTERISK_VERSION.Matches(line)) + { + if (m.Groups.Count >= 2) + { + version = m.Groups[1].Value; if (version.StartsWith("1.4.")) { VAR_DELIMITER = new char[] { '|' }; @@ -1612,56 +963,56 @@ namespace AsterNET.Manager } else throw new ManagerException("Unknown Asterisk version " + version); - } - } - } - } + } + } + } + } - Response.ManagerResponse showVersionFilesResponse = SendAction(new Action.CommandAction("show version files"), defaultResponseTimeout * 2); - if (showVersionFilesResponse is Response.CommandResponse) - { - IList showVersionFilesResult = ((Response.CommandResponse)showVersionFilesResponse).Result; - if (showVersionFilesResult != null && showVersionFilesResult.Count > 0) - { - string line1; - line1 = (string)showVersionFilesResult[0]; - if (line1 != null && line1.StartsWith("File")) - return AsteriskVersion.ASTERISK_1_2; - } - } - return AsteriskVersion.ASTERISK_1_0; - } + Response.ManagerResponse showVersionFilesResponse = SendAction(new Action.CommandAction("show version files"), defaultResponseTimeout * 2); + if (showVersionFilesResponse is Response.CommandResponse) + { + IList showVersionFilesResult = ((Response.CommandResponse)showVersionFilesResponse).Result; + if (showVersionFilesResult != null && showVersionFilesResult.Count > 0) + { + string line1; + line1 = (string)showVersionFilesResult[0]; + if (line1 != null && line1.StartsWith("File")) + return AsteriskVersion.ASTERISK_1_2; + } + } + return AsteriskVersion.ASTERISK_1_0; + } - #endregion + #endregion - #region connect() - protected internal bool connect() - { - bool result = false; - bool startReader = false; + #region connect() + protected internal bool connect() + { + bool result = false; + bool startReader = false; - lock (lockSocket) - { - if (mrSocket == null) - { + lock (lockSocket) + { + if (mrSocket == null) + { #if LOGGER - logger.Info("Connecting to {0}:{1}", hostname, port); + logger.Info("Connecting to {0}:{1}", hostname, port); #endif - try - { - mrSocket = new SocketConnection(hostname, port, socketEncoding); - result = mrSocket.IsConnected; - } + try + { + mrSocket = new SocketConnection(hostname, port, socketEncoding); + result = mrSocket.IsConnected; + } #if LOGGER - catch (Exception ex) - { - logger.Info("Connect - Exception : {0}", ex.Message); + catch (Exception ex) + { + logger.Info("Connect - Exception : {0}", ex.Message); #else catch { #endif - result = false; - } + result = false; + } if (result) { if (mrReader == null) @@ -1682,862 +1033,868 @@ namespace AsterNET.Manager { mrSocket = null; } - } - } + } + } if (startReader) { mrReaderThread.Start(); } - return IsConnected(); - } - #endregion + return IsConnected(); + } + #endregion - #region disconnect() - /// Closes the socket connection. - private void disconnect(bool withDie) - { - lock (lockSocket) - { - if (withDie) - { - reconnectEnable = false; - reconnected = false; - enableEvents = true; - } + #region disconnect() + /// Closes the socket connection. + private void disconnect(bool withDie) + { + lock (lockSocket) + { + if (withDie) + { + reconnectEnable = false; + reconnected = false; + enableEvents = true; + } - if (mrReader != null) - { - if (withDie) - { - mrReader.Die = true; - mrReader = null; - } - else - mrReader.Socket = null; - } + if (mrReader != null) + { + if (withDie) + { + mrReader.Die = true; + mrReader = null; + } + else + mrReader.Socket = null; + } - if (this.mrSocket != null) - { - mrSocket.Close(); - mrSocket = null; - } + if (this.mrSocket != null) + { + mrSocket.Close(); + mrSocket = null; + } - responseEventHandlers.Clear(); - responseHandlers.Clear(); - pingHandlers.Clear(); - } - } - #endregion + responseEventHandlers.Clear(); + responseHandlers.Clear(); + pingHandlers.Clear(); + } + } + #endregion - #region reconnect(bool init) - /// - /// Reconnects to the asterisk server when the connection is lost.
- /// While keepAlive is true we will try to reconnect. - /// Reconnection attempts will be stopped when the logoff() method - /// is called or when the login after a successful reconnect results in an - /// AuthenticationFailedException suggesting that the manager - /// credentials have changed and keepAliveAfterAuthenticationFailure is not set.
- /// This method is called when a DisconnectEvent is received from the reader. - ///
- private void reconnect(bool init) - { + #region reconnect(bool init) + /// + /// Reconnects to the asterisk server when the connection is lost.
+ /// While keepAlive is true we will try to reconnect. + /// Reconnection attempts will be stopped when the logoff() method + /// is called or when the login after a successful reconnect results in an + /// AuthenticationFailedException suggesting that the manager + /// credentials have changed and keepAliveAfterAuthenticationFailure is not set.
+ /// This method is called when a DisconnectEvent is received from the reader. + ///
+ private void reconnect(bool init) + { #if LOGGER - logger.Warning("reconnect (init: {0}), reconnectCount:{1}", init, reconnectCount); + logger.Warning("reconnect (init: {0}), reconnectCount:{1}", init, reconnectCount); #endif - if (init) - reconnectCount = 0; - else if (reconnectCount++ > reconnectRetryMax) - reconnectEnable = false; + if (init) + reconnectCount = 0; + else if (reconnectCount++ > reconnectRetryMax) + reconnectEnable = false; - if (reconnectEnable) - { + if (reconnectEnable) + { #if LOGGER - logger.Warning("Try reconnect."); + logger.Warning("Try reconnect."); #endif - enableEvents = false; - reconnected = true; - disconnect(false); + enableEvents = false; + reconnected = true; + disconnect(false); - int retryCount = 0; - while (reconnectEnable && !mrReader.Die) - { - if (retryCount >= reconnectRetryMax) - reconnectEnable = false; - else - { - try - { - if (retryCount < reconnectRetryFast) - { - // Try to reconnect quite fast for the first times - // this succeeds if the server has just been restarted + int retryCount = 0; + while (reconnectEnable && !mrReader.Die) + { + if (retryCount >= reconnectRetryMax) + reconnectEnable = false; + else + { + try + { + if (retryCount < reconnectRetryFast) + { + // Try to reconnect quite fast for the first times + // this succeeds if the server has just been restarted #if LOGGER - logger.Info("Reconnect delay : {0}, retry : {1}", reconnectIntervalFast, retryCount); + logger.Info("Reconnect delay : {0}, retry : {1}", reconnectIntervalFast, retryCount); #endif - Thread.Sleep(reconnectIntervalFast); - } - else - { - // slow down after unsuccessful attempts assuming a shutdown of the server + Thread.Sleep(reconnectIntervalFast); + } + else + { + // slow down after unsuccessful attempts assuming a shutdown of the server #if LOGGER - logger.Info("Reconnect delay : {0}, retry : {1}", reconnectIntervalMax, retryCount); + logger.Info("Reconnect delay : {0}, retry : {1}", reconnectIntervalMax, retryCount); #endif - Thread.Sleep(reconnectIntervalMax); - } - } - catch (ThreadInterruptedException) - { - continue; - } + Thread.Sleep(reconnectIntervalMax); + } + } + catch (ThreadInterruptedException) + { + continue; + } #if LOGGER - catch (Exception ex) - { - logger.Info("Reconnect delay exception : ", ex.Message); + catch (Exception ex) + { + logger.Info("Reconnect delay exception : ", ex.Message); #else catch { #endif - continue; - } + continue; + } - try - { + try + { #if LOGGER - logger.Info("Try connect."); + logger.Info("Try connect."); #endif - if (connect()) - break; - } + if (connect()) + break; + } #if LOGGER - catch(Exception ex) - { - logger.Info("Connect exception : ", ex.Message); + catch (Exception ex) + { + logger.Info("Connect exception : ", ex.Message); #else catch { #endif - } - retryCount++; - } - } - } + } + retryCount++; + } + } + } - if (!reconnectEnable) - { + if (!reconnectEnable) + { #if LOGGER - logger.Info("Can't reconnect."); + logger.Info("Can't reconnect."); #endif - enableEvents = true; - reconnected = false; - disconnect(true); - fireEvent(new DisconnectEvent(this)); - } - } - #endregion + enableEvents = true; + reconnected = false; + disconnect(true); + fireEvent(new DisconnectEvent(this)); + } + } + #endregion - #region createInternalActionId() - /// - /// Creates a new unique internal action id based on the hash code of this connection and a sequence. - /// - private string createInternalActionId() - { - return this.GetHashCode() + "_" + (this.actionIdCount++); - } - #endregion + #region createInternalActionId() + /// + /// Creates a new unique internal action id based on the hash code of this connection and a sequence. + /// + private string createInternalActionId() + { + return this.GetHashCode() + "_" + (this.actionIdCount++); + } + #endregion - #region Login() - /// - /// Logs in to the Asterisk manager using asterisk's MD5 based - /// challenge/response protocol. The login is delayed until the protocol - /// identifier has been received by the reader. - /// - /// AuthenticationFailedException if the username and/or password are incorrect - /// TimeoutException if no response is received within the specified timeout period - /// - /// - public void Login() - { - login(defaultResponseTimeout); - } - /// - /// Log in to the Asterisk manager using asterisk's MD5 based - /// challenge/response protocol. The login is delayed until the protocol - /// identifier has been received by the reader. - /// - /// Timeout in milliseconds to login. - public void Login(int timeout) - { - login(timeout); - } - #endregion + #region Login() + /// + /// Logs in to the Asterisk manager using asterisk's MD5 based + /// challenge/response protocol. The login is delayed until the protocol + /// identifier has been received by the reader. + /// + /// AuthenticationFailedException if the username and/or password are incorrect + /// TimeoutException if no response is received within the specified timeout period + /// + /// + public void Login() + { + login(defaultResponseTimeout); + } + /// + /// Log in to the Asterisk manager using asterisk's MD5 based + /// challenge/response protocol. The login is delayed until the protocol + /// identifier has been received by the reader. + /// + /// Timeout in milliseconds to login. + public void Login(int timeout) + { + login(timeout); + } + #endregion - #region IsConnected() - /// Returns true if there is a socket connection to the - /// asterisk server, false otherwise. - /// - /// - /// true if there is a socket connection to the - /// asterisk server, false otherwise. - /// - public bool IsConnected() - { - bool result = false; - lock (lockSocket) - result = mrSocket != null && mrSocket.IsConnected; - return result; - } - #endregion + #region IsConnected() + /// Returns true if there is a socket connection to the + /// asterisk server, false otherwise. + /// + /// + /// true if there is a socket connection to the + /// asterisk server, false otherwise. + /// + public bool IsConnected() + { + bool result = false; + lock (lockSocket) + result = mrSocket != null && mrSocket.IsConnected; + return result; + } + #endregion - #region Logoff() - /// - /// Sends a LogoffAction and disconnects from the server. - /// - public void Logoff() - { - lock (lockSocket) - { - // stop reconnecting when we got disconnected - reconnectEnable = false; - if (mrReader != null && mrSocket != null) - try - { - mrReader.IsLogoff = true; - SendAction(new Action.LogoffAction()); - } - catch - { } - } - disconnect(true); - } - #endregion + #region Logoff() + /// + /// Sends a LogoffAction and disconnects from the server. + /// + public void Logoff() + { + lock (lockSocket) + { + // stop reconnecting when we got disconnected + reconnectEnable = false; + if (mrReader != null && mrSocket != null) + try + { + mrReader.IsLogoff = true; + SendAction(new Action.LogoffAction()); + } + catch + { } + } + disconnect(true); + } + #endregion - #region SendAction(action) - /// - /// Send Action with default timeout. - /// - /// - /// - public Response.ManagerResponse SendAction(Action.ManagerAction action) - { - return SendAction(action, defaultResponseTimeout); - } - #endregion + #region SendAction(action) + /// + /// Send Action with default timeout. + /// + /// + /// + public Response.ManagerResponse SendAction(Action.ManagerAction action) + { + return SendAction(action, defaultResponseTimeout); + } + #endregion - #region SendAction(action, timeout) - /// - /// Send action ans with timeout (milliseconds) - /// - /// action to send - /// timeout in milliseconds - /// - public Response.ManagerResponse SendAction(ManagerAction action, int timeOut) - { - AutoResetEvent autoEvent = new AutoResetEvent(false); - ResponseHandler handler = new ResponseHandler(action, autoEvent); + #region SendAction(action, timeout) + /// + /// Send action ans with timeout (milliseconds) + /// + /// action to send + /// timeout in milliseconds + /// + public Response.ManagerResponse SendAction(ManagerAction action, int timeOut) + { + AutoResetEvent autoEvent = new AutoResetEvent(false); + ResponseHandler handler = new ResponseHandler(action, autoEvent); - int hash = SendAction(action, handler); - bool result = autoEvent.WaitOne(timeOut <= 0 ? -1 : timeOut, true); + int hash = SendAction(action, handler); + bool result = autoEvent.WaitOne(timeOut <= 0 ? -1 : timeOut, true); - RemoveResponseHandler(handler); + RemoveResponseHandler(handler); - if (result) - return handler.Response; - throw new TimeoutException("Timeout waiting for response to " + action.Action); - } - #endregion + if (result) + return handler.Response; + throw new TimeoutException("Timeout waiting for response to " + action.Action); + } + #endregion - #region SendAction(action, responseHandler) - public int SendAction(ManagerAction action, ResponseHandler responseHandler) - { - if (action == null) - throw new ArgumentException("Unable to send action: action is null."); + #region SendAction(action, responseHandler) + public int SendAction(ManagerAction action, ResponseHandler responseHandler) + { + if (action == null) + throw new ArgumentException("Unable to send action: action is null."); - if (mrSocket == null) - throw new SystemException("Unable to send " + action.Action + " action: not connected."); + if (mrSocket == null) + throw new SystemException("Unable to send " + action.Action + " action: not connected."); - // if the responseHandler is null the user is obviously not interested in the response, thats fine. - string internalActionId = string.Empty; - if (responseHandler != null) - { - internalActionId = createInternalActionId(); - responseHandler.Hash = internalActionId.GetHashCode(); - AddResponseHandler(responseHandler); - } + // if the responseHandler is null the user is obviously not interested in the response, thats fine. + string internalActionId = string.Empty; + if (responseHandler != null) + { + internalActionId = createInternalActionId(); + responseHandler.Hash = internalActionId.GetHashCode(); + AddResponseHandler(responseHandler); + } - SendToAsterisk(action, internalActionId); + SendToAsterisk(action, internalActionId); - return responseHandler != null ? responseHandler.Hash : 0; - } - #endregion + return responseHandler != null ? responseHandler.Hash : 0; + } + #endregion - #region SendEventGeneratingAction(action) - public ResponseEvents SendEventGeneratingAction(ManagerActionEvent action) - { - return SendEventGeneratingAction(action, defaultEventTimeout); - } - #endregion + #region SendEventGeneratingAction(action) + public ResponseEvents SendEventGeneratingAction(ManagerActionEvent action) + { + return SendEventGeneratingAction(action, defaultEventTimeout); + } + #endregion - #region SendEventGeneratingAction(action, timeout) - /// - /// - /// - /// - /// wait timeout in milliseconds - /// - public ResponseEvents SendEventGeneratingAction(ManagerActionEvent action, int timeout) - { - if (action == null) - throw new ArgumentException("Unable to send action: action is null."); - else if (action.ActionCompleteEventClass() == null) - throw new ArgumentException("Unable to send action: ActionCompleteEventClass is null."); - else if (!typeof(ResponseEvent).IsAssignableFrom(action.ActionCompleteEventClass())) - throw new ArgumentException("Unable to send action: ActionCompleteEventClass is not a ResponseEvent."); + #region SendEventGeneratingAction(action, timeout) + /// + /// + /// + /// + /// wait timeout in milliseconds + /// + public ResponseEvents SendEventGeneratingAction(ManagerActionEvent action, int timeout) + { + if (action == null) + throw new ArgumentException("Unable to send action: action is null."); + else if (action.ActionCompleteEventClass() == null) + throw new ArgumentException("Unable to send action: ActionCompleteEventClass is null."); + else if (!typeof(ResponseEvent).IsAssignableFrom(action.ActionCompleteEventClass())) + throw new ArgumentException("Unable to send action: ActionCompleteEventClass is not a ResponseEvent."); - if (mrSocket == null) - throw new SystemException("Unable to send " + action.Action + " action: not connected."); + if (mrSocket == null) + throw new SystemException("Unable to send " + action.Action + " action: not connected."); - AutoResetEvent autoEvent = new AutoResetEvent(false); - ResponseEventHandler handler = new ResponseEventHandler(this, action, autoEvent); + AutoResetEvent autoEvent = new AutoResetEvent(false); + ResponseEventHandler handler = new ResponseEventHandler(this, action, autoEvent); - string internalActionId = createInternalActionId(); - handler.Hash = internalActionId.GetHashCode(); - AddResponseHandler(handler); - AddResponseEventHandler(handler); + string internalActionId = createInternalActionId(); + handler.Hash = internalActionId.GetHashCode(); + AddResponseHandler(handler); + AddResponseEventHandler(handler); - SendToAsterisk(action, internalActionId); + SendToAsterisk(action, internalActionId); - bool result = autoEvent.WaitOne(timeout <= 0 ? -1 : timeout, true); + bool result = autoEvent.WaitOne(timeout <= 0 ? -1 : timeout, true); - RemoveResponseHandler(handler); - RemoveResponseEventHandler(handler); + RemoveResponseHandler(handler); + RemoveResponseEventHandler(handler); - if (result) - return handler.ResponseEvents; + if (result) + return handler.ResponseEvents; - throw new EventTimeoutException("Timeout waiting for response or response events to " + action.Action, handler.ResponseEvents); - } - #endregion + throw new EventTimeoutException("Timeout waiting for response or response events to " + action.Action, handler.ResponseEvents); + } + #endregion - #region Response Handler helpers - private void AddResponseHandler(IResponseHandler handler) - { - lock (lockHandlers) - { - if (handler.Action is PingAction) - pingHandlers[handler.Hash] = handler; - else - responseHandlers[handler.Hash] = handler; - } - } + #region Response Handler helpers + private void AddResponseHandler(IResponseHandler handler) + { + lock (lockHandlers) + { + if (handler.Action is PingAction) + pingHandlers[handler.Hash] = handler; + else + responseHandlers[handler.Hash] = handler; + } + } - private void AddResponseEventHandler(IResponseHandler handler) - { - lock (lockHandlers) - responseEventHandlers[handler.Hash] = handler; - } + private void AddResponseEventHandler(IResponseHandler handler) + { + lock (lockHandlers) + responseEventHandlers[handler.Hash] = handler; + } - internal void RemoveResponseHandler(IResponseHandler handler) - { - int hash = handler.Hash; - if (hash != 0) - lock (lockHandlers) - if (responseHandlers.ContainsKey(hash)) - responseHandlers.Remove(hash); - } + internal void RemoveResponseHandler(IResponseHandler handler) + { + int hash = handler.Hash; + if (hash != 0) + lock (lockHandlers) + if (responseHandlers.ContainsKey(hash)) + responseHandlers.Remove(hash); + } - internal void RemoveResponseEventHandler(IResponseHandler handler) - { - int hash = handler.Hash; - if (hash != 0) - lock (lockHandlers) - if (responseEventHandlers.ContainsKey(hash)) - responseEventHandlers.Remove(hash); - } + internal void RemoveResponseEventHandler(IResponseHandler handler) + { + int hash = handler.Hash; + if (hash != 0) + lock (lockHandlers) + if (responseEventHandlers.ContainsKey(hash)) + responseEventHandlers.Remove(hash); + } - private IResponseHandler GetRemoveResponseHandler(int hash) - { - IResponseHandler handler = null; - if (hash != 0) - lock (lockHandlers) - if (responseHandlers.ContainsKey(hash)) - { - handler = responseHandlers[hash]; - responseHandlers.Remove(hash); - } - return handler; - } + private IResponseHandler GetRemoveResponseHandler(int hash) + { + IResponseHandler handler = null; + if (hash != 0) + lock (lockHandlers) + if (responseHandlers.ContainsKey(hash)) + { + handler = responseHandlers[hash]; + responseHandlers.Remove(hash); + } + return handler; + } - private IResponseHandler GetRemoveResponseEventHandler(int hash) - { - IResponseHandler handler = null; - if (hash != 0) - lock (lockHandlers) - if (responseEventHandlers.ContainsKey(hash)) - { - handler = responseEventHandlers[hash]; - responseEventHandlers.Remove(hash); - } - return handler; - } + private IResponseHandler GetRemoveResponseEventHandler(int hash) + { + IResponseHandler handler = null; + if (hash != 0) + lock (lockHandlers) + if (responseEventHandlers.ContainsKey(hash)) + { + handler = responseEventHandlers[hash]; + responseEventHandlers.Remove(hash); + } + return handler; + } - private IResponseHandler GetResponseHandler(int hash) - { - IResponseHandler handler = null; - if (hash != 0) - lock (lockHandlers) - if (responseHandlers.ContainsKey(hash)) - handler = responseHandlers[hash]; - return handler; - } + private IResponseHandler GetResponseHandler(int hash) + { + IResponseHandler handler = null; + if (hash != 0) + lock (lockHandlers) + if (responseHandlers.ContainsKey(hash)) + handler = responseHandlers[hash]; + return handler; + } - private IResponseHandler GetResponseEventHandler(int hash) - { - IResponseHandler handler = null; - if (hash != 0) - lock (lockHandlers) - if (responseEventHandlers.ContainsKey(hash)) - handler = responseEventHandlers[hash]; - return handler; - } - #endregion + private IResponseHandler GetResponseEventHandler(int hash) + { + IResponseHandler handler = null; + if (hash != 0) + lock (lockHandlers) + if (responseEventHandlers.ContainsKey(hash)) + handler = responseEventHandlers[hash]; + return handler; + } + #endregion - #region SendToAsterisk(ManagerAction action, string internalActionId) + #region SendToAsterisk(ManagerAction action, string internalActionId) - internal void SendToAsterisk(ManagerAction action, string internalActionId) - { - if (mrSocket == null) - throw new SystemException("Unable to send action: socket is null"); + internal void SendToAsterisk(ManagerAction action, string internalActionId) + { + if (mrSocket == null) + throw new SystemException("Unable to send action: socket is null"); - string buffer = BuildAction(action, internalActionId); + string buffer = BuildAction(action, internalActionId); #if LOGGER - logger.Debug("Sent action : '{0}' : {1}", internalActionId, action); + logger.Debug("Sent action : '{0}' : {1}", internalActionId, action); #endif - if (sa == null) - sa = new SendToAsteriskDelegate(sendToAsterisk); - sa.Invoke(buffer); - } + if (sa == null) + sa = new SendToAsteriskDelegate(sendToAsterisk); + sa.Invoke(buffer); + } - private delegate void SendToAsteriskDelegate(string buffer); - private SendToAsteriskDelegate sa = null; + private delegate void SendToAsteriskDelegate(string buffer); + private SendToAsteriskDelegate sa = null; - private void sendToAsterisk(string buffer) - { - mrSocket.Write(buffer); - } + private void sendToAsterisk(string buffer) + { + mrSocket.Write(buffer); + } - #endregion + #endregion - #region BuildAction(action) - public string BuildAction(Action.ManagerAction action) - { - return BuildAction(action, null); - } - #endregion + #region BuildAction(action) + public string BuildAction(Action.ManagerAction action) + { + return BuildAction(action, null); + } + #endregion - #region BuildAction(action, internalActionId) - public string BuildAction(ManagerAction action, string internalActionId) - { - MethodInfo getter; - object value; - StringBuilder sb = new StringBuilder(); - string valueAsString = string.Empty; + #region BuildAction(action, internalActionId) + public string BuildAction(ManagerAction action, string internalActionId) + { + MethodInfo getter; + object value; + StringBuilder sb = new StringBuilder(); + string valueAsString = string.Empty; - if (typeof(Action.ProxyAction).IsAssignableFrom(action.GetType())) - sb.Append(string.Concat("ProxyAction: ", action.Action, Common.LINE_SEPARATOR)); - else - sb.Append(string.Concat("Action: ", action.Action, Common.LINE_SEPARATOR)); + if (typeof(Action.ProxyAction).IsAssignableFrom(action.GetType())) + sb.Append(string.Concat("ProxyAction: ", action.Action, Common.LINE_SEPARATOR)); + else + sb.Append(string.Concat("Action: ", action.Action, Common.LINE_SEPARATOR)); - if (string.IsNullOrEmpty(internalActionId)) - valueAsString = action.ActionId; - else - valueAsString = string.Concat(internalActionId, Common.INTERNAL_ACTION_ID_DELIMITER, action.ActionId); + if (string.IsNullOrEmpty(internalActionId)) + valueAsString = action.ActionId; + else + valueAsString = string.Concat(internalActionId, Common.INTERNAL_ACTION_ID_DELIMITER, action.ActionId); - if (!string.IsNullOrEmpty(valueAsString)) - sb.Append(string.Concat("ActionID: ", valueAsString, Common.LINE_SEPARATOR)); + if (!string.IsNullOrEmpty(valueAsString)) + sb.Append(string.Concat("ActionID: ", valueAsString, Common.LINE_SEPARATOR)); - Dictionary getters = Helper.GetGetters(action.GetType()); + Dictionary getters = Helper.GetGetters(action.GetType()); - foreach (string name in getters.Keys) - { - string nameLower = name.ToLower(Helper.CultureInfo); - if (nameLower == "class" || nameLower == "action" || nameLower == "actionid") - continue; + foreach (string name in getters.Keys) + { + string nameLower = name.ToLower(Helper.CultureInfo); + if (nameLower == "class" || nameLower == "action" || nameLower == "actionid") + continue; - getter = getters[name]; - Type propType = getter.ReturnType; - if (!(propType == typeof(string) - || propType == typeof(bool) - || propType == typeof(double) - || propType == typeof(DateTime) - || propType == typeof(int) - || propType == typeof(long) - || propType == typeof(Dictionary) - ) - ) - continue; + getter = getters[name]; + Type propType = getter.ReturnType; + if (!(propType == typeof(string) + || propType == typeof(bool) + || propType == typeof(double) + || propType == typeof(DateTime) + || propType == typeof(int) + || propType == typeof(long) + || propType == typeof(Dictionary) + ) + ) + continue; - try - { - value = getter.Invoke(action, new object[] { }); - } - catch (UnauthorizedAccessException ex) - { + try + { + value = getter.Invoke(action, new object[] { }); + } + catch (UnauthorizedAccessException ex) + { #if LOGGER - logger.Error("Unable to retrieve property '" + name + "' of " + action.GetType(), ex); - continue; + logger.Error("Unable to retrieve property '" + name + "' of " + action.GetType(), ex); + continue; #else throw new ManagerException("Unable to retrieve property '" + name + "' of " + action.GetType(), ex); #endif - } - catch (TargetInvocationException ex) - { + } + catch (TargetInvocationException ex) + { #if LOGGER - logger.Error("Unable to retrieve property '" + name + "' of " + action.GetType(), ex); - continue; + logger.Error("Unable to retrieve property '" + name + "' of " + action.GetType(), ex); + continue; #else throw new ManagerException("Unable to retrieve property '" + name + "' of " + action.GetType(), ex); #endif - } + } - if (value == null) - continue; - if (value is string) - { - valueAsString = (string)value; - if (valueAsString.Length == 0) - continue; - } - else if (value is bool) - valueAsString = ((bool)value ? "true" : "false"); - else if (value is DateTime) - valueAsString = value.ToString(); - else if (value is IDictionary) - { - valueAsString = Helper.JoinVariables((IDictionary)value, Common.LINE_SEPARATOR, ": "); - if (valueAsString.Length == 0) - continue; - sb.Append(valueAsString); - sb.Append(Common.LINE_SEPARATOR); - continue; - } - else - valueAsString = value.ToString(); + if (value == null) + continue; + if (value is string) + { + valueAsString = (string)value; + if (valueAsString.Length == 0) + continue; + } + else if (value is bool) + valueAsString = ((bool)value ? "true" : "false"); + else if (value is DateTime) + valueAsString = value.ToString(); + else if (value is IDictionary) + { + valueAsString = Helper.JoinVariables((IDictionary)value, Common.LINE_SEPARATOR, ": "); + if (valueAsString.Length == 0) + continue; + sb.Append(valueAsString); + sb.Append(Common.LINE_SEPARATOR); + continue; + } + else + valueAsString = value.ToString(); - sb.Append(string.Concat(name, ": ", valueAsString, Common.LINE_SEPARATOR)); - } + sb.Append(string.Concat(name, ": ", valueAsString, Common.LINE_SEPARATOR)); + } IActionVariable actionVar = action as IActionVariable; - if ( actionVar != null ) + if (actionVar != null) { var variables = actionVar.GetVariables(); - if ( variables != null && variables.Count > 0 ) + if (variables != null && variables.Count > 0) { - sb.Append( string.Concat( "Variable: ", Helper.JoinVariables( actionVar.GetVariables(), VAR_DELIMITER, "=" ), Common.LINE_SEPARATOR ) ); + sb.Append(string.Concat("Variable: ", Helper.JoinVariables(actionVar.GetVariables(), VAR_DELIMITER, "="), Common.LINE_SEPARATOR)); } } sb.Append(Common.LINE_SEPARATOR); - return sb.ToString(); - } - #endregion + return sb.ToString(); + } + #endregion - #region GetProtocolIdentifier() - public string GetProtocolIdentifier() - { - return this.protocolIdentifier; - } - #endregion + #region GetProtocolIdentifier() + public string GetProtocolIdentifier() + { + return this.protocolIdentifier; + } + #endregion - #region RegisterUserEventClass(class) - /// - /// Register User Event Class - /// - /// - public void RegisterUserEventClass(Type userEventClass) - { - Helper.RegisterEventClass(registeredEventClasses, userEventClass); - } - #endregion + #region RegisterUserEventClass(class) + /// + /// Register User Event Class + /// + /// + public void RegisterUserEventClass(Type userEventClass) + { + Helper.RegisterEventClass(registeredEventClasses, userEventClass); + } + #endregion - #region DispatchResponse(response) - /// - /// This method is called by the reader whenever a ManagerResponse is - /// received. The response is dispatched to the associated ManagerResponseHandler. - /// - /// the response received by the reader - /// - internal void DispatchResponse(Dictionary buffer) - { + #region DispatchResponse(response) + /// + /// This method is called by the reader whenever a ManagerResponse is + /// received. The response is dispatched to the associated ManagerResponseHandler. + /// + /// the response received by the reader + /// + internal void DispatchResponse(Dictionary buffer) + { #if LOGGER - logger.Debug("Dispatch response packet : {0}", Helper.JoinVariables(buffer, ", ", ": ")); + logger.Debug("Dispatch response packet : {0}", Helper.JoinVariables(buffer, ", ", ": ")); #endif - DispatchResponse(buffer, null); - } + DispatchResponse(buffer, null); + } - internal void DispatchResponse(ManagerResponse response) - { + internal void DispatchResponse(ManagerResponse response) + { #if LOGGER - logger.Debug("Dispatch response : {0}", response); + logger.Debug("Dispatch response : {0}", response); #endif - DispatchResponse(null, response); - } + DispatchResponse(null, response); + } - internal void DispatchResponse(Dictionary buffer, ManagerResponse response) - { - string responseActionId = string.Empty; - string actionId = string.Empty; - IResponseHandler responseHandler = null; + internal void DispatchResponse(Dictionary buffer, ManagerResponse response) + { + string responseActionId = string.Empty; + string actionId = string.Empty; + IResponseHandler responseHandler = null; - if (buffer != null) - { - if (buffer["response"].ToLower(Helper.CultureInfo) == "error") - response = new ManagerError(buffer); - else if (buffer.ContainsKey("actionid")) - actionId = buffer["actionid"]; - } + if (buffer != null) + { + if (buffer["response"].ToLower(Helper.CultureInfo) == "error") + response = new ManagerError(buffer); + else if (buffer.ContainsKey("actionid")) + actionId = buffer["actionid"]; + } - if (response != null) - actionId = response.ActionId; + if (response != null) + actionId = response.ActionId; - if (!string.IsNullOrEmpty(actionId)) - { - int hash = Helper.GetInternalActionId(actionId).GetHashCode(); - responseActionId = Helper.StripInternalActionId(actionId); - responseHandler = GetRemoveResponseHandler(hash); + if (!string.IsNullOrEmpty(actionId)) + { + int hash = Helper.GetInternalActionId(actionId).GetHashCode(); + responseActionId = Helper.StripInternalActionId(actionId); + responseHandler = GetRemoveResponseHandler(hash); - if (response != null) - response.ActionId = responseActionId; - if (responseHandler != null) - { - if (response == null) - { - ManagerActionResponse action = responseHandler.Action as ManagerActionResponse; - if (action == null || (response = action.ActionCompleteResponseClass() as ManagerResponse) == null) - response = Helper.BuildResponse(buffer); - else - Helper.SetAttributes(response, buffer); - response.ActionId = responseActionId; - } + if (response != null) + response.ActionId = responseActionId; + if (responseHandler != null) + { + if (response == null) + { + ManagerActionResponse action = responseHandler.Action as ManagerActionResponse; + if (action == null || (response = action.ActionCompleteResponseClass() as ManagerResponse) == null) + response = Helper.BuildResponse(buffer); + else + Helper.SetAttributes(response, buffer); + response.ActionId = responseActionId; + } - try - { - responseHandler.HandleResponse(response); - } - catch (Exception ex) - { + try + { + responseHandler.HandleResponse(response); + } + catch (Exception ex) + { #if LOGGER - logger.Error("Unexpected exception in responseHandler {0}\n{1}", response, ex); + logger.Error("Unexpected exception in responseHandler {0}\n{1}", response, ex); #else throw new ManagerException("Unexpected exception in responseHandler " + responseHandler.GetType().FullName, ex); #endif - } - } - } - - if (response == null && buffer.ContainsKey("ping") && buffer["ping"] == "Pong") - { - response = Helper.BuildResponse(buffer); - foreach (ResponseHandler pingHandler in pingHandlers.Values) - pingHandler.HandleResponse(response); - pingHandlers.Clear(); - } + } + } + } - if (!reconnected) - return; + if (response == null && buffer.ContainsKey("ping") && buffer["ping"] == "Pong") + { + response = Helper.BuildResponse(buffer); + foreach (ResponseHandler pingHandler in pingHandlers.Values) + pingHandler.HandleResponse(response); + pingHandlers.Clear(); + } - if (response == null) - { - response = Helper.BuildResponse(buffer); - response.ActionId = responseActionId; - } + if (!reconnected) + return; + + if (response == null) + { + response = Helper.BuildResponse(buffer); + response.ActionId = responseActionId; + } #if LOGGER - logger.Info("Reconnected - DispatchEvent : " + response); + logger.Info("Reconnected - DispatchEvent : " + response); #endif - #region Support background reconnect - if (response is ChallengeResponse) - { - string key = null; - if (response.IsSuccess()) - { - ChallengeResponse challengeResponse = (ChallengeResponse)response; - string challenge = challengeResponse.Challenge; - try - { - Util.MD5Support md = Util.MD5Support.GetInstance(); - if (challenge != null) - md.Update(UTF8Encoding.UTF8.GetBytes(challenge)); - if (password != null) - md.Update(UTF8Encoding.UTF8.GetBytes(password)); - key = Helper.ToHexString(md.DigestData); - } + #region Support background reconnect + if (response is ChallengeResponse) + { + string key = null; + if (response.IsSuccess()) + { + ChallengeResponse challengeResponse = (ChallengeResponse)response; + string challenge = challengeResponse.Challenge; + try + { + Util.MD5Support md = Util.MD5Support.GetInstance(); + if (challenge != null) + md.Update(UTF8Encoding.UTF8.GetBytes(challenge)); + if (password != null) + md.Update(UTF8Encoding.UTF8.GetBytes(password)); + key = Helper.ToHexString(md.DigestData); + } #if LOGGER - catch (Exception ex) - { - logger.Error("Unable to create login key using MD5 Message Digest", ex); + catch (Exception ex) + { + logger.Error("Unable to create login key using MD5 Message Digest", ex); #else catch { #endif - key = null; - } - } - bool fail = true; - if (!string.IsNullOrEmpty(key)) - try - { - Action.LoginAction loginAction = new Action.LoginAction(username, "MD5", key); - SendAction(loginAction, null); - fail = false; - } - catch { } - if (fail) - if (keepAliveAfterAuthenticationFailure) - reconnect(true); - else - disconnect(true); - } - else if (response is ManagerError) - { - if (keepAliveAfterAuthenticationFailure) - reconnect(true); - else - disconnect(true); - } - else if (response is ManagerResponse) - { - if (response.IsSuccess()) - { - reconnected = false; - enableEvents = true; - reconnectEnable = keepAlive; - ConnectEvent ce = new ConnectEvent(this); - ce.Reconnect = true; - ce.ProtocolIdentifier = protocolIdentifier; - fireEvent(ce); - } - else if (keepAliveAfterAuthenticationFailure) - reconnect(true); - else - disconnect(true); - } - #endregion - } - #endregion + key = null; + } + } + bool fail = true; + if (!string.IsNullOrEmpty(key)) + try + { + Action.LoginAction loginAction = new Action.LoginAction(username, "MD5", key); + SendAction(loginAction, null); + fail = false; + } + catch { } + if (fail) + if (keepAliveAfterAuthenticationFailure) + reconnect(true); + else + disconnect(true); + } + else if (response is ManagerError) + { + if (keepAliveAfterAuthenticationFailure) + reconnect(true); + else + disconnect(true); + } + else if (response is ManagerResponse) + { + if (response.IsSuccess()) + { + reconnected = false; + enableEvents = true; + reconnectEnable = keepAlive; + ConnectEvent ce = new ConnectEvent(this); + ce.Reconnect = true; + ce.ProtocolIdentifier = protocolIdentifier; + fireEvent(ce); + } + else if (keepAliveAfterAuthenticationFailure) + reconnect(true); + else + disconnect(true); + } + #endregion + } + #endregion - #region DispatchEvent(...) - /// - /// This method is called by the reader whenever a ManagerEvent is received. - /// The event is dispatched to all registered ManagerEventHandlers. - /// - /// the event received by the reader - /// - internal void DispatchEvent(Dictionary buffer) - { - ManagerEvent e = Helper.BuildEvent(registeredEventClasses, this, buffer); - DispatchEvent(e); - } + #region DispatchEvent(...) + /// + /// This method is called by the reader whenever a ManagerEvent is received. + /// The event is dispatched to all registered ManagerEventHandlers. + /// + /// the event received by the reader + /// + internal void DispatchEvent(Dictionary buffer) + { + ManagerEvent e = Helper.BuildEvent(registeredEventClasses, this, buffer); + DispatchEvent(e); + } - internal void DispatchEvent(ManagerEvent e) - { + internal void DispatchEvent(ManagerEvent e) + { #if LOGGER - logger.Debug("Dispatching event: {0}", e); + logger.Debug("Dispatching event: {0}", e); #endif - if (e is ResponseEvent) - { - ResponseEvent responseEvent = (ResponseEvent)e; - if (!string.IsNullOrEmpty(responseEvent.ActionId) && !string.IsNullOrEmpty(responseEvent.InternalActionId)) - { - ResponseEventHandler eventHandler = (ResponseEventHandler)GetResponseEventHandler(responseEvent.InternalActionId.GetHashCode()); - if (eventHandler != null) - try - { - eventHandler.HandleEvent(e); - } - catch (SystemException ex) - { + if (e is ResponseEvent) + { + ResponseEvent responseEvent = (ResponseEvent)e; + if (!string.IsNullOrEmpty(responseEvent.ActionId) && !string.IsNullOrEmpty(responseEvent.InternalActionId)) + { + ResponseEventHandler eventHandler = (ResponseEventHandler)GetResponseEventHandler(responseEvent.InternalActionId.GetHashCode()); + if (eventHandler != null) + try + { + eventHandler.HandleEvent(e); + } + catch (SystemException ex) + { #if LOGGER - logger.Error("Unexpected exception", ex); + logger.Error("Unexpected exception", ex); #else throw ex; #endif - } - } - } + } + } + } - #region ConnectEvent - if (e is ConnectEvent) - { - string protocol = ((ConnectEvent)e).ProtocolIdentifier; + #region ConnectEvent + if (e is ConnectEvent) + { + string protocol = ((ConnectEvent)e).ProtocolIdentifier; #if LOGGER - logger.Info("Connected via {0}", protocol); + logger.Info("Connected via {0}", protocol); #endif - if (!string.IsNullOrEmpty(protocol) && protocol.StartsWith("Asterisk Call Manager")) - { - this.protocolIdentifier = protocol; - } - else - { - this.protocolIdentifier = (string.IsNullOrEmpty(protocol) ? "Empty" : protocol); + if (!string.IsNullOrEmpty(protocol) && protocol.StartsWith("Asterisk Call Manager")) + { + this.protocolIdentifier = protocol; + } + else + { + this.protocolIdentifier = (string.IsNullOrEmpty(protocol) ? "Empty" : protocol); #if LOGGER - logger.Warning("Unsupported protocol version '{0}'. Use at your own risk.", protocol); + logger.Warning("Unsupported protocol version '{0}'. Use at your own risk.", protocol); #endif - } - if (reconnected) - { + } + if (reconnected) + { #if LOGGER - logger.Info("Send Challenge action."); + logger.Info("Send Challenge action."); #endif - ChallengeAction challengeAction = new ChallengeAction(); - try - { - SendAction(challengeAction, null); - } + ChallengeAction challengeAction = new ChallengeAction(); + try + { + SendAction(challengeAction, null); + } #if LOGGER - catch(Exception ex) - { - logger.Info("Send Challenge fail : ", ex.Message); + catch (Exception ex) + { + logger.Info("Send Challenge fail : ", ex.Message); #else catch { #endif - disconnect(true); - } - return; - } - } - #endregion + disconnect(true); + } + return; + } + } + #endregion - if (reconnected && e is DisconnectEvent) - { - ((DisconnectEvent)e).Reconnect = true; - fireEvent(e); - reconnect(false); - } - else if (!reconnected && reconnectEnable && (e is DisconnectEvent || e is ReloadEvent || e is ShutdownEvent)) - { - ((ConnectionStateEvent)e).Reconnect = true; - fireEvent(e); - reconnect(true); - } - else - fireEvent(e); - } + if (reconnected && e is DisconnectEvent) + { + ((DisconnectEvent)e).Reconnect = true; + fireEvent(e); + reconnect(false); + } + else if (!reconnected && reconnectEnable && (e is DisconnectEvent || e is ReloadEvent || e is ShutdownEvent)) + { + ((ConnectionStateEvent)e).Reconnect = true; + fireEvent(e); + reconnect(true); + } + else + fireEvent(e); + } - private void eventComplete(IAsyncResult result) - { - } + private void eventComplete(IAsyncResult result) + { + } - private void fireEvent(ManagerEvent e) - { - if (enableEvents && internalEvent != null) - if(UseASyncEvents) - internalEvent.BeginInvoke(this, e, new AsyncCallback(eventComplete), null); + private void fireEvent(ManagerEvent e) + { + if (enableEvents && internalEvent != null) + if (UseASyncEvents) + internalEvent.BeginInvoke(this, e, new AsyncCallback(eventComplete), null); else internalEvent.Invoke(this, e); - } - #endregion - } + } + + private void fireEvent(EventHandler astEvent, ManagerEvent arg) where T : ManagerEvent + { + if (astEvent != null) + astEvent(this, (T)arg); + } + #endregion + } } \ No newline at end of file From d1bb4249b88e3bbe3b1e897bf335071d5335887a Mon Sep 17 00:00:00 2001 From: zsender Date: Thu, 6 Apr 2017 09:25:48 +0300 Subject: [PATCH 2/8] fix subscribe event (for better code readability) addcomment to method fireEvent --- .../Asterisk.NET.Test/Program.cs | 12 ++++---- .../Asterisk.NET.WinForm/FormMain.cs | 2 +- .../Asterisk.NET/Manager/ManagerConnection.cs | 29 ++++++++++++------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs b/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs index d39c86e..5d2eeeb 100644 --- a/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs +++ b/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs @@ -138,13 +138,13 @@ Ctrl-C to exit"); manager.RegisterUserEventClass(typeof(UserAgentLoginEvent)); // Add or Remove events - manager.UserEvents += dam_UserEvents; + manager.UserEvents += new EventHandler(dam_UserEvents); // Dont't display this event - manager.NewExten += manager_IgnoreEvent; + manager.NewExten += new EventHandler(manager_IgnoreEvent); // Display all other - manager.UnhandledEvent += dam_Events; + manager.UnhandledEvent += new EventHandler(dam_Events); // +++ Only to debug purpose manager.FireAllEvents = true; @@ -289,7 +289,7 @@ Ctrl-C to exit"); Console.WriteLine("Redirect Call from " + ORIGINATE_CHANNEL + " to " + ORIGINATE_EXTRA_CHANNEL + " or press ESC."); // Wait for Dial Event from ORIGINATE_CHANNEL EventHandler de = dam_Dial; - manager.Dial += de; + manager.Dial += new EventHandler(de); while (transferChannel == null) { System.Threading.Thread.Sleep(100); @@ -323,8 +323,8 @@ Ctrl-C to exit"); // Link event used to define monitor channel Console.WriteLine("Monitor call. Please call " + ORIGINATE_CHANNEL + " and answer or press ESC."); // Wait for Link event - EventHandler le = dam_Link; - manager.Link += le; + EventHandler le = new EventHandler(dam_Link); + manager.Link += new EventHandler(le); while (monitorChannel == null) { System.Threading.Thread.Sleep(100); diff --git a/Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs b/Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs index 89dcec4..6ac81b2 100644 --- a/Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs +++ b/Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs @@ -28,7 +28,7 @@ namespace AsterNET.WinForm btnConnect.Enabled = false; manager = new ManagerConnection(address, port, user, password); - manager.UnhandledEvent += manager_Events; + manager.UnhandledEvent += new EventHandler(manager_Events); try { // Uncomment next 2 line comments to Disable timeout (debug mode) diff --git a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs index d3dd4be..943c8bb 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs @@ -58,7 +58,6 @@ namespace AsterNET.Manager private int reconnectCount; private Dictionary registeredEventClasses; - //private Dictionary registeredEventHandlers; private Dictionary> registeredEventHandlers; private event EventHandler internalEvent; private bool fireAllEvents = false; @@ -639,7 +638,9 @@ namespace AsterNET.Manager } if (fireAllEvents) + { fireEvent(UnhandledEvent, e); + } } #endregion @@ -1183,7 +1184,7 @@ namespace AsterNET.Manager enableEvents = true; reconnected = false; disconnect(true); - fireEvent(new DisconnectEvent(this)); + fireInternalEvent(new DisconnectEvent(this)); } } #endregion @@ -1766,7 +1767,7 @@ namespace AsterNET.Manager ConnectEvent ce = new ConnectEvent(this); ce.Reconnect = true; ce.ProtocolIdentifier = protocolIdentifier; - fireEvent(ce); + fireInternalEvent(ce); } else if (keepAliveAfterAuthenticationFailure) reconnect(true); @@ -1864,36 +1865,44 @@ namespace AsterNET.Manager if (reconnected && e is DisconnectEvent) { ((DisconnectEvent)e).Reconnect = true; - fireEvent(e); + fireInternalEvent(e); reconnect(false); } else if (!reconnected && reconnectEnable && (e is DisconnectEvent || e is ReloadEvent || e is ShutdownEvent)) { ((ConnectionStateEvent)e).Reconnect = true; - fireEvent(e); + fireInternalEvent(e); reconnect(true); } else - fireEvent(e); + fireInternalEvent(e); } private void eventComplete(IAsyncResult result) { } - private void fireEvent(ManagerEvent e) + private void fireInternalEvent(ManagerEvent e) { if (enableEvents && internalEvent != null) + { if (UseASyncEvents) internalEvent.BeginInvoke(this, e, new AsyncCallback(eventComplete), null); else internalEvent.Invoke(this, e); + } } - private void fireEvent(EventHandler astEvent, ManagerEvent arg) where T : ManagerEvent + /// + /// This method is called when send event to client if subscribed + /// + /// EventHandler argument + /// Event delegate + /// ManagerEvent or inherited class. Argument of eventHandler. + private void fireEvent(EventHandler asterEvent, ManagerEvent arg) where T : ManagerEvent { - if (astEvent != null) - astEvent(this, (T)arg); + if (asterEvent != null) + asterEvent(this, (T)arg); } #endregion } From 269ac0e5d907def5682bfba74a33fed90b00243c Mon Sep 17 00:00:00 2001 From: Nadobko Bogdan Date: Mon, 15 Jan 2018 21:03:40 +0200 Subject: [PATCH 3/8] Fixed indent of brace --- Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs index 943c8bb..99660df 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs @@ -640,7 +640,7 @@ namespace AsterNET.Manager if (fireAllEvents) { fireEvent(UnhandledEvent, e); - } + } } #endregion From a4f79d68ae68805399a3ca5715ab5026cd88d036 Mon Sep 17 00:00:00 2001 From: Nadobko Bogdan Date: Mon, 15 Jan 2018 21:28:22 +0200 Subject: [PATCH 4/8] fixed of parameter name in description --- Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs index 99660df..77c92e3 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs @@ -577,7 +577,7 @@ namespace AsterNET.Manager /// the port where Asterisk listens for incoming Manager API connections, usually 5038. /// the username to use for login /// the password to use for login - /// text encoding to asterisk input/output stream + /// text encoding to asterisk input/output stream public ManagerConnection(string hostname, int port, string username, string password, Encoding encoding) : this() { @@ -635,6 +635,7 @@ namespace AsterNET.Manager else { fireEvent(UnhandledEvent, e); + return; } if (fireAllEvents) From 6c6f327606199d0e51d98ed7f6401dc35d1c6ea6 Mon Sep 17 00:00:00 2001 From: zsender Date: Mon, 15 Jan 2018 22:43:35 +0200 Subject: [PATCH 5/8] fixed by comment "Need to add return after this line still." --- Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs index 77c92e3..15cede9 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs @@ -631,11 +631,11 @@ namespace AsterNET.Manager { var currentEvent = registeredEventHandlers[eventHash]; currentEvent(e); + return; } else { fireEvent(UnhandledEvent, e); - return; } if (fireAllEvents) From 0f61e78fe6d5985638b9a1c4a5caa2369025d7cc Mon Sep 17 00:00:00 2001 From: zsender Date: Tue, 16 Jan 2018 08:39:11 +0200 Subject: [PATCH 6/8] fixed for PR 121. Called UnhandledEvent, allows you see events that you aren't currently subscribed --- Asterisk.2013/Asterisk.NET/Helper.cs | 2 +- .../Asterisk.NET/Manager/ManagerConnection.cs | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Asterisk.2013/Asterisk.NET/Helper.cs b/Asterisk.2013/Asterisk.NET/Helper.cs index 8d2ff60..49bb485 100644 --- a/Asterisk.2013/Asterisk.NET/Helper.cs +++ b/Asterisk.2013/Asterisk.NET/Helper.cs @@ -874,7 +874,7 @@ namespace AsterNET #region RegisterEventHandler(Dictionary> list, Type eventType, Action action) - internal static void RegisterEventHandler(Dictionary> list, Type eventType, Action action) + internal static void RegisterEventHandler(Dictionary> list, Type eventType, Func action) { var eventTypeName = eventType.Name; int eventHash = eventTypeName.GetHashCode(); diff --git a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs index 15cede9..5620d3f 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Threading; using System.Collections; using AsterNET.Manager.Action; @@ -7,11 +6,9 @@ using AsterNET.Manager.Event; using AsterNET.Manager.Response; using System.Text.RegularExpressions; using System.Text; -using System.Net.Sockets; using System.Collections.Generic; using System.Reflection; using AsterNET.IO; -using AsterNET.Util; namespace AsterNET.Manager { @@ -58,7 +55,7 @@ namespace AsterNET.Manager private int reconnectCount; private Dictionary registeredEventClasses; - private Dictionary> registeredEventHandlers; + private Dictionary> registeredEventHandlers; private event EventHandler internalEvent; private bool fireAllEvents = false; private Thread callerThread; @@ -446,7 +443,7 @@ namespace AsterNET.Manager Helper.RegisterBuiltinEventClasses(registeredEventClasses); - registeredEventHandlers = new Dictionary>(); + registeredEventHandlers = new Dictionary>(); #region Event mapping table Helper.RegisterEventHandler(registeredEventHandlers, typeof(AgentCallbackLoginEvent), arg => fireEvent(AgentCallbackLogin, arg)); @@ -630,12 +627,10 @@ namespace AsterNET.Manager if (registeredEventHandlers.ContainsKey(eventHash)) { var currentEvent = registeredEventHandlers[eventHash]; - currentEvent(e); - return; - } - else - { - fireEvent(UnhandledEvent, e); + if (currentEvent(e)) + { + return; + } } if (fireAllEvents) @@ -1900,10 +1895,15 @@ namespace AsterNET.Manager /// EventHandler argument /// Event delegate /// ManagerEvent or inherited class. Argument of eventHandler. - private void fireEvent(EventHandler asterEvent, ManagerEvent arg) where T : ManagerEvent + private bool fireEvent(EventHandler asterEvent, ManagerEvent arg) where T : ManagerEvent { if (asterEvent != null) + { asterEvent(this, (T)arg); + return true; + } + + return false; } #endregion } From d69f7ffd642f125210177c833fc706832481bb9e Mon Sep 17 00:00:00 2001 From: zsender Date: Fri, 6 Jul 2018 00:59:19 +0300 Subject: [PATCH 7/8] Fixed PR conflicts --- .../Asterisk.NET.Test/Program.cs | 6 +- Asterisk.2013/Asterisk.NET/AsterNET.csproj | 8 ++ .../Asterisk.NET/FastAGI/AsteriskFastAGI.cs | 23 ++++- .../GeneralMappingStrategy.cs | 3 +- Asterisk.2013/Asterisk.NET/Helper.cs | 2 +- .../Asterisk.NET/IO/SocketConnection.cs | 11 ++- .../Manager/Action/FilterAction.cs | 55 ++++++++++++ .../Manager/Action/OriginateAction.cs | 2 +- .../Manager/Action/QueueSummaryAction.cs | 51 ++++++++++++ .../Manager/Event/AbstractAgentVariables.cs | 18 ++-- .../Event/ChallengeResponseFailedEvent.cs | 16 ++++ .../Manager/Event/ChallengeSentEvent.cs | 16 ++++ .../Manager/Event/DeviceStateChangeEvent.cs | 17 ++++ .../Manager/Event/InvalidAccountIDEvent.cs | 16 ++++ .../Manager/Event/QueueCallerJoinEvent.cs | 26 ++++-- .../Manager/Event/QueueCallerLeaveEvent.cs | 22 +++-- .../Manager/Event/QueueMemberAddedEvent.cs | 76 +++-------------- .../Manager/Event/QueueMemberPausedEvent.cs | 52 +++++------- .../Manager/Event/QueueMemberPenaltyEvent.cs | 11 +-- .../Manager/Event/QueueMemberRemovedEvent.cs | 28 +++---- .../Event/QueueMemberRinginuseEvent.cs | 27 +++--- .../Manager/Event/QueueMemberStatusEvent.cs | 83 +++---------------- .../Manager/Event/QueueSummaryEvent.cs | 48 +++++++++++ .../Manager/Event/SuccessfulAuthEvent.cs | 16 ++++ .../Asterisk.NET/Manager/ManagerConnection.cs | 70 +++++++++++----- README.md | 1 + 26 files changed, 433 insertions(+), 271 deletions(-) create mode 100644 Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs create mode 100644 Asterisk.2013/Asterisk.NET/Manager/Action/QueueSummaryAction.cs create mode 100644 Asterisk.2013/Asterisk.NET/Manager/Event/ChallengeResponseFailedEvent.cs create mode 100644 Asterisk.2013/Asterisk.NET/Manager/Event/ChallengeSentEvent.cs create mode 100644 Asterisk.2013/Asterisk.NET/Manager/Event/DeviceStateChangeEvent.cs create mode 100644 Asterisk.2013/Asterisk.NET/Manager/Event/InvalidAccountIDEvent.cs create mode 100644 Asterisk.2013/Asterisk.NET/Manager/Event/QueueSummaryEvent.cs create mode 100644 Asterisk.2013/Asterisk.NET/Manager/Event/SuccessfulAuthEvent.cs diff --git a/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs b/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs index 5d2eeeb..bec6da2 100644 --- a/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs +++ b/Asterisk.2013/Asterisk.NET.Test/Asterisk.NET.Test/Program.cs @@ -288,8 +288,8 @@ Ctrl-C to exit"); Console.WriteLine("Redirect Call from " + ORIGINATE_CHANNEL + " to " + ORIGINATE_EXTRA_CHANNEL + " or press ESC."); // Wait for Dial Event from ORIGINATE_CHANNEL - EventHandler de = dam_Dial; - manager.Dial += new EventHandler(de); + EventHandler de = new EventHandler(dam_Dial); + manager.Dial += de; while (transferChannel == null) { System.Threading.Thread.Sleep(100); @@ -324,7 +324,7 @@ Ctrl-C to exit"); Console.WriteLine("Monitor call. Please call " + ORIGINATE_CHANNEL + " and answer or press ESC."); // Wait for Link event EventHandler le = new EventHandler(dam_Link); - manager.Link += new EventHandler(le); + manager.Link += le; while (monitorChannel == null) { System.Threading.Thread.Sleep(100); diff --git a/Asterisk.2013/Asterisk.NET/AsterNET.csproj b/Asterisk.2013/Asterisk.NET/AsterNET.csproj index 7301a75..7efe675 100644 --- a/Asterisk.2013/Asterisk.NET/AsterNET.csproj +++ b/Asterisk.2013/Asterisk.NET/AsterNET.csproj @@ -167,6 +167,7 @@ + @@ -195,6 +196,7 @@ + @@ -256,6 +258,7 @@ + @@ -323,6 +326,11 @@ + + + + + diff --git a/Asterisk.2013/Asterisk.NET/FastAGI/AsteriskFastAGI.cs b/Asterisk.2013/Asterisk.NET/FastAGI/AsteriskFastAGI.cs index 8e7decf..c200a7c 100644 --- a/Asterisk.2013/Asterisk.NET/FastAGI/AsteriskFastAGI.cs +++ b/Asterisk.2013/Asterisk.NET/FastAGI/AsteriskFastAGI.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using System.Net; using System.Text; @@ -233,13 +234,29 @@ namespace AsterNET.FastAGI var ipAddress = IPAddress.Parse(address); serverSocket = new ServerSocket(port, ipAddress, SocketEncoding); } - catch (IOException ex) + catch (Exception ex) { #if LOGGER - logger.Error("Unable start AGI Server: cannot to bind to " + address + ":" + port + ".", ex); + if (ex is IOException) + { + logger.Error("Unable start AGI Server: cannot to bind to " + address + ":" + port + ".", ex); + } #endif + + if (serverSocket != null) + { + serverSocket.Close(); + serverSocket = null; + } + + pool.Shutdown(); +#if LOGGER + logger.Info("AGI Server shut down."); +#endif + throw ex; } + #if LOGGER logger.Info("Listening on " + address + ":" + port + "."); #endif @@ -287,7 +304,7 @@ namespace AsterNET.FastAGI serverSocket = null; pool.Shutdown(); #if LOGGER - logger.Info("AGIServer shut down."); + logger.Info("AGI Server shut down."); #endif } } diff --git a/Asterisk.2013/Asterisk.NET/FastAGI/MappingStrategies/GeneralMappingStrategy.cs b/Asterisk.2013/Asterisk.NET/FastAGI/MappingStrategies/GeneralMappingStrategy.cs index 344fc94..b149ebd 100644 --- a/Asterisk.2013/Asterisk.NET/FastAGI/MappingStrategies/GeneralMappingStrategy.cs +++ b/Asterisk.2013/Asterisk.NET/FastAGI/MappingStrategies/GeneralMappingStrategy.cs @@ -47,6 +47,7 @@ namespace AsterNET.FastAGI.MappingStrategies /// public string ScriptAssmebly { get; set; } + [XmlIgnoreAttribute] public Assembly PreLoadedAssembly { get; set; } public static List LoadMappings(string pathToXml) @@ -184,4 +185,4 @@ namespace AsterNET.FastAGI.MappingStrategies } } -} \ No newline at end of file +} diff --git a/Asterisk.2013/Asterisk.NET/Helper.cs b/Asterisk.2013/Asterisk.NET/Helper.cs index 49bb485..e6fc507 100644 --- a/Asterisk.2013/Asterisk.NET/Helper.cs +++ b/Asterisk.2013/Asterisk.NET/Helper.cs @@ -872,7 +872,7 @@ namespace AsterNET #endregion - #region RegisterEventHandler(Dictionary> list, Type eventType, Action action) + #region RegisterEventHandler(Dictionary list, int index, Type eventType) internal static void RegisterEventHandler(Dictionary> list, Type eventType, Func action) { diff --git a/Asterisk.2013/Asterisk.NET/IO/SocketConnection.cs b/Asterisk.2013/Asterisk.NET/IO/SocketConnection.cs index 07145ae..5df2484 100644 --- a/Asterisk.2013/Asterisk.NET/IO/SocketConnection.cs +++ b/Asterisk.2013/Asterisk.NET/IO/SocketConnection.cs @@ -11,7 +11,7 @@ namespace AsterNET.IO private TcpClient tcpClient; private NetworkStream networkStream; private StreamReader reader; - private StreamWriter writer; + private BinaryWriter writer; private Encoding encoding; private bool initial; @@ -29,8 +29,7 @@ namespace AsterNET.IO this.tcpClient = new TcpClient(host, port); this.networkStream = this.tcpClient.GetStream(); this.reader = new StreamReader(this.networkStream, encoding); - this.writer = new StreamWriter(this.networkStream, encoding); - this.writer.AutoFlush = true; + this.writer = new BinaryWriter(this.networkStream, encoding); } #endregion @@ -47,8 +46,7 @@ namespace AsterNET.IO this.tcpClient = tcpClient; this.networkStream = this.tcpClient.GetStream(); this.reader = new StreamReader(this.networkStream, encoding); - this.writer = new StreamWriter(this.networkStream, encoding); - this.writer.AutoFlush = true; + this.writer = new BinaryWriter(this.networkStream, encoding); } #endregion @@ -156,7 +154,8 @@ namespace AsterNET.IO /// connection has already been closed. public void Write(string s) { - writer.Write(s); + writer.Write(encoding.GetBytes(s)); + writer.Flush(); } #endregion diff --git a/Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs b/Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs new file mode 100644 index 0000000..765f99b --- /dev/null +++ b/Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs @@ -0,0 +1,55 @@ +namespace AsterNET.Manager.Action +{ + /// + /// Dynamically add filters for the current manager session + /// The filters added are only used for the current session. Once the connection is closed the filters are removed. + /// This comand requires the system permission because this command can be used to create filters that may bypass filters defined in manager.conf + /// + public class FilterAction : ManagerAction + { + #region Action + + /// + /// Get the name of this action, i.e. "Filter". + /// + public override string Action + { + get { return "Filter"; } + } + + #endregion + + #region Operation + + /// + /// Add - Add a filter + /// + public string Operation { get; set; } + + #endregion + + #region Filter + + /// + /// Filters can be whitelist or blacklist + /// Example whitelist filter: "Event: Newchannel" + /// Example blacklist filter: "!Channel: DAHDI.*" + /// + public string Filter { get; set; } + + #endregion + + #region FilterAction(string filter) + + /// + /// Add - Add a filter + /// + /// + public FilterAction(string filter) + { + Filter = filter; + } + + #endregion + } +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Action/OriginateAction.cs b/Asterisk.2013/Asterisk.NET/Manager/Action/OriginateAction.cs index a57e46d..0dd5469 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Action/OriginateAction.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Action/OriginateAction.cs @@ -159,7 +159,7 @@ namespace AsterNET.Manager.Action /// Example: "VAR1=abc|VAR2=def" sets the channel variables VAR1 to "abc" and VAR2 to "def". /// - [Obsolete("Don't use this anymore - the delimiter is not server context aware", true)] + [Obsolete("Use GetVariables and SetVariables instead.", true)] public string Variable { get { return null; /* return Helper.JoinVariables(variables, Common.GET_VAR_DELIMITER(this.Server), "="); */ } diff --git a/Asterisk.2013/Asterisk.NET/Manager/Action/QueueSummaryAction.cs b/Asterisk.2013/Asterisk.NET/Manager/Action/QueueSummaryAction.cs new file mode 100644 index 0000000..703daae --- /dev/null +++ b/Asterisk.2013/Asterisk.NET/Manager/Action/QueueSummaryAction.cs @@ -0,0 +1,51 @@ +using AsterNET.Manager.Event; +using System; + +namespace AsterNET.Manager.Action +{ + /// + /// Show queue summary + /// + /// + public class QueueSummaryAction : ManagerActionEvent + { + #region Action + + /// + /// Get the name of this action, i.e. "Filter". + /// + public override string Action + { + get { return "QueueSummary"; } + } + + #endregion + + #region MyRegion + + /// + /// Name of queue + /// + public string Queue { get; set; } + + #endregion + + #region QueueSummaryAction(string queue) + + public QueueSummaryAction(string queue) + { + Queue = queue; + } + + #endregion + + #region ActionCompleteEventClass() + + public override Type ActionCompleteEventClass() + { + return typeof(QueueSummaryEvent); + } + + #endregion + } +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/AbstractAgentVariables.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/AbstractAgentVariables.cs index 365dc2a..bd87013 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/AbstractAgentVariables.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/AbstractAgentVariables.cs @@ -18,26 +18,26 @@ namespace AsterNET.Manager.Event /// Get/Set the variables to set on the queue call in native asterisk format.
/// Example: "VAR1=abc|VAR2=def". /// - [Obsolete("Don't use this anymore - the delimiter is not server context aware", true)] - public string Variable - { - get { return null; /* return Helper.JoinVariables(variables, Common.GET_VAR_DELIMITER(this.Server), "="); */ } - set { /* variables = Helper.ParseVariables(variables, value, Common.GET_VAR_DELIMITER(this.Server)); */ } - } + [Obsolete("Use GetVariables and SetVariables instead.", true)] + public string Variable + { + get { return null; /* return Helper.JoinVariables(variables, Common.GET_VAR_DELIMITER(this.Server), "="); */ } + set { /* variables = Helper.ParseVariables(variables, value, Common.GET_VAR_DELIMITER(this.Server)); */ } + } #endregion #region GetVariables() /// /// Get the variables dictionary to set on the originated call. /// - public Dictionary GetVariables() + public Dictionary GetVariables() { return variables; } #endregion - #region SetVariables(Dictionary vars) - /// + #region SetVariables(Dictionary vars) + /// /// Set the variables dictionary to set on the originated call. /// public void SetVariables(Dictionary vars) diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/ChallengeResponseFailedEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/ChallengeResponseFailedEvent.cs new file mode 100644 index 0000000..170b5cb --- /dev/null +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/ChallengeResponseFailedEvent.cs @@ -0,0 +1,16 @@ +namespace AsterNET.Manager.Event +{ + + /// + /// Raised when a request's attempt to authenticate has been challenged, and the request failed the authentication challenge.
+ ///
+ public class ChallengeResponseFailedEvent : ManagerEvent +{ + public ChallengeResponseFailedEvent(ManagerConnection source) + : base(source) + { + } + + public string Status { get; set; } + } +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/ChallengeSentEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/ChallengeSentEvent.cs new file mode 100644 index 0000000..3107bbe --- /dev/null +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/ChallengeSentEvent.cs @@ -0,0 +1,16 @@ +namespace AsterNET.Manager.Event +{ + + /// + /// Raised when an Asterisk service sends an authentication challenge to a request..
+ ///
+ public class ChallengeSentEvent : ManagerEvent + { + public ChallengeSentEvent(ManagerConnection source) + : base(source) + { + } + + public string Status { get; set; } + } +} \ No newline at end of file diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/DeviceStateChangeEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/DeviceStateChangeEvent.cs new file mode 100644 index 0000000..3ffb3df --- /dev/null +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/DeviceStateChangeEvent.cs @@ -0,0 +1,17 @@ +namespace AsterNET.Manager.Event +{ + + /// + /// Raised when a device state changes.
+ /// This differs from the ExtensionStatus event because this event is raised for all device state changes, not only for changes that affect dialplan hints. + ///
+ public class DeviceStateChangeEvent : ManagerEvent + { + public DeviceStateChangeEvent(ManagerConnection source) + : base(source) + { + } + + public string Status { get; set; } + } +} \ No newline at end of file diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/InvalidAccountIDEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/InvalidAccountIDEvent.cs new file mode 100644 index 0000000..9971054 --- /dev/null +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/InvalidAccountIDEvent.cs @@ -0,0 +1,16 @@ +namespace AsterNET.Manager.Event +{ + + /// + /// Raised when a request fails an authentication check due to an invalid account ID.
+ ///
+ public class InvalidAccountIDEvent : ManagerEvent + { + public InvalidAccountIDEvent(ManagerConnection source) + : base(source) + { + } + + public string Status { get; set; } + } +} \ No newline at end of file diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueCallerJoinEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueCallerJoinEvent.cs index 0416417..78e7c65 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueCallerJoinEvent.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueCallerJoinEvent.cs @@ -1,15 +1,23 @@ namespace AsterNET.Manager.Event { - /// - /// A QueueCallerJoinEvent is triggered when a channel joins a queue.
- ///
- public class QueueCallerJoinEvent : QueueEvent - { - public string Position { get; set; } - - public QueueCallerJoinEvent(ManagerConnection source) + /// + /// A QueueCallerJoinEvent is triggered when a channel joins a queue.
+ ///
+ public class QueueCallerJoinEvent : JoinEvent + { + // "Channel" in ManagerEvent.cs + + // "Queue" in QueueEvent.cs + + // "CallerId" in JoinEvent.cs + + // "CallerIdName" in JoinEvent.cs + + // "Position" in JoinEvent.cs + + public QueueCallerJoinEvent(ManagerConnection source) : base(source) { } } -} \ No newline at end of file +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueCallerLeaveEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueCallerLeaveEvent.cs index dff535a..86fc7b8 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueCallerLeaveEvent.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueCallerLeaveEvent.cs @@ -1,15 +1,19 @@ namespace AsterNET.Manager.Event { - /// - /// A QueueCallerLeaveEvent is triggered when a channel leaves a queue.
- ///
- public class QueueCallerLeaveEvent : QueueEvent - { - public string Position { get; set; } - - public QueueCallerLeaveEvent(ManagerConnection source) + /// + /// A QueueCallerLeaveEvent is triggered when a channel leaves a queue.
+ ///
+ public class QueueCallerLeaveEvent : LeaveEvent + { + // "Channel" in ManagerEvent.cs + + // "Queue" in QueueEvent.cs + + // "Count" in QueueEvent.cs + + public QueueCallerLeaveEvent(ManagerConnection source) : base(source) { } } -} \ No newline at end of file +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberAddedEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberAddedEvent.cs index 0bd5cd9..4ee20fa 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberAddedEvent.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberAddedEvent.cs @@ -1,73 +1,21 @@ namespace AsterNET.Manager.Event { - /// - /// A QueueMemberAddedEvent is triggered when a queue member is added to a queue.
- /// It is implemented in apps/app_queue.c.
- /// - /// Available since : Asterisk 1.2.
- ///
- ///
- public class QueueMemberAddedEvent : AbstractQueueMemberEvent + /// + /// A QueueMemberAddedEvent is triggered when a queue member is added to a queue.
+ /// It is implemented in apps/app_queue.c.
+ /// + /// Available since : Asterisk 1.2.
+ ///
+ ///
+ public class QueueMemberAddedEvent : AbstractQueueMemberEvent { /// - /// Returns the name of the member's interface.
- /// E.g. the channel name or agent group. + /// Creates a new QueueMemberAddedEvent ///
- public new string MemberName { get; set; } - - /// - /// Get/Set if the added member is a dynamic or static queue member. - /// "dynamic" if the added member is a dynamic queue member, - /// "static" if the added member is a static queue member. - /// - public new string Membership { get; set; } - - /// - /// Get/Set the penalty for the added member. When calls are distributed - /// members with higher penalties are considered last. - /// - public new int Penalty { get; set; } - - /// - /// Get/Set the number of calls answered by the member. - /// - public new int CallsTaken { get; set; } - - /// - /// Get/Set the time (in seconds since 01/01/1970) the last successful call answered by the added member was hungup. - /// - public new long LastCall { get; set; } - - /// - /// Get/Set the status of this queue member.
- /// Valid status codes are:
- /// - /// AST_DEVICE_UNKNOWN - /// AST_DEVICE_NOT_INUSE - /// AST_DEVICE_INUSE - /// AST_DEVICE_BUSY - /// AST_DEVICE_INVALID - /// AST_DEVICE_UNAVAILABLE - /// AST_DEVICE_RINGING - /// AST_DEVICE_RINGINUSE - /// AST_DEVICE_ONHOLD - /// - ///
- public new int Status { get; set; } - - /// - /// Get/Set value if this queue member is paused (not accepting calls).
- /// true if this member has been paused or false if not. - ///
- public new bool Paused { get; set; } - - /// - /// Creates a new QueueMemberAddedEvent - /// - /// ManagerConnection passed through in the event. - public QueueMemberAddedEvent(ManagerConnection source) + /// ManagerConnection passed through in the event. + public QueueMemberAddedEvent(ManagerConnection source) : base(source) { } } -} \ No newline at end of file +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberPausedEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberPausedEvent.cs index 6d00390..1aff4ba 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberPausedEvent.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberPausedEvent.cs @@ -2,39 +2,29 @@ using System; namespace AsterNET.Manager.Event { - /// - /// A QueueMemberPausedEvent is triggered when a queue member is paused or unpaused.
- /// It is implemented in apps/app_queue.c.
- /// - /// Available since : Asterisk 1.2.
- /// Replaced by : since Asterisk 12.
- /// Removed since : Asterisk 13.
- ///
- ///
+ /// + /// A QueueMemberPausedEvent is triggered when a queue member is paused or unpaused.
+ /// It is implemented in apps/app_queue.c.
+ /// + /// Available since : Asterisk 1.2.
+ /// Replaced by : since Asterisk 12.
+ /// Removed since : Asterisk 13.
+ ///
+ ///
public class QueueMemberPausedEvent : AbstractQueueMemberEvent { - /// - /// The reason a member was paused - /// - public string Reason { get; set; } - - /// - /// Not Available, use instead. - /// - public new string PausedReason { get; set; } - - /// - /// Not Available, use instead. - /// - public new bool InCall { get; set; } - - /// - /// Creates a new QueueMemberPausedEvent - /// - /// ManagerConnection passed through in the event. - public QueueMemberPausedEvent(ManagerConnection source) + /// + /// The reason a member was paused + /// + public string Reason { get; set; } + + /// + /// Creates a new QueueMemberPausedEvent + /// + /// ManagerConnection passed through in the event. + public QueueMemberPausedEvent(ManagerConnection source) : base(source) { - } + } } -} \ No newline at end of file +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberPenaltyEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberPenaltyEvent.cs index 417c46b..8918042 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberPenaltyEvent.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberPenaltyEvent.cs @@ -6,15 +6,10 @@ namespace AsterNET.Manager.Event public class QueueMemberPenaltyEvent : AbstractQueueMemberEvent { /// - /// Get/Set the penalty for the queue location. + /// Creates a new QueueMemberPenaltyEvent /// - public new int Penalty { get; set; } - - /// - /// Creates a new QueueMemberPenaltyEvent - /// - /// ManagerConnection passed through in the event. - public QueueMemberPenaltyEvent(ManagerConnection source) + /// ManagerConnection passed through in the event. + public QueueMemberPenaltyEvent(ManagerConnection source) : base(source) { } diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberRemovedEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberRemovedEvent.cs index b8d424d..27182e1 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberRemovedEvent.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberRemovedEvent.cs @@ -1,27 +1,21 @@ namespace AsterNET.Manager.Event { - /// - /// A QueueMemberRemovedEvent is triggered when a queue member is removed from a queue.
- /// It is implemented in apps/app_queue.c.
- /// - /// Available since : Asterisk 1.2.
- ///
- ///
- public class QueueMemberRemovedEvent : AbstractQueueMemberEvent + /// + /// A QueueMemberRemovedEvent is triggered when a queue member is removed from a queue.
+ /// It is implemented in apps/app_queue.c.
+ /// + /// Available since : Asterisk 1.2.
+ ///
+ ///
+ public class QueueMemberRemovedEvent : AbstractQueueMemberEvent { /// - /// Returns the name of the member's interface.
- /// E.g. the channel name or agent group. + /// Creates a new QueueMemberRemovedEvent ///
- public new string MemberName { get; set; } - - /// - /// Creates a new QueueMemberRemovedEvent - /// - /// ManagerConnection passed through in the event. + /// ManagerConnection passed through in the event. public QueueMemberRemovedEvent(ManagerConnection source) : base(source) { } } -} \ No newline at end of file +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberRinginuseEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberRinginuseEvent.cs index 97a2b23..05c1c0c 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberRinginuseEvent.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberRinginuseEvent.cs @@ -1,24 +1,17 @@ namespace AsterNET.Manager.Event { - /// - /// Raised when a member's ringinuse setting is changed - /// - public class QueueMemberRinginuseEvent : AbstractQueueMemberEvent - { - - /// - /// Evaluates if Ringinuse, - /// if not.
- ///
- public new bool Ringinuse { get; set; } - - /// - /// Creates a new QueueMemberRinginuseEvent - /// - /// ManagerConnection passed through in the event. + /// + /// Raised when a member's ringinuse setting is changed + /// + public class QueueMemberRinginuseEvent : AbstractQueueMemberEvent + { + /// + /// Creates a new QueueMemberRinginuseEvent + /// + /// ManagerConnection passed through in the event. public QueueMemberRinginuseEvent(ManagerConnection source) : base(source) { } } -} \ No newline at end of file +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberStatusEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberStatusEvent.cs index fb1fce9..8cafaf7 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberStatusEvent.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueMemberStatusEvent.cs @@ -1,80 +1,17 @@ namespace AsterNET.Manager.Event { - /// - /// Raised when a Queue member's status has changed - /// - public class QueueMemberStatusEvent : AbstractQueueMemberEvent - { - /// - /// Returns the name of the member's interface.
- /// E.g. the channel name or agent group. - ///
- public new string MemberName { get; set; } - - /// - /// Channel technology or location from which to read device state changes.
- ///
- public new string StateInterface { get; set; } - - /// - /// Get/Set if the added member is a dynamic or static queue member. - /// "dynamic" if the added member is a dynamic queue member, - /// "static" if the added member is a static queue member. - /// - public new string Membership { get; set; } - - /// - /// Get/Set the penalty for the added member. When calls are distributed - /// members with higher penalties are considered last. - /// - public new int Penalty { get; set; } - - /// - /// Get/Set the number of calls answered by the member. - /// - public new int CallsTaken { get; set; } - - /// - /// Get/Set the time (in seconds since 01/01/1970) the last successful call answered by the added member was hungup. - /// - public new long LastCall { get; set; } - - /// - /// Evaluates if member is in call, - /// after LastCall time is updated.
- ///
- public new bool InCall { get; set; } - - /// - /// Get/Set the status of this queue member.
- /// Valid status codes are:
- /// - /// AST_DEVICE_UNKNOWN - /// AST_DEVICE_NOT_INUSE - /// AST_DEVICE_INUSE - /// AST_DEVICE_BUSY - /// AST_DEVICE_INVALID - /// AST_DEVICE_UNAVAILABLE - /// AST_DEVICE_RINGING - /// AST_DEVICE_RINGINUSE - /// AST_DEVICE_ONHOLD - /// - ///
- public new int Status { get; set; } - - /// - /// Get/Set value if this queue member is paused (not accepting calls).
- /// true if this member has been paused or false if not. - ///
- public new bool Paused { get; set; } - - /// - /// Creates a new QueueMemberStatusEvent - /// - /// ManagerConnection passed through in the event. + /// + /// Raised when a Queue member's status has changed + /// + public class QueueMemberStatusEvent : AbstractQueueMemberEvent + { + /// + /// Creates a new QueueMemberStatusEvent + /// + /// ManagerConnection passed through in the event. public QueueMemberStatusEvent(ManagerConnection source) : base(source) { } } -} \ No newline at end of file +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/QueueSummaryEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueSummaryEvent.cs new file mode 100644 index 0000000..9f48db6 --- /dev/null +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/QueueSummaryEvent.cs @@ -0,0 +1,48 @@ +namespace AsterNET.Manager.Event +{ + /// + /// + /// + public class QueueSummaryEvent : ManagerEvent + { + public QueueSummaryEvent(ManagerConnection source) + : base(source) + { + } + + /// + /// Queue name + /// + public string Queue { get; set; } + + /// + /// Logged operators count in queue + /// + public int LoggedIn { get; set; } + + /// + /// Available operators in queue + /// + public int Available { get; set; } + + /// + /// Calls count + /// + public int Callers { get; set; } + + /// + /// + /// + public int HoldTime { get; set; } + + /// + /// Total talk time + /// + public int TalkTime { get; set; } + + /// + /// + /// + public int LongestHoldTime { get; set; } + } +} diff --git a/Asterisk.2013/Asterisk.NET/Manager/Event/SuccessfulAuthEvent.cs b/Asterisk.2013/Asterisk.NET/Manager/Event/SuccessfulAuthEvent.cs new file mode 100644 index 0000000..32f7570 --- /dev/null +++ b/Asterisk.2013/Asterisk.NET/Manager/Event/SuccessfulAuthEvent.cs @@ -0,0 +1,16 @@ +namespace AsterNET.Manager.Event +{ + + /// + /// Raised when a request successfully authenticates with a service..
+ ///
+ public class SuccessfulAuthEvent : ManagerEvent + { + public SuccessfulAuthEvent(ManagerConnection source) + : base(source) + { + } + + public string Status { get; set; } + } +} \ No newline at end of file diff --git a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs index 5620d3f..d1fe667 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/ManagerConnection.cs @@ -196,7 +196,7 @@ namespace AsterNET.Manager /// A MeetMeLeave is triggered if a channel leaves a meet me conference.
///
public event EventHandler MeetMeLeave; - // public event MeetMeStopTalkingEventHandler MeetMeStopTalking; + // public event EventHandler MeetMeStopTalking; /// /// A MeetMeTalkingEvent is triggered when a user starts talking in a meet me conference.
/// To enable talker detection you must pass the option 'T' to the MeetMe application. @@ -222,15 +222,15 @@ namespace AsterNET.Manager /// A NewState is triggered when the state of a channel has changed.
///
public event EventHandler NewState; - // public event OriginateEventHandler Originate; + // public event EventHandler Originate; /// /// An OriginateFailure is triggered when the execution of an OriginateAction failed. /// - // public event OriginateFailureEventHandler OriginateFailure; + // public event EventHandler OriginateFailure; /// /// An OriginateSuccess is triggered when the execution of an OriginateAction succeeded. /// - // public event OriginateSuccessEventHandler OriginateSuccess; + // public event EventHandler OriginateSuccess; /// /// An OriginateResponse is triggered when the execution of an Originate. /// @@ -426,6 +426,36 @@ namespace AsterNET.Manager /// public event EventHandler QueueMemberPause; + /// + /// A ChallengeResponseFailed is triggered when a request's attempt to authenticate has been challenged, and the request failed the authentication challenge. + /// + public event EventHandler ChallengeResponseFailed; + + /// + /// A InvalidAccountID is triggered when a request fails an authentication check due to an invalid account ID. + /// + public event EventHandler InvalidAccountID; + + /// + /// A DeviceStateChanged is triggered when a device state changes. + /// + public event EventHandler DeviceStateChanged; + + /// + /// A ChallengeSent is triggered when an Asterisk service sends an authentication challenge to a request.. + /// + public event EventHandler ChallengeSent; + + /// + /// A SuccessfulAuth is triggered when a request successfully authenticates with a service. + /// + public event EventHandler SuccessfulAuth; + + /// + /// Raised when call queue summary + /// + public event EventHandler QueueSummary; + #endregion #region Constructor - ManagerConnection() @@ -462,7 +492,6 @@ namespace AsterNET.Manager Helper.RegisterEventHandler(registeredEventHandlers, typeof(DBGetResponseEvent), arg => fireEvent(DBGetResponse, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(DialEvent), arg => fireEvent(Dial, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, typeof(DNDStateEvent), arg => fireEvent(DNDState, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(ExtensionStatusEvent), arg => fireEvent(ExtensionStatus, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(HangupEvent), arg => fireEvent(Hangup, arg)); @@ -484,8 +513,8 @@ namespace AsterNET.Manager Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallEvent), arg => fireEvent(ParkedCall, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallGiveUpEvent), arg => fireEvent(ParkedCallGiveUp, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallsCompleteEvent), arg => fireEvent(ParkedCallsComplete, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallTimeOutEvent), arg => fireEvent(ParkedCallsComplete, arg)); - Helper.RegisterEventHandler(registeredEventHandlers, typeof(PeerEntryEvent), arg => fireEvent(ParkedCallTimeOut, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ParkedCallTimeOutEvent), arg => fireEvent(ParkedCallTimeOut, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(PeerEntryEvent), arg => fireEvent(PeerEntry, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(PeerlistCompleteEvent), arg => fireEvent(PeerlistComplete, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(PeerStatusEvent), arg => fireEvent(PeerStatus, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueEntryEvent), arg => fireEvent(QueueEntry, arg)); @@ -540,11 +569,16 @@ namespace AsterNET.Manager Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueCallerJoinEvent), arg => fireEvent(QueueCallerJoin, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueCallerLeaveEvent), arg => fireEvent(QueueCallerLeave, arg)); Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueMemberPauseEvent), arg => fireEvent(QueueMemberPause, arg)); - + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ChallengeResponseFailedEvent), arg => fireEvent(ChallengeResponseFailed, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(InvalidAccountIDEvent), arg => fireEvent(InvalidAccountID, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(DeviceStateChangeEvent), arg => fireEvent(DeviceStateChanged, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(ChallengeSentEvent), arg => fireEvent(ChallengeSent, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(SuccessfulAuthEvent), arg => fireEvent(SuccessfulAuth, arg)); + Helper.RegisterEventHandler(registeredEventHandlers, typeof(QueueSummaryEvent), arg => fireEvent(QueueSummary, arg)); + #endregion this.internalEvent += new EventHandler(internalEventHandler); - } #endregion @@ -574,7 +608,7 @@ namespace AsterNET.Manager /// the port where Asterisk listens for incoming Manager API connections, usually 5038. /// the username to use for login /// the password to use for login - /// text encoding to asterisk input/output stream + /// text encoding to asterisk input/output stream public ManagerConnection(string hostname, int port, string username, string password, Encoding encoding) : this() { @@ -1180,7 +1214,7 @@ namespace AsterNET.Manager enableEvents = true; reconnected = false; disconnect(true); - fireInternalEvent(new DisconnectEvent(this)); + fireEvent(new DisconnectEvent(this)); } } #endregion @@ -1763,7 +1797,7 @@ namespace AsterNET.Manager ConnectEvent ce = new ConnectEvent(this); ce.Reconnect = true; ce.ProtocolIdentifier = protocolIdentifier; - fireInternalEvent(ce); + fireEvent(ce); } else if (keepAliveAfterAuthenticationFailure) reconnect(true); @@ -1861,32 +1895,30 @@ namespace AsterNET.Manager if (reconnected && e is DisconnectEvent) { ((DisconnectEvent)e).Reconnect = true; - fireInternalEvent(e); + fireEvent(e); reconnect(false); } else if (!reconnected && reconnectEnable && (e is DisconnectEvent || e is ReloadEvent || e is ShutdownEvent)) { ((ConnectionStateEvent)e).Reconnect = true; - fireInternalEvent(e); + fireEvent(e); reconnect(true); } else - fireInternalEvent(e); + fireEvent(e); } private void eventComplete(IAsyncResult result) { } - private void fireInternalEvent(ManagerEvent e) + private void fireEvent(ManagerEvent e) { if (enableEvents && internalEvent != null) - { if (UseASyncEvents) internalEvent.BeginInvoke(this, e, new AsyncCallback(eventComplete), null); else internalEvent.Invoke(this, e); - } } /// @@ -1907,4 +1939,4 @@ namespace AsterNET.Manager } #endregion } -} \ No newline at end of file +} diff --git a/README.md b/README.md index 4396a66..b0ac189 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![Build Status](https://travis-ci.org/AsterNET/AsterNET.svg?branch=master)](https://travis-ci.org/AsterNET/AsterNET) +[![NuGet](https://img.shields.io/nuget/v/AsterNET.svg)](https://www.nuget.org/packages/AsterNET) AsterNET is an open source framework for Asterisk AMI and FastAGI. AsterNET allows you to talk to Asterisk AMI from any .NET application and create FastAGI applications in any .NET language. From 84fe677d7a9b8a4eab2593a10cdff209da7dd086 Mon Sep 17 00:00:00 2001 From: zsender Date: Fri, 6 Jul 2018 08:51:03 +0300 Subject: [PATCH 8/8] Added argument "operation" in constructor --- Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs b/Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs index 765f99b..b5369df 100644 --- a/Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs +++ b/Asterisk.2013/Asterisk.NET/Manager/Action/FilterAction.cs @@ -44,10 +44,12 @@ /// /// Add - Add a filter /// - /// - public FilterAction(string filter) + /// Add a filter + /// Filters can be whitelist or blacklist + public FilterAction(string filter, string operation = "Add") { Filter = filter; + Operation = operation; } #endregion