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);
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);
}
}
}