1
0
Fork 0
mirror of https://github.com/besterprotocol/besterd synced 2023-12-13 21:00:32 +01:00
besterd/source/server/types.d

142 lines
3.6 KiB
D
Raw Normal View History

2020-04-16 15:02:34 +02:00
module server.types;
import utils.debugging : debugPrint;
import std.conv : to;
import std.socket : Socket, AddressFamily, SocketType, ProtocolType, parseAddress, SocketFlags;
2020-04-16 17:05:56 +02:00
import core.thread : Thread;
import std.stdio : writeln;
2020-04-16 18:46:26 +02:00
import std.json : JSONValue, parseJSON, JSONException;
2020-04-16 15:02:34 +02:00
public class BesterServer
{
2020-04-16 16:39:31 +02:00
/* The server's socket */
private Socket serverSocket;
this(string bindAddress, ushort listenPort)
{
debugPrint("Binding to address: " ~ bindAddress ~ " and port " ~ to!(string)(listenPort));
2020-04-16 16:39:31 +02:00
initialize(bindAddress, listenPort);
}
private void initialize(string bindAddress, ushort listenPort)
{
/* Create a socket */
2020-04-16 16:41:56 +02:00
serverSocket = new Socket(AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP);
2020-04-16 16:43:00 +02:00
serverSocket.bind(parseAddress(bindAddress, listenPort));
2020-04-16 16:39:31 +02:00
}
/* Start listen loop */
public void run()
{
2020-04-16 16:43:00 +02:00
serverSocket.listen(1); /* TODO: This value */
2020-04-16 16:39:31 +02:00
debugPrint("Server listen loop started");
2020-04-16 17:05:56 +02:00
while(true)
{
/* Wait for an incoming connection */
Socket clientConnection = serverSocket.accept();
/* Create a new client connection handler and start its thread */
BesterConnection besterConnection = new BesterConnection(clientConnection);
besterConnection.start();
2020-04-16 17:05:56 +02:00
}
}
}
private class BesterConnection : Thread
{
/* The socket to the client */
private Socket clientConnection;
this(Socket clientConnection)
{
/* Save socket and set thread worker function pointer */
super(&run);
this.clientConnection = clientConnection;
debugPrint("New client handler spawned for " ~ clientConnection.remoteAddress().toAddrString());
2020-04-16 17:05:56 +02:00
}
/* Read/send loop */
private void run()
{
/* Receive buffer */
byte[] buffer;
2020-04-16 16:39:31 +02:00
while(true)
{
/* Make the dynamic array's size 4 */
buffer.length = 4;
/* Read the first 4 bytes (retrieve message size) */
long bytesReceived = clientConnection.receive(buffer);
writeln("PreambleWait: Bytes received: ", cast(ulong)bytesReceived);
/* Make sure exactly 4 bytes were received */
if (bytesReceived != 4)
{
/* If we don't get exactly 4 bytes, drop the client */
debugPrint("Did not get exactly 4 bytes for preamble, disconnecting client...");
clientConnection.close();
break;
}
/* Get the message length */
int messageLength = *(cast(int*)buffer.ptr);
writeln("Message length: ", cast(uint)messageLength);
/* TODO: Testing locally ain't good as stuff arrives way too fast, although not as fast as I can type */
/* What must happen is a loop to loop and wait for data */
2020-04-16 18:26:53 +02:00
/* Full message buffer */
byte[] messageBuffer;
2020-04-16 18:30:47 +02:00
/* TODO: Add timeout if we haven't received a message in a certain amount of time */
2020-04-16 18:26:53 +02:00
uint currentByte = 0;
while(currentByte < cast(uint)messageLength)
{
/* Receive 20 bytes (at most) at a time */
byte[20] messageBufferPartial;
bytesReceived = clientConnection.receive(messageBufferPartial);
/* Append the received bytes to the FULL message buffer */
messageBuffer ~= messageBufferPartial[0..bytesReceived];
2020-04-16 18:52:28 +02:00
/* TODO: Bug when over send, we must not allow this */
2020-04-16 18:26:53 +02:00
/* Increment counter of received bytes */
currentByte += bytesReceived;
2020-04-16 18:30:47 +02:00
writeln("Received ", currentByte, "/", cast(uint)messageLength, " bytes");
2020-04-16 18:26:53 +02:00
}
2020-04-16 18:46:26 +02:00
/* Process the message */
processMessage(messageBuffer);
}
}
/* Process the received message */
private void processMessage(byte[] messageBuffer)
{
/* The message as a JSONValue struct */
JSONValue jsonMessage;
try
{
/* Convert message to JSON */
jsonMessage = parseJSON(cast(string)messageBuffer);
2020-04-16 18:46:26 +02:00
writeln("JSON received: ", jsonMessage);
}
catch(JSONException exception)
{
/* TODO: Implement this */
2020-04-16 16:39:31 +02:00
}
2020-04-16 18:46:26 +02:00
}
2020-04-16 17:05:56 +02:00
2020-04-16 15:02:34 +02:00
}