39#define STR(x) STR_HELP(x).c_str()
56 if (
rec.isReusablePort()) {
57 HostRecord& host = getHostRecord(prev.
getHost());
60 if (
rec.isReusableIp()) {
61 if (
rec.getAddress().getCarrier() ==
"mcast") {
62 mcastRecord.releaseAddress(
rec.getAddress().getHost().c_str());
66 tmpNames.release(name);
70 event.addString(name.c_str());
81 const std::string& remote)
83 bool reusablePort =
false;
84 bool reusableIp =
false;
98 std::string portName = name;
99 if (portName ==
"...") {
100 portName = tmpNames.get();
103 std::string carrier =
suggestion.getCarrier();
104 if (carrier ==
"...") {
111 if (carrier !=
"mcast") {
112 if (remote ==
"...") {
113 yCError(
NAMESERVER,
"remote machine name was not found! can only guess it is local...");
130 port = getHostRecord(
machine).get();
144 event.addString(
suggestion.getRegName().c_str());
153 std::string base = name;
155 if (name.find(
"/net=") == 0) {
160 base = name.substr(
patEnd);
165 NameRecord*
rec = getNameRecord(base,
false);
166 if (
rec !=
nullptr) {
168 std::string ip =
rec->matchProp(
"ips",
pat);
172 c.setHost(
sip.at(0));
176 return rec->getAddress();
182NameServer::NameRecord* NameServer::getNameRecord(
const std::string& name,
185 auto entry = nameMap.find(name);
186 if (
entry == nameMap.end()) {
190 nameMap.emplace(name, NameRecord());
191 entry = nameMap.find(name);
194 return &(
entry->second);
198NameServer::HostRecord* NameServer::getHostRecord(
const std::string& name,
201 auto entry = hostMap.find(name);
202 if (
entry == hostMap.end()) {
206 hostMap[name] = HostRecord();
207 entry = hostMap.find(name);
211 return &(
entry->second);
224void NameServer::setup()
229 dispatcher.add(
"register", &NameServer::cmdRegister);
230 dispatcher.add(
"unregister", &NameServer::cmdUnregister);
231 dispatcher.add(
"query", &NameServer::cmdQuery);
232 dispatcher.add(
"help", &NameServer::cmdHelp);
233 dispatcher.add(
"set", &NameServer::cmdSet);
234 dispatcher.add(
"get", &NameServer::cmdGet);
235 dispatcher.add(
"check", &NameServer::cmdCheck);
236 dispatcher.add(
"match", &NameServer::cmdMatch);
237 dispatcher.add(
"list", &NameServer::cmdList);
238 dispatcher.add(
"route", &NameServer::cmdRoute);
239 dispatcher.add(
"gc", &NameServer::cmdGarbageCollect);
240 dispatcher.add(
"bot", &NameServer::cmdBot);
241 dispatcher.add(
"announce", &NameServer::cmdAnnounce);
243 ndispatcher.add(
"list", &NameServer::ncmdList);
244 ndispatcher.add(
"query", &NameServer::ncmdQuery);
245 ndispatcher.add(
"version", &NameServer::ncmdVersion);
246 ndispatcher.add(
"set", &NameServer::ncmdSet);
247 ndispatcher.add(
"get", &NameServer::ncmdGet);
250std::string NameServer::cmdRegister(
int argc,
char* argv[])
253 std::string remote = argv[0];
258 return "need at least one argument";
260 std::string portName =
STR(argv[0]);
263 std::string carrier =
"...";
272 if (std::string(
"...") == argv[3]) {
275 port = yarp::conf::numeric::from_string<int>(argv[3]);
287std::string NameServer::cmdQuery(
int argc,
char* argv[])
294 return "need at least one argument";
296 std::string portName =
STR(argv[0]);
301std::string NameServer::cmdUnregister(
int argc,
char* argv[])
308 return "need at least one argument";
310 std::string portName =
STR(argv[0]);
316std::string NameServer::cmdAnnounce(
int argc,
char* argv[])
325std::string NameServer::cmdRoute(
int argc,
char* argv[])
332 return terminate(
"need at least two arguments: the source port and the target port\n(followed by an optional list of carriers in decreasing order of desirability)");
334 std::string src =
STR(argv[0]);
335 std::string dest =
STR(argv[1]);
355 NameRecord&
srcRec = getNameRecord(src);
356 NameRecord&
destRec = getNameRecord(dest);
359 for (
int i = 0; i < argc; i++) {
360 std::string carrier = argv[i];
361 if (
srcRec.checkProp(
"offers", carrier) &&
destRec.checkProp(
"accepts", carrier)) {
363 if (carrier ==
"local" || carrier ==
"shmem") {
365 if (carrier ==
"local") {
366 if (
srcRec.getProp(
"process") !=
destRec.getProp(
"process")) {
386 std::string result =
"port ";
387 result += src +
" route " + dest +
" = " +
pref +
"\n";
392std::string NameServer::cmdHelp(
int argc,
char* argv[])
398 std::string result =
"Here are some ways to use the name server:\n";
404 result += std::string(
"+ help\n");
405 result += std::string(
"+ list\n");
406 result += std::string(
"+ register $portname\n");
407 result += std::string(
"+ register $portname $carrier $ipAddress $portNumber\n");
408 result += std::string(
" (if you want a field set automatically, write '...')\n");
409 result += std::string(
"+ unregister $portname\n");
410 result += std::string(
"+ query $portname\n");
411 result += std::string(
"+ set $portname $property $value\n");
412 result += std::string(
"+ get $portname $property\n");
413 result += std::string(
"+ check $portname $property\n");
414 result += std::string(
"+ match $portname $property $prefix\n");
415 result += std::string(
"+ route $port1 $port2\n");
416 result += std::string(
"+ gc\n");
421std::string NameServer::cmdSet(
int argc,
char* argv[])
428 return "need at least two arguments: the port name, and a key";
430 std::string target =
STR(argv[0]);
431 std::string key = argv[1];
432 NameRecord&
nameRecord = getNameRecord(target);
434 for (
int i = 2; i < argc; i++) {
437 return terminate(std::string(
"port ") + target +
" property " + key +
" = " +
nameRecord.getProp(key) +
"\n");
440std::string NameServer::cmdGet(
int argc,
char* argv[])
447 return "need exactly two arguments: the port name, and a key";
449 std::string target =
STR(argv[0]);
450 std::string key = argv[1];
451 NameRecord&
nameRecord = getNameRecord(target);
452 return terminate(std::string(
"port ") + target +
" property " + key +
" = " +
nameRecord.getProp(key) +
"\n");
455std::string NameServer::cmdMatch(
int argc,
char* argv[])
462 return "need exactly three arguments: the port name, a key, and a prefix";
464 std::string target =
STR(argv[0]);
465 std::string key = argv[1];
466 std::string prefix = argv[2];
467 NameRecord&
nameRecord = getNameRecord(target);
468 return terminate(std::string(
"port ") + target +
" property " + key +
" = " +
nameRecord.matchProp(key, prefix) +
"\n");
471std::string NameServer::cmdCheck(
int argc,
char* argv[])
478 return "need at least two arguments: the port name, and a key";
480 std::string response;
481 std::string target =
STR(argv[0]);
482 std::string key = argv[1];
483 NameRecord&
nameRecord = getNameRecord(target);
484 for (
int i = 2; i < argc; i++) {
485 std::string val =
"false";
492 response.append(
"port ").append(target).append(
" property ").append(key).append(
" value ").append(argv[i]).append(
" present ").append(val);
499std::string NameServer::cmdList(
int argc,
char* argv[])
503 std::string response;
505 std::multiset<std::string>
lines;
506 for (
auto&
it : nameMap) {
507 NameRecord&
rec =
it.second;
512 for (
const auto& line :
lines) {
520std::string NameServer::cmdBot(
int argc,
char* argv[])
526 std::string key = argv[0];
529 Bottle result = ndispatcher.dispatch(
this, key.c_str(), argc, argv);
536Bottle NameServer::ncmdList(
int argc,
char* argv[])
543 prefix =
STR(argv[0]);
547 for (
auto&
it : nameMap) {
548 NameRecord&
rec =
it.second;
549 std::string
iname =
rec.getAddress().getRegName();
550 if (
iname.find(prefix) == 0) {
551 if (
iname == prefix ||
iname[prefix.length()] ==
'/' || prefix[prefix.length() - 1] ==
'/') {
552 if (
rec.getAddress().isValid()) {
567 std::string portName =
STR(argv[0]);
569 response =
botify(address);
591 std::string target =
STR(argv[0]);
592 std::string key =
STR(argv[1]);
593 NameRecord&
nameRecord = getNameRecord(target);
595 for (
int i = 2; i < argc; i++) {
607 std::string target =
STR(argv[0]);
608 std::string key = argv[1];
609 NameRecord&
nameRecord = getNameRecord(target);
616std::string NameServer::cmdGarbageCollect(
int argc,
char* argv[])
620 std::string response;
622 response =
"No cleaning done.\n";
633 result =
"registration name ";
636 result =
"registration name ";
637 result = result + address.
getRegName() +
" ip " +
"none" +
" port " +
"none" +
" type " + address.
getCarrier() +
"\n";
649 bname.addString(
"name");
655 bnum.addString(
"port_number");
668 bstate.addString(
"error");
670 bstate.addString(
"port not known");
680 return str +
"*** end of message";
691 std::string result =
"no command given";
694 if (
ss.size() >= 2) {
695 std::string key =
ss.at(1);
700 std::vector<char*> args;
701 args.reserve(
ss.size());
702 std::transform(
ss.begin() + 1,
ss.end(), std::back_inserter(args), [](
const std::string& str) { return const_cast<char*>(str.c_str()); });
703 args.push_back(
nullptr);
704 int argc =
static_cast<int>(args.size()) - 1;
705 char** argv = args.data();
707 result = dispatcher.dispatch(
this, key.c_str(), argc, argv);
708 if (result.empty()) {
709 Bottle b = ndispatcher.dispatch(
this, key.c_str(), argc, argv);
711 if (!result.empty()) {
712 result = result +
"\n";
727 rcmd.addString(
"ignored_legacy");
729 std::string in =
rcmd.toString();
730 std::string out =
apply(in, remote);
736#ifndef DOXYGEN_SHOULD_SKIP_THIS
753 std::string ref =
"NAME_SERVER ";
755 std::string msg =
"?";
771 size_t index = msg.find(
"NAME_SERVER");
776 std::string result =
server->apply(msg, remote);
779 if (result.empty()) {
780 result =
ns_terminate(std::string(
"unknown command ") + msg +
"\n");
784 for (
char i : result) {
796 if (end != std::string::npos) {
802 yCInfo(
NAMESERVER,
"Name server ignoring unknown command: %s", msg.c_str());
822 setBasePort(basePort);
825 void setPort(
Port& port)
830 void onEvent(
Bottle& event)
override
832 if (port !=
nullptr) {
const yarp::os::LogComponent & NAMESERVER()
static std::string STR_HELP(const char *txt)
static std::string ns_terminate(const std::string &str)
A simple collection of objects that can be described and transmitted in a portable way.
void addVocab32(yarp::conf::vocab32_t x)
Places a vocabulary item in the bottle, at the end of the list.
void fromString(const std::string &text)
Initializes bottle from a string.
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
void addString(const char *str)
Places a string in the bottle, at the end of the list.
std::string toString() const override
Gives a human-readable textual representation of the bottle.
A mini-server for performing network communication in the background.
An interface for reading from a network connection.
virtual bool isTextMode() const =0
Check if the connection is text mode.
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
virtual std::string expectText(const char terminatingChar='\n')=0
Read some text from the network connection.
virtual Contact getRemoteContact() const =0
Gets information about who is supplying the data being read, if that information is available.
virtual bool isActive() const =0
An interface for writing to a network connection.
virtual void appendText(const std::string &str, const char terminate='\n')=0
Send a terminated string to the network connection.
static int getDefaultPortRange()
Under normal operation, YARP has a name server that manages a pool of (socket) ports starting at a po...
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
A mini-server for network communication.
bool write(const PortWriter &writer, const PortWriter *callback=nullptr) const override
Write an object to the port.
A single value (typically within a Bottle).
void fromString(const char *str)
Set value to correspond to a textual representation.
virtual std::string asString() const
Get string value.
Implementation of a YARP2-conforming name server.
static std::string textify(const Contact &address)
std::string apply(const std::string &txt, const Contact &remote) override
Contact queryName(const std::string &name)
static yarp::os::Bottle botify(const Contact &address)
Contact unregisterName(const std::string &name)
std::string terminate(const std::string &str)
virtual void onEvent(yarp::os::Bottle &event)
Contact registerName(const std::string &name, const Contact &address)
#define yCInfo(component,...)
#define yCError(component,...)
#define yCAssert(component, x)
#define yCTrace(component,...)
#define yCDebug(component,...)
#define YARP_OS_LOG_COMPONENT(name, name_string)
std::string to_string(IntegerType x)
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.
The components from which ports and connections are built.
An interface to the operating system, including Port based communication.