Files
memgraph/src/communication/messaging/protocol.cpp
Mislav Bradac eb272f0b67 Assert on endpoint failures
Summary: .

Reviewers: mferencevic, florijan

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1045
2017-12-12 14:27:24 +01:00

109 lines
3.1 KiB
C++

#include <sstream>
#include "communication/messaging/distributed.hpp"
#include "communication/messaging/local.hpp"
#include "communication/messaging/protocol.hpp"
#include "fmt/format.h"
#include "glog/logging.h"
namespace communication::messaging {
Session::Session(Socket &&socket, SessionData &data)
: socket_(std::move(socket)), system_(data.system) {}
bool Session::Alive() const { return alive_; }
std::string Session::GetStringAndShift(SizeT len) {
std::string ret(reinterpret_cast<char *>(buffer_.data()), len);
buffer_.Shift(len);
return ret;
}
void Session::Execute() {
if (buffer_.size() < sizeof(SizeT)) return;
SizeT len_channel = GetLength();
if (buffer_.size() < 2 * sizeof(SizeT) + len_channel) return;
SizeT len_data = GetLength(sizeof(SizeT) + len_channel);
if (buffer_.size() < 2 * sizeof(SizeT) + len_data + len_channel) return;
// Remove the length bytes from the buffer.
buffer_.Shift(sizeof(SizeT));
auto channel = GetStringAndShift(len_channel);
buffer_.Shift(sizeof(SizeT));
// TODO: check for exceptions
std::istringstream stream;
stream.str(std::string(reinterpret_cast<char *>(buffer_.data()), len_data));
::cereal::BinaryInputArchive iarchive{stream};
std::unique_ptr<Message> message{nullptr};
iarchive(message);
buffer_.Shift(len_data);
LocalWriter writer(system_, channel);
writer.Send(std::move(message));
}
StreamBuffer Session::Allocate() { return buffer_.Allocate(); }
void Session::Written(size_t len) { buffer_.Written(len); }
void Session::Close() {
DLOG(INFO) << "Closing session";
this->socket_.Close();
}
SizeT Session::GetLength(int offset) {
SizeT ret = *reinterpret_cast<SizeT *>(buffer_.data() + offset);
return ret;
}
bool SendLength(Socket &socket, SizeT length) {
return socket.Write(reinterpret_cast<uint8_t *>(&length), sizeof(SizeT));
}
void SendMessage(const std::string &address, uint16_t port,
const std::string &channel, std::unique_ptr<Message> message) {
CHECK(message) << "Trying to send nullptr instead of message";
// Initialize endpoint.
Endpoint endpoint(address.c_str(), port);
Socket socket;
if (!socket.Connect(endpoint)) {
LOG(INFO) << "Couldn't connect to remote address: " << address << ":"
<< port;
return;
}
if (!SendLength(socket, channel.size())) {
LOG(INFO) << "Couldn't send channel size!";
return;
}
if (!socket.Write(channel)) {
LOG(INFO) << "Couldn't send channel data!";
return;
}
// Serialize and send message
std::ostringstream stream;
::cereal::BinaryOutputArchive oarchive(stream);
oarchive(message);
const std::string &buffer = stream.str();
int64_t message_size = 2 * sizeof(SizeT) + buffer.size() + channel.size();
CHECK(message_size <= kMaxMessageSize) << fmt::format(
"Trying to send message of size {}, max message size is {}", message_size,
kMaxMessageSize);
if (!SendLength(socket, buffer.size())) {
LOG(INFO) << "Couldn't send message size!";
return;
}
if (!socket.Write(buffer)) {
LOG(INFO) << "Couldn't send message data!";
return;
}
}
}