00001
00003
00004 #include "EventFilter/StorageManager/interface/CurlInterface.h"
00005 #include "EventFilter/StorageManager/interface/Exception.h"
00006
00007 using namespace stor;
00008
00009 CurlInterfacePtr CurlInterface::interface_;
00010 pthread_mutex_t* CurlInterface::mutexes_ = 0;
00011
00012
00013 CurlInterface::CurlInterface()
00014 {
00015 curl_global_init(CURL_GLOBAL_ALL);
00016 const int cryptoNumLocks = CRYPTO_num_locks();
00017
00018
00019 mutexes_ = (pthread_mutex_t*)malloc( cryptoNumLocks * sizeof(pthread_mutex_t) );
00020 if ( ! mutexes_ )
00021 XCEPT_RAISE(stor::exception::Exception, "Failed to allocate memory for SSL mutexes");
00022
00023 for (int i = 0; i < cryptoNumLocks; ++i)
00024 pthread_mutex_init(&mutexes_[i],0);
00025
00026 CRYPTO_set_id_callback(sslIdFunction);
00027 CRYPTO_set_locking_callback(sslLockingFunction);
00028 }
00029
00030
00031 CurlInterface::~CurlInterface()
00032 {
00033 CRYPTO_set_id_callback(0);
00034 CRYPTO_set_locking_callback(0);
00035
00036 for (int i = 0; i < CRYPTO_num_locks(); ++i)
00037 pthread_mutex_destroy(&mutexes_[i]);
00038 free(mutexes_);
00039 mutexes_ = NULL;
00040
00041 curl_global_cleanup();
00042 }
00043
00044
00045 boost::shared_ptr<CurlInterface> CurlInterface::getInterface()
00046 {
00047 if (interface_.get() == 0)
00048 {
00049 interface_.reset( new CurlInterface() );
00050 }
00051
00052 return interface_;
00053 }
00054
00055
00056 CURLcode CurlInterface::getContent
00057 (
00058 const std::string& url,
00059 const std::string& user,
00060 Content& content
00061 )
00062 {
00063 CURL* curl = curl_easy_init();
00064 if ( ! curl ) return CURLE_FAILED_INIT;
00065
00066 curl_easy_setopt(curl, CURLOPT_USERPWD, user.c_str());
00067
00068 return do_curl(curl, url, content);
00069 }
00070
00071
00072 CURLcode CurlInterface::postBinaryMessage
00073 (
00074 const std::string& url,
00075 void* buf,
00076 size_t size,
00077 Content& content
00078 )
00079 {
00080 CURL* curl = curl_easy_init();
00081 if ( ! curl ) return CURLE_FAILED_INIT;
00082
00083 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf);
00084 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, size);
00085
00086 struct curl_slist *headers=NULL;
00087 headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
00088 headers = curl_slist_append(headers, "Content-Transfer-Encoding: binary");
00089 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
00090
00091 const CURLcode status = do_curl(curl, url, content);
00092 curl_slist_free_all(headers);
00093
00094 return status;
00095 }
00096
00097
00098 CURLcode CurlInterface::do_curl(CURL* curl, const std::string& url, Content& content)
00099 {
00100 char errorBuffer[CURL_ERROR_SIZE];
00101
00102 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
00103 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 4);
00104 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
00105 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, stor::CurlInterface::writeToString);
00106 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
00107 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
00108 curl_easy_setopt(curl, CURLOPT_FAILONERROR,1);
00109
00110 const CURLcode returnCode = curl_easy_perform(curl);
00111
00112 curl_easy_cleanup(curl);
00113
00114 if (returnCode != CURLE_OK)
00115 {
00116 size_t i = 0;
00117 content.clear();
00118 while ( errorBuffer[i] != '\0' )
00119 {
00120 content.push_back( errorBuffer[i] );
00121 ++i;
00122 }
00123 content.push_back('\0');
00124 }
00125
00126 return returnCode;
00127 }
00128
00129
00130 size_t CurlInterface::writeToString(char *data, size_t size, size_t nmemb, Content* buffer)
00131 {
00132 if (buffer == NULL) return 0;
00133
00134 const size_t length = size * nmemb;
00135 buffer->insert(buffer->end(), data, data+length);
00136 return length;
00137 }
00138
00139
00140 void CurlInterface::sslLockingFunction(int mode, int n, const char* file, int line)
00141 {
00142 if (mode & CRYPTO_LOCK)
00143 pthread_mutex_lock(&mutexes_[n]);
00144 else
00145 pthread_mutex_unlock(&mutexes_[n]);
00146 }
00147
00148
00149 unsigned long CurlInterface::sslIdFunction(void)
00150 {
00151 return ( (unsigned long)pthread_self() );
00152 }
00153
00154