2015-07-12 11:24:34 -07:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
/* 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"
|
|
|
|
|
|
2015-07-20 20:34:19 -07:00
|
|
|
#define kClearAllMagic 0xD06CB27Aul
|
2015-07-12 11:24:34 -07:00
|
|
|
|
2015-07-17 07:21:07 -07:00
|
|
|
using namespace nt;
|
2015-07-12 11:24:34 -07:00
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
|
|
|
|
|
GetEntryTypeFunc get_entry_type) {
|
2015-07-12 11:24:34 -07:00
|
|
|
unsigned int msg_type;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read8(&msg_type)) return nullptr;
|
|
|
|
|
auto msg =
|
|
|
|
|
std::make_shared<Message>(static_cast<MsgType>(msg_type), private_init());
|
2015-07-12 11:24:34 -07:00
|
|
|
switch (msg_type) {
|
|
|
|
|
case kKeepAlive:
|
|
|
|
|
break;
|
|
|
|
|
case kClientHello: {
|
|
|
|
|
unsigned int proto_rev;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read16(&proto_rev)) return nullptr;
|
2015-07-12 23:35:23 -07:00
|
|
|
msg->m_id = proto_rev;
|
2015-07-12 11:24:34 -07:00
|
|
|
// This intentionally uses the provided proto_rev instead of
|
|
|
|
|
// decoder.proto_rev().
|
|
|
|
|
if (proto_rev >= 0x0300u) {
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.ReadString(&msg->m_str)) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kProtoUnsup: {
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read16(&msg->m_id)) return nullptr; // proto rev
|
2015-07-12 11:24:34 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kServerHelloDone:
|
|
|
|
|
if (decoder.proto_rev() < 0x0300u) {
|
|
|
|
|
decoder.set_error("received SERVER_HELLO_DONE in protocol < 3.0");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
|
|
|
|
break;
|
2015-07-31 20:14:15 -07:00
|
|
|
case kServerHello:
|
|
|
|
|
if (decoder.proto_rev() < 0x0300u) {
|
|
|
|
|
decoder.set_error("received SERVER_HELLO_DONE in protocol < 3.0");
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (!decoder.Read8(&msg->m_flags)) return nullptr;
|
|
|
|
|
if (!decoder.ReadString(&msg->m_str)) return nullptr;
|
|
|
|
|
break;
|
2015-07-12 11:24:34 -07:00
|
|
|
case kClientHelloDone:
|
|
|
|
|
if (decoder.proto_rev() < 0x0300u) {
|
|
|
|
|
decoder.set_error("received CLIENT_HELLO_DONE in protocol < 3.0");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case kEntryAssign: {
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.ReadString(&msg->m_str)) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
NT_Type type;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.ReadType(&type)) return nullptr; // name
|
|
|
|
|
if (!decoder.Read16(&msg->m_id)) return nullptr; // id
|
|
|
|
|
if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // seq num
|
2015-07-12 11:24:34 -07:00
|
|
|
if (decoder.proto_rev() >= 0x0300u) {
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read8(&msg->m_flags)) return nullptr; // flags
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
2015-07-16 01:38:27 -07:00
|
|
|
msg->m_value = decoder.ReadValue(type);
|
|
|
|
|
if (!msg->m_value) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kEntryUpdate: {
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read16(&msg->m_id)) return nullptr; // id
|
|
|
|
|
if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // seq num
|
2015-07-12 11:24:34 -07:00
|
|
|
NT_Type type;
|
|
|
|
|
if (decoder.proto_rev() >= 0x0300u) {
|
|
|
|
|
unsigned int itype;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read8(&itype)) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
type = static_cast<NT_Type>(itype);
|
|
|
|
|
} else
|
2015-07-12 23:35:23 -07:00
|
|
|
type = get_entry_type(msg->m_id);
|
2015-07-16 01:38:27 -07:00
|
|
|
msg->m_value = decoder.ReadValue(type);
|
|
|
|
|
if (!msg->m_value) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kFlagsUpdate: {
|
|
|
|
|
if (decoder.proto_rev() < 0x0300u) {
|
|
|
|
|
decoder.set_error("received FLAGS_UPDATE in protocol < 3.0");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read16(&msg->m_id)) return nullptr;
|
|
|
|
|
if (!decoder.Read8(&msg->m_flags)) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kEntryDelete: {
|
|
|
|
|
if (decoder.proto_rev() < 0x0300u) {
|
|
|
|
|
decoder.set_error("received ENTRY_DELETE in protocol < 3.0");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read16(&msg->m_id)) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kClearEntries: {
|
|
|
|
|
if (decoder.proto_rev() < 0x0300u) {
|
|
|
|
|
decoder.set_error("received CLEAR_ENTRIES in protocol < 3.0");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
|
|
|
|
unsigned long magic;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read32(&magic)) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
if (magic != kClearAllMagic) {
|
|
|
|
|
decoder.set_error(
|
|
|
|
|
"received incorrect CLEAR_ENTRIES magic value, ignoring");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kExecuteRpc: {
|
|
|
|
|
if (decoder.proto_rev() < 0x0300u) {
|
|
|
|
|
decoder.set_error("received EXECUTE_RPC in protocol < 3.0");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read16(&msg->m_id)) return nullptr;
|
|
|
|
|
if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // uid
|
2015-07-12 11:24:34 -07:00
|
|
|
unsigned long size;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.ReadUleb128(&size)) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
const char* params;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read(¶ms, size)) return nullptr;
|
2015-07-12 23:35:23 -07:00
|
|
|
msg->m_str = llvm::StringRef(params, size);
|
2015-07-12 11:24:34 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kRpcResponse: {
|
|
|
|
|
if (decoder.proto_rev() < 0x0300u) {
|
|
|
|
|
decoder.set_error("received RPC_RESPONSE in protocol < 3.0");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read16(&msg->m_id)) return nullptr;
|
|
|
|
|
if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // uid
|
2015-07-12 11:24:34 -07:00
|
|
|
unsigned long size;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.ReadUleb128(&size)) return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
const char* results;
|
2015-07-15 21:20:18 -07:00
|
|
|
if (!decoder.Read(&results, size)) return nullptr;
|
2015-07-12 23:35:23 -07:00
|
|
|
msg->m_str = llvm::StringRef(results, size);
|
2015-07-12 11:24:34 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
decoder.set_error("unrecognized message type");
|
2015-07-15 21:20:18 -07:00
|
|
|
return nullptr;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
2015-07-15 21:20:18 -07:00
|
|
|
return msg;
|
2015-07-12 11:24:34 -07:00
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::ClientHello(llvm::StringRef self_id) {
|
|
|
|
|
auto msg = std::make_shared<Message>(kClientHello, private_init());
|
|
|
|
|
msg->m_str = self_id;
|
2015-07-12 11:24:34 -07:00
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::ServerHello(unsigned int flags,
|
|
|
|
|
llvm::StringRef self_id) {
|
|
|
|
|
auto msg = std::make_shared<Message>(kServerHello, private_init());
|
|
|
|
|
msg->m_str = self_id;
|
|
|
|
|
msg->m_flags = flags;
|
2015-07-12 11:24:34 -07:00
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::EntryAssign(llvm::StringRef name,
|
|
|
|
|
unsigned int id,
|
|
|
|
|
unsigned int seq_num,
|
|
|
|
|
std::shared_ptr<Value> value,
|
|
|
|
|
unsigned int flags) {
|
|
|
|
|
auto msg = std::make_shared<Message>(kEntryAssign, private_init());
|
|
|
|
|
msg->m_str = name;
|
|
|
|
|
msg->m_value = value;
|
|
|
|
|
msg->m_id = id;
|
|
|
|
|
msg->m_flags = flags;
|
|
|
|
|
msg->m_seq_num_uid = seq_num;
|
2015-07-12 11:24:34 -07:00
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::EntryUpdate(unsigned int id,
|
|
|
|
|
unsigned int seq_num,
|
|
|
|
|
std::shared_ptr<Value> value) {
|
|
|
|
|
auto msg = std::make_shared<Message>(kEntryUpdate, private_init());
|
|
|
|
|
msg->m_value = value;
|
|
|
|
|
msg->m_id = id;
|
|
|
|
|
msg->m_seq_num_uid = seq_num;
|
2015-07-12 11:24:34 -07:00
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::FlagsUpdate(unsigned int id,
|
|
|
|
|
unsigned int flags) {
|
|
|
|
|
auto msg = std::make_shared<Message>(kFlagsUpdate, private_init());
|
|
|
|
|
msg->m_id = id;
|
|
|
|
|
msg->m_flags = flags;
|
2015-07-12 11:24:34 -07:00
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::EntryDelete(unsigned int id) {
|
|
|
|
|
auto msg = std::make_shared<Message>(kEntryDelete, private_init());
|
|
|
|
|
msg->m_id = id;
|
2015-07-12 11:24:34 -07:00
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::ExecuteRpc(unsigned int id, unsigned int uid,
|
2015-07-16 01:38:27 -07:00
|
|
|
llvm::ArrayRef<Value> params) {
|
2015-07-12 11:24:34 -07:00
|
|
|
WireEncoder enc(0x0300);
|
|
|
|
|
for (auto& param : params) enc.WriteValue(param);
|
|
|
|
|
return ExecuteRpc(id, uid, enc.ToStringRef());
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::ExecuteRpc(unsigned int id, unsigned int uid,
|
|
|
|
|
llvm::StringRef params) {
|
|
|
|
|
auto msg = std::make_shared<Message>(kExecuteRpc, private_init());
|
|
|
|
|
msg->m_str = params;
|
|
|
|
|
msg->m_id = id;
|
|
|
|
|
msg->m_seq_num_uid = uid;
|
2015-07-12 11:24:34 -07:00
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::RpcResponse(
|
2015-07-16 01:38:27 -07:00
|
|
|
unsigned int id, unsigned int uid, llvm::ArrayRef<Value> results) {
|
2015-07-12 11:24:34 -07:00
|
|
|
WireEncoder enc(0x0300);
|
|
|
|
|
for (auto& result : results) enc.WriteValue(result);
|
|
|
|
|
return RpcResponse(id, uid, enc.ToStringRef());
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-15 21:20:18 -07:00
|
|
|
std::shared_ptr<Message> Message::RpcResponse(unsigned int id, unsigned int uid,
|
|
|
|
|
llvm::StringRef results) {
|
|
|
|
|
auto msg = std::make_shared<Message>(kRpcResponse, private_init());
|
|
|
|
|
msg->m_str = results;
|
|
|
|
|
msg->m_id = id;
|
|
|
|
|
msg->m_seq_num_uid = uid;
|
2015-07-12 11:24:34 -07:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|