diff --git a/EonaCat.Network/System/Sockets/Client.cs b/EonaCat.Network/System/Sockets/Client.cs
deleted file mode 100644
index b45b8b3..0000000
--- a/EonaCat.Network/System/Sockets/Client.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Sockets;
-
-namespace EonaCat.Sockets
-{
- public delegate void SendBytesTo(byte[] data, EndPoint point);
-
- public class Client : IDisposable
- {
- ///
- /// Unique client id.
- ///
- public string Guid { get; set; }
-
- ///
- /// Client socket.
- ///
- public Socket Socket { get; set; }
-
- ///
- /// Receive buffer.
- ///
- public byte[] Buffer { get; set; }
-
- ///
- /// Buffer size
- ///
- public static int BufferSize { get; set; } = 1024 * 1024; // 1024KB
-
- ///
- /// Socket connection state.
- ///
- public bool IsConnected => !((Socket.Poll(1000, SelectMode.SelectRead) && (Socket.Available == 0)) || !Socket.Connected);
- ///
- /// Client ip.
- ///
- public IPAddress RemoteIP => (Socket.RemoteEndPoint as IPEndPoint)?.Address;
- ///
- /// Client port.
- ///
- public int RemotePort => (Socket.RemoteEndPoint as IPEndPoint).Port;
-
- public event SendBytesTo SendData;
-
- public Client()
- {
- Buffer = new byte[BufferSize];
- }
-
- public void Dispose()
- {
- Socket.Close();
- }
-
- ///
- /// Send data to the client.
- ///
- /// Data for sending
- public void Send(byte[] data)
- {
- switch (Socket.SocketType)
- {
- case SocketType.Stream:
- Socket.BeginSend(data, 0, data.Length, 0, EndSend, null);
- break;
- case SocketType.Dgram when SendData != null:
- SendData?.Invoke(data, Socket.RemoteEndPoint);
- break;
- case SocketType.Dgram:
- Socket.BeginSendTo(data, 0, data.Length, 0, Socket.RemoteEndPoint, EndSendTo, null);
- break;
- }
- }
-
- private void EndSend(IAsyncResult ar)
- {
- Socket.EndSend(ar);
- }
-
- private void EndSendTo(IAsyncResult ar)
- {
- Socket.EndSendTo(ar);
- }
- }
-}
\ No newline at end of file
diff --git a/EonaCat.Network/System/Sockets/NetworkType.cs b/EonaCat.Network/System/Sockets/NetworkType.cs
deleted file mode 100644
index 4da774e..0000000
--- a/EonaCat.Network/System/Sockets/NetworkType.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-
-namespace EonaCat.Sockets
-{
- [Flags]
- public enum NetworkType
- {
- Tcp,
- Udp
- }
-}
diff --git a/EonaCat.Network/System/Sockets/RemoteInfo.cs b/EonaCat.Network/System/Sockets/RemoteInfo.cs
new file mode 100644
index 0000000..21f3405
--- /dev/null
+++ b/EonaCat.Network/System/Sockets/RemoteInfo.cs
@@ -0,0 +1,17 @@
+using System.Net;
+using System.Net.Sockets;
+
+namespace EonaCat.Dns.Core.Sockets
+{
+ public class RemoteInfo
+ {
+ public bool IsTcp { get; set; }
+ public bool HasEndpoint => EndPoint != null;
+ public EndPoint EndPoint { get; set; }
+ public byte[] Data { get; set; }
+ public IPAddress Address => HasEndpoint ? ((IPEndPoint)EndPoint).Address : null;
+ public int Port => HasEndpoint ? ((IPEndPoint)EndPoint).Port : 0;
+ public Socket Socket { get; set; }
+ public bool IsIpv6 { get; set; }
+ }
+}
diff --git a/EonaCat.Network/System/Sockets/SocketClient.cs b/EonaCat.Network/System/Sockets/SocketClient.cs
deleted file mode 100644
index 8e05950..0000000
--- a/EonaCat.Network/System/Sockets/SocketClient.cs
+++ /dev/null
@@ -1,189 +0,0 @@
-using System;
-using System.IO;
-using System.Net;
-using System.Net.Sockets;
-
-namespace EonaCat.Sockets
-{
- public class SocketClient : Client, IDisposable
- {
- ///
- /// Client type
- ///
- public NetworkType ClientType { get; set; }
-
- ///
- /// Timer interval
- ///
- public int LoopInterval { get; set; } = 100;
-
- ///
- /// Only for UDP. Sending 1 byte data for check connected state.
- ///
- public int UDPDataInterval { get; set; } = 5000;
-
- ///
- /// Called when client connected
- ///
- public event EventHandler OnConnected;
- ///
- /// Called when client disconnected
- ///
- public event EventHandler OnDisconnected;
-
- ///
- /// Called when received data from server
- ///
- public event EventHandler OnReceived;
-
- ///
- /// Called when client has an error
- ///
- public event EventHandler OnError;
-
- private System.Timers.Timer UDPTimer { get; set; }
- private System.Timers.Timer DisconnectTimer { get; set; }
-
- ///
- /// SocketClient class constructor.
- ///
- /// Client type
- public SocketClient(NetworkType type)
- {
- ClientType = type;
- UDPTimer = new System.Timers.Timer(UDPDataInterval);
- UDPTimer.Elapsed += (s, e) =>
- {
- if (IsConnected)
- Socket.Send(new byte[] { 0 });
- };
- DisconnectTimer = new System.Timers.Timer(LoopInterval);
- DisconnectTimer.Elapsed += (s, e) =>
- {
- if (!IsConnected)
- {
- Disconnect();
- }
- };
- }
-
- public new void Dispose()
- {
- Disconnect();
- }
-
- ///
- /// Connect to remote host
- ///
- /// Remote ip address
- /// Remote port
- public void Connect(IPAddress address, int port) => Connect(new IPEndPoint(address, port));
-
- ///
- /// Connect to remote host
- ///
- /// Remote end point
- public void Connect(IPEndPoint point)
- {
- try
- {
- if (ClientType == NetworkType.Tcp)
- {
- Socket = new Socket(point.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
- Socket.BeginConnect(point, ConnectCallback, null);
- }
- else if (ClientType == NetworkType.Udp)
- {
- Socket = new Socket(point.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
- Socket.Connect(point);
- Socket.Send(new byte[] { 0 });
- OnConnected?.Invoke(this, EventArgs.Empty);
- UDPTimer.Start();
- DisconnectTimer.Start();
- Socket.BeginReceive(Buffer, 0, BufferSize, 0, ReadCallbackUDP, null);
- }
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
-
- ///
- /// Disconnect from remote host
- ///
- public void Disconnect()
- {
- try
- {
- if (Socket == null)
- return;
- UDPTimer.Stop();
- DisconnectTimer.Stop();
- Socket.Close();
- OnDisconnected?.Invoke(this, EventArgs.Empty);
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
-
- private void ConnectCallback(IAsyncResult ar)
- {
- try
- {
- Socket.EndConnect(ar);
- OnConnected?.Invoke(this, EventArgs.Empty);
- DisconnectTimer.Start();
- Socket.BeginReceive(Buffer, 0, BufferSize, 0, ReadCallback, null);
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
-
- private void ReadCallback(IAsyncResult ar)
- {
- try
- {
- if (!Socket.Connected)
- return;
- int readBytes = Socket.EndReceive(ar);
- if (readBytes > 0)
- {
- byte[] data = new byte[readBytes];
- Array.Copy(Buffer, data, readBytes);
- OnReceived?.Invoke(this, new SocketClientEventArgs() { Data = data });
- }
- Socket.BeginReceive(Buffer, 0, BufferSize, 0, ReadCallback, null);
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
-
- private void ReadCallbackUDP(IAsyncResult ar)
- {
- try
- {
- if (!Socket.Connected)
- return;
- int readBytes = Socket.EndReceive(ar);
- if (readBytes > 0)
- {
- byte[] data = new byte[readBytes];
- Array.Copy(Buffer, data, readBytes);
- OnReceived?.Invoke(this, new SocketClientEventArgs() { Data = data });
- }
- Socket.BeginReceive(Buffer, 0, BufferSize, 0, ReadCallbackUDP, null);
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
- }
-}
diff --git a/EonaCat.Network/System/Sockets/SocketClientEventArgs.cs b/EonaCat.Network/System/Sockets/SocketClientEventArgs.cs
deleted file mode 100644
index f7729fb..0000000
--- a/EonaCat.Network/System/Sockets/SocketClientEventArgs.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System;
-
-namespace EonaCat.Sockets
-{
- public class SocketClientEventArgs : EventArgs
- {
- public byte[] Data { get; set; }
- }
-}
diff --git a/EonaCat.Network/System/Sockets/SocketServer.cs b/EonaCat.Network/System/Sockets/SocketServer.cs
deleted file mode 100644
index 6077249..0000000
--- a/EonaCat.Network/System/Sockets/SocketServer.cs
+++ /dev/null
@@ -1,542 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Sockets;
-using System.Runtime.InteropServices;
-using System.Threading;
-using System.Threading.Tasks;
-using EonaCat.Helpers.Controls;
-
-namespace EonaCat.Sockets
-{
- public class SocketServer : IDisposable
- {
- ///
- /// Unique server id.
- ///
- public string Guid { get; set; }
-
- ///
- /// Listening ip address.
- ///
- public IPAddress IPAddress { get; set; }
-
- ///
- /// Listening port.
- ///
- public int Port { get; set; }
-
- ///
- /// List of connected clients.
- ///
- public List ConnectedClients { get; set; } = new List();
-
- ///
- /// Interval to check for disconnected clients
- ///
- public int DisconnectionCheckInterval { get; set; } = 50;
-
- ///
- /// Determines if we need to reuse the socket address
- /// (default: false)
- ///
- public bool ReuseAddress { get; set; }
-
- ///
- /// Determines if the socket is in blocking mode
- ///
- public bool IsSocketBlockingDisabled { get; set; }
-
-
- ///
- /// Socket backlog. The maximum length of the pending connections queue.
- ///
- public int Backlog { get; set; } = 0;
- ///
- /// Server type.
- ///
- public NetworkType ServerType { get; set; }
-
- ///
- /// Only for UDP.
- /// (default: true)
- ///
- public bool UseClientManager { get; set; } = true;
-
- ///
- /// Only for UDP.
- /// Accept 1 byte data for connected state check.
- ///
- private int _UDPDataInterval { get => (int)(UDPDataInterval * 1.5); }
- public int UDPDataInterval { get; set; } = 5000;
-
- ///
- /// Called when new client connected
- ///
- public event EventHandler OnConnected;
- ///
- /// Called when client disconnected
- ///
- public event EventHandler OnDisconnected;
- ///
- /// Called when received data from client
- ///
- public event EventHandler OnReceived;
- ///
- /// Called when server catch error
- ///
- public event EventHandler OnError;
- ///
- /// Called when executing Start() function
- ///
- public event EventHandler OnStart;
- ///
- /// Called when executing Stop() function
- ///
- public event EventHandler OnStop;
-
- private Socket Server { get; set; }
- private EonaCatTimer DisconnectTimerUdp { get; set; }
- private EonaCatTimer DisconnectTimerTcp { get; set; }
- private Dictionary LastDataReceivedTime { get; set; }
- private double TimeNow { get => (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; }
-
- public SocketServer(NetworkType type, string address, int port)
- {
- if (!IPAddress.TryParse(address, out var ipAddress))
- {
- throw new Exception("Invalid IP address specified");
- }
-
- SetupSocketServer(type, ipAddress, port);
- }
-
- ///
- /// Constructor
- ///
- /// Server type (TCP, UDP)
- /// Server listening ip
- /// Server listening port
- public SocketServer(NetworkType type, IPAddress address, int port)
- {
- SetupSocketServer(type, address, port);
- }
-
- private void SetupSocketServer(NetworkType type, IPAddress address, int port)
- {
- Guid = System.Guid.NewGuid().ToString();
- ServerType = type;
- IPAddress = address;
- Port = port;
- }
-
- private readonly List _removedEndpoints = new List();
-
- private void UdpCheckCallback()
- {
- _removedEndpoints.Clear();
- var now = TimeNow;
- foreach (var kp in LastDataReceivedTime.Where(kp => now - kp.Value > _UDPDataInterval / 1000))
- {
- lock (ConnectedClients)
- {
- var client = ConnectedClients.FirstOrDefault(x => x.Guid == kp.Key.ToString());
- if (client == null)
- {
- continue;
- }
- OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
- ConnectedClients.Remove(client);
- _removedEndpoints.Add(kp.Key);
- }
- }
-
- lock (LastDataReceivedTime)
- {
- foreach (var r in _removedEndpoints)
- {
- LastDataReceivedTime.Remove(r);
- }
- }
- }
-
- private void TcpCheckCallback()
- {
- lock (ConnectedClients)
- {
- ConnectedClients.RemoveAll(x =>
- {
- if (x.IsConnected)
- {
- return false;
- }
-
- OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = x });
- return true;
- });
- }
- }
-
- public void Dispose()
- {
- Stop();
- }
-
- ///
- /// Start server
- ///
- public async Task StartAsync()
- {
- try
- {
- switch (ServerType)
- {
- case NetworkType.Tcp:
- Server = new Socket(IPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
- ConfigureSocketOptions();
-
- // Check if we need to override the socket with a custom socket
- if (CustomTcpSocket != null)
- {
- Server = CustomTcpSocket;
- }
-
- DisconnectTimerTcp = new EonaCatTimer(TimeSpan.FromMilliseconds(DisconnectionCheckInterval), TcpCheckCallback);
- DisconnectTimerTcp.Start();
- break;
- case NetworkType.Udp:
- {
- if (UseClientManager)
- {
- LastDataReceivedTime = new Dictionary();
- DisconnectTimerUdp = new EonaCatTimer(TimeSpan.FromMilliseconds(DisconnectionCheckInterval), UdpCheckCallback);
- DisconnectTimerUdp.Start();
- }
- Server = new Socket(IPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
- ConfigureSocketOptions();
-
- // Check if we need to override the socket with a custom socket
- if (CustomUdpSocket != null)
- {
- Server = CustomUdpSocket;
- }
- break;
- }
- }
- Server.ReceiveBufferSize = Client.BufferSize;
- Server.SendBufferSize = Client.BufferSize;
- Server.Bind(new IPEndPoint(IPAddress, Port));
- if (ServerType == NetworkType.Tcp)
- {
- Server.Listen(Backlog);
- }
- await Task.Run(ListenLoop);
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
-
- ///
- /// Setup this udp socket to override the default one
- /// (default: null => using default)
- ///
- public Socket CustomUdpSocket { get; set; }
-
- ///
- /// Setup this tcp socket to override the default one
- /// (default: null => using default)
- ///
- public Socket CustomTcpSocket { get; set; }
-
- private static void SetConnectionReset(Socket socket)
- {
- if (socket.ProtocolType != ProtocolType.Udp || !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- return;
- }
-
- // Disable ICMP packet shutdown (forcibly closed)
- const uint IOC_IN = 0x80000000;
- const uint IOC_VENDOR = 0x18000000;
- uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
- socket.IOControl((int)SIO_UDP_CONNRESET, new[] { Convert.ToByte(false) }, null);
- }
-
- private void ConfigureSocketOptions()
- {
- // Disable ICMP packet shutdown
- SetConnectionReset(Server);
-
- if (ReuseAddress)
- {
- Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- }
-
- Server.Blocking = IsSocketBlockingDisabled;
- }
-
- ///
- /// Stop server
- ///
- public void Stop()
- {
- try
- {
- DisconnectTimerUdp?.Stop();
- DisconnectTimerTcp?.Stop();
- foreach (var client in ConnectedClients)
- {
- OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
- client.Socket.Close();
- }
- ConnectedClients.Clear();
- OnStop?.Invoke(this, EventArgs.Empty);
- Server.Close();
- }
- catch (SocketException socketException)
- {
- OnError?.Invoke(this, new ErrorEventArgs(socketException));
- }
- }
-
- private void ListenLoop()
- {
- try
- {
- OnStart?.Invoke(this, CustomTcpSocket != null || CustomUdpSocket != null ? "Custom socket was used" : string.Empty);
-
- switch (ServerType)
- {
- case NetworkType.Tcp:
- BeginTcpAccept();
- break;
-
- case NetworkType.Udp:
- BeginUdpReceive();
- break;
-
- default:
- throw new NotSupportedException("Protocol type not supported");
- }
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
-
- private void BeginTcpAccept()
- {
- Server.BeginAccept(AcceptCallback, Server);
- }
-
- private void BeginUdpReceive()
- {
- var loopbackAddress = Server.AddressFamily == AddressFamily.InterNetworkV6
- ? IPAddress.IPv6Loopback
- : IPAddress.Loopback;
-
- var buffer = new byte[Client.BufferSize];
- EndPoint remoteIp = new IPEndPoint(loopbackAddress, 0);
- Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, UseClientManager ? AcceptClientsCallbackUdp : ReadClientCallbackUdp, new object[] { buffer, remoteIp, Server });
- }
-
- private void ReadCallback(IAsyncResult ar)
- {
- try
- {
- var client = (Client)ar.AsyncState;
- var bytesRead = client.Socket.EndReceive(ar);
- if (bytesRead > 0)
- {
- var data = new byte[bytesRead];
- Array.Copy(client.Buffer, 0, data, 0, bytesRead);
- OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Client = client, Data = data });
-
- // read any remaining data
- while (client.Socket.Available > 0)
- {
- bytesRead = client.Socket.Receive(client.Buffer, 0, Client.BufferSize, SocketFlags.None);
- data = new byte[bytesRead];
- Array.Copy(client.Buffer, 0, data, 0, bytesRead);
- OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Client = client, Data = data });
- }
-
- client.Socket.BeginReceive(client.Buffer, 0, Client.BufferSize, 0, ReadCallback, client); // recursive call
- }
- else
- {
- OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
- lock (ConnectedClients)
- {
- ConnectedClients.Remove(client);
- }
- }
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- catch (ObjectDisposedException) { }
- }
-
- private void AcceptCallback(IAsyncResult ar)
- {
- try
- {
- var listener = (Socket)ar.AsyncState;
- var handler = listener.EndAccept(ar);
- var client = new Client()
- {
- Guid = System.Guid.NewGuid().ToString(),
- Socket = handler
- };
- lock (ConnectedClients)
- {
- ConnectedClients.Add(client);
- }
-
- OnConnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
- client.Socket.BeginReceive(client.Buffer, 0, Client.BufferSize, 0, ReadCallback, client); // recursive call
-
- Thread.Sleep(DisconnectionCheckInterval);
-
- if (listener.IsBound) // check if the listener is still bound
- {
- listener.BeginAccept(AcceptCallback, Server); // recursive call
- }
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- catch (ObjectDisposedException)
- {
- }
- }
-
- private void AcceptClientsCallbackUdp(IAsyncResult ar)
- {
- try
- {
- var objects = (object[])ar.AsyncState;
- var buffer = objects[0] as byte[];
- var remoteIp = objects[1] as EndPoint;
- var listener = objects[2] as Socket;
- var bytesRead = listener.EndReceiveFrom(ar, ref remoteIp);
-
- Client client;
- lock (ConnectedClients)
- {
- client = ConnectedClients.FirstOrDefault(x => x.Guid == remoteIp.ToString());
- if (client == null)
- {
- client = new Client()
- {
- Guid = remoteIp.ToString(),
- Socket = new Socket(remoteIp.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
- };
- client.SendData += SendData;
- client.Socket.Connect(remoteIp);
- if (client.IsConnected)
- {
- ConnectedClients.Add(client);
- OnConnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
- }
- }
- }
-
- if (bytesRead > 0)
- {
- var data = new byte[bytesRead];
- Array.Copy(buffer, 0, data, 0, bytesRead);
- OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Client = client, Data = data, });
- }
- else
- {
- lock (LastDataReceivedTime)
- {
- if (LastDataReceivedTime.ContainsKey(remoteIp))
- {
- LastDataReceivedTime[remoteIp] = TimeNow;
- }
- else
- {
- LastDataReceivedTime.Add(remoteIp, TimeNow);
- }
- }
- }
-
- Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, AcceptClientsCallbackUdp, new object[] { buffer, remoteIp, listener });
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- catch (ObjectDisposedException) { }
- }
-
- private void ReadClientCallbackUdp(IAsyncResult ar)
- {
- try
- {
- var objects = (object[])ar.AsyncState;
- var buffer = objects[0] as byte[];
- var remoteIp = objects[1] as EndPoint;
- var listener = objects[2] as Socket;
- var bytesRead = listener.EndReceiveFrom(ar, ref remoteIp);
- while (bytesRead > 0)
- {
- var data = new byte[bytesRead];
- Array.Copy(buffer, 0, data, 0, bytesRead);
- OnReceived?.Invoke(this, new SocketServerDataEventArgs()
- {
- Data = data,
- Client = new Client()
- {
- Guid = remoteIp.ToString(),
- Socket = new Socket(remoteIp.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
- }
- });
-
- // read any remaining data
- bytesRead = listener.ReceiveFrom(buffer, 0, Client.BufferSize, SocketFlags.None, ref remoteIp);
- }
- listener.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, ReadClientCallbackUdp, new object[] { buffer, remoteIp, listener });
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- catch (ObjectDisposedException) { }
- }
-
- public void SendData(byte[] data, EndPoint point)
- {
- try
- {
- Server.BeginSendTo(data, 0, data.Length, 0, point, EndSendTo, null);
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
-
- private void EndSendTo(IAsyncResult ar)
- {
- try
- {
- Server.EndSendTo(ar);
- }
- catch (SocketException se)
- {
- OnError?.Invoke(this, new ErrorEventArgs(se));
- }
- }
- }
-}
\ No newline at end of file
diff --git a/EonaCat.Network/System/Sockets/SocketServerEventArgs.cs b/EonaCat.Network/System/Sockets/SocketServerEventArgs.cs
deleted file mode 100644
index ac64e80..0000000
--- a/EonaCat.Network/System/Sockets/SocketServerEventArgs.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-
-namespace EonaCat.Sockets
-{
- public class SocketServerDataEventArgs : EventArgs
- {
- ///
- /// Client.
- ///
- public Client Client { get; set; }
-
- ///
- /// Received data.
- ///
- public byte[] Data { get; set; }
- }
-
- public class SocketServerClientEventArgs : EventArgs
- {
- ///
- /// Client connection.
- ///
- public Client Client { get; set; }
- }
-}
diff --git a/EonaCat.Network/System/Sockets/Tcp/SocketTcpClient.cs b/EonaCat.Network/System/Sockets/Tcp/SocketTcpClient.cs
new file mode 100644
index 0000000..6aa4e09
--- /dev/null
+++ b/EonaCat.Network/System/Sockets/Tcp/SocketTcpClient.cs
@@ -0,0 +1,90 @@
+using System;
+using System.ComponentModel;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading.Tasks;
+
+namespace EonaCat.Dns.Core.Sockets.Tcp
+{
+ public class SocketTcpClient
+ {
+ public event Action OnConnect;
+ public event Action OnReceive;
+ public event Action OnDisconnect;
+ public event Action OnSend;
+
+ private Socket socket;
+
+ public Task ConnectAsync(string ipAddress, int port)
+ {
+ if (!IPAddress.TryParse(ipAddress, out IPAddress ip))
+ {
+ throw new Exception("Invalid ipAddress given");
+ }
+
+ return CreateSocketTcpClientAsync(ip, port);
+ }
+
+ private async Task CreateSocketTcpClientAsync(IPAddress ipAddress, int port)
+ {
+ IsIP6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
+ socket = new Socket(IsIP6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ try
+ {
+ await socket.ConnectAsync(ipAddress, port).ConfigureAwait(false);
+ OnConnect?.Invoke(new RemoteInfo { IsTcp = true, IsIpv6 = IsIP6 });
+ _ = StartReceivingAsync();
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine($"SocketException: {ex.Message}");
+ Disconnect();
+ }
+ }
+
+ public bool IsIP6 { get; private set; }
+
+ private Task StartReceivingAsync()
+ {
+ byte[] buffer = new byte[1024];
+ return Task.Factory.StartNew(async () =>
+ {
+ while (socket.Connected)
+ {
+ try
+ {
+ int received = await socket.ReceiveAsync(new ArraySegment(buffer), SocketFlags.None).ConfigureAwait(false);
+ if (received > 0)
+ {
+ byte[] data = new byte[received];
+ Array.Copy(buffer, data, received);
+ OnReceive?.Invoke(new RemoteInfo
+ { IsTcp = true, Data = data, EndPoint = socket.RemoteEndPoint, IsIpv6 = IsIP6 });
+ }
+ else
+ {
+ break;
+ }
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine($"SocketException: {ex.Message}");
+ break;
+ }
+ }
+ OnDisconnect?.Invoke(new RemoteInfo { IsTcp = true, EndPoint = socket.RemoteEndPoint, IsIpv6 = IsIP6 });
+ });
+ }
+
+ public async Task SendAsync(byte[] data)
+ {
+ await socket.SendAsync(new ArraySegment(data), SocketFlags.None).ConfigureAwait(false);
+ OnSend?.Invoke(new RemoteInfo { EndPoint = socket.RemoteEndPoint, Data = data, IsIpv6 = IsIP6 });
+ }
+
+ public void Disconnect()
+ {
+ socket.Close();
+ }
+ }
+}
diff --git a/EonaCat.Network/System/Sockets/Tcp/SocketTcpServer.cs b/EonaCat.Network/System/Sockets/Tcp/SocketTcpServer.cs
new file mode 100644
index 0000000..9616d1a
--- /dev/null
+++ b/EonaCat.Network/System/Sockets/Tcp/SocketTcpServer.cs
@@ -0,0 +1,81 @@
+using System.Net.Sockets;
+using System.Net;
+using System;
+using System.Threading.Tasks;
+
+namespace EonaCat.Dns.Core.Sockets.Tcp
+{
+ public class SocketTcpServer
+ {
+ public event Action OnConnect;
+ public event Action OnReceive;
+ public event Action OnSend;
+ public event Action OnDisconnect;
+
+ private TcpListener listener;
+
+ public SocketTcpServer(IPAddress ipAddress, int port)
+ {
+ listener = new TcpListener(ipAddress, port);
+ }
+
+ public SocketTcpServer(string ipAddress, int port)
+ {
+ IPAddress address = IPAddress.Parse(ipAddress);
+ listener = new TcpListener(address, port);
+ }
+
+ public async Task Start()
+ {
+ listener.Start();
+ while (true)
+ {
+ try
+ {
+ TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
+ Socket socket = client.Client;
+ OnConnect?.Invoke(new RemoteInfo { Socket = socket, IsTcp = true, IsIpv6 = socket.RemoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6, EndPoint = socket.RemoteEndPoint });
+ _ = StartReceiving(socket);
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine($"SocketException: {ex.Message}");
+ }
+ }
+ }
+
+ private async Task StartReceiving(Socket socket)
+ {
+ byte[] buffer = new byte[1024];
+ while (socket.Connected)
+ {
+ try
+ {
+ int received = await socket.ReceiveAsync(new ArraySegment(buffer), SocketFlags.None).ConfigureAwait(false);
+ if (received > 0)
+ {
+ byte[] data = new byte[received];
+ Array.Copy(buffer, data, received);
+ OnReceive?.Invoke(new RemoteInfo { Socket = socket, IsTcp = true, IsIpv6 = socket.RemoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6, EndPoint = socket.RemoteEndPoint, Data = data});
+ }
+ else
+ {
+ break;
+ }
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine($"SocketException: {ex.Message}");
+ break;
+ }
+ }
+ OnDisconnect?.Invoke(new RemoteInfo {Socket = socket, IsIpv6 = socket.RemoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6, IsTcp = true, EndPoint = socket.RemoteEndPoint });
+ }
+
+ public async Task SendTo(Socket socket, byte[] data)
+ {
+ await socket.SendAsync(new ArraySegment(data), SocketFlags.None).ConfigureAwait(false);
+ OnSend?.Invoke(new RemoteInfo { Socket = socket, IsTcp = true, EndPoint = socket.RemoteEndPoint, IsIpv6 = socket.RemoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6, Data = data });
+ }
+ }
+}
\ No newline at end of file
diff --git a/EonaCat.Network/System/Sockets/Udp/SocketUdpClient.cs b/EonaCat.Network/System/Sockets/Udp/SocketUdpClient.cs
new file mode 100644
index 0000000..3900ae1
--- /dev/null
+++ b/EonaCat.Network/System/Sockets/Udp/SocketUdpClient.cs
@@ -0,0 +1,91 @@
+using System.Net.Sockets;
+using System.Net;
+using System.Threading.Tasks;
+using System;
+
+namespace EonaCat.Dns.Core.Sockets.Udp
+{
+ public class SocketUdpClient
+ {
+ public event Action OnConnect;
+ public event Action OnReceive;
+ public event Action OnDisconnect;
+ public event Action OnSend;
+
+ private UdpClient udpClient;
+
+ public SocketUdpClient(IPAddress ipAddress, int port)
+ {
+ CreateUdpClient(ipAddress, port);
+ }
+
+ private void CreateUdpClient(IPAddress ipAddress, int port)
+ {
+ IsIP6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
+ udpClient = new UdpClient(ipAddress.AddressFamily);
+
+ if (IsIP6)
+ {
+ udpClient.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
+ }
+
+ udpClient.Client.Bind(new IPEndPoint(IsIP6 ? IPAddress.IPv6Any : IPAddress.Any, 0));
+
+ if (IsMulticastGroupEnabled)
+ {
+ udpClient.JoinMulticastGroup(ipAddress);
+ }
+
+ _ = StartReceivingAsync();
+ }
+
+ public bool IsMulticastGroupEnabled { get; set; }
+
+ public bool IsIP6 { get; private set; }
+
+ public SocketUdpClient(string ipAddress, int port)
+ {
+ if (!IPAddress.TryParse(ipAddress, out IPAddress ip))
+ {
+ throw new Exception("Invalid ipAddress given");
+ }
+
+ CreateUdpClient(ip, port);
+ }
+
+ private Task StartReceivingAsync()
+ {
+ return Task.Factory.StartNew(async () =>
+ {
+ while (true)
+ {
+ try
+ {
+ UdpReceiveResult result = await udpClient.ReceiveAsync();
+ OnReceive?.Invoke(result.Buffer);
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine($"SocketException: {ex.Message}");
+ break;
+ }
+ }
+ OnDisconnect?.Invoke(udpClient.Client.LocalEndPoint);
+ });
+ }
+
+ public async Task SendTo(EndPoint endPoint, byte[] data)
+ {
+ if (endPoint is IPEndPoint ipEndPoint)
+ {
+ await udpClient.SendAsync(data, ipEndPoint).AsTask().ConfigureAwait(false);
+ OnSend?.Invoke(endPoint, data);
+ }
+ }
+
+ public void Disconnect()
+ {
+ udpClient.Close();
+ }
+ }
+}
diff --git a/EonaCat.Network/System/Sockets/Udp/SocketUdpServer.cs b/EonaCat.Network/System/Sockets/Udp/SocketUdpServer.cs
new file mode 100644
index 0000000..7c5aeb0
--- /dev/null
+++ b/EonaCat.Network/System/Sockets/Udp/SocketUdpServer.cs
@@ -0,0 +1,113 @@
+using System.Net.Sockets;
+using System.Net;
+using System.Text;
+using System;
+using System.Runtime.InteropServices;
+using System.Net.NetworkInformation;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.DataProtection;
+using static SQLite.SQLite3;
+using System.ComponentModel;
+
+namespace EonaCat.Dns.Core.Sockets.Udp
+{
+ public class SocketUdpServer
+ {
+ public event Action OnReceive;
+ public event Action OnSend;
+ public event Action OnDisconnect;
+
+
+ private UdpClient udpClient;
+
+ public bool IsIP6 { get; private set; }
+
+ public SocketUdpServer(IPAddress ipAddress, int port)
+ {
+ CreateUdpServer(ipAddress, port);
+ }
+
+ public SocketUdpServer(string ipAddress, int port)
+ {
+ if (!IPAddress.TryParse(ipAddress, out IPAddress ip))
+ {
+ throw new Exception("Invalid ipAddress given");
+ }
+
+ CreateUdpServer(ip, port);
+ }
+
+
+ private static void SetConnectionReset(Socket socket)
+ {
+ if (socket.ProtocolType != ProtocolType.Udp && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ return;
+ }
+
+ // Disable ICMP packet shutdown (forcibly closed)
+ const int SioUdpConnReset = -1744830452;
+
+ byte[] inValue = { 0, 0, 0, 0 };
+ socket.IOControl(SioUdpConnReset, inValue, null);
+ }
+
+ private void CreateUdpServer(IPAddress ipAddress, int port)
+ {
+ IsIP6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
+ udpClient = new UdpClient(ipAddress.AddressFamily);
+ SetConnectionReset(udpClient.Client);
+
+ if (IsIP6)
+ {
+ udpClient.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
+ }
+
+ udpClient.Client.Bind(new IPEndPoint(ipAddress, port));
+ }
+
+ public Task StartAsync()
+ {
+ return Task.Factory.StartNew(async () =>
+ {
+ while (true)
+ {
+ try
+ {
+ UdpReceiveResult result = await udpClient.ReceiveAsync().ConfigureAwait(false);
+ OnReceive?.Invoke(new RemoteInfo()
+ {
+ EndPoint = result.RemoteEndPoint,
+ IsIpv6 = result.RemoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6,
+ Data = result.Buffer
+ });
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine($"SocketException: {ex.Message}");
+ }
+ }
+ });
+ }
+
+ public async Task SendToAsync(EndPoint endPoint, byte[] data)
+ {
+ if (endPoint is IPEndPoint ipEndPoint)
+ {
+ await udpClient.SendAsync(data, ipEndPoint).AsTask().ConfigureAwait(false);
+ OnSend?.Invoke(new RemoteInfo() { EndPoint = endPoint, Data = data, IsIpv6 = endPoint.AddressFamily == AddressFamily.InterNetworkV6 });
+ }
+ }
+
+ public async Task SendToAllAsync(byte[] data)
+ {
+ // get all connected clients
+ IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
+ IPEndPoint[] endPoints = ipProperties.GetActiveUdpListeners();
+ foreach (IPEndPoint endPoint in endPoints)
+ {
+ await udpClient.SendAsync(data, data.Length, endPoint).ConfigureAwait(false);
+ }
+ }
+ }
+}