Initial test implementation of output message queuing.

This commit is contained in:
Barra Ó Catháin 2023-11-07 11:52:20 +00:00 committed by Barry Kane
parent 6fc2e4d2b9
commit 89d520dc15
4 changed files with 220 additions and 19 deletions

View File

@ -8,7 +8,8 @@ SilverMUDServer_SOURCES = \
source/server/player-data.c \
source/server/connections.c \
source/server/scheme-integration.c \
source/server/main.c
source/server/output-queue.c \
source/server/main.c
SilverMUDClient_SOURCES = \
source/messages.c \

View File

@ -20,6 +20,7 @@
#include <netinet/in.h>
#include <gnutls/gnutls.h>
#include "output-queue.h"
#include "player-data.h"
#include "connections.h"
#include "../messages.h"
@ -199,7 +200,7 @@ int main (int argc, char ** argv)
// Create some structures needed to store global state:
struct PlayerList * globalPlayerList = createPlayerList();
struct OutputQueue * globalOutputQueue = createOutputQueue();
// Start a REPL thread:
//pthread_t schemeREPLThread;
//pthread_create(&schemeREPLThread, NULL, schemeREPLHandler, NULL);
@ -311,23 +312,10 @@ int main (int argc, char ** argv)
continue;
}
// ONLY FOR DEMO
struct ServerToClientMessage outputMessage;
// Copy the message to the output format:
outputMessage.type = LOCAL_CHAT;
strncpy(outputMessage.name, connection->player->name, 64);
strncpy(outputMessage.content, message.content, MESSAGE_CONTENT_LENGTH);
// Echo the message into all other clients: (Temporary)
struct ClientConnectionNode * currentClient = clientConnections.head;
while (currentClient != NULL)
{
gnutls_record_send(*currentClient->connection->tlsSession, &outputMessage,
sizeof(struct ServerToClientMessage));
currentClient = currentClient->next;
}
]
pushOutputMessage(globalOutputQueue, false, globalPlayerList, LOCAL_CHAT,
connection->player->name, message.content,
MESSAGE_NAME_LENGTH, MESSAGE_CONTENT_LENGTH);
}
}
else
@ -339,7 +327,29 @@ int main (int argc, char ** argv)
close(events[index].data.fd);
removeConnectionByFileDescriptor(&clientConnections, events[index].data.fd);
}
}
}
// Output the queue:
struct OutputMessage * currentMessage = NULL;
while (globalOutputQueue->count != 0)
{
currentMessage = popOutputMessage(globalOutputQueue);
struct PlayerListNode * currentPlayerNode = currentMessage->recepients->head;
while (currentPlayerNode != NULL)
{
gnutls_record_send(*currentPlayerNode->player->connection->tlsSession,
currentMessage->message, sizeof(struct ServerToClientMessage));
currentPlayerNode = currentPlayerNode->next;
}
if (currentMessage->deallocatePlayerList == true)
{
deallocatePlayerList(&currentMessage->recepients);
}
deallocateOutputMessage(&currentMessage);
}
}

View File

@ -0,0 +1,129 @@
// =========================================
// | SilverMUD Server - output-queue.c |
// | Copyright (C) 2023, Barra Ó Catháin |
// | See end of file for copyright notice. |
// =========================================
#include <string.h>
#include <stdbool.h>
#include <pthread.h>
#include "output-queue.h"
struct OutputQueue * const createOutputQueue()
{
// Allocate a new queue:
struct OutputQueue * const newQueue = calloc(1, sizeof(struct OutputQueue));
// Initialize it:
pthread_mutex_init(&newQueue->mutex, NULL);
newQueue->count = 0;
newQueue->front = NULL;
newQueue->back = NULL;
// Return the new queue:
return newQueue;
}
size_t pushOutputMessage(struct OutputQueue * const queue,
const bool deallocatePlayerList,
struct PlayerList * const recepients,
const enum MessageTypes type,
const char const * name, const char const * content,
const size_t nameLength, const size_t contentLength)
{
// Allocate the appropriate memory for the queued message:
struct OutputMessage * newMessage = calloc(1, sizeof(struct OutputMessage));
newMessage->message = calloc(1, sizeof(struct ServerToClientMessage));
// Copy in the appropriate values to the ServerToClientMessage:
newMessage->message->type = type;
strncpy(newMessage->message->name, name, (nameLength < MESSAGE_NAME_LENGTH) ?
nameLength : MESSAGE_NAME_LENGTH);
newMessage->message->name[MESSAGE_NAME_LENGTH - 1] = '\0';
strncpy(newMessage->message->content, content, (contentLength < MESSAGE_CONTENT_LENGTH) ?
contentLength : MESSAGE_CONTENT_LENGTH);
newMessage->message->content[MESSAGE_CONTENT_LENGTH - 1] = '\0';
// Copy in the appropriate values to the OutputMessage:
newMessage->deallocatePlayerList = deallocatePlayerList;
newMessage->recepients = recepients;
// Entering critical section - Lock the queue:
pthread_mutex_lock(&queue->mutex);
// Add it to the queue:
if (queue->back != NULL)
{
queue->back->next = newMessage;
queue->back = newMessage;
}
if (queue->front == NULL)
{
queue->front = newMessage;
queue->back = newMessage;
}
queue->count++;
// Leaving critical section - Unlock the queue:
pthread_mutex_unlock(&queue->mutex);
return queue->count;
}
struct OutputMessage * popOutputMessage(struct OutputQueue * queue)
{
if (queue->count == 0)
{
return NULL;
}
// Entering the critical section - Lock the queue:
pthread_mutex_lock(&queue->mutex);
struct OutputMessage * message = queue->front;
queue->count--;
if(queue->count == 0)
{
queue->front = NULL;
queue->back = NULL;
}
else
{
queue->front = queue->front->next;
}
// Leaving the critical section - Unlock the queue:
pthread_mutex_unlock(&queue->mutex);
return message;
}
void deallocateOutputMessage(struct OutputMessage ** message)
{
// Free and set the pointer to NULL:
free(*message);
message = NULL;
}
// ====================================================
// | End of output-queue.c, copyright notice follows. |
// ====================================================
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

View File

@ -0,0 +1,61 @@
// =========================================
// | SilverMUD Server - output-queue.h |
// | Copyright (C) 2023, Barra Ó Catháin |
// | See end of file for copyright notice. |
// =========================================
#ifndef OUTPUT_QUEUE_H
#define OUTPUT_QUEUE_H
#include <stdbool.h>
#include <pthread.h>
#include "../messages.h"
struct OutputMessage
{
// Allows for easy reuse of existing player lists, such as the global list
// or an area's playerlist:
bool deallocatePlayerList;
struct OutputMessage * next;
struct PlayerList * recepients;
struct ServerToClientMessage * message;
};
struct OutputQueue
{
pthread_mutex_t mutex;
size_t count;
struct OutputMessage * front, * back;
};
struct OutputQueue * const createOutputQueue();
size_t pushOutputMessage(struct OutputQueue * const queue,
const bool deallocatePlayerList,
struct PlayerList * const recepients,
const enum MessageTypes type,
const char const * name, const char const * content,
const size_t nameLength, const size_t contentLength);
struct OutputMessage * popOutputMessage();
void deallocateOutputMessage(struct OutputMessage ** message);
#endif
// ====================================================
// | End of output-queue.h, copyright notice follows. |
// ====================================================
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.