diff --git a/DTLib.Network/DTLib.Network.csproj b/DTLib.Network/DTLib.Network.csproj
index 25c9a9a..1948be1 100644
--- a/DTLib.Network/DTLib.Network.csproj
+++ b/DTLib.Network/DTLib.Network.csproj
@@ -15,7 +15,7 @@
embedded
10
- disable
+ enable
disable
diff --git a/DTLib.Network/FSP2/Client.cs b/DTLib.Network/FSP2/Client.cs
new file mode 100644
index 0000000..b2ac795
--- /dev/null
+++ b/DTLib.Network/FSP2/Client.cs
@@ -0,0 +1,18 @@
+using System.Net;
+
+namespace DTLib.Network.FSP2;
+
+public class Client : IDisposable
+{
+ private TCPSocketClient _tcp;
+
+ public Client(IPEndPoint serverEndpoint)
+ {
+ _tcp = new TCPSocketClient(serverEndpoint);
+ }
+
+ public void Dispose()
+ {
+ _tcp.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/DTLib.Network/FSP2/Request.cs b/DTLib.Network/FSP2/Request.cs
new file mode 100644
index 0000000..a77788d
--- /dev/null
+++ b/DTLib.Network/FSP2/Request.cs
@@ -0,0 +1,13 @@
+namespace DTLib.Network.FSP2;
+
+public enum RequestType
+{
+ Message,
+ DownloadFile,
+ UploadFile
+}
+
+public record Request(RequestType Type)
+{
+
+}
\ No newline at end of file
diff --git a/DTLib.Network/FSP2/Response.cs b/DTLib.Network/FSP2/Response.cs
new file mode 100644
index 0000000..48c20fd
--- /dev/null
+++ b/DTLib.Network/FSP2/Response.cs
@@ -0,0 +1,13 @@
+namespace DTLib.Network.FSP2;
+
+public enum ResponseStatus
+{
+ OK,
+ InvalidRequest,
+ AccessDenied
+}
+
+public record Response(ResponseStatus Status)
+{
+
+}
\ No newline at end of file
diff --git a/DTLib.Network/FSP2/Server.cs b/DTLib.Network/FSP2/Server.cs
new file mode 100644
index 0000000..666e4d6
--- /dev/null
+++ b/DTLib.Network/FSP2/Server.cs
@@ -0,0 +1,26 @@
+using System.Net;
+
+namespace DTLib.Network.FSP2;
+
+public class Server : IDisposable
+{
+
+ private TCPSocketServer _tcp;
+ private readonly Func _requestHandler;
+
+ public Server(IPEndPoint localEndpoint, Func requestHandler, Action exceptionHandler)
+ {
+ _requestHandler = requestHandler;
+ _tcp = new TCPSocketServer(localEndpoint, HandleFSP2Connection, exceptionHandler);
+ }
+
+ void HandleFSP2Connection(TCPSocketServer.ConnectionParams p)
+ {
+
+ }
+
+ public void Dispose()
+ {
+ _tcp.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/DTLib.Network/Functions.cs b/DTLib.Network/Functions.cs
new file mode 100644
index 0000000..7dab119
--- /dev/null
+++ b/DTLib.Network/Functions.cs
@@ -0,0 +1,19 @@
+global using System.Net.Sockets;
+global using System;
+global using System.Threading;
+global using System.Collections.Generic;
+global using System.Linq;
+global using System.Text;
+global using DTLib.Extensions;
+global using DTLib.Filesystem;
+global using static DTLib.Logging.InternalLog;
+using System.Diagnostics;
+using System.Net.Http;
+
+namespace DTLib.Network;
+
+public static class Functions
+{
+ /// gets public ip of this machine from ifconfig.me
+ public static string GetPublicIP() => new HttpClient().GetStringAsync("https://ifconfig.me/ip").GetAwaiter().GetResult();
+}
diff --git a/DTLib.Network/OldNetwork.cs b/DTLib.Network/OldNetwork.cs
deleted file mode 100644
index 06aa6b8..0000000
--- a/DTLib.Network/OldNetwork.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-global using System.Net.Sockets;
-global using System;
-global using System.Threading;
-global using System.Collections.Generic;
-global using System.Linq;
-global using System.Text;
-global using DTLib.Extensions;
-global using DTLib.Filesystem;
-global using static DTLib.Logging.InternalLog;
-using System.Diagnostics;
-using System.Net.Http;
-
-namespace DTLib.Network;
-
-//
-// пара почти никогда не используемых методов
-//
-public static class OldNetwork
-{
-
-
- // получает с сайта публичный ip
- public static string GetPublicIP() => new HttpClient().GetStringAsync("https://ifconfig.me/ip").GetAwaiter().GetResult();
-
- // пингует айпи с помощью встроенной в винду проги, возвращает задержку
- public static string PingIP(string address)
- {
- var proc = new Process();
- proc.StartInfo.FileName = "cmd.exe";
- proc.StartInfo.Arguments = "/c @echo off & chcp 65001 >nul & ping -n 5 " + address;
- proc.StartInfo.CreateNoWindow = true;
- proc.StartInfo.UseShellExecute = false;
- proc.StartInfo.RedirectStandardOutput = true;
- proc.Start();
- System.IO.StreamReader outStream = proc.StandardOutput;
- string rezult = outStream.ReadToEnd();
- rezult = rezult.Remove(0, rezult.LastIndexOf('=') + 2);
- return rezult.Remove(rezult.Length - 4);
- }
-
-}
diff --git a/DTLib.Network/TCPSocketClient.cs b/DTLib.Network/TCPSocketClient.cs
new file mode 100644
index 0000000..511ede9
--- /dev/null
+++ b/DTLib.Network/TCPSocketClient.cs
@@ -0,0 +1,45 @@
+using System.Net;
+
+namespace DTLib.Network;
+
+public class TCPSocketClient : IDisposable
+{
+ protected Socket? _mainSocket;
+ public readonly IPEndPoint ServerEndpoint;
+
+ public TCPSocketClient(IPEndPoint serverEndpoint)
+ {
+ ServerEndpoint = serverEndpoint;
+ }
+
+ public virtual void Connect()
+ {
+ _mainSocket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ _mainSocket.Connect(ServerEndpoint);
+ }
+
+ public virtual void Stop()
+ {
+ if(_mainSocket is null)
+ return;
+ _mainSocket.Shutdown(SocketShutdown.Both);
+ _mainSocket.Close();
+ _mainSocket = null;
+ }
+
+ public void Dispose() => Stop();
+
+ public void Send(byte[] buffer)
+ {
+ if (_mainSocket is null)
+ throw new NullReferenceException("TCP socket is null! You have to call Connect() befure calling Send()");
+ _mainSocket.Send(buffer);
+ }
+
+ public int Recieve(ref byte[] buffer)
+ {
+ if (_mainSocket is null)
+ throw new NullReferenceException("TCP socket is null! You have to call Connect() befure calling Recieve()");
+ _mainSocket.Receive(buffer);
+ }
+}
\ No newline at end of file
diff --git a/DTLib.Network/TCPSocketServer.cs b/DTLib.Network/TCPSocketServer.cs
new file mode 100644
index 0000000..b09852a
--- /dev/null
+++ b/DTLib.Network/TCPSocketServer.cs
@@ -0,0 +1,101 @@
+using System.Net;
+
+namespace DTLib.Network;
+
+///
+/// Multi-threaded TCP
+///
+public class TCPSocketServer : IDisposable
+{
+ public readonly IPEndPoint LocalEndPoint;
+
+ public record ConnectionParams(Socket ConnectionSocket, Thread ConnectionThread);
+
+ protected Action? _connectionHandler;
+ protected Action _exceptionCallback;
+ protected Socket? _mainSocket;
+
+ /// address and port of the server in the local network
+ /// this delegate is called on every incoming socket connection
+ /// this delegate is called on every Exception throwed in threads created by the server
+ public TCPSocketServer(IPEndPoint localEndpoint,
+ Action? incomingConnectionHandler,
+ Action exceptionCallback)
+ {
+ LocalEndPoint = localEndpoint;
+ _connectionHandler = incomingConnectionHandler;
+ _exceptionCallback = exceptionCallback;
+ }
+
+ private volatile int acceptLoopRunning = 0;
+
+ ///
+ /// Starts server on a new thread
+ ///
+ /// the server is already started
+ public virtual void Listen()
+ {
+ if (Interlocked.CompareExchange(ref acceptLoopRunning, 1, 1) == 1)
+ throw new Exception("Server is already started. Stop it to ");
+
+ _mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ _mainSocket.Bind(LocalEndPoint);
+ _mainSocket.Listen(64);
+ Thread loopThread = new Thread(AcceptLoop);
+ loopThread.Start();
+ }
+
+ /// server runs this loop in special thread
+ private void AcceptLoop()
+ {
+ try
+ {
+ // atomic (thread-safe) comparison acceptLoopRunning==1
+ while (Interlocked.CompareExchange(ref acceptLoopRunning, 1, 1) == 1)
+ {
+ Socket incomingConnection = _mainSocket!.Accept();
+ Thread connectionThread = new Thread(HandleConnection);
+ connectionThread.Start(new ConnectionParams(incomingConnection, connectionThread));
+ }
+ }
+ catch (Exception e)
+ {
+ _exceptionCallback(e);
+ Stop();
+ }
+ }
+
+
+ private void HandleConnection(object? _p)
+ {
+ var p = (ConnectionParams)_p!;
+ try
+ {
+ _connectionHandler?.Invoke(p);
+ }
+ catch (Exception e)
+ {
+ _exceptionCallback(e);
+ }
+ finally
+ {
+ p.ConnectionSocket.Shutdown(SocketShutdown.Both);
+ p.ConnectionSocket.Close();
+ }
+ }
+
+ public virtual void Stop()
+ {
+ // atomic (thread-safe) comparison acceptLoopRunning==0 and assignement acceptLoopRunning=0
+ if (Interlocked.CompareExchange(ref acceptLoopRunning, 0, 1) == 0)
+ throw new Exception("Server isn't running");
+
+ if(_mainSocket is null)
+ return;
+
+ _mainSocket.Shutdown(SocketShutdown.Both);
+ _mainSocket.Close();
+ }
+
+ public void Dispose() => Stop();
+}
\ No newline at end of file