aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/client.hpp17
-rw-r--r--include/comms.hpp32
-rw-r--r--include/server.hpp27
-rw-r--r--include/util.hpp141
4 files changed, 217 insertions, 0 deletions
diff --git a/include/client.hpp b/include/client.hpp
new file mode 100644
index 0000000..dfc3e0c
--- /dev/null
+++ b/include/client.hpp
@@ -0,0 +1,17 @@
+#ifndef client_H
+#define client_H
+
+#include "comms.hpp"
+
+void RemoveConnection(int i);
+int Send_Blocking(int sockFD, const BYTE *data, int len);
+
+void DoClient(const char *svrIP, int svrPort, const char *fileName);
+
+void doClientCommand(int i);
+
+void prepareSend(int i, Header header);
+int processReception(int i);
+void printMessage(int i);
+
+#endif
diff --git a/include/comms.hpp b/include/comms.hpp
new file mode 100644
index 0000000..1b2a942
--- /dev/null
+++ b/include/comms.hpp
@@ -0,0 +1,32 @@
+#ifndef COMM_UTIL_H
+#define COMM_UTIL_H
+#include "util.hpp"
+
+struct CONN_STAT {
+ int id; // Unique id to identify a client instance
+ bool isLoggedIn; // Used by server to identify that this connection is logged
+ // in
+ struct timeb lastTime; // Last time this connection was used (used to detect
+ // s2c closure)
+ bool recInitHeader; // False until initial header is recieved
+ bool expectingHeader; // The message to be read is a header (irrelevent for
+ // senders)
+ enum LinkType linkType; // MESSAGE_LINK (persistent) or FILE_LINK (one off)
+ enum Direction direction; // C2S or S2C
+ char name[9]; // The user this connection is with
+ int nBuffered; // number of bytes in the buffer
+ int messageLen; // size of the current message being sent (includes header)
+ int nToDo; // num bytes to do before current messsage is completed (message
+ // len --> 0)
+ bool changeDirection; // Flag to change the direction of the connection once
+ // the current communication finishes
+ bool shouldClose; // Flag to destroy this connection
+};
+
+int Send_NonBlocking(int sockFD, BYTE *data, struct CONN_STAT *pStat,
+ struct pollfd *pPeer);
+int Recv_NonBlocking(int sockFD, BYTE *data, struct CONN_STAT *pStat,
+ struct pollfd *pPeer);
+void SetNonBlockIO(int fd);
+
+#endif
diff --git a/include/server.hpp b/include/server.hpp
new file mode 100644
index 0000000..ab77ad8
--- /dev/null
+++ b/include/server.hpp
@@ -0,0 +1,27 @@
+#ifndef server_H
+#define server_H
+
+// Comms includes util.hpp
+#include "comms.hpp"
+
+void SetNonBlockIO(int fd);
+void RemoveConnection(int i);
+
+int Send_NonBlocking(int sockFD, BYTE *data, struct CONN_STAT *pStat,
+ struct pollfd *pPeer);
+int Recv_NonBlocking(int sockFD, BYTE *data, struct CONN_STAT *pStat,
+ struct pollfd *pPeer);
+
+int processReception(int i);
+void doServerCommand(int i);
+void sendMessageToId(int id, bool reqLoggedIn, Header header, char *message);
+void sendMessageToAllLoggedIn(Header header, char *message);
+void sendMessageToAllLoggedInExceptSender(int senderID, Header header,
+ char *message);
+void sendMessageToName(char *name, Header header, char *message);
+void prepareMessage(int i, Header header, char *message);
+void printServerCommand(int i);
+
+void DoServer(int svrPort);
+
+#endif
diff --git a/include/util.hpp b/include/util.hpp
new file mode 100644
index 0000000..10887df
--- /dev/null
+++ b/include/util.hpp
@@ -0,0 +1,141 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+// Get your libraries here
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/timeb.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
+
+#define NAME "SERVER"
+#define ANON "Anonymous"
+#define LINE_SIZE 5000 // overkill
+
+#define BUF_LEN 12000000 // overkill
+#define MAX_REQUEST_SIZE 10000000
+#define MIN_USERNAME_LEN 4
+#define MAX_USERNAME_LEN 8
+#define MIN_PASSWORD_LEN 4
+#define MAX_PASSWORD_LEN 8
+
+enum Command {
+ REGISTER = 0, // [username] [password] Register a new account
+ LOGIN = 1, // [username] [password] Log in with an existing account and enter
+ // the chat room
+ LOGOUT = 2, // Log out and leave the chat room
+ SEND = 3, // [msg] Send a public message
+ SEND2 = 4, // [username] [msg] Send a private message to a user
+ SENDA = 5, // [msg] Send an anonymous public message
+ SENDA2 = 6, // [username] [msg] Send an anonymous private message to a user
+ SENDF = 7, // [local file] Send a file publicly
+ SENDF2 = 8, // [username] [local file] Send a file to a user privately
+ LIST = 9, // List all online users
+ DELAY = 10, // [N] A special command that delays for N seconds before
+ // executing the next command in the script
+
+ GETF = 11, // [filename] Server telling clinet to request a file, clinet
+ // requesting a file
+ PING = 12, // Check that connection is still there (nop)
+ CONNECT = 13, // [unique id] Allows the server to identify specific users when
+ // they are logged in multiple times
+
+ INVALID = 15 // Used when no valid command is found
+};
+
+enum LinkType { MESSAGE_LINK, FILE_LINK };
+
+typedef unsigned char BYTE;
+typedef unsigned int DWORD;
+typedef unsigned short WORD;
+
+enum Command parse_command(char *line);
+bool isValidUsername(char *username);
+bool isValidPassword(char *password);
+
+void Error(const char *format, ...);
+void Log(const char *format, ...);
+
+void buf2i(BYTE *buf, int &i);
+void i2buf(int &i, BYTE *buf);
+
+const char *com2str(enum Command command);
+
+double timeDifference(struct timeb a, struct timeb b);
+
+int getNumEntries(const char *databse);
+bool loginQuery(const char *database, char *username, char *password);
+bool usernameQuery(const char *database, char *username);
+
+void recordEntry(const char *database, char *key, char *value);
+void clearDatabase(const char *database);
+
+int buf2file(BYTE *buf, int nbytes, char *filename);
+int file2buf(char *filename, BYTE *buf);
+
+#define HEADER_LEN 13 // number of bytes in a message header
+
+enum Direction { C2S, S2C }; // client to server, server to client
+enum Flag { SUCCESS, FAIL }; // success, failure
+enum Recipient { PUB, PRIV }; // send to all, send to one
+enum Trace { SIGN, ANNON }; // send publically, send anonymously
+
+class Header {
+public:
+ enum Direction m_direction;
+ enum Flag m_flag;
+ enum Recipient m_recipient;
+ enum Trace m_trace;
+ enum Command m_command;
+
+ BYTE m_name[9];
+
+ int m_size;
+
+ Header(); // constructor
+
+ void encode(BYTE *buf); // encode message to buffer
+ void decode(BYTE *buf); // decode buffer to message
+
+ void setFlags(enum Direction direction, enum Flag flag,
+ enum Recipient recipient, enum Trace trace);
+
+ void displayContents(bool tab); // helper to print contents of class
+};
+
+inline bool operator==(const Header &lfs, const Header &rhs) {
+ bool result = true;
+
+ result &= lfs.m_direction == rhs.m_direction;
+ result &= lfs.m_flag == rhs.m_flag;
+ result &= lfs.m_recipient == rhs.m_recipient;
+ result &= lfs.m_trace == rhs.m_trace;
+ result &= lfs.m_command == rhs.m_command;
+
+ for (int i = 0; i < MAX_USERNAME_LEN; i++)
+ result &= lfs.m_name[i] == rhs.m_name[i];
+
+ result &= lfs.m_size == rhs.m_size;
+
+ return result;
+}
+
+inline bool operator!=(const Header &lhs, const Header &rhs) {
+ return !(lhs == rhs);
+}
+
+#endif