memgraph/experimental/distributed/src/protocol.hpp
Goran Zuzic 8f33269b03 Make System a singleton + Fix some protocol errors
Reviewers: mferencevic, sasa.stanko

Reviewed By: mferencevic, sasa.stanko

Differential Revision: https://phabricator.memgraph.io/D693
2017-08-22 16:30:25 +02:00

132 lines
3.5 KiB
C++

#pragma once
#include "communication/bolt/v1/decoder/buffer.hpp"
#include "io/network/epoll.hpp"
#include "io/network/network_endpoint.hpp"
#include "io/network/socket.hpp"
#include "io/network/stream_buffer.hpp"
class Message;
/**
* @brief Protocol
*
* Has classes and functions that implement server and client sides of our
* distributed protocol.
*
* The protocol consists of two stages.
* The first stage is a handshake stage when the client sends to the server
* reactor and channel names which it wants to communicate with.
* The second stage is sending messages.
*
* HANDSHAKE
*
* Client sends:
* len_reactor_name(SizeT) len_channel_name(SizeT) reactor_name channel_name
* Server responds:
* 0x40 if the reactor/channel combo doesn't exist
* 0x80 if the reactor/channel combo exists
*
* MESSAGES
*
* Client sends:
* len_message(SizeT) cereal_encoded_binary_message
* Server responds:
* 0x40 if the reactor/channel combo doesn't exist or the message wasn't
* successfully decoded and delivered
* 0x80 if the reactor/channel combo exist and the message was successfully
* decoded and delivered
*
* Currently the server is implemented to handle more than one message after
* the initial handshake, but the client can only send one message.
*/
namespace Protocol {
using Endpoint = io::network::NetworkEndpoint;
using Socket = io::network::Socket;
using StreamBuffer = io::network::StreamBuffer;
// this buffer should be larger than the largest serialized message
using Buffer = communication::bolt::Buffer<262144>;
using SizeT = uint16_t;
/**
* Distributed Protocol Data
*
* This typically holds living data shared by all sessions. Currently empty.
*/
struct Data {
// empty
};
/**
* Distributed Protocol Session
*
* This class is responsible for handling a single client connection.
*
* @tparam Socket type of socket (could be a network socket or test socket)
*/
class Session {
private:
public:
Session(Socket &&socket, Data &data);
/**
* Returns the protocol alive state
*/
bool Alive() const;
/**
* Executes the protocol after data has been read into the buffer.
* Goes through the protocol states in order to execute commands from the
* client.
*/
void Execute();
/**
* Allocates data from the internal buffer.
* Used in the underlying network stack to asynchronously read data
* from the client.
* @returns a StreamBuffer to the allocated internal data buffer
*/
StreamBuffer Allocate();
/**
* Notifies the internal buffer of written data.
* Used in the underlying network stack to notify the internal buffer
* how many bytes of data have been written.
* @param len how many data was written to the buffer
*/
void Written(size_t len);
/**
* Closes the session (client socket).
*/
void Close();
io::network::Epoll::Event event_;
Socket socket_;
private:
SizeT GetLength(int offset = 0);
std::string GetStringAndShift(SizeT len);
bool SendSuccess(bool success);
bool alive_{true};
bool handshake_done_{false};
std::string reactor_{""};
std::string channel_{""};
Buffer buffer_;
};
/**
* Distributed Protocol Send Message
*
* This function sends a message to the specified server.
* If message is a nullptr then it only checks whether the remote reactor
* and channel exist, else it returns the complete message send success.
*/
bool SendMessage(std::string address, uint16_t port, std::string reactor,
std::string channel, std::unique_ptr<Message> message);
}