using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using DFEngine.Logging;
namespace DFEngine.Network
{
///
/// 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 BacklogSize = 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 = BacklogSize)
{
if (!IPAddress.TryParse(ipAddress, out var address))
{
SocketLog.Write(SocketLogLevel.Exception, $"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)
{
SocketLog.Write(SocketLogLevel.Exception, "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();
}
}
}