YARP
Yet Another Robot Platform
Contact.cpp
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  * Copyright (C) 2006, 2011 Anne van Rossum <anne@almende.com>
5  * All rights reserved.
6  *
7  * This software may be modified and distributed under the terms of the
8  * BSD-3-Clause license. See the accompanying LICENSE file for details.
9  */
10 
11 #include <yarp/os/Contact.h>
12 #include <yarp/os/NetType.h>
13 #include <yarp/os/Searchable.h>
14 #include <yarp/os/Value.h>
18 
19 #include <cstdio>
20 #include <cstdlib>
21 #include <cstring>
22 #include <utility>
23 
24 #if defined(YARP_HAS_ACE)
25 # include <ace/INET_Addr.h>
26 // In one the ACE headers there is a definition of "main" for WIN32
27 # ifdef main
28 # undef main
29 # endif
30 #else
31 # include <arpa/inet.h>
32 # include <sys/socket.h>
33 # include <sys/types.h>
34 #endif
35 
36 
37 using yarp::os::Contact;
39 using yarp::os::NetType;
41 using yarp::os::Value;
43 
44 #if !defined(YARP_HAS_ACE)
45 namespace {
46 YARP_OS_LOG_COMPONENT(CONTACT, "yarp.os.Contact" )
47 }
48 #endif
49 
50 #ifndef DOXYGEN_SHOULD_SKIP_THIS
51 
52 class Contact::Private
53 {
54 public:
55  Private(std::string regName,
56  std::string carrier,
57  std::string hostname,
58  int port) :
59  regName(std::move(regName)),
60  carrier(std::move(carrier)),
61  hostname(std::move(hostname)),
62  port(port),
63  timeout(-1)
64  {
65  }
66 
67  std::string regName;
68  std::string carrier;
69  std::string hostname;
70  NestedContact nestedContact;
71 
72  int port;
73  float timeout;
74 };
75 
76 #endif // DOXYGEN_SHOULD_SKIP_THIS
77 
78 
79 Contact::Contact(const std::string& hostname,
80  int port) :
81  mPriv(new Private(std::string(), std::string(), hostname, port))
82 {
83 }
84 
85 Contact::Contact(const std::string& carrier,
86  const std::string& hostname,
87  int port) :
88  mPriv(new Private(std::string(), carrier, hostname, port))
89 {
90 }
91 
92 Contact::Contact(const std::string& name,
93  const std::string& carrier,
94  const std::string& hostname,
95  int port) :
96  mPriv(new Private(name, carrier, hostname, port))
97 {
98 }
99 
101  mPriv(new Private(*(rhs.mPriv)))
102 {
103 }
104 
105 Contact::Contact(Contact&& rhs) noexcept :
106  mPriv(rhs.mPriv)
107 {
108  rhs.mPriv = nullptr;
109 }
110 
112 {
113  delete mPriv;
114 }
115 
117 {
118  if (&rhs != this) {
119  *mPriv = *(rhs.mPriv);
120  }
121  return *this;
122 }
123 
125 {
126  if (&rhs != this) {
127  std::swap(mPriv, rhs.mPriv);
128  }
129  return *this;
130 }
131 
133 {
134  Contact result;
135  result.mPriv->port = config.check("port_number", Value(-1)).asInt32();
136  result.mPriv->hostname = config.check("ip", Value("")).asString();
137  result.mPriv->regName = config.check("name", Value("")).asString();
138  result.mPriv->carrier = config.check("carrier", Value("tcp")).asString();
139  return result;
140 }
141 
142 Contact Contact::fromString(const std::string& txt)
143 {
144  std::string str(txt);
145  Contact c;
146  std::string::size_type start = 0;
147  std::string::size_type base = str.find("://");
148  std::string::size_type offset = 2;
149  if (base == std::string::npos) {
150  base = str.find(":/");
151  offset = 1;
152  }
153  if (base == std::string::npos) {
154  if (str.length() > 0 && str[0] == '/') {
155  base = 0;
156  offset = 0;
157  }
158  }
159  if (base != std::string::npos) {
160  c.mPriv->carrier = str.substr(0, base);
161  start = base + offset;
162  // check if we have a direct machine:NNN syntax
163  std::string::size_type colon = std::string::npos;
164  int mode = 0;
165  int nums = 0;
166  std::string::size_type i;
167  for (i = start + 1; i < str.length(); i++) {
168  char ch = str[i];
169  if (ch == ':') {
170  if (mode == 0) {
171  colon = i;
172  mode = 1;
173  continue;
174  }
175  mode = -1;
176  break;
177  }
178  if (ch == '/') {
179  break;
180  }
181  if (mode == 1) {
182  if (ch >= '0' && ch <= '9') {
183  nums++;
184  continue;
185  }
186  mode = -1;
187  break;
188  }
189  }
190  if (mode == 1 && nums >= 1) {
191  // yes, machine:nnn
192  if (c.mPriv->carrier.empty()) {
193  c.mPriv->carrier = "tcp";
194  }
195  c.mPriv->hostname = str.substr(start + 1, colon - start - 1);
196  c.mPriv->port = atoi(str.substr(colon + 1, nums).c_str());
197  start = i;
198  }
199  }
200  std::string rname = str.substr(start);
201  if (rname != "/") {
202  c.mPriv->regName = rname;
203  }
204  return c;
205 }
206 
207 
208 std::string Contact::getName() const
209 {
210  if (!mPriv->regName.empty()) {
211  return mPriv->regName;
212  }
213  if (!mPriv->hostname.empty() && mPriv->port >= 0) {
214  std::string name = std::string("/") + mPriv->hostname + ":" + NetType::toString(mPriv->port);
215  return name;
216  }
217  return {};
218 }
219 
220 std::string Contact::getRegName() const
221 {
222  return mPriv->regName;
223 }
224 
225 void Contact::setName(const std::string& name)
226 {
227  mPriv->regName = name;
228 }
229 
230 
231 std::string Contact::getHost() const
232 {
233  return mPriv->hostname;
234 }
235 
236 void Contact::setHost(const std::string& hostname)
237 {
238  this->mPriv->hostname = hostname;
239 }
240 
241 
242 int Contact::getPort() const
243 {
244  return mPriv->port;
245 }
246 
247 void Contact::setPort(int port)
248 {
249  mPriv->port = port;
250 }
251 
252 
253 std::string Contact::getCarrier() const
254 {
255  return mPriv->carrier;
256 }
257 
258 void Contact::setCarrier(const std::string& carrier)
259 {
260  mPriv->carrier = carrier;
261 }
262 
263 
265 {
266  return mPriv->nestedContact;
267 }
268 
270 {
271  this->mPriv->nestedContact = nestedContact;
272 }
273 
274 
276 {
277  return mPriv->timeout >= 0;
278 }
279 
280 float Contact::getTimeout() const
281 {
282  return mPriv->timeout;
283 }
284 
285 void Contact::setTimeout(float timeout)
286 {
287  this->mPriv->timeout = timeout;
288 }
289 
290 
291 void Contact::setSocket(const std::string& carrier,
292  const std::string& hostname,
293  int port)
294 {
295  mPriv->carrier = carrier;
296  mPriv->hostname = hostname;
297  mPriv->port = port;
298 }
299 
300 
301 bool Contact::isValid() const
302 {
303  return mPriv->port >= 0;
304 }
305 
306 std::string Contact::toString() const
307 {
308  std::string name = getName();
309  if (!mPriv->carrier.empty()) {
310  return mPriv->carrier + ":/" + name;
311  }
312  return name;
313 }
314 
315 
316 std::string Contact::toURI(bool includeCarrier) const
317 {
318  std::string result;
319  if (includeCarrier && !mPriv->carrier.empty()) {
320  result += mPriv->carrier;
321  result += ":/";
322  }
323  if (!mPriv->hostname.empty() && mPriv->port >= 0) {
324  result += "/";
325  result += mPriv->hostname;
326  result += ":";
327  result += NetType::toString(mPriv->port);
328  result += "/";
329  }
330  return result;
331 }
332 
333 
334 std::string Contact::convertHostToIp(const char* name)
335 {
336 #if defined(YARP_HAS_ACE)
337  ACE_INET_Addr addr((u_short)0, name);
338  char ipstr[256];
339  addr.get_host_addr(ipstr, sizeof(ipstr));
340 
341 #else
342  char ipstr[INET6_ADDRSTRLEN];
343  int status;
344  struct addrinfo hints, *res, *p;
345 
346  memset(&hints, 0, sizeof hints); // make sure the struct is empty
347  hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
348  hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
349  hints.ai_flags = AI_PASSIVE; // fill in my IP for me
350 
351  if ((status = yarp::os::impl::getaddrinfo(name, "http", &hints, &res)) != 0) {
352  yCError(CONTACT, "getaddrinfo error: %s\n", yarp::os::impl::gai_strerror(status));
353  std::exit(1);
354  }
355 
356  for (p = res; p != nullptr; p = p->ai_next) {
357  void* addr;
358 
359  if (p->ai_family == AF_INET) { // IPv4
360  auto* ipv4 = reinterpret_cast<struct sockaddr_in*>(p->ai_addr);
361  addr = &(ipv4->sin_addr);
362  } else { // IPv6
363  auto* ipv6 = reinterpret_cast<struct sockaddr_in6*>(p->ai_addr);
364  addr = &(ipv6->sin6_addr);
365  }
366 
367  // convert the IP to a string and print it:
368  inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
369  }
370  yarp::os::impl::freeaddrinfo(res);
371 #endif
372 
373  if (NameConfig::isLocalName(ipstr)) {
374  return NameConfig::getHostName();
375  }
376  return ipstr;
377 }
yarp::os::Searchable
A base class for nested structures that can be searched.
Definition: Searchable.h:69
yarp::os::NestedContact
A placeholder for rich contact information.
Definition: NestedContact.h:27
yarp::os::Contact::getName
std::string getName() const
Get the name associated with this Contact.
Definition: Contact.cpp:208
yarp::os::NetType
Various utilities related to types and formats.
Definition: NetType.h:29
yarp::os::Contact::setName
void setName(const std::string &name)
Set the name associated with this Contact.
Definition: Contact.cpp:225
yarp::os::Contact::~Contact
virtual ~Contact()
Destructor.
Definition: Contact.cpp:111
yarp::os::Contact::convertHostToIp
static std::string convertHostToIp(const char *name)
If the host is a machine name, convert it to a plausible IP address.
Definition: Contact.cpp:334
LogComponent.h
Searchable.h
yarp::os::Contact::getRegName
std::string getRegName() const
Get the name associated with this Contact.
Definition: Contact.cpp:220
yarp::os::Contact::fromConfig
static Contact fromConfig(const Searchable &config)
Factory method.
Definition: Contact.cpp:132
yarp::os::Contact::toString
std::string toString() const
Get a textual representation of the Contact.
Definition: Contact.cpp:306
NetType.h
yarp::os::Contact::hasTimeout
bool hasTimeout() const
Check if this Contact has a timeout.
Definition: Contact.cpp:275
yarp::os::Contact::toURI
std::string toURI(bool includeCarrier=true) const
Get a representation of the Contact as a URI.
Definition: Contact.cpp:316
yarp::os::Contact::operator=
Contact & operator=(const Contact &rhs)
Copy assignment operator.
Definition: Contact.cpp:116
PlatformNetdb.h
yarp::os::Contact::Contact
Contact(const std::string &name=std::string(), const std::string &carrier=std::string(), const std::string &hostname=std::string(), int port=-1)
Constructor.
Definition: Contact.cpp:92
yarp::os::Contact::getPort
int getPort() const
Get the port number associated with this Contact for socket communication.
Definition: Contact.cpp:242
yarp::os::Contact::fromString
static Contact fromString(const std::string &txt)
Factory method.
Definition: Contact.cpp:142
yarp::os::Contact::getCarrier
std::string getCarrier() const
Get the carrier associated with this Contact for socket communication.
Definition: Contact.cpp:253
yarp::os::Contact::setPort
void setPort(int port)
Set the port number to be the input parameter.
Definition: Contact.cpp:247
yarp::os::Searchable::check
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
yarp::os::Contact::getTimeout
float getTimeout() const
Get timeout for this Address.
Definition: Contact.cpp:280
NameConfig.h
yarp::os::Contact::setSocket
void setSocket(const std::string &carrier, const std::string &hostname, int port)
Set information to a Contact about how to reach it using socket communication.
Definition: Contact.cpp:291
yarp::os::Contact::setCarrier
void setCarrier(const std::string &carrier)
Set the carrier to use for this Contact.
Definition: Contact.cpp:258
yarp::os::Contact::setNestedContact
void setNestedContact(const yarp::os::NestedContact &nestedContact)
Sets the NestedContact containing extra information for this Contact.
Definition: Contact.cpp:269
yarp::os::NetType::toString
static std::string toString(int x)
Definition: NetType.cpp:138
yCError
#define yCError(component,...)
Definition: LogComponent.h:157
yarp::os::Contact::getNested
const NestedContact & getNested() const
Get the NestedContact containing extra information for this Contact.
Definition: Contact.cpp:264
yarp::os::Contact::isValid
bool isValid() const
Checks if a Contact is tagged as valid.
Definition: Contact.cpp:301
yarp::os::Contact::getHost
std::string getHost() const
Get the host name associated with this Contact for socket communication.
Definition: Contact.cpp:231
yarp::os::Contact
Represents how to reach a part of a YARP network.
Definition: Contact.h:39
yarp::os::Value
A single value (typically within a Bottle).
Definition: Value.h:47
yarp::os::Contact::setHost
void setHost(const std::string &hostname)
Set the host name to be the input parameter.
Definition: Contact.cpp:236
Contact.h
yarp::os::impl::NameConfig
Small helper class to help deal with legacy YARP configuration files.
Definition: NameConfig.h:28
YARP_OS_LOG_COMPONENT
#define YARP_OS_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:37
yarp::os::Contact::setTimeout
void setTimeout(float timeout)
Set timeout for this Contact.
Definition: Contact.cpp:285
Value.h