summaryrefslogtreecommitdiff
path: root/NetServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'NetServer.cs')
-rw-r--r--NetServer.cs170
1 files changed, 86 insertions, 84 deletions
diff --git a/NetServer.cs b/NetServer.cs
index cab6a00..a0910ba 100644
--- a/NetServer.cs
+++ b/NetServer.cs
@@ -1,110 +1,112 @@
-using System.Buffers.Binary;
-using System.Collections.Concurrent;
-using System.Net;
-using System.Net.NetworkInformation;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading.Channels;
+using LiteNetLib;
+using LiteNetLib.Utils;
namespace OnekoOnline.Net;
-static class Server
+class Server
{
public static bool ServerRunning = false;
- static readonly ConcurrentDictionary<int, ServerUser> users = [];
+ readonly Dictionary<int, ServerUser> users = [];
+ readonly EventBasedNetListener Listener;
+ readonly NetManager NetServer;
- public static async void Init(int port)
+ public Server(int Port, int MaxConnections, string ServerPassword = "")
{
- TcpListener listener = new(IPAddress.Any, port);
- listener.Start(10);
- ServerRunning = true;
-
- while (ServerRunning)
- {
- TcpClient tcpSocket = await listener.AcceptTcpClientAsync();
- UdpClient udpSocket = new((IPEndPoint)tcpSocket.Client.RemoteEndPoint!);
-
- ServerUser newUser = new(tcpSocket.GetHashCode(), tcpSocket, udpSocket);
-
- Console.WriteLine("Accepted a connection from: " + tcpSocket.Client.RemoteEndPoint);
-
- await Task.Factory.StartNew(() => SetupUser(newUser));
- }
- }
-
- static async Task SetupUser(ServerUser user)
- {
- await Task.WhenAny(ExchangeUserData(user), Task.Delay(7000));
-
- if (user.ExchangedData) {
- //Send current user data
- foreach (ServerUser otherUser in users.Values.Where(u => u.ExchangedData)) {
- //Send username and spritesheet
- await NetBase.SendReliableData(new Packet(PacketType.OnekoSpritesheet, otherUser.SpriteSheet!, otherUser.Id), user.Tcp.GetStream());
- await NetBase.SendReliableData(new Packet(PacketType.Username, Encoding.UTF8.GetBytes(otherUser.Username!), otherUser.Id), user.Tcp.GetStream());
- //Ask users to take your data
- await otherUser.ToSend.Writer.WriteAsync(new Packet(PacketType.Username, Encoding.UTF8.GetBytes(user.Username!), user.Id));
- await otherUser.ToSend.Writer.WriteAsync(new Packet(PacketType.OnekoSpritesheet, user.SpriteSheet!, user.Id));
- Console.WriteLine($"Sent {otherUser.Username}'s Data to {user.Username}");
+ Listener = new();
+ NetServer = new(Listener);
+ ServerRunning = NetServer.Start(Port);
+
+ if (!ServerRunning) return;
+
+ Listener.ConnectionRequestEvent += request => {
+ if (NetServer.ConnectedPeersCount < MaxConnections) request.AcceptIfKey(ServerPassword);
+ else request.Reject();
+ };
+
+ Listener.PeerConnectedEvent += peer => {
+ Console.WriteLine($"New connection from {peer.EndPoint}!");
+ users.Add(peer.Id, new ServerUser(peer.Id, peer));
+ };
+
+ Listener.PeerDisconnectedEvent += (peer, info) => {
+ Console.WriteLine($"{peer.EndPoint} Disconnected! Reason: {info.Reason}");
+ users.Remove(peer.Id);
+
+ NetDataWriter writer = new();
+ //Send all users a disconnect message
+ foreach (ServerUser user in users.Values) {
+ user.Peer.Send(new PacketInfo(PacketType.Disconnect, peer.Id).Serialize(), DeliveryMethod.ReliableUnordered);
}
+ };
+
+ Listener.NetworkReceiveEvent += (fromPeer, dataReader, channel, DeliveryMethod) => {
+ PacketInfo info = dataReader.GetPacketInfo();
+ ServerUser user = users[fromPeer.Id];
+
+ //Size limits for packet types
+ if (info.Type == PacketType.OnekoSpritesheet && dataReader.AvailableBytes > 30000) return;
+ else if (info.Type != PacketType.OnekoSpritesheet && dataReader.AvailableBytes > 500) return;
+
+ if (info.Type == PacketType.OnekoSpritesheet) user.SpriteSheet = dataReader.GetRemainingBytes();
+ else if (info.Type == PacketType.Username) user.Username = dataReader.GetString(64);
+
+ if (user.ExchangedData && !user.sentId) {
+ NetDataWriter writer = new();
+ //Send ID
+ writer.Put(user.Id);
+ fromPeer.Send(writer, DeliveryMethod.ReliableUnordered);
+ user.sentId = true;
+
+ Console.WriteLine($"{fromPeer.EndPoint} is {user.Username}!");
+
+ foreach (ServerUser toSend in users.Values)
+ {
+ if (!toSend.ExchangedData || toSend == user) continue;
+
+ //Send all current users spritesheets to this user.
+ writer.ResetWithInfo(new PacketInfo(PacketType.OnekoSpritesheet, toSend.Id), toSend.SpriteSheet!.Length);
+ writer.Put(toSend.SpriteSheet);
+ fromPeer.Send(writer, DeliveryMethod.ReliableUnordered);
+
+ writer.ResetWithInfo(new PacketInfo(PacketType.Username, toSend.Id));
+ writer.Put(toSend.Username);
+ fromPeer.Send(writer, DeliveryMethod.ReliableUnordered);
+
+ //Send all current users this users spritesheet
+ writer.ResetWithInfo(new PacketInfo(PacketType.OnekoSpritesheet, user.Id), user.SpriteSheet!.Length);
+ writer.Put(user.SpriteSheet);
+ toSend.Peer.Send(writer, DeliveryMethod.ReliableUnordered);
+
+ writer.ResetWithInfo(new PacketInfo(PacketType.Username, user.Id));
+ writer.Put(user.Username);
+ toSend.Peer.Send(writer, DeliveryMethod.ReliableUnordered);
+ }
+ }
+ };
- users.GetOrAdd(user.Id, user);
- await Task.Factory.StartNew(() => UpdateUser(user));
- } else {
- Console.WriteLine($"{user.Tcp.Client.RemoteEndPoint} failed to send required data, terminating connection.");
- user.Dispose();
- }
+ Console.WriteLine("Server Initialized!");
}
- static async Task ExchangeUserData(ServerUser user)
+ public void Poll()
{
- while (!user.ExchangedData)
- {
- Packet packet = await NetBase.GetReliableData(user.Tcp.GetStream());
-
- if (packet.Data.Length > 50000) break;
-
- if (packet.Type == PacketType.Username) {
- user.Username = Encoding.UTF8.GetString(packet.Data);
- } else if (packet.Type == PacketType.OnekoSpritesheet) {
- user.SpriteSheet = packet.Data;
- }
- }
-
- if (!user.ExchangedData) return;
-
- //Send ID
- byte[] idData = new byte[sizeof(int)];
- BinaryPrimitives.WriteInt32LittleEndian(idData, user.Id);
- await NetBase.SendReliableData(new Packet(PacketType.UserId, idData, 0), user.Tcp.GetStream());
-
- Console.WriteLine($"{user.Tcp.Client.RemoteEndPoint} is {user.Username}!");
+ NetServer.PollEvents();
}
- static async Task UpdateUser(ServerUser user)
+ public void Disconnect()
{
- while (user.Tcp.Connected) {
- Packet toSend = await user.ToSend.Reader.ReadAsync(user.UpdateCancel.Token);
- await NetBase.SendReliableData(toSend, user.Tcp.GetStream(), user.UpdateCancel.Token);
- }
- //users.TryRemove(user.Id, out _);
- //user.Dispose();
+ NetServer.DisconnectAll();
}
}
-class ServerUser(int id, TcpClient tcp, UdpClient udp) : User(id), IDisposable
+class ServerUser(int id, NetPeer peer) : User(id), IDisposable
{
//Network
- public readonly TcpClient Tcp = tcp;
- public readonly UdpClient Udp = udp;
- public readonly Channel<Packet> ToSend = Channel.CreateUnbounded<Packet>();
- public CancellationTokenSource UpdateCancel = new();
+ public readonly NetPeer Peer = peer;
+ public bool sentId = false;
public void Dispose()
{
- UpdateCancel.Cancel();
- Tcp.Dispose();
- Udp.Dispose();
+ Peer.Disconnect();
}
} \ No newline at end of file