CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/EventFilter/StorageManager/src/CurlInterface.cc

Go to the documentation of this file.
00001 // $Id: CurlInterface.cc,v 1.4 2011/11/16 14:32:22 mommsen Exp $
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   //setup array to store all of the mutexes available to OpenSSL.
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); // seconds
00104   curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // do not send any signals
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