diff Net/TCPStream.cs @ 0:3ab940a0c7a0

Initial commit
author Ivo Smits <Ivo@UCIS.nl>
date Tue, 11 Sep 2012 16:28:53 +0200
parents
children d0117dc37c34
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Net/TCPStream.cs	Tue Sep 11 16:28:53 2012 +0200
@@ -0,0 +1,254 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+namespace UCIS.Net {
+	public class TCPStream : Stream, INetworkConnection {
+		private static long _totalBytesRead = 0;
+		private static long _totalBytesWritten = 0;
+		public static ulong TotalBytesWritten { get { return (ulong)_totalBytesWritten; } set { _totalBytesWritten = (long)value; } }
+		public static ulong TotalBytesRead { get { return (ulong)_totalBytesRead; } set { _totalBytesRead = (long)value; } }
+
+		private Socket _Socket;
+		private byte _PeekByte;
+		private bool _HasPeekByte;
+		private ulong _BytesWritten;
+		private ulong _BytesRead;
+		private DateTime _StartTime;
+		private bool _Blocking;
+
+		public event EventHandler Closed;
+
+		public TCPStream(Socket Socket) {
+			_Socket = Socket;
+			_HasPeekByte = false;
+			_StartTime = DateTime.Now;
+			_Blocking = _Socket.Blocking;
+		}
+
+		public Socket Socket {
+			get { return _Socket; }
+		}
+
+		public DateTime CreationTime {
+			get { return _StartTime; }
+		}
+
+		public bool Blocking {
+			get { return _Blocking; }
+			set {
+				Socket.Blocking = value;
+				_Blocking = value;
+			}
+		}
+
+		public bool NoDelay {
+			get { return Socket.NoDelay; }
+			set { Socket.NoDelay = value; }
+		}
+
+		public override bool CanTimeout {
+			get { return true; }
+		}
+
+		public override int ReadTimeout {
+			get { return Socket.ReceiveTimeout; }
+			set { Socket.ReceiveTimeout = value; }
+		}
+
+		public override int WriteTimeout {
+			get { return Socket.SendTimeout; }
+			set { Socket.SendTimeout = value; }
+		}
+
+		public override int ReadByte() {
+			if (_HasPeekByte) {
+				_HasPeekByte = false;
+				return _PeekByte;
+			} else {
+				byte[] Buffer = new byte[1];
+				if (Read(Buffer, 0, 1) != 1) return -1;
+				return Buffer[0];
+			}
+		}
+
+		public override int Read(byte[] buffer, int offset, int size) {
+			int Count = 0;
+
+			if (size < 1) return 0;
+			if (_HasPeekByte) {
+				buffer[offset] = _PeekByte;
+				_HasPeekByte = false;
+				Count = 1;
+				offset += 1;
+				size -= 1;
+			}
+
+			try {
+				if (size > 0) Count += Socket.Receive(buffer, offset, size, SocketFlags.None);
+			} catch (SocketException ex) {
+				switch (ex.SocketErrorCode) {
+					case SocketError.WouldBlock:
+						_Socket.Blocking = _Blocking;
+						throw new TimeoutException("The receive operation would block", ex);
+					case SocketError.TimedOut:
+						throw new TimeoutException("The receive operation timed out", ex);
+					case SocketError.ConnectionReset:
+					case SocketError.Disconnecting:
+					case SocketError.NetworkDown:
+					case SocketError.NetworkReset:
+					case SocketError.NetworkUnreachable:
+					case SocketError.NotConnected:
+						Close();
+						throw new SocketException((int)ex.SocketErrorCode);
+					default:
+						throw new SocketException((int)ex.SocketErrorCode);
+				}
+			}
+
+			_BytesRead += (ulong)Count;
+			Interlocked.Add(ref _totalBytesRead, (long)Count);
+			return Count;
+		}
+
+		public int PeekByte() {
+			if (_HasPeekByte) {
+				return _PeekByte;
+			} else {
+				int Result = 0;
+				Result = ReadByte();
+				if (Result >= 0 && Result <= 255) {
+					_PeekByte = (byte)Result;
+					_HasPeekByte = true;
+				}
+				return Result;
+			}
+		}
+
+		public int WriteBufferSize {
+			get { return Socket.SendBufferSize; }
+			set { Socket.SendBufferSize = value; }
+		}
+
+		public int ReadBufferSize {
+			get { return Socket.ReceiveBufferSize; }
+			set { Socket.ReceiveBufferSize = value; }
+		}
+
+		public override bool CanRead {
+			get { return Socket.Connected && (Blocking || (Socket.Available > 0)); }
+		}
+
+		public override bool CanSeek {
+			get { return false; }
+		}
+
+		public override bool CanWrite {
+			get { return Socket.Connected; }
+		}
+
+		public override void Flush() {
+			//Do nothing
+			//_Socket.NoDelay = true;
+		}
+
+		public override long Length {
+			get {
+				throw new NotSupportedException();
+			}
+		}
+
+		public override long Position {
+			get {
+				throw new NotSupportedException();
+			}
+			set {
+				throw new NotSupportedException();
+			}
+		}
+
+		public override long Seek(long offset, SeekOrigin origin) {
+			throw new NotSupportedException();
+		}
+
+		public override void SetLength(long value) {
+			throw new NotSupportedException();
+		}
+
+		public override void Write(byte[] buffer, int offset, int size) {
+			int left = size;
+			if (_Socket == null) throw new ObjectDisposedException("socket");
+			try {
+				while (left > 0) {
+					int sent = _Socket.Send(buffer, offset, left, 0);
+					left -= sent;
+					offset += sent;
+				}
+			} catch (SocketException ex) {
+				switch (ex.SocketErrorCode) {
+					case SocketError.WouldBlock:
+						_Socket.Blocking = _Blocking;
+						throw new TimeoutException("The send operation would block", ex);
+					case SocketError.TimedOut:
+						throw new TimeoutException("The send operation timed out", ex);
+					case SocketError.ConnectionReset:
+					case SocketError.Disconnecting:
+					case SocketError.NetworkDown:
+					case SocketError.NetworkReset:
+					case SocketError.NetworkUnreachable:
+					case SocketError.NotConnected:
+						Close();
+						throw new SocketException((int)ex.SocketErrorCode);
+					default:
+						throw new SocketException((int)ex.SocketErrorCode);
+				}
+			}
+			_BytesWritten += (ulong)size;
+			Interlocked.Add(ref _totalBytesWritten, (long)size);
+		}
+
+		public override void Close() {
+			System.Net.Sockets.Socket s = Interlocked.Exchange(ref _Socket, null);
+			try {
+				if (s != null) {
+					try {
+						if (s.Connected) s.Shutdown(SocketShutdown.Both);
+					} catch { }
+					s.Close();
+				}
+			} finally {
+				base.Close();
+				if (Closed != null) Closed(this, new EventArgs());
+			}
+		}
+
+		public bool Connected {
+			get {
+				if (Socket == null) return false;
+				if (Socket.Connected) return true;
+				Close();
+				return false;
+			}
+		}
+
+		public object Tag { get; set; }
+
+		public ulong BytesWritten { get { return _BytesWritten; } }
+		public ulong BytesRead { get { return _BytesRead; } }
+		public TimeSpan Age { get { return DateTime.Now.Subtract(_StartTime); } }
+		public EndPoint RemoteEndPoint {
+			get {
+				if (_Socket == null || !_Socket.Connected) return null;
+				try {
+					return _Socket.RemoteEndPoint;
+				} catch (SocketException) {
+					return null;
+				}
+			}
+		}
+		//public Object Proxy { get { return null; } }
+		Object INetworkConnection.Handler { get { return Tag; } }
+	}
+}