using System; using System.Net.Sockets; using System.Threading.Tasks; using System.Net; using SBRL.Utilities; using System.IO; using System.Collections.Generic; namespace PixelHub.Server { /// /// Provides the server component of the Hull Pixelbot server that can be used to control any number of pixel bots at once. /// public class PixelHub { TextWriter logger; IPAddress bindAddress = IPAddress.Any; int port; TcpListener server; /// /// A list of PixelBots that are currently connected to the PixelHub. /// public List ConnectedBots = new List(); /// /// Whether the Hull Pixelbot server is currently active and listening. /// public bool Active { get; private set; } = false; /// /// The IPAddress that the PixelHub is (or should be) bound to. /// /// /// You can only set this Property with generating an exception if the server /// hasn't already been started with Listen(). /// public IPAddress BindAddress { get { return bindAddress; } set { if (Active == true) throw new InvalidOperationException("Error: The bind address can't be changed once the server has started listening!"); bindAddress = value; } } /// /// The port number that the PixelHb is (or should be) listening on. /// /// /// You can only set this Property with generating an exception if the server /// hasn't already been started with Listen(). /// public int Port { get { return port; } set { if (Active == true) throw new InvalidOperationException("Error: The port can't be changed once the server has started listening!"); port = value; } } /// /// Squashes the BindAddress and the port number together to form the endpoint that the server /// is (or should be) listening on. /// public IPEndPoint Endpoint { get { return new IPEndPoint(BindAddress, Port); } } /// /// Creates a new Pixelhub instance. /// /// The port to listen on. /// The TextWriter to send log messages to. public PixelHub(int inPort, TextWriter inLogger) { Port = inPort; logger = inLogger; } /// /// Creates a new Pixelhub instance. /// /// The port to listen on. public PixelHub(int inPort) : this(inPort, Console.Out) { } /// /// Starts the PixelHub server and begins listening for connections. /// public async Task Listen() { server = new TcpListener(Endpoint); server.Start(); logger.WriteLine("TCP Listener set up on {0}.", Endpoint); Active = true; while(true) { TcpClient nextClient = await server.AcceptTcpClientAsync(); AsyncTools.ForgetTask(Handle(nextClient)); } // TODO: Add an shutdown CancellationToken thingy here //Active = false; } /// /// Handles a single connection. /// /// The TcpClient connection to handle. private async Task Handle(TcpClient client) { logger.WriteLine("Accepted connection from {0}.", client.Client.RemoteEndPoint); PixelBot pixelBot = new PixelBot(client); ConnectedBots.Add(pixelBot); await pixelBot.Handle(); ConnectedBots.Remove(pixelBot); logger.WriteLine("Lost connection from {0}.", client.Client.RemoteEndPoint); } } }