server.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
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   // Make sure we don't get any callbacks while destructing
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 // Interface
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 } // namespace rve_rpc


rve_rpc
Author(s): Josh Faust
autogenerated on Wed Dec 11 2013 14:30:53