college-projects/include/protocol.hpp

175 lines
4.4 KiB
C++

#ifndef PROTOCOL_HPP_
#define PROTOCOL_HPP_
#include <string>
#include <unordered_map>
#include <list>
#include <Client.hpp>
#include "topic.hpp"
using namespace std;
/*
* Bytes that notify the subscriber what kind of message it
* is about to receive.
*
*/
#define IDREQUEST_ANNOUNCEMENT_BYTE 0xFF
#define TOPIC_ANNOUNCEMENT_BYTE 1
#define CONNECTION_REFUSED_BYTE 2
#define INVALID_REQUEST_ANNOUNCEMENT_BYTE 3
/*
* Maximum size of data that the protocol can operate with.
*
*/
#define BUFLEN (sizeof (Topic))
/*
* Maximum length of a client id.
*
*/
#define CLIENTID_MAX_LEN 10
/*
* Format of subscribe and unsubscribe requests.
*
*/
#define SUBSCRIBE "subscribe"
#define UNSUBSCRIBE "unsubscribe"
/*
* Format of store and forward options.
*
*/
#define SF_ON "1"
#define SF_OFF "0"
/*
* Maximul length (in bytes) of a un/subscribe request.
* Length of UNSUBSCRIBE + length of SF option + maximum length of a topic
* + 2 spaces.
*
*/
#define REQUEST_MAX_LEN (sizeof(UNSUBSCRIBE) - 1 + \
sizeof(SF_ON) - 1 + TOPIC_MAX_LEN + sizeof(uint8_t) * 2)
/*
* Lengths (in words separated by space) of subscribe and unsubscribe requests.
*
*/
#define SUBSCRIBE_REQUEST_LENGTH 3
#define UNSUBSCRIBE_REQUEST_LENGTH 2
/*
* Makes a request for the client_id to a client described by a file
* descriptor @client. It has also a error handler macro associated.
* If a send or recv call fails then the function will return an
* empty string and a error mesage will be displayed.
*
*/
string request_client_id(int client);
#define REQUEST_CLIENT_ID_ERROR(assertion, call_description) \
do { \
if (assertion) { \
fprintf(stderr, "(%s, %d): ", \
__FILE__, __LINE__); \
perror(call_description); \
return {}; \
} \
} while (0)
/*
* Reply for the above mentioned request. The @client_id is transmited
* via the connection established by @socket.
*
* @return: REPLY_SUCCESSFUL if the subscriber sent bytes on the socket
* REPLY_FAILED if the subscriber failed to send bytes
*
*/
#define REPLY_SUCCESSFUL 0
#define REPLY_FAILED 1
#define REPLY_CLIENT_ID_ERROR(assertion, call_description) \
do { \
if (assertion) { \
fprintf(stderr, "(%s, %d): ", \
__FILE__, __LINE__); \
perror(call_description); \
return REPLY_FAILED; \
} \
} while (0)
int reply_client_id(int socket, char *client_id);
/*
* Reply with a CONNECTION_REFUSED_BYTE from server to let the client
* know that there is already a client with the same clientID.
*
*/
#define REPLY_CONNECTION_REFUSED_ERROR(assertion, call_description) \
do { \
if (assertion) { \
fprintf(stderr, "(%s, %d): ", \
__FILE__, __LINE__); \
perror(call_description); \
} \
} while (0)
void reply_connection_refused(int socket);
/*
* Reply with a INVALID_REQUEST_ANNOUNCEMENT_BYTE from server to let the cient
* know that the un/subscribe request is sent is invalid.
*
*/
#define REPLY_INVALID_REQUEST_ERROR(assertion, call_description) \
do { \
if (assertion) { \
fprintf(stderr, "(%s, %d): ", \
__FILE__, __LINE__); \
perror(call_description); \
} \
} while (0)
void reply_invalid_request(int socket);
/*
* When a subscriber sends a subscribe request, this function will resolve
* the request by adding the client in @topics_table.
*
* @return: CONNECTION_CLOSED_ERROR - connection was closed and the request
* could not be processed
* INVALID_REQUEST_ERROR - the request does not have the falid format
* REQUEST_SUCCESSFUL - the request was successfully
* processed
*
* The error macro is used when the function cannot read data from the
* socket.
*
*/
#define REQUEST_SUCCESSFUL 1
#define CONNECTION_CLOSED_ERROR 0
#define INVALID_REQUEST_ERROR -1
int resolve_subscribe_request(int client,
unordered_map<string, list<Client>>& topics_table);
#define RESOLVE_SUBSCRIBE_REQUEST_ERROR(assertion, call_description) \
do { \
if (assertion) { \
fprintf(stderr, "(%s, %d): ", \
__FILE__, __LINE__); \
perror(call_description); \
return CONNECTION_CLOSED_ERROR; \
} \
} while (0)
#endif