diff options
Diffstat (limited to '')
-rw-r--r-- | include/client.hpp | 17 | ||||
-rw-r--r-- | include/comms.hpp | 32 | ||||
-rw-r--r-- | include/server.hpp | 27 | ||||
-rw-r--r-- | include/util.hpp | 141 |
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 |