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