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 "ros/master.h"
00029 #include "ros/xmlrpc_manager.h"
00030 #include "ros/this_node.h"
00031 #include "ros/init.h"
00032 #include "ros/network.h"
00033
00034 #include <ros/console.h>
00035 #include <ros/assert.h>
00036
00037 #include "XmlRpc.h"
00038
00039 namespace ros
00040 {
00041
00042 namespace master
00043 {
00044
00045 uint32_t g_port = 0;
00046 std::string g_host;
00047 std::string g_uri;
00048 ros::WallDuration g_retry_timeout;
00049
00050 void init(const M_string& remappings)
00051 {
00052 M_string::const_iterator it = remappings.find("__master");
00053 if (it != remappings.end())
00054 {
00055 g_uri = it->second;
00056 }
00057
00058 if (g_uri.empty())
00059 {
00060 char *master_uri_env = NULL;
00061 #ifdef _MSC_VER
00062 _dupenv_s(&master_uri_env, NULL, "ROS_MASTER_URI");
00063 #else
00064 master_uri_env = getenv("ROS_MASTER_URI");
00065 #endif
00066 if (!master_uri_env)
00067 {
00068 ROS_FATAL( "ROS_MASTER_URI is not defined in the environment. Either " \
00069 "type the following or (preferrably) add this to your " \
00070 "~/.bashrc file in order set up your " \
00071 "local machine as a ROS master:\n\n" \
00072 "export ROS_MASTER_URI=http://localhost:11311\n\n" \
00073 "then, type 'roscore' in another shell to actually launch " \
00074 "the master program.");
00075 ROS_BREAK();
00076 }
00077
00078 g_uri = master_uri_env;
00079
00080 #ifdef _MSC_VER
00081
00082 free(master_uri_env);
00083 #endif
00084 }
00085
00086
00087 if (!network::splitURI(g_uri, g_host, g_port))
00088 {
00089 ROS_FATAL( "Couldn't parse the master URI [%s] into a host:port pair.", g_uri.c_str());
00090 ROS_BREAK();
00091 }
00092 }
00093
00094 const std::string& getHost()
00095 {
00096 return g_host;
00097 }
00098
00099 uint32_t getPort()
00100 {
00101 return g_port;
00102 }
00103
00104 const std::string& getURI()
00105 {
00106 return g_uri;
00107 }
00108
00109 void setRetryTimeout(ros::WallDuration timeout)
00110 {
00111 g_retry_timeout = timeout;
00112 }
00113
00114 bool check()
00115 {
00116 XmlRpc::XmlRpcValue args, result, payload;
00117 args[0] = this_node::getName();
00118 return execute("getPid", args, result, payload, false);
00119 }
00120
00121 bool getTopics(V_TopicInfo& topics)
00122 {
00123 XmlRpc::XmlRpcValue args, result, payload;
00124 args[0] = this_node::getName();
00125 args[1] = "";
00126
00127 if (!execute("getPublishedTopics", args, result, payload, true))
00128 {
00129 return false;
00130 }
00131
00132 topics.clear();
00133 for (int i = 0; i < payload.size(); i++)
00134 {
00135 topics.push_back(TopicInfo(std::string(payload[i][0]), std::string(payload[i][1])));
00136 }
00137
00138 return true;
00139 }
00140
00141 bool getNodes(V_string& nodes)
00142 {
00143 XmlRpc::XmlRpcValue args, result, payload;
00144 args[0] = this_node::getName();
00145
00146 if (!execute("getSystemState", args, result, payload, true))
00147 {
00148 return false;
00149 }
00150
00151 S_string node_set;
00152 for (int i = 0; i < payload.size(); ++i)
00153 {
00154 for (int j = 0; j < payload[i].size(); ++j)
00155 {
00156 XmlRpc::XmlRpcValue val = payload[i][j][1];
00157 for (int k = 0; k < val.size(); ++k)
00158 {
00159 std::string name = payload[i][j][1][k];
00160 node_set.insert(name);
00161 }
00162 }
00163 }
00164
00165 nodes.insert(nodes.end(), node_set.begin(), node_set.end());
00166
00167 return true;
00168 }
00169
00170 #if defined(__APPLE__)
00171 boost::mutex g_xmlrpc_call_mutex;
00172 #endif
00173
00174 bool execute(const std::string& method, const XmlRpc::XmlRpcValue& request, XmlRpc::XmlRpcValue& response, XmlRpc::XmlRpcValue& payload, bool wait_for_master)
00175 {
00176 ros::WallTime start_time = ros::WallTime::now();
00177
00178 std::string master_host = getHost();
00179 uint32_t master_port = getPort();
00180 XmlRpc::XmlRpcClient *c = XMLRPCManager::instance()->getXMLRPCClient(master_host, master_port, "/");
00181 bool printed = false;
00182 bool slept = false;
00183 bool ok = true;
00184 do
00185 {
00186 bool b = false;
00187 {
00188 #if defined(__APPLE__)
00189 boost::mutex::scoped_lock lock(g_xmlrpc_call_mutex);
00190 #endif
00191
00192 b = c->execute(method.c_str(), request, response);
00193 }
00194
00195 ok = !ros::isShuttingDown() && !XMLRPCManager::instance()->isShuttingDown();
00196
00197 if (!b && ok)
00198 {
00199 if (!printed && wait_for_master)
00200 {
00201 ROS_ERROR("[%s] Failed to contact master at [%s:%d]. %s", method.c_str(), master_host.c_str(), master_port, wait_for_master ? "Retrying..." : "");
00202 printed = true;
00203 }
00204
00205 if (!wait_for_master)
00206 {
00207 XMLRPCManager::instance()->releaseXMLRPCClient(c);
00208 return false;
00209 }
00210
00211 if (g_retry_timeout.isZero())
00212 {
00213 if (g_retry_timeout > ros::WallDuration(0) && (ros::WallTime::now() - start_time) >= g_retry_timeout)
00214 {
00215 ROS_ERROR("[%s] Timed out trying to connect to the master after [%f] seconds", method.c_str(), g_retry_timeout.toSec());
00216 XMLRPCManager::instance()->releaseXMLRPCClient(c);
00217 return false;
00218 }
00219 }
00220
00221 ros::WallDuration(0.05).sleep();
00222 slept = true;
00223 }
00224 else
00225 {
00226 if (!XMLRPCManager::instance()->validateXmlrpcResponse(method, response, payload))
00227 {
00228 XMLRPCManager::instance()->releaseXMLRPCClient(c);
00229
00230 return false;
00231 }
00232
00233 break;
00234 }
00235
00236 ok = !ros::isShuttingDown() && !XMLRPCManager::instance()->isShuttingDown();
00237 } while(ok);
00238
00239 if (ok && slept)
00240 {
00241 ROS_INFO("Connected to master at [%s:%d]", master_host.c_str(), master_port);
00242 }
00243
00244 XMLRPCManager::instance()->releaseXMLRPCClient(c);
00245
00246 return true;
00247 }
00248
00249 }
00250
00251 }