diff --git a/src/Message.cpp b/src/Message.cpp new file mode 100644 index 0000000000..609fd2e5b3 --- /dev/null +++ b/src/Message.cpp @@ -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(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(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(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, + 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) { + 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 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 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; + } +} diff --git a/src/Message.h b/src/Message.h new file mode 100644 index 0000000000..ef70b6b377 --- /dev/null +++ b/src/Message.h @@ -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 + +#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, + unsigned int flags); + static Message EntryUpdate(unsigned int id, unsigned int seq_num, + std::shared_ptr 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 params); + static Message ExecuteRpc(unsigned int id, unsigned int uid, + llvm::StringRef params); + static Message RpcResponse(unsigned int id, unsigned int uid, + llvm::ArrayRef 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 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_ diff --git a/src/MessageReader.cpp b/src/MessageReader.cpp deleted file mode 100644 index 9fc308b1af..0000000000 --- a/src/MessageReader.cpp +++ /dev/null @@ -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 -#include -#include - -#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(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; -} diff --git a/src/MessageReader.h b/src/MessageReader.h deleted file mode 100644 index f0ff76e259..0000000000 --- a/src/MessageReader.h +++ /dev/null @@ -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_ diff --git a/src/MessageWriter.cpp b/src/MessageWriter.cpp deleted file mode 100644 index c481dabbaf..0000000000 --- a/src/MessageWriter.cpp +++ /dev/null @@ -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 params) { - WriteRpc(NT_MSG_EXECUTE_RPC, id, uid, params); -} - -void MessageWriter::WriteRpcResponse(unsigned int id, unsigned int uid, - llvm::ArrayRef results) { - WriteRpc(NT_MSG_RPC_RESPONSE, id, uid, results); -} - -void MessageWriter::WriteRpc(unsigned int msg_type, unsigned int id, - unsigned int uid, - llvm::ArrayRef 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); -} diff --git a/src/MessageWriter.h b/src/MessageWriter.h deleted file mode 100644 index d21a96e197..0000000000 --- a/src/MessageWriter.h +++ /dev/null @@ -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 params); - void WriteRpcResponse(unsigned int id, unsigned int uid, - llvm::ArrayRef 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 values); -}; - -} // namespace ntimpl - -#endif // NT_MESSAGEWRITER_H_ diff --git a/src/Value.h b/src/Value.h index 1015e36ba5..d028110e32 100644 --- a/src/Value.h +++ b/src/Value.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); } diff --git a/src/WireDecoder.cpp b/src/WireDecoder.cpp index 8682c997a9..d161e832e2 100644 --- a/src/WireDecoder.cpp +++ b/src/WireDecoder.cpp @@ -12,7 +12,6 @@ #include #include -#include "internal.h" #include "leb128.h" using namespace ntimpl; diff --git a/src/WireDecoder.h b/src/WireDecoder.h index 053ea90728..749279a9dd 100644 --- a/src/WireDecoder.h +++ b/src/WireDecoder.h @@ -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 diff --git a/src/WireEncoder.cpp b/src/WireEncoder.cpp index 47fc7c13a5..9c5a3c66df 100644 --- a/src/WireEncoder.cpp +++ b/src/WireEncoder.cpp @@ -12,7 +12,6 @@ #include #include -#include "internal.h" #include "leb128.h" using namespace ntimpl; diff --git a/src/WireEncoder.h b/src/WireEncoder.h index 487c0f4710..2f6a804217 100644 --- a/src/WireEncoder.h +++ b/src/WireEncoder.h @@ -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. */ diff --git a/src/internal.h b/src/internal.h deleted file mode 100644 index 1d9f0849ff..0000000000 --- a/src/internal.h +++ /dev/null @@ -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_