Basic implementation of player lists and tying connections to players
This commit is contained in:
parent
5a53e9f197
commit
54b613befe
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "connections.h"
|
||||
|
||||
struct ClientConnectionNode * findMiddle(struct ClientConnectionNode * start, struct ClientConnectionNode * end)
|
||||
static struct ClientConnectionNode * findMiddle(struct ClientConnectionNode * start, struct ClientConnectionNode * end)
|
||||
{
|
||||
while (start != end)
|
||||
{
|
||||
|
|
|
@ -101,6 +101,9 @@ int main (int argc, char ** argv)
|
|||
|
||||
// Create a client connection list to allow us to associate TLS sessions and sockets and players:
|
||||
struct ClientConnectionList clientConnections;
|
||||
|
||||
// Create some structures needed to store global state:
|
||||
struct PlayerList * globalPlayerList = createPlayerList();
|
||||
|
||||
// Start a REPL thread:
|
||||
//pthread_t schemeREPLThread;
|
||||
|
@ -120,7 +123,7 @@ int main (int argc, char ** argv)
|
|||
}
|
||||
|
||||
for (int index = 0; index < eventsCount; index++)
|
||||
{
|
||||
{
|
||||
// If it's the master socket, it's a new client connecting:
|
||||
if (events[index].data.fd == masterSocket)
|
||||
{
|
||||
|
@ -134,7 +137,7 @@ int main (int argc, char ** argv)
|
|||
// Accept the connection:
|
||||
int newSocket = accept(masterSocket, NULL, NULL);
|
||||
gnutls_transport_set_int(*tlsSession, newSocket);
|
||||
|
||||
|
||||
// Perform a TLS handshake:
|
||||
int handshakeReturnValue = 0;
|
||||
do
|
||||
|
@ -142,7 +145,6 @@ int main (int argc, char ** argv)
|
|||
handshakeReturnValue = gnutls_handshake(*tlsSession);
|
||||
} while (handshakeReturnValue < 0 && gnutls_error_is_fatal(handshakeReturnValue) == 0);
|
||||
|
||||
|
||||
// If the handshake was unsuccessful, close the connection:
|
||||
if (handshakeReturnValue < 0)
|
||||
{
|
||||
|
@ -162,7 +164,9 @@ int main (int argc, char ** argv)
|
|||
// Add the connection to the list:
|
||||
struct ClientConnection * newConnection = addNewConnection(&clientConnections, newSocket, tlsSession);
|
||||
newConnection->player = createNewPlayer(newConnection);
|
||||
sprintf(newConnection->player->name, "Player %02d", clientConnections.clientCount);
|
||||
sprintf(newConnection->player->name, "Player %02d", globalPlayerList->count + 1);
|
||||
addToPlayerList(newConnection->player, globalPlayerList);
|
||||
|
||||
|
||||
// Print a message:
|
||||
printf("New connection established. %d client(s), session ID %u.\n",
|
||||
|
@ -175,18 +179,17 @@ int main (int argc, char ** argv)
|
|||
if (connection != NULL)
|
||||
{
|
||||
// Read the data from the TLS session:
|
||||
struct ClientToServerMessage message;
|
||||
int returnValue = gnutls_record_recv(*connection->tlsSession, &message, sizeof(struct ClientToServerMessage));
|
||||
struct ClientToServerMessage message;
|
||||
int returnValue = gnutls_record_recv(*connection->tlsSession, &message, sizeof(struct ClientToServerMessage));
|
||||
|
||||
if (returnValue == 0 || returnValue == -10)
|
||||
{
|
||||
printf("Closing session ID: %u.\n", *connection->tlsSession);
|
||||
epoll_ctl(connectedClients, EPOLL_CTL_DEL, connection->fileDescriptor, &watchedEvents);
|
||||
gnutls_bye(*connection->tlsSession, 2);
|
||||
shutdown(connection->fileDescriptor, 2);
|
||||
close(connection->fileDescriptor);
|
||||
deallocatePlayer(&connection->player);
|
||||
removeConnectionByFileDescriptor(&clientConnections, connection->fileDescriptor);
|
||||
close(connection->fileDescriptor);
|
||||
//deallocatePlayer(&connection->player);
|
||||
continue;
|
||||
}
|
||||
else if (returnValue == sizeof(struct ClientToServerMessage))
|
||||
{
|
||||
|
@ -231,6 +234,9 @@ int main (int argc, char ** argv)
|
|||
|
||||
// Wait for all other threads to terminate:
|
||||
//pthread_join(schemeREPLThread, NULL);
|
||||
|
||||
// Deallocate the global state structures:
|
||||
deallocatePlayerList(&globalPlayerList);
|
||||
|
||||
// Return a successful status code to the operating system:
|
||||
return 0;
|
||||
|
|
|
@ -3,9 +3,29 @@
|
|||
// | Copyright (C) 2023, Barra Ó Catháin |
|
||||
// | See end of file for copyright notice. |
|
||||
// =========================================
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "player-data.h"
|
||||
|
||||
// Internal Functions:
|
||||
// ===================
|
||||
static struct PlayerListNode * findMiddle(struct PlayerListNode * start, struct PlayerListNode * end)
|
||||
{
|
||||
while (start != end)
|
||||
{
|
||||
start = start->next;
|
||||
if(start == end)
|
||||
{
|
||||
return start;
|
||||
}
|
||||
end = end->previous;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
// ====================
|
||||
|
||||
// Allocates and sets up a new player according to the world's starter character sheet:
|
||||
struct Player * createNewPlayer(struct ClientConnection * connection)
|
||||
{
|
||||
|
@ -22,6 +42,152 @@ void deallocatePlayer(struct Player ** player)
|
|||
*player = NULL;
|
||||
}
|
||||
|
||||
struct PlayerList * createPlayerList()
|
||||
{
|
||||
struct PlayerList * newPlayerList = calloc(1, sizeof(struct PlayerList));
|
||||
newPlayerList->count = 0;
|
||||
newPlayerList->head = NULL;
|
||||
newPlayerList->tail = NULL;
|
||||
|
||||
return newPlayerList;
|
||||
}
|
||||
|
||||
void deallocatePlayerList(struct PlayerList ** playerList)
|
||||
{
|
||||
struct PlayerListNode * node = (*playerList)->head, * nextNode;
|
||||
|
||||
// Deallocate all nodes in the list:
|
||||
while (node != NULL)
|
||||
{
|
||||
nextNode = node->next;
|
||||
free(node);
|
||||
node = nextNode;
|
||||
}
|
||||
|
||||
// Deallocate the list itself:
|
||||
free(*playerList);
|
||||
|
||||
// Set the pointer to null:
|
||||
playerList = NULL;
|
||||
}
|
||||
|
||||
int addToPlayerList(struct Player * player, struct PlayerList * playerList)
|
||||
{
|
||||
// Check that the player isn't already in the list:
|
||||
if (isInPlayerList(player, playerList))
|
||||
{
|
||||
return playerList->count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a node to add to the list:
|
||||
struct PlayerListNode * newNode = calloc(1, sizeof(struct PlayerListNode));
|
||||
newNode->player = player;
|
||||
newNode->next = NULL;
|
||||
newNode->previous = NULL;
|
||||
|
||||
// Find the position that the new node is to go into:
|
||||
|
||||
// If the list is empty:
|
||||
if (playerList->count == 0)
|
||||
{
|
||||
playerList->head = newNode;
|
||||
playerList->tail = newNode;
|
||||
playerList->count = 1;
|
||||
return playerList->count;
|
||||
}
|
||||
|
||||
struct PlayerListNode * currentNode = playerList->head;
|
||||
while (strncmp(player->name, currentNode->player->name, 64) < 0)
|
||||
{
|
||||
// If we reach the end of the list:
|
||||
if (currentNode->next == NULL)
|
||||
{
|
||||
currentNode->next = newNode;
|
||||
newNode->previous = currentNode;
|
||||
playerList->tail = newNode;
|
||||
playerList->count++;
|
||||
|
||||
return playerList->count;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
currentNode = currentNode->next;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the appropriate pointers in the new node:
|
||||
newNode->previous = currentNode->previous;
|
||||
currentNode->previous = newNode;
|
||||
newNode->next = currentNode;
|
||||
|
||||
// Set the proper pointers if we're at the ends of the list:
|
||||
if (newNode->previous == NULL)
|
||||
{
|
||||
playerList->head = newNode;
|
||||
}
|
||||
if (newNode->next == NULL)
|
||||
{
|
||||
playerList->tail = newNode;
|
||||
}
|
||||
|
||||
playerList->count++;
|
||||
|
||||
return playerList->count;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the Player with the given name from a PlayerList, or NULL otherwise:
|
||||
struct Player * getFromPlayerList(char * playerName, struct PlayerList * playerList)
|
||||
{
|
||||
struct PlayerListNode * start = playerList->head, * end = playerList->tail, * middle = findMiddle(start, end);
|
||||
int returnValue = 0;
|
||||
|
||||
while (start != end)
|
||||
{
|
||||
returnValue = strncmp(middle->player->name, playerName, 64);
|
||||
|
||||
if (returnValue < 0)
|
||||
{
|
||||
start = middle->next;
|
||||
middle = findMiddle(start, end);
|
||||
}
|
||||
else if (returnValue > 0)
|
||||
{
|
||||
end = middle->next;
|
||||
middle = findMiddle(start, end);
|
||||
}
|
||||
else if (returnValue == 0)
|
||||
{
|
||||
return middle->player;
|
||||
}
|
||||
}
|
||||
if (strncmp(start->player->name, playerName, 64) == 0)
|
||||
{
|
||||
return start->player;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the given Player is in the given PlayerList:
|
||||
bool isInPlayerList(struct Player * player, struct PlayerList * playerList)
|
||||
{
|
||||
struct PlayerListNode * currentNode = playerList->head;
|
||||
while (currentNode != NULL)
|
||||
{
|
||||
if (currentNode->player == player)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
currentNode = currentNode->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===================================================
|
||||
// | End of player-data.c, copyright notice follows. |
|
||||
// ===================================================
|
||||
|
|
|
@ -5,20 +5,61 @@
|
|||
// =========================================
|
||||
#ifndef PLAYER_DATA_H
|
||||
#define PLAYER_DATA_H
|
||||
#include <stdbool.h>
|
||||
#include "connections.h"
|
||||
|
||||
// =================================================================
|
||||
// Players - A structure for representing a single player character:
|
||||
// =================================================================
|
||||
struct Player
|
||||
{
|
||||
struct ClientConnection * connection;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
// Functions:
|
||||
// ==========
|
||||
|
||||
// Allocates and sets up a new player according to the world's starter character sheet:
|
||||
struct Player * createNewPlayer(struct ClientConnection * connection);
|
||||
|
||||
// Deallocates a player:
|
||||
void deallocatePlayer(struct Player ** player);
|
||||
|
||||
// ========================================================================================
|
||||
// Player Lists - A structure for managing a collection of players in a doubly linked list:
|
||||
// ========================================================================================
|
||||
struct PlayerListNode
|
||||
{
|
||||
struct Player * player;
|
||||
struct PlayerListNode * next, * previous;
|
||||
};
|
||||
|
||||
struct PlayerList
|
||||
{
|
||||
size_t count;
|
||||
struct PlayerListNode * head, * tail;
|
||||
};
|
||||
|
||||
// Functions:
|
||||
// ==========
|
||||
|
||||
struct PlayerList * createPlayerList();
|
||||
void deallocatePlayerList(struct PlayerList ** playerList);
|
||||
|
||||
// Adds a Player into a PlayerList, in a sorted position by character name.
|
||||
// Returns the count of players in the list:
|
||||
int addToPlayerList(struct Player * player, struct PlayerList * playerList);
|
||||
|
||||
// Remove a Player from a PlayerList. Returns the count of players in the list:
|
||||
int removeFromPlayerList(struct Player * player, struct PlayerList * playerList);
|
||||
|
||||
// Returns the Player with the given name from a PlayerList, or NULL otherwise:
|
||||
struct Player * getFromPlayerList(char * playerName, struct PlayerList * playerList);
|
||||
|
||||
// Returns true if the given Player is in the given PlayerList:
|
||||
bool isInPlayerList(struct Player * player, struct PlayerList * playerList);
|
||||
|
||||
#endif
|
||||
// ===================================================
|
||||
// | End of player-data.h, copyright notice follows. |
|
||||
|
|
|
@ -5,23 +5,7 @@
|
|||
// ===========================================
|
||||
#include <libguile.h>
|
||||
|
||||
#include "scheme-integration.h"
|
||||
|
||||
// The function ran by the Scheme thread which runs a text-based REPL:
|
||||
void * schemeREPLHandler (void * threadParameters)
|
||||
{
|
||||
// Initialize Scheme:
|
||||
scm_init_guile();
|
||||
|
||||
// Enable Readline support:
|
||||
scm_c_eval_string("(begin (use-modules (ice-9 readline)) (activate-readline))");
|
||||
|
||||
// Start a Scheme REPL:
|
||||
scm_shell(0, NULL);
|
||||
|
||||
// Return NULL to the calling thread:
|
||||
return NULL;
|
||||
}
|
||||
SCM scheme_get_player_by_name(SCM name);
|
||||
|
||||
// ==========================================================
|
||||
// | End of scheme-integration.c, copyright notice follows. |
|
||||
|
|
|
@ -6,14 +6,8 @@
|
|||
#ifndef SCHEME_INTEGRATION_H
|
||||
#define SCHEME_INTEGRATION_H
|
||||
|
||||
struct SchemeThreadArguments
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// The function ran by the Scheme thread which initializes the REPL:
|
||||
void * schemeREPLHandler (void * threadParameters);
|
||||
|
||||
SCM scheme_get_player_by_name(SCM name);
|
||||
|
||||
#endif
|
||||
// ==========================================================
|
||||
// | End of scheme-integration.h, copyright notice follows. |
|
||||
|
|
Loading…
Reference in New Issue