<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][16212] </title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=16212">16212</a></dd>
<dt>Author</dt> <dd>verifier</dd>
<dt>Date</dt> <dd>2010-01-08 10:38:57 -0600 (Fri, 08 Jan 2010)</dd>
</dl>
<h3>Log Message</h3>
<pre>Bugfixes and a fix when FS reports incorrect content-length.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunkcontribverifierEventSockettrunkFreeSwitchEventSocketEventParsercs">freeswitch/trunk/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventParser.cs</a></li>
<li><a href="#freeswitchtrunkcontribverifierEventSockettrunkFreeSwitchEventSocketEventSocketcs">freeswitch/trunk/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventSocket.cs</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunkcontribverifierEventSockettrunkFreeSwitchEventSocketEventParsercs"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventParser.cs (16211 => 16212)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventParser.cs        2010-01-08 16:31:56 UTC (rev 16211)
+++ freeswitch/trunk/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventParser.cs        2010-01-08 16:38:57 UTC (rev 16212)
</span><span class="lines">@@ -79,25 +79,21 @@
</span><span class="cx"> _text.Append(_piecesToAppend.Dequeue());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+                        if (_text.Length == 0)
+                                return null;
+
</ins><span class="cx"> PlainEventMsg plainEvent;
</span><span class="cx"> lock (_text)
</span><span class="cx"> {
</span><del>- int i = 0;
</del><ins>+         int i = 0;
+                                IgnoreLineBreaks(ref i);
+         _text.Remove(0, i);
</ins><span class="cx">
</span><del>- // find complete header
- bool found = false;
- for (; i < _text.Length - 1; ++i)
- {
- if (_text[i] == '\n' && _text[i + 1] == '\n')
- {
- found = true;
- break;
- }
- }
- if (!found)
- return null;
</del><ins>+         i = FindEmptyLine(i);
+                                if (i == -1)
+                                        return null;
</ins><span class="cx">
</span><del>- // extract header
</del><ins>+         // extract header
</ins><span class="cx"> char[] chars = new char[i];
</span><span class="cx"> _text.CopyTo(0, chars, 0, i);
</span><span class="cx"> string headers = new string(chars);
</span><span class="lines">@@ -114,7 +110,7 @@
</span><span class="cx"> // this will eat that kind of header.
</span><span class="cx"> if (_text.Length >= BugWorkaround.Length + i)
</span><span class="cx"> {
</span><del>- found = true;
</del><ins>+ bool found = true;
</ins><span class="cx"> for (int index = 0; index < BugWorkaround.Length; ++index)
</span><span class="cx"> {
</span><span class="cx"> if (_text[index + i] != BugWorkaround[index])
</span><span class="lines">@@ -137,8 +133,18 @@
</span><span class="cx"> return null;
</span><span class="cx">
</span><span class="cx"> // extract body
</span><del>- chars = new char[plainEvent.ContentLength];
- _text.CopyTo(i, chars, 0, plainEvent.ContentLength);
</del><ins>+
+                                        // since Freeswitch report false sizes sometimes,
+                                        // we need to go through all lines to find contents.
+         int endOfBody = FindEmptyLine(i) + 2; // include the first and last \n
+                                        if (endOfBody-i != plainEvent.ContentLength)
+                                        {
+                                                Console.WriteLine("Invalid content length, actual length: " + (endOfBody - i) + ", reported length: " +
+                                                 plainEvent.ContentLength);
+                                                plainEvent.ContentLength = endOfBody - i;
+                                        }
+                                        chars = new char[plainEvent.ContentLength];
+                                        _text.CopyTo(i, chars, 0, plainEvent.ContentLength);
</ins><span class="cx"> plainEvent.Body = new string(chars);
</span><span class="cx">
</span><span class="cx"> // api/response is buggy for originate, no \n\n are appended at the end.
</span><span class="lines">@@ -175,8 +181,18 @@
</span><span class="cx"> return plainEvent;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+         private int FindEmptyLine(int i)
+         {
+                 for (; i < _text.Length - 1; ++i)
+                 {
+                         if (_text[i] == '\n' && _text[i + 1] == '\n')
+                                 return i;
+                 }
+                 return -1;
+         }
</ins><span class="cx">
</span><del>- public void Append(string text)
</del><ins>+
+         public void Append(string text)
</ins><span class="cx"> {
</span><span class="cx"> lock (_piecesToAppend)
</span><span class="cx"> _piecesToAppend.Enqueue(text);
</span></span></pre></div>
<a id="freeswitchtrunkcontribverifierEventSockettrunkFreeSwitchEventSocketEventSocketcs"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventSocket.cs (16211 => 16212)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventSocket.cs        2010-01-08 16:31:56 UTC (rev 16211)
+++ freeswitch/trunk/contrib/verifier/EventSocket/trunk/FreeSwitchEventSocket/EventSocket.cs        2010-01-08 16:38:57 UTC (rev 16212)
</span><span class="lines">@@ -8,335 +8,342 @@
</span><span class="cx">
</span><span class="cx"> namespace FreeSwitch.EventSocket
</span><span class="cx"> {
</span><del>- public delegate void MessageHandler(PlainEventMsg msg);
</del><ins>+        public delegate void MessageHandler(PlainEventMsg msg);
</ins><span class="cx">
</span><del>- public class EventSocket
- {
- #region Delegates
</del><ins>+        public class EventSocket
+        {
+                #region Delegates
</ins><span class="cx">
</span><del>- public delegate void EventSocketHandler(EventSocket client);
</del><ins>+                public delegate void DataHandler(string data);
</ins><span class="cx">
</span><del>- public delegate void DataHandler(string data);
</del><ins>+                public delegate void EventSocketHandler(EventSocket client);
</ins><span class="cx">
</span><del>- #endregion
</del><ins>+                #endregion
</ins><span class="cx">
</span><del>- private LogWriterHandler _logWriter;
- private readonly Queue<CmdBase> _commands = new Queue<CmdBase>();
- private bool _autoConnect = true;
- private Events _events;
- private string _hostName;
- private readonly EventParser _parser = new EventParser();
- public event DataHandler DataReceived;
- private string _password = "ClueCon";
- private int _port = 8021;
- private readonly object _lockobj = new object();
- private readonly byte[] _readBuffer = new byte[8192];
- private Socket _socket;
- private NetworkStream _stream;
- private Timer _timer;
- private bool _authed;
- const int RetryTimeout = 5000;
- private bool _parsing;
</del><ins>+                private const int RetryTimeout = 5000;
</ins><span class="cx">
</span><del>- /// <summary>
- /// Initializes a new instance of the <see cref="EventSocket"/> class.
- /// </summary>
- /// <param name="logWriter">The log writer.</param>
- public EventSocket(LogWriterHandler logWriter)
- {
- LogWriter = logWriter ?? NullWriter.Write;
- CreateSocket();
- }
</del><ins>+                private readonly Queue<CmdBase> _commands = new Queue<CmdBase>();
+                private readonly object _lockobj = new object();
+                private readonly ManualResetEvent _parseEvent = new ManualResetEvent(false);
+                private readonly EventParser _parser = new EventParser();
+                private readonly Thread _parseThread;
+                private readonly byte[] _readBuffer = new byte[8192];
+                private bool _authed;
+                private bool _autoConnect = true;
+                private Events _events;
+                private string _hostName;
+                private bool _isRunning = true;
+                private LogWriterHandler _logWriter;
+                private bool _parsing;
+                private string _password = "ClueCon";
+                private int _port = 8021;
+                private Socket _socket;
+                private NetworkStream _stream;
+                private Timer _timer;
</ins><span class="cx">
</span><del>- private void CreateSocket()
- {
- _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- _socket.NoDelay = true;
- _socket.ReceiveBufferSize = 65535;
- }
</del><ins>+                /// <summary>
+                /// Initializes a new instance of the <see cref="EventSocket"/> class.
+                /// </summary>
+                /// <param name="logWriter">The log writer.</param>
+                public EventSocket(LogWriterHandler logWriter)
+                {
+                        LogWriter = logWriter ?? NullWriter.Write;
+                        CreateSocket();
+                        _parseThread = new Thread(OnParseMessages);
+                        _parseThread.IsBackground = true;
+                        _parseThread.Start();
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- /// Used to authenticate towards FreeSWITCH.
- /// </summary>
- /// <remarks>
- /// Default is "ClueCon"
- /// </remarks>
- public string Password
- {
- get { return _password; }
- set { _password = value; }
- }
</del><ins>+                /// <summary>
+                /// Used to authenticate towards FreeSWITCH.
+                /// </summary>
+                /// <remarks>
+                /// Default is "ClueCon"
+                /// </remarks>
+                public string Password
+                {
+                        get { return _password; }
+                        set { _password = value; }
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- /// Connect automatically again if socket is disconnected.
- /// </summary>
- public bool AutoConnect
- {
- get { return _autoConnect; }
- set { _autoConnect = value; }
- }
</del><ins>+                /// <summary>
+                /// Connect automatically again if socket is disconnected.
+                /// </summary>
+                public bool AutoConnect
+                {
+                        get { return _autoConnect; }
+                        set { _autoConnect = value; }
+                }
</ins><span class="cx">
</span><del>- public LogWriterHandler LogWriter
- {
- get { return _logWriter; }
- set { _logWriter = value ?? NullWriter.Write; }
- }
</del><ins>+                public LogWriterHandler LogWriter
+                {
+                        get { return _logWriter; }
+                        set { _logWriter = value ?? NullWriter.Write; }
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- /// A event have been received
- /// </summary>
- public event MessageHandler MessageReceived = delegate{};
</del><ins>+                public event DataHandler DataReceived;
</ins><span class="cx">
</span><del>- /// <summary>
- /// Socket got disconnected (due to remote peer)
- /// </summary>
- public event EventSocketHandler Disconnected = delegate{};
</del><ins>+                private void CreateSocket()
+                {
+                        _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+                        _socket.NoDelay = true;
+                        _socket.ReceiveBufferSize = 65535;
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- /// Socket is now connected
- /// </summary>
- public event EventSocketHandler Connected = delegate{};
</del><ins>+                public void Stop()
+                {
+                        _isRunning = false;
+                        _parseEvent.Set();
+                        _autoConnect = false;
+                        _parseThread.Join(1000);
+                        _socket.Close();
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- /// Connect to FreeSWITCH
- /// </summary>
- /// <param name="server">hostname/ipaddress colon port</param>
- /// <example>
- /// <code>eventSocket.Connect("localhost:1234");</code>
- /// </example>
- public void Connect(string server)
- {
- int pos = server.IndexOf(':');
- if (pos == -1)
- _hostName = server;
- else
- {
- _port = int.Parse(server.Substring(pos + 1));
- _hostName = server.Substring(0, pos);
- }
</del><ins>+                private void OnParseMessages()
+                {
+                        while (true)
+                        {
+                                _parseEvent.WaitOne();
+                                _parseEvent.Reset();
+                                if (!_isRunning)
+                                        break;
</ins><span class="cx">
</span><del>- Connect();
- }
</del><ins>+                                try
+                                {
+                                        ParseMessages();
+                                }
+                                catch (Exception err)
+                                {
+                                        LogWriter(LogPrio.Warning,
+                                         "Failed to parse event message." + Environment.NewLine + "Exception: " + err +
+                                         Environment.NewLine + _parser.Text);
+                                        HandleDisconnect();
+                                }
+                        }
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- /// Connect to the previously specified host.
- /// </summary>
- public void Connect()
- {
- if (_hostName == null)
- throw new InvalidOperationException("Must call the other Connect method first to set hostname/port.");
</del><ins>+                /// <summary>
+                /// A event have been received
+                /// </summary>
+                public event MessageHandler MessageReceived = delegate { };
</ins><span class="cx">
</span><del>- try
- {
- TryConnect();
- LogWriter(LogPrio.Debug, "Connected to freeswitch.");
- }
-                        catch(InvalidOperationException err)
</del><ins>+                /// <summary>
+                /// Socket got disconnected (due to remote peer)
+                /// </summary>
+                public event EventSocketHandler Disconnected = delegate { };
+
+                /// <summary>
+                /// Socket is now connected
+                /// </summary>
+                public event EventSocketHandler Connected = delegate { };
+
+                /// <summary>
+                /// Connect to FreeSWITCH
+                /// </summary>
+                /// <param name="server">hostname/ipaddress colon port</param>
+                /// <example>
+                /// <code>eventSocket.Connect("localhost:1234");</code>
+                /// </example>
+                public void Connect(string server)
+                {
+                        int pos = server.IndexOf(':');
+                        if (pos == -1)
+                                _hostName = server;
+                        else
</ins><span class="cx">                         {
</span><ins>+                                _port = int.Parse(server.Substring(pos + 1));
+                                _hostName = server.Substring(0, pos);
+                        }
+
+                        Connect();
+                }
+
+                /// <summary>
+                /// Connect to the previously specified host.
+                /// </summary>
+                public void Connect()
+                {
+                        if (_hostName == null)
+                                throw new InvalidOperationException("Must call the other Connect method first to set hostname/port.");
+
+                        try
+                        {
+                                TryConnect();
+                                LogWriter(LogPrio.Debug, "Connected to freeswitch.");
+                        }
+                        catch (InvalidOperationException err)
+                        {
</ins><span class="cx">                                 LogWriter(LogPrio.Debug, "Failed to connect to freeswitch, reason: " + err.Message);
</span><span class="cx">                                 HandleDisconnect();
</span><span class="cx">                         }
</span><del>- catch (SocketException err)
- {
- LogWriter(LogPrio.Debug, "Failed to connect to freeswitch, reason: " + err.Message);
- HandleDisconnect();
- }
- }
</del><ins>+                        catch (SocketException err)
+                        {
+                                LogWriter(LogPrio.Debug, "Failed to connect to freeswitch, reason: " + err.Message);
+                                HandleDisconnect();
+                        }
+                }
</ins><span class="cx">
</span><del>- private void TryConnect()
- {
- lock (_lockobj)
- {
- _socket.Connect(_hostName, _port);
- if (_stream == null)
- _stream = new NetworkStream(_socket, false);
</del><ins>+                private void TryConnect()
+                {
+                        lock (_lockobj)
+                        {
+                                _socket.Connect(_hostName, _port);
+                                if (_stream == null)
+                                        _stream = new NetworkStream(_socket, false);
</ins><span class="cx">
</span><del>- Connected(this);
- BeginRead();
- }
- }
</del><ins>+                                Connected(this);
+                                BeginRead();
+                        }
+                }
</ins><span class="cx">
</span><del>- private void BeginRead()
- {
- _stream.BeginRead(_readBuffer, 0, _readBuffer.Length, OnReadCompleted, null);
- }
</del><ins>+                private void BeginRead()
+                {
+                        _stream.BeginRead(_readBuffer, 0, _readBuffer.Length, OnReadCompleted, null);
+                }
</ins><span class="cx">
</span><del>- private void OnReadCompleted(IAsyncResult ar)
- {
- try
- {
- ReceiveWrapper(ar);
- }
- catch(Exception err)
- {
- _logWriter(LogPrio.Error, err.ToString());
- }
- }
</del><ins>+                private void OnReadCompleted(IAsyncResult ar)
+                {
+                        try
+                        {
+                                ReceiveWrapper(ar);
+                        }
+                        catch (Exception err)
+                        {
+                                _logWriter(LogPrio.Error, err.ToString());
+                        }
+                }
</ins><span class="cx">
</span><del>- private void ReceiveWrapper(IAsyncResult ar)
- {
- string inbuffer;
- try
- {
- if (_stream == null)
- return;
</del><ins>+                private void ReceiveWrapper(IAsyncResult ar)
+                {
+                        string inbuffer;
+                        try
+                        {
+                                if (_stream == null)
+                                        return;
</ins><span class="cx">
</span><del>- int bytesRead = _stream.EndRead(ar);
- if (bytesRead == 0)
- {
- LogWriter(LogPrio.Error, "Got disconnected (0 bytes read).");
- HandleDisconnect();
- return;
- }
- inbuffer = Encoding.ASCII.GetString(_readBuffer, 0, bytesRead);
- BeginRead();
- }
- catch (Exception err)
- {
- LogWriter(LogPrio.Debug, "IO exception during read: " + err.Message);
- // Remote end disconnected.
- HandleDisconnect();
- return;
- }
</del><ins>+                                int bytesRead = _stream.EndRead(ar);
+                                if (bytesRead == 0)
+                                {
+                                        LogWriter(LogPrio.Error, "Got disconnected (0 bytes read).");
+                                        HandleDisconnect();
+                                        return;
+                                }
+                                inbuffer = Encoding.ASCII.GetString(_readBuffer, 0, bytesRead);
+                                BeginRead();
+                        }
+                        catch (Exception err)
+                        {
+                                LogWriter(LogPrio.Debug, "IO exception during read: " + err.Message);
+                                // Remote end disconnected.
+                                HandleDisconnect();
+                                return;
+                        }
</ins><span class="cx">
</span><del>- _parser.Append(inbuffer);
- if (!string.IsNullOrEmpty(inbuffer))
- DataReceived(inbuffer);
</del><ins>+                        _parser.Append(inbuffer);
+                        if (!string.IsNullOrEmpty(inbuffer))
+                                DataReceived(inbuffer);
</ins><span class="cx">
</span><del>- try
- {
- ParseMessages();
- }
- catch (InvalidDataException err)
- {
- LogWriter(LogPrio.Warning,
- "Failed to parse event message." + Environment.NewLine + "Exception: " + err +
- Environment.NewLine + _parser.Text);
- HandleDisconnect();
- }
- catch (ArgumentException err)
- {
- LogWriter(LogPrio.Warning,
- "Failed to parse event message." + Environment.NewLine + "Exception: " + err +
- Environment.NewLine + _parser.Text);
- HandleDisconnect();
- }
- }
</del><ins>+                        _parseEvent.Set();
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- /// Subscribe on the specified events.
- /// </summary>
- /// <param name="events">The events.</param>
- public void Subscribe(Events events)
- {
- _events = events;
- if (_socket.Connected && _authed)
- RequestEvents();
- }
</del><ins>+                /// <summary>
+                /// Subscribe on the specified events.
+                /// </summary>
+                /// <param name="events">The events.</param>
+                public void Subscribe(Events events)
+                {
+                        _events = events;
+                        if (_socket.Connected && _authed)
+                                RequestEvents();
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- ///
- /// </summary>
- /// <param name="s"></param>
- /// <exception cref="InvalidOperationException"></exception>
- /// <exception cref="ObjectDisposedException"></exception>
- private void Write(string s)
- {
- if (_socket == null)
- return;
- if (!_socket.Connected)
- {
</del><ins>+                /// <summary>
+                ///
+                /// </summary>
+                /// <param name="s"></param>
+                /// <exception cref="InvalidOperationException"></exception>
+                /// <exception cref="ObjectDisposedException"></exception>
+                private void Write(string s)
+                {
+                        if (_socket == null)
+                                return;
+                        if (!_socket.Connected)
+                        {
</ins><span class="cx">                                 if (_timer == null)
</span><span class="cx">                                         _timer = new Timer(OnTryConnect, null, RetryTimeout, RetryTimeout);
</span><del>-         return;
- }
</del><ins>+                                return;
+                        }
</ins><span class="cx">
</span><del>- byte[] bytes = Encoding.ASCII.GetBytes(s);
- _stream.Write(bytes, 0, bytes.Length);
- }
</del><ins>+                        byte[] bytes = Encoding.ASCII.GetBytes(s);
+                        _stream.Write(bytes, 0, bytes.Length);
+                }
</ins><span class="cx">
</span><del>- static readonly object locker = new object();
- private void ParseMessages()
- {
-
- lock (locker)
- {
- if (_parsing)
- return;
- _parsing = true;
- }
</del><ins>+                // Should ONLY be called from the parsing thread.
+                private void ParseMessages()
+                {
+                        PlainEventMsg msg = _parser.ParseOne();
+                        while (msg != null)
+                        {
+                                LogWriter(LogPrio.Trace, "MessageType: " + msg.ContentType);
+                                switch (msg.ContentType)
+                                {
+                                        case "auth/request":
+                                                {
+                                                        var cmd = new AuthCommand(_password);
+                                                        cmd.ReplyReceived += OnAuthed;
+                                                        _commands.Enqueue(cmd);
+                                                        Write(cmd + "\n\n");
+                                                }
+                                                break;
+                                        case "api/response":
+                                        case "command/reply":
+                                                if (_commands.Count > 0)
+                                                {
+                                                        CmdBase cmd = _commands.Dequeue();
+                                                        cmd.HandleReply(cmd.CreateReply(msg.Body.Trim()));
+                                                }
+                                                else
+                                                        LogWriter(LogPrio.Debug, "Got command reply or api response, but no actual command/api: " + msg.Body);
+                                                break;
+                                        default:
+                                                MessageReceived(msg);
+                                                break;
+                                }
+                                msg = _parser.ParseOne();
+                        }
+                }
</ins><span class="cx">
</span><del>- try
- {
- PlainEventMsg msg = _parser.ParseOne();
- while (msg != null)
- {
-                                        LogWriter(LogPrio.Trace, "MessageType: " + msg.ContentType);
-                                        switch (msg.ContentType)
- {
- case "auth/request":
- {
- AuthCommand cmd = new AuthCommand(_password);
- cmd.ReplyReceived += OnAuthed;
- _commands.Enqueue(cmd);
- Write(cmd + "\n\n");
- }
- break;
- case "api/response":
- case "command/reply":
- if (_commands.Count > 0)
- {
- CmdBase cmd = _commands.Dequeue();
- cmd.HandleReply(cmd.CreateReply(msg.Body.Trim()));
- }
- else
- LogWriter(LogPrio.Debug, "Got command reply or api response, but no actual command/api: " + msg.Body);
- break;
- default:
- MessageReceived(msg);
- break;
- }
- msg = _parser.ParseOne();
- }
- }
- finally
- {
- lock (locker)
- _parsing = false;
- }
- }
</del><ins>+                private void OnAuthed(CmdBase command, CommandReply reply)
+                {
+                        LogWriter(LogPrio.Trace, "We have not authenticated.");
+                        _authed = true;
+                        RequestEvents();
+                }
</ins><span class="cx">
</span><del>- private void OnAuthed(CmdBase command, CommandReply reply)
- {
- LogWriter(LogPrio.Trace, "We have not authenticated.");
- _authed = true;
- RequestEvents();
- }
</del><ins>+                private void HandleDisconnect()
+                {
+                        _parser.Clear();
+                        _authed = false;
+                        _socket.Close();
+                        CreateSocket();
+                        if (_stream != null)
+                        {
+                                _stream.Dispose();
+                                _stream = null;
+                        }
</ins><span class="cx">
</span><del>- private void HandleDisconnect()
- {
- _parser.Clear();
- _authed = false;
- _socket.Close();
- CreateSocket();
- if (_stream != null)
- {
- _stream.Dispose();
- _stream = null;
- }
-
- Disconnected(this);
- if (!AutoConnect || _timer != null)
</del><ins>+                        Disconnected(this);
+                        if (!AutoConnect || _timer != null)
</ins><span class="cx">                                 return;
</span><span class="cx">
</span><del>- LogWriter(LogPrio.Info, "Launching autoconnect timer.");
- _timer = new Timer(OnTryConnect, this, RetryTimeout, RetryTimeout);
- }
</del><ins>+                        LogWriter(LogPrio.Info, "Launching autoconnect timer.");
+                        _timer = new Timer(OnTryConnect, this, RetryTimeout, RetryTimeout);
+                }
</ins><span class="cx">
</span><del>-         private void OnTryConnect(object state)
-         {
-                 try
-                 {
</del><ins>+                private void OnTryConnect(object state)
+                {
+                        try
+                        {
</ins><span class="cx">                                 TryConnect();
</span><span class="cx">                                 LogWriter(LogPrio.Info, "Connected again.");
</span><span class="cx">                                 if (_timer == null)
</span><span class="lines">@@ -346,50 +353,50 @@
</span><span class="cx">                                 _timer = null;
</span><span class="cx">                                 tmr.Change(Timeout.Infinite, Timeout.Infinite);
</span><span class="cx">                                 tmr.Dispose();
</span><del>-                 }
-                        catch(Exception err)
</del><ins>+                        }
+                        catch (Exception err)
</ins><span class="cx">                         {
</span><span class="cx">                                 if (!(err is SocketException))
</span><span class="cx">                                         LogWriter(LogPrio.Error, "Unexpected exception in try connect: " + err);
</span><span class="cx">                         }
</span><del>-         }
</del><ins>+                }
</ins><span class="cx">
</span><del>-         private void RequestEvents()
- {
- if (_events.Count <= 0 && _authed)
- return;
</del><ins>+                private void RequestEvents()
+                {
+                        if (_events.Count <= 0 && _authed)
+                                return;
</ins><span class="cx">
</span><del>- Write("event plain " + GetEventString() + "\n\n");
- }
</del><ins>+                        Write("event plain " + GetEventString() + "\n\n");
+                }
</ins><span class="cx">
</span><del>- private string GetEventString()
- {
- string events = string.Empty;
- for (int i = 0; i < _events.Count; ++i)
- events += StringHelper.CamelCaseToUpperCase(_events[i].ToString()) + " ";
- return events;
- }
</del><ins>+                private string GetEventString()
+                {
+                        string events = string.Empty;
+                        for (int i = 0; i < _events.Count; ++i)
+                                events += StringHelper.CamelCaseToUpperCase(_events[i].ToString()) + " ";
+                        return events;
+                }
</ins><span class="cx">
</span><del>- /// <summary>
- /// Send a command to FreeSwitch.
- /// Do you want a response? Then use the delegate in the Command class.
- /// </summary>
- /// <param name="command">Command to send.</param>
- /// <exception cref="IOException">If socket is not connected.</exception>
- /// <exception cref="InvalidOperationException"></exception>
- /// <exception cref="ObjectDisposedException"></exception>
- public void Send(CmdBase command)
- {
- if (!_socket.Connected)
- {
- LogWriter(LogPrio.Debug, "Tried to send command when we are not connected: " + command);
- throw new IOException("Socket is not connected.");
- }
</del><ins>+                /// <summary>
+                /// Send a command to FreeSwitch.
+                /// Do you want a response? Then use the delegate in the Command class.
+                /// </summary>
+                /// <param name="command">Command to send.</param>
+                /// <exception cref="IOException">If socket is not connected.</exception>
+                /// <exception cref="InvalidOperationException"></exception>
+                /// <exception cref="ObjectDisposedException"></exception>
+                public void Send(CmdBase command)
+                {
+                        if (!_socket.Connected)
+                        {
+                                LogWriter(LogPrio.Debug, "Tried to send command when we are not connected: " + command);
+                                throw new IOException("Socket is not connected.");
+                        }
</ins><span class="cx">
</span><del>- _commands.Enqueue(command);
</del><ins>+                        _commands.Enqueue(command);
</ins><span class="cx">
</span><del>- // All commands need replies.
- Write(command + "\n\n");
- }
- }
</del><ins>+                        // All commands need replies.
+                        Write(command + "\n\n");
+                }
+        }
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>
</body>
</html>