Go to the documentation of this file.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
00029
00030 #include <rve_rpc/server.h>
00031
00032 #include <ros/ros.h>
00033 #include <ros/callback_queue.h>
00034
00035 #include <rve_rpc/ProtocolMethodsAdded.h>
00036
00037 namespace rve_rpc
00038 {
00039
00040 struct Server::Impl
00041 {
00042 Impl(const std::string& name, const ros::NodeHandle& nh);
00043 ~Impl();
00044 void ready();
00045 void addMethod(const std::string& name, const CallbackHelperPtr& helper);
00046
00047 void callback(const ros::MessageEvent<RequestWrapper const>& evt);
00048
00049 void subscriberConnected(const ros::SingleSubscriberPublisher& pub);
00050 ResponseWrapperPtr createClientConnectedResponse();
00051
00052 void handleProtocolMessage(const RequestWrapperConstPtr& req);
00053 void handleClientConnected(const RequestWrapperConstPtr& req);
00054
00055 void respond(const ResponseWrapperConstPtr& res);
00056
00057 ros::NodeHandle nh_;
00058 ros::Publisher pub_;
00059 ros::Subscriber sub_;
00060 std::string name_;
00061 bool ready_;
00062
00063 typedef std::map<std::string, CallbackHelperPtr> M_Method;
00064 M_Method methods_;
00065 boost::mutex methods_mutex_;
00066
00067 bool shutting_down_;
00068 boost::mutex shutting_down_mutex_;
00069 };
00070
00071 Server::Impl::Impl(const std::string& name, const ros::NodeHandle& nh)
00072 : nh_(nh, name)
00073 , name_(name)
00074 , ready_(false)
00075 , shutting_down_(false)
00076 {
00077 }
00078
00079 Server::Impl::~Impl()
00080 {
00081 {
00082 boost::mutex::scoped_lock lock(shutting_down_mutex_);
00083 shutting_down_ = true;
00084 }
00085
00086 pub_.shutdown();
00087 sub_.shutdown();
00088 }
00089
00090 void fillMethodSpec(const std::string& name, const CallbackHelperPtr& helper, MethodSpec& spec)
00091 {
00092 spec.name = name;
00093 spec.request_md5sum = helper->getRequestMD5Sum();
00094 spec.request_datatype = helper->getRequestDataType();
00095 spec.request_definition = helper->getRequestDefinition();
00096 spec.response_md5sum = helper->getResponseMD5Sum();
00097 spec.response_datatype = helper->getResponseDataType();
00098 spec.response_definition = helper->getResponseDefinition();
00099 }
00100
00101 ResponseWrapperPtr Server::Impl::createClientConnectedResponse()
00102 {
00103 std::pair<ResponseWrapperPtr, boost::shared_ptr<ProtocolMethodsAdded> > pair = makeResponse<ProtocolMethodsAdded>();
00104 ResponseWrapperPtr& res = pair.first;
00105 ProtocolMethodsAddedPtr& header = pair.second;
00106
00107 res->request_id = rve_common::UUID::generate();
00108 res->protocol = Response::PROTOCOL_METHODS_ADDED;
00109
00110 M_Method::const_iterator it = methods_.begin();
00111 M_Method::const_iterator end = methods_.end();
00112 for (; it != end; ++it)
00113 {
00114 const std::string& name = it->first;
00115 const CallbackHelperPtr& helper = it->second;
00116 MethodSpec spec;
00117 fillMethodSpec(name, helper, spec);
00118 header->methods.push_back(spec);
00119 }
00120
00121 return res;
00122 }
00123
00124 void Server::Impl::subscriberConnected(const ros::SingleSubscriberPublisher& pub)
00125 {
00126 pub.publish(createClientConnectedResponse());
00127 }
00128
00129 void Server::Impl::handleClientConnected(const RequestWrapperConstPtr& req)
00130 {
00131 pub_.publish(createClientConnectedResponse());
00132 }
00133
00134 void Server::Impl::handleProtocolMessage(const RequestWrapperConstPtr& req)
00135 {
00136 switch (req->protocol)
00137 {
00138 case Request::PROTOCOL_CLIENT_CONNECT:
00139 handleClientConnected(req);
00140 break;
00141 default:
00142 ROS_ERROR("Unknown protocol type %d", req->protocol);
00143 }
00144 }
00145
00146 void Server::Impl::ready()
00147 {
00148 ROS_ASSERT(!pub_);
00149 ROS_ASSERT(!sub_);
00150 pub_ = nh_.advertise<ResponseWrapper>("response", 0, boost::bind(&Impl::subscriberConnected, this, _1));
00151 sub_ = nh_.subscribe("request", 0, &Impl::callback, this);
00152 ready_ = true;
00153 }
00154
00155 void Server::Impl::addMethod(const std::string& name, const CallbackHelperPtr& helper)
00156 {
00157 {
00158 boost::mutex::scoped_lock lock(methods_mutex_);
00159 ROS_ASSERT(methods_.count(name) == 0);
00160 methods_[name] = helper;
00161 }
00162
00163 if (ready_)
00164 {
00165 MethodSpec spec;
00166 fillMethodSpec(name, helper, spec);
00167
00168 std::pair<ResponseWrapperPtr, boost::shared_ptr<ProtocolMethodsAdded> > pair = makeResponse<ProtocolMethodsAdded>();
00169 ResponseWrapperPtr& res = pair.first;
00170 res->request_id = rve_common::UUID::generate();
00171 res->protocol = Response::PROTOCOL_METHODS_ADDED;
00172
00173 ProtocolMethodsAddedPtr& methods_added = pair.second;
00174 methods_added->methods.push_back(spec);
00175 pub_.publish(res);
00176 }
00177 }
00178
00179 void Server::Impl::callback(const ros::MessageEvent<RequestWrapper const>& evt)
00180 {
00181 RequestWrapperConstPtr req = evt.getMessage();
00182 if (req->protocol > 0)
00183 {
00184 handleProtocolMessage(req);
00185 }
00186 else
00187 {
00188 CallbackHelperPtr helper;
00189
00190 {
00191 boost::mutex::scoped_lock lock(methods_mutex_);
00192 M_Method::iterator it = methods_.find(req->method);
00193 if (it == methods_.end())
00194 {
00195 ResponseWrapperPtr res(new ResponseWrapper);
00196 res->request_id = req->request_id;
00197 res->error_code = Response::UNKNOWN_METHOD;
00198 res->error_string = req->method;
00199 pub_.publish(res);
00200 return;
00201 }
00202
00203 helper = it->second;
00204 }
00205
00206
00207 helper->call(evt, boost::bind(&Server::Impl::respond, this, _1));
00208 }
00209 }
00210
00211 void Server::Impl::respond(const ResponseWrapperConstPtr& res)
00212 {
00213 boost::mutex::scoped_lock lock(shutting_down_mutex_);
00214 if (shutting_down_)
00215 {
00216 return;
00217 }
00218
00219 pub_.publish(res);
00220 }
00221
00223
00225
00226 Server::Server(const std::string& name, const ros::NodeHandle& nh)
00227 : impl_(new Impl(name, nh))
00228 {
00229
00230 }
00231
00232 void Server::ready()
00233 {
00234 impl_->ready();
00235 }
00236
00237 void Server::addMethod(const std::string& name, const CallbackHelperPtr& helper)
00238 {
00239 impl_->addMethod(name, helper);
00240 }
00241
00242 }