From cca00ca97ecc0b3581aed1c29fdd9b84d12d27c9 Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Fri, 22 May 2020 14:32:28 +0300 Subject: [PATCH] SSL --- Esyur/Net/HTTP/HTTPServer.cs | 6 +- .../Net/IIP/DistributedConnectionProtocol.cs | 4 +- Esyur/Net/Sockets/SSLSocket.cs | 348 ++++++++++++------ Esyur/Net/Sockets/TCPSocket.cs | 27 +- 4 files changed, 253 insertions(+), 132 deletions(-) diff --git a/Esyur/Net/HTTP/HTTPServer.cs b/Esyur/Net/HTTP/HTTPServer.cs index a21cc4f..0ead13b 100644 --- a/Esyur/Net/HTTP/HTTPServer.cs +++ b/Esyur/Net/HTTP/HTTPServer.cs @@ -306,9 +306,9 @@ namespace Esyur.Net.HTTP else ipAdd = IPAddress.Parse(IP); - // if (ssl) - // listener = new SSLSocket(new IPEndPoint(ipAdd, port), new X509Certificate2(certificate)); - // else + if (SSL) + listener = new SSLSocket(new IPEndPoint(ipAdd, Port), new X509Certificate2(Certificate)); + else listener = new TCPSocket(new IPEndPoint(ipAdd, Port)); Start(listener); diff --git a/Esyur/Net/IIP/DistributedConnectionProtocol.cs b/Esyur/Net/IIP/DistributedConnectionProtocol.cs index 3cc2a4a..4b7df69 100644 --- a/Esyur/Net/IIP/DistributedConnectionProtocol.cs +++ b/Esyur/Net/IIP/DistributedConnectionProtocol.cs @@ -1200,7 +1200,7 @@ namespace Esyur.Net.IIP return; } - if (rt is System.Collections.IEnumerable && !(rt is Array || rt is Structure)) + if (rt is System.Collections.IEnumerable && !(rt is Array || rt is Structure || rt is string)) { var enu = rt as System.Collections.IEnumerable; @@ -1361,7 +1361,7 @@ namespace Esyur.Net.IIP return; } - if (rt is System.Collections.IEnumerable && !(rt is Array)) + if (rt is System.Collections.IEnumerable && !(rt is Array || rt is Structure || rt is string)) { var enu = rt as System.Collections.IEnumerable; diff --git a/Esyur/Net/Sockets/SSLSocket.cs b/Esyur/Net/Sockets/SSLSocket.cs index d7187bb..1a38e2a 100644 --- a/Esyur/Net/Sockets/SSLSocket.cs +++ b/Esyur/Net/Sockets/SSLSocket.cs @@ -43,15 +43,19 @@ namespace Esyur.Net.Sockets { Socket sock; byte[] receiveBuffer; - + + bool held; + + //ArraySegment receiveBufferSegment; + NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); - object sendLock = new object(); + readonly object sendLock = new object(); - Queue sendBufferQueue = new Queue(); + Queue, byte[]>> sendBufferQueue = new Queue, byte[]>>();// Queue(); bool asyncSending; - + bool began = false; SocketState state = SocketState.Initial; @@ -60,80 +64,119 @@ namespace Esyur.Net.Sockets public event ISocketCloseEvent OnClose; public event DestroyedEvent OnDestroy; + SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs(); + SslStream ssl; X509Certificate2 cert; bool server; string hostname; - private void Connected(Task t) - { - if (server) - { - ssl.AuthenticateAsServerAsync(cert).ContinueWith(Authenticated); - } - else - { - ssl.AuthenticateAsClientAsync(hostname).ContinueWith(Authenticated); - } - } - public AsyncReply Connect(string hostname, ushort port) + public async AsyncReply Connect(string hostname, ushort port) { var rt = new AsyncReply(); + state = SocketState.Connecting; + await sock.ConnectAsync(hostname, port); + + if (server) + await ssl.AuthenticateAsServerAsync(cert); + else + await ssl.AuthenticateAsClientAsync(hostname); + try { - state = SocketState.Connecting; - sock.ConnectAsync(hostname, port).ContinueWith((x) => - { - if (x.IsFaulted) - rt.TriggerError(x.Exception); - else - rt.Trigger(true); + state = SocketState.Established; + OnConnect?.Invoke(); - Connected(x); - }); + if (!server) + Begin(); } catch (Exception ex) { - rt.TriggerError(ex); + state = SocketState.Terminated; + Close(); + Global.Log(ex); } - return rt; + return true; } - private void DataSent(Task task) - { - try - { + //private void DataSent(Task task) + //{ + // try + // { + // if (sendBufferQueue.Count > 0) + // { + // byte[] data = sendBufferQueue.Dequeue(); + // lock (sendLock) + // ssl.WriteAsync(data, 0, data.Length).ContinueWith(DataSent); + // } + // else + // { + // asyncSending = false; + // } + // } + // catch (Exception ex) + // { + // if (state != SocketState.Closed && !sock.Connected) + // { + // state = SocketState.Terminated; + // Close(); + // } + + // asyncSending = false; + + // Global.Log("SSLSocket", LogType.Error, ex.ToString()); + // } + //} + + + private void SendCallback(IAsyncResult ar) + { + if (ar != null && ar.AsyncState != null) + ((AsyncReply)ar.AsyncState).Trigger(true); + + lock (sendLock) + { if (sendBufferQueue.Count > 0) { - byte[] data = sendBufferQueue.Dequeue(); - lock (sendLock) - ssl.WriteAsync(data, 0, data.Length).ContinueWith(DataSent); + var kv = sendBufferQueue.Dequeue(); + + try + { + ssl.BeginWrite(kv.Value, 0, kv.Value.Length, SendCallback, kv.Key); + } + catch (Exception ex) + { + asyncSending = false; + + try + { + kv.Key.Trigger(false); + + if (state != SocketState.Closed && !sock.Connected) + { + state = SocketState.Terminated; + Close(); + } + } + catch (Exception ex2) + { + state = SocketState.Terminated; + } + + Global.Log("TCPSocket", LogType.Error, ex.ToString()); + } } else { asyncSending = false; } } - catch (Exception ex) - { - if (state != SocketState.Closed && !sock.Connected) - { - state = SocketState.Terminated; - Close(); - } - - asyncSending = false; - - Global.Log("SSLSocket", LogType.Error, ex.ToString()); - } } - - public IPEndPoint LocalEndPoint { get { return (IPEndPoint)sock.LocalEndPoint; } @@ -185,14 +228,14 @@ namespace Esyur.Net.Sockets cert = certificate; sock = Socket; receiveBuffer = new byte[sock.ReceiveBufferSize]; - + ssl = new SslStream(new NetworkStream(sock)); server = authenticateAsServer; } - + public void Close() { if (state != SocketState.Closed && state != SocketState.Terminated) @@ -215,65 +258,137 @@ namespace Esyur.Net.Sockets OnClose?.Invoke(); } + public void Send(byte[] message) { Send(message, 0, message.Length); } + public void Send(byte[] message, int offset, int size) { + + + var msg = message.Clip((uint)offset, (uint)size); + lock (sendLock) { - if (asyncSending) + + if (!sock.Connected) + return; + + if (asyncSending || held) { - sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size)); + sendBufferQueue.Enqueue(new KeyValuePair, byte[]>(null, msg));// message.Clip((uint)offset, (uint)size)); } else { asyncSending = true; - ssl.WriteAsync(message, offset, size).ContinueWith(DataSent); + try + { + ssl.BeginWrite(msg, 0, msg.Length, SendCallback, null); + } + catch + { + asyncSending = false; + state = SocketState.Terminated; + Close(); + } } } } - void Authenticated(Task task) - { - try - { - state = SocketState.Established; - OnConnect?.Invoke(); + //public void Send(byte[] message) + //{ + // Send(message, 0, message.Length); + //} - if (!server) - Begin(); - } - catch (Exception ex) + //public void Send(byte[] message, int offset, int size) + //{ + // lock (sendLock) + // { + // if (asyncSending) + // { + // sendBufferQueue.Enqueue(message.Clip((uint)offset, (uint)size)); + // } + // else + // { + // asyncSending = true; + // ssl.WriteAsync(message, offset, size).ContinueWith(DataSent); + // } + // } + //} + + + + //private void DataReceived(Task task) + //{ + // try + // { + // if (state == SocketState.Closed || state == SocketState.Terminated) + // return; + + // if (task.Result <= 0) + // { + // Close(); + // return; + // } + + // receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)task.Result); + // OnReceive?.Invoke(receiveNetworkBuffer); + // if (state == SocketState.Established) + // ssl.ReadAsync(receiveBuffer, 0, receiveBuffer.Length).ContinueWith(DataReceived); + // } + // catch (Exception ex) + // { + // if (state != SocketState.Closed && !sock.Connected) + // { + // state = SocketState.Terminated; + // Close(); + // } + + // Global.Log("SSLSocket", LogType.Error, ex.ToString()); + // } + //} + + public bool Begin() + { + if (began) + return false; + + began = true; + + if (state == SocketState.Established) { - state = SocketState.Terminated; - Close(); - Global.Log(ex); + ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this); + return true; } + else + return false; } - private void DataReceived(Task task) + + private void ReceiveCallback(IAsyncResult results) { try { - // SocketError err; - - if (state == SocketState.Closed || state == SocketState.Terminated) + if (state != SocketState.Established) return; - if (task.Result <= 0) + var bytesReceived = ssl.EndRead(results); + + if (bytesReceived <= 0) { Close(); return; } + receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)bytesReceived); - receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)task.Result); OnReceive?.Invoke(receiveNetworkBuffer); - if (state == SocketState.Established) - ssl.ReadAsync(receiveBuffer, 0, receiveBuffer.Length).ContinueWith(DataReceived); + + ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this); + } catch (Exception ex) { @@ -287,19 +402,6 @@ namespace Esyur.Net.Sockets } } - public bool Begin() - { - if (state == SocketState.Established) - { - ssl.ReadAsync(receiveBuffer, 0, receiveBuffer.Length).ContinueWith(DataReceived); - return true; - } - else - return false; - } - - - public bool Trigger(ResourceTrigger trigger) { return true; @@ -313,50 +415,78 @@ namespace Esyur.Net.Sockets public async AsyncReply AcceptAsync() { - //var reply = new AsyncReply(); - try { - return new SSLSocket(await sock.AcceptAsync(), cert, true); - - //sock.AcceptAsync().ContinueWith((x) => - //{ - // try - // { - // reply.Trigger(new SSLSocket(x.Result, cert, true)); - // } - // catch - // { - // reply.Trigger(null); - // } - - //}, null); - + var s = await sock.AcceptAsync(); + return new SSLSocket(s, cert, true); } catch { state = SocketState.Terminated; return null; } - - //return reply; } + public void Hold() { - throw new NotImplementedException(); + held = true; } public void Unhold() { - throw new NotImplementedException(); + try + { + SendCallback(null); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + finally + { + held = false; + } } + public AsyncReply SendAsync(byte[] message, int offset, int length) { - throw new NotImplementedException(); + + var msg = message.Clip((uint)offset, (uint)length); + + lock (sendLock) + { + if (!sock.Connected) + return new AsyncReply(false); + + var rt = new AsyncReply(); + + if (asyncSending || held) + { + sendBufferQueue.Enqueue(new KeyValuePair, byte[]>(rt, msg)); + } + else + { + asyncSending = true; + try + { + ssl.BeginWrite(msg, 0, msg.Length, SendCallback, rt);// null); + } + catch (Exception ex) + { + rt.TriggerError(ex); + asyncSending = false; + state = SocketState.Terminated; + Close(); + } + } + + return rt; + } } + public ISocket Accept() { try diff --git a/Esyur/Net/Sockets/TCPSocket.cs b/Esyur/Net/Sockets/TCPSocket.cs index 99e5c52..f2410fd 100644 --- a/Esyur/Net/Sockets/TCPSocket.cs +++ b/Esyur/Net/Sockets/TCPSocket.cs @@ -128,21 +128,11 @@ namespace Esyur.Net.Sockets return; } - //if (receiveNetworkBuffer.Protected) - // Console.WriteLine(); - - //lock (receiveNetworkBuffer.SyncLock) receiveNetworkBuffer.Write(receiveBuffer, 0, (uint)task.Result); - - //Console.WriteLine("TC IN: " + (uint)task.Result + " " + DC.ToHex(receiveBuffer, 0, (uint)task.Result)); - OnReceive?.Invoke(receiveNetworkBuffer); if (state == SocketState.Established) - { sock.ReceiveAsync(receiveBufferSegment, SocketFlags.None).ContinueWith(DataReceived); - } - } catch (Exception ex) { @@ -175,7 +165,7 @@ namespace Esyur.Net.Sockets OnReceive?.Invoke(receiveNetworkBuffer); if (state == SocketState.Established) - while(!sock.ReceiveAsync(e)) + while (!sock.ReceiveAsync(e)) { if (e.SocketError != SocketError.Success) { @@ -376,9 +366,10 @@ namespace Esyur.Net.Sockets asyncSending = true; try { - sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, PacketSent, null); + sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, SendCallback, null); } - catch { + catch + { asyncSending = false; state = SocketState.Terminated; Close(); @@ -389,7 +380,7 @@ namespace Esyur.Net.Sockets } - private void PacketSent(IAsyncResult ar) + private void SendCallback(IAsyncResult ar) { if (ar != null && ar.AsyncState != null) ((AsyncReply)ar.AsyncState).Trigger(true); @@ -402,7 +393,7 @@ namespace Esyur.Net.Sockets try { - sock.BeginSend(kv.Value, 0, kv.Value.Length, SocketFlags.None, PacketSent, kv.Key); + sock.BeginSend(kv.Value, 0, kv.Value.Length, SocketFlags.None, SendCallback, kv.Key); } catch (Exception ex) { @@ -482,7 +473,7 @@ namespace Esyur.Net.Sockets { try { - PacketSent(null); + SendCallback(null); } catch (Exception ex) { @@ -515,9 +506,9 @@ namespace Esyur.Net.Sockets asyncSending = true; try { - sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, PacketSent, rt);// null); + sock.BeginSend(msg, 0, msg.Length, SocketFlags.None, SendCallback, rt);// null); } - catch(Exception ex) + catch (Exception ex) { rt.TriggerError(ex); asyncSending = false;