1) Change return type to WvCasStatus for functions in wv_cas_types.cc.

2) Add a binary wv_cas_types_example.
3) Surface wv_cas_key_fetcher *source code* to partner to serve as an example of how they would make a HTTP request to acquire an entitlement key from license server.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=229953562
This commit is contained in:
Fang Yu
2019-01-18 10:38:34 -08:00
parent 6e1f377329
commit e7173c82cd
25 changed files with 1213 additions and 173 deletions

View File

@@ -22,6 +22,8 @@ filegroup(
name = "binary_release_files",
srcs = glob(["*.h"]) + [
":wv_ecmg",
"wv_cas_key_fetcher.cc",
"wv_cas_types.cc",
],
)
@@ -127,7 +129,9 @@ cc_library(
"@abseil_repo//absl/base:core_headers",
"@abseil_repo//absl/strings",
"@curl_repo//:curl",
"//util:error_space",
"//common:signature_util",
"//common:status",
"//media_cas_packager_sdk/internal:key_fetcher",
"//protos/public:media_cas_encryption_proto",
],
@@ -181,3 +185,12 @@ cc_binary(
"//media_cas_packager_sdk/internal:ecmg_client_handler",
],
)
cc_binary(
name = "wv_emmg",
srcs = ["wv_emmg.cc"],
deps = [
"//base",
"//media_cas_packager_sdk/internal:emmg",
],
)

View File

@@ -103,8 +103,6 @@ Status WvCasKeyFetcher::RequestEntitlementKey(const std::string& request_string,
}
// Processes signed response.
// TODO(b/114741232): Seems we are getting CasEncryptionResponse back instead
// of SignedCasEncryptionResponse.
LOG(INFO) << "Json CasEncryptionResponse: " << http_response.response();
CasEncryptionResponse response;
if (!JsonStringToMessage(http_response.response(), &response).ok()) {

View File

@@ -79,8 +79,8 @@ bool StringToCryptoMode(const std::string& str, CryptoMode* mode) {
return false;
}
Status CreateWvCasEncryptionRequestJson(const WvCasEncryptionRequest& request,
std::string* request_json) {
WvCasStatus CreateWvCasEncryptionRequestJson(
const WvCasEncryptionRequest& request, std::string* request_json) {
CHECK(request_json);
CasEncryptionRequest request_proto;
@@ -100,23 +100,23 @@ Status CreateWvCasEncryptionRequestJson(const WvCasEncryptionRequest& request,
// NOTE: MessageToJsonString will automatically converts 'bytes' type fields
// to base64. For example content ID '21140844' becomes 'MjExNDA4NDQ='.
if (!MessageToJsonString(request_proto, request_json, print_options).ok()) {
return Status(error::INTERNAL,
"Failed to convert request message to json.");
LOG(ERROR) << "Failed to convert request message to json.";
return INTERNAL;
}
return OkStatus();
return OK;
}
Status ParseWvCasEncryptionResponseJson(const std::string& response_json,
WvCasEncryptionResponse* response) {
WvCasStatus ParseWvCasEncryptionResponseJson(
const std::string& response_json, WvCasEncryptionResponse* response) {
CHECK(response);
CasEncryptionResponse response_proto;
// NOTE: JsonStringToMessage will automatically perform base64 decode for
// 'bytes' type fields.
if (!JsonStringToMessage(response_json, &response_proto).ok()) {
return Status(error::INTERNAL,
"Failed to convert response json to message.");
LOG(ERROR) << "Failed to convert response json to message.";
return INTERNAL;
}
response->status =
@@ -133,7 +133,7 @@ Status ParseWvCasEncryptionResponseJson(const std::string& response_json,
response->entitlement_keys.push_back(key_info);
}
return OkStatus();
return OK;
}
} // namespace cas

View File

@@ -114,15 +114,15 @@ struct WvCasEncryptionResponse {
// request JSON message.
// And that signed JSON message can be sent to Widevine license server for
// aquiring entitlement keys.
Status CreateWvCasEncryptionRequestJson(const WvCasEncryptionRequest& request,
std::string* request_json);
WvCasStatus CreateWvCasEncryptionRequestJson(
const WvCasEncryptionRequest& request, std::string* request_json);
// Parses a WvCasEncryptionResponse in JSON format, returns a
// WvCasEncryptionResponse.
// |response_json| is supposed to be the 'response' field in the signed
// response from Widevine license server.
Status ParseWvCasEncryptionResponseJson(const std::string& response_json,
WvCasEncryptionResponse* response);
WvCasStatus ParseWvCasEncryptionResponseJson(const std::string& response_json,
WvCasEncryptionResponse* response);
} // namespace cas
} // namespace widevine

View File

@@ -56,7 +56,8 @@ TEST(WvCasTypesTest, CreateWvCasEncryptionRequestJson) {
request.key_rotation = true;
std::string actual_request_json;
EXPECT_OK(CreateWvCasEncryptionRequestJson(request, &actual_request_json));
EXPECT_EQ(OK,
CreateWvCasEncryptionRequestJson(request, &actual_request_json));
// Content_id has been base64 encoded.
std::string expected_request_json =
@@ -76,7 +77,8 @@ TEST(WvCasTypesTest, ParseWvCasEncryptionResponseJson) {
"\"key_slot\":\"ODD\"}]}";
WvCasEncryptionResponse actual_response;
EXPECT_OK(ParseWvCasEncryptionResponseJson(response_json, &actual_response));
EXPECT_EQ(OK,
ParseWvCasEncryptionResponseJson(response_json, &actual_response));
EXPECT_EQ(WvCasEncryptionResponse::Status::OK, actual_response.status);
// 21140844 is base64 decode of "MjExNDA4NDQ=".

View File

@@ -6,15 +6,17 @@
// widevine-licensing@google.com.
////////////////////////////////////////////////////////////////////////////////
// Example server that listens on a port for Simulcrypt API messages.
// Widevine MediaCAS ECMG server.
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include "gflags/gflags.h"
#include "glog/logging.h"

View File

@@ -0,0 +1,92 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright 2019 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.
////////////////////////////////////////////////////////////////////////////////
// Widevine MediaCAS EMMG server.
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "media_cas_packager_sdk/internal/emmg.h"
DEFINE_string(mux_address, "", "Mux server address");
DEFINE_int32(mux_port, 0, "Mux server port number");
// EMMG specfic configs.
DEFINE_int32(client_id, 0, "EMMG client_id");
DEFINE_int32(section_tspkt_flag, 1, "EMMG section_tspkt_flag");
DEFINE_int32(data_channel_id, 0, "EMMG data_channel_id");
DEFINE_int32(data_stream_id, 0, "EMMG data_stream_id");
DEFINE_int32(data_id, 0, "EMMG data_id");
// data_type: type of data carried in the datagram in the stream:
// 0x00: EMM;
// 0x01: private data;
// 0x02: DVB reserved (ECM);
// other values: DVB reserved.
DEFINE_int32(data_type, 0, "EMMG data_type");
#define BUFFER_SIZE (1024)
void BuildEmmgConfig(widevine::cas::EmmgConfig *config) {
CHECK(config);
config->client_id = FLAGS_client_id;
config->section_tspkt_flag = FLAGS_section_tspkt_flag;
config->data_channel_id = FLAGS_data_channel_id;
config->data_stream_id = FLAGS_data_stream_id;
config->data_id = FLAGS_data_id;
config->data_type = FLAGS_data_type;
}
int main(int argc, char **argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
CHECK(!FLAGS_mux_address.empty()) << "flag --mux_address is required";
CHECK(FLAGS_mux_port != 0) << "flag --mux_port is required";
// Create server address.
struct hostent ret;
struct hostent *server;
char buffer[BUFFER_SIZE];
int h_errnop = 0;
int return_val = gethostbyname_r(FLAGS_mux_address.c_str(), &ret, buffer,
sizeof(buffer), &server, &h_errnop);
if (return_val != 0 || server == nullptr) {
LOG(FATAL) << "gethostbyname_r failed for " << FLAGS_mux_address;
}
struct sockaddr_in server_address;
bzero(reinterpret_cast<char *>(&server_address), sizeof(server_address));
server_address.sin_family = AF_INET;
bcopy(server->h_addr,
reinterpret_cast<char *>(&server_address.sin_addr.s_addr),
server->h_length);
server_address.sin_port = htons(FLAGS_mux_port);
// Connect to server.
int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket_fd < 0) {
LOG(FATAL) << "Failed to create socket.";
}
if (connect(server_socket_fd,
reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address)) < 0) {
LOG(FATAL) << "Failed to connect to server.";
}
// Send EMMG messages.
widevine::cas::EmmgConfig emmg_config;
BuildEmmgConfig(&emmg_config);
widevine::cas::Emmg emmg(&emmg_config, server_socket_fd);
emmg.Start();
close(server_socket_fd);
return 0;
}