THRIFT-2081 Specified timeout should be used in TSocket.Open()
authorJens Geyer <jensg@apache.org>
Fri, 5 Jul 2013 17:20:27 +0000 (19:20 +0200)
committerJens Geyer <jensg@apache.org>
Fri, 5 Jul 2013 17:20:27 +0000 (19:20 +0200)
Patch: Jens Geyer

lib/csharp/src/Transport/TSocket.cs

index c05b6c2..1d50968 100644 (file)
@@ -131,11 +131,78 @@ namespace Thrift.Transport
                                InitSocket();
                        }
 
-                       client.Connect(host, port);
+                       if( timeout == 0)                       // no timeout -> infinite
+                       {
+                               client.Connect(host, port);
+                       }
+                       else                        // we have a timeout -> use it
+                       {
+                ConnectHelper hlp = new ConnectHelper(client);
+                IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
+                bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
+                if (!bConnected)
+                {
+                    lock (hlp.Mutex)
+                    {
+                        if( hlp.CallbackDone)
+                        {
+                            asyncres.AsyncWaitHandle.Close();
+                            client.Close();
+                        }
+                        else
+                        {
+                            hlp.DoCleanup = true;
+                            client = null;
+                        }
+                    }
+                    throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
+                }
+                       }
+
                        inputStream = client.GetStream();
                        outputStream = client.GetStream();
                }
 
+
+        static void ConnectCallback(IAsyncResult asyncres)
+        {
+            ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
+            lock (hlp.Mutex)
+            {
+                hlp.CallbackDone = true;
+                    
+                try
+                {
+                    if( hlp.Client.Client != null)
+                        hlp.Client.EndConnect(asyncres);
+                }
+                catch (SocketException)
+                {
+                    // catch that away
+                }
+
+                if (hlp.DoCleanup) 
+                {
+                    asyncres.AsyncWaitHandle.Close();
+                    if (hlp.Client is IDisposable)
+                        ((IDisposable)hlp.Client).Dispose();
+                    hlp.Client = null;
+                }
+            }
+        }
+
+        private class ConnectHelper
+        {
+            public object Mutex = new object();
+            public bool DoCleanup = false;
+            public bool CallbackDone = false;
+            public TcpClient Client;
+            public ConnectHelper(TcpClient client)
+            {
+                Client = client;
+            }
+        }
+
                public override void Close()
                {
                        base.Close();