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