blob: c50b3d4b649eec5d28f5bacfa2435f54f7d249bd [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 "ntcore.h"
9
10#include <cassert>
11#include <cstdio>
12#include <cstdlib>
13
14#include "Dispatcher.h"
15#include "Log.h"
16#include "Notifier.h"
17#include "RpcServer.h"
18#include "Storage.h"
19#include "WireDecoder.h"
20#include "WireEncoder.h"
21
22namespace nt {
23
24/*
25 * Table Functions
26 */
27
28std::shared_ptr<Value> GetEntryValue(StringRef name) {
29 return Storage::GetInstance().GetEntryValue(name);
30}
31
32bool SetEntryValue(StringRef name, std::shared_ptr<Value> value) {
33 return Storage::GetInstance().SetEntryValue(name, value);
34}
35
36void SetEntryTypeValue(StringRef name, std::shared_ptr<Value> value) {
37 Storage::GetInstance().SetEntryTypeValue(name, value);
38}
39
40void SetEntryFlags(StringRef name, unsigned int flags) {
41 Storage::GetInstance().SetEntryFlags(name, flags);
42}
43
44unsigned int GetEntryFlags(StringRef name) {
45 return Storage::GetInstance().GetEntryFlags(name);
46}
47
48void DeleteEntry(StringRef name) {
49 Storage::GetInstance().DeleteEntry(name);
50}
51
52void DeleteAllEntries() {
53 Storage::GetInstance().DeleteAllEntries();
54}
55
56std::vector<EntryInfo> GetEntryInfo(StringRef prefix, unsigned int types) {
57 return Storage::GetInstance().GetEntryInfo(prefix, types);
58}
59
60void Flush() {
61 Dispatcher::GetInstance().Flush();
62}
63
64/*
65 * Callback Creation Functions
66 */
67
68void SetListenerOnStart(std::function<void()> on_start) {
69 Notifier::GetInstance().SetOnStart(on_start);
70}
71
72void SetListenerOnExit(std::function<void()> on_exit) {
73 Notifier::GetInstance().SetOnExit(on_exit);
74}
75
76unsigned int AddEntryListener(StringRef prefix, EntryListenerCallback callback,
77 unsigned int flags) {
78 Notifier& notifier = Notifier::GetInstance();
79 unsigned int uid = notifier.AddEntryListener(prefix, callback, flags);
80 notifier.Start();
81 if ((flags & NT_NOTIFY_IMMEDIATE) != 0)
82 Storage::GetInstance().NotifyEntries(prefix, callback);
83 return uid;
84}
85
86void RemoveEntryListener(unsigned int entry_listener_uid) {
87 Notifier::GetInstance().RemoveEntryListener(entry_listener_uid);
88}
89
90unsigned int AddConnectionListener(ConnectionListenerCallback callback,
91 bool immediate_notify) {
92 Notifier& notifier = Notifier::GetInstance();
93 unsigned int uid = notifier.AddConnectionListener(callback);
94 Notifier::GetInstance().Start();
95 if (immediate_notify) Dispatcher::GetInstance().NotifyConnections(callback);
96 return uid;
97}
98
99void RemoveConnectionListener(unsigned int conn_listener_uid) {
100 Notifier::GetInstance().RemoveConnectionListener(conn_listener_uid);
101}
102
103bool NotifierDestroyed() { return Notifier::destroyed(); }
104
105/*
106 * Remote Procedure Call Functions
107 */
108
109void CreateRpc(StringRef name, StringRef def, RpcCallback callback) {
110 Storage::GetInstance().CreateRpc(name, def, callback);
111}
112
113void CreatePolledRpc(StringRef name, StringRef def) {
114 Storage::GetInstance().CreatePolledRpc(name, def);
115}
116
117bool PollRpc(bool blocking, RpcCallInfo* call_info) {
118 return RpcServer::GetInstance().PollRpc(blocking, call_info);
119}
120
121void PostRpcResponse(unsigned int rpc_id, unsigned int call_uid,
122 StringRef result) {
123 RpcServer::GetInstance().PostRpcResponse(rpc_id, call_uid, result);
124}
125
126unsigned int CallRpc(StringRef name, StringRef params) {
127 return Storage::GetInstance().CallRpc(name, params);
128}
129
130bool GetRpcResult(bool blocking, unsigned int call_uid, std::string* result) {
131 return Storage::GetInstance().GetRpcResult(blocking, call_uid, result);
132}
133
134std::string PackRpcDefinition(const RpcDefinition& def) {
135 WireEncoder enc(0x0300);
136 enc.Write8(def.version);
137 enc.WriteString(def.name);
138
139 // parameters
140 unsigned int params_size = def.params.size();
141 if (params_size > 0xff) params_size = 0xff;
142 enc.Write8(params_size);
143 for (std::size_t i = 0; i < params_size; ++i) {
144 enc.WriteType(def.params[i].def_value->type());
145 enc.WriteString(def.params[i].name);
146 enc.WriteValue(*def.params[i].def_value);
147 }
148
149 // results
150 unsigned int results_size = def.results.size();
151 if (results_size > 0xff) results_size = 0xff;
152 enc.Write8(results_size);
153 for (std::size_t i = 0; i < results_size; ++i) {
154 enc.WriteType(def.results[i].type);
155 enc.WriteString(def.results[i].name);
156 }
157
158 return enc.ToStringRef();
159}
160
161bool UnpackRpcDefinition(StringRef packed, RpcDefinition* def) {
162 raw_mem_istream is(packed.data(), packed.size());
163 WireDecoder dec(is, 0x0300);
164 if (!dec.Read8(&def->version)) return false;
165 if (!dec.ReadString(&def->name)) return false;
166
167 // parameters
168 unsigned int params_size;
169 if (!dec.Read8(&params_size)) return false;
170 def->params.resize(0);
171 def->params.reserve(params_size);
172 for (std::size_t i = 0; i < params_size; ++i) {
173 RpcParamDef pdef;
174 NT_Type type;
175 if (!dec.ReadType(&type)) return false;
176 if (!dec.ReadString(&pdef.name)) return false;
177 pdef.def_value = dec.ReadValue(type);
178 if (!pdef.def_value) return false;
179 def->params.emplace_back(std::move(pdef));
180 }
181
182 // results
183 unsigned int results_size;
184 if (!dec.Read8(&results_size)) return false;
185 def->results.resize(0);
186 def->results.reserve(results_size);
187 for (std::size_t i = 0; i < results_size; ++i) {
188 RpcResultDef rdef;
189 if (!dec.ReadType(&rdef.type)) return false;
190 if (!dec.ReadString(&rdef.name)) return false;
191 def->results.emplace_back(std::move(rdef));
192 }
193
194 return true;
195}
196
197std::string PackRpcValues(ArrayRef<std::shared_ptr<Value>> values) {
198 WireEncoder enc(0x0300);
199 for (auto& value : values) enc.WriteValue(*value);
200 return enc.ToStringRef();
201}
202
203std::vector<std::shared_ptr<Value>> UnpackRpcValues(StringRef packed,
204 ArrayRef<NT_Type> types) {
205 raw_mem_istream is(packed.data(), packed.size());
206 WireDecoder dec(is, 0x0300);
207 std::vector<std::shared_ptr<Value>> vec;
208 for (auto type : types) {
209 auto item = dec.ReadValue(type);
210 if (!item) return std::vector<std::shared_ptr<Value>>();
211 vec.emplace_back(std::move(item));
212 }
213 return vec;
214}
215
216/*
217 * Client/Server Functions
218 */
219
220void SetNetworkIdentity(StringRef name) {
221 Dispatcher::GetInstance().SetIdentity(name);
222}
223
224void StartServer(StringRef persist_filename, const char *listen_address,
225 unsigned int port) {
226 Dispatcher::GetInstance().StartServer(persist_filename, listen_address, port);
227}
228
229void StopServer() {
230 Dispatcher::GetInstance().Stop();
231}
232
233void StartClient(const char *server_name, unsigned int port) {
234 Dispatcher::GetInstance().StartClient(server_name, port);
235}
236
237void StopClient() {
238 Dispatcher::GetInstance().Stop();
239}
240
241void StopRpcServer() {
242 RpcServer::GetInstance().Stop();
243}
244
245void StopNotifier() {
246 Notifier::GetInstance().Stop();
247}
248
249void SetUpdateRate(double interval) {
250 Dispatcher::GetInstance().SetUpdateRate(interval);
251}
252
253std::vector<ConnectionInfo> GetConnections() {
254 return Dispatcher::GetInstance().GetConnections();
255}
256
257/*
258 * Persistent Functions
259 */
260
261const char* SavePersistent(StringRef filename) {
262 return Storage::GetInstance().SavePersistent(filename, false);
263}
264
265const char* LoadPersistent(
266 StringRef filename,
267 std::function<void(size_t line, const char* msg)> warn) {
268 return Storage::GetInstance().LoadPersistent(filename, warn);
269}
270
271void SetLogger(LogFunc func, unsigned int min_level) {
272 Logger& logger = Logger::GetInstance();
273 logger.SetLogger(func);
274 logger.set_min_level(min_level);
275}
276
277} // namespace nt