$search
00001 /* 00002 * Copyright (C) 2009, Willow Garage, Inc. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are met: 00006 * * Redistributions of source code must retain the above copyright notice, 00007 * this list of conditions and the following disclaimer. 00008 * * Redistributions in binary form must reproduce the above copyright 00009 * notice, this list of conditions and the following disclaimer in the 00010 * documentation and/or other materials provided with the distribution. 00011 * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its 00012 * contributors may be used to endorse or promote products derived from 00013 * this software without specific prior written permission. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00016 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00017 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00019 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00020 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00021 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00023 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00024 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00025 * POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "ros/service_client.h" 00029 #include "ros/service_server_link.h" 00030 #include "ros/connection.h" 00031 #include "ros/service_manager.h" 00032 #include "ros/service.h" 00033 00034 namespace ros 00035 { 00036 00037 ServiceClient::Impl::Impl() 00038 : is_shutdown_(false) 00039 { } 00040 00041 ServiceClient::Impl::~Impl() 00042 { 00043 shutdown(); 00044 } 00045 00046 void ServiceClient::Impl::shutdown() 00047 { 00048 if (!is_shutdown_) 00049 { 00050 if (!persistent_) 00051 { 00052 is_shutdown_ = true; 00053 } 00054 00055 if (server_link_) 00056 { 00057 server_link_->getConnection()->drop(Connection::Destructing); 00058 server_link_.reset(); 00059 } 00060 } 00061 } 00062 00063 bool ServiceClient::Impl::isValid() const 00064 { 00065 // Non-persistent connections are always valid 00066 if (!persistent_) 00067 { 00068 return true; 00069 } 00070 00071 if (is_shutdown_) 00072 { 00073 return false; 00074 } 00075 00076 if (!server_link_) 00077 { 00078 return false; 00079 } 00080 00081 return server_link_->isValid(); 00082 } 00083 00084 ServiceClient::ServiceClient(const std::string& service_name, bool persistent, const M_string& header_values, const std::string& service_md5sum) 00085 : impl_(new Impl) 00086 { 00087 impl_->name_ = service_name; 00088 impl_->persistent_ = persistent; 00089 impl_->header_values_ = header_values; 00090 impl_->service_md5sum_ = service_md5sum; 00091 00092 if (persistent) 00093 { 00094 impl_->server_link_ = ServiceManager::instance()->createServiceServerLink(impl_->name_, impl_->persistent_, impl_->service_md5sum_, impl_->service_md5sum_, impl_->header_values_); 00095 } 00096 } 00097 00098 ServiceClient::ServiceClient(const ServiceClient& rhs) 00099 { 00100 impl_ = rhs.impl_; 00101 } 00102 00103 ServiceClient::~ServiceClient() 00104 { 00105 00106 } 00107 00108 bool ServiceClient::call(const SerializedMessage& req, SerializedMessage& resp, const std::string& service_md5sum) 00109 { 00110 if (service_md5sum != impl_->service_md5sum_) 00111 { 00112 ROS_ERROR("Call to service [%s] with md5sum [%s] does not match md5sum when the handle was created ([%s])", impl_->name_.c_str(), service_md5sum.c_str(), impl_->service_md5sum_.c_str()); 00113 00114 return false; 00115 } 00116 00117 ServiceServerLinkPtr link; 00118 00119 if (impl_->persistent_) 00120 { 00121 if (!impl_->server_link_) 00122 { 00123 impl_->server_link_ = ServiceManager::instance()->createServiceServerLink(impl_->name_, impl_->persistent_, service_md5sum, service_md5sum, impl_->header_values_); 00124 00125 if (!impl_->server_link_) 00126 { 00127 return false; 00128 } 00129 } 00130 00131 link = impl_->server_link_; 00132 } 00133 else 00134 { 00135 link = ServiceManager::instance()->createServiceServerLink(impl_->name_, impl_->persistent_, service_md5sum, service_md5sum, impl_->header_values_); 00136 00137 if (!link) 00138 { 00139 return false; 00140 } 00141 } 00142 00143 bool ret = link->call(req, resp); 00144 link.reset(); 00145 00146 // If we're shutting down but the node haven't finished yet, wait until we do 00147 while (ros::isShuttingDown() && ros::ok()) 00148 { 00149 ros::WallDuration(0.001).sleep(); 00150 } 00151 00152 return ret; 00153 } 00154 00155 bool ServiceClient::isValid() const 00156 { 00157 if (!impl_) 00158 { 00159 return false; 00160 } 00161 00162 return impl_->isValid(); 00163 } 00164 00165 void ServiceClient::shutdown() 00166 { 00167 if (impl_) 00168 { 00169 impl_->shutdown(); 00170 } 00171 } 00172 00173 bool ServiceClient::waitForExistence(ros::Duration timeout) 00174 { 00175 if (impl_) 00176 { 00177 return service::waitForService(impl_->name_, timeout); 00178 } 00179 00180 return false; 00181 } 00182 00183 bool ServiceClient::exists() 00184 { 00185 if (impl_) 00186 { 00187 return service::exists(impl_->name_, false); 00188 } 00189 00190 return false; 00191 } 00192 00193 std::string ServiceClient::getService() 00194 { 00195 if (impl_) 00196 { 00197 return impl_->name_; 00198 } 00199 00200 return ""; 00201 } 00202 00203 }