// Copyright 2018 RED Software, LLC. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
namespace IgniteEngine.Networking
{
///
/// Class that listens for incoming network connections using the
/// TCP socket protocol.
///
public class NetworkServer : Object
{
///
/// The default backlog size, which will be used if none is provided.
///
public const int BACKLOG_SIZE = 100;
///
/// A list of the active connections to the .
///
public List Connections { get; }
///
/// Returns true if this server listens for local (server-to-server) connections.
///
public bool IsInterService => connectionType != NetworkConnectionType.NCT_CLIENT;
///
/// The type of connections the server is listening for.
///
private readonly NetworkConnectionType connectionType;
///
/// The socket that listens for connections.
///
private readonly Socket socket;
///
/// Creates a new instance of the class.
///
public NetworkServer(NetworkConnectionType connectionType)
{
Connections = new List();
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.connectionType = connectionType;
}
///
/// Places the server in the listening state.
///
/// The IP address to listen for connection on.
/// The port to listen for connections on.
/// The maximum number of pending connections in the queue.
public void Listen(string ipAddress, ushort port, int backlog = BACKLOG_SIZE)
{
if (!IPAddress.TryParse(ipAddress, out var address))
{
Debug.LogAssert($"The IPAddress {ipAddress} is invalid.");
return;
}
socket.Bind(new IPEndPoint(address, port));
socket.Listen(backlog);
socket.BeginAccept(AcceptConnection, socket);
}
///
/// Accepts a pending connection.
///
/// The status of the operation.
private void AcceptConnection(IAsyncResult e)
{
if (e.AsyncState == null)
{
Debug.LogAssert("NetworkServer::AcceptConnection : AsyncState is null");
return;
}
var serverSocket = (Socket) e.AsyncState;
var clientSocket = serverSocket.EndAccept(e);
if (clientSocket != null)
{
var connection = new NetworkConnection(this, clientSocket, connectionType);
if (connection.IsConnected)
{
Connections.Add(connection);
}
}
// Begin accepting connections again.
serverSocket.BeginAccept(AcceptConnection, serverSocket);
}
///
/// Destroys the instance.
///
protected override void Destroy()
{
// Close() calls the dispose method for us.
socket.Close();
}
}
}