mirror of
https://github.com/akuker/RASCSI.git
synced 2025-01-12 01:29:58 +00:00
Allow rasctl to connect from a different host (#134)
* Set hostname * Added option for hostname * Support connecting from a different host * Squashed commit of the following: commit 6698b8b90a0760102ce9fb30a5ee0656dd46491c Author: akuker <34318535+akuker@users.noreply.github.com> Date: Mon Jul 19 01:19:41 2021 -0500 Remove extraneous carriage return (#135) Co-authored-by: Tony Kuker <akuker@gmail.com> commit af6e311e6eab40255572d2e55b20ab6edb6871ea Author: uweseimet <48174652+uweseimet@users.noreply.github.com> Date: Mon Jul 19 00:15:13 2021 +0200 protobuf-based rasctl/rascsi command interface (#129) * Initial protobuf definition * protobuf result message draft * Merge with develop branch * Makefile generates protobuf-based source files * Interface update * Fixed typo * Fixed typo * Updated returning status * Serialize return data * Use correct descriptor * Made interface fields required * Deserialize result * Serialization update * Updated serialization * Serialization update * Updated deserialization * status handling update * Evaluate status * Revert "Evaluate status" This reverts commit 3d8f2c3252a10618dede5f5fd80c84115551fc7d. * Completed sense_key enum * Renaming * Added protobuf Command * Updated command evaluation * Interface update * Interface update * Added DeviceType enum * Improved type-safety * Fixed typo * Type-safety update * Fixed typo * Error handling update * Updated list handling * Error handling update * Use more C++ strings * protobuf enums can provide their names * Fixed listing devices * Updated logging * Enum usage cleanup * More enum cleanup * Fixed command check * Updated type check * Updated enums * Removed unused variable * Removed goto, added exception * Socket handling cleanup * Code locality cleanup * Added helper method * Extracted code * Updated socket/file handling * Use C++ I/O * Use tolower() * Renaming * Simplified has_suffix * Fixed typo * Use spdlog namespace * Simplified formatting (endl) of error messages * Added -s option for changing the runtime log level to rasctl * Renaming * Renaming * Updated error reporting * Fixed log string formatting * String conversion cleanup * Fixed typo * Log mmap error (happens on 64 bit) * Improved proto3 compatibility, updated error handling * CHanges based on review * Fixed comment * Comment update * Updated ListDevice to not directly write to the stream * Use size_t * Renaming * Buffering update * MapController should not use fp * Use fd, not fp * rasctl has to display *all* results * rasctl has to display *all* results * Error handling update * Updated to proto3 protocol * Optimization by using protobuf-lite * RaspBian outdated protoc does not support _Name * Added protobuf-compiler to easyinstall.sh Co-authored-by: akuker <34318535+akuker@users.noreply.github.com> * Resolved merge conflicts * Updated help message * Re-added CR/LF * Updated error handling * Use fd instead of fp * Removed CR/LF * Comment update * Fixed data types * Data type update * Updated help message * Added new option to usage info, rascsi: use -s instead of -l for consistency * Display name of (remote) host in error message * Fixed buffer overflow, cfilesystem.cpp:1185 assumes size of 11 bytes * Revert "Fixed buffer overflow, cfilesystem.cpp:1185 assumes size of 11 bytes" This reverts commit 126592d411121e0a807c287b867895d9786025e0.
This commit is contained in:
parent
6698b8b90a
commit
0032ce5010
@ -104,12 +104,14 @@ void Banner(int argc, char* argv[])
|
||||
if ((argc > 1 && strcmp(argv[1], "-h") == 0) ||
|
||||
(argc > 1 && strcmp(argv[1], "--help") == 0)){
|
||||
FPRT(stdout,"\n");
|
||||
FPRT(stdout,"Usage: %s [-IDn FILE] ...\n\n", argv[0]);
|
||||
FPRT(stdout,"Usage: %s [-IDn FILE] [-s LOG_LEVEL] ...\n\n", argv[0]);
|
||||
FPRT(stdout," n is SCSI identification number(0-7).\n");
|
||||
FPRT(stdout," FILE is disk image file.\n\n");
|
||||
FPRT(stdout,"Usage: %s [-HDn FILE] ...\n\n", argv[0]);
|
||||
FPRT(stdout," FILE is disk image file.\n");
|
||||
FPRT(stdout," LOG_LEVEL is {trace|debug|info|warn|err|critical|off}, default is 'trace'\n\n");
|
||||
FPRT(stdout,"Usage: %s [-HDn FILE] [-s LOG_LEVEL] ...\n\n", argv[0]);
|
||||
FPRT(stdout," n is X68000 SASI HD number(0-15).\n");
|
||||
FPRT(stdout," FILE is disk image file, \"daynaport\", or \"bridge\".\n\n");
|
||||
FPRT(stdout," FILE is disk image file, \"daynaport\", or \"bridge\".\n");
|
||||
FPRT(stdout," LOG_LEVEL is {trace|debug|info|warn|err|critical|off}, default is 'trace'\n\n");
|
||||
FPRT(stdout," Image type is detected based on file extension.\n");
|
||||
FPRT(stdout," hdf : SASI HD image(XM6 SASI HD image)\n");
|
||||
FPRT(stdout," hds : SCSI HD image(XM6 SCSI HD image)\n");
|
||||
@ -144,9 +146,9 @@ BOOL Init()
|
||||
}
|
||||
|
||||
// Create socket for monitor
|
||||
monsocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
monsocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sin_family = PF_INET;
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(6868);
|
||||
server.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
@ -457,20 +459,27 @@ bool MapController(Disk **map)
|
||||
return status;
|
||||
}
|
||||
|
||||
bool ReturnStatus(FILE *fp, bool status = true, const string msg = "") {
|
||||
bool ReturnStatus(int fd, bool status = true, const string msg = "") {
|
||||
#ifdef BAREMETAL
|
||||
if (msg.length()) {
|
||||
FPRT(fp, msg.c_str());
|
||||
FPRT(fp, "\n");
|
||||
FPRT(stderr, msg.c_str());
|
||||
FPRT(stderr, "\n");
|
||||
}
|
||||
#else
|
||||
Result result;
|
||||
result.set_msg(msg);
|
||||
result.set_status(status);
|
||||
if (fd == -1) {
|
||||
if (msg.length()) {
|
||||
FPRT(stderr, msg.c_str());
|
||||
FPRT(stderr, "\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
Result result;
|
||||
result.set_status(status);
|
||||
|
||||
string data;
|
||||
result.SerializeToString(&data);
|
||||
SerializeProtobufData(fp, data);
|
||||
string data;
|
||||
result.SerializeToString(&data);
|
||||
SerializeProtobufData(fd, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
return status;
|
||||
@ -506,10 +515,10 @@ void SetLogLevel(const string& log_level) {
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Command Processing
|
||||
// Command Processing. If fd is -1 error messages are displayed on the console.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
bool ProcessCmd(FILE *fp, const Command &command)
|
||||
bool ProcessCmd(int fd, const Command &command)
|
||||
{
|
||||
Disk *map[CtrlMax * UnitNum];
|
||||
Filepath filepath;
|
||||
@ -531,12 +540,12 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
|
||||
// Check the Controller Number
|
||||
if (id < 0 || id >= CtrlMax) {
|
||||
return ReturnStatus(fp, false, "Error : Invalid ID");
|
||||
return ReturnStatus(fd, false, "Error : Invalid ID");
|
||||
}
|
||||
|
||||
// Check the Unit Number
|
||||
if (un < 0 || un >= UnitNum) {
|
||||
return ReturnStatus(fp, false, "Error : Invalid unit number");
|
||||
return ReturnStatus(fd, false, "Error : Invalid unit number");
|
||||
}
|
||||
|
||||
// Connect Command
|
||||
@ -548,7 +557,7 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
// Check the extension
|
||||
int len = params.length();
|
||||
if (len < 5 || params[len - 4] != '.') {
|
||||
return ReturnStatus(fp, false);
|
||||
return ReturnStatus(fd, false);
|
||||
}
|
||||
|
||||
// If the extension is not SASI type, replace with SCSI
|
||||
@ -591,7 +600,7 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
default:
|
||||
ostringstream msg;
|
||||
msg << "rasctl sent a command for an invalid drive type: " << type;
|
||||
return ReturnStatus(fp, false, msg.str());
|
||||
return ReturnStatus(fd, false, msg.str());
|
||||
}
|
||||
|
||||
// drive checks files
|
||||
@ -610,7 +619,7 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
|
||||
ostringstream msg;
|
||||
msg << "Error : File open error [" << file << "]";
|
||||
return ReturnStatus(fp, false, msg.str());
|
||||
return ReturnStatus(fd, false, msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,14 +641,14 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
LOGINFO("rasctl added new %s device. ID: %d UN: %d", type_str, id, un);
|
||||
}
|
||||
|
||||
return ReturnStatus(fp, status, status ? "" : "Error : SASI and SCSI can't be mixed\n");
|
||||
return ReturnStatus(fd, status, status ? "" : "Error : SASI and SCSI can't be mixed\n");
|
||||
}
|
||||
|
||||
// Does the controller exist?
|
||||
if (ctrl[id] == NULL) {
|
||||
LOGWARN("rasctl sent a command for invalid controller %d", id);
|
||||
|
||||
return ReturnStatus(fp, false, "Error : No such device");
|
||||
return ReturnStatus(fd, false, "Error : No such device");
|
||||
}
|
||||
|
||||
// Does the unit exist?
|
||||
@ -647,7 +656,7 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
if (pUnit == NULL) {
|
||||
LOGWARN("rasctl sent a command for invalid unit ID %d UN %d", id, un);
|
||||
|
||||
return ReturnStatus(fp, false, "Error : No such device");
|
||||
return ReturnStatus(fd, false, "Error : No such device");
|
||||
}
|
||||
|
||||
type_str[0] = (char)(pUnit->GetID() >> 24);
|
||||
@ -665,7 +674,7 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
|
||||
// Re-map the controller
|
||||
bool status = MapController(map);
|
||||
return ReturnStatus(fp, status, status ? "" : "Error : SASI and SCSI can't be mixed\n");
|
||||
return ReturnStatus(fd, status, status ? "" : "Error : SASI and SCSI can't be mixed\n");
|
||||
}
|
||||
|
||||
// Valid only for MO or CD
|
||||
@ -675,7 +684,7 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
|
||||
ostringstream msg;
|
||||
msg << "Error : Operation denied (Device type " << type_str << " isn't removable)";
|
||||
return ReturnStatus(fp, false, msg.str());
|
||||
return ReturnStatus(fd, false, msg.str());
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
@ -687,7 +696,7 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
ostringstream msg;
|
||||
msg << "Error : File open error [" << params << "]";
|
||||
|
||||
return ReturnStatus(fp, false, msg.str());
|
||||
return ReturnStatus(fd, false, msg.str());
|
||||
}
|
||||
break;
|
||||
|
||||
@ -700,7 +709,7 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O')) {
|
||||
LOGWARN("rasctl sent an invalid PROTECT command for %s ID: %d UN: %d", type_str, id, un);
|
||||
|
||||
return ReturnStatus(fp, false, "Error : Operation denied (Device isn't MO)");
|
||||
return ReturnStatus(fd, false, "Error : Operation denied (Device isn't MO)");
|
||||
}
|
||||
LOGINFO("rasctl is setting write protect to %d for %s ID: %d UN: %d",!pUnit->IsWriteP(), type_str, id, un);
|
||||
pUnit->WriteP(!pUnit->IsWriteP());
|
||||
@ -710,10 +719,10 @@ bool ProcessCmd(FILE *fp, const Command &command)
|
||||
ostringstream msg;
|
||||
msg << "Received unknown command from rasctl: " << cmd;
|
||||
LOGWARN("%s", msg.str().c_str());
|
||||
return ReturnStatus(fp, false, msg.str());
|
||||
return ReturnStatus(fd, false, msg.str());
|
||||
}
|
||||
|
||||
return ReturnStatus(fp, true);
|
||||
return ReturnStatus(fd, true);
|
||||
}
|
||||
|
||||
bool has_suffix(const string& filename, const string& suffix) {
|
||||
@ -875,7 +884,7 @@ BOOL ParseConfig(int argc, char* argv[])
|
||||
command.set_cmd(0);
|
||||
command.set_type(type);
|
||||
command.set_file(argPath);
|
||||
if (!ProcessCmd(stderr, command)) {
|
||||
if (!ProcessCmd(-1, command)) {
|
||||
goto parse_error;
|
||||
}
|
||||
}
|
||||
@ -904,7 +913,7 @@ bool ParseArgument(int argc, char* argv[])
|
||||
string log_level = "trace";
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "-IiHhL:l:D:d:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "-IiHhL:s:D:d:")) != -1) {
|
||||
switch (tolower(opt)) {
|
||||
case 'i':
|
||||
is_sasi = false;
|
||||
@ -918,7 +927,7 @@ bool ParseArgument(int argc, char* argv[])
|
||||
id = -1;
|
||||
continue;
|
||||
|
||||
case 'l':
|
||||
case 's':
|
||||
log_level = optarg;
|
||||
continue;
|
||||
|
||||
@ -978,7 +987,7 @@ bool ParseArgument(int argc, char* argv[])
|
||||
command.set_cmd(ATTACH);
|
||||
command.set_type(type);
|
||||
command.set_params(path);
|
||||
if (!ProcessCmd(stderr, command)) {
|
||||
if (!ProcessCmd(-1, command)) {
|
||||
return false;
|
||||
}
|
||||
id = -1;
|
||||
@ -1022,7 +1031,6 @@ void FixCpu(int cpu)
|
||||
static void *MonThread(void *param)
|
||||
{
|
||||
int fd;
|
||||
FILE *fp;
|
||||
|
||||
// Scheduler Settings
|
||||
struct sched_param schedparam;
|
||||
@ -1052,11 +1060,6 @@ static void *MonThread(void *param)
|
||||
}
|
||||
|
||||
// Fetch the command
|
||||
fp = fdopen(fd, "r+");
|
||||
if (!fp) {
|
||||
throw ioexception("fdopen() failed");
|
||||
}
|
||||
|
||||
Command command;
|
||||
command.ParseFromString(DeserializeProtobufData(fd));
|
||||
|
||||
@ -1068,7 +1071,7 @@ static void *MonThread(void *param)
|
||||
|
||||
string data;
|
||||
result.SerializeToString(&data);
|
||||
SerializeProtobufData(fp, data);
|
||||
SerializeProtobufData(fd, data);
|
||||
}
|
||||
else if (command.cmd() == LOG_LEVEL) {
|
||||
SetLogLevel(command.params());
|
||||
@ -1079,11 +1082,9 @@ static void *MonThread(void *param)
|
||||
usleep(500 * 1000);
|
||||
}
|
||||
|
||||
ProcessCmd(fp, command);
|
||||
ProcessCmd(fd, command);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
@ -1094,9 +1095,6 @@ static void *MonThread(void *param)
|
||||
// Fall through
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
@ -1120,6 +1118,8 @@ int startrascsi(void)
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#endif // BAREMETAL
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
int i;
|
||||
int actid;
|
||||
DWORD now;
|
||||
|
@ -9,6 +9,7 @@
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include <netdb.h>
|
||||
#include "os.h"
|
||||
#include "rascsi_version.h"
|
||||
#include "exceptions.h"
|
||||
@ -23,32 +24,38 @@ using namespace rasctl_interface;
|
||||
// Send Command
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
bool SendCommand(const Command& command)
|
||||
BOOL SendCommand(const char *hostname, const Command& command)
|
||||
{
|
||||
// Create a socket to send the command
|
||||
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
struct sockaddr_in server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sin_family = PF_INET;
|
||||
server.sin_port = htons(6868);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(6868);
|
||||
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
int fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
|
||||
struct hostent *host = gethostbyname(hostname);
|
||||
if(!host) {
|
||||
fprintf(stderr, "Error : Can't resolve hostname '%s'\n", hostname);
|
||||
return false;
|
||||
}
|
||||
memcpy((char *)&server.sin_addr.s_addr, (char *)host->h_addr, host->h_length);
|
||||
|
||||
// Connect
|
||||
if (connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
|
||||
cerr << "Error : Can't connect to rascsi process" << endl;
|
||||
fprintf(stderr, "Error : Can't connect to rascsi process on host '%s'\n", hostname);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send the command
|
||||
FILE *fp = fdopen(fd, "r+");
|
||||
|
||||
string data;
|
||||
command.SerializeToString(&data);
|
||||
SerializeProtobufData(fp, data);
|
||||
|
||||
// Receive the message
|
||||
bool status = true;
|
||||
try {
|
||||
Result result;
|
||||
SerializeProtobufData(fd, data);
|
||||
|
||||
Result result;
|
||||
result.ParseFromString(DeserializeProtobufData(fd));
|
||||
|
||||
status = result.status();
|
||||
@ -63,8 +70,7 @@ bool SendCommand(const Command& command)
|
||||
// Fall through
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
close(fd);
|
||||
close(fd);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -76,17 +82,20 @@ bool SendCommand(const Command& command)
|
||||
//---------------------------------------------------------------------------
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
// Display help
|
||||
if (argc < 2) {
|
||||
cerr << "SCSI Target Emulator RaSCSI Controller" << endl;
|
||||
cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl;
|
||||
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-t TYPE] [-f FILE] [-s LOG_LEVEL]" << endl;
|
||||
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-t TYPE] [-f FILE] [-h HOSTNAME] [-s LOG_LEVEL]" << endl;
|
||||
cerr << " where ID := {0|1|2|3|4|5|6|7}" << endl;
|
||||
cerr << " UNIT := {0|1} default setting is 0." << endl;
|
||||
cerr << " CMD := {attach|detach|insert|eject|protect}" << endl;
|
||||
cerr << " TYPE := {hd|mo|cd|bridge|daynaport}" << endl;
|
||||
cerr << " FILE := image file path" << endl;
|
||||
cerr << " LOG_LEVEL := log level" << endl;
|
||||
cerr << " HOSTNAME := rascsi host to connect to, default is 'localhost'" << endl;
|
||||
cerr << " LOG_LEVEL := log level {trace|debug|info|warn|err|critical|off}, default is 'trace'" << endl;
|
||||
cerr << " If CMD is 'attach' or 'insert' the FILE parameter is required." << endl;
|
||||
cerr << "Usage: " << argv[0] << " -l" << endl;
|
||||
cerr << " Print device list." << endl;
|
||||
@ -100,10 +109,10 @@ int main(int argc, char* argv[])
|
||||
int un = 0;
|
||||
Operation cmd = LIST;
|
||||
DeviceType type = UNDEFINED;
|
||||
const char *hostname = "localhost";
|
||||
string params;
|
||||
opterr = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "i:u:c:t:f:s:l")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "i:u:c:t:f:h:s:l")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i':
|
||||
id = optarg[0] - '0';
|
||||
@ -177,6 +186,10 @@ int main(int argc, char* argv[])
|
||||
cmd = LIST;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
hostname = optarg;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
cmd = LOG_LEVEL;
|
||||
params = optarg;
|
||||
@ -189,14 +202,14 @@ int main(int argc, char* argv[])
|
||||
if (cmd == LOG_LEVEL) {
|
||||
command.set_cmd(LOG_LEVEL);
|
||||
command.set_params(params);
|
||||
SendCommand(command);
|
||||
SendCommand(hostname, command);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// List display only
|
||||
if (cmd == LIST || (id < 0 && type == UNDEFINED && params.empty())) {
|
||||
command.set_cmd(LIST);
|
||||
SendCommand(command);
|
||||
SendCommand(hostname, command);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -248,7 +261,7 @@ int main(int argc, char* argv[])
|
||||
if (!params.empty()) {
|
||||
command.set_params(params);
|
||||
}
|
||||
if (!SendCommand(command)) {
|
||||
if (!SendCommand(hostname, command)) {
|
||||
exit(ENOTCONN);
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
#include "exceptions.h"
|
||||
#include "rasutil.h"
|
||||
@ -23,17 +22,22 @@ using namespace std;
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void SerializeProtobufData(FILE *fp, const string& data)
|
||||
void SerializeProtobufData(int fd, const string& data)
|
||||
{
|
||||
// Write the size of the protobuf data as a header
|
||||
size_t size = data.length();
|
||||
fwrite(&size, sizeof(size), 1, fp);
|
||||
int32_t size = data.length();
|
||||
if (write(fd, &size, sizeof(size)) != sizeof(size)) {
|
||||
throw ioexception("Cannot write protobuf header");
|
||||
}
|
||||
|
||||
// Write the actual protobuf data
|
||||
void *buf = malloc(size);
|
||||
memcpy(buf, data.data(), size);
|
||||
fwrite(buf, size, 1, fp);
|
||||
fflush(fp);
|
||||
if (write(fd, buf, size) != size) {
|
||||
free(buf);
|
||||
|
||||
throw ioexception("Cannot write protobuf data");
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
@ -41,17 +45,15 @@ void SerializeProtobufData(FILE *fp, const string& data)
|
||||
string DeserializeProtobufData(int fd)
|
||||
{
|
||||
// First read the header with the size of the protobuf data
|
||||
size_t size;
|
||||
size_t res = read(fd, &size, sizeof(int));
|
||||
if (res != sizeof(int)) {
|
||||
int32_t size;
|
||||
if (read(fd, &size, sizeof(size)) != sizeof(size)) {
|
||||
// No more data
|
||||
return "";
|
||||
}
|
||||
|
||||
// Read the actual protobuf data
|
||||
void *buf = malloc(size);
|
||||
res = read(fd, buf, size);
|
||||
if (res != size) {
|
||||
if (read(fd, buf, size) != (ssize_t)size) {
|
||||
free(buf);
|
||||
|
||||
throw ioexception("Missing protobuf data");
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
void SerializeProtobufData(FILE *fp, const std::string& data);
|
||||
void SerializeProtobufData(int fd, const std::string& data);
|
||||
std::string DeserializeProtobufData(int fd);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user