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;
}
}
}
}
}