blob: 161d303ed7d114ad208f9386ad7cd315b44d55b2 [file] [log] [blame]
Brian Silvermanf7bd1c22015-12-24 16:07:11 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2015. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "Message.h"
9
10#include "Log.h"
11#include "WireDecoder.h"
12#include "WireEncoder.h"
13
14#define kClearAllMagic 0xD06CB27Aul
15
16using namespace nt;
17
18std::shared_ptr<Message> Message::Read(WireDecoder& decoder,
19 GetEntryTypeFunc get_entry_type) {
20 unsigned int msg_type;
21 if (!decoder.Read8(&msg_type)) return nullptr;
22 auto msg =
23 std::make_shared<Message>(static_cast<MsgType>(msg_type), private_init());
24 switch (msg_type) {
25 case kKeepAlive:
26 break;
27 case kClientHello: {
28 unsigned int proto_rev;
29 if (!decoder.Read16(&proto_rev)) return nullptr;
30 msg->m_id = proto_rev;
31 // This intentionally uses the provided proto_rev instead of
32 // decoder.proto_rev().
33 if (proto_rev >= 0x0300u) {
34 if (!decoder.ReadString(&msg->m_str)) return nullptr;
35 }
36 break;
37 }
38 case kProtoUnsup: {
39 if (!decoder.Read16(&msg->m_id)) return nullptr; // proto rev
40 break;
41 }
42 case kServerHelloDone:
43 if (decoder.proto_rev() < 0x0300u) {
44 decoder.set_error("received SERVER_HELLO_DONE in protocol < 3.0");
45 return nullptr;
46 }
47 break;
48 case kServerHello:
49 if (decoder.proto_rev() < 0x0300u) {
50 decoder.set_error("received SERVER_HELLO_DONE in protocol < 3.0");
51 return nullptr;
52 }
53 if (!decoder.Read8(&msg->m_flags)) return nullptr;
54 if (!decoder.ReadString(&msg->m_str)) return nullptr;
55 break;
56 case kClientHelloDone:
57 if (decoder.proto_rev() < 0x0300u) {
58 decoder.set_error("received CLIENT_HELLO_DONE in protocol < 3.0");
59 return nullptr;
60 }
61 break;
62 case kEntryAssign: {
63 if (!decoder.ReadString(&msg->m_str)) return nullptr;
64 NT_Type type;
65 if (!decoder.ReadType(&type)) return nullptr; // name
66 if (!decoder.Read16(&msg->m_id)) return nullptr; // id
67 if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // seq num
68 if (decoder.proto_rev() >= 0x0300u) {
69 if (!decoder.Read8(&msg->m_flags)) return nullptr; // flags
70 }
71 msg->m_value = decoder.ReadValue(type);
72 if (!msg->m_value) return nullptr;
73 break;
74 }
75 case kEntryUpdate: {
76 if (!decoder.Read16(&msg->m_id)) return nullptr; // id
77 if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // seq num
78 NT_Type type;
79 if (decoder.proto_rev() >= 0x0300u) {
80 if (!decoder.ReadType(&type)) return nullptr;
81 } else {
82 type = get_entry_type(msg->m_id);
83 }
84 DEBUG4("update message data type: " << type);
85 msg->m_value = decoder.ReadValue(type);
86 if (!msg->m_value) return nullptr;
87 break;
88 }
89 case kFlagsUpdate: {
90 if (decoder.proto_rev() < 0x0300u) {
91 decoder.set_error("received FLAGS_UPDATE in protocol < 3.0");
92 return nullptr;
93 }
94 if (!decoder.Read16(&msg->m_id)) return nullptr;
95 if (!decoder.Read8(&msg->m_flags)) return nullptr;
96 break;
97 }
98 case kEntryDelete: {
99 if (decoder.proto_rev() < 0x0300u) {
100 decoder.set_error("received ENTRY_DELETE in protocol < 3.0");
101 return nullptr;
102 }
103 if (!decoder.Read16(&msg->m_id)) return nullptr;
104 break;
105 }
106 case kClearEntries: {
107 if (decoder.proto_rev() < 0x0300u) {
108 decoder.set_error("received CLEAR_ENTRIES in protocol < 3.0");
109 return nullptr;
110 }
111 unsigned long magic;
112 if (!decoder.Read32(&magic)) return nullptr;
113 if (magic != kClearAllMagic) {
114 decoder.set_error(
115 "received incorrect CLEAR_ENTRIES magic value, ignoring");
116 return nullptr;
117 }
118 break;
119 }
120 case kExecuteRpc: {
121 if (decoder.proto_rev() < 0x0300u) {
122 decoder.set_error("received EXECUTE_RPC in protocol < 3.0");
123 return nullptr;
124 }
125 if (!decoder.Read16(&msg->m_id)) return nullptr;
126 if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // uid
127 unsigned long size;
128 if (!decoder.ReadUleb128(&size)) return nullptr;
129 const char* params;
130 if (!decoder.Read(&params, size)) return nullptr;
131 msg->m_str = llvm::StringRef(params, size);
132 break;
133 }
134 case kRpcResponse: {
135 if (decoder.proto_rev() < 0x0300u) {
136 decoder.set_error("received RPC_RESPONSE in protocol < 3.0");
137 return nullptr;
138 }
139 if (!decoder.Read16(&msg->m_id)) return nullptr;
140 if (!decoder.Read16(&msg->m_seq_num_uid)) return nullptr; // uid
141 unsigned long size;
142 if (!decoder.ReadUleb128(&size)) return nullptr;
143 const char* results;
144 if (!decoder.Read(&results, size)) return nullptr;
145 msg->m_str = llvm::StringRef(results, size);
146 break;
147 }
148 default:
149 decoder.set_error("unrecognized message type");
150 INFO("unrecognized message type: " << msg_type);
151 return nullptr;
152 }
153 return msg;
154}
155
156std::shared_ptr<Message> Message::ClientHello(llvm::StringRef self_id) {
157 auto msg = std::make_shared<Message>(kClientHello, private_init());
158 msg->m_str = self_id;
159 return msg;
160}
161
162std::shared_ptr<Message> Message::ServerHello(unsigned int flags,
163 llvm::StringRef self_id) {
164 auto msg = std::make_shared<Message>(kServerHello, private_init());
165 msg->m_str = self_id;
166 msg->m_flags = flags;
167 return msg;
168}
169
170std::shared_ptr<Message> Message::EntryAssign(llvm::StringRef name,
171 unsigned int id,
172 unsigned int seq_num,
173 std::shared_ptr<Value> value,
174 unsigned int flags) {
175 auto msg = std::make_shared<Message>(kEntryAssign, private_init());
176 msg->m_str = name;
177 msg->m_value = value;
178 msg->m_id = id;
179 msg->m_flags = flags;
180 msg->m_seq_num_uid = seq_num;
181 return msg;
182}
183
184std::shared_ptr<Message> Message::EntryUpdate(unsigned int id,
185 unsigned int seq_num,
186 std::shared_ptr<Value> value) {
187 auto msg = std::make_shared<Message>(kEntryUpdate, private_init());
188 msg->m_value = value;
189 msg->m_id = id;
190 msg->m_seq_num_uid = seq_num;
191 return msg;
192}
193
194std::shared_ptr<Message> Message::FlagsUpdate(unsigned int id,
195 unsigned int flags) {
196 auto msg = std::make_shared<Message>(kFlagsUpdate, private_init());
197 msg->m_id = id;
198 msg->m_flags = flags;
199 return msg;
200}
201
202std::shared_ptr<Message> Message::EntryDelete(unsigned int id) {
203 auto msg = std::make_shared<Message>(kEntryDelete, private_init());
204 msg->m_id = id;
205 return msg;
206}
207
208std::shared_ptr<Message> Message::ExecuteRpc(unsigned int id, unsigned int uid,
209 llvm::StringRef params) {
210 auto msg = std::make_shared<Message>(kExecuteRpc, private_init());
211 msg->m_str = params;
212 msg->m_id = id;
213 msg->m_seq_num_uid = uid;
214 return msg;
215}
216
217std::shared_ptr<Message> Message::RpcResponse(unsigned int id, unsigned int uid,
218 llvm::StringRef results) {
219 auto msg = std::make_shared<Message>(kRpcResponse, private_init());
220 msg->m_str = results;
221 msg->m_id = id;
222 msg->m_seq_num_uid = uid;
223 return msg;
224}
225
226void Message::Write(WireEncoder& encoder) const {
227 switch (m_type) {
228 case kKeepAlive:
229 encoder.Write8(kKeepAlive);
230 break;
231 case kClientHello:
232 encoder.Write8(kClientHello);
233 encoder.Write16(encoder.proto_rev());
234 if (encoder.proto_rev() < 0x0300u) return;
235 encoder.WriteString(m_str);
236 break;
237 case kProtoUnsup:
238 encoder.Write8(kProtoUnsup);
239 encoder.Write16(encoder.proto_rev());
240 break;
241 case kServerHelloDone:
242 encoder.Write8(kServerHelloDone);
243 break;
244 case kServerHello:
245 if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
246 encoder.Write8(kServerHello);
247 encoder.Write8(m_flags);
248 encoder.WriteString(m_str);
249 break;
250 case kClientHelloDone:
251 if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
252 encoder.Write8(kClientHelloDone);
253 break;
254 case kEntryAssign:
255 encoder.Write8(kEntryAssign);
256 encoder.WriteString(m_str);
257 encoder.WriteType(m_value->type());
258 encoder.Write16(m_id);
259 encoder.Write16(m_seq_num_uid);
260 if (encoder.proto_rev() >= 0x0300u) encoder.Write8(m_flags);
261 encoder.WriteValue(*m_value);
262 break;
263 case kEntryUpdate:
264 encoder.Write8(kEntryUpdate);
265 encoder.Write16(m_id);
266 encoder.Write16(m_seq_num_uid);
267 if (encoder.proto_rev() >= 0x0300u) encoder.WriteType(m_value->type());
268 encoder.WriteValue(*m_value);
269 break;
270 case kFlagsUpdate:
271 if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
272 encoder.Write8(kFlagsUpdate);
273 encoder.Write16(m_id);
274 encoder.Write8(m_flags);
275 break;
276 case kEntryDelete:
277 if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
278 encoder.Write8(kEntryDelete);
279 encoder.Write16(m_id);
280 break;
281 case kClearEntries:
282 if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
283 encoder.Write8(kClearEntries);
284 encoder.Write32(kClearAllMagic);
285 break;
286 case kExecuteRpc:
287 if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
288 encoder.Write8(kExecuteRpc);
289 encoder.Write16(m_id);
290 encoder.Write16(m_seq_num_uid);
291 encoder.WriteString(m_str);
292 break;
293 case kRpcResponse:
294 if (encoder.proto_rev() < 0x0300u) return; // new message in version 3.0
295 encoder.Write8(kRpcResponse);
296 encoder.Write16(m_id);
297 encoder.Write16(m_seq_num_uid);
298 encoder.WriteString(m_str);
299 break;
300 default:
301 break;
302 }
303}