YARP
Yet Another Robot Platform
NameServer.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef YARP_OS_IMPL_NAMESERVER_H
8#define YARP_OS_IMPL_NAMESERVER_H
9
10#include <yarp/conf/string.h>
11#include <yarp/conf/numeric.h>
12
13#include <yarp/os/Bottle.h>
14#include <yarp/os/Contact.h>
16#include <yarp/os/NetType.h>
17#include <yarp/os/Time.h>
19
20#include <map>
21#include <mutex>
22#include <string>
23#include <vector>
24
26
27namespace yarp::os::impl {
28
33{
34public:
35 virtual ~NameServerStub() = default;
36 virtual std::string apply(const std::string& txt, const Contact& remote) = 0;
37};
38
43{
44public:
46 mutex()
47 {
48 setup();
49 }
50
51 virtual ~NameServer() = default;
52
53 // address may be partial - partial information gets filled in
54 // (not YARP2 compliant yet, won't do fill-in)
55 Contact registerName(const std::string& name,
56 const Contact& address)
57 {
58 return registerName(name, address, "...");
59 }
60
61 Contact registerName(const std::string& name,
62 const Contact& address,
63 const std::string& remote);
64
65 Contact registerName(const std::string& name)
66 {
67 return registerName(name, Contact());
68 }
69
70 Contact queryName(const std::string& name);
71
72 Contact unregisterName(const std::string& name);
73
74 std::string apply(const std::string& txt, const Contact& remote) override;
75
76 bool apply(const yarp::os::Bottle& cmd, yarp::os::Bottle& result, const Contact& remote);
77
78 std::string apply(const std::string& txt)
79 {
80 return apply(txt, Contact());
81 }
82
83 virtual void onEvent(yarp::os::Bottle& event)
84 {
85 YARP_UNUSED(event);
86 }
87
88 static std::string textify(const Contact& address);
89 static yarp::os::Bottle botify(const Contact& address);
90
91 void setBasePort(int basePort)
92 {
93 this->basePort = basePort;
94 mcastRecord.setBasePort(basePort);
95 }
96
97
98private:
99 void setup();
100
101 template <class T>
102 class ReusableRecord
103 {
104 private:
105 std::vector<T> reuse;
106
107 public:
108 virtual ~ReusableRecord() = default;
109
110 virtual T fresh() = 0;
111
112 void release(const T& o)
113 {
114 reuse.push_back(o);
115 }
116
117 T getFree()
118 {
119 if (reuse.size() >= 1) {
120 T result = reuse[reuse.size() - 1];
121 reuse.pop_back();
122 return result;
123 }
124 return fresh();
125 }
126 };
127
128
129 class DisposableNameRecord : public ReusableRecord<int>
130 {
131 private:
132 int base;
133 std::string prefix;
134
135 public:
136 DisposableNameRecord()
137 {
138 base = 1;
139 prefix = "/tmp/port/";
140 }
141
142 std::string get()
143 {
144 return prefix + yarp::conf::numeric::to_string(getFree());
145 }
146
147 int fresh() override
148 {
149 int result = base;
150 base++;
151 return result;
152 }
153
154 bool release(const std::string& name)
155 {
156 if (name.find(prefix) == 0) {
157 std::string num = name.substr(prefix.length());
158 int x = yarp::conf::numeric::from_string<int>(num);
159 ReusableRecord<int>::release(x);
160 return true;
161 }
162 return false;
163 }
164 };
165
166
167 class HostRecord : public ReusableRecord<int>
168 {
169 private:
170 int base;
171
172 public:
173 HostRecord()
174 {
175 // FIXME HostRecord has hardcoded base
176 base = 0;
177 }
178
179 void setBase(int base)
180 {
181 this->base = base;
182 }
183
184 int get()
185 {
186 int result = ReusableRecord<int>::getFree();
187 yCTrace(NAMESERVER, "host record says %d is free", result);
188 return result;
189 }
190
191 int fresh() override
192 {
193 int result = base++;
194 return result;
195 }
196 };
197
198
199 class McastRecord : public ReusableRecord<int>
200 {
201 private:
202 int base;
203 int last;
204 int basePort;
205
206 public:
207 McastRecord()
208 {
209 // FIXME: mcast records are never reused
210 base = 0;
211 basePort = 0;
212 last = 0;
213 }
214
215 void setBasePort(int basePort)
216 {
217 this->basePort = basePort;
218 }
219
220 int fresh() override
221 {
222 int result = base;
223 base++;
224 return result;
225 }
226
227 std::string get()
228 {
229 int x = getFree();
230 last = x;
231 int v1 = x % 255;
232 int v2 = x / 255;
233 yCAssert(NAMESERVER, v2 < 255);
234 return std::string("224.1.") + yarp::conf::numeric::to_string(v2 + 1) + "." + yarp::conf::numeric::to_string(v1 + 1);
235 }
236
237 int lastPortNumber()
238 {
239 return basePort + last;
240 }
241
242 void releaseAddress(const char* addr)
243 {
244 auto ss = yarp::conf::string::split(addr, '.');
245 constexpr size_t ipv4_size = 4;
246 int ip[] = {224, 3, 1, 1};
247 yCAssert(NAMESERVER, ss.size() == ipv4_size);
248 for (size_t i = 0; i < ipv4_size; ++i) {
249 ip[i] = yarp::conf::numeric::from_string<int>(ss[i]);
250 }
251
252 int v2 = ip[2] - 1;
253 int v1 = ip[3] - 1;
254 int x = v2 * 255 + v1;
255 yCInfo(NAMESERVER, "Releasing %s %d %d:%d\n", addr, x, v2, v1);
256 release(x);
257 }
258 };
259
260
261 class PropertyRecord
262 {
263 private:
264 std::vector<std::string> prop;
265
266 public:
267 PropertyRecord()
268 {
269 }
270
271 void clear()
272 {
273 prop.clear();
274 }
275
276 void add(const std::string& p)
277 {
278 prop.push_back(p);
279 }
280
281 bool check(const std::string& p)
282 {
283 for (unsigned int i = 0; i < prop.size(); i++) {
284 if (prop[i] == p) {
285 return true;
286 }
287 }
288 return false;
289 }
290
291 std::string match(const std::string& str)
292 {
293 std::string base = "";
294 bool needSpace = false;
295 for (unsigned int i = 0; i < prop.size(); i++) {
296 if (prop[i].find(str) == 0) {
297 if (needSpace) {
298 base += " ";
299 }
300 base += prop[i];
301 needSpace = true;
302 }
303 }
304 return base;
305 }
306
307 std::string toString() const
308 {
309 std::string base = "";
310 for (unsigned int i = 0; i < prop.size(); i++) {
311 if (i > 0) {
312 base += " ";
313 }
314 base += prop[i];
315 }
316 return base;
317 }
318 };
319
320 class NameRecord
321 {
322 private:
323 bool reusablePort;
324 bool reusableIp;
325 std::map<std::string, PropertyRecord> propMap;
326 Contact address;
327
328 public:
329 NameRecord() :
330 address()
331 {
332 reusableIp = false;
333 reusablePort = false;
334 }
335
336 NameRecord(const NameRecord& alt) :
337 address()
338 {
339 YARP_UNUSED(alt);
340 reusableIp = false;
341 reusablePort = false;
342 }
343
344 bool isReusablePort()
345 {
346 return reusablePort;
347 }
348
349 bool isReusableIp()
350 {
351 return reusableIp;
352 }
353
354 void clear()
355 {
356 propMap.clear();
357 address = Contact();
358 reusableIp = false;
359 reusablePort = false;
360 }
361
362 void setAddress(const Contact& address,
363 bool reusablePort = false,
364 bool reusableIp = false)
365 {
366 this->address = address;
367 this->reusablePort = reusablePort;
368 this->reusableIp = reusableIp;
369 }
370
371 Contact getAddress()
372 {
373 return address;
374 }
375
376
377 PropertyRecord* getPR(const std::string& key, bool create = true)
378 {
379 std::map<std::string, PropertyRecord>::iterator entry = propMap.find(key);
380 if (entry == propMap.end()) {
381 if (!create) {
382 return nullptr;
383 }
384 propMap[key] = PropertyRecord();
385 entry = propMap.find(key);
386 }
387 yCAssert(NAMESERVER, entry != propMap.end());
388 return &(entry->second);
389 }
390
391 void clearProp(const std::string& key)
392 {
393 getPR(key)->clear();
394 }
395
396 void addProp(const std::string& key, const std::string& val)
397 {
398 getPR(key)->add(val);
399 }
400
401 std::string getProp(const std::string& key)
402 {
403 PropertyRecord* rec = getPR(key, false);
404 if (rec != nullptr) {
405 return rec->toString();
406 }
407 return {};
408 }
409
410 bool checkProp(const std::string& key, const std::string& val)
411 {
412 PropertyRecord* rec = getPR(key, false);
413 if (rec != nullptr) {
414 return rec->check(val);
415 }
416 return false;
417 }
418
419 std::string matchProp(const std::string& key, const std::string& val)
420 {
421 PropertyRecord* rec = getPR(key, false);
422 if (rec != nullptr) {
423 return rec->match(val);
424 }
425 return {};
426 }
427 };
428
429
430 std::string cmdRegister(int argc, char* argv[]);
431 std::string cmdQuery(int argc, char* argv[]);
432 std::string cmdUnregister(int argc, char* argv[]);
433 std::string cmdAnnounce(int argc, char* argv[]);
434 std::string cmdHelp(int argc, char* argv[]);
435 std::string cmdSet(int argc, char* argv[]);
436 std::string cmdGet(int argc, char* argv[]);
437 std::string cmdCheck(int argc, char* argv[]);
438 std::string cmdMatch(int argc, char* argv[]);
439 std::string cmdList(int argc, char* argv[]);
440 std::string cmdRoute(int argc, char* argv[]);
441 std::string cmdGarbageCollect(int argc, char* argv[]);
442 std::string cmdBot(int argc, char* argv[]);
443
444 // making a more easy to parse interface
445 yarp::os::Bottle ncmdList(int argc, char* argv[]);
446 yarp::os::Bottle ncmdQuery(int argc, char* argv[]);
447 yarp::os::Bottle ncmdVersion(int argc, char* argv[]);
448 yarp::os::Bottle ncmdSet(int argc, char* argv[]);
449 yarp::os::Bottle ncmdGet(int argc, char* argv[]);
450
451 std::map<std::string, NameRecord> nameMap;
452 std::map<std::string, HostRecord> hostMap;
453
454 McastRecord mcastRecord;
455 DisposableNameRecord tmpNames;
456
457 NameRecord* getNameRecord(const std::string& name, bool create);
458
459 NameRecord& getNameRecord(const std::string& name)
460 {
461 NameRecord* result = getNameRecord(name, true);
462 yCAssert(NAMESERVER, result != nullptr);
463 return *result;
464 }
465
466 HostRecord* getHostRecord(const std::string& name, bool create);
467
468 HostRecord& getHostRecord(const std::string& name)
469 {
470 HostRecord* result = getHostRecord(name, true);
471 yCAssert(NAMESERVER, result != nullptr);
472 return *result;
473 }
474
475 Dispatcher<NameServer, std::string> dispatcher;
476 Dispatcher<NameServer, yarp::os::Bottle> ndispatcher;
477
478protected:
479 std::string terminate(const std::string& str);
480
482
483private:
484 std::mutex mutex;
485};
486
487} // namespace yarp::os::impl
488
489#endif // YARP_OS_IMPL_NAMESERVER_H
const yarp::os::LogComponent & NAMESERVER()
Definition: NameServer.cpp:30
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:64
Represents how to reach a part of a YARP network.
Definition: Contact.h:33
Stub for a YARP2-conforming name server.
Definition: NameServer.h:33
virtual std::string apply(const std::string &txt, const Contact &remote)=0
virtual ~NameServerStub()=default
Implementation of a YARP2-conforming name server.
Definition: NameServer.h:43
std::string apply(const std::string &txt)
Definition: NameServer.h:78
virtual ~NameServer()=default
virtual void onEvent(yarp::os::Bottle &event)
Definition: NameServer.h:83
Contact registerName(const std::string &name, const Contact &address)
Definition: NameServer.h:55
Contact registerName(const std::string &name)
Definition: NameServer.h:65
void setBasePort(int basePort)
Definition: NameServer.h:91
std::string toString(const T &value)
convert an arbitrary type to string.
#define yCInfo(component,...)
Definition: LogComponent.h:171
#define yCAssert(component, x)
Definition: LogComponent.h:240
#define yCTrace(component,...)
Definition: LogComponent.h:84
#define YARP_DECLARE_LOG_COMPONENT(name)
Definition: LogComponent.h:73
std::string to_string(IntegerType x)
Definition: numeric.h:115
ContainerT split(const typename ContainerT::value_type &s, std::basic_regex< typename ContainerT::value_type::value_type > regex)
Utility to split a string by a separator, into a vector of strings.
Definition: string.h:26
The components from which ports and connections are built.
#define YARP_UNUSED(var)
Definition: api.h:162
#define YARP_os_impl_API
Definition: api.h:46