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