2022-09-25 21:49:24 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// SCSI Target Emulator RaSCSI Reloaded
|
|
|
|
// for Raspberry Pi
|
|
|
|
//
|
|
|
|
// Copyright (C) 2022 Uwe Seimet
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "rascsi_interface.pb.h"
|
|
|
|
#include "rascsi_exceptions.h"
|
2022-10-04 15:23:42 +00:00
|
|
|
#include "protobuf_serializer.h"
|
2022-09-25 21:49:24 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace rascsi_interface;
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2022-10-04 15:23:42 +00:00
|
|
|
// Serialize/Deserialize protobuf message: Length followed by the actual data.
|
|
|
|
// A little endian platform is assumed.
|
2022-09-25 21:49:24 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2022-10-04 15:23:42 +00:00
|
|
|
void ProtobufSerializer::SerializeMessage(int fd, const google::protobuf::Message& message) const
|
2022-09-25 21:49:24 +00:00
|
|
|
{
|
|
|
|
string data;
|
|
|
|
message.SerializeToString(&data);
|
|
|
|
|
|
|
|
// Write the size of the protobuf data as a header
|
|
|
|
auto size = (int32_t)data.length();
|
|
|
|
if (write(fd, &size, sizeof(size)) != sizeof(size)) {
|
|
|
|
throw io_exception("Can't write protobuf message header");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the actual protobuf data
|
|
|
|
if (write(fd, data.data(), size) != size) {
|
|
|
|
throw io_exception("Can't write protobuf message data");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-04 15:23:42 +00:00
|
|
|
void ProtobufSerializer::DeserializeMessage(int fd, google::protobuf::Message& message) const
|
2022-09-25 21:49:24 +00:00
|
|
|
{
|
|
|
|
// Read the header with the size of the protobuf data
|
|
|
|
vector<byte> header_buf(4);
|
|
|
|
if (ReadBytes(fd, header_buf) < header_buf.size()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t size = ((int)header_buf[3] << 24) + ((int)header_buf[2] << 16) + ((int)header_buf[1] << 8) + (int)header_buf[0];
|
|
|
|
if (size <= 0) {
|
|
|
|
throw io_exception("Invalid protobuf message header");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the binary protobuf data
|
|
|
|
vector<byte> data_buf(size);
|
|
|
|
if (ReadBytes(fd, data_buf) < data_buf.size()) {
|
|
|
|
throw io_exception("Missing protobuf message data");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create protobuf message
|
|
|
|
string data((const char *)data_buf.data(), size);
|
|
|
|
message.ParseFromString(data);
|
|
|
|
}
|
|
|
|
|
2022-10-04 15:23:42 +00:00
|
|
|
size_t ProtobufSerializer::ReadBytes(int fd, vector<byte>& buf) const
|
2022-09-25 21:49:24 +00:00
|
|
|
{
|
|
|
|
size_t offset = 0;
|
|
|
|
while (offset < buf.size()) {
|
|
|
|
ssize_t len = read(fd, &buf[offset], buf.size() - offset);
|
|
|
|
if (len <= 0) {
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|