namespace Netkraft
{
public class NetkraftClient
{
private Socket _socket;
private readonly List< ClientConnection> _clientConnections = new List< ClientConnection>();
private Dictionary< IPEndPoint, ClientConnection> _iPEndPointToUnhandledConnections = null;
private readonly Dictionary< IPEndPoint, ClientConnection> _iPEndPointToClientConnection = new Dictionary< IPEndPoint, ClientConnection>();
private MemoryStream _instantMessageStream = new MemoryStream();
//Receive vars
private MemoryStream _receiveStream = new MemoryStream();
private readonly byte[] _buffer = new byte[65536]; //UDP messages can't exceed 65507 bytes so this should always be sufficient
private EndPoint _sender = new IPEndPoint(IPAddress.Any, 0);
public Action< RequestJoinResponse> JoinResponseCallback = null;
public Action< RequestJoin, ClientConnection> ClientJoinCallback = null;
private Random _rand = new Random();
public int FakeLossPercentage = 0;
//Constuctor
public NetkraftClient(int port)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);//Socket that supports IPV4
_socket.Bind(new IPEndPoint(IPAddress.Any, port));
new Thread(Receive).Start();
}
private void Receive()
{
while(true)
{
int size = _socket.ReceiveFrom(_buffer, ref _sender);
if (_iPEndPointToClientConnection.ContainsKey((IPEndPoint)_sender))
{
_iPEndPointToClientConnection[(IPEndPoint)_sender].Receive(_buffer, size);
}
//Host handling unhandled connections
else if(_iPEndPointToUnhandledConnections != null)
{
lock (_iPEndPointToUnhandledConnections)
{
if (!_iPEndPointToUnhandledConnections.ContainsKey((IPEndPoint)_sender))
_iPEndPointToUnhandledConnections.Add((IPEndPoint)_sender, new ClientConnection(this, (IPEndPoint)_sender));
_iPEndPointToUnhandledConnections[(IPEndPoint)_sender].Receive(_buffer, size);
}
}
}
}
internal void SendStream(MemoryStream stream, int sizeOfStreamToSend, ClientConnection client)
{
if (_rand.Next(1, 100) < FakeLossPercentage) return;
_socket.SendTo(stream.GetBuffer(), 0, sizeOfStreamToSend, SocketFlags.None, client.IpEndPoint);
}
//Public methods!
/// < summary>
/// Send a message to all connected clients Immediately not wating for the next tick.
/// < /summary>
/// < param name="message">Message to send< /param>
public void SendImmediately(object message)
public void AddToQueue(object message)
public void SendQueue()
public void Host()
public void Join(string ip, int port)
public ClientConnection AddEndPoint(IPEndPoint ipEndPoint)
{
ClientConnection c = new ClientConnection(this, ipEndPoint);
_clientConnections.Add(c);
if(!_iPEndPointToClientConnection.ContainsKey(ipEndPoint))
_iPEndPointToClientConnection.Add(ipEndPoint, c);
return c;
}
public void ReceiveTick()
{
for(int i=0;i< _clientConnections.Count; i++)
_clientConnections[i].ReceiveTick();
//Unhandeld
if (_iPEndPointToUnhandledConnections == null) return;
lock (_iPEndPointToUnhandledConnections)
{
foreach (ClientConnection CC in _iPEndPointToUnhandledConnections.Values)
CC.ReceiveTickRestrictive();
}
}
}
}