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 }