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 #include "resource_retriever/retriever.h"
00029
00030 #include <string.h>
00031
00032 #include <ros/package.h>
00033 #include <ros/console.h>
00034
00035 #include <curl/curl.h>
00036
00037 namespace resource_retriever
00038 {
00039
00040 class CURLStaticInit
00041 {
00042 public:
00043 CURLStaticInit()
00044 : initialized_(false)
00045 {
00046 CURLcode ret = curl_global_init(CURL_GLOBAL_ALL);
00047 if (ret != 0)
00048 {
00049 ROS_ERROR("Error initializing libcurl! retcode = %d", ret);
00050 }
00051 else
00052 {
00053 initialized_ = true;
00054 }
00055 }
00056
00057 ~CURLStaticInit()
00058 {
00059 if (initialized_)
00060 {
00061 curl_global_cleanup();
00062 }
00063 }
00064
00065 bool initialized_;
00066 };
00067 static CURLStaticInit g_curl_init;
00068
00069 Retriever::Retriever()
00070 {
00071 curl_handle_ = curl_easy_init();
00072 }
00073
00074 Retriever::~Retriever()
00075 {
00076 if (curl_handle_)
00077 {
00078 curl_easy_cleanup(curl_handle_);
00079 }
00080 }
00081
00082 struct MemoryBuffer
00083 {
00084 std::vector<uint8_t> v;
00085 };
00086
00087 size_t curlWriteFunc(void* buffer, size_t size, size_t nmemb, void* userp)
00088 {
00089 MemoryBuffer* membuf = (MemoryBuffer*)userp;
00090
00091 size_t prev_size = membuf->v.size();
00092 membuf->v.resize(prev_size + size * nmemb);
00093 memcpy(&membuf->v[prev_size], buffer, size * nmemb);
00094
00095 return size * nmemb;
00096 }
00097
00098 MemoryResource Retriever::get(const std::string& url)
00099 {
00100 std::string mod_url = url;
00101 if (url.find("package://") == 0)
00102 {
00103 mod_url.erase(0, strlen("package://"));
00104 size_t pos = mod_url.find("/");
00105 if (pos == std::string::npos)
00106 {
00107 throw Exception(url, "Could not parse package:// format into file:// format");
00108 }
00109
00110 std::string package = mod_url.substr(0, pos);
00111 mod_url.erase(0, pos);
00112 std::string package_path = ros::package::getPath(package);
00113
00114 if (package_path.empty())
00115 {
00116 throw Exception(url, "Package [" + package + "] does not exist");
00117 }
00118
00119 mod_url = "file://" + package_path + mod_url;
00120 }
00121
00122 curl_easy_setopt(curl_handle_, CURLOPT_URL, mod_url.c_str());
00123 curl_easy_setopt(curl_handle_, CURLOPT_WRITEFUNCTION, curlWriteFunc);
00124
00125 char error_buffer[CURL_ERROR_SIZE];
00126 curl_easy_setopt(curl_handle_, CURLOPT_ERRORBUFFER , error_buffer);
00127
00128 MemoryResource res;
00129 MemoryBuffer buf;
00130 curl_easy_setopt(curl_handle_, CURLOPT_WRITEDATA, &buf);
00131
00132 CURLcode ret = curl_easy_perform(curl_handle_);
00133 if (ret != 0)
00134 {
00135 throw Exception(mod_url, error_buffer);
00136 }
00137 else if (!buf.v.empty())
00138 {
00139 res.size = buf.v.size();
00140 res.data.reset(new uint8_t[res.size]);
00141 memcpy(res.data.get(), &buf.v[0], res.size);
00142 }
00143
00144 return res;
00145 }
00146
00147 }