1
0
mirror of https://github.com/deavminet/dnetd synced 2024-09-21 09:43:37 +02:00
dnetd_old/source/dnetd/dserver.d

258 lines
5.0 KiB
D
Raw Normal View History

2020-09-23 09:37:18 +02:00
/**
* DServer
*
* Represents a server instance.
*
* Holds a list of DConnections,
* configuration parameters and
* more.
*/
module dnetd.dserver;
import core.thread : Thread;
import std.socket : Address, Socket, AddressFamily, SocketType, ProtocolType;
2020-09-23 09:37:18 +02:00
import dnetd.dconnection;
2020-09-23 18:52:11 +02:00
import dnetd.dchannel;
import std.string : cmp;
import core.sync.mutex : Mutex;
import std.stdio;
import std.conv : to;
2020-09-23 09:37:18 +02:00
public class DServer : Thread
{
/* The server's socket to bind, listen and accept connections from */
private Socket serverSocket;
/* Bind address */
private Address sockAddress;
/**
* Connection queue
*/
2020-09-23 09:37:18 +02:00
private DConnection[] connectionQueue;
private Mutex connectionLock;
2020-09-23 18:52:11 +02:00
/**
* Channels
*/
private DChannel[] channels;
private Mutex channelLock;
2020-09-23 09:37:18 +02:00
this(Address sockAddress)
{
/* Set the function to be called on thread start */
super(&dequeueLoop);
/* Set the listening address */
this.sockAddress = sockAddress;
/* Initialize the server */
init();
/* Start the server */
startServer();
}
private void init()
{
/* Setup socket */
initNetwork();
/* Setup queues */
initQueues();
2020-09-23 18:52:11 +02:00
/* Setup locks */
initLocks();
2020-09-23 09:37:18 +02:00
}
/**
* Creates the socket, binds it
* to the given address
*/
private void initNetwork()
{
/* Create the socket */
serverSocket = new Socket(AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP);
2020-09-23 09:37:18 +02:00
/* Bind the socket to the given address */
serverSocket.bind(sockAddress);
}
/**
* Creates all needed queues
* and their mutexes
*/
private void initQueues()
{
/* TODO: Implement me */
}
2020-09-23 18:52:11 +02:00
private void initLocks()
{
/* Initialize the connection lock */
connectionLock = new Mutex();
/* Initialize the channel lock */
2020-09-23 18:52:11 +02:00
channelLock = new Mutex();
}
2020-09-23 09:37:18 +02:00
private void startServer()
{
/* Start the connection dequeue thread */
start();
}
private void dequeueLoop()
{
/* Start accepting-and-enqueuing connections */
serverSocket.listen(0); /* TODO: Linux be lile, hehahahhahahah who gives one - I give zero */
while(true)
{
/* Dequeue a connection */
Socket socket = serverSocket.accept();
/* Spawn a connection handler */
2020-09-23 18:52:11 +02:00
DConnection connection = new DConnection(this, socket);
2020-09-23 09:37:18 +02:00
/* Add to the connection queue */
addConnection(connection);
2020-09-23 09:37:18 +02:00
}
}
2020-09-23 18:52:11 +02:00
public void addChannel(DConnection causer, DChannel channel)
{
/* Lock the channels list */
channelLock.lock();
channels ~= channel;
/* TODO: Use causer */
/* Unlock the channels list */
channelLock.unlock();
}
public void addConnection(DConnection connection)
{
/* Lock the connections list */
connectionLock.lock();
/* Add to the connection queue */
connectionQueue ~= connection;
2020-09-28 12:50:40 +02:00
writeln("Added connection to queue "~to!(string)(connection));
/* Unlock the connections list */
connectionLock.unlock();
}
/* TODO Remove connection */
2020-09-28 12:50:40 +02:00
public void removeConnection(DConnection connection)
{
2020-09-28 12:50:40 +02:00
/* Lock the connections list */
connectionLock.lock();
/* The new connection queue */
DConnection[] connectionQueueNew;
foreach(DConnection currentConnection; connectionQueue)
{
if(!(currentConnection is connection))
{
connectionQueueNew ~= currentConnection;
}
}
/* Set this as the new queue */
connectionQueue = connectionQueueNew;
/* TODO: Implement removal */
writeln("Remove connection from queue "~to!(string)(connection));
/* Unlock the connections list */
connectionLock.unlock();
}
2020-09-23 18:52:11 +02:00
public DChannel getChannelByName(string channelName)
{
/* The channel */
DChannel channel = null;
2020-09-23 18:52:11 +02:00
/* Lock the channels list */
channelLock.lock();
foreach(DChannel currentChannel; channels)
{
if(cmp(currentChannel.getName(), channelName) == 0)
{
channel = currentChannel;
break;
2020-09-23 18:52:11 +02:00
}
}
/* Unlock the channels list */
channelLock.unlock();
return channel;
2020-09-23 18:52:11 +02:00
}
2020-09-24 12:32:00 +02:00
/**
* Returns the DConnection with the matching
* username, null if not found
*/
public DConnection findUser(string username)
{
/* Get all the current connections */
DConnection[] connections = getConnections();
/* Find the user with the matching user name */
foreach(DConnection connection; connections)
{
/* The connection must be a user (not unspec or server) */
if(connection.getConnectionType() == DConnection.ConnectionType.CLIENT)
{
/* Match the username */
if(cmp(connection.getUsername(), username) == 0)
{
return connection;
}
}
}
return null;
}
public DConnection[] getConnections()
{
/* The current connections list */
DConnection[] currentConnections;
/* Lock the connections list */
connectionLock.lock();
currentConnections = connectionQueue;
/* Unlock the connections list */
connectionLock.unlock();
return currentConnections;
}
2020-09-24 12:32:00 +02:00
public DChannel[] getChannels()
{
2020-09-26 15:05:52 +02:00
/* The current channels list */
DChannel[] currentChannels;
/* Lock the channels list */
channelLock.lock();
currentChannels = channels;
/* Unlock the channels list */
channelLock.unlock();
return currentChannels;
2020-09-24 12:32:00 +02:00
}
2020-09-23 09:37:18 +02:00
}