I have a multi-threaded asynchronous socket listener. I want to check if the request is safe or not. But I want to check that the AcceptCallBack method does not ReceiveCallBack.
I will do this because I want my code to work for both HTTP and HTTPS. If the request comes from HTTPS, I will simply continue with SslStream authentication instead of the raw socket.
Here is my code:
using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Text; namespace LearnRequestType { class StackOverFlow { private static readonly ManualResetEvent _manualResetEvent = new ManualResetEvent(false); private void StartListening() { IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 9002); if (localEndPoint != null) { Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (listener != null) { listener.Bind(localEndPoint); listener.Listen(10); Console.WriteLine("Socket listener is running..."); listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); } } } private void AcceptCallback(IAsyncResult ar) { _manualResetEvent.Set(); Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); StateObject state = new StateObject(); state.workSocket = handler;
If I change the AcceptCallBack and StateObject Class methods as follows:
private void AcceptCallback(IAsyncResult ar) { _manualResetEvent.Set(); Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); try { sslStream = new SslStream(new NetworkStream(handler, true)); // try to authenticate sslStream.AuthenticateAsServer(_cert, false, System.Security.Authentication.SslProtocols.Tls, true); state.workStream = sslStream; state.workStream.ReadTimeout = 100000; state.workStream.WriteTimeout = 100000; if (state.workStream.IsAuthenticated) { state.workStream.BeginRead(state.buffer, 0, StateObject.BufferSize, ReceiveCallback, state); } } catch (IOException ex) { // ıf we get handshake failed due to an unexpected packet format, this means incoming data is not HTTPS // Continue with socket not sslstream state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); } StateObject state = new StateObject(); state.workStream = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); } public class StateObject { public Socket workSocket = null; public SslStream workStream = null; public const int BufferSize = 1024; public byte[] buffer = new byte[BufferSize]; public StringBuilder sb = new StringBuilder(); }
I can decide if the incoming data type is HTTP or HTTPS, but if it is HTTP, it will be processed by the catch block every time, so this will decrease the performance of the application.
Is there another way?