daemon now uses configuration file for network parameters, also added motd command and serverinfo command (not yet implemented)

This commit is contained in:
Tristan B. Kildaire 2020-10-02 16:11:27 +02:00
parent c8a9c2bffe
commit ef90f1ba13
6 changed files with 315 additions and 9 deletions

View File

@ -1,8 +1,9 @@
{
"general" : {
"address" : "0.0.0.0",
"addresses" : ["0.0.0.0"],
"port" : "7777",
"network" : "aBasedIRCNetwork",
"name" : "MyBrandSpankingNewIRCServer"
"name" : "MyBrandSpankingNewIRCServer",
"motd" : "Welcome to my generic dnet chat server!"
}
}

View File

@ -143,13 +143,46 @@ Request format:
|-- 9 --|-- channel --|
```
Reply format:
```
|-- status (1 byte) --|-- channel members (CSV) --|
```
### `serverinfo`
Request format:
```
|-- 10 --|
```
Reply format:
```
|-- status (1 byte) --|-- server info(CSV) --|
```
#### Format of server info (CSV)
```
<serverName>,<networkName>,<userCount>,<channelCount>
```
### `motd`
Request format:
```
|-- 11 --|
```
Reply format:
```
|-- status (1 byte) --|-- motd --|
```
### `chanprop`

View File

@ -1,13 +1,82 @@
import std.stdio;
import std.socket : parseAddress;
import dnetd.dserver : DServer;
import dnetd.dconfig : DConfig;
import std.json;
import std.exception;
void main()
void main(string[] args)
{
/* TODO: Args for bind */
/* Configuration file */
string configFilename;
/* If there are no arguments */
if(!args.length)
{
/* Use the default file */
configFilename = "config.json";
}
/* If there is one argument */
else if(args.length == 1)
{
/* use the specified one */
configFilename = args[0];
}
/* Illegal amount of guns in one household (no such thing) */
else
{
writeln("Invalid number of arguments");
return;
}
/* Configuration file contents */
byte[] data;
DServer dserver = new DServer(parseAddress("0.0.0.0", 7777));
try
{
/* Open the file for reading */
File config;
config.open(configFilename, "r");
/* Read the configuration file data */
data.length = config.size();
data = config.rawRead(data);
config.close();
}
catch(ErrnoException e)
{
writeln("Failure to use configuration file'"~configFilename~"' with error:\n\n"~e.toString());
return;
}
/* The JSON */
JSONValue json;
try
{
/* Parse the configuration file */
json = parseJSON(cast(string)data);
}
catch(JSONException e)
{
writeln("Failure to parse configuration file'"~configFilename~"' with error:\n\n"~e.toString());
return;
}
/* Create a new configuration file and check configuration parameters */
DConfig config = DConfig.getConfig(json);
/* If the configuration reading was successful (valid JSON) */
if(config)
{
/* Start the server */
DServer dserver = new DServer(config);
}
else
{
writeln("Failure to read a valid dnetd configuration file'"~configFilename~"'");
}
}

View File

@ -0,0 +1,138 @@
/**
* DConfig
*
* Represents all configuration parameters
*/
module dnetd.dconfig;
import std.json;
import std.conv;
import std.socket : Address, parseAddress;
public final class DConfig
{
/* General configuration */
private DGeneralConfig generalConfig;
/* Link configuration */
private DLinkConfig linksConfig;
private this()
{
/* TODO: */
}
public DGeneralConfig getGeneral()
{
return generalConfig;
}
public DLinkConfig getLinks()
{
return linksConfig;
}
public static DConfig getConfig(JSONValue json)
{
/* The newly created configuration */
DConfig config = new DConfig();
try
{
/* TODO: Parse */
/* Get the `general` block */
JSONValue generalBlock = json["general"];
config.generalConfig = DGeneralConfig.getConfig(generalBlock);
/* Get the `links` block */
JSONValue linksBlock = json["links"];
//config.linksConfig = DLinkConfig.getConfig(linksBlock);
}
catch(JSONException e)
{
/* Set config to null (signals an error) */
config = null;
}
return config;
}
public JSONValue saveConfig()
{
JSONValue config;
return config;
}
}
public final class DGeneralConfig
{
/* Addresses to bind sockets to */
private string[] addresses;
private ushort port;
/* Server information */
private string network;
private string name;
private string motd;
private this()
{
}
public static DGeneralConfig getConfig(JSONValue generalBlock)
{
/* The generated general config */
DGeneralConfig config = new DGeneralConfig();
try
{
/* Set the addresses */
foreach(JSONValue address; generalBlock["addresses"].array())
{
config.addresses ~= [address.str()];
}
/* Set the ports */
config.port = to!(ushort)(generalBlock["port"].str());
/* Set the network name */
config.network = generalBlock["network"].str();
/* Set the server name */
config.name = generalBlock["name"].str();
/* Set the message of the day */
config.motd = generalBlock["motd"].str();
}
catch(JSONException e)
{
/* Set the config to null (signals an error) */
config = null;
}
return config;
}
public string getMotd()
{
return motd;
}
public Address getAddress()
{
/* TODO: Add multi address support later */
return parseAddress(addresses[0], port);
}
}
public final class DLinkConfig
{
}

View File

@ -42,6 +42,8 @@ public class DConnection : Thread
MSG,
MEMBER_COUNT,
MEMBER_LIST,
SERVER_INFO,
MOTD,
UNKNOWN
}
@ -244,6 +246,16 @@ public class DConnection : Thread
{
command = Command.MEMBER_LIST;
}
else if(commandByte == cast(ulong)10)
{
command = Command.SERVER_INFO;
}
else if(commandByte == cast(ulong)11)
{
command = Command.MOTD;
}
return command;
@ -541,6 +553,32 @@ public class DConnection : Thread
}
/* If `serverinfo` command (requires: authed, !unspec) */
else if(command == Command.SERVER_INFO && hasAuthed && connType != ConnectionType.UNSPEC)
{
/* Status */
bool status = true;
/* Get the server info */
string serverInfo = server.getServerInfo();
/* Encode the reply */
reply ~= [status];
reply ~= serverInfo;
}
/* If `motd` command (requires: _nothing_) */
else if(command == Command.MOTD)
{
/* Status */
bool status = true;
/* Get the message of the day */
string motd = server.getConfig().getGeneral().getMotd();
/* Encode the reply */
reply ~= [status];
reply ~= motd;
}
/* If no matching built-in command was found */
else

View File

@ -18,6 +18,7 @@ import std.string : cmp;
import core.sync.mutex : Mutex;
import std.stdio;
import std.conv : to;
import dnetd.dconfig;
public class DServer : Thread
{
@ -28,6 +29,9 @@ public class DServer : Thread
private Address sockAddress;
/* Server configuration */
private DConfig config;
/**
* Connection queue
*/
@ -40,13 +44,17 @@ public class DServer : Thread
private DChannel[] channels;
private Mutex channelLock;
this(Address sockAddress)
/* TODO: Implement new constructor */
this(DConfig config)
{
/* Set the function to be called on thread start */
super(&dequeueLoop);
/* Set the server's config */
this.config = config;
/* Set the listening address */
this.sockAddress = sockAddress;
this.sockAddress = config.getGeneral().getAddress();
/* Initialize the server */
init();
@ -55,6 +63,11 @@ public class DServer : Thread
startServer();
}
public DConfig getConfig()
{
return config;
}
private void init()
{
/* Setup socket */
@ -309,4 +322,18 @@ public class DServer : Thread
return currentChannels;
}
public string getServerInfo()
{
/* The server information */
string serverInfo;
/* TODO: Fetch serverName */
/* TODO: Fetch networkName */
/* TODO: Fetch userCount */
/* TODO: Fetch channelCount */
return serverInfo;
}
}