/Asterisk.NET/Manager/ManagerConnection.cs
C# | 2258 lines | 1733 code | 151 blank | 374 comment | 326 complexity | 7c7c2fff77b76d0d082c9ecfa17b5ce6 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- using System;
- using System.IO;
- using System.Threading;
- using System.Collections;
- using Asterisk.NET.Manager.Action;
- using Asterisk.NET.Manager.Event;
- using Asterisk.NET.Manager.Response;
- using System.Text.RegularExpressions;
- using System.Text;
- using System.Net.Sockets;
- using System.Collections.Generic;
- using System.Reflection;
- using Asterisk.NET.IO;
- using Asterisk.NET.Util;
- namespace Asterisk.NET.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 CdrEventHandler(object sender, Event.CdrEvent e);
- public delegate void CelEventHandler(object sender, Event.CelEvent e);
- public delegate void DBGetResponseEventHandler(object sender, Event.DBGetResponseEvent e);
- public delegate void DialEventHandler(object sender, Event.DialEvent 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 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 ZapShowChannelsCompleteEventHandler(object sender, Event.ZapShowChannelsCompleteEvent e);
- public delegate void ZapShowChannelsEventHandler(object sender, Event.ZapShowChannelsEvent e);
- public delegate void ConnectionStateEventHandler(object sender, Event.ConnectionStateEvent e);
- #endregion
- /// <summary>
- /// Default implemention of the ManagerConnection interface.
- /// </summary>
- public class ManagerConnection
- {
- #region Variables
- #if LOGGER
- private ILogger logger = Logger.Instance();
- #endif
- private long actionIdCount = 0;
- private string hostname;
- private int port;
- private string username;
- private string password;
- private SocketConnection mrSocket;
- private ThreadClass 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<int, IResponseHandler> responseHandlers;
- private Dictionary<int, IResponseHandler> pingHandlers;
- private Dictionary<int, IResponseHandler> responseEventHandlers;
- private int pingInterval = 10000;
- 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 Dictionary<int, ConstructorInfo> registeredEventClasses;
- private Dictionary<int, int> registeredEventHandlers;
- private event ManagerEventHandler internalEvent;
- private bool fireAllEvents = false;
- private Thread callerThread;
- private bool traceCallerThread = true;
- /// <summary> Default Fast Reconnect retry counter.</summary>
- private int reconnectRetryFast = 5;
- /// <summary> Default Maximum Reconnect retry counter.</summary>
- private int reconnectRetryMax = 10;
- /// <summary> Default Fast Reconnect interval in milliseconds.</summary>
- private int reconnectIntervalFast = 5000;
- /// <summary> Default Slow Reconnect interval in milliseconds.</summary>
- private int reconnectIntervalMax = 10000;
- #endregion
- #region Events
- /// <summary>
- /// An UnhandledEvent is triggered on unknown event.
- /// </summary>
- public event ManagerEventHandler UnhandledEvent;
- /// <summary>
- /// An AgentCallbackLogin is triggered when an agent is successfully logged in.
- /// </summary>
- public event AgentCallbackLoginEventHandler AgentCallbackLogin;
- /// <summary>
- /// An AgentCallbackLogoff is triggered when an agent that previously logged in is logged of.<br/>
- /// </summary>
- public event AgentCallbackLogoffEventHandler AgentCallbackLogoff;
- /// <summary>
- /// An AgentCalled is triggered when an agent is ring.<br/>
- /// To enable AgentCalled you have to set <code>eventwhencalled = yes</code> in <code>queues.conf</code>.<br/>
- /// </summary>
- public event AgentCalledEventHandler AgentCalled;
- /// <summary>
- /// An AgentCompleteEvent is triggered when at the end of a call if the caller was connected to an agent.
- /// </summary>
- public event AgentCompleteEventHandler AgentComplete;
- /// <summary>
- /// An AgentConnectEvent is triggered when a caller is connected to an agent.
- /// </summary>
- public event AgentConnectEventHandler AgentConnect;
- /// <summary>
- /// An AgentDumpEvent is triggered when an agent dumps the caller while listening to the queue announcement.
- /// </summary>
- public event AgentDumpEventHandler AgentDump;
- /// <summary>
- /// An AgentLoginEvent is triggered when an agent is successfully logged in using AgentLogin.
- /// </summary>
- public event AgentLoginEventHandler AgentLogin;
- /// <summary>
- /// An AgentCallbackLogoffEvent is triggered when an agent that previously logged in using AgentLogin is logged of.
- /// </summary>
- public event AgentLogoffEventHandler AgentLogoff;
- /// <summary>
- /// An AgentsCompleteEvent is triggered after the state of all agents has been reported in response to an AgentsAction.
- /// </summary>
- public event AgentsCompleteEventHandler AgentsComplete;
- /// <summary>
- /// An AgentsEvent is triggered for each agent in response to an AgentsAction.
- /// </summary>
- public event AgentsEventHandler Agents;
- /// <summary>
- /// An AlarmEvent is triggered when a Zap channel leaves alarm state.
- /// </summary>
- public event AlarmClearEventHandler AlarmClear;
- /// <summary>
- /// An AlarmEvent is triggered when a Zap channel enters or changes alarm state.
- /// </summary>
- public event AlarmEventHandler Alarm;
- public event CelEventHandler Cel;
- /// <summary>
- /// A CdrEvent is triggered when a call detail record is generated, usually at the end of a call.
- /// </summary>
- public event CdrEventHandler Cdr;
- public event DBGetResponseEventHandler DBGetResponse;
- /// <summary>
- /// A Dial is triggered whenever a phone attempts to dial someone.<br/>
- /// </summary>
- public event DialEventHandler Dial;
- /// <summary>
- /// A DNDStateEvent is triggered by the Zap channel driver when a channel enters or leaves DND (do not disturb) state.
- /// </summary>
- public event DNDStateEventHandler DNDState;
- /// <summary>
- /// An ExtensionStatus is triggered when the state of an extension changes.<br/>
- /// </summary>
- public event ExtensionStatusEventHandler ExtensionStatus;
- /// <summary>
- /// A Hangup is triggered when a channel is hung up.<br/>
- /// </summary>
- public event HangupEventHandler Hangup;
- /// <summary>
- /// A HoldedCall is triggered when a channel is put on hold.<br/>
- /// </summary>
- public event HoldedCallEventHandler HoldedCall;
- /// <summary>
- /// A Hold is triggered by the SIP channel driver when a channel is put on hold.<br/>
- /// </summary>
- public event HoldEventHandler Hold;
- /// <summary>
- /// A Join is triggered when a channel joines a queue.<br/>
- /// </summary>
- public event JoinEventHandler Join;
- /// <summary>
- /// A Leave is triggered when a channel leaves a queue.<br/>
- /// </summary>
- public event LeaveEventHandler Leave;
- /// <summary>
- /// A Link is triggered when two voice channels are linked together and voice data exchange commences.<br/>
- /// 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.
- /// </summary>
- public event LinkEventHandler Link;
- /// <summary>
- /// A LogChannel is triggered when logging is turned on or off.<br/>
- /// </summary>
- public event LogChannelEventHandler LogChannel;
- /// <summary>
- /// A MeetMeJoin is triggered if a channel joins a meet me conference.<br/>
- /// </summary>
- public event MeetMeJoinEventHandler MeetMeJoin;
- /// <summary>
- /// A MeetMeLeave is triggered if a channel leaves a meet me conference.<br/>
- /// </summary>
- public event MeetMeLeaveEventHandler MeetMeLeave;
- // public event MeetMeStopTalkingEventHandler MeetMeStopTalking;
- /// <summary>
- /// A MeetMeTalkingEvent is triggered when a user starts talking in a meet me conference.<br/>
- /// To enable talker detection you must pass the option 'T' to the MeetMe application.
- /// </summary>
- public event MeetMeTalkingEventHandler MeetMeTalking;
- /// <summary>
- /// A MessageWaiting is triggered when someone leaves voicemail.<br/>
- /// </summary>
- public event MessageWaitingEventHandler MessageWaiting;
- /// <summary>
- /// A NewCallerId is triggered when the caller id of a channel changes.<br/>
- /// </summary>
- public event NewCallerIdEventHandler NewCallerId;
- /// <summary>
- /// A NewChannel is triggered when a new channel is created.<br/>
- /// </summary>
- public event NewChannelEventHandler NewChannel;
- /// <summary>
- /// A NewExten is triggered when a channel is connected to a new extension.<br/>
- /// </summary>
- public event NewExtenEventHandler NewExten;
- /// <summary>
- /// A NewState is triggered when the state of a channel has changed.<br/>
- /// </summary>
- public event NewStateEventHandler NewState;
- // public event OriginateEventHandler Originate;
- /// <summary>
- /// An OriginateFailure is triggered when the execution of an OriginateAction failed.
- /// </summary>
- // public event OriginateFailureEventHandler OriginateFailure;
- /// <summary>
- /// An OriginateSuccess is triggered when the execution of an OriginateAction succeeded.
- /// </summary>
- // public event OriginateSuccessEventHandler OriginateSuccess;
- /// <summary>
- /// An OriginateResponse is triggered when the execution of an Originate.
- /// </summary>
- public event OriginateResponseEventHandler OriginateResponse;
- /// <summary>
- /// A ParkedCall is triggered when a channel is parked (in this case no
- /// action id is set) and in response to a ParkedCallsAction.<br/>
- /// </summary>
- public event ParkedCallEventHandler ParkedCall;
- /// <summary>
- /// A ParkedCallGiveUp is triggered when a channel that has been parked is hung up.<br/>
- /// </summary>
- public event ParkedCallGiveUpEventHandler ParkedCallGiveUp;
- /// <summary>
- /// A ParkedCallsComplete is triggered after all parked calls have been reported in response to a ParkedCallsAction.
- /// </summary>
- public event ParkedCallsCompleteEventHandler ParkedCallsComplete;
- /// <summary>
- /// A ParkedCallTimeOut is triggered when call parking times out for a given channel.<br/>
- /// </summary>
- public event ParkedCallTimeOutEventHandler ParkedCallTimeOut;
- /// <summary>
- /// A PeerEntry is triggered in response to a SIPPeersAction or SIPShowPeerAction and contains information about a peer.<br/>
- /// </summary>
- public event PeerEntryEventHandler PeerEntry;
- /// <summary>
- /// A PeerlistComplete is triggered after the details of all peers has been reported in response to an SIPPeersAction or SIPShowPeerAction.<br/>
- /// </summary>
- public event PeerlistCompleteEventHandler PeerlistComplete;
- /// <summary>
- /// A PeerStatus is triggered when a SIP or IAX client attempts to registrer at this asterisk server.<br/>
- /// </summary>
- public event PeerStatusEventHandler PeerStatus;
- /// <summary>
- /// A QueueEntryEvent is triggered in response to a QueueStatusAction and contains information about an entry in a queue.
- /// </summary>
- public event QueueEntryEventHandler QueueEntry;
- /// <summary>
- /// A QueueMemberAddedEvent is triggered when a queue member is added to a queue.
- /// </summary>
- public event QueueMemberAddedEventHandler QueueMemberAdded;
- /// <summary>
- /// A QueueMemberEvent is triggered in response to a QueueStatusAction and contains information about a member of a queue.
- /// </summary>
- public event QueueMemberEventHandler QueueMember;
- /// <summary>
- /// A QueueMemberPausedEvent is triggered when a queue member is paused or unpaused.
- /// </summary>
- public event QueueMemberPausedEventHandler QueueMemberPaused;
- /// <summary>
- /// A QueueMemberRemovedEvent is triggered when a queue member is removed from a queue.
- /// </summary>
- public event QueueMemberRemovedEventHandler QueueMemberRemoved;
- /// <summary>
- /// A QueueMemberStatusEvent shows the status of a QueueMemberEvent.
- /// </summary>
- public event QueueMemberStatusEventHandler QueueMemberStatus;
- /// <summary>
- /// A QueueParamsEvent is triggered in response to a QueueStatusAction and contains the parameters of a queue.
- /// </summary>
- public event QueueParamsEventHandler QueueParams;
- /// <summary>
- /// A QueueStatusCompleteEvent is triggered after the state of all queues has been reported in response to a QueueStatusAction.
- /// </summary>
- public event QueueStatusCompleteEventHandler QueueStatusComplete;
- /// <summary>
- /// A Registry is triggered when this asterisk server attempts to register
- /// as a client at another SIP or IAX server.<br/>
- /// </summary>
- public event RegistryEventHandler Registry;
- /// <summary>
- /// A RenameEvent is triggered when the name of a channel is changed.
- /// </summary>
- public event RenameEventHandler Rename;
- /// <summary>
- /// A StatusCompleteEvent is triggered after the state of all channels has been reported in response to a StatusAction.
- /// </summary>
- public event StatusCompleteEventHandler StatusComplete;
- /// <summary>
- /// A StatusEvent is triggered for each active channel in response to a StatusAction.
- /// </summary>
- public event StatusEventHandler Status;
- /// <summary>
- /// An UnholdEvent is triggered by the SIP channel driver when a channel is no longer put on hold.
- /// </summary>
- public event UnholdEventHandler Unhold;
- /// <summary>
- /// An UnlinkEvent is triggered when a link between two voice channels is discontinued, for example, just before call completion.
- /// </summary>
- public event UnlinkEventHandler Unlink;
- /// <summary>
- /// A UnparkedCallEvent is triggered when a channel that has been parked is resumed.
- /// </summary>
- public event UnparkedCallEventHandler UnparkedCall;
- /// <summary>
- /// A ZapShowChannelsEvent is triggered on UserEvent in dialplan.
- /// </summary>
- public event UserEventHandler UserEvents;
- /// <summary>
- /// A ZapShowChannelsCompleteEvent is triggered after the state of all zap channels has been reported in response to a ZapShowChannelsAction.
- /// </summary>
- public event ZapShowChannelsCompleteEventHandler ZapShowChannelsComplete;
- /// <summary>
- /// A ZapShowChannelsEvent is triggered in response to a ZapShowChannelsAction and shows the state of a zap channel.
- /// </summary>
- public event ZapShowChannelsEventHandler ZapShowChannels;
- /// <summary>
- /// A ConnectionState is triggered after Connect/Disconnect/Reload/Shutdown events.
- /// </summary>
- public event ConnectionStateEventHandler ConnectionState;
- #endregion
- #region Constructor - ManagerConnection()
- /// <summary> Creates a new instance.</summary>
- public ManagerConnection()
- {
- callerThread = Thread.CurrentThread;
- socketEncoding = Encoding.ASCII;
- responseHandlers = new Dictionary<int, IResponseHandler>();
- pingHandlers = new Dictionary<int, IResponseHandler>();
- responseEventHandlers = new Dictionary<int, IResponseHandler>();
- registeredEventClasses = new Dictionary<int, ConstructorInfo>();
- Helper.RegisterBuiltinEventClasses(registeredEventClasses);
- registeredEventHandlers = new Dictionary<int, int>();
- #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));
-
- Helper.RegisterEventHandler(registeredEventHandlers, 13, typeof(CelEvent));
- Helper.RegisterEventHandler(registeredEventHandlers, 14, typeof(DBGetResponseEvent));
- Helper.RegisterEventHandler(registeredEventHandlers, 15, typeof(DialEvent));
- 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, 52, typeof(RenameEvent));
- 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, 62, typeof(ConnectEvent));
- Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(DisconnectEvent));
- Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(ReloadEvent));
- Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(ShutdownEvent));
- #endregion
- this.internalEvent += new ManagerEventHandler(internalEventHandler);
- }
- #endregion
- #region Constructor - ManagerConnection(hostname, port, username, password)
- /// <summary>
- /// Creates a new instance with the given connection parameters.
- /// </summary>
- /// <param name="hostname">the hosname of the Asterisk server to connect to.</param>
- /// <param name="port">the port where Asterisk listens for incoming Manager API connections, usually 5038.</param>
- /// <param name="username">the username to use for login</param>
- /// <param name="password">the password to use for login</param>
- public ManagerConnection(string hostname, int port, string username, string password)
- : this()
- {
- this.hostname = hostname;
- this.port = port;
- this.username = username;
- this.password = password;
- }
- #endregion
- #region Constructor - ManagerConnection(hostname, port, username, password, Encoding socketEncoding)
- /// <summary>
- /// Creates a new instance with the given connection parameters.
- /// </summary>
- /// <param name="hostname">the hosname of the Asterisk server to connect to.</param>
- /// <param name="port">the port where Asterisk listens for incoming Manager API connections, usually 5038.</param>
- /// <param name="username">the username to use for login</param>
- /// <param name="password">the password to use for login</param>
- /// <param name="socketEncoding">text encoding to asterisk input/output stream</param>
- 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
- /// <summary>
- /// Default Fast Reconnect retry counter.
- /// </summary>
- public int ReconnectRetryFast
- {
- get { return reconnectRetryFast; }
- set { reconnectRetryFast = value; }
- }
- /// <summary> Default Maximum Reconnect retry counter.</summary>
- public int ReconnectRetryMax
- {
- get { return reconnectRetryMax; }
- set { reconnectRetryMax = value; }
- }
- /// <summary> Default Fast Reconnect interval in milliseconds.</summary>
- public int ReconnectIntervalFast
- {
- get { return reconnectIntervalFast; }
- set { reconnectIntervalFast = value; }
- }
- /// <summary> Default Slow Reconnect interval in milliseconds.</summary>
- public int ReconnectIntervalMax
- {
- get { return reconnectIntervalMax; }
- set { reconnectIntervalMax = value; }
- }
- #region TraceCallerThread
- /// <summary>
- /// Enable
- /// </summary>
- internal bool TraceCallerThread
- {
- get { return traceCallerThread; }
- set { traceCallerThread = value; }
- }
- #endregion
- #region CallerThread
- internal Thread CallerThread
- {
- get { return callerThread; }
- }
- #endregion
- #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;
- case 13:
- if (Cel != null)
- {
- Cel(this, (CelEvent)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 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
- case 62:
- if (ConnectionState != null)
- {
- ConnectionState(this, (ConnectionStateEvent)e);
- return;
- }
- break;
- default:
- if (UnhandledEvent != null)
- UnhandledEvent(this, e);
- return;
- }
- }
- if (fireAllEvents && UnhandledEvent != null)
- UnhandledEvent(this, e);
- }
- #endregion
- #region FireAllEvents
- /// <summary>
- /// If this property set to <b>true</b> then ManagerConnection send all unassigned events to UnhandledEvent handler,<br/>
- /// if set to <b>false</b> then all unassgned events lost and send only UnhandledEvent.<br/>
- /// Default: <b>false</b>
- /// </summary>
- public bool FireAllEvents
- {
- get { return this.fireAllEvents; }
- set { this.fireAllEvents = value; }
- }
- #endregion
- #region PingInterval
- /// <summary>
- /// Timeout from Ping to Pong. If no Pong received send Disconnect event. Set to zero to disable.
- /// </summary>
- public int PingInterval
- {
- get { return pingInterval; }
- set { pingInterval = value; }
- }
- #endregion
- #region Hostname
- /// <summary> Sets the hostname of the asterisk server to connect to.<br/>
- /// Default is <code>localhost</code>.
- /// </summary>
- public string Hostname
- {
- get { return hostname; }
- set { hostname = value; }
- }
- #endregion
- #region Port
- /// <summary>
- /// Sets the port to use to connect to the asterisk server. This is the port
- /// specified in asterisk's <code>manager.conf</code> file.<br/>
- /// Default is 5038.
- /// </summary>
- public int Port
- {
- get { return port; }
- set { port = value; }
- }
- #endregion
- #region UserName
- /// <summary>
- /// Sets the username to use to connect to the asterisk server. This is the
- /// username specified in asterisk's <code>manager.conf</code> file.
- /// </summary>
- public string Username
- {
- get { return username; }
- set { username = value; }
- }
- #endregion
- #region Password
- /// <summary>
- /// Sets the password to use to connect to the asterisk server. This is the
- /// password specified in asterisk's <code>manager.conf</code> file.
- /// </summary>
- public string Password
- {
- get { return password; }
- set { password = value; }
- }
- #endregion
- #region DefaultResponseTimeout
- /// <summary> Sets the time in milliseconds the synchronous method
- /// will wait for a response before throwing a TimeoutException.<br/>
- /// Default is 2000.
- /// </summary>
- public int DefaultResponseTimeout
- {
- get { return defaultResponseTimeout; }
- set { defaultResponseTimeout = value; }
- }
- #endregion
- #region DefaultEventTimeout
- /// <summary> Sets the time in milliseconds the synchronous method
- /// will wait for a response and the last response event before throwing a TimeoutException.<br/>
- /// Default is 5000.
- /// </summary>
- public int DefaultEventTimeout
- {
- get { return defaultEventTimeout; }
- set { defaultEventTimeout = value; }
- }
- #endregion
- #region SleepTime
- /// <summary> 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.<br/>
- /// The sleepTime attribute is also used when checking for the protocol
- /// identifer.<br/>
- /// Default is 50.
- /// </summary>
- /// <deprecated> this has been replaced by an interrupt based response checking approach.</deprecated>
- public int SleepTime
- {
- get { return sleepTime; }
- set { sleepTime = value; }
- }
- #endregion
- #region KeepAliveAfterAuthenticationFailure
- /// <summary> Set to <code>true</code> to try reconnecting to ther asterisk serve
- /// even if the reconnection attempt threw an AuthenticationFailedException.<br/>
- /// Default is <code>false</code>.
- /// </summary>
- public bool KeepAliveAfterAuthenticationFailure
- {
- set { keepAliveAfterAuthenticationFailure = value; }
- get { return keepAliveAfterAuthenticationFailure; }
- }
- #endregion
- #region KeepAlive
- /// <summary>
- /// Should we attempt to reconnect when the connection is lost?<br/>
- /// This is set to <code>true</code> after successful login and to <code>false</code> after logoff or after an authentication failure when keepAliveAfterAuthenticationFailure is <code>false</code>.
- /// </summary>
- public bool KeepAlive
- {
- get { return keepAlive; }
- set { keepAlive = value; }
- }
- #endregion
- #region SocketEncoding
- /// <summary>
- /// Socket Encoding - default ASCII
- /// </summary>
- public Encoding SocketEncoding
- {
- get { return socketEncoding; }
- set { socketEncoding = value; }
- }
- #endregion
- #region Version
- public string Version
- {
- get { return version; }
- }
- #endregion
- #region AsteriskVersion
- public AsteriskVersion AsteriskVersion
- {
- get { return asteriskVersion; }
- }
- #endregion
- #region login(timeout)
- /// <summary>
- /// Does the real login, following the steps outlined below.<br/>
- /// Connects to the asterisk server by calling connect() if not already connected<br/>
- /// Waits until the protocol identifier is received. This is checked every sleepTime ms but not longer than timeout ms in total.<br/>
- /// Sends a ChallengeAction requesting a challenge for authType MD5.<br/>
- /// When the ChallengeResponse is received a LoginAction is sent using the calculated key (MD5 hash of the password appended to the received challenge).<br/>
- /// </summary>
- /// <param name="timeout">the maximum time to wait for the protocol identifier (in ms)</param>
- /// <throws>
- /// 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.
- /// </throws>
- /// <throws>
- /// 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.
- /// </throws>
- private void login(int timeout)
- {
- enableEvents = false;
- if (reconnected)
- {
- #if LOGGER
- logger.Error("Login during reconnect state.");
- #endif
- 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
- { }
- 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);
- #if LOGGER
- 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);
- }
- 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;
- #if LOGGER
- logger.Info("Successfully logged in");
- #endif
- asteriskVersion = determineVersion();
- #if LOGGER
- 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);
- }
- #endregion
- #region determineVersion()
- protected internal AsteriskVersion determineVersion()
- {
- // First try version check to 1.4 & 1.6
- 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."))
- return AsteriskVersion.ASTERISK_1_4;
- else if (version.StartsWith("1.6."))
- return AsteriskVersion.ASTERISK_1_6;
- else if (version.StartsWith("1.8."))
- return AsteriskVersion.ASTERISK_1_8;
- 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;
- }
- #endregion
- #region connect()
- protected internal bool connect()
- {
- bool result = false;
- bool startReader = false;
- lock (lockSocket)
- {
- if (mrSocket == null)
- {
- #if LOGGER
- logger.Info("Connecting to {0}:{1}", hostname, port);
- #endif
- try
- {
- mrSocket = new SocketConnection(hostname, port, socketEncoding);
- result = mrSocket.IsConnected;
- }
- #if LOGGER
- catch (Exception ex)
- {
- logger.Info("Connect - Exception : {0}", ex.Message);
- #else
- catch
- {
- #endif
- result = false;
- }
- if (result)
- {
- if (this.mrReader == null)
- {
- mrReader = new ManagerReader(this);
- mrReaderThread = new Util.ThreadClass(new ThreadStart(this.mrReader.Run), "ManagerReader-" + DateTime.Now.Second);
- mrReader.Socket = mrSocket;
- startReader = true;
- }
- else
- mrReader.Socket = mrSocket;
- mrReader.Reinitialize();
- }
- else
- mrSocket = null;
- }
- }
- if (startReader)
- mrReaderThread.Start();
- return IsConnected();
- }
- #endregion
- #region disconnect()
- /// <summary> Closes the socket connection.</summary>
- 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 (this.mrSocket != null)
- {
- mrSocket.Close();
- mrSocket = null;
- }
- responseEventHandlers.Clear();
- responseHandlers.Clear();
- pingHandlers.Clear();
- }
- }
- #endregion
- #region reconnect(bool init)
- /// <summary>
- /// Reconnects to the asterisk server when the connection is lost.<br/>
- /// While keepAlive is <code>true</code> 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.<br/>
- /// This method is called when a DisconnectEvent is received from the reader.
- /// </summary>
- private void reconnect(bool init)
- {
- #if LOGGER
- logger.Warning("reconnect (init: {0}), reconnectCount:{1}", init, reconnectCount);
- #endif
- if (init)
- reconnectCount = 0;
- else if (reconnectCount++ > reconnectRetryMax)
- reconnectEnable = false;
- if (reconnectEnable)
- {
- #if LOGGER
- logger.Warning("Try reconnect.");
- #endif
- enableEvents = false;
- reconnected = true;
- disconne…
Large files files are truncated, but you can click here to view the full file