Replace MessageReader and MessageWriter with Message.

Change-Id: I4b23d5a1e0e39dc2487f252a0947f11328e33090
This commit is contained in:
Peter Johnson
2015-07-12 11:24:34 -07:00
parent 1760d32019
commit 2016bcb37a
12 changed files with 435 additions and 446 deletions

330
src/Message.cpp Normal file
View File

@@ -0,0 +1,330 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "Message.h"
#include "WireDecoder.h"
#include "WireEncoder.h"
static constexpr unsigned long kClearAllMagic = 0xD06CB27Aul;
using namespace ntimpl;
bool Message::Read(WireDecoder& decoder,
NT_Type (*get_entry_type)(unsigned int id), Message* msg) {
unsigned int msg_type;
if (!decoder.Read8(&msg_type)) return false;
switch (msg_type) {
case kKeepAlive:
*msg = KeepAlive();
break;
case kClientHello: {
unsigned int proto_rev;
if (!decoder.Read16(&proto_rev)) return false;
StringValue self_id;
// This intentionally uses the provided proto_rev instead of
// decoder.proto_rev().
if (proto_rev >= 0x0300u) {
if (!decoder.ReadString(&self_id)) return false;
}
*msg = Message(kClientHello);
msg->m_str = std::move(self_id);
msg->m_id = proto_rev;
break;
}
case kProtoUnsup: {
unsigned int proto_rev;
if (!decoder.Read16(&proto_rev)) return false;
*msg = ProtoUnsup();
msg->m_id = proto_rev;
break;
}
case kServerHelloDone:
if (decoder.proto_rev() < 0x0300u) {
decoder.set_error("received SERVER_HELLO_DONE in protocol < 3.0");
return false;
}
*msg = ServerHelloDone();
break;
case kClientHelloDone:
if (decoder.proto_rev() < 0x0300u) {
decoder.set_error("received CLIENT_HELLO_DONE in protocol < 3.0");
return false;
}
*msg = ClientHelloDone();
break;
case kEntryAssign: {
StringValue name;
if (!decoder.ReadString(&name)) return false;
NT_Type type;
if (!decoder.ReadType(&type)) return false;
unsigned int id, seq_num;
if (!decoder.Read16(&id)) return false;
if (!decoder.Read16(&seq_num)) return false;
unsigned int flags = 0;
if (decoder.proto_rev() >= 0x0300u) {
if (!decoder.Read8(&flags)) return false;
}
Value value;
if (!decoder.ReadValue(type, &value)) return false;
*msg = Message(kEntryAssign);
msg->m_str = std::move(name);
msg->m_value = std::make_shared<Value>(std::move(value));
msg->m_id = id;
msg->m_flags = flags;
msg->m_seq_num_uid = seq_num;
break;
}
case kEntryUpdate: {
unsigned int id, seq_num;
if (!decoder.Read16(&id)) return false;
if (!decoder.Read16(&seq_num)) return false;
NT_Type type;
if (decoder.proto_rev() >= 0x0300u) {
unsigned int itype;
if (!decoder.Read8(&itype)) return false;
type = static_cast<NT_Type>(itype);
} else
type = get_entry_type(id);
Value value;
if (!decoder.ReadValue(type, &value)) return false;
*msg = Message(kEntryUpdate);
msg->m_value = std::make_shared<Value>(std::move(value));
msg->m_id = id;
msg->m_seq_num_uid = seq_num;
break;
}
case kFlagsUpdate: {
if (decoder.proto_rev() < 0x0300u) {
decoder.set_error("received FLAGS_UPDATE in protocol < 3.0");
return false;
}
unsigned int id, flags;
if (!decoder.Read16(&id)) return false;
if (!decoder.Read8(&flags)) return false;
*msg = FlagsUpdate(id, flags);
break;
}
case kEntryDelete: {
if (decoder.proto_rev() < 0x0300u) {
decoder.set_error("received ENTRY_DELETE in protocol < 3.0");
return false;
}
unsigned int id;
if (!decoder.Read16(&id)) return false;
*msg = EntryDelete(id);
break;
}
case kClearEntries: {
if (decoder.proto_rev() < 0x0300u) {
decoder.set_error("received CLEAR_ENTRIES in protocol < 3.0");
return false;
}
unsigned long magic;
if (!decoder.Read32(&magic)) return false;
if (magic != kClearAllMagic) {
decoder.set_error(
"received incorrect CLEAR_ENTRIES magic value, ignoring");
return true;
}
*msg = ClearEntries();
break;
}
case kExecuteRpc: {
if (decoder.proto_rev() < 0x0300u) {
decoder.set_error("received EXECUTE_RPC in protocol < 3.0");
return false;
}
unsigned int id, uid;
if (!decoder.Read16(&id)) return false;
if (!decoder.Read16(&uid)) return false;
unsigned long size;
if (!decoder.ReadUleb128(&size)) return false;
const char* params;
if (!decoder.Read(&params, size)) return false;
*msg = ExecuteRpc(id, uid, llvm::StringRef(params, size));
break;
}
case kRpcResponse: {
if (decoder.proto_rev() < 0x0300u) {
decoder.set_error("received RPC_RESPONSE in protocol < 3.0");
return false;
}
unsigned int id, uid;
if (!decoder.Read16(&id)) return false;
if (!decoder.Read16(&uid)) return false;
unsigned long size;
if (!decoder.ReadUleb128(&size)) return false;
const char* results;
if (!decoder.Read(&results, size)) return false;
*msg = RpcResponse(id, uid, llvm::StringRef(results, size));
break;
}
default:
decoder.set_error("unrecognized message type");
return false;
}
return true;
}
Message Message::ClientHello(llvm::StringRef self_id) {
Message msg(kClientHello);
msg.m_str = StringValue(self_id);
return msg;
}
Message Message::ServerHello(unsigned int flags, llvm::StringRef self_id) {
Message msg(kServerHello);
msg.m_str = StringValue(self_id);
msg.m_flags = flags;
return msg;
}
Message Message::EntryAssign(llvm::StringRef name, unsigned int id,
unsigned int seq_num, std::shared_ptr<Value> value,
unsigned int flags) {
Message msg(kEntryAssign);
msg.m_str = StringValue(name);
msg.m_value = value;
msg.m_id = id;
msg.m_flags = flags;
msg.m_seq_num_uid = seq_num;
return msg;
}
Message Message::EntryUpdate(unsigned int id, unsigned int seq_num,
std::shared_ptr<Value> value) {
Message msg(kEntryUpdate);
msg.m_value = value;
msg.m_id = id;
msg.m_seq_num_uid = seq_num;
return msg;
}
Message Message::FlagsUpdate(unsigned int id, unsigned int flags) {
Message msg(kFlagsUpdate);
msg.m_id = id;
msg.m_flags = flags;
return msg;
}
Message Message::EntryDelete(unsigned int id) {
Message msg(kEntryDelete);
msg.m_id = id;
return msg;
}
Message Message::ExecuteRpc(unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> params) {
WireEncoder enc(0x0300);
for (auto& param : params) enc.WriteValue(param);
return ExecuteRpc(id, uid, enc.ToStringRef());
}
Message Message::ExecuteRpc(unsigned int id, unsigned int uid,
llvm::StringRef params) {
Message msg(kExecuteRpc);
msg.m_str = StringValue(params);
msg.m_id = id;
msg.m_seq_num_uid = uid;
return msg;
}
Message Message::RpcResponse(unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> results) {
WireEncoder enc(0x0300);
for (auto& result : results) enc.WriteValue(result);
return RpcResponse(id, uid, enc.ToStringRef());
}
Message Message::RpcResponse(unsigned int id, unsigned int uid,
llvm::StringRef results) {
Message msg(kRpcResponse);
msg.m_str = StringValue(results);
msg.m_id = id;
msg.m_seq_num_uid = uid;
return msg;
}
void Message::Write(WireEncoder& encoder) const {
switch (m_type) {
case kKeepAlive:
encoder.Write8(kKeepAlive);
break;
case kClientHello:
encoder.Write8(kClientHello);
encoder.Write16(encoder.proto_rev());
if (encoder.proto_rev() < 0x0300u) return;
encoder.WriteString(m_str);
break;
case kProtoUnsup:
encoder.Write8(kProtoUnsup);
encoder.Write16(encoder.proto_rev());
break;
case kServerHelloDone:
encoder.Write8(kServerHelloDone);
break;
case kServerHello:
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
encoder.Write8(kServerHello);
encoder.Write8(m_flags);
encoder.WriteString(m_str);
break;
case kClientHelloDone:
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
encoder.Write8(kClientHelloDone);
break;
case kEntryAssign:
encoder.Write8(kEntryAssign);
encoder.WriteString(m_str);
encoder.WriteType(m_value->type());
encoder.Write16(m_id);
encoder.Write16(m_seq_num_uid);
if (encoder.proto_rev() >= 0x0300u) encoder.Write8(m_flags);
encoder.WriteValue(*m_value);
break;
case kEntryUpdate:
encoder.Write8(kEntryUpdate);
encoder.Write16(m_id);
encoder.Write16(m_seq_num_uid);
if (encoder.proto_rev() >= 0x0300u) encoder.Write8(m_value->type());
encoder.WriteValue(*m_value);
break;
case kFlagsUpdate:
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
encoder.Write8(kFlagsUpdate);
encoder.Write16(m_id);
encoder.Write8(m_flags);
break;
case kEntryDelete:
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
encoder.Write8(kEntryDelete);
encoder.Write16(m_id);
break;
case kClearEntries:
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
encoder.Write8(kClearEntries);
encoder.Write32(kClearAllMagic);
break;
case kExecuteRpc:
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
encoder.Write8(kExecuteRpc);
encoder.Write16(m_id);
encoder.Write16(m_seq_num_uid);
encoder.WriteString(m_str);
break;
case kRpcResponse:
if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
encoder.Write8(kRpcResponse);
encoder.Write16(m_id);
encoder.Write16(m_seq_num_uid);
encoder.WriteString(m_str);
break;
default:
break;
}
}

95
src/Message.h Normal file
View File

@@ -0,0 +1,95 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_MESSAGE_H_
#define NT_MESSAGE_H_
#include <memory>
#include "Value.h"
namespace ntimpl {
class WireDecoder;
class WireEncoder;
class Message {
public:
enum MsgType {
kUnknown = -1,
kKeepAlive = 0x00,
kClientHello = 0x01,
kProtoUnsup = 0x02,
kServerHelloDone = 0x03,
kServerHello = 0x04,
kClientHelloDone = 0x05,
kEntryAssign = 0x10,
kEntryUpdate = 0x11,
kFlagsUpdate = 0x12,
kEntryDelete = 0x13,
kClearEntries = 0x14,
kExecuteRpc = 0x20,
kRpcResponse = 0x21
};
Message() : m_type(kUnknown), m_id(0), m_flags(0), m_seq_num_uid(0) {}
MsgType type() const { return m_type; }
bool Is(MsgType type) const { return type == m_type; }
// Read and write from wire representation
void Write(WireEncoder& encoder) const;
static bool Read(WireDecoder& decoder,
NT_Type (*get_entry_type)(unsigned int id), Message* msg);
// Create messages without data
static Message KeepAlive() { return Message(kKeepAlive); }
static Message ProtoUnsup() { return Message(kProtoUnsup); }
static Message ServerHelloDone() { return Message(kServerHelloDone); }
static Message ClientHelloDone() { return Message(kClientHelloDone); }
static Message ClearEntries() { return Message(kClearEntries); }
// Create messages with data
static Message ClientHello(llvm::StringRef self_id);
static Message ServerHello(unsigned int flags, llvm::StringRef self_id);
static Message EntryAssign(llvm::StringRef name, unsigned int id,
unsigned int seq_num, std::shared_ptr<Value> value,
unsigned int flags);
static Message EntryUpdate(unsigned int id, unsigned int seq_num,
std::shared_ptr<Value> value);
static Message FlagsUpdate(unsigned int id, unsigned int flags);
static Message EntryDelete(unsigned int id);
static Message ExecuteRpc(unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> params);
static Message ExecuteRpc(unsigned int id, unsigned int uid,
llvm::StringRef params);
static Message RpcResponse(unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> results);
static Message RpcResponse(unsigned int id, unsigned int uid,
llvm::StringRef results);
Message(const Message&) = delete;
Message& operator=(const Message&) = delete;
Message(Message&&) = default;
Message& operator=(Message&&) = default;
private:
Message(MsgType type);
MsgType m_type;
// Message data. Use varies by message type.
StringValue m_str;
std::shared_ptr<Value> m_value;
unsigned int m_id; // also used for proto_rev
unsigned int m_flags;
unsigned int m_seq_num_uid;
};
} // namespace ntimpl
#endif // NT_MESSAGE_H_

View File

@@ -1,170 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "MessageReader.h"
#include <cassert>
#include <cstdlib>
#include <cstring>
#include "internal.h"
#include "leb128.h"
using namespace ntimpl;
void MessageHandler::anchor() {}
MessageReader::MessageReader(MessageHandler& handler, raw_istream& is,
unsigned int proto_rev)
: WireDecoder(is, proto_rev), m_handler(handler) {}
MessageReader::~MessageReader() {}
bool MessageReader::ReadMessage() {
unsigned int msg_type;
if (!Read8(&msg_type)) return false;
switch (msg_type) {
case NT_MSG_KEEP_ALIVE:
m_handler.GotKeepAlive();
break;
case NT_MSG_CLIENT_HELLO: {
unsigned int proto_rev;
if (!Read16(&proto_rev)) return false;
StringValue self_id;
// This intentionally uses the provided proto_rev instead of
// m_proto_rev.
if (proto_rev >= 0x0300u) {
if (!ReadString(&self_id)) return false;
}
m_handler.GotClientHello(proto_rev, std::move(self_id));
break;
}
case NT_MSG_PROTO_UNSUP: {
unsigned int proto_rev;
if (!Read16(&proto_rev)) return false;
m_handler.GotProtoUnsup(proto_rev);
break;
}
case NT_MSG_SERVER_HELLO_DONE:
if (m_proto_rev < 0x0300u) {
m_error = "received SERVER_HELLO_DONE in protocol < 3.0";
return false;
}
m_handler.GotServerHelloDone();
break;
case NT_MSG_CLIENT_HELLO_DONE:
if (m_proto_rev < 0x0300u) {
m_error = "received CLIENT_HELLO_DONE in protocol < 3.0";
return false;
}
m_handler.GotClientHelloDone();
break;
case NT_MSG_ENTRY_ASSIGN: {
StringValue name;
if (!ReadString(&name)) return false;
NT_Type type;
if (!ReadType(&type)) return false;
unsigned int id, seq_num;
if (!Read16(&id)) return false;
if (!Read16(&seq_num)) return false;
unsigned int flags = 0;
if (m_proto_rev >= 0x0300u) {
if (!Read8(&flags)) return false;
}
Value value;
if (!ReadValue(type, &value)) return false;
m_handler.GotEntryAssign(std::move(name), id, seq_num, std::move(value),
flags);
break;
}
case NT_MSG_ENTRY_UPDATE: {
unsigned int id, seq_num;
Value value;
if (!Read16(&id)) return false;
if (!Read16(&seq_num)) return false;
NT_Type type;
if (m_proto_rev >= 0x0300u) {
unsigned int itype;
if (!Read8(&itype)) return false;
type = static_cast<NT_Type>(itype);
} else
type = m_handler.GetEntryType(id);
if (!ReadValue(type, &value)) return false;
m_handler.GotEntryUpdate(id, seq_num, std::move(value));
break;
}
case NT_MSG_FLAGS_UPDATE: {
if (m_proto_rev < 0x0300u) {
m_error = "received FLAGS_UPDATE in protocol < 3.0";
return false;
}
unsigned int id, flags;
if (!Read16(&id)) return false;
if (!Read8(&flags)) return false;
m_handler.GotFlagsUpdate(id, flags);
break;
}
case NT_MSG_ENTRY_DELETE: {
if (m_proto_rev < 0x0300u) {
m_error = "received ENTRY_DELETE in protocol < 3.0";
return false;
}
unsigned int id;
if (!Read16(&id)) return false;
m_handler.GotEntryDelete(id);
break;
}
case NT_MSG_CLEAR_ENTRIES: {
if (m_proto_rev < 0x0300u) {
m_error = "received CLEAR_ENTRIES in protocol < 3.0";
return false;
}
unsigned long magic;
if (!Read32(&magic)) return false;
if (magic != NT_CLEAR_ALL_MAGIC) {
m_error = "received incorrect CLEAR_ENTRIES magic value, ignoring";
return true;
}
m_handler.GotClearEntries();
break;
}
case NT_MSG_EXECUTE_RPC: {
if (m_proto_rev < 0x0300u) {
m_error = "received EXECUTE_RPC in protocol < 3.0";
return false;
}
unsigned int id, uid;
if (!Read16(&id)) return false;
if (!Read16(&uid)) return false;
unsigned long size;
if (!ReadUleb128(&size)) return false;
const char* params;
if (!Read(&params, size)) return false;
m_handler.GotExecuteRpc(id, uid, llvm::StringRef(params, size));
break;
}
case NT_MSG_RPC_RESPONSE: {
if (m_proto_rev < 0x0300u) {
m_error = "received RPC_RESPONSE in protocol < 3.0";
return false;
}
unsigned int id, uid;
if (!Read16(&id)) return false;
if (!Read16(&uid)) return false;
unsigned long size;
if (!ReadUleb128(&size)) return false;
const char* results;
if (!Read(&results, size)) return false;
m_handler.GotRpcResponse(id, uid, llvm::StringRef(results, size));
break;
}
default:
m_error = "unrecognized message type";
return false;
}
return true;
}

View File

@@ -1,71 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_MESSAGEREADER_H_
#define NT_MESSAGEREADER_H_
#include "Value.h"
#include "WireDecoder.h"
namespace ntimpl {
class MessageHandler {
void anchor();
public:
// Needed for protocol rev 2.0 ENTRY_UPDATE messages.
virtual NT_Type GetEntryType(unsigned int id) = 0;
virtual ~MessageHandler() {}
virtual void GotKeepAlive() = 0;
virtual void GotClientHello(unsigned int proto_rev,
StringValue&& self_id) = 0;
virtual void GotProtoUnsup(unsigned int proto_rev) = 0;
virtual void GotServerHelloDone() = 0;
virtual void GotServerHello(unsigned int flags, StringValue&& self_id) = 0;
virtual void GotClientHelloDone() = 0;
virtual void GotEntryAssign(StringValue&& name, unsigned int id,
unsigned int seq_num, Value&& value,
unsigned int flags) = 0;
virtual void GotEntryUpdate(unsigned int id, unsigned int seq_num,
Value&& value) = 0;
virtual void GotFlagsUpdate(unsigned int id, unsigned int flags) = 0;
virtual void GotEntryDelete(unsigned int id) = 0;
virtual void GotClearEntries() = 0;
virtual void GotExecuteRpc(unsigned int id, unsigned int uid,
llvm::StringRef params) = 0;
virtual void GotRpcResponse(unsigned int id, unsigned int uid,
llvm::StringRef results) = 0;
MessageHandler() = default;
MessageHandler(const MessageHandler&) = delete;
MessageHandler& operator=(const MessageHandler&) = delete;
};
class MessageReader : private WireDecoder {
public:
explicit MessageReader(MessageHandler& handler, raw_istream& is,
unsigned int proto_rev);
~MessageReader();
bool ReadMessage();
using WireDecoder::set_proto_rev;
using WireDecoder::proto_rev;
using WireDecoder::Reset;
using WireDecoder::error;
MessageReader(const MessageReader&) = delete;
MessageReader& operator=(const MessageReader&) = delete;
private:
MessageHandler& m_handler;
};
} // namespace ntimpl
#endif // NT_MESSAGEREADER_H_

View File

@@ -1,110 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "MessageWriter.h"
#include "internal.h"
using namespace ntimpl;
MessageWriter::~MessageWriter() {}
void MessageWriter::WriteKeepAlive() { Write8(NT_MSG_KEEP_ALIVE); }
void MessageWriter::WriteClientHello(llvm::StringRef self_id) {
Write8(NT_MSG_CLIENT_HELLO);
Write16(m_proto_rev);
if (m_proto_rev < 0x0300u) return;
WriteString(self_id);
}
void MessageWriter::WriteProtoUnsup() {
Write8(NT_MSG_PROTO_UNSUP);
Write16(m_proto_rev);
}
void MessageWriter::WriteServerHelloDone() { Write8(NT_MSG_SERVER_HELLO_DONE); }
void MessageWriter::WriteServerHello(unsigned int flags,
llvm::StringRef self_id) {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_SERVER_HELLO);
Write8(flags);
WriteString(self_id);
}
void MessageWriter::WriteClientHelloDone() {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_CLIENT_HELLO_DONE);
}
void MessageWriter::WriteEntryAssign(llvm::StringRef name, unsigned int id,
unsigned int seq_num,
const NT_Value& value,
unsigned int flags) {
Write8(NT_MSG_ENTRY_ASSIGN);
WriteString(name);
WriteType(value.type);
Write16(id);
Write16(seq_num);
if (m_proto_rev >= 0x0300u) Write8(flags);
WriteValue(value);
}
void MessageWriter::WriteEntryUpdate(unsigned int id, unsigned int seq_num,
const NT_Value& value) {
Write8(NT_MSG_ENTRY_UPDATE);
Write16(id);
Write16(seq_num);
if (m_proto_rev >= 0x0300u) Write8(value.type);
WriteValue(value);
}
void MessageWriter::WriteFlagsUpdate(unsigned int id, unsigned int flags) {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_FLAGS_UPDATE);
Write16(id);
Write8(flags);
}
void MessageWriter::WriteEntryDelete(unsigned int id) {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_ENTRY_DELETE);
Write16(id);
}
void MessageWriter::WriteClearEntries() {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(NT_MSG_CLEAR_ENTRIES);
Write32(NT_CLEAR_ALL_MAGIC);
}
void MessageWriter::WriteExecuteRpc(unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> params) {
WriteRpc(NT_MSG_EXECUTE_RPC, id, uid, params);
}
void MessageWriter::WriteRpcResponse(unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> results) {
WriteRpc(NT_MSG_RPC_RESPONSE, id, uid, results);
}
void MessageWriter::WriteRpc(unsigned int msg_type, unsigned int id,
unsigned int uid,
llvm::ArrayRef<NT_Value> values) {
if (m_proto_rev < 0x0300u) return; // new message in version 3.0
Write8(msg_type);
Write16(id);
Write16(uid);
unsigned long len = 0;
for (auto& value : values) len += GetValueSize(value);
WriteUleb128(len);
for (auto& value : values) WriteValue(value);
}

View File

@@ -1,59 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_MESSAGEWRITER_H_
#define NT_MESSAGEWRITER_H_
#include "WireEncoder.h"
#include "llvm/ArrayRef.h"
#include "llvm/StringRef.h"
namespace ntimpl {
class MessageWriter : private WireEncoder {
public:
explicit MessageWriter(unsigned int proto_rev) : WireEncoder(proto_rev) {}
~MessageWriter();
using WireEncoder::set_proto_rev;
using WireEncoder::proto_rev;
using WireEncoder::Reset;
using WireEncoder::error;
using WireEncoder::data;
using WireEncoder::size;
void WriteKeepAlive();
void WriteClientHello(llvm::StringRef self_id);
void WriteProtoUnsup();
void WriteServerHelloDone();
void WriteServerHello(unsigned int flags, llvm::StringRef self_id);
void WriteClientHelloDone();
void WriteEntryAssign(llvm::StringRef name, unsigned int id,
unsigned int seq_num, const NT_Value& value,
unsigned int flags);
void WriteEntryUpdate(unsigned int id, unsigned int seq_num,
const NT_Value& value);
void WriteFlagsUpdate(unsigned int id, unsigned int flags);
void WriteEntryDelete(unsigned int id);
void WriteClearEntries();
void WriteExecuteRpc(unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> params);
void WriteRpcResponse(unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> results);
MessageWriter(const MessageWriter&) = delete;
MessageWriter& operator=(const MessageWriter&) = delete;
private:
void WriteRpc(unsigned int msg_type, unsigned int id, unsigned int uid,
llvm::ArrayRef<NT_Value> values);
};
} // namespace ntimpl
#endif // NT_MESSAGEWRITER_H_

View File

@@ -18,6 +18,7 @@
namespace ntimpl {
class Message;
class StringValueTest;
class Storage;
class Value;
@@ -28,6 +29,7 @@ class WireDecoder;
* C++ wrapper class around NT_String.
*/
class StringValue : private NT_String {
friend class Message;
friend class StringValueTest;
friend class Value;
friend class WireDecoder;
@@ -83,8 +85,9 @@ inline bool operator!=(const StringValue& lhs, llvm::StringRef rhs) {
* C++ wrapper class around NT_Value.
*/
class Value : private NT_Value {
friend class ValueTest;
friend class Message;
friend class Storage;
friend class ValueTest;
friend class WireDecoder;
public:
Value() { NT_InitValue(this); }

View File

@@ -12,7 +12,6 @@
#include <cstdlib>
#include <cstring>
#include "internal.h"
#include "leb128.h"
using namespace ntimpl;

View File

@@ -42,6 +42,8 @@ class WireDecoder {
*/
const char* error() const { return m_error; }
void set_error(const char* error) { m_error = error; }
/* Reads the specified number of bytes.
* @param buf pointer to read data (output parameter)
* @param len number of bytes to read

View File

@@ -12,7 +12,6 @@
#include <cstdlib>
#include <cstring>
#include "internal.h"
#include "leb128.h"
using namespace ntimpl;

View File

@@ -50,6 +50,10 @@ class WireEncoder {
/* Returns number of bytes written to memory buffer. */
std::size_t size() const { return m_cur - m_start; }
llvm::StringRef ToStringRef() const {
return llvm::StringRef(m_start, m_cur - m_start);
}
/* Ensures the buffer has sufficient space to write len bytes. Reallocates
* the buffer if necessary.
*/

View File

@@ -1,33 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2015. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef NT_INTERNAL_H_
#define NT_INTERNAL_H_
namespace ntimpl {
enum MsgType {
NT_MSG_KEEP_ALIVE = 0x00,
NT_MSG_CLIENT_HELLO = 0x01,
NT_MSG_PROTO_UNSUP = 0x02,
NT_MSG_SERVER_HELLO_DONE = 0x03,
NT_MSG_SERVER_HELLO = 0x04,
NT_MSG_CLIENT_HELLO_DONE = 0x05,
NT_MSG_ENTRY_ASSIGN = 0x10,
NT_MSG_ENTRY_UPDATE = 0x11,
NT_MSG_FLAGS_UPDATE = 0x12,
NT_MSG_ENTRY_DELETE = 0x13,
NT_MSG_CLEAR_ENTRIES = 0x14,
NT_MSG_EXECUTE_RPC = 0x20,
NT_MSG_RPC_RESPONSE = 0x21
};
#define NT_CLEAR_ALL_MAGIC 0xD06CB27Aul
} // namespace ntimpl
#endif // NT_INTERNAL_H_