00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "config.h"
00029 #include "ros/network.h"
00030 #include "ros/file_log.h"
00031 #include "ros/exceptions.h"
00032 #include "ros/io.h"
00033 #include <ros/console.h>
00034 #include <ros/assert.h>
00035 #ifdef HAVE_IFADDRS_H
00036 #include <ifaddrs.h>
00037 #endif
00038
00039 #include <boost/lexical_cast.hpp>
00040
00041 namespace ros
00042 {
00043
00044 namespace network
00045 {
00046
00047 std::string g_host;
00048 uint16_t g_tcpros_server_port = 0;
00049
00050 const std::string& getHost()
00051 {
00052 return g_host;
00053 }
00054
00055 bool splitURI(const std::string& uri, std::string& host, uint32_t& port)
00056 {
00057
00058 if (uri.substr(0, 7) == std::string("http://"))
00059 host = uri.substr(7);
00060 else if (uri.substr(0, 9) == std::string("rosrpc://"))
00061 host = uri.substr(9);
00062
00063 std::string::size_type colon_pos = host.find_first_of(":");
00064 if (colon_pos == std::string::npos)
00065 return false;
00066 std::string port_str = host.substr(colon_pos+1);
00067 std::string::size_type slash_pos = port_str.find_first_of("/");
00068 if (slash_pos != std::string::npos)
00069 port_str = port_str.erase(slash_pos);
00070 port = atoi(port_str.c_str());
00071 host = host.erase(colon_pos);
00072 return true;
00073 }
00074
00075 uint16_t getTCPROSPort()
00076 {
00077 return g_tcpros_server_port;
00078 }
00079
00080 static bool isPrivateIP(const char *ip)
00081 {
00082 bool b = !strncmp("192.168", ip, 7) || !strncmp("10.", ip, 3) ||
00083 !strncmp("169.254", ip, 7);
00084 return b;
00085 }
00086
00087 std::string determineHost()
00088 {
00089 std::string ip_env;
00090
00091 if ( get_environment_variable(ip_env, "ROS_HOSTNAME")) {
00092 ROSCPP_LOG_DEBUG( "determineIP: using value of ROS_HOSTNAME:%s:", ip_env.c_str());
00093 return ip_env;
00094 }
00095
00096
00097 if ( get_environment_variable(ip_env, "ROS_IP")) {
00098 ROSCPP_LOG_DEBUG( "determineIP: using value of ROS_IP:%s:", ip_env.c_str());
00099 return ip_env;
00100 }
00101
00102
00103 char host[1024];
00104 memset(host,0,sizeof(host));
00105 if(gethostname(host,sizeof(host)-1) != 0)
00106 {
00107 ROS_ERROR("determineIP: gethostname failed");
00108 }
00109
00110 else if(strlen(host) && strcmp("localhost", host))
00111 {
00112 return std::string(host);
00113 }
00114
00115
00116
00117 #ifdef HAVE_IFADDRS_H
00118 struct ifaddrs *ifa = NULL, *ifp = NULL;
00119 int rc;
00120 if ((rc = getifaddrs(&ifp)) < 0)
00121 {
00122 ROS_FATAL("error in getifaddrs: [%s]", strerror(rc));
00123 ROS_BREAK();
00124 }
00125 char preferred_ip[200] = {0};
00126 for (ifa = ifp; ifa; ifa = ifa->ifa_next)
00127 {
00128 char ip_[200];
00129 socklen_t salen;
00130 if (!ifa->ifa_addr)
00131 continue;
00132 if (ifa->ifa_addr->sa_family == AF_INET)
00133 salen = sizeof(struct sockaddr_in);
00134 else if (ifa->ifa_addr->sa_family == AF_INET6)
00135 salen = sizeof(struct sockaddr_in6);
00136 else
00137 continue;
00138 if (getnameinfo(ifa->ifa_addr, salen, ip_, sizeof(ip_), NULL, 0,
00139 NI_NUMERICHOST) < 0)
00140 {
00141 ROSCPP_LOG_DEBUG( "getnameinfo couldn't get the ip of interface [%s]", ifa->ifa_name);
00142 continue;
00143 }
00144
00145
00146 if (!strcmp("127.0.0.1", ip_) || strchr(ip_,':'))
00147 continue;
00148 if (ifa->ifa_addr->sa_family == AF_INET6 && !preferred_ip[0])
00149 strcpy(preferred_ip, ip_);
00150 else if (isPrivateIP(ip_) && !preferred_ip[0])
00151 strcpy(preferred_ip, ip_);
00152 else if (!isPrivateIP(ip_) &&
00153 (isPrivateIP(preferred_ip) || !preferred_ip[0]))
00154 strcpy(preferred_ip, ip_);
00155 }
00156 freeifaddrs(ifp);
00157 if (!preferred_ip[0])
00158 {
00159 ROS_ERROR( "Couldn't find a preferred IP via the getifaddrs() call; I'm assuming that your IP "
00160 "address is 127.0.0.1. This should work for local processes, "
00161 "but will almost certainly not work if you have remote processes."
00162 "Report to the ROS development team to seek a fix.");
00163 return std::string("127.0.0.1");
00164 }
00165 ROSCPP_LOG_DEBUG( "preferred IP is guessed to be %s", preferred_ip);
00166 return std::string(preferred_ip);
00167 #else
00168
00169
00170 ROS_ERROR( "You don't have the getifaddrs() call; I'm assuming that your IP "
00171 "address is 127.0.0.1. This should work for local processes, "
00172 "but will almost certainly not work if you have remote processes."
00173 "Report to the ROS development team to seek a fix.");
00174 return std::string("127.0.0.1");
00175 #endif
00176 }
00177
00178 void init(const M_string& remappings)
00179 {
00180 M_string::const_iterator it = remappings.find("__hostname");
00181 if (it != remappings.end())
00182 {
00183 g_host = it->second;
00184 }
00185 else
00186 {
00187 it = remappings.find("__ip");
00188 if (it != remappings.end())
00189 {
00190 g_host = it->second;
00191 }
00192 }
00193
00194 it = remappings.find("__tcpros_server_port");
00195 if (it != remappings.end())
00196 {
00197 try
00198 {
00199 g_tcpros_server_port = boost::lexical_cast<uint16_t>(it->second);
00200 }
00201 catch (boost::bad_lexical_cast&)
00202 {
00203 throw ros::InvalidPortException("__tcpros_server_port [" + it->second + "] was not specified as a number within the 0-65535 range");
00204 }
00205 }
00206
00207 if (g_host.empty())
00208 {
00209 g_host = determineHost();
00210 }
00211 }
00212
00213 }
00214
00215 }