Basic message queuing implemented
- Messages are now queued on reception by the server. - Message queue datastructures are now added.
This commit is contained in:
parent
e4b8693037
commit
4ddb80b8b2
2
Makefile
2
Makefile
|
@ -6,7 +6,7 @@ serversrc = $(wildcard src/misc/*.c) \
|
||||||
src/SilverMUDServer.c
|
src/SilverMUDServer.c
|
||||||
serverobj = $(serversrc:.c=.o)
|
serverobj = $(serversrc:.c=.o)
|
||||||
CLIENTLDFLAGS= -lpthread -lncurses -lgnutls
|
CLIENTLDFLAGS= -lpthread -lncurses -lgnutls
|
||||||
SERVERLDFLAGS= -lncurses -lgnutls
|
SERVERLDFLAGS= -lpthread -lncurses -lgnutls
|
||||||
SilverMUDClient: $(clientobj)
|
SilverMUDClient: $(clientobj)
|
||||||
gcc -s -O3 -o $@ $^ $(CLIENTLDFLAGS)
|
gcc -s -O3 -o $@ $^ $(CLIENTLDFLAGS)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
* SilverMUD: An extensible terminal-top role playing game engine
|
* SilverMUD: The Hackable Terminal-Top Roleplaying Game.
|
||||||
SilverMUD is a tool for creating engaging and communal stories, all over the
|
SilverMUD is a tool for creating engaging and communal stories, all over the
|
||||||
world through the internet. It's designed to give a game master the same power
|
world through the internet. It's designed to give a gamemaster the same power
|
||||||
to improvise that they have at the table, through simple programming and
|
to improvise that they have at the table, through simple programming and
|
||||||
easy-to-understand structures.
|
easy-to-understand structures.
|
||||||
** Player's Guide
|
** Player's Guide
|
||||||
|
|
|
@ -13,11 +13,10 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
|
#include "misc/constants.h"
|
||||||
#include "misc/playerdata.h"
|
#include "misc/playerdata.h"
|
||||||
#include "misc/texteffects.h"
|
#include "misc/texteffects.h"
|
||||||
#include "misc/inputoutput.h"
|
#include "misc/inputoutput.h"
|
||||||
#include "misc/inputhandling.h"
|
|
||||||
static int MAX = 2048;
|
|
||||||
|
|
||||||
// A struct for passing arguments to our threads containing a file descriptor and a window pointer:
|
// A struct for passing arguments to our threads containing a file descriptor and a window pointer:
|
||||||
typedef struct threadparameters
|
typedef struct threadparameters
|
||||||
|
|
|
@ -14,31 +14,32 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
#include "misc/lists.h"
|
#include "misc/lists.h"
|
||||||
|
#include "misc/constants.h"
|
||||||
#include "misc/playerdata.h"
|
#include "misc/playerdata.h"
|
||||||
#include "misc/texteffects.h"
|
#include "misc/texteffects.h"
|
||||||
#include "misc/inputoutput.h"
|
#include "misc/inputoutput.h"
|
||||||
#include "misc/inputhandling.h"
|
|
||||||
|
|
||||||
const int PORT = 5000;
|
|
||||||
const int PLAYERCOUNT = 64;
|
|
||||||
typedef struct sockaddr sockaddr;
|
typedef struct sockaddr sockaddr;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
bool keepRunning = true;
|
bool keepRunning = true;
|
||||||
int socketFileDesc, connectionFileDesc, length, clientsAmount,
|
int socketFileDesc, connectionFileDesc, length, clientsAmount,
|
||||||
socketCheck, activityCheck, readLength, returnVal;
|
socketCheck, activityCheck, returnVal;
|
||||||
fd_set connectedClients;
|
fd_set connectedClients;
|
||||||
int clientSockets[PLAYERCOUNT];
|
int clientSockets[PLAYERCOUNT];
|
||||||
userMessage sendBuffer, receiveBuffer;
|
userMessage sendBuffer, receiveBuffer;
|
||||||
playerInfo connectedPlayers[PLAYERCOUNT];
|
playerInfo connectedPlayers[PLAYERCOUNT];
|
||||||
char testString[32] = "Hehe.";
|
char testString[32] = "Hehe.";
|
||||||
struct sockaddr_in serverAddress, clientAddress;
|
struct sockaddr_in serverAddress, clientAddress;
|
||||||
|
inputMessageQueue * inputQueue = createInputMessageQueue();
|
||||||
|
outputMessageQueue * outputQueue = createOutputMessageQueue();
|
||||||
|
|
||||||
// Initialize playerdata:
|
// Initialize playerdata:
|
||||||
for (int index = 0; index < PLAYERCOUNT; index++)
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
{
|
{
|
||||||
strcpy(connectedPlayers[index].playerName, "UNNAMED");
|
sprintf(testString, "UNNAMED %d", index);
|
||||||
|
strcpy(connectedPlayers[index].playerName, testString);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give an intro: Display the Silverkin Industries logo and splash text.
|
// Give an intro: Display the Silverkin Industries logo and splash text.
|
||||||
|
@ -187,18 +188,47 @@ int main()
|
||||||
|
|
||||||
if(FD_ISSET(socketCheck, &connectedClients))
|
if(FD_ISSET(socketCheck, &connectedClients))
|
||||||
{
|
{
|
||||||
messageReceive(tlssessions[index], &receiveBuffer);
|
if(messageReceive(tlssessions[index], &receiveBuffer) == -10)
|
||||||
sprintf(testString, "User %d", index);
|
|
||||||
strcpy(sendBuffer.senderName, testString);
|
|
||||||
userInputSanatize(receiveBuffer.messageContent, sizeof(receiveBuffer.messageContent));
|
|
||||||
strcpy(sendBuffer.messageContent, receiveBuffer.messageContent);
|
|
||||||
for (int sendIndex = 0; sendIndex < clientsAmount; sendIndex++)
|
|
||||||
{
|
{
|
||||||
messageSend(tlssessions[sendIndex], &sendBuffer);
|
gnutls_bye(tlssessions[index], GNUTLS_SHUT_RDWR);
|
||||||
|
gnutls_deinit(tlssessions[index]);
|
||||||
|
shutdown(clientSockets[index], 2);
|
||||||
|
close(clientSockets[index]);
|
||||||
|
clientSockets[index] = 0;
|
||||||
|
tlssessions[index] = NULL;
|
||||||
|
gnutls_init(&tlssessions[index], GNUTLS_SERVER);
|
||||||
|
gnutls_priority_set_direct(tlssessions[index], "NORMAL:+ANON-ECDH:+ANON-DH", NULL);
|
||||||
|
gnutls_credentials_set(tlssessions[index], GNUTLS_CRD_ANON, &serverkey);
|
||||||
|
gnutls_handshake_set_timeout(tlssessions[index], GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queueInputMessage(inputQueue, receiveBuffer, &connectedPlayers[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TEMPORARY: MOVE INPUT MESSAGES TO OUTPUT MESSAGES:
|
||||||
|
while(inputQueue->currentLength > 0)
|
||||||
|
{
|
||||||
|
inputMessage * message = peekInputMessage(inputQueue);
|
||||||
|
strncpy(message->content->senderName, message->sender->playerName, 32);
|
||||||
|
userInputSanatize(message->content->messageContent, MAX);
|
||||||
|
if(message->content->messageContent[0] != '\n')
|
||||||
|
{
|
||||||
|
queueOutputMessage(outputQueue, *message->content);
|
||||||
|
}
|
||||||
|
dequeueInputMessage(inputQueue);
|
||||||
|
}
|
||||||
|
while(outputQueue->currentLength > 0)
|
||||||
|
{
|
||||||
|
outputMessage * message = peekOutputMessage(outputQueue);
|
||||||
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
|
{
|
||||||
|
messageSend(tlssessions[index], message->content);
|
||||||
|
}
|
||||||
|
dequeueOutputMessage(outputQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Constants.h: Contains configurable constants for SilverMUD.
|
||||||
|
// Barry Kane, 2022.
|
||||||
|
#ifndef CONSTANTS_H
|
||||||
|
#define CONSTANTS_H
|
||||||
|
#define PORT 5000
|
||||||
|
#define MAX 2048
|
||||||
|
#define PLAYERCOUNT 64
|
||||||
|
#define MAXQUEUELENGTH 2048
|
||||||
|
#endif
|
|
@ -1,33 +1,282 @@
|
||||||
// inputoutput.c: Implementation of input output library for SilverMUD.
|
// inputoutput.c: Implementation of input/output library for SilverMUD.
|
||||||
// Barry Kane, 2022.
|
// Barry Kane, 2022.
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "constants.h"
|
||||||
|
#include "playerdata.h"
|
||||||
#include "inputoutput.h"
|
#include "inputoutput.h"
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
// Sends a message to a given TLS session, wraps the calls to gnutls_write:
|
// Sends a message to a given TLS session, wraps the calls to gnutls_write:
|
||||||
void messageSend(gnutls_session_t receivingSession, userMessage * messageToSend)
|
int messageSend(gnutls_session_t receivingSession, userMessage * messageToSend)
|
||||||
{
|
{
|
||||||
int returnValue = 0;
|
int returnValue = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
returnValue = gnutls_record_send(receivingSession, messageToSend->senderName, sizeof(((userMessage*)0)->senderName));
|
returnValue = gnutls_record_send(receivingSession, messageToSend->senderName,
|
||||||
|
sizeof(((userMessage*)0)->senderName));
|
||||||
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
returnValue = gnutls_record_send(receivingSession, messageToSend->messageContent, sizeof(((userMessage*)0)->messageContent));
|
returnValue = gnutls_record_send(receivingSession, messageToSend->messageContent,
|
||||||
|
sizeof(((userMessage*)0)->messageContent));
|
||||||
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recieves a message from a given TLS session, wraps the calls to gnutls_read:
|
// Recieves a message from a given TLS session, wraps the calls to gnutls_read:
|
||||||
void messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToMessage)
|
int messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToMessage)
|
||||||
{
|
{
|
||||||
int returnValue = 0;
|
int returnValue = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
returnValue = gnutls_record_recv(receiveFromSession, receiveToMessage->senderName, sizeof(((userMessage*)0)->senderName));
|
returnValue = gnutls_record_recv(receiveFromSession, receiveToMessage->senderName,
|
||||||
|
sizeof(((userMessage*)0)->senderName));
|
||||||
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
returnValue = gnutls_record_recv(receiveFromSession, receiveToMessage->messageContent, sizeof(((userMessage*)0)->messageContent));
|
returnValue = gnutls_record_recv(receiveFromSession, receiveToMessage->messageContent,
|
||||||
|
sizeof(((userMessage*)0)->messageContent));
|
||||||
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputMessageQueue * createOutputMessageQueue(void)
|
||||||
|
{
|
||||||
|
outputMessageQueue * newQueue = malloc(sizeof(outputMessageQueue));
|
||||||
|
newQueue->front = NULL;
|
||||||
|
newQueue->back = NULL;
|
||||||
|
newQueue->currentLength = 0;
|
||||||
|
newQueue->lock = false;
|
||||||
|
return newQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int queueOutputMessage(outputMessageQueue * queue, userMessage messageToQueue)
|
||||||
|
{
|
||||||
|
// Copy the message into a new output message:
|
||||||
|
outputMessage * outputMessage = malloc(sizeof(outputMessage));
|
||||||
|
|
||||||
|
// Allocate the internal userMessage to store the message:
|
||||||
|
outputMessage->content = malloc(sizeof(userMessage));
|
||||||
|
|
||||||
|
// Copy the userMessage to the internal userMessage:
|
||||||
|
strncpy(outputMessage->content->senderName, messageToQueue.senderName, 32);
|
||||||
|
strncpy(outputMessage->content->messageContent, messageToQueue.messageContent, MAX);
|
||||||
|
|
||||||
|
// We have no targets, NULL sends to all players in an area:
|
||||||
|
outputMessage->targets[0] = NULL;
|
||||||
|
|
||||||
|
// Wait for the queue to unlock:
|
||||||
|
while (queue->lock);
|
||||||
|
|
||||||
|
// Lock the queue:
|
||||||
|
queue->lock = true;
|
||||||
|
|
||||||
|
// Check that we're not overflowing the queue:
|
||||||
|
if ((queue->currentLength + 1) > MAXQUEUELENGTH)
|
||||||
|
{
|
||||||
|
// Unlock the queue:
|
||||||
|
queue->lock = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the queue is empty, set the first message as both the front and back of the queue:
|
||||||
|
if(queue->front == NULL)
|
||||||
|
{
|
||||||
|
queue->front = outputMessage;
|
||||||
|
queue->back = outputMessage;
|
||||||
|
queue->currentLength++;
|
||||||
|
|
||||||
|
// Unlock the queue:
|
||||||
|
queue->lock = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queue->back->next = outputMessage;
|
||||||
|
queue->back = outputMessage;
|
||||||
|
queue->currentLength++;
|
||||||
|
|
||||||
|
// Unlock the queue:
|
||||||
|
queue->lock = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dequeueOutputMessage(outputMessageQueue * queue)
|
||||||
|
{
|
||||||
|
// Wait for the queue to unlock:
|
||||||
|
while (queue->lock);
|
||||||
|
|
||||||
|
// Lock the queue:
|
||||||
|
queue->lock = true;
|
||||||
|
|
||||||
|
// Check the list isn't empty:
|
||||||
|
if(queue->front == NULL)
|
||||||
|
{
|
||||||
|
queue->lock = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is only one item in the queue:
|
||||||
|
else if(queue->front == queue->back)
|
||||||
|
{
|
||||||
|
free(queue->front->content);
|
||||||
|
free(queue->front);
|
||||||
|
queue->front = NULL;
|
||||||
|
queue->back = NULL;
|
||||||
|
queue->currentLength--;
|
||||||
|
queue->lock = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the front item:
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputMessage * messageToDelete = queue->front;
|
||||||
|
queue->front = queue->front->next;
|
||||||
|
free(messageToDelete->content);
|
||||||
|
free(messageToDelete);
|
||||||
|
queue->currentLength--;
|
||||||
|
queue->lock = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inputMessageQueue * createInputMessageQueue(void)
|
||||||
|
{
|
||||||
|
inputMessageQueue * newQueue = malloc(sizeof(inputMessageQueue));
|
||||||
|
newQueue->front = NULL;
|
||||||
|
newQueue->back = NULL;
|
||||||
|
newQueue->currentLength = 0;
|
||||||
|
newQueue->lock = false;
|
||||||
|
return newQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dequeueInputMessage(inputMessageQueue * queue)
|
||||||
|
{
|
||||||
|
// Wait for the queue to unlock:
|
||||||
|
while (queue->lock);
|
||||||
|
|
||||||
|
// Lock the queue:
|
||||||
|
queue->lock = true;
|
||||||
|
|
||||||
|
// Check the list isn't empty:
|
||||||
|
if(queue->front == NULL)
|
||||||
|
{
|
||||||
|
queue->lock = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is only one item in the queue:
|
||||||
|
else if(queue->front == queue->back)
|
||||||
|
{
|
||||||
|
free(queue->front->content);
|
||||||
|
free(queue->front);
|
||||||
|
queue->front = NULL;
|
||||||
|
queue->back = NULL;
|
||||||
|
queue->currentLength--;
|
||||||
|
queue->lock = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the front item:
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inputMessage * messageToDelete = queue->front;
|
||||||
|
queue->front = queue->front->next;
|
||||||
|
free(messageToDelete->content);
|
||||||
|
free(messageToDelete);
|
||||||
|
queue->currentLength--;
|
||||||
|
queue->lock = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int queueInputMessage(inputMessageQueue * queue, userMessage messageToQueue, playerInfo * sendingPlayer)
|
||||||
|
{
|
||||||
|
// Copy the message into a new input message:
|
||||||
|
inputMessage * inputMessage = malloc(sizeof(inputMessage));
|
||||||
|
|
||||||
|
// Allocate the internal userMessage to store the message:
|
||||||
|
inputMessage->content = malloc(sizeof(userMessage));
|
||||||
|
|
||||||
|
// Copy the userMessage to the internal userMessage:
|
||||||
|
strncpy(inputMessage->content->senderName, messageToQueue.senderName, 32);
|
||||||
|
strncpy(inputMessage->content->messageContent, messageToQueue.messageContent, MAX);
|
||||||
|
|
||||||
|
// We have no targets, NULL sends to all players in an area:
|
||||||
|
inputMessage->sender = sendingPlayer;
|
||||||
|
|
||||||
|
// Wait for the queue to unlock:
|
||||||
|
while (queue->lock);
|
||||||
|
|
||||||
|
// Lock the queue:
|
||||||
|
queue->lock = true;
|
||||||
|
|
||||||
|
// Check that we're not overflowing the queue:
|
||||||
|
if ((queue->currentLength + 1) > MAXQUEUELENGTH)
|
||||||
|
{
|
||||||
|
// Unlock the queue:
|
||||||
|
queue->lock = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the queue is empty, set the first message as both the front and back of the queue:
|
||||||
|
if(queue->front == NULL)
|
||||||
|
{
|
||||||
|
queue->front = inputMessage;
|
||||||
|
queue->back = inputMessage;
|
||||||
|
queue->currentLength++;
|
||||||
|
|
||||||
|
// Unlock the queue:
|
||||||
|
queue->lock = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queue->back->next = inputMessage;
|
||||||
|
queue->back = inputMessage;
|
||||||
|
queue->currentLength++;
|
||||||
|
|
||||||
|
// Unlock the queue:
|
||||||
|
queue->lock = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void userInputSanatize(char * inputString, int length)
|
||||||
|
{
|
||||||
|
for(int index = 0; index <= length; index++)
|
||||||
|
{
|
||||||
|
if(!isprint(inputString[index]))
|
||||||
|
{
|
||||||
|
inputString[index] = '\n';
|
||||||
|
inputString[index + 1] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputString[length - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the front inputMessage from an inputMessageQueue:
|
||||||
|
inputMessage * peekInputMessage(inputMessageQueue * queue)
|
||||||
|
{
|
||||||
|
return queue->front;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputMessage * peekOutputMessage(outputMessageQueue * queue)
|
||||||
|
{
|
||||||
|
return queue->front;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,104 @@
|
||||||
// inputoutput.h: Header file contatning function prototypes and datastructures
|
// inputoutput.h: Header file contatning function prototypes and datastructures
|
||||||
// for dealing with input and output.
|
// for dealing with input and output.
|
||||||
// Barry Kane, 2022.
|
// Barry Kane, 2022.
|
||||||
#ifndef INPUTOUTPUt_H
|
#ifndef INPUTOUTPUT_H
|
||||||
#define INPUTOUTPUT_H
|
#define INPUTOUTPUT_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "constants.h"
|
||||||
|
#include "playerdata.h"
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
// A message datastructure containing a user/character name and the content:
|
// A message datastructure containing a user/character name and the content:
|
||||||
typedef struct userMessage
|
typedef struct userMessage
|
||||||
{
|
{
|
||||||
char senderName[32];
|
char senderName[32];
|
||||||
char messageContent[2048];
|
char messageContent[MAX];
|
||||||
} userMessage;
|
} userMessage;
|
||||||
|
|
||||||
// Sends a message to a given TLS session, wraps the calls to gnutls_write:
|
// =================
|
||||||
void messageSend(gnutls_session_t receivingSession, userMessage * messageToSend);
|
// -=[Message I/O]=-
|
||||||
|
// =================
|
||||||
|
|
||||||
// Recieves a message from a given TLS session, wraps the calls to gnutls_read:
|
// Sends a message to a given TLS session, wraps the calls to gnutls_write:
|
||||||
void messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToMessage);
|
int messageSend(gnutls_session_t receivingSession, userMessage * messageToSend);
|
||||||
|
|
||||||
|
// Receives a message from a given TLS session, wraps the calls to gnutls_read:
|
||||||
|
int messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToMessage);
|
||||||
|
|
||||||
|
// ===================
|
||||||
|
// -=[Output Queue]=-:
|
||||||
|
// ===================
|
||||||
|
typedef struct outputMessage outputMessage;
|
||||||
|
typedef struct outputMessage
|
||||||
|
{
|
||||||
|
outputMessage * next;
|
||||||
|
playerInfo * targets[PLAYERCOUNT];
|
||||||
|
userMessage * content;
|
||||||
|
} outputMessage;
|
||||||
|
|
||||||
|
// A first-in first-out queue for message output to players:
|
||||||
|
typedef struct outputMessageQueue
|
||||||
|
{
|
||||||
|
bool lock;
|
||||||
|
int currentLength;
|
||||||
|
outputMessage * back;
|
||||||
|
outputMessage * front;
|
||||||
|
} outputMessageQueue;
|
||||||
|
|
||||||
|
// Creates and initializes a outputMessageQueue:
|
||||||
|
outputMessageQueue * createOutputMessageQueue(void);
|
||||||
|
|
||||||
|
// Enqueue a userMessage to an outputMessageQueue:
|
||||||
|
int queueOutputMessage(outputMessageQueue * queue, userMessage messageToQueue);
|
||||||
|
// int queueOutputMessage(outputMessageQueue * queue, userMessage * messageToQueue,
|
||||||
|
// playerInfo * targets, int numberOfTargets);
|
||||||
|
|
||||||
|
// Dequeue the front outputMessage from an outputMessageQueue:
|
||||||
|
int dequeueOutputMessage(outputMessageQueue * queue);
|
||||||
|
|
||||||
|
// Return the front outputMessage from an outputMessageQueue:
|
||||||
|
outputMessage * peekOutputMessage(outputMessageQueue * queue);
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// -=[Input Queue]=-:
|
||||||
|
// ==================
|
||||||
|
typedef struct inputMessage inputMessage;
|
||||||
|
typedef struct inputMessage
|
||||||
|
{
|
||||||
|
inputMessage * next;
|
||||||
|
playerInfo * sender;
|
||||||
|
userMessage * content;
|
||||||
|
} inputMessage;
|
||||||
|
|
||||||
|
// A first-in first-out queue for message input from players:
|
||||||
|
typedef struct inputMessageQueue
|
||||||
|
{
|
||||||
|
bool lock;
|
||||||
|
int currentLength;
|
||||||
|
inputMessage * back;
|
||||||
|
inputMessage * front;
|
||||||
|
} inputMessageQueue;
|
||||||
|
|
||||||
|
// Create a inputMessageQueue:
|
||||||
|
inputMessageQueue * createInputMessageQueue(void);
|
||||||
|
|
||||||
|
// Enqueue a userMessage to an inputMessageQueue:
|
||||||
|
int queueInputMessage(inputMessageQueue * queue, userMessage messageToQueue, playerInfo * sendingPlayer);
|
||||||
|
|
||||||
|
// Dequeue the front inputMessage from an inputMessageQueue:
|
||||||
|
int dequeueInputMessage(inputMessageQueue * queue);
|
||||||
|
|
||||||
|
// Return the front inputMessage from an inputMessageQueue:
|
||||||
|
inputMessage * peekInputMessage(inputMessageQueue * queue);
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// -=[Input Sanitation]=-
|
||||||
|
// ======================
|
||||||
|
|
||||||
|
// Sanatize user input to ensure it's okay to send to the server:
|
||||||
|
void userInputSanatize(char * inputString, int length);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// playerdata.h: Header file containing data structures for player data and function
|
// playerdata.h: Header file containing data structures for player data and function
|
||||||
// prototypes for interacting with said data.
|
// prototypes for interacting with said data.
|
||||||
// Barry Kane, 2021.
|
|
||||||
#ifndef PLAYERDATA_H
|
#ifndef PLAYERDATA_H
|
||||||
#define PLAYERDATA_H
|
#define PLAYERDATA_H
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -33,7 +32,7 @@ int movePlayerToArea(playerInfo * player, char * requestedPath);
|
||||||
// Create an area given a name and description:
|
// Create an area given a name and description:
|
||||||
playerArea * createArea(char * nameString, char * descriptionString);
|
playerArea * createArea(char * nameString, char * descriptionString);
|
||||||
|
|
||||||
// Create a path between two areas given two areas and a string:
|
// Create a path between two areas given two areas and two strings:
|
||||||
int createPath(playerArea * fromArea, playerArea * toArea, char * pathFromString, char * pathToString);
|
int createPath(playerArea * fromArea, playerArea * toArea, char * fromDescription, char * toDescription);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include "../misc/inputoutput.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
userMessage A, B, C;
|
||||||
|
strncpy(A.senderName, "Bob\0", 32 -1);
|
||||||
|
strncpy(A.messageContent, "joins the fray!\0", MAX-1);
|
||||||
|
strncpy(B.senderName, "Alice\0", 32 -1);
|
||||||
|
strncpy(B.messageContent, "challenges the unknown!\0", MAX -1);
|
||||||
|
strncpy(C.senderName, "Tom\0", 32 -1);
|
||||||
|
strncpy(C.messageContent, "Attacks them all!\0", MAX -1);
|
||||||
|
outputMessageQueue * testQueue = createOutputMessageQueue();
|
||||||
|
printf("Queue Created.\n");
|
||||||
|
printf("%d", queueOutputMessage(testQueue, A));
|
||||||
|
printf("Queued A.\n");
|
||||||
|
printf("%d", queueOutputMessage(testQueue, B));
|
||||||
|
printf("Queued B.\n");
|
||||||
|
printf("%d", queueOutputMessage(testQueue, C));
|
||||||
|
printf("Queued C.\n");
|
||||||
|
printf("%s\n", testQueue->front->content->senderName);
|
||||||
|
printf("%s\n", testQueue->front->content->messageContent);
|
||||||
|
printf("%s\n", testQueue->front->next->content->senderName);
|
||||||
|
printf("%s\n", testQueue->front->next->content->messageContent);
|
||||||
|
printf("%s\n", testQueue->front->next->next->content->senderName);
|
||||||
|
printf("%s\n", testQueue->front->next->next->content->messageContent);
|
||||||
|
printf("%s\n", testQueue->front->content->senderName);
|
||||||
|
dequeueOutputMessage(testQueue);
|
||||||
|
printf("%s\n", testQueue->front->content->senderName);
|
||||||
|
dequeueOutputMessage(testQueue);
|
||||||
|
printf("%s\n", testQueue->front->content->senderName);
|
||||||
|
// dequeueOutputMessage(testQueue);
|
||||||
|
// printf("%s\n", testQueue->front->content->senderName);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue