diff --git a/common/certificate_type.h b/common/certificate_type.h new file mode 100644 index 0000000..b63a639 --- /dev/null +++ b/common/certificate_type.h @@ -0,0 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef COMMON_CERTIFICATE_TYPE_H_ +#define COMMON_CERTIFICATE_TYPE_H_ + +namespace widevine { + +enum CertificateType { + kCertificateTypeTesting, + kCertificateTypeDevelopment, + kCertificateTypeProduction, +}; + +} // namespace widevine + +#endif // COMMON_CERTIFICATE_TYPE_H_ diff --git a/libwvpl_cas_proxy.so b/libwvpl_cas_proxy.so new file mode 100755 index 0000000..c84febd Binary files /dev/null and b/libwvpl_cas_proxy.so differ diff --git a/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_environment.h b/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_environment.h new file mode 100644 index 0000000..6bafa56 --- /dev/null +++ b/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_environment.h @@ -0,0 +1,50 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2018 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef MEDIA_CAS_PROXY_SDK_EXTERNAL_COMMON_WVPL_WVPL_CAS_PROXY_ENVIRONMENT_H_ +#define MEDIA_CAS_PROXY_SDK_EXTERNAL_COMMON_WVPL_WVPL_CAS_PROXY_ENVIRONMENT_H_ + +#include +#include "sdk/external/common/wvpl/wvpl_sdk_environment.h" + +namespace widevine_server { +namespace wv_pl_sdk { + +class WvPLCASProxySession; + +class WvPLCASProxyEnvironment : public WvPLSDKEnvironment { + public: + /** + * Constructor. + * + * @param config_values + */ + explicit WvPLCASProxyEnvironment( + const std::map& config_values); + + /** + * Destructor. + */ + ~WvPLCASProxyEnvironment() override; + + /** + * Creates a session for the license request from the Widevine CDM. + * + * @param license_request_from_cdm + * @param session + * + * @return WvPLStatus enumeration + */ + virtual WvPLStatus CreateSession(const std::string& cas_license_request, + WvPLCASProxySession** cas_proxy_session); +}; + +} // namespace wv_pl_sdk +} // namespace widevine_server + +#endif // MEDIA_CAS_PROXY_SDK_EXTERNAL_COMMON_WVPL_WVPL_CAS_PROXY_ENVIRONMENT_H_ diff --git a/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_session.h b/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_session.h new file mode 100644 index 0000000..7a61e20 --- /dev/null +++ b/media_cas_proxy_sdk/external/common/wvpl/wvpl_cas_proxy_session.h @@ -0,0 +1,85 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2018 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef MEDIA_CAS_PROXY_SDK_EXTERNAL_COMMON_WVPL_WVPL_CAS_PROXY_SESSION_H_ +#define MEDIA_CAS_PROXY_SDK_EXTERNAL_COMMON_WVPL_WVPL_CAS_PROXY_SESSION_H_ + +#include +#include "sdk/external/common/wvpl/wvpl_sdk_session.h" + +namespace widevine_server { +namespace wv_pl_sdk { + +constexpr uint32_t kMajorVersion = 1; +constexpr uint32_t kMinorVersion = 0; +constexpr uint32_t kRelease = 1; + +/** + * Models a session for Widevine CAS Proxy functionality for + * communication with the Widevine License Service. The API allows a partner to + * inspect a license request and to generate a license request. + * + * Inherits the following "public" methods. + * - WvPLStatus AddKey(const WvPLKey& key); + * - const std::vector& key() const; + * - void set_policy(const WvPLPlaybackPolicy& policy); + * - const WvPLPlaybackPolicy& policy() const; + * - void set_session_init(const WvPLSessionInit& session_init); + * - const WvPLSessionInit& session_init(); + * - WvPLStatus GetPsshData(WvPLWidevinePsshData* wvpl_widevine_pssh_data) + * const; + * - WvPLStatus GetClientInfo(WvPLClientInfo* client_info) const; + * - WvPLStatus GetClientCapabilities(WvPLClientCapabilities* + * client_capabilities) const; + * - WvPLStatus GetDeviceInfo(WvPLDeviceInfo* device_info) const; + * - MessageType message_type() const; + * + * "Implements" the following "public" methods. + * - bool IsChromeCDM() const; + * - PlatformVerificationStatus VerifyPlatform(); + */ +class WvPLCASProxySession : public WvPLSDKSession { + public: + ~WvPLCASProxySession() override {} + + /** + * Returns a std::string containing the version in the form - + * .. + */ + static std::string GetVersionString(); + + /** + * Returns whether the CAS license request originated from Widevine Chrome + * CDM. Since MediaCAS is part of the Android framework, this method would + * return "false" for requests from AndroidTV. + */ + bool IsChromeCDM() const override; + + /** + * Returns the enum PlatformVerificationStatus for the CAS license request + * from the Widevine CDM. Since CAS license requests do not require client + * platform verification currently, this method would return + * PLATFORM_NO_VERIFICATION. + */ + PlatformVerificationStatus VerifyPlatform() override; + + private: + friend class WvPLCASProxyEnvironment; + friend class WvPLCASProxyEnvironmentTest; + friend class WvPLCASProxySessionTest; + + explicit WvPLCASProxySession(const std::string& cas_license_request_from_cdm) {} + + WvPLStatus ParsePsshData( + WvPLWidevinePsshData* wvpl_widevine_pssh_data) const override; +}; + +} // namespace wv_pl_sdk +} // namespace widevine_server + +#endif // MEDIA_CAS_PROXY_SDK_EXTERNAL_COMMON_WVPL_WVPL_CAS_PROXY_SESSION_H_ diff --git a/sdk/external/common/wvpl/wvpl_sdk_environment.h b/sdk/external/common/wvpl/wvpl_sdk_environment.h new file mode 100644 index 0000000..6a6d3ca --- /dev/null +++ b/sdk/external/common/wvpl/wvpl_sdk_environment.h @@ -0,0 +1,132 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SDK_EXTERNAL_COMMON_WVPL_WVPL_SDK_ENVIRONMENT_H_ +#define SDK_EXTERNAL_COMMON_WVPL_WVPL_SDK_ENVIRONMENT_H_ + +#include + +#include "common/certificate_type.h" +#include "sdk/external/common/wvpl/wvpl_types.h" +#include "protos/public/device_certificate_status.pb.h" +#include "protos/public/provisioned_device_info.pb.h" + +namespace widevine_server { +namespace wv_pl_sdk { + +// These fields show the configuration options that can be initialized via +// the implementation classes (WvPLEnvironment and WvPLProxyEnvironment). +const char kDeviceCertificateExpiration[] = "device_certificate_expiration"; +const char kAllowUnknownDevice[] = "allow_unknown_device"; +const char kProvider[] = "provider"; +const char kProviderIv[] = "provider_iv"; +const char kProviderKey[] = "provider_key"; +const char kApiVerInKcb[] = "api_ver_in_kcb"; +const char kLimitUsageStatsToErrorsOnly[] = "limit_usage_stats_to_errors_only"; +// Valid values are 'test' and 'prod'. +const char kDrmCertificateType[] = "drm_certificate_type"; + +/** + * Parent class of SDK environment. This class is not be instantiated directly, + * but its API can be accessed via the derived environment classes. + */ +class WvPLSDKEnvironment { + public: + virtual ~WvPLSDKEnvironment() {} + static void SetConfigValue(const std::map& config_values); + // Generates a license response containing a message generated in response to + // an error condition. |create_session_status| is a previous error status + // returned by the CreateSession(). |license_response| points to a std::string to + // contain the license response and may not be NULL. This method returns true + // if there is an error license to be sent to the client, or false + // otherwise. + static bool GenerateErrorResponse(const WvPLStatus& create_session_status, + std::string* license_response); + + /** + * Add a service certificate system-wide at the sdk. |service_certificate| + * is a Google-generated certificate used to authenticate the service + * provider. |service_private_key| is the encrypted PKCS#8 private RSA key + * corresponding to the service certificate. |service_private_key_passphrase| + * is the password required to decrypt |service_private_key|. This is a + * thread-safe call. + * + * @param service_certificate + * @param service_private_key + * @param service_private_key_passphrase + * + * @return WvPLStatus enumeration + */ + virtual WvPLStatus SetDrmServiceCertificate( + const std::string& service_certificate, const std::string& service_private_key, + const std::string& service_private_key_passphrase); + + // Returns the DRM Root Certificate type. This would be a setting passed into + // the environment, by a derived class constructor. + virtual std::string GetDrmCertificateType() { return drm_certificate_type_; } + + protected: + // Return the signature for the provider specified in the |config_values| + // parameter in the constructor. |signature| is owned by the caller. + static WvPLStatus GenerateSignature(const std::string& plain_text, + std::string* signature); + /** + * Insert or update provisionedDeviceInfoMap with device info in + * certificate_status_list. + */ + static WvPLStatus UpdateProvisionedDeviceInfoMap( + const widevine::DeviceCertificateStatusList& + certificate_status_list); + + // Number of seconds until the certificate status list expires after its + // creation time. Default value is 604800 seconds. + uint32_t device_certificate_expiration_seconds_ = 604800; + // "config_values" setting for "kDrmCertificateType". + // Supported values are "test" and "prod". Default value is "prod". + std::string drm_certificate_type_ = "prod"; + // name of the provider hosting this service. + std::string provider_; + // value of the "iv" specified for the provider. + std::string* provider_iv_; + // value of the "key" specified for the provider. + std::string* provider_key_; + static std::map* config_values_; + // is_service_certificate_loaded_ is not thread safe. + bool is_service_certificate_loaded_ = false; + // If true, allow devices not in the certificate status list. + bool allow_unknown_device_ = false; + // DRM Certificate type. + widevine::CertificateType certificate_type_ = + widevine::kCertificateTypeProduction; + + private: + /** + * Return provisioned_device_info if the device_info_map_ contains system_id. + * + * @return WvPLStatus - Status::OK if success, else error. + */ + static WvPLStatus LookupDeviceInfo( + uint32_t system_id, + widevine::ProvisionedDeviceInfo* provisioned_device_info); + + /** + * Add a device to the current environment/session. + */ + static void AddDeviceInfo( + const widevine::ProvisionedDeviceInfo& provisioned_device_info); + + static std::map* GetConfigValue(); + friend class WvPLSDKSession; + friend class WvPLProxySessionTest; + friend class WvPLSessionTest; +}; + +} // namespace wv_pl_sdk +} // namespace widevine_server + +#endif // SDK_EXTERNAL_COMMON_WVPL_WVPL_SDK_ENVIRONMENT_H_ diff --git a/sdk/external/common/wvpl/wvpl_sdk_session.h b/sdk/external/common/wvpl/wvpl_sdk_session.h new file mode 100644 index 0000000..971a64e --- /dev/null +++ b/sdk/external/common/wvpl/wvpl_sdk_session.h @@ -0,0 +1,198 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2018 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SDK_EXTERNAL_COMMON_WVPL_WVPL_SDK_SESSION_H_ +#define SDK_EXTERNAL_COMMON_WVPL_WVPL_SDK_SESSION_H_ + +#include "sdk/external/common/wvpl/wvpl_types.h" +#include "protos/public/client_identification.pb.h" +#include "protos/public/device_certificate_status.pb.h" +#include "protos/public/license_protocol.pb.h" +#include "protos/public/license_server_sdk.pb.h" +#include "protos/public/provisioned_device_info.pb.h" + +namespace widevine { +class SessionInit; +} +namespace widevine_server { +namespace wv_pl_sdk { + +class WvPLSDKSession { + public: + virtual ~WvPLSDKSession() = 0; + + public: + // Add WvPLKey. + virtual WvPLStatus AddKey(const WvPLKey& key); + + // Get the WvPLKey. + virtual const std::vector& key() const { return keys_; } + + // Set the license policy. + virtual void set_policy(const WvPLPlaybackPolicy& policy) { + policy_ = policy; + } + + // Get the license policy. + virtual const WvPLPlaybackPolicy& policy() const { return policy_; } + + // Set the Session Init. + virtual void set_session_init(const WvPLSessionInit& session_init) { + session_init_ = session_init; + } + + // Get the Session Init. + virtual const WvPLSessionInit& session_init() const { return session_init_; } + + virtual bool IsChromeCDM() const; + + /** + * Returns the Widevine PSSH data for the license request handled by this + * session. + * + * @param wvpl_widevine_pssh_data. + * @return WvPLStatus - Status::OK if success, else error. + */ + virtual WvPLStatus GetPsshData( + WvPLWidevinePsshData* wvpl_widevine_pssh_data) const; + + /** + * Returns the ClientIdentification information for the license request + * handled by this session. + * + * @param client_info + * @return WvPLStatus - Status::OK if success, else error. + */ + virtual WvPLStatus GetClientInfo(WvPLClientInfo* client_info) const; + /** + * Returns the WvPL Client Capabilities information for the license request + * handled by this session. + * + * @param client_capabilities. + * @return WvPLStatus - Status::OK if success, else error. + */ + virtual WvPLStatus GetClientCapabilities( + WvPLClientCapabilities* client_capabilities) const; + + /** + * Returns the WvPLDeviceInfo information for the license request + * handled by this session. + * + * @param device_info + * @return WvPLStatus - Status::OK if success, else error. + */ + virtual WvPLStatus GetDeviceInfo(WvPLDeviceInfo* device_info) const; + + /** + * Returns the type of the message handled by this session. + * + * @return MessageType enumeration. + */ + virtual MessageType message_type() const; + + virtual PlatformVerificationStatus VerifyPlatform() = 0; + + virtual widevine::LicenseRequest::RequestType request_type() const { + return request_type_; + } + + protected: + uint32_t system_id_ = 0xFFFFFFFF; + std::string user_agent_; + std::vector keys_; + WvPLPlaybackPolicy policy_; + WvPLSessionInit session_init_; + WvPLWidevinePsshData pssh_data_; + widevine::ClientIdentification client_id_; + bool has_pssh_data_ = false; + bool has_system_id_ = false; + bool has_client_id_ = false; + MessageType message_type_ = UNKNOWN; + PlatformVerificationStatus platform_verification_status_ = + PLATFORM_NO_VERIFICATION; + std::unique_ptr + signed_message_request_from_cdm_; + std::string license_request_from_cdm_; + std::string remote_attestation_cert_serial_number_; + std::unique_ptr sdk_license_request_; + widevine::LicenseRequest::RequestType request_type_; + virtual WvPLStatus VerifyRemoteAttestation(); + + // Returns the WvPL Client Capabilities information for the license request + // handled by this session. + WvPLStatus GetWvPLClientCapabilities( + const widevine::ClientIdentification& client_id, + WvPLClientCapabilities* client_capabilities) const; + + // Copies/translates the output protection from a WvPL Key into an SDK + // key container. + void CopyOutputProtection( + const WvPLKey& wvpl_key, + widevine::License_KeyContainer* sdk_key_container); + virtual void CopySecurityLevel( + const WvPLOutputProtection& output_protection, TrackType track_type, + widevine::License::KeyContainer* key_container); + + // Copies/translates the policy from a WvPL policy into an SDK policy. A + // helper function for GenerateLicenseRequestAsJSON. + virtual void CopyPlaybackPolicy(const WvPLPlaybackPolicy& wvpl_policy, + widevine::License::Policy* sdk_policy); + + // Copy the |cgms_value| into the key container. A helper function for + // GenerateLicenseRequestAsJSON. + virtual void CopyCGMS(CGMS cgms_value, + widevine::License::KeyContainer::OutputProtection* + output_protection); + + // Copy the |hdcp_value| into the key container. + virtual void CopyHDCP(HDCP hdcp_value, + widevine::License::KeyContainer::OutputProtection* + output_protection); + + // Copy the |hdcp_value| into the client_capabilities. + virtual void CopyHDCPToClientCapabilities( + widevine::ClientIdentification::ClientCapabilities::HdcpVersion + hdcp_value, + WvPLClientCapabilities* client_capabilities) const; + + // Copy the |analog_output_capabilities| into the client_capabilities. + virtual void CopyAnalogOutputCapabilities( + widevine::ClientIdentification::ClientCapabilities:: + AnalogOutputCapabilities analog_output_capabilities, + WvPLClientCapabilities* client_capabilities) const; + + // Copy the WvPLSession Init into Session Init. + virtual void CopySessionInit(const WvPLSessionInit& wvpl_session_init, + widevine::SessionInit* session_init); + + // Copy the WvPLDeviceInfo into ProvisionedDeviceInfo. + virtual void CopyProvisionedDeviceInfo( + const WvPLDeviceInfo& wvpl_device_info, + widevine::ProvisionedDeviceInfo* device_info); + + // Populate deviceInfo, clientIdentification and psshdata for license request. + WvPLStatus ParseLicenseRequest(); + + // Copy the WvPLSessionState to SessionState. + void CopySessionState(const WvPLSessionState& wvpl_session_state, + widevine::SessionState* session_state); + + private: + /** + * Parses WvPLWidevinePsshData in the new license request. + * + * @return WvPLStatus - Status::OK if success, else error. + */ + virtual WvPLStatus ParsePsshData( + WvPLWidevinePsshData* wvpl_widevine_pssh_data) const = 0; +}; + +} // namespace wv_pl_sdk +} // namespace widevine_server + +#endif // SDK_EXTERNAL_COMMON_WVPL_WVPL_SDK_SESSION_H_ diff --git a/sdk/external/common/wvpl/wvpl_types.h b/sdk/external/common/wvpl/wvpl_types.h new file mode 100644 index 0000000..9fe5236 --- /dev/null +++ b/sdk/external/common/wvpl/wvpl_types.h @@ -0,0 +1,931 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SDK_EXTERNAL_COMMON_WVPL_WVPL_TYPES_H_ +#define SDK_EXTERNAL_COMMON_WVPL_WVPL_TYPES_H_ + +#include +#include +#include +#include +#include + +#include "util/status.h" + +// TODO(user) Split wvpl_types.h into wvpl_common_types.h , +// wvpl_license_sdk_types.h, wvpl_proxy_sdk_types.h and +// wvpl_packager_sdk_types.h. + +namespace widevine_server { +namespace wv_pl_sdk { +typedef widevine::util::Status WvPLStatus; +typedef uint32_t uint32_t; +typedef int64_t int64_t; + +/** + * Represents the key type for the keys that are used when generating a license. + * The generated license includes a key container, which in turn, contains the + * key material, metadata and policy needed to use the key. + */ +enum KeyType { + UNKNOWN_KEY = 0, + // Key used to decrypt media content. + CONTENT = 1, + // Key used for wrapping content keys. + ENTITLEMENT = 2 +}; + +enum LicenseType { + STREAMING = 1, + OFFLINE = 2, +}; + +/** + * Represents the type of message. This struct is used by Proxy SDK. + */ +enum MessageType { + UNKNOWN = 0, + LICENSE_REQUEST = 1, + SERVICE_CERTIFICATE_REQUEST = 4 +}; + +enum CertificateKeyType { + RSA_2048 = 0, + RSA_3072 = 1, +}; + +enum PlatformVerificationStatus { + PLATFORM_UNVERIFIED = 0, + PLATFORM_TAMPERED = 1, + PLATFORM_SOFTWARE_VERIFIED = 2, + PLATFORM_HARDWARE_VERIFIED = 3, + PLATFORM_NO_VERIFICATION = 4, + PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED = 5 +}; + +// LINT.IfChange +enum HDCP { + HDCP_NONE = 0, + HDCP_V1 = 1, + HDCP_V2 = 2, + HDCP_V2_1 = 3, + HDCP_V2_2 = 4, + HDCP_V2_3 = 5, + HDCP_NO_DIGITAL_OUTPUT = 0xff +}; + +enum SecurityLevel { + SECURITY_LEVEL_UNDEFINED = 0, + SW_SECURE_CRYPTO = 1, + SW_SECURE_DECODE = 2, + HW_SECURE_CRYPTO = 3, + HW_SECURE_DECODE = 4, + HW_SECURE_ALL = 5 +}; + +enum DeviceSecurityLevel { + DEVICE_LEVEL_UNSPECIFIED = 0, + DEVICE_LEVEL_1 = 1, + DEVICE_LEVEL_2 = 2, + DEVICE_LEVEL_3 = 3 +}; + +enum CGMS { + CGMS_NONE = 42, + COPY_FREE = 0, + COPY_ONCE = 2, + COPY_NEVER = 3, +}; + +enum TrackType { + TRACK_TYPE_UNSPECIFIED = 0, + AUDIO = 1, + VIDEO_SD = 2, + VIDEO_HD = 3, + VIDEO_UHD1 = 4, + VIDEO_UHD2 = 5, +}; + +enum AnalogOutputCapabilities { + ANALOG_OUTPUT_UNKNOWN = 0, + ANALOG_OUTPUT_NONE = 1, + ANALOG_OUTPUT_SUPPORTED = 2, + ANALOG_OUTPUT_SUPPORTS_CGMS_A = 3, +}; + +struct WvPLPlaybackPolicy { + WvPLPlaybackPolicy() { + license_duration_seconds_ = 0; + playback_duration_seconds_ = 0; + renewal_interval_seconds_ = 0; + renewal_recovery_duration_seconds_ = 0; + renewal_retry_interval_seconds_ = 0; + can_play_ = true; + can_renew_ = false; + can_persist_ = false; + } + + void set_license_duration_seconds(uint32_t duration) { + license_duration_seconds_ = duration; + } + uint32_t license_duration_seconds() const { return license_duration_seconds_; } + void set_playback_duration_seconds(uint32_t duration) { + playback_duration_seconds_ = duration; + } + uint32_t playback_duration_seconds() const { + return playback_duration_seconds_; + } + void set_renewal_interval_seconds(uint32_t duration) { + renewal_interval_seconds_ = duration; + } + uint32_t renewal_interval_seconds() const { return renewal_interval_seconds_; } + void set_renewal_recovery_duration_seconds(int64_t dur) { + renewal_recovery_duration_seconds_ = dur; + } + int64_t renewal_recovery_duration_seconds() const { + return renewal_recovery_duration_seconds_; + } + void set_renewal_retry_interval_seconds(int64_t retry_interval) { + renewal_retry_interval_seconds_ = retry_interval; + } + int64_t renewal_retry_interval_seconds() const { + return renewal_retry_interval_seconds_; + } + void set_renew_with_usage(bool usage_flag) { renew_with_usage_ = usage_flag; } + bool renew_with_usage() const { return renew_with_usage_; } + void set_renewal_url(const std::string& url) { renewal_url_ = url; } + const std::string& renewal_url() const { return renewal_url_; } + void set_can_play(bool play_flag) { can_play_ = play_flag; } + bool can_play() const { return can_play_; } + void set_can_persist(bool persist_flag) { can_persist_ = persist_flag; } + bool can_persist() const { return can_persist_; } + void set_can_renew(bool renew_flag) { can_renew_ = renew_flag; } + bool can_renew() const { return can_renew_; } + + // The license window. Once a license is granted, the number of seconds to use + // this license. Default is 0, indicating unlimited license. + uint32_t license_duration_seconds_; + + // The playback window. Once initial playback starts, the number of seconds + // to use the license. Default is 0, indicating unlimited but not to exceed + // the license_duration_window. + uint32_t playback_duration_seconds_; + + // How many seconds after license_start_time, before renewal is first + // attempted. + uint32_t renewal_interval_seconds_; + + // The window of time, in which playback is allowed to continue while + // renewal is attempted, yet unsuccessful due to backend problems with + // the license server. + int64_t renewal_recovery_duration_seconds_; + + // Specifies the delay in seconds between subsequent license + // renewal requests, in case of failure. + int64_t renewal_retry_interval_seconds_; + + // Indicates that the license shall be sent for renewal when usage is + // started. + bool renew_with_usage_; + + // Renewal requests are sent to this URL. + std::string renewal_url_; + + // Indicates that playback of ths content is allowed. + bool can_play_; + + // Indicates that the license may be persisted to non-volatile storage for + // offline use. + bool can_persist_; + + // Indicates that renewal of this license is allowed. + bool can_renew_; +}; + +/** + * LicenseIdentification is propagated from LicenseRequest to License, + * incrementing version with each iteration. + * */ +struct LicenseIdentification { + LicenseIdentification() { + version_ = 0; + type_ = STREAMING; + } + + // |request_id| must be specified in bytes. + void set_request_id(const std::string& request_id) { + request_id_ = request_id; + } + + const std::string& request_id() { return request_id_; } + + // |session_id| must be specified in bytes. + void set_session_id(const std::string& session_id) { + session_id_ = session_id; + } + + const std::string& session_id() { return session_id_; } + + // |purchase_id| must be specified in bytes. + void set_purchase_id(const std::string& purchase_id) { + purchase_id_ = purchase_id; + } + + const std::string& purchase_id() { return purchase_id_; } + + void set_type(LicenseType type) { type_ = type; } + + LicenseType type() { return type_; } + + uint32_t version() { return version_; } + + void set_version(uint32_t version) { version_ = version; } + + // |provider_session_token| must be specified in bytes. + void set_provider_session_token(const std::string& provider_session_token) { + provider_session_token_ = provider_session_token; + } + + const std::string& provider_session_token() { + return provider_session_token_; + } + + // License request id. + std::string request_id_; // NOLINT + // Session identifier for license request. + std::string session_id_; // NOLINT + // Session token for the session. This token is for use by the license + // provider, and is akin to a session cookie. It will be copied to + // LicenseIdentfication::provider_session_token, and sent back in all + std::string provider_session_token_; // NOLINT + // Purchase identifier. + std::string purchase_id_; // NOLINT + // Type of the license, default value is Streaming. + LicenseType type_; // NOLINT + // Version of license request. + uint32_t version_; // NOLINT +}; + +/** + * This message is used by the server to preserve and restore session state. + * */ +struct WvPLSessionState { + WvPLSessionState() { + keybox_system_id_ = 0; + license_counter_ = 0; + } + + void set_license_id(const LicenseIdentification& license_id) { + license_id_ = license_id; + } + + const LicenseIdentification& license_id() const { return license_id_; } + + LicenseIdentification* mutable_license_id() { return &license_id_; } + + const std::string& signing_key() const { return signing_key_; } + + // |signing_key| must be specified in bytes. + void set_signing_key(const std::string& signing_key) { + signing_key_ = signing_key; + } + + uint32_t keybox_system_id() const { return keybox_system_id_; } + + void set_keybox_system_id(uint32_t keybox_system_id) { + keybox_system_id_ = keybox_system_id; + } + + uint32_t license_counter() const { return license_counter_; } + + void set_license_counter(uint32_t license_counter) { + license_counter_ = license_counter; + } + + const std::string& provider_client_token() const { + return provider_client_token_; + } + + // |provider_client_token| must be specified in bytes. + void set_provider_client_token(const std::string& provider_client_token) { + provider_client_token_ = provider_client_token; + } + + // License information propagated from license request to the license. + LicenseIdentification license_id_; // NOLINT + // Provider client token sent back in the license. + std::string provider_client_token_; // NOLINT + // Signing_key should be 512 bits in length to be split into two + // (server || client) HMAC-SHA256 keys. + std::string signing_key_; // NOLINT + // System_id in keybox. + uint32_t keybox_system_id_; // NOLINT + // License counter associated with the |provider_client_token|. + uint32_t license_counter_; // NOLINT +}; + +struct WvPLVideoResolutionConstraint { + WvPLVideoResolutionConstraint() { + min_resolution_pixels_ = 0; + max_resolution_pixels_ = 0; + hdcp_ = HDCP_NONE; + } + + void set_min_resolution_pixels(uint32_t pixels) { + min_resolution_pixels_ = pixels; + } + + void set_max_resolution_pixels(uint32_t pixels) { + max_resolution_pixels_ = pixels; + } + + void set_hdcp(HDCP hdcp_value) { hdcp_ = hdcp_value; } + + HDCP hdcp() const { return hdcp_; } + + uint32_t min_resolution_pixels() const { return min_resolution_pixels_; } + + uint32_t max_resolution_pixels() const { return max_resolution_pixels_; } + + // Minimum and maximum video resolutions in the range (height x width). + uint32_t min_resolution_pixels_; + uint32_t max_resolution_pixels_; + // Optional output protection requirements for this range. If not + // specified, the output protection in WvPLKey applies. + HDCP hdcp_; +}; + +struct WvPLOutputProtection { + WvPLOutputProtection() { + hdcp_ = HDCP_NONE; + secure_data_path_ = false; + security_level_ = SECURITY_LEVEL_UNDEFINED; + disable_analog_output_ = false; + disable_digital_output_ = false; + cgms_ = CGMS_NONE; + } + + void set_hdcp(HDCP hdcp_value) { hdcp_ = hdcp_value; } + + HDCP hdcp() const { return hdcp_; } + + // Setting true indicates security_level is HW_SECURE_ALL, otherwise the + // default is false which maps to security_level of SW_SECURE_CRYPTO. This + // value is ignored if security_level is set directly. + void set_secure_data_path(bool secure_flag) { + secure_data_path_ = secure_flag; + } + + bool secure_data_path() const { return secure_data_path_; } + + // Setting security_level directly takes precedence over setting the + // |secure_data_path|. For most applications, there is no need to set the + // security_level directly. Using |secure_data_path| is sufficient. + void set_security_level(SecurityLevel level) { security_level_ = level; } + + SecurityLevel security_level() const { return security_level_; } + + // Set to true to disable analog output. + void set_disable_analog_output(bool flag) { disable_analog_output_ = flag; } + + bool disable_analog_output() const { return disable_analog_output_; } + + // Set to true to disable digital output. + void set_disable_digital_output(bool flag) { disable_digital_output_ = flag; } + + bool disable_digital_output() const { return disable_digital_output_; } + + // CGMS-A setting + void set_cgms(CGMS cgms_value) { cgms_ = cgms_value; } + + CGMS cgms() const { return cgms_; } + + // Indicates whether HDCP is required on digital outputs. Default is None. + HDCP hdcp_; + + // Crypto operations and handling of the media must be performed within a + // hardware backed trusted environment. Default is false. + bool secure_data_path_; + + // Security level robustness defined by Widevine. Default is UNDEFINED in + // which case secure_data_path_ is used. If secure_data_path_ is false, + // security_level_ is set to SW_SECURE_CRYPTO. If secure_data_path_ is + // true, security_level_ is set to HW_SECURE_ALL; + SecurityLevel security_level_; + + // Set to disable analog output. + bool disable_analog_output_; + + // Set to disable digital output. + bool disable_digital_output_; + + // CGMS-A analog output. + CGMS cgms_; +}; + +struct WvPLKey { + WvPLKey() {} + + // |key_id| must be specified in bytes. + void set_key_id(const std::string& key_id) { key_id_ = key_id; } + + const std::string& key_id() const { return key_id_; } + + // |key_bytes| must be specified in bytes. + void set_key_bytes(const std::string& key_bytes) { key_bytes_ = key_bytes; } + + const std::string& key_bytes() const { return key_bytes_; } + + void set_output_protection(const WvPLOutputProtection& out_prot) { + output_protection_ = out_prot; + } + + void set_requested_output_protection(const WvPLOutputProtection& out_prot) { + requested_output_protection_ = out_prot; + } + + const WvPLOutputProtection& output_protection() const { + return output_protection_; + } + + const WvPLOutputProtection& requested_output_protection() const { + return requested_output_protection_; + } + + WvPLOutputProtection* mutable_output_protection() { + return &output_protection_; + } + + WvPLOutputProtection* mutable_requested_output_protection() { + return &requested_output_protection_; + } + + const std::vector + video_resolution_constraints() const { + return video_resolution_constraints_; + } + + void AddVideoResolutionConstraint( + const WvPLVideoResolutionConstraint& constraint) { + video_resolution_constraints_.push_back(constraint); + } + + void set_track_type(const TrackType track_type) { track_type_ = track_type; } + + TrackType track_type() const { return track_type_; } + + void set_key_type(const KeyType key_type) { key_type_ = key_type; } + + KeyType key_type() const { return key_type_; } + + std::string key_id_; + std::string key_bytes_; + WvPLOutputProtection output_protection_; + WvPLOutputProtection requested_output_protection_; + // If the video resolution of the content being decrypted/decoded falls + // within one of the specified ranges, the optional output protections may + // be applied. + std::vector video_resolution_constraints_; + TrackType track_type_ = TRACK_TYPE_UNSPECIFIED; + KeyType key_type_ = CONTENT; +}; + +struct WvPLDeviceInfo { + WvPLDeviceInfo() { + security_level_ = DEVICE_LEVEL_UNSPECIFIED; + system_id_ = 0; + test_device_ = false; + } + void set_system_id(uint32_t system_id) { system_id_ = system_id; } + uint32_t system_id() const { return system_id_; } + void set_soc(const std::string& soc) { soc_ = soc; } + const std::string& soc() const { return soc_; } + + void set_manufacturer(const std::string& manufacturer) { + manufacturer_ = manufacturer; + } + const std::string& manufacturer() const { return manufacturer_; } + + void set_model(const std::string& model) { model_ = model; } + const std::string& model() const { return model_; } + + void set_device_type(const std::string& device_type) { + device_type_ = device_type; + } + const std::string& device_type() const { return device_type_; } + + void set_security_level(DeviceSecurityLevel level) { + security_level_ = level; + } + DeviceSecurityLevel security_level() const { return security_level_; } + + void set_test_device(bool test_device) { test_device_ = test_device; } + bool test_device() const { return test_device_; } + + void set_serial_number(const std::string& serial_number) { + serial_number_ = serial_number; + } + const std::string& serial_number() const { return serial_number_; } + + void set_service_id(const std::string& service_id) { + service_id_ = service_id; + } + const std::string& service_id() const { return service_id_; } + + // Widevine system ID for this device family. + uint32_t system_id_; + // Name of system-on-a-chip. + std::string soc_; + // Name of manufacturer. + std::string manufacturer_; + // Manufacturer's model name. + std::string model_; + // Type of device (Phone, Tablet, TV, etc). + std::string device_type_; + // Widevine-defined security level. + DeviceSecurityLevel security_level_; + // True if the certificate corresponds to a test (non production) device. + bool test_device_; + // 128-bit globally unique serial number of certificate. + std::string serial_number_; + // Service identifier (web origin) for the provider which owns the + // certificate. + std::string service_id_; +}; + +// This message is used to hold usage data for each Widevine system Id. +struct WvPLLicenseStatusCounterData { + // Initialize members + WvPLLicenseStatusCounterData() : license_status_(0), status_count_(0) {} + uint32_t license_status_; + // Count of occurences of the above status; + uint32_t status_count_; +}; + +// This message is used to hold usage data for each device model. +struct WvPLDeviceModelCounterData { + std::string device_model_; + // Key is each status we returned associated with the above model; + std::map status_map_; +}; + +// This message is used to hold usage data for each device make. +struct WvPLDeviceMakeCounterData { + std::string device_make_; + // Key is each model associated with this device make. + std::map model_map_; +}; + +// This message is used to hold usage data for each Widevine system Id. +struct WvPLSystemIdCounterData { + // Initialize members + WvPLSystemIdCounterData() : system_id_(0) {} + uint32_t system_id_; + // Key is each make we handled associated with the above system Id. + std::map make_map_; +}; + +// This top level message contains aggregated usage data for license requests. +struct WvPLCounterData { + // Initialize members + WvPLCounterData() : start_time_utc_(0), end_time_utc_(0) {} + // Time of the first license in this structure, represented as seconds since + // Unix epoch. + time_t start_time_utc_; + // Time of the last license in this structure, represented as seconds since + // Unix epoch. + time_t end_time_utc_; + // Key is each system Id we handled. + std::map system_id_map_; +}; + +struct WvPLSessionInit { + WvPLSessionInit() + : license_start_time_(0), override_provider_client_token_(false) {} + // Accessors + void set_session_id(const std::string& session_id) { + session_id_ = session_id; + } + std::string session_id() const { return session_id_; } + + void set_purchase_id(const std::string& purchase_id) { + purchase_id_ = purchase_id; + } + std::string purchase_id() const { return purchase_id_; } + + void set_master_signing_key(const std::string& master_signing_key) { + master_signing_key_ = master_signing_key; + } + std::string master_signing_key() const { return master_signing_key_; } + + void set_license_start_time(const int64_t license_start_time) { + license_start_time_ = license_start_time; + } + int64_t license_start_time() const { return license_start_time_; } + + void set_provider_client_token(const std::string& provider_client_token) { + provider_client_token_ = provider_client_token; + } + std::string provider_client_token() const { return provider_client_token_; } + + void set_provider_session_token(const std::string& provider_session_token) { + provider_session_token_ = provider_session_token; + } + std::string provider_session_token() const { return provider_session_token_; } + + void set_override_provider_client_token(bool override_provider_client_token) { + override_provider_client_token_ = override_provider_client_token; + } + bool override_provider_client_token() const { + return override_provider_client_token_; + } + + // Identifier for the session. + std::string session_id_; + // Identifier for the purchased content. + std::string purchase_id_; + // Master signing key should be 128 bits in length. + std::string master_signing_key_; + // signing_key should be 512 bits in length to be split into two + // (server || client) HMAC-SHA256 keys. + std::string signing_key_; + // The reference time in UTC as calculated by the client clock. + int64_t license_start_time_; + // Client token for the session. + std::string provider_client_token_; + // Session token for the session. + std::string provider_session_token_; + // If false and the license request contains a |provider_client_token_|, + // use the token from that request even if |provider_client_token_| is + // specified. + // If true and the license request contains a |provider_client_token_|, + // use |provider_client_token_|. + bool override_provider_client_token_; +}; + +struct WvPLClientCapabilities { + WvPLClientCapabilities() {} + + // Accessors + void set_client_token(bool client_token) { client_token_ = client_token; } + + bool client_token() const { return client_token_; } + + void set_session_token(bool session_token) { session_token_ = session_token; } + + bool session_token() const { return session_token_; } + + void set_video_resolution_constraints(bool video_resolution_constraints) { + video_resolution_constraints_ = video_resolution_constraints; + } + + bool video_resolution_constraints() const { + return video_resolution_constraints_; + } + + void set_max_hdcp_version(HDCP max_hdcp_version) { + max_hdcp_version_ = max_hdcp_version; + } + + HDCP max_hdcp_version() const { return max_hdcp_version_; } + + void set_oem_crypto_api_version(uint32_t oem_crypto_api_version) { + oem_crypto_api_version_ = oem_crypto_api_version; + } + + uint32_t oem_crypto_api_version() const { return oem_crypto_api_version_; } + + void set_anti_rollback_usage_table(bool anti_rollback_usage_table) { + anti_rollback_usage_table_ = anti_rollback_usage_table; + } + + bool anti_rollback_usage_table() const { return anti_rollback_usage_table_; } + + void set_srm_version(uint32_t srm_version) { srm_version_ = srm_version; } + + uint32_t srm_version() const { return srm_version_; } + + void set_can_update_srm(bool can_update_srm) { + can_update_srm_ = can_update_srm; + } + + bool can_update_srm() const { return can_update_srm_; } + + void add_supported_certificate_key_type(const CertificateKeyType key_type) { + supported_certificate_key_type_.push_back(key_type); + } + const std::list supported_certificate_key_type() const { + return supported_certificate_key_type_; + } + + void set_analog_output_capabilities( + const AnalogOutputCapabilities analog_output_capabilities) { + analog_output_capabilities_ = analog_output_capabilities; + } + + const AnalogOutputCapabilities analog_output_capabilities() const { + return analog_output_capabilities_; + } + + void set_can_disable_analog_output(bool can_disable_analog_output) { + can_disable_analog_output_ = can_disable_analog_output; + } + + bool can_disable_analog_output() const { return can_disable_analog_output_; } + + // Member variables + // Client token generated by the content provider. + bool client_token_ = false; + // A token associated with the client session. + bool session_token_ = false; + // Video resolution constraints. If the video resolution of the + // content being decrypted/decoded falls within one of the specified ranges, + // the required_protections may be applied. Otherwise an error will be + // reported. + // NOTE: Use of this feature is not recommended, as it is only supported on + // a small number of platforms. + bool video_resolution_constraints_ = false; + // The max "High-bandwidth Digital Content Protection" (HDCP) version + // supported by the client. + HDCP max_hdcp_version_ = HDCP_NONE; + // The OEM Crypto API version supported by the client. + uint32_t oem_crypto_api_version_; + // Flag to indicate the key must only be used if the client + // supports anti rollback of the user table. Content provider can query the + // client capabilities to determine if the client support this feature. + bool anti_rollback_usage_table_ = false; + // The client shall report |srm_version| if available. + uint32_t srm_version_; + // A device may have SRM data, and report a version, but may not be capable + // of updating SRM data. + bool can_update_srm_ = false; + // A list of CertificateKeyTypes. + std::list supported_certificate_key_type_; + // Analog capabilities of the device. + AnalogOutputCapabilities analog_output_capabilities_ = ANALOG_OUTPUT_UNKNOWN; + // Indicates if the device can disable it's analog output. + bool can_disable_analog_output_ = false; +}; + +/** + * Represents the Client Identification information. In the License Proxy + * SDK, this structure is populated as a result of parsing the license + * request from the CDM. This struct is used by Proxy SDK. + */ +struct WvPLClientInfo { + WvPLClientInfo() + : max_hdcp_version_(HDCP_NONE), + oem_crypto_api_version_(0), + analog_output_capabilities_(ANALOG_OUTPUT_UNKNOWN), + can_disable_analog_output_(false) {} + + // Accessors + void set_max_hdcp_version(HDCP max_hdcp_version) { + max_hdcp_version_ = max_hdcp_version; + } + HDCP max_hdcp_version() const { return max_hdcp_version_; } + + void set_oem_crypto_api_version(uint32_t oem_crypto_api_version) { + oem_crypto_api_version_ = oem_crypto_api_version; + } + uint32_t oem_crypto_api_version() const { return oem_crypto_api_version_; } + + void set_provider_client_token(const std::string& provider_client_token) { + provider_client_token_ = provider_client_token; + } + const std::string& provider_client_token() const { + return provider_client_token_; + } + + void set_cdm_version(const std::string& cdm_version) { + cdm_version_ = cdm_version; + } + const std::string& cdm_version() const { return cdm_version_; } + + void set_name_value(const std::string& name, const std::string& value) { + names_values_.insert(std::make_pair(name, value)); + } + const std::map& names_values() { + return names_values_; + } + void set_analog_output_capabilities(AnalogOutputCapabilities capability) { + analog_output_capabilities_ = capability; + } + const AnalogOutputCapabilities analog_output_capabilities() const { + return analog_output_capabilities_; + } + void set_can_disable_analog_output(bool can_disable) { + can_disable_analog_output_ = can_disable; + } + bool can_disable_analog_output() const { return can_disable_analog_output_; } + + const WvPLClientCapabilities client_capabilities() const { + return client_capabilities_; + } + + void set_client_capabilities( + const WvPLClientCapabilities& client_capabilities) { + client_capabilities_ = client_capabilities; + } + + // Member variables + // The max "High-bandwidth Digital Content Protection" (HDCP) version + // supported by the device. + HDCP max_hdcp_version_; + // The OEM Crypto API version supported by the client. + uint32_t oem_crypto_api_version_; + // The client CDM version. + std::string cdm_version_; + // The client token generated by the content provider. + std::string provider_client_token_; + // Map of other fields specified as name-value pairs representing the + // client. + std::map names_values_; + // Analog capabilities of the device. + AnalogOutputCapabilities analog_output_capabilities_; + // Indicates if the device can disable it's analog output. + bool can_disable_analog_output_; + // Capabilities which not all clients may support. Used for the license + // exchange protocol only. + WvPLClientCapabilities client_capabilities_; +}; + +struct WvPLEntitledKey { + WvPLEntitledKey() {} + // Accessors. + void set_entitlement_key_id(const std::string& entitlement_key_id) { + entitlement_key_id_ = entitlement_key_id; + } + const std::string& entitlement_key_id() const { return entitlement_key_id_; } + + void set_key_id(const std::string& key_id) { key_id_ = key_id; } + const std::string& key_id() const { return key_id_; } + + void set_key_bytes(const std::string& key_bytes) { key_bytes_ = key_bytes; } + const std::string& key_bytes() const { return key_bytes_; } + + void set_entitlement_key_iv(const std::string& entitlement_key_iv) { + entitlement_key_iv_ = entitlement_key_iv; + } + const std::string& entitlement_key_iv() const { return entitlement_key_iv_; } + + void set_entitlement_key_size_bytes(uint32_t entitlement_key_size_bytes) { + entitlement_key_size_bytes_ = entitlement_key_size_bytes; + } + uint32_t entitlement_key_size_bytes() const { + return entitlement_key_size_bytes_; + } + + // Member variables. + // ID of entitlement key used for wrapping |key|. + std::string entitlement_key_id_; + // ID of the entitled key. + std::string key_id_; + // Wrapped key. + std::string key_bytes_; + // IV used for wrapping |key|. + std::string entitlement_key_iv_; + // Size of entitlement key used for wrapping |key|. + uint32_t entitlement_key_size_bytes_ = 32; +}; + +/* + * Defines the 'pssh' box for Common Encryption (CENC). + */ +struct WvPLWidevinePsshData { + WvPLWidevinePsshData() {} + + // Accessors + void set_content_id(const std::string& content_id) { + content_id_ = content_id; + } + const std::string content_id() const { return content_id_; } + + void set_key_id(const std::string& key_id) { key_ids_.push_back(key_id); } + const std::list& key_ids() const { return key_ids_; } + + void add_entitled_key(const WvPLEntitledKey& entitled_key) { + entitled_keys_.push_back(entitled_key); + } + const std::list& entitled_keys() const { + return entitled_keys_; + } + + // Member variables + // A list of key identifiers, for entitlement keys or content keys. + std::list key_ids_; + // The content identifier. + std::string content_id_; + // A list of wrapped keys. + std::list entitled_keys_; +}; + +} // namespace wv_pl_sdk +} // namespace widevine_server + +#endif // SDK_EXTERNAL_COMMON_WVPL_WVPL_TYPES_H_ diff --git a/util/error_space.h b/util/error_space.h new file mode 100644 index 0000000..68c093a --- /dev/null +++ b/util/error_space.h @@ -0,0 +1,83 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef UTIL_ERROR_SPACE_H_ +#define UTIL_ERROR_SPACE_H_ + +#include + +namespace widevine { +namespace util { + +class ErrorSpace { + public: + std::string SpaceName() const { return space_name_func_(this); } + std::string String(int code) const { return code_to_string_func_(this, code); } + + protected: + // typedef instead of using statements for SWIG compatibility. + typedef std::string (*SpaceNameFunc)(const ErrorSpace* space); + typedef std::string (*CodeToStringFunc)(const ErrorSpace* space, int code); + constexpr ErrorSpace(SpaceNameFunc space_name_func, + CodeToStringFunc code_to_string_func) + : space_name_func_(space_name_func), + code_to_string_func_(code_to_string_func) {} + + private: + const SpaceNameFunc space_name_func_; + const CodeToStringFunc code_to_string_func_; +}; + +// Manages creation of error space subclasses. +template +class ErrorSpaceImpl : public ErrorSpace { + public: + constexpr ErrorSpaceImpl() + : ErrorSpace(&ErrorSpaceImpl::SpaceNameImpl, + &ErrorSpaceImpl::CodeToStringImpl) {} + + // Returns the canonical instance of the `T` error space. + static constexpr const T* Get(); + + private: + // These functions adapt the stateful implementation that takes a space + // pointer to stateless static methods, so that clients of ErrorSpaceImpl are + // safe to have constexpr global instances. + static std::string SpaceNameImpl(const ErrorSpace* /*space*/) { + return T::SpaceName(); + } + + static std::string CodeToStringImpl(const ErrorSpace* /*space*/, int code) { + return T::CodeToString(code); + } +}; + +namespace internal { + +// Provides a global constexpr instance of the error space `T`. +// We need the indirection because ErrorSpaceImpl can't declare constexpr +// instances of T since it is not yet fully declared. +template +struct ErrorSpaceInstance { + static constexpr T value = {}; +}; + +template +constexpr T ErrorSpaceInstance::value; + +} // namespace internal + +template +constexpr const T* ErrorSpaceImpl::Get() { + return &internal::ErrorSpaceInstance::value; +} + +} // namespace util +} // namespace widevine + +#endif // UTIL_ERROR_SPACE_H_ diff --git a/util/status.h b/util/status.h new file mode 100644 index 0000000..5e3b15b --- /dev/null +++ b/util/status.h @@ -0,0 +1,119 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 Google LLC. +// +// This software is licensed under the terms defined in the Widevine Master +// License Agreement. For a copy of this agreement, please contact +// widevine-licensing@google.com. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef UTIL_STATUS_H_ +#define UTIL_STATUS_H_ + +#include + +#include "util/error_space.h" + +namespace widevine { +namespace util { +namespace error { + +enum StatusCode { + // Success. + OK = 0, + + // Client specified an invalid argument. + INVALID_ARGUMENT = 3, + + // Some requested entity (e.g., file or directory) was not found. + NOT_FOUND = 5, + + // Some entity that we attempted to create (e.g., file or directory) + // already exists. + ALREADY_EXISTS = 6, + + // The caller does not have permission to execute the specified + // operation. PERMISSION_DENIED must not be used for rejections + // caused by exhausting some resource (use RESOURCE_EXHAUSTED + // instead for those errors). + PERMISSION_DENIED = 7, + + // Operation is not implemented or not supported/enabled in this service. + UNIMPLEMENTED = 12, + + // Internal errors. Means some invariants expected by underlying + // system has been broken. If you see one of these errors, + // something is very broken. + INTERNAL = 13, + + // Operation is not implemented or not supported/enabled in this service. + UNAVAILABLE = 14, + + // Number of generic (non license related) errors. + NUM_ERRORS, +}; + +} // namespace error + +class GenericErrorSpace : public ErrorSpaceImpl { + public: + static std::string SpaceName(); + static std::string CodeToString(int code); +}; + +class Status { + public: + Status() : status_code_(error::OK) {} + ~Status() {} + explicit Status(error::StatusCode c) : status_code_(c) {} + Status(error::StatusCode c, const std::string& error_message) + : status_code_(c), error_message_(error_message) {} + Status(const ErrorSpace* e, error::StatusCode c, + const std::string& error_message) { + SetError(e, c, error_message); + } + Status(const ErrorSpace* e, int error, const std::string& error_message) { + SetError(e, error, error_message); + } + void SetError(const ErrorSpace* e, int c, const std::string& error_message) { + error_space_ = e; + status_code_ = c; + error_message_ = error_message; + } + + bool ok() const { return status_code_ == error::OK; } + const ErrorSpace* error_space() const { return error_space_; } + static const ErrorSpace* canonical_space() { + return GenericErrorSpace::Get(); + } + std::string ToString() const; + std::string error_message() const { return error_message_; } + int error_code() const { return status_code_; } + + private: + const ErrorSpace* error_space_ = GenericErrorSpace::Get(); + int status_code_; + std::string error_message_; +}; // class Status + +inline Status OkStatus() { return Status(); } + +// Here error_message_ is ignored during comparison. +inline bool operator==(const Status& s1, const Status& s2) { + return s1.error_space() == s2.error_space() && + s1.error_code() == s2.error_code(); +} +inline bool operator!=(const Status& s1, const Status& s2) { + return s1.error_space() != s2.error_space() || + s1.error_code() != s2.error_code(); +} + +// Prints a human-readable representation of 'x' to 'os'. +std::ostream& operator<<(std::ostream& os, const Status& x); + +#define CHECK_OK(expression) CHECK_EQ(util::error::OK, expression.error_code()) + + +} // namespace util +} // namespace widevine + +#endif // UTIL_STATUS_H_