PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Manos/Manos.Managed/Socket.cs

https://github.com/TimGebhardt/manos
C# | 355 lines | 308 code | 47 blank | 0 comment | 52 complexity | 33ae34fed2b038a4809ef4588f691a2d MD5 | raw file
Possible License(s): BSD-2-Clause
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net.Sockets;
  6. using System.Net;
  7. using Manos.IO;
  8. using Manos.Collections;
  9. namespace Manos.Managed
  10. {
  11. public class Socket : Manos.IO.Socket
  12. {
  13. System.Net.Sockets.Socket socket;
  14. Action connectedCallback;
  15. Action<Socket> acceptedCallback;
  16. Stream stream;
  17. IOLoop loop;
  18. public Socket (IOLoop loop)
  19. {
  20. if (loop == null)
  21. throw new ArgumentNullException ("loop");
  22. this.loop = loop;
  23. }
  24. Socket (IOLoop loop, System.Net.Sockets.Socket socket) : this (loop)
  25. {
  26. this.socket = socket;
  27. this.address = ((IPEndPoint) socket.RemoteEndPoint).Address.ToString ();
  28. this.port = ((IPEndPoint) socket.RemoteEndPoint).Port;
  29. }
  30. class SocketStream : Manos.IO.Stream
  31. {
  32. Socket parent;
  33. bool readAllowed, writeAllowed;
  34. long readLimit, position;
  35. byte [] receiveBuffer = new byte [4096];
  36. System.Timers.Timer readTimer, writeTimer;
  37. public SocketStream (Socket parent)
  38. {
  39. this.parent = parent;
  40. }
  41. public override long Position {
  42. get { return position; }
  43. set { SeekTo (value); }
  44. }
  45. public override bool CanRead {
  46. get { return true; }
  47. }
  48. public override bool CanWrite {
  49. get { return true; }
  50. }
  51. public override bool CanTimeout {
  52. get { return true; }
  53. }
  54. public override TimeSpan ReadTimeout {
  55. get { return readTimer == null ? TimeSpan.Zero : TimeSpan.FromMilliseconds (readTimer.Interval); }
  56. set {
  57. if (value < TimeSpan.Zero)
  58. throw new ArgumentException ("value");
  59. if (readTimer == null) {
  60. readTimer = new System.Timers.Timer (value.TotalMilliseconds);
  61. readTimer.Elapsed += HandleReadTimerElapsed;
  62. }
  63. if (value == TimeSpan.Zero) {
  64. readTimer.Stop ();
  65. } else {
  66. readTimer.Interval = value.TotalMilliseconds;
  67. readTimer.Start ();
  68. }
  69. }
  70. }
  71. public override TimeSpan WriteTimeout {
  72. get { return writeTimer == null ? TimeSpan.Zero : TimeSpan.FromMilliseconds (writeTimer.Interval); }
  73. set {
  74. if (value < TimeSpan.Zero)
  75. throw new ArgumentException ("value");
  76. if (writeTimer == null) {
  77. writeTimer = new System.Timers.Timer (value.TotalMilliseconds);
  78. writeTimer.Elapsed += HandleWriteTimerElapsed;
  79. }
  80. if (value == TimeSpan.Zero) {
  81. writeTimer.Stop ();
  82. } else {
  83. writeTimer.Interval = value.TotalMilliseconds;
  84. writeTimer.Start ();
  85. }
  86. }
  87. }
  88. void HandleReadTimerElapsed (object sender, System.Timers.ElapsedEventArgs e)
  89. {
  90. if (readAllowed) {
  91. RaiseError (new TimeoutException ());
  92. PauseReading ();
  93. }
  94. }
  95. void HandleWriteTimerElapsed (object sender, System.Timers.ElapsedEventArgs e)
  96. {
  97. if (writeAllowed) {
  98. RaiseError (new TimeoutException ());
  99. PauseWriting ();
  100. }
  101. }
  102. public override void Write (IEnumerable<ByteBuffer> data)
  103. {
  104. base.Write (data);
  105. ResumeWriting ();
  106. }
  107. public override void ResumeReading ()
  108. {
  109. ResumeReading (long.MaxValue);
  110. }
  111. public override void ResumeReading (long forBytes)
  112. {
  113. if (forBytes < 0)
  114. throw new ArgumentException ("forBytes");
  115. readLimit = forBytes;
  116. throw new NotImplementedException ();
  117. }
  118. public override void ResumeWriting ()
  119. {
  120. writeAllowed = true;
  121. HandleWrite ();
  122. }
  123. public override void PauseReading ()
  124. {
  125. readAllowed = false;
  126. }
  127. public override void PauseWriting ()
  128. {
  129. writeAllowed = false;
  130. }
  131. public override void Flush ()
  132. {
  133. }
  134. public override IDisposable Read (Action<ByteBuffer> onData, Action<Exception> onError, Action onClose)
  135. {
  136. ResumeReading ();
  137. return base.Read (onData, onError, onClose);
  138. }
  139. protected override void HandleWrite ()
  140. {
  141. if (writeAllowed) {
  142. base.HandleWrite ();
  143. }
  144. }
  145. protected override int WriteSingleBuffer (ByteBuffer buffer)
  146. {
  147. SocketError err;
  148. parent.socket.BeginSend (buffer.Bytes, buffer.Position, buffer.Length, SocketFlags.None, out err, ar => {
  149. if (writeTimer != null) {
  150. writeTimer.Stop ();
  151. writeTimer.Start ();
  152. }
  153. parent.socket.EndSend (ar);
  154. if (err != SocketError.Success) {
  155. parent.loop.NonBlockInvoke (delegate {
  156. RaiseError (new SocketException ());
  157. });
  158. } else {
  159. parent.loop.NonBlockInvoke (ResumeWriting);
  160. }
  161. }, null);
  162. return buffer.Length;
  163. }
  164. void HandleRead ()
  165. {
  166. if (!readAllowed) {
  167. return;
  168. }
  169. SocketError se;
  170. int length = (int) Math.Min (readLimit, receiveBuffer.Length);
  171. parent.socket.BeginReceive (receiveBuffer, 0, length, SocketFlags.None, out se, ReadCallback, null);
  172. }
  173. void ReadCallback (IAsyncResult ar)
  174. {
  175. if (readTimer != null) {
  176. readTimer.Stop ();
  177. readTimer.Start ();
  178. }
  179. SocketError error;
  180. int len = parent.socket.EndReceive (ar, out error);
  181. if (error != SocketError.Success) {
  182. parent.loop.NonBlockInvoke (delegate {
  183. RaiseError (new SocketException ());
  184. });
  185. } else if (len == 0) {
  186. parent.loop.NonBlockInvoke (RaiseEndOfStream);
  187. } else {
  188. parent.loop.NonBlockInvoke (delegate {
  189. RaiseData (new ByteBuffer (receiveBuffer, 0, len));
  190. HandleRead ();
  191. });
  192. }
  193. }
  194. protected override void RaiseData (ByteBuffer data)
  195. {
  196. position += data.Length;
  197. base.RaiseData (data);
  198. }
  199. public override void Close ()
  200. {
  201. if (parent == null) {
  202. return;
  203. }
  204. parent.socket.BeginDisconnect (false, ar => {
  205. try {
  206. parent.socket.EndDisconnect (ar);
  207. RaiseEndOfStream ();
  208. parent = null;
  209. if (readTimer != null) {
  210. readTimer.Dispose ();
  211. }
  212. if (writeTimer != null) {
  213. writeTimer.Dispose ();
  214. }
  215. readTimer = null;
  216. writeTimer = null;
  217. base.Close ();
  218. } catch {
  219. }
  220. }, null);
  221. base.Close ();
  222. }
  223. }
  224. public override Manos.IO.Stream GetSocketStream ()
  225. {
  226. if (state != Socket.SocketState.Open)
  227. throw new InvalidOperationException ();
  228. if (stream == null)
  229. stream = new SocketStream (this);
  230. return stream;
  231. }
  232. public override void Connect (string host, int port, Action callback)
  233. {
  234. if (state != Socket.SocketState.Invalid)
  235. throw new InvalidOperationException ();
  236. address = host;
  237. this.port = port;
  238. connectedCallback = callback;
  239. IPAddress addr;
  240. if (!IPAddress.TryParse (host, out addr)) {
  241. Dns.BeginGetHostEntry (host, (a) => {
  242. try {
  243. IPHostEntry ep = Dns.EndGetHostEntry (a);
  244. StartConnectingSocket (ep.AddressList [0], port);
  245. } catch {
  246. }
  247. }, null);
  248. } else {
  249. StartConnectingSocket (addr, port);
  250. }
  251. }
  252. void StartConnectingSocket (IPAddress addr, int port)
  253. {
  254. socket = new System.Net.Sockets.Socket (addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  255. try {
  256. socket.BeginConnect (addr, port, (ar) => {
  257. try {
  258. socket.EndConnect (ar);
  259. loop.NonBlockInvoke (connectedCallback);
  260. } catch {
  261. }
  262. }, null);
  263. } catch {
  264. }
  265. }
  266. public override void Listen (string host, int port, Action<Manos.IO.Socket> callback)
  267. {
  268. if (state != Socket.SocketState.Invalid)
  269. throw new InvalidOperationException ();
  270. address = host;
  271. this.port = port;
  272. acceptedCallback = callback;
  273. IPAddress addr;
  274. if (!IPAddress.TryParse (host, out addr)) {
  275. Dns.BeginGetHostEntry (host, (a) => {
  276. try {
  277. IPHostEntry ep = Dns.EndGetHostEntry (a);
  278. StartListeningSocket (ep.AddressList [0], port);
  279. } catch {
  280. }
  281. }, null);
  282. } else {
  283. StartListeningSocket (addr, port);
  284. }
  285. }
  286. void StartListeningSocket (IPAddress addr, int port)
  287. {
  288. socket = new System.Net.Sockets.Socket (addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  289. try {
  290. socket.Bind (new IPEndPoint (addr, port));
  291. socket.Listen (5);
  292. socket.BeginAccept (AcceptCallback, null);
  293. } catch {
  294. }
  295. }
  296. void AcceptCallback (IAsyncResult ar)
  297. {
  298. try {
  299. var sock = socket.EndAccept (ar);
  300. loop.NonBlockInvoke (delegate {
  301. acceptedCallback (new Socket (loop, sock));
  302. });
  303. socket.BeginAccept (AcceptCallback, null);
  304. } catch {
  305. }
  306. }
  307. }
  308. }