From 875c39090c7dfb1c760f890f3d158d913f366438 Mon Sep 17 00:00:00 2001 From: jbleclere Date: Fri, 4 Sep 2020 12:17:37 +0000 Subject: [PATCH] debug --- internal_inc/ws_client.h | 105 +++++++++++++++++++++---------------- source/csp.cpp | 18 +++---- source/drm_manager.cpp | 7 +-- source/utils.cpp | 2 +- source/ws_client.cpp | 109 +++++++++++++++++++-------------------- 5 files changed, 123 insertions(+), 118 deletions(-) diff --git a/internal_inc/ws_client.h b/internal_inc/ws_client.h index ed87e711..4493e966 100644 --- a/internal_inc/ws_client.h +++ b/internal_inc/ws_client.h @@ -53,6 +53,7 @@ class CurlEasyPost { const uint32_t cConnectionTimeoutMS = 30000; // Timeout default value in milliseconds CURL *curl = NULL; + std::string mUrl; struct curl_slist *mHeaders_p = NULL; struct curl_slist *mHostResolveList = NULL; std::list data; // keep data until request performed @@ -81,82 +82,96 @@ class CurlEasyPost { || resp_code == 560 // Accelize License generation temporary issue ; } + static DRM_ErrorCode httpCode2DrmCode( const uint32_t http_resp_code ) { + if ( http_resp_code == 200 ) + return DRM_OK; + if ( CurlEasyPost::is_error_retryable( http_resp_code ) ) + return DRM_WSMayRetry; + if ( ( http_resp_code >= 400 ) && ( http_resp_code < 500 ) ) + return DRM_WSReqError; + return DRM_WSError; + } CurlEasyPost(); ~CurlEasyPost(); - long perform( std::string* resp, std::chrono::steady_clock::time_point& deadline ); - long perform( std::string* resp, std::chrono::milliseconds& timeout ); - long perform_put( std::string* resp, std::string url, const uint32_t& timeout_ms ); + double getTotalTime(); + + void setVerbosity( const uint32_t verbosity ); + + void setHostResolves( const Json::Value& host_json ); + + void setURL( std::string url ); + + template + void appendHeader( T&& header ) { + data.push_back( std::forward(header) ); + Debug2( "Add {} to CURL header", std::forward(header) ); + mHeaders_p = curl_slist_append( mHeaders_p, data.back().c_str() ); + } + + template + void setPostFields( T&& postfields ) { + data.push_back( std::forward(postfields) ); + curl_easy_setopt( curl, CURLOPT_POSTFIELDSIZE, data.back().size() ); + curl_easy_setopt( curl, CURLOPT_POSTFIELDS, data.back().c_str() ); + } + + void setConnectionTimeoutMS( const uint32_t timeoutMS ) { mConnectionTimeoutMS = timeoutMS; } + uint32_t getConnectionTimeoutMS() const { return mConnectionTimeoutMS; } + + uint32_t perform( std::string* resp, std::chrono::steady_clock::time_point& deadline ); + uint32_t perform( std::string* resp, int32_t timeout ); + std::string perform_put( std::string url, const uint32_t& timeout_ms ); template T perform( std::string url, const uint32_t& timeout_ms ) { - T resp; + T response; + uint32_t resp_code; // Configure and execute CURL command curl_easy_setopt( curl, CURLOPT_URL, url.c_str() ); if ( mHeaders_p ) { curl_easy_setopt( curl, CURLOPT_HTTPHEADER, mHeaders_p ); } - curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, &CurlEasyPost::write_callback ); - curl_easy_setopt( curl, CURLOPT_WRITEDATA, &resp ); - curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, mErrBuff.data() ); - curl_easy_setopt( curl, CURLOPT_FOLLOWLOCATION, 1L ); + curl_easy_setopt( curl, CURLOPT_WRITEDATA, &response ); curl_easy_setopt( curl, CURLOPT_CONNECTTIMEOUT_MS, mConnectionTimeoutMS ); if ( timeout_ms <= 0 ) Throw( DRM_WSTimedOut, "Did not perform HTTP request to Accelize webservice because deadline is reached." ); curl_easy_setopt( curl, CURLOPT_TIMEOUT_MS, timeout_ms ); CURLcode res = curl_easy_perform( curl ); - // Analyze HTTP answer - long resp_code; - curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &resp_code ); - Debug( "Received code {} from {} in {} ms", resp_code, url, getTotalTime() * 1000 ); - + // Analyze libcurl response if ( res != CURLE_OK ) { if ( res == CURLE_COULDNT_RESOLVE_PROXY || res == CURLE_COULDNT_RESOLVE_HOST || res == CURLE_COULDNT_CONNECT || res == CURLE_OPERATION_TIMEDOUT ) { Throw( DRM_WSMayRetry, "Failed performing HTTP request to Accelize webservice ({}) : {}", - curl_easy_strerror( res ), mErrBuff.data() ); + curl_easy_strerror( res ), mErrBuff.data() ); //LCOV_EXCL_LINE } else { Throw( DRM_ExternFail, "Failed performing HTTP request to Accelize webservice ({}) : {}", - curl_easy_strerror( res ), mErrBuff.data() ); + curl_easy_strerror( res ), mErrBuff.data() ); //LCOV_EXCL_LINE } } - return resp; - } - - double getTotalTime(); - - void setVerbosity( const uint32_t verbosity ); - - void setHostResolves( const Json::Value& host_json ); - - template - void setURL(T&& url) { - data.push_back( std::forward(url) ); - curl_easy_setopt( curl, CURLOPT_URL, data.back().c_str() ); - } - - template - void appendHeader( T&& header ) { - data.push_back( std::forward(header) ); - Debug2( "Add {} to CURL header", std::forward(header) ); - mHeaders_p = curl_slist_append( mHeaders_p, data.back().c_str() ); - } + curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &resp_code ); + Debug( "Received code {} from {} in {} ms", resp_code, url, getTotalTime() * 1000 ); - template - void setPostFields( T&& postfields ) { - data.push_back( std::forward(postfields) ); - curl_easy_setopt( curl, CURLOPT_POSTFIELDSIZE, data.back().size() ); - curl_easy_setopt( curl, CURLOPT_POSTFIELDS, data.back().c_str() ); + // Analyze HTTP response + if ( resp_code != 200 ) { + // An error occurred + DRM_ErrorCode drm_error; + if ( CurlEasyPost::is_error_retryable( resp_code ) ) + drm_error = DRM_WSMayRetry; + else if ( ( resp_code >= 400 ) && ( resp_code < 500 ) ) + drm_error = DRM_WSReqError; + else + drm_error = DRM_WSError; + Throw( drm_error, "OAuth2 Web Service error {}: {}", resp_code, response ); + } + return response; } - void setConnectionTimeoutMS( const uint32_t timeoutMS ) { mConnectionTimeoutMS = timeoutMS; } - uint32_t getConnectionTimeoutMS() const { return mConnectionTimeoutMS; } - protected: static size_t write_callback( void *contents, size_t size, size_t nmemb, std::string *userp ) { @@ -164,7 +179,7 @@ class CurlEasyPost { try { userp->append( (const char*)contents, realsize ); } catch( const std::bad_alloc& e ) { - Throw( DRM_ExternFail, "Curl write callback exception: {}", e.what() ); + Throw( DRM_ExternFail, "Curl write callback exception: {}", e.what() ); //LCOV_EXCL_LINE } return realsize; } diff --git a/source/csp.cpp b/source/csp.cpp index 62af3564..79c28a30 100644 --- a/source/csp.cpp +++ b/source/csp.cpp @@ -63,32 +63,27 @@ Aws::Aws():CspBase( "Aws", 100 ) {} Json::Value Aws::get_metadata() { Json::Value metadata = Json::nullValue; - std::string token, resp; + std::string token; uint32_t timeout_ms = mHTTPRequest.getConnectionTimeoutMS(); // Using IMDSv2 method // Get token CurlEasyPost tokenReq; - tokenReq.setURL( "http://169.254.169.254/latest/api/token" ); tokenReq.setConnectionTimeoutMS( timeout_ms ); tokenReq.setVerbosity( mVerbosity ); tokenReq.appendHeader( "X-aws-ec2-metadata-token-ttl-seconds: 21600" ); - tokenReq.perform_put( &token, "http://169.254.169.254/latest/api/token", timeout_ms ); - mHTTPRequest.appendHeader( fmt::format("X-aws-ec2-metadata-token: {}", token) ); + token = tokenReq.perform_put( "http://169.254.169.254/latest/api/token", timeout_ms ); // Collect Alibaba information + mHTTPRequest.appendHeader( fmt::format("X-aws-ec2-metadata-token: {}", token) ); std::string base_url("http://169.254.169.254/latest"); metadata["instance_id"] = mHTTPRequest.perform( fmt::format( "{}/meta-data/instance-id", base_url ), timeout_ms ); metadata["instance_type"] = mHTTPRequest.perform( fmt::format( "{}/meta-data/instance-type", base_url ), timeout_ms ); metadata["ami_id"] = mHTTPRequest.perform( fmt::format( "{}/meta-data/ami-id", base_url ), timeout_ms ); - std::string inst_doc = mHTTPRequest.perform( fmt::format( "{}/dynamic/instance-identity/document", base_url ), timeout_ms ); - std::cout << "inst_doc=" << inst_doc << std::endl; - std::string region; - metadata["region"] = "region"; - - std::cout << "metadata=" << metadata.toStyledString() << std::endl; - + std::string doc_string = mHTTPRequest.perform( fmt::format( "{}/dynamic/instance-identity/document", base_url ), timeout_ms ); + Json::Value doc_json = parseJsonString( doc_string ); + metadata["region"] = doc_json["region"]; return metadata; } @@ -108,7 +103,6 @@ Json::Value Alibaba::get_metadata() { metadata["instance_type"] = mHTTPRequest.perform( fmt::format( "{}/instance/instance-type", base_url ), timeout_ms ); metadata["ami_id"] = mHTTPRequest.perform( fmt::format( "{}/image-id", base_url ), timeout_ms ); metadata["region"] = mHTTPRequest.perform( fmt::format( "{}/region-id", base_url ), timeout_ms ); - std::cout << "metadata=" << metadata.toStyledString() << std::endl; return metadata; } diff --git a/source/drm_manager.cpp b/source/drm_manager.cpp index 9008afdd..7edcb4df 100644 --- a/source/drm_manager.cpp +++ b/source/drm_manager.cpp @@ -341,9 +341,6 @@ class DRM_LOCAL DrmManager::Impl { mBypassFrequencyDetection ).asBool(); } - // If possible extract host and card information - getHostAndCardInfo(); - } catch( const Exception &e ) { if ( e.getErrCode() != DRM_BadFormat ) throw; @@ -903,6 +900,10 @@ class DRM_LOCAL DrmManager::Impl { } else { mWsClient.reset( new DrmWSClient( mConfFilePath, mCredFilePath ) ); } + + // Collect host and card information when possible + getHostAndCardInfo(); + } // Get DRM HDK version diff --git a/source/utils.cpp b/source/utils.cpp index cc37ab8c..c855521a 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -164,7 +164,7 @@ Json::Value parseJsonString( const std::string &json_string ) { if ( json_node.empty() || json_node.isNull() ) Throw( DRM_BadArg, "JSON string is empty" ); - Debug( "Extracted JSON Object: {}", json_node.toStyledString() ); + Debug2( "Extracted JSON Object: {}", json_node.toStyledString() ); return json_node; } diff --git a/source/ws_client.cpp b/source/ws_client.cpp index 5fa73ca8..3543564d 100644 --- a/source/ws_client.cpp +++ b/source/ws_client.cpp @@ -34,6 +34,11 @@ CurlEasyPost::CurlEasyPost() { curl = curl_easy_init(); if ( !curl ) Throw( DRM_ExternFail, "Curl : cannot init curl_easy" ); + curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, &CurlEasyPost::write_callback ); + curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, mErrBuff.data() ); + curl_easy_setopt( curl, CURLOPT_FOLLOWLOCATION, 1L ); + curl_easy_setopt( curl, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt( curl, CURLOPT_TCP_KEEPALIVE, 1L); } CurlEasyPost::~CurlEasyPost() { @@ -49,6 +54,11 @@ void CurlEasyPost::setVerbosity( const uint32_t verbosity ) { curl_easy_setopt(curl, CURLOPT_VERBOSE, verbosity); } +void CurlEasyPost::setURL( std::string url ) { + mUrl = url; + curl_easy_setopt( curl, CURLOPT_URL, mUrl.c_str() ); +} + void CurlEasyPost::setHostResolves( const Json::Value& host_json ) { if ( host_json != Json::nullValue ) { if ( mHostResolveList != NULL ) { @@ -68,65 +78,68 @@ void CurlEasyPost::setHostResolves( const Json::Value& host_json ) { } } -long CurlEasyPost::perform( std::string* resp, std::chrono::milliseconds& timeout ) { +uint32_t CurlEasyPost::perform( std::string* response, int32_t timeout_ms ) { CURLcode res; - long resp_code; + uint32_t resp_code; + + if ( timeout_ms <= 0 ) + Throw( DRM_WSTimedOut, "Did not perform HTTP request to Accelize webservice because deadline is reached." ); + // Configure and execute CURL command if ( mHeaders_p ) { curl_easy_setopt( curl, CURLOPT_HTTPHEADER, mHeaders_p ); } - curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, &CurlEasyPost::write_callback ); - curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void*)resp ); - curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, mErrBuff.data() ); - curl_easy_setopt( curl, CURLOPT_FOLLOWLOCATION, 1L ); + curl_easy_setopt( curl, CURLOPT_WRITEDATA, response ); curl_easy_setopt( curl, CURLOPT_CONNECTTIMEOUT_MS, mConnectionTimeoutMS ); - // Compute timeout - if ( timeout <= std::chrono::milliseconds( 0 ) ) - Throw( DRM_WSTimedOut, "Did not perform HTTP request to Accelize webservice because deadline is reached." ); - curl_easy_setopt( curl, CURLOPT_TIMEOUT_MS, timeout.count() ); - + curl_easy_setopt( curl, CURLOPT_TIMEOUT_MS, timeout_ms ); res = curl_easy_perform( curl ); + + // Analyze libcurl response if ( res != CURLE_OK ) { + // A libcurl error occurred if ( res == CURLE_COULDNT_RESOLVE_PROXY || res == CURLE_COULDNT_RESOLVE_HOST || res == CURLE_COULDNT_CONNECT || res == CURLE_OPERATION_TIMEDOUT ) { - Throw( DRM_WSMayRetry, "Failed performing HTTP request to Accelize webservice ({}) : {}", + Throw( DRM_WSMayRetry, "libcurl failed to perform HTTP request to Accelize webservice ({}) : {}", curl_easy_strerror( res ), mErrBuff.data() ); } else { - Throw( DRM_ExternFail, "Failed performing HTTP request to Accelize webservice ({}) : {}", + Throw( DRM_ExternFail, "libcurl failed to perform HTTP request to Accelize webservice ({}) : {}", curl_easy_strerror( res ), mErrBuff.data() ); } } curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &resp_code ); + Debug( "Received code {} from {} in {} ms", resp_code, mUrl, getTotalTime() * 1000 ); return resp_code; } -long CurlEasyPost::perform( std::string* resp, std::chrono::steady_clock::time_point& deadline ) { - std::chrono::milliseconds timeout = std::chrono::duration_cast( deadline - std::chrono::steady_clock::now() ); - std::chrono::milliseconds limit( mConnectionTimeoutMS ); - if ( timeout >= limit ) - timeout = limit; - return perform( resp, timeout ); +uint32_t CurlEasyPost::perform( std::string* response, std::chrono::steady_clock::time_point& deadline ) { + std::chrono::milliseconds timeout_chrono = std::chrono::duration_cast( deadline - std::chrono::steady_clock::now() ); + int32_t timeout_ms = timeout_chrono.count(); + if ( timeout_ms >= (int32_t)mConnectionTimeoutMS ) + timeout_ms = mConnectionTimeoutMS; + return perform( response, timeout_ms ); } -long CurlEasyPost::perform_put( std::string* resp, std::string url, const uint32_t& timeout_ms ) { +std::string CurlEasyPost::perform_put( std::string url, const uint32_t& timeout_ms ) { + std::string response; + uint32_t resp_code; + + if ( timeout_ms <= 0 ) + Throw( DRM_WSTimedOut, "Did not perform HTTP request to Accelize webservice because deadline is reached." ); + + // Configure and execute CURL command curl_easy_setopt( curl, CURLOPT_URL, url.c_str() ); if ( mHeaders_p ) { curl_easy_setopt( curl, CURLOPT_HTTPHEADER, mHeaders_p ); } - curl_easy_setopt( curl, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PUT"); - curl_easy_setopt( curl, CURLOPT_TCP_KEEPALIVE, 1L); - curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, &CurlEasyPost::write_callback ); - curl_easy_setopt( curl, CURLOPT_WRITEDATA, resp ); - curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, mErrBuff.data() ); + curl_easy_setopt( curl, CURLOPT_WRITEDATA, &response ); curl_easy_setopt( curl, CURLOPT_CONNECTTIMEOUT_MS, mConnectionTimeoutMS ); - if ( timeout_ms <= 0 ) - Throw( DRM_WSTimedOut, "Did not perform HTTP request to Accelize webservice because deadline is reached." ); curl_easy_setopt( curl, CURLOPT_TIMEOUT_MS, timeout_ms ); - CURLcode res = curl_easy_perform( curl ); + + // Analyze HTTP answer if ( res != CURLE_OK ) { if ( res == CURLE_COULDNT_RESOLVE_PROXY || res == CURLE_COULDNT_RESOLVE_HOST @@ -139,9 +152,9 @@ long CurlEasyPost::perform_put( std::string* resp, std::string url, const uint32 curl_easy_strerror( res ), mErrBuff.data() ); } } - long resp_code; curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &resp_code ); - return resp_code; + Debug( "Received code {} from {} in {} ms", resp_code, url, getTotalTime() * 1000 ); + return response; } double CurlEasyPost::getTotalTime() { @@ -199,7 +212,7 @@ DrmWSClient::DrmWSClient( const std::string &conf_file_path, const std::string & } catch( Exception &e ) { Throw( e.getErrCode(), "Error with credential file '{}': {}", cred_file_path, e.what() ); } - // Restore originla file log level + // Restore original file log level if ( logFileLevel <= spdlog::level::debug ) logFileHandler->set_level( logFileLevel ); @@ -272,9 +285,6 @@ void DrmWSClient::requestOAuth2token( TClock::time_point deadline ) { std::string response; long resp_code = mOAUth2Request.perform( &response, deadline ); - Debug( "Received code {} from OAuth2 Web Service in {} ms", - resp_code, mOAUth2Request.getTotalTime() * 1000 ); - // Parse response std::string error_msg; Json::Value json_resp; @@ -285,17 +295,9 @@ void DrmWSClient::requestOAuth2token( TClock::time_point deadline ) { error_msg = e.what(); } // Analyze response - if ( resp_code != 200 ) { - // An error occurred - DRM_ErrorCode drm_error; - if ( CurlEasyPost::is_error_retryable( resp_code ) ) - drm_error = DRM_WSMayRetry; - else if ( ( resp_code >= 400 ) && ( resp_code < 500 ) ) - drm_error = DRM_WSReqError; - else - drm_error = DRM_WSError; + DRM_ErrorCode drm_error = CurlEasyPost::httpCode2DrmCode( resp_code ); + if ( drm_error != DRM_OK ) Throw( drm_error, "OAuth2 Web Service error {}: {}", resp_code, response ); - } // Verify response parsing if ( json_resp == Json::nullValue ) @@ -324,9 +326,6 @@ Json::Value DrmWSClient::requestMetering( const std::string url, const Json::Val std::string response; long resp_code = req.perform( &response, deadline ); - Debug( "Received code {} from Metering Web Service in {} ms", - resp_code, req.getTotalTime() * 1000 ); - // Parse response std::string error_msg; Json::Value json_resp; @@ -338,17 +337,13 @@ Json::Value DrmWSClient::requestMetering( const std::string url, const Json::Val } // Analyze response - if ( resp_code != 200 ) { - // An error occurred - DRM_ErrorCode drm_error; - if ( CurlEasyPost::is_error_retryable( resp_code ) || ( resp_code == 401 ) ) - drm_error = DRM_WSMayRetry; - else if ( ( resp_code >= 400 ) && ( resp_code < 500 ) ) - drm_error = DRM_WSReqError; - else - drm_error = DRM_WSError; + DRM_ErrorCode drm_error = CurlEasyPost::httpCode2DrmCode( resp_code ); + if ( resp_code == 401 ) + drm_error = DRM_WSMayRetry; + // An error occurred + if ( drm_error != DRM_OK ) Throw( drm_error, "Metering Web Service error {}: {}", resp_code, response ); - } + // Verify response parsing if ( json_resp == Json::nullValue ) Throw( DRM_WSRespError, "Failed to parse response from Metering Web Service because {}: {}",