PageRenderTime 60ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/Asterisk.NET/Manager/ManagerConnection.cs

https://github.com/pruiz/AsteriskDotNet
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

  1. using System;
  2. using System.IO;
  3. using System.Threading;
  4. using System.Collections;
  5. using Asterisk.NET.Manager.Action;
  6. using Asterisk.NET.Manager.Event;
  7. using Asterisk.NET.Manager.Response;
  8. using System.Text.RegularExpressions;
  9. using System.Text;
  10. using System.Net.Sockets;
  11. using System.Collections.Generic;
  12. using System.Reflection;
  13. using Asterisk.NET.IO;
  14. using Asterisk.NET.Util;
  15. namespace Asterisk.NET.Manager
  16. {
  17. #region Event delegate
  18. public delegate void ManagerEventHandler(object sender, ManagerEvent e);
  19. public delegate void AgentCallbackLoginEventHandler(object sender, Event.AgentCallbackLoginEvent e);
  20. public delegate void AgentCallbackLogoffEventHandler(object sender, Event.AgentCallbackLogoffEvent e);
  21. public delegate void AgentCalledEventHandler(object sender, Event.AgentCalledEvent e);
  22. public delegate void AgentCompleteEventHandler(object sender, Event.AgentCompleteEvent e);
  23. public delegate void AgentConnectEventHandler(object sender, Event.AgentConnectEvent e);
  24. public delegate void AgentDumpEventHandler(object sender, Event.AgentDumpEvent e);
  25. public delegate void AgentLoginEventHandler(object sender, Event.AgentLoginEvent e);
  26. public delegate void AgentLogoffEventHandler(object sender, Event.AgentLogoffEvent e);
  27. public delegate void AgentsCompleteEventHandler(object sender, Event.AgentsCompleteEvent e);
  28. public delegate void AgentsEventHandler(object sender, Event.AgentsEvent e);
  29. public delegate void AlarmClearEventHandler(object sender, Event.AlarmClearEvent e);
  30. public delegate void AlarmEventHandler(object sender, Event.AlarmEvent e);
  31. public delegate void CdrEventHandler(object sender, Event.CdrEvent e);
  32. public delegate void CelEventHandler(object sender, Event.CelEvent e);
  33. public delegate void DBGetResponseEventHandler(object sender, Event.DBGetResponseEvent e);
  34. public delegate void DialEventHandler(object sender, Event.DialEvent e);
  35. public delegate void DNDStateEventHandler(object sender, Event.DNDStateEvent e);
  36. public delegate void ExtensionStatusEventHandler(object sender, Event.ExtensionStatusEvent e);
  37. public delegate void HangupEventHandler(object sender, Event.HangupEvent e);
  38. public delegate void HoldedCallEventHandler(object sender, Event.HoldedCallEvent e);
  39. public delegate void HoldEventHandler(object sender, Event.HoldEvent e);
  40. public delegate void JoinEventHandler(object sender, Event.JoinEvent e);
  41. public delegate void LeaveEventHandler(object sender, Event.LeaveEvent e);
  42. public delegate void LinkEventHandler(object sender, Event.LinkEvent e);
  43. public delegate void LogChannelEventHandler(object sender, Event.LogChannelEvent e);
  44. public delegate void MeetMeJoinEventHandler(object sender, Event.MeetmeJoinEvent e);
  45. public delegate void MeetMeLeaveEventHandler(object sender, Event.MeetmeLeaveEvent e);
  46. public delegate void MeetMeTalkingEventHandler(object sender, Event.MeetmeTalkingEvent e);
  47. public delegate void MessageWaitingEventHandler(object sender, Event.MessageWaitingEvent e);
  48. public delegate void NewCallerIdEventHandler(object sender, Event.NewCallerIdEvent e);
  49. public delegate void NewChannelEventHandler(object sender, Event.NewChannelEvent e);
  50. public delegate void NewExtenEventHandler(object sender, Event.NewExtenEvent e);
  51. public delegate void NewStateEventHandler(object sender, Event.NewStateEvent e);
  52. public delegate void OriginateResponseEventHandler(object sender, Event.OriginateResponseEvent e);
  53. public delegate void ParkedCallEventHandler(object sender, Event.ParkedCallEvent e);
  54. public delegate void ParkedCallGiveUpEventHandler(object sender, Event.ParkedCallGiveUpEvent e);
  55. public delegate void ParkedCallsCompleteEventHandler(object sender, Event.ParkedCallsCompleteEvent e);
  56. public delegate void ParkedCallTimeOutEventHandler(object sender, Event.ParkedCallTimeOutEvent e);
  57. public delegate void PeerEntryEventHandler(object sender, Event.PeerEntryEvent e);
  58. public delegate void PeerlistCompleteEventHandler(object sender, Event.PeerlistCompleteEvent e);
  59. public delegate void PeerStatusEventHandler(object sender, Event.PeerStatusEvent e);
  60. public delegate void QueueEntryEventHandler(object sender, Event.QueueEntryEvent e);
  61. public delegate void QueueMemberAddedEventHandler(object sender, Event.QueueMemberAddedEvent e);
  62. public delegate void QueueMemberEventHandler(object sender, Event.QueueMemberEvent e);
  63. public delegate void QueueMemberPausedEventHandler(object sender, Event.QueueMemberPausedEvent e);
  64. public delegate void QueueMemberRemovedEventHandler(object sender, Event.QueueMemberRemovedEvent e);
  65. public delegate void QueueMemberStatusEventHandler(object sender, Event.QueueMemberStatusEvent e);
  66. public delegate void QueueParamsEventHandler(object sender, Event.QueueParamsEvent e);
  67. public delegate void QueueStatusCompleteEventHandler(object sender, Event.QueueStatusCompleteEvent e);
  68. public delegate void RegistryEventHandler(object sender, Event.RegistryEvent e);
  69. public delegate void RenameEventHandler(object sender, Event.RenameEvent e);
  70. public delegate void StatusCompleteEventHandler(object sender, Event.StatusCompleteEvent e);
  71. public delegate void StatusEventHandler(object sender, Event.StatusEvent e);
  72. public delegate void UnholdEventHandler(object sender, Event.UnholdEvent e);
  73. public delegate void UnlinkEventHandler(object sender, Event.UnlinkEvent e);
  74. public delegate void UnparkedCallEventHandler(object sender, Event.UnparkedCallEvent e);
  75. public delegate void UserEventHandler(object sender, Event.UserEvent e);
  76. public delegate void ZapShowChannelsCompleteEventHandler(object sender, Event.ZapShowChannelsCompleteEvent e);
  77. public delegate void ZapShowChannelsEventHandler(object sender, Event.ZapShowChannelsEvent e);
  78. public delegate void ConnectionStateEventHandler(object sender, Event.ConnectionStateEvent e);
  79. #endregion
  80. /// <summary>
  81. /// Default implemention of the ManagerConnection interface.
  82. /// </summary>
  83. public class ManagerConnection
  84. {
  85. #region Variables
  86. #if LOGGER
  87. private ILogger logger = Logger.Instance();
  88. #endif
  89. private long actionIdCount = 0;
  90. private string hostname;
  91. private int port;
  92. private string username;
  93. private string password;
  94. private SocketConnection mrSocket;
  95. private ThreadClass mrReaderThread;
  96. private ManagerReader mrReader;
  97. private int defaultResponseTimeout = 2000;
  98. private int defaultEventTimeout = 5000;
  99. private int sleepTime = 50;
  100. private bool keepAlive = true;
  101. private bool keepAliveAfterAuthenticationFailure = false;
  102. private string protocolIdentifier;
  103. private AsteriskVersion asteriskVersion;
  104. private Dictionary<int, IResponseHandler> responseHandlers;
  105. private Dictionary<int, IResponseHandler> pingHandlers;
  106. private Dictionary<int, IResponseHandler> responseEventHandlers;
  107. private int pingInterval = 10000;
  108. private object lockSocket = new object();
  109. private object lockHandlers = new object();
  110. private bool enableEvents = true;
  111. private string version = string.Empty;
  112. private Encoding socketEncoding = Encoding.ASCII;
  113. private bool reconnected = false;
  114. private bool reconnectEnable = false;
  115. private int reconnectCount;
  116. private Dictionary<int, ConstructorInfo> registeredEventClasses;
  117. private Dictionary<int, int> registeredEventHandlers;
  118. private event ManagerEventHandler internalEvent;
  119. private bool fireAllEvents = false;
  120. private Thread callerThread;
  121. private bool traceCallerThread = true;
  122. /// <summary> Default Fast Reconnect retry counter.</summary>
  123. private int reconnectRetryFast = 5;
  124. /// <summary> Default Maximum Reconnect retry counter.</summary>
  125. private int reconnectRetryMax = 10;
  126. /// <summary> Default Fast Reconnect interval in milliseconds.</summary>
  127. private int reconnectIntervalFast = 5000;
  128. /// <summary> Default Slow Reconnect interval in milliseconds.</summary>
  129. private int reconnectIntervalMax = 10000;
  130. #endregion
  131. #region Events
  132. /// <summary>
  133. /// An UnhandledEvent is triggered on unknown event.
  134. /// </summary>
  135. public event ManagerEventHandler UnhandledEvent;
  136. /// <summary>
  137. /// An AgentCallbackLogin is triggered when an agent is successfully logged in.
  138. /// </summary>
  139. public event AgentCallbackLoginEventHandler AgentCallbackLogin;
  140. /// <summary>
  141. /// An AgentCallbackLogoff is triggered when an agent that previously logged in is logged of.<br/>
  142. /// </summary>
  143. public event AgentCallbackLogoffEventHandler AgentCallbackLogoff;
  144. /// <summary>
  145. /// An AgentCalled is triggered when an agent is ring.<br/>
  146. /// To enable AgentCalled you have to set <code>eventwhencalled = yes</code> in <code>queues.conf</code>.<br/>
  147. /// </summary>
  148. public event AgentCalledEventHandler AgentCalled;
  149. /// <summary>
  150. /// An AgentCompleteEvent is triggered when at the end of a call if the caller was connected to an agent.
  151. /// </summary>
  152. public event AgentCompleteEventHandler AgentComplete;
  153. /// <summary>
  154. /// An AgentConnectEvent is triggered when a caller is connected to an agent.
  155. /// </summary>
  156. public event AgentConnectEventHandler AgentConnect;
  157. /// <summary>
  158. /// An AgentDumpEvent is triggered when an agent dumps the caller while listening to the queue announcement.
  159. /// </summary>
  160. public event AgentDumpEventHandler AgentDump;
  161. /// <summary>
  162. /// An AgentLoginEvent is triggered when an agent is successfully logged in using AgentLogin.
  163. /// </summary>
  164. public event AgentLoginEventHandler AgentLogin;
  165. /// <summary>
  166. /// An AgentCallbackLogoffEvent is triggered when an agent that previously logged in using AgentLogin is logged of.
  167. /// </summary>
  168. public event AgentLogoffEventHandler AgentLogoff;
  169. /// <summary>
  170. /// An AgentsCompleteEvent is triggered after the state of all agents has been reported in response to an AgentsAction.
  171. /// </summary>
  172. public event AgentsCompleteEventHandler AgentsComplete;
  173. /// <summary>
  174. /// An AgentsEvent is triggered for each agent in response to an AgentsAction.
  175. /// </summary>
  176. public event AgentsEventHandler Agents;
  177. /// <summary>
  178. /// An AlarmEvent is triggered when a Zap channel leaves alarm state.
  179. /// </summary>
  180. public event AlarmClearEventHandler AlarmClear;
  181. /// <summary>
  182. /// An AlarmEvent is triggered when a Zap channel enters or changes alarm state.
  183. /// </summary>
  184. public event AlarmEventHandler Alarm;
  185. public event CelEventHandler Cel;
  186. /// <summary>
  187. /// A CdrEvent is triggered when a call detail record is generated, usually at the end of a call.
  188. /// </summary>
  189. public event CdrEventHandler Cdr;
  190. public event DBGetResponseEventHandler DBGetResponse;
  191. /// <summary>
  192. /// A Dial is triggered whenever a phone attempts to dial someone.<br/>
  193. /// </summary>
  194. public event DialEventHandler Dial;
  195. /// <summary>
  196. /// A DNDStateEvent is triggered by the Zap channel driver when a channel enters or leaves DND (do not disturb) state.
  197. /// </summary>
  198. public event DNDStateEventHandler DNDState;
  199. /// <summary>
  200. /// An ExtensionStatus is triggered when the state of an extension changes.<br/>
  201. /// </summary>
  202. public event ExtensionStatusEventHandler ExtensionStatus;
  203. /// <summary>
  204. /// A Hangup is triggered when a channel is hung up.<br/>
  205. /// </summary>
  206. public event HangupEventHandler Hangup;
  207. /// <summary>
  208. /// A HoldedCall is triggered when a channel is put on hold.<br/>
  209. /// </summary>
  210. public event HoldedCallEventHandler HoldedCall;
  211. /// <summary>
  212. /// A Hold is triggered by the SIP channel driver when a channel is put on hold.<br/>
  213. /// </summary>
  214. public event HoldEventHandler Hold;
  215. /// <summary>
  216. /// A Join is triggered when a channel joines a queue.<br/>
  217. /// </summary>
  218. public event JoinEventHandler Join;
  219. /// <summary>
  220. /// A Leave is triggered when a channel leaves a queue.<br/>
  221. /// </summary>
  222. public event LeaveEventHandler Leave;
  223. /// <summary>
  224. /// A Link is triggered when two voice channels are linked together and voice data exchange commences.<br/>
  225. /// Several Link events may be seen for a single call. This can occur when Asterisk fails to setup a
  226. /// native bridge for the call.This is when Asterisk must sit between two telephones and perform
  227. /// CODEC conversion on their behalf.
  228. /// </summary>
  229. public event LinkEventHandler Link;
  230. /// <summary>
  231. /// A LogChannel is triggered when logging is turned on or off.<br/>
  232. /// </summary>
  233. public event LogChannelEventHandler LogChannel;
  234. /// <summary>
  235. /// A MeetMeJoin is triggered if a channel joins a meet me conference.<br/>
  236. /// </summary>
  237. public event MeetMeJoinEventHandler MeetMeJoin;
  238. /// <summary>
  239. /// A MeetMeLeave is triggered if a channel leaves a meet me conference.<br/>
  240. /// </summary>
  241. public event MeetMeLeaveEventHandler MeetMeLeave;
  242. // public event MeetMeStopTalkingEventHandler MeetMeStopTalking;
  243. /// <summary>
  244. /// A MeetMeTalkingEvent is triggered when a user starts talking in a meet me conference.<br/>
  245. /// To enable talker detection you must pass the option 'T' to the MeetMe application.
  246. /// </summary>
  247. public event MeetMeTalkingEventHandler MeetMeTalking;
  248. /// <summary>
  249. /// A MessageWaiting is triggered when someone leaves voicemail.<br/>
  250. /// </summary>
  251. public event MessageWaitingEventHandler MessageWaiting;
  252. /// <summary>
  253. /// A NewCallerId is triggered when the caller id of a channel changes.<br/>
  254. /// </summary>
  255. public event NewCallerIdEventHandler NewCallerId;
  256. /// <summary>
  257. /// A NewChannel is triggered when a new channel is created.<br/>
  258. /// </summary>
  259. public event NewChannelEventHandler NewChannel;
  260. /// <summary>
  261. /// A NewExten is triggered when a channel is connected to a new extension.<br/>
  262. /// </summary>
  263. public event NewExtenEventHandler NewExten;
  264. /// <summary>
  265. /// A NewState is triggered when the state of a channel has changed.<br/>
  266. /// </summary>
  267. public event NewStateEventHandler NewState;
  268. // public event OriginateEventHandler Originate;
  269. /// <summary>
  270. /// An OriginateFailure is triggered when the execution of an OriginateAction failed.
  271. /// </summary>
  272. // public event OriginateFailureEventHandler OriginateFailure;
  273. /// <summary>
  274. /// An OriginateSuccess is triggered when the execution of an OriginateAction succeeded.
  275. /// </summary>
  276. // public event OriginateSuccessEventHandler OriginateSuccess;
  277. /// <summary>
  278. /// An OriginateResponse is triggered when the execution of an Originate.
  279. /// </summary>
  280. public event OriginateResponseEventHandler OriginateResponse;
  281. /// <summary>
  282. /// A ParkedCall is triggered when a channel is parked (in this case no
  283. /// action id is set) and in response to a ParkedCallsAction.<br/>
  284. /// </summary>
  285. public event ParkedCallEventHandler ParkedCall;
  286. /// <summary>
  287. /// A ParkedCallGiveUp is triggered when a channel that has been parked is hung up.<br/>
  288. /// </summary>
  289. public event ParkedCallGiveUpEventHandler ParkedCallGiveUp;
  290. /// <summary>
  291. /// A ParkedCallsComplete is triggered after all parked calls have been reported in response to a ParkedCallsAction.
  292. /// </summary>
  293. public event ParkedCallsCompleteEventHandler ParkedCallsComplete;
  294. /// <summary>
  295. /// A ParkedCallTimeOut is triggered when call parking times out for a given channel.<br/>
  296. /// </summary>
  297. public event ParkedCallTimeOutEventHandler ParkedCallTimeOut;
  298. /// <summary>
  299. /// A PeerEntry is triggered in response to a SIPPeersAction or SIPShowPeerAction and contains information about a peer.<br/>
  300. /// </summary>
  301. public event PeerEntryEventHandler PeerEntry;
  302. /// <summary>
  303. /// A PeerlistComplete is triggered after the details of all peers has been reported in response to an SIPPeersAction or SIPShowPeerAction.<br/>
  304. /// </summary>
  305. public event PeerlistCompleteEventHandler PeerlistComplete;
  306. /// <summary>
  307. /// A PeerStatus is triggered when a SIP or IAX client attempts to registrer at this asterisk server.<br/>
  308. /// </summary>
  309. public event PeerStatusEventHandler PeerStatus;
  310. /// <summary>
  311. /// A QueueEntryEvent is triggered in response to a QueueStatusAction and contains information about an entry in a queue.
  312. /// </summary>
  313. public event QueueEntryEventHandler QueueEntry;
  314. /// <summary>
  315. /// A QueueMemberAddedEvent is triggered when a queue member is added to a queue.
  316. /// </summary>
  317. public event QueueMemberAddedEventHandler QueueMemberAdded;
  318. /// <summary>
  319. /// A QueueMemberEvent is triggered in response to a QueueStatusAction and contains information about a member of a queue.
  320. /// </summary>
  321. public event QueueMemberEventHandler QueueMember;
  322. /// <summary>
  323. /// A QueueMemberPausedEvent is triggered when a queue member is paused or unpaused.
  324. /// </summary>
  325. public event QueueMemberPausedEventHandler QueueMemberPaused;
  326. /// <summary>
  327. /// A QueueMemberRemovedEvent is triggered when a queue member is removed from a queue.
  328. /// </summary>
  329. public event QueueMemberRemovedEventHandler QueueMemberRemoved;
  330. /// <summary>
  331. /// A QueueMemberStatusEvent shows the status of a QueueMemberEvent.
  332. /// </summary>
  333. public event QueueMemberStatusEventHandler QueueMemberStatus;
  334. /// <summary>
  335. /// A QueueParamsEvent is triggered in response to a QueueStatusAction and contains the parameters of a queue.
  336. /// </summary>
  337. public event QueueParamsEventHandler QueueParams;
  338. /// <summary>
  339. /// A QueueStatusCompleteEvent is triggered after the state of all queues has been reported in response to a QueueStatusAction.
  340. /// </summary>
  341. public event QueueStatusCompleteEventHandler QueueStatusComplete;
  342. /// <summary>
  343. /// A Registry is triggered when this asterisk server attempts to register
  344. /// as a client at another SIP or IAX server.<br/>
  345. /// </summary>
  346. public event RegistryEventHandler Registry;
  347. /// <summary>
  348. /// A RenameEvent is triggered when the name of a channel is changed.
  349. /// </summary>
  350. public event RenameEventHandler Rename;
  351. /// <summary>
  352. /// A StatusCompleteEvent is triggered after the state of all channels has been reported in response to a StatusAction.
  353. /// </summary>
  354. public event StatusCompleteEventHandler StatusComplete;
  355. /// <summary>
  356. /// A StatusEvent is triggered for each active channel in response to a StatusAction.
  357. /// </summary>
  358. public event StatusEventHandler Status;
  359. /// <summary>
  360. /// An UnholdEvent is triggered by the SIP channel driver when a channel is no longer put on hold.
  361. /// </summary>
  362. public event UnholdEventHandler Unhold;
  363. /// <summary>
  364. /// An UnlinkEvent is triggered when a link between two voice channels is discontinued, for example, just before call completion.
  365. /// </summary>
  366. public event UnlinkEventHandler Unlink;
  367. /// <summary>
  368. /// A UnparkedCallEvent is triggered when a channel that has been parked is resumed.
  369. /// </summary>
  370. public event UnparkedCallEventHandler UnparkedCall;
  371. /// <summary>
  372. /// A ZapShowChannelsEvent is triggered on UserEvent in dialplan.
  373. /// </summary>
  374. public event UserEventHandler UserEvents;
  375. /// <summary>
  376. /// A ZapShowChannelsCompleteEvent is triggered after the state of all zap channels has been reported in response to a ZapShowChannelsAction.
  377. /// </summary>
  378. public event ZapShowChannelsCompleteEventHandler ZapShowChannelsComplete;
  379. /// <summary>
  380. /// A ZapShowChannelsEvent is triggered in response to a ZapShowChannelsAction and shows the state of a zap channel.
  381. /// </summary>
  382. public event ZapShowChannelsEventHandler ZapShowChannels;
  383. /// <summary>
  384. /// A ConnectionState is triggered after Connect/Disconnect/Reload/Shutdown events.
  385. /// </summary>
  386. public event ConnectionStateEventHandler ConnectionState;
  387. #endregion
  388. #region Constructor - ManagerConnection()
  389. /// <summary> Creates a new instance.</summary>
  390. public ManagerConnection()
  391. {
  392. callerThread = Thread.CurrentThread;
  393. socketEncoding = Encoding.ASCII;
  394. responseHandlers = new Dictionary<int, IResponseHandler>();
  395. pingHandlers = new Dictionary<int, IResponseHandler>();
  396. responseEventHandlers = new Dictionary<int, IResponseHandler>();
  397. registeredEventClasses = new Dictionary<int, ConstructorInfo>();
  398. Helper.RegisterBuiltinEventClasses(registeredEventClasses);
  399. registeredEventHandlers = new Dictionary<int, int>();
  400. #region Event mapping table
  401. Helper.RegisterEventHandler(registeredEventHandlers, 0, typeof(AgentCallbackLoginEvent));
  402. Helper.RegisterEventHandler(registeredEventHandlers, 1, typeof(AgentCallbackLogoffEvent));
  403. Helper.RegisterEventHandler(registeredEventHandlers, 2, typeof(AgentCalledEvent));
  404. Helper.RegisterEventHandler(registeredEventHandlers, 3, typeof(AgentCompleteEvent));
  405. Helper.RegisterEventHandler(registeredEventHandlers, 4, typeof(AgentConnectEvent));
  406. Helper.RegisterEventHandler(registeredEventHandlers, 5, typeof(AgentDumpEvent));
  407. Helper.RegisterEventHandler(registeredEventHandlers, 6, typeof(AgentLoginEvent));
  408. Helper.RegisterEventHandler(registeredEventHandlers, 7, typeof(AgentLogoffEvent));
  409. Helper.RegisterEventHandler(registeredEventHandlers, 8, typeof(AgentsCompleteEvent));
  410. Helper.RegisterEventHandler(registeredEventHandlers, 9, typeof(AgentsEvent));
  411. Helper.RegisterEventHandler(registeredEventHandlers, 10, typeof(AlarmClearEvent));
  412. Helper.RegisterEventHandler(registeredEventHandlers, 11, typeof(AlarmEvent));
  413. Helper.RegisterEventHandler(registeredEventHandlers, 12, typeof(CdrEvent));
  414. Helper.RegisterEventHandler(registeredEventHandlers, 13, typeof(CelEvent));
  415. Helper.RegisterEventHandler(registeredEventHandlers, 14, typeof(DBGetResponseEvent));
  416. Helper.RegisterEventHandler(registeredEventHandlers, 15, typeof(DialEvent));
  417. Helper.RegisterEventHandler(registeredEventHandlers, 17, typeof(DNDStateEvent));
  418. Helper.RegisterEventHandler(registeredEventHandlers, 18, typeof(ExtensionStatusEvent));
  419. Helper.RegisterEventHandler(registeredEventHandlers, 19, typeof(HangupEvent));
  420. Helper.RegisterEventHandler(registeredEventHandlers, 20, typeof(HoldedCallEvent));
  421. Helper.RegisterEventHandler(registeredEventHandlers, 21, typeof(HoldEvent));
  422. Helper.RegisterEventHandler(registeredEventHandlers, 22, typeof(JoinEvent));
  423. Helper.RegisterEventHandler(registeredEventHandlers, 23, typeof(LeaveEvent));
  424. Helper.RegisterEventHandler(registeredEventHandlers, 24, typeof(LinkEvent));
  425. Helper.RegisterEventHandler(registeredEventHandlers, 25, typeof(LogChannelEvent));
  426. Helper.RegisterEventHandler(registeredEventHandlers, 26, typeof(MeetmeJoinEvent));
  427. Helper.RegisterEventHandler(registeredEventHandlers, 27, typeof(MeetmeLeaveEvent));
  428. Helper.RegisterEventHandler(registeredEventHandlers, 28, typeof(MeetmeTalkingEvent));
  429. Helper.RegisterEventHandler(registeredEventHandlers, 29, typeof(MessageWaitingEvent));
  430. Helper.RegisterEventHandler(registeredEventHandlers, 30, typeof(NewCallerIdEvent));
  431. Helper.RegisterEventHandler(registeredEventHandlers, 31, typeof(NewChannelEvent));
  432. Helper.RegisterEventHandler(registeredEventHandlers, 32, typeof(NewExtenEvent));
  433. Helper.RegisterEventHandler(registeredEventHandlers, 33, typeof(NewStateEvent));
  434. Helper.RegisterEventHandler(registeredEventHandlers, 34, typeof(OriginateResponseEvent));
  435. Helper.RegisterEventHandler(registeredEventHandlers, 35, typeof(ParkedCallEvent));
  436. Helper.RegisterEventHandler(registeredEventHandlers, 36, typeof(ParkedCallGiveUpEvent));
  437. Helper.RegisterEventHandler(registeredEventHandlers, 37, typeof(ParkedCallsCompleteEvent));
  438. Helper.RegisterEventHandler(registeredEventHandlers, 38, typeof(ParkedCallTimeOutEvent));
  439. Helper.RegisterEventHandler(registeredEventHandlers, 39, typeof(PeerEntryEvent));
  440. Helper.RegisterEventHandler(registeredEventHandlers, 40, typeof(PeerlistCompleteEvent));
  441. Helper.RegisterEventHandler(registeredEventHandlers, 41, typeof(PeerStatusEvent));
  442. Helper.RegisterEventHandler(registeredEventHandlers, 42, typeof(QueueEntryEvent));
  443. Helper.RegisterEventHandler(registeredEventHandlers, 43, typeof(QueueMemberAddedEvent));
  444. Helper.RegisterEventHandler(registeredEventHandlers, 44, typeof(QueueMemberEvent));
  445. Helper.RegisterEventHandler(registeredEventHandlers, 45, typeof(QueueMemberPausedEvent));
  446. Helper.RegisterEventHandler(registeredEventHandlers, 46, typeof(QueueMemberRemovedEvent));
  447. Helper.RegisterEventHandler(registeredEventHandlers, 47, typeof(QueueMemberStatusEvent));
  448. Helper.RegisterEventHandler(registeredEventHandlers, 48, typeof(QueueParamsEvent));
  449. Helper.RegisterEventHandler(registeredEventHandlers, 49, typeof(QueueStatusCompleteEvent));
  450. Helper.RegisterEventHandler(registeredEventHandlers, 50, typeof(RegistryEvent));
  451. Helper.RegisterEventHandler(registeredEventHandlers, 52, typeof(RenameEvent));
  452. Helper.RegisterEventHandler(registeredEventHandlers, 54, typeof(StatusCompleteEvent));
  453. Helper.RegisterEventHandler(registeredEventHandlers, 55, typeof(StatusEvent));
  454. Helper.RegisterEventHandler(registeredEventHandlers, 56, typeof(UnholdEvent));
  455. Helper.RegisterEventHandler(registeredEventHandlers, 57, typeof(UnlinkEvent));
  456. Helper.RegisterEventHandler(registeredEventHandlers, 58, typeof(UnparkedCallEvent));
  457. Helper.RegisterEventHandler(registeredEventHandlers, 59, typeof(UserEvent));
  458. Helper.RegisterEventHandler(registeredEventHandlers, 60, typeof(ZapShowChannelsCompleteEvent));
  459. Helper.RegisterEventHandler(registeredEventHandlers, 61, typeof(ZapShowChannelsEvent));
  460. Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(ConnectEvent));
  461. Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(DisconnectEvent));
  462. Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(ReloadEvent));
  463. Helper.RegisterEventHandler(registeredEventHandlers, 62, typeof(ShutdownEvent));
  464. #endregion
  465. this.internalEvent += new ManagerEventHandler(internalEventHandler);
  466. }
  467. #endregion
  468. #region Constructor - ManagerConnection(hostname, port, username, password)
  469. /// <summary>
  470. /// Creates a new instance with the given connection parameters.
  471. /// </summary>
  472. /// <param name="hostname">the hosname of the Asterisk server to connect to.</param>
  473. /// <param name="port">the port where Asterisk listens for incoming Manager API connections, usually 5038.</param>
  474. /// <param name="username">the username to use for login</param>
  475. /// <param name="password">the password to use for login</param>
  476. public ManagerConnection(string hostname, int port, string username, string password)
  477. : this()
  478. {
  479. this.hostname = hostname;
  480. this.port = port;
  481. this.username = username;
  482. this.password = password;
  483. }
  484. #endregion
  485. #region Constructor - ManagerConnection(hostname, port, username, password, Encoding socketEncoding)
  486. /// <summary>
  487. /// Creates a new instance with the given connection parameters.
  488. /// </summary>
  489. /// <param name="hostname">the hosname of the Asterisk server to connect to.</param>
  490. /// <param name="port">the port where Asterisk listens for incoming Manager API connections, usually 5038.</param>
  491. /// <param name="username">the username to use for login</param>
  492. /// <param name="password">the password to use for login</param>
  493. /// <param name="socketEncoding">text encoding to asterisk input/output stream</param>
  494. public ManagerConnection(string hostname, int port, string username, string password, Encoding encoding)
  495. : this()
  496. {
  497. this.hostname = hostname;
  498. this.port = port;
  499. this.username = username;
  500. this.password = password;
  501. this.socketEncoding = encoding;
  502. }
  503. #endregion
  504. /// <summary>
  505. /// Default Fast Reconnect retry counter.
  506. /// </summary>
  507. public int ReconnectRetryFast
  508. {
  509. get { return reconnectRetryFast; }
  510. set { reconnectRetryFast = value; }
  511. }
  512. /// <summary> Default Maximum Reconnect retry counter.</summary>
  513. public int ReconnectRetryMax
  514. {
  515. get { return reconnectRetryMax; }
  516. set { reconnectRetryMax = value; }
  517. }
  518. /// <summary> Default Fast Reconnect interval in milliseconds.</summary>
  519. public int ReconnectIntervalFast
  520. {
  521. get { return reconnectIntervalFast; }
  522. set { reconnectIntervalFast = value; }
  523. }
  524. /// <summary> Default Slow Reconnect interval in milliseconds.</summary>
  525. public int ReconnectIntervalMax
  526. {
  527. get { return reconnectIntervalMax; }
  528. set { reconnectIntervalMax = value; }
  529. }
  530. #region TraceCallerThread
  531. /// <summary>
  532. /// Enable
  533. /// </summary>
  534. internal bool TraceCallerThread
  535. {
  536. get { return traceCallerThread; }
  537. set { traceCallerThread = value; }
  538. }
  539. #endregion
  540. #region CallerThread
  541. internal Thread CallerThread
  542. {
  543. get { return callerThread; }
  544. }
  545. #endregion
  546. #region internalEventHandler(object sender, ManagerEvent e)
  547. private void internalEventHandler(object sender, ManagerEvent e)
  548. {
  549. int eventHash = e.GetType().Name.GetHashCode();
  550. if (registeredEventHandlers.ContainsKey(eventHash))
  551. {
  552. switch (registeredEventHandlers[eventHash])
  553. {
  554. #region A-C
  555. case 0:
  556. if (AgentCallbackLogin != null)
  557. {
  558. AgentCallbackLogin(this, (AgentCallbackLoginEvent)e);
  559. return;
  560. }
  561. break;
  562. case 1:
  563. if (AgentCallbackLogoff != null)
  564. {
  565. AgentCallbackLogoff(this, (AgentCallbackLogoffEvent)e);
  566. return;
  567. }
  568. break;
  569. case 2:
  570. if (AgentCalled != null)
  571. {
  572. AgentCalled(this, (Event.AgentCalledEvent)e);
  573. return;
  574. }
  575. break;
  576. case 3:
  577. if (AgentComplete != null)
  578. {
  579. AgentComplete(this, (Event.AgentCompleteEvent)e);
  580. return;
  581. }
  582. break;
  583. case 4:
  584. if (AgentConnect != null)
  585. {
  586. AgentConnect(this, (Event.AgentConnectEvent)e);
  587. return;
  588. }
  589. break;
  590. case 5:
  591. if (AgentDump != null)
  592. {
  593. AgentDump(this, (Event.AgentDumpEvent)e);
  594. return;
  595. }
  596. break;
  597. case 6:
  598. if (AgentLogin != null)
  599. {
  600. AgentLogin(this, (Event.AgentLoginEvent)e);
  601. return;
  602. }
  603. break;
  604. case 7:
  605. if (AgentLogoff != null)
  606. {
  607. AgentLogoff(this, (Event.AgentLogoffEvent)e);
  608. return;
  609. }
  610. break;
  611. case 8:
  612. if (AgentsComplete != null)
  613. {
  614. AgentsComplete(this, (AgentsCompleteEvent)e);
  615. return;
  616. }
  617. break;
  618. case 9:
  619. if (Agents != null)
  620. {
  621. Agents(this, (AgentsEvent)e);
  622. return;
  623. }
  624. break;
  625. case 10:
  626. if (AlarmClear != null)
  627. {
  628. AlarmClear(this, (AlarmClearEvent)e);
  629. return;
  630. }
  631. break;
  632. case 11:
  633. if (Alarm != null)
  634. {
  635. Alarm(this, (AlarmEvent)e);
  636. return;
  637. }
  638. break;
  639. case 12:
  640. if (Cdr != null)
  641. {
  642. Cdr(this, (CdrEvent)e);
  643. return;
  644. }
  645. break;
  646. case 13:
  647. if (Cel != null)
  648. {
  649. Cel(this, (CelEvent)e);
  650. return;
  651. }
  652. break;
  653. #endregion
  654. #region D-L
  655. case 14:
  656. if (DBGetResponse != null)
  657. {
  658. DBGetResponse(this, (DBGetResponseEvent)e);
  659. return;
  660. }
  661. break;
  662. case 15:
  663. if (Dial != null)
  664. {
  665. Dial(this, (DialEvent)e);
  666. return;
  667. }
  668. break;
  669. case 17:
  670. if (DNDState != null)
  671. {
  672. DNDState(this, (DNDStateEvent)e);
  673. return;
  674. }
  675. break;
  676. case 18:
  677. if (ExtensionStatus != null)
  678. {
  679. ExtensionStatus(this, (ExtensionStatusEvent)e);
  680. return;
  681. }
  682. break;
  683. case 19:
  684. if (Hangup != null)
  685. {
  686. Hangup(this, (HangupEvent)e);
  687. return;
  688. }
  689. break;
  690. case 20:
  691. if (HoldedCall != null)
  692. {
  693. HoldedCall(this, (HoldedCallEvent)e);
  694. return;
  695. }
  696. break;
  697. case 21:
  698. if (Hold != null)
  699. {
  700. Hold(this, (HoldEvent)e);
  701. return;
  702. }
  703. break;
  704. case 22:
  705. if (Join != null)
  706. {
  707. Join(this, (JoinEvent)e);
  708. return;
  709. }
  710. break;
  711. case 23:
  712. if (Leave != null)
  713. {
  714. Leave(this, (LeaveEvent)e);
  715. return;
  716. }
  717. break;
  718. case 24:
  719. if (Link != null)
  720. {
  721. Link(this, (LinkEvent)e);
  722. return;
  723. }
  724. break;
  725. case 25:
  726. if (LogChannel != null)
  727. {
  728. LogChannel(this, (LogChannelEvent)e);
  729. return;
  730. }
  731. break;
  732. #endregion
  733. #region M-P
  734. case 26:
  735. if (MeetMeJoin != null)
  736. {
  737. MeetMeJoin(this, (MeetmeJoinEvent)e);
  738. return;
  739. }
  740. break;
  741. case 27:
  742. if (MeetMeLeave != null)
  743. {
  744. MeetMeLeave(this, (MeetmeLeaveEvent)e);
  745. return;
  746. }
  747. break;
  748. case 28:
  749. if (MeetMeTalking != null)
  750. {
  751. MeetMeTalking(this, (MeetmeTalkingEvent)e);
  752. return;
  753. }
  754. break;
  755. case 29:
  756. if (MessageWaiting != null)
  757. {
  758. MessageWaiting(this, (MessageWaitingEvent)e);
  759. return;
  760. }
  761. break;
  762. case 30:
  763. if (NewCallerId != null)
  764. {
  765. NewCallerId(this, (NewCallerIdEvent)e);
  766. return;
  767. }
  768. break;
  769. case 31:
  770. if (NewChannel != null)
  771. {
  772. NewChannel(this, (NewChannelEvent)e);
  773. return;
  774. }
  775. break;
  776. case 32:
  777. if (NewExten != null)
  778. {
  779. NewExten(this, (NewExtenEvent)e);
  780. return;
  781. }
  782. break;
  783. case 33:
  784. if (NewState != null)
  785. {
  786. NewState(this, (NewStateEvent)e);
  787. return;
  788. }
  789. break;
  790. case 34:
  791. if (OriginateResponse != null)
  792. {
  793. OriginateResponse(this, (OriginateResponseEvent)e);
  794. return;
  795. }
  796. break;
  797. case 35:
  798. if (ParkedCall != null)
  799. {
  800. ParkedCall(this, (ParkedCallEvent)e);
  801. return;
  802. }
  803. break;
  804. case 36:
  805. if (ParkedCallGiveUp != null)
  806. {
  807. ParkedCallGiveUp(this, (ParkedCallGiveUpEvent)e);
  808. return;
  809. }
  810. break;
  811. case 37:
  812. if (ParkedCallsComplete != null)
  813. {
  814. ParkedCallsComplete(this, (ParkedCallsCompleteEvent)e);
  815. return;
  816. }
  817. break;
  818. case 38:
  819. if (ParkedCallTimeOut != null)
  820. {
  821. ParkedCallTimeOut(this, (ParkedCallTimeOutEvent)e);
  822. return;
  823. }
  824. break;
  825. case 39:
  826. if (PeerEntry != null)
  827. {
  828. PeerEntry(this, (PeerEntryEvent)e);
  829. return;
  830. }
  831. break;
  832. case 40:
  833. if (PeerlistComplete != null)
  834. {
  835. PeerlistComplete(this, (PeerlistCompleteEvent)e);
  836. return;
  837. }
  838. break;
  839. case 41:
  840. if (PeerStatus != null)
  841. {
  842. PeerStatus(this, (PeerStatusEvent)e);
  843. return;
  844. }
  845. break;
  846. #endregion
  847. #region Q-Z
  848. case 42:
  849. if (QueueEntry != null)
  850. {
  851. QueueEntry(this, (QueueEntryEvent)e);
  852. return;
  853. }
  854. break;
  855. case 43:
  856. if (QueueMemberAdded != null)
  857. {
  858. QueueMemberAdded(this, (QueueMemberAddedEvent)e);
  859. return;
  860. }
  861. break;
  862. case 44:
  863. if (QueueMember != null)
  864. {
  865. QueueMember(this, (QueueMemberEvent)e);
  866. return;
  867. }
  868. break;
  869. case 45:
  870. if (QueueMemberPaused != null)
  871. {
  872. QueueMemberPaused(this, (QueueMemberPausedEvent)e);
  873. return;
  874. }
  875. break;
  876. case 46:
  877. if (QueueMemberRemoved != null)
  878. {
  879. QueueMemberRemoved(this, (QueueMemberRemovedEvent)e);
  880. return;
  881. }
  882. break;
  883. case 47:
  884. if (QueueMemberStatus != null)
  885. {
  886. QueueMemberStatus(this, (QueueMemberStatusEvent)e);
  887. return;
  888. }
  889. break;
  890. case 48:
  891. if (QueueParams != null)
  892. {
  893. QueueParams(this, (QueueParamsEvent)e);
  894. return;
  895. }
  896. break;
  897. case 49:
  898. if (QueueStatusComplete != null)
  899. {
  900. QueueStatusComplete(this, (QueueStatusCompleteEvent)e);
  901. return;
  902. }
  903. break;
  904. case 50:
  905. if (Registry != null)
  906. {
  907. Registry(this, (RegistryEvent)e);
  908. return;
  909. }
  910. break;
  911. case 52:
  912. if (Rename != null)
  913. {
  914. Rename(this, (RenameEvent)e);
  915. return;
  916. }
  917. break;
  918. case 54:
  919. if (StatusComplete != null)
  920. {
  921. StatusComplete(this, (StatusCompleteEvent)e);
  922. return;
  923. }
  924. break;
  925. case 55:
  926. if (Status != null)
  927. {
  928. Status(this, (StatusEvent)e);
  929. return;
  930. }
  931. break;
  932. case 56:
  933. if (Unhold != null)
  934. {
  935. Unhold(this, (UnholdEvent)e);
  936. return;
  937. }
  938. break;
  939. case 57:
  940. if (Unlink != null)
  941. {
  942. Unlink(this, (UnlinkEvent)e);
  943. return;
  944. }
  945. break;
  946. case 58:
  947. if (UnparkedCall != null)
  948. {
  949. UnparkedCall(this, (UnparkedCallEvent)e);
  950. return;
  951. }
  952. break;
  953. case 59:
  954. if (UserEvents != null)
  955. {
  956. UserEvents(this, (UserEvent)e);
  957. return;
  958. }
  959. break;
  960. case 60:
  961. if (ZapShowChannelsComplete != null)
  962. {
  963. ZapShowChannelsComplete(this, (ZapShowChannelsCompleteEvent)e);
  964. return;
  965. }
  966. break;
  967. case 61:
  968. if (ZapShowChannels != null)
  969. {
  970. ZapShowChannels(this, (ZapShowChannelsEvent)e);
  971. return;
  972. }
  973. break;
  974. #endregion
  975. case 62:
  976. if (ConnectionState != null)
  977. {
  978. ConnectionState(this, (ConnectionStateEvent)e);
  979. return;
  980. }
  981. break;
  982. default:
  983. if (UnhandledEvent != null)
  984. UnhandledEvent(this, e);
  985. return;
  986. }
  987. }
  988. if (fireAllEvents && UnhandledEvent != null)
  989. UnhandledEvent(this, e);
  990. }
  991. #endregion
  992. #region FireAllEvents
  993. /// <summary>
  994. /// If this property set to <b>true</b> then ManagerConnection send all unassigned events to UnhandledEvent handler,<br/>
  995. /// if set to <b>false</b> then all unassgned events lost and send only UnhandledEvent.<br/>
  996. /// Default: <b>false</b>
  997. /// </summary>
  998. public bool FireAllEvents
  999. {
  1000. get { return this.fireAllEvents; }
  1001. set { this.fireAllEvents = value; }
  1002. }
  1003. #endregion
  1004. #region PingInterval
  1005. /// <summary>
  1006. /// Timeout from Ping to Pong. If no Pong received send Disconnect event. Set to zero to disable.
  1007. /// </summary>
  1008. public int PingInterval
  1009. {
  1010. get { return pingInterval; }
  1011. set { pingInterval = value; }
  1012. }
  1013. #endregion
  1014. #region Hostname
  1015. /// <summary> Sets the hostname of the asterisk server to connect to.<br/>
  1016. /// Default is <code>localhost</code>.
  1017. /// </summary>
  1018. public string Hostname
  1019. {
  1020. get { return hostname; }
  1021. set { hostname = value; }
  1022. }
  1023. #endregion
  1024. #region Port
  1025. /// <summary>
  1026. /// Sets the port to use to connect to the asterisk server. This is the port
  1027. /// specified in asterisk's <code>manager.conf</code> file.<br/>
  1028. /// Default is 5038.
  1029. /// </summary>
  1030. public int Port
  1031. {
  1032. get { return port; }
  1033. set { port = value; }
  1034. }
  1035. #endregion
  1036. #region UserName
  1037. /// <summary>
  1038. /// Sets the username to use to connect to the asterisk server. This is the
  1039. /// username specified in asterisk's <code>manager.conf</code> file.
  1040. /// </summary>
  1041. public string Username
  1042. {
  1043. get { return username; }
  1044. set { username = value; }
  1045. }
  1046. #endregion
  1047. #region Password
  1048. /// <summary>
  1049. /// Sets the password to use to connect to the asterisk server. This is the
  1050. /// password specified in asterisk's <code>manager.conf</code> file.
  1051. /// </summary>
  1052. public string Password
  1053. {
  1054. get { return password; }
  1055. set { password = value; }
  1056. }
  1057. #endregion
  1058. #region DefaultResponseTimeout
  1059. /// <summary> Sets the time in milliseconds the synchronous method
  1060. /// will wait for a response before throwing a TimeoutException.<br/>
  1061. /// Default is 2000.
  1062. /// </summary>
  1063. public int DefaultResponseTimeout
  1064. {
  1065. get { return defaultResponseTimeout; }
  1066. set { defaultResponseTimeout = value; }
  1067. }
  1068. #endregion
  1069. #region DefaultEventTimeout
  1070. /// <summary> Sets the time in milliseconds the synchronous method
  1071. /// will wait for a response and the last response event before throwing a TimeoutException.<br/>
  1072. /// Default is 5000.
  1073. /// </summary>
  1074. public int DefaultEventTimeout
  1075. {
  1076. get { return defaultEventTimeout; }
  1077. set { defaultEventTimeout = value; }
  1078. }
  1079. #endregion
  1080. #region SleepTime
  1081. /// <summary> Sets the time in milliseconds the synchronous methods
  1082. /// SendAction(Action.ManagerAction) and
  1083. /// SendAction(Action.ManagerAction, long) will sleep between two checks
  1084. /// for the arrival of a response. This value should be rather small.<br/>
  1085. /// The sleepTime attribute is also used when checking for the protocol
  1086. /// identifer.<br/>
  1087. /// Default is 50.
  1088. /// </summary>
  1089. /// <deprecated> this has been replaced by an interrupt based response checking approach.</deprecated>
  1090. public int SleepTime
  1091. {
  1092. get { return sleepTime; }
  1093. set { sleepTime = value; }
  1094. }
  1095. #endregion
  1096. #region KeepAliveAfterAuthenticationFailure
  1097. /// <summary> Set to <code>true</code> to try reconnecting to ther asterisk serve
  1098. /// even if the reconnection attempt threw an AuthenticationFailedException.<br/>
  1099. /// Default is <code>false</code>.
  1100. /// </summary>
  1101. public bool KeepAliveAfterAuthenticationFailure
  1102. {
  1103. set { keepAliveAfterAuthenticationFailure = value; }
  1104. get { return keepAliveAfterAuthenticationFailure; }
  1105. }
  1106. #endregion
  1107. #region KeepAlive
  1108. /// <summary>
  1109. /// Should we attempt to reconnect when the connection is lost?<br/>
  1110. /// 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>.
  1111. /// </summary>
  1112. public bool KeepAlive
  1113. {
  1114. get { return keepAlive; }
  1115. set { keepAlive = value; }
  1116. }
  1117. #endregion
  1118. #region SocketEncoding
  1119. /// <summary>
  1120. /// Socket Encoding - default ASCII
  1121. /// </summary>
  1122. public Encoding SocketEncoding
  1123. {
  1124. get { return socketEncoding; }
  1125. set { socketEncoding = value; }
  1126. }
  1127. #endregion
  1128. #region Version
  1129. public string Version
  1130. {
  1131. get { return version; }
  1132. }
  1133. #endregion
  1134. #region AsteriskVersion
  1135. public AsteriskVersion AsteriskVersion
  1136. {
  1137. get { return asteriskVersion; }
  1138. }
  1139. #endregion
  1140. #region login(timeout)
  1141. /// <summary>
  1142. /// Does the real login, following the steps outlined below.<br/>
  1143. /// Connects to the asterisk server by calling connect() if not already connected<br/>
  1144. /// Waits until the protocol identifier is received. This is checked every sleepTime ms but not longer than timeout ms in total.<br/>
  1145. /// Sends a ChallengeAction requesting a challenge for authType MD5.<br/>
  1146. /// When the ChallengeResponse is received a LoginAction is sent using the calculated key (MD5 hash of the password appended to the received challenge).<br/>
  1147. /// </summary>
  1148. /// <param name="timeout">the maximum time to wait for the protocol identifier (in ms)</param>
  1149. /// <throws>
  1150. /// AuthenticationFailedException if username or password are incorrect and the login action returns an error or if the MD5
  1151. /// hash cannot be computed. The connection is closed in this case.
  1152. /// </throws>
  1153. /// <throws>
  1154. /// TimeoutException if a timeout occurs either while waiting for the
  1155. /// protocol identifier or when sending the challenge or login
  1156. /// action. The connection is closed in this case.
  1157. /// </throws>
  1158. private void login(int timeout)
  1159. {
  1160. enableEvents = false;
  1161. if (reconnected)
  1162. {
  1163. #if LOGGER
  1164. logger.Error("Login during reconnect state.");
  1165. #endif
  1166. throw new AuthenticationFailedException("Unable login during reconnect state.");
  1167. }
  1168. reconnectEnable = false;
  1169. DateTime start = DateTime.Now;
  1170. do
  1171. {
  1172. if (connect())
  1173. {
  1174. // Increase delay after connection up to 500 ms
  1175. Thread.Sleep(10 * sleepTime); // 200 milliseconds delay
  1176. }
  1177. try
  1178. {
  1179. Thread.Sleep(4 * sleepTime); // 200 milliseconds delay
  1180. }
  1181. catch
  1182. { }
  1183. if (string.IsNullOrEmpty(protocolIdentifier) && timeout > 0 && Helper.GetMillisecondsFrom(start) > timeout)
  1184. {
  1185. disconnect(true);
  1186. throw new TimeoutException("Timeout waiting for protocol identifier");
  1187. }
  1188. } while (string.IsNullOrEmpty(protocolIdentifier));
  1189. ChallengeAction challengeAction = new ChallengeAction();
  1190. Response.ManagerResponse response = SendAction(challengeAction, defaultResponseTimeout * 2);
  1191. if (response is ChallengeResponse)
  1192. {
  1193. ChallengeResponse challengeResponse = (ChallengeResponse)response;
  1194. string key, challenge = challengeResponse.Challenge;
  1195. try
  1196. {
  1197. Util.MD5Support md = Util.MD5Support.GetInstance();
  1198. if (challenge != null)
  1199. md.Update(UTF8Encoding.UTF8.GetBytes(challenge));
  1200. if (password != null)
  1201. md.Update(UTF8Encoding.UTF8.GetBytes(password));
  1202. key = Helper.ToHexString(md.DigestData);
  1203. }
  1204. catch (Exception ex)
  1205. {
  1206. disconnect(true);
  1207. #if LOGGER
  1208. logger.Error("Unable to create login key using MD5 Message Digest.", ex);
  1209. #endif
  1210. throw new AuthenticationFailedException("Unable to create login key using MD5 Message Digest.", ex);
  1211. }
  1212. Action.LoginAction loginAction = new Action.LoginAction(username, "MD5", key);
  1213. Response.ManagerResponse loginResponse = SendAction(loginAction);
  1214. if (loginResponse is Response.ManagerError)
  1215. {
  1216. disconnect(true);
  1217. throw new AuthenticationFailedException(loginResponse.Message);
  1218. }
  1219. // successfully logged in so assure that we keep trying to reconnect when disconnected
  1220. reconnectEnable = keepAlive;
  1221. #if LOGGER
  1222. logger.Info("Successfully logged in");
  1223. #endif
  1224. asteriskVersion = determineVersion();
  1225. #if LOGGER
  1226. logger.Info("Determined Asterisk version: " + asteriskVersion);
  1227. #endif
  1228. enableEvents = true;
  1229. ConnectEvent ce = new ConnectEvent(this);
  1230. ce.ProtocolIdentifier = this.protocolIdentifier;
  1231. DispatchEvent(ce);
  1232. }
  1233. else if (response is ManagerError)
  1234. throw new ManagerException("Unable login to Asterisk - " + response.Message);
  1235. else
  1236. throw new ManagerException("Unknown response during login to Asterisk - " + response.GetType().Name + " with message " + response.Message);
  1237. }
  1238. #endregion
  1239. #region determineVersion()
  1240. protected internal AsteriskVersion determineVersion()
  1241. {
  1242. // First try version check to 1.4 & 1.6
  1243. Response.ManagerResponse response;
  1244. response = SendAction(new Action.CommandAction("core show version"), defaultResponseTimeout * 2);
  1245. if (response is Response.CommandResponse)
  1246. {
  1247. foreach (string line in ((Response.CommandResponse)response).Result)
  1248. {
  1249. foreach (Match m in Common.ASTERISK_VERSION.Matches(line))
  1250. {
  1251. if (m.Groups.Count >= 2)
  1252. {
  1253. version = m.Groups[1].Value;
  1254. if (version.StartsWith("1.4."))
  1255. return AsteriskVersion.ASTERISK_1_4;
  1256. else if (version.StartsWith("1.6."))
  1257. return AsteriskVersion.ASTERISK_1_6;
  1258. else if (version.StartsWith("1.8."))
  1259. return AsteriskVersion.ASTERISK_1_8;
  1260. else
  1261. throw new ManagerException("Unknown Asterisk version " + version);
  1262. }
  1263. }
  1264. }
  1265. }
  1266. Response.ManagerResponse showVersionFilesResponse = SendAction(new Action.CommandAction("show version files"), defaultResponseTimeout * 2);
  1267. if (showVersionFilesResponse is Response.CommandResponse)
  1268. {
  1269. IList showVersionFilesResult = ((Response.CommandResponse)showVersionFilesResponse).Result;
  1270. if (showVersionFilesResult != null && showVersionFilesResult.Count > 0)
  1271. {
  1272. string line1;
  1273. line1 = (string)showVersionFilesResult[0];
  1274. if (line1 != null && line1.StartsWith("File"))
  1275. return AsteriskVersion.ASTERISK_1_2;
  1276. }
  1277. }
  1278. return AsteriskVersion.ASTERISK_1_0;
  1279. }
  1280. #endregion
  1281. #region connect()
  1282. protected internal bool connect()
  1283. {
  1284. bool result = false;
  1285. bool startReader = false;
  1286. lock (lockSocket)
  1287. {
  1288. if (mrSocket == null)
  1289. {
  1290. #if LOGGER
  1291. logger.Info("Connecting to {0}:{1}", hostname, port);
  1292. #endif
  1293. try
  1294. {
  1295. mrSocket = new SocketConnection(hostname, port, socketEncoding);
  1296. result = mrSocket.IsConnected;
  1297. }
  1298. #if LOGGER
  1299. catch (Exception ex)
  1300. {
  1301. logger.Info("Connect - Exception : {0}", ex.Message);
  1302. #else
  1303. catch
  1304. {
  1305. #endif
  1306. result = false;
  1307. }
  1308. if (result)
  1309. {
  1310. if (this.mrReader == null)
  1311. {
  1312. mrReader = new ManagerReader(this);
  1313. mrReaderThread = new Util.ThreadClass(new ThreadStart(this.mrReader.Run), "ManagerReader-" + DateTime.Now.Second);
  1314. mrReader.Socket = mrSocket;
  1315. startReader = true;
  1316. }
  1317. else
  1318. mrReader.Socket = mrSocket;
  1319. mrReader.Reinitialize();
  1320. }
  1321. else
  1322. mrSocket = null;
  1323. }
  1324. }
  1325. if (startReader)
  1326. mrReaderThread.Start();
  1327. return IsConnected();
  1328. }
  1329. #endregion
  1330. #region disconnect()
  1331. /// <summary> Closes the socket connection.</summary>
  1332. private void disconnect(bool withDie)
  1333. {
  1334. lock (lockSocket)
  1335. {
  1336. if (withDie)
  1337. {
  1338. reconnectEnable = false;
  1339. reconnected = false;
  1340. enableEvents = true;
  1341. }
  1342. if (mrReader != null)
  1343. {
  1344. if (withDie)
  1345. {
  1346. mrReader.Die = true;
  1347. mrReader = null;
  1348. }
  1349. else
  1350. mrReader.Socket = null;
  1351. }
  1352. if (this.mrSocket != null)
  1353. {
  1354. mrSocket.Close();
  1355. mrSocket = null;
  1356. }
  1357. responseEventHandlers.Clear();
  1358. responseHandlers.Clear();
  1359. pingHandlers.Clear();
  1360. }
  1361. }
  1362. #endregion
  1363. #region reconnect(bool init)
  1364. /// <summary>
  1365. /// Reconnects to the asterisk server when the connection is lost.<br/>
  1366. /// While keepAlive is <code>true</code> we will try to reconnect.
  1367. /// Reconnection attempts will be stopped when the logoff() method
  1368. /// is called or when the login after a successful reconnect results in an
  1369. /// AuthenticationFailedException suggesting that the manager
  1370. /// credentials have changed and keepAliveAfterAuthenticationFailure is not set.<br/>
  1371. /// This method is called when a DisconnectEvent is received from the reader.
  1372. /// </summary>
  1373. private void reconnect(bool init)
  1374. {
  1375. #if LOGGER
  1376. logger.Warning("reconnect (init: {0}), reconnectCount:{1}", init, reconnectCount);
  1377. #endif
  1378. if (init)
  1379. reconnectCount = 0;
  1380. else if (reconnectCount++ > reconnectRetryMax)
  1381. reconnectEnable = false;
  1382. if (reconnectEnable)
  1383. {
  1384. #if LOGGER
  1385. logger.Warning("Try reconnect.");
  1386. #endif
  1387. enableEvents = false;
  1388. reconnected = true;
  1389. disconne

Large files files are truncated, but you can click here to view the full file