Commit 8192fb46 authored by hclam@chromium.org's avatar hclam@chromium.org

Set AES key and IV mask to CastSender

Adding parameters to Cast Streaming Extensions API to configure
AES encryption key and IV mask to CastSender.

BUG=315931

Review URL: https://codereview.chromium.org/121543003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243540 0039d316-1c4b-4281-b951-d872f2087c98
parent 82854755
...@@ -21,7 +21,7 @@ namespace cast.streaming.rtpStream { ...@@ -21,7 +21,7 @@ namespace cast.streaming.rtpStream {
// Synchronization source identifier. // Synchronization source identifier.
long? ssrc; long? ssrc;
long? feedback_ssrc; long? feedbackSsrc;
long? clockRate; long? clockRate;
...@@ -38,6 +38,12 @@ namespace cast.streaming.rtpStream { ...@@ -38,6 +38,12 @@ namespace cast.streaming.rtpStream {
// Video height in pixels. // Video height in pixels.
long? height; long? height;
// 16 bytes AES key encoded in Base64.
DOMString? aesKey;
// 16 bytes AES IV (Initialization vector) mask encoded in Base64.
DOMString? aesIvMask;
// A list of codec specific params. // A list of codec specific params.
CodecSpecificParams[] codecSpecificParams; CodecSpecificParams[] codecSpecificParams;
}; };
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <functional> #include <functional>
#include "base/base64.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "chrome/common/extensions/api/cast_streaming_rtp_stream.h" #include "chrome/common/extensions/api/cast_streaming_rtp_stream.h"
...@@ -35,6 +36,8 @@ const char kRtpStreamNotFound[] = "The RTP stream cannot be found"; ...@@ -35,6 +36,8 @@ const char kRtpStreamNotFound[] = "The RTP stream cannot be found";
const char kUdpTransportNotFound[] = "The UDP transport cannot be found"; const char kUdpTransportNotFound[] = "The UDP transport cannot be found";
const char kInvalidUdpParams[] = "Invalid UDP params"; const char kInvalidUdpParams[] = "Invalid UDP params";
const char kInvalidRtpParams[] = "Invalid value for RTP params"; const char kInvalidRtpParams[] = "Invalid value for RTP params";
const char kInvalidAesKey[] = "Invalid value for AES key";
const char kInvalidAesIvMask[] = "Invalid value for AES IV mask";
const char kUnableToConvertArgs[] = "Unable to convert arguments"; const char kUnableToConvertArgs[] = "Unable to convert arguments";
const char kUnableToConvertParams[] = "Unable to convert params"; const char kUnableToConvertParams[] = "Unable to convert params";
...@@ -52,8 +55,9 @@ void FromCastCodecSpecificParams(const CastCodecSpecificParams& cast_params, ...@@ -52,8 +55,9 @@ void FromCastCodecSpecificParams(const CastCodecSpecificParams& cast_params,
ext_params->value = cast_params.value; ext_params->value = cast_params.value;
} }
void ToCastRtpPayloadParams(const RtpPayloadParams& ext_params, bool ToCastRtpPayloadParamsOrThrow(v8::Isolate* isolate,
CastRtpPayloadParams* cast_params) { const RtpPayloadParams& ext_params,
CastRtpPayloadParams* cast_params) {
cast_params->payload_type = ext_params.payload_type; cast_params->payload_type = ext_params.payload_type;
cast_params->codec_name = ext_params.codec_name; cast_params->codec_name = ext_params.codec_name;
cast_params->ssrc = ext_params.ssrc ? *ext_params.ssrc : 0; cast_params->ssrc = ext_params.ssrc ? *ext_params.ssrc : 0;
...@@ -67,12 +71,26 @@ void ToCastRtpPayloadParams(const RtpPayloadParams& ext_params, ...@@ -67,12 +71,26 @@ void ToCastRtpPayloadParams(const RtpPayloadParams& ext_params,
cast_params->channels = ext_params.channels ? *ext_params.channels : 0; cast_params->channels = ext_params.channels ? *ext_params.channels : 0;
cast_params->width = ext_params.width ? *ext_params.width : 0; cast_params->width = ext_params.width ? *ext_params.width : 0;
cast_params->height = ext_params.height ? *ext_params.height : 0; cast_params->height = ext_params.height ? *ext_params.height : 0;
if (ext_params.aes_key &&
!base::Base64Decode(*ext_params.aes_key, &cast_params->aes_key)) {
isolate->ThrowException(v8::Exception::Error(
v8::String::NewFromUtf8(isolate, kInvalidAesKey)));
return false;
}
if (ext_params.aes_iv_mask &&
!base::Base64Decode(*ext_params.aes_iv_mask,
&cast_params->aes_iv_mask)) {
isolate->ThrowException(v8::Exception::Error(
v8::String::NewFromUtf8(isolate, kInvalidAesIvMask)));
return false;
}
for (size_t i = 0; i < ext_params.codec_specific_params.size(); ++i) { for (size_t i = 0; i < ext_params.codec_specific_params.size(); ++i) {
CastCodecSpecificParams cast_codec_params; CastCodecSpecificParams cast_codec_params;
ToCastCodecSpecificParams(*ext_params.codec_specific_params[i], ToCastCodecSpecificParams(*ext_params.codec_specific_params[i],
&cast_codec_params); &cast_codec_params);
cast_params->codec_specific_params.push_back(cast_codec_params); cast_params->codec_specific_params.push_back(cast_codec_params);
} }
return true;
} }
void FromCastRtpPayloadParams(const CastRtpPayloadParams& cast_params, void FromCastRtpPayloadParams(const CastRtpPayloadParams& cast_params,
...@@ -114,14 +132,21 @@ void FromCastRtpCaps(const CastRtpCaps& cast_caps, RtpCaps* ext_caps) { ...@@ -114,14 +132,21 @@ void FromCastRtpCaps(const CastRtpCaps& cast_caps, RtpCaps* ext_caps) {
} }
} }
void ToCastRtpParams(const RtpParams& ext_params, CastRtpParams* cast_params) { bool ToCastRtpParamsOrThrow(v8::Isolate* isolate,
const RtpParams& ext_params,
CastRtpParams* cast_params) {
std::copy(ext_params.rtcp_features.begin(), ext_params.rtcp_features.end(), std::copy(ext_params.rtcp_features.begin(), ext_params.rtcp_features.end(),
cast_params->rtcp_features.begin()); cast_params->rtcp_features.begin());
for (size_t i = 0; i < ext_params.payloads.size(); ++i) { for (size_t i = 0; i < ext_params.payloads.size(); ++i) {
CastRtpPayloadParams cast_payload_params; CastRtpPayloadParams cast_payload_params;
ToCastRtpPayloadParams(*ext_params.payloads[i], &cast_payload_params); if (!ToCastRtpPayloadParamsOrThrow(isolate,
*ext_params.payloads[i],
&cast_payload_params)) {
return false;
}
cast_params->payloads.push_back(cast_payload_params); cast_params->payloads.push_back(cast_payload_params);
} }
return true;
} }
} // namespace } // namespace
...@@ -277,7 +302,9 @@ void CastStreamingNativeHandler::StartCastRtpStream( ...@@ -277,7 +302,9 @@ void CastStreamingNativeHandler::StartCastRtpStream(
} }
CastRtpCaps cast_params; CastRtpCaps cast_params;
ToCastRtpParams(*params, &cast_params); v8::Isolate* isolate = context()->v8_context()->GetIsolate();
if (!ToCastRtpParamsOrThrow(isolate, *params, &cast_params))
return;
transport->Start(cast_params); transport->Start(cast_params);
} }
......
...@@ -54,14 +54,14 @@ CastRtpPayloadParams DefaultVp8Payload() { ...@@ -54,14 +54,14 @@ CastRtpPayloadParams DefaultVp8Payload() {
CastRtpCaps DefaultAudioCaps() { CastRtpCaps DefaultAudioCaps() {
CastRtpCaps caps; CastRtpCaps caps;
caps.payloads.push_back(DefaultOpusPayload()); caps.payloads.push_back(DefaultOpusPayload());
// TODO(hclam): Fill in |rtcp_features| and |fec_mechanisms|. // TODO(hclam): Fill in |rtcp_features|.
return caps; return caps;
} }
CastRtpCaps DefaultVideoCaps() { CastRtpCaps DefaultVideoCaps() {
CastRtpCaps caps; CastRtpCaps caps;
caps.payloads.push_back(DefaultVp8Payload()); caps.payloads.push_back(DefaultVp8Payload());
// TODO(hclam): Fill in |rtcp_features| and |fec_mechanisms|. // TODO(hclam): Fill in |rtcp_features|.
return caps; return caps;
} }
...@@ -77,6 +77,8 @@ bool ToAudioSenderConfig(const CastRtpParams& params, ...@@ -77,6 +77,8 @@ bool ToAudioSenderConfig(const CastRtpParams& params,
config->frequency = payload_params.clock_rate; config->frequency = payload_params.clock_rate;
config->channels = payload_params.channels; config->channels = payload_params.channels;
config->bitrate = payload_params.max_bitrate; config->bitrate = payload_params.max_bitrate;
config->aes_key = payload_params.aes_key;
config->aes_iv_mask = payload_params.aes_iv_mask;
config->codec = media::cast::kPcm16; config->codec = media::cast::kPcm16;
if (payload_params.codec_name == kCodecNameOpus) if (payload_params.codec_name == kCodecNameOpus)
config->codec = media::cast::kOpus; config->codec = media::cast::kOpus;
...@@ -98,6 +100,8 @@ bool ToVideoSenderConfig(const CastRtpParams& params, ...@@ -98,6 +100,8 @@ bool ToVideoSenderConfig(const CastRtpParams& params,
config->height = payload_params.height; config->height = payload_params.height;
config->min_bitrate = config->start_bitrate = payload_params.min_bitrate; config->min_bitrate = config->start_bitrate = payload_params.min_bitrate;
config->max_bitrate = payload_params.max_bitrate; config->max_bitrate = payload_params.max_bitrate;
config->aes_key = payload_params.aes_key;
config->aes_iv_mask = payload_params.aes_iv_mask;
if (payload_params.codec_name == kCodecNameVp8) if (payload_params.codec_name == kCodecNameVp8)
config->codec = media::cast::kVp8; config->codec = media::cast::kVp8;
else else
......
...@@ -56,6 +56,12 @@ struct CastRtpPayloadParams { ...@@ -56,6 +56,12 @@ struct CastRtpPayloadParams {
// Name of the codec used. // Name of the codec used.
std::string codec_name; std::string codec_name;
// AES encryption key.
std::string aes_key;
// AES encryption IV mask.
std::string aes_iv_mask;
// List of codec specific parameters. // List of codec specific parameters.
std::vector<CastCodecSpecificParams> codec_specific_params; std::vector<CastCodecSpecificParams> codec_specific_params;
...@@ -71,9 +77,6 @@ struct CastRtpCaps { ...@@ -71,9 +77,6 @@ struct CastRtpCaps {
// Names of supported RTCP features. // Names of supported RTCP features.
std::vector<std::string> rtcp_features; std::vector<std::string> rtcp_features;
// Names of supported FEC (Forward Error Correction) mechanisms.
std::vector<std::string> fec_mechanisms;
CastRtpCaps(); CastRtpCaps();
~CastRtpCaps(); ~CastRtpCaps();
}; };
......
...@@ -6,22 +6,25 @@ var rtpStream = chrome.cast.streaming.rtpStream; ...@@ -6,22 +6,25 @@ var rtpStream = chrome.cast.streaming.rtpStream;
var tabCapture = chrome.tabCapture; var tabCapture = chrome.tabCapture;
var udpTransport = chrome.cast.streaming.udpTransport; var udpTransport = chrome.cast.streaming.udpTransport;
var createSession = chrome.cast.streaming.session.create; var createSession = chrome.cast.streaming.session.create;
var pass = chrome.test.callbackPass;
chrome.test.runTests([ chrome.test.runTests([
function rtpStreamStart() { function rtpStreamStart() {
tabCapture.capture({audio: true, video: true}, function(stream) { console.log("[TEST] rtpStreamStart");
tabCapture.capture({audio: true, video: true},
pass(function(stream) {
console.log("Got MediaStream."); console.log("Got MediaStream.");
chrome.test.assertTrue(!!stream); chrome.test.assertTrue(!!stream);
createSession(stream.getAudioTracks()[0], createSession(stream.getAudioTracks()[0],
stream.getVideoTracks()[0], stream.getVideoTracks()[0],
function(stream, audioId, videoId, udpId) { pass(function(stream, audioId, videoId, udpId) {
console.log("Starting."); console.log("Starting.");
var audioParams = rtpStream.getCaps(audioId); var audioParams = rtpStream.getCaps(audioId);
var videoParams = rtpStream.getCaps(videoId); var videoParams = rtpStream.getCaps(videoId);
rtpStream.start(audioId, audioParams); rtpStream.start(audioId, audioParams);
rtpStream.start(videoId, videoParams); rtpStream.start(videoId, videoParams);
udpTransport.start(udpId, {address: "127.0.0.1", port: 2344}); udpTransport.start(udpId, {address: "127.0.0.1", port: 2344});
window.setTimeout(function() { window.setTimeout(pass(function() {
console.log("Stopping."); console.log("Stopping.");
rtpStream.stop(audioId); rtpStream.stop(audioId);
rtpStream.stop(videoId); rtpStream.stop(videoId);
...@@ -32,8 +35,34 @@ chrome.test.runTests([ ...@@ -32,8 +35,34 @@ chrome.test.runTests([
chrome.test.assertEq(audioParams.payloads[0].codecName, "OPUS"); chrome.test.assertEq(audioParams.payloads[0].codecName, "OPUS");
chrome.test.assertEq(videoParams.payloads[0].codecName, "VP8"); chrome.test.assertEq(videoParams.payloads[0].codecName, "VP8");
chrome.test.succeed(); chrome.test.succeed();
}, 0); }), 0);
}.bind(null, stream)); }.bind(null, stream)));
}); }));
},
function invalidKey() {
console.log("[TEST] invalidKey");
tabCapture.capture({audio: true, video: true},
pass(function(stream) {
chrome.test.assertTrue(!!stream);
createSession(stream.getAudioTracks()[0],
stream.getVideoTracks()[0],
pass(function(stream, audioId, videoId, udpId) {
// AES key is invalid and exception is expected.
try {
var audioParams = rtpStream.getCaps(audioId);
var videoParams = rtpStream.getCaps(videoId);
audioParams.payloads[0].aesKey = "google";
videoParams.payloads[0].aesIvMask = "chrome";
rtpStream.start(audioId, audioParams);
rtpStream.start(videoId, videoParams);
} catch (e) {
rtpStream.destroy(audioId);
rtpStream.destroy(videoId);
udpTransport.destroy(udpId);
stream.stop();
chrome.test.succeed();
}
}.bind(null, stream)));
}));
}, },
]); ]);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment