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 #ifndef ROSCPP_SERVICE_MESSAGE_HELPER_H
00029 #define ROSCPP_SERVICE_MESSAGE_HELPER_H
00030
00031 #include "ros/forwards.h"
00032 #include "ros/common.h"
00033 #include "ros/message.h"
00034 #include "ros/message_traits.h"
00035 #include "ros/service_traits.h"
00036 #include "ros/serialization.h"
00037
00038 #include <boost/type_traits/is_base_of.hpp>
00039 #include <boost/utility/enable_if.hpp>
00040
00041 namespace ros
00042 {
00043 struct ServiceCallbackHelperCallParams
00044 {
00045 SerializedMessage request;
00046 SerializedMessage response;
00047 boost::shared_ptr<M_string> connection_header;
00048 };
00049
00050 template<typename T>
00051 typename boost::enable_if<boost::is_base_of<ros::Message, T> >::type assignServiceConnectionHeader(T* t, const boost::shared_ptr<M_string>& connection_header)
00052 {
00053 t->__connection_header = connection_header;
00054 }
00055
00056 template<typename T>
00057 typename boost::disable_if<boost::is_base_of<ros::Message, T> >::type assignServiceConnectionHeader(T* t, const boost::shared_ptr<M_string>& connection_header)
00058 {
00059 }
00060
00061 template<typename M>
00062 inline boost::shared_ptr<M> defaultServiceCreateFunction()
00063 {
00064 return boost::shared_ptr<M>(new M);
00065 }
00066
00067 template<typename MReq, typename MRes>
00068 struct ServiceSpecCallParams
00069 {
00070 boost::shared_ptr<MReq> request;
00071 boost::shared_ptr<MRes> response;
00072 boost::shared_ptr<M_string> connection_header;
00073 };
00074
00080 template<typename MReq, typename MRes>
00081 class ServiceEvent
00082 {
00083 public:
00084 typedef MReq RequestType;
00085 typedef MRes ResponseType;
00086 typedef boost::shared_ptr<RequestType> RequestPtr;
00087 typedef boost::shared_ptr<ResponseType> ResponsePtr;
00088 typedef boost::function<bool(ServiceEvent<RequestType, ResponseType>&)> CallbackType;
00089
00090 static bool call(const CallbackType& cb, ServiceSpecCallParams<RequestType, ResponseType>& params)
00091 {
00092 ServiceEvent<RequestType, ResponseType> event(params.request, params.response, params.connection_header);
00093 return cb(event);
00094 }
00095
00096 ServiceEvent(const boost::shared_ptr<MReq const>& req, const boost::shared_ptr<MRes>& res, const boost::shared_ptr<M_string>& connection_header)
00097 : request_(req)
00098 , response_(res)
00099 , connection_header_(connection_header)
00100 {}
00101
00105 const RequestType& getRequest() const { return *request_; }
00109 ResponseType& getResponse() const { return *response_; }
00113 M_string& getConnectionHeader() const { return *connection_header_; }
00114
00118 const std::string& getCallerName() const { return (*connection_header_)["callerid"]; }
00119 private:
00120 boost::shared_ptr<RequestType const> request_;
00121 boost::shared_ptr<ResponseType> response_;
00122 boost::shared_ptr<M_string> connection_header_;
00123 };
00124
00125 template<typename MReq, typename MRes>
00126 struct ServiceSpec
00127 {
00128 typedef MReq RequestType;
00129 typedef MRes ResponseType;
00130 typedef boost::shared_ptr<RequestType> RequestPtr;
00131 typedef boost::shared_ptr<ResponseType> ResponsePtr;
00132 typedef boost::function<bool(RequestType&, ResponseType&)> CallbackType;
00133
00134 static bool call(const CallbackType& cb, ServiceSpecCallParams<RequestType, ResponseType>& params)
00135 {
00136 return cb(*params.request, *params.response);
00137 }
00138 };
00139
00145 class ServiceCallbackHelper
00146 {
00147 public:
00148 virtual ~ServiceCallbackHelper() {}
00149 virtual bool call(ServiceCallbackHelperCallParams& params) = 0;
00150 };
00151 typedef boost::shared_ptr<ServiceCallbackHelper> ServiceCallbackHelperPtr;
00152
00156 template<typename Spec>
00157 class ServiceCallbackHelperT : public ServiceCallbackHelper
00158 {
00159 public:
00160 typedef typename Spec::RequestType RequestType;
00161 typedef typename Spec::ResponseType ResponseType;
00162 typedef typename Spec::RequestPtr RequestPtr;
00163 typedef typename Spec::ResponsePtr ResponsePtr;
00164 typedef typename Spec::CallbackType Callback;
00165 typedef boost::function<RequestPtr()> ReqCreateFunction;
00166 typedef boost::function<ResponsePtr()> ResCreateFunction;
00167
00168 ServiceCallbackHelperT(const Callback& callback,
00169 const ReqCreateFunction& create_req =
00170
00171
00172 static_cast<RequestPtr(*)()>(defaultServiceCreateFunction<RequestType>),
00173 const ResCreateFunction& create_res =
00174 static_cast<ResponsePtr(*)()>(defaultServiceCreateFunction<ResponseType>))
00175 : callback_(callback)
00176 , create_req_(create_req)
00177 , create_res_(create_res)
00178 {
00179 }
00180
00181 virtual bool call(ServiceCallbackHelperCallParams& params)
00182 {
00183 namespace ser = serialization;
00184 RequestPtr req(create_req_());
00185 ResponsePtr res(create_res_());
00186
00187 assignServiceConnectionHeader(req.get(), params.connection_header);
00188 ser::deserializeMessage(params.request, *req);
00189
00190 ServiceSpecCallParams<RequestType, ResponseType> call_params;
00191 call_params.request = req;
00192 call_params.response = res;
00193 call_params.connection_header = params.connection_header;
00194 bool ok = Spec::call(callback_, call_params);
00195 params.response = ser::serializeServiceResponse(ok, *res);
00196 return ok;
00197 }
00198
00199 private:
00200 Callback callback_;
00201 ReqCreateFunction create_req_;
00202 ResCreateFunction create_res_;
00203 };
00204
00205 }
00206
00207 #endif // ROSCPP_SERVICE_MESSAGE_HELPER_H