<!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 &lt; _text.Length - 1; ++i)
-                {
-                    if (_text[i] == '\n' &amp;&amp; _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 &gt;= 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 &lt; 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(&quot;Invalid content length, actual length: &quot; + (endOfBody - i) + &quot;, reported length: &quot; +
+                                                                  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 &lt; _text.Length - 1; ++i)
+                    {
+                            if (_text[i] == '\n' &amp;&amp; _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&lt;CmdBase&gt; _commands = new Queue&lt;CmdBase&gt;();
-        private bool _autoConnect = true;
-        private Events _events;
-        private string _hostName;
-        private readonly EventParser _parser = new EventParser();
-        public event DataHandler DataReceived;
-        private string _password = &quot;ClueCon&quot;;
-        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>-        /// &lt;summary&gt;
-        /// Initializes a new instance of the &lt;see cref=&quot;EventSocket&quot;/&gt; class.
-        /// &lt;/summary&gt;
-        /// &lt;param name=&quot;logWriter&quot;&gt;The log writer.&lt;/param&gt;
-        public EventSocket(LogWriterHandler logWriter)
-        {
-            LogWriter = logWriter ?? NullWriter.Write;
-            CreateSocket();
-        }
</del><ins>+                private readonly Queue&lt;CmdBase&gt; _commands = new Queue&lt;CmdBase&gt;();
+                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 = &quot;ClueCon&quot;;
+                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>+                /// &lt;summary&gt;
+                /// Initializes a new instance of the &lt;see cref=&quot;EventSocket&quot;/&gt; class.
+                /// &lt;/summary&gt;
+                /// &lt;param name=&quot;logWriter&quot;&gt;The log writer.&lt;/param&gt;
+                public EventSocket(LogWriterHandler logWriter)
+                {
+                        LogWriter = logWriter ?? NullWriter.Write;
+                        CreateSocket();
+                        _parseThread = new Thread(OnParseMessages);
+                        _parseThread.IsBackground = true;
+                        _parseThread.Start();
+                }
</ins><span class="cx"> 
</span><del>-        /// &lt;summary&gt;
-        /// Used to authenticate towards FreeSWITCH.
-        /// &lt;/summary&gt;
-        /// &lt;remarks&gt;
-        /// Default is &quot;ClueCon&quot;
-        /// &lt;/remarks&gt;
-        public string Password
-        {
-            get { return _password; }
-            set { _password = value; }
-        }
</del><ins>+                /// &lt;summary&gt;
+                /// Used to authenticate towards FreeSWITCH.
+                /// &lt;/summary&gt;
+                /// &lt;remarks&gt;
+                /// Default is &quot;ClueCon&quot;
+                /// &lt;/remarks&gt;
+                public string Password
+                {
+                        get { return _password; }
+                        set { _password = value; }
+                }
</ins><span class="cx"> 
</span><del>-        /// &lt;summary&gt;
-        /// Connect automatically again if socket is disconnected.
-        /// &lt;/summary&gt;
-        public bool AutoConnect
-        {
-            get { return _autoConnect; }
-            set { _autoConnect = value; }
-        }
</del><ins>+                /// &lt;summary&gt;
+                /// Connect automatically again if socket is disconnected.
+                /// &lt;/summary&gt;
+                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>-        /// &lt;summary&gt;
-        /// A event have been received
-        /// &lt;/summary&gt;
-        public event MessageHandler MessageReceived = delegate{};
</del><ins>+                public event DataHandler DataReceived;
</ins><span class="cx"> 
</span><del>-        /// &lt;summary&gt;
-        /// Socket got disconnected (due to remote peer)
-        /// &lt;/summary&gt;
-        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>-        /// &lt;summary&gt;
-        /// Socket is now connected
-        /// &lt;/summary&gt;
-        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>-        /// &lt;summary&gt;
-        /// Connect to FreeSWITCH
-        /// &lt;/summary&gt;
-        /// &lt;param name=&quot;server&quot;&gt;hostname/ipaddress colon port&lt;/param&gt;
-        /// &lt;example&gt;
-        /// &lt;code&gt;eventSocket.Connect(&quot;localhost:1234&quot;);&lt;/code&gt;
-        /// &lt;/example&gt;
-        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,
+                                                  &quot;Failed to parse event message.&quot; + Environment.NewLine + &quot;Exception: &quot; + err +
+                                                  Environment.NewLine + _parser.Text);
+                                        HandleDisconnect();
+                                }
+                        }
+                }
</ins><span class="cx"> 
</span><del>-        /// &lt;summary&gt;
-        /// Connect to the previously specified host.
-        /// &lt;/summary&gt;
-        public void Connect()
-        {
-            if (_hostName == null)
-                throw new InvalidOperationException(&quot;Must call the other Connect method first to set hostname/port.&quot;);
</del><ins>+                /// &lt;summary&gt;
+                /// A event have been received
+                /// &lt;/summary&gt;
+                public event MessageHandler MessageReceived = delegate { };
</ins><span class="cx"> 
</span><del>-            try
-            {
-                TryConnect();
-                LogWriter(LogPrio.Debug, &quot;Connected to freeswitch.&quot;);
-            }
-                        catch(InvalidOperationException err)
</del><ins>+                /// &lt;summary&gt;
+                /// Socket got disconnected (due to remote peer)
+                /// &lt;/summary&gt;
+                public event EventSocketHandler Disconnected = delegate { };
+
+                /// &lt;summary&gt;
+                /// Socket is now connected
+                /// &lt;/summary&gt;
+                public event EventSocketHandler Connected = delegate { };
+
+                /// &lt;summary&gt;
+                /// Connect to FreeSWITCH
+                /// &lt;/summary&gt;
+                /// &lt;param name=&quot;server&quot;&gt;hostname/ipaddress colon port&lt;/param&gt;
+                /// &lt;example&gt;
+                /// &lt;code&gt;eventSocket.Connect(&quot;localhost:1234&quot;);&lt;/code&gt;
+                /// &lt;/example&gt;
+                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();
+                }
+
+                /// &lt;summary&gt;
+                /// Connect to the previously specified host.
+                /// &lt;/summary&gt;
+                public void Connect()
+                {
+                        if (_hostName == null)
+                                throw new InvalidOperationException(&quot;Must call the other Connect method first to set hostname/port.&quot;);
+
+                        try
+                        {
+                                TryConnect();
+                                LogWriter(LogPrio.Debug, &quot;Connected to freeswitch.&quot;);
+                        }
+                        catch (InvalidOperationException err)
+                        {
</ins><span class="cx">                                 LogWriter(LogPrio.Debug, &quot;Failed to connect to freeswitch, reason: &quot; + err.Message);
</span><span class="cx">                                 HandleDisconnect();
</span><span class="cx">                         }
</span><del>-            catch (SocketException err)
-            {
-                LogWriter(LogPrio.Debug, &quot;Failed to connect to freeswitch, reason: &quot; + err.Message);
-                HandleDisconnect();
-            }
-        }
</del><ins>+                        catch (SocketException err)
+                        {
+                                LogWriter(LogPrio.Debug, &quot;Failed to connect to freeswitch, reason: &quot; + 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, &quot;Got disconnected (0 bytes read).&quot;);
-                    HandleDisconnect();
-                    return;
-                }
-                inbuffer = Encoding.ASCII.GetString(_readBuffer, 0, bytesRead);
-                BeginRead();
-            }
-            catch (Exception err)
-            {
-                LogWriter(LogPrio.Debug, &quot;IO exception during read: &quot; + err.Message);
-                // Remote end disconnected.
-                HandleDisconnect();
-                return;
-            }
</del><ins>+                                int bytesRead = _stream.EndRead(ar);
+                                if (bytesRead == 0)
+                                {
+                                        LogWriter(LogPrio.Error, &quot;Got disconnected (0 bytes read).&quot;);
+                                        HandleDisconnect();
+                                        return;
+                                }
+                                inbuffer = Encoding.ASCII.GetString(_readBuffer, 0, bytesRead);
+                                BeginRead();
+                        }
+                        catch (Exception err)
+                        {
+                                LogWriter(LogPrio.Debug, &quot;IO exception during read: &quot; + 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,
-                          &quot;Failed to parse event message.&quot; + Environment.NewLine + &quot;Exception: &quot; + err +
-                          Environment.NewLine + _parser.Text);
-                HandleDisconnect();
-            }
-            catch (ArgumentException err)
-            {
-                LogWriter(LogPrio.Warning,
-                          &quot;Failed to parse event message.&quot; + Environment.NewLine + &quot;Exception: &quot; + err +
-                          Environment.NewLine + _parser.Text);
-                HandleDisconnect();
-            }
-        }
</del><ins>+                        _parseEvent.Set();
+                }
</ins><span class="cx"> 
</span><del>-        /// &lt;summary&gt;
-        /// Subscribe on the specified events.
-        /// &lt;/summary&gt;
-        /// &lt;param name=&quot;events&quot;&gt;The events.&lt;/param&gt;
-        public void Subscribe(Events events)
-        {
-            _events = events;
-            if (_socket.Connected &amp;&amp; _authed)
-                RequestEvents();
-        }
</del><ins>+                /// &lt;summary&gt;
+                /// Subscribe on the specified events.
+                /// &lt;/summary&gt;
+                /// &lt;param name=&quot;events&quot;&gt;The events.&lt;/param&gt;
+                public void Subscribe(Events events)
+                {
+                        _events = events;
+                        if (_socket.Connected &amp;&amp; _authed)
+                                RequestEvents();
+                }
</ins><span class="cx"> 
</span><del>-        /// &lt;summary&gt;
-        /// 
-        /// &lt;/summary&gt;
-        /// &lt;param name=&quot;s&quot;&gt;&lt;/param&gt;
-        /// &lt;exception cref=&quot;InvalidOperationException&quot;&gt;&lt;/exception&gt;
-        /// &lt;exception cref=&quot;ObjectDisposedException&quot;&gt;&lt;/exception&gt;
-        private void Write(string s)
-        {
-            if (_socket == null)
-                return;
-            if (!_socket.Connected)
-            {
</del><ins>+                /// &lt;summary&gt;
+                /// 
+                /// &lt;/summary&gt;
+                /// &lt;param name=&quot;s&quot;&gt;&lt;/param&gt;
+                /// &lt;exception cref=&quot;InvalidOperationException&quot;&gt;&lt;/exception&gt;
+                /// &lt;exception cref=&quot;ObjectDisposedException&quot;&gt;&lt;/exception&gt;
+                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, &quot;MessageType: &quot; + msg.ContentType);
+                                switch (msg.ContentType)
+                                {
+                                        case &quot;auth/request&quot;:
+                                                {
+                                                        var cmd = new AuthCommand(_password);
+                                                        cmd.ReplyReceived += OnAuthed;
+                                                        _commands.Enqueue(cmd);
+                                                        Write(cmd + &quot;\n\n&quot;);
+                                                }
+                                                break;
+                                        case &quot;api/response&quot;:
+                                        case &quot;command/reply&quot;:
+                                                if (_commands.Count &gt; 0)
+                                                {
+                                                        CmdBase cmd = _commands.Dequeue();
+                                                        cmd.HandleReply(cmd.CreateReply(msg.Body.Trim()));
+                                                }
+                                                else
+                                                        LogWriter(LogPrio.Debug, &quot;Got command reply or api response, but no actual command/api: &quot; + 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, &quot;MessageType: &quot; + msg.ContentType);
-                                        switch (msg.ContentType)
-                    {
-                        case &quot;auth/request&quot;:
-                            {
-                                AuthCommand cmd = new AuthCommand(_password);
-                                cmd.ReplyReceived += OnAuthed;
-                                _commands.Enqueue(cmd);
-                                Write(cmd + &quot;\n\n&quot;);
-                            }
-                            break;
-                        case &quot;api/response&quot;:
-                        case &quot;command/reply&quot;:
-                            if (_commands.Count &gt; 0)
-                            {
-                                CmdBase cmd = _commands.Dequeue();
-                                cmd.HandleReply(cmd.CreateReply(msg.Body.Trim()));
-                            }
-                            else
-                                LogWriter(LogPrio.Debug, &quot;Got command reply or api response, but no actual command/api: &quot; + 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, &quot;We have not authenticated.&quot;);
+                        _authed = true;
+                        RequestEvents();
+                }
</ins><span class="cx"> 
</span><del>-        private void OnAuthed(CmdBase command, CommandReply reply)
-        {
-            LogWriter(LogPrio.Trace, &quot;We have not authenticated.&quot;);
-            _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, &quot;Launching autoconnect timer.&quot;);
-            _timer = new Timer(OnTryConnect, this, RetryTimeout, RetryTimeout);
-        }
</del><ins>+                        LogWriter(LogPrio.Info, &quot;Launching autoconnect timer.&quot;);
+                        _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, &quot;Connected again.&quot;);
</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, &quot;Unexpected exception in try connect: &quot; + err);
</span><span class="cx">                         }
</span><del>-            }
</del><ins>+                }
</ins><span class="cx"> 
</span><del>-            private void RequestEvents()
-        {
-            if (_events.Count &lt;= 0 &amp;&amp; _authed)
-                return;
</del><ins>+                private void RequestEvents()
+                {
+                        if (_events.Count &lt;= 0 &amp;&amp; _authed)
+                                return;
</ins><span class="cx"> 
</span><del>-            Write(&quot;event plain &quot; + GetEventString() + &quot;\n\n&quot;);
-        }
</del><ins>+                        Write(&quot;event plain &quot; + GetEventString() + &quot;\n\n&quot;);
+                }
</ins><span class="cx"> 
</span><del>-        private string GetEventString()
-        {
-            string events = string.Empty;
-            for (int i = 0; i &lt; _events.Count; ++i)
-                events += StringHelper.CamelCaseToUpperCase(_events[i].ToString()) + &quot; &quot;;
-            return events;
-        }
</del><ins>+                private string GetEventString()
+                {
+                        string events = string.Empty;
+                        for (int i = 0; i &lt; _events.Count; ++i)
+                                events += StringHelper.CamelCaseToUpperCase(_events[i].ToString()) + &quot; &quot;;
+                        return events;
+                }
</ins><span class="cx"> 
</span><del>-        /// &lt;summary&gt;
-        /// Send a command to FreeSwitch.
-        /// Do you want a response? Then use the delegate in the Command class.
-        /// &lt;/summary&gt;
-        /// &lt;param name=&quot;command&quot;&gt;Command to send.&lt;/param&gt;
-        /// &lt;exception cref=&quot;IOException&quot;&gt;If socket is not connected.&lt;/exception&gt;
-        /// &lt;exception cref=&quot;InvalidOperationException&quot;&gt;&lt;/exception&gt;
-        /// &lt;exception cref=&quot;ObjectDisposedException&quot;&gt;&lt;/exception&gt;
-        public void Send(CmdBase command)
-        {
-            if (!_socket.Connected)
-            {
-                LogWriter(LogPrio.Debug, &quot;Tried to send command when we are not connected: &quot; + command);
-                throw new IOException(&quot;Socket is not connected.&quot;);
-            }
</del><ins>+                /// &lt;summary&gt;
+                /// Send a command to FreeSwitch.
+                /// Do you want a response? Then use the delegate in the Command class.
+                /// &lt;/summary&gt;
+                /// &lt;param name=&quot;command&quot;&gt;Command to send.&lt;/param&gt;
+                /// &lt;exception cref=&quot;IOException&quot;&gt;If socket is not connected.&lt;/exception&gt;
+                /// &lt;exception cref=&quot;InvalidOperationException&quot;&gt;&lt;/exception&gt;
+                /// &lt;exception cref=&quot;ObjectDisposedException&quot;&gt;&lt;/exception&gt;
+                public void Send(CmdBase command)
+                {
+                        if (!_socket.Connected)
+                        {
+                                LogWriter(LogPrio.Debug, &quot;Tried to send command when we are not connected: &quot; + command);
+                                throw new IOException(&quot;Socket is not connected.&quot;);
+                        }
</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 + &quot;\n\n&quot;);
-        }
-    }
</del><ins>+                        // All commands need replies.
+                        Write(command + &quot;\n\n&quot;);
+                }
+        }
</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>