This is not specific to Amqp.Net Lite, but it is helpful to list the common issues with using TLS/SSL on NETMF.

Emulator hangs when using "amqps" address.

The issue is in the emulator driver implementation. The SSL driver internally calls the .Net SslStream.Read(...) to read data from socket. This call blocks if no data is available. For request/response style protocol, it may work fine since when read is issued, the response is expected to be there. However, AMQP is an asynchronous protocol. A read is always performed on the transport. When it is blocked, the control will not go back to NETMF core. You can apply the following patch and all NETMF tests should pass over SSL connection.

Index: Framework/Tools/Emulator/Sockets.cs
===================================================================
--- Framework/Tools/Emulator/Sockets.cs	(revision 42476)
+++ Framework/Tools/Emulator/Sockets.cs	(working copy)
@@ -288,6 +288,39 @@
             }
         }
 
+        internal void SignalSocketEvent(int socket, bool fRead)
+        {
+            SocketData sd;
+            if (_isInitialized)
+            {
+                if (GetSocketData(socket, out sd))
+                {
+                    if (fRead)
+                    {
+                        lock (m_read)
+                        {
+                            if (!m_read.Contains(sd.Socket))
+                            {
+                                m_read.Add(sd.Socket);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        lock (m_write)
+                        {
+                            if (!m_write.Contains(sd.Socket))
+                            {
+                                m_write.Add(sd.Socket);
+                            }
+                        }
+                    }
+                }
+
+                SignalThread();
+            }
+        }
+
         bool _socketsShuttingDown = false;
 
         List<Socket> m_read = new List<Socket>();
@@ -430,7 +463,7 @@
                 this.Emulator.SetSystemEvents(Events.SystemEvents.SOCKET);
             }
         }
-        
+
         [MethodImplAttribute(MethodImplOptions.Synchronized)]
         void EnsureInitialized()
         {
Index: Framework/Tools/Emulator/Ssl.cs
===================================================================
--- Framework/Tools/Emulator/Ssl.cs	(revision 42476)
+++ Framework/Tools/Emulator/Ssl.cs	(working copy)
@@ -60,11 +60,13 @@
                 internal byte[] ManagedBuffer;
                 internal int Socket;
                 internal int Length;
+                internal int Offset;
             }
 
             internal SslStream m_stream;
             internal SslAsyncState m_state = SslAsyncState.Init;
             internal object m_asyncData = null;
+            internal SslReadData m_readData;
         }
 
         Dictionary<int, SslData> _sslDataCollection = new Dictionary<int, SslData>();
@@ -430,7 +432,6 @@
         }
 
 
-        [MethodImplAttribute(MethodImplOptions.Synchronized)]
         public int Read(int socket, IntPtr Data, int size)
         {
             int len = 0;
@@ -438,30 +439,71 @@
 
             if (!GetSslData(socket, out ssd)) return (int)SocketError.SocketError;
 
-            try
+            if (ssd.m_state == SslStreamData.SslAsyncState.Failed)
+                return _socketsDriver.ReturnError(SocketError.ConnectionReset);
+
+            var readData = ssd.m_readData;
+            if (readData != null)
             {
-                byte[] managedBuffer = new byte[size];
-
-                len = ssd.m_stream.Read(managedBuffer, 0, size);
-
-                if (len > 0)
+                lock (ssd)
                 {
-                    Marshal.Copy(managedBuffer, 0, Data, len);
+                    len = Math.Min(size, readData.Length - readData.Offset);
+                    if (len > 0)
+                    {
+                        Marshal.Copy(readData.ManagedBuffer, readData.Offset, Data, len);
+                        readData.Offset += len;
+                        if (readData.Offset == readData.Length) ssd.m_readData = null;
+                    }
+                    else
+                    {
+                        _socketsDriver.ClearSocketEvent(socket, true);
+                        len = -2;
+                    }
                 }
-                else
+            }
+            else
+            {
+                try
                 {
-                    _socketsDriver.ClearSocketEvent(socket, true);
+                    byte[] managedBuffer = new byte[size];
+
+                    ssd.m_readData = new SslStreamData.SslReadData(socket, managedBuffer);
+                    ssd.m_stream.BeginRead(managedBuffer, 0, size, this.EndRead, ssd.m_readData);
+                    len = -2;
                 }
+                catch (Exception e)
+                {
+                    Console.Error.WriteLine("Write Failed... " + e.Message);
+                    len = (int)SocketError.SocketError;
+                }
             }
-            catch (Exception e)
-            {
-                Console.Error.WriteLine("Write Failed... " + e.Message);
-                return (int)SocketError.SocketError;
-            }
 
             return len;
         }
 
+        void EndRead(IAsyncResult result)
+        {
+            var readData = (SslStreamData.SslReadData)result.AsyncState;
+            SslStreamData ssd;
+            if (!GetSslData(readData.Socket, out ssd)) return;
+
+            lock (ssd)
+            {
+                try
+                {
+                    readData.Length = ssd.m_stream.EndRead(result);
+                }
+                catch (Exception e)
+                {
+                    Console.Error.WriteLine("Read Failed... " + e.Message);
+                    ssd.m_readData = null;
+                    ssd.m_state = SslStreamData.SslAsyncState.Failed;
+                }
+
+                _socketsDriver.SignalSocketEvent(readData.Socket, true);
+            }
+        }
+
         public int CloseSocket( int socket )
         {
             lock (_sslStreams)
@@ -608,9 +650,13 @@
 
             if (!GetSslData(socket, out ssd)) return (int)SocketError.SocketError;
 
-            if(!_socketsDriver.GetSocket(socket, out sock)) return (int)SocketError.SocketError;
+            if (!_socketsDriver.GetSocket(socket, out sock)) return (int)SocketError.SocketError;
 
-            return sock.Poll(0,SelectMode.SelectRead) ? 1024 : 0;
+            var readData = ssd.m_readData;
+            int ret = readData != null ?
+                readData.Length - readData.Offset :
+                sock.Poll(0, SelectMode.SelectRead) ? 1024 : 0;
+            return ret;
         }
     }    
 }

Last edited Sep 29, 2014 at 5:53 AM by xinchen, version 2