Mercurial > hg > ucis.core
annotate Net/TCPServer.cs @ 108:819fb56a56ea
Removed rate limiting code from TCPServer
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Mon, 27 Oct 2014 23:24:32 +0100 |
parents | 4ba4fd48e1da |
children |
rev | line source |
---|---|
0 | 1 ???using System; |
2 using System.Net; | |
3 using System.Net.Sockets; | |
4 using System.Threading; | |
5 using System.Collections.Generic; | |
6 | |
7 namespace UCIS.Net { | |
8 public class TCPServer { | |
9 public class ModuleCollection : Dictionary<byte, IModule> { | |
10 public void Add(char Key, IModule Value) { | |
11 base.Add((byte)Key, Value); | |
12 } | |
13 public void Remove(char Key) { | |
14 base.Remove((byte)Key); | |
15 } | |
16 } | |
17 | |
18 public class ClientAcceptedEventArgs : EventArgs { | |
19 private TCPStream _client; | |
20 internal ClientAcceptedEventArgs(TCPStream client) { | |
21 _client = client; | |
22 } | |
23 public TCPStream Client { get { return _client; } } | |
24 } | |
25 | |
26 public event EventHandler<ClientAcceptedEventArgs> ClientAccepted; | |
27 | |
28 private Socket _Listener; | |
29 private UCIS.ThreadPool _ThreadPool; | |
30 private NetworkConnectionList _Clients = new NetworkConnectionList(); | |
31 private ModuleCollection _Modules = new ModuleCollection(); | |
32 private IModule _CatchAllModule = null; | |
33 | |
34 public TCPServer() { | |
35 _ThreadPool = UCIS.ThreadPool.DefaultPool; | |
36 } | |
37 | |
38 public NetworkConnectionList Clients { | |
39 get { return _Clients; } | |
40 } | |
41 | |
42 public ModuleCollection Modules { | |
43 get { return _Modules; } | |
44 } | |
45 | |
46 public IModule CatchAllModule { | |
47 get { | |
48 return _CatchAllModule; | |
49 } | |
50 set { | |
51 _CatchAllModule = value; | |
52 } | |
53 } | |
54 | |
55 public EndPoint LocalEndPoint { get { return _Listener.LocalEndPoint; } } | |
56 | |
57 public void Listen(int Port) { | |
58 Listen(AddressFamily.InterNetwork, Port); | |
59 } | |
60 public void Listen(AddressFamily af, int Port) { | |
61 Stop(); | |
62 _Listener = new Socket(af, SocketType.Stream, ProtocolType.Tcp); | |
63 _Listener.Bind(new IPEndPoint(af == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any, Port)); | |
64 _Listener.Listen(25); | |
65 _Listener.BeginAccept(AcceptCallback, null); | |
66 } | |
67 | |
68 public void Stop() { | |
69 if (_Listener != null && _Listener.IsBound) _Listener.Close(); | |
70 _Listener = null; | |
71 } | |
72 | |
73 public void Close() { | |
74 Close(true); | |
75 } | |
76 public void Close(bool CloseClients) { | |
77 Stop(); | |
78 if (CloseClients) { | |
79 _Clients.CloseAll(); | |
80 if (_Clients.Count > 0) Console.WriteLine("TCPServer.Close: Warning: " + _Clients.Count.ToString() + " connections were not properly terminated."); | |
81 } else { | |
82 _Clients.Clear(); | |
83 } | |
84 } | |
85 | |
108
819fb56a56ea
Removed rate limiting code from TCPServer
Ivo Smits <Ivo@UCIS.nl>
parents:
105
diff
changeset
|
86 private void AcceptCallback(IAsyncResult ar) { |
819fb56a56ea
Removed rate limiting code from TCPServer
Ivo Smits <Ivo@UCIS.nl>
parents:
105
diff
changeset
|
87 if (_Listener == null) return; |
0 | 88 Socket Socket = null; |
89 try { | |
90 Socket = _Listener.EndAccept(ar); | |
91 } catch (ObjectDisposedException) { | |
92 Console.WriteLine("TCPServer.AcceptCallback Listener object has been disposed. Aborting."); | |
93 return; | |
94 } catch (SocketException ex) { | |
95 Console.WriteLine("TCPServer.AcceptCallback SocketException: " + ex.Message); | |
96 Socket = null; | |
97 } | |
98 if (Socket != null) { | |
99 try { | |
108
819fb56a56ea
Removed rate limiting code from TCPServer
Ivo Smits <Ivo@UCIS.nl>
parents:
105
diff
changeset
|
100 Client Client = new Client(Socket, this); |
0 | 101 _Clients.Add(Client); |
102 if (ClientAccepted != null) ClientAccepted(this, new ClientAcceptedEventArgs(Client)); | |
103 Client.Start(_ThreadPool); | |
104 } catch (Exception ex) { | |
105 Console.WriteLine(ex.ToString()); | |
106 } | |
107 } | |
108
819fb56a56ea
Removed rate limiting code from TCPServer
Ivo Smits <Ivo@UCIS.nl>
parents:
105
diff
changeset
|
108 _Listener.BeginAccept(AcceptCallback, null); |
0 | 109 } |
110 | |
111 public interface IModule { | |
112 // Return value: True = Close connection, False = keep alive | |
113 bool Accept(TCPStream Stream); | |
114 } | |
115 | |
116 private class Client : TCPStream { | |
117 private TCPServer _Server; | |
118 private IModule _Module; | |
119 private byte _MagicNumber; | |
120 | |
121 public TCPServer Server { | |
122 get { return _Server; } | |
123 } | |
124 public IModule Module { | |
125 get { return _Module; } | |
126 } | |
127 | |
128 private void _Stream_Closed(object sender, EventArgs e) { | |
129 _Module = null; | |
130 _Server = null; | |
131 base.Closed -= _Stream_Closed; | |
132 } | |
133 | |
134 internal Client(Socket Socket, TCPServer Server) : base(Socket) { | |
135 _Server = Server; | |
136 base.Closed += _Stream_Closed; | |
137 this.Tag = Server; | |
138 } | |
139 | |
140 internal void Start(UCIS.ThreadPool Pool) { | |
108
819fb56a56ea
Removed rate limiting code from TCPServer
Ivo Smits <Ivo@UCIS.nl>
parents:
105
diff
changeset
|
141 Pool.QueueWorkItem(WorkerProc, null); |
0 | 142 } |
143 | |
144 private void WorkerProc(object state) { | |
145 bool CloseSocket = true; | |
146 try { | |
147 try { | |
148 //base.NoDelay = true; | |
149 base.ReadTimeout = 5000; | |
150 //Console.WriteLine("TCPServer: Accepted connection from " + base.Socket.RemoteEndPoint.ToString()); | |
151 _MagicNumber = (byte)base.PeekByte(); | |
152 } catch (TimeoutException ex) { | |
153 Console.WriteLine("TCPServer: Caught TimeoutException while reading magic number: " + ex.Message); | |
154 return; | |
155 } | |
156 if (_Server._Modules.TryGetValue(_MagicNumber, out _Module)) { | |
157 this.Tag = _Module; | |
158 CloseSocket = _Module.Accept(this); | |
159 } else if (_Server._CatchAllModule != null) { | |
160 this.Tag = _Server._CatchAllModule; | |
161 CloseSocket = _Server._CatchAllModule.Accept(this); | |
162 } else { | |
163 this.Tag = this; | |
164 Console.WriteLine("TCPServer: Unknown magic number: " + _MagicNumber.ToString()); | |
165 } | |
166 } catch (ThreadAbortException) { | |
167 Console.WriteLine("TCPServer: Caught ThreadAbortException"); | |
168 } catch (SocketException ex) { | |
169 Console.WriteLine("TCPServer: Caught SocketException: " + ex.Message); | |
170 } catch (Exception ex) { | |
171 Console.WriteLine("TCPServer: Caught Exception: " + ex.ToString()); | |
172 } finally { | |
173 try { | |
174 if (CloseSocket) base.Close(); | |
175 } catch { } | |
176 } | |
177 } | |
178 } | |
179 } | |
180 } |