// This file is provided under The MIT License as part of RiptideNetworking. // Copyright (c) Tom Weiland // For additional information please see the included LICENSE.md file or view it on GitHub: // https://github.com/RiptideNetworking/Riptide/blob/main/LICENSE.md using System; using System.Collections.Generic; using System.Net; namespace Riptide.Transports.Udp { /// A server which can accept connections from s. public class UdpServer : UdpPeer, IServer { /// public event EventHandler Connected; /// public event EventHandler DataReceived; /// public ushort Port { get; private set; } /// The currently open connections, accessible by their endpoints. private Dictionary connections; /// The IP address to bind the socket to, if any. private readonly IPAddress listenAddress; /// public UdpServer(SocketMode mode = SocketMode.Both, int socketBufferSize = DefaultSocketBufferSize) : base(mode, socketBufferSize) { } /// Initializes the transport, binding the socket to a specific IP address. /// The IP address to bind the socket to. /// How big the socket's send and receive buffers should be. public UdpServer(IPAddress listenAddress, int socketBufferSize = DefaultSocketBufferSize) : base(SocketMode.Both, socketBufferSize) { this.listenAddress = listenAddress; } /// public void Start(ushort port) { Port = port; connections = new Dictionary(); OpenSocket(listenAddress, port); } /// Decides what to do with a connection attempt. /// The endpoint the connection attempt is coming from. /// Whether or not the connection attempt was from a new connection. private bool HandleConnectionAttempt(IPEndPoint fromEndPoint) { if (connections.ContainsKey(fromEndPoint)) return false; UdpConnection connection = new UdpConnection(fromEndPoint, this); connections.Add(fromEndPoint, connection); OnConnected(connection); return true; } /// public void Close(Connection connection) { if (connection is UdpConnection udpConnection) connections.Remove(udpConnection.RemoteEndPoint); } /// public void Shutdown() { CloseSocket(); connections.Clear(); } /// Invokes the event. /// The successfully established connection. protected virtual void OnConnected(Connection connection) { Connected?.Invoke(this, new ConnectedEventArgs(connection)); } /// protected override void OnDataReceived(byte[] dataBuffer, int amount, IPEndPoint fromEndPoint) { if ((MessageHeader)(dataBuffer[0] & Message.HeaderBitmask) == MessageHeader.Connect && !HandleConnectionAttempt(fromEndPoint)) return; if (connections.TryGetValue(fromEndPoint, out Connection connection) && !connection.IsNotConnected) DataReceived?.Invoke(this, new DataReceivedEventArgs(dataBuffer, amount, connection)); } } }