402 lines
12 KiB
C#

using DX86.Modules;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace DX86
{
/// <summary>
/// Represents the type of server, either TCP or UDP.
/// </summary>
public enum ServerType
{
TCP,
UDP
}
/// <summary>
/// The main class for the DX86 server. This class manages the TCP and UDP server functionality, including accepting client connections, receiving messages, and handling client disconnections.
/// </summary>
public class DX86
{
private MessageSender ms;
private TcpListener tcpServer;
private UdpClient udpServer;
private List<TcpClient> tcpClients = new List<TcpClient>();
private readonly object clientListLock = new object();
private ServerType serverType;
public event Action<TcpClient> ClientConnected;
public event Action<TcpClient, string> MessageReceived;
public event Action<TcpClient> ClientDisconnected;
public event Action<UdpClient> UdpClientConnected;
public event Action<IPEndPoint, string> UdpMessageReceived;
public event Action<UdpClient> UdpClientDisconnected;
public DX86(MessageSender ms, ServerType type)
{
this.ms = ms;
this.serverType = type;
ms.Log("[DX86] DX86 initialized for " + type.ToString() + " server.");
}
public void StartServer(string ipAddress, int port)
{
if (serverType == ServerType.TCP)
{
tcpServer = new TcpListener(IPAddress.Parse(ipAddress), port);
tcpServer.Start();
ms.Log($"[DX86] TCP server started on {ipAddress}:{port}");
AcceptTcpClientsAsync();
}
else if (serverType == ServerType.UDP)
{
udpServer = new UdpClient(port);
ms.Log($"[DX86] UDP server started on {ipAddress}:{port}");
ReceiveUdpMessagesAsync();
}
}
private async Task ReceiveUdpMessagesAsync()
{
while (true)
{
try
{
var receivedResult = await udpServer.ReceiveAsync();
string message = Encoding.UTF8.GetString(receivedResult.Buffer);
//ms.Log($"[DX86] Received UDP message from {receivedResult.RemoteEndPoint}: {message}");
// Trigger the event
UdpMessageReceived?.Invoke(receivedResult.RemoteEndPoint, message);
}
catch (Exception ex)
{
ms.Error("[DX86] Error receiving UDP message: " + ex.Message);
// Optionally handle specific exceptions or rethrow
}
}
}
public void StopServer()
{
if (serverType == ServerType.TCP)
{
tcpServer.Stop();
lock (clientListLock)
{
foreach (var client in tcpClients)
{
client.Close();
}
tcpClients.Clear();
}
ms.Log("[DX86] TCP server stopped.");
}
else if (serverType == ServerType.UDP)
{
udpServer.Close();
ms.Log("[DX86] UDP server stopped.");
}
}
private async Task AcceptTcpClientsAsync()
{
while (true)
{
var client = await tcpServer.AcceptTcpClientAsync();
lock (clientListLock)
{
tcpClients.Add(client);
}
ClientConnected?.Invoke(client);
ms.Log("[DX86] Client connected.");
HandleTcpClientAsync(client);
}
}
private async Task HandleTcpClientAsync(TcpClient client)
{
var stream = client.GetStream();
byte[] buffer = new byte[1024];
int numBytesRead;
try
{
while ((numBytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string receivedMessage = Encoding.UTF8.GetString(buffer, 0, numBytesRead);
// remove last \n and \r from receivedMessage (if its on last position)
if (receivedMessage.EndsWith("\n"))
{
receivedMessage = receivedMessage.Substring(0, receivedMessage.Length - 1);
}
if (receivedMessage.EndsWith("\r"))
{
receivedMessage = receivedMessage.Substring(0, receivedMessage.Length - 1);
}
if (receivedMessage.EndsWith("\n"))
{
receivedMessage = receivedMessage.Substring(0, receivedMessage.Length - 1);
}
if (receivedMessage.EndsWith("\r"))
{
receivedMessage = receivedMessage.Substring(0, receivedMessage.Length - 1);
}
MessageReceived?.Invoke(client, receivedMessage);
//ms.Log($"[DX86] Message from client: {receivedMessage}");
BroadcastMessage(receivedMessage, client);
}
}
catch (Exception ex)
{
ms.Error("[DX86] Error handling client: " + ex.Message);
ms.Debug("[DX86] Stack Trace: " + ex.StackTrace);
}
finally
{
lock (clientListLock)
{
tcpClients.Remove(client);
}
client.Close();
ClientDisconnected?.Invoke(client);
ms.Log("[DX86] Client disconnected.");
}
}
public async Task SendMessageAsync(TcpClient client, string message)
{
try
{
var stream = client.GetStream();
var buffer = Encoding.UTF8.GetBytes(message);
stream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
ms.Error($"[DX86] DX86 Failed to send message to {client.Client.RemoteEndPoint}: {ex.Message}");
}
}
public async Task SendUdpMessageAsync(string message, string ipAddress, int port)
{
try
{
var udpClient = new UdpClient();
var buffer = Encoding.UTF8.GetBytes(message);
await udpClient.SendAsync(buffer, buffer.Length, new IPEndPoint(IPAddress.Parse(ipAddress), port));
udpClient.Close();
ms.Log($"[DX86] Sent UDP message to {ipAddress}:{port}");
}
catch (Exception ex)
{
ms.Error("[DX86] Error sending UDP message: " + ex.Message);
}
}
public void BroadcastMessage(string message, TcpClient sender)
{
lock (clientListLock)
{
foreach (var client in tcpClients)
{
if (client != sender && client.Connected)
{
try
{
var buffer = Encoding.UTF8.GetBytes(message);
client.GetStream().WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
ms.Error($"[DX86] Failed to send message to {client.Client.RemoteEndPoint}: {ex.Message}");
}
}
}
}
}
public static string GetVersion()
{
return "0.243.554.3 - BETA";
}
}
}
/*
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace DX86
{
public class DX86
{
private MessageSender ms;
private TcpListener server;
private List<TcpClient> clients = new List<TcpClient>();
public event Action<TcpClient> ClientConnected;
public event Action<TcpClient, string> MessageReceived;
public event Action<TcpClient> ClientDisconnected;
public DX86(MessageSender ms)
{
this.ms = ms;
ms.Log("[DX86] DX86 initialized!");
}
public void StartServer(string ipAddress, int port)
{
server = new TcpListener(IPAddress.Parse(ipAddress), port);
server.Start();
ms.Log($"[DX86] DX86 started on {ipAddress}:{port}");
AcceptClientsAsync();
}
public void StopServer()
{
server.Stop(); // Stop the TcpListener.
foreach (var client in clients)
{
if (client.Connected)
{
client.Close(); // Disconnect each client.
}
}
clients.Clear(); // Clear the list of clients.
ms.Log("[DX86] DX86 stopped.");
}
private async Task AcceptClientsAsync()
{
while (true)
{
var client = await server.AcceptTcpClientAsync();
clients.Add(client);
ClientConnected?.Invoke(client);
ms.Log("[DX86] DX86 Client connected.");
HandleClientAsync(client);
}
}
private async Task HandleClientAsync(TcpClient client)
{
var stream = client.GetStream();
var buffer = new byte[1024];
try
{
while (true)
{
var byteCount = await stream.ReadAsync(buffer, 0, buffer.Length);
if (byteCount == 0) break;
var message = Encoding.UTF8.GetString(buffer, 0, byteCount);
MessageReceived?.Invoke(client, message);
BroadcastMessage(message, client);
}
}
catch (Exception ex)
{
ms.Error("[DX86] DX86: " + ex.Message);
}
finally
{
clients.Remove(client);
client.Close();
ClientDisconnected?.Invoke(client);
ms.Log("[DX86] DX86 Client disconnected.");
}
}
public async Task SendMessageAsync(TcpClient client, string message)
{
try
{
var stream = client.GetStream();
var buffer = Encoding.UTF8.GetBytes(message);
stream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
ms.Error($"[DX86] DX86 Failed to send message to {client.Client.RemoteEndPoint}: {ex.Message}");
}
}
private void BroadcastMessage(string message, TcpClient sender)
{
foreach (var client in clients)
{
if (client != sender)
{
try
{
var stream = client.GetStream();
var buffer = Encoding.UTF8.GetBytes(message);
stream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
ms.Error($"[DX86] DX86 Failed to send message to {client.Client.RemoteEndPoint}: {ex.Message}");
}
}
}
}
}
}
*/
/*
namespace DX86;
public class DX86
{
private MessageSender ms;
private List<Client?> clientList;
public DX86(MessageSender ms)
{
ms.Log("[DX86] Initializing DX86...");
this.ms = ms;
this.clientList = new List<Client?>();
ms.Log("[DX86] DX86 initialized!");
}
public void CreateClient()
{
clientList.Add(new Client());
}
public int GetClientCount()
{
return clientList.Count;
}
public Client? GetClient(int id)
{
try
{
return clientList[id];
}
catch (Exception e)
{
ms.Error("[DX86] Error getting client: " + e.Message);
return null;
}
}
}
*/