Added initial GnuTLS encryption.
- Added inputoutput.c - Added inputoutput.h - inputoutput contains wrapper and helper functions for transmitting messages over GnuTLS. - Moved the userMessage struct definition to inputoutput. - Reworked client and server to use GnuTLS. - Removed all commands from server in preperation for upcoming command and message queues. - Names and areas are no longer considered for messaging. - Changed Makefile to link GnuTLS.
This commit is contained in:
parent
235ff8e74f
commit
5d772df469
4
Makefile
4
Makefile
|
@ -5,8 +5,8 @@ clientobj = $(clientsrc:.c=.o)
|
||||||
serversrc = $(wildcard src/misc/*.c) \
|
serversrc = $(wildcard src/misc/*.c) \
|
||||||
src/SilverMUDServer.c
|
src/SilverMUDServer.c
|
||||||
serverobj = $(serversrc:.c=.o)
|
serverobj = $(serversrc:.c=.o)
|
||||||
CLIENTLDFLAGS= -lpthread -lncurses
|
CLIENTLDFLAGS= -lpthread -lncurses -lgnutls
|
||||||
SERVERLDFLAGS= -lncurses
|
SERVERLDFLAGS= -lncurses -lgnutls
|
||||||
SilverMUDClient: $(clientobj)
|
SilverMUDClient: $(clientobj)
|
||||||
gcc -s -O3 -o $@ $^ $(CLIENTLDFLAGS)
|
gcc -s -O3 -o $@ $^ $(CLIENTLDFLAGS)
|
||||||
|
|
||||||
|
|
|
@ -9,17 +9,19 @@
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
#include "misc/playerdata.h"
|
#include "misc/playerdata.h"
|
||||||
#include "misc/texteffects.h"
|
#include "misc/texteffects.h"
|
||||||
|
#include "misc/inputoutput.h"
|
||||||
#include "misc/inputhandling.h"
|
#include "misc/inputhandling.h"
|
||||||
#define MAX 2048
|
|
||||||
#define PORT 5000
|
#define PORT 5000
|
||||||
#define SA struct sockaddr
|
#define SA struct sockaddr
|
||||||
|
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
|
||||||
{
|
{
|
||||||
int socketDescriptor;
|
gnutls_session_t tlssession;
|
||||||
FILE * loggingstream;
|
FILE * loggingstream;
|
||||||
bool loggingflag;
|
bool loggingflag;
|
||||||
WINDOW * window;
|
WINDOW * window;
|
||||||
|
@ -32,28 +34,28 @@ void * messageSender(void * parameters)
|
||||||
{
|
{
|
||||||
// Takes user input in a window, sanatizes it, and sends it to the server:
|
// Takes user input in a window, sanatizes it, and sends it to the server:
|
||||||
struct threadparameters *threadParameters = parameters;
|
struct threadparameters *threadParameters = parameters;
|
||||||
char sendBuffer[MAX];
|
userMessage sendBuffer;
|
||||||
|
|
||||||
while (!shouldExit)
|
while (!shouldExit)
|
||||||
{
|
{
|
||||||
bzero(sendBuffer, MAX);
|
|
||||||
wprintw(threadParameters->window, "\n\n\nCOMM-LINK> ");
|
wprintw(threadParameters->window, "\n\n\nCOMM-LINK> ");
|
||||||
if(wgetnstr(threadParameters->window, sendBuffer, MAX) == ERR)
|
if(wgetnstr(threadParameters->window, sendBuffer.messageContent, MAX) == ERR)
|
||||||
{
|
{
|
||||||
// Quit if there's any funny business with getting input:
|
// Quit if there's any funny business with getting input:
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
if(sendBuffer[0] == '\n')
|
if(sendBuffer.messageContent[0] == '\n')
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(threadParameters->loggingflag == true)
|
if(threadParameters->loggingflag == true)
|
||||||
{
|
{
|
||||||
fputs(sendBuffer, threadParameters->loggingstream);
|
fputs(sendBuffer.messageContent, threadParameters->loggingstream);
|
||||||
fputs("\n", threadParameters->loggingstream);
|
fputs("\n", threadParameters->loggingstream);
|
||||||
fflush(threadParameters->loggingstream);
|
fflush(threadParameters->loggingstream);
|
||||||
}
|
}
|
||||||
write(threadParameters->socketDescriptor, sendBuffer, MAX);
|
wprintw(threadParameters->window, sendBuffer.messageContent);
|
||||||
|
messageSend(threadParameters->tlssession, &sendBuffer);
|
||||||
}
|
}
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
@ -66,15 +68,14 @@ void * messageReceiver(void * parameters)
|
||||||
userMessage receiveBuffer;
|
userMessage receiveBuffer;
|
||||||
while (!shouldExit)
|
while (!shouldExit)
|
||||||
{
|
{
|
||||||
read(threadParameters->socketDescriptor, &receiveBuffer.senderName, sizeof(receiveBuffer.senderName));
|
messageReceive(threadParameters->tlssession, &receiveBuffer);
|
||||||
read(threadParameters->socketDescriptor, &receiveBuffer.messageContent, sizeof(receiveBuffer.messageContent));
|
|
||||||
if(receiveBuffer.senderName[0] == '\0')
|
if(receiveBuffer.senderName[0] == '\0')
|
||||||
{
|
{
|
||||||
if(receiveBuffer.messageContent[0] == '\0')
|
//if(receiveBuffer.messageContent[0] == '\0')
|
||||||
{
|
//{
|
||||||
shouldExit = true;
|
// shouldExit = true;
|
||||||
pthread_exit(NULL);
|
// pthread_exit(NULL);
|
||||||
}
|
//}
|
||||||
slowPrintNcurses("\n --====<>====-- \n", 8000, threadParameters->window);
|
slowPrintNcurses("\n --====<>====-- \n", 8000, threadParameters->window);
|
||||||
slowPrintNcurses(receiveBuffer.messageContent, 8000, threadParameters->window);
|
slowPrintNcurses(receiveBuffer.messageContent, 8000, threadParameters->window);
|
||||||
slowPrintNcurses("\n --====<>====-- \n", 8000, threadParameters->window);
|
slowPrintNcurses("\n --====<>====-- \n", 8000, threadParameters->window);
|
||||||
|
@ -92,9 +93,6 @@ void * messageReceiver(void * parameters)
|
||||||
slowPrintNcurses(": ", 8000, threadParameters->window);
|
slowPrintNcurses(": ", 8000, threadParameters->window);
|
||||||
slowPrintNcurses(receiveBuffer.messageContent, 8000, threadParameters->window);
|
slowPrintNcurses(receiveBuffer.messageContent, 8000, threadParameters->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(receiveBuffer.senderName, sizeof(receiveBuffer.senderName));
|
|
||||||
bzero(receiveBuffer.messageContent, sizeof(receiveBuffer.messageContent));
|
|
||||||
}
|
}
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
@ -191,8 +189,31 @@ int main(int argc, char **argv)
|
||||||
slowPrint("Connected to the Silverkin Industries Comm-Link Server:\nHave a pleasant day.\n", 8000);
|
slowPrint("Connected to the Silverkin Industries Comm-Link Server:\nHave a pleasant day.\n", 8000);
|
||||||
}
|
}
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
|
|
||||||
// Setup Ncurses:
|
/* TODO: Negotiate TLS
|
||||||
|
Need to pull in GNU TLS, and do the same on the server-side. */
|
||||||
|
// Setup a GnuTLS session and initialize it:
|
||||||
|
gnutls_session_t tlssession = NULL;
|
||||||
|
if(gnutls_init(&tlssession, GNUTLS_CLIENT) < 0)
|
||||||
|
{
|
||||||
|
// Failure Case
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
gnutls_anon_client_credentials_t clientkey = NULL;
|
||||||
|
gnutls_anon_allocate_client_credentials(&clientkey);
|
||||||
|
gnutls_credentials_set(tlssession, GNUTLS_CRD_ANON, &clientkey);
|
||||||
|
/* Bind the open socket to the TLS session. */
|
||||||
|
gnutls_transport_set_int(tlssession, sockfd);
|
||||||
|
gnutls_priority_set_direct(tlssession, "PERFORMANCE:+ANON-ECDH:+ANON-DH", NULL);
|
||||||
|
|
||||||
|
/* Set default timeout for the handshake. */
|
||||||
|
gnutls_handshake_set_timeout(tlssession, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
|
||||||
|
int r = -1;
|
||||||
|
do {
|
||||||
|
r = gnutls_handshake(tlssession);
|
||||||
|
} while (r < 0 && gnutls_error_is_fatal(r) == 0);
|
||||||
|
|
||||||
|
// Setup Ncurses:
|
||||||
initscr();
|
initscr();
|
||||||
|
|
||||||
// Create two pointers to structs to pass arguments to the threads:
|
// Create two pointers to structs to pass arguments to the threads:
|
||||||
|
@ -204,14 +225,14 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
// Make the windows for the structs, and pass the socket descriptor:
|
// Make the windows for the structs, and pass the socket descriptor:
|
||||||
logArea->window = newwin(LINES - 5, COLS - 2, 1, 1);
|
logArea->window = newwin(LINES - 5, COLS - 2, 1, 1);
|
||||||
logArea->socketDescriptor = sockfd;
|
logArea->tlssession = tlssession;
|
||||||
logArea->loggingflag = chatlogging;
|
logArea->loggingflag = chatlogging;
|
||||||
if(chatlog != NULL)
|
if(chatlog != NULL)
|
||||||
{
|
{
|
||||||
logArea->loggingstream = chatlog;
|
logArea->loggingstream = chatlog;
|
||||||
}
|
}
|
||||||
messageArea->window = newwin(3, COLS, LINES - 3, 0);
|
messageArea->window = newwin(3, COLS, LINES - 3, 0);
|
||||||
messageArea->socketDescriptor = sockfd;
|
messageArea->tlssession = tlssession;
|
||||||
messageArea->loggingflag = gamelogging;
|
messageArea->loggingflag = gamelogging;
|
||||||
if(gamelog != NULL)
|
if(gamelog != NULL)
|
||||||
{
|
{
|
||||||
|
@ -244,7 +265,7 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
fclose(gamelog);
|
fclose(gamelog);
|
||||||
}
|
}
|
||||||
if(chatlog != NULL)
|
if(chatlog != NULL)
|
||||||
{
|
{
|
||||||
fclose(chatlog);
|
fclose(chatlog);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,25 +12,29 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
#include "misc/lists.h"
|
#include "misc/lists.h"
|
||||||
#include "misc/playerdata.h"
|
#include "misc/playerdata.h"
|
||||||
#include "misc/texteffects.h"
|
#include "misc/texteffects.h"
|
||||||
|
#include "misc/inputoutput.h"
|
||||||
#include "misc/inputhandling.h"
|
#include "misc/inputhandling.h"
|
||||||
|
|
||||||
const int PORT = 5000;
|
const int PORT = 5000;
|
||||||
|
const int PLAYERCOUNT = 64;
|
||||||
typedef struct sockaddr sockaddr;
|
typedef struct sockaddr sockaddr;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
bool keepRunning = true;
|
||||||
int socketFileDesc, connectionFileDesc, length, clientsAmount,
|
int socketFileDesc, connectionFileDesc, length, clientsAmount,
|
||||||
socketCheck, activityCheck, readLength;
|
socketCheck, activityCheck, readLength, returnVal;
|
||||||
int clientSockets[64];
|
|
||||||
int maxClients = 64;
|
|
||||||
userMessage messageBuffer;
|
|
||||||
char receiveBuffer[2048];
|
|
||||||
fd_set connectedClients;
|
fd_set connectedClients;
|
||||||
playerInfo connectedPlayers[64];
|
int clientSockets[PLAYERCOUNT];
|
||||||
|
userMessage sendBuffer, receiveBuffer;
|
||||||
|
playerInfo connectedPlayers[PLAYERCOUNT];
|
||||||
|
char testString[32] = "Hehe.";
|
||||||
struct sockaddr_in serverAddress, clientAddress;
|
struct sockaddr_in serverAddress, clientAddress;
|
||||||
|
|
||||||
// Initialize areas:
|
// Initialize areas:
|
||||||
areaNode * areas = createAreaList(createArea("Spawn - North", "A large area, mostly empty, as if the designer hadn't bothered to put anything in it, just yet."));
|
areaNode * areas = createAreaList(createArea("Spawn - North", "A large area, mostly empty, as if the designer hadn't bothered to put anything in it, just yet."));
|
||||||
addAreaNodeToList(areas, createArea("Spawn - South", "A strange, white void. You feel rather uncomfortable."));
|
addAreaNodeToList(areas, createArea("Spawn - South", "A strange, white void. You feel rather uncomfortable."));
|
||||||
|
@ -39,7 +43,7 @@ int main()
|
||||||
createPath(getAreaFromList(areas, 2), getAreaFromList(areas, 1), "Back to South Spawn", "Path to Enlightenment.");
|
createPath(getAreaFromList(areas, 2), getAreaFromList(areas, 1), "Back to South Spawn", "Path to Enlightenment.");
|
||||||
|
|
||||||
// Initialize playerdata:
|
// Initialize playerdata:
|
||||||
for (int index = 0; index < maxClients; index++)
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
{
|
{
|
||||||
strcpy(connectedPlayers[index].playerName, "UNNAMED");
|
strcpy(connectedPlayers[index].playerName, "UNNAMED");
|
||||||
connectedPlayers[index].currentArea = getAreaFromList(areas, 0);
|
connectedPlayers[index].currentArea = getAreaFromList(areas, 0);
|
||||||
|
@ -50,7 +54,7 @@ int main()
|
||||||
slowPrint("\n--==== \033[33;40mSILVERKIN INDUSTRIES\033[0m COMM-LINK SERVER ====--\nVersion Alpha 0.3\n", 5000);
|
slowPrint("\n--==== \033[33;40mSILVERKIN INDUSTRIES\033[0m COMM-LINK SERVER ====--\nVersion Alpha 0.3\n", 5000);
|
||||||
|
|
||||||
// Initialize the sockets to 0, so we don't crash.
|
// Initialize the sockets to 0, so we don't crash.
|
||||||
for (int index = 0; index < maxClients; index++)
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
{
|
{
|
||||||
clientSockets[index] = 0;
|
clientSockets[index] = 0;
|
||||||
}
|
}
|
||||||
|
@ -59,13 +63,13 @@ int main()
|
||||||
socketFileDesc = socket(AF_INET, SOCK_STREAM, 0);
|
socketFileDesc = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (socketFileDesc == -1)
|
if (socketFileDesc == -1)
|
||||||
{
|
{
|
||||||
perror("Socket creation is \033[33;40mRED.\033[0m Aborting launch.\n");
|
perror("\tSocket Creation is:\t\033[33;40mRED.\033[0m Aborting launch.\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slowPrint(" Socket creation is \033[32;40mGREEN.\033[0m\n", 5000);
|
slowPrint("\tSocket Creation is:\t\033[32;40mGREEN.\033[0m\n", 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(&serverAddress, sizeof(serverAddress));
|
bzero(&serverAddress, sizeof(serverAddress));
|
||||||
|
@ -78,37 +82,59 @@ int main()
|
||||||
// Binding newly created socket to given IP, and checking it works:
|
// Binding newly created socket to given IP, and checking it works:
|
||||||
if ((bind(socketFileDesc, (sockaddr*)&serverAddress, sizeof(serverAddress))) != 0)
|
if ((bind(socketFileDesc, (sockaddr*)&serverAddress, sizeof(serverAddress))) != 0)
|
||||||
{
|
{
|
||||||
perror("Socket binding is \033[33;40mRED.\033[0m Aborting launch.\n");
|
perror("\tSocket Binding is:\t\033[33;40mRED.\033[0m Aborting launch.\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slowPrint(" Socket binding is \033[32;40mGREEN.\033[0m\n", 5000);
|
slowPrint("\tSocket Binding is:\t\033[32;40mGREEN.\033[0m\n", 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's start listening:
|
// Let's start listening:
|
||||||
if ((listen(socketFileDesc, 64)) != 0)
|
if ((listen(socketFileDesc, PLAYERCOUNT)) != 0)
|
||||||
{
|
{
|
||||||
perror("Server listening is \033[33;40mRED.\033[0m Aborting launch.\n");
|
perror("\tServer Listening is:\t\033[33;40mRED.\033[0m Aborting launch.\n");
|
||||||
exit(0);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slowPrint(" Server listening is \033[32;40mGREEN.\033[0m\n", 5000);
|
slowPrint("\tServer Listening is:\t\033[32;40mGREEN.\033[0m\n", 5000);
|
||||||
}
|
}
|
||||||
length = sizeof(clientAddress);
|
length = sizeof(clientAddress);
|
||||||
|
|
||||||
// Accept the data packet from client and verify it:
|
gnutls_session_t tlssessions[PLAYERCOUNT];
|
||||||
while (1)
|
gnutls_anon_server_credentials_t serverkey = NULL;
|
||||||
|
gnutls_anon_allocate_server_credentials(&serverkey);
|
||||||
|
gnutls_anon_set_server_known_dh_params(serverkey, GNUTLS_SEC_PARAM_MEDIUM);
|
||||||
|
|
||||||
|
// Initialize all the TLS Sessions to NULL: We use this to check if it's an "empty connection."
|
||||||
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
|
{
|
||||||
|
tlssessions[index] = NULL;
|
||||||
|
if (gnutls_init(&tlssessions[index], GNUTLS_SERVER) < 0)
|
||||||
|
{
|
||||||
|
perror("\tTLS Sessions Initialization is:\t\033[33;40mRED.\033[0m Aborting launch.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
slowPrint("\tTLS Sessions Initialization is:\t\033[32;40mGREEN.\033[0m\n", 5000);
|
||||||
|
|
||||||
|
while(keepRunning)
|
||||||
{
|
{
|
||||||
|
// Clear the set of file descriptors and add the master socket:
|
||||||
FD_ZERO(&connectedClients);
|
FD_ZERO(&connectedClients);
|
||||||
FD_SET(socketFileDesc, &connectedClients);
|
FD_SET(socketFileDesc, &connectedClients);
|
||||||
clientsAmount = socketFileDesc;
|
clientsAmount = socketFileDesc;
|
||||||
bzero(receiveBuffer, sizeof(receiveBuffer));
|
|
||||||
for (int i = 0; i < maxClients; i++)
|
// Find all sockets that are still working and place them in the set:
|
||||||
{
|
for(int index = 0; index < PLAYERCOUNT; index++)
|
||||||
|
{
|
||||||
// Just get the one we're working with to another name:
|
// Just get the one we're working with to another name:
|
||||||
socketCheck = clientSockets[i];
|
socketCheck = clientSockets[index];
|
||||||
|
|
||||||
// If it's working, bang it into the list:
|
// If it's working, bang it into the list:
|
||||||
if(socketCheck > 0)
|
if(socketCheck > 0)
|
||||||
|
@ -134,165 +160,81 @@ int main()
|
||||||
// If it's the master socket selected, there is a new connection:
|
// If it's the master socket selected, there is a new connection:
|
||||||
if (FD_ISSET(socketFileDesc, &connectedClients))
|
if (FD_ISSET(socketFileDesc, &connectedClients))
|
||||||
{
|
{
|
||||||
if ((connectionFileDesc = accept(socketFileDesc, (struct sockaddr *)&clientAddress, (socklen_t*)&length))<0)
|
if ((connectionFileDesc = accept(socketFileDesc, (struct sockaddr *)&clientAddress, (socklen_t*)&length)) < 0)
|
||||||
{
|
{
|
||||||
perror("Failed to accept connection. Aborting.\n");
|
perror("Failed to accept connection. Aborting.\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print new connection details:
|
|
||||||
printf("Client connected: Socket file descriptor: #%d, IP address: %s, Port: %d.\n",
|
|
||||||
connectionFileDesc, inet_ntoa(clientAddress.sin_addr) , ntohs
|
|
||||||
(clientAddress.sin_port));
|
|
||||||
|
|
||||||
// See if we can put in the client:
|
// See if we can put in the client:
|
||||||
for (int i = 0; i < maxClients; i++)
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
{
|
{
|
||||||
// When there is an empty slot, pop it in:
|
// When there is an empty slot, pop it in:
|
||||||
if( clientSockets[i] == 0 )
|
if (clientSockets[index] == 0)
|
||||||
{
|
{
|
||||||
clientSockets[i] = connectionFileDesc;
|
clientSockets[index] = connectionFileDesc;
|
||||||
printf("Adding to list of sockets as %d.\n" , i);
|
printf("Adding to list of sockets as %d.\n", index);
|
||||||
|
gnutls_transport_set_int(tlssessions[index], clientSockets[index]);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
returnVal = gnutls_handshake(tlssessions[index]);
|
||||||
|
}
|
||||||
|
while (returnVal < 0 && gnutls_error_is_fatal(returnVal) == 0);
|
||||||
|
strcpy(sendBuffer.senderName, "");
|
||||||
|
strcpy(sendBuffer.messageContent, "Welcome to the server!");
|
||||||
|
messageSend(tlssessions[index], &sendBuffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Otherwise, it's a client we need to interact with:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Otherwise, it's a client socket to be interacted with:
|
for (int index = 0; index < PLAYERCOUNT; index++)
|
||||||
for (int i = 0; i < maxClients; i++)
|
|
||||||
{
|
{
|
||||||
socketCheck = clientSockets[i];
|
socketCheck = clientSockets[index];
|
||||||
|
|
||||||
if (FD_ISSET(socketCheck, &connectedClients))
|
if(FD_ISSET(socketCheck, &connectedClients))
|
||||||
{
|
{
|
||||||
//Check if it was for closing, and also read the incoming message
|
messageReceive(tlssessions[index], &receiveBuffer);
|
||||||
explicit_bzero(receiveBuffer, sizeof(receiveBuffer));
|
sprintf(testString, "User %d", index);
|
||||||
readLength = read(socketCheck, receiveBuffer, sizeof(receiveBuffer));
|
strcpy(sendBuffer.senderName, testString);
|
||||||
userInputSanatize(receiveBuffer, 2048);
|
userInputSanatize(receiveBuffer.messageContent, sizeof(receiveBuffer.messageContent));
|
||||||
if (readLength == 0)
|
strcpy(sendBuffer.messageContent, receiveBuffer.messageContent);
|
||||||
|
for (int sendIndex = 0; sendIndex < clientsAmount; sendIndex++)
|
||||||
{
|
{
|
||||||
// Somebody disconnected , get his details and print:
|
messageSend(tlssessions[sendIndex], &sendBuffer);
|
||||||
getpeername(socketCheck, (struct sockaddr*)&clientAddress, (socklen_t*)&length);
|
|
||||||
printf("Client disconnected: IP Address: %s, Port: %d.\n",
|
|
||||||
inet_ntoa(clientAddress.sin_addr) , ntohs(clientAddress.sin_port));
|
|
||||||
|
|
||||||
// Close the socket and mark as 0 in list for reuse:
|
|
||||||
close(socketCheck);
|
|
||||||
clientSockets[i] = 0;
|
|
||||||
}
|
}
|
||||||
// Name change command: Move logic to a command interpreter later:
|
}
|
||||||
else if (receiveBuffer[0] == '/')
|
|
||||||
{
|
|
||||||
if(strncmp(receiveBuffer, "/NAME", 5) == 0)
|
|
||||||
{
|
|
||||||
char newName[32];
|
|
||||||
strncpy(newName, &receiveBuffer[6], 32);
|
|
||||||
// Remove newlines:
|
|
||||||
for (int index = 0; index < 32; index++)
|
|
||||||
{
|
|
||||||
if (newName[index] == '\n')
|
|
||||||
{
|
|
||||||
newName[index] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int index = 0; index < maxClients; index++)
|
|
||||||
{
|
|
||||||
if(strncmp(newName, connectedPlayers[index].playerName, 32) == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(newName[0] != '\0')
|
|
||||||
{
|
|
||||||
strncpy(connectedPlayers[i].playerName, newName, 32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(strncmp(receiveBuffer, "/EXIT", 5) == 0)
|
|
||||||
{
|
|
||||||
strcpy(messageBuffer.senderName, "\0");
|
|
||||||
strcpy(messageBuffer.messageContent, "\0");
|
|
||||||
write(socketCheck, messageBuffer.senderName, sizeof(messageBuffer.senderName));
|
|
||||||
write(socketCheck, messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
|
|
||||||
printf("Client disconnected: IP Address: %s, Port: %d.\n",
|
|
||||||
inet_ntoa(clientAddress.sin_addr) , ntohs(clientAddress.sin_port));
|
|
||||||
|
|
||||||
close(socketCheck);
|
|
||||||
clientSockets[i] = 0;
|
|
||||||
}
|
|
||||||
else if(strncmp(receiveBuffer, "/LOOK", 5) == 0)
|
|
||||||
{
|
|
||||||
strcat(messageBuffer.messageContent, connectedPlayers[i].currentArea->areaDescription);
|
|
||||||
strcat(messageBuffer.messageContent, "\nYou see:");
|
|
||||||
for(int index = 0; index < 16; index++)
|
|
||||||
{
|
|
||||||
if(connectedPlayers[i].currentArea->areaExits[index] != NULL)
|
|
||||||
{
|
|
||||||
strcat(messageBuffer.messageContent, "\n - ");
|
|
||||||
strcat(messageBuffer.messageContent, connectedPlayers[i].currentArea->areaExits[index]->pathName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write(socketCheck, messageBuffer.senderName, sizeof(messageBuffer.senderName));
|
|
||||||
write(socketCheck, messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
|
|
||||||
bzero(messageBuffer.senderName, sizeof(messageBuffer.senderName));
|
|
||||||
bzero(messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
|
|
||||||
}
|
|
||||||
else if(strncmp(receiveBuffer, "/MOVE", 5) == 0)
|
|
||||||
{
|
|
||||||
char requestedPath[32];
|
|
||||||
strncpy(requestedPath, &receiveBuffer[6], 32);
|
|
||||||
userInputSanatize(requestedPath, 32);
|
|
||||||
// Remove newlines:
|
|
||||||
for (int index = 0; index < 32; index++)
|
|
||||||
{
|
|
||||||
if (requestedPath[index] == '\n')
|
|
||||||
{
|
|
||||||
requestedPath[index] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
requestedPath[31] = '\0';
|
|
||||||
if(movePlayerToArea(&connectedPlayers[i], requestedPath) == 0)
|
|
||||||
{
|
|
||||||
strcpy(messageBuffer.senderName, "\0");
|
|
||||||
strcpy(messageBuffer.messageContent, connectedPlayers[i].currentArea->areaDescription);
|
|
||||||
write(socketCheck, messageBuffer.senderName, sizeof(messageBuffer.senderName));
|
|
||||||
write(socketCheck, messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strcpy(messageBuffer.senderName, "");
|
|
||||||
strcpy(messageBuffer.messageContent, "You can't go somewhere that doesn't exist!");
|
|
||||||
write(socketCheck, messageBuffer.senderName, sizeof(messageBuffer.senderName));
|
|
||||||
write(socketCheck, messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
|
|
||||||
bzero(messageBuffer.senderName, sizeof(messageBuffer.senderName));
|
|
||||||
bzero(messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Echo back the message that came in:
|
|
||||||
else if (receiveBuffer[0] == '\n')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("%d/%s/%s: %s", clientSockets[i], connectedPlayers[i].currentArea->areaName, connectedPlayers[i].playerName, receiveBuffer);
|
|
||||||
fflush(stdout);
|
|
||||||
strcpy(messageBuffer.senderName, connectedPlayers[i].playerName);
|
|
||||||
strcpy(messageBuffer.messageContent, receiveBuffer);
|
|
||||||
for (int sendIndex = 0; sendIndex < clientsAmount; sendIndex++)
|
|
||||||
{
|
|
||||||
if(clientSockets[sendIndex] != STDIN_FILENO && (connectedPlayers[i].currentArea == connectedPlayers[sendIndex].currentArea))
|
|
||||||
{
|
|
||||||
write(clientSockets[sendIndex], messageBuffer.senderName, sizeof(messageBuffer.senderName));
|
|
||||||
write(clientSockets[sendIndex], messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bzero(messageBuffer.senderName, sizeof(messageBuffer.senderName));
|
|
||||||
bzero(messageBuffer.messageContent, sizeof(messageBuffer.messageContent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* // TODO: Implement the ability to connect clients, and pass messages to the relevant queues. */
|
||||||
|
/* // Check if there's a new client by checking the master socket: */
|
||||||
|
/* connectionFileDesc = accept(socketFileDesc,(struct sockaddr *)&clientAddress, (socklen_t*)&length); */
|
||||||
|
/* gnutls_transport_set_int(tlssessions[0], connectionFileDesc); */
|
||||||
|
/* int returnVal = -1; */
|
||||||
|
/* do */
|
||||||
|
/* { */
|
||||||
|
/* returnVal = gnutls_handshake(tlssessions[0]); */
|
||||||
|
/* } */
|
||||||
|
/* while (returnVal < 0 && gnutls_error_is_fatal(returnVal) == 0); */
|
||||||
|
|
||||||
|
/* if (returnVal < 0) */
|
||||||
|
/* { */
|
||||||
|
/* fprintf(stderr, "*** Handshake has failed (%s)\n\n", gnutls_strerror(returnVal)); */
|
||||||
|
/* } */
|
||||||
|
/* strcpy(sendBuffer.senderName, "Test"); */
|
||||||
|
/* strcpy(sendBuffer.messageContent, "GnuTLS, baybee!\n"); */
|
||||||
|
|
||||||
|
/* messageSend(tlssessions[0], &sendBuffer); */
|
||||||
|
/* while(true) */
|
||||||
|
/* { */
|
||||||
|
/* messageReceive(tlssessions[0], &receiveBuffer); */
|
||||||
|
/* userInputSanatize(receiveBuffer.messageContent, 2048); */
|
||||||
|
/* strcpy(sendBuffer.messageContent, receiveBuffer.messageContent); */
|
||||||
|
/* messageSend(tlssessions[0], &sendBuffer); */
|
||||||
|
/* } */
|
||||||
|
/* gnutls_bye(tlssessions[0], GNUTLS_SHUT_RDWR); */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// inputoutput.c: Implementation of input output library for SilverMUD.
|
||||||
|
// Barry Kane, 2022.
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "inputoutput.h"
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
// Sends a message to a given TLS session, wraps the calls to gnutls_write:
|
||||||
|
void messageSend(gnutls_session_t receivingSession, userMessage * messageToSend)
|
||||||
|
{
|
||||||
|
int returnValue = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
returnValue = gnutls_record_send(receivingSession, messageToSend->senderName, sizeof(((userMessage*)0)->senderName));
|
||||||
|
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
returnValue = gnutls_record_send(receivingSession, messageToSend->messageContent, sizeof(((userMessage*)0)->messageContent));
|
||||||
|
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recieves a message from a given TLS session, wraps the calls to gnutls_read:
|
||||||
|
void messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToMessage)
|
||||||
|
{
|
||||||
|
int returnValue = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
returnValue = gnutls_record_recv(receiveFromSession, receiveToMessage->senderName, sizeof(((userMessage*)0)->senderName));
|
||||||
|
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
returnValue = gnutls_record_recv(receiveFromSession, receiveToMessage->messageContent, sizeof(((userMessage*)0)->messageContent));
|
||||||
|
} while (returnValue == GNUTLS_E_AGAIN || returnValue == GNUTLS_E_INTERRUPTED);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
// inputoutput.h: Header file contatning function prototypes and datastructures
|
||||||
|
// for dealing with input and output.
|
||||||
|
// Barry Kane, 2022.
|
||||||
|
#ifndef INPUTOUTPUt_H
|
||||||
|
#define INPUTOUTPUT_H
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
// A message datastructure containing a user/character name and the content:
|
||||||
|
typedef struct userMessage
|
||||||
|
{
|
||||||
|
char senderName[32];
|
||||||
|
char messageContent[2048];
|
||||||
|
} userMessage;
|
||||||
|
|
||||||
|
// Sends a message to a given TLS session, wraps the calls to gnutls_write:
|
||||||
|
void messageSend(gnutls_session_t receivingSession, userMessage * messageToSend);
|
||||||
|
|
||||||
|
// Recieves a message from a given TLS session, wraps the calls to gnutls_read:
|
||||||
|
void messageReceive(gnutls_session_t receiveFromSession, userMessage * receiveToMessage);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,17 +1,10 @@
|
||||||
// playerdata.h: Header file containing data structures for player data and function
|
// playerdata.h: Header file containing data structures for player data and function
|
||||||
// definitions for interacting with said data.
|
// prototypes for interacting with said data.
|
||||||
// Barry Kane, 2021.
|
// Barry Kane, 2021.
|
||||||
#ifndef PLAYERDATA_H
|
#ifndef PLAYERDATA_H
|
||||||
#define PLAYERDATA_H
|
#define PLAYERDATA_H
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef struct userMessage
|
|
||||||
{
|
|
||||||
char senderName[32];
|
|
||||||
char messageContent[2048];
|
|
||||||
|
|
||||||
} userMessage;
|
|
||||||
|
|
||||||
typedef struct playerPath playerPath;
|
typedef struct playerPath playerPath;
|
||||||
typedef struct playerArea playerArea;
|
typedef struct playerArea playerArea;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "../misc/lists.h"
|
||||||
|
#include "../misc/playerdata.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
areaNode * areaList = createAreaList(createArea("Test Area A", "This is Test Area A"));
|
||||||
|
areaNode * counter = areaList;
|
||||||
|
addAreaNodeToList(areaList, createArea("Test Area B", "This is Test Area B"));
|
||||||
|
addAreaNodeToList(areaList, createArea("Test Area C", "This is Test Area C"));
|
||||||
|
for(int index = 0; index <= 2; index++)
|
||||||
|
{
|
||||||
|
printf("%s\n", counter->data->areaName);
|
||||||
|
counter = counter->next;
|
||||||
|
}
|
||||||
|
deleteAreaNodeFromList(areaList, getAreaFromList(areaList, 1));
|
||||||
|
addAreaNodeToList(areaList, createArea("Test Area D", "This is Test Area D"));
|
||||||
|
counter = areaList;
|
||||||
|
for(int index = 0; index <= 2; index++)
|
||||||
|
{
|
||||||
|
printf("%s\n", counter->data->areaName);
|
||||||
|
counter = counter->next;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue