service_client_link.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
37 #include "ros/header.h"
38 #include "ros/connection.h"
39 #include "ros/service_manager.h"
41 #include "ros/this_node.h"
42 #include "ros/file_log.h"
43 
44 #include <boost/bind.hpp>
45 
46 namespace ros
47 {
48 
50 : persistent_(false)
51 {
52 }
53 
55 {
56  if (connection_)
57  {
58  if (connection_->isSendingHeaderError())
59  {
60  connection_->removeDropListener(dropped_conn_);
61  }
62  else
63  {
65  }
66  }
67 }
68 
70 {
71  connection_ = connection;
72  dropped_conn_ = connection_->addDropListener(boost::bind(&ServiceClientLink::onConnectionDropped, this, _1));
73 
74  return true;
75 }
76 
78 {
79  std::string md5sum, service, client_callerid;
80  if (!header.getValue("md5sum", md5sum)
81  || !header.getValue("service", service)
82  || !header.getValue("callerid", client_callerid))
83  {
84  std::string msg("bogus tcpros header. did not have the "
85  "required elements: md5sum, service, callerid");
86 
87  ROS_ERROR("%s", msg.c_str());
88  connection_->sendHeaderError(msg);
89 
90  return false;
91  }
92 
93  std::string persistent;
94  if (header.getValue("persistent", persistent))
95  {
96  if (persistent == "1" || persistent == "true")
97  {
98  persistent_ = true;
99  }
100  }
101 
102  ROSCPP_LOG_DEBUG("Service client [%s] wants service [%s] with md5sum [%s]", client_callerid.c_str(), service.c_str(), md5sum.c_str());
103  ServicePublicationPtr ss = ServiceManager::instance()->lookupServicePublication(service);
104  if (!ss)
105  {
106  std::string msg = std::string("received a tcpros connection for a "
107  "nonexistent service [") +
108  service + std::string("].");
109 
110  ROS_ERROR("%s", msg.c_str());
111  connection_->sendHeaderError(msg);
112 
113  return false;
114  }
115  if (ss->getMD5Sum() != md5sum &&
116  (md5sum != std::string("*") && ss->getMD5Sum() != std::string("*")))
117  {
118  std::string msg = std::string("client wants service ") + service +
119  std::string(" to have md5sum ") + md5sum +
120  std::string(", but it has ") + ss->getMD5Sum() +
121  std::string(". Dropping connection.");
122 
123  ROS_ERROR("%s", msg.c_str());
124  connection_->sendHeaderError(msg);
125 
126  return false;
127  }
128 
129  // Check whether the service (ss here) has been deleted from
130  // advertised_topics through a call to unadvertise(), which could
131  // have happened while we were waiting for the subscriber to
132  // provide the md5sum.
133  if(ss->isDropped())
134  {
135  std::string msg = std::string("received a tcpros connection for a "
136  "nonexistent service [") +
137  service + std::string("].");
138 
139  ROS_ERROR("%s", msg.c_str());
140  connection_->sendHeaderError(msg);
141 
142  return false;
143  }
144  else
145  {
147 
148  // Send back a success, with info
149  M_string m;
150  m["request_type"] = ss->getRequestDataType();
151  m["response_type"] = ss->getResponseDataType();
152  m["type"] = ss->getDataType();
153  m["md5sum"] = ss->getMD5Sum();
154  m["callerid"] = this_node::getName();
155  connection_->writeHeader(m, boost::bind(&ServiceClientLink::onHeaderWritten, this, _1));
156 
157  ss->addServiceClientLink(shared_from_this());
158  }
159 
160  return true;
161 }
162 
164 {
165  (void)conn;
166  ROS_ASSERT(conn == connection_);
167 
168  if (ServicePublicationPtr parent = parent_.lock())
169  {
170  parent->removeServiceClientLink(shared_from_this());
171  }
172 }
173 
175 {
176  (void)conn;
177  connection_->read(4, boost::bind(&ServiceClientLink::onRequestLength, this, _1, _2, _3, _4));
178 }
179 
180 void ServiceClientLink::onRequestLength(const ConnectionPtr& conn, const boost::shared_array<uint8_t>& buffer, uint32_t size, bool success)
181 {
182  (void)size;
183  if (!success)
184  return;
185 
186  ROS_ASSERT(conn == connection_);
187  ROS_ASSERT(size == 4);
188 
189  uint32_t len = *((uint32_t*)buffer.get());
190 
191  if (len > 1000000000)
192  {
193  ROS_ERROR("a message of over a gigabyte was " \
194  "predicted in tcpros. that seems highly " \
195  "unlikely, so I'll assume protocol " \
196  "synchronization is lost.");
197  conn->drop(Connection::Destructing);
198  return;
199  }
200 
201  connection_->read(len, boost::bind(&ServiceClientLink::onRequest, this, _1, _2, _3, _4));
202 }
203 
204 void ServiceClientLink::onRequest(const ConnectionPtr& conn, const boost::shared_array<uint8_t>& buffer, uint32_t size, bool success)
205 {
206  (void)conn;
207  if (!success)
208  return;
209 
210  ROS_ASSERT(conn == connection_);
211 
212  if (ServicePublicationPtr parent = parent_.lock())
213  {
214  parent->processRequest(buffer, size, shared_from_this());
215  }
216  else
217  {
218  ROS_BREAK();
219  }
220 }
221 
223 {
224  (void)conn;
225  ROS_ASSERT(conn == connection_);
226 
227  if (persistent_)
228  {
229  connection_->read(4, boost::bind(&ServiceClientLink::onRequestLength, this, _1, _2, _3, _4));
230  }
231  else
232  {
234  }
235 }
236 
238 {
239  (void)ok;
240  connection_->write(res.buf, res.num_bytes, boost::bind(&ServiceClientLink::onResponseWritten, this, _1));
241 }
242 
243 
244 } // namespace ros
245 
ROSCPP_DECL const std::string & getName()
Returns the name of the current node.
Definition: this_node.cpp:74
static const ServiceManagerPtr & instance()
std::map< std::string, std::string > M_string
#define ROSCPP_LOG_DEBUG(...)
Definition: file_log.h:35
ROSCPP_DECL bool ok()
Check whether it&#39;s time to exit.
Definition: init.cpp:589
boost::weak_ptr< ServicePublication > ServicePublicationWPtr
boost::shared_array< uint8_t > buf
bool getValue(const std::string &key, std::string &value) const
const char * md5sum()
#define ROS_ASSERT(cond)
#define ROS_BREAK()
#define ROS_ERROR(...)


roscpp
Author(s): Morgan Quigley, Josh Faust, Brian Gerkey, Troy Straszheim, Dirk Thomas
autogenerated on Mon Feb 28 2022 23:33:27