using System; using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using Mistox.ResevedPackets; namespace Mistox.Client { public class MistoxClient { public string ServerName { get; private set; } = ""; // The Name of the server public string UserName { get; private set; } = ""; // My UserName public bool Alive { get; set; } = true; // Is the server running public bool isAuthenticated { get; set; } = false; // Is the server authenticated public ConcurrentDictionary clientConnections { get; private set; } // UserName, Connection public mTCPClient ServerConnection {get; private set; } // Global TCP Server Connection public UdpClient ClientSocket { get; private set; } // Global UDP Sender public UDPReceiver UdpReceiver { get; private set; } // Global UDP Receiver private readonly string ConnectionKey = ""; // Server Connection Key public MistoxClient(string userName, string connectionKey, IPEndPoint Server) { // Create and listen on UDP ClientSocket = new UdpClient( Server.Port ); UdpReceiver = new UDPReceiver( this ); UserName = userName; ConnectionKey = connectionKey; // Create and connect to server on TCP Console.WriteLine( "The client is initilized and trying to connect to the server at ip : " + Server.Address ); try { ServerConnection = new mTCPClient( this, Server ); Console.WriteLine( "Connected to the server sucessfully" ); Alive = true; } catch( Exception e ) { Console.WriteLine( "An error has occured with the connection to the server. Error { " ); Console.WriteLine( e.ToString() ); Console.WriteLine( "}" ); Alive = false; } } public async Task TryAuth() { Console.WriteLine("Attempting to authenticate against the server..."); await ServerConnection.Send(new UserAuthPacket { UserName = UserName, ConnectionKey = ConnectionKey }); } ///////////////////////////// // Receive Methods ///////////////////////////// public void UserConnected(UserConnectedPacket packet) { IPEndPoint remoteUser = new IPEndPoint(packet.ClientIPAddress, packet.ClientPort); mUDPClient user = new mUDPClient(this, remoteUser) { UserName = packet.UserName }; clientConnections[remoteUser] = user; InvokeOnUserConnected(user); } public void UserDisconnected(UserDisconnectedPacket packet) { mUDPClient client = null; foreach(mUDPClient cur in clientConnections.Values) { if (cur.UserName.ToLower() == packet.UserName.ToLower()) { client = cur; break; } } if (client != null) { InvokeOnUserDisconnected( client ); client.Alive = false; client.Dispose(); clientConnections[client._remoteHost] = null; } } ///////////////////////////// // Events ///////////////////////////// public event Action onDataReceived; public void InvokeOnReceived(dynamic DataPacket, mUDPClient remote = null){ switch (DataPacket as object) { case UserConnectedPacket packet: UserConnected(packet); break; case UserDisconnectedPacket packet: UserDisconnected(packet); break; case null: Console.WriteLine("Received a null packet."); break; default: onDataReceived?.Invoke(DataPacket); break; } } public event Action onServerConnected; public void InvokeOnServerConnected(){ Alive = true; Task.Run(async () => { try { await TryAuth(); } catch {} }); onServerConnected?.Invoke(); } public event Action onUserConnected; public void InvokeOnUserConnected(mUDPClient ConnectedUser){ onUserConnected?.Invoke(ConnectedUser); } public event Action onUserDisconnected; public void InvokeOnUserDisconnected(mUDPClient DisconnectedUser){ onUserDisconnected?.Invoke(DisconnectedUser); } public event Action onServerDisconnected; public void InvokeOnServerDisconnected(){ Alive = false; onServerDisconnected?.Invoke(); } public async Task SendAllClients(Packet data) { foreach( mUDPClient cur in clientConnections.Values ){ await cur.Send( data ); } } public async Task SendClient(string UserName, Packet data) { foreach( mUDPClient cur in clientConnections.Values ) { if (cur.UserName.ToLower() == UserName.ToLower()) { await cur.Send( data ); break; } } } public async Task SendServer(Packet data) { await ServerConnection.Send( data ); } } }