Import Cobalt 10.55341
diff --git a/src/base/time.cc b/src/base/time.cc
index 6d20667..fad5508 100644
--- a/src/base/time.cc
+++ b/src/base/time.cc
@@ -15,6 +15,7 @@
#include "base/third_party/nspr/prtime.h"
#include "base/logging.h"
+#include "starboard/double.h"
namespace base {
@@ -137,7 +138,7 @@
// static
Time Time::FromDoubleT(double dt) {
- if (dt == 0 || isnan(dt))
+ if (dt == 0 || SbDoubleIsNan(dt))
return Time(); // Preserve 0 so we can tell it doesn't exist.
if (dt == std::numeric_limits<double>::max())
return Max();
diff --git a/src/cobalt/accessibility/starboard_tts_engine.cc b/src/cobalt/accessibility/starboard_tts_engine.cc
index d2788fc..6fb7a10 100644
--- a/src/cobalt/accessibility/starboard_tts_engine.cc
+++ b/src/cobalt/accessibility/starboard_tts_engine.cc
@@ -21,12 +21,12 @@
namespace cobalt {
namespace accessibility {
-void StarboardTTSEngine::SpeakNow(const std::string& text) OVERRIDE {
+void StarboardTTSEngine::SpeakNow(const std::string& text) {
SbSpeechSynthesisCancel();
Speak(text);
}
-void StarboardTTSEngine::Speak(const std::string& text) OVERRIDE {
+void StarboardTTSEngine::Speak(const std::string& text) {
SbSpeechSynthesisSpeak(text.c_str());
}
diff --git a/src/cobalt/base/tokens.h b/src/cobalt/base/tokens.h
index c70a97e..7ca128e 100644
--- a/src/cobalt/base/tokens.h
+++ b/src/cobalt/base/tokens.h
@@ -21,82 +21,90 @@
namespace base {
// clang-format off
-#define TOKENS_FOR_EACH_WITH_NAME_ONLY(MacroOpWithNameOnly) \
- MacroOpWithNameOnly(addsourcebuffer) \
- MacroOpWithNameOnly(addtrack) \
- MacroOpWithNameOnly(abort) \
- MacroOpWithNameOnly(additions) \
- MacroOpWithNameOnly(all) \
- MacroOpWithNameOnly(alt) \
- MacroOpWithNameOnly(animationend) \
- MacroOpWithNameOnly(assertive) \
- MacroOpWithNameOnly(attributes) \
- MacroOpWithNameOnly(blur) \
- MacroOpWithNameOnly(boundary) \
- MacroOpWithNameOnly(canplay) \
- MacroOpWithNameOnly(canplaythrough) \
- MacroOpWithNameOnly(change) \
- MacroOpWithNameOnly(characterData) \
- MacroOpWithNameOnly(childList) \
- MacroOpWithNameOnly(close) \
- MacroOpWithNameOnly(durationchange) \
- MacroOpWithNameOnly(emptied) \
- MacroOpWithNameOnly(end) \
- MacroOpWithNameOnly(ended) \
- MacroOpWithNameOnly(error) \
- MacroOpWithNameOnly(focus) \
- MacroOpWithNameOnly(hashchange) \
- MacroOpWithNameOnly(keyadded) \
- MacroOpWithNameOnly(keydown) \
- MacroOpWithNameOnly(keyerror) \
- MacroOpWithNameOnly(keymessage) \
- MacroOpWithNameOnly(keypress) \
- MacroOpWithNameOnly(keyup) \
- MacroOpWithNameOnly(load) \
- MacroOpWithNameOnly(loadeddata) \
- MacroOpWithNameOnly(loadedmetadata) \
- MacroOpWithNameOnly(loadend) \
- MacroOpWithNameOnly(loadstart) \
- MacroOpWithNameOnly(mark) \
- MacroOpWithNameOnly(message) \
- MacroOpWithNameOnly(needkey) \
- MacroOpWithNameOnly(nomatch) \
- MacroOpWithNameOnly(off) \
- MacroOpWithNameOnly(open) \
- MacroOpWithNameOnly(pause) \
- MacroOpWithNameOnly(play) \
- MacroOpWithNameOnly(playing) \
- MacroOpWithNameOnly(polite) \
- MacroOpWithNameOnly(progress) \
- MacroOpWithNameOnly(ratechange) \
- MacroOpWithNameOnly(readystatechange) \
- MacroOpWithNameOnly(removals) \
- MacroOpWithNameOnly(removesourcebuffer) \
- MacroOpWithNameOnly(removetrack) \
- MacroOpWithNameOnly(result) \
- MacroOpWithNameOnly(resume) \
- MacroOpWithNameOnly(securitypolicyviolation) \
- MacroOpWithNameOnly(seeked) \
- MacroOpWithNameOnly(seeking) \
- MacroOpWithNameOnly(soundend) \
- MacroOpWithNameOnly(soundstart) \
- MacroOpWithNameOnly(sourceclose) \
- MacroOpWithNameOnly(sourceended) \
- MacroOpWithNameOnly(sourceopen) \
- MacroOpWithNameOnly(start) \
- MacroOpWithNameOnly(storage) \
- MacroOpWithNameOnly(stalled) \
- MacroOpWithNameOnly(suspend) \
- MacroOpWithNameOnly(text) \
- MacroOpWithNameOnly(timeout) \
- MacroOpWithNameOnly(timeupdate) \
- MacroOpWithNameOnly(transitionend) \
- MacroOpWithNameOnly(unload) \
- MacroOpWithNameOnly(update) \
- MacroOpWithNameOnly(updateend) \
- MacroOpWithNameOnly(updatestart) \
- MacroOpWithNameOnly(voiceschanged) \
- MacroOpWithNameOnly(volumechange) \
+#if defined(COBALT_MEDIA_SOURCE_2016)
+#define TOKENS_FOR_EACH_WITH_NAME_ONLY_EME(MacroOpWithNameOnly) \
+ MacroOpWithNameOnly(encrypted)
+#else // defined(COBALT_MEDIA_SOURCE_2016)
+#define TOKENS_FOR_EACH_WITH_NAME_ONLY_EME(MacroOpWithNameOnly) \
+ MacroOpWithNameOnly(keyadded) \
+ MacroOpWithNameOnly(keyerror) \
+ MacroOpWithNameOnly(keymessage) \
+ MacroOpWithNameOnly(needkey)
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
+
+#define TOKENS_FOR_EACH_WITH_NAME_ONLY(MacroOpWithNameOnly) \
+ TOKENS_FOR_EACH_WITH_NAME_ONLY_EME(MacroOpWithNameOnly) \
+ MacroOpWithNameOnly(addsourcebuffer) \
+ MacroOpWithNameOnly(addtrack) \
+ MacroOpWithNameOnly(abort) \
+ MacroOpWithNameOnly(additions) \
+ MacroOpWithNameOnly(all) \
+ MacroOpWithNameOnly(alt) \
+ MacroOpWithNameOnly(animationend) \
+ MacroOpWithNameOnly(assertive) \
+ MacroOpWithNameOnly(attributes) \
+ MacroOpWithNameOnly(blur) \
+ MacroOpWithNameOnly(boundary) \
+ MacroOpWithNameOnly(canplay) \
+ MacroOpWithNameOnly(canplaythrough) \
+ MacroOpWithNameOnly(change) \
+ MacroOpWithNameOnly(characterData) \
+ MacroOpWithNameOnly(childList) \
+ MacroOpWithNameOnly(close) \
+ MacroOpWithNameOnly(durationchange) \
+ MacroOpWithNameOnly(emptied) \
+ MacroOpWithNameOnly(end) \
+ MacroOpWithNameOnly(ended) \
+ MacroOpWithNameOnly(error) \
+ MacroOpWithNameOnly(focus) \
+ MacroOpWithNameOnly(hashchange) \
+ MacroOpWithNameOnly(keydown) \
+ MacroOpWithNameOnly(keypress) \
+ MacroOpWithNameOnly(keyup) \
+ MacroOpWithNameOnly(load) \
+ MacroOpWithNameOnly(loadeddata) \
+ MacroOpWithNameOnly(loadedmetadata) \
+ MacroOpWithNameOnly(loadend) \
+ MacroOpWithNameOnly(loadstart) \
+ MacroOpWithNameOnly(mark) \
+ MacroOpWithNameOnly(message) \
+ MacroOpWithNameOnly(nomatch) \
+ MacroOpWithNameOnly(off) \
+ MacroOpWithNameOnly(open) \
+ MacroOpWithNameOnly(pause) \
+ MacroOpWithNameOnly(play) \
+ MacroOpWithNameOnly(playing) \
+ MacroOpWithNameOnly(polite) \
+ MacroOpWithNameOnly(progress) \
+ MacroOpWithNameOnly(ratechange) \
+ MacroOpWithNameOnly(readystatechange) \
+ MacroOpWithNameOnly(removals) \
+ MacroOpWithNameOnly(removesourcebuffer) \
+ MacroOpWithNameOnly(removetrack) \
+ MacroOpWithNameOnly(result) \
+ MacroOpWithNameOnly(resume) \
+ MacroOpWithNameOnly(securitypolicyviolation) \
+ MacroOpWithNameOnly(seeked) \
+ MacroOpWithNameOnly(seeking) \
+ MacroOpWithNameOnly(soundend) \
+ MacroOpWithNameOnly(soundstart) \
+ MacroOpWithNameOnly(sourceclose) \
+ MacroOpWithNameOnly(sourceended) \
+ MacroOpWithNameOnly(sourceopen) \
+ MacroOpWithNameOnly(start) \
+ MacroOpWithNameOnly(storage) \
+ MacroOpWithNameOnly(stalled) \
+ MacroOpWithNameOnly(suspend) \
+ MacroOpWithNameOnly(text) \
+ MacroOpWithNameOnly(timeout) \
+ MacroOpWithNameOnly(timeupdate) \
+ MacroOpWithNameOnly(transitionend) \
+ MacroOpWithNameOnly(unload) \
+ MacroOpWithNameOnly(update) \
+ MacroOpWithNameOnly(updateend) \
+ MacroOpWithNameOnly(updatestart) \
+ MacroOpWithNameOnly(voiceschanged) \
+ MacroOpWithNameOnly(volumechange) \
MacroOpWithNameOnly(waiting)
#define TOKENS_FOR_EACH_WITH_NAME_AND_VALUE(MacroOpWithNameAndValue) \
diff --git a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
index 5741eb5..f6620f0 100644
--- a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
+++ b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
@@ -17,6 +17,7 @@
#include "base/stringprintf.h"
#include "cobalt/bindings/testing/bindings_test_base.h"
#include "cobalt/bindings/testing/numeric_types_test_interface.h"
+#include "starboard/double.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -81,7 +82,7 @@
// warning C4800: 'int' : forcing value to bool 'true' or 'false'
#pragma warning(disable:4800)
#endif
- return isnan(number);
+ return SbDoubleIsNan(number);
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 0bd7afe..765245a 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -471,6 +471,17 @@
}
#endif // !defined(COBALT_FORCE_HTTPS)
+ if (command_line->HasSwitch(switches::kVideoPlaybackRateMultiplier)) {
+ double playback_rate = 1.0;
+ base::StringToDouble(command_line->GetSwitchValueASCII(
+ switches::kVideoPlaybackRateMultiplier),
+ &playback_rate);
+ options.web_module_options.video_playback_rate_multiplier =
+ static_cast<float>(playback_rate);
+ DLOG(INFO) << "Set video playback rate multiplier to "
+ << options.web_module_options.video_playback_rate_multiplier;
+ }
+
EnableUsingStubImageDecoderIfRequired();
if (command_line->HasSwitch(browser::switches::kDisableWebmVp9)) {
@@ -497,6 +508,13 @@
}
#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
+ if (command_line->HasSwitch(browser::switches::kDisableNavigationWhitelist)) {
+ LOG(ERROR) << "\n"
+ << " *** Disabling the default navigation whitelist! ***\n"
+ << " *** Do not run in this mode in production! ***";
+ options.web_module_options.location_policy = "h5vcc-location-src *";
+ }
+
account_manager_.reset(new account::AccountManager());
browser_module_.reset(new BrowserModule(initial_url, system_window_.get(),
account_manager_.get(), options));
diff --git a/src/cobalt/browser/browser_bindings_gen.gyp b/src/cobalt/browser/browser_bindings_gen.gyp
index aa35c9a..685296f 100644
--- a/src/cobalt/browser/browser_bindings_gen.gyp
+++ b/src/cobalt/browser/browser_bindings_gen.gyp
@@ -97,8 +97,6 @@
'../dom/html_image_element.idl',
'../dom/html_link_element.idl',
'../dom/html_media_element.idl',
- #'../dom/html_media_element_eme.idl',
- #'../dom/html_media_encrypted_event.idl',
'../dom/html_meta_element.idl',
'../dom/html_paragraph_element.idl',
'../dom/html_script_element.idl',
@@ -110,18 +108,6 @@
'../dom/keyboard_event.idl',
'../dom/location.idl',
'../dom/media_error.idl',
- '../dom/media_key_complete_event.idl',
- '../dom/media_key_error.idl',
- '../dom/media_key_error_event.idl',
- '../dom/media_key_message_event.idl',
- #'../dom/media_key_message_event_init.idl',
- '../dom/media_key_needed_event.idl',
- #'../dom/media_key_session.idl',
- #'../dom/media_key_status_map.idl',
- #'../dom/media_key_system_access.idl',
- #'../dom/media_key_system_configuration.idl',
- #'../dom/media_key_system_media_capability.idl',
- #'../dom/media_keys.idl',
'../dom/media_query_list.idl',
'../dom/media_source.idl',
'../dom/memory_info.idl',
@@ -131,7 +117,6 @@
'../dom/mutation_record.idl',
'../dom/named_node_map.idl',
'../dom/navigator.idl',
- #'../dom/navigator_eme.idl',
'../dom/node.idl',
'../dom/node_list.idl',
'../dom/performance.idl',
@@ -219,7 +204,6 @@
'../xhr/xml_http_request_upload.idl',
],
-
# IDL files that will end up generating a .h that will be #included in
# Cobalt directly. IDL files for dictionaries and enums.
'generated_header_idl_files': [
@@ -227,8 +211,6 @@
'../audio/audio_node_channel_interpretation.idl',
'../dom/blob_property_bag.idl',
'../dom/dom_parser_supported_type.idl',
- '../dom/media_key_status.idl',
- '../dom/media_keys_requirement.idl',
'../dom/media_source_end_of_stream_error.idl',
'../dom/media_source_ready_state.idl',
'../dom/mutation_observer_init.idl',
@@ -238,11 +220,11 @@
'../media_session/media_metadata_init.idl',
'../media_session/media_session_action.idl',
'../media_session/media_session_playback_state.idl',
- '../speech/speech_synthesis_error_code.idl',
'../speech/speech_recognition_error_code.idl',
- '../websocket/close_event_init.idl',
+ '../speech/speech_synthesis_error_code.idl',
'../web_animations/animation_fill_mode.idl',
'../web_animations/animation_playback_direction.idl',
+ '../websocket/close_event_init.idl',
],
# Partial interfaces and the right-side of "implements". Also includes
@@ -252,12 +234,13 @@
'dependency_idl_files': [
'../cssom/link_style.idl',
+ '../dom/buffer_source.idl',
+ '../dom/document__web_animations_api.idl',
'../dom/document_cssom.idl',
'../dom/document_html5.idl',
- '../dom/document__web_animations_api.idl',
+ '../dom/element_css_inline_style.idl',
'../dom/element_cssom_view.idl',
'../dom/element_dom_parsing_and_serialization.idl',
- '../dom/element_css_inline_style.idl',
'../dom/global_crypto.idl',
'../dom/global_event_handlers.idl',
'../dom/html_element_cssom_view.idl',
@@ -272,14 +255,50 @@
'../dom/speech_synthesis_getter.idl',
'../dom/url_utils.idl',
'../dom/window__animation_timing.idl',
+ '../dom/window__performance.idl',
'../dom/window_cssom.idl',
'../dom/window_cssom_view.idl',
- '../dom/window__performance.idl',
'../dom/window_event_handlers.idl',
'../dom/window_local_storage.idl',
'../dom/window_session_storage.idl',
'../dom/window_timers.idl',
'../media_session/navigator_media_session.idl',
],
+
+ 'conditions': [
+ ['cobalt_media_source_2016==1', {
+ 'source_idl_files': [
+ '../dom/eme/media_encrypted_event.idl',
+ '../dom/eme/media_key_message_event.idl',
+ '../dom/eme/media_key_session.idl',
+ '../dom/eme/media_key_system_access.idl',
+ '../dom/eme/media_keys.idl',
+ ],
+ 'generated_header_idl_files': [
+ '../dom/eme/media_encrypted_event_init.idl',
+ '../dom/eme/media_key_message_event_init.idl',
+ '../dom/eme/media_key_message_type.idl',
+ '../dom/eme/media_key_session_type.idl',
+ '../dom/eme/media_key_system_configuration.idl',
+ '../dom/eme/media_key_system_media_capability.idl',
+ '../dom/eme/media_keys_requirement.idl',
+ ],
+ 'dependency_idl_files': [
+ '../dom/eme/html_media_element.idl',
+ '../dom/eme/navigator.idl',
+ ],
+ }, {
+ 'source_idl_files': [
+ '../dom/media_key_complete_event.idl',
+ '../dom/media_key_error.idl',
+ '../dom/media_key_error_event.idl',
+ '../dom/media_key_message_event.idl',
+ '../dom/media_key_needed_event.idl',
+ ],
+ 'dependency_idl_files': [
+ '../dom/html_media_element_eme_01b.idl',
+ ],
+ }],
+ ],
},
}
diff --git a/src/cobalt/browser/cobalt.gyp b/src/cobalt/browser/cobalt.gyp
index 6950cdd..d858eac 100644
--- a/src/cobalt/browser/cobalt.gyp
+++ b/src/cobalt/browser/cobalt.gyp
@@ -23,6 +23,15 @@
'conditions': [
['cobalt_enable_lib == 1', {
'sources': ['lib/main.cc',],
+ 'all_dependent_settings': {
+ 'target_conditions': [
+ ['_type=="executable" and _toolset=="target"', {
+ 'sources': [
+ 'lib/imported/main_stub.cc',
+ ],
+ }],
+ ],
+ },
}, {
'sources': ['main.cc',],
}],
diff --git a/src/cobalt/browser/lib/imported/main.h b/src/cobalt/browser/lib/imported/main.h
index c3abcb8..1cbfd3a 100644
--- a/src/cobalt/browser/lib/imported/main.h
+++ b/src/cobalt/browser/lib/imported/main.h
@@ -18,25 +18,19 @@
#ifndef COBALT_BROWSER_LIB_IMPORTED_MAIN_H_
#define COBALT_BROWSER_LIB_IMPORTED_MAIN_H_
+#include "starboard/event.h"
+#include "starboard/export.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-// Structure representing an input event and its data. This provides a subset
-// of SbEvent so that clients don't have to copy the Starboard headers into
-// their codebase.
-typedef struct CbLibKeyInputEvent {
- unsigned char keycode;
- bool pressed;
-} CbLibKeyInputEvent;
-
// Invoked after Cobalt has been initialized.
-void CbLibOnCobaltInitialized();
+SB_IMPORT_PLATFORM void CbLibOnCobaltInitialized();
// Invoked when Cobalt is receiving an event from Starboard.
-// Returns true if the event should pass through to Cobalt; returns false if
-// the event was consumed.
-bool CbLibHandleEvent(const CbLibKeyInputEvent& event);
+// Returns true if the client consumed |event|; false otherwise.
+SB_IMPORT_PLATFORM bool CbLibHandleEvent(const SbEvent* event);
#ifdef __cplusplus
} // extern "C"
diff --git a/src/cobalt/browser/lib/imported/main_stub.cc b/src/cobalt/browser/lib/imported/main_stub.cc
new file mode 100644
index 0000000..ad5c642
--- /dev/null
+++ b/src/cobalt/browser/lib/imported/main_stub.cc
@@ -0,0 +1,9 @@
+#include "cobalt/browser/lib/imported/main.h"
+
+// Empty implementations so that 'lib' targets can be compiled into executables
+// by the builder without missing symbol definitions.
+void CbLibOnCobaltInitialized() {}
+bool CbLibHandleEvent(const SbEvent* event) {
+ (void) event;
+ return false;
+}
diff --git a/src/cobalt/browser/lib/main.cc b/src/cobalt/browser/lib/main.cc
index 51cd1e4..5d0fb44 100644
--- a/src/cobalt/browser/lib/main.cc
+++ b/src/cobalt/browser/lib/main.cc
@@ -23,26 +23,6 @@
namespace {
-bool SbEventToCbLibKeyInputEvent(
- const SbEvent* starboard_event,
- CbLibKeyInputEvent* out_key_input_event) {
- if (starboard_event == NULL ||
- starboard_event->type != SbEventType::kSbEventTypeInput) {
- return false;
- }
- const SbInputData* input_data =
- static_cast<SbInputData*>(starboard_event->data);
- if (input_data->device_type !=
- SbInputDeviceType::kSbInputDeviceTypeKeyboard) {
- return false;
- }
- out_key_input_event->pressed =
- input_data->type == SbInputEventType::kSbInputEventTypePress;
- out_key_input_event->keycode =
- static_cast<unsigned char>(input_data->character);
- return true;
-}
-
cobalt::browser::Application* g_application = NULL;
void StartApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
@@ -62,9 +42,7 @@
}
void HandleEvent(const SbEvent* starboard_event) {
- CbLibKeyInputEvent key;
- if (!SbEventToCbLibKeyInputEvent(starboard_event, &key) ||
- CbLibHandleEvent(key)) {
+ if (!CbLibHandleEvent(starboard_event)) {
cobalt::browser::EventHandler::HandleEvent(starboard_event);
}
}
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index 5e2ffd0..3b43b3d 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -112,6 +112,10 @@
#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
+// Disables the hard-coded navigation whitelist without disabling any other
+// security checks. This is enabled in Gold builds.
+const char kDisableNavigationWhitelist[] = "disable_navigation_whitelist";
+
// Determines the capacity of the image cache which manages image surfaces
// downloaded from a web page. While it depends on the platform, often (and
// ideally) these images are cached within GPU memory.
@@ -173,6 +177,10 @@
// Specifies the maximum GPU usage of the cobalt.
const char kMaxCobaltGpuUsage[] = "max_cobalt_gpu_usage";
+// Specifies the multiplier of video playback rate. Set to a value greater than
+// 1.0 to play video faster. Set to a value less than 1.0 to play video slower.
+const char kVideoPlaybackRateMultiplier[] = "video_playback_rate_multiplier";
+
} // namespace switches
} // namespace browser
} // namespace cobalt
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index 9214784..49a5fc7 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -47,6 +47,7 @@
extern const char kWebDriverListenIp[];
#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
+extern const char kDisableNavigationWhitelist[];
extern const char kImageCacheSizeInBytes[];
extern const char kInitialURL[];
extern const char kRemoteTypefaceCacheSizeInBytes[];
@@ -62,6 +63,8 @@
extern const char kMaxCobaltCpuUsage[];
extern const char kMaxCobaltGpuUsage[];
+extern const char kVideoPlaybackRateMultiplier[];
+
} // namespace switches
} // namespace browser
} // namespace cobalt
diff --git a/src/cobalt/browser/testdata/eme-demo/eme-demo.html b/src/cobalt/browser/testdata/eme-demo/eme-demo.html
new file mode 100644
index 0000000..0ebf640
--- /dev/null
+++ b/src/cobalt/browser/testdata/eme-demo/eme-demo.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+ | Copyright 2017 Google Inc. All Rights Reserved.
+ |
+ | Licensed under the Apache License, Version 2.0 (the "License");
+ | you may not use this file except in compliance with the License.
+ | You may obtain a copy of the License at
+ |
+ | http://www.apache.org/licenses/LICENSE-2.0
+ |
+ | Unless required by applicable law or agreed to in writing, software
+ | distributed under the License is distributed on an "AS IS" BASIS,
+ | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ | See the License for the specific language governing permissions and
+ | limitations under the License.
+ -->
+<html>
+<head>
+ <title>Encrypted Media Extensions (16 March 2017) Demo</title>
+ <style>
+ body {
+ background-color: white;
+ }
+ video {
+ height: 240px;
+ width: 426px;
+ }
+ </style>
+</head>
+
+<body>
+ <video></video>
+ <script src="eme-demo.js"></script>
+</body>
+</html>
diff --git a/src/cobalt/browser/testdata/eme-demo/eme-demo.js b/src/cobalt/browser/testdata/eme-demo/eme-demo.js
new file mode 100644
index 0000000..1a111db
--- /dev/null
+++ b/src/cobalt/browser/testdata/eme-demo/eme-demo.js
@@ -0,0 +1,89 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+function fetchArrayBuffer(method, url, body, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.responseType = 'arraybuffer';
+ xhr.addEventListener('load', function() {
+ callback(xhr.response);
+ });
+ xhr.open(method, url);
+ xhr.send(body);
+}
+
+function extractLicense(licenseArrayBuffer) {
+ var licenseArray = new Uint8Array(licenseArrayBuffer);
+ var licenseStartIndex = licenseArray.length - 2;
+ while (licenseStartIndex >= 0) {
+ if (licenseArray[licenseStartIndex] == 13 &&
+ licenseArray[licenseStartIndex + 1] == 10) {
+ licenseStartIndex += 2;
+ break;
+ }
+ --licenseStartIndex;
+ }
+
+ return licenseArray.subarray(licenseStartIndex);
+}
+
+var videoContentType = 'video/mp4; codecs="avc1.640028"';
+var audioContentType = 'audio/mp4; codecs="mp4a.40.2"';
+
+navigator.requestMediaKeySystemAccess('com.widevine.alpha', [{
+ 'initDataTypes': ['cenc'],
+ 'videoCapabilities': [{'contentType': videoContentType}],
+ 'audioCapabilities': [{'contentType': audioContentType}]
+}]).then(function(mediaKeySystemAccess) {
+ return mediaKeySystemAccess.createMediaKeys();
+}).then(function(mediaKeys) {
+ var videoElement = document.querySelector('video');
+
+ videoElement.setMediaKeys(mediaKeys);
+
+ mediaKeySession = mediaKeys.createSession();
+ mediaKeySession.addEventListener('message', function(messageEvent) {
+ var licenseServerUrl = 'https://dash-mse-test.appspot.com/api/drm/widevine?drm_system=widevine&source=YOUTUBE&ip=0.0.0.0&ipbits=0&expire=19000000000&key=test_key1&sparams=ip,ipbits,expire,drm_system,source,video_id&video_id=03681262dc412c06&signature=9C4BE99E6F517B51FED1F0B3B31966D3C5DAB9D6.6A1F30BB35F3A39A4CA814B731450D4CBD198FFD';
+ fetchArrayBuffer('POST', licenseServerUrl, messageEvent.message,
+ function(licenseArrayBuffer) {
+ mediaKeySession.update(extractLicense(licenseArrayBuffer));
+ });
+ });
+
+ videoElement.addEventListener('encrypted', function(encryptedEvent) {
+ mediaKeySession.generateRequest(
+ encryptedEvent.initDataType, encryptedEvent.initData);
+ });
+
+ var mediaSource = new MediaSource();
+ mediaSource.addEventListener('sourceopen', function() {
+ var videoSourceBuffer = mediaSource.addSourceBuffer(videoContentType);
+ fetchArrayBuffer('GET',
+ 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/oops_cenc-20121114-142.mp4',
+ null,
+ function(videoArrayBuffer) {
+ videoSourceBuffer.appendBuffer(videoArrayBuffer);
+ });
+
+ var audioSourceBuffer = mediaSource.addSourceBuffer(audioContentType);
+ fetchArrayBuffer('GET',
+ 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/oops_cenc-20121114-148.mp4',
+ null,
+ function(audioArrayBuffer) {
+ audioSourceBuffer.appendBuffer(audioArrayBuffer);
+ });
+ });
+
+ videoElement.src = URL.createObjectURL(mediaSource);
+ videoElement.play();
+});
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 2b6aad6..380b091 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -495,7 +495,8 @@
data.window_close_callback, data.window_minimize_callback,
data.system_window_, data.options.camera_3d,
media_session_client_->GetMediaSession(),
- data.options.csp_insecure_allowed_token, data.dom_max_element_depth);
+ data.options.csp_insecure_allowed_token, data.dom_max_element_depth,
+ data.options.video_playback_rate_multiplier);
DCHECK(window_);
window_weak_ = base::AsWeakPtr(window_.get());
@@ -779,10 +780,12 @@
debug_overlay_->ClearInput();
#endif
- // Finally purge the resource provider's caches and mark that we have no
- // resource provider.
- resource_provider_->PurgeCaches();
resource_provider_ = NULL;
+
+ // Force garbage collection in |javascript_engine_|.
+ if (javascript_engine_) {
+ javascript_engine_->CollectGarbage();
+ }
}
void WebModule::Impl::Resume(render_tree::ResourceProvider* resource_provider) {
@@ -850,7 +853,8 @@
image_cache_capacity_multiplier_when_playing_video(1.0f),
thread_priority(base::kThreadPriority_Normal),
loader_thread_priority(base::kThreadPriority_Low),
- animated_image_decode_thread_priority(base::kThreadPriority_Low) {}
+ animated_image_decode_thread_priority(base::kThreadPriority_Low),
+ video_playback_rate_multiplier(1.f) {}
WebModule::WebModule(
const GURL& initial_url,
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index 3e29f72..d590e3e 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -169,6 +169,10 @@
scoped_refptr<input::Camera3D> camera_3d;
script::JavaScriptEngine::Options javascript_options;
+
+ // The video playback rate will be multiplied with the following value. Its
+ // default value is 1.0.
+ float video_playback_rate_multiplier;
};
typedef layout::LayoutManager::LayoutResults LayoutResults;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 9f62695..c2eb52e 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-52708
\ No newline at end of file
+55341
\ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index ddfd269..0c93ea2 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -43,6 +43,17 @@
'sb_enable_lib%': '<(sb_enable_lib)',
'cobalt_enable_lib': '<(sb_enable_lib)',
+ # This variable defines what Cobalt's preferred strategy should be for
+ # handling internally triggered application exit requests (e.g. the user
+ # chooses to back out of the application).
+ # 'stop' -- The application should call SbSystemRequestStop() on exit,
+ # resulting in a complete shutdown of the application.
+ # 'suspend' -- The application should call SbSystemRequestSuspend() on
+ # exit, resulting in the application being "minimized".
+ # 'noexit' -- The application should never allow the user to trigger an
+ # exit, this will be managed by the system.
+ 'cobalt_user_on_exit_strategy': 'stop',
+
# Contains the current font package selection. This can be used to trade
# font quality, coverage, and latency for different font package sizes.
# The font package can be one of the following options:
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/cobalt/dom/buffer_source.h
similarity index 60%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/cobalt/dom/buffer_source.h
index 51e1f2e..a796675 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/cobalt/dom/buffer_source.h
@@ -12,9 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#ifndef COBALT_DOM_BUFFER_SOURCE_H_
+#define COBALT_DOM_BUFFER_SOURCE_H_
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include "cobalt/script/union_type.h"
+
+namespace cobalt {
+namespace dom {
+
+class ArrayBuffer;
+class ArrayBufferView;
+
+typedef script::UnionType2<scoped_refptr<ArrayBufferView>,
+ scoped_refptr<ArrayBuffer> > BufferSource;
+
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_BUFFER_SOURCE_H_
diff --git a/src/cobalt/base/math.h b/src/cobalt/dom/buffer_source.idl
similarity index 77%
rename from src/cobalt/base/math.h
rename to src/cobalt/dom/buffer_source.idl
index 4723bfb..91cb04a 100644
--- a/src/cobalt/base/math.h
+++ b/src/cobalt/dom/buffer_source.idl
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+// https://www.w3.org/TR/WebIDL-1/#common-BufferSource
-#include <cmath>
-
-#endif // COBALT_BASE_MATH_H_
+typedef (ArrayBufferView or ArrayBuffer) BufferSource;
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc
index 754ee9b..09a671c 100644
--- a/src/cobalt/dom/document.cc
+++ b/src/cobalt/dom/document.cc
@@ -676,8 +676,13 @@
}
void Document::PurgeCachedResources() {
+ // Set the font faces to dirty prior to purging the font cache so that they'll
+ // be restored when processing resumes.
+ are_font_faces_dirty_ = true;
+ font_cache_->PurgeCachedResources();
+
// Set the computed style to dirty so that it'll be able to update any
- // elements that had images purged when it resumes.
+ // elements that had images purged when processing resumes.
is_computed_style_dirty_ = true;
scoped_refptr<HTMLHtmlElement> current_html = html();
diff --git a/src/cobalt/dom/dom.gyp b/src/cobalt/dom/dom.gyp
index a815619..6738764 100644
--- a/src/cobalt/dom/dom.gyp
+++ b/src/cobalt/dom/dom.gyp
@@ -37,6 +37,7 @@
'blob.cc',
'blob.h',
'blob_property_bag.h',
+ 'buffer_source.h',
'camera_3d.cc',
'camera_3d.h',
'camera_3d_impl.cc',
@@ -169,16 +170,6 @@
'local_storage_database.h',
'location.cc',
'location.h',
- 'media_error.h',
- 'media_key_complete_event.cc',
- 'media_key_complete_event.h',
- 'media_key_error.h',
- 'media_key_error_event.cc',
- 'media_key_error_event.h',
- 'media_key_message_event.cc',
- 'media_key_message_event.h',
- 'media_key_needed_event.cc',
- 'media_key_needed_event.h',
'media_query_list.cc',
'media_query_list.h',
'memory_info.cc',
@@ -287,6 +278,16 @@
'conditions': [
['cobalt_media_source_2016==1', {
'sources': [
+ 'eme/media_encrypted_event.cc',
+ 'eme/media_encrypted_event.h',
+ 'eme/media_key_message_event.cc',
+ 'eme/media_key_message_event.h',
+ 'eme/media_key_session.cc',
+ 'eme/media_key_session.h',
+ 'eme/media_key_system_access.cc',
+ 'eme/media_key_system_access.h',
+ 'eme/media_keys.cc',
+ 'eme/media_keys.h',
'media_source/media_source.cc',
'media_source/media_source.h',
'media_source/source_buffer.cc',
@@ -299,6 +300,16 @@
],
}, {
'sources': [
+ 'media_error.h',
+ 'media_key_complete_event.cc',
+ 'media_key_complete_event.h',
+ 'media_key_error.h',
+ 'media_key_error_event.cc',
+ 'media_key_error_event.h',
+ 'media_key_message_event.cc',
+ 'media_key_message_event.h',
+ 'media_key_needed_event.cc',
+ 'media_key_needed_event.h',
'media_source.cc',
'media_source.h',
'source_buffer.cc',
diff --git a/src/cobalt/dom/element.h b/src/cobalt/dom/element.h
index 1e64100..01901c9 100644
--- a/src/cobalt/dom/element.h
+++ b/src/cobalt/dom/element.h
@@ -71,6 +71,7 @@
// Web API: Element
//
+ base::Token local_name() const { return local_name_; }
base::Token tag_name() const;
@@ -126,8 +127,6 @@
// Custom, not in any spec.
//
- base::Token local_name() const { return local_name_; }
-
// Returns whether the element has no children at all except comments or
// processing instructions.
// https://www.w3.org/TR/selectors4/#empty-pseudo
diff --git a/src/cobalt/dom/element.idl b/src/cobalt/dom/element.idl
index 98a77a2..d168de1 100644
--- a/src/cobalt/dom/element.idl
+++ b/src/cobalt/dom/element.idl
@@ -15,6 +15,7 @@
// https://www.w3.org/TR/dom/#element
interface Element : Node {
+ readonly attribute DOMString localName;
readonly attribute DOMString tagName;
attribute DOMString id;
attribute DOMString className;
diff --git a/src/cobalt/dom/element_test.cc b/src/cobalt/dom/element_test.cc
index 1e84b7a..5d1f52f 100644
--- a/src/cobalt/dom/element_test.cc
+++ b/src/cobalt/dom/element_test.cc
@@ -123,7 +123,7 @@
EXPECT_EQ(NULL, text->AsElement());
}
-TEST_F(ElementTest, TagName) {
+TEST_F(ElementTest, TagNameAndLocalName) {
scoped_refptr<Element> element_in_html =
new Element(document_, base::Token("eLeMeNt"));
EXPECT_EQ("ELEMENT", element_in_html->tag_name());
diff --git a/src/cobalt/dom/html_media_element_eme.idl b/src/cobalt/dom/eme/html_media_element.idl
similarity index 80%
rename from src/cobalt/dom/html_media_element_eme.idl
rename to src/cobalt/dom/eme/html_media_element.idl
index 3b3d924..120d983 100644
--- a/src/cobalt/dom/html_media_element_eme.idl
+++ b/src/cobalt/dom/eme/html_media_element.idl
@@ -12,11 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#htmlmediaelement-extensions
+// https://www.w3.org/TR/encrypted-media/#htmlmediaelement-extensions
partial interface HTMLMediaElement {
readonly attribute MediaKeys? mediaKeys;
attribute EventHandler onencrypted;
- attribute EventHandler onwaitingforkey;
+ // TODO: Implement the event handler for the waitingforkey event.
+ // attribute EventHandler onwaitingforkey;
Promise<void> setMediaKeys(MediaKeys? mediaKeys);
};
diff --git a/src/cobalt/dom/eme/media_encrypted_event.cc b/src/cobalt/dom/eme/media_encrypted_event.cc
new file mode 100644
index 0000000..9bfe06c
--- /dev/null
+++ b/src/cobalt/dom/eme/media_encrypted_event.cc
@@ -0,0 +1,36 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/dom/eme/media_encrypted_event.h"
+
+#include "cobalt/base/tokens.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+// See step 5 in https://www.w3.org/TR/encrypted-media/#initdata-encountered.
+MediaEncryptedEvent::MediaEncryptedEvent(const std::string& type)
+ : Event(base::Token(type), kNotBubbles, kNotCancelable) {}
+
+// See step 5 in https://www.w3.org/TR/encrypted-media/#initdata-encountered.
+MediaEncryptedEvent::MediaEncryptedEvent(
+ const std::string& type, const MediaEncryptedEventInit& event_init_dict)
+ : Event(base::Token(type), kNotBubbles, kNotCancelable),
+ init_data_type_(event_init_dict.init_data_type()),
+ init_data_(event_init_dict.init_data()) {}
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
diff --git a/src/cobalt/dom/eme/media_encrypted_event.h b/src/cobalt/dom/eme/media_encrypted_event.h
new file mode 100644
index 0000000..c803777
--- /dev/null
+++ b/src/cobalt/dom/eme/media_encrypted_event.h
@@ -0,0 +1,55 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_DOM_EME_MEDIA_ENCRYPTED_EVENT_H_
+#define COBALT_DOM_EME_MEDIA_ENCRYPTED_EVENT_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "cobalt/dom/array_buffer.h"
+#include "cobalt/dom/eme/media_encrypted_event_init.h"
+#include "cobalt/dom/event.h"
+#include "cobalt/script/wrappable.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+// The MediaEncryptedEvent object is used for the encrypted event.
+// https://www.w3.org/TR/encrypted-media/#mediaencryptedevent
+class MediaEncryptedEvent : public Event {
+ public:
+ // Web API: MediaEncryptedEvent
+ //
+
+ explicit MediaEncryptedEvent(const std::string& type);
+ MediaEncryptedEvent(const std::string& type,
+ const MediaEncryptedEventInit& event_init_dict);
+
+ const std::string& init_data_type() const { return init_data_type_; }
+ const scoped_refptr<ArrayBuffer>& init_data() const { return init_data_; }
+
+ DEFINE_WRAPPABLE_TYPE(MediaEncryptedEvent);
+
+ private:
+ std::string init_data_type_;
+ scoped_refptr<ArrayBuffer> init_data_;
+};
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_EME_MEDIA_ENCRYPTED_EVENT_H_
diff --git a/src/cobalt/dom/media_encrypted_event.idl b/src/cobalt/dom/eme/media_encrypted_event.idl
similarity index 80%
rename from src/cobalt/dom/media_encrypted_event.idl
rename to src/cobalt/dom/eme/media_encrypted_event.idl
index cd33c01..835165b 100644
--- a/src/cobalt/dom/media_encrypted_event.idl
+++ b/src/cobalt/dom/eme/media_encrypted_event.idl
@@ -12,12 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediaencryptedevent
-
-dictionary MediaEncryptedEventInit : EventInit {
- DOMString initDataType = "";
- ArrayBuffer? initData = null;
-};
+// https://www.w3.org/TR/encrypted-media/#mediaencryptedevent
[Constructor(DOMString type, optional MediaEncryptedEventInit eventInitDict)]
interface MediaEncryptedEvent : Event {
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/cobalt/dom/eme/media_encrypted_event_init.idl
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/cobalt/dom/eme/media_encrypted_event_init.idl
index 51e1f2e..25ad898 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/cobalt/dom/eme/media_encrypted_event_init.idl
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+// https://www.w3.org/TR/encrypted-media/#mediaencryptedeventinit
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
+dictionary MediaEncryptedEventInit : EventInit {
+ DOMString initDataType = "";
+ ArrayBuffer? initData = null;
};
diff --git a/src/cobalt/dom/eme/media_key_message_event.cc b/src/cobalt/dom/eme/media_key_message_event.cc
new file mode 100644
index 0000000..0226561
--- /dev/null
+++ b/src/cobalt/dom/eme/media_key_message_event.cc
@@ -0,0 +1,33 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/dom/eme/media_key_message_event.h"
+
+#include "cobalt/base/tokens.h"
+#include "cobalt/dom/eme/media_key_message_type.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+// See step 2 in https://www.w3.org/TR/encrypted-media/#queue-message.
+MediaKeyMessageEvent::MediaKeyMessageEvent(
+ const std::string& type, const MediaKeyMessageEventInit& event_init_dict)
+ : Event(base::Token(type), kNotBubbles, kNotCancelable),
+ message_type_(event_init_dict.message_type()),
+ message_(event_init_dict.message()) {}
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
diff --git a/src/cobalt/dom/eme/media_key_message_event.h b/src/cobalt/dom/eme/media_key_message_event.h
new file mode 100644
index 0000000..aa3379e
--- /dev/null
+++ b/src/cobalt/dom/eme/media_key_message_event.h
@@ -0,0 +1,55 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_DOM_EME_MEDIA_KEY_MESSAGE_EVENT_H_
+#define COBALT_DOM_EME_MEDIA_KEY_MESSAGE_EVENT_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "cobalt/dom/array_buffer.h"
+#include "cobalt/dom/eme/media_key_message_event_init.h"
+#include "cobalt/dom/eme/media_key_message_type.h"
+#include "cobalt/dom/event.h"
+#include "cobalt/script/wrappable.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+// The MediaKeyMessageEvent object is used for the message event.
+// https://www.w3.org/TR/encrypted-media/#mediakeymessageevent
+class MediaKeyMessageEvent : public Event {
+ public:
+ // Web IDL: MediaKeyMessageEvent
+ //
+
+ MediaKeyMessageEvent(const std::string& type,
+ const MediaKeyMessageEventInit& event_init_dict);
+
+ MediaKeyMessageType message_type() const { return message_type_; }
+ const scoped_refptr<ArrayBuffer>& message() const { return message_; }
+
+ DEFINE_WRAPPABLE_TYPE(MediaKeyMessageEvent);
+
+ private:
+ MediaKeyMessageType message_type_;
+ scoped_refptr<ArrayBuffer> message_;
+};
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_EME_MEDIA_KEY_MESSAGE_EVENT_H_
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/cobalt/dom/eme/media_key_message_event.idl
similarity index 69%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/cobalt/dom/eme/media_key_message_event.idl
index 51e1f2e..9e459ac 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/cobalt/dom/eme/media_key_message_event.idl
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+// https://www.w3.org/TR/encrypted-media/#mediakeymessageevent
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
+[Constructor(DOMString type, MediaKeyMessageEventInit eventInitDict)]
+interface MediaKeyMessageEvent : Event {
+ readonly attribute MediaKeyMessageType messageType;
+ readonly attribute ArrayBuffer message;
};
diff --git a/src/cobalt/dom/media_key_message_event_init.idl b/src/cobalt/dom/eme/media_key_message_event_init.idl
similarity index 82%
rename from src/cobalt/dom/media_key_message_event_init.idl
rename to src/cobalt/dom/eme/media_key_message_event_init.idl
index 9115a44..0f6602c 100644
--- a/src/cobalt/dom/media_key_message_event_init.idl
+++ b/src/cobalt/dom/eme/media_key_message_event_init.idl
@@ -12,7 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// https://www.w3.org/TR/encrypted-media/#mediakeymessageeventinit
+
dictionary MediaKeyMessageEventInit : EventInit {
- MediaKeyMessageType messageType = "license-request";
- ArrayBuffer message;
+ required MediaKeyMessageType messageType;
+ required ArrayBuffer message;
};
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/cobalt/dom/eme/media_key_message_type.idl
similarity index 71%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/cobalt/dom/eme/media_key_message_type.idl
index 51e1f2e..1125463 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/cobalt/dom/eme/media_key_message_type.idl
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+// https://www.w3.org/TR/encrypted-media/#idl-def-mediakeymessagetype
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
+enum MediaKeyMessageType {
+ "license-request",
+ // TODO: Implement other message types.
+ // "license-renewal",
+ // "license-release",
+ // "individualization-request"
};
diff --git a/src/cobalt/dom/eme/media_key_session.cc b/src/cobalt/dom/eme/media_key_session.cc
new file mode 100644
index 0000000..f66bf48
--- /dev/null
+++ b/src/cobalt/dom/eme/media_key_session.cc
@@ -0,0 +1,325 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/dom/eme/media_key_session.h"
+
+#include "cobalt/dom/array_buffer.h"
+#include "cobalt/dom/array_buffer_view.h"
+#include "cobalt/dom/dom_exception.h"
+#include "cobalt/dom/eme/media_key_message_event.h"
+#include "cobalt/dom/eme/media_key_message_event_init.h"
+#include "cobalt/dom/eme/media_keys.h"
+#include "cobalt/script/script_value_factory.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+// See step 3.1 of
+// https://www.w3.org/TR/encrypted-media/#dom-mediakeys-createsession.
+MediaKeySession::MediaKeySession(
+ scoped_ptr<media::DrmSystem::Session> drm_system_session,
+ script::ScriptValueFactory* script_value_factory,
+ const ClosedCallback& closed_callback)
+ : drm_system_session_(drm_system_session.Pass()),
+ script_value_factory_(script_value_factory),
+ uninitialized_(true),
+ callable_(false),
+ closed_callback_(closed_callback),
+ ALLOW_THIS_IN_INITIALIZER_LIST(closed_promise_reference_(
+ this, script_value_factory->CreateBasicPromise<void>())),
+ initiated_by_generate_request_(false) {}
+
+// Session ID should be empty for uninitialized sessions according to step 3.1
+// of https://www.w3.org/TR/encrypted-media/#dom-mediakeys-createsession.
+std::string MediaKeySession::session_id() const {
+ return drm_system_session_->id().value_or("");
+}
+
+MediaKeySession::~MediaKeySession() {}
+
+const MediaKeySession::VoidPromiseValue* MediaKeySession::closed() const {
+ return &closed_promise_reference_.referenced_value();
+}
+
+const EventTarget::EventListenerScriptValue* MediaKeySession::onmessage()
+ const {
+ return GetAttributeEventListener(base::Tokens::message());
+}
+
+void MediaKeySession::set_onmessage(
+ const EventListenerScriptValue& event_listener) {
+ SetAttributeEventListener(base::Tokens::message(), event_listener);
+}
+
+namespace {
+
+void GetBufferAndSize(const BufferSource& buffer_source, const uint8** buffer,
+ int* buffer_size) {
+ if (buffer_source.IsType<scoped_refptr<ArrayBufferView> >()) {
+ scoped_refptr<ArrayBufferView> array_buffer_view =
+ buffer_source.AsType<scoped_refptr<ArrayBufferView> >();
+ *buffer = static_cast<const uint8*>(array_buffer_view->base_address());
+ *buffer_size = array_buffer_view->byte_length();
+ } else if (buffer_source.IsType<scoped_refptr<ArrayBuffer> >()) {
+ scoped_refptr<ArrayBuffer> array_buffer =
+ buffer_source.AsType<scoped_refptr<ArrayBuffer> >();
+ *buffer = array_buffer->data();
+ *buffer_size = array_buffer->byte_length();
+ } else {
+ NOTREACHED();
+ }
+}
+
+} // namespace
+
+// See
+// https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-generaterequest.
+scoped_ptr<MediaKeySession::VoidPromiseValue> MediaKeySession::GenerateRequest(
+ const std::string& init_data_type, const BufferSource& init_data) {
+ scoped_ptr<VoidPromiseValue> promise =
+ script_value_factory_->CreateBasicPromise<void>();
+ VoidPromiseValue::StrongReference promise_reference(*promise);
+
+ // 1. If this object is closed, return a promise rejected with
+ // an InvalidStateError.
+ // 2. If this object's uninitialized value is false, return a promise rejected
+ // with an InvalidStateError.
+ if (drm_system_session_->is_closed() || !uninitialized_) {
+ promise_reference.value().Reject(
+ new DOMException(DOMException::kInvalidStateErr));
+ return promise.Pass();
+ }
+
+ // 3. Let this object's uninitialized value be false.
+ uninitialized_ = false;
+
+ const uint8* init_data_buffer;
+ int init_data_buffer_size;
+ GetBufferAndSize(init_data, &init_data_buffer, &init_data_buffer_size);
+
+ // 4. If initDataType is the empty string, return a promise rejected with
+ // a newly created TypeError.
+ // 5. If initData is an empty array, return a promise rejected with a newly
+ // created TypeError.
+ if (init_data_type.empty() || init_data_buffer_size == 0) {
+ promise_reference.value().Reject(script::kTypeError);
+ return promise.Pass();
+ }
+
+ // 10.2. The user agent must thoroughly validate the initialization data
+ // before passing it to the CDM.
+ //
+ // Sanitation is the responsibility of Starboard implementers.
+
+ // 10.9. Use the CDM.
+ initiated_by_generate_request_ = true;
+ drm_system_session_->GenerateUpdateRequest(
+ init_data_type, init_data_buffer, init_data_buffer_size,
+ base::Bind(&MediaKeySession::OnSessionUpdateRequestGenerated,
+ base::AsWeakPtr(this),
+ base::Owned(new VoidPromiseValue::Reference(this, *promise))),
+ base::Bind(&MediaKeySession::OnSessionUpdateRequestDidNotGenerate,
+ base::AsWeakPtr(this),
+ base::Owned(new VoidPromiseValue::Reference(this, *promise))));
+
+ // 11. Return promise.
+ return promise.Pass();
+}
+
+// See https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-update.
+scoped_ptr<MediaKeySession::VoidPromiseValue> MediaKeySession::Update(
+ const BufferSource& response) {
+ scoped_ptr<VoidPromiseValue> promise =
+ script_value_factory_->CreateBasicPromise<void>();
+ VoidPromiseValue::StrongReference promise_reference(*promise);
+
+ // 1. If this object is closed, return a promise rejected with
+ // an InvalidStateError.
+ // 2. If this object's callable value is false, return a promise rejected
+ // with an InvalidStateError.
+ if (drm_system_session_->is_closed() || !callable_) {
+ promise_reference.value().Reject(
+ new DOMException(DOMException::kInvalidStateErr));
+ return promise.Pass();
+ }
+
+ const uint8* response_buffer;
+ int response_buffer_size;
+ GetBufferAndSize(response, &response_buffer, &response_buffer_size);
+
+ // 3. If response is an empty array, return a promise rejected with a newly
+ // created TypeError.
+ if (response_buffer_size == 0) {
+ promise_reference.value().Reject(script::kTypeError);
+ return promise.Pass();
+ }
+
+ // 6.1. Let sanitized response be a validated and/or sanitized version of
+ // response copy.
+ //
+ // Sanitation is the responsibility of Starboard implementers.
+
+ // 6.7. Use the CDM.
+ drm_system_session_->Update(
+ response_buffer, response_buffer_size,
+ base::Bind(&MediaKeySession::OnSessionUpdated, base::AsWeakPtr(this),
+ base::Owned(new VoidPromiseValue::Reference(this, *promise))),
+ base::Bind(&MediaKeySession::OnSessionDidNotUpdate, base::AsWeakPtr(this),
+ base::Owned(new VoidPromiseValue::Reference(this, *promise))));
+
+ // 7. Return promise.
+ return promise.Pass();
+}
+
+// See https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-close.
+scoped_ptr<MediaKeySession::VoidPromiseValue> MediaKeySession::Close() {
+ scoped_ptr<VoidPromiseValue> promise =
+ script_value_factory_->CreateBasicPromise<void>();
+ VoidPromiseValue::StrongReference promise_reference(*promise);
+
+ // 2. If session is closed, return a resolved promise.
+ if (drm_system_session_->is_closed()) {
+ promise_reference.value().Resolve();
+ return promise.Pass();
+ }
+
+ // 3. If session's callable value is false, return a promise rejected with
+ // an InvalidStateError.
+ if (!callable_) {
+ promise_reference.value().Reject(
+ new DOMException(DOMException::kInvalidStateErr));
+ return promise.Pass();
+ }
+
+ // 5.2. Use CDM to close the key session associated with session.
+ drm_system_session_->Close();
+
+ // Let |MediaKeys| know that the session should be removed from the list
+ // of open sessions.
+ closed_callback_.Run(this);
+
+ // 5.3.1. Run the Session Closed algorithm on the session.
+ OnClosed();
+
+ // 5.3.2. Resolve promise.
+ promise_reference.value().Resolve();
+ return promise.Pass();
+}
+
+// See
+// https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-generaterequest.
+void MediaKeySession::OnSessionUpdateRequestGenerated(
+ VoidPromiseValue::Reference* promise_reference, scoped_array<uint8> message,
+ int message_size) {
+ MediaKeyMessageEventInit media_key_message_event_init;
+ // 10.9.4. If a license request for the requested license type can be
+ // generated based on the sanitized init data:
+ // 10.9.4.1. Let message be a license request for the requested license type
+ // generated based on the sanitized init data interpreted
+ // per initDataType.
+ // Otherwise:
+ // 10.9.4.1. Let message be the request that needs to be processed before
+ // a license request request for the requested license type can be
+ // generated based on the sanitized init data.
+ media_key_message_event_init.set_message(new ArrayBuffer(
+ NULL, ArrayBuffer::kFromHeap, message.Pass(), message_size));
+ // 10.9.4.2. Let message type reflect the type of message, either
+ // "license-request" or "individualization-request".
+ //
+ // TODO: Introduce message type parameter to |SbDrmSessionUpdateRequestFunc|
+ // and stop pretending that all messages are license requests.
+ media_key_message_event_init.set_message_type(
+ kMediaKeyMessageTypeLicenseRequest);
+
+ // 10.3. Let this object's callable value be true.
+ callable_ = true;
+
+ // 10.4. Run the Queue a "message" Event algorithm on the session.
+ //
+ // TODO: Implement Event.isTrusted as per
+ // https://www.w3.org/TR/dom/#dom-event-istrusted and set it to true.
+ DispatchEvent(
+ new MediaKeyMessageEvent("message", media_key_message_event_init));
+
+ // 10.5. Resolve promise.
+ //
+ // If the request was generated spontaneously by the underlying DRM system,
+ // we shouldn't resolve the promise returned by |GenerateRequest|. The promise
+ // was resolved in the first invocation of this method and now is simply
+ // hanging around.
+ if (initiated_by_generate_request_) {
+ initiated_by_generate_request_ = false;
+ promise_reference->value().Resolve();
+ }
+}
+
+// See
+// https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-generaterequest.
+void MediaKeySession::OnSessionUpdateRequestDidNotGenerate(
+ VoidPromiseValue::Reference* promise_reference) {
+ // 10.10.1. If any of the preceding steps failed, reject promise with a new
+ // DOMException whose name is the appropriate error name.
+ //
+ // TODO: Introduce Starboard API that allows CDM to propagate error codes.
+ promise_reference->value().Reject(new DOMException(DOMException::kNone));
+}
+
+// See https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-update.
+void MediaKeySession::OnSessionUpdated(
+ VoidPromiseValue::Reference* promise_reference) {
+ // 8.1.1. If the set of keys known to the CDM for this object changed or
+ // the status of any key(s) changed, run the Update Key Statuses
+ // algorithm on the session.
+ //
+ // TODO: Implement key statuses.
+
+ // 8.1.2. If the expiration time for the session changed, run the Update
+ // Expiration algorithm on the session.
+ //
+ // TODO: Implement expiration.
+
+ // 8.2. Resolve promise.
+ promise_reference->value().Resolve();
+}
+
+// See https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-update.
+void MediaKeySession::OnSessionDidNotUpdate(
+ VoidPromiseValue::Reference* promise_reference) {
+ // 8.1.3. If any of the preceding steps failed, reject promise with a new
+ // DOMException whose name is the appropriate error name.
+ //
+ // TODO: Introduce Starboard API that allows CDM to propagate error codes.
+ promise_reference->value().Reject(new DOMException(DOMException::kNone));
+}
+
+// See https://www.w3.org/TR/encrypted-media/#session-closed.
+void MediaKeySession::OnClosed() {
+ // 2. Run the Update Key Statuses algorithm on the session, providing an empty
+ // sequence.
+ //
+ // TODO: Implement key statuses.
+
+ // 3. Run the Update Expiration algorithm on the session, providing NaN.
+ //
+ // TODO: Implement expiration.
+
+ // 4. Let promise be the closed attribute of the session.
+ // 5. Resolve promise.
+ closed_promise_reference_.value().Resolve();
+}
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
diff --git a/src/cobalt/dom/eme/media_key_session.h b/src/cobalt/dom/eme/media_key_session.h
new file mode 100644
index 0000000..4419362
--- /dev/null
+++ b/src/cobalt/dom/eme/media_key_session.h
@@ -0,0 +1,91 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_DOM_EME_MEDIA_KEY_SESSION_H_
+#define COBALT_DOM_EME_MEDIA_KEY_SESSION_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "cobalt/dom/buffer_source.h"
+#include "cobalt/dom/event_target.h"
+#include "cobalt/media/base/drm_system.h"
+#include "cobalt/script/promise.h"
+#include "cobalt/script/script_value_factory.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+// A session provides a context for message exchange with the CDM as a result
+// of which keys are made available to the CDM.
+// https://www.w3.org/TR/encrypted-media/#key-session
+//
+// Also see https://www.w3.org/TR/encrypted-media/#mediakeysession-interface.
+class MediaKeySession : public EventTarget {
+ public:
+ typedef script::ScriptValue<script::Promise<void> > VoidPromiseValue;
+ typedef base::Callback<void(MediaKeySession* session)> ClosedCallback;
+
+ // Custom, not in any spec.
+ MediaKeySession(scoped_ptr<media::DrmSystem::Session> drm_system_session,
+ script::ScriptValueFactory* script_value_factory,
+ const ClosedCallback& closed_callback);
+
+ // Web IDL: MediaKeySession.
+ std::string session_id() const;
+ const VoidPromiseValue* closed() const;
+ const EventListenerScriptValue* onmessage() const;
+ void set_onmessage(const EventListenerScriptValue& event_listener);
+ scoped_ptr<VoidPromiseValue> GenerateRequest(
+ const std::string& init_data_type, const BufferSource& init_data);
+ scoped_ptr<VoidPromiseValue> Update(const BufferSource& response);
+ scoped_ptr<VoidPromiseValue> Close();
+
+ DEFINE_WRAPPABLE_TYPE(MediaKeySession);
+
+ private:
+ ~MediaKeySession() OVERRIDE;
+
+ void OnSessionUpdateRequestGenerated(
+ VoidPromiseValue::Reference* promise_reference,
+ scoped_array<uint8> message, int message_size);
+ void OnSessionUpdateRequestDidNotGenerate(
+ VoidPromiseValue::Reference* promise_reference);
+ void OnSessionUpdated(VoidPromiseValue::Reference* promise_reference);
+ void OnSessionDidNotUpdate(VoidPromiseValue::Reference* promise_reference);
+ void OnClosed();
+
+ scoped_ptr<media::DrmSystem::Session> drm_system_session_;
+ script::ScriptValueFactory* const script_value_factory_;
+ bool uninitialized_;
+ bool callable_;
+
+ // TODO: Remove |closed_callback_| and change call sites to use closed()
+ // promise instead, once Cobalt switches to native SpiderMonkey
+ // promises.
+ const ClosedCallback closed_callback_;
+ const VoidPromiseValue::Reference closed_promise_reference_;
+
+ bool initiated_by_generate_request_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaKeySession);
+};
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_EME_MEDIA_KEY_SESSION_H_
diff --git a/src/cobalt/dom/eme/media_key_session.idl b/src/cobalt/dom/eme/media_key_session.idl
new file mode 100644
index 0000000..c458e27
--- /dev/null
+++ b/src/cobalt/dom/eme/media_key_session.idl
@@ -0,0 +1,35 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// https://www.w3.org/TR/encrypted-media/#mediakeysession-interface
+
+interface MediaKeySession : EventTarget {
+ readonly attribute DOMString sessionId;
+ // TODO: Implement |expiration|.
+ // readonly attribute unrestricted double expiration;
+ readonly attribute Promise<void> closed;
+ // TODO: Implement |keyStatuses|.
+ // readonly attribute MediaKeyStatusMap keyStatuses;
+ // TODO: Implement |onkeystatuseschange|.
+ // attribute EventHandler onkeystatuseschange;
+ attribute EventHandler onmessage;
+ Promise<void> generateRequest(DOMString initDataType,
+ BufferSource initData);
+ // TODO: Trivially implement persistent sessions.
+ // Promise<boolean> load(DOMString sessionId);
+ Promise<void> update(BufferSource response);
+ Promise<void> close();
+ // TODO: Implement |remove|.
+ // Promise<void> remove();
+};
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/cobalt/dom/eme/media_key_session_type.idl
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/cobalt/dom/eme/media_key_session_type.idl
index 51e1f2e..eb82c35 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/cobalt/dom/eme/media_key_session_type.idl
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+// https://www.w3.org/TR/encrypted-media/#idl-def-mediakeysessiontype
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
+enum MediaKeySessionType {
+ "temporary",
+ // TODO: Trivially implement persistent sessions.
+ // "persistent-license"
};
diff --git a/src/cobalt/dom/eme/media_key_system_access.cc b/src/cobalt/dom/eme/media_key_system_access.cc
new file mode 100644
index 0000000..14c8f2c
--- /dev/null
+++ b/src/cobalt/dom/eme/media_key_system_access.cc
@@ -0,0 +1,53 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/dom/eme/media_key_system_access.h"
+
+#include "cobalt/dom/eme/media_keys.h"
+#include "cobalt/script/script_value_factory.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+MediaKeySystemAccess::MediaKeySystemAccess(
+ const std::string& key_system,
+ const MediaKeySystemConfiguration& configuration,
+ script::ScriptValueFactory* script_value_factory)
+ : key_system_(key_system),
+ configuration_(configuration),
+ script_value_factory_(script_value_factory) {}
+
+// See
+// https://www.w3.org/TR/encrypted-media/#dom-mediakeysystemaccess-createmediakeys.
+scoped_ptr<MediaKeySystemAccess::InterfacePromiseValue>
+MediaKeySystemAccess::CreateMediaKeys() const {
+ // 1. Let promise be a new promise.
+ scoped_ptr<InterfacePromiseValue> promise =
+ script_value_factory_
+ ->CreateInterfacePromise<scoped_refptr<MediaKeys> >();
+ InterfacePromiseValue::StrongReference promise_reference(*promise);
+
+ // 2.10. Let media keys be a new MediaKeys object.
+ scoped_refptr<MediaKeys> media_keys(
+ new MediaKeys(key_system_, script_value_factory_));
+
+ // 2.11. Resolve promise with media keys.
+ promise_reference.value().Resolve(media_keys);
+ return promise.Pass();
+}
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
diff --git a/src/cobalt/dom/eme/media_key_system_access.h b/src/cobalt/dom/eme/media_key_system_access.h
new file mode 100644
index 0000000..4bf3fb2
--- /dev/null
+++ b/src/cobalt/dom/eme/media_key_system_access.h
@@ -0,0 +1,64 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_DOM_EME_MEDIA_KEY_SYSTEM_ACCESS_H_
+#define COBALT_DOM_EME_MEDIA_KEY_SYSTEM_ACCESS_H_
+
+#include <string>
+
+#include "cobalt/dom/eme/media_key_system_configuration.h"
+#include "cobalt/script/promise.h"
+#include "cobalt/script/script_value_factory.h"
+#include "cobalt/script/wrappable.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+// Provides access to a key system.
+// https://www.w3.org/TR/encrypted-media/#mediakeysystemaccess-interface
+class MediaKeySystemAccess : public script::Wrappable {
+ public:
+ typedef script::ScriptValue<script::Promise<
+ scoped_refptr<script::Wrappable> > > InterfacePromiseValue;
+
+ // Custom, not in any spec.
+ MediaKeySystemAccess(const std::string& key_system,
+ const MediaKeySystemConfiguration& configuration,
+ script::ScriptValueFactory* script_value_factory);
+
+ // Web API: MediaKeySystemAccess.
+ const std::string& key_system() const { return key_system_; }
+ const MediaKeySystemConfiguration& GetConfiguration() const {
+ return configuration_;
+ }
+ scoped_ptr<InterfacePromiseValue> CreateMediaKeys() const;
+
+ DEFINE_WRAPPABLE_TYPE(MediaKeySystemAccess);
+
+ private:
+ ~MediaKeySystemAccess() OVERRIDE {}
+
+ const std::string key_system_;
+ const MediaKeySystemConfiguration configuration_;
+ script::ScriptValueFactory* script_value_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaKeySystemAccess);
+};
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_EME_MEDIA_KEY_SYSTEM_ACCESS_H_
diff --git a/src/cobalt/dom/media_key_system_access.idl b/src/cobalt/dom/eme/media_key_system_access.idl
similarity index 82%
rename from src/cobalt/dom/media_key_system_access.idl
rename to src/cobalt/dom/eme/media_key_system_access.idl
index 15f7210..c8d99d2 100644
--- a/src/cobalt/dom/media_key_system_access.idl
+++ b/src/cobalt/dom/eme/media_key_system_access.idl
@@ -12,13 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemaccess-interface
-
-enum MediaKeysRequirement {
- "required",
- "optional",
- "not-allowed"
-};
+// https://www.w3.org/TR/encrypted-media/#mediakeysystemaccess-interface
interface MediaKeySystemAccess {
readonly attribute DOMString keySystem;
diff --git a/src/cobalt/dom/eme/media_key_system_configuration.idl b/src/cobalt/dom/eme/media_key_system_configuration.idl
new file mode 100644
index 0000000..5c53286
--- /dev/null
+++ b/src/cobalt/dom/eme/media_key_system_configuration.idl
@@ -0,0 +1,28 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// https://www.w3.org/TR/encrypted-media/#mediakeysystemconfiguration-dictionary
+
+// TODO: Implement default values for sequence types.
+dictionary MediaKeySystemConfiguration {
+ DOMString label = "";
+ sequence<DOMString> initDataTypes /*= []*/;
+ sequence<MediaKeySystemMediaCapability> audioCapabilities /*= []*/;
+ sequence<MediaKeySystemMediaCapability> videoCapabilities /*= []*/;
+ // TODO: Implement distinctive identifiers.
+ // MediaKeysRequirement distinctiveIdentifier = "optional";
+ // TODO: Trivially implement persistent sessions.
+ // MediaKeysRequirement persistentState = "optional";
+ // sequence<DOMString> sessionTypes;
+};
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/cobalt/dom/eme/media_key_system_media_capability.idl
similarity index 73%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/cobalt/dom/eme/media_key_system_media_capability.idl
index 51e1f2e..f78210f 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/cobalt/dom/eme/media_key_system_media_capability.idl
@@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+// https://www.w3.org/TR/encrypted-media/#mediakeysystemmediacapability-dictionary
dictionary MediaKeySystemMediaCapability {
DOMString contentType = "";
- DOMString robustness = "";
+ // TODO: Implement robustness as per
+ // https://www.w3.org/TR/encrypted-media/#dom-mediakeysystemmediacapability-robustness.
+ // DOMString robustness = "";
};
diff --git a/src/cobalt/dom/eme/media_keys.cc b/src/cobalt/dom/eme/media_keys.cc
new file mode 100644
index 0000000..861d44d
--- /dev/null
+++ b/src/cobalt/dom/eme/media_keys.cc
@@ -0,0 +1,60 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/dom/eme/media_keys.h"
+
+#include "base/bind.h"
+#include "cobalt/dom/dom_exception.h"
+#include "cobalt/dom/eme/media_key_session.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+MediaKeys::MediaKeys(const std::string& key_system,
+ script::ScriptValueFactory* script_value_factory)
+ : script_value_factory_(script_value_factory),
+ drm_system_(new media::DrmSystem(key_system.c_str())) {}
+
+// See https://www.w3.org/TR/encrypted-media/#dom-mediakeys-createsession.
+scoped_refptr<MediaKeySession> MediaKeys::CreateSession(
+ MediaKeySessionType session_type, script::ExceptionState* exception_state) {
+ // 1. If this object's supported session types value does not contain
+ // sessionType, throw a NotSupportedError.
+ if (session_type != kMediaKeySessionTypeTemporary) {
+ DOMException::Raise(DOMException::kNotSupportedErr, exception_state);
+ return NULL;
+ }
+
+ // 3. Let session be a new MediaKeySession object.
+ scoped_refptr<MediaKeySession> session(new MediaKeySession(
+ drm_system_->CreateSession(), script_value_factory_,
+ base::Bind(&MediaKeys::OnSessionClosed, base::Unretained(this))));
+ open_sessions_.push_back(session);
+ return session;
+}
+
+void MediaKeys::OnSessionClosed(MediaKeySession* session) {
+ // Erase-remove idiom, see
+ // https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom.
+ open_sessions_.erase(
+ std::remove(open_sessions_.begin(), open_sessions_.end(), session),
+ open_sessions_.end());
+}
+
+MediaKeys::~MediaKeys() {}
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
diff --git a/src/cobalt/dom/eme/media_keys.h b/src/cobalt/dom/eme/media_keys.h
new file mode 100644
index 0000000..52013df
--- /dev/null
+++ b/src/cobalt/dom/eme/media_keys.h
@@ -0,0 +1,77 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_DOM_EME_MEDIA_KEYS_H_
+#define COBALT_DOM_EME_MEDIA_KEYS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cobalt/dom/buffer_source.h"
+#include "cobalt/dom/eme/media_key_session.h"
+#include "cobalt/dom/eme/media_key_session_type.h"
+#include "cobalt/media/base/drm_system.h"
+#include "cobalt/script/script_value_factory.h"
+#include "cobalt/script/wrappable.h"
+
+namespace cobalt {
+namespace dom {
+namespace eme {
+
+// Represents a set of keys that an associated HTMLMediaElement can use
+// for decryption of media data during playback.
+// https://www.w3.org/TR/encrypted-media/#mediakeys-interface
+class MediaKeys : public script::Wrappable {
+ public:
+ // Custom, not in any spec.
+
+ MediaKeys(const std::string& key_system,
+ script::ScriptValueFactory* script_value_factory);
+
+ media::DrmSystem* drm_system() const { return drm_system_.get(); }
+
+ // Web API: MediaKeys.
+
+ scoped_refptr<MediaKeySession> CreateSession(
+ MediaKeySessionType session_type,
+ script::ExceptionState* exception_state);
+
+ DEFINE_WRAPPABLE_TYPE(MediaKeys);
+
+ private:
+ ~MediaKeys() OVERRIDE;
+
+ void OnSessionClosed(MediaKeySession* session);
+
+ script::ScriptValueFactory* script_value_factory_;
+ scoped_ptr<media::DrmSystem> drm_system_;
+
+ // A MediaKeySession object shall not be destroyed and shall continue
+ // to receive events if it is not closed and the MediaKeys object that created
+ // it remains accessible.
+ // https://www.w3.org/TR/encrypted-media/#mediakeysession-interface
+ //
+ // Number of sessions is expected to be very small, typically one.
+ std::vector<scoped_refptr<MediaKeySession> > open_sessions_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaKeys);
+};
+
+} // namespace eme
+} // namespace dom
+} // namespace cobalt
+
+#endif // COBALT_DOM_EME_MEDIA_KEYS_H_
diff --git a/src/cobalt/dom/media_keys.idl b/src/cobalt/dom/eme/media_keys.idl
similarity index 65%
rename from src/cobalt/dom/media_keys.idl
rename to src/cobalt/dom/eme/media_keys.idl
index 4c4aa1b..fc1a35f 100644
--- a/src/cobalt/dom/media_keys.idl
+++ b/src/cobalt/dom/eme/media_keys.idl
@@ -12,15 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeys-interface
-
-enum MediaKeySessionType {
- "temporary",
- "persistent-usage-record",
- "persistent-license"
-};
+// https://www.w3.org/TR/encrypted-media/#mediakeys-interface
interface MediaKeys {
- MediaKeySession createSession(optional MediaKeySessionType sessionType = "temporary");
- Promise<boolean> setServerCertificate(BufferSource serverCertificate);
+ [RaisesException] MediaKeySession createSession(
+ optional MediaKeySessionType sessionType = "temporary");
+ // TODO: Trivially implement server certificates.
+ // Promise<boolean> setServerCertificate(BufferSource serverCertificate);
};
diff --git a/src/cobalt/dom/media_keys_requirement.idl b/src/cobalt/dom/eme/media_keys_requirement.idl
similarity index 100%
rename from src/cobalt/dom/media_keys_requirement.idl
rename to src/cobalt/dom/eme/media_keys_requirement.idl
diff --git a/src/cobalt/dom/navigator_eme.idl b/src/cobalt/dom/eme/navigator.idl
similarity index 69%
rename from src/cobalt/dom/navigator_eme.idl
rename to src/cobalt/dom/eme/navigator.idl
index f0219ad..1abf852 100644
--- a/src/cobalt/dom/navigator_eme.idl
+++ b/src/cobalt/dom/eme/navigator.idl
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#navigator-extension-requestmediakeysystemaccess
+// https://www.w3.org/TR/encrypted-media/#navigator-extension-requestmediakeysystemaccess
partial interface Navigator {
- Promise<MediaKeySystemAccess> requestMediaKeySystemAccess(
- DOMString keySystem,
- sequence<MediaKeySystemConfiguration> supportedConfigurations);
+ Promise<MediaKeySystemAccess> requestMediaKeySystemAccess(
+ DOMString keySystem,
+ sequence<MediaKeySystemConfiguration> supportedConfigurations);
};
diff --git a/src/cobalt/dom/font_cache.cc b/src/cobalt/dom/font_cache.cc
index 28da2c0..4fff414 100644
--- a/src/cobalt/dom/font_cache.cc
+++ b/src/cobalt/dom/font_cache.cc
@@ -90,6 +90,17 @@
}
}
+void FontCache::PurgeCachedResources() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ font_face_map_->clear();
+ font_list_map_.clear();
+ inactive_font_set_.clear();
+ font_map_.clear();
+ character_fallback_typeface_maps_.clear();
+ requested_remote_typeface_cache_.clear();
+ local_typeface_map_.clear();
+}
+
void FontCache::ProcessInactiveFontListsAndFonts() {
DCHECK(thread_checker_.CalledOnValidThread());
base::TimeTicks current_time = base::TimeTicks::Now();
diff --git a/src/cobalt/dom/font_cache.h b/src/cobalt/dom/font_cache.h
index 3d05696..e90adf9 100644
--- a/src/cobalt/dom/font_cache.h
+++ b/src/cobalt/dom/font_cache.h
@@ -181,6 +181,9 @@
// the map.
void SetFontFaceMap(scoped_ptr<FontFaceMap> font_face_map);
+ // Purge all caches within the font cache.
+ void PurgeCachedResources();
+
// Process unused font lists and fonts, potentially purging them from the
// cache if they meet the removal requirements.
void ProcessInactiveFontListsAndFonts();
diff --git a/src/cobalt/dom/html_element_context.cc b/src/cobalt/dom/html_element_context.cc
index b7aeed0..064403a 100644
--- a/src/cobalt/dom/html_element_context.cc
+++ b/src/cobalt/dom/html_element_context.cc
@@ -35,6 +35,7 @@
remote_typeface_cache_(NULL),
mesh_cache_(NULL),
dom_stat_tracker_(NULL),
+ video_playback_rate_multiplier_(1.f),
sync_load_thread_("Synchronous Load"),
html_element_factory_(new HTMLElementFactory()) {
sync_load_thread_.Start();
@@ -54,7 +55,7 @@
reduced_image_cache_capacity_manager,
loader::font::RemoteTypefaceCache* remote_typeface_cache,
loader::mesh::MeshCache* mesh_cache, DomStatTracker* dom_stat_tracker,
- const std::string& language)
+ const std::string& language, float video_playback_rate_multiplier)
: fetcher_factory_(fetcher_factory),
css_parser_(css_parser),
dom_parser_(dom_parser),
@@ -72,6 +73,7 @@
mesh_cache_(mesh_cache),
dom_stat_tracker_(dom_stat_tracker),
language_(language),
+ video_playback_rate_multiplier_(video_playback_rate_multiplier),
sync_load_thread_("Synchronous Load"),
html_element_factory_(new HTMLElementFactory()) {
sync_load_thread_.Start();
diff --git a/src/cobalt/dom/html_element_context.h b/src/cobalt/dom/html_element_context.h
index cae6ad8..2eb952f 100644
--- a/src/cobalt/dom/html_element_context.h
+++ b/src/cobalt/dom/html_element_context.h
@@ -61,7 +61,7 @@
reduced_image_cache_capacity_manager,
loader::font::RemoteTypefaceCache* remote_typeface_cache,
loader::mesh::MeshCache* mesh_cache, DomStatTracker* dom_stat_tracker,
- const std::string& language);
+ const std::string& language, float video_playback_rate_multiplier = 1.0);
~HTMLElementContext();
loader::FetcherFactory* fetcher_factory() { return fetcher_factory_; }
@@ -107,6 +107,10 @@
const std::string& language() const { return language_; }
+ float video_playback_rate_multiplier() const {
+ return video_playback_rate_multiplier_;
+ }
+
base::Thread* sync_load_thread() { return &sync_load_thread_; }
HTMLElementFactory* html_element_factory() {
@@ -136,6 +140,7 @@
loader::mesh::MeshCache* const mesh_cache_;
DomStatTracker* const dom_stat_tracker_;
const std::string language_;
+ const float video_playback_rate_multiplier_;
base::Thread sync_load_thread_;
scoped_ptr<HTMLElementFactory> html_element_factory_;
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc
index 5e98f55..869d4c2 100644
--- a/src/cobalt/dom/html_media_element.cc
+++ b/src/cobalt/dom/html_media_element.cc
@@ -33,19 +33,23 @@
#include "cobalt/dom/event.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/html_video_element.h"
-#include "cobalt/dom/media_key_complete_event.h"
-#include "cobalt/dom/media_key_error_event.h"
-#include "cobalt/dom/media_key_message_event.h"
-#include "cobalt/dom/media_key_needed_event.h"
#include "cobalt/dom/media_source.h"
#include "cobalt/dom/media_source_ready_state.h"
#include "cobalt/loader/fetcher_factory.h"
#include "cobalt/media/fetcher_buffered_data_source.h"
#include "cobalt/media/web_media_player_factory.h"
+#include "cobalt/script/script_value_factory.h"
+#include "starboard/double.h"
#if defined(COBALT_MEDIA_SOURCE_2016)
+#include "cobalt/dom/eme/media_encrypted_event.h"
+#include "cobalt/dom/eme/media_encrypted_event_init.h"
#include "cobalt/media/base/media_log.h"
#else // defined(COBALT_MEDIA_SOURCE_2016)
+#include "cobalt/dom/media_key_complete_event.h"
+#include "cobalt/dom/media_key_error_event.h"
+#include "cobalt/dom/media_key_message_event.h"
+#include "cobalt/dom/media_key_needed_event.h"
#include "media/base/filter_collection.h"
#include "media/base/media_log.h"
#endif // defined(COBALT_MEDIA_SOURCE_2016)
@@ -80,23 +84,6 @@
#endif // LOG_MEDIA_ELEMENT_ACTIVITIES
-void RaiseMediaKeyException(WebMediaPlayer::MediaKeyException exception,
- script::ExceptionState* exception_state) {
- DCHECK_NE(exception, WebMediaPlayer::kMediaKeyExceptionNoError);
- switch (exception) {
- case WebMediaPlayer::kMediaKeyExceptionInvalidPlayerState:
- DOMException::Raise(DOMException::kInvalidStateErr, exception_state);
- break;
- case WebMediaPlayer::kMediaKeyExceptionKeySystemNotSupported:
- DOMException::Raise(DOMException::kNotSupportedErr, exception_state);
- break;
- case WebMediaPlayer::kMediaKeyExceptionNoError:
- default:
- NOTREACHED();
- break;
- }
-}
-
// This struct manages the user log information for HTMLMediaElement count.
struct HTMLMediaElementCountLog {
HTMLMediaElementCountLog() : count(0) {
@@ -122,7 +109,7 @@
: HTMLElement(document, tag_name),
load_state_(kWaitingForSource),
ALLOW_THIS_IN_INITIALIZER_LIST(event_queue_(this)),
- playback_rate_(1.0f),
+ playback_rate_(1.f),
default_playback_rate_(1.0f),
network_state_(kNetworkEmpty),
ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
@@ -228,6 +215,90 @@
return result;
}
+#if defined(COBALT_MEDIA_SOURCE_2016)
+
+const EventTarget::EventListenerScriptValue* HTMLMediaElement::onencrypted()
+ const {
+ return GetAttributeEventListener(base::Tokens::encrypted());
+}
+
+void HTMLMediaElement::set_onencrypted(
+ const EventListenerScriptValue& event_listener) {
+ SetAttributeEventListener(base::Tokens::encrypted(), event_listener);
+}
+
+// See https://www.w3.org/TR/encrypted-media/#dom-htmlmediaelement-setmediakeys.
+scoped_ptr<HTMLMediaElement::VoidPromiseValue> HTMLMediaElement::SetMediaKeys(
+ const scoped_refptr<eme::MediaKeys>& media_keys) {
+ scoped_ptr<VoidPromiseValue> promise = node_document()
+ ->html_element_context()
+ ->script_value_factory()
+ ->CreateBasicPromise<void>();
+ VoidPromiseValue::StrongReference promise_reference(*promise);
+
+ // 1. If mediaKeys and the mediaKeys attribute are the same object, return
+ // a resolved promise.
+ if (media_keys_ == media_keys) {
+ promise_reference.value().Resolve();
+ return promise.Pass();
+ }
+
+ // 5.2. If the mediaKeys attribute is not null:
+ if (media_keys_) {
+ // 5.2.3. Stop using the CDM instance represented by the mediaKeys attribute
+ // to decrypt media data and remove the association with the media
+ // element.
+ //
+ // Since Starboard doesn't allow to detach SbDrmSystem from SbPlayer,
+ // re-create the entire player.
+ if (player_) {
+ ClearMediaPlayer();
+ CreateMediaPlayer();
+ }
+ }
+
+ // 5.3. If mediaKeys is not null:
+ if (media_keys) {
+ // 5.3.1. Associate the CDM instance represented by mediaKeys with
+ // the media element for decrypting media data.
+ if (player_) {
+ player_->SetDrmSystem(media_keys->drm_system());
+ }
+ }
+
+ // 5.4. Set the mediaKeys attribute to mediaKeys.
+ media_keys_ = media_keys;
+
+ // 5.6. Resolve promise.
+ promise_reference.value().Resolve();
+
+ // 6. Return promise.
+ return promise.Pass();
+}
+
+#else // defined(COBALT_MEDIA_SOURCE_2016)
+
+namespace {
+
+void RaiseMediaKeyException(WebMediaPlayer::MediaKeyException exception,
+ script::ExceptionState* exception_state) {
+ DCHECK_NE(exception, WebMediaPlayer::kMediaKeyExceptionNoError);
+ switch (exception) {
+ case WebMediaPlayer::kMediaKeyExceptionInvalidPlayerState:
+ DOMException::Raise(DOMException::kInvalidStateErr, exception_state);
+ break;
+ case WebMediaPlayer::kMediaKeyExceptionKeySystemNotSupported:
+ DOMException::Raise(DOMException::kNotSupportedErr, exception_state);
+ break;
+ case WebMediaPlayer::kMediaKeyExceptionNoError:
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+} // namespace
+
void HTMLMediaElement::GenerateKeyRequest(
const std::string& key_system,
const base::optional<scoped_refptr<Uint8Array> >& init_data,
@@ -339,6 +410,8 @@
}
}
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
+
uint16_t HTMLMediaElement::ready_state() const {
MLOG() << ready_state_;
return static_cast<uint16_t>(ready_state_);
@@ -420,13 +493,15 @@
void HTMLMediaElement::set_playback_rate(float rate) {
MLOG() << rate;
+
if (playback_rate_ != rate) {
playback_rate_ = rate;
ScheduleOwnEvent(base::Tokens::ratechange());
}
if (player_ && PotentiallyPlaying()) {
- player_->SetRate(rate);
+ player_->SetRate(rate *
+ html_element_context()->video_playback_rate_multiplier());
}
}
@@ -647,15 +722,18 @@
}
}
- player_.reset();
player_ =
html_element_context()->web_media_player_factory()->CreateWebMediaPlayer(
this);
-#if !defined(COBALT_MEDIA_SOURCE_2016)
+#if defined(COBALT_MEDIA_SOURCE_2016)
+ if (media_keys_) {
+ player_->SetDrmSystem(media_keys_->drm_system());
+ }
+#else // defined(COBALT_MEDIA_SOURCE_2016)
if (media_source_) {
media_source_->SetPlayer(player_.get());
}
-#endif // !defined(COBALT_MEDIA_SOURCE_2016)
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
node_document()->OnDOMMutation();
InvalidateLayoutBoxesOfNodeAndAncestors();
}
@@ -1293,7 +1371,9 @@
// Set rate, muted before calling play in case they were set before the
// media engine was setup. The media engine should just stash the rate and
// muted values since it isn't already playing.
- player_->SetRate(playback_rate_);
+ player_->SetRate(
+ playback_rate_ *
+ html_element_context()->video_playback_rate_multiplier());
player_->SetVolume(muted_ ? 0 : volume_);
player_->Play();
@@ -1332,7 +1412,7 @@
bool HTMLMediaElement::EndedPlayback() const {
float dur = duration();
- if (!player_ || isnan(dur)) {
+ if (!player_ || SbDoubleIsNan(dur)) {
return false;
}
@@ -1450,7 +1530,8 @@
// When the current playback position reaches the end of the media resource
// when the direction of playback is forwards, then the user agent must follow
// these steps:
- if (!isnan(dur) && (0.0f != dur) && now >= dur && playback_rate_ > 0) {
+ if (!SbDoubleIsNan(dur) && (0.0f != dur) && now >= dur &&
+ playback_rate_ > 0) {
// If the media element has a loop attribute specified and does not have a
// current media controller,
if (loop()) {
@@ -1547,13 +1628,50 @@
}
#if defined(COBALT_MEDIA_SOURCE_2016)
-void HTMLMediaElement::EncryptedMediaInitData(
- media::EmeInitDataType /*init_data_type*/,
- const unsigned char* /*init_data*/, unsigned int /*init_data_length*/) {
- // TODO: Implement as per EME 2017.
- NOTIMPLEMENTED();
+
+namespace {
+
+// Initialization data types are defined in
+// https://www.w3.org/TR/eme-initdata-registry/#registry.
+std::string ToInitDataTypeString(media::EmeInitDataType init_data_type) {
+ switch (init_data_type) {
+ case media::kEmeInitDataTypeWebM:
+ return "webm";
+ case media::kEmeInitDataTypeCenc:
+ return "cenc";
+ case media::kEmeInitDataTypeKeyIds:
+ return "keyids";
+ default:
+ LOG(WARNING) << "Unknown EME initialization data type.";
+ return "";
+ }
}
-#endif // defined(COBALT_MEDIA_SOURCE_2016)
+
+} // namespace
+
+// See https://www.w3.org/TR/encrypted-media/#initdata-encountered.
+void HTMLMediaElement::EncryptedMediaInitDataEncountered(
+ media::EmeInitDataType init_data_type, const unsigned char* init_data,
+ unsigned int init_data_length) {
+ // TODO: Implement "4. If the media data is CORS-same-origin and not mixed
+ // content".
+
+ // 5. Queue a task to create an event named encrypted that does not bubble
+ // and is not cancellable using the MediaEncryptedEvent interface [...],
+ // and dispatch it at the media element.
+ //
+ // TODO: Implement Event.isTrusted as per
+ // https://www.w3.org/TR/dom/#dom-event-istrusted and set it to true.
+ eme::MediaEncryptedEventInit media_encrypted_event_init;
+ media_encrypted_event_init.set_init_data_type(
+ ToInitDataTypeString(init_data_type));
+ media_encrypted_event_init.set_init_data(
+ new ArrayBuffer(NULL, init_data, init_data_length));
+ event_queue_.Enqueue(
+ new eme::MediaEncryptedEvent("encrypted", media_encrypted_event_init));
+}
+
+#else // defined(COBALT_MEDIA_SOURCE_2016)
void HTMLMediaElement::KeyAdded(const std::string& key_system,
const std::string& session_id) {
@@ -1616,6 +1734,8 @@
new Uint8Array(NULL, init_data, init_data_length, NULL)));
}
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
+
void HTMLMediaElement::ClearMediaSource() {
#if defined(COBALT_MEDIA_SOURCE_2016)
if (media_source_) {
diff --git a/src/cobalt/dom/html_media_element.h b/src/cobalt/dom/html_media_element.h
index 73b7a8e..154d73c 100644
--- a/src/cobalt/dom/html_media_element.h
+++ b/src/cobalt/dom/html_media_element.h
@@ -31,6 +31,7 @@
#include "cobalt/script/exception_state.h"
#include "googleurl/src/gurl.h"
#if defined(COBALT_MEDIA_SOURCE_2016)
+#include "cobalt/dom/eme/media_keys.h"
#include "cobalt/media/player/web_media_player.h"
#else // defined(COBALT_MEDIA_SOURCE_2016)
#include "cobalt/dom/media_source.h"
@@ -49,12 +50,10 @@
#else // defined(COBALT_MEDIA_SOURCE_2016)
typedef ::media::WebMediaPlayer WebMediaPlayer;
typedef ::media::WebMediaPlayerClient WebMediaPlayerClient;
-#endif // defined(WebMediaPlayerDelegate)
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
// The HTMLMediaElement is the base of HTMLAudioElement and HTMLVideoElement.
// https://www.w3.org/TR/html5/embedded-content-0.html#media-element
-// It also implements methods defined in Encrypted Media Extensions.
-// https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1b/encrypted-media/encrypted-media.html
class HTMLMediaElement : public HTMLElement, private WebMediaPlayerClient {
public:
HTMLMediaElement(Document* document, base::Token tag_name);
@@ -83,6 +82,18 @@
std::string CanPlayType(const std::string& mimeType);
std::string CanPlayType(const std::string& mimeType,
const std::string& key_system);
+
+#if defined(COBALT_MEDIA_SOURCE_2016)
+ const EventListenerScriptValue* onencrypted() const;
+ void set_onencrypted(const EventListenerScriptValue& event_listener);
+
+ const scoped_refptr<eme::MediaKeys>& media_keys() const {
+ return media_keys_;
+ }
+ typedef script::ScriptValue<script::Promise<void> > VoidPromiseValue;
+ scoped_ptr<VoidPromiseValue> SetMediaKeys(
+ const scoped_refptr<eme::MediaKeys>& media_keys);
+#else // defined(COBALT_MEDIA_SOURCE_2016)
void GenerateKeyRequest(
const std::string& key_system,
const base::optional<scoped_refptr<Uint8Array> >& init_data,
@@ -95,6 +106,7 @@
void CancelKeyRequest(const std::string& key_system,
const base::optional<std::string>& session_id,
script::ExceptionState* exception_state);
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
// Ready state
enum ReadyState {
@@ -232,10 +244,10 @@
std::string SourceURL() const OVERRIDE;
bool PreferDecodeToTexture() const OVERRIDE;
#if defined(COBALT_MEDIA_SOURCE_2016)
- void EncryptedMediaInitData(media::EmeInitDataType init_data_type,
- const unsigned char* init_data,
- unsigned int init_data_length) OVERRIDE;
-#endif // defined(COBALT_MEDIA_SOURCE_2016)
+ void EncryptedMediaInitDataEncountered(
+ media::EmeInitDataType init_data_type, const unsigned char* init_data,
+ unsigned int init_data_length) OVERRIDE;
+#else // defined(COBALT_MEDIA_SOURCE_2016)
void KeyAdded(const std::string& key_system,
const std::string& session_id) OVERRIDE;
void KeyError(const std::string& key_system, const std::string& session_id,
@@ -246,6 +258,7 @@
void KeyNeeded(const std::string& key_system, const std::string& session_id,
const unsigned char* init_data,
unsigned int init_data_length) OVERRIDE;
+#endif // !defined(COBALT_MEDIA_SOURCE_2016)
void ClearMediaSource();
#if !defined(COBALT_MEDIA_SOURCE_2016)
void SetSourceState(MediaSourceReadyState ready_state);
@@ -312,6 +325,10 @@
base::optional<loader::image::ReducedCacheCapacityManager::Request>
reduced_image_cache_capacity_request_;
+#if defined(COBALT_MEDIA_SOURCE_2016)
+ scoped_refptr<eme::MediaKeys> media_keys_;
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
+
DISALLOW_COPY_AND_ASSIGN(HTMLMediaElement);
};
diff --git a/src/cobalt/dom/html_media_element.idl b/src/cobalt/dom/html_media_element.idl
index 425ae67..a4b7c04 100644
--- a/src/cobalt/dom/html_media_element.idl
+++ b/src/cobalt/dom/html_media_element.idl
@@ -59,12 +59,4 @@
attribute boolean controls;
[RaisesException] attribute double volume;
attribute boolean muted;
-
- // Encrypted Media Extensions methods
- [RaisesException] void generateKeyRequest(DOMString keySystem,
- Uint8Array? initData);
- [RaisesException] void addKey(DOMString keySystem, Uint8Array key,
- Uint8Array? initData, DOMString? sessionId);
- [RaisesException] void cancelKeyRequest(DOMString keySystem,
- DOMString? sessionId);
};
diff --git a/src/cobalt/dom/html_media_element_eme_01b.idl b/src/cobalt/dom/html_media_element_eme_01b.idl
new file mode 100644
index 0000000..0112a8e
--- /dev/null
+++ b/src/cobalt/dom/html_media_element_eme_01b.idl
@@ -0,0 +1,24 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1b/encrypted-media/encrypted-media.html#extensions
+
+partial interface HTMLMediaElement {
+ [RaisesException] void generateKeyRequest(DOMString keySystem,
+ Uint8Array? initData);
+ [RaisesException] void addKey(DOMString keySystem, Uint8Array key,
+ Uint8Array? initData, DOMString? sessionId);
+ [RaisesException] void cancelKeyRequest(DOMString keySystem,
+ DOMString? sessionId);
+};
diff --git a/src/cobalt/dom/media_key_message_event.idl b/src/cobalt/dom/media_key_message_event.idl
index 2b06c5f..c7738d3 100644
--- a/src/cobalt/dom/media_key_message_event.idl
+++ b/src/cobalt/dom/media_key_message_event.idl
@@ -12,20 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-/*
-enum MediaKeyMessageType {
- "license-request",
- "license-renewal",
- "license-release",
- "individualization-request"
-};
-
-[Constructor (DOMString type, optional MediaKeyMessageEventInit eventInitDict)]
-interface MediaKeyMessageEvent : Event {
- readonly attribute MediaKeyMessageType messageType;
- readonly attribute ArrayBuffer message;
-};
-*/
+// https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1b/encrypted-media/encrypted-media.html#dom-mediakeymessageevent
interface MediaKeyMessageEvent : Event {
readonly attribute DOMString keySystem;
diff --git a/src/cobalt/dom/media_key_needed_event.idl b/src/cobalt/dom/media_key_needed_event.idl
index c69f2c7..d9eda1e 100644
--- a/src/cobalt/dom/media_key_needed_event.idl
+++ b/src/cobalt/dom/media_key_needed_event.idl
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1b/encrypted-media/encrypted-media.html#dom-mediakeyneededevent
+
interface MediaKeyNeededEvent : Event {
readonly attribute DOMString keySystem;
readonly attribute DOMString sessionId;
diff --git a/src/cobalt/dom/media_key_session.idl b/src/cobalt/dom/media_key_session.idl
deleted file mode 100644
index 90b6344..0000000
--- a/src/cobalt/dom/media_key_session.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysession-interface
-
-interface MediaKeySession : EventTarget {
- readonly attribute DOMString sessionId;
- readonly attribute unrestricted double expiration;
- readonly attribute Promise<void> closed;
- readonly attribute MediaKeyStatusMap keyStatuses;
- attribute EventHandler onkeystatuseschange;
- attribute EventHandler onmessage;
- Promise<void> generateRequest(DOMString initDataType, BufferSource initData);
- Promise<boolean> load(DOMString sessionId);
- Promise<void> update(BufferSource response);
- Promise<void> close();
- Promise<void> remove();
-};
diff --git a/src/cobalt/dom/media_key_status.idl b/src/cobalt/dom/media_key_status.idl
deleted file mode 100644
index 583215a..0000000
--- a/src/cobalt/dom/media_key_status.idl
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeystatusmap-interface
-
-enum MediaKeyStatus {
- "usable",
- "expired",
- "released",
- "output-restricted",
- "output-downscaled",
- "status-pending",
- "internal-error"
-};
diff --git a/src/cobalt/dom/media_key_status_map.h b/src/cobalt/dom/media_key_status_map.h
deleted file mode 100644
index 414b0f6..0000000
--- a/src/cobalt/dom/media_key_status_map.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef COBALT_DOM_MEDIA_KEY_STATUS_MAP_H_
-#define COBALT_DOM_MEDIA_KEY_STATUS_MAP_H_
-
-#include "base/basictypes.h"
-#include "cobalt/dom/array_buffer.h"
-#include "cobalt/dom/array_buffer_view.h"
-#include "cobalt/script/union_type.h"
-#include "cobalt/script/value_handle.h"
-#include "cobalt/script/wrappable.h"
-
-namespace cobalt {
-namespace dom {
-
-class MediaKeyStatusMap : public script::Wrappable {
- public:
- typedef script::UnionType2<scoped_refptr<ArrayBufferView>,
- scoped_refptr<ArrayBuffer> > BufferSource;
- uint32_t size() const { return 0; }
- bool Has(BufferSource keyId) const { return false; }
- const script::ValueHandleHolder* Get(BufferSource keyId) const {
- return NULL;
- }
-
- DEFINE_WRAPPABLE_TYPE(MediaKeyStatusMap);
-
- private:
-};
-
-} // namespace dom
-} // namespace cobalt
-
-#endif // COBALT_DOM_MEDIA_KEY_STATUS_MAP_H_
diff --git a/src/cobalt/dom/media_key_status_map.idl b/src/cobalt/dom/media_key_status_map.idl
deleted file mode 100644
index a3bb962..0000000
--- a/src/cobalt/dom/media_key_status_map.idl
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeystatusmap-interface
-
-enum MediaKeyStatus {
- "usable",
- "expired",
- "released",
- "output-restricted",
- "output-downscaled",
- "status-pending",
- "internal-error"
-};
-
-//callback MediaKeyStatusMapForEachCallback =
-// void(MediaKeyStatus status, BufferSource source, MediaKeyStatusMap map);
-
-// https://www.w3.org/TR/WebIDL-1/#common-BufferSource
-typedef (ArrayBufferView or ArrayBuffer) BufferSource;
-
-interface MediaKeyStatusMap {
- readonly attribute unsigned long size;
- boolean has(BufferSource keyId);
- any get(BufferSource keyId);
-
- // iterable<BufferSource, MediaKeyStatus>;
- //object entries();
- //void forEach(function MediaKeyStatusMapForEachCallback);
- //object keys();
- //object values();
- //Iterator @@iterator();
-};
diff --git a/src/cobalt/dom/media_key_system_configuration.idl b/src/cobalt/dom/media_key_system_configuration.idl
deleted file mode 100644
index 0ac303b..0000000
--- a/src/cobalt/dom/media_key_system_configuration.idl
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemconfiguration-dictionary
-
-dictionary MediaKeySystemConfiguration {
- DOMString label = "";
- sequence<DOMString> initDataTypes = [];
- sequence<MediaKeySystemMediaCapability> audioCapabilities = [];
- sequence<MediaKeySystemMediaCapability> videoCapabilities = [];
- MediaKeysRequirement distinctiveIdentifier = "optional";
- MediaKeysRequirement persistentState = "optional";
- sequence<DOMString> sessionTypes;
-};
diff --git a/src/cobalt/dom/media_source.cc b/src/cobalt/dom/media_source.cc
index 20cc705..d8330cb 100644
--- a/src/cobalt/dom/media_source.cc
+++ b/src/cobalt/dom/media_source.cc
@@ -31,6 +31,7 @@
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/event.h"
#include "cobalt/media/can_play_type_handler.h"
+#include "starboard/double.h"
namespace cobalt {
namespace dom {
@@ -100,7 +101,7 @@
void MediaSource::set_duration(double duration,
script::ExceptionState* exception_state) {
- if (duration < 0.0 || isnan(duration)) {
+ if (duration < 0.0 || SbDoubleIsNan(duration)) {
DOMException::Raise(DOMException::kInvalidAccessErr, exception_state);
return;
}
diff --git a/src/cobalt/dom/media_source/media_source.cc b/src/cobalt/dom/media_source/media_source.cc
index c87fdb5..c3fab91 100644
--- a/src/cobalt/dom/media_source/media_source.cc
+++ b/src/cobalt/dom/media_source/media_source.cc
@@ -58,6 +58,7 @@
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/event.h"
#include "cobalt/media/base/pipeline_status.h"
+#include "starboard/double.h"
#include "starboard/media.h"
namespace cobalt {
@@ -141,7 +142,7 @@
void MediaSource::set_duration(double duration,
script::ExceptionState* exception_state) {
- if (duration < 0.0 || isnan(duration)) {
+ if (duration < 0.0 || SbDoubleIsNan(duration)) {
DOMException::Raise(DOMException::kIndexSizeErr, exception_state);
return;
}
diff --git a/src/cobalt/dom/navigator.cc b/src/cobalt/dom/navigator.cc
index 185385c..b567262 100644
--- a/src/cobalt/dom/navigator.cc
+++ b/src/cobalt/dom/navigator.cc
@@ -14,7 +14,12 @@
#include "cobalt/dom/navigator.h"
+#include "cobalt/dom/dom_exception.h"
+#if defined(COBALT_MEDIA_SOURCE_2016)
+#include "cobalt/dom/eme/media_key_system_access.h"
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
#include "cobalt/media_session/media_session_client.h"
+#include "cobalt/script/script_value_factory.h"
using cobalt::media_session::MediaSession;
@@ -47,10 +52,75 @@
return plugins_;
}
-const scoped_refptr<cobalt::media_session::MediaSession>&
-Navigator::media_session() const {
+const scoped_refptr<media_session::MediaSession>& Navigator::media_session()
+ const {
return media_session_;
}
+#if defined(COBALT_MEDIA_SOURCE_2016)
+
+namespace {
+
+// TODO: Implement "3.1.1.1 Get Supported Configuration" using
+// SbMediaCanPlayMimeAndKeySystem().
+// https://www.w3.org/TR/encrypted-media/#get-supported-configuration
+bool MaybeGetSupportedConfiguration(
+ const std::string& /*key_system*/,
+ const eme::MediaKeySystemConfiguration& candidate_configuration,
+ eme::MediaKeySystemConfiguration* supported_configuration) {
+ *supported_configuration = candidate_configuration;
+ return true;
+}
+
+} // namespace
+
+// See
+// https://www.w3.org/TR/encrypted-media/#dom-navigator-requestmediakeysystemaccess.
+scoped_ptr<Navigator::InterfacePromiseValue>
+Navigator::RequestMediaKeySystemAccess(
+ const std::string& key_system,
+ const script::Sequence<eme::MediaKeySystemConfiguration>&
+ supported_configurations) {
+ scoped_ptr<InterfacePromiseValue> promise =
+ script_value_factory_
+ ->CreateInterfacePromise<scoped_refptr<eme::MediaKeySystemAccess> >();
+ InterfacePromiseValue::StrongReference promise_reference(*promise);
+
+ // 1. If |keySystem| is the empty string, return a promise rejected
+ // with a newly created TypeError.
+ // 2. If |supportedConfigurations| is empty, return a promise rejected
+ // with a newly created TypeError.
+ if (key_system.empty() || supported_configurations.empty()) {
+ promise_reference.value().Reject(script::kTypeError);
+ return promise.Pass();
+ }
+
+ // 6.3. For each value in |supportedConfigurations|:
+ for (size_t configuration_index = 0;
+ configuration_index < supported_configurations.size();
+ ++configuration_index) {
+ // 6.3.3. If supported configuration is not NotSupported:
+ eme::MediaKeySystemConfiguration supported_configuration;
+ if (MaybeGetSupportedConfiguration(
+ key_system, supported_configurations.at(configuration_index),
+ &supported_configuration)) {
+ // 6.3.3.1. Let access be a new MediaKeySystemAccess object.
+ scoped_refptr<eme::MediaKeySystemAccess> media_key_system_access(
+ new eme::MediaKeySystemAccess(key_system, supported_configuration,
+ script_value_factory_));
+ // 6.3.3.2. Resolve promise.
+ promise_reference.value().Resolve(media_key_system_access);
+ return promise.Pass();
+ }
+ }
+
+ // 6.4. Reject promise with a NotSupportedError.
+ promise_reference.value().Reject(
+ new DOMException(DOMException::kNotSupportedErr));
+ return promise.Pass();
+}
+
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
+
} // namespace dom
} // namespace cobalt
diff --git a/src/cobalt/dom/navigator.h b/src/cobalt/dom/navigator.h
index a962803..740f9eb 100644
--- a/src/cobalt/dom/navigator.h
+++ b/src/cobalt/dom/navigator.h
@@ -18,9 +18,13 @@
#include <string>
#include "base/memory/ref_counted.h"
+#if defined(COBALT_MEDIA_SOURCE_2016)
+#include "cobalt/dom/eme/media_key_system_configuration.h"
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
#include "cobalt/dom/mime_type_array.h"
#include "cobalt/dom/plugin_array.h"
#include "cobalt/media_session/media_session.h"
+#include "cobalt/script/promise.h"
#include "cobalt/script/script_value_factory.h"
#include "cobalt/script/wrappable.h"
@@ -54,6 +58,16 @@
const scoped_refptr<cobalt::media_session::MediaSession>& media_session()
const;
+#if defined(COBALT_MEDIA_SOURCE_2016)
+ // Web API: extension defined in Encrypted Media Extensions (16 March 2017).
+ typedef script::ScriptValue<script::Promise<
+ scoped_refptr<script::Wrappable> > > InterfacePromiseValue;
+ scoped_ptr<InterfacePromiseValue> RequestMediaKeySystemAccess(
+ const std::string& key_system,
+ const script::Sequence<eme::MediaKeySystemConfiguration>&
+ supported_configurations);
+#endif // defined(COBALT_MEDIA_SOURCE_2016)
+
DEFINE_WRAPPABLE_TYPE(Navigator);
private:
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index a270c9d..554ce06 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -97,7 +97,8 @@
system_window::SystemWindow* system_window,
const scoped_refptr<input::Camera3D>& camera_3d,
const scoped_refptr<MediaSession>& media_session,
- int csp_insecure_allowed_token, int dom_max_element_depth)
+ int csp_insecure_allowed_token, int dom_max_element_depth,
+ float video_playback_rate_multiplier)
: width_(width),
height_(height),
html_element_context_(new HTMLElementContext(
@@ -105,7 +106,8 @@
web_media_player_factory, script_runner, script_value_factory,
media_source_registry, resource_provider, animated_image_tracker,
image_cache, reduced_image_cache_capacity_manager,
- remote_typeface_cache, mesh_cache, dom_stat_tracker, language)),
+ remote_typeface_cache, mesh_cache, dom_stat_tracker, language,
+ video_playback_rate_multiplier)),
performance_(new Performance(new base::SystemMonotonicClock())),
ALLOW_THIS_IN_INITIALIZER_LIST(document_(new Document(
html_element_context_.get(),
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index 7a90c00..0fc144b 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -133,7 +133,8 @@
system_window::SystemWindow* system_window,
const scoped_refptr<input::Camera3D>& camera_3d,
const scoped_refptr<cobalt::media_session::MediaSession>& media_session,
- int csp_insecure_allowed_token = 0, int dom_max_element_depth = 0);
+ int csp_insecure_allowed_token = 0, int dom_max_element_depth = 0,
+ float video_playback_rate_multiplier = 1.f);
// Web API: Window
//
diff --git a/src/cobalt/h5vcc/h5vcc.gyp b/src/cobalt/h5vcc/h5vcc.gyp
index 6c5c7b6..1e71529 100644
--- a/src/cobalt/h5vcc/h5vcc.gyp
+++ b/src/cobalt/h5vcc/h5vcc.gyp
@@ -90,6 +90,9 @@
},
}],
],
+ 'defines': [
+ 'COBALT_USER_ON_EXIT_STRATEGY="<(cobalt_user_on_exit_strategy)"',
+ ],
},
{
diff --git a/src/cobalt/h5vcc/h5vcc_system.cc b/src/cobalt/h5vcc/h5vcc_system.cc
index 60e396d..2b96110 100644
--- a/src/cobalt/h5vcc/h5vcc_system.cc
+++ b/src/cobalt/h5vcc/h5vcc_system.cc
@@ -64,5 +64,21 @@
// return false to indicate the client should launch their own dialog.
bool H5vccSystem::TriggerHelp() const { return false; }
+uint32 H5vccSystem::user_on_exit_strategy() const {
+ // Convert from the Cobalt gyp setting variable's enum options to the H5VCC
+ // interface enum options.
+ std::string exit_strategy_str(COBALT_USER_ON_EXIT_STRATEGY);
+ if (exit_strategy_str == "stop") {
+ return static_cast<UserOnExitStrategy>(kUserOnExitStrategyClose);
+ } else if (exit_strategy_str == "suspend") {
+ return static_cast<UserOnExitStrategy>(kUserOnExitStrategyMinimize);
+ } else if (exit_strategy_str == "noexit") {
+ return static_cast<UserOnExitStrategy>(kUserOnExitStrategyNoExit);
+ } else {
+ NOTREACHED() << "Unknown gyp-defined exit strategy.";
+ return static_cast<UserOnExitStrategy>(kUserOnExitStrategyClose);
+ }
+}
+
} // namespace h5vcc
} // namespace cobalt
diff --git a/src/cobalt/h5vcc/h5vcc_system.h b/src/cobalt/h5vcc/h5vcc_system.h
index e192581..5928ed8 100644
--- a/src/cobalt/h5vcc/h5vcc_system.h
+++ b/src/cobalt/h5vcc/h5vcc_system.h
@@ -35,6 +35,14 @@
bool TriggerHelp() const;
+ enum UserOnExitStrategy {
+ kUserOnExitStrategyClose,
+ kUserOnExitStrategyMinimize,
+ kUserOnExitStrategyNoExit,
+ };
+
+ uint32 user_on_exit_strategy() const;
+
DEFINE_WRAPPABLE_TYPE(H5vccSystem);
private:
diff --git a/src/cobalt/h5vcc/h5vcc_system.idl b/src/cobalt/h5vcc/h5vcc_system.idl
index a1612e4..787116d 100644
--- a/src/cobalt/h5vcc/h5vcc_system.idl
+++ b/src/cobalt/h5vcc/h5vcc_system.idl
@@ -19,4 +19,21 @@
readonly attribute DOMString region;
readonly attribute DOMString version;
boolean triggerHelp();
+
+ // enum UserOnExitStrategy
+ //
+ // When a user requests to leave the application, window.close() should be
+ // called.
+ const unsigned long USER_ON_EXIT_STRATEGY_CLOSE = 0;
+ // When a user requests to leave the application, window.minimize() should be
+ // called.
+ const unsigned long USER_ON_EXIT_STRATEGY_MINIMIZE = 1;
+ // The user should not be allowed to initiate an application exit request.
+ const unsigned long USER_ON_EXIT_STRATEGY_NO_EXIT = 2;
+
+ // This variable defines what Cobalt's preferred strategy should be for
+ // handling internally triggered application exit requests (e.g. the user
+ // chooses to back out of the application). See the comments in the
+ // enum above for more information about possible values.
+ readonly attribute unsigned long userOnExitStrategy;
};
diff --git a/src/cobalt/layout/box.h b/src/cobalt/layout/box.h
index 42cfc71..3484227 100644
--- a/src/cobalt/layout/box.h
+++ b/src/cobalt/layout/box.h
@@ -21,7 +21,6 @@
#include "base/memory/ref_counted.h"
#include "base/optional.h"
-#include "cobalt/base/math.h"
#include "cobalt/cssom/css_computed_style_declaration.h"
#include "cobalt/cssom/css_style_declaration.h"
#include "cobalt/dom/node.h"
diff --git a/src/cobalt/layout/layout_unit.h b/src/cobalt/layout/layout_unit.h
index d65f08d..c3b3520 100644
--- a/src/cobalt/layout/layout_unit.h
+++ b/src/cobalt/layout/layout_unit.h
@@ -23,7 +23,6 @@
#include "base/basictypes.h"
#include "base/logging.h"
-#include "cobalt/base/math.h"
namespace cobalt {
namespace layout {
diff --git a/src/cobalt/layout/line_box.cc b/src/cobalt/layout/line_box.cc
index e4f3eea..452f2b0 100644
--- a/src/cobalt/layout/line_box.cc
+++ b/src/cobalt/layout/line_box.cc
@@ -17,7 +17,6 @@
#include <algorithm>
#include <limits>
-#include "cobalt/base/math.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/box.h"
#include "cobalt/layout/used_style.h"
diff --git a/src/cobalt/layout/text_box.cc b/src/cobalt/layout/text_box.cc
index a13b1c0..0dd7e44 100644
--- a/src/cobalt/layout/text_box.cc
+++ b/src/cobalt/layout/text_box.cc
@@ -17,7 +17,6 @@
#include <algorithm>
#include <limits>
-#include "cobalt/base/math.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/shadow_value.h"
#include "cobalt/layout/render_tree_animations.h"
diff --git a/src/cobalt/loader/image/animated_webp_image.cc b/src/cobalt/loader/image/animated_webp_image.cc
index a6a9373..d43449f 100644
--- a/src/cobalt/loader/image/animated_webp_image.cc
+++ b/src/cobalt/loader/image/animated_webp_image.cc
@@ -16,7 +16,8 @@
#include "cobalt/loader/image/animated_webp_image.h"
-#include "cobalt/loader/image/webp_image_decoder.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/loader/image/image_decoder.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/render_tree/composition_node.h"
#include "cobalt/render_tree/image_node.h"
@@ -170,11 +171,22 @@
}
}
+namespace {
+
+void RecordImage(scoped_refptr<render_tree::Image>* image_pointer,
+ const scoped_refptr<loader::image::Image>& image) {
+ image::StaticImage* static_image =
+ base::polymorphic_downcast<loader::image::StaticImage*>(image.get());
+ DCHECK(static_image);
+ *image_pointer = static_image->image();
+}
+
+} // namespace
+
bool AnimatedWebPImage::DecodeOneFrame(int frame_index) {
TRACK_MEMORY_SCOPE("Rendering");
base::AutoLock lock(lock_);
WebPIterator webp_iterator;
- WEBPImageDecoder webp_image_decoder(resource_provider_);
scoped_refptr<render_tree::Image> next_frame_image;
// Decode the current frame.
@@ -185,24 +197,18 @@
if (!webp_iterator.complete) {
return false;
}
- webp_image_decoder.DecodeChunk(webp_iterator.fragment.bytes,
- webp_iterator.fragment.size);
- if (!webp_image_decoder.FinishWithSuccess()) {
+
+ ImageDecoder image_decoder(
+ resource_provider_, base::Bind(&RecordImage, &next_frame_image),
+ ImageDecoder::ErrorCallback(), ImageDecoder::kImageTypeWebP);
+ image_decoder.DecodeChunk(
+ reinterpret_cast<const char*>(webp_iterator.fragment.bytes),
+ webp_iterator.fragment.size);
+ image_decoder.Finish();
+ if (!next_frame_image) {
LOG(ERROR) << "Failed to decode WebP image frame.";
return false;
}
-
- scoped_ptr<render_tree::ImageData> next_frame_data = AllocateImageData(
- math::Size(webp_iterator.width, webp_iterator.height));
- DCHECK(next_frame_data);
- {
- TRACE_EVENT0("cobalt::loader::image", "SbMemoryCopy");
- SbMemoryCopy(next_frame_data->GetMemory(),
- webp_image_decoder.GetOriginalMemory(),
- webp_iterator.width * webp_iterator.height *
- render_tree::BytesPerPixel(pixel_format_));
- }
- next_frame_image = resource_provider_->CreateImage(next_frame_data.Pass());
}
// Alpha blend the current frame on top of the buffer.
diff --git a/src/cobalt/loader/image/image_decoder.cc b/src/cobalt/loader/image/image_decoder.cc
index 831a574..a44f373 100644
--- a/src/cobalt/loader/image/image_decoder.cc
+++ b/src/cobalt/loader/image/image_decoder.cc
@@ -51,27 +51,18 @@
result->append(message);
}
-// The various types of images we support decoding.
-enum ImageType {
- kImageTypeInvalid,
- kImageTypeGIF,
- kImageTypeJPEG,
- kImageTypePNG,
- kImageTypeWebP,
-};
-
// Determine the ImageType of an image from its signature.
-ImageType DetermineImageType(const uint8* header) {
+ImageDecoder::ImageType DetermineImageType(const uint8* header) {
if (!memcmp(header, "\xFF\xD8\xFF", 3)) {
- return kImageTypeJPEG;
+ return ImageDecoder::kImageTypeJPEG;
} else if (!memcmp(header, "GIF87a", 6) || !memcmp(header, "GIF89a", 6)) {
- return kImageTypeGIF;
+ return ImageDecoder::kImageTypeGIF;
} else if (!memcmp(header, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8)) {
- return kImageTypePNG;
+ return ImageDecoder::kImageTypePNG;
} else if (!memcmp(header, "RIFF", 4) && !memcmp(header + 8, "WEBPVP", 6)) {
- return kImageTypeWebP;
+ return ImageDecoder::kImageTypeWebP;
} else {
- return kImageTypeInvalid;
+ return ImageDecoder::kImageTypeInvalid;
}
}
@@ -83,9 +74,22 @@
: resource_provider_(resource_provider),
success_callback_(success_callback),
error_callback_(error_callback),
+ image_type_(kImageTypeInvalid),
state_(resource_provider_ ? kWaitingForHeader : kSuspended),
is_deletion_pending_(false) {
- TRACE_EVENT0("cobalt::loader::image", "ImageDecoder::ImageDecoder()");
+ signature_cache_.position = 0;
+}
+
+ImageDecoder::ImageDecoder(render_tree::ResourceProvider* resource_provider,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback,
+ ImageType image_type)
+ : resource_provider_(resource_provider),
+ success_callback_(success_callback),
+ error_callback_(error_callback),
+ image_type_(image_type),
+ state_(resource_provider_ ? kWaitingForHeader : kSuspended),
+ is_deletion_pending_(false) {
signature_cache_.position = 0;
}
@@ -269,17 +273,17 @@
namespace {
#if defined(STARBOARD)
#if SB_VERSION(3) && SB_HAS(GRAPHICS)
-const char* GetMimeTypeFromImageType(ImageType image_type) {
+const char* GetMimeTypeFromImageType(ImageDecoder::ImageType image_type) {
switch (image_type) {
- case kImageTypeJPEG:
+ case ImageDecoder::kImageTypeJPEG:
return "image/jpeg";
- case kImageTypePNG:
+ case ImageDecoder::kImageTypePNG:
return "image/png";
- case kImageTypeGIF:
+ case ImageDecoder::kImageTypeGIF:
return "image/gif";
- case kImageTypeWebP:
+ case ImageDecoder::kImageTypeWebP:
return "image/webp";
- case kImageTypeInvalid:
+ case ImageDecoder::kImageTypeInvalid:
return NULL;
default: { NOTREACHED(); }
}
@@ -288,7 +292,7 @@
// If |mime_type| is empty, |image_type| will be used to deduce the mime type.
scoped_ptr<ImageDataDecoder> MaybeCreateStarboardDecoder(
- const std::string& mime_type, ImageType image_type,
+ const std::string& mime_type, ImageDecoder::ImageType image_type,
render_tree::ResourceProvider* resource_provider) {
// clang-format off
const SbDecodeTargetFormat kPreferredFormats[] = {
@@ -331,12 +335,13 @@
#endif // defined(STARBOARD)
scoped_ptr<ImageDataDecoder> CreateImageDecoderFromImageType(
- ImageType image_type, render_tree::ResourceProvider* resource_provider) {
+ ImageDecoder::ImageType image_type,
+ render_tree::ResourceProvider* resource_provider) {
// Call different types of decoders by matching the image signature.
if (s_use_stub_image_decoder) {
return make_scoped_ptr<ImageDataDecoder>(
new StubImageDecoder(resource_provider));
- } else if (image_type == kImageTypeJPEG) {
+ } else if (image_type == ImageDecoder::kImageTypeJPEG) {
#if defined(USE_PS3_JPEG_IMAGE_DECODER)
return make_scoped_ptr<ImageDataDecoder>(
new JPEGImageDecoderPS3(resource_provider));
@@ -344,13 +349,13 @@
return make_scoped_ptr<ImageDataDecoder>(
new JPEGImageDecoder(resource_provider));
#endif // defined(USE_PS3_JPEG_IMAGE_DECODER)
- } else if (image_type == kImageTypePNG) {
+ } else if (image_type == ImageDecoder::kImageTypePNG) {
return make_scoped_ptr<ImageDataDecoder>(
new PNGImageDecoder(resource_provider));
- } else if (image_type == kImageTypeWebP) {
+ } else if (image_type == ImageDecoder::kImageTypeWebP) {
return make_scoped_ptr<ImageDataDecoder>(
new WEBPImageDecoder(resource_provider));
- } else if (image_type == kImageTypeGIF) {
+ } else if (image_type == ImageDecoder::kImageTypeGIF) {
return make_scoped_ptr<ImageDataDecoder>(
new DummyGIFImageDecoder(resource_provider));
} else {
@@ -374,17 +379,19 @@
return false;
}
- const ImageType image_type = DetermineImageType(signature_cache_.data);
+ if (image_type_ == kImageTypeInvalid) {
+ image_type_ = DetermineImageType(signature_cache_.data);
+ }
#if defined(STARBOARD)
#if SB_VERSION(3) && SB_HAS(GRAPHICS)
decoder_ =
- MaybeCreateStarboardDecoder(mime_type_, image_type, resource_provider_);
+ MaybeCreateStarboardDecoder(mime_type_, image_type_, resource_provider_);
#endif // SB_VERSION(3) && SB_HAS(GRAPHICS)
#endif // defined(STARBOARD)
if (!decoder_) {
- decoder_ = CreateImageDecoderFromImageType(image_type, resource_provider_);
+ decoder_ = CreateImageDecoderFromImageType(image_type_, resource_provider_);
}
if (!decoder_) {
diff --git a/src/cobalt/loader/image/image_decoder.h b/src/cobalt/loader/image/image_decoder.h
index 2127a07..8004dc9 100644
--- a/src/cobalt/loader/image/image_decoder.h
+++ b/src/cobalt/loader/image/image_decoder.h
@@ -28,19 +28,31 @@
namespace loader {
namespace image {
-// This class handles decoding any image type. When the image type is determined
-// by the signature in the data being received, an image data decoder specific
+// This class handles decoding any image. If image type is not given, it is
+// determined by the signature in the data. Then an image data decoder specific
// to that image type is created to parse the data. When the decoding is
// complete, the image decoder retrieves the data and uses it to create the
// image.
class ImageDecoder : public Decoder {
public:
+ // The various types of images we support decoding.
+ enum ImageType {
+ kImageTypeInvalid,
+ kImageTypeGIF,
+ kImageTypeJPEG,
+ kImageTypePNG,
+ kImageTypeWebP,
+ };
+
typedef base::Callback<void(const scoped_refptr<Image>&)> SuccessCallback;
typedef base::Callback<void(const std::string&)> ErrorCallback;
ImageDecoder(render_tree::ResourceProvider* resource_provider,
const SuccessCallback& success_callback,
const ErrorCallback& error_callback);
+ ImageDecoder(render_tree::ResourceProvider* resource_provider,
+ const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback, ImageType image_type);
// From Decoder.
LoadResponseType OnResponseStarted(
@@ -84,6 +96,7 @@
render_tree::ResourceProvider* resource_provider_;
const SuccessCallback success_callback_;
const ErrorCallback error_callback_;
+ ImageType image_type_;
scoped_ptr<ImageDataDecoder> decoder_;
SignatureCache signature_cache_;
State state_;
diff --git a/src/cobalt/math/linear_interpolator.h b/src/cobalt/math/linear_interpolator.h
new file mode 100644
index 0000000..728f70f
--- /dev/null
+++ b/src/cobalt/math/linear_interpolator.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_MATH_LINEAR_INTERPOLATOR_H_
+#define COBALT_MATH_LINEAR_INTERPOLATOR_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "starboard/types.h"
+
+namespace cobalt {
+namespace math {
+
+// LinearInterpolator effectively generates outputs based on a table. This can
+// be used for function approximation (ie. sine) or arbitrary functions that
+// need specific values at specific inputs, and interpolated values otherwise.
+// KeyT and ValueT can be any builtin integer and float point type.
+// It's recommended that double types are used unless speed is required, then
+// use other types.
+//
+// Performance:
+// This table increases the computation on the order of O(n) of the number
+// of interpolation points. However in practice the number of interpolation
+// points is small enough (<20) where this linear search is faster than binary
+// lookup.
+//
+// Discontinuous values:
+// This table supports discontinuous values. To enable this feature, insert a
+// pair of duplicate keys, each with a different value. See example below.
+//
+// Example (continuous):
+// LinearInterpolator<float, float> interp;
+// interp.Add(0, 0);
+// interp.Add(1, 2);
+// EXPECT_FLOAT_EQ(0.f, interp.Map(0.0f));
+// EXPECT_FLOAT_EQ(1.f, interp.Map(0.5f));
+// EXPECT_FLOAT_EQ(2.f, interp.Map(1.0f));
+//
+// Example (discontinuous):
+// LinearInterpolator<double, float> interp;
+// interp.Add(0, 0);
+// interp.Add(1, 1); // Discontinuity at input = 1.
+// interp.Add(1, 3);
+// interp.Add(2, 4);
+// static const double kErrorThreshold = .1f;
+// static const double kEpsilon = std::numeric_limits<double>::epsilon()*4.0;
+// EXPECT_NEAR(1.0, interp.Map(1.f - kEpsilon), kErrorThreshold);
+// EXPECT_FLOAT_EQ(3, interp.Map(1.f));
+// EXPECT_NEAR(3.0, interp.Map(1.f + kEpsilon), kErrorThreshold);
+template <typename KeyT, typename ValueT>
+class LinearInterpolator {
+ public:
+ ValueT Map(const KeyT& key) const {
+ return Interp(key);
+ }
+
+ // Adds a key to the table. For a continuous piecewise line-curve each key
+ // added must be greater in value than the last key added.
+ // If duplicate keys are entered sequentially then this will introduce
+ // a discontinuity - a big jump in the returned value from Map() when the
+ // input crosses the discontinuity point.
+ void Add(const KeyT& key, const ValueT& val) {
+ if (!table_.empty()) {
+ DCHECK_LE(table_.back().first, key) << "Keys are not in order.";
+ }
+ table_.push_back(std::pair<KeyT, ValueT>(key, val));
+ }
+ void Clear() {
+ table_.clear();
+ }
+
+ private:
+ ValueT Interp(const KeyT& k) const {
+ if (table_.empty()) {
+ return ValueT(0);
+ }
+
+ // Contains the indices which reference keys before and after the key.
+ std::pair<size_t, size_t> indices = SelectInterpPoints(k);
+
+ // Singular value, no interpolation needed.
+ if (indices.first == indices.second) {
+ return table_[indices.first].second;
+ }
+
+ // Perform the interpolation with the given key & value lines.
+ const std::pair<KeyT, ValueT>& curr = table_[indices.first];
+ const std::pair<KeyT, ValueT>& next = table_[indices.second];
+
+ // Duplicate keys, select the second value. This prevents
+ // LinearInterpolation() from dividing by 0 for duplicate keys.
+ if (curr.first == next.first) {
+ return next.second;
+ }
+
+ return LinearInterpolation(k, curr.first, next.first,
+ curr.second, next.second);
+ }
+
+ // Linearly walk through the table looking for a pair of interpolation
+ // points. Linear walking must be used because this table uses duplicate
+ // keys generate discontinuous outputs.
+ std::pair<size_t, size_t> SelectInterpPoints(const KeyT& k) const {
+ DCHECK(!table_.empty());
+ if (k < table_[0].first) {
+ return std::pair<size_t, size_t>(0, 0);
+ }
+
+ for (size_t i = 0; i < table_.size() - 1; ++i) {
+ const std::pair<KeyT, ValueT>& curr = table_[i];
+ const std::pair<KeyT, ValueT>& next = table_[i+1];
+
+ if (curr.first <= k && k < next.first) {
+ return std::pair<size_t, size_t>(i, i+1);
+ }
+ }
+
+ return std::pair<size_t, size_t>(table_.size() - 1, table_.size() - 1);
+ }
+
+ // Maps a value in the range [x1, x2] to the range [y1, y2].
+ static const ValueT LinearInterpolation(const KeyT& t,
+ const KeyT& x1, const KeyT& x2,
+ const ValueT& y1, const ValueT& y2) {
+ ValueT return_val =
+ static_cast<ValueT>((t - x1) * (y2 - y1) / (x2 - x1) + y1);
+ return return_val;
+ }
+
+ typedef std::vector<std::pair<KeyT, ValueT> > VectorType;
+ VectorType table_;
+};
+
+} // namespace math
+} // namespace cobalt
+
+#endif // COBALT_MATH_LINEAR_INTERPOLATOR_H_
diff --git a/src/cobalt/math/linear_interpolator_unittest.cc b/src/cobalt/math/linear_interpolator_unittest.cc
new file mode 100644
index 0000000..399baf4
--- /dev/null
+++ b/src/cobalt/math/linear_interpolator_unittest.cc
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/math/linear_interpolator.h"
+
+#include <limits>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cobalt {
+namespace math {
+
+TEST(LinearInterpolator, SimpleInterpolation) {
+ LinearInterpolator<float, float> interp;
+ interp.Add(0, 0);
+ interp.Add(1, 2);
+
+ // Expect that value of 0.0f maps to 0.0f
+ EXPECT_FLOAT_EQ(0.f, interp.Map(0.0f));
+ // Expect that value of 0.5f maps to 1.0f
+ EXPECT_FLOAT_EQ(1.f, interp.Map(0.5f));
+ // Expect that value of 1.5f maps to 2.0f
+ EXPECT_FLOAT_EQ(2.f, interp.Map(1.0f));
+}
+
+// Tests the expectation that clearing the interpolator works.
+TEST(LinearInterpolator, Clear) {
+ LinearInterpolator<int, int> interp;
+ interp.Add(-1, 0);
+ interp.Add(1, 2);
+
+ interp.Clear();
+
+ EXPECT_FLOAT_EQ(0, interp.Map(-1));
+ EXPECT_FLOAT_EQ(0, interp.Map(1));
+}
+
+// Tests the expectation that interpolating on one value in the table works
+// as expected: to always return that value.
+TEST(LinearInterpolator, InterpolateSingularValue) {
+ LinearInterpolator<size_t, size_t> interp;
+ interp.Add(2, 10);
+
+ EXPECT_EQ(10, interp.Map(2));
+ EXPECT_EQ(10, interp.Map(1));
+ EXPECT_EQ(10, interp.Map(3));
+}
+
+// Tests the expectation that we can introduce an discontinuity by passing
+// in duplicate keys.
+TEST(LinearInterpolator, Discontinuity) {
+ LinearInterpolator<double, float> interp;
+ interp.Add(0, 0);
+ interp.Add(1, 1); // Discontinuity at input = 1.
+ interp.Add(1, 3);
+ interp.Add(2, 4);
+
+ static const double kErrorThreshold = .1f;
+ static const double kEpsilon = std::numeric_limits<double>::epsilon()*4.0;
+
+ EXPECT_NEAR(1.0, interp.Map(1.f - kEpsilon), kErrorThreshold);
+ // Expect that at the discontinuity point value of 1, that the value that
+ // the interpolator produces is 3.
+ EXPECT_FLOAT_EQ(3, interp.Map(1.f));
+ EXPECT_NEAR(3.0, interp.Map(1.f + kEpsilon), kErrorThreshold);
+}
+
+// Tests that extrapolation is forbidden with this interpolator.
+TEST(LinearInterpolator, ExtrapolationForbidden) {
+ LinearInterpolator<float, float> interp;
+ interp.Add(0, 0);
+ interp.Add(1, 2);
+
+ // Expect that values less than the minimal key value is clamped.
+ EXPECT_FLOAT_EQ(0.0f, interp.Map(-1.0f));
+ // Expect that values greater than the maximum key value is clamped.
+ EXPECT_FLOAT_EQ(2.0f, interp.Map(2.0f));
+}
+
+// Some more real world values.
+TEST(LinearInterpolator, UseComplexFloat) {
+ LinearInterpolator<float, float> interp;
+ interp.Add(0, 0);
+ interp.Add(41, 1);
+ interp.Add(1023, 15);
+
+ EXPECT_FLOAT_EQ(0.0f, interp.Map(0.f));
+ EXPECT_FLOAT_EQ(0.5f, interp.Map(41.f/2.f));
+ EXPECT_FLOAT_EQ(1.0f, interp.Map(41.f));
+ EXPECT_FLOAT_EQ(15.f, interp.Map(1023.f));
+}
+
+// Tests that this interpolator works with integer keys and float values.
+TEST(LinearInterpolator, UseIntegerKeyWithFloatValue) {
+ LinearInterpolator<int, float> interp;
+ interp.Add(0, 0.f);
+ interp.Add(10, 1.f);
+ interp.Add(100, 2.f);
+
+ EXPECT_FLOAT_EQ(0.0f, interp.Map(0));
+ EXPECT_FLOAT_EQ(0.5f, interp.Map(5));
+ EXPECT_FLOAT_EQ(1.0f, interp.Map(10));
+ EXPECT_FLOAT_EQ(2.0f, interp.Map(100));
+}
+
+// Tests that this interpolator works with integer keys and int values.
+TEST(LinearInterpolator, UseIntegerKeyWithIntegerValue) {
+ LinearInterpolator<int, int> interp;
+ interp.Add(0, 0);
+ interp.Add(10, 100);
+ interp.Add(100, 1000);
+
+ EXPECT_EQ(0, interp.Map(0));
+ EXPECT_EQ(50, interp.Map(5));
+ EXPECT_EQ(100, interp.Map(10));
+ EXPECT_EQ(550, interp.Map(55));
+ EXPECT_EQ(1000, interp.Map(100));
+}
+
+} // namespace math
+} // namespace cobalt
diff --git a/src/cobalt/math/math.gyp b/src/cobalt/math/math.gyp
index 692d7ec..f457fdd 100644
--- a/src/cobalt/math/math.gyp
+++ b/src/cobalt/math/math.gyp
@@ -18,6 +18,7 @@
'insets_base.h',
'insets_f.cc',
'insets_f.h',
+ 'linear_interpolator.h',
'matrix3_f.cc',
'matrix3_f.h',
'matrix_interpolation.cc',
@@ -75,6 +76,7 @@
'box_unittest.cc',
'cubic_bezier_unittest.cc',
'insets_unittest.cc',
+ 'linear_interpolator_unittest.cc',
'matrix3_unittest.cc',
'matrix_interpolation_unittest.cc',
'point3_unittest.cc',
diff --git a/src/cobalt/media/base/drm_system.cc b/src/cobalt/media/base/drm_system.cc
index 38a0be8..639051f 100644
--- a/src/cobalt/media/base/drm_system.cc
+++ b/src/cobalt/media/base/drm_system.cc
@@ -20,72 +20,179 @@
namespace cobalt {
namespace media {
-DrmSystem::DrmSystem(const char* key_system, DrmSystemClient* client)
- : client_(client),
- wrapped_drm_system_(SbDrmCreateSystem(key_system, this,
+DrmSystem::Session::Session(DrmSystem* drm_system)
+ : drm_system_(drm_system), closed_(false) {}
+
+DrmSystem::Session::~Session() {
+ if (id_ && !closed_) {
+ // Auto-closing semantics is derived from EME spec.
+ //
+ // If a MediaKeySession object is not closed when it becomes inaccessible
+ // to the page, the CDM shall close the key session associated with
+ // the object.
+ // https://www.w3.org/TR/encrypted-media/#mediakeysession-interface
+ Close();
+ }
+}
+
+void DrmSystem::Session::GenerateUpdateRequest(
+ const std::string& type, const uint8* init_data, int init_data_length,
+ const SessionUpdateRequestGeneratedCallback&
+ session_update_request_generated_callback,
+ const SessionUpdateRequestDidNotGenerateCallback&
+ session_update_request_did_not_generate_callback) {
+ update_request_generated_callback_ =
+ session_update_request_generated_callback;
+ drm_system_->GenerateSessionUpdateRequest(
+ this, type, init_data, init_data_length,
+ session_update_request_generated_callback,
+ session_update_request_did_not_generate_callback);
+}
+
+void DrmSystem::Session::Update(
+ const uint8* key, int key_length,
+ const SessionUpdatedCallback& session_updated_callback,
+ const SessionDidNotUpdateCallback& session_did_not_update_callback) {
+ drm_system_->UpdateSession(*id_, key, key_length, session_updated_callback,
+ session_did_not_update_callback);
+}
+
+void DrmSystem::Session::Close() {
+ drm_system_->CloseSession(*id_);
+ closed_ = true;
+}
+
+DrmSystem::DrmSystem(const char* key_system)
+ : wrapped_drm_system_(SbDrmCreateSystem(key_system, this,
OnSessionUpdateRequestGeneratedFunc,
OnSessionUpdatedFunc)),
- message_loop_(MessageLoop::current()) {
+ message_loop_(MessageLoop::current()),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
+ weak_this_(weak_ptr_factory_.GetWeakPtr()),
+ next_session_update_request_ticket_(0),
+ next_session_update_ticket_(0) {
DCHECK_NE(kSbDrmSystemInvalid, wrapped_drm_system_);
}
DrmSystem::~DrmSystem() { SbDrmDestroySystem(wrapped_drm_system_); }
-void DrmSystem::GenerateSessionUpdateRequest(int ticket,
- const std::string& type,
- const uint8_t* init_data,
- int init_data_length) {
+scoped_ptr<DrmSystem::Session> DrmSystem::CreateSession() {
+ return make_scoped_ptr(new Session(this));
+}
+
+void DrmSystem::GenerateSessionUpdateRequest(
+ Session* session, const std::string& type, const uint8_t* init_data,
+ int init_data_length, const SessionUpdateRequestGeneratedCallback&
+ session_update_request_generated_callback,
+ const SessionUpdateRequestDidNotGenerateCallback&
+ session_update_request_did_not_generate_callback) {
+ // Store the context of the call.
+ SessionUpdateRequest session_update_request;
+ session_update_request.session = session;
+ session_update_request.generated_callback =
+ session_update_request_generated_callback;
+ session_update_request.did_not_generate_callback =
+ session_update_request_did_not_generate_callback;
+ int ticket = next_session_update_request_ticket_++;
+ ticket_to_session_update_request_map_.insert(
+ std::make_pair(ticket, session_update_request));
+
SbDrmGenerateSessionUpdateRequest(wrapped_drm_system_, ticket, type.c_str(),
init_data, init_data_length);
}
-void DrmSystem::UpdateSession(int ticket, const std::string& session_id,
- const uint8_t* key, int key_length) {
+void DrmSystem::UpdateSession(
+ const std::string& session_id, const uint8_t* key, int key_length,
+ const SessionUpdatedCallback& session_updated_callback,
+ const SessionDidNotUpdateCallback& session_did_not_update_callback) {
+ // Store the context of the call.
+ SessionUpdate session_update;
+ session_update.updated_callback = session_updated_callback;
+ session_update.did_not_update_callback = session_did_not_update_callback;
+ int ticket = next_session_update_ticket_++;
+ ticket_to_session_update_map_.insert(std::make_pair(ticket, session_update));
+
SbDrmUpdateSession(wrapped_drm_system_, ticket, key, key_length,
session_id.c_str(), session_id.size());
}
void DrmSystem::CloseSession(const std::string& session_id) {
+ id_to_session_map_.erase(session_id);
SbDrmCloseSession(wrapped_drm_system_, session_id.c_str(), session_id.size());
}
-void DrmSystem::OnSessionUpdateRequestGenerated(int ticket,
- const void* session_id,
- int session_id_size,
- const void* content,
- int content_size) {
- if (session_id) {
- std::string session_id_copy(
- static_cast<const char*>(session_id),
- static_cast<const char*>(session_id) + session_id_size);
+void DrmSystem::OnSessionUpdateRequestGenerated(
+ int ticket, const base::optional<std::string>& session_id,
+ scoped_array<uint8> message, int message_size) {
+ if (SbDrmTicketIsValid(ticket)) {
+ // Called back as a result of |SbDrmGenerateSessionUpdateRequest|.
- scoped_array<uint8> content_copy(new uint8[content_size]);
- SbMemoryCopy(content_copy.get(), content, content_size);
+ // Restore the context of |GenerateSessionUpdateRequest|.
+ TicketToSessionUpdateRequestMap::iterator session_update_request_iterator =
+ ticket_to_session_update_request_map_.find(ticket);
+ if (session_update_request_iterator ==
+ ticket_to_session_update_request_map_.end()) {
+ LOG(ERROR) << "Unknown session update request ticket: " << ticket << ".";
+ return;
+ }
+ const SessionUpdateRequest& session_update_request =
+ session_update_request_iterator->second;
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&DrmSystemClient::OnSessionUpdateRequestGenerated,
- base::Unretained(client_), ticket, session_id_copy,
- base::Passed(&content_copy), content_size));
+ // Interpret the result.
+ if (session_id) {
+ // Successful request generation.
+
+ // Enable session lookup by id which is used by spontaneous callbacks.
+ session_update_request.session->set_id(*session_id);
+ id_to_session_map_.insert(
+ std::make_pair(*session_id, session_update_request.session));
+
+ session_update_request.generated_callback.Run(message.Pass(),
+ message_size);
+ } else {
+ // Failure during request generation.
+ session_update_request.did_not_generate_callback.Run();
+ }
+
+ // Sweep the context of |GenerateSessionUpdateRequest|.
+ ticket_to_session_update_request_map_.erase(
+ session_update_request_iterator);
} else {
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&DrmSystemClient::OnSessionUpdateRequestDidNotGenerate,
- base::Unretained(client_), ticket));
+ // Called back spontaneously by the underlying DRM system.
+
+ // Find the session by ID.
+ IdToSessionMap::iterator session_iterator =
+ id_to_session_map_.find(*session_id);
+ if (session_iterator == id_to_session_map_.end()) {
+ LOG(ERROR) << "Unknown session id: " << *session_id << ".";
+ return;
+ }
+ Session* session = session_iterator->second;
+
+ session->update_request_generated_callback().Run(message.Pass(),
+ message_size);
}
}
-void DrmSystem::OnSessionUpdated(int ticket, const void* /*session_id*/,
- int /*session_id_size*/, bool succeeded) {
- if (succeeded) {
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&DrmSystemClient::OnSessionUpdated,
- base::Unretained(client_), ticket));
- } else {
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&DrmSystemClient::OnSessionDidNotUpdate,
- base::Unretained(client_), ticket));
+void DrmSystem::OnSessionUpdated(int ticket, bool succeeded) {
+ // Restore the context of |UpdateSession|.
+ TicketToSessionUpdateMap::iterator session_update_iterator =
+ ticket_to_session_update_map_.find(ticket);
+ if (session_update_iterator == ticket_to_session_update_map_.end()) {
+ LOG(ERROR) << "Unknown session update ticket: " << ticket << ".";
+ return;
}
+ const SessionUpdate& session_update = session_update_iterator->second;
+
+ // Interpret the result.
+ if (succeeded) {
+ session_update.updated_callback.Run();
+ } else {
+ session_update.did_not_update_callback.Run();
+ }
+
+ // Sweep the context of |UpdateSession|.
+ ticket_to_session_update_map_.erase(session_update_iterator);
}
// static
@@ -97,20 +204,35 @@
DrmSystem* drm_system = static_cast<DrmSystem*>(context);
DCHECK_EQ(wrapped_drm_system, drm_system->wrapped_drm_system_);
- drm_system->OnSessionUpdateRequestGenerated(
- ticket, session_id, session_id_size, content, content_size);
+ base::optional<std::string> session_id_copy;
+ scoped_array<uint8> content_copy;
+ if (session_id) {
+ session_id_copy =
+ std::string(static_cast<const char*>(session_id),
+ static_cast<const char*>(session_id) + session_id_size);
+
+ content_copy.reset(new uint8[content_size]);
+ SbMemoryCopy(content_copy.get(), content, content_size);
+ }
+
+ drm_system->message_loop_->PostTask(
+ FROM_HERE, base::Bind(&DrmSystem::OnSessionUpdateRequestGenerated,
+ drm_system->weak_this_, ticket, session_id_copy,
+ base::Passed(&content_copy), content_size));
}
// static
void DrmSystem::OnSessionUpdatedFunc(SbDrmSystem wrapped_drm_system,
void* context, int ticket,
- const void* session_id,
- int session_id_size, bool succeeded) {
+ const void* /*session_id*/,
+ int /*session_id_size*/, bool succeeded) {
DCHECK(context);
DrmSystem* drm_system = static_cast<DrmSystem*>(context);
DCHECK_EQ(wrapped_drm_system, drm_system->wrapped_drm_system_);
- drm_system->OnSessionUpdated(ticket, session_id, session_id_size, succeeded);
+ drm_system->message_loop_->PostTask(
+ FROM_HERE, base::Bind(&DrmSystem::OnSessionUpdated,
+ drm_system->weak_this_, ticket, succeeded));
}
} // namespace media
diff --git a/src/cobalt/media/base/drm_system.h b/src/cobalt/media/base/drm_system.h
index 018c428..8596241 100644
--- a/src/cobalt/media/base/drm_system.h
+++ b/src/cobalt/media/base/drm_system.h
@@ -17,8 +17,11 @@
#include <string>
+#include "base/hash_tables.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
-#include "cobalt/media/base/drm_system_client.h"
+#include "base/optional.h"
#include "starboard/drm.h"
#if SB_API_VERSION < 4
@@ -30,32 +33,122 @@
// A C++ wrapper around |SbDrmSystem|.
//
-// Ensures that calls to |DrmSystemClient| are always asynchronous and performed
+// Ensures that callbacks are always asynchronous and performed
// from the same thread where |DrmSystem| was instantiated.
class DrmSystem {
public:
- DrmSystem(const char* key_system, DrmSystemClient* client);
+ typedef base::Callback<void(scoped_array<uint8> message, int message_size)>
+ SessionUpdateRequestGeneratedCallback;
+ typedef base::Callback<void()> SessionUpdateRequestDidNotGenerateCallback;
+ typedef base::Callback<void()> SessionUpdatedCallback;
+ typedef base::Callback<void()> SessionDidNotUpdateCallback;
+
+ // Flyweight that provides RAII semantics for sessions.
+ // Most of logic is implemented by |DrmSystem|.
+ class Session {
+ public:
+ ~Session();
+
+ const base::optional<std::string>& id() const { return id_; }
+
+ // Wraps |SbDrmGenerateSessionUpdateRequest|.
+ //
+ // |session_update_request_generated_callback| is called upon a successful
+ // request generation. IMPORTANT: It may be called multiple times after
+ // a single call to |CreateSessionAndGenerateUpdateRequest|, for example
+ // when the underlying DRM system needs to update a license.
+ //
+ // |session_update_request_did_not_generate_callback| is called upon a
+ // failure during request generation. Unlike its successful counterpart,
+ // never called spontaneously.
+ void GenerateUpdateRequest(
+ const std::string& type, const uint8* init_data, int init_data_length,
+ const SessionUpdateRequestGeneratedCallback&
+ session_update_request_generated_callback,
+ const SessionUpdateRequestDidNotGenerateCallback&
+ session_update_request_did_not_generate_callback);
+
+ // Wraps |SbDrmUpdateSession|.
+ //
+ // |session_updated_callback| is called upon a successful session update.
+ // |session_did_not_update_callback| is called upon a failure during session
+ // update.
+ void Update(
+ const uint8* key, int key_length,
+ const SessionUpdatedCallback& session_updated_callback,
+ const SessionDidNotUpdateCallback& session_did_not_update_callback);
+
+ // Wraps |SbDrmCloseSession|.
+ void Close();
+ bool is_closed() const { return closed_; }
+
+ private:
+ // Private API for |DrmSystem|.
+ explicit Session(DrmSystem* drm_system);
+ void set_id(const std::string& id) { id_ = id; }
+ const SessionUpdateRequestGeneratedCallback&
+ update_request_generated_callback() const {
+ return update_request_generated_callback_;
+ }
+
+ DrmSystem* const drm_system_;
+ bool closed_;
+ base::optional<std::string> id_;
+ // Supports spontaneous invocations of |SbDrmSessionUpdateRequestFunc|.
+ SessionUpdateRequestGeneratedCallback update_request_generated_callback_;
+
+ friend class DrmSystem;
+
+ DISALLOW_COPY_AND_ASSIGN(Session);
+ };
+
+ explicit DrmSystem(const char* key_system);
~DrmSystem();
SbDrmSystem wrapped_drm_system() { return wrapped_drm_system_; }
- // Wraps |SbDrmGenerateSessionUpdateRequest|.
- void GenerateSessionUpdateRequest(int ticket, const std::string& type,
- const uint8* init_data,
- int init_data_length);
- // Wraps |SbDrmUpdateSession|.
- void UpdateSession(int ticket, const std::string& session_id,
- const uint8* key, int key_length);
- // Wraps |SbDrmCloseSession|.
- void CloseSession(const std::string& session_id);
+ scoped_ptr<Session> CreateSession();
private:
- void OnSessionUpdateRequestGenerated(int ticket, const void* session_id,
- int session_id_size, const void* content,
- int content_size);
- void OnSessionUpdated(int ticket, const void* session_id, int session_id_size,
- bool succeeded);
+ // Stores context of |GenerateSessionUpdateRequest|.
+ struct SessionUpdateRequest {
+ Session* session;
+ SessionUpdateRequestGeneratedCallback generated_callback;
+ SessionUpdateRequestDidNotGenerateCallback did_not_generate_callback;
+ };
+ typedef base::hash_map<int, SessionUpdateRequest>
+ TicketToSessionUpdateRequestMap;
+ typedef base::hash_map<std::string, Session*> IdToSessionMap;
+
+ // Stores context of |Session::Update|.
+ struct SessionUpdate {
+ SessionUpdatedCallback updated_callback;
+ SessionDidNotUpdateCallback did_not_update_callback;
+ };
+ typedef base::hash_map<int, SessionUpdate> TicketToSessionUpdateMap;
+
+ // Private API for |Session|.
+ void GenerateSessionUpdateRequest(
+ Session* session, const std::string& type, const uint8_t* init_data,
+ int init_data_length, const SessionUpdateRequestGeneratedCallback&
+ session_update_request_generated_callback,
+ const SessionUpdateRequestDidNotGenerateCallback&
+ session_update_request_did_not_generate_callback);
+ void UpdateSession(
+ const std::string& session_id, const uint8_t* key, int key_length,
+ const SessionUpdatedCallback& session_updated_callback,
+ const SessionDidNotUpdateCallback& session_did_not_update_callback);
+ void CloseSession(const std::string& session_id);
+
+ // Called on the constructor thread, parameters are copied and owned by these
+ // methods.
+ void OnSessionUpdateRequestGenerated(
+ int ticket, const base::optional<std::string>& session_id,
+ scoped_array<uint8> message, int message_size);
+ void OnSessionUpdated(int ticket, bool succeeded);
+
+ // Called on any thread, parameters need to be copied immediately.
static void OnSessionUpdateRequestGeneratedFunc(
SbDrmSystem wrapped_drm_system, void* context, int ticket,
const void* session_id, int session_id_size, const void* content,
@@ -65,10 +158,26 @@
const void* session_id,
int session_id_length, bool succeeded);
- DrmSystemClient* const client_;
const SbDrmSystem wrapped_drm_system_;
MessageLoop* const message_loop_;
+ // Factory should only be used to create the initial weak pointer. All
+ // subsequent weak pointers are created by copying the initial one. This is
+ // required to keep weak pointers bound to the constructor thread.
+ base::WeakPtrFactory<DrmSystem> weak_ptr_factory_;
+ base::WeakPtr<DrmSystem> weak_this_;
+
+ // Supports concurrent calls to |GenerateSessionUpdateRequest|.
+ int next_session_update_request_ticket_;
+ TicketToSessionUpdateRequestMap ticket_to_session_update_request_map_;
+
+ // Supports spontaneous invocations of |SbDrmSessionUpdateRequestFunc|.
+ IdToSessionMap id_to_session_map_;
+
+ // Supports concurrent calls to |Session::Update|.
+ int next_session_update_ticket_;
+ TicketToSessionUpdateMap ticket_to_session_update_map_;
+
DISALLOW_COPY_AND_ASSIGN(DrmSystem);
};
diff --git a/src/cobalt/media/base/drm_system_client.h b/src/cobalt/media/base/drm_system_client.h
deleted file mode 100644
index a0fddfe..0000000
--- a/src/cobalt/media/base/drm_system_client.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef COBALT_MEDIA_BASE_DRM_SYSTEM_CLIENT_H_
-#define COBALT_MEDIA_BASE_DRM_SYSTEM_CLIENT_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-
-namespace cobalt {
-namespace media {
-
-// An interface to be implemented by clients of |DrmSystem|.
-//
-// Calls to |DrmSystemClient| are always performed from the same thread
-// where |DrmSystem| was instantiated.
-class DrmSystemClient {
- public:
- // When called as a result of |DrmSystem::GenerateSessionUpdateRequest|, this
- // method denotes a successful request generation.
- //
- // This method may be called multiple times after a single call to
- // |GenerateSessionUpdateRequest|, for example when the underlying DRM system
- // needs to update a license. In this case |ticket| will be
- // |kSbDrmTicketInvalid|.
- virtual void OnSessionUpdateRequestGenerated(int ticket,
- const std::string& session_id,
- scoped_array<uint8> message,
- int message_size) = 0;
- // Called as a result of |GenerateSessionUpdateRequest| and denotes a failure
- // during request generation.
- //
- // Unlike its successful counterpart, never called spontaneously.
- virtual void OnSessionUpdateRequestDidNotGenerate(int ticket) = 0;
-
- // Called as a result of |UpdateSession| and denotes a successful session
- // update.
- virtual void OnSessionUpdated(int ticket) = 0;
- // Called as a result of |UpdateSession| and denotes a failure during session
- // update.
- virtual void OnSessionDidNotUpdate(int ticket) = 0;
-
- protected:
- virtual ~DrmSystemClient() {}
-};
-
-} // namespace media
-} // namespace cobalt
-
-#endif // COBALT_MEDIA_BASE_DRM_SYSTEM_CLIENT_H_
diff --git a/src/cobalt/media/media2.gyp b/src/cobalt/media/media2.gyp
index 18c1683..982b364 100644
--- a/src/cobalt/media/media2.gyp
+++ b/src/cobalt/media/media2.gyp
@@ -65,7 +65,6 @@
'base/demuxer_stream_provider.h',
'base/drm_system.cc',
'base/drm_system.h',
- 'base/drm_system_client.h',
'base/encryption_scheme.cc',
'base/encryption_scheme.h',
'base/hdr_metadata.cc',
diff --git a/src/cobalt/media/media_module.cc b/src/cobalt/media/media_module.cc
index d92a105..d444ea8 100644
--- a/src/cobalt/media/media_module.cc
+++ b/src/cobalt/media/media_module.cc
@@ -86,6 +86,8 @@
void MediaModule::SuspendTask() {
DCHECK(message_loop_->BelongsToCurrentThread());
+ suspended_ = true;
+
for (Players::iterator iter = players_.begin(); iter != players_.end();
++iter) {
DCHECK(!iter->second);
@@ -105,6 +107,8 @@
iter->first->Resume();
}
}
+
+ suspended_ = false;
}
void MediaModule::RegisterPlayerTask(WebMediaPlayer* player) {
@@ -115,6 +119,10 @@
// Track debug state for the most recently added WebMediaPlayer instance.
RegisterDebugState(player);
+
+ if (suspended_) {
+ player->Suspend();
+ }
}
void MediaModule::UnregisterPlayerTask(WebMediaPlayer* player) {
diff --git a/src/cobalt/media/media_module.h b/src/cobalt/media/media_module.h
index f45ef44..f4b10c2 100644
--- a/src/cobalt/media/media_module.h
+++ b/src/cobalt/media/media_module.h
@@ -118,7 +118,7 @@
protected:
explicit MediaModule(const math::Size& output_size)
- : thread_("media_module"), output_size_(output_size) {
+ : thread_("media_module"), output_size_(output_size), suspended_(false) {
thread_.Start();
message_loop_ = thread_.message_loop_proxy();
}
@@ -140,6 +140,7 @@
scoped_refptr<base::MessageLoopProxy> message_loop_;
Players players_;
math::Size output_size_;
+ bool suspended_;
};
} // namespace media
diff --git a/src/cobalt/media/player/web_media_player.h b/src/cobalt/media/player/web_media_player.h
index 6cd7800..f81d2ad 100644
--- a/src/cobalt/media/player/web_media_player.h
+++ b/src/cobalt/media/player/web_media_player.h
@@ -165,27 +165,6 @@
return false;
}
- // Returns whether keySystem is supported. If true, the result will be
- // reported by an event.
- virtual MediaKeyException GenerateKeyRequest(
- const std::string& /* key_system */, const unsigned char* /* init_data */,
- unsigned /* init_data_length */) {
- return kMediaKeyExceptionKeySystemNotSupported;
- }
- virtual MediaKeyException AddKey(const std::string& /* key_system */,
- const unsigned char* /* key */,
- unsigned /* key_length */,
- const unsigned char* /* init_data */,
- unsigned /* init_data_length */,
- const std::string& /* session_id */) {
- return kMediaKeyExceptionKeySystemNotSupported;
- }
- virtual MediaKeyException CancelKeyRequest(
- const std::string& /* key_system */,
- const std::string& /* session_id */) {
- return kMediaKeyExceptionKeySystemNotSupported;
- }
-
virtual SetBoundsCB GetSetBoundsCB() { return SetBoundsCB(); }
// Instruct WebMediaPlayer to enter/exit fullscreen.
@@ -213,21 +192,6 @@
// as |NetworkStateChanged|, |SourceOpened|, |EncryptedMediaInitData|.
class WebMediaPlayerClient {
public:
- enum MediaKeyErrorCode {
- kMediaKeyErrorCodeUnknown = 1,
- kMediaKeyErrorCodeClient,
- kMediaKeyErrorCodeService,
- kMediaKeyErrorCodeOutput,
- kMediaKeyErrorCodeHardwareChange,
- kMediaKeyErrorCodeDomain,
- kUnknownError = kMediaKeyErrorCodeUnknown,
- kClientError = kMediaKeyErrorCodeClient,
- kServiceError = kMediaKeyErrorCodeService,
- kOutputError = kMediaKeyErrorCodeOutput,
- kHardwareChangeError = kMediaKeyErrorCodeHardwareChange,
- kDomainError = kMediaKeyErrorCodeDomain,
- };
-
virtual void NetworkStateChanged() = 0;
virtual void ReadyStateChanged() = 0;
virtual void TimeChanged() = 0;
@@ -248,34 +212,9 @@
// Notifies the client that a video is encrypted. Client is supposed to call
// |WebMediaPlayer::SetDrmSystem| as soon as possible to avoid stalling
// playback.
- virtual void EncryptedMediaInitData(EmeInitDataType init_data_type,
- const unsigned char* init_data,
- unsigned init_data_length) = 0;
- // TODO: Make the EME related functions pure virtual again once
- // we have proper EME implementation. Currently empty implementation are
- // provided to make media temporarily work.
- virtual void KeyAdded(const std::string& /* key_system */,
- const std::string& /* session_id */) {
- NOTIMPLEMENTED();
- }
- virtual void KeyError(const std::string& /* key_system */,
- const std::string& /* session_id */, MediaKeyErrorCode,
- unsigned short /* system_code */) {
- NOTIMPLEMENTED();
- }
- virtual void KeyMessage(const std::string& /* key_system */,
- const std::string& /* session_id */,
- const unsigned char* /* message */,
- unsigned /* message_length */,
- const std::string& /* default_url */) {
- NOTIMPLEMENTED();
- }
- virtual void KeyNeeded(const std::string& /* key_system */,
- const std::string& /* session_id */,
- const unsigned char* /* init_data */,
- unsigned /* init_data_length */) {
- NOTIMPLEMENTED();
- }
+ virtual void EncryptedMediaInitDataEncountered(EmeInitDataType init_data_type,
+ const unsigned char* init_data,
+ unsigned init_data_length) = 0;
// TODO: Revisit the necessity of the following functions.
virtual void CloseHelperPlugin() { NOTREACHED(); }
virtual void DisableAcceleratedCompositing() {}
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc
index 7bff85f..c8477bd 100644
--- a/src/cobalt/media/player/web_media_player_impl.cc
+++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -213,7 +213,8 @@
chunk_demuxer_.reset(new ChunkDemuxer(
buffer_allocator_,
BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData),
+ BIND_TO_RENDER_LOOP(
+ &WebMediaPlayerImpl::OnEncryptedMediaInitDataEncountered),
media_log_, true));
supports_save_ = false;
@@ -757,12 +758,12 @@
*is_seeking = state_.seeking;
}
-void WebMediaPlayerImpl::OnEncryptedMediaInitData(
+void WebMediaPlayerImpl::OnEncryptedMediaInitDataEncountered(
EmeInitDataType init_data_type, const std::vector<uint8_t>& init_data) {
DCHECK_EQ(main_loop_, MessageLoop::current());
- GetClient()->EncryptedMediaInitData(init_data_type, &init_data[0],
- init_data.size());
+ GetClient()->EncryptedMediaInitDataEncountered(init_data_type, &init_data[0],
+ init_data.size());
}
WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() {
diff --git a/src/cobalt/media/player/web_media_player_impl.h b/src/cobalt/media/player/web_media_player_impl.h
index 9df3e68..3babef5 100644
--- a/src/cobalt/media/player/web_media_player_impl.h
+++ b/src/cobalt/media/player/web_media_player_impl.h
@@ -209,8 +209,8 @@
void GetMediaTimeAndSeekingState(base::TimeDelta* media_time,
bool* is_seeking) const;
- void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
- const std::vector<uint8_t>& init_data);
+ void OnEncryptedMediaInitDataEncountered(
+ EmeInitDataType init_data_type, const std::vector<uint8_t>& init_data);
// Getter method to |client_|.
WebMediaPlayerClient* GetClient();
diff --git a/src/cobalt/media/sandbox/web_media_player_helper.cc b/src/cobalt/media/sandbox/web_media_player_helper.cc
index 2adef29..adb3afe 100644
--- a/src/cobalt/media/sandbox/web_media_player_helper.cc
+++ b/src/cobalt/media/sandbox/web_media_player_helper.cc
@@ -47,9 +47,9 @@
#endif // defined(COBALT_MEDIA_SOURCE_2016)
std::string SourceURL() const OVERRIDE { return ""; }
#if defined(COBALT_MEDIA_SOURCE_2016)
- void EncryptedMediaInitData(EmeInitDataType init_data_type,
- const unsigned char* init_data,
- unsigned init_data_length) OVERRIDE {}
+ void EncryptedMediaInitDataEncountered(EmeInitDataType init_data_type,
+ const unsigned char* init_data,
+ unsigned init_data_length) OVERRIDE {}
#endif // defined(COBALT_MEDIA_SOURCE_2016)
};
diff --git a/src/cobalt/render_tree/mock_resource_provider.h b/src/cobalt/render_tree/mock_resource_provider.h
index 0fba09f..1d13b6c 100644
--- a/src/cobalt/render_tree/mock_resource_provider.h
+++ b/src/cobalt/render_tree/mock_resource_provider.h
@@ -164,8 +164,6 @@
Mesh::DrawMode draw_mode) {
return make_scoped_refptr(CreateMeshMock(vertices.get(), draw_mode));
}
-
- virtual void PurgeCaches() {}
};
} // namespace render_tree
diff --git a/src/cobalt/render_tree/resource_provider.h b/src/cobalt/render_tree/resource_provider.h
index be1c28e..4a648d1 100644
--- a/src/cobalt/render_tree/resource_provider.h
+++ b/src/cobalt/render_tree/resource_provider.h
@@ -210,17 +210,13 @@
render_tree::FontProvider* font_provider,
render_tree::FontVector* maybe_used_fonts) = 0;
- // Cconsumes a list of vertices and returns
- // a Mesh instance.
+ // Consumes a list of vertices and returns a Mesh instance.
virtual scoped_refptr<Mesh> CreateMesh(
scoped_ptr<std::vector<Mesh::Vertex> > vertices,
Mesh::DrawMode draw_mode) = 0;
virtual scoped_refptr<Image> DrawOffscreenImage(
const scoped_refptr<render_tree::Node>& root) = 0;
-
- // Purges any caches being used by the render_tree consumer.
- virtual void PurgeCaches() = 0;
};
} // namespace render_tree
diff --git a/src/cobalt/render_tree/resource_provider_stub.h b/src/cobalt/render_tree/resource_provider_stub.h
index 0f70147..5d33cd0 100644
--- a/src/cobalt/render_tree/resource_provider_stub.h
+++ b/src/cobalt/render_tree/resource_provider_stub.h
@@ -331,8 +331,6 @@
UNREFERENCED_PARAMETER(root);
return scoped_refptr<Image>(NULL);
}
-
- void PurgeCaches() OVERRIDE {}
};
} // namespace render_tree
diff --git a/src/cobalt/renderer/backend/backend.gyp b/src/cobalt/renderer/backend/backend.gyp
index d1f4aa2..b2f6e71 100644
--- a/src/cobalt/renderer/backend/backend.gyp
+++ b/src/cobalt/renderer/backend/backend.gyp
@@ -16,7 +16,11 @@
'targets': [
{
'target_name': 'renderer_backend',
- 'type': 'none',
+ 'type': 'static_library',
+ 'sources': [
+ 'render_target.cc',
+ 'render_target.h',
+ ],
'dependencies': [
'<(DEPTH)/cobalt/base/base.gyp:base',
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.cc b/src/cobalt/renderer/backend/egl/graphics_context.cc
index 7b8b9bd..1211584 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_context.cc
@@ -245,7 +245,22 @@
// that can be bound using eglMakeCurrent.
DCHECK_EQ(surface->GetPlatformHandle(), 0);
- EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
+ eglMakeCurrent(display_, egl_surface, egl_surface, context_);
+ EGLint make_current_error = eglGetError();
+ if (make_current_error != EGL_SUCCESS) {
+ LOG(ERROR) << "eglMakeCurrent ERROR: " << make_current_error;
+ if (make_current_error == EGL_BAD_ALLOC ||
+ make_current_error == EGL_BAD_NATIVE_WINDOW) {
+ LOG(ERROR) << "eglMakeCurrent raised either EGL_BAD_ALLOC or "
+ "EGL_BAD_NATIVE_WINDOW, continuing with null surface "
+ "under the assumption that our window surface has become "
+ "invalid due to a suspend or shutdown being triggered.";
+ egl_surface = null_surface_->GetSurface();
+ EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
+ } else {
+ NOTREACHED() << "Unexpected error when calling eglMakeCurrent().";
+ }
+ }
// Minimize calls to glBindFramebuffer. Normally, nothing keeps their
// framebuffer object bound, so 0 is normally bound at this point --
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/cobalt/renderer/backend/render_target.cc
similarity index 62%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/cobalt/renderer/backend/render_target.cc
index 51e1f2e..3126b97 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/cobalt/renderer/backend/render_target.cc
@@ -12,9 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "cobalt/renderer/backend/render_target.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include "starboard/atomic.h"
+
+namespace cobalt {
+namespace renderer {
+namespace backend {
+
+SbAtomic32 RenderTarget::serial_counter_ = 1;
+
+RenderTarget::RenderTarget() {
+ serial_number_ = SbAtomicBarrier_Increment(&serial_counter_, 1);
+}
+
+} // namespace backend
+} // namespace renderer
+} // namespace cobalt
diff --git a/src/cobalt/renderer/backend/render_target.h b/src/cobalt/renderer/backend/render_target.h
index ebaa335..fef9bc6 100644
--- a/src/cobalt/renderer/backend/render_target.h
+++ b/src/cobalt/renderer/backend/render_target.h
@@ -34,6 +34,8 @@
// after rendering is completed.
class RenderTarget : public base::RefCountedThreadSafe<RenderTarget> {
public:
+ RenderTarget();
+
// Return metadata about the render target such as dimensions and format.
virtual const math::Size& GetSize() = 0;
@@ -41,10 +43,16 @@
// passed into platform-specific code.
virtual intptr_t GetPlatformHandle() = 0;
+ // Each render is assigned a unique serial number on construction.
+ int32_t GetSerialNumber() const { return serial_number_; }
+
protected:
// Concrete child classes should declare their destructors as private.
friend class base::RefCountedThreadSafe<RenderTarget>;
virtual ~RenderTarget() {}
+
+ static SbAtomic32 serial_counter_;
+ int32_t serial_number_;
};
} // namespace backend
diff --git a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
index d7cf41c..1c5e2d4 100644
--- a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
@@ -34,13 +34,13 @@
return coord_mapping.output_bounds.size().GetArea() * 4;
}
-CachedSoftwareRasterizer::CachedSoftwareRasterizer(SbBlitterDevice device,
- SbBlitterContext context,
- int cache_capacity)
+CachedSoftwareRasterizer::CachedSoftwareRasterizer(
+ SbBlitterDevice device, SbBlitterContext context, int cache_capacity,
+ bool purge_skia_font_caches_on_destruction)
: cache_capacity_(cache_capacity),
device_(device),
context_(context),
- software_rasterizer_(0),
+ software_rasterizer_(0, purge_skia_font_caches_on_destruction),
cache_memory_usage_(
"Memory.CachedSoftwareRasterizer.CacheUsage", 0,
"Total memory occupied by cached software-rasterized surfaces."),
@@ -56,6 +56,7 @@
DCHECK(iter->second.cached);
SbBlitterDestroySurface(iter->second.surface);
}
+ surface_map_.clear();
}
void CachedSoftwareRasterizer::OnStartNewFrame() {
diff --git a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h
index 99cefba..ce37064 100644
--- a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h
@@ -73,7 +73,8 @@
};
CachedSoftwareRasterizer(SbBlitterDevice device, SbBlitterContext context,
- int cache_capacity);
+ int cache_capacity,
+ bool purge_skia_font_caches_on_destruction);
~CachedSoftwareRasterizer();
// Should be called once per frame. This method will remove from the cache
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
index a67044e..2ed5599 100644
--- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
@@ -46,7 +46,8 @@
int skia_atlas_width, int skia_atlas_height,
int scratch_surface_size_in_bytes,
int surface_cache_size_in_bytes,
- int software_surface_cache_size_in_bytes);
+ int software_surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction);
~Impl();
void Submit(const scoped_refptr<render_tree::Node>& render_tree,
@@ -99,7 +100,8 @@
int skia_atlas_width, int skia_atlas_height,
int scratch_surface_size_in_bytes,
int surface_cache_size_in_bytes,
- int software_surface_cache_size_in_bytes)
+ int software_surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction)
: context_(base::polymorphic_downcast<backend::GraphicsContextBlitter*>(
graphics_context)),
submit_count_(0),
@@ -109,7 +111,8 @@
scratch_surface_size_in_bytes),
software_surface_cache_(context_->GetSbBlitterDevice(),
context_->GetSbBlitterContext(),
- software_surface_cache_size_in_bytes)
+ software_surface_cache_size_in_bytes,
+ purge_skia_font_caches_on_destruction)
#if defined(ENABLE_DEBUG_CONSOLE)
,
toggle_highlight_software_draws_(false),
@@ -294,15 +297,14 @@
#endif // #if defined(COBALT_RENDER_DIRTY_REGION_ONLY)
HardwareRasterizer::HardwareRasterizer(
- backend::GraphicsContext* graphics_context,
- int skia_atlas_width, int skia_atlas_height,
- int scratch_surface_size_in_bytes, int surface_cache_size_in_bytes,
- int software_surface_cache_size_in_bytes)
- : impl_(new Impl(graphics_context,
- skia_atlas_width, skia_atlas_height,
- scratch_surface_size_in_bytes,
- surface_cache_size_in_bytes,
- software_surface_cache_size_in_bytes)) {}
+ backend::GraphicsContext* graphics_context, int skia_atlas_width,
+ int skia_atlas_height, int scratch_surface_size_in_bytes,
+ int surface_cache_size_in_bytes, int software_surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction)
+ : impl_(new Impl(graphics_context, skia_atlas_width, skia_atlas_height,
+ scratch_surface_size_in_bytes, surface_cache_size_in_bytes,
+ software_surface_cache_size_in_bytes,
+ purge_skia_font_caches_on_destruction)) {}
HardwareRasterizer::~HardwareRasterizer() {}
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h
index 20afd3e..e830221 100644
--- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h
@@ -40,7 +40,8 @@
int skia_atlas_width, int skia_atlas_height,
int scratch_surface_size_in_bytes,
int surface_cache_size_in_bytes,
- int software_surface_cache_size_in_bytes);
+ int software_surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction);
virtual ~HardwareRasterizer();
// Consume the render tree and output the results to the render target passed
diff --git a/src/cobalt/renderer/rasterizer/blitter/resource_provider.cc b/src/cobalt/renderer/rasterizer/blitter/resource_provider.cc
index f72fafa..2315836 100644
--- a/src/cobalt/renderer/rasterizer/blitter/resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/resource_provider.cc
@@ -213,8 +213,6 @@
new SinglePlaneImage(root, submit_offscreen_callback_, device_));
}
-void ResourceProvider::PurgeCaches() { skia_resource_provider_->PurgeCaches(); }
-
} // namespace blitter
} // namespace rasterizer
} // namespace renderer
diff --git a/src/cobalt/renderer/rasterizer/blitter/resource_provider.h b/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
index bf67280..3f01c64 100644
--- a/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
@@ -113,8 +113,6 @@
scoped_refptr<render_tree::Image> DrawOffscreenImage(
const scoped_refptr<render_tree::Node>& root) OVERRIDE;
- void PurgeCaches() OVERRIDE;
-
private:
SbBlitterDevice device_;
diff --git a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc
index f8e683c..33dc2d1 100644
--- a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc
@@ -29,11 +29,13 @@
namespace rasterizer {
namespace blitter {
-SoftwareRasterizer::SoftwareRasterizer(backend::GraphicsContext* context,
- int surface_cache_size)
+SoftwareRasterizer::SoftwareRasterizer(
+ backend::GraphicsContext* context, int surface_cache_size,
+ bool purge_skia_font_caches_on_destruction)
: context_(base::polymorphic_downcast<backend::GraphicsContextBlitter*>(
context)),
- skia_rasterizer_(surface_cache_size) {}
+ skia_rasterizer_(surface_cache_size,
+ purge_skia_font_caches_on_destruction) {}
void SoftwareRasterizer::Submit(
const scoped_refptr<render_tree::Node>& render_tree,
diff --git a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
index b868493..5c5d533 100644
--- a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
@@ -38,7 +38,8 @@
class SoftwareRasterizer : public Rasterizer {
public:
explicit SoftwareRasterizer(backend::GraphicsContext* context,
- int surface_cache_size);
+ int surface_cache_size,
+ bool purge_skia_font_caches_on_destruction);
void Submit(const scoped_refptr<render_tree::Node>& render_tree,
const scoped_refptr<backend::RenderTarget>& render_target,
diff --git a/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.cc
index 2cc8005..10c3a9d 100644
--- a/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.cc
@@ -46,7 +46,8 @@
int skia_atlas_width, int skia_atlas_height,
int skia_cache_size_in_bytes,
int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes);
+ int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction);
~Impl();
void Submit(const scoped_refptr<render_tree::Node>& render_tree,
@@ -85,11 +86,13 @@
int skia_atlas_width, int skia_atlas_height,
int skia_cache_size_in_bytes,
int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes)
+ int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction)
: fallback_rasterizer_(new skia::HardwareRasterizer(
graphics_context, skia_atlas_width, skia_atlas_height,
skia_cache_size_in_bytes, scratch_surface_cache_size_in_bytes,
- 0 /* fallback rasterizer should not use a surface cache */)),
+ 0 /* fallback rasterizer should not use a surface cache */,
+ purge_skia_font_caches_on_destruction)),
graphics_context_(
base::polymorphic_downcast<backend::GraphicsContextEGL*>(
graphics_context)) {
@@ -271,11 +274,13 @@
HardwareRasterizer::HardwareRasterizer(
backend::GraphicsContext* graphics_context, int skia_atlas_width,
int skia_atlas_height, int skia_cache_size_in_bytes,
- int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes)
- : impl_(new Impl(graphics_context, skia_atlas_width, skia_atlas_height,
- skia_cache_size_in_bytes,
- scratch_surface_cache_size_in_bytes,
- surface_cache_size_in_bytes)) {}
+ int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction)
+ : impl_(new Impl(
+ graphics_context, skia_atlas_width, skia_atlas_height,
+ skia_cache_size_in_bytes, scratch_surface_cache_size_in_bytes,
+ surface_cache_size_in_bytes, purge_skia_font_caches_on_destruction)) {
+}
void HardwareRasterizer::Submit(
const scoped_refptr<render_tree::Node>& render_tree,
diff --git a/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.h b/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.h
index dc5c9b4..dc03019 100644
--- a/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/egl/hardware_rasterizer.h
@@ -49,7 +49,8 @@
int skia_atlas_width, int skia_atlas_height,
int skia_cache_size_in_bytes,
int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes);
+ int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction);
void Submit(const scoped_refptr<render_tree::Node>& render_tree,
const scoped_refptr<backend::RenderTarget>& render_target,
diff --git a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
index 319f6ed..c567846 100644
--- a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
@@ -30,11 +30,13 @@
namespace rasterizer {
namespace egl {
-SoftwareRasterizer::SoftwareRasterizer(backend::GraphicsContext* context,
- int surface_cache_size)
+SoftwareRasterizer::SoftwareRasterizer(
+ backend::GraphicsContext* context, int surface_cache_size,
+ bool purge_skia_font_caches_on_destruction)
: context_(
base::polymorphic_downcast<backend::GraphicsContextEGL*>(context)),
- skia_rasterizer_(surface_cache_size) {}
+ skia_rasterizer_(surface_cache_size,
+ purge_skia_font_caches_on_destruction) {}
void SoftwareRasterizer::Submit(
const scoped_refptr<render_tree::Node>& render_tree,
diff --git a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
index ce906c0..afb3c0b 100644
--- a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
@@ -38,7 +38,8 @@
class SoftwareRasterizer : public Rasterizer {
public:
explicit SoftwareRasterizer(backend::GraphicsContext* context,
- int surface_cache_size);
+ int surface_cache_size,
+ bool purge_skia_font_caches_on_destruction);
void Submit(const scoped_refptr<render_tree::Node>& render_tree,
const scoped_refptr<backend::RenderTarget>& render_target,
diff --git a/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc b/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
index 8ac80c8..5ce02f6 100644
--- a/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/lib/external_rasterizer.cc
@@ -35,7 +35,8 @@
int skia_atlas_width, int skia_atlas_height,
int skia_cache_size_in_bytes,
int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes);
+ int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction);
~Impl();
void Submit(const scoped_refptr<render_tree::Node>& render_tree,
@@ -62,14 +63,16 @@
int skia_atlas_width, int skia_atlas_height,
int skia_cache_size_in_bytes,
int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes)
+ int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction)
: graphics_context_(
base::polymorphic_downcast<backend::GraphicsContextEGL*>(
graphics_context)),
hardware_rasterizer_(graphics_context, skia_atlas_width,
skia_atlas_height, skia_cache_size_in_bytes,
scratch_surface_cache_size_in_bytes,
- surface_cache_size_in_bytes) {
+ surface_cache_size_in_bytes,
+ purge_skia_font_caches_on_destruction) {
options_.flags = skia::HardwareRasterizer::kSubmitFlags_Clear;
graphics_context_->MakeCurrent();
@@ -120,11 +123,13 @@
ExternalRasterizer::ExternalRasterizer(
backend::GraphicsContext* graphics_context, int skia_atlas_width,
int skia_atlas_height, int skia_cache_size_in_bytes,
- int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes)
+ int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction)
: impl_(new Impl(graphics_context, skia_atlas_width, skia_atlas_height,
skia_cache_size_in_bytes,
scratch_surface_cache_size_in_bytes,
- surface_cache_size_in_bytes)) {}
+ surface_cache_size_in_bytes,
+ purge_skia_font_caches_on_destruction)) {}
ExternalRasterizer::~ExternalRasterizer() {}
diff --git a/src/cobalt/renderer/rasterizer/lib/external_rasterizer.h b/src/cobalt/renderer/rasterizer/lib/external_rasterizer.h
index 49ffc32..16f6f66 100644
--- a/src/cobalt/renderer/rasterizer/lib/external_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/lib/external_rasterizer.h
@@ -37,7 +37,8 @@
int skia_atlas_width, int skia_atlas_height,
int skia_cache_size_in_bytes,
int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes);
+ int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction);
virtual ~ExternalRasterizer();
void Submit(const scoped_refptr<render_tree::Node>& render_tree,
diff --git a/src/cobalt/renderer/rasterizer/lib/imported/graphics.h b/src/cobalt/renderer/rasterizer/lib/imported/graphics.h
index 125f85f..cde0573 100644
--- a/src/cobalt/renderer/rasterizer/lib/imported/graphics.h
+++ b/src/cobalt/renderer/rasterizer/lib/imported/graphics.h
@@ -18,20 +18,21 @@
#ifndef COBALT_RENDERER_RASTERIZER_LIB_IMPORTED_GRAPHICS_H_
#define COBALT_RENDERER_RASTERIZER_LIB_IMPORTED_GRAPHICS_H_
-// TODO: Use starboard/types.h instead.
-#include <stdint.h>
+#include "starboard/export.h"
+#include "starboard/types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
// Invoked from the rasterization thread after the GL context has been created.
-void CbLibOnGraphicsContextCreated();
+SB_IMPORT_PLATFORM void CbLibOnGraphicsContextCreated();
// Invoked as often as the platform can swap buffers from the rasterization
// thread. |render_tree_texture_handle| corresponds to a GLint texture ID for
// the current RenderTree.
-void CbLibRenderFrame(intptr_t render_tree_texture_handle);
+SB_IMPORT_PLATFORM void CbLibRenderFrame(intptr_t render_tree_texture_handle);
#ifdef __cplusplus
} // extern "C"
diff --git a/src/cobalt/renderer/rasterizer/lib/imported/graphics_stub.cc b/src/cobalt/renderer/rasterizer/lib/imported/graphics_stub.cc
new file mode 100644
index 0000000..5d9ece0
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/lib/imported/graphics_stub.cc
@@ -0,0 +1,8 @@
+#include "cobalt/renderer/rasterizer/lib/imported/graphics.h"
+
+// Empty implementations so that 'lib' targets can be compiled into executables
+// by the builder without missing symbol definitions.
+void CbLibOnGraphicsContextCreated() {}
+void CbLibRenderFrame(intptr_t render_tree_texture_handle) {
+ (void)render_tree_texture_handle;
+}
diff --git a/src/cobalt/renderer/rasterizer/lib/lib.gyp b/src/cobalt/renderer/rasterizer/lib/lib.gyp
index 3ff61a8..df38bb4 100644
--- a/src/cobalt/renderer/rasterizer/lib/lib.gyp
+++ b/src/cobalt/renderer/rasterizer/lib/lib.gyp
@@ -25,6 +25,15 @@
'external_rasterizer.cc',
'renderer_module_default_options_lib.cc'
],
+ 'all_dependent_settings': {
+ 'target_conditions': [
+ ['_type=="executable" and _toolset=="target"', {
+ 'sources': [
+ 'imported/graphics_stub.cc',
+ ],
+ }],
+ ],
+ },
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/cobalt/render_tree/render_tree.gyp:render_tree',
diff --git a/src/cobalt/renderer/rasterizer/lib/renderer_module_default_options_lib.cc b/src/cobalt/renderer/rasterizer/lib/renderer_module_default_options_lib.cc
index 955ea45..4caa615 100644
--- a/src/cobalt/renderer/rasterizer/lib/renderer_module_default_options_lib.cc
+++ b/src/cobalt/renderer/rasterizer/lib/renderer_module_default_options_lib.cc
@@ -24,12 +24,12 @@
const RendererModule::Options& options) {
return scoped_ptr<rasterizer::Rasterizer>(
new rasterizer::lib::ExternalRasterizer(
- graphics_context,
- options.skia_glyph_texture_atlas_dimensions.width(),
- options.skia_glyph_texture_atlas_dimensions.height(),
- options.skia_cache_size_in_bytes,
- options.scratch_surface_cache_size_in_bytes,
- options.surface_cache_size_in_bytes));
+ graphics_context, options.skia_glyph_texture_atlas_dimensions.width(),
+ options.skia_glyph_texture_atlas_dimensions.height(),
+ options.skia_cache_size_in_bytes,
+ options.scratch_surface_cache_size_in_bytes,
+ options.surface_cache_size_in_bytes,
+ options.purge_skia_font_caches_on_destruction));
}
} // namespace
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
index e569def..b90a09a 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -56,8 +56,8 @@
public:
Impl(backend::GraphicsContext* graphics_context, int skia_atlas_width,
int skia_atlas_height, int skia_cache_size_in_bytes,
- int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes);
+ int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction);
~Impl();
void AdvanceFrame();
@@ -82,8 +82,7 @@
// Note: We cannot store a SkAutoTUnref<SkSurface> in the map because it is
// not copyable; so we must manually manage our references when adding /
// removing SkSurfaces from it.
- typedef base::linked_hash_map<
- backend::RenderTarget*, SkSurface*> SkSurfaceMap;
+ typedef base::linked_hash_map<int32_t, SkSurface*> SkSurfaceMap;
class CachedScratchSurfaceHolder
: public RenderTreeNodeVisitor::ScratchSurface {
public:
@@ -364,7 +363,8 @@
int skia_atlas_width, int skia_atlas_height,
int skia_cache_size_in_bytes,
int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes)
+ int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction)
: graphics_context_(
base::polymorphic_downcast<backend::GraphicsContextEGL*>(
graphics_context)) {
@@ -404,7 +404,8 @@
resource_provider_.reset(new HardwareResourceProvider(
graphics_context_, gr_context_,
base::Bind(&HardwareRasterizer::Impl::SubmitOffscreenToRenderTarget,
- base::Unretained(this))));
+ base::Unretained(this)),
+ purge_skia_font_caches_on_destruction));
graphics_context_->ReleaseCurrentContext();
@@ -589,7 +590,8 @@
SkCanvas* HardwareRasterizer::Impl::GetCanvasFromRenderTarget(
const scoped_refptr<backend::RenderTarget>& render_target) {
SkSurface* sk_output_surface;
- SkSurfaceMap::iterator iter = sk_output_surface_map_.find(render_target);
+ int32_t surface_map_key = render_target->GetSerialNumber();
+ SkSurfaceMap::iterator iter = sk_output_surface_map_.find(surface_map_key);
if (iter == sk_output_surface_map_.end()) {
// Remove the least recently used SkSurface from the map if we exceed the
// max allowed saved surfaces.
@@ -613,13 +615,13 @@
// Create an SkSurface from the render target so that we can acquire a
// SkCanvas object from it in Submit().
sk_output_surface = CreateSkiaRenderTargetSurface(skia_render_target);
- sk_output_surface_map_[render_target] = sk_output_surface;
+ sk_output_surface_map_[surface_map_key] = sk_output_surface;
} else {
- sk_output_surface = sk_output_surface_map_[render_target];
+ sk_output_surface = sk_output_surface_map_[surface_map_key];
// Mark this RenderTarget/SkCanvas pair as the most recently used by
// popping it and re-adding it.
sk_output_surface_map_.erase(iter);
- sk_output_surface_map_[render_target] = sk_output_surface;
+ sk_output_surface_map_[surface_map_key] = sk_output_surface;
}
return sk_output_surface->getCanvas();
}
@@ -627,6 +629,9 @@
void HardwareRasterizer::Impl::RasterizeRenderTreeToCanvas(
const scoped_refptr<render_tree::Node>& render_tree, SkCanvas* canvas) {
TRACE_EVENT0("cobalt::renderer", "RasterizeRenderTreeToCanvas");
+ // TODO: This trace uses the name in the current benchmark to keep it work as
+ // expected. Remove after switching to webdriver benchmark.
+ TRACE_EVENT0("cobalt::renderer", "VisitRenderTree");
RenderTreeNodeVisitor::CreateScratchSurfaceFunction
create_scratch_surface_function =
base::Bind(&HardwareRasterizer::Impl::CreateScratchSurface,
@@ -650,11 +655,13 @@
HardwareRasterizer::HardwareRasterizer(
backend::GraphicsContext* graphics_context, int skia_atlas_width,
int skia_atlas_height, int skia_cache_size_in_bytes,
- int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes)
- : impl_(new Impl(graphics_context, skia_atlas_width, skia_atlas_height,
- skia_cache_size_in_bytes,
- scratch_surface_cache_size_in_bytes,
- surface_cache_size_in_bytes)) {}
+ int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction)
+ : impl_(new Impl(
+ graphics_context, skia_atlas_width, skia_atlas_height,
+ skia_cache_size_in_bytes, scratch_surface_cache_size_in_bytes,
+ surface_cache_size_in_bytes, purge_skia_font_caches_on_destruction)) {
+}
HardwareRasterizer::~HardwareRasterizer() {}
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h
index 7343ca0..aba9fd4 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h
@@ -54,7 +54,8 @@
int skia_atlas_width, int skia_atlas_height,
int skia_cache_size_in_bytes,
int scratch_surface_cache_size_in_bytes,
- int surface_cache_size_in_bytes);
+ int surface_cache_size_in_bytes,
+ bool purge_skia_font_caches_on_destruction);
virtual ~HardwareRasterizer();
// Consume the render tree and output the results to the render target passed
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
index 504faab..e8a4a08 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -47,10 +47,13 @@
HardwareResourceProvider::HardwareResourceProvider(
backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
- SubmitOffscreenCallback submit_offscreen_callback)
+ SubmitOffscreenCallback submit_offscreen_callback,
+ bool purge_skia_font_caches_on_destruction)
: cobalt_context_(cobalt_context),
gr_context_(gr_context),
submit_offscreen_callback_(submit_offscreen_callback),
+ purge_skia_font_caches_on_destruction_(
+ purge_skia_font_caches_on_destruction),
self_message_loop_(MessageLoop::current()) {
// Initialize the font manager now to ensure that it doesn't get initialized
// on multiple threads simultaneously later.
@@ -68,6 +71,17 @@
SB_HAS(GRAPHICS)
}
+HardwareResourceProvider::~HardwareResourceProvider() {
+ if (purge_skia_font_caches_on_destruction_) {
+ text_shaper_.PurgeCaches();
+
+ SkAutoTUnref<SkFontMgr> font_manager(SkFontMgr::RefDefault());
+ SkFontMgr_Cobalt* cobalt_font_manager =
+ base::polymorphic_downcast<SkFontMgr_Cobalt*>(font_manager.get());
+ cobalt_font_manager->PurgeCaches();
+ }
+}
+
void HardwareResourceProvider::Finish() {
// Wait for any resource-related to complete (by waiting for all tasks to
// complete).
@@ -380,13 +394,6 @@
self_message_loop_));
}
-void HardwareResourceProvider::PurgeCaches() {
- SkAutoTUnref<SkFontMgr> font_manager(SkFontMgr::RefDefault());
- SkFontMgr_Cobalt* cobalt_font_manager =
- base::polymorphic_downcast<SkFontMgr_Cobalt*>(font_manager.get());
- cobalt_font_manager->PurgeCaches();
-}
-
} // namespace skia
} // namespace rasterizer
} // namespace renderer
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
index 5fe7814..d5540a8 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
@@ -39,7 +39,9 @@
public:
HardwareResourceProvider(backend::GraphicsContextEGL* cobalt_context,
GrContext* gr_context,
- SubmitOffscreenCallback submit_offscreen_callback);
+ SubmitOffscreenCallback submit_offscreen_callback,
+ bool purge_skia_font_caches_on_destruction);
+ ~HardwareResourceProvider() OVERRIDE;
void Finish() OVERRIDE;
@@ -136,12 +138,11 @@
scoped_refptr<render_tree::Image> DrawOffscreenImage(
const scoped_refptr<render_tree::Node>& root) OVERRIDE;
- void PurgeCaches() OVERRIDE;
-
private:
backend::GraphicsContextEGL* cobalt_context_;
GrContext* gr_context_;
SubmitOffscreenCallback submit_offscreen_callback_;
+ const bool purge_skia_font_caches_on_destruction_;
TextShaper text_shaper_;
diff --git a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc
index 0434fe2..05cde83 100644
--- a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc
+++ b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc
@@ -195,42 +195,32 @@
SkSafeUnref(skia_face);
}
-// Wrapper class for a HarfBuzz face created from a given Skia face.
-class HarfBuzzFace {
- public:
- HarfBuzzFace() : face_(NULL) {}
-
- ~HarfBuzzFace() {
- if (face_) {
- hb_face_destroy(face_);
- }
- }
-
- void Init(SkTypeface* skia_face) {
- face_ = hb_face_create_for_tables(GetFontTable, skia_face, UnrefSkTypeface);
- DCHECK(face_);
- }
-
- hb_face_t* get() { return face_; }
-
- private:
- hb_face_t* face_;
-};
-
} // namespace
-// Creates a HarfBuzz font from the given Skia font.
-hb_font_t* CreateHarfBuzzFont(Font* skia_font) {
- static std::map<SkFontID, HarfBuzzFace> face_caches;
+HarfBuzzFontProvider::HarfBuzzFace::HarfBuzzFace() : face_(NULL) {}
+HarfBuzzFontProvider::HarfBuzzFace::~HarfBuzzFace() {
+ if (face_) {
+ hb_face_destroy(face_);
+ }
+}
+
+void HarfBuzzFontProvider::HarfBuzzFace::Init(SkTypeface* skia_face) {
+ face_ = hb_face_create_for_tables(GetFontTable, skia_face, UnrefSkTypeface);
+ DCHECK(face_);
+}
+
+hb_face_t* HarfBuzzFontProvider::HarfBuzzFace::get() { return face_; }
+
+hb_font_t* HarfBuzzFontProvider::GetHarfBuzzFont(Font* skia_font) {
// Retrieve the typeface from the cache. In the case where it does not already
// exist, it will be NULL and we must create it.
- HarfBuzzFace& face_cache = face_caches[skia_font->GetTypefaceId()];
- if (face_cache.get() == NULL) {
- face_cache.Init(skia_font->GetSkTypeface());
+ HarfBuzzFace& face = face_cache_[skia_font->GetTypefaceId()];
+ if (face.get() == NULL) {
+ face.Init(skia_font->GetSkTypeface());
}
- hb_font_t* harfbuzz_font = hb_font_create(face_cache.get());
+ hb_font_t* harfbuzz_font = hb_font_create(face.get());
const int scale = SkScalarToFixed(skia_font->size());
hb_font_set_scale(harfbuzz_font, scale, scale);
hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), skia_font, NULL);
@@ -238,6 +228,8 @@
return harfbuzz_font;
}
+void HarfBuzzFontProvider::PurgeCaches() { face_cache_.clear(); }
+
} // namespace skia
} // namespace rasterizer
} // namespace renderer
diff --git a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h
index 16b07e4..607c302 100644
--- a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h
+++ b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h
@@ -15,20 +15,40 @@
#ifndef COBALT_RENDERER_RASTERIZER_SKIA_HARFBUZZ_FONT_H_
#define COBALT_RENDERER_RASTERIZER_SKIA_HARFBUZZ_FONT_H_
+#include <map>
+
#include "cobalt/renderer/rasterizer/skia/font.h"
#include "third_party/harfbuzz-ng/src/hb.h"
-class SkTypeface;
-
namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace skia {
-class Font;
+class HarfBuzzFontProvider {
+ public:
+ // Returns the HarfBuzz font that corresponds to the given Skia font.
+ hb_font_t* GetHarfBuzzFont(Font* skia_font);
+ void PurgeCaches();
-hb_font_t* CreateHarfBuzzFont(Font* skia_font);
+ private:
+ // Wrapper class for a HarfBuzz face created from a given Skia face.
+ class HarfBuzzFace {
+ public:
+ HarfBuzzFace();
+ ~HarfBuzzFace();
+
+ void Init(SkTypeface* skia_face);
+
+ hb_face_t* get();
+
+ private:
+ hb_face_t* face_;
+ };
+
+ std::map<SkFontID, HarfBuzzFace> face_cache_;
+};
} // namespace skia
} // namespace rasterizer
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
index 36d4b6f..d26d31e 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
@@ -63,6 +63,13 @@
void SkFontMgr_Cobalt::PurgeCaches() {
SkGraphics::PurgeFontCache();
local_typeface_stream_manager_.PurgeUnusedMemoryChunks();
+
+ // Lock the family mutex prior to purging each family's unreferenced
+ // typefaces.
+ SkAutoMutexAcquire scoped_mutex(family_mutex_);
+ for (int i = 0; i < families_.count(); ++i) {
+ families_[i]->PurgeUnreferencedTypefaces();
+ }
}
SkTypeface* SkFontMgr_Cobalt::MatchFaceName(const char face_name[]) {
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
index 2b5718b..6196cc6 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
@@ -415,8 +415,8 @@
SkAutoTUnref<SkFileMemoryChunkStream> stream(stream_provider->OpenStream());
if (GenerateStyleFaceInfo(style_entry, stream)) {
- LOG(ERROR) << "Scanned font from file: " << style_entry->face_name.c_str()
- << "(" << style_entry->face_style << ")";
+ LOG(INFO) << "Scanned font from file: " << style_entry->face_name.c_str()
+ << "(" << style_entry->face_style << ")";
style_entry->typeface.reset(
SkNEW_ARGS(SkTypeface_CobaltStreamProvider,
(stream_provider, style_entry->face_index,
@@ -427,3 +427,14 @@
<< style_entry->font_file_path.c_str();
}
}
+
+void SkFontStyleSet_Cobalt::PurgeUnreferencedTypefaces() {
+ // Walk each of the styles looking for any that have a non-NULL typeface.
+ // These are purged if they are unreferenced outside of the style set.
+ for (int i = 0; i < styles_.count(); ++i) {
+ SkAutoTUnref<SkTypeface>& typeface = styles_[i]->typeface;
+ if (typeface.get() != NULL && typeface->getRefCnt() == 1) {
+ typeface.reset(NULL);
+ }
+ }
+}
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h
index 7d6648a..2180d1a 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h
@@ -36,8 +36,7 @@
// for specific characters during fallback.
//
// Both the character map of the style set and the typeface of each individual
-// entry are lazily loaded the first time that they are needed. After this, they
-// are retained in memory.
+// entry are lazily loaded the first time that they are needed.
class SkFontStyleSet_Cobalt : public SkFontStyleSet {
public:
struct SkFontStyleSetEntry_Cobalt : public SkRefCnt {
@@ -118,6 +117,9 @@
SkFontStyleSetEntry_Cobalt* style,
SkFileMemoryChunkStreamProvider* stream_provider = NULL);
+ // Purge typefaces that are only referenced internally.
+ void PurgeUnreferencedTypefaces();
+
// NOTE: The following variables can safely be accessed outside of the mutex.
SkFileMemoryChunkStreamManager* const local_typeface_stream_manager_;
SkMutex* const manager_owned_mutex_;
diff --git a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc
index 0f1968a..bcc5e04 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc
@@ -64,7 +64,8 @@
class SoftwareRasterizer::Impl {
public:
- explicit Impl(int surface_cache_size);
+ explicit Impl(int surface_cache_size,
+ bool purge_skia_font_caches_on_destruction);
// Consume the render tree and output the results to the render target passed
// into the constructor.
@@ -80,8 +81,10 @@
base::optional<common::SurfaceCache> surface_cache_;
};
-SoftwareRasterizer::Impl::Impl(int surface_cache_size)
- : resource_provider_(new SoftwareResourceProvider()) {
+SoftwareRasterizer::Impl::Impl(int surface_cache_size,
+ bool purge_skia_font_caches_on_destruction)
+ : resource_provider_(
+ new SoftwareResourceProvider(purge_skia_font_caches_on_destruction)) {
TRACE_EVENT0("cobalt::renderer", "SoftwareRasterizer::SoftwareRasterizer()");
if (surface_cache_size > 0) {
@@ -135,8 +138,9 @@
return resource_provider_.get();
}
-SoftwareRasterizer::SoftwareRasterizer(int surface_cache_size)
- : impl_(new Impl(surface_cache_size)) {}
+SoftwareRasterizer::SoftwareRasterizer(int surface_cache_size,
+ bool purge_caches_on_destruction)
+ : impl_(new Impl(surface_cache_size, purge_caches_on_destruction)) {}
SoftwareRasterizer::~SoftwareRasterizer() {}
diff --git a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h
index c0c2a7a..f935de4 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h
@@ -35,7 +35,8 @@
// class can send the results to a display or render target.
class SoftwareRasterizer {
public:
- explicit SoftwareRasterizer(int surface_cache_size);
+ explicit SoftwareRasterizer(int surface_cache_size,
+ bool purge_skia_font_caches_on_destruction);
~SoftwareRasterizer();
// Consume the render tree and output the results to the render target passed
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
index 32d795e..30a4cd8 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
@@ -37,12 +37,26 @@
namespace rasterizer {
namespace skia {
-SoftwareResourceProvider::SoftwareResourceProvider() {
+SoftwareResourceProvider::SoftwareResourceProvider(
+ bool purge_skia_font_caches_on_destruction)
+ : purge_skia_font_caches_on_destruction_(
+ purge_skia_font_caches_on_destruction) {
// Initialize the font manager now to ensure that it doesn't get initialized
// on multiple threads simultaneously later.
SkSafeUnref(SkFontMgr::RefDefault());
}
+SoftwareResourceProvider::~SoftwareResourceProvider() {
+ if (purge_skia_font_caches_on_destruction_) {
+ text_shaper_.PurgeCaches();
+
+ SkAutoTUnref<SkFontMgr> font_manager(SkFontMgr::RefDefault());
+ SkFontMgr_Cobalt* cobalt_font_manager =
+ base::polymorphic_downcast<SkFontMgr_Cobalt*>(font_manager.get());
+ cobalt_font_manager->PurgeCaches();
+ }
+}
+
bool SoftwareResourceProvider::PixelFormatSupported(
render_tree::PixelFormat pixel_format) {
return RenderTreeSurfaceFormatToSkia(pixel_format) == kN32_SkColorType;
@@ -233,13 +247,6 @@
return scoped_refptr<render_tree::Image>(NULL);
}
-void SoftwareResourceProvider::PurgeCaches() {
- SkAutoTUnref<SkFontMgr> font_manager(SkFontMgr::RefDefault());
- SkFontMgr_Cobalt* cobalt_font_manager =
- base::polymorphic_downcast<SkFontMgr_Cobalt*>(font_manager.get());
- cobalt_font_manager->PurgeCaches();
-}
-
} // namespace skia
} // namespace rasterizer
} // namespace renderer
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
index 1f0d1f4..67e8e2d 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
@@ -31,7 +31,8 @@
// are to be consumed by this skia software rasterizer.
class SoftwareResourceProvider : public render_tree::ResourceProvider {
public:
- SoftwareResourceProvider();
+ explicit SoftwareResourceProvider(bool purge_skia_font_caches_on_destruction);
+ ~SoftwareResourceProvider() OVERRIDE;
void Finish() OVERRIDE{};
@@ -121,9 +122,9 @@
scoped_refptr<render_tree::Image> DrawOffscreenImage(
const scoped_refptr<render_tree::Node>& root) OVERRIDE;
- void PurgeCaches() OVERRIDE;
-
private:
+ const bool purge_skia_font_caches_on_destruction_;
+
TextShaper text_shaper_;
};
diff --git a/src/cobalt/renderer/rasterizer/skia/text_shaper.cc b/src/cobalt/renderer/rasterizer/skia/text_shaper.cc
index 5d8ee0f..e307c8e 100644
--- a/src/cobalt/renderer/rasterizer/skia/text_shaper.cc
+++ b/src/cobalt/renderer/rasterizer/skia/text_shaper.cc
@@ -119,6 +119,11 @@
NULL, NULL, maybe_used_fonts);
}
+void TextShaper::PurgeCaches() {
+ base::AutoLock lock(shaping_mutex_);
+ harfbuzz_font_provider_.PurgeCaches();
+}
+
float TextShaper::ShapeText(const char16* text_buffer, size_t text_length,
const std::string& language, bool is_rtl,
render_tree::FontProvider* font_provider,
@@ -285,7 +290,8 @@
float* total_width) {
TryAddFontToUsedFonts(script_run.font, maybe_used_fonts);
- hb_font_t* harfbuzz_font = CreateHarfBuzzFont(script_run.font);
+ hb_font_t* harfbuzz_font =
+ harfbuzz_font_provider_.GetHarfBuzzFont(script_run.font);
// Ensure that the local text buffer is large enough to hold the normalized
// string.
diff --git a/src/cobalt/renderer/rasterizer/skia/text_shaper.h b/src/cobalt/renderer/rasterizer/skia/text_shaper.h
index 982e1d3..e111ce6 100644
--- a/src/cobalt/renderer/rasterizer/skia/text_shaper.h
+++ b/src/cobalt/renderer/rasterizer/skia/text_shaper.h
@@ -25,6 +25,7 @@
#include "cobalt/render_tree/font_provider.h"
#include "cobalt/renderer/rasterizer/skia/font.h"
#include "cobalt/renderer/rasterizer/skia/glyph_buffer.h"
+#include "cobalt/renderer/rasterizer/skia/harfbuzz_font.h"
#include "third_party/harfbuzz-ng/src/hb.h"
#include "third_party/harfbuzz-ng/src/hb-icu.h"
@@ -90,6 +91,10 @@
render_tree::FontProvider* font_provider,
render_tree::FontVector* maybe_used_fonts);
+ // Purges any caches being used by the text shaper; currently, this consists
+ // of the HarfBuzzFontProvider's cache.
+ void PurgeCaches();
+
private:
// Internal class used for tracking the vertical bounds of a text buffer
// during shaping when bounds are requested (i.e. the passed in |maybe_bounds|
@@ -155,8 +160,8 @@
render_tree::FontVector* maybe_used_fonts,
float* current_width);
- // Shape a simple text run, relying on the skia::Font objects provided by
- // the FontProvider to determine the shaping data.
+ // Shape a simple text run, relying on the skia::Font objects provided by the
+ // FontProvider to determine the shaping data.
void ShapeSimpleRun(const char16* text_buffer, size_t text_length,
render_tree::FontProvider* font_provider,
SkTextBlobBuilder* maybe_builder,
@@ -181,6 +186,9 @@
// the same time.
base::Lock shaping_mutex_;
+ // Provides fonts needed by HarfBuzz during complex shaping.
+ HarfBuzzFontProvider harfbuzz_font_provider_;
+
// The allocated glyph and positions data. This is retained in between shaping
// calls to prevent constantly needing to allocate the arrays. In the case
// where a larger array is needed than the current size, larger arrays are
diff --git a/src/cobalt/renderer/render_tree_pixel_tester.cc b/src/cobalt/renderer/render_tree_pixel_tester.cc
index eb92656..a428a17 100644
--- a/src/cobalt/renderer/render_tree_pixel_tester.cc
+++ b/src/cobalt/renderer/render_tree_pixel_tester.cc
@@ -69,6 +69,11 @@
// Create the rasterizer using the platform default RenderModule options.
RendererModule::Options render_module_options;
+
+ // Don't purge the Skia font caches on destruction. Doing so will result in
+ // too much font thrashing during the tests.
+ render_module_options.purge_skia_font_caches_on_destruction = false;
+
rasterizer_ = render_module_options.create_rasterizer_function.Run(
graphics_context_.get(), render_module_options);
}
diff --git a/src/cobalt/renderer/renderer_module.cc b/src/cobalt/renderer/renderer_module.cc
index 28cbe93..084390e 100644
--- a/src/cobalt/renderer/renderer_module.cc
+++ b/src/cobalt/renderer/renderer_module.cc
@@ -24,7 +24,8 @@
namespace renderer {
RendererModule::Options::Options()
- : skia_glyph_texture_atlas_dimensions(2048, 2048) {
+ : skia_glyph_texture_atlas_dimensions(2048, 2048),
+ purge_skia_font_caches_on_destruction(true) {
// Call into platform-specific code for setting up render module options.
SetPerPlatformDefaultOptions();
}
diff --git a/src/cobalt/renderer/renderer_module.h b/src/cobalt/renderer/renderer_module.h
index 0e92c82..70d0364 100644
--- a/src/cobalt/renderer/renderer_module.h
+++ b/src/cobalt/renderer/renderer_module.h
@@ -77,6 +77,12 @@
// buffer will not be frequently swapped.
bool submit_even_if_render_tree_is_unchanged;
+ // If this flag is set to true, which is the default value, then all of
+ // Skia's font caches are purged during destruction. These caches have
+ // lifespans that are uncoupled from the resource provider's, and will not
+ // be purged on destruction when this is set to false.
+ bool purge_skia_font_caches_on_destruction;
+
// On modes with a 3D camera controllable by user input, fetch the affine
// transforms needed to render the scene from the camera's view.
GetCameraTransformCallback get_camera_transform;
diff --git a/src/cobalt/renderer/renderer_module_default_options_starboard.cc b/src/cobalt/renderer/renderer_module_default_options_starboard.cc
index fc3f3e0..0251fee 100644
--- a/src/cobalt/renderer/renderer_module_default_options_starboard.cc
+++ b/src/cobalt/renderer/renderer_module_default_options_starboard.cc
@@ -38,7 +38,8 @@
#if COBALT_FORCE_SOFTWARE_RASTERIZER
return scoped_ptr<rasterizer::Rasterizer>(
new rasterizer::egl::SoftwareRasterizer(
- graphics_context, options.surface_cache_size_in_bytes));
+ graphics_context, options.surface_cache_size_in_bytes,
+ options.purge_skia_font_caches_on_destruction));
#elif defined(COBALT_FORCE_DIRECT_GLES_RASTERIZER)
return scoped_ptr<rasterizer::Rasterizer>(
new rasterizer::egl::HardwareRasterizer(
@@ -46,7 +47,8 @@
options.skia_glyph_texture_atlas_dimensions.height(),
options.skia_cache_size_in_bytes,
options.scratch_surface_cache_size_in_bytes,
- options.surface_cache_size_in_bytes));
+ options.surface_cache_size_in_bytes,
+ options.purge_skia_font_caches_on_destruction));
#else
return scoped_ptr<rasterizer::Rasterizer>(
new rasterizer::skia::HardwareRasterizer(
@@ -54,13 +56,15 @@
options.skia_glyph_texture_atlas_dimensions.height(),
options.skia_cache_size_in_bytes,
options.scratch_surface_cache_size_in_bytes,
- options.surface_cache_size_in_bytes));
+ options.surface_cache_size_in_bytes,
+ options.purge_skia_font_caches_on_destruction));
#endif // COBALT_FORCE_SOFTWARE_RASTERIZER
#elif SB_HAS(BLITTER)
#if COBALT_FORCE_SOFTWARE_RASTERIZER
return scoped_ptr<rasterizer::Rasterizer>(
new rasterizer::blitter::SoftwareRasterizer(
- graphics_context, options.surface_cache_size_in_bytes));
+ graphics_context, options.surface_cache_size_in_bytes,
+ options.purge_skia_font_caches_on_destruction));
#else
return scoped_ptr<rasterizer::Rasterizer>(
new rasterizer::blitter::HardwareRasterizer(
@@ -68,7 +72,8 @@
options.skia_glyph_texture_atlas_dimensions.height(),
options.scratch_surface_cache_size_in_bytes,
options.surface_cache_size_in_bytes,
- options.software_surface_cache_size_in_bytes));
+ options.software_surface_cache_size_in_bytes,
+ options.purge_skia_font_caches_on_destruction));
#endif // COBALT_FORCE_SOFTWARE_RASTERIZER
#else
#error "Either GLES2 or the Starboard Blitter API must be available."
diff --git a/src/cobalt/renderer/renderer_module_default_options_win.cc b/src/cobalt/renderer/renderer_module_default_options_win.cc
index 5809d2c..163fe2b 100644
--- a/src/cobalt/renderer/renderer_module_default_options_win.cc
+++ b/src/cobalt/renderer/renderer_module_default_options_win.cc
@@ -27,13 +27,15 @@
#if COBALT_FORCE_SOFTWARE_RASTERIZER
return scoped_ptr<rasterizer::Rasterizer>(
new rasterizer::egl::SoftwareRasterizer(
- graphics_context, options.surface_cache_size_in_bytes));
+ graphics_context, options.surface_cache_size_in_bytes,
+ options.purge_skia_font_caches_on_destruction));
#else
return scoped_ptr<rasterizer::Rasterizer>(
new rasterizer::skia::HardwareRasterizer(
graphics_context, options.skia_cache_size_in_bytes,
options.scratch_surface_cache_size_in_bytes,
- options.surface_cache_size_in_bytes));
+ options.surface_cache_size_in_bytes,
+ options.purge_skia_font_caches_on_destruction));
#endif // #if COBALT_FORCE_SOFTWARE_RASTERIZER
}
} // namespace
diff --git a/src/cobalt/script/mozjs-45/conversion_helpers.h b/src/cobalt/script/mozjs-45/conversion_helpers.h
index 95a752e..c8e4c93 100644
--- a/src/cobalt/script/mozjs-45/conversion_helpers.h
+++ b/src/cobalt/script/mozjs-45/conversion_helpers.h
@@ -154,19 +154,19 @@
// https://heycam.github.io/webidl/#abstract-opdef-converttoint
template <>
inline const double UpperBound<int64_t>() {
- const double kInt64UpperBound = static_cast<double>((1ull << 53) - 1);
+ const double kInt64UpperBound = static_cast<double>((1ll << 53) - 1);
return kInt64UpperBound;
}
template <>
inline const double LowerBound<int64_t>() {
- const double kInt64LowerBound = static_cast<double>(-(1ull << 53) + 1);
+ const double kInt64LowerBound = static_cast<double>(-(1ll << 53) + 1);
return kInt64LowerBound;
}
template <>
inline const double UpperBound<uint64_t>() {
- const double kUInt64UpperBound = static_cast<double>((1ull << 53) - 1);
+ const double kUInt64UpperBound = static_cast<double>((1ll << 53) - 1);
return kUInt64UpperBound;
}
diff --git a/src/cobalt/script/mozjs-45/mozjs-45.gyp b/src/cobalt/script/mozjs-45/mozjs-45.gyp
index d0f416c..6959bcd 100644
--- a/src/cobalt/script/mozjs-45/mozjs-45.gyp
+++ b/src/cobalt/script/mozjs-45/mozjs-45.gyp
@@ -80,8 +80,7 @@
{
# This target takes specified files and embeds them as header files for
- # inclusion into the binary. The script currently requires all resources
- # to be embedded to live in the same directory.
+ # inclusion into the binary.
'target_name': 'embed_mozjs_resources_as_header_files',
'type': 'none',
# Because we generate a header, we must set the hard_dependency flag.
@@ -92,6 +91,9 @@
},
'sources': [
'<(DEPTH)/third_party/promise-polyfill/promise.min.js',
+ '<(DEPTH)/cobalt/streams/embedded_scripts/byte_length_queuing_strategy.js',
+ '<(DEPTH)/cobalt/streams/embedded_scripts/count_queuing_strategy.js',
+ '<(DEPTH)/cobalt/streams/embedded_scripts/readable_stream.js',
],
'actions': [
{
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
index 2f5af46..2bd7c41 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
@@ -269,6 +269,19 @@
return success;
}
+void MozjsGlobalEnvironment::EvaluateEmbeddedScript(
+ const unsigned char* data, size_t size, const char* filename) {
+ TRACK_MEMORY_SCOPE("Javascript");
+ std::string source(reinterpret_cast<const char*>(data), size);
+ scoped_refptr<SourceCode> source_code =
+ new MozjsSourceCode(source, base::SourceLocation(filename, 1, 1));
+ std::string result;
+ bool success = EvaluateScript(source_code, &result);
+ if (!success) {
+ DLOG(FATAL) << result;
+ }
+}
+
std::vector<StackFrame> MozjsGlobalEnvironment::GetStackTrace(int max_frames) {
DCHECK(thread_checker_.CalledOnValidThread());
return util::GetStackTrace(context_, max_frames);
@@ -351,17 +364,22 @@
}
void MozjsGlobalEnvironment::EvaluateAutomatics() {
- TRACK_MEMORY_SCOPE("Javascript");
- std::string source(
- reinterpret_cast<const char*>(MozjsEmbeddedResources::promise_min_js),
- sizeof(MozjsEmbeddedResources::promise_min_js));
- scoped_refptr<SourceCode> source_code =
- new MozjsSourceCode(source, base::SourceLocation("promise.min.js", 1, 1));
- std::string result;
- bool success = EvaluateScript(source_code, &result);
- if (!success) {
- DLOG(FATAL) << result;
- }
+ EvaluateEmbeddedScript(
+ MozjsEmbeddedResources::promise_min_js,
+ sizeof(MozjsEmbeddedResources::promise_min_js),
+ "promise.min.js");
+ EvaluateEmbeddedScript(
+ MozjsEmbeddedResources::byte_length_queuing_strategy_js,
+ sizeof(MozjsEmbeddedResources::byte_length_queuing_strategy_js),
+ "byte_length_queuing_strategy.js");
+ EvaluateEmbeddedScript(
+ MozjsEmbeddedResources::count_queuing_strategy_js,
+ sizeof(MozjsEmbeddedResources::count_queuing_strategy_js),
+ "count_queuing_strategy.js");
+ EvaluateEmbeddedScript(
+ MozjsEmbeddedResources::readable_stream_js,
+ sizeof(MozjsEmbeddedResources::readable_stream_js),
+ "readable_stream.js");
}
InterfaceData* MozjsGlobalEnvironment::GetInterfaceData(intptr_t key) {
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.h b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
index c6cfb2a..0a5a573 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.h
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
@@ -149,6 +149,9 @@
bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code,
JS::MutableHandleValue out_result);
+ void EvaluateEmbeddedScript(const unsigned char* data, size_t size,
+ const char* filename);
+
static void TraceFunction(JSTracer* trace, void* data);
// Helper struct to ensure the context is destroyed in the correct order
diff --git a/src/cobalt/script/mozjs-45/native_promise.h b/src/cobalt/script/mozjs-45/native_promise.h
index 1dfccb5..cc4be5d 100644
--- a/src/cobalt/script/mozjs-45/native_promise.h
+++ b/src/cobalt/script/mozjs-45/native_promise.h
@@ -169,6 +169,16 @@
out_value.setObjectOrNull(native_promise->promise());
}
+// Destroys |promise_holder| as soon as the conversion is done.
+// This is useful when a wrappable is not interested in retaining a reference
+// to a promise, typically when a promise is resolved or rejected synchronously.
+template <typename T>
+inline void ToJSValue(JSContext* context,
+ scoped_ptr<ScriptValue<Promise<T> > > promise_holder,
+ JS::MutableHandleValue out_value) {
+ ToJSValue(context, promise_holder.get(), out_value);
+}
+
} // namespace mozjs
} // namespace script
} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/conversion_helpers.h b/src/cobalt/script/mozjs/conversion_helpers.h
index 88a13b8..0aa9192 100644
--- a/src/cobalt/script/mozjs/conversion_helpers.h
+++ b/src/cobalt/script/mozjs/conversion_helpers.h
@@ -152,19 +152,19 @@
// https://heycam.github.io/webidl/#abstract-opdef-converttoint
template <>
inline const double UpperBound<int64_t>() {
- const double kInt64UpperBound = static_cast<double>((1ull << 53) - 1);
+ const double kInt64UpperBound = static_cast<double>((1ll << 53) - 1);
return kInt64UpperBound;
}
template <>
inline const double LowerBound<int64_t>() {
- const double kInt64LowerBound = static_cast<double>(-(1ull << 53) + 1);
+ const double kInt64LowerBound = static_cast<double>(-(1ll << 53) + 1);
return kInt64LowerBound;
}
template <>
inline const double UpperBound<uint64_t>() {
- const double kUInt64UpperBound = static_cast<double>((1ull << 53) - 1);
+ const double kUInt64UpperBound = static_cast<double>((1ll << 53) - 1);
return kUInt64UpperBound;
}
diff --git a/src/cobalt/script/mozjs/native_promise.h b/src/cobalt/script/mozjs/native_promise.h
index e291197..f184076 100644
--- a/src/cobalt/script/mozjs/native_promise.h
+++ b/src/cobalt/script/mozjs/native_promise.h
@@ -169,6 +169,16 @@
out_value.setObjectOrNull(native_promise->promise());
}
+// Destroys |promise_holder| as soon as the conversion is done.
+// This is useful when a wrappable is not interested in retaining a reference
+// to a promise, typically when a promise is resolved or rejected synchronously.
+template <typename T>
+inline void ToJSValue(JSContext* context,
+ scoped_ptr<ScriptValue<Promise<T> > > promise_holder,
+ JS::MutableHandleValue out_value) {
+ ToJSValue(context, promise_holder.get(), out_value);
+}
+
} // namespace mozjs
} // namespace script
} // namespace cobalt
diff --git a/src/cobalt/script/script_value.h b/src/cobalt/script/script_value.h
index 0553bd1..7b9edac 100644
--- a/src/cobalt/script/script_value.h
+++ b/src/cobalt/script/script_value.h
@@ -54,6 +54,12 @@
// constructor.
class Reference {
public:
+ Reference(Wrappable* wrappable, scoped_ptr<ScriptValue> script_value)
+ : owner_(wrappable), referenced_value_(script_value.Pass()) {
+ DCHECK(referenced_value_);
+ referenced_value_->RegisterOwner(owner_);
+ }
+
Reference(Wrappable* wrappable, const ScriptValue& script_value)
: owner_(wrappable), referenced_value_(script_value.MakeCopy()) {
DCHECK(referenced_value_);
@@ -85,6 +91,12 @@
// doesn't need to be retained past the scope of the function.
class StrongReference {
public:
+ explicit StrongReference(scoped_ptr<ScriptValue> script_value)
+ : referenced_value_(script_value.Pass()) {
+ DCHECK(referenced_value_);
+ referenced_value_->PreventGarbageCollection();
+ }
+
explicit StrongReference(const ScriptValue& script_value)
: referenced_value_(script_value.MakeCopy()) {
DCHECK(referenced_value_);
diff --git a/src/cobalt/streams/byte_length_queuing_strategy.js b/src/cobalt/streams/byte_length_queuing_strategy.js
new file mode 100644
index 0000000..dd1a0a1
--- /dev/null
+++ b/src/cobalt/streams/byte_length_queuing_strategy.js
@@ -0,0 +1,34 @@
+// ==ClosureCompiler==
+// @output_file_name byte_length_queuing_strategy.js
+// @compilation_level SIMPLE_OPTIMIZATIONS
+// @language_out ES5_STRICT
+// ==/ClosureCompiler==
+
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function(global) {
+ 'use strict';
+
+ const defineProperty = global.Object.defineProperty;
+
+ class ByteLengthQueuingStrategy {
+ constructor(options) {
+ defineProperty(this, 'highWaterMark', {
+ value: options.highWaterMark,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ }
+ size(chunk) { return chunk.byteLength; }
+ }
+
+ defineProperty(global, 'ByteLengthQueuingStrategy', {
+ value: ByteLengthQueuingStrategy,
+ enumerable: false,
+ configurable: true,
+ writable: true
+ });
+})(this);
diff --git a/src/cobalt/streams/count_queuing_strategy.js b/src/cobalt/streams/count_queuing_strategy.js
new file mode 100644
index 0000000..5fc5715
--- /dev/null
+++ b/src/cobalt/streams/count_queuing_strategy.js
@@ -0,0 +1,35 @@
+// ==ClosureCompiler==
+// @output_file_name count_queuing_strategy.js
+// @compilation_level SIMPLE_OPTIMIZATIONS
+// @language_out ES5_STRICT
+// ==/ClosureCompiler==
+
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function(global) {
+ 'use strict';
+
+ const defineProperty = global.Object.defineProperty;
+
+ class CountQueuingStrategy {
+ constructor(options) {
+ defineProperty(this, 'highWaterMark', {
+ value: options.highWaterMark,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ }
+
+ size(chunk) { return 1; }
+ }
+
+ defineProperty(global, 'CountQueuingStrategy', {
+ value: CountQueuingStrategy,
+ enumerable: false,
+ configurable: true,
+ writable: true
+ });
+})(this);
diff --git a/src/cobalt/streams/embedded_scripts/byte_length_queuing_strategy.js b/src/cobalt/streams/embedded_scripts/byte_length_queuing_strategy.js
new file mode 100644
index 0000000..7a537ac
--- /dev/null
+++ b/src/cobalt/streams/embedded_scripts/byte_length_queuing_strategy.js
@@ -0,0 +1 @@
+'use strict';(function(b){var c=b.Object.defineProperty,d=function(a){c(this,"highWaterMark",{value:a.highWaterMark,enumerable:!0,configurable:!0,writable:!0})};d.prototype.size=function(a){return a.byteLength};c(b,"ByteLengthQueuingStrategy",{value:d,enumerable:!1,configurable:!0,writable:!0})})(this);
\ No newline at end of file
diff --git a/src/cobalt/streams/embedded_scripts/count_queuing_strategy.js b/src/cobalt/streams/embedded_scripts/count_queuing_strategy.js
new file mode 100644
index 0000000..288aed3
--- /dev/null
+++ b/src/cobalt/streams/embedded_scripts/count_queuing_strategy.js
@@ -0,0 +1 @@
+'use strict';(function(a){var b=a.Object.defineProperty,c=function(a){b(this,"highWaterMark",{value:a.highWaterMark,enumerable:!0,configurable:!0,writable:!0})};c.prototype.size=function(a){return 1};b(a,"CountQueuingStrategy",{value:c,enumerable:!1,configurable:!0,writable:!0})})(this);
\ No newline at end of file
diff --git a/src/cobalt/streams/embedded_scripts/readable_stream.js b/src/cobalt/streams/embedded_scripts/readable_stream.js
new file mode 100644
index 0000000..3017cdd
--- /dev/null
+++ b/src/cobalt/streams/embedded_scripts/readable_stream.js
@@ -0,0 +1,47 @@
+'use strict';(function(global){const v8_InternalPackedArray=global.Array;function v8_createPrivateSymbol(x){return Symbol(x)}function v8_simpleBind(fn,obj){return fn.bind(obj)}const arraySlice=global.Array.prototype.slice;function v8_uncurryThis(fn){return function(obj){return fn.apply(obj,arraySlice.call(arguments,1))}}const v8_PromiseBase=global.Promise;const _promiseResolve=v8_createPrivateSymbol("[[Resolve]]");const _promiseReject=v8_createPrivateSymbol("[[Reject]]");function v8_Promise(){var that=
+this;v8_PromiseBase.call(this,function(resolve,reject){that[_promiseResolve]=resolve;that[_promiseReject]=reject})}v8_Promise.prototype=v8_PromiseBase.prototype;function v8_createPromise(){return new v8_Promise}function v8_isPromise(obj){return obj instanceof v8_Promise}function v8_resolvePromise(promise,value){promise[_promiseResolve](value)}function v8_rejectPromise(promise,reason){promise[_promiseReject](reason)}function v8_markPromiseAsHandled(promise){try{thenPromise(promise,undefined,()=>{})}catch(error){}}
+const QUEUE_MAX_ARRAY_SIZE=16384;class SimpleQueue{constructor(){this.front={elements:new v8_InternalPackedArray,next:undefined};this.back=this.front;this.cursor=0;this.size=0}get length(){return this.size}push(element){++this.size;if(this.back.elements.length===QUEUE_MAX_ARRAY_SIZE){const oldBack=this.back;this.back={elements:new v8_InternalPackedArray,next:undefined};oldBack.next=this.back}this.back.elements.push(element)}shift(){--this.size;if(this.front.elements.length===this.cursor){this.front=
+this.front.next;this.cursor=0}const element=this.front.elements[this.cursor];this.front.elements[this.cursor]=undefined;++this.cursor;return element}forEach(callback){let i=this.cursor;let node=this.front;let elements=node.elements;while(i!==elements.length||node.next!==undefined){if(i===elements.length){node=node.next;elements=node.elements;i=0}callback(elements[i]);++i}}peek(){if(this.front.elements.length===this.cursor)return this.front.next.elements[0];return this.front.elements[this.cursor]}}
+const streamErrors_illegalInvocation="Illegal invocation";const streamErrors_illegalConstructor="Illegal constructor";const streamErrors_invalidType="Invalid type is specified";const streamErrors_invalidSize="The return value of a queuing strategy's size function must be a finite, non-NaN, non-negative number";const streamErrors_sizeNotAFunction="A queuing strategy's size property must be a function";const streamErrors_invalidHWM="A queueing strategy's highWaterMark property must be a nonnegative, non-NaN number";
+const _reader=v8_createPrivateSymbol("[[reader]]");const _storedError=v8_createPrivateSymbol("[[storedError]]");const _controller=v8_createPrivateSymbol("[[controller]]");const _closedPromise=v8_createPrivateSymbol("[[closedPromise]]");const _ownerReadableStream=v8_createPrivateSymbol("[[ownerReadableStream]]");const _readRequests=v8_createPrivateSymbol("[[readRequests]]");const createWithExternalControllerSentinel=v8_createPrivateSymbol("flag for UA-created ReadableStream to pass");const _readableStreamBits=
+v8_createPrivateSymbol("bit field for [[state]] and [[disturbed]]");const DISTURBED=1;const STATE_MASK=6;const STATE_BITS_OFFSET=1;const STATE_READABLE=0;const STATE_CLOSED=1;const STATE_ERRORED=2;const _underlyingSource=v8_createPrivateSymbol("[[underlyingSource]]");const _controlledReadableStream=v8_createPrivateSymbol("[[controlledReadableStream]]");const _queue=v8_createPrivateSymbol("[[queue]]");const _totalQueuedSize=v8_createPrivateSymbol("[[totalQueuedSize]]");const _strategySize=v8_createPrivateSymbol("[[strategySize]]");
+const _strategyHWM=v8_createPrivateSymbol("[[strategyHWM]]");const _readableStreamDefaultControllerBits=v8_createPrivateSymbol("bit field for [[started]], [[closeRequested]], [[pulling]], [[pullAgain]]");const STARTED=1;const CLOSE_REQUESTED=2;const PULLING=4;const PULL_AGAIN=8;const EXTERNALLY_CONTROLLED=16;const undefined=global.undefined;const Infinity=global.Infinity;const defineProperty=global.Object.defineProperty;const hasOwnProperty=v8_uncurryThis(global.Object.hasOwnProperty);const callFunction=
+v8_uncurryThis(global.Function.prototype.call);const applyFunction=v8_uncurryThis(global.Function.prototype.apply);const TypeError=global.TypeError;const RangeError=global.RangeError;const Number=global.Number;const Number_isNaN=Number.isNaN;const Number_isFinite=Number.isFinite;const Promise=global.Promise;const thenPromise=v8_uncurryThis(Promise.prototype.then);const Promise_resolve=v8_simpleBind(Promise.resolve,Promise);const Promise_reject=v8_simpleBind(Promise.reject,Promise);const errCancelLockedStream=
+"Cannot cancel a readable stream that is locked to a reader";const errEnqueueCloseRequestedStream="Cannot enqueue a chunk into a readable stream that is closed or has been requested to be closed";const errCancelReleasedReader="This readable stream reader has been released and cannot be used to cancel its previous owner stream";const errReadReleasedReader="This readable stream reader has been released and cannot be used to read from its previous owner stream";const errCloseCloseRequestedStream="Cannot close a readable stream that has already been requested to be closed";
+const errEnqueueClosedStream="Cannot enqueue a chunk into a closed readable stream";const errEnqueueErroredStream="Cannot enqueue a chunk into an errored readable stream";const errCloseClosedStream="Cannot close a closed readable stream";const errCloseErroredStream="Cannot close an errored readable stream";const errErrorClosedStream="Cannot error a close readable stream";const errErrorErroredStream="Cannot error a readable stream that is already errored";const errGetReaderNotByteStream="This readable stream does not support BYOB readers";
+const errGetReaderBadMode='Invalid reader mode given: expected undefined or "byob"';const errReaderConstructorBadArgument="ReadableStreamReader constructor argument is not a readable stream";const errReaderConstructorStreamAlreadyLocked="ReadableStreamReader constructor can only accept readable streams that are not yet locked to a reader";const errReleaseReaderWithPendingRead="Cannot release a readable stream reader when it still has outstanding read() calls that have not yet settled";const errReleasedReaderClosedPromise=
+"This readable stream reader has been released and cannot be used to monitor the stream's state";const errTmplMustBeFunctionOrUndefined=(name)=>`${name} must be a function or undefined`;class ReadableStream{constructor(){const underlyingSource=arguments[0]===undefined?{}:arguments[0];const strategy=arguments[1]===undefined?{}:arguments[1];const size=strategy.size;let highWaterMark=strategy.highWaterMark;if(highWaterMark===undefined)highWaterMark=1;this[_readableStreamBits]=0;ReadableStreamSetState(this,
+STATE_READABLE);this[_reader]=undefined;this[_storedError]=undefined;this[_controller]=undefined;const type=underlyingSource.type;const typeString=String(type);if(typeString==="bytes")throw new RangeError("bytes type is not yet implemented");else if(type!==undefined)throw new RangeError(streamErrors_invalidType);this[_controller]=new ReadableStreamDefaultController(this,underlyingSource,size,highWaterMark,arguments[2])}get locked(){if(IsReadableStream(this)===false)throw new TypeError(streamErrors_illegalInvocation);
+return IsReadableStreamLocked(this)}cancel(reason){if(IsReadableStream(this)===false)return Promise_reject(new TypeError(streamErrors_illegalInvocation));if(IsReadableStreamLocked(this)===true)return Promise_reject(new TypeError(errCancelLockedStream));return ReadableStreamCancel(this,reason)}getReader({mode}={}){if(IsReadableStream(this)===false)throw new TypeError(streamErrors_illegalInvocation);if(mode==="byob")throw new TypeError(errGetReaderNotByteStream);if(mode===undefined)return AcquireReadableStreamDefaultReader(this);
+throw new RangeError(errGetReaderBadMode);}pipeThrough({writable,readable},options){throw new TypeError("pipeThrough not implemented");}pipeTo(dest,{preventClose,preventAbort,preventCancel}={}){throw new TypeError("pipeTo not implemented");}tee(){if(IsReadableStream(this)===false)throw new TypeError(streamErrors_illegalInvocation);return ReadableStreamTee(this)}}class ReadableStreamDefaultController{constructor(stream,underlyingSource,size,highWaterMark){if(IsReadableStream(stream)===false)throw new TypeError(streamErrors_illegalConstructor);
+if(stream[_controller]!==undefined)throw new TypeError(streamErrors_illegalConstructor);this[_controlledReadableStream]=stream;this[_underlyingSource]=underlyingSource;this[_queue]=new SimpleQueue;this[_totalQueuedSize]=0;this[_readableStreamDefaultControllerBits]=0;if(arguments[4]===createWithExternalControllerSentinel)this[_readableStreamDefaultControllerBits]|=EXTERNALLY_CONTROLLED;const normalizedStrategy=ValidateAndNormalizeQueuingStrategy(size,highWaterMark);this[_strategySize]=normalizedStrategy.size;
+this[_strategyHWM]=normalizedStrategy.highWaterMark;const controller=this;const startResult=CallOrNoop(underlyingSource,"start",this,"underlyingSource.start");thenPromise(Promise_resolve(startResult),()=>{controller[_readableStreamDefaultControllerBits]|=STARTED;ReadableStreamDefaultControllerCallPullIfNeeded(controller)},(r)=>{if(ReadableStreamGetState(stream)===STATE_READABLE)ReadableStreamDefaultControllerError(controller,r)})}get desiredSize(){if(IsReadableStreamDefaultController(this)===false)throw new TypeError(streamErrors_illegalInvocation);
+return ReadableStreamDefaultControllerGetDesiredSize(this)}close(){if(IsReadableStreamDefaultController(this)===false)throw new TypeError(streamErrors_illegalInvocation);const stream=this[_controlledReadableStream];if(this[_readableStreamDefaultControllerBits]&CLOSE_REQUESTED)throw new TypeError(errCloseCloseRequestedStream);const state=ReadableStreamGetState(stream);if(state===STATE_ERRORED)throw new TypeError(errCloseErroredStream);if(state===STATE_CLOSED)throw new TypeError(errCloseClosedStream);
+return ReadableStreamDefaultControllerClose(this)}enqueue(chunk){if(IsReadableStreamDefaultController(this)===false)throw new TypeError(streamErrors_illegalInvocation);const stream=this[_controlledReadableStream];if(this[_readableStreamDefaultControllerBits]&CLOSE_REQUESTED)throw new TypeError(errEnqueueCloseRequestedStream);const state=ReadableStreamGetState(stream);if(state===STATE_ERRORED)throw new TypeError(errEnqueueErroredStream);if(state===STATE_CLOSED)throw new TypeError(errEnqueueClosedStream);
+return ReadableStreamDefaultControllerEnqueue(this,chunk)}error(e){if(IsReadableStreamDefaultController(this)===false)throw new TypeError(streamErrors_illegalInvocation);const stream=this[_controlledReadableStream];const state=ReadableStreamGetState(stream);if(state===STATE_ERRORED)throw new TypeError(errErrorErroredStream);if(state===STATE_CLOSED)throw new TypeError(errErrorClosedStream);return ReadableStreamDefaultControllerError(this,e)}}function ReadableStreamDefaultControllerCancel(controller,
+reason){controller[_queue]=new SimpleQueue;const underlyingSource=controller[_underlyingSource];return PromiseCallOrNoop(underlyingSource,"cancel",reason,"underlyingSource.cancel")}function ReadableStreamDefaultControllerPull(controller){const stream=controller[_controlledReadableStream];if(controller[_queue].length>0){const chunk=DequeueValue(controller);if(controller[_readableStreamDefaultControllerBits]&CLOSE_REQUESTED&&controller[_queue].length===0)ReadableStreamClose(stream);else ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+return Promise_resolve(CreateIterResultObject(chunk,false))}const pendingPromise=ReadableStreamAddReadRequest(stream);ReadableStreamDefaultControllerCallPullIfNeeded(controller);return pendingPromise}function ReadableStreamAddReadRequest(stream){const promise=v8_createPromise();stream[_reader][_readRequests].push(promise);return promise}class ReadableStreamDefaultReader{constructor(stream){if(IsReadableStream(stream)===false)throw new TypeError(errReaderConstructorBadArgument);if(IsReadableStreamLocked(stream)===
+true)throw new TypeError(errReaderConstructorStreamAlreadyLocked);ReadableStreamReaderGenericInitialize(this,stream);this[_readRequests]=new SimpleQueue}get closed(){if(IsReadableStreamDefaultReader(this)===false)return Promise_reject(new TypeError(streamErrors_illegalInvocation));return this[_closedPromise]}cancel(reason){if(IsReadableStreamDefaultReader(this)===false)return Promise_reject(new TypeError(streamErrors_illegalInvocation));const stream=this[_ownerReadableStream];if(stream===undefined)return Promise_reject(new TypeError(errCancelReleasedReader));
+return ReadableStreamReaderGenericCancel(this,reason)}read(){if(IsReadableStreamDefaultReader(this)===false)return Promise_reject(new TypeError(streamErrors_illegalInvocation));if(this[_ownerReadableStream]===undefined)return Promise_reject(new TypeError(errReadReleasedReader));return ReadableStreamDefaultReaderRead(this)}releaseLock(){if(IsReadableStreamDefaultReader(this)===false)throw new TypeError(streamErrors_illegalInvocation);const stream=this[_ownerReadableStream];if(stream===undefined)return undefined;
+if(this[_readRequests].length>0)throw new TypeError(errReleaseReaderWithPendingRead);ReadableStreamReaderGenericRelease(this)}}function ReadableStreamReaderGenericCancel(reader,reason){return ReadableStreamCancel(reader[_ownerReadableStream],reason)}function AcquireReadableStreamDefaultReader(stream){return new ReadableStreamDefaultReader(stream)}function ReadableStreamCancel(stream,reason){stream[_readableStreamBits]|=DISTURBED;const state=ReadableStreamGetState(stream);if(state===STATE_CLOSED)return Promise_resolve(undefined);
+if(state===STATE_ERRORED)return Promise_reject(stream[_storedError]);ReadableStreamClose(stream);const sourceCancelPromise=ReadableStreamDefaultControllerCancel(stream[_controller],reason);return thenPromise(sourceCancelPromise,()=>undefined)}function ReadableStreamDefaultControllerClose(controller){const stream=controller[_controlledReadableStream];controller[_readableStreamDefaultControllerBits]|=CLOSE_REQUESTED;if(controller[_queue].length===0)ReadableStreamClose(stream)}function ReadableStreamFulfillReadRequest(stream,
+chunk,done){const reader=stream[_reader];const readRequest=stream[_reader][_readRequests].shift();v8_resolvePromise(readRequest,CreateIterResultObject(chunk,done))}function ReadableStreamDefaultControllerEnqueue(controller,chunk){const stream=controller[_controlledReadableStream];if(IsReadableStreamLocked(stream)===true&&ReadableStreamGetNumReadRequests(stream)>0)ReadableStreamFulfillReadRequest(stream,chunk,false);else{let chunkSize=1;const strategySize=controller[_strategySize];if(strategySize!==
+undefined)try{chunkSize=strategySize(chunk)}catch(chunkSizeE){if(ReadableStreamGetState(stream)===STATE_READABLE)ReadableStreamDefaultControllerError(controller,chunkSizeE);throw chunkSizeE;}try{EnqueueValueWithSize(controller,chunk,chunkSize)}catch(enqueueE){if(ReadableStreamGetState(stream)===STATE_READABLE)ReadableStreamDefaultControllerError(controller,enqueueE);throw enqueueE;}}ReadableStreamDefaultControllerCallPullIfNeeded(controller)}function ReadableStreamGetState(stream){return(stream[_readableStreamBits]&
+STATE_MASK)>>STATE_BITS_OFFSET}function ReadableStreamSetState(stream,state){stream[_readableStreamBits]=stream[_readableStreamBits]&~STATE_MASK|state<<STATE_BITS_OFFSET}function ReadableStreamDefaultControllerError(controller,e){controller[_queue]=new SimpleQueue;const stream=controller[_controlledReadableStream];ReadableStreamError(stream,e)}function ReadableStreamError(stream,e){stream[_storedError]=e;ReadableStreamSetState(stream,STATE_ERRORED);const reader=stream[_reader];if(reader===undefined)return undefined;
+if(IsReadableStreamDefaultReader(reader)===true){reader[_readRequests].forEach((request)=>v8_rejectPromise(request,e));reader[_readRequests]=new SimpleQueue}v8_rejectPromise(reader[_closedPromise],e);v8_markPromiseAsHandled(reader[_closedPromise])}function ReadableStreamClose(stream){ReadableStreamSetState(stream,STATE_CLOSED);const reader=stream[_reader];if(reader===undefined)return undefined;if(IsReadableStreamDefaultReader(reader)===true){reader[_readRequests].forEach((request)=>v8_resolvePromise(request,
+CreateIterResultObject(undefined,true)));reader[_readRequests]=new SimpleQueue}v8_resolvePromise(reader[_closedPromise],undefined)}function ReadableStreamDefaultControllerGetDesiredSize(controller){const stream=controller[_controlledReadableStream];const state=ReadableStreamGetState(stream);if(state===STATE_CLOSED)return 0;else if(state===STATE_ERRORED)return null;const queueSize=GetTotalQueueSize(controller);return controller[_strategyHWM]-queueSize}function IsReadableStream(x){return hasOwnProperty(x,
+_controller)}function IsReadableStreamDisturbed(stream){return stream[_readableStreamBits]&DISTURBED}function IsReadableStreamLocked(stream){return stream[_reader]!==undefined}function IsReadableStreamDefaultController(x){return hasOwnProperty(x,_controlledReadableStream)}function IsReadableStreamDefaultReader(x){return hasOwnProperty(x,_readRequests)}function IsReadableStreamReadable(stream){return ReadableStreamGetState(stream)===STATE_READABLE}function IsReadableStreamClosed(stream){return ReadableStreamGetState(stream)===
+STATE_CLOSED}function IsReadableStreamErrored(stream){return ReadableStreamGetState(stream)===STATE_ERRORED}function ReadableStreamReaderGenericInitialize(reader,stream){const controller=stream[_controller];if(controller[_readableStreamDefaultControllerBits]&EXTERNALLY_CONTROLLED){const underlyingSource=controller[_underlyingSource];callFunction(underlyingSource.notifyLockAcquired,underlyingSource)}reader[_ownerReadableStream]=stream;stream[_reader]=reader;switch(ReadableStreamGetState(stream)){case STATE_READABLE:reader[_closedPromise]=
+v8_createPromise();break;case STATE_CLOSED:reader[_closedPromise]=Promise_resolve(undefined);break;case STATE_ERRORED:reader[_closedPromise]=Promise_reject(stream[_storedError]);v8_markPromiseAsHandled(reader[_closedPromise]);break}}function ReadableStreamReaderGenericRelease(reader){const controller=reader[_ownerReadableStream][_controller];if(controller[_readableStreamDefaultControllerBits]&EXTERNALLY_CONTROLLED){const underlyingSource=controller[_underlyingSource];callFunction(underlyingSource.notifyLockReleased,
+underlyingSource)}if(ReadableStreamGetState(reader[_ownerReadableStream])===STATE_READABLE)v8_rejectPromise(reader[_closedPromise],new TypeError(errReleasedReaderClosedPromise));else reader[_closedPromise]=Promise_reject(new TypeError(errReleasedReaderClosedPromise));v8_markPromiseAsHandled(reader[_closedPromise]);reader[_ownerReadableStream][_reader]=undefined;reader[_ownerReadableStream]=undefined}function ReadableStreamDefaultReaderRead(reader){const stream=reader[_ownerReadableStream];stream[_readableStreamBits]|=
+DISTURBED;if(ReadableStreamGetState(stream)===STATE_CLOSED)return Promise_resolve(CreateIterResultObject(undefined,true));if(ReadableStreamGetState(stream)===STATE_ERRORED)return Promise_reject(stream[_storedError]);return ReadableStreamDefaultControllerPull(stream[_controller])}function ReadableStreamDefaultControllerCallPullIfNeeded(controller){const shouldPull=ReadableStreamDefaultControllerShouldCallPull(controller);if(shouldPull===false)return undefined;if(controller[_readableStreamDefaultControllerBits]&
+PULLING){controller[_readableStreamDefaultControllerBits]|=PULL_AGAIN;return undefined}controller[_readableStreamDefaultControllerBits]|=PULLING;const underlyingSource=controller[_underlyingSource];const pullPromise=PromiseCallOrNoop(underlyingSource,"pull",controller,"underlyingSource.pull");thenPromise(pullPromise,()=>{controller[_readableStreamDefaultControllerBits]&=~PULLING;if(controller[_readableStreamDefaultControllerBits]&PULL_AGAIN){controller[_readableStreamDefaultControllerBits]&=~PULL_AGAIN;
+ReadableStreamDefaultControllerCallPullIfNeeded(controller)}},(e)=>{if(ReadableStreamGetState(controller[_controlledReadableStream])===STATE_READABLE)ReadableStreamDefaultControllerError(controller,e)})}function ReadableStreamDefaultControllerShouldCallPull(controller){const stream=controller[_controlledReadableStream];const state=ReadableStreamGetState(stream);if(state===STATE_CLOSED||state===STATE_ERRORED)return false;if(controller[_readableStreamDefaultControllerBits]&CLOSE_REQUESTED)return false;
+if(!(controller[_readableStreamDefaultControllerBits]&STARTED))return false;if(IsReadableStreamLocked(stream)===true&&ReadableStreamGetNumReadRequests(stream)>0)return true;const desiredSize=ReadableStreamDefaultControllerGetDesiredSize(controller);if(desiredSize>0)return true;return false}function ReadableStreamGetNumReadRequests(stream){const reader=stream[_reader];const readRequests=reader[_readRequests];return readRequests.length}function ReadableStreamTee(stream){const reader=AcquireReadableStreamDefaultReader(stream);
+let closedOrErrored=false;let canceled1=false;let canceled2=false;let reason1;let reason2;let promise=v8_createPromise();const branch1Stream=new ReadableStream({pull,cancel:cancel1});const branch2Stream=new ReadableStream({pull,cancel:cancel2});const branch1=branch1Stream[_controller];const branch2=branch2Stream[_controller];thenPromise(reader[_closedPromise],undefined,function(r){if(closedOrErrored===true)return;ReadableStreamDefaultControllerError(branch1,r);ReadableStreamDefaultControllerError(branch2,
+r);closedOrErrored=true});return[branch1Stream,branch2Stream];function pull(){return thenPromise(ReadableStreamDefaultReaderRead(reader),function(result){const value=result.value;const done=result.done;if(done===true&&closedOrErrored===false){if(canceled1===false)ReadableStreamDefaultControllerClose(branch1);if(canceled2===false)ReadableStreamDefaultControllerClose(branch2);closedOrErrored=true}if(closedOrErrored===true)return;if(canceled1===false)ReadableStreamDefaultControllerEnqueue(branch1,value);
+if(canceled2===false)ReadableStreamDefaultControllerEnqueue(branch2,value)})}function cancel1(reason){canceled1=true;reason1=reason;if(canceled2===true){const compositeReason=[reason1,reason2];const cancelResult=ReadableStreamCancel(stream,compositeReason);v8_resolvePromise(promise,cancelResult)}return promise}function cancel2(reason){canceled2=true;reason2=reason;if(canceled1===true){const compositeReason=[reason1,reason2];const cancelResult=ReadableStreamCancel(stream,compositeReason);v8_resolvePromise(promise,
+cancelResult)}return promise}}function DequeueValue(controller){const result=controller[_queue].shift();controller[_totalQueuedSize]-=result.size;return result.value}function EnqueueValueWithSize(controller,value,size){size=Number(size);if(Number_isNaN(size)||size===+Infinity||size<0)throw new RangeError(streamErrors_invalidSize);controller[_totalQueuedSize]+=size;controller[_queue].push({value,size})}function GetTotalQueueSize(controller){return controller[_totalQueuedSize]}function ValidateAndNormalizeQueuingStrategy(size,
+highWaterMark){if(size!==undefined&&typeof size!=="function")throw new TypeError(streamErrors_sizeNotAFunction);highWaterMark=Number(highWaterMark);if(Number_isNaN(highWaterMark))throw new RangeError(streamErrors_invalidHWM);if(highWaterMark<0)throw new RangeError(streamErrors_invalidHWM);return{size,highWaterMark}}function CallOrNoop(O,P,arg,nameForError){const method=O[P];if(method===undefined)return undefined;if(typeof method!=="function")throw new TypeError(errTmplMustBeFunctionOrUndefined(nameForError));
+return callFunction(method,O,arg)}function PromiseCallOrNoop(O,P,arg,nameForError){let method;try{method=O[P]}catch(methodE){return Promise_reject(methodE)}if(method===undefined)return Promise_resolve(undefined);if(typeof method!=="function")return Promise_reject(new TypeError(errTmplMustBeFunctionOrUndefined(nameForError)));try{return Promise_resolve(callFunction(method,O,arg))}catch(e){return Promise_reject(e)}}function CreateIterResultObject(value,done){return{value,done}}defineProperty(global,
+"ReadableStream",{value:ReadableStream,enumerable:false,configurable:true,writable:true})})(this);
\ No newline at end of file
diff --git a/src/cobalt/streams/readable_stream.js b/src/cobalt/streams/readable_stream.js
new file mode 100644
index 0000000..5943f89
--- /dev/null
+++ b/src/cobalt/streams/readable_stream.js
@@ -0,0 +1,1083 @@
+// ==ClosureCompiler==
+// @output_file_name readable_stream.js
+// @compilation_level WHITESPACE_ONLY
+// @language_out ES6_STRICT
+// ==/ClosureCompiler==
+
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function(global) {
+ 'use strict';
+
+ // Mimic functionality provided to v8 extras.
+ const v8_InternalPackedArray = global.Array;
+
+ function v8_createPrivateSymbol(x) {
+ return Symbol(x);
+ }
+
+ function v8_simpleBind(fn, obj) {
+ return fn.bind(obj);
+ }
+
+ const arraySlice = global.Array.prototype.slice;
+ function v8_uncurryThis(fn) {
+ return function(obj) {
+ return fn.apply(obj, arraySlice.call(arguments, 1));
+ }
+ }
+
+ const v8_PromiseBase = global.Promise;
+ const _promiseResolve = v8_createPrivateSymbol('[[Resolve]]');
+ const _promiseReject = v8_createPrivateSymbol('[[Reject]]');
+
+ function v8_Promise() {
+ var that = this;
+ v8_PromiseBase.call(this, function(resolve, reject) {
+ that[_promiseResolve] = resolve;
+ that[_promiseReject] = reject;
+ });
+ }
+
+ v8_Promise.prototype = v8_PromiseBase.prototype;
+
+ function v8_createPromise() {
+ return new v8_Promise();
+ }
+
+ function v8_isPromise(obj) {
+ return obj instanceof v8_Promise;
+ }
+
+ function v8_resolvePromise(promise, value) {
+ promise[_promiseResolve](value);
+ }
+
+ function v8_rejectPromise(promise, reason) {
+ promise[_promiseReject](reason);
+ }
+
+ function v8_markPromiseAsHandled(promise) {
+ try {
+ thenPromise(promise, undefined, () => {});
+ } catch(error) {
+ }
+ }
+
+ /* SimpleQueue.js: begin */
+ // Simple queue structure. Avoids scalability issues with using
+ // InternalPackedArray directly by using multiple arrays in a linked list and
+ // keeping the array size bounded.
+ const QUEUE_MAX_ARRAY_SIZE = 16384;
+ class SimpleQueue {
+ constructor() {
+ this.front = {
+ elements: new v8_InternalPackedArray(),
+ next: undefined,
+ };
+ this.back = this.front;
+ // The cursor is used to avoid calling InternalPackedArray.shift().
+ this.cursor = 0;
+ this.size = 0;
+ }
+
+ get length() {
+ return this.size;
+ }
+
+ push(element) {
+ ++this.size;
+ if (this.back.elements.length === QUEUE_MAX_ARRAY_SIZE) {
+ const oldBack = this.back;
+ this.back = {
+ elements: new v8_InternalPackedArray(),
+ next: undefined,
+ };
+ oldBack.next = this.back;
+ }
+ this.back.elements.push(element);
+ }
+
+ shift() {
+ // assert(this.size > 0);
+ --this.size;
+ if (this.front.elements.length === this.cursor) {
+ // assert(this.cursor === QUEUE_MAX_ARRAY_SIZE);
+ // assert(this.front.next !== undefined);
+ this.front = this.front.next;
+ this.cursor = 0;
+ }
+ const element = this.front.elements[this.cursor];
+ // Permit shifted element to be garbage collected.
+ this.front.elements[this.cursor] = undefined;
+ ++this.cursor;
+
+ return element;
+ }
+
+ forEach(callback) {
+ let i = this.cursor;
+ let node = this.front;
+ let elements = node.elements;
+ while (i !== elements.length || node.next !== undefined) {
+ if (i === elements.length) {
+ // assert(node.next !== undefined);
+ // assert(i === QUEUE_MAX_ARRAY_SIZE);
+ node = node.next;
+ elements = node.elements;
+ i = 0;
+ }
+ callback(elements[i]);
+ ++i;
+ }
+ }
+
+ // Return the element that would be returned if shift() was called now,
+ // without modifying the queue.
+ peek() {
+ // assert(this.size > 0);
+ if (this.front.elements.length === this.cursor) {
+ // assert(this.cursor === QUEUE_MAX_ARRAY_SIZE)
+ // assert(this.front.next !== undefined);
+ return this.front.next.elements[0];
+ }
+ return this.front.elements[this.cursor];
+ }
+ }
+ /* SimpleQueue.js: end */
+
+ /* CommonStrings.js: begin */
+ const streamErrors_illegalInvocation = 'Illegal invocation';
+ const streamErrors_illegalConstructor = 'Illegal constructor';
+ const streamErrors_invalidType = 'Invalid type is specified';
+ const streamErrors_invalidSize = 'The return value of a queuing strategy\'s size function must be a finite, non-NaN, non-negative number';
+ const streamErrors_sizeNotAFunction = 'A queuing strategy\'s size property must be a function';
+ const streamErrors_invalidHWM = 'A queueing strategy\'s highWaterMark property must be a nonnegative, non-NaN number';
+ /* CommonStrings.js: end */
+
+ const _reader = v8_createPrivateSymbol('[[reader]]');
+ const _storedError = v8_createPrivateSymbol('[[storedError]]');
+ const _controller = v8_createPrivateSymbol('[[controller]]');
+
+ const _closedPromise = v8_createPrivateSymbol('[[closedPromise]]');
+ const _ownerReadableStream =
+ v8_createPrivateSymbol('[[ownerReadableStream]]');
+
+ const _readRequests = v8_createPrivateSymbol('[[readRequests]]');
+
+ const createWithExternalControllerSentinel =
+ v8_createPrivateSymbol('flag for UA-created ReadableStream to pass');
+
+ const _readableStreamBits = v8_createPrivateSymbol('bit field for [[state]] and [[disturbed]]');
+ const DISTURBED = 0b1;
+ // The 2nd and 3rd bit are for [[state]].
+ const STATE_MASK = 0b110;
+ const STATE_BITS_OFFSET = 1;
+ const STATE_READABLE = 0;
+ const STATE_CLOSED = 1;
+ const STATE_ERRORED = 2;
+
+ const _underlyingSource = v8_createPrivateSymbol('[[underlyingSource]]');
+ const _controlledReadableStream =
+ v8_createPrivateSymbol('[[controlledReadableStream]]');
+ const _queue = v8_createPrivateSymbol('[[queue]]');
+ const _totalQueuedSize = v8_createPrivateSymbol('[[totalQueuedSize]]');
+ const _strategySize = v8_createPrivateSymbol('[[strategySize]]');
+ const _strategyHWM = v8_createPrivateSymbol('[[strategyHWM]]');
+
+ const _readableStreamDefaultControllerBits = v8_createPrivateSymbol(
+ 'bit field for [[started]], [[closeRequested]], [[pulling]], [[pullAgain]]');
+ const STARTED = 0b1;
+ const CLOSE_REQUESTED = 0b10;
+ const PULLING = 0b100;
+ const PULL_AGAIN = 0b1000;
+ const EXTERNALLY_CONTROLLED = 0b10000;
+
+ const undefined = global.undefined;
+ const Infinity = global.Infinity;
+
+ const defineProperty = global.Object.defineProperty;
+ const hasOwnProperty = v8_uncurryThis(global.Object.hasOwnProperty);
+ const callFunction = v8_uncurryThis(global.Function.prototype.call);
+ const applyFunction = v8_uncurryThis(global.Function.prototype.apply);
+
+ const TypeError = global.TypeError;
+ const RangeError = global.RangeError;
+
+ const Number = global.Number;
+ const Number_isNaN = Number.isNaN;
+ const Number_isFinite = Number.isFinite;
+
+ const Promise = global.Promise;
+ const thenPromise = v8_uncurryThis(Promise.prototype.then);
+ const Promise_resolve = v8_simpleBind(Promise.resolve, Promise);
+ const Promise_reject = v8_simpleBind(Promise.reject, Promise);
+
+ const errCancelLockedStream =
+ 'Cannot cancel a readable stream that is locked to a reader';
+ const errEnqueueCloseRequestedStream =
+ 'Cannot enqueue a chunk into a readable stream that is closed or has been requested to be closed';
+ const errCancelReleasedReader =
+ 'This readable stream reader has been released and cannot be used to cancel its previous owner stream';
+ const errReadReleasedReader =
+ 'This readable stream reader has been released and cannot be used to read from its previous owner stream';
+ const errCloseCloseRequestedStream =
+ 'Cannot close a readable stream that has already been requested to be closed';
+ const errEnqueueClosedStream = 'Cannot enqueue a chunk into a closed readable stream';
+ const errEnqueueErroredStream = 'Cannot enqueue a chunk into an errored readable stream';
+ const errCloseClosedStream = 'Cannot close a closed readable stream';
+ const errCloseErroredStream = 'Cannot close an errored readable stream';
+ const errErrorClosedStream = 'Cannot error a close readable stream';
+ const errErrorErroredStream =
+ 'Cannot error a readable stream that is already errored';
+ const errGetReaderNotByteStream = 'This readable stream does not support BYOB readers';
+ const errGetReaderBadMode = 'Invalid reader mode given: expected undefined or "byob"';
+ const errReaderConstructorBadArgument =
+ 'ReadableStreamReader constructor argument is not a readable stream';
+ const errReaderConstructorStreamAlreadyLocked =
+ 'ReadableStreamReader constructor can only accept readable streams that are not yet locked to a reader';
+ const errReleaseReaderWithPendingRead =
+ 'Cannot release a readable stream reader when it still has outstanding read() calls that have not yet settled';
+ const errReleasedReaderClosedPromise =
+ 'This readable stream reader has been released and cannot be used to monitor the stream\'s state';
+
+ const errTmplMustBeFunctionOrUndefined = name =>
+ `${name} must be a function or undefined`;
+
+ class ReadableStream {
+ constructor() {
+ // TODO(domenic): when V8 gets default parameters and destructuring, all
+ // this can be cleaned up.
+ const underlyingSource = arguments[0] === undefined ? {} : arguments[0];
+ const strategy = arguments[1] === undefined ? {} : arguments[1];
+ const size = strategy.size;
+ let highWaterMark = strategy.highWaterMark;
+ if (highWaterMark === undefined) {
+ highWaterMark = 1;
+ }
+
+ this[_readableStreamBits] = 0b0;
+ ReadableStreamSetState(this, STATE_READABLE);
+ this[_reader] = undefined;
+ this[_storedError] = undefined;
+
+ // Avoid allocating the controller if the stream is going to be controlled
+ // externally (i.e. from C++) anyway. All calls to underlyingSource
+ // methods will disregard their controller argument in such situations
+ // (but see below).
+
+ this[_controller] = undefined;
+
+ const type = underlyingSource.type;
+ const typeString = String(type);
+ if (typeString === 'bytes') {
+ throw new RangeError('bytes type is not yet implemented');
+ } else if (type !== undefined) {
+ throw new RangeError(streamErrors_invalidType);
+ }
+
+ this[_controller] =
+ new ReadableStreamDefaultController(this, underlyingSource, size, highWaterMark, arguments[2]);
+ }
+
+ get locked() {
+ if (IsReadableStream(this) === false) {
+ throw new TypeError(streamErrors_illegalInvocation);
+ }
+
+ return IsReadableStreamLocked(this);
+ }
+
+ cancel(reason) {
+ if (IsReadableStream(this) === false) {
+ return Promise_reject(new TypeError(streamErrors_illegalInvocation));
+ }
+
+ if (IsReadableStreamLocked(this) === true) {
+ return Promise_reject(new TypeError(errCancelLockedStream));
+ }
+
+ return ReadableStreamCancel(this, reason);
+ }
+
+ getReader({ mode } = {}) {
+ if (IsReadableStream(this) === false) {
+ throw new TypeError(streamErrors_illegalInvocation);
+ }
+
+ if (mode === 'byob') {
+ // TODO(ricea): When BYOB readers are supported:
+ //
+ // a. If
+ // ! IsReadableByteStreamController(this.[[_controller]])
+ // is false, throw a TypeError exception.
+ // b. Return ? AcquireReadableStreamBYOBReader(this).
+ throw new TypeError(errGetReaderNotByteStream);
+ }
+
+ if (mode === undefined) {
+ return AcquireReadableStreamDefaultReader(this);
+ }
+
+ throw new RangeError(errGetReaderBadMode);
+ }
+
+ pipeThrough({writable, readable}, options) {
+ throw new TypeError('pipeThrough not implemented');
+ }
+
+ pipeTo(dest, {preventClose, preventAbort, preventCancel} = {}) {
+ throw new TypeError('pipeTo not implemented');
+ }
+
+ tee() {
+ if (IsReadableStream(this) === false) {
+ throw new TypeError(streamErrors_illegalInvocation);
+ }
+
+ return ReadableStreamTee(this);
+ }
+ }
+
+ class ReadableStreamDefaultController {
+ // Cobalt: Constructor has a hidden argument at the end to designate
+ // whether it is externally controlled. Exposing this would fail the
+ // web platform test checking the number of parameters the constructor
+ // accepts.
+ constructor(stream, underlyingSource, size, highWaterMark) {
+ if (IsReadableStream(stream) === false) {
+ throw new TypeError(streamErrors_illegalConstructor);
+ }
+
+ if (stream[_controller] !== undefined) {
+ throw new TypeError(streamErrors_illegalConstructor);
+ }
+
+ this[_controlledReadableStream] = stream;
+
+ this[_underlyingSource] = underlyingSource;
+
+ this[_queue] = new SimpleQueue();
+ this[_totalQueuedSize] = 0;
+
+ this[_readableStreamDefaultControllerBits] = 0b0;
+ // Cobalt: Hidden constructor parameter to designate whether the
+ // is externally controlled.
+ if (arguments[4] === createWithExternalControllerSentinel) {
+ this[_readableStreamDefaultControllerBits] |= EXTERNALLY_CONTROLLED;
+ }
+
+ const normalizedStrategy =
+ ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
+ this[_strategySize] = normalizedStrategy.size;
+ this[_strategyHWM] = normalizedStrategy.highWaterMark;
+
+ const controller = this;
+
+ const startResult = CallOrNoop(
+ underlyingSource, 'start', this, 'underlyingSource.start');
+ thenPromise(Promise_resolve(startResult),
+ () => {
+ controller[_readableStreamDefaultControllerBits] |= STARTED;
+ ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+ },
+ r => {
+ if (ReadableStreamGetState(stream) === STATE_READABLE) {
+ ReadableStreamDefaultControllerError(controller, r);
+ }
+ });
+ }
+
+ get desiredSize() {
+ if (IsReadableStreamDefaultController(this) === false) {
+ throw new TypeError(streamErrors_illegalInvocation);
+ }
+
+ return ReadableStreamDefaultControllerGetDesiredSize(this);
+ }
+
+ close() {
+ if (IsReadableStreamDefaultController(this) === false) {
+ throw new TypeError(streamErrors_illegalInvocation);
+ }
+
+ const stream = this[_controlledReadableStream];
+
+ if (this[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
+ throw new TypeError(errCloseCloseRequestedStream);
+ }
+
+ const state = ReadableStreamGetState(stream);
+ if (state === STATE_ERRORED) {
+ throw new TypeError(errCloseErroredStream);
+ }
+ if (state === STATE_CLOSED) {
+ throw new TypeError(errCloseClosedStream);
+ }
+
+ return ReadableStreamDefaultControllerClose(this);
+ }
+
+ enqueue(chunk) {
+ if (IsReadableStreamDefaultController(this) === false) {
+ throw new TypeError(streamErrors_illegalInvocation);
+ }
+
+ const stream = this[_controlledReadableStream];
+
+ if (this[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
+ throw new TypeError(errEnqueueCloseRequestedStream);
+ }
+
+ const state = ReadableStreamGetState(stream);
+ if (state === STATE_ERRORED) {
+ throw new TypeError(errEnqueueErroredStream);
+ }
+ if (state === STATE_CLOSED) {
+ throw new TypeError(errEnqueueClosedStream);
+ }
+
+ return ReadableStreamDefaultControllerEnqueue(this, chunk);
+ }
+
+ error(e) {
+ if (IsReadableStreamDefaultController(this) === false) {
+ throw new TypeError(streamErrors_illegalInvocation);
+ }
+
+ const stream = this[_controlledReadableStream];
+
+ const state = ReadableStreamGetState(stream);
+ if (state === STATE_ERRORED) {
+ throw new TypeError(errErrorErroredStream);
+ }
+ if (state === STATE_CLOSED) {
+ throw new TypeError(errErrorClosedStream);
+ }
+
+ return ReadableStreamDefaultControllerError(this, e);
+ }
+ }
+
+ function ReadableStreamDefaultControllerCancel(controller, reason) {
+ controller[_queue] = new SimpleQueue();
+
+ const underlyingSource = controller[_underlyingSource];
+ return PromiseCallOrNoop(underlyingSource, 'cancel', reason, 'underlyingSource.cancel');
+ }
+
+ function ReadableStreamDefaultControllerPull(controller) {
+ const stream = controller[_controlledReadableStream];
+
+ if (controller[_queue].length > 0) {
+ const chunk = DequeueValue(controller);
+
+ if ((controller[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) &&
+ controller[_queue].length === 0) {
+ ReadableStreamClose(stream);
+ } else {
+ ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+ }
+
+ return Promise_resolve(CreateIterResultObject(chunk, false));
+ }
+
+ const pendingPromise = ReadableStreamAddReadRequest(stream);
+ ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+ return pendingPromise;
+ }
+
+ function ReadableStreamAddReadRequest(stream) {
+ const promise = v8_createPromise();
+ stream[_reader][_readRequests].push(promise);
+ return promise;
+ }
+
+ class ReadableStreamDefaultReader {
+ constructor(stream) {
+ if (IsReadableStream(stream) === false) {
+ throw new TypeError(errReaderConstructorBadArgument);
+ }
+ if (IsReadableStreamLocked(stream) === true) {
+ throw new TypeError(errReaderConstructorStreamAlreadyLocked);
+ }
+
+ ReadableStreamReaderGenericInitialize(this, stream);
+
+ this[_readRequests] = new SimpleQueue();
+ }
+
+ get closed() {
+ if (IsReadableStreamDefaultReader(this) === false) {
+ return Promise_reject(new TypeError(streamErrors_illegalInvocation));
+ }
+
+ return this[_closedPromise];
+ }
+
+ cancel(reason) {
+ if (IsReadableStreamDefaultReader(this) === false) {
+ return Promise_reject(new TypeError(streamErrors_illegalInvocation));
+ }
+
+ const stream = this[_ownerReadableStream];
+ if (stream === undefined) {
+ return Promise_reject(new TypeError(errCancelReleasedReader));
+ }
+
+ return ReadableStreamReaderGenericCancel(this, reason);
+ }
+
+ read() {
+ if (IsReadableStreamDefaultReader(this) === false) {
+ return Promise_reject(new TypeError(streamErrors_illegalInvocation));
+ }
+
+ if (this[_ownerReadableStream] === undefined) {
+ return Promise_reject(new TypeError(errReadReleasedReader));
+ }
+
+ return ReadableStreamDefaultReaderRead(this);
+ }
+
+ releaseLock() {
+ if (IsReadableStreamDefaultReader(this) === false) {
+ throw new TypeError(streamErrors_illegalInvocation);
+ }
+
+ const stream = this[_ownerReadableStream];
+ if (stream === undefined) {
+ return undefined;
+ }
+
+ if (this[_readRequests].length > 0) {
+ throw new TypeError(errReleaseReaderWithPendingRead);
+ }
+
+ ReadableStreamReaderGenericRelease(this);
+ }
+ }
+
+ function ReadableStreamReaderGenericCancel(reader, reason) {
+ return ReadableStreamCancel(reader[_ownerReadableStream], reason);
+ }
+
+ //
+ // Readable stream abstract operations
+ //
+
+ function AcquireReadableStreamDefaultReader(stream) {
+ return new ReadableStreamDefaultReader(stream);
+ }
+
+ function ReadableStreamCancel(stream, reason) {
+ stream[_readableStreamBits] |= DISTURBED;
+
+ const state = ReadableStreamGetState(stream);
+ if (state === STATE_CLOSED) {
+ return Promise_resolve(undefined);
+ }
+ if (state === STATE_ERRORED) {
+ return Promise_reject(stream[_storedError]);
+ }
+
+ ReadableStreamClose(stream);
+
+ const sourceCancelPromise = ReadableStreamDefaultControllerCancel(stream[_controller], reason);
+ return thenPromise(sourceCancelPromise, () => undefined);
+ }
+
+ function ReadableStreamDefaultControllerClose(controller) {
+ const stream = controller[_controlledReadableStream];
+
+ controller[_readableStreamDefaultControllerBits] |= CLOSE_REQUESTED;
+
+ if (controller[_queue].length === 0) {
+ ReadableStreamClose(stream);
+ }
+ }
+
+ function ReadableStreamFulfillReadRequest(stream, chunk, done) {
+ const reader = stream[_reader];
+
+ const readRequest = stream[_reader][_readRequests].shift();
+ v8_resolvePromise(readRequest, CreateIterResultObject(chunk, done));
+ }
+
+ function ReadableStreamDefaultControllerEnqueue(controller, chunk) {
+ const stream = controller[_controlledReadableStream];
+
+ if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
+ ReadableStreamFulfillReadRequest(stream, chunk, false);
+ } else {
+ let chunkSize = 1;
+
+ const strategySize = controller[_strategySize];
+ if (strategySize !== undefined) {
+ try {
+ chunkSize = strategySize(chunk);
+ } catch (chunkSizeE) {
+ if (ReadableStreamGetState(stream) === STATE_READABLE) {
+ ReadableStreamDefaultControllerError(controller, chunkSizeE);
+ }
+ throw chunkSizeE;
+ }
+ }
+
+ try {
+ EnqueueValueWithSize(controller, chunk, chunkSize);
+ } catch (enqueueE) {
+ if (ReadableStreamGetState(stream) === STATE_READABLE) {
+ ReadableStreamDefaultControllerError(controller, enqueueE);
+ }
+ throw enqueueE;
+ }
+ }
+
+ ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+ }
+
+ function ReadableStreamGetState(stream) {
+ return (stream[_readableStreamBits] & STATE_MASK) >> STATE_BITS_OFFSET;
+ }
+
+ function ReadableStreamSetState(stream, state) {
+ stream[_readableStreamBits] = (stream[_readableStreamBits] & ~STATE_MASK) |
+ (state << STATE_BITS_OFFSET);
+ }
+
+ function ReadableStreamDefaultControllerError(controller, e) {
+ controller[_queue] = new SimpleQueue();
+ const stream = controller[_controlledReadableStream];
+ ReadableStreamError(stream, e);
+ }
+
+ function ReadableStreamError(stream, e) {
+ stream[_storedError] = e;
+ ReadableStreamSetState(stream, STATE_ERRORED);
+
+ const reader = stream[_reader];
+ if (reader === undefined) {
+ return undefined;
+ }
+
+ if (IsReadableStreamDefaultReader(reader) === true) {
+ reader[_readRequests].forEach(request => v8_rejectPromise(request, e));
+ reader[_readRequests] = new SimpleQueue();
+ }
+
+ v8_rejectPromise(reader[_closedPromise], e);
+ v8_markPromiseAsHandled(reader[_closedPromise]);
+ }
+
+ function ReadableStreamClose(stream) {
+ ReadableStreamSetState(stream, STATE_CLOSED);
+
+ const reader = stream[_reader];
+ if (reader === undefined) {
+ return undefined;
+ }
+
+ if (IsReadableStreamDefaultReader(reader) === true) {
+ reader[_readRequests].forEach(request =>
+ v8_resolvePromise(request, CreateIterResultObject(undefined, true)));
+ reader[_readRequests] = new SimpleQueue();
+ }
+
+ v8_resolvePromise(reader[_closedPromise], undefined);
+ }
+
+ function ReadableStreamDefaultControllerGetDesiredSize(controller) {
+ // Cobalt: When the state is closed or errored, return particular values.
+ const stream = controller[_controlledReadableStream];
+ const state = ReadableStreamGetState(stream);
+ if (state === STATE_CLOSED) {
+ return 0;
+ } else if (state === STATE_ERRORED) {
+ return null;
+ }
+
+ const queueSize = GetTotalQueueSize(controller);
+ return controller[_strategyHWM] - queueSize;
+ }
+
+ function IsReadableStream(x) {
+ return hasOwnProperty(x, _controller);
+ }
+
+ function IsReadableStreamDisturbed(stream) {
+ return stream[_readableStreamBits] & DISTURBED;
+ }
+
+ function IsReadableStreamLocked(stream) {
+ return stream[_reader] !== undefined;
+ }
+
+ function IsReadableStreamDefaultController(x) {
+ return hasOwnProperty(x, _controlledReadableStream);
+ }
+
+ function IsReadableStreamDefaultReader(x) {
+ return hasOwnProperty(x, _readRequests);
+ }
+
+ function IsReadableStreamReadable(stream) {
+ return ReadableStreamGetState(stream) === STATE_READABLE;
+ }
+
+ function IsReadableStreamClosed(stream) {
+ return ReadableStreamGetState(stream) === STATE_CLOSED;
+ }
+
+ function IsReadableStreamErrored(stream) {
+ return ReadableStreamGetState(stream) === STATE_ERRORED;
+ }
+
+ function ReadableStreamReaderGenericInitialize(reader, stream) {
+ // TODO(yhirano): Remove this when we don't need hasPendingActivity in
+ // blink::UnderlyingSourceBase.
+ const controller = stream[_controller];
+ if (controller[_readableStreamDefaultControllerBits] & EXTERNALLY_CONTROLLED) {
+ // The stream is created with an external controller (i.e. made in
+ // Blink).
+ const underlyingSource = controller[_underlyingSource];
+ callFunction(underlyingSource.notifyLockAcquired, underlyingSource);
+ }
+
+ reader[_ownerReadableStream] = stream;
+ stream[_reader] = reader;
+
+ switch (ReadableStreamGetState(stream)) {
+ case STATE_READABLE:
+ reader[_closedPromise] = v8_createPromise();
+ break;
+ case STATE_CLOSED:
+ reader[_closedPromise] = Promise_resolve(undefined);
+ break;
+ case STATE_ERRORED:
+ reader[_closedPromise] = Promise_reject(stream[_storedError]);
+ v8_markPromiseAsHandled(reader[_closedPromise]);
+ break;
+ }
+ }
+
+ function ReadableStreamReaderGenericRelease(reader) {
+ // TODO(yhirano): Remove this when we don't need hasPendingActivity in
+ // blink::UnderlyingSourceBase.
+ const controller = reader[_ownerReadableStream][_controller];
+ if (controller[_readableStreamDefaultControllerBits] & EXTERNALLY_CONTROLLED) {
+ // The stream is created with an external controller (i.e. made in
+ // Blink).
+ const underlyingSource = controller[_underlyingSource];
+ callFunction(underlyingSource.notifyLockReleased, underlyingSource);
+ }
+
+ if (ReadableStreamGetState(reader[_ownerReadableStream]) === STATE_READABLE) {
+ v8_rejectPromise(reader[_closedPromise], new TypeError(errReleasedReaderClosedPromise));
+ } else {
+ reader[_closedPromise] = Promise_reject(new TypeError(errReleasedReaderClosedPromise));
+ }
+ v8_markPromiseAsHandled(reader[_closedPromise]);
+
+ reader[_ownerReadableStream][_reader] = undefined;
+ reader[_ownerReadableStream] = undefined;
+ }
+
+ function ReadableStreamDefaultReaderRead(reader) {
+ const stream = reader[_ownerReadableStream];
+ stream[_readableStreamBits] |= DISTURBED;
+
+ if (ReadableStreamGetState(stream) === STATE_CLOSED) {
+ return Promise_resolve(CreateIterResultObject(undefined, true));
+ }
+
+ if (ReadableStreamGetState(stream) === STATE_ERRORED) {
+ return Promise_reject(stream[_storedError]);
+ }
+
+ return ReadableStreamDefaultControllerPull(stream[_controller]);
+ }
+
+ function ReadableStreamDefaultControllerCallPullIfNeeded(controller) {
+ const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller);
+ if (shouldPull === false) {
+ return undefined;
+ }
+
+ if (controller[_readableStreamDefaultControllerBits] & PULLING) {
+ controller[_readableStreamDefaultControllerBits] |= PULL_AGAIN;
+ return undefined;
+ }
+
+ controller[_readableStreamDefaultControllerBits] |= PULLING;
+
+ const underlyingSource = controller[_underlyingSource];
+ const pullPromise = PromiseCallOrNoop(
+ underlyingSource, 'pull', controller, 'underlyingSource.pull');
+
+ thenPromise(pullPromise,
+ () => {
+ controller[_readableStreamDefaultControllerBits] &= ~PULLING;
+
+ if (controller[_readableStreamDefaultControllerBits] & PULL_AGAIN) {
+ controller[_readableStreamDefaultControllerBits] &= ~PULL_AGAIN;
+ ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+ }
+ },
+ e => {
+ if (ReadableStreamGetState(controller[_controlledReadableStream]) === STATE_READABLE) {
+ ReadableStreamDefaultControllerError(controller, e);
+ }
+ });
+ }
+
+ function ReadableStreamDefaultControllerShouldCallPull(controller) {
+ const stream = controller[_controlledReadableStream];
+
+ const state = ReadableStreamGetState(stream);
+ if (state === STATE_CLOSED || state === STATE_ERRORED) {
+ return false;
+ }
+
+ if (controller[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
+ return false;
+ }
+
+ if (!(controller[_readableStreamDefaultControllerBits] & STARTED)) {
+ return false;
+ }
+
+ if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
+ return true;
+ }
+
+ const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
+ if (desiredSize > 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+ function ReadableStreamGetNumReadRequests(stream) {
+ const reader = stream[_reader];
+ const readRequests = reader[_readRequests];
+ return readRequests.length;
+ }
+
+ // Potential future optimization: use class instances for the underlying
+ // sources, so that we don't re-create
+ // closures every time.
+
+ // TODO(domenic): shouldClone argument from spec not supported yet
+ function ReadableStreamTee(stream) {
+ const reader = AcquireReadableStreamDefaultReader(stream);
+
+ let closedOrErrored = false;
+ let canceled1 = false;
+ let canceled2 = false;
+ let reason1;
+ let reason2;
+ let promise = v8_createPromise();
+
+ const branch1Stream = new ReadableStream({pull, cancel: cancel1});
+
+ const branch2Stream = new ReadableStream({pull, cancel: cancel2});
+
+ const branch1 = branch1Stream[_controller];
+ const branch2 = branch2Stream[_controller];
+
+ thenPromise(
+ reader[_closedPromise], undefined, function(r) {
+ if (closedOrErrored === true) {
+ return;
+ }
+
+ ReadableStreamDefaultControllerError(branch1, r);
+ ReadableStreamDefaultControllerError(branch2, r);
+ closedOrErrored = true;
+ });
+
+ return [branch1Stream, branch2Stream];
+
+ function pull() {
+ return thenPromise(
+ ReadableStreamDefaultReaderRead(reader), function(result) {
+ const value = result.value;
+ const done = result.done;
+
+ if (done === true && closedOrErrored === false) {
+ if (canceled1 === false) {
+ ReadableStreamDefaultControllerClose(branch1);
+ }
+ if (canceled2 === false) {
+ ReadableStreamDefaultControllerClose(branch2);
+ }
+ closedOrErrored = true;
+ }
+
+ if (closedOrErrored === true) {
+ return;
+ }
+
+ if (canceled1 === false) {
+ ReadableStreamDefaultControllerEnqueue(branch1, value);
+ }
+
+ if (canceled2 === false) {
+ ReadableStreamDefaultControllerEnqueue(branch2, value);
+ }
+ });
+ }
+
+ function cancel1(reason) {
+ canceled1 = true;
+ reason1 = reason;
+
+ if (canceled2 === true) {
+ const compositeReason = [reason1, reason2];
+ const cancelResult = ReadableStreamCancel(stream, compositeReason);
+ v8_resolvePromise(promise, cancelResult);
+ }
+
+ return promise;
+ }
+
+ function cancel2(reason) {
+ canceled2 = true;
+ reason2 = reason;
+
+ if (canceled1 === true) {
+ const compositeReason = [reason1, reason2];
+ const cancelResult = ReadableStreamCancel(stream, compositeReason);
+ v8_resolvePromise(promise, cancelResult);
+ }
+
+ return promise;
+ }
+ }
+
+ //
+ // Queue-with-sizes
+ //
+
+ function DequeueValue(controller) {
+ const result = controller[_queue].shift();
+ controller[_totalQueuedSize] -= result.size;
+ return result.value;
+ }
+
+ function EnqueueValueWithSize(controller, value, size) {
+ size = Number(size);
+ if (Number_isNaN(size) || size === +Infinity || size < 0) {
+ throw new RangeError(streamErrors_invalidSize);
+ }
+
+ controller[_totalQueuedSize] += size;
+ controller[_queue].push({value, size});
+ }
+
+ function GetTotalQueueSize(controller) { return controller[_totalQueuedSize]; }
+
+ //
+ // Other helpers
+ //
+
+ function ValidateAndNormalizeQueuingStrategy(size, highWaterMark) {
+ if (size !== undefined && typeof size !== 'function') {
+ throw new TypeError(streamErrors_sizeNotAFunction);
+ }
+
+ highWaterMark = Number(highWaterMark);
+ if (Number_isNaN(highWaterMark)) {
+ throw new RangeError(streamErrors_invalidHWM);
+ }
+ if (highWaterMark < 0) {
+ throw new RangeError(streamErrors_invalidHWM);
+ }
+
+ return {size, highWaterMark};
+ }
+
+ // Modified from InvokeOrNoop in spec
+ function CallOrNoop(O, P, arg, nameForError) {
+ const method = O[P];
+ if (method === undefined) {
+ return undefined;
+ }
+ if (typeof method !== 'function') {
+ throw new TypeError(errTmplMustBeFunctionOrUndefined(nameForError));
+ }
+
+ return callFunction(method, O, arg);
+ }
+
+
+ // Modified from PromiseInvokeOrNoop in spec
+ function PromiseCallOrNoop(O, P, arg, nameForError) {
+ let method;
+ try {
+ method = O[P];
+ } catch (methodE) {
+ return Promise_reject(methodE);
+ }
+
+ if (method === undefined) {
+ return Promise_resolve(undefined);
+ }
+
+ if (typeof method !== 'function') {
+ return Promise_reject(new TypeError(errTmplMustBeFunctionOrUndefined(nameForError)));
+ }
+
+ try {
+ return Promise_resolve(callFunction(method, O, arg));
+ } catch (e) {
+ return Promise_reject(e);
+ }
+ }
+
+ function CreateIterResultObject(value, done) { return {value, done}; }
+
+
+ //
+ // Additions to the global
+ //
+
+ defineProperty(global, 'ReadableStream', {
+ value: ReadableStream,
+ enumerable: false,
+ configurable: true,
+ writable: true
+ });
+
+ //
+ // Exports to Blink
+ //
+
+/*
+ binding.AcquireReadableStreamDefaultReader = AcquireReadableStreamDefaultReader;
+ binding.IsReadableStream = IsReadableStream;
+ binding.IsReadableStreamDisturbed = IsReadableStreamDisturbed;
+ binding.IsReadableStreamLocked = IsReadableStreamLocked;
+ binding.IsReadableStreamReadable = IsReadableStreamReadable;
+ binding.IsReadableStreamClosed = IsReadableStreamClosed;
+ binding.IsReadableStreamErrored = IsReadableStreamErrored;
+ binding.IsReadableStreamDefaultReader = IsReadableStreamDefaultReader;
+ binding.ReadableStreamDefaultReaderRead = ReadableStreamDefaultReaderRead;
+ binding.ReadableStreamTee = ReadableStreamTee;
+
+ binding.ReadableStreamDefaultControllerClose = ReadableStreamDefaultControllerClose;
+ binding.ReadableStreamDefaultControllerGetDesiredSize = ReadableStreamDefaultControllerGetDesiredSize;
+ binding.ReadableStreamDefaultControllerEnqueue = ReadableStreamDefaultControllerEnqueue;
+ binding.ReadableStreamDefaultControllerError = ReadableStreamDefaultControllerError;
+
+ binding.createReadableStreamWithExternalController =
+ (underlyingSource, strategy) => {
+ return new ReadableStream(
+ underlyingSource, strategy, createWithExternalControllerSentinel);
+ };
+*/
+})(this);
diff --git a/src/cobalt/trace_event/benchmark_internal.h b/src/cobalt/trace_event/benchmark_internal.h
index c6a13cd..f060a2d 100644
--- a/src/cobalt/trace_event/benchmark_internal.h
+++ b/src/cobalt/trace_event/benchmark_internal.h
@@ -62,18 +62,20 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
@@ -155,36 +157,40 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
@@ -293,54 +299,60 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
switch (measurement_type_3) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " flow duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " flow duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " in-scope duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " in-scope duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_3) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_3) +\
+ " time between event starts in seconds", \
event_3_samples_));\
} break;\
}\
@@ -477,72 +489,80 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
switch (measurement_type_3) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " flow duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " flow duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " in-scope duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " in-scope duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_3) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_3) +\
+ " time between event starts in seconds", \
event_3_samples_));\
} break;\
}\
switch (measurement_type_4) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " flow duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " flow duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " in-scope duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " in-scope duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_4) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_4) +\
+ " time between event starts in seconds", \
event_4_samples_));\
} break;\
}\
@@ -706,90 +726,100 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
switch (measurement_type_3) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " flow duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " flow duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " in-scope duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " in-scope duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_3) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_3) +\
+ " time between event starts in seconds", \
event_3_samples_));\
} break;\
}\
switch (measurement_type_4) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " flow duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " flow duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " in-scope duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " in-scope duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_4) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_4) +\
+ " time between event starts in seconds", \
event_4_samples_));\
} break;\
}\
switch (measurement_type_5) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " flow duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " flow duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " in-scope duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " in-scope duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_5) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_5) +\
+ " time between event starts in seconds", \
event_5_samples_));\
} break;\
}\
@@ -981,108 +1011,120 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
switch (measurement_type_3) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " flow duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " flow duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " in-scope duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " in-scope duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_3) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_3) +\
+ " time between event starts in seconds", \
event_3_samples_));\
} break;\
}\
switch (measurement_type_4) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " flow duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " flow duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " in-scope duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " in-scope duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_4) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_4) +\
+ " time between event starts in seconds", \
event_4_samples_));\
} break;\
}\
switch (measurement_type_5) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " flow duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " flow duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " in-scope duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " in-scope duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_5) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_5) +\
+ " time between event starts in seconds", \
event_5_samples_));\
} break;\
}\
switch (measurement_type_6) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " flow duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " flow duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " in-scope duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " in-scope duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_6) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_6) +\
+ " time between event starts in seconds", \
event_6_samples_));\
} break;\
}\
@@ -1301,126 +1343,140 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
switch (measurement_type_3) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " flow duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " flow duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " in-scope duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " in-scope duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_3) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_3) +\
+ " time between event starts in seconds", \
event_3_samples_));\
} break;\
}\
switch (measurement_type_4) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " flow duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " flow duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " in-scope duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " in-scope duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_4) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_4) +\
+ " time between event starts in seconds", \
event_4_samples_));\
} break;\
}\
switch (measurement_type_5) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " flow duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " flow duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " in-scope duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " in-scope duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_5) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_5) +\
+ " time between event starts in seconds", \
event_5_samples_));\
} break;\
}\
switch (measurement_type_6) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " flow duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " flow duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " in-scope duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " in-scope duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_6) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_6) +\
+ " time between event starts in seconds", \
event_6_samples_));\
} break;\
}\
switch (measurement_type_7) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_7) + " flow duration in seconds",\
+ Result(std::string(event_name_7) +\
+ " flow duration in seconds", \
event_7_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_7) + " in-scope duration in seconds",\
+ Result(std::string(event_name_7) +\
+ " in-scope duration in seconds", \
event_7_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_7) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_7) +\
+ " time between event starts in seconds", \
event_7_samples_));\
} break;\
}\
@@ -1667,144 +1723,160 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
switch (measurement_type_3) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " flow duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " flow duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " in-scope duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " in-scope duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_3) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_3) +\
+ " time between event starts in seconds", \
event_3_samples_));\
} break;\
}\
switch (measurement_type_4) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " flow duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " flow duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " in-scope duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " in-scope duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_4) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_4) +\
+ " time between event starts in seconds", \
event_4_samples_));\
} break;\
}\
switch (measurement_type_5) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " flow duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " flow duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " in-scope duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " in-scope duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_5) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_5) +\
+ " time between event starts in seconds", \
event_5_samples_));\
} break;\
}\
switch (measurement_type_6) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " flow duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " flow duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " in-scope duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " in-scope duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_6) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_6) +\
+ " time between event starts in seconds", \
event_6_samples_));\
} break;\
}\
switch (measurement_type_7) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_7) + " flow duration in seconds",\
+ Result(std::string(event_name_7) +\
+ " flow duration in seconds", \
event_7_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_7) + " in-scope duration in seconds",\
+ Result(std::string(event_name_7) +\
+ " in-scope duration in seconds", \
event_7_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_7) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_7) +\
+ " time between event starts in seconds", \
event_7_samples_));\
} break;\
}\
switch (measurement_type_8) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_8) + " flow duration in seconds",\
+ Result(std::string(event_name_8) +\
+ " flow duration in seconds", \
event_8_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_8) + " in-scope duration in seconds",\
+ Result(std::string(event_name_8) +\
+ " in-scope duration in seconds", \
event_8_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_8) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_8) +\
+ " time between event starts in seconds", \
event_8_samples_));\
} break;\
}\
@@ -2078,162 +2150,180 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
switch (measurement_type_3) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " flow duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " flow duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " in-scope duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " in-scope duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_3) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_3) +\
+ " time between event starts in seconds", \
event_3_samples_));\
} break;\
}\
switch (measurement_type_4) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " flow duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " flow duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " in-scope duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " in-scope duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_4) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_4) +\
+ " time between event starts in seconds", \
event_4_samples_));\
} break;\
}\
switch (measurement_type_5) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " flow duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " flow duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " in-scope duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " in-scope duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_5) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_5) +\
+ " time between event starts in seconds", \
event_5_samples_));\
} break;\
}\
switch (measurement_type_6) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " flow duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " flow duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " in-scope duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " in-scope duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_6) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_6) +\
+ " time between event starts in seconds", \
event_6_samples_));\
} break;\
}\
switch (measurement_type_7) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_7) + " flow duration in seconds",\
+ Result(std::string(event_name_7) +\
+ " flow duration in seconds", \
event_7_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_7) + " in-scope duration in seconds",\
+ Result(std::string(event_name_7) +\
+ " in-scope duration in seconds", \
event_7_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_7) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_7) +\
+ " time between event starts in seconds", \
event_7_samples_));\
} break;\
}\
switch (measurement_type_8) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_8) + " flow duration in seconds",\
+ Result(std::string(event_name_8) +\
+ " flow duration in seconds", \
event_8_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_8) + " in-scope duration in seconds",\
+ Result(std::string(event_name_8) +\
+ " in-scope duration in seconds", \
event_8_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_8) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_8) +\
+ " time between event starts in seconds", \
event_8_samples_));\
} break;\
}\
switch (measurement_type_9) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_9) + " flow duration in seconds",\
+ Result(std::string(event_name_9) +\
+ " flow duration in seconds", \
event_9_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_9) + " in-scope duration in seconds",\
+ Result(std::string(event_name_9) +\
+ " in-scope duration in seconds", \
event_9_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_9) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_9) +\
+ " time between event starts in seconds", \
event_9_samples_));\
} break;\
}\
@@ -2535,181 +2625,200 @@
switch (measurement_type_1) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " flow duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " flow duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_1) + " in-scope duration in seconds",\
+ Result(std::string(event_name_1) +\
+ " in-scope duration in seconds", \
event_1_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_1) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_1) +\
+ " time between event starts in seconds", \
event_1_samples_));\
} break;\
}\
switch (measurement_type_2) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " flow duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " flow duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_2) + " in-scope duration in seconds",\
+ Result(std::string(event_name_2) +\
+ " in-scope duration in seconds", \
event_2_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_2) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_2) +\
+ " time between event starts in seconds", \
event_2_samples_));\
} break;\
}\
switch (measurement_type_3) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " flow duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " flow duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_3) + " in-scope duration in seconds",\
+ Result(std::string(event_name_3) +\
+ " in-scope duration in seconds", \
event_3_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_3) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_3) +\
+ " time between event starts in seconds", \
event_3_samples_));\
} break;\
}\
switch (measurement_type_4) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " flow duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " flow duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_4) + " in-scope duration in seconds",\
+ Result(std::string(event_name_4) +\
+ " in-scope duration in seconds", \
event_4_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_4) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_4) +\
+ " time between event starts in seconds", \
event_4_samples_));\
} break;\
}\
switch (measurement_type_5) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " flow duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " flow duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_5) + " in-scope duration in seconds",\
+ Result(std::string(event_name_5) +\
+ " in-scope duration in seconds", \
event_5_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_5) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_5) +\
+ " time between event starts in seconds", \
event_5_samples_));\
} break;\
}\
switch (measurement_type_6) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " flow duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " flow duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_6) + " in-scope duration in seconds",\
+ Result(std::string(event_name_6) +\
+ " in-scope duration in seconds", \
event_6_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_6) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_6) +\
+ " time between event starts in seconds", \
event_6_samples_));\
} break;\
}\
switch (measurement_type_7) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_7) + " flow duration in seconds",\
+ Result(std::string(event_name_7) +\
+ " flow duration in seconds", \
event_7_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_7) + " in-scope duration in seconds",\
+ Result(std::string(event_name_7) +\
+ " in-scope duration in seconds", \
event_7_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_7) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_7) +\
+ " time between event starts in seconds", \
event_7_samples_));\
} break;\
}\
switch (measurement_type_8) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_8) + " flow duration in seconds",\
+ Result(std::string(event_name_8) +\
+ " flow duration in seconds", \
event_8_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_8) + " in-scope duration in seconds",\
+ Result(std::string(event_name_8) +\
+ " in-scope duration in seconds", \
event_8_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_8) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_8) +\
+ " time between event starts in seconds", \
event_8_samples_));\
} break;\
}\
switch (measurement_type_9) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_9) + " flow duration in seconds",\
+ Result(std::string(event_name_9) +\
+ " flow duration in seconds", \
event_9_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_9) + " in-scope duration in seconds",\
+ Result(std::string(event_name_9) +\
+ " in-scope duration in seconds", \
event_9_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_9) + " time between event starts in \
- seconds",\
+ Result(std::string(event_name_9) +\
+ " time between event starts in seconds", \
event_9_samples_));\
} break;\
}\
switch (measurement_type_10) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_10) + " flow duration in seconds",\
+ Result(std::string(event_name_10) +\
+ " flow duration in seconds", \
event_10_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_10) + " in-scope duration in \
- seconds",\
+ Result(std::string(event_name_10) +\
+ " in-scope duration in seconds", \
event_10_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_10) + " time between event starts \
- in seconds",\
+ Result(std::string(event_name_10) +\
+ " time between event starts in seconds", \
event_10_samples_));\
} break;\
}\
diff --git a/src/cobalt/trace_event/benchmark_internal.h.pump b/src/cobalt/trace_event/benchmark_internal.h.pump
index 80121f3..9a9d9fa 100644
--- a/src/cobalt/trace_event/benchmark_internal.h.pump
+++ b/src/cobalt/trace_event/benchmark_internal.h.pump
@@ -81,17 +81,20 @@
switch (measurement_type_$(ARG)) {\
case cobalt::trace_event::FLOW_DURATION: {\
results.push_back(\
- Result(std::string(event_name_$(ARG)) + " flow duration in seconds",\
+ Result(std::string(event_name_$(ARG)) +\
+ " flow duration in seconds", \
event_$(ARG)_samples_));\
} break;\
case cobalt::trace_event::IN_SCOPE_DURATION: {\
results.push_back(\
- Result(std::string(event_name_$(ARG)) + " in-scope duration in seconds",\
+ Result(std::string(event_name_$(ARG)) +\
+ " in-scope duration in seconds", \
event_$(ARG)_samples_));\
} break;\
case cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS: {\
results.push_back(\
- Result(std::string(event_name_$(ARG)) + " time between event starts in seconds",\
+ Result(std::string(event_name_$(ARG)) +\
+ " time between event starts in seconds", \
event_$(ARG)_samples_));\
} break;\
}\
diff --git a/src/nb/README.md b/src/nb/README.md
new file mode 100644
index 0000000..ee6c322
--- /dev/null
+++ b/src/nb/README.md
@@ -0,0 +1,14 @@
+# Nanobase
+
+Nanobase is essentially a minified/lightweight version of Chromium's base
+library, though it does include utility classes that Chromium's base does not.
+
+Its usefulness is found in the fact that its only dependency is starboard,
+making it very portable and easy to include in projects that don't want
+to depend on Chromium's base (which currently would require the Chromium
+repository to be available and that may not be desirable).
+
+An example project that depends on nb is glimp, which was the project that
+initiated the creation of nb. We wanted glimp to be portable alongside
+Starboard, and so in order to enable that, we wanted to avoid a dependency
+on Chromium's base.
diff --git a/src/nb/analytics/memory_tracker_helpers.cc b/src/nb/analytics/memory_tracker_helpers.cc
index 4ec1de7..4d1f7ad 100644
--- a/src/nb/analytics/memory_tracker_helpers.cc
+++ b/src/nb/analytics/memory_tracker_helpers.cc
@@ -200,7 +200,8 @@
it != pointer_map_.end(); ++it) {
const AllocationRecord& rec = it->second;
AllocationGroup* group = rec.allocation_group;
- group->AddAllocation(-rec.size);
+ const int64_t size = static_cast<int64_t>(rec.size);
+ group->AddAllocation(-size);
}
return pointer_map_.clear();
}
@@ -260,9 +261,8 @@
return true;
}
-size_t ConcurrentAllocationMap::hash_ptr(const void* ptr) {
+uint32_t ConcurrentAllocationMap::hash_ptr(const void* ptr) {
uintptr_t val = reinterpret_cast<uintptr_t>(ptr);
-
return RuntimeHash32(reinterpret_cast<const char*>(&val), sizeof(val));
}
diff --git a/src/nb/analytics/memory_tracker_helpers.h b/src/nb/analytics/memory_tracker_helpers.h
index 653a47f..70cf32b 100644
--- a/src/nb/analytics/memory_tracker_helpers.h
+++ b/src/nb/analytics/memory_tracker_helpers.h
@@ -205,7 +205,7 @@
private:
SB_DISALLOW_COPY_AND_ASSIGN(ConcurrentAllocationMap);
// Takes a pointer and generates a hash.
- static size_t hash_ptr(const void* ptr);
+ static uint32_t hash_ptr(const void* ptr);
int ToIndex(const void* ptr) const;
AtomicAllocationMap pointer_map_array_[kNumElements];
diff --git a/src/nb/memory_scope_test.cc b/src/nb/memory_scope_test.cc
index e734c2f..d9180f9 100644
--- a/src/nb/memory_scope_test.cc
+++ b/src/nb/memory_scope_test.cc
@@ -227,16 +227,7 @@
true}; // true allows caching.
NbPushMemoryScope(&info);
-
- ASSERT_FALSE(test_memory_reporter()->stack_thread_local()->empty());
- NbMemoryScopeInfo* info_ptr =
- test_memory_reporter()->stack_thread_local()->front();
-
- EXPECT_EQ(&info, info_ptr);
- EXPECT_STREQ(info.file_name_, file_name);
- EXPECT_STREQ(info.function_name_, function_name);
- EXPECT_EQ(info.line_number_, line_number);
-
+ ASSERT_TRUE(test_memory_reporter()->stack_thread_local()->empty());
NbPopMemoryScope();
EXPECT_TRUE(test_memory_reporter()->stack_thread_local()->empty());
}
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index a549295..742cded 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -60,6 +60,7 @@
// Adds kSbSystemPropertyUserAgentAuxField to the SbSystemPropertyId
// enum to allow platform-specific User-Agent suffix.
+// NOLINTNEXTLINE(whitespace/line_length)
#define SB_USER_AGENT_AUX_SYSTEM_PROPERTY_API_VERSION SB_EXPERIMENTAL_API_VERSION
// Introduce 'starboard/speech_recognizer.h'
@@ -67,6 +68,10 @@
// speech recognizer feature.
#define SB_SPEECH_RECOGNIZER_API_VERSION SB_EXPERIMENTAL_API_VERSION
+// Introduce pointer (mouse) input support. This extends the SbInput interface
+// with some enum values and data members to allow mouse, wheel, and more
+// generic pointer input.
+#define SB_POINTER_INPUT_API_VERSION SB_EXPERIMENTAL_API_VERSION
// --- Common Detected Features ----------------------------------------------
#if defined(__GNUC__)
diff --git a/src/starboard/input.h b/src/starboard/input.h
index 10c919a..c6e0fd7 100644
--- a/src/starboard/input.h
+++ b/src/starboard/input.h
@@ -33,9 +33,9 @@
// device type produces correspond to |SbInputEventType| values.
typedef enum SbInputDeviceType {
// Input from a gesture-detection mechanism. Examples include Kinect,
- // Wiimotes, LG Magic Remotes, etc...
+ // Wiimotes, etc...
//
- // Produces |Move|, |Grab|, |Ungrab|, |Press| and |Unpress| events.
+ // Produces |Move|, |Press| and |Unpress| events.
kSbInputDeviceTypeGesture,
// Input from a gamepad, following the layout provided in the W3C Web Gamepad
@@ -49,12 +49,14 @@
// Produces |Press| and |Unpress| events.
kSbInputDeviceTypeKeyboard,
+#if SB_API_VERSION <= 4
// Input from a microphone that would provide audio data to the caller, who
// may then find some way to detect speech or other sounds within it. It may
// have processed or filtered the audio in some way before it arrives.
//
// Produces |Audio| events.
kSbInputDeviceTypeMicrophone,
+#endif
// Input from a traditional mouse.
//
@@ -66,12 +68,14 @@
// Produces |Press| and |Unpress| events.
kSbInputDeviceTypeRemote,
+#if SB_API_VERSION <= 4
// Input from a speech command analyzer, which is some hardware or software
// that, given a set of known phrases, activates when one of the registered
// phrases is heard.
//
// Produces |Command| events.
kSbInputDeviceTypeSpeechCommand,
+#endif
// Input from a single- or multi-touchscreen.
//
@@ -86,15 +90,15 @@
// The action that an input event represents.
typedef enum SbInputEventType {
+#if SB_API_VERSION <= 4
// Receipt of Audio. Some audio data was received by the input microphone.
kSbInputEventTypeAudio,
-
// Receipt of a command. A command was received from some semantic source,
// like a speech recognizer.
kSbInputEventTypeCommand,
-
// Grab activation. This event type is deprecated.
kSbInputEventTypeGrab,
+#endif
// Device Movement. In the case of |Mouse|, and perhaps |Gesture|, the
// movement tracks an absolute cursor position. In the case of |TouchPad|,
@@ -108,12 +112,19 @@
// Injecting repeat presses is up to the client.
kSbInputEventTypePress,
+#if SB_API_VERSION <= 4
// Grab deactivation. This event type is deprecated.
kSbInputEventTypeUngrab,
+#endif
// Key or button deactivation. The counterpart to the |Press| event, this
// event is sent when the key or button being pressed is released.
kSbInputEventTypeUnpress,
+
+#if SB_API_VERSION >= SB_POINTER_INPUT_API_VERSION
+ // Wheel movement. Provides relative movements of the |Mouse| wheel.
+ kSbInputEventTypeWheel,
+#endif
} SbInputEventType;
// A 2-dimensional vector used to represent points and motion vectors.
@@ -168,6 +179,29 @@
// The relative motion vector of this input. The value is |0| if this data
// is not applicable.
SbInputVector delta;
+
+#if SB_API_VERSION >= SB_POINTER_INPUT_API_VERSION
+ // The normalized pressure of the pointer input in the range of
+ // [0,1], where 0 and 1 represent the minimum and maximum pressure
+ // the hardware is capable of detecting, respectively. Use NaN for
+ // devices that do not report pressure. This value is only used for input
+ // events with device type mouse or touch screen.
+ float pressure;
+
+ // The (width, height) of the contact geometry of the pointer.
+ // This defines the limits of the values reported for the pointer
+ // coordinates in the 'position' field. If (NaN, NaN) is specified,
+ // the width and height of the window will be used. This value is only used
+ // for input events with device type mouse or touch screen.
+ SbInputVector size;
+
+ // The (x, y) angle in degrees, in the range of [-90, 90] of the
+ // pointer, relative to the z axis. Positive values are for tilt
+ // to the right (x), and towards the user (y). Use (NaN, NaN) for
+ // devices that do not report tilt. This value is only used for input events
+ // with device type mouse or touch screen.
+ SbInputVector tilt;
+#endif
} SbInputData;
#ifdef __cplusplus
diff --git a/src/starboard/key.h b/src/starboard/key.h
index b50608f..8191acd 100644
--- a/src/starboard/key.h
+++ b/src/starboard/key.h
@@ -19,6 +19,8 @@
#ifndef STARBOARD_KEY_H_
#define STARBOARD_KEY_H_
+#include "starboard/configuration.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -279,6 +281,13 @@
kSbKeyModifiersCtrl = 1 << 1,
kSbKeyModifiersMeta = 1 << 2,
kSbKeyModifiersShift = 1 << 3,
+#if SB_API_VERSION >= SB_POINTER_INPUT_API_VERSION
+ kSbKeyModifiersPointerButtonLeft = 1 << 4,
+ kSbKeyModifiersPointerButtonRight = 1 << 5,
+ kSbKeyModifiersPointerButtonMiddle = 1 << 6,
+ kSbKeyModifiersPointerButtonBack = 1 << 7,
+ kSbKeyModifiersPointerButtonForward = 1 << 8,
+#endif
} SbKeyModifiers;
#ifdef __cplusplus
diff --git a/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi b/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi
index eca2f8e..5cde2f7 100644
--- a/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi
+++ b/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi
@@ -123,11 +123,7 @@
'-std=c99',
],
'cflags_cc': [
- # Limit to gnu++98. This allows Linux to be a canary build for any
- # C++11 features that are not supported on some platforms' compilers.
- # We do allow ourselves GNU extensions, which are assumed to exist
- # by Chromium code.
- '-std=gnu++98',
+ '-std=gnu++11',
],
'target_conditions': [
['cobalt_code==1', {
@@ -149,6 +145,8 @@
'-Wno-unused-parameter',
# Do not warn for implicit type conversions that may change a value.
'-Wno-conversion',
+ # Do not warn about an implicit exception spec mismatch.
+ '-Wno-implicit-exception-spec-mismatch',
],
}],
['use_asan==1', {
diff --git a/src/starboard/nplb/condition_variable_wait_timed_test.cc b/src/starboard/nplb/condition_variable_wait_timed_test.cc
index 7507a91..8698e37 100644
--- a/src/starboard/nplb/condition_variable_wait_timed_test.cc
+++ b/src/starboard/nplb/condition_variable_wait_timed_test.cc
@@ -28,6 +28,8 @@
TakeThenSignalEntryPoint, context);
const SbTime kDelay = kSbTimeMillisecond * 10;
+ // Allow millisecond-level precision.
+ const SbTime kPrecision = kSbTimeMillisecond;
// We know the thread hasn't signaled the condition variable yet, and won't
// unless we tell it, so it should wait at least the whole delay time.
@@ -38,8 +40,8 @@
&context->condition, &context->mutex, kDelay);
EXPECT_EQ(kSbConditionVariableTimedOut, result);
SbTimeMonotonic elapsed = SbTimeGetMonotonicNow() - start;
- EXPECT_LE(kDelay, elapsed);
- EXPECT_GT(kDelay * 2, elapsed);
+ EXPECT_LE(kDelay, elapsed + kPrecision);
+ EXPECT_GT(kDelay * 2, elapsed - kPrecision);
EXPECT_TRUE(SbMutexRelease(&context->mutex));
}
diff --git a/src/starboard/nplb/cryptography_transform_gcm_test.cc b/src/starboard/nplb/cryptography_transform_gcm_test.cc
index 819b63d..d2674a4 100644
--- a/src/starboard/nplb/cryptography_transform_gcm_test.cc
+++ b/src/starboard/nplb/cryptography_transform_gcm_test.cc
@@ -310,7 +310,7 @@
}
*out = buf.Pass();
- *out_len = len / 2;
+ *out_len = static_cast<int>(len / 2);
}
std::string hexdump(const void *in, int len) {
diff --git a/src/starboard/nplb/cryptography_transform_test.cc b/src/starboard/nplb/cryptography_transform_test.cc
index ae916a7..fc44126 100644
--- a/src/starboard/nplb/cryptography_transform_test.cc
+++ b/src/starboard/nplb/cryptography_transform_test.cc
@@ -45,8 +45,8 @@
return;
}
- const int kInputSize = SbStringGetLength(kClearText);
- const int kBufferSize = sizeof(kClearText);
+ const int kInputSize = static_cast<int>(SbStringGetLength(kClearText));
+ const int kBufferSize = static_cast<int>(sizeof(kClearText));
char* cipher_text = new char[kBufferSize];
SbMemorySet(cipher_text, 0, kBufferSize);
int count = SbCryptographyTransform(transformer, kClearText, kInputSize,
diff --git a/src/starboard/nplb/directory_create_test.cc b/src/starboard/nplb/directory_create_test.cc
index 2b8fb21..738bae9 100644
--- a/src/starboard/nplb/directory_create_test.cc
+++ b/src/starboard/nplb/directory_create_test.cc
@@ -55,15 +55,30 @@
EXPECT_TRUE(SbDirectoryCanOpen(path.c_str()));
}
-TEST(SbDirectoryCreateTest, SunnyDayRoot) {
- const char* kRootPath = SB_FILE_SEP_STRING;
- EXPECT_TRUE(SbDirectoryCanOpen(kRootPath));
- EXPECT_TRUE(SbDirectoryCreate(kRootPath));
- EXPECT_TRUE(SbDirectoryCanOpen(kRootPath));
+TEST(SbDirectoryCreateTest, SunnyDayTempDirectory) {
+ const int kMaxFilePath = SB_FILE_MAX_PATH;
+ char temp_path[kMaxFilePath];
+ bool system_path_success =
+ SbSystemGetPath(kSbSystemPathTempDirectory, temp_path, kMaxFilePath);
+ ASSERT_TRUE(system_path_success);
+ EXPECT_TRUE(SbDirectoryCanOpen(temp_path));
+ EXPECT_TRUE(SbDirectoryCreate(temp_path));
+ EXPECT_TRUE(SbDirectoryCanOpen(temp_path));
+}
- EXPECT_TRUE(SbDirectoryCanOpen(kManyFileSeparators));
- EXPECT_TRUE(SbDirectoryCreate(kManyFileSeparators));
- EXPECT_TRUE(SbDirectoryCanOpen(kManyFileSeparators));
+TEST(SbDirectoryCreateTest, SunnyDayTempDirectoryManySeparators) {
+ const int kMaxFilePath = SB_FILE_MAX_PATH;
+ char temp_path[kMaxFilePath];
+ bool system_path_success =
+ SbSystemGetPath(kSbSystemPathTempDirectory, temp_path, kMaxFilePath);
+ ASSERT_TRUE(system_path_success);
+ const int new_size =
+ SbStringConcat(temp_path, kManyFileSeparators, kMaxFilePath);
+ ASSERT_LT(new_size, kMaxFilePath);
+
+ EXPECT_TRUE(SbDirectoryCanOpen(temp_path));
+ EXPECT_TRUE(SbDirectoryCreate(temp_path));
+ EXPECT_TRUE(SbDirectoryCanOpen(temp_path));
}
TEST(SbDirectoryCreateTest, FailureNullPath) {
diff --git a/src/starboard/nplb/directory_open_test.cc b/src/starboard/nplb/directory_open_test.cc
index 8eff98f..f37dd9c 100644
--- a/src/starboard/nplb/directory_open_test.cc
+++ b/src/starboard/nplb/directory_open_test.cc
@@ -72,7 +72,7 @@
EXPECT_TRUE(SbFileExists(path.c_str()));
// Funny way to make sure the directory seems valid but doesn't exist.
- int len = path.length();
+ int len = static_cast<int>(path.length());
if (path[len - 1] != 'z') {
path[len - 1] = 'z';
} else {
diff --git a/src/starboard/nplb/file_read_test.cc b/src/starboard/nplb/file_read_test.cc
index a4c828d..23c12f5 100644
--- a/src/starboard/nplb/file_read_test.cc
+++ b/src/starboard/nplb/file_read_test.cc
@@ -140,7 +140,7 @@
}
// Read off the end of the file.
- int position = SbFileSeek(file, kSbFileFromEnd, 0);
+ int position = static_cast<int>(SbFileSeek(file, kSbFileFromEnd, 0));
EXPECT_EQ(kFileSize, position);
int bytes_read = TypeParam::Read(file, buffer, kBufferLength);
EXPECT_EQ(0, bytes_read);
@@ -210,7 +210,8 @@
}
// Read from the middle of the file.
- int position = SbFileSeek(file, kSbFileFromBegin, kFileSize / 4);
+ int position =
+ static_cast<int>(SbFileSeek(file, kSbFileFromBegin, kFileSize / 4));
EXPECT_EQ(kFileSize / 4, position);
int bytes_read = TypeParam::Read(file, buffer, kBufferLength);
EXPECT_GE(kBufferLength, bytes_read);
diff --git a/src/starboard/nplb/file_seek_test.cc b/src/starboard/nplb/file_seek_test.cc
index 0debe02..f8f41aa 100644
--- a/src/starboard/nplb/file_seek_test.cc
+++ b/src/starboard/nplb/file_seek_test.cc
@@ -23,16 +23,18 @@
namespace {
TEST(SbFileSeekTest, InvalidFileErrors) {
- int result = SbFileSeek(kSbFileInvalid, kSbFileFromBegin, 50);
+ int result =
+ static_cast<int>(SbFileSeek(kSbFileInvalid, kSbFileFromBegin, 50));
EXPECT_EQ(-1, result);
- result = SbFileSeek(kSbFileInvalid, kSbFileFromEnd, -50);
+ result = static_cast<int>(SbFileSeek(kSbFileInvalid, kSbFileFromEnd, -50));
EXPECT_EQ(-1, result);
- result = SbFileSeek(kSbFileInvalid, kSbFileFromCurrent, -50);
+ result =
+ static_cast<int>(SbFileSeek(kSbFileInvalid, kSbFileFromCurrent, -50));
EXPECT_EQ(-1, result);
- result = SbFileSeek(kSbFileInvalid, kSbFileFromCurrent, 50);
+ result = static_cast<int>(SbFileSeek(kSbFileInvalid, kSbFileFromCurrent, 50));
EXPECT_EQ(-1, result);
}
diff --git a/src/starboard/nplb/file_truncate_test.cc b/src/starboard/nplb/file_truncate_test.cc
index c4d7a06..c21cad5 100644
--- a/src/starboard/nplb/file_truncate_test.cc
+++ b/src/starboard/nplb/file_truncate_test.cc
@@ -82,13 +82,13 @@
EXPECT_EQ(kStartSize, info.size);
}
- int position = SbFileSeek(file, kSbFileFromCurrent, 0);
+ int position = static_cast<int>(SbFileSeek(file, kSbFileFromCurrent, 0));
EXPECT_EQ(0, position);
bool result = SbFileTruncate(file, kEndSize);
EXPECT_TRUE(result);
- position = SbFileSeek(file, kSbFileFromCurrent, 0);
+ position = static_cast<int>(SbFileSeek(file, kSbFileFromCurrent, 0));
EXPECT_EQ(0, position);
{
diff --git a/src/starboard/nplb/file_write_test.cc b/src/starboard/nplb/file_write_test.cc
index e503a86..1b3eefc 100644
--- a/src/starboard/nplb/file_write_test.cc
+++ b/src/starboard/nplb/file_write_test.cc
@@ -100,7 +100,7 @@
// Tests reading and writing from same opened file.
bool result = SbFileFlush(file);
ASSERT_TRUE(result);
- int position = SbFileSeek(file, kSbFileFromBegin, 0);
+ int position = static_cast<int>(SbFileSeek(file, kSbFileFromBegin, 0));
ASSERT_EQ(0, position);
// Read and check the whole file.
diff --git a/src/starboard/nplb/rwlock_test.cc b/src/starboard/nplb/rwlock_test.cc
index b31df05..6ef24fd 100644
--- a/src/starboard/nplb/rwlock_test.cc
+++ b/src/starboard/nplb/rwlock_test.cc
@@ -199,7 +199,7 @@
ThreadRWLockStressTest::SharedData shared_data;
std::vector<AbstractTestThread*> threads;
- for (size_t i = 0; i < NUM_STRESS_THREADS; ++i) {
+ for (int i = 0; i < NUM_STRESS_THREADS; ++i) {
int32_t start_value = i * kNumValuesEachThread;
int32_t end_value = (i + 1) * kNumValuesEachThread;
ThreadRWLockStressTest* thread =
diff --git a/src/starboard/nplb/semaphore_test.cc b/src/starboard/nplb/semaphore_test.cc
index 05de364..e81b762 100644
--- a/src/starboard/nplb/semaphore_test.cc
+++ b/src/starboard/nplb/semaphore_test.cc
@@ -90,9 +90,8 @@
thread.Join();
EXPECT_TRUE(thread.result_signaled_);
- EXPECT_NEAR(thread.result_wait_time_,
- wait_time / 2,
- kSbTimeMillisecond * 10); // Error threshold
+ EXPECT_NEAR(thread.result_wait_time_ * 1.0, wait_time * 0.5,
+ kSbTimeMillisecond * 10.0); // Error threshold
}
double IsDoubleNear(double first, double second, double diff_threshold) {
@@ -120,7 +119,8 @@
thread.Join();
EXPECT_FALSE(thread.result_signaled_);
- if (IsDoubleNear(wait_time, thread.result_wait_time_, kTimeThreshold)) {
+ if (IsDoubleNear(1.0 * wait_time, 1.0 * thread.result_wait_time_,
+ kTimeThreshold * 1.0)) {
return; // Test passed.
}
}
diff --git a/src/starboard/nplb/string_concat_test.cc b/src/starboard/nplb/string_concat_test.cc
index 158390c..0e3af9a 100644
--- a/src/starboard/nplb/string_concat_test.cc
+++ b/src/starboard/nplb/string_concat_test.cc
@@ -24,8 +24,8 @@
void TestConcat(const char* initial, const char* source, bool is_short) {
const int kDestinationOffset = 16;
- int initial_length = SbStringGetLength(initial);
- int source_length = SbStringGetLength(source);
+ int initial_length = static_cast<int>(SbStringGetLength(initial));
+ int source_length = static_cast<int>(SbStringGetLength(source));
int destination_size =
initial_length + source_length + kDestinationOffset * 2;
int destination_limit = initial_length + source_length + 1;
diff --git a/src/starboard/nplb/string_concat_wide_test.cc b/src/starboard/nplb/string_concat_wide_test.cc
index f4367d7..9713411 100644
--- a/src/starboard/nplb/string_concat_wide_test.cc
+++ b/src/starboard/nplb/string_concat_wide_test.cc
@@ -22,8 +22,8 @@
void TestConcat(const wchar_t* initial, const wchar_t* source, bool is_short) {
const int kDestinationOffset = 16;
- int initial_length = SbStringGetLengthWide(initial);
- int source_length = SbStringGetLengthWide(source);
+ int initial_length = static_cast<int>(SbStringGetLengthWide(initial));
+ int source_length = static_cast<int>(SbStringGetLengthWide(source));
int destination_size =
initial_length + source_length + kDestinationOffset * 2;
int destination_limit = initial_length + source_length + 1;
diff --git a/src/starboard/nplb/string_copy_test.cc b/src/starboard/nplb/string_copy_test.cc
index 00e8e83..0fe6d9f 100644
--- a/src/starboard/nplb/string_copy_test.cc
+++ b/src/starboard/nplb/string_copy_test.cc
@@ -23,7 +23,7 @@
void TestCopy(const char* source, bool is_short) {
const int kDestinationOffset = 16;
- int source_length = SbStringGetLength(source);
+ int source_length = static_cast<int>(SbStringGetLength(source));
int destination_size = source_length + kDestinationOffset * 2;
int destination_limit = source_length + 1;
if (is_short) {
diff --git a/src/starboard/nplb/string_copy_wide_test.cc b/src/starboard/nplb/string_copy_wide_test.cc
index 0a98d75..9a682b5 100644
--- a/src/starboard/nplb/string_copy_wide_test.cc
+++ b/src/starboard/nplb/string_copy_wide_test.cc
@@ -21,7 +21,7 @@
void TestCopy(const wchar_t* source, bool is_short) {
const int kDestinationOffset = 16;
- int source_length = SbStringGetLengthWide(source);
+ int source_length = static_cast<int>(SbStringGetLengthWide(source));
int destination_size = source_length + kDestinationOffset * 2;
int destination_limit = source_length + 1;
if (is_short) {
diff --git a/src/starboard/nplb/system_get_path_test.cc b/src/starboard/nplb/system_get_path_test.cc
index 2e9ddf0..ea36035 100644
--- a/src/starboard/nplb/system_get_path_test.cc
+++ b/src/starboard/nplb/system_get_path_test.cc
@@ -37,7 +37,7 @@
}
if (result) {
EXPECT_NE('\xCD', path[0]) << LOCAL_CONTEXT;
- int len = strlen(path);
+ int len = static_cast<int>(strlen(path));
EXPECT_GT(len, 0) << LOCAL_CONTEXT;
} else {
EXPECT_EQ('\xCD', path[0]) << LOCAL_CONTEXT;
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc
index ef4078f..e27b2ce 100644
--- a/src/starboard/nplb/system_get_property_test.cc
+++ b/src/starboard/nplb/system_get_property_test.cc
@@ -54,7 +54,7 @@
}
if (result) {
EXPECT_NE('\xCD', value[0]) << LOCAL_CONTEXT;
- int len = SbStringGetLength(value);
+ int len = static_cast<int>(SbStringGetLength(value));
EXPECT_GT(len, 0) << LOCAL_CONTEXT;
} else {
EXPECT_EQ('\xCD', value[0]) << LOCAL_CONTEXT;
diff --git a/src/starboard/nplb/thread_get_id_test.cc b/src/starboard/nplb/thread_get_id_test.cc
index 4ecf448..a2ef7d8 100644
--- a/src/starboard/nplb/thread_get_id_test.cc
+++ b/src/starboard/nplb/thread_get_id_test.cc
@@ -46,7 +46,7 @@
for (int i = 0; i < kThreads; ++i) {
void* result = NULL;
EXPECT_TRUE(SbThreadJoin(threads[i], &result));
- SbThreadId id = nplb::FromVoid(result);
+ SbThreadId id = static_cast<SbThreadId>(nplb::FromVoid(result));
EXPECT_NE(id, SbThreadGetId());
thread_ids[i] = id;
}
diff --git a/src/starboard/nplb/thread_sleep_test.cc b/src/starboard/nplb/thread_sleep_test.cc
index 626f185..0bebdb9 100644
--- a/src/starboard/nplb/thread_sleep_test.cc
+++ b/src/starboard/nplb/thread_sleep_test.cc
@@ -20,6 +20,9 @@
namespace nplb {
namespace {
+// Allow millisecond-level precision.
+const SbTime kPrecision = kSbTimeMillisecond;
+
TEST(SbThreadSleepTest, SunnyDay) {
SbThreadSleep(0);
// Well, my work here is done.
@@ -30,13 +33,15 @@
// the thread can wake up, something I completely sympathize with.
TEST(SbThreadSleepTest, SunnyDayAtLeastDelay) {
const int kTrials = 12;
+ const int64_t one = 1;
for (int trial = 0; trial < kTrials; ++trial) {
// This tests several delays, between about 15 to about 4 milliseconds.
- const SbTime kDelay = kSbTimeSecond / (1 << ((trial % 3) + 6));
+ const SbTime kDelay = kSbTimeSecond / (one << ((trial % 3) + 6));
SbTimeMonotonic start = SbTimeGetMonotonicNow();
SbThreadSleep(kDelay);
- EXPECT_LE(start + kDelay, SbTimeGetMonotonicNow()) << "Trial " << trial
- << ", kDelay=" << kDelay;
+ SbTimeMonotonic end = SbTimeGetMonotonicNow();
+ EXPECT_LE(start + kDelay, end + kPrecision) << "Trial " << trial
+ << ", kDelay=" << kDelay;
}
}
diff --git a/src/starboard/shared/starboard/file_mode_string_to_flags.cc b/src/starboard/shared/starboard/file_mode_string_to_flags.cc
index b3575e1..04e7512 100644
--- a/src/starboard/shared/starboard/file_mode_string_to_flags.cc
+++ b/src/starboard/shared/starboard/file_mode_string_to_flags.cc
@@ -33,7 +33,7 @@
return 0;
}
- int length = SbStringGetLength(mode);
+ int length = static_cast<int>(SbStringGetLength(mode));
if (length < 1) {
return 0;
}
diff --git a/src/starboard/shared/starboard/media/mime_type.cc b/src/starboard/shared/starboard/media/mime_type.cc
index 4986d87..524c85c 100644
--- a/src/starboard/shared/starboard/media/mime_type.cc
+++ b/src/starboard/shared/starboard/media/mime_type.cc
@@ -67,8 +67,11 @@
for (;;) {
size_t next = str.find(ch, pos);
- result.push_back(str.substr(pos, next - pos));
- Trim(&result.back());
+ std::string sub_str = str.substr(pos, next - pos);
+ Trim(&sub_str);
+ if (!sub_str.empty()) {
+ result.push_back(sub_str);
+ }
if (next == str.npos) {
break;
}
@@ -85,7 +88,9 @@
MimeType::MimeType(const std::string& content_type) : is_valid_(false) {
Strings components = SplitAndTrim(content_type, ';');
- SB_DCHECK(!components.empty());
+ if (components.empty()) {
+ return;
+ }
// 1. Verify if there is a valid type/subtype in the very beginning.
if (ContainsSpace(components.front())) {
@@ -171,7 +176,10 @@
int MimeType::GetParamIntValue(int index) const {
SB_DCHECK(is_valid());
SB_DCHECK(index < GetParamCount());
- SB_DCHECK(GetParamType(index) == kParamTypeInteger);
+
+ if (GetParamType(index) != kParamTypeInteger) {
+ return 0;
+ }
int i;
SbStringScanF(params_[index].value.c_str(), "%d", &i);
@@ -181,8 +189,11 @@
float MimeType::GetParamFloatValue(int index) const {
SB_DCHECK(is_valid());
SB_DCHECK(index < GetParamCount());
- SB_DCHECK(GetParamType(index) == kParamTypeInteger ||
- GetParamType(index) == kParamTypeFloat);
+
+ if (GetParamType(index) != kParamTypeInteger &&
+ GetParamType(index) != kParamTypeFloat) {
+ return 0.0f;
+ }
float f;
SbStringScanF(params_[index].value.c_str(), "%g", &f);
diff --git a/src/starboard/shared/starboard/player/filter/audio_buffer_queue.cc b/src/starboard/shared/starboard/player/filter/audio_buffer_queue.cc
new file mode 100644
index 0000000..c051ee8
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/audio_buffer_queue.cc
@@ -0,0 +1,140 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cobalt/media/base/audio_buffer_queue.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "cobalt/media/base/audio_bus.h"
+
+namespace cobalt {
+namespace media {
+
+AudioBufferQueue::AudioBufferQueue() {
+ Clear();
+}
+AudioBufferQueue::~AudioBufferQueue() {}
+
+void AudioBufferQueue::Clear() {
+ buffers_.clear();
+ current_buffer_ = buffers_.begin();
+ current_buffer_offset_ = 0;
+ frames_ = 0;
+}
+
+void AudioBufferQueue::Append(const scoped_refptr<AudioBuffer>& buffer_in) {
+ // Add the buffer to the queue. Inserting into deque invalidates all
+ // iterators, so point to the first buffer.
+ buffers_.push_back(buffer_in);
+ current_buffer_ = buffers_.begin();
+
+ // Update the |frames_| counter since we have added frames.
+ frames_ += buffer_in->frame_count();
+ CHECK_GT(frames_, 0); // make sure it doesn't overflow.
+}
+
+int AudioBufferQueue::ReadFrames(int frames,
+ int dest_frame_offset,
+ AudioBus* dest) {
+ DCHECK_GE(dest->frames(), frames + dest_frame_offset);
+ return InternalRead(frames, true, 0, dest_frame_offset, dest);
+}
+
+int AudioBufferQueue::PeekFrames(int frames,
+ int source_frame_offset,
+ int dest_frame_offset,
+ AudioBus* dest) {
+ DCHECK_GE(dest->frames(), frames);
+ return InternalRead(frames, false, source_frame_offset, dest_frame_offset,
+ dest);
+}
+
+void AudioBufferQueue::SeekFrames(int frames) {
+ // Perform seek only if we have enough bytes in the queue.
+ CHECK_LE(frames, frames_);
+ int taken = InternalRead(frames, true, 0, 0, NULL);
+ DCHECK_EQ(taken, frames);
+}
+
+int AudioBufferQueue::InternalRead(int frames,
+ bool advance_position,
+ int source_frame_offset,
+ int dest_frame_offset,
+ AudioBus* dest) {
+ // Counts how many frames are actually read from the buffer queue.
+ int taken = 0;
+ BufferQueue::iterator current_buffer = current_buffer_;
+ int current_buffer_offset = current_buffer_offset_;
+
+ int frames_to_skip = source_frame_offset;
+ while (taken < frames) {
+ // |current_buffer| is valid since the first time this buffer is appended
+ // with data. Make sure there is data to be processed.
+ if (current_buffer == buffers_.end())
+ break;
+
+ scoped_refptr<AudioBuffer> buffer = *current_buffer;
+
+ int remaining_frames_in_buffer =
+ buffer->frame_count() - current_buffer_offset;
+
+ if (frames_to_skip > 0) {
+ // If there are frames to skip, do it first. May need to skip into
+ // subsequent buffers.
+ int skipped = std::min(remaining_frames_in_buffer, frames_to_skip);
+ current_buffer_offset += skipped;
+ frames_to_skip -= skipped;
+ } else {
+ // Find the right amount to copy from the current buffer. We shall copy no
+ // more than |frames| frames in total and each single step copies no more
+ // than the current buffer size.
+ int copied = std::min(frames - taken, remaining_frames_in_buffer);
+
+ // if |dest| is NULL, there's no need to copy.
+ if (dest) {
+ buffer->ReadFrames(copied, current_buffer_offset,
+ dest_frame_offset + taken, dest);
+ }
+
+ // Increase total number of frames copied, which regulates when to end
+ // this loop.
+ taken += copied;
+
+ // We have read |copied| frames from the current buffer. Advance the
+ // offset.
+ current_buffer_offset += copied;
+ }
+
+ // Has the buffer has been consumed?
+ if (current_buffer_offset == buffer->frame_count()) {
+ // If we are at the last buffer, no more data to be copied, so stop.
+ BufferQueue::iterator next = current_buffer + 1;
+ if (next == buffers_.end())
+ break;
+
+ // Advances the iterator.
+ current_buffer = next;
+ current_buffer_offset = 0;
+ }
+ }
+
+ if (advance_position) {
+ // Update the appropriate values since |taken| frames have been copied out.
+ frames_ -= taken;
+ DCHECK_GE(frames_, 0);
+ DCHECK(current_buffer_ != buffers_.end() || frames_ == 0);
+
+ // Remove any buffers before the current buffer as there is no going
+ // backwards.
+ buffers_.erase(buffers_.begin(), current_buffer);
+ current_buffer_ = buffers_.begin();
+ current_buffer_offset_ = current_buffer_offset;
+ }
+
+ return taken;
+}
+
+} // namespace media
+} // namespace cobalt
diff --git a/src/starboard/shared/starboard/player/filter/audio_buffer_queue.h b/src/starboard/shared/starboard/player/filter/audio_buffer_queue.h
new file mode 100644
index 0000000..64162a4
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/audio_buffer_queue.h
@@ -0,0 +1,90 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COBALT_MEDIA_BASE_AUDIO_BUFFER_QUEUE_H_
+#define COBALT_MEDIA_BASE_AUDIO_BUFFER_QUEUE_H_
+
+#include <deque>
+
+#include "base/basictypes.h"
+#include "cobalt/media/base/audio_buffer.h"
+#include "cobalt/media/base/media_export.h"
+
+namespace cobalt {
+namespace media {
+
+class AudioBus;
+
+// A queue of AudioBuffers to support reading of arbitrary chunks of a media
+// data source. Audio data can be copied into an AudioBus for output. The
+// current position can be forwarded to anywhere in the buffered data.
+//
+// This class is not inherently thread-safe. Concurrent access must be
+// externally serialized.
+class MEDIA_EXPORT AudioBufferQueue {
+ public:
+ AudioBufferQueue();
+ ~AudioBufferQueue();
+
+ // Clears the buffer queue.
+ void Clear();
+
+ // Appends |buffer_in| to this queue.
+ void Append(const scoped_refptr<AudioBuffer>& buffer_in);
+
+ // Reads a maximum of |frames| frames into |dest| from the current position.
+ // Returns the number of frames read. The current position will advance by the
+ // amount of frames read. |dest_frame_offset| specifies a starting offset into
+ // |dest|. On each call, the frames are converted from their source format
+ // into the destination AudioBus.
+ int ReadFrames(int frames, int dest_frame_offset, AudioBus* dest);
+
+ // Copies up to |frames| frames from current position to |dest|. Returns
+ // number of frames copied. Doesn't advance current position. Starts at
+ // |source_frame_offset| from current position. |dest_frame_offset| specifies
+ // a starting offset into |dest|. On each call, the frames are converted from
+ // their source format into the destination AudioBus.
+ int PeekFrames(int frames,
+ int source_frame_offset,
+ int dest_frame_offset,
+ AudioBus* dest);
+
+ // Moves the current position forward by |frames| frames. If |frames| exceeds
+ // frames available, the seek operation will fail.
+ void SeekFrames(int frames);
+
+ // Returns the number of frames buffered beyond the current position.
+ int frames() const { return frames_; }
+
+ private:
+ // Definition of the buffer queue.
+ typedef std::deque<scoped_refptr<AudioBuffer> > BufferQueue;
+
+ // An internal method shared by ReadFrames() and SeekFrames() that actually
+ // does reading. It reads a maximum of |frames| frames into |dest|. Returns
+ // the number of frames read. The current position will be moved forward by
+ // the number of frames read if |advance_position| is set. If |dest| is NULL,
+ // only the current position will advance but no data will be copied.
+ // |source_frame_offset| can be used to skip frames before reading.
+ // |dest_frame_offset| specifies a starting offset into |dest|.
+ int InternalRead(int frames,
+ bool advance_position,
+ int source_frame_offset,
+ int dest_frame_offset,
+ AudioBus* dest);
+
+ BufferQueue::iterator current_buffer_;
+ BufferQueue buffers_;
+ int current_buffer_offset_;
+
+ // Number of frames available to be read in the buffer.
+ int frames_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioBufferQueue);
+};
+
+} // namespace media
+} // namespace cobalt
+
+#endif // COBALT_MEDIA_BASE_AUDIO_BUFFER_QUEUE_H_
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_algorithm.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_algorithm.cc
new file mode 100644
index 0000000..5143d7b
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_algorithm.cc
@@ -0,0 +1,396 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cobalt/media/filters/audio_renderer_algorithm.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include "base/logging.h"
+#include "cobalt/media/base/audio_bus.h"
+#include "cobalt/media/base/limits.h"
+#include "cobalt/media/filters/wsola_internals.h"
+#include "starboard/memory.h"
+
+namespace cobalt {
+namespace media {
+
+// Waveform Similarity Overlap-and-add (WSOLA).
+//
+// One WSOLA iteration
+//
+// 1) Extract |target_block_| as input frames at indices
+// [|target_block_index_|, |target_block_index_| + |ola_window_size_|).
+// Note that |target_block_| is the "natural" continuation of the output.
+//
+// 2) Extract |search_block_| as input frames at indices
+// [|search_block_index_|,
+// |search_block_index_| + |num_candidate_blocks_| + |ola_window_size_|).
+//
+// 3) Find a block within the |search_block_| that is most similar
+// to |target_block_|. Let |optimal_index| be the index of such block and
+// write it to |optimal_block_|.
+//
+// 4) Update:
+// |optimal_block_| = |transition_window_| * |target_block_| +
+// (1 - |transition_window_|) * |optimal_block_|.
+//
+// 5) Overlap-and-add |optimal_block_| to the |wsola_output_|.
+//
+// 6) Update:
+// |target_block_| = |optimal_index| + |ola_window_size_| / 2.
+// |output_index_| = |output_index_| + |ola_window_size_| / 2,
+// |search_block_center_offset_| = |output_index_| * |playback_rate|, and
+// |search_block_index_| = |search_block_center_offset_| -
+// |search_block_center_offset_|.
+
+// Max/min supported playback rates for fast/slow audio. Audio outside of these
+// ranges are muted.
+// Audio at these speeds would sound better under a frequency domain algorithm.
+static const double kMinPlaybackRate = 0.5;
+static const double kMaxPlaybackRate = 4.0;
+
+// Overlap-and-add window size in milliseconds.
+static const int kOlaWindowSizeMs = 20;
+
+// Size of search interval in milliseconds. The search interval is
+// [-delta delta] around |output_index_| * |playback_rate|. So the search
+// interval is 2 * delta.
+static const int kWsolaSearchIntervalMs = 30;
+
+// The maximum size in seconds for the |audio_buffer_|. Arbitrarily determined.
+static const int kMaxCapacityInSeconds = 3;
+
+// The minimum size in ms for the |audio_buffer_|. Arbitrarily determined.
+static const int kStartingCapacityInMs = 200;
+
+AudioRendererAlgorithm::AudioRendererAlgorithm()
+ : channels_(0),
+ samples_per_second_(0),
+ muted_partial_frame_(0),
+ capacity_(0),
+ output_time_(0.0),
+ search_block_center_offset_(0),
+ search_block_index_(0),
+ num_candidate_blocks_(0),
+ target_block_index_(0),
+ ola_window_size_(0),
+ ola_hop_size_(0),
+ num_complete_frames_(0),
+ initial_capacity_(0),
+ max_capacity_(0) {}
+
+AudioRendererAlgorithm::~AudioRendererAlgorithm() {}
+
+void AudioRendererAlgorithm::Initialize(const AudioParameters& params) {
+ CHECK(params.IsValid());
+
+ channels_ = params.channels();
+ samples_per_second_ = params.sample_rate();
+ initial_capacity_ = capacity_ =
+ std::max(params.frames_per_buffer() * 2,
+ ConvertMillisecondsToFrames(kStartingCapacityInMs));
+ max_capacity_ =
+ std::max(initial_capacity_, kMaxCapacityInSeconds * samples_per_second_);
+ num_candidate_blocks_ = ConvertMillisecondsToFrames(kWsolaSearchIntervalMs);
+ ola_window_size_ = ConvertMillisecondsToFrames(kOlaWindowSizeMs);
+
+ // Make sure window size in an even number.
+ ola_window_size_ += ola_window_size_ & 1;
+ ola_hop_size_ = ola_window_size_ / 2;
+
+ // |num_candidate_blocks_| / 2 is the offset of the center of the search
+ // block to the center of the first (left most) candidate block. The offset
+ // of the center of a candidate block to its left most point is
+ // |ola_window_size_| / 2 - 1. Note that |ola_window_size_| is even and in
+ // our convention the center belongs to the left half, so we need to subtract
+ // one frame to get the correct offset.
+ //
+ // Search Block
+ // <------------------------------------------->
+ //
+ // |ola_window_size_| / 2 - 1
+ // <----
+ //
+ // |num_candidate_blocks_| / 2
+ // <----------------
+ // center
+ // X----X----------------X---------------X-----X
+ // <----------> <---------->
+ // Candidate ... Candidate
+ // 1, ... |num_candidate_blocks_|
+ search_block_center_offset_ =
+ num_candidate_blocks_ / 2 + (ola_window_size_ / 2 - 1);
+
+ ola_window_.reset(new float[ola_window_size_]);
+ internal::GetSymmetricHanningWindow(ola_window_size_, ola_window_.get());
+
+ transition_window_.reset(new float[ola_window_size_ * 2]);
+ internal::GetSymmetricHanningWindow(2 * ola_window_size_,
+ transition_window_.get());
+
+ wsola_output_ = AudioBus::Create(channels_, ola_window_size_ + ola_hop_size_);
+ wsola_output_->Zero(); // Initialize for overlap-and-add of the first block.
+
+ // Auxiliary containers.
+ optimal_block_ = AudioBus::Create(channels_, ola_window_size_);
+ search_block_ = AudioBus::Create(
+ channels_, num_candidate_blocks_ + (ola_window_size_ - 1));
+ target_block_ = AudioBus::Create(channels_, ola_window_size_);
+}
+
+int AudioRendererAlgorithm::FillBuffer(AudioBus* dest, int dest_offset,
+ int requested_frames,
+ double playback_rate) {
+ if (playback_rate == 0) return 0;
+
+ DCHECK_GT(playback_rate, 0);
+ DCHECK_EQ(channels_, dest->channels());
+
+ // Optimize the muted case to issue a single clear instead of performing
+ // the full crossfade and clearing each crossfaded frame.
+ if (playback_rate < kMinPlaybackRate || playback_rate > kMaxPlaybackRate) {
+ int frames_to_render =
+ std::min(static_cast<int>(audio_buffer_.frames() / playback_rate),
+ requested_frames);
+
+ // Compute accurate number of frames to actually skip in the source data.
+ // Includes the leftover partial frame from last request. However, we can
+ // only skip over complete frames, so a partial frame may remain for next
+ // time.
+ muted_partial_frame_ += frames_to_render * playback_rate;
+ // Handle the case where muted_partial_frame_ rounds up to
+ // audio_buffer_.frames()+1.
+ int seek_frames = std::min(static_cast<int>(muted_partial_frame_),
+ audio_buffer_.frames());
+ dest->ZeroFramesPartial(dest_offset, frames_to_render);
+ audio_buffer_.SeekFrames(seek_frames);
+
+ // Determine the partial frame that remains to be skipped for next call. If
+ // the user switches back to playing, it may be off time by this partial
+ // frame, which would be undetectable. If they subsequently switch to
+ // another playback rate that mutes, the code will attempt to line up the
+ // frames again.
+ muted_partial_frame_ -= seek_frames;
+ return frames_to_render;
+ }
+
+ int slower_step = ceil(ola_window_size_ * playback_rate);
+ int faster_step = ceil(ola_window_size_ / playback_rate);
+
+ // Optimize the most common |playback_rate| ~= 1 case to use a single copy
+ // instead of copying frame by frame.
+ if (ola_window_size_ <= faster_step && slower_step >= ola_window_size_) {
+ const int frames_to_copy =
+ std::min(audio_buffer_.frames(), requested_frames);
+ const int frames_read =
+ audio_buffer_.ReadFrames(frames_to_copy, dest_offset, dest);
+ DCHECK_EQ(frames_read, frames_to_copy);
+ return frames_read;
+ }
+
+ int rendered_frames = 0;
+ do {
+ rendered_frames +=
+ WriteCompletedFramesTo(requested_frames - rendered_frames,
+ dest_offset + rendered_frames, dest);
+ } while (rendered_frames < requested_frames &&
+ RunOneWsolaIteration(playback_rate));
+ return rendered_frames;
+}
+
+void AudioRendererAlgorithm::FlushBuffers() {
+ // Clear the queue of decoded packets (releasing the buffers).
+ audio_buffer_.Clear();
+ output_time_ = 0.0;
+ search_block_index_ = 0;
+ target_block_index_ = 0;
+ wsola_output_->Zero();
+ num_complete_frames_ = 0;
+
+ // Reset |capacity_| so growth triggered by underflows doesn't penalize seek
+ // time.
+ capacity_ = initial_capacity_;
+}
+
+void AudioRendererAlgorithm::EnqueueBuffer(
+ const scoped_refptr<AudioBuffer>& buffer_in) {
+ DCHECK(!buffer_in->end_of_stream());
+ audio_buffer_.Append(buffer_in);
+}
+
+bool AudioRendererAlgorithm::IsQueueFull() {
+ return audio_buffer_.frames() >= capacity_;
+}
+
+void AudioRendererAlgorithm::IncreaseQueueCapacity() {
+ DCHECK_LE(capacity_, max_capacity_);
+ capacity_ = std::min(2 * capacity_, max_capacity_);
+}
+
+int64_t AudioRendererAlgorithm::GetMemoryUsage() const {
+ return audio_buffer_.frames() * channels_ * sizeof(float);
+}
+
+bool AudioRendererAlgorithm::CanPerformWsola() const {
+ const int search_block_size = num_candidate_blocks_ + (ola_window_size_ - 1);
+ const int frames = audio_buffer_.frames();
+ return target_block_index_ + ola_window_size_ <= frames &&
+ search_block_index_ + search_block_size <= frames;
+}
+
+int AudioRendererAlgorithm::ConvertMillisecondsToFrames(int ms) const {
+ return ms * (samples_per_second_ /
+ static_cast<double>(base::Time::kMillisecondsPerSecond));
+}
+
+bool AudioRendererAlgorithm::RunOneWsolaIteration(double playback_rate) {
+ if (!CanPerformWsola()) return false;
+
+ GetOptimalBlock();
+
+ // Overlap-and-add.
+ for (int k = 0; k < channels_; ++k) {
+ const float* const ch_opt_frame = optimal_block_->channel(k);
+ float* ch_output = wsola_output_->channel(k) + num_complete_frames_;
+ for (int n = 0; n < ola_hop_size_; ++n) {
+ ch_output[n] = ch_output[n] * ola_window_[ola_hop_size_ + n] +
+ ch_opt_frame[n] * ola_window_[n];
+ }
+
+ // Copy the second half to the output.
+ SbMemoryCopy(&ch_output[ola_hop_size_], &ch_opt_frame[ola_hop_size_],
+ sizeof(*ch_opt_frame) * ola_hop_size_);
+ }
+
+ num_complete_frames_ += ola_hop_size_;
+ UpdateOutputTime(playback_rate, ola_hop_size_);
+ RemoveOldInputFrames(playback_rate);
+ return true;
+}
+
+void AudioRendererAlgorithm::UpdateOutputTime(double playback_rate,
+ double time_change) {
+ output_time_ += time_change;
+ // Center of the search region, in frames.
+ const int search_block_center_index =
+ static_cast<int>(output_time_ * playback_rate + 0.5);
+ search_block_index_ = search_block_center_index - search_block_center_offset_;
+}
+
+void AudioRendererAlgorithm::RemoveOldInputFrames(double playback_rate) {
+ const int earliest_used_index =
+ std::min(target_block_index_, search_block_index_);
+ if (earliest_used_index <= 0) return; // Nothing to remove.
+
+ // Remove frames from input and adjust indices accordingly.
+ audio_buffer_.SeekFrames(earliest_used_index);
+ target_block_index_ -= earliest_used_index;
+
+ // Adjust output index.
+ double output_time_change =
+ static_cast<double>(earliest_used_index) / playback_rate;
+ CHECK_GE(output_time_, output_time_change);
+ UpdateOutputTime(playback_rate, -output_time_change);
+}
+
+int AudioRendererAlgorithm::WriteCompletedFramesTo(int requested_frames,
+ int dest_offset,
+ AudioBus* dest) {
+ int rendered_frames = std::min(num_complete_frames_, requested_frames);
+
+ if (rendered_frames == 0)
+ return 0; // There is nothing to read from |wsola_output_|, return.
+
+ wsola_output_->CopyPartialFramesTo(0, rendered_frames, dest_offset, dest);
+
+ // Remove the frames which are read.
+ int frames_to_move = wsola_output_->frames() - rendered_frames;
+ for (int k = 0; k < channels_; ++k) {
+ float* ch = wsola_output_->channel(k);
+ SbMemoryMove(ch, &ch[rendered_frames], sizeof(*ch) * frames_to_move);
+ }
+ num_complete_frames_ -= rendered_frames;
+ return rendered_frames;
+}
+
+bool AudioRendererAlgorithm::TargetIsWithinSearchRegion() const {
+ const int search_block_size = num_candidate_blocks_ + (ola_window_size_ - 1);
+
+ return target_block_index_ >= search_block_index_ &&
+ target_block_index_ + ola_window_size_ <=
+ search_block_index_ + search_block_size;
+}
+
+void AudioRendererAlgorithm::GetOptimalBlock() {
+ int optimal_index = 0;
+
+ // An interval around last optimal block which is excluded from the search.
+ // This is to reduce the buzzy sound. The number 160 is rather arbitrary and
+ // derived heuristically.
+ const int kExcludeIntervalLengthFrames = 160;
+ if (TargetIsWithinSearchRegion()) {
+ optimal_index = target_block_index_;
+ PeekAudioWithZeroPrepend(optimal_index, optimal_block_.get());
+ } else {
+ PeekAudioWithZeroPrepend(target_block_index_, target_block_.get());
+ PeekAudioWithZeroPrepend(search_block_index_, search_block_.get());
+ int last_optimal =
+ target_block_index_ - ola_hop_size_ - search_block_index_;
+ internal::Interval exclude_iterval =
+ std::make_pair(last_optimal - kExcludeIntervalLengthFrames / 2,
+ last_optimal + kExcludeIntervalLengthFrames / 2);
+
+ // |optimal_index| is in frames and it is relative to the beginning of the
+ // |search_block_|.
+ optimal_index = internal::OptimalIndex(
+ search_block_.get(), target_block_.get(), exclude_iterval);
+
+ // Translate |index| w.r.t. the beginning of |audio_buffer_| and extract the
+ // optimal block.
+ optimal_index += search_block_index_;
+ PeekAudioWithZeroPrepend(optimal_index, optimal_block_.get());
+
+ // Make a transition from target block to the optimal block if different.
+ // Target block has the best continuation to the current output.
+ // Optimal block is the most similar block to the target, however, it might
+ // introduce some discontinuity when over-lap-added. Therefore, we combine
+ // them for a smoother transition. The length of transition window is twice
+ // as that of the optimal-block which makes it like a weighting function
+ // where target-block has higher weight close to zero (weight of 1 at index
+ // 0) and lower weight close the end.
+ for (int k = 0; k < channels_; ++k) {
+ float* ch_opt = optimal_block_->channel(k);
+ const float* const ch_target = target_block_->channel(k);
+ for (int n = 0; n < ola_window_size_; ++n) {
+ ch_opt[n] = ch_opt[n] * transition_window_[n] +
+ ch_target[n] * transition_window_[ola_window_size_ + n];
+ }
+ }
+ }
+
+ // Next target is one hop ahead of the current optimal.
+ target_block_index_ = optimal_index + ola_hop_size_;
+}
+
+void AudioRendererAlgorithm::PeekAudioWithZeroPrepend(int read_offset_frames,
+ AudioBus* dest) {
+ CHECK_LE(read_offset_frames + dest->frames(), audio_buffer_.frames());
+
+ int write_offset = 0;
+ int num_frames_to_read = dest->frames();
+ if (read_offset_frames < 0) {
+ int num_zero_frames_appended =
+ std::min(-read_offset_frames, num_frames_to_read);
+ read_offset_frames = 0;
+ num_frames_to_read -= num_zero_frames_appended;
+ write_offset = num_zero_frames_appended;
+ dest->ZeroFrames(num_zero_frames_appended);
+ }
+ audio_buffer_.PeekFrames(num_frames_to_read, read_offset_frames, write_offset,
+ dest);
+}
+
+} // namespace media
+} // namespace cobalt
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_algorithm.h b/src/starboard/shared/starboard/player/filter/audio_renderer_algorithm.h
new file mode 100644
index 0000000..e2becc9
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_algorithm.h
@@ -0,0 +1,218 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// AudioRendererAlgorithm buffers and transforms audio data. The owner of
+// this object provides audio data to the object through EnqueueBuffer() and
+// requests data from the buffer via FillBuffer().
+//
+// This class is *not* thread-safe. Calls to enqueue and retrieve data must be
+// locked if called from multiple threads.
+//
+// AudioRendererAlgorithm uses the Waveform Similarity Overlap and Add (WSOLA)
+// algorithm to stretch or compress audio data to meet playback speeds less than
+// or greater than the natural playback of the audio stream. The algorithm
+// preserves local properties of the audio, therefore, pitch and harmonics are
+// are preserved. See audio_renderer_algorith.cc for a more elaborate
+// description of the algorithm.
+//
+// Audio at very low or very high playback rates are muted to preserve quality.
+
+#ifndef COBALT_MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_
+#define COBALT_MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_
+
+#include <memory>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "cobalt/media/base/audio_buffer.h"
+#include "cobalt/media/base/audio_buffer_queue.h"
+#include "cobalt/media/base/audio_parameters.h"
+#include "starboard/types.h"
+
+namespace cobalt {
+namespace media {
+
+class AudioBus;
+
+class MEDIA_EXPORT AudioRendererAlgorithm {
+ public:
+ AudioRendererAlgorithm();
+ ~AudioRendererAlgorithm();
+
+ // Initializes this object with information about the audio stream.
+ void Initialize(const AudioParameters& params);
+
+ // Tries to fill |requested_frames| frames into |dest| with possibly scaled
+ // data from our |audio_buffer_|. Data is scaled based on |playback_rate|,
+ // using a variation of the Overlap-Add method to combine sample windows.
+ //
+ // Data from |audio_buffer_| is consumed in proportion to the playback rate.
+ //
+ // |dest_offset| is the offset in frames for writing into |dest|.
+ //
+ // Returns the number of frames copied into |dest|.
+ int FillBuffer(AudioBus* dest, int dest_offset, int requested_frames,
+ double playback_rate);
+
+ // Clears |audio_buffer_|.
+ void FlushBuffers();
+
+ // Enqueues a buffer. It is called from the owner of the algorithm after a
+ // read completes.
+ void EnqueueBuffer(const scoped_refptr<AudioBuffer>& buffer_in);
+
+ // Returns true if |audio_buffer_| is at or exceeds capacity.
+ bool IsQueueFull();
+
+ // Returns the capacity of |audio_buffer_| in frames.
+ int QueueCapacity() const { return capacity_; }
+
+ // Increase the capacity of |audio_buffer_| if possible.
+ void IncreaseQueueCapacity();
+
+ // Returns an estimate of the amount of memory (in bytes) used for frames.
+ int64_t GetMemoryUsage() const;
+
+ // Returns the number of frames left in |audio_buffer_|, which may be larger
+ // than QueueCapacity() in the event that EnqueueBuffer() delivered more data
+ // than |audio_buffer_| was intending to hold.
+ int frames_buffered() { return audio_buffer_.frames(); }
+
+ // Returns the samples per second for this audio stream.
+ int samples_per_second() { return samples_per_second_; }
+
+ private:
+ // Within |search_block_|, find the block of data that is most similar to
+ // |target_block_|, and write it in |optimal_block_|. This method assumes that
+ // there is enough data to perform a search, i.e. |search_block_| and
+ // |target_block_| can be extracted from the available frames.
+ void GetOptimalBlock();
+
+ // Read a maximum of |requested_frames| frames from |wsola_output_|. Returns
+ // number of frames actually read.
+ int WriteCompletedFramesTo(int requested_frames, int output_offset,
+ AudioBus* dest);
+
+ // Fill |dest| with frames from |audio_buffer_| starting from frame
+ // |read_offset_frames|. |dest| is expected to have the same number of
+ // channels as |audio_buffer_|. A negative offset, i.e.
+ // |read_offset_frames| < 0, is accepted assuming that |audio_buffer| is zero
+ // for negative indices. This might happen for few first frames. This method
+ // assumes there is enough frames to fill |dest|, i.e. |read_offset_frames| +
+ // |dest->frames()| does not extend to future.
+ void PeekAudioWithZeroPrepend(int read_offset_frames, AudioBus* dest);
+
+ // Run one iteration of WSOLA, if there are sufficient frames. This will
+ // overlap-and-add one block to |wsola_output_|, hence, |num_complete_frames_|
+ // is incremented by |ola_hop_size_|.
+ bool RunOneWsolaIteration(double playback_rate);
+
+ // Seek |audio_buffer_| forward to remove frames from input that are not used
+ // any more. State of the WSOLA will be updated accordingly.
+ void RemoveOldInputFrames(double playback_rate);
+
+ // Update |output_time_| by |time_change|. In turn |search_block_index_| is
+ // updated.
+ void UpdateOutputTime(double playback_rate, double time_change);
+
+ // Is |target_block_| fully within |search_block_|? If so, we don't need to
+ // perform the search.
+ bool TargetIsWithinSearchRegion() const;
+
+ // Do we have enough data to perform one round of WSOLA?
+ bool CanPerformWsola() const;
+
+ // Converts a time in milliseconds to frames using |samples_per_second_|.
+ int ConvertMillisecondsToFrames(int ms) const;
+
+ // Number of channels in audio stream.
+ int channels_;
+
+ // Sample rate of audio stream.
+ int samples_per_second_;
+
+ // Buffered audio data.
+ AudioBufferQueue audio_buffer_;
+
+ // If muted, keep track of partial frames that should have been skipped over.
+ double muted_partial_frame_;
+
+ // How many frames to have in the queue before we report the queue is full.
+ int capacity_;
+
+ // Book keeping of the current time of generated audio, in frames. This
+ // should be appropriately updated when out samples are generated, regardless
+ // of whether we push samples out when FillBuffer() is called or we store
+ // audio in |wsola_output_| for the subsequent calls to FillBuffer().
+ // Furthermore, if samples from |audio_buffer_| are evicted then this
+ // member variable should be updated based on |playback_rate_|.
+ // Note that this member should be updated ONLY by calling UpdateOutputTime(),
+ // so that |search_block_index_| is update accordingly.
+ double output_time_;
+
+ // The offset of the center frame of |search_block_| w.r.t. its first frame.
+ int search_block_center_offset_;
+
+ // Index of the beginning of the |search_block_|, in frames.
+ int search_block_index_;
+
+ // Number of Blocks to search to find the most similar one to the target
+ // frame.
+ int num_candidate_blocks_;
+
+ // Index of the beginning of the target block, counted in frames.
+ int target_block_index_;
+
+ // Overlap-and-add window size in frames.
+ int ola_window_size_;
+
+ // The hop size of overlap-and-add in frames. This implementation assumes 50%
+ // overlap-and-add.
+ int ola_hop_size_;
+
+ // Number of frames in |wsola_output_| that overlap-and-add is completed for
+ // them and can be copied to output if FillBuffer() is called. It also
+ // specifies the index where the next WSOLA window has to overlap-and-add.
+ int num_complete_frames_;
+
+ // This stores a part of the output that is created but couldn't be rendered.
+ // Output is generated frame-by-frame which at some point might exceed the
+ // number of requested samples. Furthermore, due to overlap-and-add,
+ // the last half-window of the output is incomplete, which is stored in this
+ // buffer.
+ std::unique_ptr<AudioBus> wsola_output_;
+
+ // Overlap-and-add window.
+ std::unique_ptr<float[]> ola_window_;
+
+ // Transition window, used to update |optimal_block_| by a weighted sum of
+ // |optimal_block_| and |target_block_|.
+ std::unique_ptr<float[]> transition_window_;
+
+ // Auxiliary variables to avoid allocation in every iteration.
+
+ // Stores the optimal block in every iteration. This is the most
+ // similar block to |target_block_| within |search_block_| and it is
+ // overlap-and-added to |wsola_output_|.
+ std::unique_ptr<AudioBus> optimal_block_;
+
+ // A block of data that search is performed over to find the |optimal_block_|.
+ std::unique_ptr<AudioBus> search_block_;
+
+ // Stores the target block, denoted as |target| above. |search_block_| is
+ // searched for a block (|optimal_block_|) that is most similar to
+ // |target_block_|.
+ std::unique_ptr<AudioBus> target_block_;
+
+ // The initial and maximum capacity calculated by Initialize().
+ int initial_capacity_;
+ int max_capacity_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithm);
+};
+
+} // namespace media
+} // namespace cobalt
+
+#endif // COBALT_MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_H_
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
index 13b9db4..96e38a7 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
@@ -220,6 +220,12 @@
*is_playing = true;
*frames_in_buffer = frames_in_buffer_;
*offset_in_frames = offset_in_frames_;
+
+ if (!end_of_stream_decoded_ && !read_from_decoder_closure_.is_valid()) {
+ read_from_decoder_closure_ =
+ Bind(&AudioRendererImpl::ReadFromDecoder, this);
+ job_queue_->Schedule(read_from_decoder_closure_);
+ }
}
void AudioRendererImpl::ConsumeFrames(int frames_consumed) {
@@ -231,15 +237,6 @@
frames_in_buffer_ -= frames_consumed;
frames_consumed_ += frames_consumed;
frames_consumed_set_at_ = SbTimeGetMonotonicNow();
-
- bool decoded_audio_available =
- pending_decoded_audio_ ||
- (end_of_stream_written_ && !end_of_stream_decoded_);
- if (decoded_audio_available && !read_from_decoder_closure_.is_valid()) {
- read_from_decoder_closure_ =
- Bind(&AudioRendererImpl::ReadFromDecoder, this);
- job_queue_->Schedule(read_from_decoder_closure_);
- }
}
void AudioRendererImpl::LogFramesConsumed() {
diff --git a/src/starboard/shared/starboard/player/filter/wsola_internals.cc b/src/starboard/shared/starboard/player/filter/wsola_internals.cc
new file mode 100644
index 0000000..507893e
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/wsola_internals.cc
@@ -0,0 +1,260 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// MSVC++ requires this to be set before any other includes to get M_PI.
+#define _USE_MATH_DEFINES
+
+#include "cobalt/media/filters/wsola_internals.h"
+
+#include <algorithm>
+#include <cmath>
+#include <limits>
+#include <memory>
+
+#include "base/logging.h"
+#include "cobalt/media/base/audio_bus.h"
+#include "starboard/memory.h"
+
+namespace cobalt {
+namespace media {
+
+namespace internal {
+
+bool InInterval(int n, Interval q) { return n >= q.first && n <= q.second; }
+
+float MultiChannelSimilarityMeasure(const float* dot_prod_a_b,
+ const float* energy_a,
+ const float* energy_b, int channels) {
+ const float kEpsilon = 1e-12f;
+ float similarity_measure = 0.0f;
+ for (int n = 0; n < channels; ++n) {
+ similarity_measure +=
+ dot_prod_a_b[n] / sqrt(energy_a[n] * energy_b[n] + kEpsilon);
+ }
+ return similarity_measure;
+}
+
+void MultiChannelDotProduct(const AudioBus* a, int frame_offset_a,
+ const AudioBus* b, int frame_offset_b,
+ int num_frames, float* dot_product) {
+ DCHECK_EQ(a->channels(), b->channels());
+ DCHECK_GE(frame_offset_a, 0);
+ DCHECK_GE(frame_offset_b, 0);
+ DCHECK_LE(frame_offset_a + num_frames, a->frames());
+ DCHECK_LE(frame_offset_b + num_frames, b->frames());
+
+ SbMemorySet(dot_product, 0, sizeof(*dot_product) * a->channels());
+ for (int k = 0; k < a->channels(); ++k) {
+ const float* ch_a = a->channel(k) + frame_offset_a;
+ const float* ch_b = b->channel(k) + frame_offset_b;
+ for (int n = 0; n < num_frames; ++n) {
+ dot_product[k] += *ch_a++ * *ch_b++;
+ }
+ }
+}
+
+void MultiChannelMovingBlockEnergies(const AudioBus* input,
+ int frames_per_block, float* energy) {
+ int num_blocks = input->frames() - (frames_per_block - 1);
+ int channels = input->channels();
+
+ for (int k = 0; k < input->channels(); ++k) {
+ const float* input_channel = input->channel(k);
+
+ energy[k] = 0;
+
+ // First block of channel |k|.
+ for (int m = 0; m < frames_per_block; ++m) {
+ energy[k] += input_channel[m] * input_channel[m];
+ }
+
+ const float* slide_out = input_channel;
+ const float* slide_in = input_channel + frames_per_block;
+ for (int n = 1; n < num_blocks; ++n, ++slide_in, ++slide_out) {
+ energy[k + n * channels] = energy[k + (n - 1) * channels] -
+ *slide_out * *slide_out +
+ *slide_in * *slide_in;
+ }
+ }
+}
+
+// Fit the curve f(x) = a * x^2 + b * x + c such that
+// f(-1) = y[0]
+// f(0) = y[1]
+// f(1) = y[2]
+// and return the maximum, assuming that y[0] <= y[1] >= y[2].
+void QuadraticInterpolation(const float* y_values, float* extremum,
+ float* extremum_value) {
+ float a = 0.5f * (y_values[2] + y_values[0]) - y_values[1];
+ float b = 0.5f * (y_values[2] - y_values[0]);
+ float c = y_values[1];
+
+ if (a == 0.f) {
+ // The coordinates are colinear (within floating-point error).
+ *extremum = 0;
+ *extremum_value = y_values[1];
+ } else {
+ *extremum = -b / (2.f * a);
+ *extremum_value = a * (*extremum) * (*extremum) + b * (*extremum) + c;
+ }
+}
+
+int DecimatedSearch(int decimation, Interval exclude_interval,
+ const AudioBus* target_block,
+ const AudioBus* search_segment,
+ const float* energy_target_block,
+ const float* energy_candidate_blocks) {
+ int channels = search_segment->channels();
+ int block_size = target_block->frames();
+ int num_candidate_blocks = search_segment->frames() - (block_size - 1);
+ std::unique_ptr<float[]> dot_prod(new float[channels]);
+ float similarity[3]; // Three elements for cubic interpolation.
+
+ int n = 0;
+ MultiChannelDotProduct(target_block, 0, search_segment, n, block_size,
+ dot_prod.get());
+ similarity[0] = MultiChannelSimilarityMeasure(
+ dot_prod.get(), energy_target_block,
+ &energy_candidate_blocks[n * channels], channels);
+
+ // Set the starting point as optimal point.
+ float best_similarity = similarity[0];
+ int optimal_index = 0;
+
+ n += decimation;
+ if (n >= num_candidate_blocks) {
+ return 0;
+ }
+
+ MultiChannelDotProduct(target_block, 0, search_segment, n, block_size,
+ dot_prod.get());
+ similarity[1] = MultiChannelSimilarityMeasure(
+ dot_prod.get(), energy_target_block,
+ &energy_candidate_blocks[n * channels], channels);
+
+ n += decimation;
+ if (n >= num_candidate_blocks) {
+ // We cannot do any more sampling. Compare these two values and return the
+ // optimal index.
+ return similarity[1] > similarity[0] ? decimation : 0;
+ }
+
+ for (; n < num_candidate_blocks; n += decimation) {
+ MultiChannelDotProduct(target_block, 0, search_segment, n, block_size,
+ dot_prod.get());
+
+ similarity[2] = MultiChannelSimilarityMeasure(
+ dot_prod.get(), energy_target_block,
+ &energy_candidate_blocks[n * channels], channels);
+
+ if ((similarity[1] > similarity[0] && similarity[1] >= similarity[2]) ||
+ (similarity[1] >= similarity[0] && similarity[1] > similarity[2])) {
+ // A local maximum is found. Do a cubic interpolation for a better
+ // estimate of candidate maximum.
+ float normalized_candidate_index;
+ float candidate_similarity;
+ QuadraticInterpolation(similarity, &normalized_candidate_index,
+ &candidate_similarity);
+
+ int candidate_index =
+ n - decimation +
+ static_cast<int>(normalized_candidate_index * decimation + 0.5f);
+ if (candidate_similarity > best_similarity &&
+ !InInterval(candidate_index, exclude_interval)) {
+ optimal_index = candidate_index;
+ best_similarity = candidate_similarity;
+ }
+ } else if (n + decimation >= num_candidate_blocks &&
+ similarity[2] > best_similarity &&
+ !InInterval(n, exclude_interval)) {
+ // If this is the end-point and has a better similarity-measure than
+ // optimal, then we accept it as optimal point.
+ optimal_index = n;
+ best_similarity = similarity[2];
+ }
+ SbMemoryMove(similarity, &similarity[1], 2 * sizeof(*similarity));
+ }
+ return optimal_index;
+}
+
+int FullSearch(int low_limit, int high_limit, Interval exclude_interval,
+ const AudioBus* target_block, const AudioBus* search_block,
+ const float* energy_target_block,
+ const float* energy_candidate_blocks) {
+ int channels = search_block->channels();
+ int block_size = target_block->frames();
+ std::unique_ptr<float[]> dot_prod(new float[channels]);
+
+ float best_similarity = std::numeric_limits<float>::min();
+ int optimal_index = 0;
+
+ for (int n = low_limit; n <= high_limit; ++n) {
+ if (InInterval(n, exclude_interval)) {
+ continue;
+ }
+ MultiChannelDotProduct(target_block, 0, search_block, n, block_size,
+ dot_prod.get());
+
+ float similarity = MultiChannelSimilarityMeasure(
+ dot_prod.get(), energy_target_block,
+ &energy_candidate_blocks[n * channels], channels);
+
+ if (similarity > best_similarity) {
+ best_similarity = similarity;
+ optimal_index = n;
+ }
+ }
+
+ return optimal_index;
+}
+
+int OptimalIndex(const AudioBus* search_block, const AudioBus* target_block,
+ Interval exclude_interval) {
+ int channels = search_block->channels();
+ DCHECK_EQ(channels, target_block->channels());
+ int target_size = target_block->frames();
+ int num_candidate_blocks = search_block->frames() - (target_size - 1);
+
+ // This is a compromise between complexity reduction and search accuracy. I
+ // don't have a proof that down sample of order 5 is optimal. One can compute
+ // a decimation factor that minimizes complexity given the size of
+ // |search_block| and |target_block|. However, my experiments show the rate of
+ // missing the optimal index is significant. This value is chosen
+ // heuristically based on experiments.
+ const int kSearchDecimation = 5;
+
+ std::unique_ptr<float[]> energy_target_block(new float[channels]);
+ std::unique_ptr<float[]> energy_candidate_blocks(
+ new float[channels * num_candidate_blocks]);
+
+ // Energy of all candid frames.
+ MultiChannelMovingBlockEnergies(search_block, target_size,
+ energy_candidate_blocks.get());
+
+ // Energy of target frame.
+ MultiChannelDotProduct(target_block, 0, target_block, 0, target_size,
+ energy_target_block.get());
+
+ int optimal_index = DecimatedSearch(
+ kSearchDecimation, exclude_interval, target_block, search_block,
+ energy_target_block.get(), energy_candidate_blocks.get());
+
+ int lim_low = std::max(0, optimal_index - kSearchDecimation);
+ int lim_high =
+ std::min(num_candidate_blocks - 1, optimal_index + kSearchDecimation);
+ return FullSearch(lim_low, lim_high, exclude_interval, target_block,
+ search_block, energy_target_block.get(),
+ energy_candidate_blocks.get());
+}
+
+void GetSymmetricHanningWindow(int window_length, float* window) {
+ const float scale = 2.0f * M_PI / window_length;
+ for (int n = 0; n < window_length; ++n)
+ window[n] = 0.5f * (1.0f - cosf(n * scale));
+}
+
+} // namespace internal
+
+} // namespace media
+} // namespace cobalt
diff --git a/src/starboard/shared/starboard/player/filter/wsola_internals.h b/src/starboard/shared/starboard/player/filter/wsola_internals.h
new file mode 100644
index 0000000..4d96b39
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/wsola_internals.h
@@ -0,0 +1,83 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A set of utility functions to perform WSOLA.
+
+#ifndef COBALT_MEDIA_FILTERS_WSOLA_INTERNALS_H_
+#define COBALT_MEDIA_FILTERS_WSOLA_INTERNALS_H_
+
+#include <utility>
+
+#include "cobalt/media/base/media_export.h"
+
+namespace cobalt {
+namespace media {
+
+class AudioBus;
+
+namespace internal {
+
+typedef std::pair<int, int> Interval;
+
+// Dot-product of channels of two AudioBus. For each AudioBus an offset is
+// given. |dot_product[k]| is the dot-product of channel |k|. The caller should
+// allocate sufficient space for |dot_product|.
+MEDIA_EXPORT void MultiChannelDotProduct(const AudioBus* a, int frame_offset_a,
+ const AudioBus* b, int frame_offset_b,
+ int num_frames, float* dot_product);
+
+// Energies of sliding windows of channels are interleaved.
+// The number windows is |input->frames()| - (|frames_per_window| - 1), hence,
+// the method assumes |energy| must be, at least, of size
+// (|input->frames()| - (|frames_per_window| - 1)) * |input->channels()|.
+MEDIA_EXPORT void MultiChannelMovingBlockEnergies(const AudioBus* input,
+ int frames_per_window,
+ float* energy);
+
+// Fit the curve f(x) = a * x^2 + b * x + c such that
+// f(-1) = y[0]
+// f(0) = y[1]
+// f(1) = y[2]
+// and return the maximum, assuming that y[0] <= y[1] >= y[2].
+MEDIA_EXPORT void QuadraticInterpolation(const float* y_values, float* extremum,
+ float* extremum_value);
+
+// Search a subset of all candid blocks. The search is performed every
+// |decimation| frames. This reduces complexity by a factor of about
+// 1 / |decimation|. A cubic interpolation is used to have a better estimate of
+// the best match.
+MEDIA_EXPORT int DecimatedSearch(int decimation, Interval exclude_interval,
+ const AudioBus* target_block,
+ const AudioBus* search_segment,
+ const float* energy_target_block,
+ const float* energy_candid_blocks);
+
+// Search [|low_limit|, |high_limit|] of |search_segment| to find a block that
+// is most similar to |target_block|. |energy_target_block| is the energy of the
+// |target_block|. |energy_candidate_blocks| is the energy of all blocks within
+// |search_block|.
+MEDIA_EXPORT int FullSearch(int low_limit, int hight_limimit,
+ Interval exclude_interval,
+ const AudioBus* target_block,
+ const AudioBus* search_block,
+ const float* energy_target_block,
+ const float* energy_candidate_blocks);
+
+// Find the index of the block, within |search_block|, that is most similar
+// to |target_block|. Obviously, the returned index is w.r.t. |search_block|.
+// |exclude_interval| is an interval that is excluded from the search.
+MEDIA_EXPORT int OptimalIndex(const AudioBus* search_block,
+ const AudioBus* target_block,
+ Interval exclude_interval);
+
+// Return a "periodic" Hann window. This is the first L samples of an L+1
+// Hann window. It is perfect reconstruction for overlap-and-add.
+MEDIA_EXPORT void GetSymmetricHanningWindow(int window_length, float* window);
+
+} // namespace internal
+
+} // namespace media
+} // namespace cobalt
+
+#endif // COBALT_MEDIA_FILTERS_WSOLA_INTERNALS_H_
diff --git a/src/starboard/shared/starboard/string_duplicate.cc b/src/starboard/shared/starboard/string_duplicate.cc
index b5e51d9..b504b16 100644
--- a/src/starboard/shared/starboard/string_duplicate.cc
+++ b/src/starboard/shared/starboard/string_duplicate.cc
@@ -14,12 +14,15 @@
#include "starboard/string.h"
+#include "starboard/log.h"
#include "starboard/memory.h"
char* SbStringDuplicate(const char* source) {
size_t length = SbStringGetLength(source);
char* result = static_cast<char*>(SbMemoryAllocate(length + 1));
- SbStringCopy(result, source, length + 1);
+ SB_DCHECK(length < kSbInt32Max);
+ int int_length = static_cast<int>(length + 1);
+ SbStringCopy(result, source, int_length);
return result;
}
diff --git a/src/starboard/shared/win32/application_stub.cc b/src/starboard/shared/win32/application_stub.cc
new file mode 100644
index 0000000..1f56080
--- /dev/null
+++ b/src/starboard/shared/win32/application_stub.cc
@@ -0,0 +1,62 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/win32/application_stub.h"
+
+#include "starboard/event.h"
+#include "starboard/log.h"
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+ApplicationStub::ApplicationStub() {
+ SB_NOTIMPLEMENTED();
+}
+
+ApplicationStub::~ApplicationStub() {
+ SB_NOTIMPLEMENTED();
+}
+
+void ApplicationStub::Initialize() {
+ SB_NOTIMPLEMENTED();
+}
+
+void ApplicationStub::Teardown() {
+ SB_NOTIMPLEMENTED();
+}
+
+bool ApplicationStub::MayHaveSystemEvents() {
+ SB_NOTIMPLEMENTED();
+ return false;
+}
+
+shared::starboard::Application::Event* ApplicationStub::PollNextSystemEvent() {
+ SB_NOTIMPLEMENTED();
+ return NULL;
+}
+
+shared::starboard::Application::Event*
+ApplicationStub::WaitForSystemEventWithTimeout(SbTime time) {
+ SB_NOTIMPLEMENTED();
+ return NULL;
+}
+
+void ApplicationStub::WakeSystemEventWait() {
+ SB_NOTIMPLEMENTED();
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/win32/application_stub.h b/src/starboard/shared/win32/application_stub.h
new file mode 100644
index 0000000..c112677
--- /dev/null
+++ b/src/starboard/shared/win32/application_stub.h
@@ -0,0 +1,54 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_WIN32_APPLICATION_STUB_H_
+#define STARBOARD_SHARED_WIN32_APPLICATION_STUB_H_
+
+#include "starboard/configuration.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/application.h"
+#include "starboard/shared/starboard/queue_application.h"
+#include "starboard/types.h"
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+// Stub application engine using the generic queue and a stub implementation.
+class ApplicationStub : public shared::starboard::QueueApplication {
+ public:
+ ApplicationStub();
+ ~ApplicationStub() SB_OVERRIDE;
+
+ static ApplicationStub* Get() {
+ return static_cast<ApplicationStub*>(shared::starboard::Application::Get());
+ }
+
+ protected:
+ // --- Application overrides ---
+ void Initialize() SB_OVERRIDE;
+ void Teardown() SB_OVERRIDE;
+
+ // --- QueueApplication overrides ---
+ bool MayHaveSystemEvents() SB_OVERRIDE;
+ Event* PollNextSystemEvent() SB_OVERRIDE;
+ Event* WaitForSystemEventWithTimeout(SbTime time) SB_OVERRIDE;
+ void WakeSystemEventWait() SB_OVERRIDE;
+};
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_WIN32_APPLICATION_STUB_H_
diff --git a/src/starboard/shared/win32/byte_swap.cc b/src/starboard/shared/win32/byte_swap.cc
new file mode 100644
index 0000000..45f4fd9
--- /dev/null
+++ b/src/starboard/shared/win32/byte_swap.cc
@@ -0,0 +1,44 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Not breaking these functions up because however one is implemented, the
+// others should be implemented similarly.
+
+#include "starboard/byte_swap.h"
+
+#include <stdlib.h>
+
+int16_t SbByteSwapS16(int16_t value) {
+ return _byteswap_ushort(value);
+}
+
+uint16_t SbByteSwapU16(uint16_t value) {
+ return _byteswap_ushort(value);
+}
+
+int32_t SbByteSwapS32(int32_t value) {
+ return _byteswap_ulong(value);
+}
+
+uint32_t SbByteSwapU32(uint32_t value) {
+ return _byteswap_ulong(value);
+}
+
+int64_t SbByteSwapS64(int64_t value) {
+ return _byteswap_uint64(value);
+}
+
+uint64_t SbByteSwapU64(uint64_t value) {
+ return _byteswap_uint64(value);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/condition_variable_broadcast.cc
similarity index 68%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/condition_variable_broadcast.cc
index 51e1f2e..f2b9ea5 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/condition_variable_broadcast.cc
@@ -12,9 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/condition_variable.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+bool SbConditionVariableBroadcast(SbConditionVariable* condition) {
+ if (!condition) {
+ return false;
+ }
+ WakeAllConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(condition));
+ return true;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/condition_variable_create.cc
similarity index 63%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/condition_variable_create.cc
index 51e1f2e..9d74a6f 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/condition_variable_create.cc
@@ -12,9 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/condition_variable.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+bool SbConditionVariableCreate(SbConditionVariable* out_condition,
+ SbMutex* /*opt_mutex*/) {
+ if (!out_condition) {
+ return false;
+ }
+ InitializeConditionVariable(
+ reinterpret_cast<PCONDITION_VARIABLE>(out_condition));
+ return true;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/condition_variable_destroy.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/condition_variable_destroy.cc
index 51e1f2e..4a24e47 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/condition_variable_destroy.cc
@@ -12,9 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/condition_variable.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+bool SbConditionVariableDestroy(SbConditionVariable* condition) {
+ if (!condition) {
+ return false;
+ }
+ return true;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/condition_variable_signal.cc
similarity index 69%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/condition_variable_signal.cc
index 51e1f2e..5e8e67b 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/condition_variable_signal.cc
@@ -12,9 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/condition_variable.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+bool SbConditionVariableSignal(SbConditionVariable* condition) {
+ if (!condition) {
+ return false;
+ }
+ WakeConditionVariable(reinterpret_cast<PCONDITION_VARIABLE>(condition));
+ return true;
+}
diff --git a/src/starboard/shared/win32/condition_variable_wait.cc b/src/starboard/shared/win32/condition_variable_wait.cc
new file mode 100644
index 0000000..a224afc
--- /dev/null
+++ b/src/starboard/shared/win32/condition_variable_wait.cc
@@ -0,0 +1,30 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/condition_variable.h"
+
+#include <windows.h>
+
+SbConditionVariableResult SbConditionVariableWait(
+ SbConditionVariable* condition,
+ SbMutex* mutex) {
+ if (!condition || !mutex) {
+ return kSbConditionVariableFailed;
+ }
+ bool result = SleepConditionVariableSRW(
+ reinterpret_cast<PCONDITION_VARIABLE>(condition),
+ reinterpret_cast<PSRWLOCK>(mutex), INFINITE, 0);
+
+ return result ? kSbConditionVariableSignaled : kSbConditionVariableFailed;
+}
diff --git a/src/starboard/shared/win32/condition_variable_wait_timed.cc b/src/starboard/shared/win32/condition_variable_wait_timed.cc
new file mode 100644
index 0000000..e967695
--- /dev/null
+++ b/src/starboard/shared/win32/condition_variable_wait_timed.cc
@@ -0,0 +1,54 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/condition_variable.h"
+
+#include <windows.h>
+
+#include "starboard/shared/win32/time_utils.h"
+
+using starboard::shared::win32::ConvertSbTimeToMillisRoundUp;
+
+SbConditionVariableResult SbConditionVariableWaitTimed(
+ SbConditionVariable* condition,
+ SbMutex* mutex,
+ SbTime timeout) {
+ if (!condition || !mutex) {
+ return kSbConditionVariableFailed;
+ }
+
+ if (timeout < 0) {
+ timeout = 0;
+ }
+ bool result = SleepConditionVariableSRW(
+ reinterpret_cast<PCONDITION_VARIABLE>(condition),
+ reinterpret_cast<PSRWLOCK>(mutex),
+ ConvertSbTimeToMillisRoundUp(timeout), 0);
+
+ if (timeout == 0) {
+ // Per documentation, "If the |timeout_duration| value is less than
+ // or equal to zero, the function returns as quickly as possible with a
+ // kSbConditionVariableTimedOut result."
+ return kSbConditionVariableTimedOut;
+ }
+
+ if (result) {
+ return kSbConditionVariableSignaled;
+ }
+
+ if (GetLastError() == ERROR_TIMEOUT) {
+ return kSbConditionVariableTimedOut;
+ }
+ return kSbConditionVariableFailed;
+}
diff --git a/src/starboard/shared/win32/directory_can_open.cc b/src/starboard/shared/win32/directory_can_open.cc
new file mode 100644
index 0000000..b64a410
--- /dev/null
+++ b/src/starboard/shared/win32/directory_can_open.cc
@@ -0,0 +1,48 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/directory.h"
+
+#include <windows.h>
+
+#include <algorithm>
+
+#include "starboard/shared/win32/directory_internal.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+bool SbDirectoryCanOpen(const char* path) {
+ if ((path == nullptr) || (path[0] == '\0')) {
+ return false;
+ }
+
+ std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+ starboard::shared::win32::TrimExtraFileSeparators(&path_wstring);
+
+ if (!starboard::shared::win32::IsAbsolutePath(path_wstring)) {
+ return false;
+ }
+
+ WIN32_FIND_DATA find_data = {0};
+
+ HANDLE search_handle = FindFirstFileExW(
+ path_wstring.c_str(), FindExInfoStandard, &find_data,
+ FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE);
+ if (!starboard::shared::win32::IsValidHandle(search_handle)) {
+ return false;
+ }
+
+ FindClose(search_handle);
+
+ return find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/directory_close.cc
similarity index 64%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/directory_close.cc
index 51e1f2e..6d7765a 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/directory_close.cc
@@ -12,9 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/directory.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+#include "starboard/shared/win32/directory_internal.h"
+
+bool SbDirectoryClose(SbDirectory directory) {
+ if (!SbDirectoryIsValid(directory)) {
+ return false;
+ }
+
+ bool success = CloseHandle(directory->directory_handle);
+
+ delete directory;
+
+ return success;
+}
diff --git a/src/starboard/shared/win32/directory_create.cc b/src/starboard/shared/win32/directory_create.cc
new file mode 100644
index 0000000..26b1845
--- /dev/null
+++ b/src/starboard/shared/win32/directory_create.cc
@@ -0,0 +1,41 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/directory.h"
+
+#include <windows.h>
+
+#include "starboard/shared/win32/directory_internal.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+bool SbDirectoryCreate(const char* path) {
+ if ((path == nullptr) || (path[0] == '\0')) {
+ return false;
+ }
+
+ std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+
+ starboard::shared::win32::TrimExtraFileSeparators(&path_wstring);
+
+ if (!starboard::shared::win32::IsAbsolutePath(path_wstring)) {
+ return false;
+ }
+
+ BOOL directory_created = CreateDirectoryW(path_wstring.c_str(), NULL);
+
+ bool directory_exists =
+ directory_created || (GetLastError() == ERROR_ALREADY_EXISTS);
+
+ return directory_exists;
+}
diff --git a/src/starboard/shared/win32/directory_get_next.cc b/src/starboard/shared/win32/directory_get_next.cc
new file mode 100644
index 0000000..514c1b6
--- /dev/null
+++ b/src/starboard/shared/win32/directory_get_next.cc
@@ -0,0 +1,94 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/directory.h"
+
+#include <windows.h>
+
+#include "starboard/log.h"
+#include "starboard/string.h"
+#include "starboard/shared/win32/directory_internal.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+namespace {
+// One of the entries of FILE_ID_BOTH_DIR_INFO is a file path, so make the
+// buffer at-least one path big.
+const std::size_t kDirectoryInfoBufferSize =
+ SB_FILE_MAX_PATH + sizeof(FILE_ID_BOTH_DIR_INFO);
+
+std::deque<std::string> GetDirectoryEntries(HANDLE directory_handle) {
+ // According to
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364226(v=vs.85).aspx,
+ // FILE_ID_BOTH_DIR_INFO must be aligned on a DWORDLONG boundary.
+ alignas(
+ sizeof(DWORDLONG)) char directory_info_buffer[kDirectoryInfoBufferSize];
+
+ std::deque<std::string> entries;
+ BOOL directory_info_success = GetFileInformationByHandleEx(
+ directory_handle, FileIdBothDirectoryInfo, directory_info_buffer,
+ SB_ARRAY_SIZE(directory_info_buffer));
+
+ if (!directory_info_success) {
+ return entries;
+ }
+
+ const char* directory_info_pointer = directory_info_buffer;
+ DWORD next_entry_offset = 0;
+
+ do {
+ auto directory_info =
+ reinterpret_cast<const FILE_ID_BOTH_DIR_INFO*>(directory_info_pointer);
+
+ // FileName is in Unicode, so divide by 2 to get the real length.
+ DWORD number_characters_in_filename = directory_info->FileNameLength / 2;
+ std::string ascii_path = starboard::shared::win32::wchar_tToUTF8(
+ directory_info->FileName, number_characters_in_filename);
+ SB_DCHECK(ascii_path.size() == number_characters_in_filename);
+ bool is_dotted_directory =
+ !ascii_path.compare(".") || !ascii_path.compare("..");
+ if (!is_dotted_directory) {
+ entries.emplace_back(std::move(ascii_path));
+ }
+ next_entry_offset = directory_info->NextEntryOffset;
+ directory_info_pointer += next_entry_offset;
+ } while (next_entry_offset != 0);
+
+ return entries;
+}
+
+} // namespace
+
+bool SbDirectoryGetNext(SbDirectory directory, SbDirectoryEntry* out_entry) {
+ if (!SbDirectoryIsValid(directory) || (out_entry == nullptr)) {
+ return false;
+ }
+
+ auto& next_directory_entries = directory->next_directory_entries;
+ if (next_directory_entries.empty()) {
+ next_directory_entries = GetDirectoryEntries(directory->directory_handle);
+ }
+
+ if (next_directory_entries.empty()) {
+ return false;
+ }
+
+ bool success = true;
+ const int entry_name_size = SB_ARRAY_SIZE_INT(out_entry->name);
+ if (SbStringCopy(out_entry->name, next_directory_entries.rbegin()->c_str(),
+ entry_name_size) >= entry_name_size) {
+ success = false;
+ }
+ directory->next_directory_entries.pop_back();
+ return success;
+}
diff --git a/src/starboard/shared/win32/directory_internal.h b/src/starboard/shared/win32/directory_internal.h
new file mode 100644
index 0000000..f27fff9
--- /dev/null
+++ b/src/starboard/shared/win32/directory_internal.h
@@ -0,0 +1,97 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_WIN32_DIRECTORY_INTERNAL_H_
+#define STARBOARD_SHARED_WIN32_DIRECTORY_INTERNAL_H_
+
+#include "starboard/directory.h"
+
+#include <algorithm>
+#include <deque>
+#include <string>
+
+#include "starboard/log.h"
+#include "starboard/memory.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/win32/file_internal.h"
+
+#pragma warning(push)
+
+// SbFilePrivate is defined as a struct, but for windows implementation
+// enough functionality has been added so that it warrants being a class
+// per Google's C++ style guide. This mismatch causes the Microsoft's compiler
+// to generate a warning.
+#pragma warning(disable : 4099)
+
+class SbDirectoryPrivate {
+ public:
+ explicit SbDirectoryPrivate(HANDLE handle) : directory_handle(handle) {}
+
+ bool HasValidHandle() const {
+ return starboard::shared::win32::IsValidHandle(directory_handle);
+ }
+
+ HANDLE directory_handle;
+ std::deque<std::string> next_directory_entries;
+
+ // SbDirectoryPrivate is neither copyable nor movable.
+ SbDirectoryPrivate(const SbDirectoryPrivate&) = delete;
+ SbDirectoryPrivate& operator=(const SbDirectoryPrivate&) = delete;
+};
+#pragma warning(pop)
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+inline bool HasValidHandle(SbDirectory directory) {
+ if (!SbDirectoryIsValid(directory)) {
+ return false;
+ }
+
+ return directory->HasValidHandle();
+}
+
+// This function strips trailing file separators from a directory name.
+// For example if the directory name was "C:\\Temp\\\\\\", it would
+// strip them, so that the directory name is now to be "C:\\temp".
+inline void TrimExtraFileSeparators(std::wstring* dirname_pointer) {
+ SB_DCHECK(dirname_pointer);
+ std::wstring& dirname = *dirname_pointer;
+ auto new_end =
+ std::find_if_not(dirname.rbegin(), dirname.rend(), [](wchar_t c) {
+ return c == SB_FILE_SEP_CHAR || c == SB_FILE_ALT_SEP_CHAR;
+ });
+ dirname.erase(new_end.base(), dirname.end());
+}
+
+inline bool IsAbsolutePath(const std::wstring& path) {
+ wchar_t full_path[SB_FILE_MAX_PATH];
+ DWORD full_path_size =
+ GetFullPathNameW(path.c_str(), SB_ARRAY_SIZE(full_path), full_path, NULL);
+ if (full_path_size == 0) {
+ return false;
+ }
+
+ int path_size = static_cast<int>(path.size());
+ return CompareStringEx(LOCALE_NAME_USER_DEFAULT, NORM_IGNORECASE,
+ path.c_str(), path_size, full_path, full_path_size,
+ NULL, NULL, 0) == CSTR_EQUAL;
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_WIN32_DIRECTORY_INTERNAL_H_
diff --git a/src/starboard/shared/win32/directory_open.cc b/src/starboard/shared/win32/directory_open.cc
new file mode 100644
index 0000000..6dade7e
--- /dev/null
+++ b/src/starboard/shared/win32/directory_open.cc
@@ -0,0 +1,58 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/directory.h"
+
+#include "starboard/shared/win32/directory_internal.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+SbDirectory SbDirectoryOpen(const char* path, SbFileError* out_error) {
+ if ((path == nullptr) || (path[0] == '\0')) {
+ if (out_error) {
+ *out_error = kSbFileErrorNotFound;
+ }
+ return kSbDirectoryInvalid;
+ }
+
+ std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+
+ if (!starboard::shared::win32::IsAbsolutePath(path_wstring)) {
+ if (out_error) {
+ *out_error = kSbFileErrorNotFound;
+ }
+ return kSbDirectoryInvalid;
+ }
+
+ HANDLE directory_handle = starboard::shared::win32::OpenFileOrDirectory(
+ path, kSbFileOpenOnly | kSbFileRead, nullptr, out_error);
+
+ if (!starboard::shared::win32::IsValidHandle(directory_handle)) {
+ return kSbDirectoryInvalid;
+ }
+
+ FILE_BASIC_INFO basic_info = {0};
+ BOOL basic_info_success = GetFileInformationByHandleEx(
+ directory_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO));
+
+ if (!basic_info_success ||
+ !(basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ CloseHandle(directory_handle);
+ if (out_error) {
+ *out_error = kSbFileErrorNotADirectory;
+ }
+ return kSbDirectoryInvalid;
+ }
+
+ return new SbDirectoryPrivate(directory_handle);
+}
diff --git a/src/starboard/shared/win32/file_can_open.cc b/src/starboard/shared/win32/file_can_open.cc
new file mode 100644
index 0000000..f4f19f6
--- /dev/null
+++ b/src/starboard/shared/win32/file_can_open.cc
@@ -0,0 +1,53 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include <windows.h>
+
+#include "starboard/shared/win32/file_internal.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+bool SbFileCanOpen(const char* path, int flags) {
+ if ((path == nullptr) || (path[0] == '\0')) {
+ return false;
+ }
+
+ bool can_read = flags & kSbFileRead;
+ bool can_write = flags & kSbFileWrite;
+ if (!can_read && !can_write) {
+ return false;
+ }
+
+ std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+ WIN32_FIND_DATA find_data = {0};
+
+ HANDLE search_handle = FindFirstFileExW(
+ path_wstring.c_str(), FindExInfoStandard, &find_data,
+ FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE);
+ if (!starboard::shared::win32::IsValidHandle(search_handle)) {
+ return false;
+ }
+
+ bool can_open = true;
+
+ if (((find_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && can_write) ||
+ !starboard::shared::win32::PathEndsWith(path_wstring, find_data.cFileName)) {
+ can_open = false;
+ }
+
+ FindClose(search_handle);
+
+ return can_open;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/file_close.cc
similarity index 68%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/file_close.cc
index 51e1f2e..ce61c54 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/file_close.cc
@@ -12,9 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/file.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+#include "starboard/shared/win32/file_internal.h"
+
+bool SbFileClose(SbFile file) {
+ if (!SbFileIsValid(file)) {
+ return false;
+ }
+
+ bool success = CloseHandle(file->file_handle);
+
+ delete file;
+
+ return success;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/file_delete.cc
similarity index 61%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/file_delete.cc
index 51e1f2e..fecbfd1 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/file_delete.cc
@@ -12,9 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/file.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+#include "starboard/shared/win32/file_internal.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+bool SbFileDelete(const char* path) {
+ if ((path == nullptr) || *path == '\0') {
+ return false;
+ }
+
+ std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+
+ return DeleteFileW(path_wstring.c_str());
+}
diff --git a/src/starboard/shared/win32/file_exists.cc b/src/starboard/shared/win32/file_exists.cc
new file mode 100644
index 0000000..160f17d
--- /dev/null
+++ b/src/starboard/shared/win32/file_exists.cc
@@ -0,0 +1,41 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include <windows.h>
+
+#include "starboard/shared/win32/file_internal.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+bool SbFileExists(const char* path) {
+ if ((path == nullptr) || (path[0] == '\0')) {
+ return false;
+ }
+
+ std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+ WIN32_FIND_DATA find_data = {0};
+
+ HANDLE search_handle = FindFirstFileExW(
+ path_wstring.c_str(), FindExInfoStandard, &find_data,
+ FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE);
+
+ if (!starboard::shared::win32::IsValidHandle(search_handle)) {
+ return false;
+ }
+
+ FindClose(search_handle);
+
+ return starboard::shared::win32::PathEndsWith(path_wstring, find_data.cFileName);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/file_flush.cc
similarity index 67%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/file_flush.cc
index 51e1f2e..1c9655c 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/file_flush.cc
@@ -12,9 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/file.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/file_internal.h"
+
+bool SbFileFlush(SbFile file) {
+ if (!starboard::shared::win32::HasValidHandle(file)) {
+ return false;
+ }
+
+ return FlushFileBuffers(file->file_handle);
+}
diff --git a/src/starboard/shared/win32/file_get_info.cc b/src/starboard/shared/win32/file_get_info.cc
new file mode 100644
index 0000000..9a25753
--- /dev/null
+++ b/src/starboard/shared/win32/file_get_info.cc
@@ -0,0 +1,59 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include <windows.h>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/file_internal.h"
+#include "starboard/shared/win32/time_utils.h"
+
+bool SbFileGetInfo(SbFile file, SbFileInfo* out_info) {
+ if (!starboard::shared::win32::HasValidHandle(file) || !out_info) {
+ return false;
+ }
+
+ FILE_BASIC_INFO basic_info = {0};
+ BOOL basic_info_success = GetFileInformationByHandleEx(
+ file->file_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO));
+ if (!basic_info_success) {
+ return false;
+ }
+
+ FILE_STANDARD_INFO standard_info = {0};
+ BOOL standard_info_success =
+ GetFileInformationByHandleEx(file->file_handle, FileStandardInfo,
+ &standard_info, sizeof(FILE_STANDARD_INFO));
+ if (!standard_info_success) {
+ return false;
+ }
+
+ out_info->size = standard_info.EndOfFile.QuadPart;
+ SB_DCHECK(out_info->size >= 0);
+
+ using starboard::shared::win32::ConvertFileTimeTicksToSbTime;
+
+ out_info->creation_time =
+ ConvertFileTimeTicksToSbTime(basic_info.CreationTime);
+ out_info->last_accessed =
+ ConvertFileTimeTicksToSbTime(basic_info.LastAccessTime);
+ out_info->last_modified =
+ ConvertFileTimeTicksToSbTime(basic_info.LastWriteTime);
+
+ out_info->is_symbolic_link = false;
+ out_info->is_directory = standard_info.Directory;
+
+ return true;
+}
diff --git a/src/starboard/shared/win32/file_get_path_info.cc b/src/starboard/shared/win32/file_get_path_info.cc
new file mode 100644
index 0000000..4ac6928
--- /dev/null
+++ b/src/starboard/shared/win32/file_get_path_info.cc
@@ -0,0 +1,55 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include <windows.h>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/file_internal.h"
+#include "starboard/shared/win32/time_utils.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+bool SbFileGetPathInfo(const char* path, SbFileInfo* out_info) {
+ if (!path || path[0] == '\0' || !out_info) {
+ return false;
+ }
+
+ std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+
+ WIN32_FILE_ATTRIBUTE_DATA attribute_data = {0};
+ if (!GetFileAttributesExW(path_wstring.c_str(), GetFileExInfoStandard,
+ &attribute_data)) {
+ return false;
+ }
+
+ out_info->size = static_cast<int64_t>(attribute_data.nFileSizeHigh) << 32 |
+ attribute_data.nFileSizeLow;
+ SB_DCHECK(out_info->size >= 0);
+
+ using starboard::shared::win32::ConvertFileTimeToSbTime;
+
+ out_info->creation_time =
+ ConvertFileTimeToSbTime(attribute_data.ftCreationTime);
+ out_info->last_accessed =
+ ConvertFileTimeToSbTime(attribute_data.ftLastAccessTime);
+ out_info->last_modified =
+ ConvertFileTimeToSbTime(attribute_data.ftLastWriteTime);
+
+ out_info->is_symbolic_link = false;
+ out_info->is_directory =
+ (attribute_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+
+ return true;
+}
diff --git a/src/starboard/shared/win32/file_internal.cc b/src/starboard/shared/win32/file_internal.cc
new file mode 100644
index 0000000..a2d7621
--- /dev/null
+++ b/src/starboard/shared/win32/file_internal.cc
@@ -0,0 +1,142 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/win32/file_internal.h"
+
+#include <windows.h>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/wchar_utils.h"
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+HANDLE OpenFileOrDirectory(const char* path,
+ int flags,
+ bool* out_created,
+ SbFileError* out_error) {
+ const DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ DWORD creation_disposition = 0;
+ if (flags & kSbFileCreateOnly) {
+ SB_DCHECK(!creation_disposition);
+ SB_DCHECK(!(flags & kSbFileCreateAlways));
+ creation_disposition = CREATE_NEW;
+ }
+
+ if (out_created) {
+ *out_created = false;
+ }
+
+ if (flags & kSbFileCreateAlways) {
+ SB_DCHECK(!creation_disposition);
+ SB_DCHECK(!(flags & kSbFileCreateOnly));
+ creation_disposition = CREATE_ALWAYS;
+ }
+
+ if (flags & kSbFileOpenTruncated) {
+ SB_DCHECK(!creation_disposition);
+ SB_DCHECK(flags & kSbFileWrite);
+ creation_disposition = TRUNCATE_EXISTING;
+ }
+
+ if (flags & kSbFileOpenOnly) {
+ SB_DCHECK(!(flags & kSbFileOpenAlways));
+ creation_disposition = OPEN_EXISTING;
+ }
+
+ if (flags & kSbFileOpenAlways) {
+ SB_DCHECK(!(flags & kSbFileOpenOnly));
+ creation_disposition = OPEN_ALWAYS;
+ }
+
+ if (!creation_disposition && !(flags & kSbFileOpenOnly) &&
+ !(flags & kSbFileOpenAlways)) {
+ SB_NOTREACHED();
+ errno = ENOTSUP;
+ if (out_error) {
+ *out_error = kSbFileErrorFailed;
+ }
+
+ return kSbFileInvalid;
+ }
+
+ DWORD desired_access = 0;
+ if (flags & kSbFileRead) {
+ desired_access |= GENERIC_READ;
+ }
+
+ const bool open_file_in_write_mode = flags & kSbFileWrite;
+ if (open_file_in_write_mode) {
+ desired_access |= GENERIC_WRITE;
+ }
+
+ // TODO: Support asynchronous IO, if necessary.
+ SB_DCHECK(!(flags & kSbFileAsync));
+
+ SB_DCHECK(desired_access != 0) << "Invalid permission flag.";
+
+ std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+
+ CREATEFILE2_EXTENDED_PARAMETERS create_ex_params = {0};
+ // Enabling |FILE_FLAG_BACKUP_SEMANTICS| allows us to figure out if the path
+ // is a directory.
+ create_ex_params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
+ create_ex_params.dwFileFlags |= FILE_FLAG_POSIX_SEMANTICS;
+ create_ex_params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+ create_ex_params.dwSecurityQosFlags = SECURITY_ANONYMOUS;
+ create_ex_params.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
+
+ HANDLE file_handle =
+ CreateFile2(path_wstring.c_str(), desired_access, share_mode,
+ creation_disposition, &create_ex_params);
+
+ if (out_created) {
+ if (flags & (kSbFileCreateAlways | kSbFileCreateOnly)) {
+ *out_created = starboard::shared::win32::IsValidHandle(file_handle);
+ }
+
+ if ((creation_disposition == OPEN_ALWAYS) && (open_file_in_write_mode)) {
+ *out_created = (GetLastError() != ERROR_ALREADY_EXISTS);
+ }
+ }
+
+ if (out_error) {
+ if (starboard::shared::win32::IsValidHandle(file_handle)) {
+ *out_error = kSbFileOk;
+ } else {
+ const DWORD last_error = GetLastError();
+ switch (last_error) {
+ case ERROR_ACCESS_DENIED:
+ *out_error = kSbFileErrorAccessDenied;
+ break;
+ case ERROR_FILE_EXISTS:
+ *out_error = kSbFileErrorAccessDenied;
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ *out_error = kSbFileErrorNotFound;
+ break;
+ default:
+ *out_error = kSbFileErrorFailed;
+ }
+ }
+ }
+
+ return file_handle;
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/win32/file_internal.h b/src/starboard/shared/win32/file_internal.h
new file mode 100644
index 0000000..56a8a13
--- /dev/null
+++ b/src/starboard/shared/win32/file_internal.h
@@ -0,0 +1,94 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_WIN32_FILE_INTERNAL_H_
+#define STARBOARD_SHARED_WIN32_FILE_INTERNAL_H_
+
+#include <wtypes.h>
+
+#include <cwchar> // This file included for std::wcslen.
+#include <string>
+
+#include "starboard/file.h"
+#include "starboard/shared/internal_only.h"
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+inline bool IsValidHandle(HANDLE handle) {
+ return handle != INVALID_HANDLE_VALUE;
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+#pragma warning(push)
+
+// SbFilePrivate is defined as a struct, but for windows implementation
+// enough functionality has been added so that it warrants being a class
+// per Google's C++ style guide. This mismatch causes the Microsoft's compiler
+// to generate a warning.
+#pragma warning(disable : 4099)
+
+class SbFilePrivate {
+ public:
+ explicit SbFilePrivate(HANDLE handle) : file_handle(handle) {}
+
+ bool HasValidHandle() const {
+ return starboard::shared::win32::IsValidHandle(file_handle);
+ }
+
+ HANDLE file_handle;
+
+ // SbFilePrivate is neither copyable nor movable.
+ SbFilePrivate(const SbFilePrivate&) = delete;
+ SbFilePrivate& operator=(const SbFilePrivate&) = delete;
+};
+#pragma warning(pop)
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+inline bool HasValidHandle(SbFile file) {
+ if (!SbFileIsValid(file)) {
+ return false;
+ }
+
+ return file->HasValidHandle();
+}
+
+inline bool PathEndsWith(const std::wstring& path, const wchar_t* filename) {
+ size_t filename_length = std::wcslen(filename);
+ if (filename_length > path.size()) {
+ return false;
+ }
+
+ size_t path_offset = path.size() - filename_length;
+
+ return wcscmp(path.c_str() + path_offset, filename) == 0;
+}
+
+HANDLE OpenFileOrDirectory(const char* path,
+ int flags,
+ bool* out_created,
+ SbFileError* out_error);
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_WIN32_FILE_INTERNAL_H_
diff --git a/src/starboard/shared/win32/file_open.cc b/src/starboard/shared/win32/file_open.cc
new file mode 100644
index 0000000..78407c5
--- /dev/null
+++ b/src/starboard/shared/win32/file_open.cc
@@ -0,0 +1,41 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include "starboard/shared/win32/file_internal.h"
+
+SbFile SbFileOpen(const char* path,
+ int flags,
+ bool* out_created,
+ SbFileError* out_error) {
+ if ((path == nullptr) || (path[0] == '\0')) {
+ if (out_created) {
+ *out_created = false;
+ }
+ if (out_error) {
+ *out_error = kSbFileErrorNotAFile;
+ }
+ return kSbFileInvalid;
+ }
+
+ HANDLE file_handle =
+ starboard::shared::win32::OpenFileOrDirectory(path, flags, out_created, out_error);
+
+ if (!starboard::shared::win32::IsValidHandle(file_handle)) {
+ return kSbFileInvalid;
+ }
+
+ return new SbFilePrivate(file_handle);
+}
diff --git a/src/starboard/shared/win32/file_read.cc b/src/starboard/shared/win32/file_read.cc
new file mode 100644
index 0000000..b2e6db8
--- /dev/null
+++ b/src/starboard/shared/win32/file_read.cc
@@ -0,0 +1,47 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include <windows.h>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/file_internal.h"
+
+int SbFileRead(SbFile file, char* data, int size) {
+ SB_DCHECK((size == 0) || (data != nullptr));
+
+ if (!starboard::shared::win32::HasValidHandle(file)) {
+ return -1;
+ }
+
+ if (size < 0) {
+ SB_NOTREACHED();
+ return -1;
+ } else if (size == 0) {
+ return 0;
+ }
+
+ DWORD number_bytes_read = 0;
+ BOOL success =
+ ReadFile(file->file_handle, data, size, &number_bytes_read, nullptr);
+
+ // Since we are only doing synchornous IO, success == FALSE implies that
+ // something is wrong.
+ if (!success) {
+ return -1;
+ }
+
+ return number_bytes_read;
+}
diff --git a/src/starboard/shared/win32/file_seek.cc b/src/starboard/shared/win32/file_seek.cc
new file mode 100644
index 0000000..54f56fa
--- /dev/null
+++ b/src/starboard/shared/win32/file_seek.cc
@@ -0,0 +1,38 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include <windows.h>
+
+#include "starboard/shared/win32/file_internal.h"
+
+int64_t SbFileSeek(SbFile file, SbFileWhence whence, int64_t offset) {
+ if (!starboard::shared::win32::HasValidHandle(file)) {
+ return -1;
+ }
+
+ LARGE_INTEGER new_file_pointer = {0};
+ LARGE_INTEGER offset_argument = {0};
+ offset_argument.QuadPart = offset;
+ BOOL success =
+ SetFilePointerEx(file->file_handle, offset_argument, &new_file_pointer,
+ static_cast<DWORD>(whence));
+
+ if (!success) {
+ return -1;
+ }
+
+ return new_file_pointer.QuadPart;
+}
diff --git a/src/starboard/shared/win32/file_truncate.cc b/src/starboard/shared/win32/file_truncate.cc
new file mode 100644
index 0000000..dd2626b
--- /dev/null
+++ b/src/starboard/shared/win32/file_truncate.cc
@@ -0,0 +1,102 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include <windows.h>
+
+#include <algorithm>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/file_internal.h"
+
+namespace {
+static const char k4KZeroPage[4 * 1024] = {0};
+
+bool WriteZerosToFile(HANDLE file_handle,
+ LARGE_INTEGER begin,
+ LARGE_INTEGER end) {
+ SB_DCHECK(starboard::shared::win32::IsValidHandle(file_handle));
+ int64_t bytes_left_to_write = end.QuadPart - begin.QuadPart;
+ if (bytes_left_to_write <= 0) {
+ return true;
+ }
+
+ // Set the file pointer to |begin|.
+ if (!SetFilePointerEx(file_handle, begin, NULL, FILE_BEGIN)) {
+ return false;
+ }
+
+ // Write from zeros from |begin| to |end|.
+ while (bytes_left_to_write > 0) {
+ int64_t bytes_to_write =
+ std::min<int64_t>(SB_ARRAY_SIZE(k4KZeroPage), bytes_left_to_write);
+ SB_DCHECK(bytes_to_write <= kSbInt32Max);
+
+ DWORD bytes_written = 0;
+ if (!WriteFile(file_handle, k4KZeroPage, static_cast<int>(bytes_to_write),
+ &bytes_written, NULL)) {
+ return false;
+ }
+
+ bytes_left_to_write -= bytes_written;
+ }
+
+ return true;
+}
+
+} // namespace
+
+bool SbFileTruncate(SbFile file, int64_t length) {
+ if (!starboard::shared::win32::HasValidHandle(file) || length < 0) {
+ return false;
+ }
+
+ HANDLE file_handle = file->file_handle;
+
+ // Get current position.
+ LARGE_INTEGER current_position = {0};
+ BOOL success =
+ SetFilePointerEx(file_handle, {0}, ¤t_position, FILE_CURRENT);
+
+ if (!success) {
+ return false;
+ }
+
+ bool return_value = false;
+ do {
+ LARGE_INTEGER old_eof = {0};
+ if (!SetFilePointerEx(file_handle, {0}, &old_eof, FILE_END)) {
+ break;
+ }
+
+ LARGE_INTEGER new_eof = {0};
+ new_eof.QuadPart = length;
+ if (!SetFilePointerEx(file_handle, new_eof, NULL, FILE_BEGIN)) {
+ break;
+ }
+
+ if (!SetEndOfFile(file_handle)) {
+ break;
+ }
+
+ WriteZerosToFile(file_handle, old_eof, new_eof);
+ return_value = true;
+ } while (0);
+
+ // Set the file pointer position back where it was.
+ SetFilePointerEx(file_handle, current_position, NULL, FILE_BEGIN);
+
+ return return_value;
+}
diff --git a/src/starboard/shared/win32/file_write.cc b/src/starboard/shared/win32/file_write.cc
new file mode 100644
index 0000000..d63bf68
--- /dev/null
+++ b/src/starboard/shared/win32/file_write.cc
@@ -0,0 +1,42 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/file.h"
+
+#include <windows.h>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/file_internal.h"
+
+int SbFileWrite(SbFile file, const char* data, int size) {
+ // TODO: Support asynchronous IO, if necessary.
+ SB_DCHECK((size == 0) || (data != nullptr));
+ if (!SbFileIsValid(file)) {
+ return -1;
+ }
+ if (size < 0) {
+ SB_NOTREACHED();
+ return -1;
+ } else if (size == 0) {
+ return 0;
+ }
+
+ DWORD bytes_written = 0;
+ bool success = WriteFile(file->file_handle, data, size, &bytes_written, NULL);
+ if (!success) {
+ return -1;
+ }
+
+ return bytes_written;
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/log.cc
similarity index 76%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/log.cc
index 4723bfb..7e1cb85 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/log.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/log.h"
-#include <cmath>
-
-#endif // COBALT_BASE_MATH_H_
+void SbLog(SbLogPriority /*priority*/, const char* message) {
+ SbLogRaw(message);
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/log_flush.cc
similarity index 77%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/log_flush.cc
index 4723bfb..a75af43 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/log_flush.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/log.h"
-#include <cmath>
+#include <stdio.h>
-#endif // COBALT_BASE_MATH_H_
+void SbLogFlush() {
+ fflush(stderr);
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/log_format.cc
similarity index 75%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/log_format.cc
index 4723bfb..ef5430b 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/log_format.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/log.h"
-#include <cmath>
-
-#endif // COBALT_BASE_MATH_H_
+void SbLogFormat(const char* format, va_list arguments) {
+ SbLogRawFormat(format, arguments);
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/log_is_tty.cc
similarity index 77%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/log_is_tty.cc
index 4723bfb..40dbc77 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/log_is_tty.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/log.h"
-#include <cmath>
-
-#endif // COBALT_BASE_MATH_H_
+bool SbLogIsTty() {
+ return false;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/log_raw.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/log_raw.cc
index 51e1f2e..d33f086 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/log_raw.cc
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/log.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <stdio.h>
+#include <windows.h>
+
+void SbLogRaw(const char* message) {
+ fprintf(stderr, "%s", message);
+ OutputDebugStringA(message);
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/log_raw_dump_stack.cc
similarity index 75%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/log_raw_dump_stack.cc
index 4723bfb..142a056 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/log_raw_dump_stack.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/log.h"
-#include <cmath>
-
-#endif // COBALT_BASE_MATH_H_
+void SbLogRawDumpStack(int /*frames_to_skip*/) {
+ SbLogRaw("TODO stack dump not implemented\n");
+}
diff --git a/src/starboard/shared/win32/log_raw_format.cc b/src/starboard/shared/win32/log_raw_format.cc
new file mode 100644
index 0000000..5b6c59e
--- /dev/null
+++ b/src/starboard/shared/win32/log_raw_format.cc
@@ -0,0 +1,31 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/log.h"
+
+#include <stdio.h>
+#include <windows.h>
+
+static const int kMaxLogLineChars = 16 * 1024;
+
+void SbLogRawFormat(const char* format, va_list arguments) {
+ vfprintf(stderr, format, arguments);
+ char log_buffer[kMaxLogLineChars];
+ int result = vsprintf_s(log_buffer, kMaxLogLineChars, format, arguments);
+ if (result >= 0) {
+ OutputDebugStringA(log_buffer);
+ } else {
+ OutputDebugStringA("[log line too long]");
+ }
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/memory_allocate_aligned_unchecked.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/memory_allocate_aligned_unchecked.cc
index 51e1f2e..0b161fb 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/memory_allocate_aligned_unchecked.cc
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/memory.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <malloc.h>
+
+void* SbMemoryAllocateAlignedUnchecked(size_t alignment, size_t size) {
+ return _aligned_malloc(size, alignment);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/memory_allocate_unchecked.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/memory_allocate_unchecked.cc
index 51e1f2e..c185f91 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/memory_allocate_unchecked.cc
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/memory.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+void* SbMemoryAllocateUnchecked(size_t size) {
+ return HeapAlloc(GetProcessHeap(), 0, size);
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/memory_free.cc
similarity index 75%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/memory_free.cc
index 4723bfb..42b83fc 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/memory_free.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/memory.h"
-#include <cmath>
+#include <windows.h>
-#endif // COBALT_BASE_MATH_H_
+void SbMemoryFree(void* memory) {
+ HeapFree(GetProcessHeap(), 0, memory);
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/memory_free_aligned.cc
similarity index 76%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/memory_free_aligned.cc
index 4723bfb..f40d0c6 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/memory_free_aligned.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/memory.h"
-#include <cmath>
+#include <malloc.h>
-#endif // COBALT_BASE_MATH_H_
+void SbMemoryFreeAligned(void* memory) {
+ _aligned_free(memory);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/memory_get_stack_bounds.cc
similarity index 66%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/memory_get_stack_bounds.cc
index 51e1f2e..5a92b61 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/memory_get_stack_bounds.cc
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/memory.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include "starboard/log.h"
+
+void SbMemoryGetStackBounds(void** /*out_high*/, void** /*out_low*/) {
+ // TODO the common way to do this is with NtQueryInformationThread
+ // for ThreadBasicInformation but that may not be available on UWP.
+ SB_NOTIMPLEMENTED();
+}
diff --git a/src/starboard/shared/win32/memory_map.cc b/src/starboard/shared/win32/memory_map.cc
new file mode 100644
index 0000000..8ec19f5
--- /dev/null
+++ b/src/starboard/shared/win32/memory_map.cc
@@ -0,0 +1,38 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/memory.h"
+
+#include <windows.h>
+
+#include "starboard/log.h"
+
+void* SbMemoryMap(int64_t size_bytes, int flags, const char* name) {
+ if (size_bytes == 0) {
+ return SB_MEMORY_MAP_FAILED;
+ }
+ ULONG protect;
+ // |flags| is a bitmask of SbMemoryMapFlags, but |protect| is not a bitmask.
+ switch (flags) {
+ case kSbMemoryMapProtectRead:
+ protect = PAGE_READONLY;
+ break;
+ case kSbMemoryMapProtectReadWrite:
+ protect = PAGE_READWRITE;
+ break;
+ default:
+ SB_NOTREACHED();
+ }
+ return VirtualAllocFromApp(NULL, size_bytes, MEM_COMMIT, protect);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/memory_reallocate_unchecked.cc
similarity index 70%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/memory_reallocate_unchecked.cc
index 51e1f2e..68ee689 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/memory_reallocate_unchecked.cc
@@ -12,9 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/memory.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+void* SbMemoryReallocateUnchecked(void* memory, size_t size) {
+ if (memory == NULL) {
+ return SbMemoryAllocateUnchecked(size);
+ }
+ return HeapReAlloc(GetProcessHeap(), 0, memory, size);
+}
diff --git a/src/starboard/shared/win32/memory_unmap.cc b/src/starboard/shared/win32/memory_unmap.cc
new file mode 100644
index 0000000..970fc9f
--- /dev/null
+++ b/src/starboard/shared/win32/memory_unmap.cc
@@ -0,0 +1,24 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/memory.h"
+
+#include <windows.h>
+
+bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes) {
+ // Note that SbMemoryUnmap documentation says that "This function can
+ // unmap multiple contiguous regions that were mapped with separate calls
+ // to SbMemoryMap()". Because of that, we cannot use MEM_FREE here.
+ return VirtualFree(virtual_address, size_bytes, MEM_DECOMMIT);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/mutex_acquire.cc
similarity index 74%
rename from src/cobalt/dom/media_key_system_media_capability.idl
rename to src/starboard/shared/win32/mutex_acquire.cc
index 51e1f2e..daca05d 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/mutex_acquire.cc
@@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/mutex.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+SbMutexResult SbMutexAcquire(SbMutex* mutex) {
+ AcquireSRWLockExclusive(reinterpret_cast<PSRWLOCK>(mutex));
+ return kSbMutexAcquired;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/mutex_acquire_try.cc
similarity index 71%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/mutex_acquire_try.cc
index 51e1f2e..0c4cee2 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/mutex_acquire_try.cc
@@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/mutex.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+SbMutexResult SbMutexAcquireTry(SbMutex* mutex) {
+ bool result = TryAcquireSRWLockExclusive(reinterpret_cast<PSRWLOCK>(mutex));
+ return result ? kSbMutexAcquired : kSbMutexBusy;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/mutex_create.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/mutex_create.cc
index 51e1f2e..5e4c1ce 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/mutex_create.cc
@@ -12,9 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/mutex.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+bool SbMutexCreate(SbMutex* mutex) {
+ if (!mutex) {
+ return false;
+ }
+ InitializeSRWLock(reinterpret_cast<PSRWLOCK>(mutex));
+ return true;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/mutex_destroy.cc
similarity index 73%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/mutex_destroy.cc
index 51e1f2e..1028687 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/mutex_destroy.cc
@@ -12,9 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/mutex.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+bool SbMutexDestroy(SbMutex* mutex) {
+ if (!mutex) {
+ return false;
+ }
+ if (SbMutexAcquireTry(mutex) == kSbMutexBusy) {
+ return false;
+ }
+ return true;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/mutex_release.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/mutex_release.cc
index 51e1f2e..ac50090 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/mutex_release.cc
@@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/mutex.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+bool SbMutexRelease(SbMutex* mutex) {
+ ReleaseSRWLockExclusive(reinterpret_cast<PSRWLOCK>(mutex));
+ return true;
+}
diff --git a/src/starboard/shared/win32/once.cc b/src/starboard/shared/win32/once.cc
new file mode 100644
index 0000000..2a31d3a
--- /dev/null
+++ b/src/starboard/shared/win32/once.cc
@@ -0,0 +1,35 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/once.h"
+
+#include <windows.h>
+
+namespace {
+BOOL CALLBACK OnceTrampoline(PINIT_ONCE once_control,
+ void* parameter,
+ void** context) {
+ static_cast<SbOnceInitRoutine>(parameter)();
+ return true;
+}
+
+} // namespace
+
+bool SbOnce(SbOnceControl* once_control, SbOnceInitRoutine init_routine) {
+ if (!once_control || !init_routine) {
+ return false;
+ }
+ return InitOnceExecuteOnce(reinterpret_cast<PINIT_ONCE>(once_control),
+ OnceTrampoline, init_routine, NULL);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/string_compare_no_case.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/string_compare_no_case.cc
index 51e1f2e..39a9f2b 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/string_compare_no_case.cc
@@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/string.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <string.h>
+
+int SbStringCompareNoCase(const char* string1, const char* string2) {
+ return _stricmp(string1, string2);
+}
+
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/string_compare_no_case_n.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/string_compare_no_case_n.cc
index 51e1f2e..cca7b9d 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/string_compare_no_case_n.cc
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/string.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <string.h>
+
+int SbStringCompareNoCaseN(const char* string1,
+ const char* string2, size_t count) {
+ return _strnicmp(string1, string2, count);
+}
+
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/string_compare_wide.cc
similarity index 73%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/string_compare_wide.cc
index 51e1f2e..876d5b7 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/string_compare_wide.cc
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/string.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <string.h>
+
+int SbStringCompareWide(const wchar_t* string1, const wchar_t* string2,
+ size_t count) {
+ return wcsncmp(string1, string2, count);
+}
+
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/string_format.cc
similarity index 68%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/string_format.cc
index 51e1f2e..1239718 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/string_format.cc
@@ -12,9 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/string.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <stdio.h>
+
+int SbStringFormat(char* out_buffer,
+ size_t buffer_size,
+ const char* format,
+ va_list arguments) {
+ return vsnprintf(out_buffer, buffer_size, format, arguments);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/string_format_wide.cc
similarity index 66%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/string_format_wide.cc
index 51e1f2e..29258dc 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/string_format_wide.cc
@@ -12,9 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/string.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <stdio.h>
+
+int SbStringFormatWide(wchar_t* out_buffer,
+ size_t buffer_size,
+ const wchar_t* format,
+ va_list arguments) {
+ return _vsnwprintf(out_buffer, buffer_size, format, arguments);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/system_break_into_debugger.cc
similarity index 74%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/system_break_into_debugger.cc
index 51e1f2e..121d052 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/system_break_into_debugger.cc
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/system.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+void SbSystemBreakIntoDebugger() {
+ // TODO: neither of these may be valid on some platforms.
+ DebugBreak();
+ ExitProcess(1);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/system_get_random_uint64.cc
similarity index 61%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/system_get_random_uint64.cc
index 51e1f2e..632c39d 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/system_get_random_uint64.cc
@@ -12,9 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/system.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+#include "starboard/log.h"
+#include "starboard/time.h"
+
+uint64_t SbSystemGetRandomUInt64() {
+ // TODO: This is DEFINITELY not cryptographically secure.
+ static bool initialized = false;
+ if (!initialized) {
+ srand(GetTickCount());
+ initialized = true;
+ }
+ return (static_cast<uint64_t>(std::rand()) << 32) | rand();
+}
diff --git a/src/starboard/shared/win32/thread_create.cc b/src/starboard/shared/win32/thread_create.cc
new file mode 100644
index 0000000..5220aad
--- /dev/null
+++ b/src/starboard/shared/win32/thread_create.cc
@@ -0,0 +1,119 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/thread.h"
+
+#include <process.h>
+#include <memory>
+
+#include "starboard/log.h"
+#include "starboard/once.h"
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::GetThreadSubsystemSingleton;
+using starboard::shared::win32::SbThreadPrivate;
+using starboard::shared::win32::ThreadSubsystemSingleton;
+
+namespace {
+
+class ThreadCreateInfo {
+ public:
+ SbThreadPrivate thread_private_;
+ SbThreadEntryPoint entry_point_;
+ void* user_context_;
+ std::string name_;
+};
+
+void CallThreadLocalDestructors() {
+ ThreadSubsystemSingleton* singleton = GetThreadSubsystemSingleton();
+
+ // TODO note that the implementation below holds a global lock
+ // while processing TLS destructors on thread exit. This could
+ // be a bottleneck in some scenarios. A lockless approach may be preferrable.
+ SbMutexAcquire(&singleton->mutex_);
+ for (auto it = singleton->thread_local_keys_.begin();
+ it != singleton->thread_local_keys_.end(); ++it) {
+ if (!it->second->destructor) {
+ continue;
+ }
+ void* entry = SbThreadGetLocalValue(it->second);
+ if (!entry) {
+ continue;
+ }
+ it->second->destructor(entry);
+ }
+ SbMutexRelease(&singleton->mutex_);
+}
+
+unsigned ThreadTrampoline(void* thread_create_info_context) {
+ std::unique_ptr<ThreadCreateInfo> info(
+ static_cast<ThreadCreateInfo*>(thread_create_info_context));
+
+ ThreadSubsystemSingleton* singleton = GetThreadSubsystemSingleton();
+
+ SbThreadSetLocalValue(singleton->thread_private_key_, &info->thread_private_);
+
+ SbThreadSetName(info->name_.c_str());
+
+ void* result = info->entry_point_(info->user_context_);
+
+ CallThreadLocalDestructors();
+
+ SbMutexAcquire(&info->thread_private_.mutex_);
+ info->thread_private_.result_ = result;
+ info->thread_private_.result_is_valid_ = true;
+ SbConditionVariableSignal(&info->thread_private_.condition_);
+ while (info->thread_private_.wait_for_join_) {
+ SbConditionVariableWait(&info->thread_private_.condition_,
+ &info->thread_private_.mutex_);
+ }
+ SbMutexRelease(&info->thread_private_.mutex_);
+
+ return 0;
+}
+
+} // namespace
+
+SbThread SbThreadCreate(int64_t stack_size,
+ SbThreadPriority /*priority*/,
+ SbThreadAffinity /*affinity*/,
+ bool joinable,
+ const char* name,
+ SbThreadEntryPoint entry_point,
+ void* context) {
+ if (entry_point == NULL) {
+ return kSbThreadInvalid;
+ }
+ ThreadCreateInfo* info = new ThreadCreateInfo();
+
+ info->entry_point_ = entry_point;
+ info->user_context_ = context;
+ info->thread_private_.wait_for_join_ = joinable;
+ if (name) {
+ info->name_ = name;
+ }
+
+ // Create the thread suspended, and then resume once ThreadCreateInfo::handle_
+ // has been set, so that it's alway valid in the ThreadCreateInfo
+ // destructor.
+ uintptr_t handle =
+ _beginthreadex(NULL, static_cast<unsigned int>(stack_size),
+ ThreadTrampoline, info, CREATE_SUSPENDED, NULL);
+
+ info->thread_private_.handle_ = reinterpret_cast<HANDLE>(handle);
+
+ ResumeThread(info->thread_private_.handle_);
+
+ return &info->thread_private_;
+}
diff --git a/src/starboard/shared/win32/thread_create_local_key.cc b/src/starboard/shared/win32/thread_create_local_key.cc
new file mode 100644
index 0000000..7f786ab
--- /dev/null
+++ b/src/starboard/shared/win32/thread_create_local_key.cc
@@ -0,0 +1,62 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/thread.h"
+
+#include <windows.h>
+
+#include "starboard/memory.h"
+#include "starboard/mutex.h"
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::GetThreadSubsystemSingleton;
+using starboard::shared::win32::ThreadSubsystemSingleton;
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+SbThreadLocalKey SbThreadCreateLocalKeyInternal(
+ SbThreadLocalDestructor destructor,
+ ThreadSubsystemSingleton* singleton) {
+ DWORD index = TlsAlloc();
+
+ if (index == TLS_OUT_OF_INDEXES) {
+ return kSbThreadLocalKeyInvalid;
+ }
+
+ SbThreadLocalKeyPrivate* result = static_cast<SbThreadLocalKeyPrivate*>(
+ SbMemoryAllocateNoReport(sizeof(SbThreadLocalKeyPrivate)));
+
+ if (result == nullptr) {
+ return kSbThreadLocalKeyInvalid;
+ }
+
+ result->tls_index = index;
+ result->destructor = destructor;
+
+ SbMutexAcquire(&singleton->mutex_);
+ singleton->thread_local_keys_.insert(std::make_pair(index, result));
+ SbMutexRelease(&singleton->mutex_);
+ return result;
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+SbThreadLocalKey SbThreadCreateLocalKey(SbThreadLocalDestructor destructor) {
+ ThreadSubsystemSingleton* singleton = GetThreadSubsystemSingleton();
+ return SbThreadCreateLocalKeyInternal(destructor, singleton);
+}
diff --git a/src/starboard/shared/win32/thread_destroy_local_key.cc b/src/starboard/shared/win32/thread_destroy_local_key.cc
new file mode 100644
index 0000000..201fc75
--- /dev/null
+++ b/src/starboard/shared/win32/thread_destroy_local_key.cc
@@ -0,0 +1,38 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/thread.h"
+
+#include <windows.h>
+
+#include "starboard/memory.h"
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::GetThreadSubsystemSingleton;
+using starboard::shared::win32::ThreadSubsystemSingleton;
+
+void SbThreadDestroyLocalKey(SbThreadLocalKey key) {
+ if (!SbThreadIsValidLocalKey(key)) {
+ return;
+ }
+ DWORD tls_index = static_cast<SbThreadLocalKeyPrivate*>(key)->tls_index;
+ ThreadSubsystemSingleton* singleton = GetThreadSubsystemSingleton();
+
+ SbMutexAcquire(&singleton->mutex_);
+ singleton->thread_local_keys_.erase(tls_index);
+ SbMutexRelease(&singleton->mutex_);
+
+ TlsFree(tls_index);
+ SbMemoryDeallocateNoReport(key);
+}
diff --git a/src/starboard/shared/win32/thread_detach.cc b/src/starboard/shared/win32/thread_detach.cc
new file mode 100644
index 0000000..422a12d
--- /dev/null
+++ b/src/starboard/shared/win32/thread_detach.cc
@@ -0,0 +1,33 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/thread.h"
+
+#include "starboard/condition_variable.h"
+#include "starboard/mutex.h"
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::SbThreadPrivate;
+
+void SbThreadDetach(SbThread thread) {
+ if (thread == kSbThreadInvalid) {
+ return;
+ }
+ SbThreadPrivate* thread_private = static_cast<SbThreadPrivate*>(thread);
+
+ SbMutexAcquire(&thread_private->mutex_);
+ thread_private->wait_for_join_ = false;
+ SbConditionVariableSignal(&thread_private->condition_);
+ SbMutexRelease(&thread_private->mutex_);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/thread_get_current.cc
similarity index 69%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/thread_get_current.cc
index 51e1f2e..12ba544 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/thread_get_current.cc
@@ -12,9 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/thread.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::GetCurrentSbThreadPrivate;
+using starboard::shared::win32::SbThreadPrivate;
+
+SbThread SbThreadGetCurrent() {
+ return GetCurrentSbThreadPrivate();
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/thread_get_id.cc
similarity index 76%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/thread_get_id.cc
index 4723bfb..b6a7293 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/thread_get_id.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/thread.h"
-#include <cmath>
+#include <windows.h>
-#endif // COBALT_BASE_MATH_H_
+SbThreadId SbThreadGetId() {
+ return GetCurrentThreadId();
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/thread_get_local_value.cc
similarity index 64%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/thread_get_local_value.cc
index 51e1f2e..64603b6 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/thread_get_local_value.cc
@@ -12,9 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/thread.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+#include "starboard/shared/win32/thread_private.h"
+
+void* SbThreadGetLocalValue(SbThreadLocalKey key) {
+ if (!SbThreadIsValidLocalKey(key)) {
+ return NULL;
+ }
+ DWORD tls_index = static_cast<SbThreadLocalKeyPrivate*>(key)->tls_index;
+ return TlsGetValue(tls_index);
+}
diff --git a/src/starboard/shared/win32/thread_get_name.cc b/src/starboard/shared/win32/thread_get_name.cc
new file mode 100644
index 0000000..a3dd3d7
--- /dev/null
+++ b/src/starboard/shared/win32/thread_get_name.cc
@@ -0,0 +1,28 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/thread.h"
+
+#include <windows.h>
+
+#include "starboard/string.h"
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::GetCurrentSbThreadPrivate;
+using starboard::shared::win32::SbThreadPrivate;
+
+void SbThreadGetName(char* buffer, int buffer_size) {
+ SbThreadPrivate* thread_private = GetCurrentSbThreadPrivate();
+ SbStringCopy(buffer, thread_private->name_.c_str(), buffer_size);
+}
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/thread_is_equal.cc
similarity index 75%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/thread_is_equal.cc
index 4723bfb..ccc2d64 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/thread_is_equal.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/thread.h"
-#include <cmath>
-
-#endif // COBALT_BASE_MATH_H_
+bool SbThreadIsEqual(SbThread thread1, SbThread thread2) {
+ return thread1 == thread2;
+}
diff --git a/src/starboard/shared/win32/thread_join.cc b/src/starboard/shared/win32/thread_join.cc
new file mode 100644
index 0000000..44e1589
--- /dev/null
+++ b/src/starboard/shared/win32/thread_join.cc
@@ -0,0 +1,47 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/thread.h"
+
+#include "starboard/condition_variable.h"
+#include "starboard/mutex.h"
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::SbThreadPrivate;
+
+bool SbThreadJoin(SbThread thread, void** out_return) {
+ if (thread == kSbThreadInvalid) {
+ return false;
+ }
+
+ SbThreadPrivate* thread_private = static_cast<SbThreadPrivate*>(thread);
+
+ SbMutexAcquire(&thread_private->mutex_);
+ if (!thread_private->wait_for_join_) {
+ // Thread has already been detached.
+ SbMutexRelease(&thread_private->mutex_);
+ return false;
+ }
+ while (!thread_private->result_is_valid_) {
+ SbConditionVariableWait(&thread_private->condition_,
+ &thread_private->mutex_);
+ }
+ thread_private->wait_for_join_ = false;
+ SbConditionVariableSignal(&thread_private->condition_);
+ if (out_return != NULL) {
+ *out_return = thread_private->result_;
+ }
+ SbMutexRelease(&thread_private->mutex_);
+ return true;
+}
diff --git a/src/starboard/shared/win32/thread_private.cc b/src/starboard/shared/win32/thread_private.cc
new file mode 100644
index 0000000..e0ee6b1
--- /dev/null
+++ b/src/starboard/shared/win32/thread_private.cc
@@ -0,0 +1,61 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/thread.h"
+
+#include <process.h>
+#include <memory>
+
+#include "starboard/log.h"
+#include "starboard/once.h"
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::GetThreadSubsystemSingleton;
+using starboard::shared::win32::SbThreadPrivate;
+using starboard::shared::win32::ThreadSubsystemSingleton;
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+SB_ONCE_INITIALIZE_FUNCTION(ThreadSubsystemSingleton,
+ GetThreadSubsystemSingleton);
+
+void RegisterMainThread() {
+ std::unique_ptr<SbThreadPrivate> thread_private(new SbThreadPrivate());
+
+ // GetCurrentThread() returns a pseudo-handle that must be duplicated
+ // to be used in general cases.
+ HANDLE pseudo_handle = GetCurrentThread();
+ HANDLE handle;
+ BOOL success =
+ DuplicateHandle(GetCurrentProcess(), pseudo_handle, GetCurrentProcess(),
+ &handle, 0, false, DUPLICATE_SAME_ACCESS);
+ SB_DCHECK(success) << "DuplicateHandle failed";
+
+ thread_private->handle_ = handle;
+ thread_private->wait_for_join_ = false;
+
+ SbThreadSetLocalValue(GetThreadSubsystemSingleton()->thread_private_key_,
+ thread_private.release());
+}
+
+SbThreadPrivate* GetCurrentSbThreadPrivate() {
+ return static_cast<SbThreadPrivate*>(SbThreadGetLocalValue(
+ GetThreadSubsystemSingleton()->thread_private_key_));
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/win32/thread_private.h b/src/starboard/shared/win32/thread_private.h
new file mode 100644
index 0000000..4bacbd8
--- /dev/null
+++ b/src/starboard/shared/win32/thread_private.h
@@ -0,0 +1,109 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_WIN32_THREAD_PRIVATE_H_
+#define STARBOARD_WIN32_THREAD_PRIVATE_H_
+
+#include <windows.h>
+#include <string>
+#include <unordered_map>
+
+#include "starboard/condition_variable.h"
+#include "starboard/mutex.h"
+#include "starboard/once.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/thread.h"
+
+struct SbThreadLocalKeyPrivate {
+ DWORD tls_index;
+ SbThreadLocalDestructor destructor;
+};
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+class ThreadSubsystemSingleton;
+
+// Creates a SbThreadLocalKey given a ThreadSubsystemSingleton. Used
+// to create the first SbThreadLocalKey.
+SbThreadLocalKey SbThreadCreateLocalKeyInternal(
+ SbThreadLocalDestructor destructor,
+ ThreadSubsystemSingleton* singleton);
+
+// Singleton state for the thread subsystem.
+class ThreadSubsystemSingleton {
+ public:
+ ThreadSubsystemSingleton()
+ : mutex_(SB_MUTEX_INITIALIZER),
+ thread_private_key_(SbThreadCreateLocalKeyInternal(NULL, this)) {}
+ // This mutex protects all class members
+ SbMutex mutex_;
+ // Allocated thread_local_keys
+ std::unordered_map<DWORD, SbThreadLocalKeyPrivate*> thread_local_keys_;
+ // Thread-local key for the thread's SbThreadPrivate
+ SbThreadLocalKey thread_private_key_;
+};
+
+// Obtains the ThreadsSubsystemSingleton();
+ThreadSubsystemSingleton* GetThreadSubsystemSingleton();
+
+// Registers the main thread. setting it's SbThreadPrivate*
+void RegisterMainThread();
+
+// Private thread state, stored in thread local storage and
+// cleaned up when thread exits.
+class SbThreadPrivate {
+ public:
+ SbThreadPrivate()
+ : mutex_(SB_MUTEX_INITIALIZER),
+ condition_(SB_CONDITION_VARIABLE_INITIALIZER),
+ handle_(NULL),
+ result_(NULL),
+ wait_for_join_(false),
+ result_is_valid_(false) {}
+
+ ~SbThreadPrivate() {
+ if (handle_) {
+ CloseHandle(handle_);
+ }
+
+ SbMutexDestroy(&mutex_);
+ SbConditionVariableDestroy(&condition_);
+ }
+
+ // This mutex protects all class members
+ SbMutex mutex_;
+ SbConditionVariable condition_;
+ std::string name_;
+ HANDLE handle_;
+ // The result of the thread. The return value of SbThreadEntryPoint
+ // to return to SbThreadJoin.
+ void* result_;
+ // True if a thread must wait to be joined before completely exiting.
+ // Changes to this must signal |condition_|.
+ bool wait_for_join_;
+ // True if |result_| is valid (the thread has completed and is waiting
+ // to exit). Changes to this must signal |condition_|.
+ bool result_is_valid_;
+};
+
+// Obtains the current thread's SbThreadPrivate* from thread-local storage.
+SbThreadPrivate* GetCurrentSbThreadPrivate();
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_WIN32_THREAD_PRIVATE_H_
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/thread_set_local_value.cc
similarity index 63%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/thread_set_local_value.cc
index 51e1f2e..95a1840 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/thread_set_local_value.cc
@@ -12,9 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/thread.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+#include "starboard/shared/win32/thread_private.h"
+
+bool SbThreadSetLocalValue(SbThreadLocalKey key, void* value) {
+ if (!SbThreadIsValidLocalKey(key)) {
+ return false;
+ }
+ DWORD tls_index = static_cast<SbThreadLocalKeyPrivate*>(key)->tls_index;
+ return TlsSetValue(tls_index, value);
+}
diff --git a/src/starboard/shared/win32/thread_set_name.cc b/src/starboard/shared/win32/thread_set_name.cc
new file mode 100644
index 0000000..aca4ad2
--- /dev/null
+++ b/src/starboard/shared/win32/thread_set_name.cc
@@ -0,0 +1,66 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/thread.h"
+
+#include <windows.h>
+
+#include "starboard/shared/win32/thread_private.h"
+
+using starboard::shared::win32::GetCurrentSbThreadPrivate;
+using starboard::shared::win32::SbThreadPrivate;
+
+namespace {
+
+// The code below is from
+// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+// A |dwThreadID| of -1 means "current thread";
+//
+// Usage: SetThreadName ((DWORD)-1, "MainThread");
+//
+const DWORD MS_VC_EXCEPTION = 0x406D1388;
+#pragma pack(push, 8)
+typedef struct tagTHREADNAME_INF {
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+void SetThreadName(DWORD dwThreadID, const char* threadName) {
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = threadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+#pragma warning(push)
+#pragma warning(disable : 6320 6322)
+ __try {
+ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
+ reinterpret_cast<ULONG_PTR*>(&info));
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ }
+#pragma warning(pop)
+}
+
+} // namespace
+
+void SbThreadSetName(const char* name) {
+ SbThreadPrivate* thread_private = GetCurrentSbThreadPrivate();
+
+ // We store the thread name in our own TLS context as well as telling
+ // the OS because it's much easier to retrieve from our own TLS context.
+ thread_private->name_ = name;
+ SetThreadName(-1, name);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/thread_sleep.cc
similarity index 67%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/thread_sleep.cc
index 51e1f2e..85c965d 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/thread_sleep.cc
@@ -12,9 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/thread.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+#include "starboard/shared/win32/time_utils.h"
+
+using starboard::shared::win32::ConvertSbTimeToMillisRoundUp;
+
+void SbThreadSleep(SbTime duration) {
+ if (duration < 0) {
+ return;
+ }
+ Sleep(ConvertSbTimeToMillisRoundUp(duration));
+}
diff --git a/src/starboard/shared/win32/thread_types_public.h b/src/starboard/shared/win32/thread_types_public.h
new file mode 100644
index 0000000..3443068
--- /dev/null
+++ b/src/starboard/shared/win32/thread_types_public.h
@@ -0,0 +1,63 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Includes threading primitive types and initializers.
+
+#ifndef STARBOARD_SHARED_WIN32_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_SHARED_WIN32_THREAD_TYPES_PUBLIC_H_
+
+// --- SbConditionVariable ---
+
+// Transparent Condition Variable handle.
+// Note: replica of RTL_CONDITION_VARIABLE in um/winnt.h to avoid include.
+typedef struct WindowsConditionVariable { void* ptr; } SbConditionVariable;
+
+// Condition Variable static initializer.
+// Note: replica of RTL_CONDITION_VARIABILE_INIT in um/winnt.h to avoid include.
+#define SB_CONDITION_VARIABLE_INITIALIZER \
+ { 0 }
+
+// --- SbMutex ---
+
+// Transparent Mutex handle.
+// Note SRWLock's are used for SbMutex because:
+// - Normal Windows CreateMutex() mutexes are very heavy-weight
+// - Critical sections do not have a static initializer
+// Note: replica of RTL_SRWLOCK in um/winnt.h to avoid include.
+typedef struct WindowsSrwLock { void* ptr; } SbMutex;
+
+// Mutex static initializer.
+// Note: replica of RTL_SRWLOCK_INIT in um/winnt.h to avoid include.
+#define SB_MUTEX_INITIALIZER \
+ { 0 }
+
+// --- SbOnce ---
+
+// Transparent Once control handle.
+typedef union WindowsRunOnce { void* ptr; } SbOnceControl;
+
+// Once static initializer.
+// Note: replica of RTL_RUN_ONCE_INIT in um/winnt.h to avoid include.
+#define SB_ONCE_INITIALIZER \
+ { 0 }
+
+// --- SbThread ---
+
+// Transparent pthread handle.
+typedef void* SbThread;
+
+// Well-defined constant value to mean "no thread handle."
+#define kSbThreadInvalid (SbThread) NULL
+
+#endif // STARBOARD_SHARED_WIN32_THREAD_TYPES_PUBLIC_H_
diff --git a/src/cobalt/base/math.h b/src/starboard/shared/win32/thread_yield.cc
similarity index 77%
copy from src/cobalt/base/math.h
copy to src/starboard/shared/win32/thread_yield.cc
index 4723bfb..2687852 100644
--- a/src/cobalt/base/math.h
+++ b/src/starboard/shared/win32/thread_yield.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
+// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_BASE_MATH_H_
-#define COBALT_BASE_MATH_H_
+#include "starboard/thread.h"
-#include <cmath>
+#include <windows.h>
-#endif // COBALT_BASE_MATH_H_
+void SbThreadYield() {
+ Sleep(0);
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/time_get_monotonic_now.cc
similarity index 73%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/time_get_monotonic_now.cc
index 51e1f2e..56a162a 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/time_get_monotonic_now.cc
@@ -12,9 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/time.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+SbTimeMonotonic SbTimeGetMonotonicNow() {
+ ULONGLONG result;
+ QueryUnbiasedInterruptTimePrecise(&result);
+
+ return static_cast<SbTimeMonotonic>(result) / 10;
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/time_get_monotonic_thread_now.cc
similarity index 73%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/time_get_monotonic_thread_now.cc
index 51e1f2e..fff4bd9 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/time_get_monotonic_thread_now.cc
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/time.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+SbTimeMonotonic SbTimeGetMonotonicThreadNow() {
+ // Neither QueryThreadCycleTime nor GetThreadTimes are listed as being
+ // available in UWP.
+ return SbTimeGetMonotonicNow();
+}
diff --git a/src/cobalt/dom/media_key_system_media_capability.idl b/src/starboard/shared/win32/time_get_now.cc
similarity index 60%
copy from src/cobalt/dom/media_key_system_media_capability.idl
copy to src/starboard/shared/win32/time_get_now.cc
index 51e1f2e..eaa1fbc 100644
--- a/src/cobalt/dom/media_key_system_media_capability.idl
+++ b/src/starboard/shared/win32/time_get_now.cc
@@ -12,9 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// https://www.w3.org/TR/2016/CR-encrypted-media-20160705/#mediakeysystemmediacapability-dictionary
+#include "starboard/time.h"
-dictionary MediaKeySystemMediaCapability {
- DOMString contentType = "";
- DOMString robustness = "";
-};
+#include <windows.h>
+
+SbTime SbTimeGetNow() {
+ SYSTEMTIME system_time;
+ GetSystemTime(&system_time);
+
+ FILETIME file_time;
+ SystemTimeToFileTime(&system_time, &file_time);
+
+ ULARGE_INTEGER large_int;
+ large_int.LowPart = file_time.dwLowDateTime;
+ large_int.HighPart = file_time.dwHighDateTime;
+ return static_cast<SbTime>(large_int.QuadPart) / 10;
+}
diff --git a/src/starboard/shared/win32/time_utils.h b/src/starboard/shared/win32/time_utils.h
new file mode 100644
index 0000000..cad1368
--- /dev/null
+++ b/src/starboard/shared/win32/time_utils.h
@@ -0,0 +1,64 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_WIN32_TIME_UTILS_H_
+#define STARBOARD_SHARED_WIN32_TIME_UTILS_H_
+
+#include "starboard/log.h"
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+inline SbTime ConvertFileTimeTicksToSbTime(const LARGE_INTEGER ticks) {
+ // According to
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
+ // FILETIME format is "Contains a 64-bit value representing the number of
+ // 100-nanosecond intervals since January 1, 1601 (UTC)"
+ const uint64_t kNumber100nanosecondTicksInMicrosecond = 10;
+ return ticks.QuadPart / kNumber100nanosecondTicksInMicrosecond;
+}
+
+inline SbTime ConvertFileTimeToSbTime(const FILETIME file_time) {
+ // According to
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx
+ // FILETIME format is "Contains a 64-bit value representing the number of
+ // 100-nanosecond intervals since January 1, 1601 (UTC)"
+ LARGE_INTEGER ticks;
+ ticks.QuadPart = (static_cast<LONGLONG>(file_time.dwHighDateTime) << 32) |
+ file_time.dwLowDateTime;
+ return ConvertFileTimeTicksToSbTime(ticks);
+}
+
+inline SbTime ConvertSystemTimeToSbTime(const SYSTEMTIME system_time) {
+ FILETIME file_time = {0};
+ SystemTimeToFileTime(&system_time, &file_time);
+ return ConvertFileTimeToSbTime(file_time);
+}
+
+// Many Win32 calls take millis, but SbTime is microseconds.
+// Many nplb tests assume waits are at least as long as requested, so
+// round up.
+inline DWORD ConvertSbTimeToMillisRoundUp(SbTime duration) {
+ const int64_t milliseconds_to_sleep =
+ (duration + kSbTimeMillisecond - 1) / kSbTimeMillisecond;
+ SB_DCHECK(milliseconds_to_sleep <= kSbInt32Max);
+ return static_cast<DWORD>(milliseconds_to_sleep);
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_WIN32_TIME_UTILS_H_
diff --git a/src/starboard/shared/win32/time_zone_get_current.cc b/src/starboard/shared/win32/time_zone_get_current.cc
new file mode 100644
index 0000000..b040059
--- /dev/null
+++ b/src/starboard/shared/win32/time_zone_get_current.cc
@@ -0,0 +1,36 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/time_zone.h"
+
+#include <windows.h>
+
+#include "starboard/log.h"
+SbTimeZone SbTimeZoneGetCurrent() {
+ DYNAMIC_TIME_ZONE_INFORMATION time_zone_info;
+
+ DWORD zone_id = GetDynamicTimeZoneInformation(&time_zone_info);
+
+ switch (zone_id) {
+ case TIME_ZONE_ID_UNKNOWN:
+ return time_zone_info.Bias;
+ case TIME_ZONE_ID_STANDARD:
+ return time_zone_info.StandardBias;
+ case TIME_ZONE_ID_DAYLIGHT:
+ return time_zone_info.DaylightBias;
+ default:
+ SB_NOTREACHED();
+ return 0;
+ }
+}
diff --git a/src/starboard/shared/win32/wchar_utils.h b/src/starboard/shared/win32/wchar_utils.h
new file mode 100644
index 0000000..948b025
--- /dev/null
+++ b/src/starboard/shared/win32/wchar_utils.h
@@ -0,0 +1,47 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_WIN32_WCHAR_UTILS_H_
+#define STARBOARD_WIN32_WCHAR_UTILS_H_
+
+#include <codecvt>
+#include <cwchar>
+#include <locale>
+#include <string>
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+inline std::string wchar_tToUTF8(const wchar_t* const str) {
+ std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
+ return converter.to_bytes(str);
+}
+
+inline std::string wchar_tToUTF8(const wchar_t* const str,
+ const std::size_t size) {
+ std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
+ return converter.to_bytes(str, str + size);
+}
+
+inline std::wstring CStringToWString(const char* str) {
+ std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
+ return converter.from_bytes(str);
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_WIN32_WCHAR_UTILS_H_
diff --git a/src/starboard/stub/gyp_configuration.gypi b/src/starboard/stub/gyp_configuration.gypi
index 3a62ad7..10e4c16 100644
--- a/src/starboard/stub/gyp_configuration.gypi
+++ b/src/starboard/stub/gyp_configuration.gypi
@@ -24,7 +24,9 @@
# This should have a default value in cobalt/base.gypi. See the comment
# there for acceptable values for this variable.
- 'javascript_engine': 'mozjs',
+ 'javascript_engine': 'mozjs-45',
+
+ 'cobalt_enable_jit': 0,
'cobalt_media_source_2016': 1,
@@ -87,6 +89,9 @@
'-Wno-unnamed-type-template-args',
# Triggered by the COMPILE_ASSERT macro.
'-Wno-unused-local-typedef',
+ # Do not warn if a function or variable cannot be implicitly
+ # instantiated.
+ '-Wno-undefined-var-template',
],
}],
['cobalt_fastbuild==0', {
@@ -118,11 +123,7 @@
#'-std=c99',
],
'cflags_cc': [
- # Limit to gnu++98. This allows stub to be a canary build for any
- # C++11 features that are not supported on some platforms' compilers.
- # We do allow ourselves GNU extensions, which are assumed to exist
- # by Chromium code.
- #'-std=gnu++98',
+ '-std=gnu++11',
],
'default_configuration': 'stub_debug',
'configurations': {
diff --git a/src/starboard/tools/raspi/run_test.py b/src/starboard/tools/raspi/run_test.py
index 5119c3a..b837307 100755
--- a/src/starboard/tools/raspi/run_test.py
+++ b/src/starboard/tools/raspi/run_test.py
@@ -21,9 +21,11 @@
import functools
import logging
import os
+import re
import signal
import sys
import textwrap
+import time
import pexpect
@@ -68,6 +70,9 @@
if not os.path.isfile(test_path):
raise ValueError('test_path ({}) must be a file.'.format(test_path))
+ # This is used to strip ansi color codes from output.
+ sanitize_line_re = re.compile(r'\x1b[^m]*m')
+
sys.stdout.write('Process launched, ID={}\n'.format(os.getpid()))
sys.stdout.flush()
@@ -81,19 +86,19 @@
options = '-avzh --exclude obj*'
source = test_dir_path
destination = raspi_user_hostname + ':~/'
- command = 'rsync ' + options + ' ' + source + ' ' + destination
- process = pexpect.spawn(command, timeout=120)
+ rsync_command = 'rsync ' + options + ' ' + source + ' ' + destination
+ rsync_process = pexpect.spawn(rsync_command, timeout=120)
signal.signal(signal.SIGINT,
- functools.partial(_SigIntOrSigTermHandler, process))
+ functools.partial(_SigIntOrSigTermHandler, rsync_process))
signal.signal(signal.SIGTERM,
- functools.partial(_SigIntOrSigTermHandler, process))
+ functools.partial(_SigIntOrSigTermHandler, rsync_process))
- process.expect(r'\S+ password:')
- process.sendline(_RASPI_PASSWORD)
+ rsync_process.expect(r'\S+ password:')
+ rsync_process.sendline(_RASPI_PASSWORD)
while True:
- line = process.readline()
+ line = sanitize_line_re.sub('', rsync_process.readline())
if line:
sys.stdout.write(line)
sys.stdout.flush()
@@ -101,21 +106,24 @@
break
# ssh into the raspi and run the test
- command = 'ssh ' + raspi_user_hostname
- process = pexpect.spawn(command, timeout=120)
+ ssh_command = 'ssh ' + raspi_user_hostname
+ ssh_process = pexpect.spawn(ssh_command, timeout=120)
signal.signal(signal.SIGINT,
- functools.partial(_SigIntOrSigTermHandler, process))
+ functools.partial(_SigIntOrSigTermHandler, ssh_process))
signal.signal(signal.SIGTERM,
- functools.partial(_SigIntOrSigTermHandler, process))
+ functools.partial(_SigIntOrSigTermHandler, ssh_process))
- process.expect(r'\S+ password:')
- process.sendline(_RASPI_PASSWORD)
- process.sendline(raspi_test_path + ' ' + flags)
+ ssh_process.expect(r'\S+ password:')
+ ssh_process.sendline(_RASPI_PASSWORD)
+
+ test_command = raspi_test_path + ' ' + flags
+ test_end_tag = 'END_TEST-{time}'.format(time=time.time())
+ ssh_process.sendline(test_command + '; echo ' + test_end_tag)
while True:
- line = process.readline()
- if line:
+ line = sanitize_line_re.sub('', ssh_process.readline())
+ if line and not line.startswith(test_end_tag):
sys.stdout.write(line)
sys.stdout.flush()
else:
diff --git a/src/third_party/mozjs-45/js/src/js.msg b/src/third_party/mozjs-45/js/src/js.msg
index 908a188..14834ec 100644
--- a/src/third_party/mozjs-45/js/src/js.msg
+++ b/src/third_party/mozjs-45/js/src/js.msg
@@ -149,8 +149,13 @@
MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
// CSP
+#if defined(COBALT)
+MSG_DEF(JSMSG_CSP_BLOCKED_EVAL, 0, JSEXN_EVALERR, "call to eval() blocked by CSP")
+MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION, 0, JSEXN_EVALERR, "call to Function() blocked by CSP")
+#else
MSG_DEF(JSMSG_CSP_BLOCKED_EVAL, 0, JSEXN_ERR, "call to eval() blocked by CSP")
MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION, 0, JSEXN_ERR, "call to Function() blocked by CSP")
+#endif
// Wrappers
MSG_DEF(JSMSG_ACCESSOR_DEF_DENIED, 1, JSEXN_ERR, "Permission denied to define accessor property {0}")
diff --git a/src/third_party/openssl/README.chromium b/src/third_party/openssl/README.chromium
index 6c8889b..d49796a 100644
--- a/src/third_party/openssl/README.chromium
+++ b/src/third_party/openssl/README.chromium
@@ -1,6 +1,6 @@
Name: openssl
URL: http://openssl.org/source/
-Version: 1.0.1p
+Version: 1.0.1r
License: BSDish
License File: openssl/LICENSE
License Android Compatible: yes
diff --git a/src/third_party/openssl/openssl/.travis-create-release.sh b/src/third_party/openssl/openssl/.travis-create-release.sh
new file mode 100644
index 0000000..0404fc1
--- /dev/null
+++ b/src/third_party/openssl/openssl/.travis-create-release.sh
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+# $1 is expected to be $TRAVIS_OS_NAME
+
+if [ "$1" == osx ]; then
+ make -f Makefile.org \
+ DISTTARVARS="NAME=_srcdist TAR_COMMAND='\$\$(TAR) \$\$(TARFLAGS) -s \"|^|\$\$(NAME)/|\" -T \$\$(TARFILE).list -cvf -' TARFLAGS='-n' TARFILE=_srcdist.tar" SHELL='sh -vx' dist
+else
+ make -f Makefile.org DISTTARVARS='TARFILE=_srcdist.tar NAME=_srcdist' SHELL='sh -v' dist
+fi
diff --git a/src/third_party/openssl/openssl/.travis.yml b/src/third_party/openssl/openssl/.travis.yml
new file mode 100644
index 0000000..ad05909
--- /dev/null
+++ b/src/third_party/openssl/openssl/.travis.yml
@@ -0,0 +1,60 @@
+language: c
+
+addons:
+ apt_packages:
+ - binutils-mingw-w64
+ - gcc-mingw-w64
+
+os:
+ - linux
+ - osx
+
+compiler:
+ - clang
+ - gcc
+ - i686-w64-mingw32-gcc
+ - x86_64-w64-mingw32-gcc
+
+env:
+ - CONFIG_OPTS=""
+ - CONFIG_OPTS="shared"
+ - CONFIG_OPTS="-d --strict-warnings"
+
+matrix:
+ exclude:
+ - os: osx
+ compiler: i686-w64-mingw32-gcc
+ - os: osx
+ compiler: x86_64-w64-mingw32-gcc
+ - compiler: i686-w64-mingw32-gcc
+ env: CONFIG_OPTS="-d --strict-warnings"
+ - compiler: x86_64-w64-mingw32-gcc
+ env: CONFIG_OPTS="-d --strict-warnings"
+
+before_script:
+ - sh .travis-create-release.sh $TRAVIS_OS_NAME
+ - tar -xvzf _srcdist.tar.gz
+ - cd _srcdist
+ - if [ "$CC" == i686-w64-mingw32-gcc ]; then
+ export CROSS_COMPILE=${CC%%gcc}; unset CC;
+ ./Configure mingw $CONFIG_OPTS;
+ elif [ "$CC" == x86_64-w64-mingw32-gcc ]; then
+ export CROSS_COMPILE=${CC%%gcc}; unset CC;
+ ./Configure mingw64 $CONFIG_OPTS;
+ else
+ ./config $CONFIG_OPTS;
+ fi
+ - cd ..
+
+script:
+ - cd _srcdist
+ - make
+ - if [ -z "$CROSS_COMPILE" ]; then make test; fi
+ - cd ..
+
+notifications:
+ recipient:
+ - openssl-commits@openssl.org
+ email:
+ on_success: change
+ on_failure: always
diff --git a/src/third_party/openssl/openssl/ACKNOWLEDGMENTS b/src/third_party/openssl/openssl/ACKNOWLEDGMENTS
index 59c6f01..d21dccb 100644
--- a/src/third_party/openssl/openssl/ACKNOWLEDGMENTS
+++ b/src/third_party/openssl/openssl/ACKNOWLEDGMENTS
@@ -1,30 +1,2 @@
-The OpenSSL project depends on volunteer efforts and financial support from
-the end user community. That support comes in the form of donations and paid
-sponsorships, software support contracts, paid consulting services
-and commissioned software development.
-
-Since all these activities support the continued development and improvement
-of OpenSSL we consider all these clients and customers as sponsors of the
-OpenSSL project.
-
-We would like to identify and thank the following such sponsors for their past
-or current significant support of the OpenSSL project:
-
-Major support:
-
- Qualys http://www.qualys.com/
-
-Very significant support:
-
- OpenGear: http://www.opengear.com/
-
-Significant support:
-
- PSW Group: http://www.psw.net/
- Acano Ltd. http://acano.com/
-
-Please note that we ask permission to identify sponsors and that some sponsors
-we consider eligible for inclusion here have requested to remain anonymous.
-
-Additional sponsorship or financial support is always welcome: for more
-information please contact the OpenSSL Software Foundation.
+Please https://www.openssl.org/community/thanks.html for the current
+acknowledgements.
diff --git a/src/third_party/openssl/openssl/CHANGES b/src/third_party/openssl/openssl/CHANGES
index 2e888f7..b84ff94 100644
--- a/src/third_party/openssl/openssl/CHANGES
+++ b/src/third_party/openssl/openssl/CHANGES
@@ -2,6 +2,69 @@
OpenSSL CHANGES
_______________
+ Changes between 1.0.1q and 1.0.1r [28 Jan 2016]
+
+ *) Protection for DH small subgroup attacks
+
+ As a precautionary measure the SSL_OP_SINGLE_DH_USE option has been
+ switched on by default and cannot be disabled. This could have some
+ performance impact.
+ [Matt Caswell]
+
+ *) SSLv2 doesn't block disabled ciphers
+
+ A malicious client can negotiate SSLv2 ciphers that have been disabled on
+ the server and complete SSLv2 handshakes even if all SSLv2 ciphers have
+ been disabled, provided that the SSLv2 protocol was not also disabled via
+ SSL_OP_NO_SSLv2.
+
+ This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram
+ and Sebastian Schinzel.
+ (CVE-2015-3197)
+ [Viktor Dukhovni]
+
+ *) Reject DH handshakes with parameters shorter than 1024 bits.
+ [Kurt Roeckx]
+
+ Changes between 1.0.1p and 1.0.1q [3 Dec 2015]
+
+ *) Certificate verify crash with missing PSS parameter
+
+ The signature verification routines will crash with a NULL pointer
+ dereference if presented with an ASN.1 signature using the RSA PSS
+ algorithm and absent mask generation function parameter. Since these
+ routines are used to verify certificate signature algorithms this can be
+ used to crash any certificate verification operation and exploited in a
+ DoS attack. Any application which performs certificate verification is
+ vulnerable including OpenSSL clients and servers which enable client
+ authentication.
+
+ This issue was reported to OpenSSL by Loïc Jonas Etienne (Qnective AG).
+ (CVE-2015-3194)
+ [Stephen Henson]
+
+ *) X509_ATTRIBUTE memory leak
+
+ When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak
+ memory. This structure is used by the PKCS#7 and CMS routines so any
+ application which reads PKCS#7 or CMS data from untrusted sources is
+ affected. SSL/TLS is not affected.
+
+ This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using
+ libFuzzer.
+ (CVE-2015-3195)
+ [Stephen Henson]
+
+ *) Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs.
+ This changes the decoding behaviour for some invalid messages,
+ though the change is mostly in the more lenient direction, and
+ legacy behaviour is preserved as much as possible.
+ [Emilia Käsper]
+
+ *) In DSA_generate_parameters_ex, if the provided seed is too short,
+ return an error
+ [Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>]
+
Changes between 1.0.1o and 1.0.1p [9 Jul 2015]
*) Alternate chains certificate forgery
@@ -15,10 +78,19 @@
This issue was reported to OpenSSL by Adam Langley/David Benjamin
(Google/BoringSSL).
+ (CVE-2015-1793)
[Matt Caswell]
- Changes between 1.0.1n and 1.0.1o [12 Jun 2015]
+ *) Race condition handling PSK identify hint
+ If PSK identity hints are received by a multi-threaded client then
+ the values are wrongly updated in the parent SSL_CTX structure. This can
+ result in a race condition potentially leading to a double free of the
+ identify hint data.
+ (CVE-2015-3196)
+ [Stephen Henson]
+
+ Changes between 1.0.1n and 1.0.1o [12 Jun 2015]
*) Fix HMAC ABI incompatibility. The previous version introduced an ABI
incompatibility in the handling of HMAC. The previous ABI has now been
restored.
@@ -55,9 +127,9 @@
callbacks.
This issue was reported to OpenSSL by Robert Swiecki (Google), and
- independently by Hanno Böck.
+ independently by Hanno Böck.
(CVE-2015-1789)
- [Emilia Käsper]
+ [Emilia Käsper]
*) PKCS7 crash with missing EnvelopedContent
@@ -71,7 +143,7 @@
This issue was reported to OpenSSL by Michal Zalewski (Google).
(CVE-2015-1790)
- [Emilia Käsper]
+ [Emilia Käsper]
*) CMS verify infinite loop with unknown hash function
@@ -94,6 +166,9 @@
*) Reject DH handshakes with parameters shorter than 768 bits.
[Kurt Roeckx and Emilia Kasper]
+ *) dhparam: generate 2048-bit parameters by default.
+ [Kurt Roeckx and Emilia Kasper]
+
Changes between 1.0.1l and 1.0.1m [19 Mar 2015]
*) Segmentation fault in ASN1_TYPE_cmp fix
@@ -132,7 +207,7 @@
This issue was reported to OpenSSL by Michal Zalewski (Google).
(CVE-2015-0289)
- [Emilia Käsper]
+ [Emilia Käsper]
*) DoS via reachable assert in SSLv2 servers fix
@@ -140,10 +215,10 @@
servers that both support SSLv2 and enable export cipher suites by sending
a specially crafted SSLv2 CLIENT-MASTER-KEY message.
- This issue was discovered by Sean Burford (Google) and Emilia Käsper
+ This issue was discovered by Sean Burford (Google) and Emilia Käsper
(OpenSSL development team).
(CVE-2015-0293)
- [Emilia Käsper]
+ [Emilia Käsper]
*) Use After Free following d2i_ECPrivatekey error fix
@@ -288,12 +363,12 @@
version does not match the session's version. Resuming with a different
version, while not strictly forbidden by the RFC, is of questionable
sanity and breaks all known clients.
- [David Benjamin, Emilia Käsper]
+ [David Benjamin, Emilia Käsper]
*) Tighten handling of the ChangeCipherSpec (CCS) message: reject
early CCS messages during renegotiation. (Note that because
renegotiation is encrypted, this early CCS was not exploitable.)
- [Emilia Käsper]
+ [Emilia Käsper]
*) Tighten client-side session ticket handling during renegotiation:
ensure that the client only accepts a session ticket if the server sends
@@ -304,7 +379,7 @@
Similarly, ensure that the client requires a session ticket if one
was advertised in the ServerHello. Previously, a TLS client would
ignore a missing NewSessionTicket message.
- [Emilia Käsper]
+ [Emilia Käsper]
Changes between 1.0.1i and 1.0.1j [15 Oct 2014]
@@ -384,10 +459,10 @@
with a null pointer dereference (read) by specifying an anonymous (EC)DH
ciphersuite and sending carefully crafted handshake messages.
- Thanks to Felix Gröbert (Google) for discovering and researching this
+ Thanks to Felix Gröbert (Google) for discovering and researching this
issue.
(CVE-2014-3510)
- [Emilia Käsper]
+ [Emilia Käsper]
*) By sending carefully crafted DTLS packets an attacker could cause openssl
to leak memory. This can be exploited through a Denial of Service attack.
@@ -424,7 +499,7 @@
properly negotiated with the client. This can be exploited through a
Denial of Service attack.
- Thanks to Joonas Kuorilehto and Riku Hietamäki (Codenomicon) for
+ Thanks to Joonas Kuorilehto and Riku Hietamäki (Codenomicon) for
discovering and researching this issue.
(CVE-2014-5139)
[Steve Henson]
@@ -436,7 +511,7 @@
Thanks to Ivan Fratric (Google) for discovering this issue.
(CVE-2014-3508)
- [Emilia Käsper, and Steve Henson]
+ [Emilia Käsper, and Steve Henson]
*) Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
for corner cases. (Certain input points at infinity could lead to
@@ -466,15 +541,15 @@
client or server. This is potentially exploitable to run arbitrary
code on a vulnerable client or server.
- Thanks to Jüri Aedla for reporting this issue. (CVE-2014-0195)
- [Jüri Aedla, Steve Henson]
+ Thanks to Jüri Aedla for reporting this issue. (CVE-2014-0195)
+ [Jüri Aedla, Steve Henson]
*) Fix bug in TLS code where clients enable anonymous ECDH ciphersuites
are subject to a denial of service attack.
- Thanks to Felix Gröbert and Ivan Fratric at Google for discovering
+ Thanks to Felix Gröbert and Ivan Fratric at Google for discovering
this issue. (CVE-2014-3470)
- [Felix Gröbert, Ivan Fratric, Steve Henson]
+ [Felix Gröbert, Ivan Fratric, Steve Henson]
*) Harmonize version and its documentation. -f flag is used to display
compilation flags.
@@ -553,9 +628,9 @@
Thanks go to Nadhem Alfardan and Kenny Paterson of the Information
Security Group at Royal Holloway, University of London
(www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and
- Emilia Käsper for the initial patch.
+ Emilia Käsper for the initial patch.
(CVE-2013-0169)
- [Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson]
+ [Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson]
*) Fix flaw in AESNI handling of TLS 1.2 and 1.1 records for CBC mode
ciphersuites which can be exploited in a denial of service attack.
@@ -730,7 +805,7 @@
EC_GROUP_new_by_curve_name() will automatically use these (while
EC_GROUP_new_curve_GFp() currently prefers the more flexible
implementations).
- [Emilia Käsper, Adam Langley, Bodo Moeller (Google)]
+ [Emilia Käsper, Adam Langley, Bodo Moeller (Google)]
*) Use type ossl_ssize_t instad of ssize_t which isn't available on
all platforms. Move ssize_t definition from e_os.h to the public
@@ -1006,7 +1081,7 @@
[Adam Langley (Google)]
*) Fix spurious failures in ecdsatest.c.
- [Emilia Käsper (Google)]
+ [Emilia Käsper (Google)]
*) Fix the BIO_f_buffer() implementation (which was mixing different
interpretations of the '..._len' fields).
@@ -1020,7 +1095,7 @@
lock to call BN_BLINDING_invert_ex, and avoids one use of
BN_BLINDING_update for each BN_BLINDING structure (previously,
the last update always remained unused).
- [Emilia Käsper (Google)]
+ [Emilia Käsper (Google)]
*) In ssl3_clear, preserve s3->init_extra along with s3->rbuf.
[Bob Buckholz (Google)]
@@ -1829,7 +1904,7 @@
*) Add RFC 3161 compliant time stamp request creation, response generation
and response verification functionality.
- [Zoltán Glózik <zglozik@opentsa.org>, The OpenTSA Project]
+ [Zoltán Glózik <zglozik@opentsa.org>, The OpenTSA Project]
*) Add initial support for TLS extensions, specifically for the server_name
extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now
@@ -2997,7 +3072,7 @@
*) BN_CTX_get() should return zero-valued bignums, providing the same
initialised value as BN_new().
- [Geoff Thorpe, suggested by Ulf Möller]
+ [Geoff Thorpe, suggested by Ulf Möller]
*) Support for inhibitAnyPolicy certificate extension.
[Steve Henson]
@@ -3016,7 +3091,7 @@
some point, these tighter rules will become openssl's default to improve
maintainability, though the assert()s and other overheads will remain only
in debugging configurations. See bn.h for more details.
- [Geoff Thorpe, Nils Larsch, Ulf Möller]
+ [Geoff Thorpe, Nils Larsch, Ulf Möller]
*) BN_CTX_init() has been deprecated, as BN_CTX is an opaque structure
that can only be obtained through BN_CTX_new() (which implicitly
@@ -3083,7 +3158,7 @@
[Douglas Stebila (Sun Microsystems Laboratories)]
*) Add the possibility to load symbols globally with DSO.
- [Götz Babin-Ebell <babin-ebell@trustcenter.de> via Richard Levitte]
+ [Götz Babin-Ebell <babin-ebell@trustcenter.de> via Richard Levitte]
*) Add the functions ERR_set_mark() and ERR_pop_to_mark() for better
control of the error stack.
@@ -3798,7 +3873,7 @@
[Steve Henson]
*) Undo Cygwin change.
- [Ulf Möller]
+ [Ulf Möller]
*) Added support for proxy certificates according to RFC 3820.
Because they may be a security thread to unaware applications,
@@ -3831,11 +3906,11 @@
[Stephen Henson, reported by UK NISCC]
*) Use Windows randomness collection on Cygwin.
- [Ulf Möller]
+ [Ulf Möller]
*) Fix hang in EGD/PRNGD query when communication socket is closed
prematurely by EGD/PRNGD.
- [Darren Tucker <dtucker@zip.com.au> via Lutz Jänicke, resolves #1014]
+ [Darren Tucker <dtucker@zip.com.au> via Lutz Jänicke, resolves #1014]
*) Prompt for pass phrases when appropriate for PKCS12 input format.
[Steve Henson]
@@ -4297,7 +4372,7 @@
pointers passed to them whenever necessary. Otherwise it is possible
the caller may have overwritten (or deallocated) the original string
data when a later ENGINE operation tries to use the stored values.
- [Götz Babin-Ebell <babinebell@trustcenter.de>]
+ [Götz Babin-Ebell <babinebell@trustcenter.de>]
*) Improve diagnostics in file reading and command-line digests.
[Ben Laurie aided and abetted by Solar Designer <solar@openwall.com>]
@@ -6402,7 +6477,7 @@
[Bodo Moeller]
*) BN_sqr() bug fix.
- [Ulf Möller, reported by Jim Ellis <jim.ellis@cavium.com>]
+ [Ulf Möller, reported by Jim Ellis <jim.ellis@cavium.com>]
*) Rabin-Miller test analyses assume uniformly distributed witnesses,
so use BN_pseudo_rand_range() instead of using BN_pseudo_rand()
@@ -6562,7 +6637,7 @@
[Bodo Moeller]
*) Fix OAEP check.
- [Ulf Möller, Bodo Möller]
+ [Ulf Möller, Bodo Möller]
*) The countermeasure against Bleichbacher's attack on PKCS #1 v1.5
RSA encryption was accidentally removed in s3_srvr.c in OpenSSL 0.9.5
@@ -6824,10 +6899,10 @@
[Bodo Moeller]
*) Use better test patterns in bntest.
- [Ulf Möller]
+ [Ulf Möller]
*) rand_win.c fix for Borland C.
- [Ulf Möller]
+ [Ulf Möller]
*) BN_rshift bugfix for n == 0.
[Bodo Moeller]
@@ -6972,14 +7047,14 @@
*) New BIO_shutdown_wr macro, which invokes the BIO_C_SHUTDOWN_WR
BIO_ctrl (for BIO pairs).
- [Bodo Möller]
+ [Bodo Möller]
*) Add DSO method for VMS.
[Richard Levitte]
*) Bug fix: Montgomery multiplication could produce results with the
wrong sign.
- [Ulf Möller]
+ [Ulf Möller]
*) Add RPM specification openssl.spec and modify it to build three
packages. The default package contains applications, application
@@ -6997,7 +7072,7 @@
*) Don't set the two most significant bits to one when generating a
random number < q in the DSA library.
- [Ulf Möller]
+ [Ulf Möller]
*) New SSL API mode 'SSL_MODE_AUTO_RETRY'. This disables the default
behaviour that SSL_read may result in SSL_ERROR_WANT_READ (even if
@@ -7263,7 +7338,7 @@
*) Randomness polling function for Win9x, as described in:
Peter Gutmann, Software Generation of Practically Strong
Random Numbers.
- [Ulf Möller]
+ [Ulf Möller]
*) Fix so PRNG is seeded in req if using an already existing
DSA key.
@@ -7483,7 +7558,7 @@
[Steve Henson]
*) Eliminate non-ANSI declarations in crypto.h and stack.h.
- [Ulf Möller]
+ [Ulf Möller]
*) Fix for SSL server purpose checking. Server checking was
rejecting certificates which had extended key usage present
@@ -7515,7 +7590,7 @@
[Bodo Moeller]
*) Bugfix for linux-elf makefile.one.
- [Ulf Möller]
+ [Ulf Möller]
*) RSA_get_default_method() will now cause a default
RSA_METHOD to be chosen if one doesn't exist already.
@@ -7604,7 +7679,7 @@
[Steve Henson]
*) des_quad_cksum() byte order bug fix.
- [Ulf Möller, using the problem description in krb4-0.9.7, where
+ [Ulf Möller, using the problem description in krb4-0.9.7, where
the solution is attributed to Derrick J Brashear <shadow@DEMENTIA.ORG>]
*) Fix so V_ASN1_APP_CHOOSE works again: however its use is strongly
@@ -7705,7 +7780,7 @@
[Rolf Haberrecker <rolf@suse.de>]
*) Assembler module support for Mingw32.
- [Ulf Möller]
+ [Ulf Möller]
*) Shared library support for HPUX (in shlib/).
[Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Anonymous]
@@ -7724,7 +7799,7 @@
*) BN_mul bugfix: In bn_mul_part_recursion() only the a>a[n] && b>b[n]
case was implemented. This caused BN_div_recp() to fail occasionally.
- [Ulf Möller]
+ [Ulf Möller]
*) Add an optional second argument to the set_label() in the perl
assembly language builder. If this argument exists and is set
@@ -7754,14 +7829,14 @@
[Steve Henson]
*) Fix potential buffer overrun problem in BIO_printf().
- [Ulf Möller, using public domain code by Patrick Powell; problem
+ [Ulf Möller, using public domain code by Patrick Powell; problem
pointed out by David Sacerdote <das33@cornell.edu>]
*) Support EGD <http://www.lothar.com/tech/crypto/>. New functions
RAND_egd() and RAND_status(). In the command line application,
the EGD socket can be specified like a seed file using RANDFILE
or -rand.
- [Ulf Möller]
+ [Ulf Möller]
*) Allow the string CERTIFICATE to be tolerated in PKCS#7 structures.
Some CAs (e.g. Verisign) distribute certificates in this form.
@@ -7794,7 +7869,7 @@
#define OPENSSL_ALGORITHM_DEFINES
#include <openssl/opensslconf.h>
defines all pertinent NO_<algo> symbols, such as NO_IDEA, NO_RSA, etc.
- [Richard Levitte, Ulf and Bodo Möller]
+ [Richard Levitte, Ulf and Bodo Möller]
*) Bugfix: Tolerate fragmentation and interleaving in the SSL 3/TLS
record layer.
@@ -7845,17 +7920,17 @@
*) Bug fix for BN_div_recp() for numerators with an even number of
bits.
- [Ulf Möller]
+ [Ulf Möller]
*) More tests in bntest.c, and changed test_bn output.
- [Ulf Möller]
+ [Ulf Möller]
*) ./config recognizes MacOS X now.
[Andy Polyakov]
*) Bug fix for BN_div() when the first words of num and divsor are
equal (it gave wrong results if (rem=(n1-q*d0)&BN_MASK2) < d0).
- [Ulf Möller]
+ [Ulf Möller]
*) Add support for various broken PKCS#8 formats, and command line
options to produce them.
@@ -7863,11 +7938,11 @@
*) New functions BN_CTX_start(), BN_CTX_get() and BT_CTX_end() to
get temporary BIGNUMs from a BN_CTX.
- [Ulf Möller]
+ [Ulf Möller]
*) Correct return values in BN_mod_exp_mont() and BN_mod_exp2_mont()
for p == 0.
- [Ulf Möller]
+ [Ulf Möller]
*) Change the SSLeay_add_all_*() functions to OpenSSL_add_all_*() and
include a #define from the old name to the new. The original intent
@@ -7891,7 +7966,7 @@
*) Source code cleanups: use const where appropriate, eliminate casts,
use void * instead of char * in lhash.
- [Ulf Möller]
+ [Ulf Möller]
*) Bugfix: ssl3_send_server_key_exchange was not restartable
(the state was not changed to SSL3_ST_SW_KEY_EXCH_B, and because of
@@ -7936,13 +8011,13 @@
[Steve Henson]
*) New function BN_pseudo_rand().
- [Ulf Möller]
+ [Ulf Möller]
*) Clean up BN_mod_mul_montgomery(): replace the broken (and unreadable)
bignum version of BN_from_montgomery() with the working code from
SSLeay 0.9.0 (the word based version is faster anyway), and clean up
the comments.
- [Ulf Möller]
+ [Ulf Möller]
*) Avoid a race condition in s2_clnt.c (function get_server_hello) that
made it impossible to use the same SSL_SESSION data structure in
@@ -7952,25 +8027,25 @@
*) The return value of RAND_load_file() no longer counts bytes obtained
by stat(). RAND_load_file(..., -1) is new and uses the complete file
to seed the PRNG (previously an explicit byte count was required).
- [Ulf Möller, Bodo Möller]
+ [Ulf Möller, Bodo Möller]
*) Clean up CRYPTO_EX_DATA functions, some of these didn't have prototypes
used (char *) instead of (void *) and had casts all over the place.
[Steve Henson]
*) Make BN_generate_prime() return NULL on error if ret!=NULL.
- [Ulf Möller]
+ [Ulf Möller]
*) Retain source code compatibility for BN_prime_checks macro:
BN_is_prime(..., BN_prime_checks, ...) now uses
BN_prime_checks_for_size to determine the appropriate number of
Rabin-Miller iterations.
- [Ulf Möller]
+ [Ulf Möller]
*) Diffie-Hellman uses "safe" primes: DH_check() return code renamed to
DH_CHECK_P_NOT_SAFE_PRIME.
(Check if this is true? OpenPGP calls them "strong".)
- [Ulf Möller]
+ [Ulf Möller]
*) Merge the functionality of "dh" and "gendh" programs into a new program
"dhparam". The old programs are retained for now but will handle DH keys
@@ -8026,7 +8101,7 @@
*) Add missing #ifndefs that caused missing symbols when building libssl
as a shared library without RSA. Use #ifndef NO_SSL2 instead of
NO_RSA in ssl/s2*.c.
- [Kris Kennaway <kris@hub.freebsd.org>, modified by Ulf Möller]
+ [Kris Kennaway <kris@hub.freebsd.org>, modified by Ulf Möller]
*) Precautions against using the PRNG uninitialized: RAND_bytes() now
has a return value which indicates the quality of the random data
@@ -8035,7 +8110,7 @@
guaranteed to be unique but not unpredictable. RAND_add is like
RAND_seed, but takes an extra argument for an entropy estimate
(RAND_seed always assumes full entropy).
- [Ulf Möller]
+ [Ulf Möller]
*) Do more iterations of Rabin-Miller probable prime test (specifically,
3 for 1024-bit primes, 6 for 512-bit primes, 12 for 256-bit primes
@@ -8065,7 +8140,7 @@
[Steve Henson]
*) Honor the no-xxx Configure options when creating .DEF files.
- [Ulf Möller]
+ [Ulf Möller]
*) Add PKCS#10 attributes to field table: challengePassword,
unstructuredName and unstructuredAddress. These are taken from
@@ -8899,7 +8974,7 @@
*) More DES library cleanups: remove references to srand/rand and
delete an unused file.
- [Ulf Möller]
+ [Ulf Möller]
*) Add support for the the free Netwide assembler (NASM) under Win32,
since not many people have MASM (ml) and it can be hard to obtain.
@@ -8988,7 +9063,7 @@
worked.
*) Fix problems with no-hmac etc.
- [Ulf Möller, pointed out by Brian Wellington <bwelling@tislabs.com>]
+ [Ulf Möller, pointed out by Brian Wellington <bwelling@tislabs.com>]
*) New functions RSA_get_default_method(), RSA_set_method() and
RSA_get_method(). These allows replacement of RSA_METHODs without having
@@ -9105,7 +9180,7 @@
[Ben Laurie]
*) DES library cleanups.
- [Ulf Möller]
+ [Ulf Möller]
*) Add support for PKCS#5 v2.0 PBE algorithms. This will permit PKCS#8 to be
used with any cipher unlike PKCS#5 v1.5 which can at most handle 64 bit
@@ -9148,7 +9223,7 @@
[Christian Forster <fo@hawo.stw.uni-erlangen.de>]
*) config now generates no-xxx options for missing ciphers.
- [Ulf Möller]
+ [Ulf Möller]
*) Support the EBCDIC character set (work in progress).
File ebcdic.c not yet included because it has a different license.
@@ -9261,7 +9336,7 @@
[Bodo Moeller]
*) Move openssl.cnf out of lib/.
- [Ulf Möller]
+ [Ulf Möller]
*) Fix various things to let OpenSSL even pass ``egcc -pipe -O2 -Wall
-Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes
@@ -9318,10 +9393,10 @@
[Ben Laurie]
*) Support Borland C++ builder.
- [Janez Jere <jj@void.si>, modified by Ulf Möller]
+ [Janez Jere <jj@void.si>, modified by Ulf Möller]
*) Support Mingw32.
- [Ulf Möller]
+ [Ulf Möller]
*) SHA-1 cleanups and performance enhancements.
[Andy Polyakov <appro@fy.chalmers.se>]
@@ -9330,7 +9405,7 @@
[Andy Polyakov <appro@fy.chalmers.se>]
*) Accept any -xxx and +xxx compiler options in Configure.
- [Ulf Möller]
+ [Ulf Möller]
*) Update HPUX configuration.
[Anonymous]
@@ -9363,7 +9438,7 @@
[Bodo Moeller]
*) OAEP decoding bug fix.
- [Ulf Möller]
+ [Ulf Möller]
*) Support INSTALL_PREFIX for package builders, as proposed by
David Harris.
@@ -9386,21 +9461,21 @@
[Niels Poppe <niels@netbox.org>]
*) New Configure option no-<cipher> (rsa, idea, rc5, ...).
- [Ulf Möller]
+ [Ulf Möller]
*) Add the PKCS#12 API documentation to openssl.txt. Preliminary support for
extension adding in x509 utility.
[Steve Henson]
*) Remove NOPROTO sections and error code comments.
- [Ulf Möller]
+ [Ulf Möller]
*) Partial rewrite of the DEF file generator to now parse the ANSI
prototypes.
[Steve Henson]
*) New Configure options --prefix=DIR and --openssldir=DIR.
- [Ulf Möller]
+ [Ulf Möller]
*) Complete rewrite of the error code script(s). It is all now handled
by one script at the top level which handles error code gathering,
@@ -9429,7 +9504,7 @@
[Steve Henson]
*) Move the autogenerated header file parts to crypto/opensslconf.h.
- [Ulf Möller]
+ [Ulf Möller]
*) Fix new 56-bit DES export ciphersuites: they were using 7 bytes instead of
8 of keying material. Merlin has also confirmed interop with this fix
@@ -9447,13 +9522,13 @@
[Andy Polyakov <appro@fy.chalmers.se>]
*) Change functions to ANSI C.
- [Ulf Möller]
+ [Ulf Möller]
*) Fix typos in error codes.
- [Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>, Ulf Möller]
+ [Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>, Ulf Möller]
*) Remove defunct assembler files from Configure.
- [Ulf Möller]
+ [Ulf Möller]
*) SPARC v8 assembler BIGNUM implementation.
[Andy Polyakov <appro@fy.chalmers.se>]
@@ -9490,7 +9565,7 @@
[Steve Henson]
*) New Configure option "rsaref".
- [Ulf Möller]
+ [Ulf Möller]
*) Don't auto-generate pem.h.
[Bodo Moeller]
@@ -9538,7 +9613,7 @@
*) New functions DSA_do_sign and DSA_do_verify to provide access to
the raw DSA values prior to ASN.1 encoding.
- [Ulf Möller]
+ [Ulf Möller]
*) Tweaks to Configure
[Niels Poppe <niels@netbox.org>]
@@ -9548,11 +9623,11 @@
[Steve Henson]
*) New variables $(RANLIB) and $(PERL) in the Makefiles.
- [Ulf Möller]
+ [Ulf Möller]
*) New config option to avoid instructions that are illegal on the 80386.
The default code is faster, but requires at least a 486.
- [Ulf Möller]
+ [Ulf Möller]
*) Got rid of old SSL2_CLIENT_VERSION (inconsistently used) and
SSL2_SERVER_VERSION (not used at all) macros, which are now the
@@ -10091,7 +10166,7 @@
Hagino <itojun@kame.net>]
*) File was opened incorrectly in randfile.c.
- [Ulf Möller <ulf@fitug.de>]
+ [Ulf Möller <ulf@fitug.de>]
*) Beginning of support for GeneralizedTime. d2i, i2d, check and print
functions. Also ASN1_TIME suite which is a CHOICE of UTCTime or
@@ -10101,7 +10176,7 @@
[Steve Henson]
*) Correct Linux 1 recognition in config.
- [Ulf Möller <ulf@fitug.de>]
+ [Ulf Möller <ulf@fitug.de>]
*) Remove pointless MD5 hash when using DSA keys in ca.
[Anonymous <nobody@replay.com>]
@@ -10248,7 +10323,7 @@
*) Fix the RSA header declarations that hid a bug I fixed in 0.9.0b but
was already fixed by Eric for 0.9.1 it seems.
- [Ben Laurie - pointed out by Ulf Möller <ulf@fitug.de>]
+ [Ben Laurie - pointed out by Ulf Möller <ulf@fitug.de>]
*) Autodetect FreeBSD3.
[Ben Laurie]
diff --git a/src/third_party/openssl/openssl/CONTRIBUTING b/src/third_party/openssl/openssl/CONTRIBUTING
new file mode 100644
index 0000000..9d63d8a
--- /dev/null
+++ b/src/third_party/openssl/openssl/CONTRIBUTING
@@ -0,0 +1,38 @@
+HOW TO CONTRIBUTE TO OpenSSL
+----------------------------
+
+Development is coordinated on the openssl-dev mailing list (see
+http://www.openssl.org for information on subscribing). If you
+would like to submit a patch, send it to rt@openssl.org with
+the string "[PATCH]" in the subject. Please be sure to include a
+textual explanation of what your patch does.
+
+You can also make GitHub pull requests. If you do this, please also send
+mail to rt@openssl.org with a brief description and a link to the PR so
+that we can more easily keep track of it.
+
+If you are unsure as to whether a feature will be useful for the general
+OpenSSL community please discuss it on the openssl-dev mailing list first.
+Someone may be already working on the same thing or there may be a good
+reason as to why that feature isn't implemented.
+
+Patches should be as up to date as possible, preferably relative to the
+current Git or the last snapshot. They should follow our coding style
+(see https://www.openssl.org/policies/codingstyle.html) and compile without
+warnings using the --strict-warnings flag. OpenSSL compiles on many varied
+platforms: try to ensure you only use portable features.
+
+Our preferred format for patch files is "git format-patch" output. For example
+to provide a patch file containing the last commit in your local git repository
+use the following command:
+
+# git format-patch --stdout HEAD^ >mydiffs.patch
+
+Another method of creating an acceptable patch file without using git is as
+follows:
+
+# cd openssl-work
+# [your changes]
+# ./Configure dist; make clean
+# cd ..
+# diff -ur openssl-orig openssl-work > mydiffs.patch
diff --git a/src/third_party/openssl/openssl/Configure b/src/third_party/openssl/openssl/Configure
index 60ec378..0a5ffac 100755
--- a/src/third_party/openssl/openssl/Configure
+++ b/src/third_party/openssl/openssl/Configure
@@ -105,6 +105,11 @@
my $gcc_devteam_warn = "-Wall -pedantic -DPEDANTIC -Wno-long-long -Wsign-compare -Wmissing-prototypes -Wshadow -Wformat -Werror -DCRYPTO_MDEBUG_ALL -DCRYPTO_MDEBUG_ABORT -DREF_CHECK -DOPENSSL_NO_DEPRECATED";
+# Warn that "make depend" should be run?
+my $warn_make_depend = 0;
+
+my $clang_devteam_warn = "-Wno-unused-parameter -Wno-missing-field-initializers -Wno-language-extension-token -Wno-extended-offsetof -Qunused-arguments";
+
my $strict_warnings = 0;
my $x86_gcc_des="DES_PTR DES_RISC1 DES_UNROLL";
@@ -197,6 +202,7 @@
"debug-linux-generic32","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -g -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
"debug-linux-generic64","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -g -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
"debug-linux-x86_64","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -m64 -DL_ENDIAN -g -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+"debug-linux-x86_64-clang","clang: -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -m64 -DL_ENDIAN -g -Wall -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
"dist", "cc:-O::(unknown)::::::",
# Basic configs that should work on any (32 and less bit) box
@@ -361,6 +367,7 @@
"linux-ia64-ecc","ecc:-DL_ENDIAN -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
"linux-ia64-icc","icc:-DL_ENDIAN -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
"linux-x86_64", "gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+"linux-x86_64-clang","clang: -m64 -DL_ENDIAN -O3 -Wall -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
"linux64-s390x", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
#### So called "highgprs" target for z/Architecture CPUs
# "Highgprs" is kernel feature first implemented in Linux 2.6.32, see
@@ -1442,7 +1449,7 @@
# linker only when --prefix is not /usr.
if ($target =~ /^BSD\-/)
{
- $shared_ldflag.=" -Wl,-rpath,\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|);
+ $shared_ldflag.=" -Wl,-rpath,\$\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|);
}
if ($sys_id ne "")
@@ -1574,11 +1581,20 @@
if ($strict_warnings)
{
+ my $ecc = $cc;
+ $ecc = "clang" if `$cc --version 2>&1` =~ /clang/;
my $wopt;
- die "ERROR --strict-warnings requires gcc" unless ($cc =~ /gcc$/);
+ die "ERROR --strict-warnings requires gcc or clang" unless ($ecc =~ /gcc$/ or $ecc =~ /clang$/);
foreach $wopt (split /\s+/, $gcc_devteam_warn)
{
- $cflags .= " $wopt" unless ($cflags =~ /$wopt/)
+ $cflags .= " $wopt" unless ($cflags =~ /(^|\s)$wopt(\s|$)/)
+ }
+ if ($ecc eq "clang")
+ {
+ foreach $wopt (split /\s+/, $clang_devteam_warn)
+ {
+ $cflags .= " $wopt" unless ($cflags =~ /(^|\s)$wopt(\s|$)/)
+ }
}
}
@@ -1940,14 +1956,8 @@
&dofile("apps/CA.pl",'/usr/local/bin/perl','^#!/', '#!%s');
}
if ($depflags ne $default_depflags && !$make_depend) {
- print <<EOF;
-
-Since you've disabled or enabled at least one algorithm, you need to do
-the following before building:
-
- make depend
-EOF
- }
+ $warn_make_depend++;
+ }
}
# create the ms/version32.rc file if needed
@@ -2026,12 +2036,18 @@
print <<\EOF if ($no_shared_warn);
-You gave the option 'shared'. Normally, that would give you shared libraries.
-Unfortunately, the OpenSSL configuration doesn't include shared library support
-for this platform yet, so it will pretend you gave the option 'no-shared'. If
-you can inform the developpers (openssl-dev\@openssl.org) how to support shared
-libraries on this platform, they will at least look at it and try their best
-(but please first make sure you have tried with a current version of OpenSSL).
+You gave the option 'shared', which is not supported on this platform, so
+we will pretend you gave the option 'no-shared'. If you know how to implement
+shared libraries, please let us know (but please first make sure you have
+tried with a current version of OpenSSL).
+EOF
+
+print <<EOF if ($warn_make_depend);
+
+*** Because of configuration changes, you MUST do the following before
+*** building:
+
+ make depend
EOF
exit(0);
diff --git a/src/third_party/openssl/openssl/FAQ b/src/third_party/openssl/openssl/FAQ
index f8ea604..22c5cf7 100644
--- a/src/third_party/openssl/openssl/FAQ
+++ b/src/third_party/openssl/openssl/FAQ
@@ -1,1039 +1,2 @@
-OpenSSL - Frequently Asked Questions
---------------------------------------
-
-[MISC] Miscellaneous questions
-
-* Which is the current version of OpenSSL?
-* Where is the documentation?
-* How can I contact the OpenSSL developers?
-* Where can I get a compiled version of OpenSSL?
-* Why aren't tools like 'autoconf' and 'libtool' used?
-* What is an 'engine' version?
-* How do I check the authenticity of the OpenSSL distribution?
-* How does the versioning scheme work?
-
-[LEGAL] Legal questions
-
-* Do I need patent licenses to use OpenSSL?
-* Can I use OpenSSL with GPL software?
-
-[USER] Questions on using the OpenSSL applications
-
-* Why do I get a "PRNG not seeded" error message?
-* Why do I get an "unable to write 'random state'" error message?
-* How do I create certificates or certificate requests?
-* Why can't I create certificate requests?
-* Why does <SSL program> fail with a certificate verify error?
-* Why can I only use weak ciphers when I connect to a server using OpenSSL?
-* How can I create DSA certificates?
-* Why can't I make an SSL connection using a DSA certificate?
-* How can I remove the passphrase on a private key?
-* Why can't I use OpenSSL certificates with SSL client authentication?
-* Why does my browser give a warning about a mismatched hostname?
-* How do I install a CA certificate into a browser?
-* Why is OpenSSL x509 DN output not conformant to RFC2253?
-* What is a "128 bit certificate"? Can I create one with OpenSSL?
-* Why does OpenSSL set the authority key identifier extension incorrectly?
-* How can I set up a bundle of commercial root CA certificates?
-
-[BUILD] Questions about building and testing OpenSSL
-
-* Why does the linker complain about undefined symbols?
-* Why does the OpenSSL test fail with "bc: command not found"?
-* Why does the OpenSSL test fail with "bc: 1 no implemented"?
-* Why does the OpenSSL test fail with "bc: stack empty"?
-* Why does the OpenSSL compilation fail on Alpha Tru64 Unix?
-* Why does the OpenSSL compilation fail with "ar: command not found"?
-* Why does the OpenSSL compilation fail on Win32 with VC++?
-* What is special about OpenSSL on Redhat?
-* Why does the OpenSSL compilation fail on MacOS X?
-* Why does the OpenSSL test suite fail on MacOS X?
-* Why does the OpenSSL test suite fail in BN_sqr test [on a 64-bit platform]?
-* Why does OpenBSD-i386 build fail on des-586.s with "Unimplemented segment type"?
-* Why does the OpenSSL test suite fail in sha512t on x86 CPU?
-* Why does compiler fail to compile sha512.c?
-* Test suite still fails, what to do?
-* I think I've found a bug, what should I do?
-* I'm SURE I've found a bug, how do I report it?
-* I've found a security issue, how do I report it?
-
-[PROG] Questions about programming with OpenSSL
-
-* Is OpenSSL thread-safe?
-* I've compiled a program under Windows and it crashes: why?
-* How do I read or write a DER encoded buffer using the ASN1 functions?
-* OpenSSL uses DER but I need BER format: does OpenSSL support BER?
-* I've tried using <M_some_evil_pkcs12_macro> and I get errors why?
-* I've called <some function> and it fails, why?
-* I just get a load of numbers for the error output, what do they mean?
-* Why do I get errors about unknown algorithms?
-* Why can't the OpenSSH configure script detect OpenSSL?
-* Can I use OpenSSL's SSL library with non-blocking I/O?
-* Why doesn't my server application receive a client certificate?
-* Why does compilation fail due to an undefined symbol NID_uniqueIdentifier?
-* I think I've detected a memory leak, is this a bug?
-* Why does Valgrind complain about the use of uninitialized data?
-* Why doesn't a memory BIO work when a file does?
-* Where are the declarations and implementations of d2i_X509() etc?
-
-===============================================================================
-
-[MISC] ========================================================================
-
-* Which is the current version of OpenSSL?
-
-The current version is available from <URL: http://www.openssl.org>.
-OpenSSL 1.0.1e was released on Feb 11th, 2013.
-
-In addition to the current stable release, you can also access daily
-snapshots of the OpenSSL development version at <URL:
-ftp://ftp.openssl.org/snapshot/>, or get it by anonymous Git access.
-
-
-* Where is the documentation?
-
-OpenSSL is a library that provides cryptographic functionality to
-applications such as secure web servers. Be sure to read the
-documentation of the application you want to use. The INSTALL file
-explains how to install this library.
-
-OpenSSL includes a command line utility that can be used to perform a
-variety of cryptographic functions. It is described in the openssl(1)
-manpage. Documentation for developers is currently being written. Many
-manual pages are available; overviews over libcrypto and
-libssl are given in the crypto(3) and ssl(3) manpages.
-
-The OpenSSL manpages are installed in /usr/local/ssl/man/ (or a
-different directory if you specified one as described in INSTALL).
-In addition, you can read the most current versions at
-<URL: http://www.openssl.org/docs/>. Note that the online documents refer
-to the very latest development versions of OpenSSL and may include features
-not present in released versions. If in doubt refer to the documentation
-that came with the version of OpenSSL you are using. The pod format
-documentation is included in each OpenSSL distribution under the docs
-directory.
-
-There is some documentation about certificate extensions and PKCS#12
-in doc/openssl.txt
-
-The original SSLeay documentation is included in OpenSSL as
-doc/ssleay.txt. It may be useful when none of the other resources
-help, but please note that it reflects the obsolete version SSLeay
-0.6.6.
-
-
-* How can I contact the OpenSSL developers?
-
-The README file describes how to submit bug reports and patches to
-OpenSSL. Information on the OpenSSL mailing lists is available from
-<URL: http://www.openssl.org>.
-
-
-* Where can I get a compiled version of OpenSSL?
-
-You can finder pointers to binary distributions in
-<URL: http://www.openssl.org/related/binaries.html> .
-
-Some applications that use OpenSSL are distributed in binary form.
-When using such an application, you don't need to install OpenSSL
-yourself; the application will include the required parts (e.g. DLLs).
-
-If you want to build OpenSSL on a Windows system and you don't have
-a C compiler, read the "Mingw32" section of INSTALL.W32 for information
-on how to obtain and install the free GNU C compiler.
-
-A number of Linux and *BSD distributions include OpenSSL.
-
-
-* Why aren't tools like 'autoconf' and 'libtool' used?
-
-autoconf will probably be used in future OpenSSL versions. If it was
-less Unix-centric, it might have been used much earlier.
-
-* What is an 'engine' version?
-
-With version 0.9.6 OpenSSL was extended to interface to external crypto
-hardware. This was realized in a special release '0.9.6-engine'. With
-version 0.9.7 the changes were merged into the main development line,
-so that the special release is no longer necessary.
-
-* How do I check the authenticity of the OpenSSL distribution?
-
-We provide MD5 digests and ASC signatures of each tarball.
-Use MD5 to check that a tarball from a mirror site is identical:
-
- md5sum TARBALL | awk '{print $1;}' | cmp - TARBALL.md5
-
-You can check authenticity using pgp or gpg. You need the OpenSSL team
-member public key used to sign it (download it from a key server, see a
-list of keys at <URL: http://www.openssl.org/about/>). Then
-just do:
-
- pgp TARBALL.asc
-
-* How does the versioning scheme work?
-
-After the release of OpenSSL 1.0.0 the versioning scheme changed. Letter
-releases (e.g. 1.0.1a) can only contain bug and security fixes and no
-new features. Minor releases change the last number (e.g. 1.0.2) and
-can contain new features that retain binary compatibility. Changes to
-the middle number are considered major releases and neither source nor
-binary compatibility is guaranteed.
-
-Therefore the answer to the common question "when will feature X be
-backported to OpenSSL 1.0.0/0.9.8?" is "never" but it could appear
-in the next minor release.
-
-[LEGAL] =======================================================================
-
-* Do I need patent licenses to use OpenSSL?
-
-The patents section of the README file lists patents that may apply to
-you if you want to use OpenSSL. For information on intellectual
-property rights, please consult a lawyer. The OpenSSL team does not
-offer legal advice.
-
-You can configure OpenSSL so as not to use IDEA, MDC2 and RC5 by using
- ./config no-idea no-mdc2 no-rc5
-
-
-* Can I use OpenSSL with GPL software?
-
-On many systems including the major Linux and BSD distributions, yes (the
-GPL does not place restrictions on using libraries that are part of the
-normal operating system distribution).
-
-On other systems, the situation is less clear. Some GPL software copyright
-holders claim that you infringe on their rights if you use OpenSSL with
-their software on operating systems that don't normally include OpenSSL.
-
-If you develop open source software that uses OpenSSL, you may find it
-useful to choose an other license than the GPL, or state explicitly that
-"This program is released under the GPL with the additional exemption that
-compiling, linking, and/or using OpenSSL is allowed." If you are using
-GPL software developed by others, you may want to ask the copyright holder
-for permission to use their software with OpenSSL.
-
-
-[USER] ========================================================================
-
-* Why do I get a "PRNG not seeded" error message?
-
-Cryptographic software needs a source of unpredictable data to work
-correctly. Many open source operating systems provide a "randomness
-device" (/dev/urandom or /dev/random) that serves this purpose.
-All OpenSSL versions try to use /dev/urandom by default; starting with
-version 0.9.7, OpenSSL also tries /dev/random if /dev/urandom is not
-available.
-
-On other systems, applications have to call the RAND_add() or
-RAND_seed() function with appropriate data before generating keys or
-performing public key encryption. (These functions initialize the
-pseudo-random number generator, PRNG.) Some broken applications do
-not do this. As of version 0.9.5, the OpenSSL functions that need
-randomness report an error if the random number generator has not been
-seeded with at least 128 bits of randomness. If this error occurs and
-is not discussed in the documentation of the application you are
-using, please contact the author of that application; it is likely
-that it never worked correctly. OpenSSL 0.9.5 and later make the
-error visible by refusing to perform potentially insecure encryption.
-
-If you are using Solaris 8, you can add /dev/urandom and /dev/random
-devices by installing patch 112438 (Sparc) or 112439 (x86), which are
-available via the Patchfinder at <URL: http://sunsolve.sun.com>
-(Solaris 9 includes these devices by default). For /dev/random support
-for earlier Solaris versions, see Sun's statement at
-<URL: http://sunsolve.sun.com/pub-cgi/retrieve.pl?doc=fsrdb/27606&zone_32=SUNWski>
-(the SUNWski package is available in patch 105710).
-
-On systems without /dev/urandom and /dev/random, it is a good idea to
-use the Entropy Gathering Demon (EGD); see the RAND_egd() manpage for
-details. Starting with version 0.9.7, OpenSSL will automatically look
-for an EGD socket at /var/run/egd-pool, /dev/egd-pool, /etc/egd-pool and
-/etc/entropy.
-
-Most components of the openssl command line utility automatically try
-to seed the random number generator from a file. The name of the
-default seeding file is determined as follows: If environment variable
-RANDFILE is set, then it names the seeding file. Otherwise if
-environment variable HOME is set, then the seeding file is $HOME/.rnd.
-If neither RANDFILE nor HOME is set, versions up to OpenSSL 0.9.6 will
-use file .rnd in the current directory while OpenSSL 0.9.6a uses no
-default seeding file at all. OpenSSL 0.9.6b and later will behave
-similarly to 0.9.6a, but will use a default of "C:\" for HOME on
-Windows systems if the environment variable has not been set.
-
-If the default seeding file does not exist or is too short, the "PRNG
-not seeded" error message may occur.
-
-The openssl command line utility will write back a new state to the
-default seeding file (and create this file if necessary) unless
-there was no sufficient seeding.
-
-Pointing $RANDFILE to an Entropy Gathering Daemon socket does not work.
-Use the "-rand" option of the OpenSSL command line tools instead.
-The $RANDFILE environment variable and $HOME/.rnd are only used by the
-OpenSSL command line tools. Applications using the OpenSSL library
-provide their own configuration options to specify the entropy source,
-please check out the documentation coming the with application.
-
-
-* Why do I get an "unable to write 'random state'" error message?
-
-
-Sometimes the openssl command line utility does not abort with
-a "PRNG not seeded" error message, but complains that it is
-"unable to write 'random state'". This message refers to the
-default seeding file (see previous answer). A possible reason
-is that no default filename is known because neither RANDFILE
-nor HOME is set. (Versions up to 0.9.6 used file ".rnd" in the
-current directory in this case, but this has changed with 0.9.6a.)
-
-
-* How do I create certificates or certificate requests?
-
-Check out the CA.pl(1) manual page. This provides a simple wrapper round
-the 'req', 'verify', 'ca' and 'pkcs12' utilities. For finer control check
-out the manual pages for the individual utilities and the certificate
-extensions documentation (in ca(1), req(1), x509v3_config(5) )
-
-
-* Why can't I create certificate requests?
-
-You typically get the error:
-
- unable to find 'distinguished_name' in config
- problems making Certificate Request
-
-This is because it can't find the configuration file. Check out the
-DIAGNOSTICS section of req(1) for more information.
-
-
-* Why does <SSL program> fail with a certificate verify error?
-
-This problem is usually indicated by log messages saying something like
-"unable to get local issuer certificate" or "self signed certificate".
-When a certificate is verified its root CA must be "trusted" by OpenSSL
-this typically means that the CA certificate must be placed in a directory
-or file and the relevant program configured to read it. The OpenSSL program
-'verify' behaves in a similar way and issues similar error messages: check
-the verify(1) program manual page for more information.
-
-
-* Why can I only use weak ciphers when I connect to a server using OpenSSL?
-
-This is almost certainly because you are using an old "export grade" browser
-which only supports weak encryption. Upgrade your browser to support 128 bit
-ciphers.
-
-
-* How can I create DSA certificates?
-
-Check the CA.pl(1) manual page for a DSA certificate example.
-
-
-* Why can't I make an SSL connection to a server using a DSA certificate?
-
-Typically you'll see a message saying there are no shared ciphers when
-the same setup works fine with an RSA certificate. There are two possible
-causes. The client may not support connections to DSA servers most web
-browsers (including Netscape and MSIE) only support connections to servers
-supporting RSA cipher suites. The other cause is that a set of DH parameters
-has not been supplied to the server. DH parameters can be created with the
-dhparam(1) command and loaded using the SSL_CTX_set_tmp_dh() for example:
-check the source to s_server in apps/s_server.c for an example.
-
-
-* How can I remove the passphrase on a private key?
-
-Firstly you should be really *really* sure you want to do this. Leaving
-a private key unencrypted is a major security risk. If you decide that
-you do have to do this check the EXAMPLES sections of the rsa(1) and
-dsa(1) manual pages.
-
-
-* Why can't I use OpenSSL certificates with SSL client authentication?
-
-What will typically happen is that when a server requests authentication
-it will either not include your certificate or tell you that you have
-no client certificates (Netscape) or present you with an empty list box
-(MSIE). The reason for this is that when a server requests a client
-certificate it includes a list of CAs names which it will accept. Browsers
-will only let you select certificates from the list on the grounds that
-there is little point presenting a certificate which the server will
-reject.
-
-The solution is to add the relevant CA certificate to your servers "trusted
-CA list". How you do this depends on the server software in uses. You can
-print out the servers list of acceptable CAs using the OpenSSL s_client tool:
-
-openssl s_client -connect www.some.host:443 -prexit
-
-If your server only requests certificates on certain URLs then you may need
-to manually issue an HTTP GET command to get the list when s_client connects:
-
-GET /some/page/needing/a/certificate.html
-
-If your CA does not appear in the list then this confirms the problem.
-
-
-* Why does my browser give a warning about a mismatched hostname?
-
-Browsers expect the server's hostname to match the value in the commonName
-(CN) field of the certificate. If it does not then you get a warning.
-
-
-* How do I install a CA certificate into a browser?
-
-The usual way is to send the DER encoded certificate to the browser as
-MIME type application/x-x509-ca-cert, for example by clicking on an appropriate
-link. On MSIE certain extensions such as .der or .cacert may also work, or you
-can import the certificate using the certificate import wizard.
-
-You can convert a certificate to DER form using the command:
-
-openssl x509 -in ca.pem -outform DER -out ca.der
-
-Occasionally someone suggests using a command such as:
-
-openssl pkcs12 -export -out cacert.p12 -in cacert.pem -inkey cakey.pem
-
-DO NOT DO THIS! This command will give away your CAs private key and
-reduces its security to zero: allowing anyone to forge certificates in
-whatever name they choose.
-
-* Why is OpenSSL x509 DN output not conformant to RFC2253?
-
-The ways to print out the oneline format of the DN (Distinguished Name) have
-been extended in version 0.9.7 of OpenSSL. Using the new X509_NAME_print_ex()
-interface, the "-nameopt" option could be introduded. See the manual
-page of the "openssl x509" commandline tool for details. The old behaviour
-has however been left as default for the sake of compatibility.
-
-* What is a "128 bit certificate"? Can I create one with OpenSSL?
-
-The term "128 bit certificate" is a highly misleading marketing term. It does
-*not* refer to the size of the public key in the certificate! A certificate
-containing a 128 bit RSA key would have negligible security.
-
-There were various other names such as "magic certificates", "SGC
-certificates", "step up certificates" etc.
-
-You can't generally create such a certificate using OpenSSL but there is no
-need to any more. Nowadays web browsers using unrestricted strong encryption
-are generally available.
-
-When there were tight restrictions on the export of strong encryption
-software from the US only weak encryption algorithms could be freely exported
-(initially 40 bit and then 56 bit). It was widely recognised that this was
-inadequate. A relaxation of the rules allowed the use of strong encryption but
-only to an authorised server.
-
-Two slighly different techniques were developed to support this, one used by
-Netscape was called "step up", the other used by MSIE was called "Server Gated
-Cryptography" (SGC). When a browser initially connected to a server it would
-check to see if the certificate contained certain extensions and was issued by
-an authorised authority. If these test succeeded it would reconnect using
-strong encryption.
-
-Only certain (initially one) certificate authorities could issue the
-certificates and they generally cost more than ordinary certificates.
-
-Although OpenSSL can create certificates containing the appropriate extensions
-the certificate would not come from a permitted authority and so would not
-be recognized.
-
-The export laws were later changed to allow almost unrestricted use of strong
-encryption so these certificates are now obsolete.
-
-
-* Why does OpenSSL set the authority key identifier (AKID) extension incorrectly?
-
-It doesn't: this extension is often the cause of confusion.
-
-Consider a certificate chain A->B->C so that A signs B and B signs C. Suppose
-certificate C contains AKID.
-
-The purpose of this extension is to identify the authority certificate B. This
-can be done either by including the subject key identifier of B or its issuer
-name and serial number.
-
-In this latter case because it is identifying certifcate B it must contain the
-issuer name and serial number of B.
-
-It is often wrongly assumed that it should contain the subject name of B. If it
-did this would be redundant information because it would duplicate the issuer
-name of C.
-
-
-* How can I set up a bundle of commercial root CA certificates?
-
-The OpenSSL software is shipped without any root CA certificate as the
-OpenSSL project does not have any policy on including or excluding
-any specific CA and does not intend to set up such a policy. Deciding
-about which CAs to support is up to application developers or
-administrators.
-
-Other projects do have other policies so you can for example extract the CA
-bundle used by Mozilla and/or modssl as described in this article:
-
- <URL: http://www.mail-archive.com/modssl-users@modssl.org/msg16980.html>
-
-
-[BUILD] =======================================================================
-
-* Why does the linker complain about undefined symbols?
-
-Maybe the compilation was interrupted, and make doesn't notice that
-something is missing. Run "make clean; make".
-
-If you used ./Configure instead of ./config, make sure that you
-selected the right target. File formats may differ slightly between
-OS versions (for example sparcv8/sparcv9, or a.out/elf).
-
-In case you get errors about the following symbols, use the config
-option "no-asm", as described in INSTALL:
-
- BF_cbc_encrypt, BF_decrypt, BF_encrypt, CAST_cbc_encrypt,
- CAST_decrypt, CAST_encrypt, RC4, RC5_32_cbc_encrypt, RC5_32_decrypt,
- RC5_32_encrypt, bn_add_words, bn_div_words, bn_mul_add_words,
- bn_mul_comba4, bn_mul_comba8, bn_mul_words, bn_sqr_comba4,
- bn_sqr_comba8, bn_sqr_words, bn_sub_words, des_decrypt3,
- des_ede3_cbc_encrypt, des_encrypt, des_encrypt2, des_encrypt3,
- des_ncbc_encrypt, md5_block_asm_host_order, sha1_block_asm_data_order
-
-If none of these helps, you may want to try using the current snapshot.
-If the problem persists, please submit a bug report.
-
-
-* Why does the OpenSSL test fail with "bc: command not found"?
-
-You didn't install "bc", the Unix calculator. If you want to run the
-tests, get GNU bc from ftp://ftp.gnu.org or from your OS distributor.
-
-
-* Why does the OpenSSL test fail with "bc: 1 no implemented"?
-
-On some SCO installations or versions, bc has a bug that gets triggered
-when you run the test suite (using "make test"). The message returned is
-"bc: 1 not implemented".
-
-The best way to deal with this is to find another implementation of bc
-and compile/install it. GNU bc (see <URL: http://www.gnu.org/software/software.html>
-for download instructions) can be safely used, for example.
-
-
-* Why does the OpenSSL test fail with "bc: stack empty"?
-
-On some DG/ux versions, bc seems to have a too small stack for calculations
-that the OpenSSL bntest throws at it. This gets triggered when you run the
-test suite (using "make test"). The message returned is "bc: stack empty".
-
-The best way to deal with this is to find another implementation of bc
-and compile/install it. GNU bc (see <URL: http://www.gnu.org/software/software.html>
-for download instructions) can be safely used, for example.
-
-
-* Why does the OpenSSL compilation fail on Alpha Tru64 Unix?
-
-On some Alpha installations running Tru64 Unix and Compaq C, the compilation
-of crypto/sha/sha_dgst.c fails with the message 'Fatal: Insufficient virtual
-memory to continue compilation.' As far as the tests have shown, this may be
-a compiler bug. What happens is that it eats up a lot of resident memory
-to build something, probably a table. The problem is clearly in the
-optimization code, because if one eliminates optimization completely (-O0),
-the compilation goes through (and the compiler consumes about 2MB of resident
-memory instead of 240MB or whatever one's limit is currently).
-
-There are three options to solve this problem:
-
-1. set your current data segment size soft limit higher. Experience shows
-that about 241000 kbytes seems to be enough on an AlphaServer DS10. You do
-this with the command 'ulimit -Sd nnnnnn', where 'nnnnnn' is the number of
-kbytes to set the limit to.
-
-2. If you have a hard limit that is lower than what you need and you can't
-get it changed, you can compile all of OpenSSL with -O0 as optimization
-level. This is however not a very nice thing to do for those who expect to
-get the best result from OpenSSL. A bit more complicated solution is the
-following:
-
------ snip:start -----
- make DIRS=crypto SDIRS=sha "`grep '^CFLAG=' Makefile.ssl | \
- sed -e 's/ -O[0-9] / -O0 /'`"
- rm `ls crypto/*.o crypto/sha/*.o | grep -v 'sha_dgst\.o'`
- make
------ snip:end -----
-
-This will only compile sha_dgst.c with -O0, the rest with the optimization
-level chosen by the configuration process. When the above is done, do the
-test and installation and you're set.
-
-3. Reconfigure the toolkit with no-sha0 option to leave out SHA0. It
-should not be used and is not used in SSL/TLS nor any other recognized
-protocol in either case.
-
-
-* Why does the OpenSSL compilation fail with "ar: command not found"?
-
-Getting this message is quite usual on Solaris 2, because Sun has hidden
-away 'ar' and other development commands in directories that aren't in
-$PATH by default. One of those directories is '/usr/ccs/bin'. The
-quickest way to fix this is to do the following (it assumes you use sh
-or any sh-compatible shell):
-
------ snip:start -----
- PATH=${PATH}:/usr/ccs/bin; export PATH
------ snip:end -----
-
-and then redo the compilation. What you should really do is make sure
-'/usr/ccs/bin' is permanently in your $PATH, for example through your
-'.profile' (again, assuming you use a sh-compatible shell).
-
-
-* Why does the OpenSSL compilation fail on Win32 with VC++?
-
-Sometimes, you may get reports from VC++ command line (cl) that it
-can't find standard include files like stdio.h and other weirdnesses.
-One possible cause is that the environment isn't correctly set up.
-To solve that problem for VC++ versions up to 6, one should run
-VCVARS32.BAT which is found in the 'bin' subdirectory of the VC++
-installation directory (somewhere under 'Program Files'). For VC++
-version 7 (and up?), which is also called VS.NET, the file is called
-VSVARS32.BAT instead.
-This needs to be done prior to running NMAKE, and the changes are only
-valid for the current DOS session.
-
-
-* What is special about OpenSSL on Redhat?
-
-Red Hat Linux (release 7.0 and later) include a preinstalled limited
-version of OpenSSL. For patent reasons, support for IDEA, RC5 and MDC2
-is disabled in this version. The same may apply to other Linux distributions.
-Users may therefore wish to install more or all of the features left out.
-
-To do this you MUST ensure that you do not overwrite the openssl that is in
-/usr/bin on your Red Hat machine. Several packages depend on this file,
-including sendmail and ssh. /usr/local/bin is a good alternative choice. The
-libraries that come with Red Hat 7.0 onwards have different names and so are
-not affected. (eg For Red Hat 7.2 they are /lib/libssl.so.0.9.6b and
-/lib/libcrypto.so.0.9.6b with symlinks /lib/libssl.so.2 and
-/lib/libcrypto.so.2 respectively).
-
-Please note that we have been advised by Red Hat attempting to recompile the
-openssl rpm with all the cryptography enabled will not work. All other
-packages depend on the original Red Hat supplied openssl package. It is also
-worth noting that due to the way Red Hat supplies its packages, updates to
-openssl on each distribution never change the package version, only the
-build number. For example, on Red Hat 7.1, the latest openssl package has
-version number 0.9.6 and build number 9 even though it contains all the
-relevant updates in packages up to and including 0.9.6b.
-
-A possible way around this is to persuade Red Hat to produce a non-US
-version of Red Hat Linux.
-
-FYI: Patent numbers and expiry dates of US patents:
-MDC-2: 4,908,861 13/03/2007
-IDEA: 5,214,703 25/05/2010
-RC5: 5,724,428 03/03/2015
-
-
-* Why does the OpenSSL compilation fail on MacOS X?
-
-If the failure happens when trying to build the "openssl" binary, with
-a large number of undefined symbols, it's very probable that you have
-OpenSSL 0.9.6b delivered with the operating system (you can find out by
-running '/usr/bin/openssl version') and that you were trying to build
-OpenSSL 0.9.7 or newer. The problem is that the loader ('ld') in
-MacOS X has a misfeature that's quite difficult to go around.
-Look in the file PROBLEMS for a more detailed explanation and for possible
-solutions.
-
-
-* Why does the OpenSSL test suite fail on MacOS X?
-
-If the failure happens when running 'make test' and the RC4 test fails,
-it's very probable that you have OpenSSL 0.9.6b delivered with the
-operating system (you can find out by running '/usr/bin/openssl version')
-and that you were trying to build OpenSSL 0.9.6d. The problem is that
-the loader ('ld') in MacOS X has a misfeature that's quite difficult to
-go around and has linked the programs "openssl" and the test programs
-with /usr/lib/libcrypto.dylib and /usr/lib/libssl.dylib instead of the
-libraries you just built.
-Look in the file PROBLEMS for a more detailed explanation and for possible
-solutions.
-
-* Why does the OpenSSL test suite fail in BN_sqr test [on a 64-bit platform]?
-
-Failure in BN_sqr test is most likely caused by a failure to configure the
-toolkit for current platform or lack of support for the platform in question.
-Run './config -t' and './apps/openssl version -p'. Do these platform
-identifiers match? If they don't, then you most likely failed to run
-./config and you're hereby advised to do so before filing a bug report.
-If ./config itself fails to run, then it's most likely problem with your
-local environment and you should turn to your system administrator (or
-similar). If identifiers match (and/or no alternative identifier is
-suggested by ./config script), then the platform is unsupported. There might
-or might not be a workaround. Most notably on SPARC64 platforms with GNU
-C compiler you should be able to produce a working build by running
-'./config -m32'. I understand that -m32 might not be what you want/need,
-but the build should be operational. For further details turn to
-<openssl-dev@openssl.org>.
-
-* Why does OpenBSD-i386 build fail on des-586.s with "Unimplemented segment type"?
-
-As of 0.9.7 assembler routines were overhauled for position independence
-of the machine code, which is essential for shared library support. For
-some reason OpenBSD is equipped with an out-of-date GNU assembler which
-finds the new code offensive. To work around the problem, configure with
-no-asm (and sacrifice a great deal of performance) or patch your assembler
-according to <URL: http://www.openssl.org/~appro/gas-1.92.3.OpenBSD.patch>.
-For your convenience a pre-compiled replacement binary is provided at
-<URL: http://www.openssl.org/~appro/gas-1.92.3.static.aout.bin>.
-Reportedly elder *BSD a.out platforms also suffer from this problem and
-remedy should be same. Provided binary is statically linked and should be
-working across wider range of *BSD branches, not just OpenBSD.
-
-* Why does the OpenSSL test suite fail in sha512t on x86 CPU?
-
-If the test program in question fails withs SIGILL, Illegal Instruction
-exception, then you more than likely to run SSE2-capable CPU, such as
-Intel P4, under control of kernel which does not support SSE2
-instruction extentions. See accompanying INSTALL file and
-OPENSSL_ia32cap(3) documentation page for further information.
-
-* Why does compiler fail to compile sha512.c?
-
-OpenSSL SHA-512 implementation depends on compiler support for 64-bit
-integer type. Few elder compilers [ULTRIX cc, SCO compiler to mention a
-couple] lack support for this and therefore are incapable of compiling
-the module in question. The recommendation is to disable SHA-512 by
-adding no-sha512 to ./config [or ./Configure] command line. Another
-possible alternative might be to switch to GCC.
-
-* Test suite still fails, what to do?
-
-Another common reason for failure to complete some particular test is
-simply bad code generated by a buggy component in toolchain or deficiency
-in run-time environment. There are few cases documented in PROBLEMS file,
-consult it for possible workaround before you beat the drum. Even if you
-don't find solution or even mention there, do reserve for possibility of
-a compiler bug. Compiler bugs might appear in rather bizarre ways, they
-never make sense, and tend to emerge when you least expect them. In order
-to identify one, drop optimization level, e.g. by editing CFLAG line in
-top-level Makefile, recompile and re-run the test.
-
-* I think I've found a bug, what should I do?
-
-If you are a new user then it is quite likely you haven't found a bug and
-something is happening you aren't familiar with. Check this FAQ, the associated
-documentation and the mailing lists for similar queries. If you are still
-unsure whether it is a bug or not submit a query to the openssl-users mailing
-list.
-
-
-* I'm SURE I've found a bug, how do I report it?
-
-Bug reports with no security implications should be sent to the request
-tracker. This can be done by mailing the report to <rt@openssl.org> (or its
-alias <openssl-bugs@openssl.org>), please note that messages sent to the
-request tracker also appear in the public openssl-dev mailing list.
-
-The report should be in plain text. Any patches should be sent as
-plain text attachments because some mailers corrupt patches sent inline.
-If your issue affects multiple versions of OpenSSL check any patches apply
-cleanly and, if possible include patches to each affected version.
-
-The report should be given a meaningful subject line briefly summarising the
-issue. Just "bug in OpenSSL" or "bug in OpenSSL 0.9.8n" is not very helpful.
-
-By sending reports to the request tracker the bug can then be given a priority
-and assigned to the appropriate maintainer. The history of discussions can be
-accessed and if the issue has been addressed or a reason why not. If patches
-are only sent to openssl-dev they can be mislaid if a team member has to
-wade through months of old messages to review the discussion.
-
-See also <URL: http://www.openssl.org/support/rt.html>
-
-
-* I've found a security issue, how do I report it?
-
-If you think your bug has security implications then please send it to
-openssl-security@openssl.org if you don't get a prompt reply at least
-acknowledging receipt then resend or mail it directly to one of the
-more active team members (e.g. Steve).
-
-Note that bugs only present in the openssl utility are not in general
-considered to be security issues.
-
-[PROG] ========================================================================
-
-* Is OpenSSL thread-safe?
-
-Yes (with limitations: an SSL connection may not concurrently be used
-by multiple threads). On Windows and many Unix systems, OpenSSL
-automatically uses the multi-threaded versions of the standard
-libraries. If your platform is not one of these, consult the INSTALL
-file.
-
-Multi-threaded applications must provide two callback functions to
-OpenSSL by calling CRYPTO_set_locking_callback() and
-CRYPTO_set_id_callback(), for all versions of OpenSSL up to and
-including 0.9.8[abc...]. As of version 1.0.0, CRYPTO_set_id_callback()
-and associated APIs are deprecated by CRYPTO_THREADID_set_callback()
-and friends. This is described in the threads(3) manpage.
-
-* I've compiled a program under Windows and it crashes: why?
-
-This is usually because you've missed the comment in INSTALL.W32.
-Your application must link against the same version of the Win32
-C-Runtime against which your openssl libraries were linked. The
-default version for OpenSSL is /MD - "Multithreaded DLL".
-
-If you are using Microsoft Visual C++'s IDE (Visual Studio), in
-many cases, your new project most likely defaulted to "Debug
-Singlethreaded" - /ML. This is NOT interchangeable with /MD and your
-program will crash, typically on the first BIO related read or write
-operation.
-
-For each of the six possible link stage configurations within Win32,
-your application must link against the same by which OpenSSL was
-built. If you are using MS Visual C++ (Studio) this can be changed
-by:
-
- 1. Select Settings... from the Project Menu.
- 2. Select the C/C++ Tab.
- 3. Select "Code Generation from the "Category" drop down list box
- 4. Select the Appropriate library (see table below) from the "Use
- run-time library" drop down list box. Perform this step for both
- your debug and release versions of your application (look at the
- top left of the settings panel to change between the two)
-
- Single Threaded /ML - MS VC++ often defaults to
- this for the release
- version of a new project.
- Debug Single Threaded /MLd - MS VC++ often defaults to
- this for the debug version
- of a new project.
- Multithreaded /MT
- Debug Multithreaded /MTd
- Multithreaded DLL /MD - OpenSSL defaults to this.
- Debug Multithreaded DLL /MDd
-
-Note that debug and release libraries are NOT interchangeable. If you
-built OpenSSL with /MD your application must use /MD and cannot use /MDd.
-
-As per 0.9.8 the above limitation is eliminated for .DLLs. OpenSSL
-.DLLs compiled with some specific run-time option [we insist on the
-default /MD] can be deployed with application compiled with different
-option or even different compiler. But there is a catch! Instead of
-re-compiling OpenSSL toolkit, as you would have to with prior versions,
-you have to compile small C snippet with compiler and/or options of
-your choice. The snippet gets installed as
-<install-root>/include/openssl/applink.c and should be either added to
-your application project or simply #include-d in one [and only one]
-of your application source files. Failure to link this shim module
-into your application manifests itself as fatal "no OPENSSL_Applink"
-run-time error. An explicit reminder is due that in this situation
-[mixing compiler options] it is as important to add CRYPTO_malloc_init
-prior first call to OpenSSL.
-
-* How do I read or write a DER encoded buffer using the ASN1 functions?
-
-You have two options. You can either use a memory BIO in conjunction
-with the i2d_*_bio() or d2i_*_bio() functions or you can use the
-i2d_*(), d2i_*() functions directly. Since these are often the
-cause of grief here are some code fragments using PKCS7 as an example:
-
- unsigned char *buf, *p;
- int len;
-
- len = i2d_PKCS7(p7, NULL);
- buf = OPENSSL_malloc(len); /* or Malloc, error checking omitted */
- p = buf;
- i2d_PKCS7(p7, &p);
-
-At this point buf contains the len bytes of the DER encoding of
-p7.
-
-The opposite assumes we already have len bytes in buf:
-
- unsigned char *p;
- p = buf;
- p7 = d2i_PKCS7(NULL, &p, len);
-
-At this point p7 contains a valid PKCS7 structure of NULL if an error
-occurred. If an error occurred ERR_print_errors(bio) should give more
-information.
-
-The reason for the temporary variable 'p' is that the ASN1 functions
-increment the passed pointer so it is ready to read or write the next
-structure. This is often a cause of problems: without the temporary
-variable the buffer pointer is changed to point just after the data
-that has been read or written. This may well be uninitialized data
-and attempts to free the buffer will have unpredictable results
-because it no longer points to the same address.
-
-
-* OpenSSL uses DER but I need BER format: does OpenSSL support BER?
-
-The short answer is yes, because DER is a special case of BER and OpenSSL
-ASN1 decoders can process BER.
-
-The longer answer is that ASN1 structures can be encoded in a number of
-different ways. One set of ways is the Basic Encoding Rules (BER) with various
-permissible encodings. A restriction of BER is the Distinguished Encoding
-Rules (DER): these uniquely specify how a given structure is encoded.
-
-Therefore, because DER is a special case of BER, DER is an acceptable encoding
-for BER.
-
-
-* I've tried using <M_some_evil_pkcs12_macro> and I get errors why?
-
-This usually happens when you try compiling something using the PKCS#12
-macros with a C++ compiler. There is hardly ever any need to use the
-PKCS#12 macros in a program, it is much easier to parse and create
-PKCS#12 files using the PKCS12_parse() and PKCS12_create() functions
-documented in doc/openssl.txt and with examples in demos/pkcs12. The
-'pkcs12' application has to use the macros because it prints out
-debugging information.
-
-
-* I've called <some function> and it fails, why?
-
-Before submitting a report or asking in one of the mailing lists, you
-should try to determine the cause. In particular, you should call
-ERR_print_errors() or ERR_print_errors_fp() after the failed call
-and see if the message helps. Note that the problem may occur earlier
-than you think -- you should check for errors after every call where
-it is possible, otherwise the actual problem may be hidden because
-some OpenSSL functions clear the error state.
-
-
-* I just get a load of numbers for the error output, what do they mean?
-
-The actual format is described in the ERR_print_errors() manual page.
-You should call the function ERR_load_crypto_strings() before hand and
-the message will be output in text form. If you can't do this (for example
-it is a pre-compiled binary) you can use the errstr utility on the error
-code itself (the hex digits after the second colon).
-
-
-* Why do I get errors about unknown algorithms?
-
-The cause is forgetting to load OpenSSL's table of algorithms with
-OpenSSL_add_all_algorithms(). See the manual page for more information. This
-can cause several problems such as being unable to read in an encrypted
-PEM file, unable to decrypt a PKCS#12 file or signature failure when
-verifying certificates.
-
-* Why can't the OpenSSH configure script detect OpenSSL?
-
-Several reasons for problems with the automatic detection exist.
-OpenSSH requires at least version 0.9.5a of the OpenSSL libraries.
-Sometimes the distribution has installed an older version in the system
-locations that is detected instead of a new one installed. The OpenSSL
-library might have been compiled for another CPU or another mode (32/64 bits).
-Permissions might be wrong.
-
-The general answer is to check the config.log file generated when running
-the OpenSSH configure script. It should contain the detailed information
-on why the OpenSSL library was not detected or considered incompatible.
-
-
-* Can I use OpenSSL's SSL library with non-blocking I/O?
-
-Yes; make sure to read the SSL_get_error(3) manual page!
-
-A pitfall to avoid: Don't assume that SSL_read() will just read from
-the underlying transport or that SSL_write() will just write to it --
-it is also possible that SSL_write() cannot do any useful work until
-there is data to read, or that SSL_read() cannot do anything until it
-is possible to send data. One reason for this is that the peer may
-request a new TLS/SSL handshake at any time during the protocol,
-requiring a bi-directional message exchange; both SSL_read() and
-SSL_write() will try to continue any pending handshake.
-
-
-* Why doesn't my server application receive a client certificate?
-
-Due to the TLS protocol definition, a client will only send a certificate,
-if explicitly asked by the server. Use the SSL_VERIFY_PEER flag of the
-SSL_CTX_set_verify() function to enable the use of client certificates.
-
-
-* Why does compilation fail due to an undefined symbol NID_uniqueIdentifier?
-
-For OpenSSL 0.9.7 the OID table was extended and corrected. In earlier
-versions, uniqueIdentifier was incorrectly used for X.509 certificates.
-The correct name according to RFC2256 (LDAP) is x500UniqueIdentifier.
-Change your code to use the new name when compiling against OpenSSL 0.9.7.
-
-
-* I think I've detected a memory leak, is this a bug?
-
-In most cases the cause of an apparent memory leak is an OpenSSL internal table
-that is allocated when an application starts up. Since such tables do not grow
-in size over time they are harmless.
-
-These internal tables can be freed up when an application closes using various
-functions. Currently these include following:
-
-Thread-local cleanup functions:
-
- ERR_remove_state()
-
-Application-global cleanup functions that are aware of usage (and therefore
-thread-safe):
-
- ENGINE_cleanup() and CONF_modules_unload()
-
-"Brutal" (thread-unsafe) Application-global cleanup functions:
-
- ERR_free_strings(), EVP_cleanup() and CRYPTO_cleanup_all_ex_data().
-
-
-* Why does Valgrind complain about the use of uninitialized data?
-
-When OpenSSL's PRNG routines are called to generate random numbers the supplied
-buffer contents are mixed into the entropy pool: so it technically does not
-matter whether the buffer is initialized at this point or not. Valgrind (and
-other test tools) will complain about this. When using Valgrind, make sure the
-OpenSSL library has been compiled with the PURIFY macro defined (-DPURIFY)
-to get rid of these warnings.
-
-
-* Why doesn't a memory BIO work when a file does?
-
-This can occur in several cases for example reading an S/MIME email message.
-The reason is that a memory BIO can do one of two things when all the data
-has been read from it.
-
-The default behaviour is to indicate that no more data is available and that
-the call should be retried, this is to allow the application to fill up the BIO
-again if necessary.
-
-Alternatively it can indicate that no more data is available and that EOF has
-been reached.
-
-If a memory BIO is to behave in the same way as a file this second behaviour
-is needed. This must be done by calling:
-
- BIO_set_mem_eof_return(bio, 0);
-
-See the manual pages for more details.
-
-
-* Where are the declarations and implementations of d2i_X509() etc?
-
-These are defined and implemented by macros of the form:
-
-
- DECLARE_ASN1_FUNCTIONS(X509) and IMPLEMENT_ASN1_FUNCTIONS(X509)
-
-The implementation passes an ASN1 "template" defining the structure into an
-ASN1 interpreter using generalised functions such as ASN1_item_d2i().
-
-
-===============================================================================
+The FAQ is now maintained on the web:
+ https://www.openssl.org/docs/faq.html
diff --git a/src/third_party/openssl/openssl/INSTALL b/src/third_party/openssl/openssl/INSTALL
index 1325079..679b30d 100644
--- a/src/third_party/openssl/openssl/INSTALL
+++ b/src/third_party/openssl/openssl/INSTALL
@@ -164,10 +164,10 @@
standard headers). If it is a problem with OpenSSL itself, please
report the problem to <openssl-bugs@openssl.org> (note that your
message will be recorded in the request tracker publicly readable
- via http://www.openssl.org/support/rt.html and will be forwarded to a
- public mailing list). Include the output of "make report" in your message.
- Please check out the request tracker. Maybe the bug was already
- reported or has already been fixed.
+ at https://www.openssl.org/community/index.html#bugs and will be
+ forwarded to a public mailing list). Include the output of "make
+ report" in your message. Please check out the request tracker. Maybe
+ the bug was already reported or has already been fixed.
[If you encounter assembler error messages, try the "no-asm"
configuration option as an immediate fix.]
diff --git a/src/third_party/openssl/openssl/LICENSE b/src/third_party/openssl/openssl/LICENSE
index e47d101..fb03713 100644
--- a/src/third_party/openssl/openssl/LICENSE
+++ b/src/third_party/openssl/openssl/LICENSE
@@ -12,7 +12,7 @@
---------------
/* ====================================================================
- * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/src/third_party/openssl/openssl/Makefile.org b/src/third_party/openssl/openssl/Makefile.org
index 55a3700..bc1c3be 100644
--- a/src/third_party/openssl/openssl/Makefile.org
+++ b/src/third_party/openssl/openssl/Makefile.org
@@ -179,8 +179,7 @@
GENERAL= Makefile
BASENAME= openssl
NAME= $(BASENAME)-$(VERSION)
-TARFILE= $(NAME).tar
-WTARFILE= $(NAME)-win.tar
+TARFILE= ../$(NAME).tar
EXHEADER= e_os2.h
HEADER= e_os.h
@@ -499,35 +498,35 @@
# would occur. Therefore the list of files is temporarily stored into a file
# and read directly, requiring GNU-Tar. Call "make TAR=gtar dist" if the normal
# tar does not support the --files-from option.
-tar:
+TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from $(TARFILE).list \
+ --owner 0 --group 0 \
+ --transform 's|^|$(NAME)/|' \
+ -cvf -
+
+$(TARFILE).list:
+ find * \! -name STATUS \! -name TABLE \! -name '*.o' \! -name '*.a' \
+ \! -name '*.so' \! -name '*.so.*' \! -name 'openssl' \
+ \( \! -name '*test' -o -name bctest -o -name pod2mantest \) \
+ \! -name '.#*' \! -name '*~' \! -type l \
+ | sort > $(TARFILE).list
+
+tar: $(TARFILE).list
find . -type d -print | xargs chmod 755
find . -type f -print | xargs chmod a+r
find . -type f -perm -0100 -print | xargs chmod a+x
- find * \! -path CVS/\* \! -path \*/CVS/\* \! -name CVS \! -name .cvsignore \! -name STATUS \! -name TABLE | sort > ../$(TARFILE).list; \
- $(TAR) $(TARFLAGS) --files-from ../$(TARFILE).list -cvf - | \
- tardy --user_number=0 --user_name=openssl \
- --group_number=0 --group_name=openssl \
- --prefix=openssl-$(VERSION) - |\
- gzip --best >../$(TARFILE).gz; \
- rm -f ../$(TARFILE).list; \
- ls -l ../$(TARFILE).gz
+ $(TAR_COMMAND) | gzip --best > $(TARFILE).gz
+ rm -f $(TARFILE).list
+ ls -l $(TARFILE).gz
-tar-snap:
- @$(TAR) $(TARFLAGS) -cvf - \
- `find * \! -path CVS/\* \! -path \*/CVS/\* \! -name CVS \! -name .cvsignore \! -name STATUS \! -name TABLE \! -name '*.o' \! -name '*.a' \! -name '*.so' \! -name '*.so.*' \! -name 'openssl' \! -name '*test' \! -name '.#*' \! -name '*~' | sort` |\
- tardy --user_number=0 --user_name=openssl \
- --group_number=0 --group_name=openssl \
- --prefix=openssl-$(VERSION) - > ../$(TARFILE);\
- ls -l ../$(TARFILE)
+tar-snap: $(TARFILE).list
+ $(TAR_COMMAND) > $(TARFILE)
+ rm -f $(TARFILE).list
+ ls -l $(TARFILE)
dist:
$(PERL) Configure dist
- @$(MAKE) dist_pem_h
@$(MAKE) SDIRS='$(SDIRS)' clean
- @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' tar
-
-dist_pem_h:
- (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean)
+ @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar
install: all install_docs install_sw
diff --git a/src/third_party/openssl/openssl/NEWS b/src/third_party/openssl/openssl/NEWS
index 5e76d3f..c8193d5 100644
--- a/src/third_party/openssl/openssl/NEWS
+++ b/src/third_party/openssl/openssl/NEWS
@@ -5,9 +5,23 @@
This file gives a brief overview of the major changes between each OpenSSL
release. For more details please read the CHANGES file.
+ Major changes between OpenSSL 1.0.1q and OpenSSL 1.0.1r [28 Jan 2016]
+
+ o Protection for DH small subgroup attacks
+ o SSLv2 doesn't block disabled ciphers (CVE-2015-3197)
+
+ Major changes between OpenSSL 1.0.1p and OpenSSL 1.0.1q [3 Dec 2015]
+
+ o Certificate verify crash with missing PSS parameter (CVE-2015-3194)
+ o X509_ATTRIBUTE memory leak (CVE-2015-3195)
+ o Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
+ o In DSA_generate_parameters_ex, if the provided seed is too short,
+ return an error
+
Major changes between OpenSSL 1.0.1o and OpenSSL 1.0.1p [9 Jul 2015]
o Alternate chains certificate forgery (CVE-2015-1793)
+ o Race condition handling PSK identify hint (CVE-2015-3196)
Major changes between OpenSSL 1.0.1n and OpenSSL 1.0.1o [12 Jun 2015]
diff --git a/src/third_party/openssl/openssl/README b/src/third_party/openssl/openssl/README
index bf03f30..5e914f8 100644
--- a/src/third_party/openssl/openssl/README
+++ b/src/third_party/openssl/openssl/README
@@ -1,7 +1,7 @@
- OpenSSL 1.0.1p 9 Jul 2015
+ OpenSSL 1.0.1r 28 Jan 2016
- Copyright (c) 1998-2011 The OpenSSL Project
+ Copyright (c) 1998-2015 The OpenSSL Project
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
All rights reserved.
@@ -10,17 +10,17 @@
The OpenSSL Project is a collaborative effort to develop a robust,
commercial-grade, fully featured, and Open Source toolkit implementing the
- Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1)
- protocols as well as a full-strength general purpose cryptography library.
- The project is managed by a worldwide community of volunteers that use the
- Internet to communicate, plan, and develop the OpenSSL toolkit and its
- related documentation.
+ Secure Sockets Layer (SSLv3) and Transport Layer Security (TLS) protocols as
+ well as a full-strength general purpose cryptograpic library. The project is
+ managed by a worldwide community of volunteers that use the Internet to
+ communicate, plan, and develop the OpenSSL toolkit and its related
+ documentation.
- OpenSSL is based on the excellent SSLeay library developed from Eric A. Young
+ OpenSSL is descended from the SSLeay library developed by Eric A. Young
and Tim J. Hudson. The OpenSSL toolkit is licensed under a dual-license (the
- OpenSSL license plus the SSLeay license) situation, which basically means
- that you are free to get and use it for commercial and non-commercial
- purposes as long as you fulfill the conditions of both licenses.
+ OpenSSL license plus the SSLeay license), which means that you are free to
+ get and use it for commercial and non-commercial purposes as long as you
+ fulfill the conditions of both licenses.
OVERVIEW
--------
@@ -28,116 +28,39 @@
The OpenSSL toolkit includes:
libssl.a:
- Implementation of SSLv2, SSLv3, TLSv1 and the required code to support
- both SSLv2, SSLv3 and TLSv1 in the one server and client.
+ Provides the client and server-side implementations for SSLv3 and TLS.
libcrypto.a:
- General encryption and X.509 v1/v3 stuff needed by SSL/TLS but not
- actually logically part of it. It includes routines for the following:
-
- Ciphers
- libdes - EAY's libdes DES encryption package which was floating
- around the net for a few years, and was then relicensed by
- him as part of SSLeay. It includes 15 'modes/variations'
- of DES (1, 2 and 3 key versions of ecb, cbc, cfb and ofb;
- pcbc and a more general form of cfb and ofb) including desx
- in cbc mode, a fast crypt(3), and routines to read
- passwords from the keyboard.
- RC4 encryption,
- RC2 encryption - 4 different modes, ecb, cbc, cfb and ofb.
- Blowfish encryption - 4 different modes, ecb, cbc, cfb and ofb.
- IDEA encryption - 4 different modes, ecb, cbc, cfb and ofb.
-
- Digests
- MD5 and MD2 message digest algorithms, fast implementations,
- SHA (SHA-0) and SHA-1 message digest algorithms,
- MDC2 message digest. A DES based hash that is popular on smart cards.
-
- Public Key
- RSA encryption/decryption/generation.
- There is no limit on the number of bits.
- DSA encryption/decryption/generation.
- There is no limit on the number of bits.
- Diffie-Hellman key-exchange/key generation.
- There is no limit on the number of bits.
-
- X.509v3 certificates
- X509 encoding/decoding into/from binary ASN1 and a PEM
- based ASCII-binary encoding which supports encryption with a
- private key. Program to generate RSA and DSA certificate
- requests and to generate RSA and DSA certificates.
-
- Systems
- The normal digital envelope routines and base64 encoding. Higher
- level access to ciphers and digests by name. New ciphers can be
- loaded at run time. The BIO io system which is a simple non-blocking
- IO abstraction. Current methods supported are file descriptors,
- sockets, socket accept, socket connect, memory buffer, buffering, SSL
- client/server, file pointer, encryption, digest, non-blocking testing
- and null.
-
- Data structures
- A dynamically growing hashing system
- A simple stack.
- A Configuration loader that uses a format similar to MS .ini files.
+ Provides general cryptographic and X.509 support needed by SSL/TLS but
+ not logically part of it.
openssl:
A command line tool that can be used for:
- Creation of RSA, DH and DSA key parameters
+ Creation of key parameters
Creation of X.509 certificates, CSRs and CRLs
- Calculation of Message Digests
- Encryption and Decryption with Ciphers
- SSL/TLS Client and Server Tests
+ Calculation of message digests
+ Encryption and decryption
+ SSL/TLS client and server tests
Handling of S/MIME signed or encrypted mail
-
-
- PATENTS
- -------
-
- Various companies hold various patents for various algorithms in various
- locations around the world. _YOU_ are responsible for ensuring that your use
- of any algorithms is legal by checking if there are any patents in your
- country. The file contains some of the patents that we know about or are
- rumored to exist. This is not a definitive list.
-
- RSA Security holds software patents on the RC5 algorithm. If you
- intend to use this cipher, you must contact RSA Security for
- licensing conditions. Their web page is http://www.rsasecurity.com/.
-
- RC4 is a trademark of RSA Security, so use of this label should perhaps
- only be used with RSA Security's permission.
-
- The IDEA algorithm is patented by Ascom in Austria, France, Germany, Italy,
- Japan, the Netherlands, Spain, Sweden, Switzerland, UK and the USA. They
- should be contacted if that algorithm is to be used; their web page is
- http://www.ascom.ch/.
-
- NTT and Mitsubishi have patents and pending patents on the Camellia
- algorithm, but allow use at no charge without requiring an explicit
- licensing agreement: http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html
+ And more...
INSTALLATION
------------
- To install this package under a Unix derivative, read the INSTALL file. For
- a Win32 platform, read the INSTALL.W32 file. For OpenVMS systems, read
- INSTALL.VMS.
-
- Read the documentation in the doc/ directory. It is quite rough, but it
- lists the functions; you will probably have to look at the code to work out
- how to use them. Look at the example programs.
-
- PROBLEMS
- --------
-
- For some platforms, there are some known problems that may affect the user
- or application author. We try to collect those in doc/PROBLEMS, with current
- thoughts on how they should be solved in a future of OpenSSL.
+ See the appropriate file:
+ INSTALL Linux, Unix, etc.
+ INSTALL.DJGPP DOS platform with DJGPP
+ INSTALL.NW Netware
+ INSTALL.OS2 OS/2
+ INSTALL.VMS VMS
+ INSTALL.W32 Windows (32bit)
+ INSTALL.W64 Windows (64bit)
+ INSTALL.WCE Windows CE
SUPPORT
-------
- See the OpenSSL website www.openssl.org for details of how to obtain
+ See the OpenSSL website www.openssl.org for details on how to obtain
commercial technical support.
If you have any problems with OpenSSL then please take the following steps
@@ -161,58 +84,36 @@
- Problem Description (steps that will reproduce the problem, if known)
- Stack Traceback (if the application dumps core)
- Report the bug to the OpenSSL project via the Request Tracker
- (http://www.openssl.org/support/rt.html) by mail to:
+ Email the report to:
- openssl-bugs@openssl.org
+ rt@openssl.org
- Note that the request tracker should NOT be used for general assistance
- or support queries. Just because something doesn't work the way you expect
- does not mean it is necessarily a bug in OpenSSL.
+ In order to avoid spam, this is a moderated mailing list, and it might
+ take a day for the ticket to show up. (We also scan posts to make sure
+ that security disclosures aren't publically posted by mistake.) Mail
+ to this address is recorded in the public RT (request tracker) database
+ (see https://www.openssl.org/community/index.html#bugs for details) and
+ also forwarded the public openssl-dev mailing list. Confidential mail
+ may be sent to openssl-security@openssl.org (PGP key available from the
+ key servers).
- Note that mail to openssl-bugs@openssl.org is recorded in the publicly
- readable request tracker database and is forwarded to a public
- mailing list. Confidential mail may be sent to openssl-security@openssl.org
- (PGP key available from the key servers).
+ Please do NOT use this for general assistance or support queries.
+ Just because something doesn't work the way you expect does not mean it
+ is necessarily a bug in OpenSSL.
+
+ You can also make GitHub pull requests. If you do this, please also send
+ mail to rt@openssl.org with a link to the PR so that we can more easily
+ keep track of it.
HOW TO CONTRIBUTE TO OpenSSL
----------------------------
- Development is coordinated on the openssl-dev mailing list (see
- http://www.openssl.org for information on subscribing). If you
- would like to submit a patch, send it to openssl-bugs@openssl.org with
- the string "[PATCH]" in the subject. Please be sure to include a
- textual explanation of what your patch does.
+ See CONTRIBUTING
- If you are unsure as to whether a feature will be useful for the general
- OpenSSL community please discuss it on the openssl-dev mailing list first.
- Someone may be already working on the same thing or there may be a good
- reason as to why that feature isn't implemented.
+ LEGALITIES
+ ----------
- Patches should be as up to date as possible, preferably relative to the
- current Git or the last snapshot. They should follow the coding style of
- OpenSSL and compile without warnings. Some of the core team developer targets
- can be used for testing purposes, (debug-steve64, debug-geoff etc). OpenSSL
- compiles on many varied platforms: try to ensure you only use portable
- features.
-
- Note: For legal reasons, contributions from the US can be accepted only
- if a TSU notification and a copy of the patch are sent to crypt@bis.doc.gov
- (formerly BXA) with a copy to the ENC Encryption Request Coordinator;
- please take some time to look at
- http://www.bis.doc.gov/Encryption/PubAvailEncSourceCodeNofify.html [sic]
- and
- http://w3.access.gpo.gov/bis/ear/pdf/740.pdf (EAR Section 740.13(e))
- for the details. If "your encryption source code is too large to serve as
- an email attachment", they are glad to receive it by fax instead; hope you
- have a cheap long-distance plan.
-
- Our preferred format for changes is "diff -u" output. You might
- generate it like this:
-
- # cd openssl-work
- # [your changes]
- # ./Configure dist; make clean
- # cd ..
- # diff -ur openssl-orig openssl-work > mydiffs.patch
-
+ A number of nations, in particular the U.S., restrict the use or export
+ of cryptography. If you are potentially subject to such restrictions
+ you should seek competent professional legal advice before attempting to
+ develop or distribute cryptographic code.
diff --git a/src/third_party/openssl/openssl/apps/Makefile b/src/third_party/openssl/openssl/apps/Makefile
index cafe554..8c3297e 100644
--- a/src/third_party/openssl/openssl/apps/Makefile
+++ b/src/third_party/openssl/openssl/apps/Makefile
@@ -135,7 +135,7 @@
depend: local_depend
@if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi
local_depend:
- @[ -z "$(THIS)" ] || $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(SRC); \
+ @[ -z "$(THIS)" ] || $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(SRC)
dclean:
$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
diff --git a/src/third_party/openssl/openssl/apps/apps.c b/src/third_party/openssl/openssl/apps/apps.c
index 6801238..8ab4833 100644
--- a/src/third_party/openssl/openssl/apps/apps.c
+++ b/src/third_party/openssl/openssl/apps/apps.c
@@ -119,9 +119,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#if !defined(OPENSSL_SYSNAME_WIN32) && !defined(NETWARE_CLIB)
-# include <strings.h>
-#endif
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
@@ -1247,7 +1244,11 @@
{"ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
{NULL, 0, 0}
};
- return set_multi_opts(flags, arg, ex_tbl);
+ if (set_multi_opts(flags, arg, ex_tbl) == 0)
+ return 0;
+ if ((*flags & XN_FLAG_SEP_MASK) == 0)
+ *flags |= XN_FLAG_SEP_CPLUS_SPC;
+ return 1;
}
int set_ext_copy(int *copy_type, const char *arg)
diff --git a/src/third_party/openssl/openssl/apps/asn1pars.c b/src/third_party/openssl/openssl/apps/asn1pars.c
index 11b0787..0a6b990 100644
--- a/src/third_party/openssl/openssl/apps/asn1pars.c
+++ b/src/third_party/openssl/openssl/apps/asn1pars.c
@@ -313,9 +313,9 @@
}
typ = ASN1_TYPE_get(at);
if ((typ == V_ASN1_OBJECT)
+ || (typ == V_ASN1_BOOLEAN)
|| (typ == V_ASN1_NULL)) {
- BIO_printf(bio_err, "Can't parse %s type\n",
- typ == V_ASN1_NULL ? "NULL" : "OBJECT");
+ BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ));
ERR_print_errors(bio_err);
goto end;
}
diff --git a/src/third_party/openssl/openssl/apps/ca.c b/src/third_party/openssl/openssl/apps/ca.c
index 97ad0c1..4d64eb2 100644
--- a/src/third_party/openssl/openssl/apps/ca.c
+++ b/src/third_party/openssl/openssl/apps/ca.c
@@ -99,25 +99,19 @@
#undef PROG
#define PROG ca_main
-#define BASE_SECTION "ca"
-#define CONFIG_FILE "openssl.cnf"
+#define BASE_SECTION "ca"
+#define CONFIG_FILE "openssl.cnf"
#define ENV_DEFAULT_CA "default_ca"
-#define STRING_MASK "string_mask"
+#define STRING_MASK "string_mask"
#define UTF8_IN "utf8"
-#define ENV_DIR "dir"
-#define ENV_CERTS "certs"
-#define ENV_CRL_DIR "crl_dir"
-#define ENV_CA_DB "CA_DB"
#define ENV_NEW_CERTS_DIR "new_certs_dir"
#define ENV_CERTIFICATE "certificate"
#define ENV_SERIAL "serial"
#define ENV_CRLNUMBER "crlnumber"
-#define ENV_CRL "crl"
#define ENV_PRIVATE_KEY "private_key"
-#define ENV_RANDFILE "RANDFILE"
#define ENV_DEFAULT_DAYS "default_days"
#define ENV_DEFAULT_STARTDATE "default_startdate"
#define ENV_DEFAULT_ENDDATE "default_enddate"
@@ -2520,6 +2514,8 @@
char **rrow, *a_tm_s;
a_tm = ASN1_UTCTIME_new();
+ if (a_tm == NULL)
+ return -1;
/* get actual time and make a string */
a_tm = X509_gmtime_adj(a_tm, 0);
diff --git a/src/third_party/openssl/openssl/apps/ecparam.c b/src/third_party/openssl/openssl/apps/ecparam.c
index 1f340a9..402fb31 100644
--- a/src/third_party/openssl/openssl/apps/ecparam.c
+++ b/src/third_party/openssl/openssl/apps/ecparam.c
@@ -413,14 +413,13 @@
}
if (check) {
- if (group == NULL)
- BIO_printf(bio_err, "no elliptic curve parameters\n");
BIO_printf(bio_err, "checking elliptic curve parameters: ");
if (!EC_GROUP_check(group, NULL)) {
BIO_printf(bio_err, "failed\n");
ERR_print_errors(bio_err);
- } else
- BIO_printf(bio_err, "ok\n");
+ goto end;
+ }
+ BIO_printf(bio_err, "ok\n");
}
diff --git a/src/third_party/openssl/openssl/apps/engine.c b/src/third_party/openssl/openssl/apps/engine.c
index 3d70cac..f54631b 100644
--- a/src/third_party/openssl/openssl/apps/engine.c
+++ b/src/third_party/openssl/openssl/apps/engine.c
@@ -1,4 +1,4 @@
-/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */
+/* apps/engine.c */
/*
* Written by Richard Levitte <richard@levitte.org> for the OpenSSL project
* 2000.
@@ -99,8 +99,6 @@
static int append_buf(char **buf, const char *s, int *size, int step)
{
- int l = strlen(s);
-
if (*buf == NULL) {
*size = step;
*buf = OPENSSL_malloc(*size);
@@ -109,9 +107,6 @@
**buf = '\0';
}
- if (**buf != '\0')
- l += 2; /* ", " */
-
if (strlen(*buf) + strlen(s) >= (unsigned int)*size) {
*size += step;
*buf = OPENSSL_realloc(*buf, *size);
diff --git a/src/third_party/openssl/openssl/apps/ocsp.c b/src/third_party/openssl/openssl/apps/ocsp.c
index 572f064..bb420c2 100644
--- a/src/third_party/openssl/openssl/apps/ocsp.c
+++ b/src/third_party/openssl/openssl/apps/ocsp.c
@@ -1003,7 +1003,7 @@
bs = OCSP_BASICRESP_new();
thisupd = X509_gmtime_adj(NULL, 0);
if (ndays != -1)
- nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24);
+ nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL);
/* Examine each certificate id in the request */
for (i = 0; i < id_count; i++) {
@@ -1220,8 +1220,8 @@
return NULL;
}
- if (BIO_get_fd(cbio, &fd) <= 0) {
- BIO_puts(err, "Can't get connection fd\n");
+ if (BIO_get_fd(cbio, &fd) < 0) {
+ BIO_puts(bio_err, "Can't get connection fd\n");
goto err;
}
diff --git a/src/third_party/openssl/openssl/apps/pkcs12.c b/src/third_party/openssl/openssl/apps/pkcs12.c
index 4ff6449..cbb75b7 100644
--- a/src/third_party/openssl/openssl/apps/pkcs12.c
+++ b/src/third_party/openssl/openssl/apps/pkcs12.c
@@ -79,7 +79,8 @@
# define CLCERTS 0x8
# define CACERTS 0x10
-int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain);
+static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) **chain);
int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen,
int options, char *pempass);
int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
@@ -134,13 +135,6 @@
apps_startup();
-# ifdef OPENSSL_FIPS
- if (FIPS_mode())
- cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
- else
-# endif
- cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
-
enc = EVP_des_ede3_cbc();
if (bio_err == NULL)
bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
@@ -148,6 +142,13 @@
if (!load_config(bio_err, NULL))
goto end;
+# ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+ else
+# endif
+ cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
+
args = argv + 1;
while (*args) {
@@ -594,7 +595,7 @@
vret = get_cert_chain(ucert, store, &chain2);
X509_STORE_free(store);
- if (!vret) {
+ if (vret == X509_V_OK) {
/* Exclude verified certificate */
for (i = 1; i < sk_X509_num(chain2); i++)
sk_X509_push(certs, sk_X509_value(chain2, i));
@@ -602,7 +603,7 @@
X509_free(sk_X509_value(chain2, 0));
sk_X509_free(chain2);
} else {
- if (vret >= 0)
+ if (vret != X509_V_ERR_UNSPECIFIED)
BIO_printf(bio_err, "Error %s getting chain.\n",
X509_verify_cert_error_string(vret));
else
@@ -906,36 +907,25 @@
/* Given a single certificate return a verified chain or NULL if error */
-/* Hope this is OK .... */
-
-int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain)
+static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) **chain)
{
X509_STORE_CTX store_ctx;
- STACK_OF(X509) *chn;
+ STACK_OF(X509) *chn = NULL;
int i = 0;
- /*
- * FIXME: Should really check the return status of X509_STORE_CTX_init
- * for an error, but how that fits into the return value of this function
- * is less obvious.
- */
- X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
- if (X509_verify_cert(&store_ctx) <= 0) {
- i = X509_STORE_CTX_get_error(&store_ctx);
- if (i == 0)
- /*
- * avoid returning 0 if X509_verify_cert() did not set an
- * appropriate error value in the context
- */
- i = -1;
- chn = NULL;
- goto err;
- } else
+ if (!X509_STORE_CTX_init(&store_ctx, store, cert, NULL)) {
+ *chain = NULL;
+ return X509_V_ERR_UNSPECIFIED;
+ }
+
+ if (X509_verify_cert(&store_ctx) > 0)
chn = X509_STORE_CTX_get1_chain(&store_ctx);
- err:
+ else if ((i = X509_STORE_CTX_get_error(&store_ctx)) == 0)
+ i = X509_V_ERR_UNSPECIFIED;
+
X509_STORE_CTX_cleanup(&store_ctx);
*chain = chn;
-
return i;
}
diff --git a/src/third_party/openssl/openssl/apps/s_client.c b/src/third_party/openssl/openssl/apps/s_client.c
index 28737b6..16833ac 100644
--- a/src/third_party/openssl/openssl/apps/s_client.c
+++ b/src/third_party/openssl/openssl/apps/s_client.c
@@ -1884,6 +1884,9 @@
EVP_PKEY_free(key);
if (pass)
OPENSSL_free(pass);
+#ifndef OPENSSL_NO_SRP
+ OPENSSL_free(srp_arg.srppassin);
+#endif
if (vpm)
X509_VERIFY_PARAM_free(vpm);
if (cbuf != NULL) {
diff --git a/src/third_party/openssl/openssl/apps/s_server.c b/src/third_party/openssl/openssl/apps/s_server.c
index b58e5e0..a8aee77 100644
--- a/src/third_party/openssl/openssl/apps/s_server.c
+++ b/src/third_party/openssl/openssl/apps/s_server.c
@@ -2654,6 +2654,21 @@
goto err;
} else {
BIO_printf(bio_s_out, "read R BLOCK\n");
+#ifndef OPENSSL_NO_SRP
+ if (BIO_should_io_special(io)
+ && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+ BIO_printf(bio_s_out, "LOOKUP renego during read\n");
+ srp_callback_parm.user =
+ SRP_VBASE_get_by_user(srp_callback_parm.vb,
+ srp_callback_parm.login);
+ if (srp_callback_parm.user)
+ BIO_printf(bio_s_out, "LOOKUP done %s\n",
+ srp_callback_parm.user->info);
+ else
+ BIO_printf(bio_s_out, "LOOKUP not successful\n");
+ continue;
+ }
+#endif
#if defined(OPENSSL_SYS_NETWARE)
delay(1000);
#elif !defined(OPENSSL_SYS_MSDOS) && !defined(__DJGPP__)
diff --git a/src/third_party/openssl/openssl/apps/speed.c b/src/third_party/openssl/openssl/apps/speed.c
index 7d9fd8a..ef72723 100644
--- a/src/third_party/openssl/openssl/apps/speed.c
+++ b/src/third_party/openssl/openssl/apps/speed.c
@@ -1,4 +1,4 @@
-/* apps/speed.c -*- mode:C; c-file-style: "eay" -*- */
+/* apps/speed.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/apps/x509.c b/src/third_party/openssl/openssl/apps/x509.c
index 929359b..e5fe610 100644
--- a/src/third_party/openssl/openssl/apps/x509.c
+++ b/src/third_party/openssl/openssl/apps/x509.c
@@ -1170,12 +1170,7 @@
if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
goto err;
- /* Lets just make it 12:00am GMT, Jan 1 1970 */
- /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
- /* 28 days to be certified */
-
- if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) ==
- NULL)
+ if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
goto err;
if (!X509_set_pubkey(x, pkey))
diff --git a/src/third_party/openssl/openssl/appveyor.yml b/src/third_party/openssl/openssl/appveyor.yml
new file mode 100644
index 0000000..8695359
--- /dev/null
+++ b/src/third_party/openssl/openssl/appveyor.yml
@@ -0,0 +1,60 @@
+platform:
+ - x86
+ - x64
+
+environment:
+ matrix:
+ - VSVER: 9
+ - VSVER: 10
+ - VSVER: 11
+ - VSVER: 12
+ - VSVER: 14
+
+configuration:
+ - plain
+ - shared
+
+matrix:
+ allow_failures:
+ - platform: x64
+ VSVER: 9
+ - platform: x64
+ VSVER: 10
+ - platform: x64
+ VSVER: 11
+
+before_build:
+ - ps: >-
+ If ($env:Platform -Match "x86") {
+ $env:VCVARS_PLATFORM="x86"
+ $env:TARGET="VC-WIN32"
+ $env:DO="do_ms"
+ } Else {
+ $env:VCVARS_PLATFORM="amd64"
+ $env:TARGET="VC-WIN64A"
+ $env:DO="do_win64a"
+ }
+ - ps: >-
+ If ($env:Configuration -Like "*shared*") {
+ $env:MAK="ntdll.mak"
+ } Else {
+ $env:MAK="nt.mak"
+ }
+ - ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS"))
+ - call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM%
+ - perl Configure %TARGET% no-asm
+ - call ms\%DO%
+
+build_script:
+ - nmake /f ms\%MAK%
+
+test_script:
+ - nmake /f ms\%MAK% test
+
+notifications:
+ - provider: Email
+ to:
+ - openssl-commits@openssl.org
+ on_build_success: false
+ on_build_failure: true
+ on_build_status_changed: true
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes.h b/src/third_party/openssl/openssl/crypto/aes/aes.h
index 56f166f..d052289 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes.h
+++ b/src/third_party/openssl/openssl/crypto/aes/aes.h
@@ -1,4 +1,4 @@
-/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes.h */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_cbc.c b/src/third_party/openssl/openssl/crypto/aes/aes_cbc.c
index e39231f..805d0e2 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_cbc.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_cbc.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_cbc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_cbc.c */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_cfb.c b/src/third_party/openssl/openssl/crypto/aes/aes_cfb.c
index 1c79ce2..1225000 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_cfb.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_cfb.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_cfb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_cfb.c */
/* ====================================================================
* Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_core.c b/src/third_party/openssl/openssl/crypto/aes/aes_core.c
index f32498f..6630d45 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_core.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_core.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_core.c */
/**
* rijndael-alg-fst.c
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_ctr.c b/src/third_party/openssl/openssl/crypto/aes/aes_ctr.c
index 3ee3822..9e760c4 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_ctr.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_ctr.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_ctr.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_ctr.c */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_ecb.c b/src/third_party/openssl/openssl/crypto/aes/aes_ecb.c
index 341e0bc..aad6b02 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_ecb.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_ecb.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_ecb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_ecb.c */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_ige.c b/src/third_party/openssl/openssl/crypto/aes/aes_ige.c
index cf31c9b..8f2b770 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_ige.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_ige.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_ige.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_ige.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_locl.h b/src/third_party/openssl/openssl/crypto/aes/aes_locl.h
index 4bf2e3a..3038b16 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_locl.h
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_locl.h
@@ -1,4 +1,4 @@
-/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes.h */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_misc.c b/src/third_party/openssl/openssl/crypto/aes/aes_misc.c
index ab948ad..fafad4d 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_misc.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_misc.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_misc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_misc.c */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_ofb.c b/src/third_party/openssl/openssl/crypto/aes/aes_ofb.c
index e6153f9..64a08ca 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_ofb.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_ofb.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_ofb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_ofb.c */
/* ====================================================================
* Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/aes_x86core.c b/src/third_party/openssl/openssl/crypto/aes/aes_x86core.c
index 1defbb1..428bd58 100644
--- a/src/third_party/openssl/openssl/crypto/aes/aes_x86core.c
+++ b/src/third_party/openssl/openssl/crypto/aes/aes_x86core.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_core.c */
/**
* rijndael-alg-fst.c
*
diff --git a/src/third_party/openssl/openssl/crypto/aes/asm/aes-586.pl b/src/third_party/openssl/openssl/crypto/aes/asm/aes-586.pl
index 687ed81..51b500d 100755
--- a/src/third_party/openssl/openssl/crypto/aes/asm/aes-586.pl
+++ b/src/third_party/openssl/openssl/crypto/aes/asm/aes-586.pl
@@ -45,7 +45,7 @@
# the undertaken effort was that it appeared that in tight IA-32
# register window little-endian flavor could achieve slightly higher
# Instruction Level Parallelism, and it indeed resulted in up to 15%
-# better performance on most recent µ-archs...
+# better performance on most recent µ-archs...
#
# Third version adds AES_cbc_encrypt implementation, which resulted in
# up to 40% performance imrovement of CBC benchmark results. 40% was
@@ -223,7 +223,7 @@
$speed_limit=512; # chunks smaller than $speed_limit are
# processed with compact routine in CBC mode
$small_footprint=1; # $small_footprint=1 code is ~5% slower [on
- # recent µ-archs], but ~5 times smaller!
+ # recent µ-archs], but ~5 times smaller!
# I favor compact code to minimize cache
# contention and in hope to "collect" 5% back
# in real-life applications...
@@ -562,7 +562,7 @@
# Performance is not actually extraordinary in comparison to pure
# x86 code. In particular encrypt performance is virtually the same.
# Decrypt performance on the other hand is 15-20% better on newer
-# µ-archs [but we're thankful for *any* improvement here], and ~50%
+# µ-archs [but we're thankful for *any* improvement here], and ~50%
# better on PIII:-) And additionally on the pros side this code
# eliminates redundant references to stack and thus relieves/
# minimizes the pressure on the memory bus.
diff --git a/src/third_party/openssl/openssl/crypto/aes/asm/aesni-x86.pl b/src/third_party/openssl/openssl/crypto/aes/asm/aesni-x86.pl
index 3dc345b..8c1d0b5 100644
--- a/src/third_party/openssl/openssl/crypto/aes/asm/aesni-x86.pl
+++ b/src/third_party/openssl/openssl/crypto/aes/asm/aesni-x86.pl
@@ -74,7 +74,7 @@
$inout4="xmm6"; $in0="xmm6";
$inout5="xmm7"; $ivec="xmm7";
-# AESNI extenstion
+# AESNI extension
sub aeskeygenassist
{ my($dst,$src,$imm)=@_;
if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
diff --git a/src/third_party/openssl/openssl/crypto/asn1/asn1_par.c b/src/third_party/openssl/openssl/crypto/asn1/asn1_par.c
index 22013b9..c4cbf23 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/asn1_par.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/asn1_par.c
@@ -65,6 +65,10 @@
#include <openssl/objects.h>
#include <openssl/asn1.h>
+#ifndef ASN1_PARSE_MAXDEPTH
+#define ASN1_PARSE_MAXDEPTH 128
+#endif
+
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
int indent);
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
@@ -131,6 +135,12 @@
#else
dump_indent = 6; /* Because we know BIO_dump_indent() */
#endif
+
+ if (depth > ASN1_PARSE_MAXDEPTH) {
+ BIO_puts(bp, "BAD RECURSION DEPTH\n");
+ return 0;
+ }
+
p = *pp;
tot = p + length;
op = p - 1;
diff --git a/src/third_party/openssl/openssl/crypto/asn1/d2i_pr.c b/src/third_party/openssl/openssl/crypto/asn1/d2i_pr.c
index a66e876..b25e8a9 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/d2i_pr.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/d2i_pr.c
@@ -75,6 +75,7 @@
long length)
{
EVP_PKEY *ret;
+ const unsigned char *p = *pp;
if ((a == NULL) || (*a == NULL)) {
if ((ret = EVP_PKEY_new()) == NULL) {
@@ -97,21 +98,23 @@
}
if (!ret->ameth->old_priv_decode ||
- !ret->ameth->old_priv_decode(ret, pp, length)) {
+ !ret->ameth->old_priv_decode(ret, &p, length)) {
if (ret->ameth->priv_decode) {
PKCS8_PRIV_KEY_INFO *p8 = NULL;
- p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, pp, length);
+ p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
if (!p8)
goto err;
EVP_PKEY_free(ret);
ret = EVP_PKCS82PKEY(p8);
PKCS8_PRIV_KEY_INFO_free(p8);
-
+ if (ret == NULL)
+ goto err;
} else {
ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
goto err;
}
}
+ *pp = p;
if (a != NULL)
(*a) = ret;
return (ret);
@@ -139,6 +142,7 @@
* input is surrounded by an ASN1 SEQUENCE.
*/
inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
+ p = *pp;
/*
* Since we only need to discern "traditional format" RSA and DSA keys we
* can just count the elements.
@@ -149,7 +153,7 @@
keytype = EVP_PKEY_EC;
else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
* traditional format */
- PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, pp, length);
+ PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
EVP_PKEY *ret;
sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
@@ -160,6 +164,9 @@
}
ret = EVP_PKCS82PKEY(p8);
PKCS8_PRIV_KEY_INFO_free(p8);
+ if (ret == NULL)
+ return NULL;
+ *pp = p;
if (a) {
*a = ret;
}
diff --git a/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c b/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
index 8c1d715..3dce02f 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
@@ -183,6 +183,8 @@
int otag;
int ret = 0;
ASN1_VALUE **pchptr, *ptmpval;
+ int combine = aclass & ASN1_TFLG_COMBINE;
+ aclass &= ~ASN1_TFLG_COMBINE;
if (!pval)
return 0;
if (aux && aux->asn1_cb)
@@ -353,9 +355,9 @@
}
asn1_set_choice_selector(pval, i, it);
- *in = p;
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
goto auxerr;
+ *in = p;
return 1;
case ASN1_ITYPE_NDEF_SEQUENCE:
@@ -492,9 +494,9 @@
/* Save encoding */
if (!asn1_enc_save(pval, *in, p - *in, it))
goto auxerr;
- *in = p;
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
goto auxerr;
+ *in = p;
return 1;
default:
@@ -503,7 +505,8 @@
auxerr:
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR);
err:
- ASN1_item_ex_free(pval, it);
+ if (combine == 0)
+ ASN1_item_ex_free(pval, it);
if (errtt)
ERR_add_error_data(4, "Field=", errtt->field_name,
", Type=", it->sname);
@@ -692,7 +695,7 @@
} else {
/* Nothing special */
ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
- -1, 0, opt, ctx);
+ -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx);
if (!ret) {
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR);
goto err;
diff --git a/src/third_party/openssl/openssl/crypto/asn1/x_bignum.c b/src/third_party/openssl/openssl/crypto/asn1/x_bignum.c
index d8d95f0..fa91799 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/x_bignum.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/x_bignum.c
@@ -144,8 +144,9 @@
int utype, char *free_cont, const ASN1_ITEM *it)
{
BIGNUM *bn;
- if (!*pval)
- bn_new(pval, it);
+
+ if (*pval == NULL && !bn_new(pval, it))
+ return 0;
bn = (BIGNUM *)*pval;
if (!BN_bin2bn(cont, len, bn)) {
bn_free(pval, it);
diff --git a/src/third_party/openssl/openssl/crypto/asn1/x_pubkey.c b/src/third_party/openssl/openssl/crypto/asn1/x_pubkey.c
index 61e2d44..965e02c 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/x_pubkey.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/x_pubkey.c
@@ -191,13 +191,16 @@
{
X509_PUBKEY *xpk;
EVP_PKEY *pktmp;
- xpk = d2i_X509_PUBKEY(NULL, pp, length);
+ const unsigned char *q;
+ q = *pp;
+ xpk = d2i_X509_PUBKEY(NULL, &q, length);
if (!xpk)
return NULL;
pktmp = X509_PUBKEY_get(xpk);
X509_PUBKEY_free(xpk);
if (!pktmp)
return NULL;
+ *pp = q;
if (a) {
EVP_PKEY_free(*a);
*a = pktmp;
diff --git a/src/third_party/openssl/openssl/crypto/asn1/x_x509.c b/src/third_party/openssl/openssl/crypto/asn1/x_x509.c
index 3858333..5bc89bd 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/x_x509.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/x_x509.c
@@ -183,16 +183,15 @@
if (!a || *a == NULL) {
freeret = 1;
}
- ret = d2i_X509(a, pp, length);
+ ret = d2i_X509(a, &q, length);
/* If certificate unreadable then forget it */
if (!ret)
return NULL;
/* update length */
- length -= *pp - q;
- if (!length)
- return ret;
- if (!d2i_X509_CERT_AUX(&ret->aux, pp, length))
+ length -= q - *pp;
+ if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length))
goto err;
+ *pp = q;
return ret;
err:
if (freeret) {
diff --git a/src/third_party/openssl/openssl/crypto/bio/b_dump.c b/src/third_party/openssl/openssl/crypto/bio/b_dump.c
index f43e6a5..3846654 100644
--- a/src/third_party/openssl/openssl/crypto/bio/b_dump.c
+++ b/src/third_party/openssl/openssl/crypto/bio/b_dump.c
@@ -107,7 +107,6 @@
if ((rows * dump_width) < len)
rows++;
for (i = 0; i < rows; i++) {
- buf[0] = '\0'; /* start with empty string */
BUF_strlcpy(buf, str, sizeof buf);
BIO_snprintf(tmp, sizeof tmp, "%04x - ", i * dump_width);
BUF_strlcat(buf, tmp, sizeof buf);
diff --git a/src/third_party/openssl/openssl/crypto/bio/bio.h b/src/third_party/openssl/openssl/crypto/bio/bio.h
index 195b5cc..814cbe8 100644
--- a/src/third_party/openssl/openssl/crypto/bio/bio.h
+++ b/src/third_party/openssl/openssl/crypto/bio/bio.h
@@ -481,11 +481,11 @@
# define BIO_get_conn_hostname(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)
# define BIO_get_conn_port(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)
# define BIO_get_conn_ip(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)
-# define BIO_get_conn_int_port(b) BIO_int_ctrl(b,BIO_C_GET_CONNECT,3,0)
+# define BIO_get_conn_int_port(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,0,NULL)
# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
-/* BIO_s_accept_socket() */
+/* BIO_s_accept() */
# define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name)
# define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)
/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */
@@ -498,6 +498,7 @@
# define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
# define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
+/* BIO_s_accept() and BIO_s_connect() */
# define BIO_do_connect(b) BIO_do_handshake(b)
# define BIO_do_accept(b) BIO_do_handshake(b)
# define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
@@ -517,12 +518,15 @@
# define BIO_get_url(b,url) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url))
# define BIO_get_no_connect_return(b) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL)
+/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */
# define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd)
# define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c)
+/* BIO_s_file() */
# define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp)
# define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp)
+/* BIO_s_fd() and BIO_s_file() */
# define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
# define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
diff --git a/src/third_party/openssl/openssl/crypto/bio/bss_bio.c b/src/third_party/openssl/openssl/crypto/bio/bss_bio.c
index ba88afb..c04d7ca 100644
--- a/src/third_party/openssl/openssl/crypto/bio/bss_bio.c
+++ b/src/third_party/openssl/openssl/crypto/bio/bss_bio.c
@@ -1,4 +1,4 @@
-/* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */
+/* crypto/bio/bss_bio.c */
/* ====================================================================
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/bio/bss_conn.c b/src/third_party/openssl/openssl/crypto/bio/bss_conn.c
index 6a5e8de..ed214ca 100644
--- a/src/third_party/openssl/openssl/crypto/bio/bss_conn.c
+++ b/src/third_party/openssl/openssl/crypto/bio/bss_conn.c
@@ -419,7 +419,7 @@
{
BIO *dbio;
int *ip;
- const char **pptr;
+ const char **pptr = NULL;
long ret = 1;
BIO_CONNECT *data;
@@ -442,19 +442,28 @@
case BIO_C_GET_CONNECT:
if (ptr != NULL) {
pptr = (const char **)ptr;
- if (num == 0) {
- *pptr = data->param_hostname;
+ }
- } else if (num == 1) {
- *pptr = data->param_port;
- } else if (num == 2) {
- *pptr = (char *)&(data->ip[0]);
- } else if (num == 3) {
- *((int *)ptr) = data->port;
+ if (b->init) {
+ if (pptr != NULL) {
+ ret = 1;
+ if (num == 0) {
+ *pptr = data->param_hostname;
+ } else if (num == 1) {
+ *pptr = data->param_port;
+ } else if (num == 2) {
+ *pptr = (char *)&(data->ip[0]);
+ } else {
+ ret = 0;
+ }
}
- if ((!b->init) || (ptr == NULL))
+ if (num == 3) {
+ ret = data->port;
+ }
+ } else {
+ if (pptr != NULL)
*pptr = "not initialized";
- ret = 1;
+ ret = 0;
}
break;
case BIO_C_SET_CONNECT:
diff --git a/src/third_party/openssl/openssl/crypto/bio/bss_dgram.c b/src/third_party/openssl/openssl/crypto/bio/bss_dgram.c
index e3e3dd0..d12b83a 100644
--- a/src/third_party/openssl/openssl/crypto/bio/bss_dgram.c
+++ b/src/third_party/openssl/openssl/crypto/bio/bss_dgram.c
@@ -515,10 +515,8 @@
switch (cmd) {
case BIO_CTRL_RESET:
num = 0;
- case BIO_C_FILE_SEEK:
ret = 0;
break;
- case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = 0;
break;
diff --git a/src/third_party/openssl/openssl/crypto/bio/bss_file.c b/src/third_party/openssl/openssl/crypto/bio/bss_file.c
index 56abcb1..a815d8e 100644
--- a/src/third_party/openssl/openssl/crypto/bio/bss_file.c
+++ b/src/third_party/openssl/openssl/crypto/bio/bss_file.c
@@ -118,33 +118,9 @@
NULL,
};
-BIO *BIO_new_file(const char *filename, const char *mode)
+# if !defined(OPENSSL_SYS_STARBOARD)
+static FILE *file_fopen(const char *filename, const char *mode)
{
- BIO *ret = NULL;
-# if defined(OPENSSL_SYS_STARBOARD)
- SbFile sb_file = kSbFileInvalid;
- SbFileError error = kSbFileOk;
- sb_file = SbFileOpen(filename, SbFileModeStringToFlags(mode), NULL, &error);
- if (!SbFileIsValid(sb_file)) {
- SYSerr(SYS_F_FOPEN, error);
- ERR_add_error_data(5, "SbFileOpen('", filename, "','", mode, "')");
- if (error == kSbFileErrorNotFound) {
- BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE);
- } else {
- BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB);
- }
-
- return (NULL);
- }
- ret = BIO_new(BIO_s_file());
- if (ret == NULL) {
- SbFileClose(sb_file);
- return (NULL);
- }
-
- BIO_clear_flags(ret, BIO_FLAGS_UPLINK);
- BIO_set_fp(ret, sb_file, BIO_CLOSE);
-# else // defined(OPENSSL_SYS_STARBOARD)
FILE *file = NULL;
# if defined(_WIN32) && defined(CP_UTF8)
@@ -191,6 +167,40 @@
# else
file = fopen(filename, mode);
# endif
+ return (file);
+}
+
+#endif // defined(OPENSSL_SYS_STARBOARD)
+
+BIO *BIO_new_file(const char *filename, const char *mode)
+{
+ BIO *ret = NULL;
+# if defined(OPENSSL_SYS_STARBOARD)
+ SbFile sb_file = kSbFileInvalid;
+ SbFileError error = kSbFileOk;
+ sb_file = SbFileOpen(filename, SbFileModeStringToFlags(mode), NULL, &error);
+ if (!SbFileIsValid(sb_file)) {
+ SYSerr(SYS_F_FOPEN, error);
+ ERR_add_error_data(5, "SbFileOpen('", filename, "','", mode, "')");
+ if (error == kSbFileErrorNotFound) {
+ BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE);
+ } else {
+ BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB);
+ }
+
+ return (NULL);
+ }
+ ret = BIO_new(BIO_s_file());
+ if (ret == NULL) {
+ SbFileClose(sb_file);
+ return (NULL);
+ }
+
+ BIO_clear_flags(ret, BIO_FLAGS_UPLINK);
+ BIO_set_fp(ret, sb_file, BIO_CLOSE);
+# else // defined(OPENSSL_SYS_STARBOARD)
+ FILE *file = file_fopen(filename, mode);
+
if (file == NULL) {
SYSerr(SYS_F_FOPEN, get_last_sys_error());
ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
diff --git a/src/third_party/openssl/openssl/crypto/bn/asm/armv4-gf2m.pl b/src/third_party/openssl/openssl/crypto/bn/asm/armv4-gf2m.pl
index c52e0b7..22ad1f8 100644
--- a/src/third_party/openssl/openssl/crypto/bn/asm/armv4-gf2m.pl
+++ b/src/third_party/openssl/openssl/crypto/bn/asm/armv4-gf2m.pl
@@ -41,13 +41,13 @@
.align 5
mul_1x1_neon:
vshl.u64 `&Dlo("q1")`,d16,#8 @ q1-q3 are slided $a
- vmull.p8 `&Q("d0")`,d16,d17 @ a·bb
+ vmull.p8 `&Q("d0")`,d16,d17 @ a·bb
vshl.u64 `&Dlo("q2")`,d16,#16
- vmull.p8 q1,`&Dlo("q1")`,d17 @ a<<8·bb
+ vmull.p8 q1,`&Dlo("q1")`,d17 @ a<<8·bb
vshl.u64 `&Dlo("q3")`,d16,#24
- vmull.p8 q2,`&Dlo("q2")`,d17 @ a<<16·bb
+ vmull.p8 q2,`&Dlo("q2")`,d17 @ a<<16·bb
vshr.u64 `&Dlo("q1")`,#8
- vmull.p8 q3,`&Dlo("q3")`,d17 @ a<<24·bb
+ vmull.p8 q3,`&Dlo("q3")`,d17 @ a<<24·bb
vshl.u64 `&Dhi("q1")`,#24
veor d0,`&Dlo("q1")`
vshr.u64 `&Dlo("q2")`,#16
@@ -158,7 +158,7 @@
################
# void bn_GF2m_mul_2x2(BN_ULONG *r,
# BN_ULONG a1,BN_ULONG a0,
-# BN_ULONG b1,BN_ULONG b0); # r[3..0]=a1a0·b1b0
+# BN_ULONG b1,BN_ULONG b0); # r[3..0]=a1a0·b1b0
($A1,$B1,$A0,$B0,$A1B1,$A0B0)=map("d$_",(18..23));
@@ -184,20 +184,20 @@
vmov d16,$A1
vmov d17,$B1
- bl mul_1x1_neon @ a1·b1
+ bl mul_1x1_neon @ a1·b1
vmov $A1B1,d0
vmov d16,$A0
vmov d17,$B0
- bl mul_1x1_neon @ a0·b0
+ bl mul_1x1_neon @ a0·b0
vmov $A0B0,d0
veor d16,$A0,$A1
veor d17,$B0,$B1
veor $A0,$A0B0,$A1B1
- bl mul_1x1_neon @ (a0+a1)·(b0+b1)
+ bl mul_1x1_neon @ (a0+a1)·(b0+b1)
- veor d0,$A0 @ (a0+a1)·(b0+b1)-a0·b0-a1·b1
+ veor d0,$A0 @ (a0+a1)·(b0+b1)-a0·b0-a1·b1
vshl.u64 d1,d0,#32
vshr.u64 d0,d0,#32
veor $A0B0,d1
@@ -220,7 +220,7 @@
mov $mask,#7<<2
sub sp,sp,#32 @ allocate tab[8]
- bl mul_1x1_ialu @ a1·b1
+ bl mul_1x1_ialu @ a1·b1
str $lo,[$ret,#8]
str $hi,[$ret,#12]
@@ -230,13 +230,13 @@
eor r2,r2,$a
eor $b,$b,r3
eor $a,$a,r2
- bl mul_1x1_ialu @ a0·b0
+ bl mul_1x1_ialu @ a0·b0
str $lo,[$ret]
str $hi,[$ret,#4]
eor $a,$a,r2
eor $b,$b,r3
- bl mul_1x1_ialu @ (a1+a0)·(b1+b0)
+ bl mul_1x1_ialu @ (a1+a0)·(b1+b0)
___
@r=map("r$_",(6..9));
$code.=<<___;
diff --git a/src/third_party/openssl/openssl/crypto/bn/asm/ia64.S b/src/third_party/openssl/openssl/crypto/bn/asm/ia64.S
index 951abc5..a9a42ab 100644
--- a/src/third_party/openssl/openssl/crypto/bn/asm/ia64.S
+++ b/src/third_party/openssl/openssl/crypto/bn/asm/ia64.S
@@ -422,7 +422,7 @@
// This loop spins in 3*(n+10) ticks on Itanium and in 2*(n+10) on
// Itanium 2. Yes, unlike previous versions it scales:-) Previous
-// version was peforming *all* additions in IALU and was starving
+// version was performing *all* additions in IALU and was starving
// for those even on Itanium 2. In this version one addition is
// moved to FPU and is folded with multiplication. This is at cost
// of propogating the result from previous call to this subroutine
@@ -568,7 +568,7 @@
// I've estimated this routine to run in ~120 ticks, but in reality
// (i.e. according to ar.itc) it takes ~160 ticks. Are those extra
// cycles consumed for instructions fetch? Or did I misinterpret some
-// clause in Itanium µ-architecture manual? Comments are welcomed and
+// clause in Itanium µ-architecture manual? Comments are welcomed and
// highly appreciated.
//
// On Itanium 2 it takes ~190 ticks. This is because of stalls on
diff --git a/src/third_party/openssl/openssl/crypto/bn/asm/s390x-gf2m.pl b/src/third_party/openssl/openssl/crypto/bn/asm/s390x-gf2m.pl
index cd9f13e..9d18d40 100644
--- a/src/third_party/openssl/openssl/crypto/bn/asm/s390x-gf2m.pl
+++ b/src/third_party/openssl/openssl/crypto/bn/asm/s390x-gf2m.pl
@@ -172,19 +172,19 @@
if ($SIZE_T==8) {
my @r=map("%r$_",(6..9));
$code.=<<___;
- bras $ra,_mul_1x1 # a1·b1
+ bras $ra,_mul_1x1 # a1·b1
stmg $lo,$hi,16($rp)
lg $a,`$stdframe+128+4*$SIZE_T`($sp)
lg $b,`$stdframe+128+6*$SIZE_T`($sp)
- bras $ra,_mul_1x1 # a0·b0
+ bras $ra,_mul_1x1 # a0·b0
stmg $lo,$hi,0($rp)
lg $a,`$stdframe+128+3*$SIZE_T`($sp)
lg $b,`$stdframe+128+5*$SIZE_T`($sp)
xg $a,`$stdframe+128+4*$SIZE_T`($sp)
xg $b,`$stdframe+128+6*$SIZE_T`($sp)
- bras $ra,_mul_1x1 # (a0+a1)·(b0+b1)
+ bras $ra,_mul_1x1 # (a0+a1)·(b0+b1)
lmg @r[0],@r[3],0($rp)
xgr $lo,$hi
diff --git a/src/third_party/openssl/openssl/crypto/bn/asm/x86-gf2m.pl b/src/third_party/openssl/openssl/crypto/bn/asm/x86-gf2m.pl
index 808a1e5..b579530 100644
--- a/src/third_party/openssl/openssl/crypto/bn/asm/x86-gf2m.pl
+++ b/src/third_party/openssl/openssl/crypto/bn/asm/x86-gf2m.pl
@@ -14,7 +14,7 @@
# the time being... Except that it has three code paths: pure integer
# code suitable for any x86 CPU, MMX code suitable for PIII and later
# and PCLMULQDQ suitable for Westmere and later. Improvement varies
-# from one benchmark and µ-arch to another. Below are interval values
+# from one benchmark and µ-arch to another. Below are interval values
# for 163- and 571-bit ECDH benchmarks relative to compiler-generated
# code:
#
@@ -226,22 +226,22 @@
&push ("edi");
&mov ($a,&wparam(1));
&mov ($b,&wparam(3));
- &call ("_mul_1x1_mmx"); # a1·b1
+ &call ("_mul_1x1_mmx"); # a1·b1
&movq ("mm7",$R);
&mov ($a,&wparam(2));
&mov ($b,&wparam(4));
- &call ("_mul_1x1_mmx"); # a0·b0
+ &call ("_mul_1x1_mmx"); # a0·b0
&movq ("mm6",$R);
&mov ($a,&wparam(1));
&mov ($b,&wparam(3));
&xor ($a,&wparam(2));
&xor ($b,&wparam(4));
- &call ("_mul_1x1_mmx"); # (a0+a1)·(b0+b1)
+ &call ("_mul_1x1_mmx"); # (a0+a1)·(b0+b1)
&pxor ($R,"mm7");
&mov ($a,&wparam(0));
- &pxor ($R,"mm6"); # (a0+a1)·(b0+b1)-a1·b1-a0·b0
+ &pxor ($R,"mm6"); # (a0+a1)·(b0+b1)-a1·b1-a0·b0
&movq ($A,$R);
&psllq ($R,32);
@@ -266,13 +266,13 @@
&mov ($a,&wparam(1));
&mov ($b,&wparam(3));
- &call ("_mul_1x1_ialu"); # a1·b1
+ &call ("_mul_1x1_ialu"); # a1·b1
&mov (&DWP(8,"esp"),$lo);
&mov (&DWP(12,"esp"),$hi);
&mov ($a,&wparam(2));
&mov ($b,&wparam(4));
- &call ("_mul_1x1_ialu"); # a0·b0
+ &call ("_mul_1x1_ialu"); # a0·b0
&mov (&DWP(0,"esp"),$lo);
&mov (&DWP(4,"esp"),$hi);
@@ -280,7 +280,7 @@
&mov ($b,&wparam(3));
&xor ($a,&wparam(2));
&xor ($b,&wparam(4));
- &call ("_mul_1x1_ialu"); # (a0+a1)·(b0+b1)
+ &call ("_mul_1x1_ialu"); # (a0+a1)·(b0+b1)
&mov ("ebp",&wparam(0));
@r=("ebx","ecx","edi","esi");
diff --git a/src/third_party/openssl/openssl/crypto/bn/asm/x86_64-gcc.c b/src/third_party/openssl/openssl/crypto/bn/asm/x86_64-gcc.c
index 9c5074b..0a5bb28 100644
--- a/src/third_party/openssl/openssl/crypto/bn/asm/x86_64-gcc.c
+++ b/src/third_party/openssl/openssl/crypto/bn/asm/x86_64-gcc.c
@@ -66,7 +66,7 @@
# undef sqr
/*-
- * "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
+ * "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
* "g"(0) let the compiler to decide where does it
* want to keep the value of zero;
*/
diff --git a/src/third_party/openssl/openssl/crypto/bn/asm/x86_64-gf2m.pl b/src/third_party/openssl/openssl/crypto/bn/asm/x86_64-gf2m.pl
index 226c66c..42bbec2 100644
--- a/src/third_party/openssl/openssl/crypto/bn/asm/x86_64-gf2m.pl
+++ b/src/third_party/openssl/openssl/crypto/bn/asm/x86_64-gf2m.pl
@@ -13,7 +13,7 @@
# in bn_gf2m.c. It's kind of low-hanging mechanical port from C for
# the time being... Except that it has two code paths: code suitable
# for any x86_64 CPU and PCLMULQDQ one suitable for Westmere and
-# later. Improvement varies from one benchmark and µ-arch to another.
+# later. Improvement varies from one benchmark and µ-arch to another.
# Vanilla code path is at most 20% faster than compiler-generated code
# [not very impressive], while PCLMULQDQ - whole 85%-160% better on
# 163- and 571-bit ECDH benchmarks on Intel CPUs. Keep in mind that
@@ -184,13 +184,13 @@
$code.=<<___;
movdqa %xmm0,%xmm4
movdqa %xmm1,%xmm5
- pclmulqdq \$0,%xmm1,%xmm0 # a1·b1
+ pclmulqdq \$0,%xmm1,%xmm0 # a1·b1
pxor %xmm2,%xmm4
pxor %xmm3,%xmm5
- pclmulqdq \$0,%xmm3,%xmm2 # a0·b0
- pclmulqdq \$0,%xmm5,%xmm4 # (a0+a1)·(b0+b1)
+ pclmulqdq \$0,%xmm3,%xmm2 # a0·b0
+ pclmulqdq \$0,%xmm5,%xmm4 # (a0+a1)·(b0+b1)
xorps %xmm0,%xmm4
- xorps %xmm2,%xmm4 # (a0+a1)·(b0+b1)-a0·b0-a1·b1
+ xorps %xmm2,%xmm4 # (a0+a1)·(b0+b1)-a0·b0-a1·b1
movdqa %xmm4,%xmm5
pslldq \$8,%xmm4
psrldq \$8,%xmm5
@@ -225,13 +225,13 @@
mov \$0xf,$mask
mov $a1,$a
mov $b1,$b
- call _mul_1x1 # a1·b1
+ call _mul_1x1 # a1·b1
mov $lo,16(%rsp)
mov $hi,24(%rsp)
mov 48(%rsp),$a
mov 64(%rsp),$b
- call _mul_1x1 # a0·b0
+ call _mul_1x1 # a0·b0
mov $lo,0(%rsp)
mov $hi,8(%rsp)
@@ -239,7 +239,7 @@
mov 56(%rsp),$b
xor 48(%rsp),$a
xor 64(%rsp),$b
- call _mul_1x1 # (a0+a1)·(b0+b1)
+ call _mul_1x1 # (a0+a1)·(b0+b1)
___
@r=("%rbx","%rcx","%rdi","%rsi");
$code.=<<___;
diff --git a/src/third_party/openssl/openssl/crypto/bn/bn_exp.c b/src/third_party/openssl/openssl/crypto/bn/bn_exp.c
index 5bb3e7a..6b5fe2b 100644
--- a/src/third_party/openssl/openssl/crypto/bn/bn_exp.c
+++ b/src/third_party/openssl/openssl/crypto/bn/bn_exp.c
@@ -278,9 +278,14 @@
}
bits = BN_num_bits(p);
-
if (bits == 0) {
- ret = BN_one(r);
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m)) {
+ ret = 1;
+ BN_zero(r);
+ } else {
+ ret = BN_one(r);
+ }
return ret;
}
@@ -414,7 +419,13 @@
}
bits = BN_num_bits(p);
if (bits == 0) {
- ret = BN_one(rr);
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m)) {
+ ret = 1;
+ BN_zero(rr);
+ } else {
+ ret = BN_one(rr);
+ }
return ret;
}
@@ -586,7 +597,7 @@
* precomputation memory layout to limit data-dependency to a minimum to
* protect secret exponents (cf. the hyper-threading timing attacks pointed
* out by Colin Percival,
- * http://www.daemong-consideredperthreading-considered-harmful/)
+ * http://www.daemonology.net/hyperthreading-considered-harmful/)
*/
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
@@ -606,15 +617,22 @@
bn_check_top(p);
bn_check_top(m);
- top = m->top;
-
- if (!(m->d[0] & 1)) {
+ if (!BN_is_odd(m)) {
BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME, BN_R_CALLED_WITH_EVEN_MODULUS);
return (0);
}
+
+ top = m->top;
+
bits = BN_num_bits(p);
if (bits == 0) {
- ret = BN_one(rr);
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m)) {
+ ret = 1;
+ BN_zero(rr);
+ } else {
+ ret = BN_one(rr);
+ }
return ret;
}
@@ -914,8 +932,9 @@
if (BN_is_one(m)) {
ret = 1;
BN_zero(rr);
- } else
+ } else {
ret = BN_one(rr);
+ }
return ret;
}
if (a == 0) {
@@ -1029,9 +1048,14 @@
}
bits = BN_num_bits(p);
-
- if (bits == 0) {
- ret = BN_one(r);
+ if (bits == 0) {
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m)) {
+ ret = 1;
+ BN_zero(r);
+ } else {
+ ret = BN_one(r);
+ }
return ret;
}
diff --git a/src/third_party/openssl/openssl/crypto/bn/bn_gcd.c b/src/third_party/openssl/openssl/crypto/bn/bn_gcd.c
index 97c55ab..ce59fe7 100644
--- a/src/third_party/openssl/openssl/crypto/bn/bn_gcd.c
+++ b/src/third_party/openssl/openssl/crypto/bn/bn_gcd.c
@@ -583,6 +583,7 @@
* BN_div_no_branch will be called eventually.
*/
pB = &local_B;
+ local_B.flags = 0;
BN_with_flags(pB, B, BN_FLG_CONSTTIME);
if (!BN_nnmod(B, pB, A, ctx))
goto err;
@@ -610,6 +611,7 @@
* BN_div_no_branch will be called eventually.
*/
pA = &local_A;
+ local_A.flags = 0;
BN_with_flags(pA, A, BN_FLG_CONSTTIME);
/* (D, M) := (A/B, A%B) ... */
diff --git a/src/third_party/openssl/openssl/crypto/bn/bn_gf2m.c b/src/third_party/openssl/openssl/crypto/bn/bn_gf2m.c
index eb7c21d..f009744 100644
--- a/src/third_party/openssl/openssl/crypto/bn/bn_gf2m.c
+++ b/src/third_party/openssl/openssl/crypto/bn/bn_gf2m.c
@@ -579,7 +579,7 @@
bn_check_top(a);
BN_CTX_start(ctx);
if ((s = BN_CTX_get(ctx)) == NULL)
- return 0;
+ goto err;
if (!bn_wexpand(s, 2 * a->top))
goto err;
@@ -703,18 +703,21 @@
int top = p->top;
BN_ULONG *udp, *bdp, *vdp, *cdp;
- bn_wexpand(u, top);
+ if (!bn_wexpand(u, top))
+ goto err;
udp = u->d;
for (i = u->top; i < top; i++)
udp[i] = 0;
u->top = top;
- bn_wexpand(b, top);
+ if (!bn_wexpand(b, top))
+ goto err;
bdp = b->d;
bdp[0] = 1;
for (i = 1; i < top; i++)
bdp[i] = 0;
b->top = top;
- bn_wexpand(c, top);
+ if (!bn_wexpand(c, top))
+ goto err;
cdp = c->d;
for (i = 0; i < top; i++)
cdp[i] = 0;
diff --git a/src/third_party/openssl/openssl/crypto/bn/bn_mont.c b/src/third_party/openssl/openssl/crypto/bn/bn_mont.c
index 0c92530..f5add2d 100644
--- a/src/third_party/openssl/openssl/crypto/bn/bn_mont.c
+++ b/src/third_party/openssl/openssl/crypto/bn/bn_mont.c
@@ -364,9 +364,9 @@
if (mont == NULL)
return;
- BN_free(&(mont->RR));
- BN_free(&(mont->N));
- BN_free(&(mont->Ni));
+ BN_clear_free(&(mont->RR));
+ BN_clear_free(&(mont->N));
+ BN_clear_free(&(mont->Ni));
if (mont->flags & BN_FLG_MALLOCED)
OPENSSL_free(mont);
}
@@ -376,6 +376,9 @@
int ret = 0;
BIGNUM *Ri, *R;
+ if (BN_is_zero(mod))
+ return 0;
+
BN_CTX_start(ctx);
if ((Ri = BN_CTX_get(ctx)) == NULL)
goto err;
diff --git a/src/third_party/openssl/openssl/crypto/bn/bn_recp.c b/src/third_party/openssl/openssl/crypto/bn/bn_recp.c
index 1f77bc5..027573c 100644
--- a/src/third_party/openssl/openssl/crypto/bn/bn_recp.c
+++ b/src/third_party/openssl/openssl/crypto/bn/bn_recp.c
@@ -155,8 +155,10 @@
if (BN_ucmp(m, &(recp->N)) < 0) {
BN_zero(d);
- if (!BN_copy(r, m))
+ if (!BN_copy(r, m)) {
+ BN_CTX_end(ctx);
return 0;
+ }
BN_CTX_end(ctx);
return (1);
}
diff --git a/src/third_party/openssl/openssl/crypto/bn/bn_x931p.c b/src/third_party/openssl/openssl/crypto/bn/bn_x931p.c
index 6d76b12..efa48bd 100644
--- a/src/third_party/openssl/openssl/crypto/bn/bn_x931p.c
+++ b/src/third_party/openssl/openssl/crypto/bn/bn_x931p.c
@@ -213,14 +213,14 @@
* exceeded.
*/
if (!BN_rand(Xp, nbits, 1, 0))
- return 0;
+ goto err;
BN_CTX_start(ctx);
t = BN_CTX_get(ctx);
for (i = 0; i < 1000; i++) {
if (!BN_rand(Xq, nbits, 1, 0))
- return 0;
+ goto err;
/* Check that |Xp - Xq| > 2^(nbits - 100) */
BN_sub(t, Xp, Xq);
if (BN_num_bits(t) > (nbits - 100))
@@ -234,6 +234,9 @@
return 0;
+ err:
+ BN_CTX_end(ctx);
+ return 0;
}
/*
diff --git a/src/third_party/openssl/openssl/crypto/bn/bntest.c b/src/third_party/openssl/openssl/crypto/bn/bntest.c
index 06662c5..6d55049 100644
--- a/src/third_party/openssl/openssl/crypto/bn/bntest.c
+++ b/src/third_party/openssl/openssl/crypto/bn/bntest.c
@@ -441,6 +441,14 @@
BN_init(&d);
BN_init(&e);
+ BN_one(&a);
+ BN_zero(&b);
+
+ if (BN_div(&d, &c, &a, &b, ctx)) {
+ fprintf(stderr, "Division by zero succeeded!\n");
+ return 0;
+ }
+
for (i = 0; i < num0 + num1; i++) {
if (i < num1) {
BN_bntest_rand(&a, 400, 0, 0);
@@ -516,9 +524,9 @@
do {
BN_bntest_rand(&a, 512, -1, 0);
BN_bntest_rand(&b, BN_BITS2, -1, 0);
- s = b.d[0];
- } while (!s);
+ } while (BN_is_zero(&b));
+ s = b.d[0];
BN_copy(&b, &a);
r = BN_div_word(&b, s);
@@ -781,6 +789,18 @@
if (mont == NULL)
return 0;
+ BN_zero(&n);
+ if (BN_MONT_CTX_set(mont, &n, ctx)) {
+ fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n");
+ return 0;
+ }
+
+ BN_set_word(&n, 16);
+ if (BN_MONT_CTX_set(mont, &n, ctx)) {
+ fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n");
+ return 0;
+ }
+
BN_bntest_rand(&a, 100, 0, 0);
BN_bntest_rand(&b, 100, 0, 0);
for (i = 0; i < num2; i++) {
@@ -887,6 +907,14 @@
d = BN_new();
e = BN_new();
+ BN_one(a);
+ BN_one(b);
+ BN_zero(c);
+ if (BN_mod_mul(e, a, b, c, ctx)) {
+ fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n");
+ return 0;
+ }
+
for (j = 0; j < 3; j++) {
BN_bntest_rand(c, 1024, 0, 0);
for (i = 0; i < num0; i++) {
@@ -952,6 +980,14 @@
d = BN_new();
e = BN_new();
+ BN_one(a);
+ BN_one(b);
+ BN_zero(c);
+ if (BN_mod_exp(d, a, b, c, ctx)) {
+ fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n");
+ return 0;
+ }
+
BN_bntest_rand(c, 30, 0, 1); /* must be odd for montgomery */
for (i = 0; i < num2; i++) {
BN_bntest_rand(a, 20 + i * 5, 0, 0);
@@ -999,6 +1035,22 @@
d = BN_new();
e = BN_new();
+ BN_one(a);
+ BN_one(b);
+ BN_zero(c);
+ if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
+ fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus "
+ "succeeded\n");
+ return 0;
+ }
+
+ BN_set_word(c, 16);
+ if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
+ fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus "
+ "succeeded\n");
+ return 0;
+ }
+
BN_bntest_rand(c, 30, 0, 1); /* must be odd for montgomery */
for (i = 0; i < num2; i++) {
BN_bntest_rand(a, 20 + i * 5, 0, 0);
diff --git a/src/third_party/openssl/openssl/crypto/bn/exptest.c b/src/third_party/openssl/openssl/crypto/bn/exptest.c
index 8b3a4ba..ac611c2 100644
--- a/src/third_party/openssl/openssl/crypto/bn/exptest.c
+++ b/src/third_party/openssl/openssl/crypto/bn/exptest.c
@@ -73,14 +73,34 @@
"string to make the random number generator think it has entropy";
/*
+ * Test that r == 0 in test_exp_mod_zero(). Returns one on success,
+ * returns zero and prints debug output otherwise.
+ */
+static int a_is_zero_mod_one(const char *method, const BIGNUM *r,
+ const BIGNUM *a) {
+ if (!BN_is_zero(r)) {
+ fprintf(stderr, "%s failed:\n", method);
+ fprintf(stderr, "a ** 0 mod 1 = r (should be 0)\n");
+ fprintf(stderr, "a = ");
+ BN_print_fp(stderr, a);
+ fprintf(stderr, "\nr = ");
+ BN_print_fp(stderr, r);
+ fprintf(stderr, "\n");
+ return 0;
+ }
+ return 1;
+}
+
+/*
* test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success.
*/
static int test_exp_mod_zero()
{
BIGNUM a, p, m;
BIGNUM r;
+ BN_ULONG one_word = 1;
BN_CTX *ctx = BN_CTX_new();
- int ret = 1;
+ int ret = 1, failed = 0;
BN_init(&m);
BN_one(&m);
@@ -92,21 +112,65 @@
BN_zero(&p);
BN_init(&r);
- BN_mod_exp(&r, &a, &p, &m, ctx);
- BN_CTX_free(ctx);
- if (BN_is_zero(&r))
- ret = 0;
- else {
- printf("1**0 mod 1 = ");
- BN_print_fp(stdout, &r);
- printf(", should be 0\n");
+ if (!BN_rand(&a, 1024, 0, 0))
+ goto err;
+
+ if (!BN_mod_exp(&r, &a, &p, &m, ctx))
+ goto err;
+
+ if (!a_is_zero_mod_one("BN_mod_exp", &r, &a))
+ failed = 1;
+
+ if (!BN_mod_exp_recp(&r, &a, &p, &m, ctx))
+ goto err;
+
+ if (!a_is_zero_mod_one("BN_mod_exp_recp", &r, &a))
+ failed = 1;
+
+ if (!BN_mod_exp_simple(&r, &a, &p, &m, ctx))
+ goto err;
+
+ if (!a_is_zero_mod_one("BN_mod_exp_simple", &r, &a))
+ failed = 1;
+
+ if (!BN_mod_exp_mont(&r, &a, &p, &m, ctx, NULL))
+ goto err;
+
+ if (!a_is_zero_mod_one("BN_mod_exp_mont", &r, &a))
+ failed = 1;
+
+ if (!BN_mod_exp_mont_consttime(&r, &a, &p, &m, ctx, NULL)) {
+ goto err;
}
+ if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", &r, &a))
+ failed = 1;
+
+ /*
+ * A different codepath exists for single word multiplication
+ * in non-constant-time only.
+ */
+ if (!BN_mod_exp_mont_word(&r, one_word, &p, &m, ctx, NULL))
+ goto err;
+
+ if (!BN_is_zero(&r)) {
+ fprintf(stderr, "BN_mod_exp_mont_word failed:\n");
+ fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n");
+ fprintf(stderr, "r = ");
+ BN_print_fp(stderr, &r);
+ fprintf(stderr, "\n");
+ return 0;
+ }
+
+ ret = failed;
+
+ err:
BN_free(&r);
BN_free(&a);
BN_free(&p);
BN_free(&m);
+ BN_CTX_free(ctx);
return ret;
}
diff --git a/src/third_party/openssl/openssl/crypto/buffer/buf_str.c b/src/third_party/openssl/openssl/crypto/buffer/buf_str.c
index 4997367..dcd523d 100644
--- a/src/third_party/openssl/openssl/crypto/buffer/buf_str.c
+++ b/src/third_party/openssl/openssl/crypto/buffer/buf_str.c
@@ -61,12 +61,13 @@
#include <stdio.h>
#endif // !defined(OPENSSL_SYS_STARBOARD)
#include "cryptlib.h"
+#include <limits.h>
#include <openssl/buffer.h>
char *BUF_strdup(const char *str)
{
if (str == NULL)
- return (NULL);
+ return NULL;
return BUF_strndup(str, OPENSSL_port_strlen(str));
}
@@ -75,14 +76,20 @@
char *ret;
if (str == NULL)
- return (NULL);
+ return NULL;
+
+ if (siz >= INT_MAX)
+ return NULL;
ret = OPENSSL_malloc(siz + 1);
if (ret == NULL) {
BUFerr(BUF_F_BUF_STRNDUP, ERR_R_MALLOC_FAILURE);
- return (NULL);
+ return NULL;
}
- BUF_strlcpy(ret, str, siz + 1);
+
+ OPENSSL_port_memcpy(ret, str, siz);
+ ret[siz] = '\0';
+
return (ret);
}
@@ -90,13 +97,13 @@
{
void *ret;
- if (data == NULL)
- return (NULL);
+ if (data == NULL || siz >= INT_MAX)
+ return NULL;
ret = OPENSSL_malloc(siz);
if (ret == NULL) {
BUFerr(BUF_F_BUF_MEMDUP, ERR_R_MALLOC_FAILURE);
- return (NULL);
+ return NULL;
}
return OPENSSL_port_memcpy(ret, data, siz);
}
diff --git a/src/third_party/openssl/openssl/crypto/buffer/buffer.h b/src/third_party/openssl/openssl/crypto/buffer/buffer.h
index 0818aae..1a8fa5d 100644
--- a/src/third_party/openssl/openssl/crypto/buffer/buffer.h
+++ b/src/third_party/openssl/openssl/crypto/buffer/buffer.h
@@ -88,7 +88,13 @@
int BUF_MEM_grow(BUF_MEM *str, size_t len);
int BUF_MEM_grow_clean(BUF_MEM *str, size_t len);
char *BUF_strdup(const char *str);
+
+/*
+ * Like strndup, but in addition, explicitly guarantees to never read past the
+ * first |siz| bytes of |str|.
+ */
char *BUF_strndup(const char *str, size_t siz);
+
void *BUF_memdup(const void *data, size_t siz);
void BUF_reverse(unsigned char *out, const unsigned char *in, size_t siz);
diff --git a/src/third_party/openssl/openssl/crypto/camellia/camellia.c b/src/third_party/openssl/openssl/crypto/camellia/camellia.c
index b4a6766..719fa61 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/camellia.c
+++ b/src/third_party/openssl/openssl/crypto/camellia/camellia.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia.c */
/* ====================================================================
* Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) .
* ALL RIGHTS RESERVED.
@@ -67,7 +67,7 @@
/*
* Algorithm Specification
- * http://info.isl.llia/specicrypt/eng/camellia/specifications.html
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
*/
/*
diff --git a/src/third_party/openssl/openssl/crypto/camellia/camellia.h b/src/third_party/openssl/openssl/crypto/camellia/camellia.h
index 6b5bbf6..8612f8b 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/camellia.h
+++ b/src/third_party/openssl/openssl/crypto/camellia/camellia.h
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia.h */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/camellia/cmll_cbc.c b/src/third_party/openssl/openssl/crypto/camellia/cmll_cbc.c
index a4907ca..4017e00 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/cmll_cbc.c
+++ b/src/third_party/openssl/openssl/crypto/camellia/cmll_cbc.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_cbc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_cbc.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/camellia/cmll_cfb.c b/src/third_party/openssl/openssl/crypto/camellia/cmll_cfb.c
index 59b8522..78f2ae4 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/cmll_cfb.c
+++ b/src/third_party/openssl/openssl/crypto/camellia/cmll_cfb.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_cfb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_cfb.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/camellia/cmll_ctr.c b/src/third_party/openssl/openssl/crypto/camellia/cmll_ctr.c
index b8f523d..95e2662 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/cmll_ctr.c
+++ b/src/third_party/openssl/openssl/crypto/camellia/cmll_ctr.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_ctr.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_ctr.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/camellia/cmll_ecb.c b/src/third_party/openssl/openssl/crypto/camellia/cmll_ecb.c
index 16f1af8..b030791 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/cmll_ecb.c
+++ b/src/third_party/openssl/openssl/crypto/camellia/cmll_ecb.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_ecb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_ecb.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/camellia/cmll_locl.h b/src/third_party/openssl/openssl/crypto/camellia/cmll_locl.h
index 4e4707b..2bd79b8 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/cmll_locl.h
+++ b/src/third_party/openssl/openssl/crypto/camellia/cmll_locl.h
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_locl.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_locl.h */
/* ====================================================================
* Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) .
* ALL RIGHTS RESERVED.
diff --git a/src/third_party/openssl/openssl/crypto/camellia/cmll_misc.c b/src/third_party/openssl/openssl/crypto/camellia/cmll_misc.c
index cbd2502..694d2fa 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/cmll_misc.c
+++ b/src/third_party/openssl/openssl/crypto/camellia/cmll_misc.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_misc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_misc.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/camellia/cmll_ofb.c b/src/third_party/openssl/openssl/crypto/camellia/cmll_ofb.c
index 46c3ae2..85eb892 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/cmll_ofb.c
+++ b/src/third_party/openssl/openssl/crypto/camellia/cmll_ofb.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_ofb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_ofb.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/camellia/cmll_utl.c b/src/third_party/openssl/openssl/crypto/camellia/cmll_utl.c
index d19ee19..d5eb6b4 100644
--- a/src/third_party/openssl/openssl/crypto/camellia/cmll_utl.c
+++ b/src/third_party/openssl/openssl/crypto/camellia/cmll_utl.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/cmll_utl.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/cmll_utl.c */
/* ====================================================================
* Copyright (c) 2011 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/cms/cms_enc.c b/src/third_party/openssl/openssl/crypto/cms/cms_enc.c
index 85ae928..b14b4b6 100644
--- a/src/third_party/openssl/openssl/crypto/cms/cms_enc.c
+++ b/src/third_party/openssl/openssl/crypto/cms/cms_enc.c
@@ -195,7 +195,7 @@
ok = 1;
err:
- if (ec->key && !keep_key) {
+ if (ec->key && (!keep_key || !ok)) {
OPENSSL_cleanse(ec->key, ec->keylen);
OPENSSL_free(ec->key);
ec->key = NULL;
diff --git a/src/third_party/openssl/openssl/crypto/cms/cms_pwri.c b/src/third_party/openssl/openssl/crypto/cms/cms_pwri.c
index a8322dc..b91c016 100644
--- a/src/third_party/openssl/openssl/crypto/cms/cms_pwri.c
+++ b/src/third_party/openssl/openssl/crypto/cms/cms_pwri.c
@@ -121,6 +121,9 @@
/* Setup algorithm identifier for cipher */
encalg = X509_ALGOR_new();
+ if (encalg == NULL) {
+ goto merr;
+ }
EVP_CIPHER_CTX_init(&ctx);
if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0) {
diff --git a/src/third_party/openssl/openssl/crypto/cms/cms_smime.c b/src/third_party/openssl/openssl/crypto/cms/cms_smime.c
index 8b37560..f45693a 100644
--- a/src/third_party/openssl/openssl/crypto/cms/cms_smime.c
+++ b/src/third_party/openssl/openssl/crypto/cms/cms_smime.c
@@ -714,7 +714,7 @@
BIO *cmsbio;
int ret = 0;
if (!(cmsbio = CMS_dataInit(cms, dcont))) {
- CMSerr(CMS_F_CMS_FINAL, ERR_R_MALLOC_FAILURE);
+ CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_LIB);
return 0;
}
diff --git a/src/third_party/openssl/openssl/crypto/comp/c_zlib.c b/src/third_party/openssl/openssl/crypto/comp/c_zlib.c
index 6731af8..9c32614 100644
--- a/src/third_party/openssl/openssl/crypto/comp/c_zlib.c
+++ b/src/third_party/openssl/openssl/crypto/comp/c_zlib.c
@@ -404,8 +404,9 @@
void COMP_zlib_cleanup(void)
{
#ifdef ZLIB_SHARED
- if (zlib_dso)
+ if (zlib_dso != NULL)
DSO_free(zlib_dso);
+ zlib_dso = NULL;
#endif
}
diff --git a/src/third_party/openssl/openssl/crypto/conf/conf_def.c b/src/third_party/openssl/openssl/crypto/conf/conf_def.c
index f70b2d0..d1a81fb 100644
--- a/src/third_party/openssl/openssl/crypto/conf/conf_def.c
+++ b/src/third_party/openssl/openssl/crypto/conf/conf_def.c
@@ -228,12 +228,11 @@
goto err;
}
- section = (char *)OPENSSL_malloc(10);
+ section = BUF_strdup("default");
if (section == NULL) {
CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
goto err;
}
- BUF_strlcpy(section, "default", 10);
if (_CONF_new_data(conf) == 0) {
CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
diff --git a/src/third_party/openssl/openssl/crypto/conf/conf_sap.c b/src/third_party/openssl/openssl/crypto/conf/conf_sap.c
index ce49e0e..33e3f72 100644
--- a/src/third_party/openssl/openssl/crypto/conf/conf_sap.c
+++ b/src/third_party/openssl/openssl/crypto/conf/conf_sap.c
@@ -93,6 +93,7 @@
CONF_modules_load_file(NULL, config_name,
CONF_MFLAGS_DEFAULT_SECTION |
CONF_MFLAGS_IGNORE_MISSING_FILE);
+ openssl_configured = 1;
}
void OPENSSL_no_config()
diff --git a/src/third_party/openssl/openssl/crypto/cryptlib.c b/src/third_party/openssl/openssl/crypto/cryptlib.c
index 3d2c1b4..62c859f 100644
--- a/src/third_party/openssl/openssl/crypto/cryptlib.c
+++ b/src/third_party/openssl/openssl/crypto/cryptlib.c
@@ -941,13 +941,29 @@
# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
/* this -------------v--- guards NT-specific calls */
if (check_winnt() && OPENSSL_isservice() > 0) {
- HANDLE h = RegisterEventSource(0, _T("OPENSSL"));
- const TCHAR *pmsg = buf;
- ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 0, 0, 1, 0, &pmsg, 0);
- DeregisterEventSource(h);
+ HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL"));
+
+ if (hEventLog != NULL) {
+ const TCHAR *pmsg = buf;
+
+ if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL,
+ 1, 0, &pmsg, NULL)) {
+#if defined(DEBUG)
+ /*
+ * We are in a situation where we tried to report a critical
+ * error and this failed for some reason. As a last resort,
+ * in debug builds, send output to the debugger or any other
+ * tool like DebugView which can monitor the output.
+ */
+ OutputDebugString(pmsg);
+#endif
+ }
+
+ (void)DeregisterEventSource(hEventLog);
+ }
} else
# endif
- MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONSTOP);
+ MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);
}
#else
void OPENSSL_showfatal(const char *fmta, ...)
diff --git a/src/third_party/openssl/openssl/crypto/des/des_old.c b/src/third_party/openssl/openssl/crypto/des/des_old.c
index 54b0968..c5c5a00 100644
--- a/src/third_party/openssl/openssl/crypto/des/des_old.c
+++ b/src/third_party/openssl/openssl/crypto/des/des_old.c
@@ -1,4 +1,4 @@
-/* crypto/des/des_old.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/des/des_old.c */
/*-
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
diff --git a/src/third_party/openssl/openssl/crypto/des/des_old.h b/src/third_party/openssl/openssl/crypto/des/des_old.h
index f1e1e2c..ee7607a 100644
--- a/src/third_party/openssl/openssl/crypto/des/des_old.h
+++ b/src/third_party/openssl/openssl/crypto/des/des_old.h
@@ -1,4 +1,4 @@
-/* crypto/des/des_old.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/des/des_old.h */
/*-
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
diff --git a/src/third_party/openssl/openssl/crypto/des/des_old2.c b/src/third_party/openssl/openssl/crypto/des/des_old2.c
index f7d28a6..247ff8d 100644
--- a/src/third_party/openssl/openssl/crypto/des/des_old2.c
+++ b/src/third_party/openssl/openssl/crypto/des/des_old2.c
@@ -1,4 +1,4 @@
-/* crypto/des/des_old.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/des/des_old.c */
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING The
diff --git a/src/third_party/openssl/openssl/crypto/dsa/dsa_ameth.c b/src/third_party/openssl/openssl/crypto/dsa/dsa_ameth.c
index c448c4e..11d57f2 100644
--- a/src/third_party/openssl/openssl/crypto/dsa/dsa_ameth.c
+++ b/src/third_party/openssl/openssl/crypto/dsa/dsa_ameth.c
@@ -321,6 +321,7 @@
dplen = i2d_ASN1_INTEGER(prkey, &dp);
ASN1_STRING_clear_free(prkey);
+ prkey = NULL;
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0,
V_ASN1_SEQUENCE, params, dp, dplen))
diff --git a/src/third_party/openssl/openssl/crypto/dsa/dsa_gen.c b/src/third_party/openssl/openssl/crypto/dsa/dsa_gen.c
index fd94005..bf683f4 100644
--- a/src/third_party/openssl/openssl/crypto/dsa/dsa_gen.c
+++ b/src/third_party/openssl/openssl/crypto/dsa/dsa_gen.c
@@ -115,16 +115,8 @@
}
# endif
else {
- const EVP_MD *evpmd;
- size_t qbits = bits >= 2048 ? 256 : 160;
-
- if (bits >= 2048) {
- qbits = 256;
- evpmd = EVP_sha256();
- } else {
- qbits = 160;
- evpmd = EVP_sha1();
- }
+ const EVP_MD *evpmd = bits >= 2048 ? EVP_sha256() : EVP_sha1();
+ size_t qbits = EVP_MD_size(evpmd) * 8;
return dsa_builtin_paramgen(ret, bits, qbits, evpmd,
seed_in, seed_len, NULL, counter_ret,
@@ -177,13 +169,14 @@
if (seed_in != NULL)
OPENSSL_port_memcpy(seed, seed_in, seed_len);
- if ((ctx = BN_CTX_new()) == NULL)
- goto err;
-
if ((mont = BN_MONT_CTX_new()) == NULL)
goto err;
+ if ((ctx = BN_CTX_new()) == NULL)
+ goto err;
+
BN_CTX_start(ctx);
+
r0 = BN_CTX_get(ctx);
g = BN_CTX_get(ctx);
W = BN_CTX_get(ctx);
@@ -204,7 +197,7 @@
if (!BN_GENCB_call(cb, 0, m++))
goto err;
- if (!seed_len) {
+ if (!seed_len || !seed_in) {
if (RAND_pseudo_bytes(seed, qsize) < 0)
goto err;
seed_is_random = 1;
diff --git a/src/third_party/openssl/openssl/crypto/dsa/dsa_ossl.c b/src/third_party/openssl/openssl/crypto/dsa/dsa_ossl.c
index 4e4af03..725c700 100644
--- a/src/third_party/openssl/openssl/crypto/dsa/dsa_ossl.c
+++ b/src/third_party/openssl/openssl/crypto/dsa/dsa_ossl.c
@@ -190,9 +190,6 @@
if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))
goto err;
- ret = DSA_SIG_new();
- if (ret == NULL)
- goto err;
/*
* Redo if r or s is zero as required by FIPS 186-3: this is very
* unlikely.
@@ -204,11 +201,14 @@
}
goto redo;
}
+ ret = DSA_SIG_new();
+ if (ret == NULL)
+ goto err;
ret->r = r;
ret->s = s;
err:
- if (!ret) {
+ if (ret == NULL) {
DSAerr(DSA_F_DSA_DO_SIGN, reason);
BN_free(r);
BN_free(s);
diff --git a/src/third_party/openssl/openssl/crypto/dso/dso.h b/src/third_party/openssl/openssl/crypto/dso/dso.h
index 7c4a1dc..c9013f5 100644
--- a/src/third_party/openssl/openssl/crypto/dso/dso.h
+++ b/src/third_party/openssl/openssl/crypto/dso/dso.h
@@ -1,4 +1,4 @@
-/* dso.h -*- mode:C; c-file-style: "eay" -*- */
+/* dso.h */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/crypto/dso/dso_dl.c b/src/third_party/openssl/openssl/crypto/dso/dso_dl.c
index 0087ac5..ceedf66 100644
--- a/src/third_party/openssl/openssl/crypto/dso/dso_dl.c
+++ b/src/third_party/openssl/openssl/crypto/dso/dso_dl.c
@@ -1,4 +1,4 @@
-/* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */
+/* dso_dl.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/crypto/dso/dso_dlfcn.c b/src/third_party/openssl/openssl/crypto/dso/dso_dlfcn.c
index f629f03..78df723 100644
--- a/src/third_party/openssl/openssl/crypto/dso/dso_dlfcn.c
+++ b/src/third_party/openssl/openssl/crypto/dso/dso_dlfcn.c
@@ -1,4 +1,4 @@
-/* dso_dlfcn.c -*- mode:C; c-file-style: "eay" -*- */
+/* dso_dlfcn.c */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/crypto/dso/dso_lib.c b/src/third_party/openssl/openssl/crypto/dso/dso_lib.c
index 09b8eaf..3312450 100644
--- a/src/third_party/openssl/openssl/crypto/dso/dso_lib.c
+++ b/src/third_party/openssl/openssl/crypto/dso/dso_lib.c
@@ -1,4 +1,4 @@
-/* dso_lib.c -*- mode:C; c-file-style: "eay" -*- */
+/* dso_lib.c */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/crypto/dso/dso_vms.c b/src/third_party/openssl/openssl/crypto/dso/dso_vms.c
index d0794b8..1efd84b 100644
--- a/src/third_party/openssl/openssl/crypto/dso/dso_vms.c
+++ b/src/third_party/openssl/openssl/crypto/dso/dso_vms.c
@@ -1,4 +1,4 @@
-/* dso_vms.c -*- mode:C; c-file-style: "eay" -*- */
+/* dso_vms.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/crypto/dso/dso_win32.c b/src/third_party/openssl/openssl/crypto/dso/dso_win32.c
index 54c943d..eaf1831 100644
--- a/src/third_party/openssl/openssl/crypto/dso/dso_win32.c
+++ b/src/third_party/openssl/openssl/crypto/dso/dso_win32.c
@@ -1,4 +1,4 @@
-/* dso_win32.c -*- mode:C; c-file-style: "eay" -*- */
+/* dso_win32.c */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/crypto/ec/ec.h b/src/third_party/openssl/openssl/crypto/ec/ec.h
index c4e7aea..2a935fd 100644
--- a/src/third_party/openssl/openssl/crypto/ec/ec.h
+++ b/src/third_party/openssl/openssl/crypto/ec/ec.h
@@ -106,7 +106,7 @@
/** the point is encoded as z||x, where the octet z specifies
* which solution of the quadratic equation y is */
POINT_CONVERSION_COMPRESSED = 2,
- /** the point is encoded as z||x||y, where z is the octet 0x02 */
+ /** the point is encoded as z||x||y, where z is the octet 0x04 */
POINT_CONVERSION_UNCOMPRESSED = 4,
/** the point is encoded as z||x||y, where the octet z specifies
* which solution of the quadratic equation y is */
diff --git a/src/third_party/openssl/openssl/crypto/ec/ec_asn1.c b/src/third_party/openssl/openssl/crypto/ec/ec_asn1.c
index 0bf3146..929884e 100644
--- a/src/third_party/openssl/openssl/crypto/ec/ec_asn1.c
+++ b/src/third_party/openssl/openssl/crypto/ec/ec_asn1.c
@@ -973,8 +973,9 @@
{
EC_GROUP *group = NULL;
ECPKPARAMETERS *params = NULL;
+ const unsigned char *p = *in;
- if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) {
+ if ((params = d2i_ECPKPARAMETERS(NULL, &p, len)) == NULL) {
ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
ECPKPARAMETERS_free(params);
return NULL;
@@ -992,6 +993,7 @@
*a = group;
ECPKPARAMETERS_free(params);
+ *in = p;
return (group);
}
@@ -1019,8 +1021,9 @@
int ok = 0;
EC_KEY *ret = NULL;
EC_PRIVATEKEY *priv_key = NULL;
+ const unsigned char *p = *in;
- if ((priv_key = d2i_EC_PRIVATEKEY(NULL, in, len)) == NULL) {
+ if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL) {
ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
return NULL;
}
@@ -1099,6 +1102,7 @@
if (a)
*a = ret;
+ *in = p;
ok = 1;
err:
if (!ok) {
diff --git a/src/third_party/openssl/openssl/crypto/ec/ec_key.c b/src/third_party/openssl/openssl/crypto/ec/ec_key.c
index b39b7e9..c99db5a 100644
--- a/src/third_party/openssl/openssl/crypto/ec/ec_key.c
+++ b/src/third_party/openssl/openssl/crypto/ec/ec_key.c
@@ -369,7 +369,10 @@
BN_CTX *ctx = NULL;
BIGNUM *tx, *ty;
EC_POINT *point = NULL;
- int ok = 0, tmp_nid, is_char_two = 0;
+ int ok = 0;
+#ifndef OPENSSL_NO_EC2M
+ int tmp_nid, is_char_two = 0;
+#endif
if (!key || !key->group || !x || !y) {
ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
@@ -385,14 +388,15 @@
if (!point)
goto err;
+ tx = BN_CTX_get(ctx);
+ ty = BN_CTX_get(ctx);
+
+#ifndef OPENSSL_NO_EC2M
tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
if (tmp_nid == NID_X9_62_characteristic_two_field)
is_char_two = 1;
- tx = BN_CTX_get(ctx);
- ty = BN_CTX_get(ctx);
-#ifndef OPENSSL_NO_EC2M
if (is_char_two) {
if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
x, y, ctx))
diff --git a/src/third_party/openssl/openssl/crypto/ec/ectest.c b/src/third_party/openssl/openssl/crypto/ec/ectest.c
index fede530..efab0b0 100644
--- a/src/third_party/openssl/openssl/crypto/ec/ectest.c
+++ b/src/third_party/openssl/openssl/crypto/ec/ectest.c
@@ -1591,7 +1591,7 @@
int degree;
/*
* Qx, Qy and D are taken from
- * http://csrcdocut.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
* Otherwise, values are standard curve parameters from FIPS 180-3
*/
const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
diff --git a/src/third_party/openssl/openssl/crypto/engine/eng_all.c b/src/third_party/openssl/openssl/crypto/engine/eng_all.c
index 7edf12e..66c4374 100644
--- a/src/third_party/openssl/openssl/crypto/engine/eng_all.c
+++ b/src/third_party/openssl/openssl/crypto/engine/eng_all.c
@@ -1,4 +1,4 @@
-/* crypto/engine/eng_all.c -*- mode: C; c-file-style: "eay" -*- */
+/* crypto/engine/eng_all.c */
/*
* Written by Richard Levitte <richard@levitte.org> for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/crypto/engine/eng_cryptodev.c b/src/third_party/openssl/openssl/crypto/engine/eng_cryptodev.c
index bcb936d..a8a24d0 100644
--- a/src/third_party/openssl/openssl/crypto/engine/eng_cryptodev.c
+++ b/src/third_party/openssl/openssl/crypto/engine/eng_cryptodev.c
@@ -1230,15 +1230,18 @@
if (cryptodev_asym(&kop, BN_num_bytes(dsa->q), r,
BN_num_bytes(dsa->q), s) == 0) {
dsaret = DSA_SIG_new();
+ if (dsaret == NULL)
+ goto err;
dsaret->r = r;
dsaret->s = s;
+ r = s = NULL;
} else {
const DSA_METHOD *meth = DSA_OpenSSL();
- BN_free(r);
- BN_free(s);
dsaret = (meth->dsa_do_sign) (dgst, dlen, dsa);
}
err:
+ BN_free(r);
+ BN_free(s);
kop.crk_param[0].crp_p = NULL;
zapparams(&kop);
return (dsaret);
diff --git a/src/third_party/openssl/openssl/crypto/engine/eng_list.c b/src/third_party/openssl/openssl/crypto/engine/eng_list.c
index 3384e31..83c95d5 100644
--- a/src/third_party/openssl/openssl/crypto/engine/eng_list.c
+++ b/src/third_party/openssl/openssl/crypto/engine/eng_list.c
@@ -260,6 +260,7 @@
}
if ((e->id == NULL) || (e->name == NULL)) {
ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_ID_OR_NAME_MISSING);
+ return 0;
}
CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
if (!engine_list_add(e)) {
diff --git a/src/third_party/openssl/openssl/crypto/evp/e_camellia.c b/src/third_party/openssl/openssl/crypto/evp/e_camellia.c
index 27bc489..f7b135d 100644
--- a/src/third_party/openssl/openssl/crypto/evp/e_camellia.c
+++ b/src/third_party/openssl/openssl/crypto/evp/e_camellia.c
@@ -1,4 +1,4 @@
-/* crypto/evp/e_camellia.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/evp/e_camellia.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/evp/e_des3.c b/src/third_party/openssl/openssl/crypto/evp/e_des3.c
index da5d4c9..bcc0db5 100644
--- a/src/third_party/openssl/openssl/crypto/evp/e_des3.c
+++ b/src/third_party/openssl/openssl/crypto/evp/e_des3.c
@@ -244,7 +244,7 @@
DES_cblock *deskey = (DES_cblock *)key;
# ifdef EVP_CHECK_DES_KEY
if (DES_set_key_checked(&deskey[0], &data(ctx)->ks1)
- ! !DES_set_key_checked(&deskey[1], &data(ctx)->ks2))
+ || DES_set_key_checked(&deskey[1], &data(ctx)->ks2))
return 0;
# else
DES_set_key_unchecked(&deskey[0], &data(ctx)->ks1);
diff --git a/src/third_party/openssl/openssl/crypto/evp/e_old.c b/src/third_party/openssl/openssl/crypto/evp/e_old.c
index c93f5a5..a23d143 100644
--- a/src/third_party/openssl/openssl/crypto/evp/e_old.c
+++ b/src/third_party/openssl/openssl/crypto/evp/e_old.c
@@ -1,4 +1,4 @@
-/* crypto/evp/e_old.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/evp/e_old.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2004.
diff --git a/src/third_party/openssl/openssl/crypto/evp/e_seed.c b/src/third_party/openssl/openssl/crypto/evp/e_seed.c
index c948a8f..7249d1b 100644
--- a/src/third_party/openssl/openssl/crypto/evp/e_seed.c
+++ b/src/third_party/openssl/openssl/crypto/evp/e_seed.c
@@ -1,4 +1,4 @@
-/* crypto/evp/e_seed.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/evp/e_seed.c */
/* ====================================================================
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/evp/encode.c b/src/third_party/openssl/openssl/crypto/evp/encode.c
index 6894fd0..dcf937f 100644
--- a/src/third_party/openssl/openssl/crypto/evp/encode.c
+++ b/src/third_party/openssl/openssl/crypto/evp/encode.c
@@ -63,9 +63,9 @@
#include "cryptlib.h"
#include <openssl/evp.h>
+static unsigned char conv_ascii2bin(unsigned char a);
#ifndef CHARSET_EBCDIC
# define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f])
-# define conv_ascii2bin(a) (data_ascii2bin[(a)&0x7f])
#else
/*
* We assume that PEM encoded files are EBCDIC files (i.e., printable text
@@ -74,7 +74,6 @@
* as the underlying textstring data_bin2ascii[] is already EBCDIC)
*/
# define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f])
-# define conv_ascii2bin(a) (data_ascii2bin[os_toascii[a]&0x7f])
#endif
/*-
@@ -106,6 +105,7 @@
#define B64_WS 0xE0
#define B64_ERROR 0xFF
#define B64_NOT_BASE64(a) (((a)|0x13) == 0xF3)
+#define B64_BASE64(a) !B64_NOT_BASE64(a)
static const unsigned char data_ascii2bin[128] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -126,6 +126,23 @@
0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
+#ifndef CHARSET_EBCDIC
+static unsigned char conv_ascii2bin(unsigned char a)
+{
+ if (a & 0x80)
+ return B64_ERROR;
+ return data_ascii2bin[a];
+}
+#else
+static unsigned char conv_ascii2bin(unsigned char a)
+{
+ a = os_toascii[a];
+ if (a & 0x80)
+ return B64_ERROR;
+ return data_ascii2bin[a];
+}
+#endif
+
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
{
ctx->length = 48;
@@ -142,7 +159,7 @@
*outl = 0;
if (inl <= 0)
return;
- OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
+ OPENSSL_port_assert(ctx->length <= (int)sizeof(ctx->enc_data));
if ((ctx->num + inl) < ctx->length) {
OPENSSL_port_memcpy(&(ctx->enc_data[ctx->num]), in, inl);
ctx->num += inl;
@@ -221,8 +238,9 @@
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
{
- ctx->length = 30;
+ /* Only ctx->num is used during decoding. */
ctx->num = 0;
+ ctx->length = 0;
ctx->line_num = 0;
ctx->expect_nl = 0;
}
@@ -231,139 +249,123 @@
* -1 for error
* 0 for last line
* 1 for full line
+ *
+ * Note: even though EVP_DecodeUpdate attempts to detect and report end of
+ * content, the context doesn't currently remember it and will accept more data
+ * in the next call. Therefore, the caller is responsible for checking and
+ * rejecting a 0 return value in the middle of content.
+ *
+ * Note: even though EVP_DecodeUpdate has historically tried to detect end of
+ * content based on line length, this has never worked properly. Therefore,
+ * we now return 0 when one of the following is true:
+ * - Padding or B64_EOF was detected and the last block is complete.
+ * - Input has zero-length.
+ * -1 is returned if:
+ * - Invalid characters are detected.
+ * - There is extra trailing padding, or data after padding.
+ * - B64_EOF is detected after an incomplete base64 block.
*/
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
- int seof = -1, eof = 0, rv = -1, ret = 0, i, v, tmp, n, ln, exp_nl;
+ int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
unsigned char *d;
n = ctx->num;
d = ctx->enc_data;
- ln = ctx->line_num;
- exp_nl = ctx->expect_nl;
- /* last line of input. */
- if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) {
+ if (n > 0 && d[n - 1] == '=') {
+ eof++;
+ if (n > 1 && d[n - 2] == '=')
+ eof++;
+ }
+
+ /* Legacy behaviour: an empty input chunk signals end of input. */
+ if (inl == 0) {
rv = 0;
goto end;
}
- /* We parse the input data */
for (i = 0; i < inl; i++) {
- /* If the current line is > 80 characters, scream alot */
- if (ln >= 80) {
- rv = -1;
- goto end;
- }
-
- /* Get char and put it into the buffer */
tmp = *(in++);
v = conv_ascii2bin(tmp);
- /* only save the good data :-) */
- if (!B64_NOT_BASE64(v)) {
- OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
- d[n++] = tmp;
- ln++;
- } else if (v == B64_ERROR) {
+ if (v == B64_ERROR) {
rv = -1;
goto end;
}
- /*
- * have we seen a '=' which is 'definitly' the last input line. seof
- * will point to the character that holds it. and eof will hold how
- * many characters to chop off.
- */
if (tmp == '=') {
- if (seof == -1)
- seof = n;
eof++;
+ } else if (eof > 0 && B64_BASE64(v)) {
+ /* More data after padding. */
+ rv = -1;
+ goto end;
}
- if (v == B64_CR) {
- ln = 0;
- if (exp_nl)
- continue;
+ if (eof > 2) {
+ rv = -1;
+ goto end;
}
- /* eoln */
- if (v == B64_EOLN) {
- ln = 0;
- if (exp_nl) {
- exp_nl = 0;
- continue;
- }
- }
- exp_nl = 0;
-
- /*
- * If we are at the end of input and it looks like a line, process
- * it.
- */
- if (((i + 1) == inl) && (((n & 3) == 0) || eof)) {
- v = B64_EOF;
- /*
- * In case things were given us in really small records (so two
- * '=' were given in separate updates), eof may contain the
- * incorrect number of ending bytes to skip, so let's redo the
- * count
- */
- eof = 0;
- if (d[n - 1] == '=')
- eof++;
- if (d[n - 2] == '=')
- eof++;
- /* There will never be more than two '=' */
+ if (v == B64_EOF) {
+ seof = 1;
+ goto tail;
}
- if ((v == B64_EOF && (n & 3) == 0) || (n >= 64)) {
- /*
- * This is needed to work correctly on 64 byte input lines. We
- * process the line and then need to accept the '\n'
- */
- if ((v != B64_EOF) && (n >= 64))
- exp_nl = 1;
- if (n > 0) {
- v = EVP_DecodeBlock(out, d, n);
- n = 0;
- if (v < 0) {
- rv = 0;
- goto end;
- }
- if (eof > v) {
- rv = -1;
- goto end;
- }
- ret += (v - eof);
- } else {
- eof = 1;
- v = 0;
- }
-
- /*
- * This is the case where we have had a short but valid input
- * line
- */
- if ((v < ctx->length) && eof) {
- rv = 0;
- goto end;
- } else
- ctx->length = v;
-
- if (seof >= 0) {
- rv = 0;
+ /* Only save valid base64 characters. */
+ if (B64_BASE64(v)) {
+ if (n >= 64) {
+ /*
+ * We increment n once per loop, and empty the buffer as soon as
+ * we reach 64 characters, so this can only happen if someone's
+ * manually messed with the ctx. Refuse to write any more data.
+ */
+ rv = -1;
goto end;
}
- out += v;
+ OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
+ d[n++] = tmp;
+ }
+
+ if (n == 64) {
+ decoded_len = EVP_DecodeBlock(out, d, n);
+ n = 0;
+ if (decoded_len < 0 || eof > decoded_len) {
+ rv = -1;
+ goto end;
+ }
+ ret += decoded_len - eof;
+ out += decoded_len - eof;
}
}
- rv = 1;
- end:
+
+ /*
+ * Legacy behaviour: if the current line is a full base64-block (i.e., has
+ * 0 mod 4 base64 characters), it is processed immediately. We keep this
+ * behaviour as applications may not be calling EVP_DecodeFinal properly.
+ */
+tail:
+ if (n > 0) {
+ if ((n & 3) == 0) {
+ decoded_len = EVP_DecodeBlock(out, d, n);
+ n = 0;
+ if (decoded_len < 0 || eof > decoded_len) {
+ rv = -1;
+ goto end;
+ }
+ ret += (decoded_len - eof);
+ } else if (seof) {
+ /* EOF in the middle of a base64 block. */
+ rv = -1;
+ goto end;
+ }
+ }
+
+ rv = seof || (n == 0 && eof) ? 0 : 1;
+end:
+ /* Legacy behaviour. This should probably rather be zeroed on error. */
*outl = ret;
ctx->num = n;
- ctx->line_num = ln;
- ctx->expect_nl = exp_nl;
return (rv);
}
diff --git a/src/third_party/openssl/openssl/crypto/evp/evp_key.c b/src/third_party/openssl/openssl/crypto/evp/evp_key.c
index cba8867..2ab7a82 100644
--- a/src/third_party/openssl/openssl/crypto/evp/evp_key.c
+++ b/src/third_party/openssl/openssl/crypto/evp/evp_key.c
@@ -109,6 +109,8 @@
if ((prompt == NULL) && (prompt_string[0] != '\0'))
prompt = prompt_string;
ui = UI_new();
+ if (ui == NULL)
+ return -1;
UI_add_input_string(ui, prompt, 0, buf, min,
(len >= BUFSIZ) ? BUFSIZ - 1 : len);
if (verify)
@@ -143,7 +145,7 @@
EVP_MD_CTX_init(&c);
for (;;) {
if (!EVP_DigestInit_ex(&c, md, NULL))
- return 0;
+ goto err;
if (addmd++)
if (!EVP_DigestUpdate(&c, &(md_buf[0]), mds))
goto err;
@@ -194,6 +196,6 @@
rv = type->key_len;
err:
EVP_MD_CTX_cleanup(&c);
- OPENSSL_cleanse(&(md_buf[0]), EVP_MAX_MD_SIZE);
+ OPENSSL_cleanse(md_buf, sizeof(md_buf));
return rv;
}
diff --git a/src/third_party/openssl/openssl/crypto/evp/evp_lib.c b/src/third_party/openssl/openssl/crypto/evp/evp_lib.c
index 15c1ef9..b7f0c50 100644
--- a/src/third_party/openssl/openssl/crypto/evp/evp_lib.c
+++ b/src/third_party/openssl/openssl/crypto/evp/evp_lib.c
@@ -70,9 +70,19 @@
if (c->cipher->set_asn1_parameters != NULL)
ret = c->cipher->set_asn1_parameters(c, type);
- else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1)
- ret = EVP_CIPHER_set_asn1_iv(c, type);
- else
+ else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
+ switch (EVP_CIPHER_CTX_mode(c)) {
+
+ case EVP_CIPH_GCM_MODE:
+ case EVP_CIPH_CCM_MODE:
+ case EVP_CIPH_XTS_MODE:
+ ret = -1;
+ break;
+
+ default:
+ ret = EVP_CIPHER_set_asn1_iv(c, type);
+ }
+ } else
ret = -1;
return (ret);
}
@@ -83,9 +93,20 @@
if (c->cipher->get_asn1_parameters != NULL)
ret = c->cipher->get_asn1_parameters(c, type);
- else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1)
- ret = EVP_CIPHER_get_asn1_iv(c, type);
- else
+ else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
+ switch (EVP_CIPHER_CTX_mode(c)) {
+
+ case EVP_CIPH_GCM_MODE:
+ case EVP_CIPH_CCM_MODE:
+ case EVP_CIPH_XTS_MODE:
+ ret = -1;
+ break;
+
+ default:
+ ret = EVP_CIPHER_get_asn1_iv(c, type);
+ break;
+ }
+ } else
ret = -1;
return (ret);
}
diff --git a/src/third_party/openssl/openssl/crypto/evp/evp_pbe.c b/src/third_party/openssl/openssl/crypto/evp/evp_pbe.c
index 0962242..ffc7e22 100644
--- a/src/third_party/openssl/openssl/crypto/evp/evp_pbe.c
+++ b/src/third_party/openssl/openssl/crypto/evp/evp_pbe.c
@@ -231,12 +231,16 @@
int md_nid, EVP_PBE_KEYGEN *keygen)
{
EVP_PBE_CTL *pbe_tmp;
- if (!pbe_algs)
+
+ if (pbe_algs == NULL) {
pbe_algs = sk_EVP_PBE_CTL_new(pbe_cmp);
- if (!(pbe_tmp = (EVP_PBE_CTL *)OPENSSL_malloc(sizeof(EVP_PBE_CTL)))) {
- EVPerr(EVP_F_EVP_PBE_ALG_ADD_TYPE, ERR_R_MALLOC_FAILURE);
- return 0;
+ if (pbe_algs == NULL)
+ goto err;
}
+
+ if ((pbe_tmp = OPENSSL_port_malloc(sizeof(*pbe_tmp))) == NULL)
+ goto err;
+
pbe_tmp->pbe_type = pbe_type;
pbe_tmp->pbe_nid = pbe_nid;
pbe_tmp->cipher_nid = cipher_nid;
@@ -245,6 +249,10 @@
sk_EVP_PBE_CTL_push(pbe_algs, pbe_tmp);
return 1;
+
+ err:
+ EVPerr(EVP_F_EVP_PBE_ALG_ADD_TYPE, ERR_R_MALLOC_FAILURE);
+ return 0;
}
int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
diff --git a/src/third_party/openssl/openssl/crypto/evp/p_lib.c b/src/third_party/openssl/openssl/crypto/evp/p_lib.c
index 9220528..8da900e 100644
--- a/src/third_party/openssl/openssl/crypto/evp/p_lib.c
+++ b/src/third_party/openssl/openssl/crypto/evp/p_lib.c
@@ -256,7 +256,7 @@
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
- if (!EVP_PKEY_set_type(pkey, type))
+ if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
return 0;
pkey->pkey.ptr = key;
return (key != NULL);
diff --git a/src/third_party/openssl/openssl/crypto/evp/pmeth_gn.c b/src/third_party/openssl/openssl/crypto/evp/pmeth_gn.c
index 55b3120..b7ee41e 100644
--- a/src/third_party/openssl/openssl/crypto/evp/pmeth_gn.c
+++ b/src/third_party/openssl/openssl/crypto/evp/pmeth_gn.c
@@ -99,12 +99,17 @@
return -1;
}
- if (!ppkey)
+ if (ppkey == NULL)
return -1;
- if (!*ppkey)
+ if (*ppkey == NULL)
*ppkey = EVP_PKEY_new();
+ if (*ppkey == NULL) {
+ EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+
ret = ctx->pmeth->paramgen(ctx, *ppkey);
if (ret <= 0) {
EVP_PKEY_free(*ppkey);
diff --git a/src/third_party/openssl/openssl/crypto/hmac/hm_ameth.c b/src/third_party/openssl/openssl/crypto/hmac/hm_ameth.c
index 4358f0a..6bed3a2 100644
--- a/src/third_party/openssl/openssl/crypto/hmac/hm_ameth.c
+++ b/src/third_party/openssl/openssl/crypto/hmac/hm_ameth.c
@@ -111,9 +111,14 @@
ASN1_OCTET_STRING *os;
os = ASN1_OCTET_STRING_new();
if (!os || !ASN1_OCTET_STRING_set(os, *pder, derlen))
- return 0;
- EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, os);
+ goto err;
+ if (!EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, os))
+ goto err;
return 1;
+
+ err:
+ ASN1_OCTET_STRING_free(os);
+ return 0;
}
static int old_hmac_encode(const EVP_PKEY *pkey, unsigned char **pder)
diff --git a/src/third_party/openssl/openssl/crypto/jpake/jpake.c b/src/third_party/openssl/openssl/crypto/jpake/jpake.c
index ed2e888..ac853d4 100644
--- a/src/third_party/openssl/openssl/crypto/jpake/jpake.c
+++ b/src/third_party/openssl/openssl/crypto/jpake/jpake.c
@@ -218,6 +218,9 @@
BIGNUM *t3 = BN_new();
int ret = 0;
+ if (h == NULL || t1 == NULL || t2 == NULL || t3 == NULL)
+ goto end;
+
zkp_hash(h, zkpg, p, ctx->p.peer_name);
/* t1 = g^b */
@@ -233,6 +236,7 @@
else
JPAKEerr(JPAKE_F_VERIFY_ZKP, JPAKE_R_ZKP_VERIFY_FAILED);
+end:
/* cleanup */
BN_free(t3);
BN_free(t2);
diff --git a/src/third_party/openssl/openssl/crypto/mem_clr.c b/src/third_party/openssl/openssl/crypto/mem_clr.c
index ab82b42..3d5612f 100644
--- a/src/third_party/openssl/openssl/crypto/mem_clr.c
+++ b/src/third_party/openssl/openssl/crypto/mem_clr.c
@@ -1,4 +1,4 @@
-/* crypto/mem_clr.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/mem_clr.c */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2002.
@@ -69,6 +69,10 @@
{
unsigned char *p = ptr;
size_t loop = len, ctr = cleanse_ctr;
+
+ if (ptr == NULL)
+ return;
+
while (loop--) {
*(p++) = (unsigned char)ctr;
ctr += (17 + ((size_t)p & 0xF));
diff --git a/src/third_party/openssl/openssl/crypto/modes/asm/ghash-armv4.pl b/src/third_party/openssl/openssl/crypto/modes/asm/ghash-armv4.pl
index d91586e..e46f8e3 100644
--- a/src/third_party/openssl/openssl/crypto/modes/asm/ghash-armv4.pl
+++ b/src/third_party/openssl/openssl/crypto/modes/asm/ghash-armv4.pl
@@ -374,8 +374,8 @@
vdup.8 $xi,`&Dlo("$IN")`[0] @ broadcast lowest byte
.Linner_neon:
subs $cnt,$cnt,#1
- vmull.p8 $Qlo,$Hlo,$xi @ H.lo·Xi[i]
- vmull.p8 $Qhi,$Hhi,$xi @ H.hi·Xi[i]
+ vmull.p8 $Qlo,$Hlo,$xi @ H.lo·Xi[i]
+ vmull.p8 $Qhi,$Hhi,$xi @ H.hi·Xi[i]
vext.8 $IN,$zero,#1 @ IN>>=8
veor $Z,$Qpost @ modulo-scheduled part
@@ -388,7 +388,7 @@
vsli.8 $Zo,$T,#1 @ compose the "carry" byte
vext.8 $Z,$zero,#1 @ Z>>=8
- vmull.p8 $R,$Zo,$mod @ "carry"·0xe1
+ vmull.p8 $R,$Zo,$mod @ "carry"·0xe1
vshr.u8 $Zo,$T,#7 @ save Z's bottom bit
vext.8 $Qpost,$Qlo,$zero,#1 @ Qlo>>=8
veor $Z,$Qhi
diff --git a/src/third_party/openssl/openssl/crypto/modes/asm/ghash-x86.pl b/src/third_party/openssl/openssl/crypto/modes/asm/ghash-x86.pl
index 83c727e..2426cd0 100644
--- a/src/third_party/openssl/openssl/crypto/modes/asm/ghash-x86.pl
+++ b/src/third_party/openssl/openssl/crypto/modes/asm/ghash-x86.pl
@@ -346,7 +346,7 @@
# effective address calculation and finally merge of value to Z.hi.
# Reference to rem_4bit is scheduled so late that I had to >>4
# rem_4bit elements. This resulted in 20-45% procent improvement
-# on contemporary µ-archs.
+# on contemporary µ-archs.
{
my $cnt;
my $rem_4bit = "eax";
diff --git a/src/third_party/openssl/openssl/crypto/o_dir.c b/src/third_party/openssl/openssl/crypto/o_dir.c
index 01a98df..c90b95f 100644
--- a/src/third_party/openssl/openssl/crypto/o_dir.c
+++ b/src/third_party/openssl/openssl/crypto/o_dir.c
@@ -1,4 +1,4 @@
-/* crypto/o_dir.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_dir.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2004.
diff --git a/src/third_party/openssl/openssl/crypto/o_dir.h b/src/third_party/openssl/openssl/crypto/o_dir.h
index 6c1b881..8125918 100644
--- a/src/third_party/openssl/openssl/crypto/o_dir.h
+++ b/src/third_party/openssl/openssl/crypto/o_dir.h
@@ -1,4 +1,4 @@
-/* crypto/o_dir.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_dir.h */
/*
* Copied from Richard Levitte's (richard@levitte.org) LP library. All
* symbol names have been changed, with permission from the author.
diff --git a/src/third_party/openssl/openssl/crypto/o_dir_test.c b/src/third_party/openssl/openssl/crypto/o_dir_test.c
index 7cdbbbc..60436b7 100644
--- a/src/third_party/openssl/openssl/crypto/o_dir_test.c
+++ b/src/third_party/openssl/openssl/crypto/o_dir_test.c
@@ -1,4 +1,4 @@
-/* crypto/o_dir.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_dir.h */
/*
* Copied from Richard Levitte's (richard@levitte.org) LP library. All
* symbol names have been changed, with permission from the author.
diff --git a/src/third_party/openssl/openssl/crypto/o_str.c b/src/third_party/openssl/openssl/crypto/o_str.c
index 95ecf04..325b48e 100644
--- a/src/third_party/openssl/openssl/crypto/o_str.c
+++ b/src/third_party/openssl/openssl/crypto/o_str.c
@@ -1,4 +1,4 @@
-/* crypto/o_str.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_str.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/src/third_party/openssl/openssl/crypto/o_str.h b/src/third_party/openssl/openssl/crypto/o_str.h
index 5313528..fa512eb 100644
--- a/src/third_party/openssl/openssl/crypto/o_str.h
+++ b/src/third_party/openssl/openssl/crypto/o_str.h
@@ -1,4 +1,4 @@
-/* crypto/o_str.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_str.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/src/third_party/openssl/openssl/crypto/o_time.c b/src/third_party/openssl/openssl/crypto/o_time.c
index ee6c780..f21fe79 100644
--- a/src/third_party/openssl/openssl/crypto/o_time.c
+++ b/src/third_party/openssl/openssl/crypto/o_time.c
@@ -1,4 +1,4 @@
-/* crypto/o_time.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_time.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/src/third_party/openssl/openssl/crypto/o_time.h b/src/third_party/openssl/openssl/crypto/o_time.h
index 700f2ef..2ad88e1 100644
--- a/src/third_party/openssl/openssl/crypto/o_time.h
+++ b/src/third_party/openssl/openssl/crypto/o_time.h
@@ -1,4 +1,4 @@
-/* crypto/o_time.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_time.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/src/third_party/openssl/openssl/crypto/ocsp/ocsp_lib.c b/src/third_party/openssl/openssl/crypto/ocsp/ocsp_lib.c
index 6ffeb39..ecfbb9b 100644
--- a/src/third_party/openssl/openssl/crypto/ocsp/ocsp_lib.c
+++ b/src/third_party/openssl/openssl/crypto/ocsp/ocsp_lib.c
@@ -249,12 +249,6 @@
if ((p = OPENSSL_port_strchr(p, ':'))) {
*p = 0;
port = p + 1;
- } else {
- /* Not found: set default port */
- if (*pssl)
- port = "443";
- else
- port = "80";
}
*pport = BUF_strdup(port);
diff --git a/src/third_party/openssl/openssl/crypto/ocsp/ocsp_prn.c b/src/third_party/openssl/openssl/crypto/ocsp/ocsp_prn.c
index 1834256..47d5f83 100644
--- a/src/third_party/openssl/openssl/crypto/ocsp/ocsp_prn.c
+++ b/src/third_party/openssl/openssl/crypto/ocsp/ocsp_prn.c
@@ -212,8 +212,7 @@
return 1;
}
- i = ASN1_STRING_length(rb->response);
- if (!(br = OCSP_response_get1_basic(o)))
+ if ((br = OCSP_response_get1_basic(o)) == NULL)
goto err;
rd = br->tbsResponseData;
l = ASN1_INTEGER_get(rd->version);
diff --git a/src/third_party/openssl/openssl/crypto/opensslconf.h.in b/src/third_party/openssl/openssl/crypto/opensslconf.h.in
index 814309b..7a1c85d 100644
--- a/src/third_party/openssl/openssl/crypto/opensslconf.h.in
+++ b/src/third_party/openssl/openssl/crypto/opensslconf.h.in
@@ -120,7 +120,7 @@
optimization options. Older Sparc's work better with only UNROLL, but
there's no way to tell at compile time what it is you're running on */
-#if defined( sun ) /* Newer Sparc's */
+#if defined( __sun ) || defined ( sun ) /* Newer Sparc's */
# define DES_PTR
# define DES_RISC1
# define DES_UNROLL
diff --git a/src/third_party/openssl/openssl/crypto/opensslv.h b/src/third_party/openssl/openssl/crypto/opensslv.h
index bd66999..3af71c4 100644
--- a/src/third_party/openssl/openssl/crypto/opensslv.h
+++ b/src/third_party/openssl/openssl/crypto/opensslv.h
@@ -30,11 +30,11 @@
* (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
* major minor fix final patch/beta)
*/
-# define OPENSSL_VERSION_NUMBER 0x1000110fL
+# define OPENSSL_VERSION_NUMBER 0x1000112fL
# ifdef OPENSSL_FIPS
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1p-fips 9 Jul 2015"
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1r-fips 28 Jan 2016"
# else
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1p 9 Jul 2015"
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1r 28 Jan 2016"
# endif
# define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT
diff --git a/src/third_party/openssl/openssl/crypto/pem/pem_info.c b/src/third_party/openssl/openssl/crypto/pem/pem_info.c
index 3f7da0e..941e05f 100644
--- a/src/third_party/openssl/openssl/crypto/pem/pem_info.c
+++ b/src/third_party/openssl/openssl/crypto/pem/pem_info.c
@@ -175,6 +175,8 @@
xi->enc_len = 0;
xi->x_pkey = X509_PKEY_new();
+ if (xi->x_pkey == NULL)
+ goto err;
ptype = EVP_PKEY_RSA;
pp = &xi->x_pkey->dec_pkey;
if ((int)OPENSSL_port_strlen(header) > 10) /* assume encrypted */
@@ -196,6 +198,8 @@
xi->enc_len = 0;
xi->x_pkey = X509_PKEY_new();
+ if (xi->x_pkey == NULL)
+ goto err;
ptype = EVP_PKEY_DSA;
pp = &xi->x_pkey->dec_pkey;
if ((int)OPENSSL_port_strlen(header) > 10) /* assume encrypted */
@@ -217,6 +221,8 @@
xi->enc_len = 0;
xi->x_pkey = X509_PKEY_new();
+ if (xi->x_pkey == NULL)
+ goto err;
ptype = EVP_PKEY_EC;
pp = &xi->x_pkey->dec_pkey;
if ((int)OPENSSL_port_strlen(header) > 10) /* assume encrypted */
diff --git a/src/third_party/openssl/openssl/crypto/pem/pvkfmt.c b/src/third_party/openssl/openssl/crypto/pem/pvkfmt.c
index dc4c7bf..21f4f42 100644
--- a/src/third_party/openssl/openssl/crypto/pem/pvkfmt.c
+++ b/src/third_party/openssl/openssl/crypto/pem/pvkfmt.c
@@ -624,13 +624,11 @@
PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
return 0;
}
- length -= 20;
} else {
if (length < 24) {
PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
return 0;
}
- length -= 24;
pvk_magic = read_ledword(&p);
if (pvk_magic != MS_PVKMAGIC) {
PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER);
@@ -692,23 +690,23 @@
inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
if (inlen <= 0) {
PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_PASSWORD_READ);
- return NULL;
+ goto err;
}
enctmp = OPENSSL_malloc(keylen + 8);
if (!enctmp) {
PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
- return NULL;
+ goto err;
}
if (!derive_pvk_key(keybuf, p, saltlen,
(unsigned char *)psbuf, inlen))
- return NULL;
+ goto err;
p += saltlen;
/* Copy BLOBHEADER across, decrypt rest */
OPENSSL_port_memcpy(enctmp, p, 8);
p += 8;
if (keylen < 8) {
PEMerr(PEM_F_DO_PVK_BODY, PEM_R_PVK_TOO_SHORT);
- return NULL;
+ goto err;
}
inlen = keylen - 8;
q = enctmp + 8;
diff --git a/src/third_party/openssl/openssl/crypto/pkcs12/p12_add.c b/src/third_party/openssl/openssl/crypto/pkcs12/p12_add.c
index 2db8ee0..8ea0e45 100644
--- a/src/third_party/openssl/openssl/crypto/pkcs12/p12_add.c
+++ b/src/third_party/openssl/openssl/crypto/pkcs12/p12_add.c
@@ -78,15 +78,19 @@
bag->type = OBJ_nid2obj(nid1);
if (!ASN1_item_pack(obj, it, &bag->value.octet)) {
PKCS12err(PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE);
- return NULL;
+ goto err;
}
if (!(safebag = PKCS12_SAFEBAG_new())) {
PKCS12err(PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG, ERR_R_MALLOC_FAILURE);
- return NULL;
+ goto err;
}
safebag->value.bag = bag;
safebag->type = OBJ_nid2obj(nid2);
return safebag;
+
+ err:
+ PKCS12_BAGS_free(bag);
+ return NULL;
}
/* Turn PKCS8 object into a keybag */
@@ -130,6 +134,7 @@
PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter,
p8))) {
PKCS12err(PKCS12_F_PKCS12_MAKE_SHKEYBAG, ERR_R_MALLOC_FAILURE);
+ PKCS12_SAFEBAG_free(bag);
return NULL;
}
@@ -147,14 +152,18 @@
p7->type = OBJ_nid2obj(NID_pkcs7_data);
if (!(p7->d.data = M_ASN1_OCTET_STRING_new())) {
PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, ERR_R_MALLOC_FAILURE);
- return NULL;
+ goto err;
}
if (!ASN1_item_pack(sk, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), &p7->d.data)) {
PKCS12err(PKCS12_F_PKCS12_PACK_P7DATA, PKCS12_R_CANT_PACK_STRUCTURE);
- return NULL;
+ goto err;
}
return p7;
+
+ err:
+ PKCS7_free(p7);
+ return NULL;
}
/* Unpack SAFEBAGS from PKCS#7 data ContentInfo */
@@ -184,7 +193,7 @@
if (!PKCS7_set_type(p7, NID_pkcs7_encrypted)) {
PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA,
PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE);
- return NULL;
+ goto err;
}
pbe_ciph = EVP_get_cipherbynid(pbe_nid);
@@ -196,7 +205,7 @@
if (!pbe) {
PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, ERR_R_MALLOC_FAILURE);
- return NULL;
+ goto err;
}
X509_ALGOR_free(p7->d.encrypted->enc_data->algorithm);
p7->d.encrypted->enc_data->algorithm = pbe;
@@ -205,10 +214,14 @@
PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), pass,
passlen, bags, 1))) {
PKCS12err(PKCS12_F_PKCS12_PACK_P7ENCDATA, PKCS12_R_ENCRYPT_ERROR);
- return NULL;
+ goto err;
}
return p7;
+
+ err:
+ PKCS7_free(p7);
+ return NULL;
}
STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass,
diff --git a/src/third_party/openssl/openssl/crypto/pkcs12/p12_crpt.c b/src/third_party/openssl/openssl/crypto/pkcs12/p12_crpt.c
index 9606d4b..9a62038 100644
--- a/src/third_party/openssl/openssl/crypto/pkcs12/p12_crpt.c
+++ b/src/third_party/openssl/openssl/crypto/pkcs12/p12_crpt.c
@@ -80,6 +80,9 @@
const unsigned char *pbuf;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
+ if (cipher == NULL)
+ return 0;
+
/* Extract useful info from parameter */
if (param == NULL || param->type != V_ASN1_SEQUENCE ||
param->value.sequence == NULL) {
diff --git a/src/third_party/openssl/openssl/crypto/pkcs12/p12_mutl.c b/src/third_party/openssl/openssl/crypto/pkcs12/p12_mutl.c
index a57e1f6..3820604 100644
--- a/src/third_party/openssl/openssl/crypto/pkcs12/p12_mutl.c
+++ b/src/third_party/openssl/openssl/crypto/pkcs12/p12_mutl.c
@@ -176,11 +176,11 @@
}
if (!saltlen)
saltlen = PKCS12_SALT_LEN;
- p12->mac->salt->length = saltlen;
- if (!(p12->mac->salt->data = OPENSSL_malloc(saltlen))) {
+ if ((p12->mac->salt->data = OPENSSL_port_malloc(saltlen)) == NULL) {
PKCS12err(PKCS12_F_PKCS12_SETUP_MAC, ERR_R_MALLOC_FAILURE);
return 0;
}
+ p12->mac->salt->length = saltlen;
if (!salt) {
if (RAND_pseudo_bytes(p12->mac->salt->data, saltlen) < 0)
return 0;
diff --git a/src/third_party/openssl/openssl/crypto/pkcs7/pk7_doit.c b/src/third_party/openssl/openssl/crypto/pkcs7/pk7_doit.c
index f1157a4..6a5cb9c 100644
--- a/src/third_party/openssl/openssl/crypto/pkcs7/pk7_doit.c
+++ b/src/third_party/openssl/openssl/crypto/pkcs7/pk7_doit.c
@@ -659,6 +659,8 @@
bio = BIO_new_mem_buf(data_body->data, data_body->length);
else {
bio = BIO_new(BIO_s_mem());
+ if (bio == NULL)
+ goto err;
BIO_set_mem_eof_return(bio, 0);
}
if (bio == NULL)
@@ -1159,7 +1161,6 @@
rsk = p7->d.signed_and_enveloped->recipientinfo;
if (rsk == NULL)
return NULL;
- ri = sk_PKCS7_RECIP_INFO_value(rsk, 0);
if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx)
return (NULL);
ri = sk_PKCS7_RECIP_INFO_value(rsk, idx);
diff --git a/src/third_party/openssl/openssl/crypto/rand/rand_vms.c b/src/third_party/openssl/openssl/crypto/rand/rand_vms.c
index a7179a4..0e10c36 100644
--- a/src/third_party/openssl/openssl/crypto/rand/rand_vms.c
+++ b/src/third_party/openssl/openssl/crypto/rand/rand_vms.c
@@ -1,4 +1,4 @@
-/* crypto/rand/rand_vms.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/rand/rand_vms.c */
/*
* Written by Richard Levitte <richard@levitte.org> for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/crypto/rc4/asm/rc4-x86_64.pl b/src/third_party/openssl/openssl/crypto/rc4/asm/rc4-x86_64.pl
index 75750db..20722d3 100755
--- a/src/third_party/openssl/openssl/crypto/rc4/asm/rc4-x86_64.pl
+++ b/src/third_party/openssl/openssl/crypto/rc4/asm/rc4-x86_64.pl
@@ -56,7 +56,7 @@
# achieves respectful 432MBps on 2.8GHz processor now. For reference.
# If executed on Xeon, current RC4_CHAR code-path is 2.7x faster than
# RC4_INT code-path. While if executed on Opteron, it's only 25%
-# slower than the RC4_INT one [meaning that if CPU µ-arch detection
+# slower than the RC4_INT one [meaning that if CPU µ-arch detection
# is not implemented, then this final RC4_CHAR code-path should be
# preferred, as it provides better *all-round* performance].
diff --git a/src/third_party/openssl/openssl/crypto/rc4/rc4_utl.c b/src/third_party/openssl/openssl/crypto/rc4/rc4_utl.c
index 7c6a15f..cbd4a24 100644
--- a/src/third_party/openssl/openssl/crypto/rc4/rc4_utl.c
+++ b/src/third_party/openssl/openssl/crypto/rc4/rc4_utl.c
@@ -1,4 +1,4 @@
-/* crypto/rc4/rc4_utl.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/rc4/rc4_utl.c */
/* ====================================================================
* Copyright (c) 2011 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/rsa/rsa_ameth.c b/src/third_party/openssl/openssl/crypto/rsa/rsa_ameth.c
index a5b1fd4..17f5d88 100644
--- a/src/third_party/openssl/openssl/crypto/rsa/rsa_ameth.c
+++ b/src/third_party/openssl/openssl/crypto/rsa/rsa_ameth.c
@@ -282,7 +282,7 @@
if (pss->maskGenAlgorithm) {
ASN1_TYPE *param = pss->maskGenAlgorithm->parameter;
if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) == NID_mgf1
- && param->type == V_ASN1_SEQUENCE) {
+ && param && param->type == V_ASN1_SEQUENCE) {
p = param->value.sequence->data;
plen = param->value.sequence->length;
*pmaskHash = d2i_X509_ALGOR(NULL, &p, plen);
diff --git a/src/third_party/openssl/openssl/crypto/rsa/rsa_chk.c b/src/third_party/openssl/openssl/crypto/rsa/rsa_chk.c
index f438386..607faa0 100644
--- a/src/third_party/openssl/openssl/crypto/rsa/rsa_chk.c
+++ b/src/third_party/openssl/openssl/crypto/rsa/rsa_chk.c
@@ -1,4 +1,4 @@
-/* crypto/rsa/rsa_chk.c -*- Mode: C; c-file-style: "eay" -*- */
+/* crypto/rsa/rsa_chk.c */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/rsa/rsa_gen.c b/src/third_party/openssl/openssl/crypto/rsa/rsa_gen.c
index 27f3432..ff0788d 100644
--- a/src/third_party/openssl/openssl/crypto/rsa/rsa_gen.c
+++ b/src/third_party/openssl/openssl/crypto/rsa/rsa_gen.c
@@ -72,6 +72,8 @@
#include <openssl/rsa.h>
#ifdef OPENSSL_FIPS
# include <openssl/fips.h>
+extern int FIPS_rsa_x931_generate_key_ex(RSA *rsa, int bits, BIGNUM *e,
+ BN_GENCB *cb);
#endif
static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
@@ -97,7 +99,7 @@
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
#ifdef OPENSSL_FIPS
if (FIPS_mode())
- return FIPS_rsa_generate_key_ex(rsa, bits, e_value, cb);
+ return FIPS_rsa_x931_generate_key_ex(rsa, bits, e_value, cb);
#endif
return rsa_builtin_keygen(rsa, bits, e_value, cb);
}
diff --git a/src/third_party/openssl/openssl/crypto/rsa/rsa_sign.c b/src/third_party/openssl/openssl/crypto/rsa/rsa_sign.c
index 9363971..e1b5aff 100644
--- a/src/third_party/openssl/openssl/crypto/rsa/rsa_sign.c
+++ b/src/third_party/openssl/openssl/crypto/rsa/rsa_sign.c
@@ -87,7 +87,7 @@
return 0;
}
#endif
- if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) {
+ if (rsa->meth->rsa_sign) {
return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa);
}
/* Special case: SSL signature, just check the length */
@@ -221,14 +221,13 @@
OPENSSL_port_memcpy(rm, s + 2, 16);
*prm_len = 16;
ret = 1;
- } else if (OPENSSL_port_memcmp(m, s + 2, 16))
+ } else if (OPENSSL_port_memcmp(m, s + 2, 16)) {
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
- else
+ } else {
ret = 1;
- }
-
- /* Special case: SSL signature */
- if (dtype == NID_md5_sha1) {
+ }
+ } else if (dtype == NID_md5_sha1) {
+ /* Special case: SSL signature */
if ((i != SSL_SIG_LENGTH) || OPENSSL_port_memcmp(s, m, SSL_SIG_LENGTH))
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
else
@@ -308,7 +307,7 @@
const unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
{
- if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify) {
+ if (rsa->meth->rsa_verify) {
return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen, rsa);
}
diff --git a/src/third_party/openssl/openssl/crypto/rsa/rsa_test.c b/src/third_party/openssl/openssl/crypto/rsa/rsa_test.c
index e971295..85c7440 100644
--- a/src/third_party/openssl/openssl/crypto/rsa/rsa_test.c
+++ b/src/third_party/openssl/openssl/crypto/rsa/rsa_test.c
@@ -297,22 +297,30 @@
} else
printf("OAEP encryption/decryption ok\n");
- /* Try decrypting corrupted ciphertexts */
+ /* Try decrypting corrupted ciphertexts. */
for (n = 0; n < clen; ++n) {
- int b;
- unsigned char saved = ctext[n];
- for (b = 0; b < 256; ++b) {
- if (b == saved)
- continue;
- ctext[n] = b;
- num = RSA_private_decrypt(num, ctext, ptext, key,
+ ctext[n] ^= 1;
+ num = RSA_private_decrypt(clen, ctext, ptext, key,
RSA_PKCS1_OAEP_PADDING);
- if (num > 0) {
- printf("Corrupt data decrypted!\n");
- err = 1;
- }
+ if (num > 0) {
+ printf("Corrupt data decrypted!\n");
+ err = 1;
+ break;
+ }
+ ctext[n] ^= 1;
+ }
+
+ /* Test truncated ciphertexts, as well as negative length. */
+ for (n = -1; n < clen; ++n) {
+ num = RSA_private_decrypt(n, ctext, ptext, key,
+ RSA_PKCS1_OAEP_PADDING);
+ if (num > 0) {
+ printf("Truncated data decrypted!\n");
+ err = 1;
+ break;
}
}
+
next:
RSA_free(key);
}
diff --git a/src/third_party/openssl/openssl/crypto/seed/seed_cbc.c b/src/third_party/openssl/openssl/crypto/seed/seed_cbc.c
index 33e6887..ee1115b 100644
--- a/src/third_party/openssl/openssl/crypto/seed/seed_cbc.c
+++ b/src/third_party/openssl/openssl/crypto/seed/seed_cbc.c
@@ -1,4 +1,4 @@
-/* crypto/seed/seed_cbc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/seed/seed_cbc.c */
/* ====================================================================
* Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/seed/seed_cfb.c b/src/third_party/openssl/openssl/crypto/seed/seed_cfb.c
index 3437d7b..b6a5648 100644
--- a/src/third_party/openssl/openssl/crypto/seed/seed_cfb.c
+++ b/src/third_party/openssl/openssl/crypto/seed/seed_cfb.c
@@ -1,4 +1,4 @@
-/* crypto/seed/seed_cfb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/seed/seed_cfb.c */
/* ====================================================================
* Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/seed/seed_ecb.c b/src/third_party/openssl/openssl/crypto/seed/seed_ecb.c
index 937a31b..9363d55 100644
--- a/src/third_party/openssl/openssl/crypto/seed/seed_ecb.c
+++ b/src/third_party/openssl/openssl/crypto/seed/seed_ecb.c
@@ -1,4 +1,4 @@
-/* crypto/seed/seed_ecb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/seed/seed_ecb.c */
/* ====================================================================
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/seed/seed_ofb.c b/src/third_party/openssl/openssl/crypto/seed/seed_ofb.c
index 6974302..48b7122 100644
--- a/src/third_party/openssl/openssl/crypto/seed/seed_ofb.c
+++ b/src/third_party/openssl/openssl/crypto/seed/seed_ofb.c
@@ -1,4 +1,4 @@
-/* crypto/seed/seed_ofb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/seed/seed_ofb.c */
/* ====================================================================
* Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/sha/asm/sha1-586.pl b/src/third_party/openssl/openssl/crypto/sha/asm/sha1-586.pl
index 1084d22..2b119ff 100644
--- a/src/third_party/openssl/openssl/crypto/sha/asm/sha1-586.pl
+++ b/src/third_party/openssl/openssl/crypto/sha/asm/sha1-586.pl
@@ -66,9 +66,9 @@
# switch to AVX alone improves performance by as little as 4% in
# comparison to SSSE3 code path. But below result doesn't look like
# 4% improvement... Trouble is that Sandy Bridge decodes 'ro[rl]' as
-# pair of µ-ops, and it's the additional µ-ops, two per round, that
+# pair of µ-ops, and it's the additional µ-ops, two per round, that
# make it run slower than Core2 and Westmere. But 'sh[rl]d' is decoded
-# as single µ-op by Sandy Bridge and it's replacing 'ro[rl]' with
+# as single µ-op by Sandy Bridge and it's replacing 'ro[rl]' with
# equivalent 'sh[rl]d' that is responsible for the impressive 5.1
# cycles per processed byte. But 'sh[rl]d' is not something that used
# to be fast, nor does it appear to be fast in upcoming Bulldozer
diff --git a/src/third_party/openssl/openssl/crypto/sha/asm/sha256-586.pl b/src/third_party/openssl/openssl/crypto/sha/asm/sha256-586.pl
index 928ec53..52a7c7f 100644
--- a/src/third_party/openssl/openssl/crypto/sha/asm/sha256-586.pl
+++ b/src/third_party/openssl/openssl/crypto/sha/asm/sha256-586.pl
@@ -21,7 +21,7 @@
# purposes.
#
# Performance improvement over compiler generated code varies from
-# 10% to 40% [see above]. Not very impressive on some µ-archs, but
+# 10% to 40% [see above]. Not very impressive on some µ-archs, but
# it's 5 times smaller and optimizies amount of writes.
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
diff --git a/src/third_party/openssl/openssl/crypto/sha/asm/sha512-586.pl b/src/third_party/openssl/openssl/crypto/sha/asm/sha512-586.pl
index 7eab6a5..9f8c51eb 100644
--- a/src/third_party/openssl/openssl/crypto/sha/asm/sha512-586.pl
+++ b/src/third_party/openssl/openssl/crypto/sha/asm/sha512-586.pl
@@ -23,7 +23,7 @@
#
# IALU code-path is optimized for elder Pentiums. On vanilla Pentium
# performance improvement over compiler generated code reaches ~60%,
-# while on PIII - ~35%. On newer µ-archs improvement varies from 15%
+# while on PIII - ~35%. On newer µ-archs improvement varies from 15%
# to 50%, but it's less important as they are expected to execute SSE2
# code-path, which is commonly ~2-3x faster [than compiler generated
# code]. SSE2 code-path is as fast as original sha512-sse2.pl, even
diff --git a/src/third_party/openssl/openssl/crypto/sha/asm/sha512-parisc.pl b/src/third_party/openssl/openssl/crypto/sha/asm/sha512-parisc.pl
old mode 100644
new mode 100755
index fc0e15b..6cad72e
--- a/src/third_party/openssl/openssl/crypto/sha/asm/sha512-parisc.pl
+++ b/src/third_party/openssl/openssl/crypto/sha/asm/sha512-parisc.pl
@@ -19,7 +19,7 @@
# SHA512 performance is >2.9x better than gcc 3.2 generated code on
# PA-7100LC, PA-RISC 1.1 processor. Then implementation detects if the
# code is executed on PA-RISC 2.0 processor and switches to 64-bit
-# code path delivering adequate peformance even in "blended" 32-bit
+# code path delivering adequate performance even in "blended" 32-bit
# build. Though 64-bit code is not any faster than code generated by
# vendor compiler on PA-8600...
#
diff --git a/src/third_party/openssl/openssl/crypto/sha/sha1test.c b/src/third_party/openssl/openssl/crypto/sha/sha1test.c
index 0052a95..551a348 100644
--- a/src/third_party/openssl/openssl/crypto/sha/sha1test.c
+++ b/src/third_party/openssl/openssl/crypto/sha/sha1test.c
@@ -157,8 +157,8 @@
if (err)
printf("ERROR: %d\n", err);
# endif
- EXIT(err);
EVP_MD_CTX_cleanup(&c);
+ EXIT(err);
return (0);
}
diff --git a/src/third_party/openssl/openssl/crypto/sparccpuid.S b/src/third_party/openssl/openssl/crypto/sparccpuid.S
index 0cc247e..c63d5da 100644
--- a/src/third_party/openssl/openssl/crypto/sparccpuid.S
+++ b/src/third_party/openssl/openssl/crypto/sparccpuid.S
@@ -123,7 +123,7 @@
fmovs %f1,%f3
fmovs %f0,%f2
- add %fp,BIAS,%i0 ! return pointer to caller´s top of stack
+ add %fp,BIAS,%i0 ! return pointer to caller´s top of stack
ret
restore
diff --git a/src/third_party/openssl/openssl/crypto/srp/srp_vfy.c b/src/third_party/openssl/openssl/crypto/srp/srp_vfy.c
index 50f75d7..c4c5ee4 100644
--- a/src/third_party/openssl/openssl/crypto/srp/srp_vfy.c
+++ b/src/third_party/openssl/openssl/crypto/srp/srp_vfy.c
@@ -198,7 +198,7 @@
static SRP_user_pwd *SRP_user_pwd_new()
{
- SRP_user_pwd *ret = OPENSSL_malloc(sizeof(SRP_user_pwd));
+ SRP_user_pwd *ret = OPENSSL_port_malloc(sizeof(SRP_user_pwd));
if (ret == NULL)
return NULL;
ret->N = NULL;
@@ -249,7 +249,7 @@
SRP_VBASE *SRP_VBASE_new(char *seed_key)
{
- SRP_VBASE *vb = (SRP_VBASE *)OPENSSL_malloc(sizeof(SRP_VBASE));
+ SRP_VBASE *vb = (SRP_VBASE *)OPENSSL_port_malloc(sizeof(SRP_VBASE));
if (vb == NULL)
return NULL;
@@ -285,7 +285,7 @@
int len;
SRP_gN_cache *newgN =
- (SRP_gN_cache *)OPENSSL_malloc(sizeof(SRP_gN_cache));
+ (SRP_gN_cache *)OPENSSL_port_malloc(sizeof(SRP_gN_cache));
if (newgN == NULL)
return NULL;
@@ -391,7 +391,7 @@
* we add this couple in the internal Stack
*/
- if ((gN = (SRP_gN *) OPENSSL_malloc(sizeof(SRP_gN))) == NULL)
+ if ((gN = (SRP_gN *) OPENSSL_port_malloc(sizeof(SRP_gN))) == NULL)
goto err;
if (!(gN->id = BUF_strdup(pp[DB_srpid]))
@@ -521,12 +521,12 @@
char **verifier, const char *N, const char *g)
{
int len;
- char *result = NULL;
- char *vf;
+ char *result = NULL, *vf = NULL;
BIGNUM *N_bn = NULL, *g_bn = NULL, *s = NULL, *v = NULL;
unsigned char tmp[MAX_LEN];
unsigned char tmp2[MAX_LEN];
char *defgNid = NULL;
+ int vfsize = 0;
if ((user == NULL) ||
(pass == NULL) || (salt == NULL) || (verifier == NULL))
@@ -564,22 +564,23 @@
goto err;
BN_bn2bin(v, tmp);
- if (((vf = OPENSSL_malloc(BN_num_bytes(v) * 2)) == NULL))
+ vfsize = BN_num_bytes(v) * 2;
+ if (((vf = OPENSSL_port_malloc(vfsize)) == NULL))
goto err;
t_tob64(vf, tmp, BN_num_bytes(v));
- *verifier = vf;
if (*salt == NULL) {
char *tmp_salt;
- if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) {
- OPENSSL_free(vf);
+ if ((tmp_salt = OPENSSL_port_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) {
goto err;
}
t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN);
*salt = tmp_salt;
}
+ *verifier = vf;
+ vf = NULL;
result = defgNid;
err:
@@ -587,11 +588,21 @@
BN_free(N_bn);
BN_free(g_bn);
}
+ OPENSSL_cleanse(vf, vfsize);
+ OPENSSL_free(vf);
+ BN_clear_free(s);
+ BN_clear_free(v);
return result;
}
/*
- * create a verifier (*salt,*verifier,g and N are BIGNUMs)
+ * create a verifier (*salt,*verifier,g and N are BIGNUMs). If *salt != NULL
+ * then the provided salt will be used. On successful exit *verifier will point
+ * to a newly allocated BIGNUM containing the verifier and (if a salt was not
+ * provided) *salt will be populated with a newly allocated BIGNUM containing a
+ * random salt.
+ * The caller is responsible for freeing the allocated *salt and *verifier
+ * BIGNUMS.
*/
int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
BIGNUM **verifier, BIGNUM *N, BIGNUM *g)
@@ -600,6 +611,7 @@
BIGNUM *x = NULL;
BN_CTX *bn_ctx = BN_CTX_new();
unsigned char tmp2[MAX_LEN];
+ BIGNUM *salttmp = NULL;
if ((user == NULL) ||
(pass == NULL) ||
@@ -614,10 +626,12 @@
if (RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN) < 0)
goto err;
- *salt = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
+ salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
+ } else {
+ salttmp = *salt;
}
- x = SRP_Calc_x(*salt, user, pass);
+ x = SRP_Calc_x(salttmp, user, pass);
*verifier = BN_new();
if (*verifier == NULL)
@@ -631,9 +645,11 @@
srp_bn_print(*verifier);
result = 1;
+ *salt = salttmp;
err:
-
+ if (*salt != salttmp)
+ BN_clear_free(salttmp);
BN_clear_free(x);
BN_CTX_free(bn_ctx);
return result;
diff --git a/src/third_party/openssl/openssl/crypto/store/store.h b/src/third_party/openssl/openssl/crypto/store/store.h
index 8343341..ce3709d 100644
--- a/src/third_party/openssl/openssl/crypto/store/store.h
+++ b/src/third_party/openssl/openssl/crypto/store/store.h
@@ -1,4 +1,4 @@
-/* crypto/store/store.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/store.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/src/third_party/openssl/openssl/crypto/store/str_lib.c b/src/third_party/openssl/openssl/crypto/store/str_lib.c
index 227b797..e3d5da9 100644
--- a/src/third_party/openssl/openssl/crypto/store/str_lib.c
+++ b/src/third_party/openssl/openssl/crypto/store/str_lib.c
@@ -1,4 +1,4 @@
-/* crypto/store/str_lib.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/str_lib.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/src/third_party/openssl/openssl/crypto/store/str_locl.h b/src/third_party/openssl/openssl/crypto/store/str_locl.h
index ac55784..c0b40f0 100644
--- a/src/third_party/openssl/openssl/crypto/store/str_locl.h
+++ b/src/third_party/openssl/openssl/crypto/store/str_locl.h
@@ -1,4 +1,4 @@
-/* crypto/store/str_locl.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/str_locl.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/src/third_party/openssl/openssl/crypto/store/str_mem.c b/src/third_party/openssl/openssl/crypto/store/str_mem.c
index 8edd0eb..6eee5bb 100644
--- a/src/third_party/openssl/openssl/crypto/store/str_mem.c
+++ b/src/third_party/openssl/openssl/crypto/store/str_mem.c
@@ -1,4 +1,4 @@
-/* crypto/store/str_mem.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/str_mem.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/src/third_party/openssl/openssl/crypto/store/str_meth.c b/src/third_party/openssl/openssl/crypto/store/str_meth.c
index d83a6de..c83fbc5 100644
--- a/src/third_party/openssl/openssl/crypto/store/str_meth.c
+++ b/src/third_party/openssl/openssl/crypto/store/str_meth.c
@@ -1,4 +1,4 @@
-/* crypto/store/str_meth.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/str_meth.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/src/third_party/openssl/openssl/crypto/ts/ts_rsp_verify.c b/src/third_party/openssl/openssl/crypto/ts/ts_rsp_verify.c
index 32b4d99..e24b2d5 100644
--- a/src/third_party/openssl/openssl/crypto/ts/ts_rsp_verify.c
+++ b/src/third_party/openssl/openssl/crypto/ts/ts_rsp_verify.c
@@ -255,7 +255,8 @@
/* chain is an out argument. */
*chain = NULL;
- X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted);
+ if (!X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted))
+ return 0;
X509_STORE_CTX_set_purpose(&cert_ctx, X509_PURPOSE_TIMESTAMP_SIGN);
i = X509_verify_cert(&cert_ctx);
if (i <= 0) {
@@ -522,7 +523,7 @@
if (ASN1_BIT_STRING_get_bit(info->failure_info,
TS_failure_info[i].code)) {
if (!first)
- strcpy(failure_text, ",");
+ strcat(failure_text, ",");
else
first = 0;
strcat(failure_text, TS_failure_info[i].text);
diff --git a/src/third_party/openssl/openssl/crypto/ui/ui.h b/src/third_party/openssl/openssl/crypto/ui/ui.h
index b917eda..0dc1633 100644
--- a/src/third_party/openssl/openssl/crypto/ui/ui.h
+++ b/src/third_party/openssl/openssl/crypto/ui/ui.h
@@ -1,4 +1,4 @@
-/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/src/third_party/openssl/openssl/crypto/ui/ui_compat.c b/src/third_party/openssl/openssl/crypto/ui/ui_compat.c
index 0ca5284..e79d54e 100644
--- a/src/third_party/openssl/openssl/crypto/ui/ui_compat.c
+++ b/src/third_party/openssl/openssl/crypto/ui/ui_compat.c
@@ -1,4 +1,4 @@
-/* crypto/ui/ui_compat.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui_compat.c */
/* ====================================================================
* Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/ui/ui_compat.h b/src/third_party/openssl/openssl/crypto/ui/ui_compat.h
index 42fb9ff..bf54154 100644
--- a/src/third_party/openssl/openssl/crypto/ui/ui_compat.h
+++ b/src/third_party/openssl/openssl/crypto/ui/ui_compat.h
@@ -1,4 +1,4 @@
-/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/src/third_party/openssl/openssl/crypto/ui/ui_lib.c b/src/third_party/openssl/openssl/crypto/ui/ui_lib.c
index 5ddd731..2f58035 100644
--- a/src/third_party/openssl/openssl/crypto/ui/ui_lib.c
+++ b/src/third_party/openssl/openssl/crypto/ui/ui_lib.c
@@ -1,4 +1,4 @@
-/* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui_lib.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/src/third_party/openssl/openssl/crypto/ui/ui_locl.h b/src/third_party/openssl/openssl/crypto/ui/ui_locl.h
index 0d919cd..bebc13a 100644
--- a/src/third_party/openssl/openssl/crypto/ui/ui_locl.h
+++ b/src/third_party/openssl/openssl/crypto/ui/ui_locl.h
@@ -1,4 +1,4 @@
-/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/src/third_party/openssl/openssl/crypto/ui/ui_openssl.c b/src/third_party/openssl/openssl/crypto/ui/ui_openssl.c
index 7753ad8..b4fb703 100644
--- a/src/third_party/openssl/openssl/crypto/ui/ui_openssl.c
+++ b/src/third_party/openssl/openssl/crypto/ui/ui_openssl.c
@@ -1,4 +1,4 @@
-/* crypto/ui/ui_openssl.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui_openssl.c */
/*
* Written by Richard Levitte (richard@levitte.org) and others for the
* OpenSSL project 2001.
diff --git a/src/third_party/openssl/openssl/crypto/ui/ui_util.c b/src/third_party/openssl/openssl/crypto/ui/ui_util.c
index f65f80d..0f29011 100644
--- a/src/third_party/openssl/openssl/crypto/ui/ui_util.c
+++ b/src/third_party/openssl/openssl/crypto/ui/ui_util.c
@@ -1,4 +1,4 @@
-/* crypto/ui/ui_util.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui_util.c */
/* ====================================================================
* Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/whrlpool/asm/wp-mmx.pl b/src/third_party/openssl/openssl/crypto/whrlpool/asm/wp-mmx.pl
index cb2381c..90c2eca 100644
--- a/src/third_party/openssl/openssl/crypto/whrlpool/asm/wp-mmx.pl
+++ b/src/third_party/openssl/openssl/crypto/whrlpool/asm/wp-mmx.pl
@@ -16,7 +16,7 @@
# table]. I stick to value of 2 for two reasons: 1. smaller table
# minimizes cache trashing and thus mitigates the hazard of side-
# channel leakage similar to AES cache-timing one; 2. performance
-# gap among different µ-archs is smaller.
+# gap among different µ-archs is smaller.
#
# Performance table lists rounded amounts of CPU cycles spent by
# whirlpool_block_mmx routine on single 64 byte input block, i.e.
diff --git a/src/third_party/openssl/openssl/crypto/x509/x509_cmp.c b/src/third_party/openssl/openssl/crypto/x509/x509_cmp.c
index 006ad6c..cdbd31a 100644
--- a/src/third_party/openssl/openssl/crypto/x509/x509_cmp.c
+++ b/src/third_party/openssl/openssl/crypto/x509/x509_cmp.c
@@ -182,11 +182,24 @@
*/
int X509_cmp(const X509 *a, const X509 *b)
{
+ int rv;
+
/* ensure hash is valid */
X509_check_purpose((X509 *)a, -1, 0);
X509_check_purpose((X509 *)b, -1, 0);
- return OPENSSL_port_memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ rv = OPENSSL_port_memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ if (rv)
+ return rv;
+ /* Check for match against stored encoding too */
+ if (!a->cert_info->enc.modified && !b->cert_info->enc.modified) {
+ rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len);
+ if (rv)
+ return rv;
+ return OPENSSL_port_memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc,
+ a->cert_info->enc.len);
+ }
+ return rv;
}
#endif
diff --git a/src/third_party/openssl/openssl/crypto/x509/x509_lu.c b/src/third_party/openssl/openssl/crypto/x509/x509_lu.c
index cbba742..28f00a4 100644
--- a/src/third_party/openssl/openssl/crypto/x509/x509_lu.c
+++ b/src/third_party/openssl/openssl/crypto/x509/x509_lu.c
@@ -526,8 +526,6 @@
X509_OBJECT *obj, xobj;
sk = sk_X509_CRL_new_null();
CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
- /* Check cache first */
- idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
/*
* Always do lookup to possibly add new CRLs to cache
diff --git a/src/third_party/openssl/openssl/crypto/x509/x509_vfy.c b/src/third_party/openssl/openssl/crypto/x509/x509_vfy.c
index 4839b5e..c2cd1ed 100644
--- a/src/third_party/openssl/openssl/crypto/x509/x509_vfy.c
+++ b/src/third_party/openssl/openssl/crypto/x509/x509_vfy.c
@@ -2029,9 +2029,10 @@
ctx->current_reasons = 0;
ctx->tree = NULL;
ctx->parent = NULL;
+ /* Zero ex_data to make sure we're cleanup-safe */
+ OPENSSL_port_memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
ctx->param = X509_VERIFY_PARAM_new();
-
if (!ctx->param) {
X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
return 0;
@@ -2040,7 +2041,6 @@
/*
* Inherit callbacks and flags from X509_STORE if not set use defaults.
*/
-
if (store)
ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
else
@@ -2048,6 +2048,7 @@
if (store) {
ctx->verify_cb = store->verify_cb;
+ /* Seems to always be 0 in OpenSSL, else must be idempotent */
ctx->cleanup = store->cleanup;
} else
ctx->cleanup = 0;
@@ -2058,7 +2059,7 @@
if (ret == 0) {
X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
if (store && store->check_issued)
@@ -2113,19 +2114,18 @@
ctx->check_policy = check_policy;
+ if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
+ &ctx->ex_data))
+ return 1;
+ X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
+
+ err:
/*
- * This OPENSSL_port_memset() can't make any sense anyway, so it's removed. As
- * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
- * corresponding "new" here and remove this bogus initialisation.
+ * On error clean up allocated storage, if the store context was not
+ * allocated with X509_STORE_CTX_new() this is our last chance to do so.
*/
- /* OPENSSL_port_memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
- &(ctx->ex_data))) {
- OPENSSL_free(ctx);
- X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- return 1;
+ X509_STORE_CTX_cleanup(ctx);
+ return 0;
}
/*
@@ -2141,8 +2141,17 @@
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
{
- if (ctx->cleanup)
+ /*
+ * We need to be idempotent because, unfortunately, free() also calls
+ * cleanup(), so the natural call sequence new(), init(), cleanup(), free()
+ * calls cleanup() for the same object twice! Thus we must zero the
+ * pointers below after they're freed!
+ */
+ /* Seems to always be 0 in OpenSSL, do this at most once. */
+ if (ctx->cleanup != NULL) {
ctx->cleanup(ctx);
+ ctx->cleanup = NULL;
+ }
if (ctx->param != NULL) {
if (ctx->parent == NULL)
X509_VERIFY_PARAM_free(ctx->param);
diff --git a/src/third_party/openssl/openssl/crypto/x509/x509_vfy.h b/src/third_party/openssl/openssl/crypto/x509/x509_vfy.h
index 02f2f89..31c7007 100644
--- a/src/third_party/openssl/openssl/crypto/x509/x509_vfy.h
+++ b/src/third_party/openssl/openssl/crypto/x509/x509_vfy.h
@@ -310,7 +310,7 @@
X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
# define X509_V_OK 0
-/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+# define X509_V_ERR_UNSPECIFIED 1
# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2
# define X509_V_ERR_UNABLE_TO_GET_CRL 3
diff --git a/src/third_party/openssl/openssl/crypto/x509v3/v3_cpols.c b/src/third_party/openssl/openssl/crypto/x509v3/v3_cpols.c
index 29470c2..764e858 100644
--- a/src/third_party/openssl/openssl/crypto/x509v3/v3_cpols.c
+++ b/src/third_party/openssl/openssl/crypto/x509v3/v3_cpols.c
@@ -189,6 +189,10 @@
goto err;
}
pol = POLICYINFO_new();
+ if (pol == NULL) {
+ X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
pol->policyid = pobj;
}
if (!sk_POLICYINFO_push(pols, pol)) {
diff --git a/src/third_party/openssl/openssl/crypto/x509v3/v3_ncons.c b/src/third_party/openssl/openssl/crypto/x509v3/v3_ncons.c
index 211519a..4967084 100644
--- a/src/third_party/openssl/openssl/crypto/x509v3/v3_ncons.c
+++ b/src/third_party/openssl/openssl/crypto/x509v3/v3_ncons.c
@@ -135,6 +135,8 @@
}
tval.value = val->value;
sub = GENERAL_SUBTREE_new();
+ if (sub == NULL)
+ goto memerr;
if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
goto err;
if (!*ptree)
diff --git a/src/third_party/openssl/openssl/crypto/x509v3/v3_pci.c b/src/third_party/openssl/openssl/crypto/x509v3/v3_pci.c
index f3ba5d2..e44bb86 100644
--- a/src/third_party/openssl/openssl/crypto/x509v3/v3_pci.c
+++ b/src/third_party/openssl/openssl/crypto/x509v3/v3_pci.c
@@ -1,9 +1,9 @@
-/* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */
+/* v3_pci.c */
/*
* Contributed to the OpenSSL Project 2004 by Richard Levitte
* (richard@levitte.org)
*/
-/* Copyright (c) 2004 Kungliga Tekniska Högskolan
+/* Copyright (c) 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/crypto/x509v3/v3_pcia.c b/src/third_party/openssl/openssl/crypto/x509v3/v3_pcia.c
index 350b398..e53c82e 100644
--- a/src/third_party/openssl/openssl/crypto/x509v3/v3_pcia.c
+++ b/src/third_party/openssl/openssl/crypto/x509v3/v3_pcia.c
@@ -1,9 +1,9 @@
-/* v3_pcia.c -*- mode:C; c-file-style: "eay" -*- */
+/* v3_pcia.c */
/*
* Contributed to the OpenSSL Project 2004 by Richard Levitte
* (richard@levitte.org)
*/
-/* Copyright (c) 2004 Kungliga Tekniska Högskolan
+/* Copyright (c) 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/demos/easy_tls/README b/src/third_party/openssl/openssl/demos/easy_tls/README
index 816a580..ee89dfb 100644
--- a/src/third_party/openssl/openssl/demos/easy_tls/README
+++ b/src/third_party/openssl/openssl/demos/easy_tls/README
@@ -62,4 +62,4 @@
day, which means that future revisions will not be fully compatible to
the current version.
-Bodo Möller <bodo@openssl.org>
+Bodo Möller <bodo@openssl.org>
diff --git a/src/third_party/openssl/openssl/demos/easy_tls/easy-tls.c b/src/third_party/openssl/openssl/demos/easy_tls/easy-tls.c
index 5682e91..ebcadaf 100644
--- a/src/third_party/openssl/openssl/demos/easy_tls/easy-tls.c
+++ b/src/third_party/openssl/openssl/demos/easy_tls/easy-tls.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C; c-file-style: "bsd" -*- */
+/* */
/*-
* easy-tls.c -- generic TLS proxy.
* $Id: easy-tls.c,v 1.4 2002/03/05 09:07:16 bodo Exp $
diff --git a/src/third_party/openssl/openssl/demos/easy_tls/easy-tls.h b/src/third_party/openssl/openssl/demos/easy_tls/easy-tls.h
index 1c587b8..b88d21c 100644
--- a/src/third_party/openssl/openssl/demos/easy_tls/easy-tls.h
+++ b/src/third_party/openssl/openssl/demos/easy_tls/easy-tls.h
@@ -1,4 +1,4 @@
-/* -*- Mode: C; c-file-style: "bsd" -*- */
+/* */
/*-
* easy-tls.h -- generic TLS proxy.
* $Id: easy-tls.h,v 1.1 2001/09/17 19:06:59 bodo Exp $
diff --git a/src/third_party/openssl/openssl/demos/engines/zencod/hw_zencod.c b/src/third_party/openssl/openssl/demos/engines/zencod/hw_zencod.c
index 0c0f524..daf0aef 100644
--- a/src/third_party/openssl/openssl/demos/engines/zencod/hw_zencod.c
+++ b/src/third_party/openssl/openssl/demos/engines/zencod/hw_zencod.c
@@ -610,7 +610,7 @@
ptr_zencod_rc4_cipher = ptr_rc4_1;
/*
- * We should peform a test to see if there is actually any unit runnig on
+ * We should perform a test to see if there is actually any unit runnig on
* the system ... Even if the cryptozen library is loaded the module coul
* not be loaded on the system ... For now we may just open and close the
* device !!
diff --git a/src/third_party/openssl/openssl/demos/tunala/tunala.c b/src/third_party/openssl/openssl/demos/tunala/tunala.c
index 11a7c5b..3ceea02 100644
--- a/src/third_party/openssl/openssl/demos/tunala/tunala.c
+++ b/src/third_party/openssl/openssl/demos/tunala/tunala.c
@@ -1154,7 +1154,7 @@
/*
* This function name is attributed to the term donated by David Schwartz
* on openssl-dev, message-ID:
- * <NCBBLIEPOCbmasEKBEAKEEDGLIAA.davids@webmaster.com>. :-)
+ * <NCBBLIEPOCNJOAEKBEAKEEDGLIAA.davids@webmaster.com>. :-)
*/
if (!state_machine_churn(&item->sm))
/*
diff --git a/src/third_party/openssl/openssl/doc/apps/ciphers.pod b/src/third_party/openssl/openssl/doc/apps/ciphers.pod
index 0aa1bad..0afe80d 100644
--- a/src/third_party/openssl/openssl/doc/apps/ciphers.pod
+++ b/src/third_party/openssl/openssl/doc/apps/ciphers.pod
@@ -205,7 +205,7 @@
cipher suites using ephemeral ECDH key agreement, including anonymous
cipher suites.
-=item B<EECDHE>
+=item B<EECDH>
cipher suites using authenticated ephemeral ECDH key agreement.
diff --git a/src/third_party/openssl/openssl/doc/apps/dgst.pod b/src/third_party/openssl/openssl/doc/apps/dgst.pod
index 9e15798..b27bb94 100644
--- a/src/third_party/openssl/openssl/doc/apps/dgst.pod
+++ b/src/third_party/openssl/openssl/doc/apps/dgst.pod
@@ -13,7 +13,6 @@
[B<-hex>]
[B<-binary>]
[B<-r>]
-[B<-hmac arg>]
[B<-non-fips-allow>]
[B<-out filename>]
[B<-sign filename>]
@@ -64,10 +63,6 @@
output the digest in the "coreutils" format used by programs like B<sha1sum>.
-=item B<-hmac arg>
-
-set the HMAC key to "arg".
-
=item B<-non-fips-allow>
Allow use of non FIPS digest when in FIPS mode. This has no effect when not in
diff --git a/src/third_party/openssl/openssl/doc/apps/genrsa.pod b/src/third_party/openssl/openssl/doc/apps/genrsa.pod
index cb03d09..3dc9870 100644
--- a/src/third_party/openssl/openssl/doc/apps/genrsa.pod
+++ b/src/third_party/openssl/openssl/doc/apps/genrsa.pod
@@ -10,12 +10,6 @@
[B<-out filename>]
[B<-passout arg>]
[B<-aes128>]
-[B<-aes128>]
-[B<-aes192>]
-[B<-aes256>]
-[B<-camellia128>]
-[B<-camellia192>]
-[B<-camellia256>]
[B<-aes192>]
[B<-aes256>]
[B<-camellia128>]
diff --git a/src/third_party/openssl/openssl/doc/apps/req.pod b/src/third_party/openssl/openssl/doc/apps/req.pod
index 0730d11..37ed377 100644
--- a/src/third_party/openssl/openssl/doc/apps/req.pod
+++ b/src/third_party/openssl/openssl/doc/apps/req.pod
@@ -490,7 +490,7 @@
The actual permitted field names are any object identifier short or
long names. These are compiled into OpenSSL and include the usual
values such as commonName, countryName, localityName, organizationName,
-organizationUnitName, stateOrProvinceName. Additionally emailAddress
+organizationalUnitName, stateOrProvinceName. Additionally emailAddress
is include as well as name, surname, givenName initials and dnQualifier.
Additional object identifiers can be defined with the B<oid_file> or
diff --git a/src/third_party/openssl/openssl/doc/apps/s_time.pod b/src/third_party/openssl/openssl/doc/apps/s_time.pod
index 5a38aa2..9082d87 100644
--- a/src/third_party/openssl/openssl/doc/apps/s_time.pod
+++ b/src/third_party/openssl/openssl/doc/apps/s_time.pod
@@ -26,7 +26,7 @@
=head1 DESCRIPTION
-The B<s_client> command implements a generic SSL/TLS client which connects to a
+The B<s_time> command implements a generic SSL/TLS client which connects to a
remote host using SSL/TLS. It can request a page from the server and includes
the time to transfer the payload data in its timing measurements. It measures
the number of connections within a given timeframe, the amount of data
@@ -127,7 +127,7 @@
=head1 NOTES
-B<s_client> can be used to measure the performance of an SSL connection.
+B<s_time> can be used to measure the performance of an SSL connection.
To connect to an SSL HTTP server and get the default page the command
openssl s_time -connect servername:443 -www / -CApath yourdir -CAfile yourfile.pem -cipher commoncipher [-ssl3]
diff --git a/src/third_party/openssl/openssl/doc/apps/x509.pod b/src/third_party/openssl/openssl/doc/apps/x509.pod
index 6109389..1bb0550 100644
--- a/src/third_party/openssl/openssl/doc/apps/x509.pod
+++ b/src/third_party/openssl/openssl/doc/apps/x509.pod
@@ -529,7 +529,8 @@
"space" additionally place a space after the separator to make it
more readable. The B<sep_multiline> uses a linefeed character for
the RDN separator and a spaced B<+> for the AVA separator. It also
-indents the fields by four characters.
+indents the fields by four characters. If no field separator is specified
+then B<sep_comma_plus_space> is used by default.
=item B<dn_rev>
diff --git a/src/third_party/openssl/openssl/doc/crypto/BIO_read.pod b/src/third_party/openssl/openssl/doc/crypto/BIO_read.pod
index b345281..2c177f0 100644
--- a/src/third_party/openssl/openssl/doc/crypto/BIO_read.pod
+++ b/src/third_party/openssl/openssl/doc/crypto/BIO_read.pod
@@ -9,9 +9,9 @@
#include <openssl/bio.h>
int BIO_read(BIO *b, void *buf, int len);
- int BIO_gets(BIO *b,char *buf, int size);
+ int BIO_gets(BIO *b, char *buf, int size);
int BIO_write(BIO *b, const void *buf, int len);
- int BIO_puts(BIO *b,const char *buf);
+ int BIO_puts(BIO *b, const char *buf);
=head1 DESCRIPTION
@@ -26,7 +26,7 @@
BIO_write() attempts to write B<len> bytes from B<buf> to BIO B<b>.
-BIO_puts() attempts to write a null terminated string B<buf> to BIO B<b>
+BIO_puts() attempts to write a null terminated string B<buf> to BIO B<b>.
=head1 RETURN VALUES
diff --git a/src/third_party/openssl/openssl/doc/crypto/BIO_s_connect.pod b/src/third_party/openssl/openssl/doc/crypto/BIO_s_connect.pod
index bcf7d8d..e238aee 100644
--- a/src/third_party/openssl/openssl/doc/crypto/BIO_s_connect.pod
+++ b/src/third_party/openssl/openssl/doc/crypto/BIO_s_connect.pod
@@ -21,8 +21,8 @@
long BIO_set_conn_int_port(BIO *b, char *port);
char *BIO_get_conn_hostname(BIO *b);
char *BIO_get_conn_port(BIO *b);
- char *BIO_get_conn_ip(BIO *b, dummy);
- long BIO_get_conn_int_port(BIO *b, int port);
+ char *BIO_get_conn_ip(BIO *b);
+ long BIO_get_conn_int_port(BIO *b);
long BIO_set_nbio(BIO *b, long n);
diff --git a/src/third_party/openssl/openssl/doc/crypto/BN_rand.pod b/src/third_party/openssl/openssl/doc/crypto/BN_rand.pod
index 3b2796c..fde5f72 100644
--- a/src/third_party/openssl/openssl/doc/crypto/BN_rand.pod
+++ b/src/third_party/openssl/openssl/doc/crypto/BN_rand.pod
@@ -19,7 +19,7 @@
=head1 DESCRIPTION
BN_rand() generates a cryptographically strong pseudo-random number of
-B<bits> bits in length and stores it in B<rnd>. If B<top> is -1, the
+B<bits> in length and stores it in B<rnd>. If B<top> is -1, the
most significant bit of the random number can be zero. If B<top> is 0,
it is set to 1, and if B<top> is 1, the two most significant bits of
the number will be set to 1, so that the product of two such random
@@ -33,7 +33,7 @@
protocols, but usually not for key generation etc.
BN_rand_range() generates a cryptographically strong pseudo-random
-number B<rnd> in the range 0 <lt>= B<rnd> E<lt> B<range>.
+number B<rnd> in the range 0 E<lt>= B<rnd> E<lt> B<range>.
BN_pseudo_rand_range() does the same, but is based on BN_pseudo_rand(),
and hence numbers generated by it are not necessarily unpredictable.
diff --git a/src/third_party/openssl/openssl/doc/crypto/DSA_generate_parameters.pod b/src/third_party/openssl/openssl/doc/crypto/DSA_generate_parameters.pod
index be7c924..f24c9c7 100644
--- a/src/third_party/openssl/openssl/doc/crypto/DSA_generate_parameters.pod
+++ b/src/third_party/openssl/openssl/doc/crypto/DSA_generate_parameters.pod
@@ -23,7 +23,7 @@
If B<seed> is B<NULL> or B<seed_len> E<lt> 20, the primes will be
generated at random. Otherwise, the seed is used to generate
them. If the given seed does not yield a prime q, a new random
-seed is chosen and placed at B<seed>.
+seed is chosen.
DSA_generate_parameters() places the iteration count in
*B<counter_ret> and a counter used for finding a generator in
diff --git a/src/third_party/openssl/openssl/doc/crypto/EVP_DigestVerifyInit.pod b/src/third_party/openssl/openssl/doc/crypto/EVP_DigestVerifyInit.pod
index cfeccd9..54cad92 100644
--- a/src/third_party/openssl/openssl/doc/crypto/EVP_DigestVerifyInit.pod
+++ b/src/third_party/openssl/openssl/doc/crypto/EVP_DigestVerifyInit.pod
@@ -37,10 +37,11 @@
or a negative value for failure. In particular a return value of -2 indicates
the operation is not supported by the public key algorithm.
-Unlike other functions the return value 0 from EVP_DigestVerifyFinal() only
-indicates that the signature did not verify successfully (that is tbs did
-not match the original data or the signature was of invalid form) it is not an
-indication of a more serious error.
+EVP_DigestVerifyFinal() returns 1 for success; any other value indicates
+failure. A return value of zero indicates that the signature did not verify
+successfully (that is, tbs did not match the original data or the signature had
+an invalid form), while other values indicate a more serious error (and
+sometimes also indicate an invalid signature form).
The error codes can be obtained from L<ERR_get_error(3)|ERR_get_error(3)>.
diff --git a/src/third_party/openssl/openssl/doc/crypto/EVP_SignInit.pod b/src/third_party/openssl/openssl/doc/crypto/EVP_SignInit.pod
index 14ecc77..c63d6b3 100644
--- a/src/third_party/openssl/openssl/doc/crypto/EVP_SignInit.pod
+++ b/src/third_party/openssl/openssl/doc/crypto/EVP_SignInit.pod
@@ -2,7 +2,8 @@
=head1 NAME
-EVP_SignInit, EVP_SignUpdate, EVP_SignFinal - EVP signing functions
+EVP_SignInit, EVP_SignInit_ex, EVP_SignUpdate, EVP_SignFinal - EVP signing
+functions
=head1 SYNOPSIS
diff --git a/src/third_party/openssl/openssl/doc/crypto/buffer.pod b/src/third_party/openssl/openssl/doc/crypto/buffer.pod
index 781f5b1..9d6de53 100644
--- a/src/third_party/openssl/openssl/doc/crypto/buffer.pod
+++ b/src/third_party/openssl/openssl/doc/crypto/buffer.pod
@@ -2,8 +2,11 @@
=head1 NAME
-BUF_MEM_new, BUF_MEM_free, BUF_MEM_grow, BUF_strdup - simple
-character arrays structure
+BUF_MEM_new, BUF_MEM_new_ex, BUF_MEM_free, BUF_MEM_grow - simple
+character array structure
+
+BUF_strdup, BUF_strndup, BUF_memdup, BUF_strlcpy, BUF_strlcat -
+standard C library equivalents
=head1 SYNOPSIS
@@ -15,26 +18,21 @@
int BUF_MEM_grow(BUF_MEM *str, int len);
- char * BUF_strdup(const char *str);
+ char *BUF_strdup(const char *str);
+
+ char *BUF_strndup(const char *str, size_t siz);
+
+ void *BUF_memdup(const void *data, size_t siz);
+
+ size_t BUF_strlcpy(char *dst, const char *src, size_t size);
+
+ size_t BUF_strlcat(char *dst, const char *src, size_t size);
=head1 DESCRIPTION
The buffer library handles simple character arrays. Buffers are used for
various purposes in the library, most notably memory BIOs.
-The library uses the BUF_MEM structure defined in buffer.h:
-
- typedef struct buf_mem_st
- {
- int length; /* current number of bytes */
- char *data;
- int max; /* size of buffer */
- } BUF_MEM;
-
-B<length> is the current size of the buffer in bytes, B<max> is the amount of
-memory allocated to the buffer. There are three functions which handle these
-and one "miscellaneous" function.
-
BUF_MEM_new() allocates a new buffer of zero size.
BUF_MEM_free() frees up an already existing buffer. The data is zeroed
@@ -44,14 +42,17 @@
B<len>. Any data already in the buffer is preserved if it increases in
size.
-BUF_strdup() copies a null terminated string into a block of allocated
-memory and returns a pointer to the allocated block.
-Unlike the standard C library strdup() this function uses OPENSSL_malloc() and so
-should be used in preference to the standard library strdup() because it can
-be used for memory leak checking or replacing the malloc() function.
+BUF_strdup(), BUF_strndup(), BUF_memdup(), BUF_strlcpy() and
+BUF_strlcat() are equivalents of the standard C library functions. The
+dup() functions use OPENSSL_malloc() underneath and so should be used
+in preference to the standard library for memory leak checking or
+replacing the malloc() function.
-The memory allocated from BUF_strdup() should be freed up using the OPENSSL_free()
-function.
+Memory allocated from these functions should be freed up using the
+OPENSSL_free() function.
+
+BUF_strndup makes the explicit guarantee that it will never read past
+the first B<siz> bytes of B<str>.
=head1 RETURN VALUES
diff --git a/src/third_party/openssl/openssl/doc/crypto/d2i_X509_NAME.pod b/src/third_party/openssl/openssl/doc/crypto/d2i_X509_NAME.pod
index 343ffe1..b025de7 100644
--- a/src/third_party/openssl/openssl/doc/crypto/d2i_X509_NAME.pod
+++ b/src/third_party/openssl/openssl/doc/crypto/d2i_X509_NAME.pod
@@ -14,7 +14,7 @@
=head1 DESCRIPTION
These functions decode and encode an B<X509_NAME> structure which is the
-the same as the B<Name> type defined in RFC2459 (and elsewhere) and used
+same as the B<Name> type defined in RFC2459 (and elsewhere) and used
for example in certificate subject and issuer names.
Othewise the functions behave in a similar way to d2i_X509() and i2d_X509()
diff --git a/src/third_party/openssl/openssl/doc/dir-locals.example.el b/src/third_party/openssl/openssl/doc/dir-locals.example.el
new file mode 100644
index 0000000..79d0b01
--- /dev/null
+++ b/src/third_party/openssl/openssl/doc/dir-locals.example.el
@@ -0,0 +1,15 @@
+;;; This is an example of what a .dir-locals.el suitable for OpenSSL
+;;; development could look like.
+;;;
+;;; Apart from setting the CC mode style to "OpenSSL-II", it also
+;;; makes sure that tabs are never used for indentation in any file,
+;;; and that the fill column is 78.
+;;;
+;;; For more information see (info "(emacs) Directory Variables")
+
+((nil
+ (indent-tabs-mode . nil)
+ (fill-column . 78)
+ )
+ (c-mode
+ (c-file-style . "OpenSSL-II")))
diff --git a/src/third_party/openssl/openssl/doc/openssl-c-indent.el b/src/third_party/openssl/openssl/doc/openssl-c-indent.el
new file mode 100644
index 0000000..144a915
--- /dev/null
+++ b/src/third_party/openssl/openssl/doc/openssl-c-indent.el
@@ -0,0 +1,62 @@
+;;; This Emacs Lisp file defines a C indentation style for OpenSSL.
+;;;
+;;; This definition is for the "CC mode" package, which is the default
+;;; mode for editing C source files in Emacs 20, not for the older
+;;; c-mode.el (which was the default in less recent releaes of Emacs 19).
+;;;
+;;; Recommended use is to add this line in your .emacs:
+;;;
+;;; (load (expand-file-name "~/PATH/TO/openssl-c-indent.el"))
+;;;
+;;; To activate this indentation style, visit a C file, type
+;;; M-x c-set-style <RET> (or C-c . for short), and enter "eay".
+;;; To toggle the auto-newline feature of CC mode, type C-c C-a.
+;;;
+;;; If you're a OpenSSL developer, you might find it more comfortable
+;;; to have this style be permanent in your OpenSSL development
+;;; directory. To have that, please perform this:
+;;;
+;;; M-x add-dir-local-variable <RET> c-mode <RET> c-file-style <RET>
+;;; "OpenSSL-II" <RET>
+;;;
+;;; A new buffer with .dir-locals.el will appear. Save it (C-x C-s).
+;;;
+;;; Alternatively, have a look at dir-locals.example.el
+
+;;; For suggesting improvements, please send e-mail to levitte@openssl.org.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Note, it could be easy to inherit from the "gnu" style... however,
+;; one never knows if that style will change somewhere in the future,
+;; so I've chosen to copy the "gnu" style values explicitely instead
+;; and mark them with a comment. // RLevitte 2015-08-31
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(c-add-style "OpenSSL-II"
+ '((c-basic-offset . 4)
+ (indent-tabs-mode . nil)
+ (fill-column . 78)
+ (comment-column . 33)
+ (c-comment-only-line-offset 0 . 0) ; From "gnu" style
+ (c-hanging-braces-alist ; From "gnu" style
+ (substatement-open before after) ; From "gnu" style
+ (arglist-cont-nonempty)) ; From "gnu" style
+ (c-offsets-alist
+ (statement-block-intro . +) ; From "gnu" style
+ (knr-argdecl-intro . 0)
+ (knr-argdecl . 0)
+ (substatement-open . +) ; From "gnu" style
+ (substatement-label . 0) ; From "gnu" style
+ (label . 1)
+ (statement-case-open . +) ; From "gnu" style
+ (statement-cont . +) ; From "gnu" style
+ (arglist-intro . c-lineup-arglist-intro-after-paren) ; From "gnu" style
+ (arglist-close . c-lineup-arglist) ; From "gnu" style
+ (inline-open . 0) ; From "gnu" style
+ (brace-list-open . +) ; From "gnu" style
+ (topmost-intro-cont first c-lineup-topmost-intro-cont
+ c-lineup-gnu-DEFUN-intro-cont) ; From "gnu" style
+ )
+ (c-special-indent-hook . c-gnu-impose-minimum) ; From "gnu" style
+ (c-block-comment-prefix . "* ")
+ ))
diff --git a/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_add_extra_chain_cert.pod b/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_add_extra_chain_cert.pod
index 5955ee1..18fb2e2 100644
--- a/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_add_extra_chain_cert.pod
+++ b/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_add_extra_chain_cert.pod
@@ -2,29 +2,39 @@
=head1 NAME
-SSL_CTX_add_extra_chain_cert - add certificate to chain
+SSL_CTX_add_extra_chain_cert, SSL_CTX_clear_extra_chain_certs - add or clear
+extra chain certificates
=head1 SYNOPSIS
#include <openssl/ssl.h>
- long SSL_CTX_add_extra_chain_cert(SSL_CTX ctx, X509 *x509)
+ long SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509);
+ long SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx);
=head1 DESCRIPTION
-SSL_CTX_add_extra_chain_cert() adds the certificate B<x509> to the certificate
-chain presented together with the certificate. Several certificates
-can be added one after the other.
+SSL_CTX_add_extra_chain_cert() adds the certificate B<x509> to the extra chain
+certificates associated with B<ctx>. Several certificates can be added one
+after another.
+
+SSL_CTX_clear_extra_chain_certs() clears all extra chain certificates
+associated with B<ctx>.
+
+These functions are implemented as macros.
=head1 NOTES
-When constructing the certificate chain, the chain will be formed from
-these certificates explicitly specified. If no chain is specified,
-the library will try to complete the chain from the available CA
-certificates in the trusted CA storage, see
+When sending a certificate chain, extra chain certificates are sent in order
+following the end entity certificate.
+
+If no chain is specified, the library will try to complete the chain from the
+available CA certificates in the trusted CA storage, see
L<SSL_CTX_load_verify_locations(3)|SSL_CTX_load_verify_locations(3)>.
-The B<x509> certificate provided to SSL_CTX_add_extra_chain_cert() will be freed by the library when the B<SSL_CTX> is destroyed. An application B<should not> free the B<x509> object.
+The B<x509> certificate provided to SSL_CTX_add_extra_chain_cert() will be
+freed by the library when the B<SSL_CTX> is destroyed. An application
+B<should not> free the B<x509> object.
=head1 RESTRICTIONS
@@ -36,8 +46,9 @@
=head1 RETURN VALUES
-SSL_CTX_add_extra_chain_cert() returns 1 on success. Check out the
-error stack to find out the reason for failure otherwise.
+SSL_CTX_add_extra_chain_cert() and SSL_CTX_clear_extra_chain_certs() return
+1 on success and 0 for failure. Check out the error stack to find out the
+reason for failure.
=head1 SEE ALSO
diff --git a/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod b/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod
new file mode 100644
index 0000000..b8147ba
--- /dev/null
+++ b/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set_tlsext_status_cb, SSL_CTX_set_tlsext_status_arg,
+SSL_set_tlsext_status_type, SSL_get_tlsext_status_ocsp_resp,
+SSL_set_tlsext_status_ocsp_resp - OCSP Certificate Status Request functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/tls1.h>
+
+ long SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
+ int (*callback)(SSL *, void *));
+ long SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
+
+ long SSL_set_tlsext_status_type(SSL *s, int type);
+
+ long SSL_get_tlsext_status_ocsp_resp(ssl, unsigned char **resp);
+ long SSL_set_tlsext_status_ocsp_resp(ssl, unsigned char *resp, int len);
+
+=head1 DESCRIPTION
+
+A client application may request that a server send back an OCSP status response
+(also known as OCSP stapling). To do so the client should call the
+SSL_set_tlsext_status_type() function prior to the start of the handshake.
+Currently the only supported type is B<TLSEXT_STATUSTYPE_ocsp>. This value
+should be passed in the B<type> argument. The client should additionally provide
+a callback function to decide what to do with the returned OCSP response by
+calling SSL_CTX_set_tlsext_status_cb(). The callback function should determine
+whether the returned OCSP response is acceptable or not. The callback will be
+passed as an argument the value previously set via a call to
+SSL_CTX_set_tlsext_status_arg(). Note that the callback will not be called in
+the event of a handshake where session resumption occurs (because there are no
+Certificates exchanged in such a handshake).
+
+The response returned by the server can be obtained via a call to
+SSL_get_tlsext_status_ocsp_resp(). The value B<*resp> will be updated to point
+to the OCSP response data and the return value will be the length of that data.
+Typically a callback would obtain an OCSP_RESPONSE object from this data via a
+call to the d2i_OCSP_RESPONSE() function. If the server has not provided any
+response data then B<*resp> will be NULL and the return value from
+SSL_get_tlsext_status_ocsp_resp() will be -1.
+
+A server application must also call the SSL_CTX_set_tlsext_status_cb() function
+if it wants to be able to provide clients with OCSP Certificate Status
+responses. Typically the server callback would obtain the server certificate
+that is being sent back to the client via a call to SSL_get_certificate();
+obtain the OCSP response to be sent back; and then set that response data by
+calling SSL_set_tlsext_status_ocsp_resp(). A pointer to the response data should
+be provided in the B<resp> argument, and the length of that data should be in
+the B<len> argument.
+
+=head1 RETURN VALUES
+
+The callback when used on the client side should return a negative value on
+error; 0 if the response is not acceptable (in which case the handshake will
+fail) or a positive value if it is acceptable.
+
+The callback when used on the server side should return with either
+SSL_TLSEXT_ERR_OK (meaning that the OCSP response that has been set should be
+returned), SSL_TLSEXT_ERR_NOACK (meaning that an OCSP response should not be
+returned) or SSL_TLSEXT_ERR_ALERT_FATAL (meaning that a fatal error has
+occurred).
+
+SSL_CTX_set_tlsext_status_cb(), SSL_CTX_set_tlsext_status_arg(),
+SSL_set_tlsext_status_type() and SSL_set_tlsext_status_ocsp_resp() return 0 on
+error or 1 on success.
+
+SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP response data
+or -1 if there is no OCSP response data.
+
+=cut
diff --git a/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod b/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod
index b754c16..234fbc8 100644
--- a/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod
+++ b/src/third_party/openssl/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod
@@ -48,25 +48,8 @@
only used for signing.
In order to perform a DH key exchange the server must use a DH group
-(DH parameters) and generate a DH key.
-The server will always generate a new DH key during the negotiation
-if either the DH parameters are supplied via callback or the
-SSL_OP_SINGLE_DH_USE option of SSL_CTX_set_options(3) is set (or both).
-It will immediately create a DH key if DH parameters are supplied via
-SSL_CTX_set_tmp_dh() and SSL_OP_SINGLE_DH_USE is not set.
-In this case,
-it may happen that a key is generated on initialization without later
-being needed, while on the other hand the computer time during the
-negotiation is being saved.
-
-If "strong" primes were used to generate the DH parameters, it is not strictly
-necessary to generate a new key for each handshake but it does improve forward
-secrecy. If it is not assured that "strong" primes were used,
-SSL_OP_SINGLE_DH_USE must be used in order to prevent small subgroup
-attacks. Always using SSL_OP_SINGLE_DH_USE has an impact on the
-computer time needed during negotiation, but it is not very large, so
-application authors/users should consider always enabling this option.
-The option is required to implement perfect forward secrecy (PFS).
+(DH parameters) and generate a DH key. The server will always generate
+a new DH key during the negotiation.
As generating DH parameters is extremely time consuming, an application
should not generate the parameters on the fly but supply the parameters.
@@ -93,10 +76,9 @@
Previous versions of the callback used B<is_export> and B<keylength>
parameters to control parameter generation for export and non-export
cipher suites. Modern servers that do not support export ciphersuites
-are advised to either use SSL_CTX_set_tmp_dh() in combination with
-SSL_OP_SINGLE_DH_USE, or alternatively, use the callback but ignore
-B<keylength> and B<is_export> and simply supply at least 2048-bit
-parameters in the callback.
+are advised to either use SSL_CTX_set_tmp_dh() or alternatively, use
+the callback but ignore B<keylength> and B<is_export> and simply
+supply at least 2048-bit parameters in the callback.
=head1 EXAMPLES
@@ -128,7 +110,6 @@
if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1) {
/* Error. */
}
- SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
...
=head1 RETURN VALUES
diff --git a/src/third_party/openssl/openssl/e_os.h b/src/third_party/openssl/openssl/e_os.h
index c86a1e4..8f67237 100644
--- a/src/third_party/openssl/openssl/e_os.h
+++ b/src/third_party/openssl/openssl/e_os.h
@@ -326,7 +326,7 @@
# undef isxdigit
# endif
# if defined(_MSC_VER) && !defined(_DLL) && defined(stdin)
-# if _MSC_VER>=1300
+# if _MSC_VER>=1300 && _MSC_VER<1600
# undef stdin
# undef stdout
# undef stderr
@@ -334,7 +334,7 @@
# define stdin (&__iob_func()[0])
# define stdout (&__iob_func()[1])
# define stderr (&__iob_func()[2])
-# elif defined(I_CAN_LIVE_WITH_LNK4049)
+# elif _MSC_VER<1300 && defined(I_CAN_LIVE_WITH_LNK4049)
# undef stdin
# undef stdout
# undef stderr
@@ -625,7 +625,7 @@
# include <sys/select.h>
# endif
-# if defined(sun)
+# if defined(__sun) || defined(sun)
# include <sys/filio.h>
# else
# ifndef VMS
@@ -667,7 +667,7 @@
# endif
-# if defined(sun) && !defined(__svr4__) && !defined(__SVR4)
+# if (defined(__sun) || defined(sun)) && !defined(__svr4__) && !defined(__SVR4)
/* include headers first, so our defines don't break it */
# include <stdlib.h>
# include <string.h>
diff --git a/src/third_party/openssl/openssl/engines/e_chil.c b/src/third_party/openssl/openssl/engines/e_chil.c
index 69d49d7..5dfab51 100644
--- a/src/third_party/openssl/openssl/engines/e_chil.c
+++ b/src/third_party/openssl/openssl/engines/e_chil.c
@@ -1,4 +1,4 @@
-/* crypto/engine/e_chil.c -*- mode: C; c-file-style: "eay" -*- */
+/* crypto/engine/e_chil.c */
/*
* Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
* (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for
@@ -839,6 +839,10 @@
bn_fix_top(rtmp->n);
res = EVP_PKEY_new();
+ if (res == NULL) {
+ HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
+ goto err;
+ }
EVP_PKEY_assign_RSA(res, rtmp);
# endif
diff --git a/src/third_party/openssl/openssl/openssl.spec b/src/third_party/openssl/openssl/openssl.spec
index 67a6074..386f9f6 100644
--- a/src/third_party/openssl/openssl/openssl.spec
+++ b/src/third_party/openssl/openssl/openssl.spec
@@ -7,7 +7,7 @@
Summary: Secure Sockets Layer and cryptography libraries and tools
Name: openssl
#Version: %{libmaj}.%{libmin}.%{librel}
-Version: 1.0.1p
+Version: 1.0.1r
Source0: ftp://ftp.openssl.org/source/%{name}-%{version}.tar.gz
License: OpenSSL
Group: System Environment/Libraries
diff --git a/src/third_party/openssl/openssl/ssl/Makefile b/src/third_party/openssl/openssl/ssl/Makefile
index 29d9e45..ad14abb 100644
--- a/src/third_party/openssl/openssl/ssl/Makefile
+++ b/src/third_party/openssl/openssl/ssl/Makefile
@@ -15,7 +15,7 @@
CFLAGS= $(INCLUDES) $(CFLAG)
GENERAL=Makefile README ssl-lib.com install.com
-TEST=ssltest.c heartbeat_test.c
+TEST=ssltest.c heartbeat_test.c clienthellotest.c
APPS=
LIB=$(TOP)/libssl.a
diff --git a/src/third_party/openssl/openssl/ssl/bio_ssl.c b/src/third_party/openssl/openssl/ssl/bio_ssl.c
index 02de512..231ba55 100644
--- a/src/third_party/openssl/openssl/ssl/bio_ssl.c
+++ b/src/third_party/openssl/openssl/ssl/bio_ssl.c
@@ -422,6 +422,10 @@
BIO_set_flags(b, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY);
b->retry_reason = b->next_bio->retry_reason;
break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ BIO_set_retry_special(b);
+ b->retry_reason = BIO_RR_SSL_X509_LOOKUP;
+ break;
default:
break;
}
diff --git a/src/third_party/openssl/openssl/ssl/clienthellotest.c b/src/third_party/openssl/openssl/ssl/clienthellotest.c
new file mode 100644
index 0000000..a00a7ea
--- /dev/null
+++ b/src/third_party/openssl/openssl/ssl/clienthellotest.c
@@ -0,0 +1,218 @@
+/* Written by Matt Caswell for the OpenSSL Project */
+/* ====================================================================
+ * Copyright (c) 1998-2015 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+
+#define CLIENT_VERSION_LEN 2
+#define SESSION_ID_LEN_LEN 1
+#define CIPHERS_LEN_LEN 2
+#define COMPRESSION_LEN_LEN 1
+#define EXTENSIONS_LEN_LEN 2
+#define EXTENSION_TYPE_LEN 2
+#define EXTENSION_SIZE_LEN 2
+
+
+#define TOTAL_NUM_TESTS 2
+
+/*
+ * Test that explicitly setting ticket data results in it appearing in the
+ * ClientHello for TLS1.2
+ */
+#define TEST_SET_SESSION_TICK_DATA_TLS_1_2 0
+
+/*
+ * Test that explicitly setting ticket data results in it appearing in the
+ * ClientHello for a negotiated SSL/TLS version
+ */
+#define TEST_SET_SESSION_TICK_DATA_VER_NEG 1
+
+int main(int argc, char *argv[])
+{
+ SSL_CTX *ctx;
+ SSL *con;
+ BIO *rbio;
+ BIO *wbio;
+ BIO *err;
+ long len;
+ unsigned char *data;
+ unsigned char *dataend;
+ char *dummytick = "Hello World!";
+ unsigned int tmplen;
+ unsigned int type;
+ unsigned int size;
+ int testresult = 0;
+ int currtest = 0;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
+ CRYPTO_malloc_debug_init();
+ CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+ /*
+ * For each test set up an SSL_CTX and SSL and see what ClientHello gets
+ * produced when we try to connect
+ */
+ for (; currtest < TOTAL_NUM_TESTS; currtest++) {
+ testresult = 0;
+ if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2) {
+ ctx = SSL_CTX_new(TLSv1_2_method());
+ } else {
+ ctx = SSL_CTX_new(SSLv23_method());
+ }
+ con = SSL_new(ctx);
+
+ rbio = BIO_new(BIO_s_mem());
+ wbio = BIO_new(BIO_s_mem());
+ SSL_set_bio(con, rbio, wbio);
+ SSL_set_connect_state(con);
+
+ if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2
+ || currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) {
+ if (!SSL_set_session_ticket_ext(con, dummytick, strlen(dummytick)))
+ goto end;
+ }
+
+ if (SSL_connect(con) > 0) {
+ /* This shouldn't succeed because we don't have a server! */
+ goto end;
+ }
+
+ len = BIO_get_mem_data(wbio, (char **)&data);
+ dataend = data + len;
+
+ /* Skip the record header */
+ data += SSL3_RT_HEADER_LENGTH;
+ /* Skip the handshake message header */
+ data += SSL3_HM_HEADER_LENGTH;
+ /* Skip client version and random */
+ data += CLIENT_VERSION_LEN + SSL3_RANDOM_SIZE;
+ if (data + SESSION_ID_LEN_LEN > dataend)
+ goto end;
+ /* Skip session id */
+ tmplen = *data;
+ data += SESSION_ID_LEN_LEN + tmplen;
+ if (data + CIPHERS_LEN_LEN > dataend)
+ goto end;
+ /* Skip ciphers */
+ tmplen = ((*data) << 8) | *(data + 1);
+ data += CIPHERS_LEN_LEN + tmplen;
+ if (data + COMPRESSION_LEN_LEN > dataend)
+ goto end;
+ /* Skip compression */
+ tmplen = *data;
+ data += COMPRESSION_LEN_LEN + tmplen;
+ if (data + EXTENSIONS_LEN_LEN > dataend)
+ goto end;
+ /* Extensions len */
+ tmplen = ((*data) << 8) | *(data + 1);
+ data += EXTENSIONS_LEN_LEN;
+ if (data + tmplen > dataend)
+ goto end;
+
+ /* Loop through all extensions */
+ while (tmplen > EXTENSION_TYPE_LEN + EXTENSION_SIZE_LEN) {
+ type = ((*data) << 8) | *(data + 1);
+ data += EXTENSION_TYPE_LEN;
+ size = ((*data) << 8) | *(data + 1);
+ data += EXTENSION_SIZE_LEN;
+ if (data + size > dataend)
+ goto end;
+
+ if (type == TLSEXT_TYPE_session_ticket) {
+ if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2
+ || currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) {
+ if (size == strlen(dummytick)
+ && memcmp(data, dummytick, size) == 0) {
+ /* Ticket data is as we expected */
+ testresult = 1;
+ } else {
+ printf("Received session ticket is not as expected\n");
+ }
+ break;
+ }
+ }
+
+ tmplen -= EXTENSION_TYPE_LEN + EXTENSION_SIZE_LEN + size;
+ data += size;
+ }
+
+ end:
+ SSL_free(con);
+ SSL_CTX_free(ctx);
+ if (!testresult) {
+ printf("ClientHello test: FAILED (Test %d)\n", currtest);
+ break;
+ }
+ }
+
+ ERR_free_strings();
+ ERR_remove_thread_state(NULL);
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+ CRYPTO_mem_leaks(err);
+
+ return testresult?0:1;
+}
diff --git a/src/third_party/openssl/openssl/ssl/d1_both.c b/src/third_party/openssl/openssl/ssl/d1_both.c
index 8dd8ea3..aaa1867 100644
--- a/src/third_party/openssl/openssl/ssl/d1_both.c
+++ b/src/third_party/openssl/openssl/ssl/d1_both.c
@@ -291,8 +291,44 @@
blocksize = 0;
frag_off = 0;
+ s->rwstate = SSL_NOTHING;
+
/* s->init_num shouldn't ever be < 0...but just in case */
while (s->init_num > 0) {
+ if (type == SSL3_RT_HANDSHAKE && s->init_off != 0) {
+ /* We must be writing a fragment other than the first one */
+
+ if (frag_off > 0) {
+ /* This is the first attempt at writing out this fragment */
+
+ if (s->init_off <= DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * Each fragment that was already sent must at least have
+ * contained the message header plus one other byte.
+ * Therefore |init_off| must have progressed by at least
+ * |DTLS1_HM_HEADER_LENGTH + 1| bytes. If not something went
+ * wrong.
+ */
+ return -1;
+ }
+
+ /*
+ * Adjust |init_off| and |init_num| to allow room for a new
+ * message header for this fragment.
+ */
+ s->init_off -= DTLS1_HM_HEADER_LENGTH;
+ s->init_num += DTLS1_HM_HEADER_LENGTH;
+ } else {
+ /*
+ * We must have been called again after a retry so use the
+ * fragment offset from our last attempt. We do not need
+ * to adjust |init_off| and |init_num| as above, because
+ * that should already have been done before the retry.
+ */
+ frag_off = s->d1->w_msg_hdr.frag_off;
+ }
+ }
+
used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH
+ mac_size + blocksize;
if (s->d1->mtu > used_len)
@@ -305,8 +341,10 @@
* grr.. we could get an error if MTU picked was wrong
*/
ret = BIO_flush(SSL_get_wbio(s));
- if (ret <= 0)
+ if (ret <= 0) {
+ s->rwstate = SSL_WRITING;
return ret;
+ }
used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) {
curr_mtu = s->d1->mtu - used_len;
@@ -332,25 +370,6 @@
* XDTLS: this function is too long. split out the CCS part
*/
if (type == SSL3_RT_HANDSHAKE) {
- if (s->init_off != 0) {
- OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
- s->init_off -= DTLS1_HM_HEADER_LENGTH;
- s->init_num += DTLS1_HM_HEADER_LENGTH;
-
- /*
- * We just checked that s->init_num > 0 so this cast should
- * be safe
- */
- if (((unsigned int)s->init_num) > curr_mtu)
- len = curr_mtu;
- else
- len = s->init_num;
- }
-
- /* Shouldn't ever happen */
- if (len > INT_MAX)
- len = INT_MAX;
-
if (len < DTLS1_HM_HEADER_LENGTH) {
/*
* len is so small that we really can't do anything sensible
@@ -438,7 +457,16 @@
}
s->init_off += ret;
s->init_num -= ret;
- frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
+ ret -= DTLS1_HM_HEADER_LENGTH;
+ frag_off += ret;
+
+ /*
+ * We save the fragment offset for the next fragment so we have it
+ * available in case of an IO retry. We don't know the length of the
+ * next fragment yet so just set that to 0 for now. It will be
+ * updated again later.
+ */
+ dtls1_fix_message_header(s, frag_off, 0);
}
}
return (0);
@@ -1490,9 +1518,12 @@
{
int ret;
#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+ BIO *wbio;
+
+ wbio = SSL_get_wbio(s);
+ if (wbio != NULL && BIO_dgram_is_sctp(wbio) &&
!(s->shutdown & SSL_SENT_SHUTDOWN)) {
- ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ ret = BIO_dgram_sctp_wait_for_dry(wbio);
if (ret < 0)
return -1;
diff --git a/src/third_party/openssl/openssl/ssl/d1_clnt.c b/src/third_party/openssl/openssl/ssl/d1_clnt.c
index 377c1e6..eb371a2 100644
--- a/src/third_party/openssl/openssl/ssl/d1_clnt.c
+++ b/src/third_party/openssl/openssl/ssl/d1_clnt.c
@@ -299,13 +299,12 @@
#endif
case SSL3_ST_CW_CLNT_HELLO_A:
- case SSL3_ST_CW_CLNT_HELLO_B:
-
s->shutdown = 0;
/* every DTLS ClientHello resets Finished MAC */
ssl3_init_finished_mac(s);
+ case SSL3_ST_CW_CLNT_HELLO_B:
dtls1_start_timer(s);
ret = dtls1_client_hello(s);
if (ret <= 0)
@@ -350,11 +349,15 @@
sizeof(DTLS1_SCTP_AUTH_LABEL),
DTLS1_SCTP_AUTH_LABEL);
- SSL_export_keying_material(s, sctpauthkey,
+ if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey),
labelbuffer,
sizeof(labelbuffer), NULL, 0,
- 0);
+ 0) <= 0) {
+ ret = -1;
+ s->state = SSL_ST_ERR;
+ goto end;
+ }
BIO_ctrl(SSL_get_wbio(s),
BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
@@ -362,6 +365,10 @@
#endif
s->state = SSL3_ST_CR_FINISHED_A;
+ if (s->tlsext_ticket_expected) {
+ /* receive renewed session ticket */
+ s->state = SSL3_ST_CR_SESSION_TICKET_A;
+ }
} else
s->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
}
@@ -484,9 +491,13 @@
snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
DTLS1_SCTP_AUTH_LABEL);
- SSL_export_keying_material(s, sctpauthkey,
+ if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
- sizeof(labelbuffer), NULL, 0, 0);
+ sizeof(labelbuffer), NULL, 0, 0) <= 0) {
+ ret = -1;
+ s->state = SSL_ST_ERR;
+ goto end;
+ }
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
diff --git a/src/third_party/openssl/openssl/ssl/d1_srvr.c b/src/third_party/openssl/openssl/ssl/d1_srvr.c
index 41c7dc5..f01b8a6 100644
--- a/src/third_party/openssl/openssl/ssl/d1_srvr.c
+++ b/src/third_party/openssl/openssl/ssl/d1_srvr.c
@@ -267,6 +267,19 @@
ssl3_init_finished_mac(s);
s->state = SSL3_ST_SR_CLNT_HELLO_A;
s->ctx->stats.sess_accept++;
+ } else if (!s->s3->send_connection_binding &&
+ !(s->options &
+ SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
+ /*
+ * Server attempting to renegotiate with client that doesn't
+ * support secure renegotiation.
+ */
+ SSLerr(SSL_F_DTLS1_ACCEPT,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ ret = -1;
+ s->state = SSL_ST_ERR;
+ goto end;
} else {
/*
* s->state == SSL_ST_RENEGOTIATE, we will just send a
@@ -405,9 +418,13 @@
snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
DTLS1_SCTP_AUTH_LABEL);
- SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey), labelbuffer,
- sizeof(labelbuffer), NULL, 0, 0);
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ sizeof(labelbuffer), NULL, 0, 0) <= 0) {
+ ret = -1;
+ s->state = SSL_ST_ERR;
+ goto end;
+ }
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
@@ -628,9 +645,13 @@
snprintf((char *)labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
DTLS1_SCTP_AUTH_LABEL);
- SSL_export_keying_material(s, sctpauthkey,
+ if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
- sizeof(labelbuffer), NULL, 0, 0);
+ sizeof(labelbuffer), NULL, 0, 0) <= 0) {
+ ret = -1;
+ s->state = SSL_ST_ERR;
+ goto end;
+ }
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
diff --git a/src/third_party/openssl/openssl/ssl/kssl.c b/src/third_party/openssl/openssl/ssl/kssl.c
index cf58567..f2839bd 100644
--- a/src/third_party/openssl/openssl/ssl/kssl.c
+++ b/src/third_party/openssl/openssl/ssl/kssl.c
@@ -1,4 +1,4 @@
-/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */
+/* ssl/kssl.c */
/*
* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
* 2000.
diff --git a/src/third_party/openssl/openssl/ssl/kssl.h b/src/third_party/openssl/openssl/ssl/kssl.h
index 9a57672..ae8a51f 100644
--- a/src/third_party/openssl/openssl/ssl/kssl.h
+++ b/src/third_party/openssl/openssl/ssl/kssl.h
@@ -1,4 +1,4 @@
-/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* ssl/kssl.h */
/*
* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
* 2000. project 2000.
diff --git a/src/third_party/openssl/openssl/ssl/kssl_lcl.h b/src/third_party/openssl/openssl/ssl/kssl_lcl.h
index 46dcef2..8e6a6d6 100644
--- a/src/third_party/openssl/openssl/ssl/kssl_lcl.h
+++ b/src/third_party/openssl/openssl/ssl/kssl_lcl.h
@@ -1,4 +1,4 @@
-/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* ssl/kssl.h */
/*
* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
* 2000. project 2000.
diff --git a/src/third_party/openssl/openssl/ssl/s23_clnt.c b/src/third_party/openssl/openssl/ssl/s23_clnt.c
index 9b0b0e8..745dca5 100644
--- a/src/third_party/openssl/openssl/ssl/s23_clnt.c
+++ b/src/third_party/openssl/openssl/ssl/s23_clnt.c
@@ -376,12 +376,13 @@
buf = (unsigned char *)s->init_buf->data;
if (s->state == SSL23_ST_CW_CLNT_HELLO_A) {
-#if 0
- /* don't reuse session-id's */
+ /*
+ * Since we're sending s23 client hello, we're not reusing a session, as
+ * we'd be using the method from the saved session instead
+ */
if (!ssl_get_new_session(s, 0)) {
- return (-1);
+ return -1;
}
-#endif
p = s->s3->client_random;
if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0)
@@ -442,9 +443,6 @@
/*
* put in the session-id length (zero since there is no reuse)
*/
-#if 0
- s->session->session_id_length = 0;
-#endif
s2n(0, d);
if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
@@ -732,6 +730,8 @@
goto err;
}
+ s->session->ssl_version = s->version;
+
/* ensure that TLS_MAX_VERSION is up-to-date */
OPENSSL_assert(s->version <= TLS_MAX_VERSION);
@@ -787,13 +787,6 @@
}
s->init_num = 0;
- /*
- * Since, if we are sending a ssl23 client hello, we are not reusing a
- * session-id
- */
- if (!ssl_get_new_session(s, 0))
- goto err;
-
return (SSL_connect(s));
err:
return (-1);
diff --git a/src/third_party/openssl/openssl/ssl/s2_srvr.c b/src/third_party/openssl/openssl/ssl/s2_srvr.c
index a0be10c..b891f26 100644
--- a/src/third_party/openssl/openssl/ssl/s2_srvr.c
+++ b/src/third_party/openssl/openssl/ssl/s2_srvr.c
@@ -405,7 +405,7 @@
}
cp = ssl2_get_cipher_by_char(p);
- if (cp == NULL) {
+ if (cp == NULL || sk_SSL_CIPHER_find(s->session->ciphers, cp) < 0) {
ssl2_return_error(s, SSL2_PE_NO_CIPHER);
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_NO_CIPHER_MATCH);
return (-1);
@@ -601,6 +601,11 @@
s->s2->tmp.cipher_spec_length = i;
n2s(p, i);
s->s2->tmp.session_id_length = i;
+ if ((i < 0) || (i > SSL_MAX_SSL_SESSION_ID_LENGTH)) {
+ ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+ SSLerr(SSL_F_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ return -1;
+ }
n2s(p, i);
s->s2->challenge_length = i;
if ((i < SSL2_MIN_CHALLENGE_LENGTH) ||
@@ -690,8 +695,12 @@
prio = cs;
allow = cl;
}
+
+ /* Generate list of SSLv2 ciphers shared between client and server */
for (z = 0; z < sk_SSL_CIPHER_num(prio); z++) {
- if (sk_SSL_CIPHER_find(allow, sk_SSL_CIPHER_value(prio, z)) < 0) {
+ const SSL_CIPHER *cp = sk_SSL_CIPHER_value(prio, z);
+ if ((cp->algorithm_ssl & SSL_SSLV2) == 0 ||
+ sk_SSL_CIPHER_find(allow, cp) < 0) {
(void)sk_SSL_CIPHER_delete(prio, z);
z--;
}
@@ -700,6 +709,13 @@
sk_SSL_CIPHER_free(s->session->ciphers);
s->session->ciphers = prio;
}
+
+ /* Make sure we have at least one cipher in common */
+ if (sk_SSL_CIPHER_num(s->session->ciphers) == 0) {
+ ssl2_return_error(s, SSL2_PE_NO_CIPHER);
+ SSLerr(SSL_F_GET_CLIENT_HELLO, SSL_R_NO_CIPHER_MATCH);
+ return -1;
+ }
/*
* s->session->ciphers should now have a list of ciphers that are on
* both the client and server. This list is ordered by the order the
diff --git a/src/third_party/openssl/openssl/ssl/s3_cbc.c b/src/third_party/openssl/openssl/ssl/s3_cbc.c
index 28ca50b..fd014b5 100644
--- a/src/third_party/openssl/openssl/ssl/s3_cbc.c
+++ b/src/third_party/openssl/openssl/ssl/s3_cbc.c
@@ -411,8 +411,9 @@
* functions, above, we know that data_plus_mac_size is large enough to contain
* a padding byte and MAC. (If the padding was invalid, it might contain the
* padding too. )
+ * Returns 1 on success or 0 on error
*/
-void ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
+int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
unsigned char *md_out,
size_t *md_out_size,
const unsigned char header[13],
@@ -455,7 +456,8 @@
switch (EVP_MD_CTX_type(ctx)) {
case NID_md5:
- MD5_Init((MD5_CTX *)md_state.c);
+ if (MD5_Init((MD5_CTX *)md_state.c) <= 0)
+ return 0;
md_final_raw = tls1_md5_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))MD5_Transform;
@@ -464,7 +466,8 @@
length_is_big_endian = 0;
break;
case NID_sha1:
- SHA1_Init((SHA_CTX *)md_state.c);
+ if (SHA1_Init((SHA_CTX *)md_state.c) <= 0)
+ return 0;
md_final_raw = tls1_sha1_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA1_Transform;
@@ -472,14 +475,16 @@
break;
#ifndef OPENSSL_NO_SHA256
case NID_sha224:
- SHA224_Init((SHA256_CTX *)md_state.c);
+ if (SHA224_Init((SHA256_CTX *)md_state.c) <= 0)
+ return 0;
md_final_raw = tls1_sha256_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
md_size = 224 / 8;
break;
case NID_sha256:
- SHA256_Init((SHA256_CTX *)md_state.c);
+ if (SHA256_Init((SHA256_CTX *)md_state.c) <= 0)
+ return 0;
md_final_raw = tls1_sha256_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
@@ -488,7 +493,8 @@
#endif
#ifndef OPENSSL_NO_SHA512
case NID_sha384:
- SHA384_Init((SHA512_CTX *)md_state.c);
+ if (SHA384_Init((SHA512_CTX *)md_state.c) <= 0)
+ return 0;
md_final_raw = tls1_sha512_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA512_Transform;
@@ -497,7 +503,8 @@
md_length_size = 16;
break;
case NID_sha512:
- SHA512_Init((SHA512_CTX *)md_state.c);
+ if (SHA512_Init((SHA512_CTX *)md_state.c) <= 0)
+ return 0;
md_final_raw = tls1_sha512_final_raw;
md_transform =
(void (*)(void *ctx, const unsigned char *block))SHA512_Transform;
@@ -514,7 +521,7 @@
OPENSSL_assert(0);
if (md_out_size)
*md_out_size = -1;
- return;
+ return 0;
}
OPENSSL_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
@@ -652,7 +659,7 @@
*/
if (header_length <= md_block_size) {
/* Should never happen */
- return;
+ return 0;
}
overhang = header_length - md_block_size;
md_transform(md_state.c, header);
@@ -733,26 +740,34 @@
}
EVP_MD_CTX_init(&md_ctx);
- EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */ );
+ if (EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */ ) <= 0)
+ goto err;
if (is_sslv3) {
/* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
OPENSSL_port_memset(hmac_pad, 0x5c, sslv3_pad_length);
- EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length);
- EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length);
- EVP_DigestUpdate(&md_ctx, mac_out, md_size);
+ if (EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length) <= 0
+ || EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length) <= 0
+ || EVP_DigestUpdate(&md_ctx, mac_out, md_size) <= 0)
+ goto err;
} else {
/* Complete the HMAC in the standard manner. */
for (i = 0; i < md_block_size; i++)
hmac_pad[i] ^= 0x6a;
- EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
- EVP_DigestUpdate(&md_ctx, mac_out, md_size);
+ if (EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size) <= 0
+ || EVP_DigestUpdate(&md_ctx, mac_out, md_size) <= 0)
+ goto err;
}
EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
if (md_out_size)
*md_out_size = md_out_size_u;
EVP_MD_CTX_cleanup(&md_ctx);
+
+ return 1;
+err:
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return 0;
}
#ifdef OPENSSL_FIPS
diff --git a/src/third_party/openssl/openssl/ssl/s3_clnt.c b/src/third_party/openssl/openssl/ssl/s3_clnt.c
index 4b5423c..0e772cb 100644
--- a/src/third_party/openssl/openssl/ssl/s3_clnt.c
+++ b/src/third_party/openssl/openssl/ssl/s3_clnt.c
@@ -1627,6 +1627,12 @@
}
p += i;
+ if (BN_is_zero(dh->p)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_VALUE);
+ goto f_err;
+ }
+
+
if (2 > n - param_len) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1647,6 +1653,11 @@
}
p += i;
+ if (BN_is_zero(dh->g)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_VALUE);
+ goto f_err;
+ }
+
if (2 > n - param_len) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1668,6 +1679,11 @@
p += i;
n -= param_len;
+ if (BN_is_zero(dh->pub_key)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_PUB_KEY_VALUE);
+ goto f_err;
+ }
+
# ifndef OPENSSL_NO_RSA
if (alg_a & SSL_aRSA)
pkey =
@@ -1870,14 +1886,20 @@
q = md_buf;
for (num = 2; num > 0; num--) {
EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
- EVP_DigestInit_ex(&md_ctx, (num == 2)
- ? s->ctx->md5 : s->ctx->sha1, NULL);
- EVP_DigestUpdate(&md_ctx, &(s->s3->client_random[0]),
- SSL3_RANDOM_SIZE);
- EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]),
- SSL3_RANDOM_SIZE);
- EVP_DigestUpdate(&md_ctx, param, param_len);
- EVP_DigestFinal_ex(&md_ctx, q, &size);
+ if (EVP_DigestInit_ex(&md_ctx,
+ (num == 2) ? s->ctx->md5 : s->ctx->sha1,
+ NULL) <= 0
+ || EVP_DigestUpdate(&md_ctx, &(s->s3->client_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(&md_ctx, param, param_len) <= 0
+ || EVP_DigestFinal_ex(&md_ctx, q, &size) <= 0) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
q += size;
j += size;
}
@@ -1896,12 +1918,16 @@
} else
#endif
{
- EVP_VerifyInit_ex(&md_ctx, md, NULL);
- EVP_VerifyUpdate(&md_ctx, &(s->s3->client_random[0]),
- SSL3_RANDOM_SIZE);
- EVP_VerifyUpdate(&md_ctx, &(s->s3->server_random[0]),
- SSL3_RANDOM_SIZE);
- EVP_VerifyUpdate(&md_ctx, param, param_len);
+ if (EVP_VerifyInit_ex(&md_ctx, md, NULL) <= 0
+ || EVP_VerifyUpdate(&md_ctx, &(s->s3->client_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_VerifyUpdate(&md_ctx, &(s->s3->server_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_VerifyUpdate(&md_ctx, param, param_len) <= 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ goto f_err;
+ }
if (EVP_VerifyFinal(&md_ctx, p, (int)n, pkey) <= 0) {
/* bad signature */
al = SSL_AD_DECRYPT_ERROR;
@@ -2121,6 +2147,7 @@
long n;
const unsigned char *p;
unsigned char *d;
+ unsigned long ticket_lifetime_hint;
n = s->method->ssl_get_message(s,
SSL3_ST_CR_SESSION_TICKET_A,
@@ -2139,6 +2166,19 @@
p = d = (unsigned char *)s->init_msg;
+ n2l(p, ticket_lifetime_hint);
+ n2s(p, ticklen);
+ /* ticket_lifetime_hint + ticket_length + ticket */
+ if (ticklen + 6 != n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ /* Server is allowed to change its mind and send an empty ticket. */
+ if (ticklen == 0)
+ return 1;
+
if (s->session->session_id_length > 0) {
int i = s->session_ctx->session_cache_mode;
SSL_SESSION *new_sess;
@@ -2170,14 +2210,6 @@
s->session = new_sess;
}
- n2l(p, s->session->tlsext_tick_lifetime_hint);
- n2s(p, ticklen);
- /* ticket_lifetime_hint + ticket_length + ticket */
- if (ticklen + 6 != n) {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
if (s->session->tlsext_tick) {
OPENSSL_free(s->session->tlsext_tick);
s->session->tlsext_ticklen = 0;
@@ -2188,6 +2220,7 @@
goto err;
}
OPENSSL_port_memcpy(s->session->tlsext_tick, p, ticklen);
+ s->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
s->session->tlsext_ticklen = ticklen;
/*
* There are two ways to detect a resumed ticket session. One is to set
@@ -2225,37 +2258,44 @@
n = s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_STATUS_A,
SSL3_ST_CR_CERT_STATUS_B,
- SSL3_MT_CERTIFICATE_STATUS, 16384, &ok);
+ -1, 16384, &ok);
if (!ok)
return ((int)n);
- if (n < 4) {
- /* need at least status type + length */
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
- goto f_err;
+
+ if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
+ /*
+ * The CertificateStatus message is optional even if
+ * tlsext_status_expected is set
+ */
+ s->s3->tmp.reuse_message = 1;
+ } else {
+ if (n < 4) {
+ /* need at least status type + length */
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ p = (unsigned char *)s->init_msg;
+ if (*p++ != TLSEXT_STATUSTYPE_ocsp) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE);
+ goto f_err;
+ }
+ n2l3(p, resplen);
+ if (resplen + 4 != n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
+ if (s->tlsext_ocsp_resp == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ s->tlsext_ocsp_resplen = resplen;
}
- p = (unsigned char *)s->init_msg;
- if (*p++ != TLSEXT_STATUSTYPE_ocsp) {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE);
- goto f_err;
- }
- n2l3(p, resplen);
- if (resplen + 4 != n) {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- if (s->tlsext_ocsp_resp)
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
- if (!s->tlsext_ocsp_resp) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- s->tlsext_ocsp_resplen = resplen;
if (s->ctx->tlsext_status_cb) {
int ret;
ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
@@ -2357,6 +2397,7 @@
|| (pkey->pkey.rsa == NULL)) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(pkey);
goto err;
}
rsa = pkey->pkey.rsa;
@@ -2804,6 +2845,11 @@
pkey_ctx = EVP_PKEY_CTX_new(pub_key =
X509_get_pubkey(peer_cert), NULL);
+ if (pkey_ctx == NULL) {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
/*
* If we have send a certificate, and certificate key
*
@@ -2813,10 +2859,13 @@
/* Otherwise, generate ephemeral key pair */
- EVP_PKEY_encrypt_init(pkey_ctx);
- /* Generate session key */
- if (RAND_bytes(premaster_secret, 32) <= 0) {
+ if (pkey_ctx == NULL
+ || EVP_PKEY_encrypt_init(pkey_ctx) <= 0
+ /* Generate session key */
+ || RAND_bytes(premaster_secret, 32) <= 0) {
EVP_PKEY_CTX_free(pkey_ctx);
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
goto err;
}
/*
@@ -2837,13 +2886,18 @@
* data
*/
ukm_hash = EVP_MD_CTX_create();
- EVP_DigestInit(ukm_hash,
- EVP_get_digestbynid(NID_id_GostR3411_94));
- EVP_DigestUpdate(ukm_hash, s->s3->client_random,
- SSL3_RANDOM_SIZE);
- EVP_DigestUpdate(ukm_hash, s->s3->server_random,
- SSL3_RANDOM_SIZE);
- EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len);
+ if (EVP_DigestInit(ukm_hash,
+ EVP_get_digestbynid(NID_id_GostR3411_94)) <= 0
+ || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
+ EVP_MD_CTX_destroy(ukm_hash);
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
EVP_MD_CTX_destroy(ukm_hash);
if (EVP_PKEY_CTX_ctrl
(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 8,
@@ -2859,7 +2913,7 @@
*(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
msglen = 255;
if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, premaster_secret, 32)
- < 0) {
+ <= 0) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
SSL_R_LIBRARY_BUG);
goto err;
@@ -3060,7 +3114,10 @@
pkey = s->cert->key->privatekey;
/* Create context from key and test if sha1 is allowed as digest */
pctx = EVP_PKEY_CTX_new(pkey, NULL);
- EVP_PKEY_sign_init(pctx);
+ if (pctx == NULL || EVP_PKEY_sign_init(pctx) <= 0) {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1()) > 0) {
if (TLS1_get_version(s) < TLS1_2_VERSION)
s->method->ssl3_enc->cert_verify_mac(s,
@@ -3197,7 +3254,6 @@
* If we get an error, we need to ssl->rwstate=SSL_X509_LOOKUP;
* return(-1); We then get retied later
*/
- i = 0;
i = ssl_do_client_cert_cb(s, &x509, &pkey);
if (i < 0) {
s->rwstate = SSL_X509_LOOKUP;
@@ -3364,7 +3420,7 @@
/* Check DHE only: static DH not implemented. */
if (alg_k & SSL_kEDH) {
int dh_size = BN_num_bits(dh->p);
- if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768)
+ if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 1024)
|| (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) {
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL);
goto f_err;
diff --git a/src/third_party/openssl/openssl/ssl/s3_enc.c b/src/third_party/openssl/openssl/ssl/s3_enc.c
index 1c800e1..597dbb9 100644
--- a/src/third_party/openssl/openssl/ssl/s3_enc.c
+++ b/src/third_party/openssl/openssl/ssl/s3_enc.c
@@ -256,7 +256,10 @@
EVP_CIPHER_CTX_init(s->enc_read_ctx);
dd = s->enc_read_ctx;
- ssl_replace_hash(&s->read_hash, m);
+ if (ssl_replace_hash(&s->read_hash, m) == NULL) {
+ SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
#ifndef OPENSSL_NO_COMP
/* COMPRESS */
if (s->expand != NULL) {
@@ -291,7 +294,10 @@
*/
EVP_CIPHER_CTX_init(s->enc_write_ctx);
dd = s->enc_write_ctx;
- ssl_replace_hash(&s->write_hash, m);
+ if (ssl_replace_hash(&s->write_hash, m) == NULL) {
+ SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
#ifndef OPENSSL_NO_COMP
/* COMPRESS */
if (s->compress != NULL) {
@@ -677,19 +683,21 @@
return 0;
npad = (48 / n) * n;
- if (sender != NULL)
- EVP_DigestUpdate(&ctx, sender, len);
- EVP_DigestUpdate(&ctx, s->session->master_key,
- s->session->master_key_length);
- EVP_DigestUpdate(&ctx, ssl3_pad_1, npad);
- EVP_DigestFinal_ex(&ctx, md_buf, &i);
+ if ((sender != NULL && EVP_DigestUpdate(&ctx, sender, len) <= 0)
+ || EVP_DigestUpdate(&ctx, s->session->master_key,
+ s->session->master_key_length) <= 0
+ || EVP_DigestUpdate(&ctx, ssl3_pad_1, npad) <= 0
+ || EVP_DigestFinal_ex(&ctx, md_buf, &i) <= 0
- EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL);
- EVP_DigestUpdate(&ctx, s->session->master_key,
- s->session->master_key_length);
- EVP_DigestUpdate(&ctx, ssl3_pad_2, npad);
- EVP_DigestUpdate(&ctx, md_buf, i);
- EVP_DigestFinal_ex(&ctx, p, &ret);
+ || EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL) <= 0
+ || EVP_DigestUpdate(&ctx, s->session->master_key,
+ s->session->master_key_length) <= 0
+ || EVP_DigestUpdate(&ctx, ssl3_pad_2, npad) <= 0
+ || EVP_DigestUpdate(&ctx, md_buf, i) <= 0
+ || EVP_DigestFinal_ex(&ctx, p, &ret) <= 0) {
+ SSLerr(SSL_F_SSL3_HANDSHAKE_MAC, ERR_R_INTERNAL_ERROR);
+ ret = 0;
+ }
EVP_MD_CTX_cleanup(&ctx);
@@ -761,33 +769,36 @@
header[j++] = rec->length & 0xff;
/* Final param == is SSLv3 */
- ssl3_cbc_digest_record(hash,
- md, &md_size,
- header, rec->input,
- rec->length + md_size, orig_len,
- mac_sec, md_size, 1);
+ if (ssl3_cbc_digest_record(hash,
+ md, &md_size,
+ header, rec->input,
+ rec->length + md_size, orig_len,
+ mac_sec, md_size, 1) <= 0)
+ return -1;
} else {
unsigned int md_size_u;
/* Chop the digest off the end :-) */
EVP_MD_CTX_init(&md_ctx);
- EVP_MD_CTX_copy_ex(&md_ctx, hash);
- EVP_DigestUpdate(&md_ctx, mac_sec, md_size);
- EVP_DigestUpdate(&md_ctx, ssl3_pad_1, npad);
- EVP_DigestUpdate(&md_ctx, seq, 8);
rec_char = rec->type;
- EVP_DigestUpdate(&md_ctx, &rec_char, 1);
p = md;
s2n(rec->length, p);
- EVP_DigestUpdate(&md_ctx, md, 2);
- EVP_DigestUpdate(&md_ctx, rec->input, rec->length);
- EVP_DigestFinal_ex(&md_ctx, md, NULL);
-
- EVP_MD_CTX_copy_ex(&md_ctx, hash);
- EVP_DigestUpdate(&md_ctx, mac_sec, md_size);
- EVP_DigestUpdate(&md_ctx, ssl3_pad_2, npad);
- EVP_DigestUpdate(&md_ctx, md, md_size);
- EVP_DigestFinal_ex(&md_ctx, md, &md_size_u);
+ if (EVP_MD_CTX_copy_ex(&md_ctx, hash) <= 0
+ || EVP_DigestUpdate(&md_ctx, mac_sec, md_size) <= 0
+ || EVP_DigestUpdate(&md_ctx, ssl3_pad_1, npad) <= 0
+ || EVP_DigestUpdate(&md_ctx, seq, 8) <= 0
+ || EVP_DigestUpdate(&md_ctx, &rec_char, 1) <= 0
+ || EVP_DigestUpdate(&md_ctx, md, 2) <= 0
+ || EVP_DigestUpdate(&md_ctx, rec->input, rec->length) <= 0
+ || EVP_DigestFinal_ex(&md_ctx, md, NULL) <= 0
+ || EVP_MD_CTX_copy_ex(&md_ctx, hash) <= 0
+ || EVP_DigestUpdate(&md_ctx, mac_sec, md_size) <= 0
+ || EVP_DigestUpdate(&md_ctx, ssl3_pad_2, npad) <= 0
+ || EVP_DigestUpdate(&md_ctx, md, md_size) <= 0
+ || EVP_DigestFinal_ex(&md_ctx, md, &md_size_u) <= 0) {
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return -1;
+ }
md_size = md_size_u;
EVP_MD_CTX_cleanup(&md_ctx);
@@ -829,17 +840,24 @@
EVP_MD_CTX_init(&ctx);
for (i = 0; i < 3; i++) {
- EVP_DigestInit_ex(&ctx, s->ctx->sha1, NULL);
- EVP_DigestUpdate(&ctx, salt[i], OPENSSL_port_strlen((const char *)salt[i]));
- EVP_DigestUpdate(&ctx, p, len);
- EVP_DigestUpdate(&ctx, &(s->s3->client_random[0]), SSL3_RANDOM_SIZE);
- EVP_DigestUpdate(&ctx, &(s->s3->server_random[0]), SSL3_RANDOM_SIZE);
- EVP_DigestFinal_ex(&ctx, buf, &n);
+ if (EVP_DigestInit_ex(&ctx, s->ctx->sha1, NULL) <= 0
+ || EVP_DigestUpdate(&ctx, salt[i],
+ OPENSSL_port_strlen((const char *)salt[i])) <= 0
+ || EVP_DigestUpdate(&ctx, p, len) <= 0
+ || EVP_DigestUpdate(&ctx, &(s->s3->client_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(&ctx, &(s->s3->server_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestFinal_ex(&ctx, buf, &n) <= 0
- EVP_DigestInit_ex(&ctx, s->ctx->md5, NULL);
- EVP_DigestUpdate(&ctx, p, len);
- EVP_DigestUpdate(&ctx, buf, n);
- EVP_DigestFinal_ex(&ctx, out, &n);
+ || EVP_DigestInit_ex(&ctx, s->ctx->md5, NULL) <= 0
+ || EVP_DigestUpdate(&ctx, p, len) <= 0
+ || EVP_DigestUpdate(&ctx, buf, n) <= 0
+ || EVP_DigestFinal_ex(&ctx, out, &n) <= 0) {
+ SSLerr(SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
+ ret = 0;
+ break;
+ }
out += n;
ret += n;
}
diff --git a/src/third_party/openssl/openssl/ssl/s3_lib.c b/src/third_party/openssl/openssl/ssl/s3_lib.c
index 73674fd..647d8da 100644
--- a/src/third_party/openssl/openssl/ssl/s3_lib.c
+++ b/src/third_party/openssl/openssl/ssl/s3_lib.c
@@ -2958,7 +2958,7 @@
void ssl3_free(SSL *s)
{
- if (s == NULL)
+ if (s == NULL || s->s3 == NULL)
return;
#ifdef TLSEXT_TYPE_opaque_prf_input
@@ -3167,13 +3167,6 @@
SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
return (ret);
}
- if (!(s->options & SSL_OP_SINGLE_DH_USE)) {
- if (!DH_generate_key(dh)) {
- DH_free(dh);
- SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
- return (ret);
- }
- }
if (s->cert->dh_tmp != NULL)
DH_free(s->cert->dh_tmp);
s->cert->dh_tmp = dh;
@@ -3224,6 +3217,8 @@
#ifndef OPENSSL_NO_TLSEXT
case SSL_CTRL_SET_TLSEXT_HOSTNAME:
if (larg == TLSEXT_NAMETYPE_host_name) {
+ size_t len;
+
if (s->tlsext_hostname != NULL)
OPENSSL_free(s->tlsext_hostname);
s->tlsext_hostname = NULL;
@@ -3231,7 +3226,8 @@
ret = 1;
if (parg == NULL)
break;
- if (OPENSSL_port_strlen((char *)parg) > TLSEXT_MAXLEN_host_name) {
+ len = OPENSSL_port_strlen((char *)parg);
+ if (len == 0 || len > TLSEXT_MAXLEN_host_name) {
SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
return 0;
}
@@ -3482,13 +3478,6 @@
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_DH_LIB);
return 0;
}
- if (!(ctx->options & SSL_OP_SINGLE_DH_USE)) {
- if (!DH_generate_key(new)) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_DH_LIB);
- DH_free(new);
- return 0;
- }
- }
if (cert->dh_tmp != NULL)
DH_free(cert->dh_tmp);
cert->dh_tmp = new;
diff --git a/src/third_party/openssl/openssl/ssl/s3_srvr.c b/src/third_party/openssl/openssl/ssl/s3_srvr.c
index d4506a9..8c76895 100644
--- a/src/third_party/openssl/openssl/ssl/s3_srvr.c
+++ b/src/third_party/openssl/openssl/ssl/s3_srvr.c
@@ -1,4 +1,4 @@
-/* ssl/s3_srvr.c -*- mode:C; c-file-style: "eay" -*- */
+/* ssl/s3_srvr.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -386,7 +386,6 @@
*/
if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)
SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_CLIENTHELLO_TLSEXT);
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
ret = -1;
s->state = SSL_ST_ERR;
goto end;
@@ -970,7 +969,7 @@
int ssl3_get_client_hello(SSL *s)
{
- int i, j, ok, al, ret = -1;
+ int i, j, ok, al, ret = -1, cookie_valid = 0;
unsigned int cookie_len;
long n;
unsigned long id;
@@ -1068,6 +1067,12 @@
goto f_err;
}
+ if ((j < 0) || (j > SSL_MAX_SSL_SESSION_ID_LENGTH)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
s->hit = 0;
/*
* Versions before 0.9.7 always allow clients to resume sessions in
@@ -1158,8 +1163,7 @@
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
goto f_err;
}
-
- ret = 2;
+ cookie_valid = 1;
}
p += cookie_len;
@@ -1267,7 +1271,7 @@
#ifndef OPENSSL_NO_TLSEXT
/* TLS extensions */
if (s->version >= SSL3_VERSION) {
- if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) {
+ if (!ssl_parse_clienthello_tlsext(s, &p, d + n, &al)) {
/* 'al' set by ssl_parse_clienthello_tlsext */
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
goto f_err;
@@ -1495,8 +1499,7 @@
}
}
- if (ret < 0)
- ret = 1;
+ ret = cookie_valid ? 2 : 1;
if (0) {
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
@@ -1506,7 +1509,7 @@
if (ciphers != NULL)
sk_SSL_CIPHER_free(ciphers);
- return (ret);
+ return ret;
}
int ssl3_send_server_hello(SSL *s)
@@ -1729,20 +1732,9 @@
}
s->s3->tmp.dh = dh;
- if ((dhp->pub_key == NULL ||
- dhp->priv_key == NULL ||
- (s->options & SSL_OP_SINGLE_DH_USE))) {
- if (!DH_generate_key(dh)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
- goto err;
- }
- } else {
- dh->pub_key = BN_dup(dhp->pub_key);
- dh->priv_key = BN_dup(dhp->priv_key);
- if ((dh->pub_key == NULL) || (dh->priv_key == NULL)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
- goto err;
- }
+ if (!DH_generate_key(dh)) {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
+ goto err;
}
r[0] = dh->p;
r[1] = dh->g;
@@ -1990,14 +1982,22 @@
for (num = 2; num > 0; num--) {
EVP_MD_CTX_set_flags(&md_ctx,
EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
- EVP_DigestInit_ex(&md_ctx, (num == 2)
- ? s->ctx->md5 : s->ctx->sha1, NULL);
- EVP_DigestUpdate(&md_ctx, &(s->s3->client_random[0]),
- SSL3_RANDOM_SIZE);
- EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]),
- SSL3_RANDOM_SIZE);
- EVP_DigestUpdate(&md_ctx, &(d[4]), n);
- EVP_DigestFinal_ex(&md_ctx, q, (unsigned int *)&i);
+ if (EVP_DigestInit_ex(&md_ctx,
+ (num == 2) ? s->ctx->md5
+ : s->ctx->sha1,
+ NULL) <= 0
+ || EVP_DigestUpdate(&md_ctx, &(s->s3->client_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(&md_ctx, &(d[4]), n) <= 0
+ || EVP_DigestFinal_ex(&md_ctx, q,
+ (unsigned int *)&i) <= 0) {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
+ ERR_LIB_EVP);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
q += i;
j += i;
}
@@ -2027,16 +2027,17 @@
#ifdef SSL_DEBUG
OPENSSL_port_printferr("Using hash %s\n", EVP_MD_name(md));
#endif
- EVP_SignInit_ex(&md_ctx, md, NULL);
- EVP_SignUpdate(&md_ctx, &(s->s3->client_random[0]),
- SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx, &(s->s3->server_random[0]),
- SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx, &(d[4]), n);
- if (!EVP_SignFinal(&md_ctx, &(p[2]),
- (unsigned int *)&i, pkey)) {
+ if (EVP_SignInit_ex(&md_ctx, md, NULL) <= 0
+ || EVP_SignUpdate(&md_ctx, &(s->s3->client_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_SignUpdate(&md_ctx, &(s->s3->server_random[0]),
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_SignUpdate(&md_ctx, &(d[4]), n) <= 0
+ || EVP_SignFinal(&md_ctx, &(p[2]),
+ (unsigned int *)&i, pkey) <= 0) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_LIB_EVP);
- goto err;
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
}
s2n(i, p);
n += i + 2;
@@ -2882,7 +2883,15 @@
pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
- EVP_PKEY_decrypt_init(pkey_ctx);
+ if (pkey_ctx == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto gerr;
+ }
/*
* If client certificate is present and is of the same type, maybe
* use it for key exchange. Don't mind errors from
@@ -3126,7 +3135,17 @@
unsigned char signature[64];
int idx;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
- EVP_PKEY_verify_init(pctx);
+ if (pctx == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ if (EVP_PKEY_verify_init(pctx) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
if (i != 64) {
OPENSSL_port_printferr("GOST signature length is %d", i);
}
diff --git a/src/third_party/openssl/openssl/ssl/ssl.h b/src/third_party/openssl/openssl/ssl/ssl.h
index d2ab0c0..105047e 100644
--- a/src/third_party/openssl/openssl/ssl/ssl.h
+++ b/src/third_party/openssl/openssl/ssl/ssl.h
@@ -602,7 +602,7 @@
# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
/* If set, always create a new key when using tmp_ecdh parameters */
# define SSL_OP_SINGLE_ECDH_USE 0x00080000L
-/* If set, always create a new key when using tmp_dh parameters */
+/* Does nothing: retained for compatibility */
# define SSL_OP_SINGLE_DH_USE 0x00100000L
/* Does nothing: retained for compatibiity */
# define SSL_OP_EPHEMERAL_RSA 0x0
@@ -2313,6 +2313,7 @@
# define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 292
# define SSL_F_SSL3_ENC 134
# define SSL_F_SSL3_GENERATE_KEY_BLOCK 238
+# define SSL_F_SSL3_GENERATE_MASTER_SECRET 388
# define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135
# define SSL_F_SSL3_GET_CERT_STATUS 289
# define SSL_F_SSL3_GET_CERT_VERIFY 136
@@ -2465,8 +2466,11 @@
# define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106
# define SSL_R_BAD_DECOMPRESSION 107
# define SSL_R_BAD_DH_G_LENGTH 108
+# define SSL_R_BAD_DH_G_VALUE 375
# define SSL_R_BAD_DH_PUB_KEY_LENGTH 109
+# define SSL_R_BAD_DH_PUB_KEY_VALUE 393
# define SSL_R_BAD_DH_P_LENGTH 110
+# define SSL_R_BAD_DH_P_VALUE 395
# define SSL_R_BAD_DIGEST_LENGTH 111
# define SSL_R_BAD_DSA_SIGNATURE 112
# define SSL_R_BAD_ECC_CERT 304
diff --git a/src/third_party/openssl/openssl/ssl/ssl3.h b/src/third_party/openssl/openssl/ssl/ssl3.h
index df6f734..a5ed610 100644
--- a/src/third_party/openssl/openssl/ssl/ssl3.h
+++ b/src/third_party/openssl/openssl/ssl/ssl3.h
@@ -263,6 +263,8 @@
# define SSL3_SESSION_ID_SIZE 32
# define SSL3_RT_HEADER_LENGTH 5
+# define SSL3_HM_HEADER_LENGTH 4
+
# ifndef SSL3_ALIGN_PAYLOAD
/*
* Some will argue that this increases memory footprint, but it's not
diff --git a/src/third_party/openssl/openssl/ssl/ssl_asn1.c b/src/third_party/openssl/openssl/ssl/ssl_asn1.c
index 44652be..19de1a9 100644
--- a/src/third_party/openssl/openssl/ssl/ssl_asn1.c
+++ b/src/third_party/openssl/openssl/ssl/ssl_asn1.c
@@ -124,13 +124,16 @@
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
{
#define LSIZE2 (sizeof(long)*2)
- int v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0, v7 = 0, v8 = 0;
+ int v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0;
unsigned char buf[4], ibuf1[LSIZE2], ibuf2[LSIZE2];
unsigned char ibuf3[LSIZE2], ibuf4[LSIZE2], ibuf5[LSIZE2];
#ifndef OPENSSL_NO_TLSEXT
int v6 = 0, v9 = 0, v10 = 0;
unsigned char ibuf6[LSIZE2];
#endif
+#ifndef OPENSSL_NO_PSK
+ int v7 = 0, v8 = 0;
+#endif
#ifndef OPENSSL_NO_COMP
unsigned char cbuf;
int v11 = 0;
diff --git a/src/third_party/openssl/openssl/ssl/ssl_cert.c b/src/third_party/openssl/openssl/ssl/ssl_cert.c
index 7e9edd3..9ee8738 100644
--- a/src/third_party/openssl/openssl/ssl/ssl_cert.c
+++ b/src/third_party/openssl/openssl/ssl/ssl_cert.c
@@ -209,6 +209,7 @@
OPENSSL_port_memset(ret, 0, sizeof(CERT));
+ ret->references = 1;
ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
/*
* or ret->key = ret->pkeys + (cert->key - cert->pkeys), if you find that
@@ -285,7 +286,6 @@
* chain is held inside SSL_CTX
*/
- ret->references = 1;
/*
* Set digests to defaults. NB: we don't copy existing values as they
* will be set during handshake.
diff --git a/src/third_party/openssl/openssl/ssl/ssl_ciph.c b/src/third_party/openssl/openssl/ssl/ssl_ciph.c
index 23c5c53..fef51c8 100644
--- a/src/third_party/openssl/openssl/ssl/ssl_ciph.c
+++ b/src/third_party/openssl/openssl/ssl/ssl_ciph.c
@@ -359,10 +359,11 @@
const EVP_PKEY_ASN1_METHOD *ameth;
int pkey_id = 0;
ameth = EVP_PKEY_asn1_find_str(NULL, pkey_name, -1);
- if (ameth) {
- EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
+ if (ameth && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
+ ameth) > 0) {
+ return pkey_id;
}
- return pkey_id;
+ return 0;
}
#else
@@ -374,7 +375,9 @@
int pkey_id = 0;
ameth = EVP_PKEY_asn1_find_str(&tmpeng, pkey_name, -1);
if (ameth) {
- EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
+ if (EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
+ ameth) <= 0)
+ pkey_id = 0;
}
if (tmpeng)
ENGINE_finish(tmpeng);
diff --git a/src/third_party/openssl/openssl/ssl/ssl_err.c b/src/third_party/openssl/openssl/ssl/ssl_err.c
index def5aea..d4b1f39 100644
--- a/src/third_party/openssl/openssl/ssl/ssl_err.c
+++ b/src/third_party/openssl/openssl/ssl/ssl_err.c
@@ -165,6 +165,8 @@
{ERR_FUNC(SSL_F_SSL3_ENC), "SSL3_ENC"},
{ERR_FUNC(SSL_F_SSL3_CHECK_FINISHED), "SSL3_CHECK_FINISHED"},
{ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK), "SSL3_GENERATE_KEY_BLOCK"},
+ {ERR_FUNC(SSL_F_SSL3_GENERATE_MASTER_SECRET),
+ "ssl3_generate_master_secret"},
{ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST),
"SSL3_GET_CERTIFICATE_REQUEST"},
{ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS), "SSL3_GET_CERT_STATUS"},
@@ -372,8 +374,11 @@
"bad data returned by callback"},
{ERR_REASON(SSL_R_BAD_DECOMPRESSION), "bad decompression"},
{ERR_REASON(SSL_R_BAD_DH_G_LENGTH), "bad dh g length"},
+ {ERR_REASON(SSL_R_BAD_DH_G_VALUE), "bad dh g value"},
{ERR_REASON(SSL_R_BAD_DH_PUB_KEY_LENGTH), "bad dh pub key length"},
+ {ERR_REASON(SSL_R_BAD_DH_PUB_KEY_VALUE), "bad dh pub key value"},
{ERR_REASON(SSL_R_BAD_DH_P_LENGTH), "bad dh p length"},
+ {ERR_REASON(SSL_R_BAD_DH_P_VALUE), "bad dh p value"},
{ERR_REASON(SSL_R_BAD_DIGEST_LENGTH), "bad digest length"},
{ERR_REASON(SSL_R_BAD_DSA_SIGNATURE), "bad dsa signature"},
{ERR_REASON(SSL_R_BAD_ECC_CERT), "bad ecc cert"},
diff --git a/src/third_party/openssl/openssl/ssl/ssl_lib.c b/src/third_party/openssl/openssl/ssl/ssl_lib.c
index 797643f..db7529f 100644
--- a/src/third_party/openssl/openssl/ssl/ssl_lib.c
+++ b/src/third_party/openssl/openssl/ssl/ssl_lib.c
@@ -310,6 +310,7 @@
s->options = ctx->options;
s->mode = ctx->mode;
s->max_cert_list = ctx->max_cert_list;
+ s->references = 1;
if (ctx->cert != NULL) {
/*
@@ -378,7 +379,6 @@
if (!s->method->ssl_new(s))
goto err;
- s->references = 1;
s->server = (ctx->method->ssl_accept == ssl_undefined_function) ? 0 : 1;
SSL_clear(s);
@@ -3286,8 +3286,11 @@
{
ssl_clear_hash_ctx(hash);
*hash = EVP_MD_CTX_create();
- if (md)
- EVP_DigestInit_ex(*hash, md, NULL);
+ if (*hash == NULL || (md && EVP_DigestInit_ex(*hash, md, NULL) <= 0)) {
+ EVP_MD_CTX_destroy(*hash);
+ *hash = NULL;
+ return NULL;
+ }
return *hash;
}
diff --git a/src/third_party/openssl/openssl/ssl/ssl_locl.h b/src/third_party/openssl/openssl/ssl/ssl_locl.h
index 55c4fdd..548f591 100644
--- a/src/third_party/openssl/openssl/ssl/ssl_locl.h
+++ b/src/third_party/openssl/openssl/ssl/ssl_locl.h
@@ -1157,7 +1157,7 @@
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
unsigned char *limit);
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data,
- unsigned char *d, int n, int *al);
+ unsigned char *limit, int *al);
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data,
unsigned char *d, int n, int *al);
int ssl_prepare_clienthello_tlsext(SSL *s);
@@ -1221,15 +1221,15 @@
SSL3_RECORD *rec,
unsigned block_size, unsigned mac_size);
char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
-void ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
- unsigned char *md_out,
- size_t *md_out_size,
- const unsigned char header[13],
- const unsigned char *data,
- size_t data_plus_mac_size,
- size_t data_plus_mac_plus_padding_size,
- const unsigned char *mac_secret,
- unsigned mac_secret_length, char is_sslv3);
+int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
+ unsigned char *md_out,
+ size_t *md_out_size,
+ const unsigned char header[13],
+ const unsigned char *data,
+ size_t data_plus_mac_size,
+ size_t data_plus_mac_plus_padding_size,
+ const unsigned char *mac_secret,
+ unsigned mac_secret_length, char is_sslv3);
void tls_fips_digest_extra(const EVP_CIPHER_CTX *cipher_ctx,
EVP_MD_CTX *mac_ctx, const unsigned char *data,
diff --git a/src/third_party/openssl/openssl/ssl/ssl_rsa.c b/src/third_party/openssl/openssl/ssl/ssl_rsa.c
index 0315adc..a33c2cc 100644
--- a/src/third_party/openssl/openssl/ssl/ssl_rsa.c
+++ b/src/third_party/openssl/openssl/ssl/ssl_rsa.c
@@ -163,7 +163,10 @@
}
RSA_up_ref(rsa);
- EVP_PKEY_assign_RSA(pkey, rsa);
+ if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
+ RSA_free(rsa);
+ return 0;
+ }
ret = ssl_set_pkey(ssl->cert, pkey);
EVP_PKEY_free(pkey);
@@ -184,6 +187,15 @@
if (c->pkeys[i].x509 != NULL) {
EVP_PKEY *pktmp;
pktmp = X509_get_pubkey(c->pkeys[i].x509);
+ if (pktmp == NULL) {
+ SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE);
+ EVP_PKEY_free(pktmp);
+ return 0;
+ }
+ /*
+ * The return code from EVP_PKEY_copy_parameters is deliberately
+ * ignored. Some EVP_PKEY types cannot do this.
+ */
EVP_PKEY_copy_parameters(pktmp, pkey);
EVP_PKEY_free(pktmp);
ERR_clear_error();
@@ -385,6 +397,10 @@
}
if (c->pkeys[i].privatekey != NULL) {
+ /*
+ * The return code from EVP_PKEY_copy_parameters is deliberately
+ * ignored. Some EVP_PKEY types cannot do this.
+ */
EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey);
ERR_clear_error();
@@ -505,7 +521,10 @@
}
RSA_up_ref(rsa);
- EVP_PKEY_assign_RSA(pkey, rsa);
+ if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
+ RSA_free(rsa);
+ return 0;
+ }
ret = ssl_set_pkey(ctx->cert, pkey);
EVP_PKEY_free(pkey);
diff --git a/src/third_party/openssl/openssl/ssl/ssl_sess.c b/src/third_party/openssl/openssl/ssl/ssl_sess.c
index be171b7..d8fb388 100644
--- a/src/third_party/openssl/openssl/ssl/ssl_sess.c
+++ b/src/third_party/openssl/openssl/ssl/ssl_sess.c
@@ -259,8 +259,8 @@
dest->tlsext_ecpointformatlist = NULL;
dest->tlsext_ellipticcurvelist = NULL;
# endif
-#endif
dest->tlsext_tick = NULL;
+#endif
#ifndef OPENSSL_NO_SRP
dest->srp_username = NULL;
#endif
@@ -327,7 +327,6 @@
goto err;
}
# endif
-#endif
if (ticket != 0) {
dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
@@ -337,6 +336,7 @@
dest->tlsext_tick_lifetime_hint = 0;
dest->tlsext_ticklen = 0;
}
+#endif
#ifndef OPENSSL_NO_SRP
if (src->srp_username) {
@@ -605,9 +605,6 @@
int r;
#endif
- if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH)
- goto err;
-
if (session_id + len > limit) {
fatal = 1;
goto err;
diff --git a/src/third_party/openssl/openssl/ssl/ssltest.c b/src/third_party/openssl/openssl/ssl/ssltest.c
index 6a0c293..349ee1e 100644
--- a/src/third_party/openssl/openssl/ssl/ssltest.c
+++ b/src/third_party/openssl/openssl/ssl/ssltest.c
@@ -142,6 +142,7 @@
/* Or gethostname won't be declared properly on Linux and GNU platforms. */
#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
#include <assert.h>
#include <errno.h>
diff --git a/src/third_party/openssl/openssl/ssl/t1_enc.c b/src/third_party/openssl/openssl/ssl/t1_enc.c
index 59d104d..fa1726b 100644
--- a/src/third_party/openssl/openssl/ssl/t1_enc.c
+++ b/src/third_party/openssl/openssl/ssl/t1_enc.c
@@ -388,6 +388,8 @@
EVP_CIPHER_CTX_init(s->enc_read_ctx);
dd = s->enc_read_ctx;
mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
+ if (mac_ctx == NULL)
+ goto err;
#ifndef OPENSSL_NO_COMP
if (s->expand != NULL) {
COMP_CTX_free(s->expand);
@@ -426,11 +428,14 @@
dd = s->enc_write_ctx;
if (SSL_IS_DTLS(s)) {
mac_ctx = EVP_MD_CTX_create();
- if (!mac_ctx)
+ if (mac_ctx == NULL)
goto err;
s->write_hash = mac_ctx;
- } else
+ } else {
mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
+ if (mac_ctx == NULL)
+ goto err;
+ }
#ifndef OPENSSL_NO_COMP
if (s->compress != NULL) {
COMP_CTX_free(s->compress);
@@ -503,7 +508,12 @@
if (!(EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER)) {
mac_key = EVP_PKEY_new_mac_key(mac_type, NULL,
mac_secret, *mac_secret_size);
- EVP_DigestSignInit(mac_ctx, NULL, m, NULL, mac_key);
+ if (mac_key == NULL
+ || EVP_DigestSignInit(mac_ctx, NULL, m, NULL, mac_key) <= 0) {
+ EVP_PKEY_free(mac_key);
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
EVP_PKEY_free(mac_key);
}
#ifdef TLS_DEBUG
@@ -916,8 +926,9 @@
}
EVP_MD_CTX_init(&ctx);
- EVP_MD_CTX_copy_ex(&ctx, d);
- EVP_DigestFinal_ex(&ctx, out, &ret);
+ if (EVP_MD_CTX_copy_ex(&ctx, d) <=0
+ || EVP_DigestFinal_ex(&ctx, out, &ret) <= 0)
+ ret = 0;
EVP_MD_CTX_cleanup(&ctx);
return ((int)ret);
}
@@ -1044,17 +1055,24 @@
* are hashing because that gives an attacker a timing-oracle.
*/
/* Final param == not SSLv3 */
- ssl3_cbc_digest_record(mac_ctx,
- md, &md_size,
- header, rec->input,
- rec->length + md_size, orig_len,
- ssl->s3->read_mac_secret,
- ssl->s3->read_mac_secret_size, 0);
+ if (ssl3_cbc_digest_record(mac_ctx,
+ md, &md_size,
+ header, rec->input,
+ rec->length + md_size, orig_len,
+ ssl->s3->read_mac_secret,
+ ssl->s3->read_mac_secret_size, 0) <= 0) {
+ if (!stream_mac)
+ EVP_MD_CTX_cleanup(&hmac);
+ return -1;
+ }
} else {
- EVP_DigestSignUpdate(mac_ctx, header, sizeof(header));
- EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length);
- t = EVP_DigestSignFinal(mac_ctx, md, &md_size);
- OPENSSL_assert(t > 0);
+ if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
+ || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
+ || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
+ if (!stream_mac)
+ EVP_MD_CTX_cleanup(&hmac);
+ return -1;
+ }
#ifdef OPENSSL_FIPS
if (!send && FIPS_mode())
tls_fips_digest_extra(ssl->enc_read_ctx,
@@ -1122,7 +1140,7 @@
so = s->s3->server_opaque_prf_input;
/*
* must be same as col (see
- * draft-resc-00.txts-opaque-prf-input-00.txt, section 3.1)
+ * draft-rescorla-tls-opaque-prf-input-00.txt, section 3.1)
*/
sol = s->s3->client_opaque_prf_input_len;
}
diff --git a/src/third_party/openssl/openssl/ssl/t1_lib.c b/src/third_party/openssl/openssl/ssl/t1_lib.c
index 15f7aa8..9bd4e57 100644
--- a/src/third_party/openssl/openssl/ssl/t1_lib.c
+++ b/src/third_party/openssl/openssl/ssl/t1_lib.c
@@ -164,7 +164,7 @@
{
#ifndef OPENSSL_NO_TLSEXT
if (s->tlsext_session_ticket) {
- OPENSSL_free(s->tlsext_session_ticket);
+ OPENSSL_port_free(s->tlsext_session_ticket);
}
#endif /* OPENSSL_NO_TLSEXT */
ssl3_free(s);
@@ -916,7 +916,7 @@
* 10.8..10.8.3 (which don't work).
*/
static void ssl_check_for_safari(SSL *s, const unsigned char *data,
- const unsigned char *d, int n)
+ const unsigned char *limit)
{
unsigned short type, size;
static const unsigned char kSafariExtensionsBlock[] = {
@@ -945,11 +945,11 @@
0x02, 0x03, /* SHA-1/ECDSA */
};
- if (data >= (d + n - 2))
+ if (data >= (limit - 2))
return;
data += 2;
- if (data > (d + n - 4))
+ if (data > (limit - 4))
return;
n2s(data, type);
n2s(data, size);
@@ -957,7 +957,7 @@
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > d + n)
+ if (data + size > limit)
return;
data += size;
@@ -965,7 +965,7 @@
const size_t len1 = sizeof(kSafariExtensionsBlock);
const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
- if (data + len1 + len2 != d + n)
+ if (data + len1 + len2 != limit)
return;
if (OPENSSL_port_memcmp(data, kSafariExtensionsBlock, len1) != 0)
return;
@@ -974,7 +974,7 @@
} else {
const size_t len = sizeof(kSafariExtensionsBlock);
- if (data + len != d + n)
+ if (data + len != limit)
return;
if (OPENSSL_port_memcmp(data, kSafariExtensionsBlock, len) != 0)
return;
@@ -984,8 +984,8 @@
}
# endif /* !OPENSSL_NO_EC */
-int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
- int n, int *al)
+int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
+ unsigned char *limit, int *al)
{
unsigned short type;
unsigned short size;
@@ -1007,34 +1007,34 @@
# ifndef OPENSSL_NO_EC
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
- ssl_check_for_safari(s, data, d, n);
+ ssl_check_for_safari(s, data, limit);
# endif /* !OPENSSL_NO_EC */
# ifndef OPENSSL_NO_SRP
if (s->srp_ctx.login != NULL) {
- OPENSSL_free(s->srp_ctx.login);
+ OPENSSL_port_free(s->srp_ctx.login);
s->srp_ctx.login = NULL;
}
# endif
s->srtp_profile = NULL;
- if (data == d + n)
+ if (data == limit)
goto ri_check;
- if (data > (d + n - 2))
+ if (data > (limit - 2))
goto err;
n2s(data, len);
- if (data > (d + n - len))
+ if (data + len != limit)
goto err;
- while (data <= (d + n - 4)) {
+ while (data <= (limit - 4)) {
n2s(data, type);
n2s(data, size);
- if (data + size > (d + n))
+ if (data + size > (limit))
goto err;
# if 0
OPENSSL_port_printferr("Received extension type %d size %d\n", type, size);
@@ -1106,7 +1106,7 @@
OPENSSL_port_memcpy(s->session->tlsext_hostname, sdata, len);
s->session->tlsext_hostname[len] = '\0';
if (OPENSSL_port_strlen(s->session->tlsext_hostname) != len) {
- OPENSSL_free(s->session->tlsext_hostname);
+ OPENSSL_port_free(s->session->tlsext_hostname);
s->session->tlsext_hostname = NULL;
*al = TLS1_AD_UNRECOGNIZED_NAME;
return 0;
@@ -1156,12 +1156,12 @@
goto err;
if (!s->hit) {
if (s->session->tlsext_ecpointformatlist) {
- OPENSSL_free(s->session->tlsext_ecpointformatlist);
+ OPENSSL_port_free(s->session->tlsext_ecpointformatlist);
s->session->tlsext_ecpointformatlist = NULL;
}
s->session->tlsext_ecpointformatlist_length = 0;
if ((s->session->tlsext_ecpointformatlist =
- OPENSSL_malloc(ecpointformatlist_length)) == NULL) {
+ OPENSSL_port_malloc(ecpointformatlist_length)) == NULL) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
@@ -1233,7 +1233,7 @@
if (s->s3->client_opaque_prf_input != NULL) {
/* shouldn't really happen */
- OPENSSL_free(s->s3->client_opaque_prf_input);
+ OPENSSL_port_free(s->s3->client_opaque_prf_input);
}
/* dummy byte just to get non-NULL */
@@ -1399,7 +1399,7 @@
}
/* Spurious data on the end */
- if (data != d + n)
+ if (data != limit)
goto err;
*p = data;
@@ -1502,9 +1502,9 @@
if (!s->hit) {
s->session->tlsext_ecpointformatlist_length = 0;
if (s->session->tlsext_ecpointformatlist != NULL)
- OPENSSL_free(s->session->tlsext_ecpointformatlist);
+ OPENSSL_port_free(s->session->tlsext_ecpointformatlist);
if ((s->session->tlsext_ecpointformatlist =
- OPENSSL_malloc(ecpointformatlist_length)) == NULL) {
+ OPENSSL_port_malloc(ecpointformatlist_length)) == NULL) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
@@ -1556,7 +1556,7 @@
if (s->s3->server_opaque_prf_input != NULL) {
/* shouldn't really happen */
- OPENSSL_free(s->s3->server_opaque_prf_input);
+ OPENSSL_port_free(s->s3->server_opaque_prf_input);
}
if (s->s3->server_opaque_prf_input_len == 0) {
/* dummy byte just to get non-NULL */
@@ -1720,7 +1720,7 @@
using_ecc = using_ecc && (s->version >= TLS1_VERSION);
if (using_ecc) {
if (s->tlsext_ecpointformatlist != NULL)
- OPENSSL_free(s->tlsext_ecpointformatlist);
+ OPENSSL_port_free(s->tlsext_ecpointformatlist);
if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL) {
SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,
ERR_R_MALLOC_FAILURE);
@@ -1735,11 +1735,11 @@
/* we support all named elliptic curves in RFC 4492 */
if (s->tlsext_ellipticcurvelist != NULL)
- OPENSSL_free(s->tlsext_ellipticcurvelist);
+ OPENSSL_port_free(s->tlsext_ellipticcurvelist);
s->tlsext_ellipticcurvelist_length =
sizeof(pref_list) / sizeof(pref_list[0]) * 2;
if ((s->tlsext_ellipticcurvelist =
- OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL) {
+ OPENSSL_port_malloc(s->tlsext_ellipticcurvelist_length)) == NULL) {
s->tlsext_ellipticcurvelist_length = 0;
SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,
ERR_R_MALLOC_FAILURE);
@@ -1768,7 +1768,7 @@
if (s->tlsext_opaque_prf_input != NULL) {
if (s->s3->client_opaque_prf_input != NULL) {
/* shouldn't really happen */
- OPENSSL_free(s->s3->client_opaque_prf_input);
+ OPENSSL_port_free(s->s3->client_opaque_prf_input);
}
if (s->tlsext_opaque_prf_input_len == 0) {
@@ -1818,7 +1818,7 @@
if (using_ecc) {
if (s->tlsext_ecpointformatlist != NULL)
- OPENSSL_free(s->tlsext_ecpointformatlist);
+ OPENSSL_port_free(s->tlsext_ecpointformatlist);
if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL) {
SSLerr(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT,
ERR_R_MALLOC_FAILURE);
@@ -1886,7 +1886,7 @@
if (s->s3->server_opaque_prf_input != NULL) {
/* shouldn't really happen */
- OPENSSL_free(s->s3->server_opaque_prf_input);
+ OPENSSL_port_free(s->s3->server_opaque_prf_input);
}
s->s3->server_opaque_prf_input = NULL;
@@ -2084,22 +2084,20 @@
}
# endif
+ OPENSSL_port_free(s->tlsext_ocsp_resp);
+ s->tlsext_ocsp_resp = NULL;
+ s->tlsext_ocsp_resplen = -1;
/*
* If we've requested certificate status and we wont get one tell the
* callback
*/
if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
- && s->ctx && s->ctx->tlsext_status_cb) {
+ && !(s->hit) && s->ctx && s->ctx->tlsext_status_cb) {
int r;
/*
- * Set resp to NULL, resplen to -1 so callback knows there is no
- * response.
+ * Call callback with resp == NULL and resplen == -1 so callback
+ * knows there is no response
*/
- if (s->tlsext_ocsp_resp) {
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = NULL;
- }
- s->tlsext_ocsp_resplen = -1;
r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
if (r == 0) {
al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
@@ -2294,10 +2292,13 @@
/* Check key name matches */
if (OPENSSL_port_memcmp(etick, tctx->tlsext_tick_key_name, 16))
return 2;
- HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
- tlsext_tick_md(), NULL);
- EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
- tctx->tlsext_tick_aes_key, etick + 16);
+ if (HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+ tlsext_tick_md(), NULL) <= 0
+ || EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+ tctx->tlsext_tick_aes_key,
+ etick + 16) <= 0) {
+ goto err;
+ }
}
/*
* Attempt to process session ticket, first conduct sanity and integrity
@@ -2305,13 +2306,14 @@
*/
mlen = HMAC_size(&hctx);
if (mlen < 0) {
- EVP_CIPHER_CTX_cleanup(&ctx);
- return -1;
+ goto err;
}
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
- HMAC_Update(&hctx, etick, eticklen);
- HMAC_Final(&hctx, tick_hmac, NULL);
+ if (HMAC_Update(&hctx, etick, eticklen) <= 0
+ || HMAC_Final(&hctx, tick_hmac, NULL) <= 0) {
+ goto err;
+ }
HMAC_CTX_cleanup(&hctx);
if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
EVP_CIPHER_CTX_cleanup(&ctx);
@@ -2322,14 +2324,13 @@
p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
sdec = OPENSSL_malloc(eticklen);
- if (!sdec) {
+ if (!sdec || EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen) <= 0) {
EVP_CIPHER_CTX_cleanup(&ctx);
return -1;
}
- EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0) {
EVP_CIPHER_CTX_cleanup(&ctx);
- OPENSSL_free(sdec);
+ OPENSSL_port_free(sdec);
return 2;
}
slen += mlen;
@@ -2337,7 +2338,7 @@
p = sdec;
sess = d2i_SSL_SESSION(NULL, &p, slen);
- OPENSSL_free(sdec);
+ OPENSSL_port_free(sdec);
if (sess) {
/*
* The session ID, if non-empty, is used by some clients to detect
@@ -2359,6 +2360,10 @@
* For session parse failure, indicate that we need to send a new ticket.
*/
return 2;
+err:
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&hctx);
+ return -1;
}
/* Tables to translate from NIDs to TLS v1.2 ids */
@@ -2586,7 +2591,7 @@
bp += payload;
/* Random padding */
if (RAND_pseudo_bytes(bp, padding) < 0) {
- OPENSSL_free(buffer);
+ OPENSSL_port_free(buffer);
return -1;
}
@@ -2598,7 +2603,7 @@
buffer, 3 + payload + padding,
s, s->msg_callback_arg);
- OPENSSL_free(buffer);
+ OPENSSL_port_free(buffer);
if (r < 0)
return r;
@@ -2693,7 +2698,7 @@
}
err:
- OPENSSL_free(buf);
+ OPENSSL_port_free(buf);
return ret;
}
diff --git a/src/third_party/openssl/openssl/ssl/tls1.h b/src/third_party/openssl/openssl/ssl/tls1.h
index 69d8186..91504b1 100644
--- a/src/third_party/openssl/openssl/ssl/tls1.h
+++ b/src/third_party/openssl/openssl/ssl/tls1.h
@@ -235,8 +235,7 @@
/*
* ExtensionType value for TLS padding extension.
- * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
- * http://tools.ietf.org/html/draft-agl-tls-padding-03
+ * http://tools.ietf.org/html/draft-agl-tls-padding
*/
# define TLSEXT_TYPE_padding 21
@@ -261,20 +260,19 @@
# define TLSEXT_TYPE_next_proto_neg 13172
# endif
-/* NameType value from RFC 3546 */
+/* NameType value from RFC3546 */
# define TLSEXT_NAMETYPE_host_name 0
-/* status request value from RFC 3546 */
+/* status request value from RFC3546 */
# define TLSEXT_STATUSTYPE_ocsp 1
-/* ECPointFormat values from draft-ietf-tls-ecc-12 */
+/* ECPointFormat values from RFC4492 */
# define TLSEXT_ECPOINTFORMAT_first 0
# define TLSEXT_ECPOINTFORMAT_uncompressed 0
# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1
# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2
# define TLSEXT_ECPOINTFORMAT_last 2
-/* Signature and hash algorithms from RFC 5246 */
-
+/* Signature and hash algorithms from RFC5246 */
# define TLSEXT_signature_anonymous 0
# define TLSEXT_signature_rsa 1
# define TLSEXT_signature_dsa 2
@@ -404,7 +402,6 @@
# define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066
/* AES ciphersuites from RFC3268 */
-
# define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F
# define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030
# define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031
@@ -570,7 +567,7 @@
# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA"
# define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA"
-/* ECC ciphersuites from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */
+/* ECC ciphersuites from RFC4492 */
# define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA"
# define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA"
# define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA"
diff --git a/src/third_party/openssl/openssl/test/Makefile b/src/third_party/openssl/openssl/test/Makefile
index eca1400..0afae14 100644
--- a/src/third_party/openssl/openssl/test/Makefile
+++ b/src/third_party/openssl/openssl/test/Makefile
@@ -67,6 +67,7 @@
HEARTBEATTEST= heartbeat_test
CONSTTIMETEST= constant_time_test
VERIFYEXTRATEST= verify_extra_test
+CLIENTHELLOTEST= clienthellotest
TESTS= alltests
@@ -78,7 +79,8 @@
$(RANDTEST)$(EXE_EXT) $(DHTEST)$(EXE_EXT) $(ENGINETEST)$(EXE_EXT) \
$(BFTEST)$(EXE_EXT) $(CASTTEST)$(EXE_EXT) $(SSLTEST)$(EXE_EXT) $(EXPTEST)$(EXE_EXT) $(DSATEST)$(EXE_EXT) $(RSATEST)$(EXE_EXT) \
$(EVPTEST)$(EXE_EXT) $(EVPEXTRATEST)$(EXE_EXT) $(IGETEST)$(EXE_EXT) $(JPAKETEST)$(EXE_EXT) $(SRPTEST)$(EXE_EXT) \
- $(ASN1TEST)$(EXE_EXT) $(HEARTBEATTEST)$(EXE_EXT) $(CONSTTIMETEST)$(EXE_EXT) $(VERIFYEXTRATEST)$(EXE_EXT)
+ $(ASN1TEST)$(EXE_EXT) $(HEARTBEATTEST)$(EXE_EXT) $(CONSTTIMETEST)$(EXE_EXT) $(VERIFYEXTRATEST)$(EXE_EXT) \
+ $(CLIENTHELLOTEST)$(EXE_EXT)
# $(METHTEST)$(EXE_EXT)
@@ -91,7 +93,8 @@
$(RANDTEST).o $(DHTEST).o $(ENGINETEST).o $(CASTTEST).o \
$(BFTEST).o $(SSLTEST).o $(DSATEST).o $(EXPTEST).o $(RSATEST).o \
$(EVPTEST).o $(EVPEXTRATEST).o $(IGETEST).o $(JPAKETEST).o $(ASN1TEST).o \
- $(HEARTBEATTEST).o $(CONSTTIMETEST).o $(VERIFYEXTRATEST).o
+ $(HEARTBEATTEST).o $(CONSTTIMETEST).o $(VERIFYEXTRATEST).o \
+ $(CLIENTHELLOTEST).o
SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
$(MD2TEST).c $(MD4TEST).c $(MD5TEST).c \
@@ -101,7 +104,8 @@
$(RANDTEST).c $(DHTEST).c $(ENGINETEST).c $(CASTTEST).c \
$(BFTEST).c $(SSLTEST).c $(DSATEST).c $(EXPTEST).c $(RSATEST).c \
$(EVPTEST).c $(EVPEXTRATEST).c $(IGETEST).c $(JPAKETEST).c $(SRPTEST).c $(ASN1TEST).c \
- $(HEARTBEATTEST).c $(CONSTTIMETEST).c $(VERIFYEXTRATEST).c
+ $(HEARTBEATTEST).c $(CONSTTIMETEST).c $(VERIFYEXTRATEST).c \
+ $(CLIENTHELLOTEST).c
EXHEADER=
HEADER= $(EXHEADER)
@@ -144,7 +148,8 @@
test_enc test_x509 test_rsa test_crl test_sid \
test_gen test_req test_pkcs7 test_verify test_dh test_dsa \
test_ss test_ca test_engine test_evp test_evp_extra test_ssl test_tsa test_ige \
- test_jpake test_srp test_cms test_heartbeat test_constant_time test_verify_extra
+ test_jpake test_srp test_cms test_heartbeat test_constant_time test_verify_extra \
+ test_clienthello
test_evp:
../util/shlib_wrap.sh ./$(EVPTEST) evptests.txt
@@ -339,6 +344,10 @@
@echo $(START) $@
../util/shlib_wrap.sh ./$(VERIFYEXTRATEST)
+test_clienthello: $(CLIENTHELLOTEST)$(EXE_EXT)
+ @echo $(START) $@
+ ../util/shlib_wrap.sh ./$(CLIENTHELLOTEST)
+
lint:
lint -DLINT $(INCLUDES) $(SRC)>fluff
@@ -510,6 +519,9 @@
$(VERIFYEXTRATEST)$(EXE_EXT): $(VERIFYEXTRATEST).o
@target=$(VERIFYEXTRATEST) $(BUILD_CMD)
+$(CLIENTHELLOTEST)$(EXE_EXT): $(CLIENTHELLOTEST).o
+ @target=$(CLIENTHELLOTEST) $(BUILD_CMD)
+
#$(AESTEST).o: $(AESTEST).c
# $(CC) -c $(CFLAGS) -DINTERMEDIATE_VALUE_KAT -DTRACE_KAT_MCT $(AESTEST).c
@@ -555,6 +567,26 @@
bntest.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h bntest.c
casttest.o: ../e_os.h ../include/openssl/cast.h ../include/openssl/e_os2.h
casttest.o: ../include/openssl/opensslconf.h casttest.c
+clienthellotest.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+clienthellotest.o: ../include/openssl/buffer.h ../include/openssl/comp.h
+clienthellotest.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h
+clienthellotest.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+clienthellotest.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+clienthellotest.o: ../include/openssl/err.h ../include/openssl/evp.h
+clienthellotest.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+clienthellotest.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+clienthellotest.o: ../include/openssl/objects.h
+clienthellotest.o: ../include/openssl/opensslconf.h
+clienthellotest.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+clienthellotest.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+clienthellotest.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+clienthellotest.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+clienthellotest.o: ../include/openssl/srtp.h ../include/openssl/ssl.h
+clienthellotest.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+clienthellotest.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+clienthellotest.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+clienthellotest.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
+clienthellotest.o: clienthellotest.c
constant_time_test.o: ../crypto/constant_time_locl.h ../e_os.h
constant_time_test.o: ../include/openssl/e_os2.h
constant_time_test.o: ../include/openssl/opensslconf.h constant_time_test.c
diff --git a/src/third_party/openssl/openssl/test/igetest.c b/src/third_party/openssl/openssl/test/igetest.c
index 0c7b357..08f361a 100644
--- a/src/third_party/openssl/openssl/test/igetest.c
+++ b/src/third_party/openssl/openssl/test/igetest.c
@@ -1,4 +1,4 @@
-/* test/igetest.c -*- mode:C; c-file-style: "eay" -*- */
+/* test/igetest.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/src/third_party/openssl/openssl/util/indent.pro b/src/third_party/openssl/openssl/util/indent.pro
index e871431..4dcda5d 100644
--- a/src/third_party/openssl/openssl/util/indent.pro
+++ b/src/third_party/openssl/openssl/util/indent.pro
@@ -749,3 +749,19 @@
-T ssl_trace_tbl
-T _stdcall
-T tls12_lookup
+-T OPTIONS
+-T OPT_PAIR
+-T uint64_t
+-T int64_t
+-T uint32_t
+-T int32_t
+-T uint16_t
+-T int16_t
+-T uint8_t
+-T int8_t
+-T STRINT_PAIR
+-T felem
+-T felem_bytearray
+-T SH_LIST
+-T PACKET
+-T RECORD_LAYER
diff --git a/src/third_party/openssl/openssl/util/mk1mf.pl b/src/third_party/openssl/openssl/util/mk1mf.pl
index 1eee7aa..5b86aa7 100755
--- a/src/third_party/openssl/openssl/util/mk1mf.pl
+++ b/src/third_party/openssl/openssl/util/mk1mf.pl
@@ -424,7 +424,7 @@
$defs= <<"EOF";
# This makefile has been automatically generated from the OpenSSL distribution.
# This single makefile will build the complete OpenSSL distribution and
-# by default leave the 'intertesting' output files in .${o}out and the stuff
+# by default leave the 'interesting' output files in .${o}out and the stuff
# that needs deleting in .${o}tmp.
# The file was generated by running 'make makefile.one', which
# does a 'make files', which writes all the environment variables from all
diff --git a/src/third_party/openssl/openssl/util/mkrc.pl b/src/third_party/openssl/openssl/util/mkrc.pl
old mode 100644
new mode 100755
index 0ceadcf..83ee6a4
--- a/src/third_party/openssl/openssl/util/mkrc.pl
+++ b/src/third_party/openssl/openssl/util/mkrc.pl
@@ -57,7 +57,7 @@
VALUE "ProductVersion", "$version\\0"
// Optional:
//VALUE "Comments", "\\0"
- VALUE "LegalCopyright", "Copyright © 1998-2006 The OpenSSL Project. Copyright © 1995-1998 Eric A. Young, Tim J. Hudson. All rights reserved.\\0"
+ VALUE "LegalCopyright", "Copyright © 1998-2006 The OpenSSL Project. Copyright © 1995-1998 Eric A. Young, Tim J. Hudson. All rights reserved.\\0"
//VALUE "LegalTrademarks", "\\0"
//VALUE "PrivateBuild", "\\0"
//VALUE "SpecialBuild", "\\0"
diff --git a/src/third_party/openssl/openssl/util/mkstack.pl b/src/third_party/openssl/openssl/util/mkstack.pl
index f708610..a86d91f 100755
--- a/src/third_party/openssl/openssl/util/mkstack.pl
+++ b/src/third_party/openssl/openssl/util/mkstack.pl
@@ -97,7 +97,7 @@
EOF
}
- foreach $type_thing (sort @sstacklst) {
+ foreach $type_thing (sort { $a->[0] cmp $b->[0]} @sstacklst) {
my $t1 = $type_thing->[0];
my $t2 = $type_thing->[1];
$new_stackfile .= <<EOF;
diff --git a/src/third_party/openssl/openssl/util/pl/VC-32.pl b/src/third_party/openssl/openssl/util/pl/VC-32.pl
index b597998..88f0f7a 100644
--- a/src/third_party/openssl/openssl/util/pl/VC-32.pl
+++ b/src/third_party/openssl/openssl/util/pl/VC-32.pl
@@ -342,15 +342,21 @@
local($ret,$_);
$file =~ s/\//$o/g if $o ne '/';
$n=&bname($target);
- $ret.="$target: $files $dep_libs\n";
+ $ret.="$target: $files $dep_libs";
if ($standalone == 1)
{
+ $ret.=" \$(OBJ_D)${o}applink.obj" if $shlib;
+ $ret.="\n";
$ret.=" \$(LINK) \$(LFLAGS) $efile$target @<<\n\t";
- $ret.= "\$(EX_LIBS) " if ($files =~ /O_FIPSCANISTER/ && !$fipscanisterbuild);
+ if ($files =~ /O_FIPSCANISTER/ && !$fipscanisterbuild) {
+ $ret.= "\$(EX_LIBS) ";
+ $ret.= "\$(OBJ_D)${o}applink.obj " if $shlib;
+ }
$ret.="$files $libs\n<<\n";
}
elsif ($standalone == 2)
{
+ $ret.="\n";
$ret.="\tSET FIPS_LINK=\$(LINK)\n";
$ret.="\tSET FIPS_CC=\$(CC)\n";
$ret.="\tSET FIPS_CC_ARGS=/Fo\$(OBJ_D)${o}fips_premain.obj \$(SHLIB_CFLAGS) -c\n";
@@ -363,6 +369,7 @@
}
else
{
+ $ret.="\n";
$ret.="\t\$(LINK) \$(LFLAGS) $efile$target @<<\n";
$ret.="\t\$(APP_EX_OBJ) $files $libs\n<<\n";
}
diff --git a/src/third_party/openssl/openssl/util/selftest.pl b/src/third_party/openssl/openssl/util/selftest.pl
old mode 100755
new mode 100644
index 7b32e9f..59842ef
--- a/src/third_party/openssl/openssl/util/selftest.pl
+++ b/src/third_party/openssl/openssl/util/selftest.pl
@@ -199,3 +199,4 @@
}
print "\nTest report in file $report\n";
+die if $ok != 2;
diff --git a/src/third_party/openssl/openssl/util/toutf8.sh b/src/third_party/openssl/openssl/util/toutf8.sh
new file mode 100644
index 0000000..8a4254b
--- /dev/null
+++ b/src/third_party/openssl/openssl/util/toutf8.sh
@@ -0,0 +1,17 @@
+#! /bin/sh
+#
+# Very simple script to detect and convert files that we want to re-encode to UTF8
+
+git ls-tree -r --name-only HEAD | \
+ while read F; do
+ charset=`file -bi "$F" | sed -e 's|.*charset=||'`
+ if [ "$charset" != "utf-8" -a "$charset" != "binary" -a "$charset" != "us-ascii" ]; then
+ iconv -f ISO-8859-1 -t UTF8 < "$F" > "$F.utf8" && \
+ ( cmp -s "$F" "$F.utf8" || \
+ ( echo "$F"
+ mv "$F" "$F.iso-8859-1"
+ mv "$F.utf8" "$F"
+ )
+ )
+ fi
+ done
diff --git a/src/tools/clang/scripts/update.py b/src/tools/clang/scripts/update.py
index ddd9098..785a0d8 100755
--- a/src/tools/clang/scripts/update.py
+++ b/src/tools/clang/scripts/update.py
@@ -421,7 +421,7 @@
# Clobber the out/ folder for configs that use clang.
-def ClobberOutFolderForClang():
+def ClobberOutFolderForClang(toolchain_timestamp):
should_wipe_out_folder = None
directory_name_of_current_file = os.path.dirname(os.path.abspath(__file__))
@@ -435,19 +435,12 @@
out_subdirs = [os.path.join(out_dir, d)
for d in os.listdir(out_dir)]
for build_folder in filter(os.path.isdir, out_subdirs):
- if not os.path.exists(os.path.join(build_folder, 'build.ninja')):
+ build_file = os.path.join(build_folder, 'build.ninja')
+
+ if not os.path.exists(build_file):
continue
- package_version_filename = os.path.join(build_folder, 'cr_build_revision')
- package_version = None
- try:
- with open(package_version_filename, 'r') as f:
- package_version = f.read()
- except IOError:
- # File does not exist
- pass
-
- if package_version == PACKAGE_VERSION:
+ if os.path.getmtime(build_file) >= toolchain_timestamp:
continue
if should_wipe_out_folder is None:
@@ -458,8 +451,10 @@
RunCommand(['ninja', '-C', build_folder, '-t', 'clean'])
- with open(package_version_filename, 'w') as f:
- f.write(PACKAGE_VERSION)
+ # Update the build file's timestamp to signal that this folder is now
+ # up-to-date. The gyp step will write new build files anyway, but this may
+ # be a config which is NOT being gyp'd.
+ os.utime(build_file, (toolchain_timestamp, toolchain_timestamp))
def UpdateClang(args):
@@ -467,12 +462,12 @@
# Required for LTO, which is used when is_official_build = true.
need_gold_plugin = sys.platform.startswith('linux')
- ClobberOutFolderForClang()
-
if ReadStampFile(
STAMP_FILE) == PACKAGE_VERSION and not args.force_local_build:
if not need_gold_plugin or os.path.exists(
os.path.join(LLVM_BUILD_DIR, "lib/LLVMgold.so")):
+ # Always check to clobber stale builds.
+ ClobberOutFolderForClang(os.path.getmtime(STAMP_FILE))
return 0
print 'Updating Clang to %s...' % PACKAGE_VERSION
@@ -506,6 +501,7 @@
LLVM_BUILD_DIR, PACKAGE_VERSION
])
WriteStampFile(PACKAGE_VERSION, STAMP_FILE)
+ ClobberOutFolderForClang(os.path.getmtime(STAMP_FILE))
return 0
except urllib2.URLError:
print 'Failed to download prebuilt clang %s' % cds_file
@@ -906,6 +902,7 @@
RunCommand(['ninja', 'check-all'], msvc_arch='x64')
WriteStampFile(PACKAGE_VERSION, STAMP_FILE)
+ ClobberOutFolderForClang(os.path.getmtime(STAMP_FILE))
print 'Clang update was successful.'
return 0
diff --git a/src/tools/gyp/pylib/gyp/generator/ninja.py b/src/tools/gyp/pylib/gyp/generator/ninja.py
index e4eaa84..53a0081 100755
--- a/src/tools/gyp/pylib/gyp/generator/ninja.py
+++ b/src/tools/gyp/pylib/gyp/generator/ninja.py
@@ -76,6 +76,10 @@
is_linux = platform.system() == 'Linux'
is_windows = platform.system() == 'Windows'
+microsoft_flavors = ['win', 'xb1', 'xb1-future']
+sony_flavors = ['ps3', 'ps4']
+windows_host_flavors = microsoft_flavors + sony_flavors
+
def StripPrefix(arg, prefix):
if arg.startswith(prefix):
return arg[len(prefix):]
@@ -89,9 +93,9 @@
# whitelist common OK ones and quote anything else.
if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg):
return arg # No quoting necessary.
- if flavor in ['win', 'xb1']:
+ if flavor in microsoft_flavors:
return gyp.msvs_emulation.QuoteForRspFile(arg)
- elif flavor in ['ps3', 'ps4'] :
+ elif flavor in sony_flavors :
# Escape double quotes.
return '"' + arg.replace('\"', '\\\"') + '"'
return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'"
@@ -100,7 +104,7 @@
def Define(d, flavor):
"""Takes a preprocessor define and returns a -D parameter that's ninja- and
shell-escaped."""
- if flavor in ['win', 'xb1']:
+ if flavor in microsoft_flavors:
# cl.exe replaces literal # characters with = in preprocesor definitions for
# some reason. Octal-encode to work around that.
d = d.replace('#', '\\%03o' % ord('#'))
@@ -183,7 +187,7 @@
# For bundles, the .TOC should be produced for the binary, not for
# FinalOutput(). But the naive approach would put the TOC file into the
# bundle, so don't do this for bundles for now.
- if flavor in ['win', 'xb1', 'ps3', 'ps4'] or self.bundle:
+ if flavor in windows_host_flavors or self.bundle:
return False
return self.type in ('shared_library', 'loadable_module')
@@ -251,7 +255,7 @@
self.abs_build_dir = abs_build_dir
self.obj_ext = '.obj' if flavor == 'win' else '.o'
- if flavor in ['win', 'ps3', 'xb1', 'ps4']:
+ if flavor in windows_host_flavors:
# See docstring of msvs_emulation.GenerateEnvironmentFiles().
self.win_env = {}
for arch in ('x86', 'x64'):
@@ -322,7 +326,7 @@
if env:
if self.flavor == 'mac':
path = gyp.xcode_emulation.ExpandEnvVars(path, env)
- elif self.flavor in ['win', 'xb1']:
+ elif self.flavor in microsoft_flavors:
path = gyp.msvs_emulation.ExpandMacros(path, env)
if path.startswith('$!'):
expanded = self.ExpandSpecial(path)
@@ -411,7 +415,7 @@
self.xcode_settings = self.msvs_settings = None
if self.flavor == 'mac':
self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
- if (self.flavor in ['win', 'ps3', 'xb1', 'ps4']
+ if (self.flavor in windows_host_flavors
and is_windows):
self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec,
generator_flags)
@@ -461,7 +465,7 @@
sources = spec.get('sources', []) + extra_sources
if sources:
pch = None
- if self.flavor in ['win', 'xb1']:
+ if self.flavor in microsoft_flavors:
gyp.msvs_emulation.VerifyMissingSources(
sources, self.abs_build_dir, generator_flags, self.GypPathToNinja)
pch = gyp.msvs_emulation.PrecompiledHeader(
@@ -477,7 +481,7 @@
link_deps += [self.GypPathToNinja(f)
for f in sources if f.endswith(self.obj_ext)]
- if self.flavor in ['win', 'xb1'] and self.target.type == 'static_library':
+ if self.flavor in microsoft_flavors and self.target.type == 'static_library':
self.target.component_objs = link_deps
# Write out a link step, if needed.
@@ -524,7 +528,7 @@
def WriteWinIdlFiles(self, spec, prebuild):
"""Writes rules to match MSVS's implicit idl handling."""
- assert self.flavor in ('win', 'xb1')
+ assert self.flavor in microsoft_flavors
if self.msvs_settings.HasExplicitIdlRules(spec):
return []
outputs = []
@@ -573,7 +577,7 @@
return '%s %s: %s' % (verb, self.name, fallback)
def IsCygwinRule(self, action):
- if self.flavor in ['ps3', 'ps4']:
+ if self.flavor in sony_flavors:
return str(action.get('msvs_cygwin_shell', 1)) != '0'
return False
@@ -806,7 +810,7 @@
self.xcode_settings.GetCflagsObjC(config_name)
cflags_objcc = ['$cflags_cc'] + \
self.xcode_settings.GetCflagsObjCC(config_name)
- elif self.flavor in ['win', 'xb1']:
+ elif self.flavor in microsoft_flavors:
cflags = self.msvs_settings.GetCflags(config_name)
cflags_c = self.msvs_settings.GetCflagsC(config_name)
cflags_cc = self.msvs_settings.GetCflagsCC(config_name)
@@ -829,7 +833,7 @@
defines = config.get('defines', []) + extra_defines
self.WriteVariableList('defines', [Define(d, self.flavor) for d in defines])
- if self.flavor in ['win', 'xb1']:
+ if self.flavor in microsoft_flavors:
self.WriteVariableList('rcflags',
[QuoteShellArgument(self.ExpandSpecial(f), self.flavor)
for f in self.msvs_settings.GetRcflags(config_name,
@@ -838,7 +842,7 @@
include_dirs = config.get('include_dirs', [])
include_dirs += config.get('include_dirs_' + self.toolset, [])
- if self.flavor in ['win', 'xb1']:
+ if self.flavor in microsoft_flavors:
include_dirs = self.msvs_settings.AdjustIncludeDirs(include_dirs,
config_name)
self.WriteVariableList('includes',
@@ -897,7 +901,7 @@
command = 'objc'
elif self.flavor == 'mac' and ext == 'mm':
command = 'objcxx'
- elif self.flavor in ['win', 'xb1'] and ext == 'rc':
+ elif self.flavor in microsoft_flavors and ext == 'rc':
command = 'rc'
obj_ext = '.res'
else:
@@ -910,7 +914,7 @@
output = self.GypPathToUniqueOutput(filename + obj_ext)
implicit = precompiled_header.GetObjDependencies([input], [output])
variables = []
- if self.flavor in ['win', 'xb1']:
+ if self.flavor in microsoft_flavors:
variables, output, implicit = precompiled_header.GetFlagsModifications(
input, output, implicit, command, cflags_c, cflags_cc,
self.ExpandSpecial)
@@ -966,10 +970,10 @@
continue
linkable = target.Linkable()
if linkable:
- if (self.flavor in ['win', 'xb1'] and target.component_objs and
+ if (self.flavor in microsoft_flavors and target.component_objs and
self.msvs_settings.IsUseLibraryDependencyInputs(config_name)):
extra_link_deps.extend(target.component_objs)
- elif (self.flavor in ['win', 'xb1', 'ps3'] and
+ elif (self.flavor in (microsoft_flavors + ['ps3']) and
target.import_lib):
extra_link_deps.append(target.import_lib)
elif target.UsesToc(self.flavor):
@@ -1000,7 +1004,7 @@
ldflags = self.xcode_settings.GetLdflags(config_name,
self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
self.GypPathToNinja)
- elif self.flavor in ['win', 'xb1']:
+ elif self.flavor in microsoft_flavors:
libflags = self.msvs_settings.GetLibFlags(config_name,
self.GypPathToNinja)
self.WriteVariableList(
@@ -1034,7 +1038,7 @@
if self.flavor == 'mac':
libraries = self.xcode_settings.AdjustLibraries(libraries)
- elif self.flavor in ['win', 'xb1']:
+ elif self.flavor in microsoft_flavors:
libraries = self.msvs_settings.AdjustLibraries(libraries)
self.WriteVariableList('libs', libraries)
@@ -1044,7 +1048,7 @@
extra_bindings.append(('soname', os.path.split(output)[1]))
extra_bindings.append(('lib',
gyp.common.EncodePOSIXShellArgument(output)))
- if self.flavor in ['win', 'xb1']:
+ if self.flavor in microsoft_flavors:
extra_bindings.append(('dll', output))
if '/NOENTRY' not in ldflags:
self.target.import_lib = output + '.lib'
@@ -1110,7 +1114,7 @@
elif spec['type'] == 'static_library':
self.target.binary = self.ComputeOutput(spec)
variables = []
- if self.flavor in ('win', 'xb1'):
+ if self.flavor in microsoft_flavors:
libflags = self.msvs_settings.GetLibFlags(config_name,
self.GypPathToNinja)
variables.append(('libflags', ' '.join(libflags)))
@@ -1121,7 +1125,7 @@
if self.xcode_settings:
variables.append(('libtool_flags',
self.xcode_settings.GetLibtoolflags(config_name)))
- if (self.flavor not in ('mac', 'win', 'xb1') and not
+ if (self.flavor not in (['mac'] + microsoft_flavors) and not
self.is_standalone_static_library):
command = 'alink_thin'
else:
@@ -1373,7 +1377,7 @@
rspfile = None
rspfile_content = None
args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args]
- if (self.flavor in ['win', 'ps3', 'xb1', 'ps4']
+ if (self.flavor in windows_host_flavors
and is_windows):
rspfile = rule_name + '.$unique_name.rsp'
# The cygwin case handles this inside the bash sub-shell.
@@ -1424,7 +1428,7 @@
global generator_extra_sources_for_rules
generator_extra_sources_for_rules = getattr(xcode_generator,
'generator_extra_sources_for_rules', [])
- elif flavor in ['win', 'xb1']:
+ elif flavor in microsoft_flavors:
default_variables.setdefault('OS', 'win')
default_variables['EXECUTABLE_SUFFIX'] = '.exe'
default_variables['STATIC_LIB_PREFIX'] = ''
@@ -1600,14 +1604,14 @@
# - If there is no 'make_global_settings' for CC.host/CXX.host or
# 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set
# to cc/cxx.
- if (flavor == 'win' or (flavor in ['ps3', 'ps4'] and is_windows)):
+ if (flavor == 'win' or (flavor in sony_flavors and is_windows)):
cc = 'cl.exe'
cxx = 'cl.exe'
ld = 'link.exe'
gyp.msvs_emulation.GenerateEnvironmentFiles(
toplevel_build, generator_flags, OpenOutput)
ld_host = '$ld'
- elif flavor == 'xb1':
+ elif flavor in ['xb1', 'xb1-future']:
cc = 'cl.exe'
cxx = 'cl.exe'
ld = 'link.exe'
@@ -1665,14 +1669,14 @@
python_exec = sys.executable
ar_flags = ''
- if flavor in ['win', 'xb1']:
+ if flavor in microsoft_flavors:
master_ninja.variable('ld', ld)
master_ninja.variable('ar', os.environ.get('AR', 'ar'))
master_ninja.variable('rc', 'rc.exe')
master_ninja.variable('asm', 'ml.exe')
master_ninja.variable('mt', 'mt.exe')
master_ninja.variable('use_dep_database', '1')
- elif flavor in ['ps3', 'ps4']:
+ elif flavor in sony_flavors:
# Require LD to be set.
master_ninja.variable('ld', os.environ.get('LD'))
master_ninja.variable('ar', os.environ.get('AR', 'ar'))
@@ -1728,8 +1732,8 @@
master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks())
master_ninja.newline()
- if flavor not in ['win', 'xb1']:
- if flavor in ['ps3', 'ps4'] :
+ if flavor not in microsoft_flavors:
+ if flavor in sony_flavors :
# uca := Unnamed Console A
dep_format = 'snc' if (flavor in ['ps3']) else 'uca'
master_ninja.rule(
@@ -1809,14 +1813,14 @@
'$arch $asm $defines $includes /c /Fo $out $in' %
python_exec))
- if flavor not in ['mac', 'win', 'xb1']:
+ if flavor not in (['mac'] + microsoft_flavors):
alink_command = 'rm -f $out && $ar $arFlags $out @$out.rsp'
# TODO: Use rcsT on Linux only.
alink_thin_command = 'rm -f $out && $ar $arThinFlags $out @$out.rsp'
ld_cmd = '$ld'
- if flavor in ['ps3', 'ps4'] and is_windows:
+ if flavor in sony_flavors and is_windows:
alink_command = 'cmd.exe /c ' + alink_command
alink_thin_command = 'cmd.exe /c ' + alink_thin_command
ld_cmd = '%s gyp-win-tool link-wrapper $arch $ld' % python_exec
@@ -1889,7 +1893,7 @@
command=(mtime_preserving_solink_base % {
'suffix': '-Wl,--start-group $in $solibs -Wl,--end-group $libs'}))
- if flavor in ['ps3', 'ps4']:
+ if flavor in sony_flavors:
# PS3 and PS4 linkers don't know about rpath.
rpath = ''
else:
@@ -1903,7 +1907,7 @@
rspfile_content=('$ldflags -o $out %s -Wl,--start-group $in $solibs '
'-Wl,--end-group $libs' % rpath),
pool='link_pool')
- elif flavor in ['win', 'xb1']:
+ elif flavor in microsoft_flavors:
master_ninja.rule(
'alink',
description='LIB $out',
@@ -1916,7 +1920,7 @@
dllcmd = ('%s gyp-win-tool link-wrapper $arch '
'$ld /nologo $implibflag /DLL /OUT:$dll '
'/PDB:$dll.pdb @$dll.rsp' % python_exec)
- if flavor != 'xb1':
+ if not flavor in ['xb1', 'xb1-future']:
# XB1 doesn't need a manifest.
dllcmd += (' && %s gyp-win-tool manifest-wrapper $arch '
'$mt -nologo -manifest $manifests -out:$dll.manifest' %
@@ -1938,7 +1942,7 @@
'$mt -nologo -manifest $manifests -out:$out.manifest' %
(python_exec, python_exec))
else:
- assert flavor == 'xb1'
+ assert flavor in ['xb1', 'xb1-future']
# XB1 doesn't need a manifest.
link_command=('%s gyp-win-tool link-wrapper $arch '
'$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' %
@@ -2027,7 +2031,7 @@
description='PACKAGE FRAMEWORK $out, POSTBUILDS',
command='./gyp-mac-tool package-framework $out $version$postbuilds '
'&& touch $out')
- if flavor in ['win', 'xb1']:
+ if flavor in microsoft_flavors:
master_ninja.rule(
'stamp',
description='STAMP $out',
@@ -2256,7 +2260,7 @@
def GenerateOutput(target_list, target_dicts, data, params):
user_config = params.get('generator_flags', {}).get('config', None)
- if gyp.common.GetFlavor(params) in ['win', 'xb1']:
+ if gyp.common.GetFlavor(params) in microsoft_flavors:
target_list, target_dicts = MSVSUtil.ShardTargets(target_list, target_dicts)
if user_config:
GenerateOutputForConfig(target_list, target_dicts, data, params,
diff --git a/src/tools/gyp/pylib/gyp/generator/qtcreator_ninja.py b/src/tools/gyp/pylib/gyp/generator/qtcreator_ninja.py
index f0f955d..24c0990 100644
--- a/src/tools/gyp/pylib/gyp/generator/qtcreator_ninja.py
+++ b/src/tools/gyp/pylib/gyp/generator/qtcreator_ninja.py
@@ -14,6 +14,7 @@
"""Gyp generator for QT Creator projects that invoke ninja."""
import os
+import re
PROJECT_DIR_RELATIVE_TO_OUTPUT_DIR = 'qtcreator_projects'
@@ -28,6 +29,14 @@
return ret
+def SplitAssignmentDefine(line):
+ matched = re.match(r'([^=\b]+)=(.*)', line)
+ if matched:
+ return matched.group(1) + ' ' + matched.group(2)
+ else:
+ return line
+
+
def GenProject(project_def, proj_dir):
"""Generates QT Creator project (.creator) and supporting files.
@@ -53,7 +62,7 @@
with open(basefilename + '.config', 'w') as f:
for define in configuration['defines']:
- f.write('#define %s\n' % define)
+ f.write('#define %s\n' % SplitAssignmentDefine(define))
with open(basefilename + '.files', 'w') as f:
for source in project_def['sources']: