blob: cf1a440b0203d2fd8bf8275bb85158711d871cc8 [file] [log] [blame]
Kevin Clarkab4460d2009-03-20 02:28:41 +00001/**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
Todd Lipcon53ae9f32009-12-07 00:42:38 +000018 *
19 * Contains some contributions under the Thrift Software License.
20 * Please see doc/old-thrift-license.txt in the Thrift distribution for
21 * details.
Kevin Clarkab4460d2009-03-20 02:28:41 +000022 */
David Reiss7f42bcf2008-01-11 20:59:12 +000023
24using System;
David Reiss7f42bcf2008-01-11 20:59:12 +000025using System.Net.Sockets;
26
27namespace Thrift.Transport
28{
Jens Geyerd5436f52014-10-03 19:50:38 +020029 public class TSocket : TStreamTransport
30 {
31 private TcpClient client = null;
32 private string host = null;
33 private int port = 0;
34 private int timeout = 0;
David Reiss7f42bcf2008-01-11 20:59:12 +000035
Jens Geyerd5436f52014-10-03 19:50:38 +020036 public TSocket(TcpClient client)
37 {
38 this.client = client;
David Reiss7f42bcf2008-01-11 20:59:12 +000039
Jens Geyerd5436f52014-10-03 19:50:38 +020040 if (IsOpen)
41 {
42 inputStream = client.GetStream();
43 outputStream = client.GetStream();
44 }
45 }
David Reiss7f42bcf2008-01-11 20:59:12 +000046
Jens Geyerd5436f52014-10-03 19:50:38 +020047 public TSocket(string host, int port)
48 : this(host, port, 0)
49 {
50 }
David Reiss7f42bcf2008-01-11 20:59:12 +000051
Jens Geyerd5436f52014-10-03 19:50:38 +020052 public TSocket(string host, int port, int timeout)
53 {
54 this.host = host;
55 this.port = port;
56 this.timeout = timeout;
David Reiss7f42bcf2008-01-11 20:59:12 +000057
Jens Geyerd5436f52014-10-03 19:50:38 +020058 InitSocket();
59 }
David Reiss7f42bcf2008-01-11 20:59:12 +000060
Jens Geyerd5436f52014-10-03 19:50:38 +020061 private void InitSocket()
62 {
Jens Geyer95717c92015-04-23 22:48:13 +020063 client = new TcpClient();
64 client.ReceiveTimeout = client.SendTimeout = timeout;
65 client.Client.NoDelay = true;
Jens Geyerd5436f52014-10-03 19:50:38 +020066 }
David Reiss7f42bcf2008-01-11 20:59:12 +000067
Jens Geyerd5436f52014-10-03 19:50:38 +020068 public int Timeout
69 {
70 set
71 {
72 client.ReceiveTimeout = client.SendTimeout = timeout = value;
73 }
74 }
David Reiss7f42bcf2008-01-11 20:59:12 +000075
Jens Geyerd5436f52014-10-03 19:50:38 +020076 public TcpClient TcpClient
77 {
78 get
79 {
80 return client;
81 }
82 }
David Reiss7f42bcf2008-01-11 20:59:12 +000083
Jens Geyerd5436f52014-10-03 19:50:38 +020084 public string Host
85 {
86 get
87 {
88 return host;
89 }
90 }
David Reiss63191332009-01-06 19:49:22 +000091
Jens Geyerd5436f52014-10-03 19:50:38 +020092 public int Port
93 {
94 get
95 {
96 return port;
97 }
98 }
David Reiss63191332009-01-06 19:49:22 +000099
Jens Geyerd5436f52014-10-03 19:50:38 +0200100 public override bool IsOpen
101 {
102 get
103 {
104 if (client == null)
105 {
106 return false;
107 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000108
Jens Geyerd5436f52014-10-03 19:50:38 +0200109 return client.Connected;
110 }
111 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000112
Jens Geyerd5436f52014-10-03 19:50:38 +0200113 public override void Open()
114 {
115 if (IsOpen)
116 {
117 throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
118 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000119
Jens Geyerd5436f52014-10-03 19:50:38 +0200120 if (String.IsNullOrEmpty(host))
121 {
122 throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
123 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000124
Jens Geyerd5436f52014-10-03 19:50:38 +0200125 if (port <= 0)
126 {
127 throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port");
128 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000129
Jens Geyerd5436f52014-10-03 19:50:38 +0200130 if (client == null)
131 {
132 InitSocket();
133 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000134
Jens Geyer95717c92015-04-23 22:48:13 +0200135 if( timeout == 0) // no timeout -> infinite
Jens Geyerd5436f52014-10-03 19:50:38 +0200136 {
137 client.Connect(host, port);
138 }
139 else // we have a timeout -> use it
140 {
Jens Geyer866c23b2013-07-05 19:20:27 +0200141 ConnectHelper hlp = new ConnectHelper(client);
142 IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
143 bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
144 if (!bConnected)
145 {
146 lock (hlp.Mutex)
147 {
Jens Geyer95717c92015-04-23 22:48:13 +0200148 if( hlp.CallbackDone)
Jens Geyer866c23b2013-07-05 19:20:27 +0200149 {
150 asyncres.AsyncWaitHandle.Close();
151 client.Close();
152 }
153 else
154 {
155 hlp.DoCleanup = true;
156 client = null;
157 }
158 }
159 throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
160 }
Jens Geyerd5436f52014-10-03 19:50:38 +0200161 }
Jens Geyer866c23b2013-07-05 19:20:27 +0200162
Jens Geyerd5436f52014-10-03 19:50:38 +0200163 inputStream = client.GetStream();
164 outputStream = client.GetStream();
165 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000166
Jens Geyer866c23b2013-07-05 19:20:27 +0200167
168 static void ConnectCallback(IAsyncResult asyncres)
169 {
170 ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
171 lock (hlp.Mutex)
172 {
173 hlp.CallbackDone = true;
Jens Geyerd5436f52014-10-03 19:50:38 +0200174
Jens Geyer866c23b2013-07-05 19:20:27 +0200175 try
176 {
Jens Geyer95717c92015-04-23 22:48:13 +0200177 if( hlp.Client.Client != null)
Jens Geyer866c23b2013-07-05 19:20:27 +0200178 hlp.Client.EndConnect(asyncres);
179 }
Jens Geyerd26f6fd2014-03-19 00:21:49 +0200180 catch (Exception)
Jens Geyer866c23b2013-07-05 19:20:27 +0200181 {
182 // catch that away
183 }
184
Jens Geyerd5436f52014-10-03 19:50:38 +0200185 if (hlp.DoCleanup)
Jens Geyer866c23b2013-07-05 19:20:27 +0200186 {
Jens Geyer95717c92015-04-23 22:48:13 +0200187 try {
Jens Geyerd5436f52014-10-03 19:50:38 +0200188 asyncres.AsyncWaitHandle.Close();
Jens Geyer95717c92015-04-23 22:48:13 +0200189 } catch (Exception) {}
Jens Geyerd5436f52014-10-03 19:50:38 +0200190
Jens Geyer95717c92015-04-23 22:48:13 +0200191 try {
Jens Geyerd5436f52014-10-03 19:50:38 +0200192 if (hlp.Client is IDisposable)
193 ((IDisposable)hlp.Client).Dispose();
Jens Geyer95717c92015-04-23 22:48:13 +0200194 } catch (Exception) {}
Jens Geyer866c23b2013-07-05 19:20:27 +0200195 hlp.Client = null;
196 }
197 }
198 }
199
200 private class ConnectHelper
201 {
202 public object Mutex = new object();
203 public bool DoCleanup = false;
204 public bool CallbackDone = false;
205 public TcpClient Client;
206 public ConnectHelper(TcpClient client)
207 {
208 Client = client;
209 }
210 }
211
Jens Geyerd5436f52014-10-03 19:50:38 +0200212 public override void Close()
213 {
214 base.Close();
215 if (client != null)
216 {
217 client.Close();
218 client = null;
219 }
220 }
Roger Meierb1ec4cc2012-04-11 21:21:41 +0000221
Jens Geyer95717c92015-04-23 22:48:13 +0200222 #region " IDisposable Support "
223 private bool _IsDisposed;
Roger Meierb1ec4cc2012-04-11 21:21:41 +0000224
Jens Geyer95717c92015-04-23 22:48:13 +0200225 // IDisposable
226 protected override void Dispose(bool disposing)
227 {
228 if (!_IsDisposed)
229 {
230 if (disposing)
Roger Meierb1ec4cc2012-04-11 21:21:41 +0000231 {
Jens Geyer95717c92015-04-23 22:48:13 +0200232 if (client != null)
233 ((IDisposable)client).Dispose();
234 base.Dispose(disposing);
Roger Meierb1ec4cc2012-04-11 21:21:41 +0000235 }
Jens Geyer95717c92015-04-23 22:48:13 +0200236 }
237 _IsDisposed = true;
Roger Meierb1ec4cc2012-04-11 21:21:41 +0000238 }
Jens Geyer95717c92015-04-23 22:48:13 +0200239 #endregion
240 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000241}