7 #include "packager/media/base/http_key_fetcher.h"
11 #include "packager/base/logging.h"
12 #include "packager/base/strings/stringprintf.h"
13 #include "packager/base/synchronization/lock.h"
18 const char kUserAgentString[] =
"shaka-packager-http_fetcher/1.0";
19 const char kSoapActionHeader[] =
20 "SOAPAction: \"http://schemas.microsoft.com/DRM/2007/03/protocols/"
21 "AcquirePackagingData\"";
22 const char kXmlContentTypeHeader[] =
"Content-Type: text/xml; charset=UTF-8";
27 ScopedCurl() { ptr_ = curl_easy_init(); }
30 curl_easy_cleanup(ptr_);
33 CURL*
get() {
return ptr_; }
37 DISALLOW_COPY_AND_ASSIGN(ScopedCurl);
40 size_t AppendToString(
char* ptr,
size_t size,
size_t nmemb, std::string* response) {
43 const size_t total_size = size * nmemb;
44 response->append(ptr, total_size);
48 class LibCurlInitializer {
50 LibCurlInitializer() : initialized_(false) {
51 base::AutoLock lock(lock_);
53 curl_global_init(CURL_GLOBAL_DEFAULT);
58 ~LibCurlInitializer() {
59 base::AutoLock lock(lock_);
61 curl_global_cleanup();
70 DISALLOW_COPY_AND_ASSIGN(LibCurlInitializer);
80 : timeout_in_seconds_(timeout_in_seconds) {}
82 HttpKeyFetcher::~HttpKeyFetcher() {}
85 const std::string& request,
86 std::string* response) {
87 return Post(url, request, response);
91 return FetchInternal(GET, path,
"", response);
95 const std::string& data,
96 std::string* response) {
97 return FetchInternal(POST, path, data, response);
100 Status HttpKeyFetcher::FetchInternal(HttpMethod method,
101 const std::string& path,
102 const std::string& data,
103 std::string* response) {
104 DCHECK(method == GET || method == POST);
105 static LibCurlInitializer lib_curl_initializer;
107 ScopedCurl scoped_curl;
108 CURL* curl = scoped_curl.get();
110 LOG(ERROR) <<
"curl_easy_init() failed.";
111 return Status(error::HTTP_FAILURE,
"curl_easy_init() failed.");
115 curl_easy_setopt(curl, CURLOPT_URL, path.c_str());
116 curl_easy_setopt(curl, CURLOPT_USERAGENT, kUserAgentString);
117 curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout_in_seconds_);
118 curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
119 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
120 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, AppendToString);
121 curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
123 if (!client_cert_private_key_file_.empty() && !client_cert_file_.empty()) {
126 curl_easy_setopt(curl, CURLOPT_SSLKEY,
127 client_cert_private_key_file_.data());
128 if (!client_cert_private_key_password_.empty()) {
129 curl_easy_setopt(curl, CURLOPT_KEYPASSWD,
130 client_cert_private_key_password_.data());
132 curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE,
"PEM");
133 curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE,
"PEM");
134 curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert_file_.data());
136 if (!ca_file_.empty()) {
138 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
139 curl_easy_setopt(curl, CURLOPT_CAINFO, ca_file_.data());
141 if (method == POST) {
142 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
143 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size());
144 if (data.find(
"soap:Envelope") > 0) {
146 struct curl_slist *chunk = NULL;
147 chunk = curl_slist_append(chunk, kXmlContentTypeHeader);
148 chunk = curl_slist_append(chunk, kSoapActionHeader);
149 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
152 CURLcode res = curl_easy_perform(curl);
153 if (res != CURLE_OK) {
154 std::string error_message = base::StringPrintf(
155 "curl_easy_perform() failed: %s.", curl_easy_strerror(res));
156 if (res == CURLE_HTTP_RETURNED_ERROR) {
157 long response_code = 0;
158 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
159 error_message += base::StringPrintf(
" Response code: %ld.", response_code);
162 LOG(ERROR) << error_message;
164 res == CURLE_OPERATION_TIMEDOUT ? error::TIME_OUT : error::HTTP_FAILURE,