using System; using System.Diagnostics; using System.Text; using System.Net; using System.Net.Sockets; namespace DOLInfoServer { public class ServerComponent : IServer { public AsyncCallback pfnWorkerCallBack; private Socket m_mainSocket; private Socket[] m_workerSocket = new Socket[10]; private int m_clientCount = 0; private static int port = 10500; private IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port); private string sessionPassword; private string keyHeader = "####"; private UTF8Encoding enc = new UTF8Encoding(); public static void Main(string[] args) { ServerComponent srvr = new ServerComponent(); srvr.StartServer(); } public void StartServer() { Console.WriteLine("DOLInfoServer started! Currently configured to listen on [all] interfaces, at port 10500."); m_mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Console.WriteLine("Binding socket...."); m_mainSocket.Bind(ipLocal); Console.WriteLine("Placing socket in listening state...."); m_mainSocket.Listen(4); Console.WriteLine("Waiting for connection...."); m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null); Console.ReadLine(); } public void OnClientConnect(IAsyncResult asyn) { try { // Here we complete/end the BeginAccept() asynchronous call // by calling EndAccept() - which returns the reference to // a new Socket object m_workerSocket[m_clientCount] = m_mainSocket.EndAccept(asyn); // Let the worker Socket do the further processing for the // just connected client WaitForData(m_workerSocket[m_clientCount]); // Now increment the client count ++m_clientCount; // Display this client connection as a status message on the GUI Console.WriteLine("New connection, sending encryption key."); AfterClientConnect(m_workerSocket[m_clientCount]); // Since the main Socket is now free, it can go back and wait for // other clients who are attempting to connect m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null); } catch (ObjectDisposedException) { System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n"); } catch (SocketException) { } } public class SocketPacket { public Socket m_currentSocket; public byte[] dataBuffer = new byte[1]; } public void AfterClientConnect(Socket dataSocket) { // compute our key from endpoint and our guid, something fancy :p string theirEndpoint = ((IPEndPoint)dataSocket.RemoteEndPoint).Address.ToString(); string ourGuid = System.Guid.NewGuid().ToString().Substring(0, theirEndpoint.Length); for (int i = 0; i < ourGuid.Length; i++) { sessionPassword += theirEndpoint[i]; sessionPassword += ourGuid[i]; } // we got our password, now send it over. // from now on, everything will be encrypted. dataSocket.Send(enc.GetBytes(keyHeader + sessionPassword)); } public void SendInfo(Socket dataSocket) { } public void DataReceived(string data, Socket dataSocket) { if (data.StartsWith("encryption acknowleded")) { Console.WriteLine("encryption is in place! :D"); SendInfo(dataSocket); } else { Console.WriteLine("encryption failed :("); dataSocket.Close(); } } // Start waiting for data from the client public void WaitForData(Socket dataSocket) { try { if (pfnWorkerCallBack == null) { // Specify the call back function which is to be // invoked when there is any write activity by the // connected client pfnWorkerCallBack = new AsyncCallback(OnDataReceived); } SocketPacket socketPkt = new SocketPacket(); socketPkt.m_currentSocket = dataSocket; // Start receiving any data written by the connected client // asynchronously dataSocket.BeginReceive(socketPkt.dataBuffer, 0, socketPkt.dataBuffer.Length, SocketFlags.None, pfnWorkerCallBack, socketPkt); } catch (SocketException) { } } // This the call back function which will be invoked when the socket // detects any client writing of data on the stream public void OnDataReceived(IAsyncResult asyn) { try { SocketPacket socketData = (SocketPacket)asyn.AsyncState; int iRx = 0; iRx = socketData.m_currentSocket.EndReceive(asyn); char[] chars = new char[iRx + 1]; System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder(); int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0); string szData = new System.String(chars); string decodedData = Crypto.Decrypt(szData, sessionPassword); DataReceived(decodedData, socketData.m_currentSocket); // Continue the waiting for data on the Socket WaitForData(socketData.m_currentSocket); } catch (ObjectDisposedException) { System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n"); } catch (SocketException) { } } void CloseSockets() { if (m_mainSocket != null) { m_mainSocket.Close(); } for (int i = 0; i < m_clientCount; i++) { if (m_workerSocket[i] != null) { m_workerSocket[i].Close(); m_workerSocket[i] = null; } } } } }