mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
Replace MessageReader and MessageWriter with Message.
Change-Id: I4b23d5a1e0e39dc2487f252a0947f11328e33090
This commit is contained in:
330
src/Message.cpp
Normal file
330
src/Message.cpp
Normal 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(¶ms, 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
95
src/Message.h
Normal 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_
|
||||
@@ -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(¶ms, 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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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); }
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "internal.h"
|
||||
#include "leb128.h"
|
||||
|
||||
using namespace ntimpl;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "internal.h"
|
||||
#include "leb128.h"
|
||||
|
||||
using namespace ntimpl;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user