134 lines
3.5 KiB
C#
134 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);
|
|
}
|
|
}
|
|
}
|
|
|