This repository has been archived on 2019-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
PixelHub/PixelHub-Server/PixelHub/PixelHub.cs

135 lines
3.5 KiB
C#

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
{
/// <summary>
/// Provides the server component of the Hull Pixelbot server that can be used to control any number of pixel bots at once.
/// </summary>
public class PixelHub
{
TextWriter logger;
IPAddress bindAddress = IPAddress.Any;
int port;
TcpListener server;
/// <summary>
/// A list of PixelBots that are currently connected to the PixelHub.
/// </summary>
public List<PixelBot> ConnectedBots = new List<PixelBot>();
/// <summary>
/// Whether the Hull Pixelbot server is currently active and listening.
/// </summary>
public bool Active { get; private set; } = false;
/// <summary>
/// The IPAddress that the PixelHub is (or should be) bound to.
/// </summary>
/// <remarks>
/// You can only set this Property with generating an exception if the server
/// hasn't already been started with Listen().
/// </remarks>
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;
}
}
/// <summary>
/// The port number that the PixelHb is (or should be) listening on.
/// </summary>
/// <remarks>
/// You can only set this Property with generating an exception if the server
/// hasn't already been started with Listen().
/// </remarks>
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;
}
}
/// <summary>
/// Squashes the BindAddress and the port number together to form the endpoint that the server
/// is (or should be) listening on.
/// </summary>
public IPEndPoint Endpoint
{
get {
return new IPEndPoint(BindAddress, Port);
}
}
/// <summary>
/// Creates a new Pixelhub instance.
/// </summary>
/// <param name="inPort">The port to listen on.</param>
/// <param name="inLogger">The TextWriter to send log messages to.</param>
public PixelHub(int inPort, TextWriter inLogger)
{
Port = inPort;
logger = inLogger;
}
/// <summary>
/// Creates a new Pixelhub instance.
/// </summary>
/// <param name="inPort">The port to listen on.</param>
public PixelHub(int inPort) : this(inPort, Console.Out)
{
}
/// <summary>
/// Starts the PixelHub server and begins listening for connections.
/// </summary>
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();
Console.WriteLine("Got connection");
AsyncTools.ForgetTask(Handle(nextClient));
}
// TODO: Add an shutdown CancellationToken thingy here
//Active = false;
}
/// <summary>
/// Handles a single connection.
/// </summary>
/// <param name="client">The TcpClient connection to handle.</param>
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);
}
}
}