network.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009, Willow Garage, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice,
7  * this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution.
11  * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
12  * contributors may be used to endorse or promote products derived from
13  * this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "config.h"
29 #include "ros/network.h"
30 #include "ros/file_log.h"
31 #include "ros/exceptions.h"
32 #include "ros/io.h" // cross-platform headers needed
33 #include <ros/console.h>
34 #include <ros/assert.h>
35 #ifdef HAVE_IFADDRS_H
36  #include <ifaddrs.h>
37  #include <sys/socket.h> // supports FreeBSD, which does not include this in ifaddrs.h
38 #endif
39 
40 #include <boost/lexical_cast.hpp>
41 
42 namespace ros
43 {
44 
45 namespace network
46 {
47 
48 std::string g_host;
49 uint16_t g_tcpros_server_port = 0;
50 
51 const std::string& getHost()
52 {
53  return g_host;
54 }
55 
56 bool splitURI(const std::string& uri, std::string& host, uint32_t& port)
57 {
58  // skip over the protocol if it's there
59  if (uri.substr(0, 7) == std::string("http://"))
60  host = uri.substr(7);
61  else if (uri.substr(0, 9) == std::string("rosrpc://"))
62  host = uri.substr(9);
63  // split out the port
64  std::string::size_type colon_pos = host.find_first_of(":");
65  if (colon_pos == std::string::npos)
66  return false;
67  std::string port_str = host.substr(colon_pos+1);
68  std::string::size_type slash_pos = port_str.find_first_of("/");
69  if (slash_pos != std::string::npos)
70  port_str = port_str.erase(slash_pos);
71  port = atoi(port_str.c_str());
72  host = host.erase(colon_pos);
73  return true;
74 }
75 
76 uint16_t getTCPROSPort()
77 {
78  return g_tcpros_server_port;
79 }
80 
81 static bool isPrivateIP(const char *ip)
82 {
83  bool b = !strncmp("192.168", ip, 7) || !strncmp("10.", ip, 3) ||
84  !strncmp("169.254", ip, 7);
85  return b;
86 }
87 
88 std::string determineHost()
89 {
90  std::string ip_env;
91  // First, did the user set ROS_HOSTNAME?
92  if ( get_environment_variable(ip_env, "ROS_HOSTNAME")) {
93  ROSCPP_LOG_DEBUG( "determineIP: using value of ROS_HOSTNAME:%s:", ip_env.c_str());
94  if (ip_env.size() == 0)
95  {
96  ROS_WARN("invalid ROS_HOSTNAME (an empty string)");
97  }
98  return ip_env;
99  }
100 
101  // Second, did the user set ROS_IP?
102  if ( get_environment_variable(ip_env, "ROS_IP")) {
103  ROSCPP_LOG_DEBUG( "determineIP: using value of ROS_IP:%s:", ip_env.c_str());
104  if (ip_env.size() == 0)
105  {
106  ROS_WARN("invalid ROS_IP (an empty string)");
107  }
108  return ip_env;
109  }
110 
111  // Third, try the hostname
112  char host[1024];
113  memset(host,0,sizeof(host));
114  if(gethostname(host,sizeof(host)-1) != 0)
115  {
116  ROS_ERROR("determineIP: gethostname failed");
117  }
118  // We don't want localhost to be our ip
119  else if(strlen(host) && strcmp("localhost", host))
120  {
121  return std::string(host);
122  }
123 
124  // Fourth, fall back on interface search, which will yield an IP address
125 
126 #ifdef HAVE_IFADDRS_H
127  struct ifaddrs *ifa = NULL, *ifp = NULL;
128  int rc;
129  if ((rc = getifaddrs(&ifp)) < 0)
130  {
131  ROS_FATAL("error in getifaddrs: [%s]", strerror(rc));
132  ROS_BREAK();
133  }
134  char preferred_ip[200] = {0};
135  for (ifa = ifp; ifa; ifa = ifa->ifa_next)
136  {
137  char ip_[200];
138  socklen_t salen;
139  if (!ifa->ifa_addr)
140  continue; // evidently this interface has no ip address
141  if (ifa->ifa_addr->sa_family == AF_INET)
142  salen = sizeof(struct sockaddr_in);
143  else if (ifa->ifa_addr->sa_family == AF_INET6)
144  salen = sizeof(struct sockaddr_in6);
145  else
146  continue;
147  if (getnameinfo(ifa->ifa_addr, salen, ip_, sizeof(ip_), NULL, 0,
148  NI_NUMERICHOST) < 0)
149  {
150  ROSCPP_LOG_DEBUG( "getnameinfo couldn't get the ip of interface [%s]", ifa->ifa_name);
151  continue;
152  }
153  //ROS_INFO( "ip of interface [%s] is [%s]", ifa->ifa_name, ip);
154  // prefer non-private IPs over private IPs
155  if (!strcmp("127.0.0.1", ip_) || strchr(ip_,':'))
156  continue; // ignore loopback unless we have no other choice
157  if (ifa->ifa_addr->sa_family == AF_INET6 && !preferred_ip[0])
158  strcpy(preferred_ip, ip_);
159  else if (isPrivateIP(ip_) && !preferred_ip[0])
160  strcpy(preferred_ip, ip_);
161  else if (!isPrivateIP(ip_) &&
162  (isPrivateIP(preferred_ip) || !preferred_ip[0]))
163  strcpy(preferred_ip, ip_);
164  }
165  freeifaddrs(ifp);
166  if (!preferred_ip[0])
167  {
168  ROS_ERROR( "Couldn't find a preferred IP via the getifaddrs() call; I'm assuming that your IP "
169  "address is 127.0.0.1. This should work for local processes, "
170  "but will almost certainly not work if you have remote processes."
171  "Report to the ROS development team to seek a fix.");
172  return std::string("127.0.0.1");
173  }
174  ROSCPP_LOG_DEBUG( "preferred IP is guessed to be %s", preferred_ip);
175  return std::string(preferred_ip);
176 #else
177  // @todo Fix IP determination in the case where getifaddrs() isn't
178  // available.
179  ROS_ERROR( "You don't have the getifaddrs() call; I'm assuming that your IP "
180  "address is 127.0.0.1. This should work for local processes, "
181  "but will almost certainly not work if you have remote processes."
182  "Report to the ROS development team to seek a fix.");
183  return std::string("127.0.0.1");
184 #endif
185 }
186 
187 void init(const M_string& remappings)
188 {
189  M_string::const_iterator it = remappings.find("__hostname");
190  if (it != remappings.end())
191  {
192  g_host = it->second;
193  }
194  else
195  {
196  it = remappings.find("__ip");
197  if (it != remappings.end())
198  {
199  g_host = it->second;
200  }
201  }
202 
203  it = remappings.find("__tcpros_server_port");
204  if (it != remappings.end())
205  {
206  try
207  {
208  g_tcpros_server_port = boost::lexical_cast<uint16_t>(it->second);
209  }
210  catch (boost::bad_lexical_cast&)
211  {
212  throw ros::InvalidPortException("__tcpros_server_port [" + it->second + "] was not specified as a number within the 0-65535 range");
213  }
214  }
215 
216  if (g_host.empty())
217  {
218  g_host = determineHost();
219  }
220 }
221 
222 } // namespace network
223 
224 } // namespace ros
ros::network::init
void init(const M_string &remappings)
Definition: network.cpp:187
ROS_BREAK
#define ROS_BREAK()
exceptions.h
ros::network::determineHost
std::string determineHost()
Definition: network.cpp:88
ros
ros::InvalidPortException
Thrown when an invalid port is specified.
Definition: exceptions.h:85
ros::network::g_tcpros_server_port
uint16_t g_tcpros_server_port
Definition: network.cpp:49
ros::network::getHost
const ROSCPP_DECL std::string & getHost()
Definition: network.cpp:51
console.h
ros::network::getTCPROSPort
ROSCPP_DECL uint16_t getTCPROSPort()
Definition: network.cpp:76
ROS_WARN
#define ROS_WARN(...)
ros::network::isPrivateIP
static bool isPrivateIP(const char *ip)
Definition: network.cpp:81
ROS_FATAL
#define ROS_FATAL(...)
ros::get_environment_variable
bool get_environment_variable(std::string &str, const char *environment_variable)
ros::network::g_host
std::string g_host
Definition: network.cpp:48
io.h
ROS_ERROR
#define ROS_ERROR(...)
network.h
assert.h
ros::network::splitURI
ROSCPP_DECL bool splitURI(const std::string &uri, std::string &host, uint32_t &port)
Definition: network.cpp:56
ROSCPP_LOG_DEBUG
#define ROSCPP_LOG_DEBUG(...)
Definition: file_log.h:35
file_log.h
ros::M_string
std::map< std::string, std::string > M_string


roscpp
Author(s): Morgan Quigley, Josh Faust, Brian Gerkey, Troy Straszheim, Dirk Thomas , Jacob Perron
autogenerated on Thu Nov 23 2023 04:01:44