Bug 1109248: Webrtc updated to branch 40 7864; pull made Wed Dec 10 12:23:33 EST 2014 rs=jesup

--HG--
rename : media/webrtc/trunk/webrtc/system_wrappers/interface/thread_annotations.h => media/webrtc/trunk/webrtc/base/thread_annotations.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/main/test/TestFEC.h => media/webrtc/trunk/webrtc/modules/audio_coding/main/test/TestRedFec.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/accelerate.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/accelerate.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/accelerate.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/accelerate.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_decoder.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder_impl.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder_impl.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_decoder_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_multi_vector.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_multi_vector.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_multi_vector.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_multi_vector.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_multi_vector_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_vector.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_vector.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_vector.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_vector.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/audio_vector_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_vector_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/background_noise.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/background_noise.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/background_noise.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/background_noise.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/background_noise_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/background_noise_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/buffer_level_filter.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/buffer_level_filter.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/buffer_level_filter.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/buffer_level_filter.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/buffer_level_filter_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/buffer_level_filter_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/comfort_noise.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/comfort_noise.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/comfort_noise.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/comfort_noise.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/comfort_noise_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/comfort_noise_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decision_logic.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decision_logic.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_fax.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decision_logic_fax.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_fax.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decision_logic_fax.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_normal.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decision_logic_normal.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_normal.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decision_logic_normal.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decision_logic_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decision_logic_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decoder_database.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decoder_database.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decoder_database.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decoder_database.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/decoder_database_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/defines.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/defines.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_manager.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/delay_manager.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_manager.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/delay_manager.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_manager_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/delay_manager_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_peak_detector.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/delay_peak_detector.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_peak_detector.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/delay_peak_detector.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/delay_peak_detector_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/delay_peak_detector_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dsp_helper.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dsp_helper.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dsp_helper.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dsp_helper.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dsp_helper_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dsp_helper_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_buffer.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dtmf_buffer.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_buffer_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dtmf_buffer_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_tone_generator.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dtmf_tone_generator.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/dtmf_tone_generator.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/dtmf_tone_generator.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/expand.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/expand.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/expand.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/expand.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/expand_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/expand_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/interface/audio_decoder.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/interface/neteq.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/interface/neteq.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/merge.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/merge.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/merge.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/merge.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/merge_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/merge_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_audio_decoder.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_audio_vector.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_audio_vector.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_buffer_level_filter.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_decoder_database.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_delay_manager.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_delay_peak_detector.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_dtmf_buffer.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_buffer.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_dtmf_tone_generator.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_tone_generator.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_external_decoder_pcm16b.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_packet_buffer.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_packet_buffer.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/mock/mock_payload_splitter.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/mock/mock_payload_splitter.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_impl.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_impl.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_stereo_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_tests.gypi
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/normal.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/normal.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/normal.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/normal.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/packet.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/packet.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/packet_buffer.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/packet_buffer.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/packet_buffer_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/packet_buffer_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/payload_splitter.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/payload_splitter.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/payload_splitter.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/payload_splitter.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/payload_splitter_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/post_decode_vad.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/post_decode_vad.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/post_decode_vad.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/post_decode_vad.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/post_decode_vad_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/post_decode_vad_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/preemptive_expand.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/preemptive_expand.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/preemptive_expand.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/preemptive_expand.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/random_vector.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/random_vector.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/random_vector.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/random_vector.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/random_vector_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/random_vector_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/rtcp.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/rtcp.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/statistics_calculator.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/statistics_calculator.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/statistics_calculator.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/statistics_calculator.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/sync_buffer.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/sync_buffer.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/sync_buffer.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/sync_buffer.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/sync_buffer_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/sync_buffer_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/test/neteq_performance_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/neteq_performance_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/time_stretch.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/time_stretch.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/time_stretch.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/time_stretch.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/time_stretch_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/time_stretch_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/timestamp_scaler.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/timestamp_scaler.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/timestamp_scaler.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/timestamp_scaler_unittest.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/audio_loop.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/audio_loop.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/audio_loop.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/audio_loop.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/input_audio_file.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/input_audio_file.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/input_audio_file.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/input_audio_file.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.h => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.h
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/neteq_rtpplay.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/tools/rtp_generator.cc => media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/rtp_generator.cc
rename : media/webrtc/trunk/webrtc/modules/audio_device/ios/audio_device_ios.cc => media/webrtc/trunk/webrtc/modules/audio_device/ios/audio_device_ios.mm
rename : media/webrtc/trunk/webrtc/modules/video_capture/ios/video_capture_ios_objc.h => media/webrtc/trunk/webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.h
rename : media/webrtc/trunk/webrtc/modules/video_capture/ios/video_capture_ios_objc.mm => media/webrtc/trunk/webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.mm
rename : media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/include/rtp_to_ntp.h => media/webrtc/trunk/webrtc/system_wrappers/interface/rtp_to_ntp.h
rename : media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/rtp_to_ntp.cc => media/webrtc/trunk/webrtc/system_wrappers/source/rtp_to_ntp.cc
rename : media/webrtc/trunk/webrtc/test/mac/run_tests.mm => media/webrtc/trunk/webrtc/test/mac/run_test.mm
rename : media/webrtc/trunk/webrtc/modules/audio_coding/neteq4/post_decode_vad_unittest.cc => media/webrtc/trunk/webrtc/test/run_test.cc
This commit is contained in:
Randell Jesup 2015-01-29 18:33:35 -05:00
Родитель f62801541d
Коммит a50873f485
2161 изменённых файлов: 168591 добавлений и 102187 удалений

Просмотреть файл

@ -0,0 +1,245 @@
# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
# TODO(kjellander): Rebase this to webrtc/build/common.gypi changes after r6330.
import("//build/config/arm.gni")
import("//build/config/crypto.gni")
import("//build/config/linux/pkg_config.gni")
import("build/webrtc.gni")
# Contains the defines and includes in common.gypi that are duplicated both as
# target_defaults and direct_dependent_settings.
config("common_inherited_config") {
defines = []
if (build_with_mozilla) {
defines += [ "WEBRTC_MOZILLA_BUILD" ]
}
if (build_with_chromium) {
defines = [
"WEBRTC_CHROMIUM_BUILD",
]
include_dirs = [
# overrides must be included first as that is the mechanism for
# selecting the override headers in Chromium.
"overrides",
# Allow includes to be prefixed with webrtc/ in case it is not an
# immediate subdirectory of the top-level.
"..",
]
}
if (is_posix) {
defines += [ "WEBRTC_POSIX" ]
}
if (is_ios) {
defines += [
"WEBRTC_MAC",
"WEBRTC_IOS",
]
}
if (is_linux) {
defines += [ "WEBRTC_LINUX" ]
}
if (is_mac) {
defines += [ "WEBRTC_MAC" ]
}
if (is_win) {
defines += [ "WEBRTC_WIN" ]
}
if (is_android) {
defines += [
"WEBRTC_LINUX",
"WEBRTC_ANDROID",
]
if (rtc_enable_android_opensl) {
defines += [ "WEBRTC_ANDROID_OPENSLES" ]
}
}
}
if (rtc_have_dbus_glib) {
pkg_config("dbus-glib") {
packages = [ "dbus-glib-1" ]
}
}
config("common_config") {
cflags = []
cflags_cc = []
if (rtc_restrict_logging) {
defines = [ "WEBRTC_RESTRICT_LOGGING" ]
}
if (rtc_have_dbus_glib) {
defines += [ "HAVE_DBUS_GLIB" ]
# TODO(kjellander): Investigate this, it seems like include <dbus/dbus.h>
# is still not found even if the execution of
# build/config/linux/pkg-config.py dbus-glib-1 returns correct include
# dirs on Linux.
all_dependent_configs = [ "dbus-glib" ]
}
if (rtc_enable_video) {
defines += [ "WEBRTC_MODULE_UTILITY_VIDEO" ]
}
if (build_with_chromium) {
defines += [ "LOGGING_INSIDE_WEBRTC" ]
} else {
if (is_posix) {
# -Wextra is currently disabled in Chromium"s common.gypi. Enable
# for targets that can handle it. For Android/arm64 right now
# there will be an "enumeral and non-enumeral type in conditional
# expression" warning in android_tools/ndk_experimental"s version
# of stlport.
# See: https://code.google.com/p/chromium/issues/detail?id=379699
if (cpu_arch != "arm64" || !is_android) {
cflags = [
"-Wextra",
# We need to repeat some flags from Chromium"s common.gypi
# here that get overridden by -Wextra.
"-Wno-unused-parameter",
"-Wno-missing-field-initializers",
"-Wno-strict-overflow",
]
cflags_cc = [
"-Wnon-virtual-dtor",
# This is enabled for clang; enable for gcc as well.
"-Woverloaded-virtual",
]
}
}
if (is_clang) {
cflags += [ "-Wthread-safety" ]
}
}
if (cpu_arch == "arm64") {
defines += [ "WEBRTC_ARCH_ARM" ]
}
if (cpu_arch == "arm") {
defines += [ "WEBRTC_ARCH_ARM" ]
if (arm_version == 7) {
defines += [ "WEBRTC_ARCH_ARM_V7" ]
if (arm_use_neon) {
defines += [ "WEBRTC_ARCH_ARM_NEON" ]
} else {
defines += [ "WEBRTC_DETECT_ARM_NEON" ]
}
}
}
if (cpu_arch == "mipsel") {
defines += [ "MIPS32_LE" ]
if (mips_fpu) {
defines += [ "MIPS_FPU_LE" ]
cflags += [ "-mhard-float" ]
} else {
cflags += [ "-msoft-float" ]
}
if (mips_arch_variant == "mips32r2") {
defines += [ "MIPS32_R2_LE" ]
cflags += [ "-mips32r2" ]
cflags_cc += [ "-mips32r2" ]
}
if (mips_dsp_rev == 1) {
defines += [ "MIPS_DSP_R1_LE" ]
cflags += [ "-mdsp" ]
cflags_cc += [ "-mdsp" ]
} else if (mips_dsp_rev == 2) {
defines += [
"MIPS_DSP_R1_LE",
"MIPS_DSP_R2_LE",
]
cflags += [ "-mdspr2" ]
cflags_cc += [ "-mdspr2" ]
}
}
# TODO(kjellander): Handle warnings on Windows where WebRTC differ from the
# default warnings set in build/config/compiler/BUILD.gn.
if (is_android && is_clang) {
# The Android NDK doesn"t provide optimized versions of these
# functions. Ensure they are disabled for all compilers.
cflags += [
"-fno-builtin-cos",
"-fno-builtin-sin",
"-fno-builtin-cosf",
"-fno-builtin-sinf",
]
}
}
static_library("webrtc") {
sources = [
"call.h",
"config.h",
"experiments.h",
"frame_callback.h",
"transport.h",
]
configs += [ ":common_config" ]
public_configs = [ ":common_inherited_config"]
deps = [
":webrtc_common",
"base:webrtc_base",
"common_audio",
"common_video",
"modules/audio_coding",
"modules/audio_conference_mixer",
"modules/audio_device",
"modules/audio_processing",
"modules/bitrate_controller",
"modules/desktop_capture",
"modules/media_file",
"modules/rtp_rtcp",
"modules/utility",
"modules/video_capture",
"modules/video_coding",
"modules/video_processing",
"modules/video_render",
"system_wrappers",
"tools",
"video",
"video_engine",
"voice_engine",
]
}
if (!build_with_chromium) {
executable("webrtc_tests") {
testonly = true
deps = [
":webrtc",
"modules/video_render:video_render_internal_impl",
"modules/video_capture:video_capture_internal_impl",
"test",
]
}
}
source_set("webrtc_common") {
sources = [
"config.h",
"config.cc",
]
if (is_clang) {
# Suppress warnings from Chrome's Clang plugins.
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
configs -= [ "//build/config/clang:find_bad_constructs" ]
}
configs += [ ":common_config" ]
public_configs = [ ":common_inherited_config" ]
}

Просмотреть файл

@ -0,0 +1,8 @@
per-file *.isolate=kjellander@webrtc.org
# These are for the common case of adding or renaming files. If you're doing
# structural changes, please get a review from a reviewer in this file.
per-file *.gyp=*
per-file *.gypi=*
per-file BUILD.gn=kjellander@webrtc.org

Просмотреть файл

@ -8,13 +8,13 @@
def _LicenseHeader(input_api):
"""Returns the license header regexp."""
# Accept any year number from 2011 to the current year
# Accept any year number from 2003 to the current year
current_year = int(input_api.time.strftime('%Y'))
allowed_years = (str(s) for s in reversed(xrange(2011, current_year + 1)))
allowed_years = (str(s) for s in reversed(xrange(2003, current_year + 1)))
years_re = '(' + '|'.join(allowed_years) + ')'
license_header = (
r'.*? Copyright \(c\) %(year)s The WebRTC project authors\. '
r'All Rights Reserved\.\n'
r'.*? Copyright( \(c\))? %(year)s The WebRTC [Pp]roject [Aa]uthors\. '
r'All [Rr]ights [Rr]eserved\.\n'
r'.*?\n'
r'.*? Use of this source code is governed by a BSD-style license\n'
r'.*? that can be found in the LICENSE file in the root of the source\n'

Просмотреть файл

@ -0,0 +1,600 @@
# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("//build/config/crypto.gni")
import("//build/config/ui.gni")
import("../build/webrtc.gni")
config("webrtc_base_config") {
include_dirs = [
"//third_party/jsoncpp/overrides/include",
"//third_party/jsoncpp/source/include",
]
defines = [
"FEATURE_ENABLE_SSL",
"LOGGING=1",
"USE_WEBRTC_DEV_BRANCH",
]
# TODO(henrike): issue 3307, make webrtc_base build without disabling
# these flags.
cflags_cc = [ "-Wno-non-virtual-dtor" ]
}
config("webrtc_base_chromium_config") {
defines = [
"NO_MAIN_THREAD_WRAPPING",
]
}
config("openssl_config") {
defines = [
"SSL_USE_OPENSSL",
"HAVE_OPENSSL_SSL_H",
]
}
config("nss_config") {
defines = [
"SSL_USE_NSS",
"HAVE_NSS_SSL_H",
"SSL_USE_NSS_RNG",
]
}
config("ios_config") {
ldflags = [
#"Foundation.framework", # Already included in //build/config:default_libs.
"Security.framework",
"SystemConfiguration.framework",
#"UIKit.framework", # Already included in //build/config:default_libs.
]
}
config("mac_config") {
ldflags = [
"Cocoa.framework",
#"Foundation.framework", # Already included in //build/config:default_libs.
#"IOKit.framework", # Already included in //build/config:default_libs.
#"Security.framework", # Already included in //build/config:default_libs.
"SystemConfiguration.framework",
]
}
config("mac_x86_config") {
libs = [
#"Carbon.framework", # Already included in //build/config:default_libs.
]
}
if (is_linux && !build_with_chromium) {
# Provides the same functionality as the //crypto:platform target, which
# WebRTC cannot use as we don't sync src/crypto from Chromium.
group("linux_system_ssl") {
if (use_openssl) {
deps = [ "//third_party/boringssl" ]
} else {
deps = [ "//net/third_party/nss/ssl:libssl" ]
public_configs = [
"//net/third_party/nss/ssl:ssl_config",
"//third_party/nss:system_nss_no_ssl_config",
]
}
}
}
if (rtc_build_ssl == 0) {
config("external_ssl_library") {
assert(rtc_ssl_root != "",
"You must specify rtc_ssl_root when rtc_build_ssl==0.")
include_dirs = [ rtc_ssl_root ]
}
}
# The subset of rtc_base approved for use outside of libjingle.
static_library("rtc_base_approved") {
configs += [ "..:common_config" ]
public_configs = [ "..:common_inherited_config" ]
sources = [
"checks.cc",
"checks.h",
"exp_filter.cc",
"exp_filter.h",
"md5.cc",
"md5.h",
"md5digest.h",
"platform_file.cc",
"platform_file.h",
"stringencode.cc",
"stringencode.h",
"stringutils.cc",
"stringutils.h",
"thread_annotations.h",
"timeutils.cc",
"timeutils.h",
]
}
static_library("webrtc_base") {
cflags = []
cflags_cc = []
libs = []
deps = [
":rtc_base_approved",
]
configs += [
"..:common_config",
":webrtc_base_config",
]
public_configs = [
"..:common_inherited_config",
":webrtc_base_config",
]
defines = [
"LOGGING=1",
"USE_WEBRTC_DEV_BRANCH",
]
sources = [
"asyncfile.cc",
"asyncfile.h",
"asynchttprequest.cc",
"asynchttprequest.h",
"asyncpacketsocket.h",
"asyncsocket.cc",
"asyncsocket.h",
"asynctcpsocket.cc",
"asynctcpsocket.h",
"asyncudpsocket.cc",
"asyncudpsocket.h",
"autodetectproxy.cc",
"autodetectproxy.h",
"base64.cc",
"base64.h",
"basicdefs.h",
"bytebuffer.cc",
"bytebuffer.h",
"byteorder.h",
"common.cc",
"common.h",
"cpumonitor.cc",
"cpumonitor.h",
"crc32.cc",
"crc32.h",
"criticalsection.h",
"cryptstring.h",
"diskcache.cc",
"diskcache.h",
"event.cc",
"event.h",
"fileutils.cc",
"fileutils.h",
"firewallsocketserver.cc",
"firewallsocketserver.h",
"flags.cc",
"flags.h",
"gunit_prod.h",
"helpers.cc",
"helpers.h",
"httpbase.cc",
"httpbase.h",
"httpclient.cc",
"httpclient.h",
"httpcommon-inl.h",
"httpcommon.cc",
"httpcommon.h",
"httprequest.cc",
"httprequest.h",
"iosfilesystem.mm",
"ipaddress.cc",
"ipaddress.h",
"linked_ptr.h",
"mathutils.h",
"messagedigest.cc",
"messagedigest.h",
"messagehandler.cc",
"messagehandler.h",
"messagequeue.cc",
"messagequeue.h",
"nethelpers.cc",
"nethelpers.h",
"network.cc",
"network.h",
"nullsocketserver.h",
"pathutils.cc",
"pathutils.h",
"physicalsocketserver.cc",
"physicalsocketserver.h",
"proxydetect.cc",
"proxydetect.h",
"proxyinfo.cc",
"proxyinfo.h",
"ratelimiter.cc",
"ratelimiter.h",
"ratetracker.cc",
"ratetracker.h",
"safe_conversions.h",
"safe_conversions_impl.h",
"scoped_autorelease_pool.h",
"scoped_autorelease_pool.mm",
"scoped_ptr.h",
"sha1.cc",
"sha1.h",
"sha1digest.h",
"signalthread.cc",
"signalthread.h",
"sigslot.h",
"sigslotrepeater.h",
"socket.h",
"socketadapters.cc",
"socketadapters.h",
"socketaddress.cc",
"socketaddress.h",
"socketaddresspair.cc",
"socketaddresspair.h",
"socketfactory.h",
"socketpool.cc",
"socketpool.h",
"socketserver.h",
"socketstream.cc",
"socketstream.h",
"ssladapter.cc",
"ssladapter.h",
"sslfingerprint.cc",
"sslfingerprint.h",
"sslidentity.cc",
"sslidentity.h",
"sslsocketfactory.cc",
"sslsocketfactory.h",
"sslstreamadapter.cc",
"sslstreamadapter.h",
"sslstreamadapterhelper.cc",
"sslstreamadapterhelper.h",
"stream.cc",
"stream.h",
"systeminfo.cc",
"systeminfo.h",
"task.cc",
"task.h",
"taskparent.cc",
"taskparent.h",
"taskrunner.cc",
"taskrunner.h",
"thread.cc",
"thread.h",
"thread_checker.h",
"thread_checker_impl.cc",
"thread_checker_impl.h",
"timing.cc",
"timing.h",
"urlencode.cc",
"urlencode.h",
"worker.cc",
"worker.h",
]
if (is_posix) {
sources += [
"unixfilesystem.cc",
"unixfilesystem.h",
]
}
if (build_with_chromium) {
sources += [
"../overrides/webrtc/base/basictypes.h",
"../overrides/webrtc/base/constructormagic.h",
"../overrides/webrtc/base/logging.cc",
"../overrides/webrtc/base/logging.h",
]
if (is_win) {
sources += [ "../overrides/webrtc/base/win32socketinit.cc" ]
}
include_dirs = [
"../overrides",
"../../boringssl/src/include",
]
public_configs += [ ":webrtc_base_chromium_config" ]
} else {
sources += [
"asyncinvoker.cc",
"asyncinvoker.h",
"asyncinvoker-inl.h",
"asyncresolverinterface.h",
"atomicops.h",
"bandwidthsmoother.cc",
"bandwidthsmoother.h",
"basictypes.h",
"bind.h",
"bind.h.pump",
"buffer.h",
"callback.h",
"callback.h.pump",
"constructormagic.h",
"filelock.cc",
"filelock.h",
"fileutils_mock.h",
"genericslot.h",
"genericslot.h.pump",
"httpserver.cc",
"httpserver.h",
"json.cc",
"json.h",
"logging.cc",
"logging.h",
"mathutils.h",
"multipart.cc",
"multipart.h",
"natserver.cc",
"natserver.h",
"natsocketfactory.cc",
"natsocketfactory.h",
"nattypes.cc",
"nattypes.h",
"optionsfile.cc",
"optionsfile.h",
"profiler.cc",
"profiler.h",
"proxyserver.cc",
"proxyserver.h",
"refcount.h",
"referencecountedsingletonfactory.h",
"rollingaccumulator.h",
"scopedptrcollection.h",
"scoped_ref_ptr.h",
"sec_buffer.h",
"sharedexclusivelock.cc",
"sharedexclusivelock.h",
"sslconfig.h",
"sslroots.h",
"stringdigest.h",
"testclient.cc",
"testclient.h",
"transformadapter.cc",
"transformadapter.h",
"versionparsing.cc",
"versionparsing.h",
"virtualsocketserver.cc",
"virtualsocketserver.h",
"window.h",
"windowpickerfactory.h",
"windowpicker.h",
]
if (is_posix) {
sources += [
"latebindingsymboltable.cc",
"latebindingsymboltable.cc.def",
"latebindingsymboltable.h",
"latebindingsymboltable.h.def",
"posix.cc",
"posix.h",
]
}
if (is_linux) {
sources += [
"dbus.cc",
"dbus.h",
"libdbusglibsymboltable.cc",
"libdbusglibsymboltable.h",
"linuxfdwalk.c",
"linuxfdwalk.h",
]
}
if (is_mac) {
sources += [
"macasyncsocket.cc",
"macasyncsocket.h",
"maccocoasocketserver.h",
"maccocoasocketserver.mm",
"macsocketserver.cc",
"macsocketserver.h",
"macwindowpicker.cc",
"macwindowpicker.h",
]
}
if (is_win) {
sources += [
"diskcache_win32.cc",
"diskcache_win32.h",
"win32regkey.cc",
"win32regkey.h",
"win32socketinit.cc",
"win32socketinit.h",
"win32socketserver.cc",
"win32socketserver.h",
]
}
if (rtc_build_json) {
deps += [ "//third_party/jsoncpp" ]
} else {
include_dirs += [ rtc_jsoncpp_root ]
# When defined changes the include path for json.h to where it is
# expected to be when building json outside of the standalone build.
defines += [ "WEBRTC_EXTERNAL_JSON" ]
}
} # !build_with_chromium
if (is_clang) {
# Suppress warnings from the Chrome Clang plugins.
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
configs -= [ "//build/config/clang:find_bad_constructs" ]
}
# TODO(henrike): issue 3307, make webrtc_base build with the Chromium default
# compiler settings.
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
cflags += [ "-Wno-uninitialized" ]
cflags_cc += [ "-Wno-non-virtual-dtor" ]
if (use_openssl) {
public_configs += [ ":openssl_config" ]
if (rtc_build_ssl) {
deps += [ "//third_party/boringssl" ]
} else {
configs += [ "external_ssl_library" ]
}
sources += [
"openssl.h",
"openssladapter.cc",
"openssladapter.h",
"openssldigest.cc",
"openssldigest.h",
"opensslidentity.cc",
"opensslidentity.h",
"opensslstreamadapter.cc",
"opensslstreamadapter.h",
]
} else {
public_configs += [ ":nss_config" ]
if (rtc_build_ssl) {
if (build_with_chromium) {
deps += [ "//crypto:platform" ]
} else {
deps += [ "//net/third_party/nss/ssl:libssl" ]
if (is_linux) {
deps += [ ":linux_system_ssl" ]
} else {
deps += [
"//third_party/nss:nspr",
"//third_party/nss:nss",
]
}
}
} else {
configs += [ "external_ssl_library" ]
}
sources += [
"nssidentity.cc",
"nssidentity.h",
"nssstreamadapter.cc",
"nssstreamadapter.h",
]
}
if (is_android) {
sources += [
"ifaddrs-android.cc",
"ifaddrs-android.h",
]
libs += [
"log",
"GLESv2"
]
}
if (is_ios) {
all_dependent_configs += [ ":ios_config" ]
}
if (use_x11) {
sources += [
"x11windowpicker.cc",
"x11windowpicker.h",
]
libs += [
"dl",
"rt",
"Xext",
"X11",
"Xcomposite",
"Xrender",
]
}
if (is_linux) {
libs += [
"dl",
"rt",
]
}
if (is_mac) {
sources += [
"maccocoathreadhelper.h",
"maccocoathreadhelper.mm",
"macconversion.cc",
"macconversion.h",
"macutils.cc",
"macutils.h",
]
all_dependent_configs = [ ":mac_config" ]
if (cpu_arch == "x86") {
all_dependent_configs += [ ":mac_x86_config" ]
}
}
if (is_win) {
sources += [
"schanneladapter.cc",
"schanneladapter.h",
"win32.cc",
"win32.h",
"win32filesystem.cc",
"win32filesystem.h",
"win32securityerrors.cc",
"win32window.cc",
"win32window.h",
"win32windowpicker.cc",
"win32windowpicker.h",
"winfirewall.cc",
"winfirewall.h",
"winping.cc",
"winping.h",
]
libs += [
"crypt32.lib",
"iphlpapi.lib",
"secur32.lib",
]
cflags += [
# Suppress warnings about WIN32_LEAN_AND_MEAN.
"/wd4005",
"/wd4703",
]
defines += [ "_CRT_NONSTDC_NO_DEPRECATE" ]
}
if (is_posix && is_debug) {
# The Chromium build/common.gypi defines this for all posix
# _except_ for ios & mac. We want it there as well, e.g.
# because ASSERT and friends trigger off of it.
defines += [ "_DEBUG" ]
}
if (is_ios || (is_mac && cpu_arch != "x86")) {
defines += [ "CARBON_DEPRECATED=YES" ]
}
if (is_linux || is_android) {
sources += [
"linux.cc",
"linux.h",
]
}
}

Просмотреть файл

@ -0,0 +1,13 @@
henrika@webrtc.org
henrike@webrtc.org
henrikg@webrtc.org
hta@webrtc.org
jiayl@webrtc.org
juberti@webrtc.org
mflodman@webrtc.org
perkj@webrtc.org
pthatcher@webrtc.org
sergeyu@chromium.org
tommi@webrtc.org
per-file BUILD.gn=kjellander@webrtc.org

Просмотреть файл

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
* Copyright 2010 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@ -8,6 +8,14 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "ACMTest.h"
#include "webrtc/base/asyncfile.h"
ACMTest::~ACMTest() {}
namespace rtc {
AsyncFile::AsyncFile() {
}
AsyncFile::~AsyncFile() {
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,40 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCFILE_H__
#define WEBRTC_BASE_ASYNCFILE_H__
#include "webrtc/base/sigslot.h"
namespace rtc {
// Provides the ability to perform file I/O asynchronously.
// TODO: Create a common base class with AsyncSocket.
class AsyncFile {
public:
AsyncFile();
virtual ~AsyncFile();
// Determines whether the file will receive read events.
virtual bool readable() = 0;
virtual void set_readable(bool value) = 0;
// Determines whether the file will receive write events.
virtual bool writable() = 0;
virtual void set_writable(bool value) = 0;
sigslot::signal1<AsyncFile*> SignalReadEvent;
sigslot::signal1<AsyncFile*> SignalWriteEvent;
sigslot::signal2<AsyncFile*, int> SignalCloseEvent;
};
} // namespace rtc
#endif // WEBRTC_BASE_ASYNCFILE_H__

Просмотреть файл

@ -0,0 +1,116 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/asynchttprequest.h"
namespace rtc {
enum {
MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE,
MSG_LAUNCH_REQUEST
};
static const int kDefaultHTTPTimeout = 30 * 1000; // 30 sec
///////////////////////////////////////////////////////////////////////////////
// AsyncHttpRequest
///////////////////////////////////////////////////////////////////////////////
AsyncHttpRequest::AsyncHttpRequest(const std::string &user_agent)
: start_delay_(0),
firewall_(NULL),
port_(80),
secure_(false),
timeout_(kDefaultHTTPTimeout),
fail_redirect_(false),
factory_(Thread::Current()->socketserver(), user_agent),
pool_(&factory_),
client_(user_agent.c_str(), &pool_),
error_(HE_NONE) {
client_.SignalHttpClientComplete.connect(this,
&AsyncHttpRequest::OnComplete);
}
AsyncHttpRequest::~AsyncHttpRequest() {
}
void AsyncHttpRequest::OnWorkStart() {
if (start_delay_ <= 0) {
LaunchRequest();
} else {
Thread::Current()->PostDelayed(start_delay_, this, MSG_LAUNCH_REQUEST);
}
}
void AsyncHttpRequest::OnWorkStop() {
// worker is already quitting, no need to explicitly quit
LOG(LS_INFO) << "HttpRequest cancelled";
}
void AsyncHttpRequest::OnComplete(HttpClient* client, HttpErrorType error) {
Thread::Current()->Clear(this, MSG_TIMEOUT);
set_error(error);
if (!error) {
LOG(LS_INFO) << "HttpRequest completed successfully";
std::string value;
if (client_.response().hasHeader(HH_LOCATION, &value)) {
response_redirect_ = value.c_str();
}
} else {
LOG(LS_INFO) << "HttpRequest completed with error: " << error;
}
worker()->Quit();
}
void AsyncHttpRequest::OnMessage(Message* message) {
switch (message->message_id) {
case MSG_TIMEOUT:
LOG(LS_INFO) << "HttpRequest timed out";
client_.reset();
worker()->Quit();
break;
case MSG_LAUNCH_REQUEST:
LaunchRequest();
break;
default:
SignalThread::OnMessage(message);
break;
}
}
void AsyncHttpRequest::DoWork() {
// Do nothing while we wait for the request to finish. We only do this so
// that we can be a SignalThread; in the future this class should not be
// a SignalThread, since it does not need to spawn a new thread.
Thread::Current()->ProcessMessages(kForever);
}
void AsyncHttpRequest::LaunchRequest() {
factory_.SetProxy(proxy_);
if (secure_)
factory_.UseSSL(host_.c_str());
bool transparent_proxy = (port_ == 80) &&
((proxy_.type == PROXY_HTTPS) || (proxy_.type == PROXY_UNKNOWN));
if (transparent_proxy) {
client_.set_proxy(proxy_);
}
client_.set_fail_redirect(fail_redirect_);
client_.set_server(SocketAddress(host_, port_));
LOG(LS_INFO) << "HttpRequest start: " << host_ + client_.request().path;
Thread::Current()->PostDelayed(timeout_, this, MSG_TIMEOUT);
client_.start();
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,104 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCHTTPREQUEST_H_
#define WEBRTC_BASE_ASYNCHTTPREQUEST_H_
#include <string>
#include "webrtc/base/event.h"
#include "webrtc/base/httpclient.h"
#include "webrtc/base/signalthread.h"
#include "webrtc/base/socketpool.h"
#include "webrtc/base/sslsocketfactory.h"
namespace rtc {
class FirewallManager;
///////////////////////////////////////////////////////////////////////////////
// AsyncHttpRequest
// Performs an HTTP request on a background thread. Notifies on the foreground
// thread once the request is done (successfully or unsuccessfully).
///////////////////////////////////////////////////////////////////////////////
class AsyncHttpRequest : public SignalThread {
public:
explicit AsyncHttpRequest(const std::string &user_agent);
~AsyncHttpRequest();
// If start_delay is less than or equal to zero, this starts immediately.
// Start_delay defaults to zero.
int start_delay() const { return start_delay_; }
void set_start_delay(int delay) { start_delay_ = delay; }
const ProxyInfo& proxy() const { return proxy_; }
void set_proxy(const ProxyInfo& proxy) {
proxy_ = proxy;
}
void set_firewall(FirewallManager * firewall) {
firewall_ = firewall;
}
// The DNS name of the host to connect to.
const std::string& host() { return host_; }
void set_host(const std::string& host) { host_ = host; }
// The port to connect to on the target host.
int port() { return port_; }
void set_port(int port) { port_ = port; }
// Whether the request should use SSL.
bool secure() { return secure_; }
void set_secure(bool secure) { secure_ = secure; }
// Time to wait on the download, in ms.
int timeout() { return timeout_; }
void set_timeout(int timeout) { timeout_ = timeout; }
// Fail redirects to allow analysis of redirect urls, etc.
bool fail_redirect() const { return fail_redirect_; }
void set_fail_redirect(bool redirect) { fail_redirect_ = redirect; }
// Returns the redirect when redirection occurs
const std::string& response_redirect() { return response_redirect_; }
HttpRequestData& request() { return client_.request(); }
HttpResponseData& response() { return client_.response(); }
HttpErrorType error() { return error_; }
protected:
void set_error(HttpErrorType error) { error_ = error; }
virtual void OnWorkStart();
virtual void OnWorkStop();
void OnComplete(HttpClient* client, HttpErrorType error);
virtual void OnMessage(Message* message);
virtual void DoWork();
private:
void LaunchRequest();
int start_delay_;
ProxyInfo proxy_;
FirewallManager* firewall_;
std::string host_;
int port_;
bool secure_;
int timeout_;
bool fail_redirect_;
SslSocketFactory factory_;
ReuseSocketPool pool_;
HttpClient client_;
HttpErrorType error_;
std::string response_redirect_;
};
} // namespace rtc
#endif // WEBRTC_BASE_ASYNCHTTPREQUEST_H_

Просмотреть файл

@ -0,0 +1,234 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string>
#include "webrtc/base/asynchttprequest.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/httpserver.h"
#include "webrtc/base/socketstream.h"
#include "webrtc/base/thread.h"
#include "webrtc/test/testsupport/gtest_disable.h"
namespace rtc {
static const SocketAddress kServerAddr("127.0.0.1", 0);
static const SocketAddress kServerHostnameAddr("localhost", 0);
static const char kServerGetPath[] = "/get";
static const char kServerPostPath[] = "/post";
static const char kServerResponse[] = "This is a test";
class TestHttpServer : public HttpServer, public sigslot::has_slots<> {
public:
TestHttpServer(Thread* thread, const SocketAddress& addr) :
socket_(thread->socketserver()->CreateAsyncSocket(addr.family(),
SOCK_STREAM)) {
socket_->Bind(addr);
socket_->Listen(5);
socket_->SignalReadEvent.connect(this, &TestHttpServer::OnAccept);
}
SocketAddress address() const { return socket_->GetLocalAddress(); }
void Close() const { socket_->Close(); }
private:
void OnAccept(AsyncSocket* socket) {
AsyncSocket* new_socket = socket_->Accept(NULL);
if (new_socket) {
HandleConnection(new SocketStream(new_socket));
}
}
rtc::scoped_ptr<AsyncSocket> socket_;
};
class AsyncHttpRequestTest : public testing::Test,
public sigslot::has_slots<> {
public:
AsyncHttpRequestTest()
: started_(false),
done_(false),
server_(Thread::Current(), kServerAddr) {
server_.SignalHttpRequest.connect(this, &AsyncHttpRequestTest::OnRequest);
}
bool started() const { return started_; }
bool done() const { return done_; }
AsyncHttpRequest* CreateGetRequest(const std::string& host, int port,
const std::string& path) {
rtc::AsyncHttpRequest* request =
new rtc::AsyncHttpRequest("unittest");
request->SignalWorkDone.connect(this,
&AsyncHttpRequestTest::OnRequestDone);
request->request().verb = rtc::HV_GET;
request->set_host(host);
request->set_port(port);
request->request().path = path;
request->response().document.reset(new MemoryStream());
return request;
}
AsyncHttpRequest* CreatePostRequest(const std::string& host, int port,
const std::string& path,
const std::string content_type,
StreamInterface* content) {
rtc::AsyncHttpRequest* request =
new rtc::AsyncHttpRequest("unittest");
request->SignalWorkDone.connect(this,
&AsyncHttpRequestTest::OnRequestDone);
request->request().verb = rtc::HV_POST;
request->set_host(host);
request->set_port(port);
request->request().path = path;
request->request().setContent(content_type, content);
request->response().document.reset(new MemoryStream());
return request;
}
const TestHttpServer& server() const { return server_; }
protected:
void OnRequest(HttpServer* server, HttpServerTransaction* t) {
started_ = true;
if (t->request.path == kServerGetPath) {
t->response.set_success("text/plain", new MemoryStream(kServerResponse));
} else if (t->request.path == kServerPostPath) {
// reverse the data and reply
size_t size;
StreamInterface* in = t->request.document.get();
StreamInterface* out = new MemoryStream();
in->GetSize(&size);
for (size_t i = 0; i < size; ++i) {
char ch;
in->SetPosition(size - i - 1);
in->Read(&ch, 1, NULL, NULL);
out->Write(&ch, 1, NULL, NULL);
}
out->Rewind();
t->response.set_success("text/plain", out);
} else {
t->response.set_error(404);
}
server_.Respond(t);
}
void OnRequestDone(SignalThread* thread) {
done_ = true;
}
private:
bool started_;
bool done_;
TestHttpServer server_;
};
TEST_F(AsyncHttpRequestTest, TestGetSuccess) {
AsyncHttpRequest* req = CreateGetRequest(
kServerHostnameAddr.hostname(), server().address().port(),
kServerGetPath);
EXPECT_FALSE(started());
req->Start();
EXPECT_TRUE_WAIT(started(), 5000); // Should have started by now.
EXPECT_TRUE_WAIT(done(), 5000);
std::string response;
EXPECT_EQ(200U, req->response().scode);
ASSERT_TRUE(req->response().document);
req->response().document->Rewind();
req->response().document->ReadLine(&response);
EXPECT_EQ(kServerResponse, response);
req->Release();
}
TEST_F(AsyncHttpRequestTest, TestGetNotFound) {
AsyncHttpRequest* req = CreateGetRequest(
kServerHostnameAddr.hostname(), server().address().port(),
"/bad");
req->Start();
EXPECT_TRUE_WAIT(done(), 5000);
size_t size;
EXPECT_EQ(404U, req->response().scode);
ASSERT_TRUE(req->response().document);
req->response().document->GetSize(&size);
EXPECT_EQ(0U, size);
req->Release();
}
TEST_F(AsyncHttpRequestTest, TestGetToNonServer) {
AsyncHttpRequest* req = CreateGetRequest(
"127.0.0.1", server().address().port(),
kServerGetPath);
// Stop the server before we send the request.
server().Close();
req->Start();
EXPECT_TRUE_WAIT(done(), 10000);
size_t size;
EXPECT_EQ(500U, req->response().scode);
ASSERT_TRUE(req->response().document);
req->response().document->GetSize(&size);
EXPECT_EQ(0U, size);
req->Release();
}
TEST_F(AsyncHttpRequestTest, DISABLED_TestGetToInvalidHostname) {
AsyncHttpRequest* req = CreateGetRequest(
"invalid", server().address().port(),
kServerGetPath);
req->Start();
EXPECT_TRUE_WAIT(done(), 5000);
size_t size;
EXPECT_EQ(500U, req->response().scode);
ASSERT_TRUE(req->response().document);
req->response().document->GetSize(&size);
EXPECT_EQ(0U, size);
req->Release();
}
TEST_F(AsyncHttpRequestTest, TestPostSuccess) {
AsyncHttpRequest* req = CreatePostRequest(
kServerHostnameAddr.hostname(), server().address().port(),
kServerPostPath, "text/plain", new MemoryStream("abcd1234"));
req->Start();
EXPECT_TRUE_WAIT(done(), 5000);
std::string response;
EXPECT_EQ(200U, req->response().scode);
ASSERT_TRUE(req->response().document);
req->response().document->Rewind();
req->response().document->ReadLine(&response);
EXPECT_EQ("4321dcba", response);
req->Release();
}
// Ensure that we shut down properly even if work is outstanding.
TEST_F(AsyncHttpRequestTest, TestCancel) {
AsyncHttpRequest* req = CreateGetRequest(
kServerHostnameAddr.hostname(), server().address().port(),
kServerGetPath);
req->Start();
req->Destroy(true);
}
TEST_F(AsyncHttpRequestTest, TestGetSuccessDelay) {
AsyncHttpRequest* req = CreateGetRequest(
kServerHostnameAddr.hostname(), server().address().port(),
kServerGetPath);
req->set_start_delay(10); // Delay 10ms.
req->Start();
Thread::SleepMs(5);
EXPECT_FALSE(started()); // Should not have started immediately.
EXPECT_TRUE_WAIT(started(), 5000); // Should have started by now.
EXPECT_TRUE_WAIT(done(), 5000);
std::string response;
EXPECT_EQ(200U, req->response().scode);
ASSERT_TRUE(req->response().document);
req->response().document->Rewind();
req->response().document->ReadLine(&response);
EXPECT_EQ(kServerResponse, response);
req->Release();
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,129 @@
/*
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCINVOKER_INL_H_
#define WEBRTC_BASE_ASYNCINVOKER_INL_H_
#include "webrtc/base/bind.h"
#include "webrtc/base/callback.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/messagehandler.h"
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/base/sigslot.h"
#include "webrtc/base/thread.h"
namespace rtc {
class AsyncInvoker;
// Helper class for AsyncInvoker. Runs a task and triggers a callback
// on the calling thread if necessary. Instances are ref-counted so their
// lifetime can be independent of AsyncInvoker.
class AsyncClosure : public RefCountInterface {
public:
virtual ~AsyncClosure() {}
// Runs the asynchronous task, and triggers a callback to the calling
// thread if needed. Should be called from the target thread.
virtual void Execute() = 0;
};
// Simple closure that doesn't trigger a callback for the calling thread.
template <class FunctorT>
class FireAndForgetAsyncClosure : public AsyncClosure {
public:
explicit FireAndForgetAsyncClosure(const FunctorT& functor)
: functor_(functor) {}
virtual void Execute() {
functor_();
}
private:
FunctorT functor_;
};
// Base class for closures that may trigger a callback for the calling thread.
// Listens for the "destroyed" signals from the calling thread and the invoker,
// and cancels the callback to the calling thread if either is destroyed.
class NotifyingAsyncClosureBase : public AsyncClosure,
public sigslot::has_slots<> {
public:
virtual ~NotifyingAsyncClosureBase() { disconnect_all(); }
protected:
NotifyingAsyncClosureBase(AsyncInvoker* invoker, Thread* calling_thread);
void TriggerCallback();
void SetCallback(const Callback0<void>& callback) {
CritScope cs(&crit_);
callback_ = callback;
}
bool CallbackCanceled() const { return calling_thread_ == NULL; }
private:
Callback0<void> callback_;
CriticalSection crit_;
AsyncInvoker* invoker_;
Thread* calling_thread_;
void CancelCallback();
};
// Closures that have a non-void return value and require a callback.
template <class ReturnT, class FunctorT, class HostT>
class NotifyingAsyncClosure : public NotifyingAsyncClosureBase {
public:
NotifyingAsyncClosure(AsyncInvoker* invoker,
Thread* calling_thread,
const FunctorT& functor,
void (HostT::*callback)(ReturnT),
HostT* callback_host)
: NotifyingAsyncClosureBase(invoker, calling_thread),
functor_(functor),
callback_(callback),
callback_host_(callback_host) {}
virtual void Execute() {
ReturnT result = functor_();
if (!CallbackCanceled()) {
SetCallback(Callback0<void>(Bind(callback_, callback_host_, result)));
TriggerCallback();
}
}
private:
FunctorT functor_;
void (HostT::*callback_)(ReturnT);
HostT* callback_host_;
};
// Closures that have a void return value and require a callback.
template <class FunctorT, class HostT>
class NotifyingAsyncClosure<void, FunctorT, HostT>
: public NotifyingAsyncClosureBase {
public:
NotifyingAsyncClosure(AsyncInvoker* invoker,
Thread* calling_thread,
const FunctorT& functor,
void (HostT::*callback)(),
HostT* callback_host)
: NotifyingAsyncClosureBase(invoker, calling_thread),
functor_(functor) {
SetCallback(Callback0<void>(Bind(callback, callback_host)));
}
virtual void Execute() {
functor_();
TriggerCallback();
}
private:
FunctorT functor_;
};
} // namespace rtc
#endif // WEBRTC_BASE_ASYNCINVOKER_INL_H_

Просмотреть файл

@ -0,0 +1,91 @@
/*
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/asyncinvoker.h"
namespace rtc {
AsyncInvoker::AsyncInvoker() : destroying_(false) {}
AsyncInvoker::~AsyncInvoker() {
destroying_ = true;
SignalInvokerDestroyed();
// Messages for this need to be cleared *before* our destructor is complete.
MessageQueueManager::Clear(this);
}
void AsyncInvoker::OnMessage(Message* msg) {
// Get the AsyncClosure shared ptr from this message's data.
ScopedRefMessageData<AsyncClosure>* data =
static_cast<ScopedRefMessageData<AsyncClosure>*>(msg->pdata);
scoped_refptr<AsyncClosure> closure = data->data();
delete msg->pdata;
msg->pdata = NULL;
// Execute the closure and trigger the return message if needed.
closure->Execute();
}
void AsyncInvoker::Flush(Thread* thread, uint32 id /*= MQID_ANY*/) {
if (destroying_) return;
// Run this on |thread| to reduce the number of context switches.
if (Thread::Current() != thread) {
thread->Invoke<void>(Bind(&AsyncInvoker::Flush, this, thread, id));
return;
}
MessageList removed;
thread->Clear(this, id, &removed);
for (MessageList::iterator it = removed.begin(); it != removed.end(); ++it) {
// This message was pending on this thread, so run it now.
thread->Send(it->phandler,
it->message_id,
it->pdata);
}
}
void AsyncInvoker::DoInvoke(Thread* thread, AsyncClosure* closure,
uint32 id) {
if (destroying_) {
LOG(LS_WARNING) << "Tried to invoke while destroying the invoker.";
// Since this call transwers ownership of |closure|, we clean it up here.
delete closure;
return;
}
thread->Post(this, id, new ScopedRefMessageData<AsyncClosure>(closure));
}
NotifyingAsyncClosureBase::NotifyingAsyncClosureBase(AsyncInvoker* invoker,
Thread* calling_thread)
: invoker_(invoker), calling_thread_(calling_thread) {
calling_thread->SignalQueueDestroyed.connect(
this, &NotifyingAsyncClosureBase::CancelCallback);
invoker->SignalInvokerDestroyed.connect(
this, &NotifyingAsyncClosureBase::CancelCallback);
}
void NotifyingAsyncClosureBase::TriggerCallback() {
CritScope cs(&crit_);
if (!CallbackCanceled() && !callback_.empty()) {
invoker_->AsyncInvoke<void>(calling_thread_, callback_);
}
}
void NotifyingAsyncClosureBase::CancelCallback() {
// If the callback is triggering when this is called, block the
// destructor of the dying object here by waiting until the callback
// is done triggering.
CritScope cs(&crit_);
// calling_thread_ == NULL means do not trigger the callback.
calling_thread_ = NULL;
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,134 @@
/*
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCINVOKER_H_
#define WEBRTC_BASE_ASYNCINVOKER_H_
#include "webrtc/base/asyncinvoker-inl.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/sigslot.h"
#include "webrtc/base/scopedptrcollection.h"
#include "webrtc/base/thread.h"
namespace rtc {
// Invokes function objects (aka functors) asynchronously on a Thread, and
// owns the lifetime of calls (ie, when this object is destroyed, calls in
// flight are cancelled). AsyncInvoker can optionally execute a user-specified
// function when the asynchronous call is complete, or operates in
// fire-and-forget mode otherwise.
//
// AsyncInvoker does not own the thread it calls functors on.
//
// A note about async calls and object lifetimes: users should
// be mindful of object lifetimes when calling functions asynchronously and
// ensure objects used by the function _cannot_ be deleted between the
// invocation and execution of the functor. AsyncInvoker is designed to
// help: any calls in flight will be cancelled when the AsyncInvoker used to
// make the call is destructed, and any calls executing will be allowed to
// complete before AsyncInvoker destructs.
//
// The easiest way to ensure lifetimes are handled correctly is to create a
// class that owns the Thread and AsyncInvoker objects, and then call its
// methods asynchronously as needed.
//
// Example:
// class MyClass {
// public:
// void FireAsyncTaskWithResult(Thread* thread, int x) {
// // Specify a callback to get the result upon completion.
// invoker_.AsyncInvoke<int>(
// thread, Bind(&MyClass::AsyncTaskWithResult, this, x),
// &MyClass::OnTaskComplete, this);
// }
// void FireAnotherAsyncTask(Thread* thread) {
// // No callback specified means fire-and-forget.
// invoker_.AsyncInvoke<void>(
// thread, Bind(&MyClass::AnotherAsyncTask, this));
//
// private:
// int AsyncTaskWithResult(int x) {
// // Some long running process...
// return x * x;
// }
// void AnotherAsyncTask() {
// // Some other long running process...
// }
// void OnTaskComplete(int result) { result_ = result; }
//
// AsyncInvoker invoker_;
// int result_;
// };
class AsyncInvoker : public MessageHandler {
public:
AsyncInvoker();
virtual ~AsyncInvoker();
// Call |functor| asynchronously on |thread|, with no callback upon
// completion. Returns immediately.
template <class ReturnT, class FunctorT>
void AsyncInvoke(Thread* thread,
const FunctorT& functor,
uint32 id = 0) {
AsyncClosure* closure =
new RefCountedObject<FireAndForgetAsyncClosure<FunctorT> >(functor);
DoInvoke(thread, closure, id);
}
// Call |functor| asynchronously on |thread|, calling |callback| when done.
template <class ReturnT, class FunctorT, class HostT>
void AsyncInvoke(Thread* thread,
const FunctorT& functor,
void (HostT::*callback)(ReturnT),
HostT* callback_host,
uint32 id = 0) {
AsyncClosure* closure =
new RefCountedObject<NotifyingAsyncClosure<ReturnT, FunctorT, HostT> >(
this, Thread::Current(), functor, callback, callback_host);
DoInvoke(thread, closure, id);
}
// Call |functor| asynchronously on |thread|, calling |callback| when done.
// Overloaded for void return.
template <class ReturnT, class FunctorT, class HostT>
void AsyncInvoke(Thread* thread,
const FunctorT& functor,
void (HostT::*callback)(),
HostT* callback_host,
uint32 id = 0) {
AsyncClosure* closure =
new RefCountedObject<NotifyingAsyncClosure<void, FunctorT, HostT> >(
this, Thread::Current(), functor, callback, callback_host);
DoInvoke(thread, closure, id);
}
// Synchronously execute on |thread| all outstanding calls we own
// that are pending on |thread|, and wait for calls to complete
// before returning. Optionally filter by message id.
// The destructor will not wait for outstanding calls, so if that
// behavior is desired, call Flush() before destroying this object.
void Flush(Thread* thread, uint32 id = MQID_ANY);
// Signaled when this object is destructed.
sigslot::signal0<> SignalInvokerDestroyed;
private:
virtual void OnMessage(Message* msg);
void DoInvoke(Thread* thread, AsyncClosure* closure, uint32 id);
bool destroying_;
DISALLOW_COPY_AND_ASSIGN(AsyncInvoker);
};
} // namespace rtc
#endif // WEBRTC_BASE_ASYNCINVOKER_H_

Просмотреть файл

@ -0,0 +1,140 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCPACKETSOCKET_H_
#define WEBRTC_BASE_ASYNCPACKETSOCKET_H_
#include "webrtc/base/dscp.h"
#include "webrtc/base/sigslot.h"
#include "webrtc/base/socket.h"
#include "webrtc/base/timeutils.h"
namespace rtc {
// This structure holds the info needed to update the packet send time header
// extension, including the information needed to update the authentication tag
// after changing the value.
struct PacketTimeUpdateParams {
PacketTimeUpdateParams()
: rtp_sendtime_extension_id(-1), srtp_auth_tag_len(-1),
srtp_packet_index(-1) {
}
int rtp_sendtime_extension_id; // extension header id present in packet.
std::vector<char> srtp_auth_key; // Authentication key.
int srtp_auth_tag_len; // Authentication tag length.
int64 srtp_packet_index; // Required for Rtp Packet authentication.
};
// This structure holds meta information for the packet which is about to send
// over network.
struct PacketOptions {
PacketOptions() : dscp(DSCP_NO_CHANGE) {}
explicit PacketOptions(DiffServCodePoint dscp) : dscp(dscp) {}
DiffServCodePoint dscp;
PacketTimeUpdateParams packet_time_params;
};
// This structure will have the information about when packet is actually
// received by socket.
struct PacketTime {
PacketTime() : timestamp(-1), not_before(-1) {}
PacketTime(int64 timestamp, int64 not_before)
: timestamp(timestamp), not_before(not_before) {
}
int64 timestamp; // Receive time after socket delivers the data.
int64 not_before; // Earliest possible time the data could have arrived,
// indicating the potential error in the |timestamp| value,
// in case the system, is busy. For example, the time of
// the last select() call.
// If unknown, this value will be set to zero.
};
inline PacketTime CreatePacketTime(int64 not_before) {
return PacketTime(TimeMicros(), not_before);
}
// Provides the ability to receive packets asynchronously. Sends are not
// buffered since it is acceptable to drop packets under high load.
class AsyncPacketSocket : public sigslot::has_slots<> {
public:
enum State {
STATE_CLOSED,
STATE_BINDING,
STATE_BOUND,
STATE_CONNECTING,
STATE_CONNECTED
};
AsyncPacketSocket() { }
virtual ~AsyncPacketSocket() { }
// Returns current local address. Address may be set to NULL if the
// socket is not bound yet (GetState() returns STATE_BINDING).
virtual SocketAddress GetLocalAddress() const = 0;
// Returns remote address. Returns zeroes if this is not a client TCP socket.
virtual SocketAddress GetRemoteAddress() const = 0;
// Send a packet.
virtual int Send(const void *pv, size_t cb, const PacketOptions& options) = 0;
virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr,
const PacketOptions& options) = 0;
// Close the socket.
virtual int Close() = 0;
// Returns current state of the socket.
virtual State GetState() const = 0;
// Get/set options.
virtual int GetOption(Socket::Option opt, int* value) = 0;
virtual int SetOption(Socket::Option opt, int value) = 0;
// Get/Set current error.
// TODO: Remove SetError().
virtual int GetError() const = 0;
virtual void SetError(int error) = 0;
// Emitted each time a packet is read. Used only for UDP and
// connected TCP sockets.
sigslot::signal5<AsyncPacketSocket*, const char*, size_t,
const SocketAddress&,
const PacketTime&> SignalReadPacket;
// Emitted when the socket is currently able to send.
sigslot::signal1<AsyncPacketSocket*> SignalReadyToSend;
// Emitted after address for the socket is allocated, i.e. binding
// is finished. State of the socket is changed from BINDING to BOUND
// (for UDP and server TCP sockets) or CONNECTING (for client TCP
// sockets).
sigslot::signal2<AsyncPacketSocket*, const SocketAddress&> SignalAddressReady;
// Emitted for client TCP sockets when state is changed from
// CONNECTING to CONNECTED.
sigslot::signal1<AsyncPacketSocket*> SignalConnect;
// Emitted for client TCP sockets when state is changed from
// CONNECTED to CLOSED.
sigslot::signal2<AsyncPacketSocket*, int> SignalClose;
// Used only for listening TCP sockets.
sigslot::signal2<AsyncPacketSocket*, AsyncPacketSocket*> SignalNewConnection;
private:
DISALLOW_EVIL_CONSTRUCTORS(AsyncPacketSocket);
};
} // namespace rtc
#endif // WEBRTC_BASE_ASYNCPACKETSOCKET_H_

Просмотреть файл

@ -0,0 +1,47 @@
/*
* Copyright 2013 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCRESOLVERINTERFACE_H_
#define WEBRTC_BASE_ASYNCRESOLVERINTERFACE_H_
#include "webrtc/base/sigslot.h"
#include "webrtc/base/socketaddress.h"
namespace rtc {
// This interface defines the methods to resolve the address asynchronously.
class AsyncResolverInterface {
public:
AsyncResolverInterface() {}
virtual ~AsyncResolverInterface() {}
// Start address resolve process.
virtual void Start(const SocketAddress& addr) = 0;
// Returns top most resolved address of |family|
virtual bool GetResolvedAddress(int family, SocketAddress* addr) const = 0;
// Returns error from resolver.
virtual int GetError() const = 0;
// Delete the resolver.
virtual void Destroy(bool wait) = 0;
// Returns top most resolved IPv4 address if address is resolved successfully.
// Otherwise returns address set in SetAddress.
SocketAddress address() const {
SocketAddress addr;
GetResolvedAddress(AF_INET, &addr);
return addr;
}
// This signal is fired when address resolve process is completed.
sigslot::signal1<AsyncResolverInterface*> SignalDone;
};
} // namespace rtc
#endif

Просмотреть файл

@ -0,0 +1,44 @@
/*
* Copyright 2010 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/asyncsocket.h"
namespace rtc {
AsyncSocket::AsyncSocket() {
}
AsyncSocket::~AsyncSocket() {
}
AsyncSocketAdapter::AsyncSocketAdapter(AsyncSocket* socket) : socket_(NULL) {
Attach(socket);
}
AsyncSocketAdapter::~AsyncSocketAdapter() {
delete socket_;
}
void AsyncSocketAdapter::Attach(AsyncSocket* socket) {
ASSERT(!socket_);
socket_ = socket;
if (socket_) {
socket_->SignalConnectEvent.connect(this,
&AsyncSocketAdapter::OnConnectEvent);
socket_->SignalReadEvent.connect(this,
&AsyncSocketAdapter::OnReadEvent);
socket_->SignalWriteEvent.connect(this,
&AsyncSocketAdapter::OnWriteEvent);
socket_->SignalCloseEvent.connect(this,
&AsyncSocketAdapter::OnCloseEvent);
}
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,124 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCSOCKET_H_
#define WEBRTC_BASE_ASYNCSOCKET_H_
#include "webrtc/base/common.h"
#include "webrtc/base/sigslot.h"
#include "webrtc/base/socket.h"
namespace rtc {
// TODO: Remove Socket and rename AsyncSocket to Socket.
// Provides the ability to perform socket I/O asynchronously.
class AsyncSocket : public Socket {
public:
AsyncSocket();
virtual ~AsyncSocket();
virtual AsyncSocket* Accept(SocketAddress* paddr) = 0;
// SignalReadEvent and SignalWriteEvent use multi_threaded_local to allow
// access concurrently from different thread.
// For example SignalReadEvent::connect will be called in AsyncUDPSocket ctor
// but at the same time the SocketDispatcher maybe signaling the read event.
// ready to read
sigslot::signal1<AsyncSocket*,
sigslot::multi_threaded_local> SignalReadEvent;
// ready to write
sigslot::signal1<AsyncSocket*,
sigslot::multi_threaded_local> SignalWriteEvent;
sigslot::signal1<AsyncSocket*> SignalConnectEvent; // connected
sigslot::signal2<AsyncSocket*, int> SignalCloseEvent; // closed
};
class AsyncSocketAdapter : public AsyncSocket, public sigslot::has_slots<> {
public:
// The adapted socket may explicitly be NULL, and later assigned using Attach.
// However, subclasses which support detached mode must override any methods
// that will be called during the detached period (usually GetState()), to
// avoid dereferencing a null pointer.
explicit AsyncSocketAdapter(AsyncSocket* socket);
virtual ~AsyncSocketAdapter();
void Attach(AsyncSocket* socket);
virtual SocketAddress GetLocalAddress() const {
return socket_->GetLocalAddress();
}
virtual SocketAddress GetRemoteAddress() const {
return socket_->GetRemoteAddress();
}
virtual int Bind(const SocketAddress& addr) {
return socket_->Bind(addr);
}
virtual int Connect(const SocketAddress& addr) {
return socket_->Connect(addr);
}
virtual int Send(const void* pv, size_t cb) {
return socket_->Send(pv, cb);
}
virtual int SendTo(const void* pv, size_t cb, const SocketAddress& addr) {
return socket_->SendTo(pv, cb, addr);
}
virtual int Recv(void* pv, size_t cb) {
return socket_->Recv(pv, cb);
}
virtual int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) {
return socket_->RecvFrom(pv, cb, paddr);
}
virtual int Listen(int backlog) {
return socket_->Listen(backlog);
}
virtual AsyncSocket* Accept(SocketAddress* paddr) {
return socket_->Accept(paddr);
}
virtual int Close() {
return socket_->Close();
}
virtual int GetError() const {
return socket_->GetError();
}
virtual void SetError(int error) {
return socket_->SetError(error);
}
virtual ConnState GetState() const {
return socket_->GetState();
}
virtual int EstimateMTU(uint16* mtu) {
return socket_->EstimateMTU(mtu);
}
virtual int GetOption(Option opt, int* value) {
return socket_->GetOption(opt, value);
}
virtual int SetOption(Option opt, int value) {
return socket_->SetOption(opt, value);
}
protected:
virtual void OnConnectEvent(AsyncSocket* socket) {
SignalConnectEvent(this);
}
virtual void OnReadEvent(AsyncSocket* socket) {
SignalReadEvent(this);
}
virtual void OnWriteEvent(AsyncSocket* socket) {
SignalWriteEvent(this);
}
virtual void OnCloseEvent(AsyncSocket* socket, int err) {
SignalCloseEvent(this, err);
}
AsyncSocket* socket_;
};
} // namespace rtc
#endif // WEBRTC_BASE_ASYNCSOCKET_H_

Просмотреть файл

@ -0,0 +1,299 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/asynctcpsocket.h"
#include <string.h>
#include "webrtc/base/byteorder.h"
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
#if defined(WEBRTC_POSIX)
#include <errno.h>
#endif // WEBRTC_POSIX
namespace rtc {
static const size_t kMaxPacketSize = 64 * 1024;
typedef uint16 PacketLength;
static const size_t kPacketLenSize = sizeof(PacketLength);
static const size_t kBufSize = kMaxPacketSize + kPacketLenSize;
static const int kListenBacklog = 5;
// Binds and connects |socket|
AsyncSocket* AsyncTCPSocketBase::ConnectSocket(
rtc::AsyncSocket* socket,
const rtc::SocketAddress& bind_address,
const rtc::SocketAddress& remote_address) {
rtc::scoped_ptr<rtc::AsyncSocket> owned_socket(socket);
if (socket->Bind(bind_address) < 0) {
LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
return NULL;
}
if (socket->Connect(remote_address) < 0) {
LOG(LS_ERROR) << "Connect() failed with error " << socket->GetError();
return NULL;
}
return owned_socket.release();
}
AsyncTCPSocketBase::AsyncTCPSocketBase(AsyncSocket* socket, bool listen,
size_t max_packet_size)
: socket_(socket),
listen_(listen),
insize_(max_packet_size),
inpos_(0),
outsize_(max_packet_size),
outpos_(0) {
inbuf_ = new char[insize_];
outbuf_ = new char[outsize_];
ASSERT(socket_.get() != NULL);
socket_->SignalConnectEvent.connect(
this, &AsyncTCPSocketBase::OnConnectEvent);
socket_->SignalReadEvent.connect(this, &AsyncTCPSocketBase::OnReadEvent);
socket_->SignalWriteEvent.connect(this, &AsyncTCPSocketBase::OnWriteEvent);
socket_->SignalCloseEvent.connect(this, &AsyncTCPSocketBase::OnCloseEvent);
if (listen_) {
if (socket_->Listen(kListenBacklog) < 0) {
LOG(LS_ERROR) << "Listen() failed with error " << socket_->GetError();
}
}
}
AsyncTCPSocketBase::~AsyncTCPSocketBase() {
delete [] inbuf_;
delete [] outbuf_;
}
SocketAddress AsyncTCPSocketBase::GetLocalAddress() const {
return socket_->GetLocalAddress();
}
SocketAddress AsyncTCPSocketBase::GetRemoteAddress() const {
return socket_->GetRemoteAddress();
}
int AsyncTCPSocketBase::Close() {
return socket_->Close();
}
AsyncTCPSocket::State AsyncTCPSocketBase::GetState() const {
switch (socket_->GetState()) {
case Socket::CS_CLOSED:
return STATE_CLOSED;
case Socket::CS_CONNECTING:
if (listen_) {
return STATE_BOUND;
} else {
return STATE_CONNECTING;
}
case Socket::CS_CONNECTED:
return STATE_CONNECTED;
default:
ASSERT(false);
return STATE_CLOSED;
}
}
int AsyncTCPSocketBase::GetOption(Socket::Option opt, int* value) {
return socket_->GetOption(opt, value);
}
int AsyncTCPSocketBase::SetOption(Socket::Option opt, int value) {
return socket_->SetOption(opt, value);
}
int AsyncTCPSocketBase::GetError() const {
return socket_->GetError();
}
void AsyncTCPSocketBase::SetError(int error) {
return socket_->SetError(error);
}
int AsyncTCPSocketBase::SendTo(const void *pv, size_t cb,
const SocketAddress& addr,
const rtc::PacketOptions& options) {
if (addr == GetRemoteAddress())
return Send(pv, cb, options);
ASSERT(false);
socket_->SetError(ENOTCONN);
return -1;
}
int AsyncTCPSocketBase::SendRaw(const void * pv, size_t cb) {
if (outpos_ + cb > outsize_) {
socket_->SetError(EMSGSIZE);
return -1;
}
memcpy(outbuf_ + outpos_, pv, cb);
outpos_ += cb;
return FlushOutBuffer();
}
int AsyncTCPSocketBase::FlushOutBuffer() {
int res = socket_->Send(outbuf_, outpos_);
if (res <= 0) {
return res;
}
if (static_cast<size_t>(res) <= outpos_) {
outpos_ -= res;
} else {
ASSERT(false);
return -1;
}
if (outpos_ > 0) {
memmove(outbuf_, outbuf_ + res, outpos_);
}
return res;
}
void AsyncTCPSocketBase::AppendToOutBuffer(const void* pv, size_t cb) {
ASSERT(outpos_ + cb < outsize_);
memcpy(outbuf_ + outpos_, pv, cb);
outpos_ += cb;
}
void AsyncTCPSocketBase::OnConnectEvent(AsyncSocket* socket) {
SignalConnect(this);
}
void AsyncTCPSocketBase::OnReadEvent(AsyncSocket* socket) {
ASSERT(socket_.get() == socket);
if (listen_) {
rtc::SocketAddress address;
rtc::AsyncSocket* new_socket = socket->Accept(&address);
if (!new_socket) {
// TODO: Do something better like forwarding the error
// to the user.
LOG(LS_ERROR) << "TCP accept failed with error " << socket_->GetError();
return;
}
HandleIncomingConnection(new_socket);
// Prime a read event in case data is waiting.
new_socket->SignalReadEvent(new_socket);
} else {
int len = socket_->Recv(inbuf_ + inpos_, insize_ - inpos_);
if (len < 0) {
// TODO: Do something better like forwarding the error to the user.
if (!socket_->IsBlocking()) {
LOG(LS_ERROR) << "Recv() returned error: " << socket_->GetError();
}
return;
}
inpos_ += len;
ProcessInput(inbuf_, &inpos_);
if (inpos_ >= insize_) {
LOG(LS_ERROR) << "input buffer overflow";
ASSERT(false);
inpos_ = 0;
}
}
}
void AsyncTCPSocketBase::OnWriteEvent(AsyncSocket* socket) {
ASSERT(socket_.get() == socket);
if (outpos_ > 0) {
FlushOutBuffer();
}
if (outpos_ == 0) {
SignalReadyToSend(this);
}
}
void AsyncTCPSocketBase::OnCloseEvent(AsyncSocket* socket, int error) {
SignalClose(this, error);
}
// AsyncTCPSocket
// Binds and connects |socket| and creates AsyncTCPSocket for
// it. Takes ownership of |socket|. Returns NULL if bind() or
// connect() fail (|socket| is destroyed in that case).
AsyncTCPSocket* AsyncTCPSocket::Create(
AsyncSocket* socket,
const SocketAddress& bind_address,
const SocketAddress& remote_address) {
return new AsyncTCPSocket(AsyncTCPSocketBase::ConnectSocket(
socket, bind_address, remote_address), false);
}
AsyncTCPSocket::AsyncTCPSocket(AsyncSocket* socket, bool listen)
: AsyncTCPSocketBase(socket, listen, kBufSize) {
}
int AsyncTCPSocket::Send(const void *pv, size_t cb,
const rtc::PacketOptions& options) {
if (cb > kBufSize) {
SetError(EMSGSIZE);
return -1;
}
// If we are blocking on send, then silently drop this packet
if (!IsOutBufferEmpty())
return static_cast<int>(cb);
PacketLength pkt_len = HostToNetwork16(static_cast<PacketLength>(cb));
AppendToOutBuffer(&pkt_len, kPacketLenSize);
AppendToOutBuffer(pv, cb);
int res = FlushOutBuffer();
if (res <= 0) {
// drop packet if we made no progress
ClearOutBuffer();
return res;
}
// We claim to have sent the whole thing, even if we only sent partial
return static_cast<int>(cb);
}
void AsyncTCPSocket::ProcessInput(char * data, size_t* len) {
SocketAddress remote_addr(GetRemoteAddress());
while (true) {
if (*len < kPacketLenSize)
return;
PacketLength pkt_len = rtc::GetBE16(data);
if (*len < kPacketLenSize + pkt_len)
return;
SignalReadPacket(this, data + kPacketLenSize, pkt_len, remote_addr,
CreatePacketTime(0));
*len -= kPacketLenSize + pkt_len;
if (*len > 0) {
memmove(data, data + kPacketLenSize + pkt_len, *len);
}
}
}
void AsyncTCPSocket::HandleIncomingConnection(AsyncSocket* socket) {
SignalNewConnection(this, new AsyncTCPSocket(socket, false));
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,100 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCTCPSOCKET_H_
#define WEBRTC_BASE_ASYNCTCPSOCKET_H_
#include "webrtc/base/asyncpacketsocket.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/socketfactory.h"
namespace rtc {
// Simulates UDP semantics over TCP. Send and Recv packet sizes
// are preserved, and drops packets silently on Send, rather than
// buffer them in user space.
class AsyncTCPSocketBase : public AsyncPacketSocket {
public:
AsyncTCPSocketBase(AsyncSocket* socket, bool listen, size_t max_packet_size);
virtual ~AsyncTCPSocketBase();
// Pure virtual methods to send and recv data.
virtual int Send(const void *pv, size_t cb,
const rtc::PacketOptions& options) = 0;
virtual void ProcessInput(char* data, size_t* len) = 0;
// Signals incoming connection.
virtual void HandleIncomingConnection(AsyncSocket* socket) = 0;
virtual SocketAddress GetLocalAddress() const;
virtual SocketAddress GetRemoteAddress() const;
virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr,
const rtc::PacketOptions& options);
virtual int Close();
virtual State GetState() const;
virtual int GetOption(Socket::Option opt, int* value);
virtual int SetOption(Socket::Option opt, int value);
virtual int GetError() const;
virtual void SetError(int error);
protected:
// Binds and connects |socket| and creates AsyncTCPSocket for
// it. Takes ownership of |socket|. Returns NULL if bind() or
// connect() fail (|socket| is destroyed in that case).
static AsyncSocket* ConnectSocket(AsyncSocket* socket,
const SocketAddress& bind_address,
const SocketAddress& remote_address);
virtual int SendRaw(const void* pv, size_t cb);
int FlushOutBuffer();
// Add data to |outbuf_|.
void AppendToOutBuffer(const void* pv, size_t cb);
// Helper methods for |outpos_|.
bool IsOutBufferEmpty() const { return outpos_ == 0; }
void ClearOutBuffer() { outpos_ = 0; }
private:
// Called by the underlying socket
void OnConnectEvent(AsyncSocket* socket);
void OnReadEvent(AsyncSocket* socket);
void OnWriteEvent(AsyncSocket* socket);
void OnCloseEvent(AsyncSocket* socket, int error);
scoped_ptr<AsyncSocket> socket_;
bool listen_;
char* inbuf_, * outbuf_;
size_t insize_, inpos_, outsize_, outpos_;
DISALLOW_EVIL_CONSTRUCTORS(AsyncTCPSocketBase);
};
class AsyncTCPSocket : public AsyncTCPSocketBase {
public:
// Binds and connects |socket| and creates AsyncTCPSocket for
// it. Takes ownership of |socket|. Returns NULL if bind() or
// connect() fail (|socket| is destroyed in that case).
static AsyncTCPSocket* Create(AsyncSocket* socket,
const SocketAddress& bind_address,
const SocketAddress& remote_address);
AsyncTCPSocket(AsyncSocket* socket, bool listen);
virtual ~AsyncTCPSocket() {}
virtual int Send(const void* pv, size_t cb,
const rtc::PacketOptions& options);
virtual void ProcessInput(char* data, size_t* len);
virtual void HandleIncomingConnection(AsyncSocket* socket);
private:
DISALLOW_EVIL_CONSTRUCTORS(AsyncTCPSocket);
};
} // namespace rtc
#endif // WEBRTC_BASE_ASYNCTCPSOCKET_H_

Просмотреть файл

@ -0,0 +1,53 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string>
#include "webrtc/base/asynctcpsocket.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/physicalsocketserver.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/virtualsocketserver.h"
namespace rtc {
class AsyncTCPSocketTest
: public testing::Test,
public sigslot::has_slots<> {
public:
AsyncTCPSocketTest()
: pss_(new rtc::PhysicalSocketServer),
vss_(new rtc::VirtualSocketServer(pss_.get())),
socket_(vss_->CreateAsyncSocket(SOCK_STREAM)),
tcp_socket_(new AsyncTCPSocket(socket_, true)),
ready_to_send_(false) {
tcp_socket_->SignalReadyToSend.connect(this,
&AsyncTCPSocketTest::OnReadyToSend);
}
void OnReadyToSend(rtc::AsyncPacketSocket* socket) {
ready_to_send_ = true;
}
protected:
scoped_ptr<PhysicalSocketServer> pss_;
scoped_ptr<VirtualSocketServer> vss_;
AsyncSocket* socket_;
scoped_ptr<AsyncTCPSocket> tcp_socket_;
bool ready_to_send_;
};
TEST_F(AsyncTCPSocketTest, OnWriteEvent) {
EXPECT_FALSE(ready_to_send_);
socket_->SignalWriteEvent(socket_);
EXPECT_TRUE(ready_to_send_);
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,122 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/asyncudpsocket.h"
#include "webrtc/base/logging.h"
namespace rtc {
static const int BUF_SIZE = 64 * 1024;
AsyncUDPSocket* AsyncUDPSocket::Create(
AsyncSocket* socket,
const SocketAddress& bind_address) {
scoped_ptr<AsyncSocket> owned_socket(socket);
if (socket->Bind(bind_address) < 0) {
LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
return NULL;
}
return new AsyncUDPSocket(owned_socket.release());
}
AsyncUDPSocket* AsyncUDPSocket::Create(SocketFactory* factory,
const SocketAddress& bind_address) {
AsyncSocket* socket =
factory->CreateAsyncSocket(bind_address.family(), SOCK_DGRAM);
if (!socket)
return NULL;
return Create(socket, bind_address);
}
AsyncUDPSocket::AsyncUDPSocket(AsyncSocket* socket)
: socket_(socket) {
ASSERT(socket_);
size_ = BUF_SIZE;
buf_ = new char[size_];
// The socket should start out readable but not writable.
socket_->SignalReadEvent.connect(this, &AsyncUDPSocket::OnReadEvent);
socket_->SignalWriteEvent.connect(this, &AsyncUDPSocket::OnWriteEvent);
}
AsyncUDPSocket::~AsyncUDPSocket() {
delete [] buf_;
}
SocketAddress AsyncUDPSocket::GetLocalAddress() const {
return socket_->GetLocalAddress();
}
SocketAddress AsyncUDPSocket::GetRemoteAddress() const {
return socket_->GetRemoteAddress();
}
int AsyncUDPSocket::Send(const void *pv, size_t cb,
const rtc::PacketOptions& options) {
return socket_->Send(pv, cb);
}
int AsyncUDPSocket::SendTo(const void *pv, size_t cb,
const SocketAddress& addr,
const rtc::PacketOptions& options) {
return socket_->SendTo(pv, cb, addr);
}
int AsyncUDPSocket::Close() {
return socket_->Close();
}
AsyncUDPSocket::State AsyncUDPSocket::GetState() const {
return STATE_BOUND;
}
int AsyncUDPSocket::GetOption(Socket::Option opt, int* value) {
return socket_->GetOption(opt, value);
}
int AsyncUDPSocket::SetOption(Socket::Option opt, int value) {
return socket_->SetOption(opt, value);
}
int AsyncUDPSocket::GetError() const {
return socket_->GetError();
}
void AsyncUDPSocket::SetError(int error) {
return socket_->SetError(error);
}
void AsyncUDPSocket::OnReadEvent(AsyncSocket* socket) {
ASSERT(socket_.get() == socket);
SocketAddress remote_addr;
int len = socket_->RecvFrom(buf_, size_, &remote_addr);
if (len < 0) {
// An error here typically means we got an ICMP error in response to our
// send datagram, indicating the remote address was unreachable.
// When doing ICE, this kind of thing will often happen.
// TODO: Do something better like forwarding the error to the user.
SocketAddress local_addr = socket_->GetLocalAddress();
LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString() << "] "
<< "receive failed with error " << socket_->GetError();
return;
}
// TODO: Make sure that we got all of the packet.
// If we did not, then we should resize our buffer to be large enough.
SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr,
CreatePacketTime(0));
}
void AsyncUDPSocket::OnWriteEvent(AsyncSocket* socket) {
SignalReadyToSend(this);
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,63 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ASYNCUDPSOCKET_H_
#define WEBRTC_BASE_ASYNCUDPSOCKET_H_
#include "webrtc/base/asyncpacketsocket.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/socketfactory.h"
namespace rtc {
// Provides the ability to receive packets asynchronously. Sends are not
// buffered since it is acceptable to drop packets under high load.
class AsyncUDPSocket : public AsyncPacketSocket {
public:
// Binds |socket| and creates AsyncUDPSocket for it. Takes ownership
// of |socket|. Returns NULL if bind() fails (|socket| is destroyed
// in that case).
static AsyncUDPSocket* Create(AsyncSocket* socket,
const SocketAddress& bind_address);
// Creates a new socket for sending asynchronous UDP packets using an
// asynchronous socket from the given factory.
static AsyncUDPSocket* Create(SocketFactory* factory,
const SocketAddress& bind_address);
explicit AsyncUDPSocket(AsyncSocket* socket);
virtual ~AsyncUDPSocket();
virtual SocketAddress GetLocalAddress() const;
virtual SocketAddress GetRemoteAddress() const;
virtual int Send(const void *pv, size_t cb,
const rtc::PacketOptions& options);
virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr,
const rtc::PacketOptions& options);
virtual int Close();
virtual State GetState() const;
virtual int GetOption(Socket::Option opt, int* value);
virtual int SetOption(Socket::Option opt, int value);
virtual int GetError() const;
virtual void SetError(int error);
private:
// Called when the underlying socket is ready to be read from.
void OnReadEvent(AsyncSocket* socket);
// Called when the underlying socket is ready to send.
void OnWriteEvent(AsyncSocket* socket);
scoped_ptr<AsyncSocket> socket_;
char* buf_;
size_t size_;
};
} // namespace rtc
#endif // WEBRTC_BASE_ASYNCUDPSOCKET_H_

Просмотреть файл

@ -0,0 +1,53 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string>
#include "webrtc/base/asyncudpsocket.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/physicalsocketserver.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/virtualsocketserver.h"
namespace rtc {
class AsyncUdpSocketTest
: public testing::Test,
public sigslot::has_slots<> {
public:
AsyncUdpSocketTest()
: pss_(new rtc::PhysicalSocketServer),
vss_(new rtc::VirtualSocketServer(pss_.get())),
socket_(vss_->CreateAsyncSocket(SOCK_DGRAM)),
udp_socket_(new AsyncUDPSocket(socket_)),
ready_to_send_(false) {
udp_socket_->SignalReadyToSend.connect(this,
&AsyncUdpSocketTest::OnReadyToSend);
}
void OnReadyToSend(rtc::AsyncPacketSocket* socket) {
ready_to_send_ = true;
}
protected:
scoped_ptr<PhysicalSocketServer> pss_;
scoped_ptr<VirtualSocketServer> vss_;
AsyncSocket* socket_;
scoped_ptr<AsyncUDPSocket> udp_socket_;
bool ready_to_send_;
};
TEST_F(AsyncUdpSocketTest, OnWriteEvent) {
EXPECT_FALSE(ready_to_send_);
socket_->SignalWriteEvent(socket_);
EXPECT_TRUE(ready_to_send_);
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,149 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ATOMICOPS_H_
#define WEBRTC_BASE_ATOMICOPS_H_
#include <string>
#include "webrtc/base/basictypes.h"
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
namespace rtc {
// A single-producer, single-consumer, fixed-size queue.
// All methods not ending in Unsafe can be safely called without locking,
// provided that calls to consumer methods (Peek/Pop) or producer methods (Push)
// only happen on a single thread per method type. If multiple threads need to
// read simultaneously or write simultaneously, other synchronization is
// necessary. Synchronization is also required if a call into any Unsafe method
// could happen at the same time as a call to any other method.
template <typename T>
class FixedSizeLockFreeQueue {
private:
// Atomic primitives and memory barrier
#if defined(__arm__)
typedef uint32 Atomic32;
// Copied from google3/base/atomicops-internals-arm-v6plus.h
static inline void MemoryBarrier() {
asm volatile("dmb":::"memory");
}
// Adapted from google3/base/atomicops-internals-arm-v6plus.h
static inline void AtomicIncrement(volatile Atomic32* ptr) {
Atomic32 str_success, value;
asm volatile (
"1:\n"
"ldrex %1, [%2]\n"
"add %1, %1, #1\n"
"strex %0, %1, [%2]\n"
"teq %0, #0\n"
"bne 1b"
: "=&r"(str_success), "=&r"(value)
: "r" (ptr)
: "cc", "memory");
}
#elif !defined(SKIP_ATOMIC_CHECK)
#error "No atomic operations defined for the given architecture."
#endif
public:
// Constructs an empty queue, with capacity 0.
FixedSizeLockFreeQueue() : pushed_count_(0),
popped_count_(0),
capacity_(0),
data_() {}
// Constructs an empty queue with the given capacity.
FixedSizeLockFreeQueue(size_t capacity) : pushed_count_(0),
popped_count_(0),
capacity_(capacity),
data_(new T[capacity]) {}
// Pushes a value onto the queue. Returns true if the value was successfully
// pushed (there was space in the queue). This method can be safely called at
// the same time as PeekFront/PopFront.
bool PushBack(T value) {
if (capacity_ == 0) {
LOG(LS_WARNING) << "Queue capacity is 0.";
return false;
}
if (IsFull()) {
return false;
}
data_[pushed_count_ % capacity_] = value;
// Make sure the data is written before the count is incremented, so other
// threads can't see the value exists before being able to read it.
MemoryBarrier();
AtomicIncrement(&pushed_count_);
return true;
}
// Retrieves the oldest value pushed onto the queue. Returns true if there was
// an item to peek (the queue was non-empty). This method can be safely called
// at the same time as PushBack.
bool PeekFront(T* value_out) {
if (capacity_ == 0) {
LOG(LS_WARNING) << "Queue capacity is 0.";
return false;
}
if (IsEmpty()) {
return false;
}
*value_out = data_[popped_count_ % capacity_];
return true;
}
// Retrieves the oldest value pushed onto the queue and removes it from the
// queue. Returns true if there was an item to pop (the queue was non-empty).
// This method can be safely called at the same time as PushBack.
bool PopFront(T* value_out) {
if (PeekFront(value_out)) {
AtomicIncrement(&popped_count_);
return true;
}
return false;
}
// Clears the current items in the queue and sets the new (fixed) size. This
// method cannot be called at the same time as any other method.
void ClearAndResizeUnsafe(int new_capacity) {
capacity_ = new_capacity;
data_.reset(new T[new_capacity]);
pushed_count_ = 0;
popped_count_ = 0;
}
// Returns true if there is no space left in the queue for new elements.
int IsFull() const { return pushed_count_ == popped_count_ + capacity_; }
// Returns true if there are no elements in the queue.
int IsEmpty() const { return pushed_count_ == popped_count_; }
// Returns the current number of elements in the queue. This is always in the
// range [0, capacity]
size_t Size() const { return pushed_count_ - popped_count_; }
// Returns the capacity of the queue (max size).
size_t capacity() const { return capacity_; }
private:
volatile Atomic32 pushed_count_;
volatile Atomic32 popped_count_;
size_t capacity_;
rtc::scoped_ptr<T[]> data_;
DISALLOW_COPY_AND_ASSIGN(FixedSizeLockFreeQueue);
};
}
#endif // WEBRTC_BASE_ATOMICOPS_H_

Просмотреть файл

@ -0,0 +1,79 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#if !defined(__arm__)
// For testing purposes, define faked versions of the atomic operations
#include "webrtc/base/basictypes.h"
namespace rtc {
typedef uint32 Atomic32;
static inline void MemoryBarrier() { }
static inline void AtomicIncrement(volatile Atomic32* ptr) {
*ptr = *ptr + 1;
}
}
#define SKIP_ATOMIC_CHECK
#endif
#include "webrtc/base/atomicops.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
TEST(FixedSizeLockFreeQueueTest, TestDefaultConstruct) {
rtc::FixedSizeLockFreeQueue<int> queue;
EXPECT_EQ(0u, queue.capacity());
EXPECT_EQ(0u, queue.Size());
EXPECT_FALSE(queue.PushBack(1));
int val;
EXPECT_FALSE(queue.PopFront(&val));
}
TEST(FixedSizeLockFreeQueueTest, TestConstruct) {
rtc::FixedSizeLockFreeQueue<int> queue(5);
EXPECT_EQ(5u, queue.capacity());
EXPECT_EQ(0u, queue.Size());
int val;
EXPECT_FALSE(queue.PopFront(&val));
}
TEST(FixedSizeLockFreeQueueTest, TestPushPop) {
rtc::FixedSizeLockFreeQueue<int> queue(2);
EXPECT_EQ(2u, queue.capacity());
EXPECT_EQ(0u, queue.Size());
EXPECT_TRUE(queue.PushBack(1));
EXPECT_EQ(1u, queue.Size());
EXPECT_TRUE(queue.PushBack(2));
EXPECT_EQ(2u, queue.Size());
EXPECT_FALSE(queue.PushBack(3));
EXPECT_EQ(2u, queue.Size());
int val;
EXPECT_TRUE(queue.PopFront(&val));
EXPECT_EQ(1, val);
EXPECT_EQ(1u, queue.Size());
EXPECT_TRUE(queue.PopFront(&val));
EXPECT_EQ(2, val);
EXPECT_EQ(0u, queue.Size());
EXPECT_FALSE(queue.PopFront(&val));
EXPECT_EQ(0u, queue.Size());
}
TEST(FixedSizeLockFreeQueueTest, TestResize) {
rtc::FixedSizeLockFreeQueue<int> queue(2);
EXPECT_EQ(2u, queue.capacity());
EXPECT_EQ(0u, queue.Size());
EXPECT_TRUE(queue.PushBack(1));
EXPECT_EQ(1u, queue.Size());
queue.ClearAndResizeUnsafe(5);
EXPECT_EQ(5u, queue.capacity());
EXPECT_EQ(0u, queue.Size());
int val;
EXPECT_FALSE(queue.PopFront(&val));
}

Просмотреть файл

@ -0,0 +1,282 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/autodetectproxy.h"
#include "webrtc/base/httpcommon.h"
#include "webrtc/base/httpcommon-inl.h"
#include "webrtc/base/nethelpers.h"
namespace rtc {
static const ProxyType TEST_ORDER[] = {
PROXY_HTTPS, PROXY_SOCKS5, PROXY_UNKNOWN
};
static const int kSavedStringLimit = 128;
static void SaveStringToStack(char *dst,
const std::string &src,
size_t dst_size) {
strncpy(dst, src.c_str(), dst_size - 1);
dst[dst_size - 1] = '\0';
}
AutoDetectProxy::AutoDetectProxy(const std::string& user_agent)
: agent_(user_agent), resolver_(NULL), socket_(NULL), next_(0) {
}
AutoDetectProxy::~AutoDetectProxy() {
if (resolver_) {
resolver_->Destroy(false);
}
}
void AutoDetectProxy::DoWork() {
// TODO: Try connecting to server_url without proxy first here?
if (!server_url_.empty()) {
LOG(LS_INFO) << "GetProxySettingsForUrl(" << server_url_ << ") - start";
GetProxyForUrl(agent_.c_str(), server_url_.c_str(), &proxy_);
LOG(LS_INFO) << "GetProxySettingsForUrl - stop";
}
Url<char> url(proxy_.address.HostAsURIString());
if (url.valid()) {
LOG(LS_WARNING) << "AutoDetectProxy removing http prefix on proxy host";
proxy_.address.SetIP(url.host());
}
LOG(LS_INFO) << "AutoDetectProxy found proxy at " << proxy_.address;
if (proxy_.type == PROXY_UNKNOWN) {
LOG(LS_INFO) << "AutoDetectProxy initiating proxy classification";
Next();
// Process I/O until Stop()
Thread::Current()->ProcessMessages(kForever);
// Clean up the autodetect socket, from the thread that created it
delete socket_;
}
// TODO: If we found a proxy, try to use it to verify that it
// works by sending a request to server_url. This could either be
// done here or by the HttpPortAllocator.
}
void AutoDetectProxy::OnMessage(Message *msg) {
if (MSG_UNRESOLVABLE == msg->message_id) {
// If we can't resolve the proxy, skip straight to failure.
Complete(PROXY_UNKNOWN);
} else if (MSG_TIMEOUT == msg->message_id) {
OnCloseEvent(socket_, ETIMEDOUT);
} else {
// This must be the ST_MSG_WORKER_DONE message that deletes the
// AutoDetectProxy object. We have observed crashes within this stack that
// seem to be highly reproducible for a small subset of users and thus are
// probably correlated with a specific proxy setting, so copy potentially
// relevant information onto the stack to make it available in Windows
// minidumps.
// Save the user agent and the number of auto-detection passes that we
// needed.
char agent[kSavedStringLimit];
SaveStringToStack(agent, agent_, sizeof agent);
int next = next_;
// Now the detected proxy config (minus the password field, which could be
// sensitive).
ProxyType type = proxy().type;
char address_hostname[kSavedStringLimit];
SaveStringToStack(address_hostname,
proxy().address.hostname(),
sizeof address_hostname);
IPAddress address_ip = proxy().address.ipaddr();
uint16 address_port = proxy().address.port();
char autoconfig_url[kSavedStringLimit];
SaveStringToStack(autoconfig_url,
proxy().autoconfig_url,
sizeof autoconfig_url);
bool autodetect = proxy().autodetect;
char bypass_list[kSavedStringLimit];
SaveStringToStack(bypass_list, proxy().bypass_list, sizeof bypass_list);
char username[kSavedStringLimit];
SaveStringToStack(username, proxy().username, sizeof username);
SignalThread::OnMessage(msg);
// Log the gathered data at a log level that will never actually be enabled
// so that the compiler is forced to retain the data on the stack.
LOG(LS_SENSITIVE) << agent << " " << next << " " << type << " "
<< address_hostname << " " << address_ip << " "
<< address_port << " " << autoconfig_url << " "
<< autodetect << " " << bypass_list << " " << username;
}
}
void AutoDetectProxy::OnResolveResult(AsyncResolverInterface* resolver) {
if (resolver != resolver_) {
return;
}
int error = resolver_->GetError();
if (error == 0) {
LOG(LS_VERBOSE) << "Resolved " << proxy_.address << " to "
<< resolver_->address();
proxy_.address = resolver_->address();
if (!DoConnect()) {
Thread::Current()->Post(this, MSG_TIMEOUT);
}
} else {
LOG(LS_INFO) << "Failed to resolve " << resolver_->address();
resolver_->Destroy(false);
resolver_ = NULL;
proxy_.address = SocketAddress();
Thread::Current()->Post(this, MSG_UNRESOLVABLE);
}
}
void AutoDetectProxy::Next() {
if (TEST_ORDER[next_] >= PROXY_UNKNOWN) {
Complete(PROXY_UNKNOWN);
return;
}
LOG(LS_VERBOSE) << "AutoDetectProxy connecting to "
<< proxy_.address.ToSensitiveString();
if (socket_) {
Thread::Current()->Clear(this, MSG_TIMEOUT);
Thread::Current()->Clear(this, MSG_UNRESOLVABLE);
socket_->Close();
Thread::Current()->Dispose(socket_);
socket_ = NULL;
}
int timeout = 2000;
if (proxy_.address.IsUnresolvedIP()) {
// Launch an asyncresolver. This thread will spin waiting for it.
timeout += 2000;
if (!resolver_) {
resolver_ = new AsyncResolver();
}
resolver_->SignalDone.connect(this, &AutoDetectProxy::OnResolveResult);
resolver_->Start(proxy_.address);
} else {
if (!DoConnect()) {
Thread::Current()->Post(this, MSG_TIMEOUT);
return;
}
}
Thread::Current()->PostDelayed(timeout, this, MSG_TIMEOUT);
}
bool AutoDetectProxy::DoConnect() {
if (resolver_) {
resolver_->Destroy(false);
resolver_ = NULL;
}
socket_ =
Thread::Current()->socketserver()->CreateAsyncSocket(
proxy_.address.family(), SOCK_STREAM);
if (!socket_) {
LOG(LS_VERBOSE) << "Unable to create socket for " << proxy_.address;
return false;
}
socket_->SignalConnectEvent.connect(this, &AutoDetectProxy::OnConnectEvent);
socket_->SignalReadEvent.connect(this, &AutoDetectProxy::OnReadEvent);
socket_->SignalCloseEvent.connect(this, &AutoDetectProxy::OnCloseEvent);
socket_->Connect(proxy_.address);
return true;
}
void AutoDetectProxy::Complete(ProxyType type) {
Thread::Current()->Clear(this, MSG_TIMEOUT);
Thread::Current()->Clear(this, MSG_UNRESOLVABLE);
if (socket_) {
socket_->Close();
}
proxy_.type = type;
LoggingSeverity sev = (proxy_.type == PROXY_UNKNOWN) ? LS_ERROR : LS_INFO;
LOG_V(sev) << "AutoDetectProxy detected "
<< proxy_.address.ToSensitiveString()
<< " as type " << proxy_.type;
Thread::Current()->Quit();
}
void AutoDetectProxy::OnConnectEvent(AsyncSocket * socket) {
std::string probe;
switch (TEST_ORDER[next_]) {
case PROXY_HTTPS:
probe.assign("CONNECT www.google.com:443 HTTP/1.0\r\n"
"User-Agent: ");
probe.append(agent_);
probe.append("\r\n"
"Host: www.google.com\r\n"
"Content-Length: 0\r\n"
"Proxy-Connection: Keep-Alive\r\n"
"\r\n");
break;
case PROXY_SOCKS5:
probe.assign("\005\001\000", 3);
break;
default:
ASSERT(false);
return;
}
LOG(LS_VERBOSE) << "AutoDetectProxy probing type " << TEST_ORDER[next_]
<< " sending " << probe.size() << " bytes";
socket_->Send(probe.data(), probe.size());
}
void AutoDetectProxy::OnReadEvent(AsyncSocket * socket) {
char data[257];
int len = socket_->Recv(data, 256);
if (len > 0) {
data[len] = 0;
LOG(LS_VERBOSE) << "AutoDetectProxy read " << len << " bytes";
}
switch (TEST_ORDER[next_]) {
case PROXY_HTTPS:
if ((len >= 2) && (data[0] == '\x05')) {
Complete(PROXY_SOCKS5);
return;
}
if ((len >= 5) && (strncmp(data, "HTTP/", 5) == 0)) {
Complete(PROXY_HTTPS);
return;
}
break;
case PROXY_SOCKS5:
if ((len >= 2) && (data[0] == '\x05')) {
Complete(PROXY_SOCKS5);
return;
}
break;
default:
ASSERT(false);
return;
}
++next_;
Next();
}
void AutoDetectProxy::OnCloseEvent(AsyncSocket * socket, int error) {
LOG(LS_VERBOSE) << "AutoDetectProxy closed with error: " << error;
++next_;
Next();
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,90 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_AUTODETECTPROXY_H_
#define WEBRTC_BASE_AUTODETECTPROXY_H_
#include <string>
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/cryptstring.h"
#include "webrtc/base/proxydetect.h"
#include "webrtc/base/proxyinfo.h"
#include "webrtc/base/signalthread.h"
namespace rtc {
///////////////////////////////////////////////////////////////////////////////
// AutoDetectProxy
///////////////////////////////////////////////////////////////////////////////
class AsyncResolverInterface;
class AsyncSocket;
class AutoDetectProxy : public SignalThread {
public:
explicit AutoDetectProxy(const std::string& user_agent);
const ProxyInfo& proxy() const { return proxy_; }
void set_server_url(const std::string& url) {
server_url_ = url;
}
void set_proxy(const SocketAddress& proxy) {
proxy_.type = PROXY_UNKNOWN;
proxy_.address = proxy;
}
void set_auth_info(bool use_auth, const std::string& username,
const CryptString& password) {
if (use_auth) {
proxy_.username = username;
proxy_.password = password;
}
}
// Default implementation of GetProxySettingsForUrl. Override for special
// implementation.
virtual bool GetProxyForUrl(const char* agent, const char* url,
rtc::ProxyInfo* proxy) {
return GetProxySettingsForUrl(agent, url, proxy, true);
}
enum { MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE,
MSG_UNRESOLVABLE,
ADP_MSG_FIRST_AVAILABLE};
protected:
virtual ~AutoDetectProxy();
// SignalThread Interface
virtual void DoWork();
virtual void OnMessage(Message *msg);
void Next();
void Complete(ProxyType type);
void OnConnectEvent(AsyncSocket * socket);
void OnReadEvent(AsyncSocket * socket);
void OnCloseEvent(AsyncSocket * socket, int error);
void OnResolveResult(AsyncResolverInterface* resolver);
bool DoConnect();
private:
std::string agent_;
std::string server_url_;
ProxyInfo proxy_;
AsyncResolverInterface* resolver_;
AsyncSocket* socket_;
int next_;
DISALLOW_IMPLICIT_CONSTRUCTORS(AutoDetectProxy);
};
} // namespace rtc
#endif // WEBRTC_BASE_AUTODETECTPROXY_H_

Просмотреть файл

@ -0,0 +1,132 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/autodetectproxy.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/httpcommon.h"
#include "webrtc/base/httpcommon-inl.h"
#include "webrtc/test/testsupport/gtest_disable.h"
namespace rtc {
static const char kUserAgent[] = "";
static const char kPath[] = "/";
static const char kHost[] = "relay.google.com";
static const uint16 kPort = 443;
static const bool kSecure = true;
// At most, AutoDetectProxy should take ~6 seconds. Each connect step is
// allotted 2 seconds, with the initial resolution + connect given an
// extra 2 seconds. The slowest case is:
// 1) Resolution + HTTPS takes full 4 seconds and fails (but resolution
// succeeds).
// 2) SOCKS5 takes the full 2 seconds.
// Socket creation time seems unbounded, and has been observed to take >1 second
// on a linux machine under load. As such, we allow for 10 seconds for timeout,
// though could still end up with some flakiness.
static const int kTimeoutMs = 10000;
class AutoDetectProxyTest : public testing::Test, public sigslot::has_slots<> {
public:
AutoDetectProxyTest() : auto_detect_proxy_(NULL), done_(false) {}
protected:
bool Create(const std::string &user_agent,
const std::string &path,
const std::string &host,
uint16 port,
bool secure,
bool startnow) {
auto_detect_proxy_ = new AutoDetectProxy(user_agent);
EXPECT_TRUE(auto_detect_proxy_ != NULL);
if (!auto_detect_proxy_) {
return false;
}
Url<char> host_url(path, host, port);
host_url.set_secure(secure);
auto_detect_proxy_->set_server_url(host_url.url());
auto_detect_proxy_->SignalWorkDone.connect(
this,
&AutoDetectProxyTest::OnWorkDone);
if (startnow) {
auto_detect_proxy_->Start();
}
return true;
}
bool Run(int timeout_ms) {
EXPECT_TRUE_WAIT(done_, timeout_ms);
return done_;
}
void SetProxy(const SocketAddress& proxy) {
auto_detect_proxy_->set_proxy(proxy);
}
void Start() {
auto_detect_proxy_->Start();
}
void TestCopesWithProxy(const SocketAddress& proxy) {
// Tests that at least autodetect doesn't crash for a given proxy address.
ASSERT_TRUE(Create(kUserAgent,
kPath,
kHost,
kPort,
kSecure,
false));
SetProxy(proxy);
Start();
ASSERT_TRUE(Run(kTimeoutMs));
}
private:
void OnWorkDone(rtc::SignalThread *thread) {
AutoDetectProxy *auto_detect_proxy =
static_cast<rtc::AutoDetectProxy *>(thread);
EXPECT_TRUE(auto_detect_proxy == auto_detect_proxy_);
auto_detect_proxy_ = NULL;
auto_detect_proxy->Release();
done_ = true;
}
AutoDetectProxy *auto_detect_proxy_;
bool done_;
};
TEST_F(AutoDetectProxyTest, TestDetectUnresolvedProxy) {
TestCopesWithProxy(rtc::SocketAddress("localhost", 9999));
}
TEST_F(AutoDetectProxyTest, TestDetectUnresolvableProxy) {
TestCopesWithProxy(rtc::SocketAddress("invalid", 9999));
}
TEST_F(AutoDetectProxyTest, TestDetectIPv6Proxy) {
TestCopesWithProxy(rtc::SocketAddress("::1", 9999));
}
TEST_F(AutoDetectProxyTest, TestDetectIPv4Proxy) {
TestCopesWithProxy(rtc::SocketAddress("127.0.0.1", 9999));
}
// Test that proxy detection completes successfully. (Does not actually verify
// the correct detection result since we don't know what proxy to expect on an
// arbitrary machine.)
TEST_F(AutoDetectProxyTest, TestProxyDetection) {
ASSERT_TRUE(Create(kUserAgent,
kPath,
kHost,
kPort,
kSecure,
true));
ASSERT_TRUE(Run(kTimeoutMs));
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,84 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/bandwidthsmoother.h"
#include <limits.h>
namespace rtc {
BandwidthSmoother::BandwidthSmoother(int initial_bandwidth_guess,
uint32 time_between_increase,
double percent_increase,
size_t samples_count_to_average,
double min_sample_count_percent)
: time_between_increase_(time_between_increase),
percent_increase_(rtc::_max(1.0, percent_increase)),
time_at_last_change_(0),
bandwidth_estimation_(initial_bandwidth_guess),
accumulator_(samples_count_to_average),
min_sample_count_percent_(
rtc::_min(1.0,
rtc::_max(0.0, min_sample_count_percent))) {
}
// Samples a new bandwidth measurement
// returns true if the bandwidth estimation changed
bool BandwidthSmoother::Sample(uint32 sample_time, int bandwidth) {
if (bandwidth < 0) {
return false;
}
accumulator_.AddSample(bandwidth);
if (accumulator_.count() < static_cast<size_t>(
accumulator_.max_count() * min_sample_count_percent_)) {
// We have not collected enough samples yet.
return false;
}
// Replace bandwidth with the mean of sampled bandwidths.
const int mean_bandwidth = static_cast<int>(accumulator_.ComputeMean());
if (mean_bandwidth < bandwidth_estimation_) {
time_at_last_change_ = sample_time;
bandwidth_estimation_ = mean_bandwidth;
return true;
}
const int old_bandwidth_estimation = bandwidth_estimation_;
const double increase_threshold_d = percent_increase_ * bandwidth_estimation_;
if (increase_threshold_d > INT_MAX) {
// If bandwidth goes any higher we would overflow.
return false;
}
const int increase_threshold = static_cast<int>(increase_threshold_d);
if (mean_bandwidth < increase_threshold) {
time_at_last_change_ = sample_time;
// The value of bandwidth_estimation remains the same if we don't exceed
// percent_increase_ * bandwidth_estimation_ for at least
// time_between_increase_ time.
} else if (sample_time >= time_at_last_change_ + time_between_increase_) {
time_at_last_change_ = sample_time;
if (increase_threshold == 0) {
// Bandwidth_estimation_ must be zero. Assume a jump from zero to a
// positive bandwidth means we have regained connectivity.
bandwidth_estimation_ = mean_bandwidth;
} else {
bandwidth_estimation_ = increase_threshold;
}
}
// Else don't make a change.
return old_bandwidth_estimation != bandwidth_estimation_;
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,59 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_BANDWIDTHSMOOTHER_H_
#define WEBRTC_BASE_BANDWIDTHSMOOTHER_H_
#include "webrtc/base/rollingaccumulator.h"
#include "webrtc/base/timeutils.h"
namespace rtc {
// The purpose of BandwidthSmoother is to smooth out bandwidth
// estimations so that 'trstate' messages can be triggered when we
// are "sure" there is sufficient bandwidth. To avoid frequent fluctuations,
// we take a slightly pessimistic view of our bandwidth. We only increase
// our estimation when we have sampled bandwidth measurements of values
// at least as large as the current estimation * percent_increase
// for at least time_between_increase time. If a sampled bandwidth
// is less than our current estimation we immediately decrease our estimation
// to that sampled value.
// We retain the initial bandwidth guess as our current bandwidth estimation
// until we have received (min_sample_count_percent * samples_count_to_average)
// number of samples. Min_sample_count_percent must be in range [0, 1].
class BandwidthSmoother {
public:
BandwidthSmoother(int initial_bandwidth_guess,
uint32 time_between_increase,
double percent_increase,
size_t samples_count_to_average,
double min_sample_count_percent);
// Samples a new bandwidth measurement.
// bandwidth is expected to be non-negative.
// returns true if the bandwidth estimation changed
bool Sample(uint32 sample_time, int bandwidth);
int get_bandwidth_estimation() const {
return bandwidth_estimation_;
}
private:
uint32 time_between_increase_;
double percent_increase_;
uint32 time_at_last_change_;
int bandwidth_estimation_;
RollingAccumulator<int> accumulator_;
double min_sample_count_percent_;
};
} // namespace rtc
#endif // WEBRTC_BASE_BANDWIDTHSMOOTHER_H_

Просмотреть файл

@ -0,0 +1,116 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <limits.h>
#include "webrtc/base/bandwidthsmoother.h"
#include "webrtc/base/gunit.h"
namespace rtc {
static const int kTimeBetweenIncrease = 10;
static const double kPercentIncrease = 1.1;
static const size_t kSamplesCountToAverage = 2;
static const double kMinSampleCountPercent = 1.0;
TEST(BandwidthSmootherTest, TestSampleIncrease) {
BandwidthSmoother mon(1000, // initial_bandwidth_guess
kTimeBetweenIncrease,
kPercentIncrease,
kSamplesCountToAverage,
kMinSampleCountPercent);
int bandwidth_sample = 1000;
EXPECT_EQ(bandwidth_sample, mon.get_bandwidth_estimation());
bandwidth_sample =
static_cast<int>(bandwidth_sample * kPercentIncrease);
EXPECT_FALSE(mon.Sample(9, bandwidth_sample));
EXPECT_TRUE(mon.Sample(10, bandwidth_sample));
EXPECT_EQ(bandwidth_sample, mon.get_bandwidth_estimation());
int next_expected_est =
static_cast<int>(bandwidth_sample * kPercentIncrease);
bandwidth_sample *= 2;
EXPECT_TRUE(mon.Sample(20, bandwidth_sample));
EXPECT_EQ(next_expected_est, mon.get_bandwidth_estimation());
}
TEST(BandwidthSmootherTest, TestSampleIncreaseFromZero) {
BandwidthSmoother mon(0, // initial_bandwidth_guess
kTimeBetweenIncrease,
kPercentIncrease,
kSamplesCountToAverage,
kMinSampleCountPercent);
const int kBandwidthSample = 1000;
EXPECT_EQ(0, mon.get_bandwidth_estimation());
EXPECT_FALSE(mon.Sample(9, kBandwidthSample));
EXPECT_TRUE(mon.Sample(10, kBandwidthSample));
EXPECT_EQ(kBandwidthSample, mon.get_bandwidth_estimation());
}
TEST(BandwidthSmootherTest, TestSampleDecrease) {
BandwidthSmoother mon(1000, // initial_bandwidth_guess
kTimeBetweenIncrease,
kPercentIncrease,
kSamplesCountToAverage,
kMinSampleCountPercent);
const int kBandwidthSample = 999;
EXPECT_EQ(1000, mon.get_bandwidth_estimation());
EXPECT_FALSE(mon.Sample(1, kBandwidthSample));
EXPECT_EQ(1000, mon.get_bandwidth_estimation());
EXPECT_TRUE(mon.Sample(2, kBandwidthSample));
EXPECT_EQ(kBandwidthSample, mon.get_bandwidth_estimation());
}
TEST(BandwidthSmootherTest, TestSampleTooFewSamples) {
BandwidthSmoother mon(1000, // initial_bandwidth_guess
kTimeBetweenIncrease,
kPercentIncrease,
10, // 10 samples.
0.5); // 5 min samples.
const int kBandwidthSample = 500;
EXPECT_EQ(1000, mon.get_bandwidth_estimation());
EXPECT_FALSE(mon.Sample(1, kBandwidthSample));
EXPECT_FALSE(mon.Sample(2, kBandwidthSample));
EXPECT_FALSE(mon.Sample(3, kBandwidthSample));
EXPECT_FALSE(mon.Sample(4, kBandwidthSample));
EXPECT_EQ(1000, mon.get_bandwidth_estimation());
EXPECT_TRUE(mon.Sample(5, kBandwidthSample));
EXPECT_EQ(kBandwidthSample, mon.get_bandwidth_estimation());
}
TEST(BandwidthSmootherTest, TestSampleRollover) {
const int kHugeBandwidth = 2000000000; // > INT_MAX/1.1
BandwidthSmoother mon(kHugeBandwidth,
kTimeBetweenIncrease,
kPercentIncrease,
kSamplesCountToAverage,
kMinSampleCountPercent);
EXPECT_FALSE(mon.Sample(10, INT_MAX));
EXPECT_FALSE(mon.Sample(11, INT_MAX));
EXPECT_EQ(kHugeBandwidth, mon.get_bandwidth_estimation());
}
TEST(BandwidthSmootherTest, TestSampleNegative) {
BandwidthSmoother mon(1000, // initial_bandwidth_guess
kTimeBetweenIncrease,
kPercentIncrease,
kSamplesCountToAverage,
kMinSampleCountPercent);
EXPECT_FALSE(mon.Sample(10, -1));
EXPECT_FALSE(mon.Sample(11, -1));
EXPECT_EQ(1000, mon.get_bandwidth_estimation());
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,733 @@
# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
{
'includes': [ '../build/common.gypi', ],
'conditions': [
['os_posix == 1 and OS != "mac" and OS != "ios"', {
'conditions': [
['sysroot!=""', {
'variables': {
'pkg-config': '../../../build/linux/pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
},
}, {
'variables': {
'pkg-config': 'pkg-config'
},
}],
],
}],
],
'targets': [
{
# Temporary target until Chromium's
# src/third_party/libjingle/libjingle.gyp is updated to use rtc_base.
# TODO(kjellander): Remove when r7140 is rolled into Chromium's DEPS.
'target_name': 'webrtc_base',
'type': 'none',
'dependencies': [
'rtc_base',
],
},
{
# The subset of rtc_base approved for use outside of libjingle.
'target_name': 'rtc_base_approved',
'type': 'static_library',
'sources': [
'checks.cc',
'checks.h',
'exp_filter.cc',
'exp_filter.h',
'md5.cc',
'md5.h',
'md5digest.h',
'platform_file.cc',
'platform_file.h',
'stringencode.cc',
'stringencode.h',
'stringutils.cc',
'stringutils.h',
'thread_annotations.h',
'timeutils.cc',
'timeutils.h',
],
},
{
'target_name': 'rtc_base',
'type': 'static_library',
'dependencies': [
'rtc_base_approved',
],
'defines': [
'FEATURE_ENABLE_SSL',
'LOGGING=1',
'USE_WEBRTC_DEV_BRANCH',
],
'sources': [
'asyncfile.cc',
'asyncfile.h',
'asynchttprequest.cc',
'asynchttprequest.h',
'asyncinvoker.cc',
'asyncinvoker.h',
'asyncinvoker-inl.h',
'asyncpacketsocket.h',
'asyncresolverinterface.h',
'asyncsocket.cc',
'asyncsocket.h',
'asynctcpsocket.cc',
'asynctcpsocket.h',
'asyncudpsocket.cc',
'asyncudpsocket.h',
'atomicops.h',
'autodetectproxy.cc',
'autodetectproxy.h',
'bandwidthsmoother.cc',
'bandwidthsmoother.h',
'base64.cc',
'base64.h',
'basicdefs.h',
'basictypes.h',
'bind.h',
'bind.h.pump',
'buffer.h',
'bytebuffer.cc',
'bytebuffer.h',
'byteorder.h',
'callback.h',
'callback.h.pump',
'constructormagic.h',
'common.cc',
'common.h',
'cpumonitor.cc',
'cpumonitor.h',
'crc32.cc',
'crc32.h',
'criticalsection.h',
'cryptstring.h',
'dbus.cc',
'dbus.h',
'diskcache.cc',
'diskcache.h',
'diskcache_win32.cc',
'diskcache_win32.h',
'event.cc',
'event.h',
'filelock.cc',
'filelock.h',
'fileutils.cc',
'fileutils.h',
'fileutils_mock.h',
'firewallsocketserver.cc',
'firewallsocketserver.h',
'flags.cc',
'flags.h',
'gunit_prod.h',
'helpers.cc',
'helpers.h',
'httpbase.cc',
'httpbase.h',
'httpclient.cc',
'httpclient.h',
'httpcommon-inl.h',
'httpcommon.cc',
'httpcommon.h',
'httprequest.cc',
'httprequest.h',
'httpserver.cc',
'httpserver.h',
'ifaddrs-android.cc',
'ifaddrs-android.h',
'iosfilesystem.mm',
'ipaddress.cc',
'ipaddress.h',
'json.cc',
'json.h',
'latebindingsymboltable.cc',
'latebindingsymboltable.cc.def',
'latebindingsymboltable.h',
'latebindingsymboltable.h.def',
'libdbusglibsymboltable.cc',
'libdbusglibsymboltable.h',
'linux.cc',
'linux.h',
'linuxfdwalk.c',
'linuxfdwalk.h',
'linked_ptr.h',
'logging.cc',
'logging.h',
'macasyncsocket.cc',
'macasyncsocket.h',
'maccocoasocketserver.h',
'maccocoasocketserver.mm',
'maccocoathreadhelper.h',
'maccocoathreadhelper.mm',
'macconversion.cc',
'macconversion.h',
'macsocketserver.cc',
'macsocketserver.h',
'macutils.cc',
'macutils.h',
'macwindowpicker.cc',
'macwindowpicker.h',
'mathutils.h',
'messagedigest.cc',
'messagedigest.h',
'messagehandler.cc',
'messagehandler.h',
'messagequeue.cc',
'messagequeue.h',
'multipart.cc',
'multipart.h',
'natserver.cc',
'natserver.h',
'natsocketfactory.cc',
'natsocketfactory.h',
'nattypes.cc',
'nattypes.h',
'nethelpers.cc',
'nethelpers.h',
'network.cc',
'network.h',
'nullsocketserver.h',
'optionsfile.cc',
'optionsfile.h',
'pathutils.cc',
'pathutils.h',
'physicalsocketserver.cc',
'physicalsocketserver.h',
'posix.cc',
'posix.h',
'profiler.cc',
'profiler.h',
'proxydetect.cc',
'proxydetect.h',
'proxyinfo.cc',
'proxyinfo.h',
'proxyserver.cc',
'proxyserver.h',
'ratelimiter.cc',
'ratelimiter.h',
'ratetracker.cc',
'ratetracker.h',
'refcount.h',
'referencecountedsingletonfactory.h',
'rollingaccumulator.h',
'safe_conversions.h',
'safe_conversions_impl.h',
'schanneladapter.cc',
'schanneladapter.h',
'scoped_autorelease_pool.h',
'scoped_autorelease_pool.mm',
'scoped_ptr.h',
'scoped_ref_ptr.h',
'scopedptrcollection.h',
'sec_buffer.h',
'sha1.cc',
'sha1.h',
'sha1digest.h',
'sharedexclusivelock.cc',
'sharedexclusivelock.h',
'signalthread.cc',
'signalthread.h',
'sigslot.h',
'sigslotrepeater.h',
'socket.h',
'socketadapters.cc',
'socketadapters.h',
'socketaddress.cc',
'socketaddress.h',
'socketaddresspair.cc',
'socketaddresspair.h',
'socketfactory.h',
'socketpool.cc',
'socketpool.h',
'socketserver.h',
'socketstream.cc',
'socketstream.h',
'ssladapter.cc',
'ssladapter.h',
'sslconfig.h',
'sslfingerprint.cc',
'sslfingerprint.h',
'sslidentity.cc',
'sslidentity.h',
'sslroots.h',
'sslsocketfactory.cc',
'sslsocketfactory.h',
'sslstreamadapter.cc',
'sslstreamadapter.h',
'sslstreamadapterhelper.cc',
'sslstreamadapterhelper.h',
'stream.cc',
'stream.h',
'stringdigest.h',
'systeminfo.cc',
'systeminfo.h',
'task.cc',
'task.h',
'taskparent.cc',
'taskparent.h',
'taskrunner.cc',
'taskrunner.h',
'testclient.cc',
'testclient.h',
'thread.cc',
'thread.h',
'thread_checker.h',
'thread_checker_impl.cc',
'thread_checker_impl.h',
'timing.cc',
'timing.h',
'transformadapter.cc',
'transformadapter.h',
'unixfilesystem.cc',
'unixfilesystem.h',
'urlencode.cc',
'urlencode.h',
'versionparsing.cc',
'versionparsing.h',
'virtualsocketserver.cc',
'virtualsocketserver.h',
'win32.cc',
'win32.h',
'win32filesystem.cc',
'win32filesystem.h',
'win32regkey.cc',
'win32regkey.h',
'win32securityerrors.cc',
'win32socketinit.cc',
'win32socketinit.h',
'win32socketserver.cc',
'win32socketserver.h',
'win32window.cc',
'win32window.h',
'win32windowpicker.cc',
'win32windowpicker.h',
'window.h',
'windowpicker.h',
'windowpickerfactory.h',
'winfirewall.cc',
'winfirewall.h',
'winping.cc',
'winping.h',
'worker.cc',
'worker.h',
'x11windowpicker.cc',
'x11windowpicker.h',
'../overrides/webrtc/base/basictypes.h',
'../overrides/webrtc/base/constructormagic.h',
'../overrides/webrtc/base/logging.cc',
'../overrides/webrtc/base/logging.h',
'../overrides/webrtc/base/win32socketinit.cc',
],
# TODO(henrike): issue 3307, make rtc_base build without disabling
# these flags.
'cflags!': [
'-Wextra',
'-Wall',
],
'cflags_cc!': [
'-Wnon-virtual-dtor',
],
'direct_dependent_settings': {
'cflags_cc!': [
'-Wnon-virtual-dtor',
],
'defines': [
'FEATURE_ENABLE_SSL',
],
},
'include_dirs': [
'../../third_party/jsoncpp/overrides/include',
'../../third_party/jsoncpp/source/include',
],
'conditions': [
['build_with_chromium==1', {
'include_dirs': [
'../overrides',
'../../boringssl/src/include',
],
'sources!': [
'asyncinvoker.cc',
'asyncinvoker.h',
'asyncinvoker-inl.h',
'asyncresolverinterface.h',
'atomicops.h',
'bandwidthsmoother.cc',
'bandwidthsmoother.h',
'basictypes.h',
'bind.h',
'bind.h.pump',
'buffer.h',
'callback.h',
'callback.h.pump',
'constructormagic.h',
'dbus.cc',
'dbus.h',
'diskcache_win32.cc',
'diskcache_win32.h',
'filelock.cc',
'filelock.h',
'fileutils_mock.h',
'genericslot.h',
'genericslot.h.pump',
'httpserver.cc',
'httpserver.h',
'json.cc',
'json.h',
'latebindingsymboltable.cc',
'latebindingsymboltable.cc.def',
'latebindingsymboltable.h',
'latebindingsymboltable.h.def',
'libdbusglibsymboltable.cc',
'libdbusglibsymboltable.h',
'linuxfdwalk.c',
'linuxfdwalk.h',
'x11windowpicker.cc',
'x11windowpicker.h',
'logging.cc',
'logging.h',
'macasyncsocket.cc',
'macasyncsocket.h',
'maccocoasocketserver.h',
'maccocoasocketserver.mm',
'macsocketserver.cc',
'macsocketserver.h',
'macwindowpicker.cc',
'macwindowpicker.h',
'mathutils.h',
'multipart.cc',
'multipart.h',
'natserver.cc',
'natserver.h',
'natsocketfactory.cc',
'natsocketfactory.h',
'nattypes.cc',
'nattypes.h',
'optionsfile.cc',
'optionsfile.h',
'posix.cc',
'posix.h',
'profiler.cc',
'profiler.h',
'proxyserver.cc',
'proxyserver.h',
'refcount.h',
'referencecountedsingletonfactory.h',
'rollingaccumulator.h',
'safe_conversions.h',
'safe_conversions_impl.h',
'scopedptrcollection.h',
'scoped_ref_ptr.h',
'sec_buffer.h',
'sharedexclusivelock.cc',
'sharedexclusivelock.h',
'sslconfig.h',
'sslroots.h',
'stringdigest.h',
'testbase64.h',
'testclient.cc',
'testclient.h',
'transformadapter.cc',
'transformadapter.h',
'versionparsing.cc',
'versionparsing.h',
'virtualsocketserver.cc',
'virtualsocketserver.h',
'win32regkey.cc',
'win32regkey.h',
'win32socketinit.cc',
'win32socketinit.h',
'win32socketserver.cc',
'win32socketserver.h',
'window.h',
'windowpickerfactory.h',
'windowpicker.h',
],
'defines': [
'NO_MAIN_THREAD_WRAPPING',
],
'direct_dependent_settings': {
'defines': [
'NO_MAIN_THREAD_WRAPPING',
],
},
}, {
'conditions': [
['build_json==1', {
'dependencies': [
'<(DEPTH)/third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
],
}, {
'include_dirs': [
'<(json_root)',
],
'defines': [
# When defined changes the include path for json.h to where it
# is expected to be when building json outside of the standalone
# build.
'WEBRTC_EXTERNAL_JSON',
],
}],
],
'sources!': [
'../overrides/webrtc/base/basictypes.h',
'../overrides/webrtc/base/constructormagic.h',
'../overrides/webrtc/base/win32socketinit.cc',
'../overrides/webrtc/base/logging.cc',
'../overrides/webrtc/base/logging.h',
],
}],
['use_openssl==1', {
'defines': [
'SSL_USE_OPENSSL',
'HAVE_OPENSSL_SSL_H',
],
'direct_dependent_settings': {
'defines': [
'SSL_USE_OPENSSL',
'HAVE_OPENSSL_SSL_H',
],
},
'sources': [
'openssl.h',
'openssladapter.cc',
'openssladapter.h',
'openssldigest.cc',
'openssldigest.h',
'opensslidentity.cc',
'opensslidentity.h',
'opensslstreamadapter.cc',
'opensslstreamadapter.h',
],
'conditions': [
['build_ssl==1', {
'dependencies': [
'<(DEPTH)/third_party/boringssl/boringssl.gyp:boringssl',
],
}, {
'include_dirs': [
'<(ssl_root)',
],
}],
],
}, {
'sources': [
'nssidentity.cc',
'nssidentity.h',
'nssstreamadapter.cc',
'nssstreamadapter.h',
],
'conditions': [
['use_legacy_ssl_defaults!=1', {
'defines': [
'SSL_USE_NSS',
'HAVE_NSS_SSL_H',
'SSL_USE_NSS_RNG',
],
'direct_dependent_settings': {
'defines': [
'SSL_USE_NSS',
'HAVE_NSS_SSL_H',
'SSL_USE_NSS_RNG',
],
},
}],
['build_ssl==1', {
'conditions': [
# On some platforms, the rest of NSS is bundled. On others,
# it's pulled from the system.
['OS == "mac" or OS == "ios" or OS == "win"', {
'dependencies': [
'<(DEPTH)/net/third_party/nss/ssl.gyp:libssl',
'<(DEPTH)/third_party/nss/nss.gyp:nspr',
'<(DEPTH)/third_party/nss/nss.gyp:nss',
],
}],
['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
'dependencies': [
'<(DEPTH)/build/linux/system.gyp:ssl',
],
}],
],
}, {
'include_dirs': [
'<(ssl_root)',
],
}],
],
}],
['OS == "android"', {
'link_settings': {
'libraries': [
'-llog',
'-lGLESv2',
],
},
}, {
'sources!': [
'ifaddrs-android.cc',
'ifaddrs-android.h',
],
}],
['OS=="ios"', {
'all_dependent_settings': {
'xcode_settings': {
'OTHER_LDFLAGS': [
'-framework Foundation',
'-framework Security',
'-framework SystemConfiguration',
'-framework UIKit',
],
},
},
}],
['use_x11 == 1', {
'link_settings': {
'libraries': [
'-ldl',
'-lrt',
'-lXext',
'-lX11',
'-lXcomposite',
'-lXrender',
],
},
}, {
'sources!': [
'x11windowpicker.cc',
'x11windowpicker.h',
],
}],
['OS=="linux"', {
'link_settings': {
'libraries': [
'-ldl',
'-lrt',
],
},
}, {
'sources!': [
'dbus.cc',
'dbus.h',
'libdbusglibsymboltable.cc',
'libdbusglibsymboltable.h',
'linuxfdwalk.c',
],
}],
['OS=="mac"', {
'all_dependent_settings': {
'link_settings': {
'xcode_settings': {
'OTHER_LDFLAGS': [
'-framework Cocoa',
'-framework Foundation',
'-framework IOKit',
'-framework Security',
'-framework SystemConfiguration',
],
},
},
},
'conditions': [
['target_arch=="ia32"', {
'all_dependent_settings': {
'link_settings': {
'xcode_settings': {
'OTHER_LDFLAGS': [
'-framework Carbon',
],
},
},
},
}],
],
}, {
'sources!': [
'macasyncsocket.cc',
'macasyncsocket.h',
'maccocoasocketserver.h',
'maccocoasocketserver.mm',
'macconversion.cc',
'macconversion.h',
'macsocketserver.cc',
'macsocketserver.h',
'macutils.cc',
'macutils.h',
'macwindowpicker.cc',
'macwindowpicker.h',
],
}],
['OS=="win"', {
'link_settings': {
'libraries': [
'-lcrypt32.lib',
'-liphlpapi.lib',
'-lsecur32.lib',
],
},
# Suppress warnings about WIN32_LEAN_AND_MEAN.
'msvs_disabled_warnings': [4005, 4703],
'defines': [
'_CRT_NONSTDC_NO_DEPRECATE',
],
}, {
'sources/': [
['exclude', 'win32[a-z0-9]*\\.(h|cc)$'],
],
'sources!': [
'schanneladapter.cc',
'schanneladapter.h',
'winping.cc',
'winping.h',
'winfirewall.cc',
'winfirewall.h',
],
}],
['os_posix==0', {
'sources!': [
'latebindingsymboltable.cc',
'latebindingsymboltable.h',
'posix.cc',
'posix.h',
'unixfilesystem.cc',
'unixfilesystem.h',
],
}, {
'configurations': {
'Debug_Base': {
'defines': [
# Chromium's build/common.gypi defines this for all posix
# _except_ for ios & mac. We want it there as well, e.g.
# because ASSERT and friends trigger off of it.
'_DEBUG',
],
},
}
}],
['OS=="ios" or (OS=="mac" and target_arch!="ia32")', {
'defines': [
'CARBON_DEPRECATED=YES',
],
}],
['OS!="ios" and OS!="mac"', {
'sources!': [
'scoped_autorelease_pool.mm',
],
}],
['OS!="linux" and OS!="android"', {
'sources!': [
'linux.cc',
'linux.h',
],
}],
],
},
],
}

Просмотреть файл

@ -0,0 +1,260 @@
//*********************************************************************
//* Base64 - a simple base64 encoder and decoder.
//*
//* Copyright (c) 1999, Bob Withers - bwit@pobox.com
//*
//* This code may be freely used for any purpose, either personal
//* or commercial, provided the authors copyright notice remains
//* intact.
//*
//* Enhancements by Stanley Yamane:
//* o reverse lookup table for the decode function
//* o reserve string buffer space in advance
//*
//*********************************************************************
#include "webrtc/base/base64.h"
#include <string.h>
#include "webrtc/base/common.h"
using std::vector;
namespace rtc {
static const char kPad = '=';
static const unsigned char pd = 0xFD; // Padding
static const unsigned char sp = 0xFE; // Whitespace
static const unsigned char il = 0xFF; // Illegal base64 character
const char Base64::Base64Table[] =
// 0000000000111111111122222222223333333333444444444455555555556666
// 0123456789012345678901234567890123456789012345678901234567890123
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// Decode Table gives the index of any valid base64 character in the
// Base64 table
// 65 == A, 97 == a, 48 == 0, 43 == +, 47 == /
const unsigned char Base64::DecodeTable[] = {
// 0 1 2 3 4 5 6 7 8 9
il,il,il,il,il,il,il,il,il,sp, // 0 - 9
sp,sp,sp,sp,il,il,il,il,il,il, // 10 - 19
il,il,il,il,il,il,il,il,il,il, // 20 - 29
il,il,sp,il,il,il,il,il,il,il, // 30 - 39
il,il,il,62,il,il,il,63,52,53, // 40 - 49
54,55,56,57,58,59,60,61,il,il, // 50 - 59
il,pd,il,il,il, 0, 1, 2, 3, 4, // 60 - 69
5, 6, 7, 8, 9,10,11,12,13,14, // 70 - 79
15,16,17,18,19,20,21,22,23,24, // 80 - 89
25,il,il,il,il,il,il,26,27,28, // 90 - 99
29,30,31,32,33,34,35,36,37,38, // 100 - 109
39,40,41,42,43,44,45,46,47,48, // 110 - 119
49,50,51,il,il,il,il,il,il,il, // 120 - 129
il,il,il,il,il,il,il,il,il,il, // 130 - 139
il,il,il,il,il,il,il,il,il,il, // 140 - 149
il,il,il,il,il,il,il,il,il,il, // 150 - 159
il,il,il,il,il,il,il,il,il,il, // 160 - 169
il,il,il,il,il,il,il,il,il,il, // 170 - 179
il,il,il,il,il,il,il,il,il,il, // 180 - 189
il,il,il,il,il,il,il,il,il,il, // 190 - 199
il,il,il,il,il,il,il,il,il,il, // 200 - 209
il,il,il,il,il,il,il,il,il,il, // 210 - 219
il,il,il,il,il,il,il,il,il,il, // 220 - 229
il,il,il,il,il,il,il,il,il,il, // 230 - 239
il,il,il,il,il,il,il,il,il,il, // 240 - 249
il,il,il,il,il,il // 250 - 255
};
bool Base64::IsBase64Char(char ch) {
return (('A' <= ch) && (ch <= 'Z')) ||
(('a' <= ch) && (ch <= 'z')) ||
(('0' <= ch) && (ch <= '9')) ||
(ch == '+') || (ch == '/');
}
bool Base64::GetNextBase64Char(char ch, char* next_ch) {
if (next_ch == NULL) {
return false;
}
const char* p = strchr(Base64Table, ch);
if (!p)
return false;
++p;
*next_ch = (*p) ? *p : Base64Table[0];
return true;
}
bool Base64::IsBase64Encoded(const std::string& str) {
for (size_t i = 0; i < str.size(); ++i) {
if (!IsBase64Char(str.at(i)))
return false;
}
return true;
}
void Base64::EncodeFromArray(const void* data, size_t len,
std::string* result) {
ASSERT(NULL != result);
result->clear();
result->resize(((len + 2) / 3) * 4);
const unsigned char* byte_data = static_cast<const unsigned char*>(data);
unsigned char c;
size_t i = 0;
size_t dest_ix = 0;
while (i < len) {
c = (byte_data[i] >> 2) & 0x3f;
(*result)[dest_ix++] = Base64Table[c];
c = (byte_data[i] << 4) & 0x3f;
if (++i < len) {
c |= (byte_data[i] >> 4) & 0x0f;
}
(*result)[dest_ix++] = Base64Table[c];
if (i < len) {
c = (byte_data[i] << 2) & 0x3f;
if (++i < len) {
c |= (byte_data[i] >> 6) & 0x03;
}
(*result)[dest_ix++] = Base64Table[c];
} else {
(*result)[dest_ix++] = kPad;
}
if (i < len) {
c = byte_data[i] & 0x3f;
(*result)[dest_ix++] = Base64Table[c];
++i;
} else {
(*result)[dest_ix++] = kPad;
}
}
}
size_t Base64::GetNextQuantum(DecodeFlags parse_flags, bool illegal_pads,
const char* data, size_t len, size_t* dpos,
unsigned char qbuf[4], bool* padded)
{
size_t byte_len = 0, pad_len = 0, pad_start = 0;
for (; (byte_len < 4) && (*dpos < len); ++*dpos) {
qbuf[byte_len] = DecodeTable[static_cast<unsigned char>(data[*dpos])];
if ((il == qbuf[byte_len]) || (illegal_pads && (pd == qbuf[byte_len]))) {
if (parse_flags != DO_PARSE_ANY)
break;
// Ignore illegal characters
} else if (sp == qbuf[byte_len]) {
if (parse_flags == DO_PARSE_STRICT)
break;
// Ignore spaces
} else if (pd == qbuf[byte_len]) {
if (byte_len < 2) {
if (parse_flags != DO_PARSE_ANY)
break;
// Ignore unexpected padding
} else if (byte_len + pad_len >= 4) {
if (parse_flags != DO_PARSE_ANY)
break;
// Ignore extra pads
} else {
if (1 == ++pad_len) {
pad_start = *dpos;
}
}
} else {
if (pad_len > 0) {
if (parse_flags != DO_PARSE_ANY)
break;
// Ignore pads which are followed by data
pad_len = 0;
}
++byte_len;
}
}
for (size_t i = byte_len; i < 4; ++i) {
qbuf[i] = 0;
}
if (4 == byte_len + pad_len) {
*padded = true;
} else {
*padded = false;
if (pad_len) {
// Roll back illegal padding
*dpos = pad_start;
}
}
return byte_len;
}
bool Base64::DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
std::string* result, size_t* data_used) {
return DecodeFromArrayTemplate<std::string>(
data, len, flags, result, data_used);
}
bool Base64::DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
vector<char>* result, size_t* data_used) {
return DecodeFromArrayTemplate<vector<char> >(data, len, flags, result,
data_used);
}
template<typename T>
bool Base64::DecodeFromArrayTemplate(const char* data, size_t len,
DecodeFlags flags, T* result,
size_t* data_used)
{
ASSERT(NULL != result);
ASSERT(flags <= (DO_PARSE_MASK | DO_PAD_MASK | DO_TERM_MASK));
const DecodeFlags parse_flags = flags & DO_PARSE_MASK;
const DecodeFlags pad_flags = flags & DO_PAD_MASK;
const DecodeFlags term_flags = flags & DO_TERM_MASK;
ASSERT(0 != parse_flags);
ASSERT(0 != pad_flags);
ASSERT(0 != term_flags);
result->clear();
result->reserve(len);
size_t dpos = 0;
bool success = true, padded;
unsigned char c, qbuf[4];
while (dpos < len) {
size_t qlen = GetNextQuantum(parse_flags, (DO_PAD_NO == pad_flags),
data, len, &dpos, qbuf, &padded);
c = (qbuf[0] << 2) | ((qbuf[1] >> 4) & 0x3);
if (qlen >= 2) {
result->push_back(c);
c = ((qbuf[1] << 4) & 0xf0) | ((qbuf[2] >> 2) & 0xf);
if (qlen >= 3) {
result->push_back(c);
c = ((qbuf[2] << 6) & 0xc0) | qbuf[3];
if (qlen >= 4) {
result->push_back(c);
c = 0;
}
}
}
if (qlen < 4) {
if ((DO_TERM_ANY != term_flags) && (0 != c)) {
success = false; // unused bits
}
if ((DO_PAD_YES == pad_flags) && !padded) {
success = false; // expected padding
}
break;
}
}
if ((DO_TERM_BUFFER == term_flags) && (dpos != len)) {
success = false; // unused chars
}
if (data_used) {
*data_used = dpos;
}
return success;
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,104 @@
//*********************************************************************
//* C_Base64 - a simple base64 encoder and decoder.
//*
//* Copyright (c) 1999, Bob Withers - bwit@pobox.com
//*
//* This code may be freely used for any purpose, either personal
//* or commercial, provided the authors copyright notice remains
//* intact.
//*********************************************************************
#ifndef WEBRTC_BASE_BASE64_H__
#define WEBRTC_BASE_BASE64_H__
#include <string>
#include <vector>
namespace rtc {
class Base64
{
public:
enum DecodeOption {
DO_PARSE_STRICT = 1, // Parse only base64 characters
DO_PARSE_WHITE = 2, // Parse only base64 and whitespace characters
DO_PARSE_ANY = 3, // Parse all characters
DO_PARSE_MASK = 3,
DO_PAD_YES = 4, // Padding is required
DO_PAD_ANY = 8, // Padding is optional
DO_PAD_NO = 12, // Padding is disallowed
DO_PAD_MASK = 12,
DO_TERM_BUFFER = 16, // Must termiante at end of buffer
DO_TERM_CHAR = 32, // May terminate at any character boundary
DO_TERM_ANY = 48, // May terminate at a sub-character bit offset
DO_TERM_MASK = 48,
// Strictest interpretation
DO_STRICT = DO_PARSE_STRICT | DO_PAD_YES | DO_TERM_BUFFER,
DO_LAX = DO_PARSE_ANY | DO_PAD_ANY | DO_TERM_CHAR,
};
typedef int DecodeFlags;
static bool IsBase64Char(char ch);
// Get the char next to the |ch| from the Base64Table.
// If the |ch| is the last one in the Base64Table then returns
// the first one from the table.
// Expects the |ch| be a base64 char.
// The result will be saved in |next_ch|.
// Returns true on success.
static bool GetNextBase64Char(char ch, char* next_ch);
// Determines whether the given string consists entirely of valid base64
// encoded characters.
static bool IsBase64Encoded(const std::string& str);
static void EncodeFromArray(const void* data, size_t len,
std::string* result);
static bool DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
std::string* result, size_t* data_used);
static bool DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
std::vector<char>* result, size_t* data_used);
// Convenience Methods
static inline std::string Encode(const std::string& data) {
std::string result;
EncodeFromArray(data.data(), data.size(), &result);
return result;
}
static inline std::string Decode(const std::string& data, DecodeFlags flags) {
std::string result;
DecodeFromArray(data.data(), data.size(), flags, &result, NULL);
return result;
}
static inline bool Decode(const std::string& data, DecodeFlags flags,
std::string* result, size_t* data_used)
{
return DecodeFromArray(data.data(), data.size(), flags, result, data_used);
}
static inline bool Decode(const std::string& data, DecodeFlags flags,
std::vector<char>* result, size_t* data_used)
{
return DecodeFromArray(data.data(), data.size(), flags, result, data_used);
}
private:
static const char Base64Table[];
static const unsigned char DecodeTable[];
static size_t GetNextQuantum(DecodeFlags parse_flags, bool illegal_pads,
const char* data, size_t len, size_t* dpos,
unsigned char qbuf[4], bool* padded);
template<typename T>
static bool DecodeFromArrayTemplate(const char* data, size_t len,
DecodeFlags flags, T* result,
size_t* data_used);
};
} // namespace rtc
#endif // WEBRTC_BASE_BASE64_H__

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,166 @@
# Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
{
'includes': [ '../build/common.gypi', ],
'targets': [
{
'target_name': 'rtc_base_tests_utils',
'type': 'static_library',
'sources': [
'unittest_main.cc',
# Also use this as a convenient dumping ground for misc files that are
# included by multiple targets below.
'fakecpumonitor.h',
'fakenetwork.h',
'fakesslidentity.h',
'faketaskrunner.h',
'gunit.h',
'testbase64.h',
'testechoserver.h',
'testutils.h',
'win32toolhelp.h',
],
'defines': [
'GTEST_RELATIVE_PATH',
],
'dependencies': [
'base.gyp:rtc_base',
'<(DEPTH)/testing/gtest.gyp:gtest',
],
'direct_dependent_settings': {
'defines': [
'GTEST_RELATIVE_PATH',
],
},
'export_dependent_settings': [
'<(DEPTH)/testing/gtest.gyp:gtest',
],
},
{
'target_name': 'rtc_base_tests',
'type': 'none',
'direct_dependent_settings': {
'sources': [
'asynchttprequest_unittest.cc',
'atomicops_unittest.cc',
'autodetectproxy_unittest.cc',
'bandwidthsmoother_unittest.cc',
'base64_unittest.cc',
'basictypes_unittest.cc',
'bind_unittest.cc',
'buffer_unittest.cc',
'bytebuffer_unittest.cc',
'byteorder_unittest.cc',
'callback_unittest.cc',
'cpumonitor_unittest.cc',
'crc32_unittest.cc',
'criticalsection_unittest.cc',
'event_unittest.cc',
'exp_filter_unittest.cc',
'filelock_unittest.cc',
'fileutils_unittest.cc',
'helpers_unittest.cc',
'httpbase_unittest.cc',
'httpcommon_unittest.cc',
'httpserver_unittest.cc',
'ipaddress_unittest.cc',
'logging_unittest.cc',
'md5digest_unittest.cc',
'messagedigest_unittest.cc',
#'messagequeue_unittest.cc',
'multipart_unittest.cc',
'nat_unittest.cc',
'network_unittest.cc',
'nullsocketserver_unittest.cc',
'optionsfile_unittest.cc',
'pathutils_unittest.cc',
'physicalsocketserver_unittest.cc',
'profiler_unittest.cc',
'proxy_unittest.cc',
'proxydetect_unittest.cc',
'ratelimiter_unittest.cc',
'ratetracker_unittest.cc',
'referencecountedsingletonfactory_unittest.cc',
'rollingaccumulator_unittest.cc',
'scopedptrcollection_unittest.cc',
'sha1digest_unittest.cc',
'sharedexclusivelock_unittest.cc',
'signalthread_unittest.cc',
'sigslot_unittest.cc',
'sigslottester.h',
'sigslottester.h.pump',
'socket_unittest.cc',
'socket_unittest.h',
'socketaddress_unittest.cc',
'stream_unittest.cc',
'stringencode_unittest.cc',
'stringutils_unittest.cc',
# TODO(ronghuawu): Reenable this test.
# 'systeminfo_unittest.cc',
'task_unittest.cc',
'testclient_unittest.cc',
'thread_checker_unittest.cc',
'thread_unittest.cc',
'timeutils_unittest.cc',
'urlencode_unittest.cc',
'versionparsing_unittest.cc',
'virtualsocket_unittest.cc',
# TODO(ronghuawu): Reenable this test.
# 'windowpicker_unittest.cc',
],
'conditions': [
['OS=="linux"', {
'sources': [
'latebindingsymboltable_unittest.cc',
# TODO(ronghuawu): Reenable this test.
# 'linux_unittest.cc',
'linuxfdwalk_unittest.cc',
],
}],
['OS=="win"', {
'sources': [
'win32_unittest.cc',
'win32regkey_unittest.cc',
'win32socketserver_unittest.cc',
'win32toolhelp_unittest.cc',
'win32window_unittest.cc',
'win32windowpicker_unittest.cc',
'winfirewall_unittest.cc',
],
'sources!': [
# TODO(ronghuawu): Fix TestUdpReadyToSendIPv6 on windows bot
# then reenable these tests.
'physicalsocketserver_unittest.cc',
'socket_unittest.cc',
'win32socketserver_unittest.cc',
'win32windowpicker_unittest.cc',
],
}],
['OS=="mac"', {
'sources': [
'macsocketserver_unittest.cc',
'macutils_unittest.cc',
],
}],
['os_posix==1', {
'sources': [
'ssladapter_unittest.cc',
'sslidentity_unittest.cc',
'sslstreamadapter_unittest.cc',
],
}],
['OS=="ios" or (OS=="mac" and target_arch!="ia32")', {
'defines': [
'CARBON_DEPRECATED=YES',
],
}],
], # conditions
},
},
],
}

Просмотреть файл

@ -0,0 +1,20 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_BASICDEFS_H_
#define WEBRTC_BASE_BASICDEFS_H_
#if HAVE_CONFIG_H
#include "config.h" // NOLINT
#endif
#define ARRAY_SIZE(x) (static_cast<int>(sizeof(x) / sizeof(x[0])))
#endif // WEBRTC_BASE_BASICDEFS_H_

Просмотреть файл

@ -0,0 +1,134 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_BASICTYPES_H_
#define WEBRTC_BASE_BASICTYPES_H_
#include <stddef.h> // for NULL, size_t
#if !(defined(_MSC_VER) && (_MSC_VER < 1600))
#include <stdint.h> // for uintptr_t
#endif
#ifdef HAVE_CONFIG_H
#include "config.h" // NOLINT
#endif
#include "webrtc/base/constructormagic.h"
#if !defined(INT_TYPES_DEFINED)
#define INT_TYPES_DEFINED
#ifdef COMPILER_MSVC
typedef unsigned __int64 uint64;
typedef __int64 int64;
#ifndef INT64_C
#define INT64_C(x) x ## I64
#endif
#ifndef UINT64_C
#define UINT64_C(x) x ## UI64
#endif
#define INT64_F "I64"
#else // COMPILER_MSVC
// On Mac OS X, cssmconfig.h defines uint64 as uint64_t
// TODO(fbarchard): Use long long for compatibility with chromium on BSD/OSX.
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
typedef uint64_t uint64;
typedef int64_t int64;
#ifndef INT64_C
#define INT64_C(x) x ## LL
#endif
#ifndef UINT64_C
#define UINT64_C(x) x ## ULL
#endif
#define INT64_F "l"
#elif defined(__LP64__)
typedef unsigned long uint64; // NOLINT
typedef long int64; // NOLINT
#ifndef INT64_C
#define INT64_C(x) x ## L
#endif
#ifndef UINT64_C
#define UINT64_C(x) x ## UL
#endif
#define INT64_F "l"
#else // __LP64__
typedef unsigned long long uint64; // NOLINT
typedef long long int64; // NOLINT
#ifndef INT64_C
#define INT64_C(x) x ## LL
#endif
#ifndef UINT64_C
#define UINT64_C(x) x ## ULL
#endif
#define INT64_F "ll"
#endif // __LP64__
#endif // COMPILER_MSVC
typedef unsigned int uint32;
typedef int int32;
typedef unsigned short uint16; // NOLINT
typedef short int16; // NOLINT
typedef unsigned char uint8;
typedef signed char int8;
#endif // INT_TYPES_DEFINED
// Detect compiler is for x86 or x64.
#if defined(__x86_64__) || defined(_M_X64) || \
defined(__i386__) || defined(_M_IX86)
#define CPU_X86 1
#endif
// Detect compiler is for arm.
#if defined(__arm__) || defined(_M_ARM)
#define CPU_ARM 1
#endif
#if defined(CPU_X86) && defined(CPU_ARM)
#error CPU_X86 and CPU_ARM both defined.
#endif
#if !defined(ARCH_CPU_BIG_ENDIAN) && !defined(ARCH_CPU_LITTLE_ENDIAN)
// x86, arm or GCC provided __BYTE_ORDER__ macros
#if CPU_X86 || CPU_ARM || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define ARCH_CPU_LITTLE_ENDIAN
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define ARCH_CPU_BIG_ENDIAN
#else
#error ARCH_CPU_BIG_ENDIAN or ARCH_CPU_LITTLE_ENDIAN should be defined.
#endif
#endif
#if defined(ARCH_CPU_BIG_ENDIAN) && defined(ARCH_CPU_LITTLE_ENDIAN)
#error ARCH_CPU_BIG_ENDIAN and ARCH_CPU_LITTLE_ENDIAN both defined.
#endif
#if defined(WEBRTC_WIN)
typedef int socklen_t;
#endif
// The following only works for C++
#ifdef __cplusplus
namespace rtc {
template<class T> inline T _min(T a, T b) { return (a > b) ? b : a; }
template<class T> inline T _max(T a, T b) { return (a < b) ? b : a; }
// For wait functions that take a number of milliseconds, kForever indicates
// unlimited time.
const int kForever = -1;
}
#define ALIGNP(p, t) \
(reinterpret_cast<uint8*>(((reinterpret_cast<uintptr_t>(p) + \
((t) - 1)) & ~((t) - 1))))
#define RTC_IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a) - 1)))
// Use these to declare and define a static local variable (static T;) so that
// it is leaked so that its destructors are not called at exit.
#define LIBJINGLE_DEFINE_STATIC_LOCAL(type, name, arguments) \
static type& name = *new type arguments
#endif // __cplusplus
#endif // WEBRTC_BASE_BASICTYPES_H_

Просмотреть файл

@ -0,0 +1,75 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/basictypes.h"
#include "webrtc/base/gunit.h"
namespace rtc {
TEST(BasicTypesTest, Endian) {
uint16 v16 = 0x1234u;
uint8 first_byte = *reinterpret_cast<uint8*>(&v16);
#if defined(ARCH_CPU_LITTLE_ENDIAN)
EXPECT_EQ(0x34u, first_byte);
#elif defined(ARCH_CPU_BIG_ENDIAN)
EXPECT_EQ(0x12u, first_byte);
#endif
}
TEST(BasicTypesTest, SizeOfTypes) {
int8 i8 = -1;
uint8 u8 = 1u;
int16 i16 = -1;
uint16 u16 = 1u;
int32 i32 = -1;
uint32 u32 = 1u;
int64 i64 = -1;
uint64 u64 = 1u;
EXPECT_EQ(1u, sizeof(i8));
EXPECT_EQ(1u, sizeof(u8));
EXPECT_EQ(2u, sizeof(i16));
EXPECT_EQ(2u, sizeof(u16));
EXPECT_EQ(4u, sizeof(i32));
EXPECT_EQ(4u, sizeof(u32));
EXPECT_EQ(8u, sizeof(i64));
EXPECT_EQ(8u, sizeof(u64));
EXPECT_GT(0, i8);
EXPECT_LT(0u, u8);
EXPECT_GT(0, i16);
EXPECT_LT(0u, u16);
EXPECT_GT(0, i32);
EXPECT_LT(0u, u32);
EXPECT_GT(0, i64);
EXPECT_LT(0u, u64);
}
TEST(BasicTypesTest, SizeOfConstants) {
EXPECT_EQ(8u, sizeof(INT64_C(0)));
EXPECT_EQ(8u, sizeof(UINT64_C(0)));
EXPECT_EQ(8u, sizeof(INT64_C(0x1234567887654321)));
EXPECT_EQ(8u, sizeof(UINT64_C(0x8765432112345678)));
}
// Test CPU_ macros
#if !defined(CPU_ARM) && defined(__arm__)
#error expected CPU_ARM to be defined.
#endif
#if !defined(CPU_X86) && (defined(WEBRTC_WIN) || defined(WEBRTC_MAC) && !defined(WEBRTC_IOS))
#error expected CPU_X86 to be defined.
#endif
#if !defined(ARCH_CPU_LITTLE_ENDIAN) && \
(defined(WEBRTC_WIN) || defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) || defined(CPU_X86))
#error expected ARCH_CPU_LITTLE_ENDIAN to be defined.
#endif
// TODO(fbarchard): Test all macros in basictypes.h
} // namespace rtc

Просмотреть файл

@ -0,0 +1,587 @@
// This file was GENERATED by command:
// pump.py bind.h.pump
// DO NOT EDIT BY HAND!!!
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// To generate bind.h from bind.h.pump, execute:
// /home/build/google3/third_party/gtest/scripts/pump.py bind.h.pump
// Bind() is an overloaded function that converts method calls into function
// objects (aka functors). It captures any arguments to the method by value
// when Bind is called, producing a stateful, nullary function object. Care
// should be taken about the lifetime of objects captured by Bind(); the
// returned functor knows nothing about the lifetime of the method's object or
// any arguments passed by pointer, and calling the functor with a destroyed
// object will surely do bad things.
//
// Example usage:
// struct Foo {
// int Test1() { return 42; }
// int Test2() const { return 52; }
// int Test3(int x) { return x*x; }
// float Test4(int x, float y) { return x + y; }
// };
//
// int main() {
// Foo foo;
// cout << rtc::Bind(&Foo::Test1, &foo)() << endl;
// cout << rtc::Bind(&Foo::Test2, &foo)() << endl;
// cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl;
// cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl;
// }
#ifndef WEBRTC_BASE_BIND_H_
#define WEBRTC_BASE_BIND_H_
#define NONAME
namespace rtc {
namespace detail {
// This is needed because the template parameters in Bind can't be resolved
// if they're used both as parameters of the function pointer type and as
// parameters to Bind itself: the function pointer parameters are exact
// matches to the function prototype, but the parameters to bind have
// references stripped. This trick allows the compiler to dictate the Bind
// parameter types rather than deduce them.
template <class T> struct identity { typedef T type; };
} // namespace detail
template <class ObjectT, class MethodT, class R>
class MethodFunctor0 {
public:
MethodFunctor0(MethodT method, ObjectT* object)
: method_(method), object_(object) {}
R operator()() const {
return (object_->*method_)(); }
private:
MethodT method_;
ObjectT* object_;
};
template <class FunctorT, class R>
class Functor0 {
public:
explicit Functor0(const FunctorT& functor)
: functor_(functor) {}
R operator()() const {
return functor_(); }
private:
FunctorT functor_;
};
#define FP_T(x) R (ObjectT::*x)()
template <class ObjectT, class R>
MethodFunctor0<ObjectT, FP_T(NONAME), R>
Bind(FP_T(method), ObjectT* object) {
return MethodFunctor0<ObjectT, FP_T(NONAME), R>(
method, object);
}
#undef FP_T
#define FP_T(x) R (ObjectT::*x)() const
template <class ObjectT, class R>
MethodFunctor0<const ObjectT, FP_T(NONAME), R>
Bind(FP_T(method), const ObjectT* object) {
return MethodFunctor0<const ObjectT, FP_T(NONAME), R>(
method, object);
}
#undef FP_T
#define FP_T(x) R (*x)()
template <class R>
Functor0<FP_T(NONAME), R>
Bind(FP_T(function)) {
return Functor0<FP_T(NONAME), R>(
function);
}
#undef FP_T
template <class ObjectT, class MethodT, class R,
class P1>
class MethodFunctor1 {
public:
MethodFunctor1(MethodT method, ObjectT* object,
P1 p1)
: method_(method), object_(object),
p1_(p1) {}
R operator()() const {
return (object_->*method_)(p1_); }
private:
MethodT method_;
ObjectT* object_;
P1 p1_;
};
template <class FunctorT, class R,
class P1>
class Functor1 {
public:
Functor1(const FunctorT& functor, P1 p1)
: functor_(functor),
p1_(p1) {}
R operator()() const {
return functor_(p1_); }
private:
FunctorT functor_;
P1 p1_;
};
#define FP_T(x) R (ObjectT::*x)(P1)
template <class ObjectT, class R,
class P1>
MethodFunctor1<ObjectT, FP_T(NONAME), R, P1>
Bind(FP_T(method), ObjectT* object,
typename detail::identity<P1>::type p1) {
return MethodFunctor1<ObjectT, FP_T(NONAME), R, P1>(
method, object, p1);
}
#undef FP_T
#define FP_T(x) R (ObjectT::*x)(P1) const
template <class ObjectT, class R,
class P1>
MethodFunctor1<const ObjectT, FP_T(NONAME), R, P1>
Bind(FP_T(method), const ObjectT* object,
typename detail::identity<P1>::type p1) {
return MethodFunctor1<const ObjectT, FP_T(NONAME), R, P1>(
method, object, p1);
}
#undef FP_T
#define FP_T(x) R (*x)(P1)
template <class R,
class P1>
Functor1<FP_T(NONAME), R, P1>
Bind(FP_T(function),
typename detail::identity<P1>::type p1) {
return Functor1<FP_T(NONAME), R, P1>(
function, p1);
}
#undef FP_T
template <class ObjectT, class MethodT, class R,
class P1,
class P2>
class MethodFunctor2 {
public:
MethodFunctor2(MethodT method, ObjectT* object,
P1 p1,
P2 p2)
: method_(method), object_(object),
p1_(p1),
p2_(p2) {}
R operator()() const {
return (object_->*method_)(p1_, p2_); }
private:
MethodT method_;
ObjectT* object_;
P1 p1_;
P2 p2_;
};
template <class FunctorT, class R,
class P1,
class P2>
class Functor2 {
public:
Functor2(const FunctorT& functor, P1 p1, P2 p2)
: functor_(functor),
p1_(p1),
p2_(p2) {}
R operator()() const {
return functor_(p1_, p2_); }
private:
FunctorT functor_;
P1 p1_;
P2 p2_;
};
#define FP_T(x) R (ObjectT::*x)(P1, P2)
template <class ObjectT, class R,
class P1,
class P2>
MethodFunctor2<ObjectT, FP_T(NONAME), R, P1, P2>
Bind(FP_T(method), ObjectT* object,
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2) {
return MethodFunctor2<ObjectT, FP_T(NONAME), R, P1, P2>(
method, object, p1, p2);
}
#undef FP_T
#define FP_T(x) R (ObjectT::*x)(P1, P2) const
template <class ObjectT, class R,
class P1,
class P2>
MethodFunctor2<const ObjectT, FP_T(NONAME), R, P1, P2>
Bind(FP_T(method), const ObjectT* object,
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2) {
return MethodFunctor2<const ObjectT, FP_T(NONAME), R, P1, P2>(
method, object, p1, p2);
}
#undef FP_T
#define FP_T(x) R (*x)(P1, P2)
template <class R,
class P1,
class P2>
Functor2<FP_T(NONAME), R, P1, P2>
Bind(FP_T(function),
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2) {
return Functor2<FP_T(NONAME), R, P1, P2>(
function, p1, p2);
}
#undef FP_T
template <class ObjectT, class MethodT, class R,
class P1,
class P2,
class P3>
class MethodFunctor3 {
public:
MethodFunctor3(MethodT method, ObjectT* object,
P1 p1,
P2 p2,
P3 p3)
: method_(method), object_(object),
p1_(p1),
p2_(p2),
p3_(p3) {}
R operator()() const {
return (object_->*method_)(p1_, p2_, p3_); }
private:
MethodT method_;
ObjectT* object_;
P1 p1_;
P2 p2_;
P3 p3_;
};
template <class FunctorT, class R,
class P1,
class P2,
class P3>
class Functor3 {
public:
Functor3(const FunctorT& functor, P1 p1, P2 p2, P3 p3)
: functor_(functor),
p1_(p1),
p2_(p2),
p3_(p3) {}
R operator()() const {
return functor_(p1_, p2_, p3_); }
private:
FunctorT functor_;
P1 p1_;
P2 p2_;
P3 p3_;
};
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3)
template <class ObjectT, class R,
class P1,
class P2,
class P3>
MethodFunctor3<ObjectT, FP_T(NONAME), R, P1, P2, P3>
Bind(FP_T(method), ObjectT* object,
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3) {
return MethodFunctor3<ObjectT, FP_T(NONAME), R, P1, P2, P3>(
method, object, p1, p2, p3);
}
#undef FP_T
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3) const
template <class ObjectT, class R,
class P1,
class P2,
class P3>
MethodFunctor3<const ObjectT, FP_T(NONAME), R, P1, P2, P3>
Bind(FP_T(method), const ObjectT* object,
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3) {
return MethodFunctor3<const ObjectT, FP_T(NONAME), R, P1, P2, P3>(
method, object, p1, p2, p3);
}
#undef FP_T
#define FP_T(x) R (*x)(P1, P2, P3)
template <class R,
class P1,
class P2,
class P3>
Functor3<FP_T(NONAME), R, P1, P2, P3>
Bind(FP_T(function),
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3) {
return Functor3<FP_T(NONAME), R, P1, P2, P3>(
function, p1, p2, p3);
}
#undef FP_T
template <class ObjectT, class MethodT, class R,
class P1,
class P2,
class P3,
class P4>
class MethodFunctor4 {
public:
MethodFunctor4(MethodT method, ObjectT* object,
P1 p1,
P2 p2,
P3 p3,
P4 p4)
: method_(method), object_(object),
p1_(p1),
p2_(p2),
p3_(p3),
p4_(p4) {}
R operator()() const {
return (object_->*method_)(p1_, p2_, p3_, p4_); }
private:
MethodT method_;
ObjectT* object_;
P1 p1_;
P2 p2_;
P3 p3_;
P4 p4_;
};
template <class FunctorT, class R,
class P1,
class P2,
class P3,
class P4>
class Functor4 {
public:
Functor4(const FunctorT& functor, P1 p1, P2 p2, P3 p3, P4 p4)
: functor_(functor),
p1_(p1),
p2_(p2),
p3_(p3),
p4_(p4) {}
R operator()() const {
return functor_(p1_, p2_, p3_, p4_); }
private:
FunctorT functor_;
P1 p1_;
P2 p2_;
P3 p3_;
P4 p4_;
};
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4)
template <class ObjectT, class R,
class P1,
class P2,
class P3,
class P4>
MethodFunctor4<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4>
Bind(FP_T(method), ObjectT* object,
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3,
typename detail::identity<P4>::type p4) {
return MethodFunctor4<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4>(
method, object, p1, p2, p3, p4);
}
#undef FP_T
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4) const
template <class ObjectT, class R,
class P1,
class P2,
class P3,
class P4>
MethodFunctor4<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4>
Bind(FP_T(method), const ObjectT* object,
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3,
typename detail::identity<P4>::type p4) {
return MethodFunctor4<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4>(
method, object, p1, p2, p3, p4);
}
#undef FP_T
#define FP_T(x) R (*x)(P1, P2, P3, P4)
template <class R,
class P1,
class P2,
class P3,
class P4>
Functor4<FP_T(NONAME), R, P1, P2, P3, P4>
Bind(FP_T(function),
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3,
typename detail::identity<P4>::type p4) {
return Functor4<FP_T(NONAME), R, P1, P2, P3, P4>(
function, p1, p2, p3, p4);
}
#undef FP_T
template <class ObjectT, class MethodT, class R,
class P1,
class P2,
class P3,
class P4,
class P5>
class MethodFunctor5 {
public:
MethodFunctor5(MethodT method, ObjectT* object,
P1 p1,
P2 p2,
P3 p3,
P4 p4,
P5 p5)
: method_(method), object_(object),
p1_(p1),
p2_(p2),
p3_(p3),
p4_(p4),
p5_(p5) {}
R operator()() const {
return (object_->*method_)(p1_, p2_, p3_, p4_, p5_); }
private:
MethodT method_;
ObjectT* object_;
P1 p1_;
P2 p2_;
P3 p3_;
P4 p4_;
P5 p5_;
};
template <class FunctorT, class R,
class P1,
class P2,
class P3,
class P4,
class P5>
class Functor5 {
public:
Functor5(const FunctorT& functor, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
: functor_(functor),
p1_(p1),
p2_(p2),
p3_(p3),
p4_(p4),
p5_(p5) {}
R operator()() const {
return functor_(p1_, p2_, p3_, p4_, p5_); }
private:
FunctorT functor_;
P1 p1_;
P2 p2_;
P3 p3_;
P4 p4_;
P5 p5_;
};
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5)
template <class ObjectT, class R,
class P1,
class P2,
class P3,
class P4,
class P5>
MethodFunctor5<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5>
Bind(FP_T(method), ObjectT* object,
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3,
typename detail::identity<P4>::type p4,
typename detail::identity<P5>::type p5) {
return MethodFunctor5<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5>(
method, object, p1, p2, p3, p4, p5);
}
#undef FP_T
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5) const
template <class ObjectT, class R,
class P1,
class P2,
class P3,
class P4,
class P5>
MethodFunctor5<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5>
Bind(FP_T(method), const ObjectT* object,
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3,
typename detail::identity<P4>::type p4,
typename detail::identity<P5>::type p5) {
return MethodFunctor5<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5>(
method, object, p1, p2, p3, p4, p5);
}
#undef FP_T
#define FP_T(x) R (*x)(P1, P2, P3, P4, P5)
template <class R,
class P1,
class P2,
class P3,
class P4,
class P5>
Functor5<FP_T(NONAME), R, P1, P2, P3, P4, P5>
Bind(FP_T(function),
typename detail::identity<P1>::type p1,
typename detail::identity<P2>::type p2,
typename detail::identity<P3>::type p3,
typename detail::identity<P4>::type p4,
typename detail::identity<P5>::type p5) {
return Functor5<FP_T(NONAME), R, P1, P2, P3, P4, P5>(
function, p1, p2, p3, p4, p5);
}
#undef FP_T
} // namespace rtc
#undef NONAME
#endif // WEBRTC_BASE_BIND_H_

Просмотреть файл

@ -0,0 +1,138 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// To generate bind.h from bind.h.pump, execute:
// /home/build/google3/third_party/gtest/scripts/pump.py bind.h.pump
// Bind() is an overloaded function that converts method calls into function
// objects (aka functors). It captures any arguments to the method by value
// when Bind is called, producing a stateful, nullary function object. Care
// should be taken about the lifetime of objects captured by Bind(); the
// returned functor knows nothing about the lifetime of the method's object or
// any arguments passed by pointer, and calling the functor with a destroyed
// object will surely do bad things.
//
// Example usage:
// struct Foo {
// int Test1() { return 42; }
// int Test2() const { return 52; }
// int Test3(int x) { return x*x; }
// float Test4(int x, float y) { return x + y; }
// };
//
// int main() {
// Foo foo;
// cout << rtc::Bind(&Foo::Test1, &foo)() << endl;
// cout << rtc::Bind(&Foo::Test2, &foo)() << endl;
// cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl;
// cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl;
// }
#ifndef WEBRTC_BASE_BIND_H_
#define WEBRTC_BASE_BIND_H_
#define NONAME
namespace rtc {
namespace detail {
// This is needed because the template parameters in Bind can't be resolved
// if they're used both as parameters of the function pointer type and as
// parameters to Bind itself: the function pointer parameters are exact
// matches to the function prototype, but the parameters to bind have
// references stripped. This trick allows the compiler to dictate the Bind
// parameter types rather than deduce them.
template <class T> struct identity { typedef T type; };
} // namespace detail
$var n = 5
$range i 0..n
$for i [[
$range j 1..i
template <class ObjectT, class MethodT, class R$for j [[,
class P$j]]>
class MethodFunctor$i {
public:
MethodFunctor$i(MethodT method, ObjectT* object$for j [[,
P$j p$j]])
: method_(method), object_(object)$for j [[,
p$(j)_(p$j)]] {}
R operator()() const {
return (object_->*method_)($for j , [[p$(j)_]]); }
private:
MethodT method_;
ObjectT* object_;$for j [[
P$j p$(j)_;]]
};
template <class FunctorT, class R$for j [[,
class P$j]]>
class Functor$i {
public:
$if i == 0 [[explicit ]]
Functor$i(const FunctorT& functor$for j [[, P$j p$j]])
: functor_(functor)$for j [[,
p$(j)_(p$j)]] {}
R operator()() const {
return functor_($for j , [[p$(j)_]]); }
private:
FunctorT functor_;$for j [[
P$j p$(j)_;]]
};
#define FP_T(x) R (ObjectT::*x)($for j , [[P$j]])
template <class ObjectT, class R$for j [[,
class P$j]]>
MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]>
Bind(FP_T(method), ObjectT* object$for j [[,
typename detail::identity<P$j>::type p$j]]) {
return MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]>(
method, object$for j [[, p$j]]);
}
#undef FP_T
#define FP_T(x) R (ObjectT::*x)($for j , [[P$j]]) const
template <class ObjectT, class R$for j [[,
class P$j]]>
MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]>
Bind(FP_T(method), const ObjectT* object$for j [[,
typename detail::identity<P$j>::type p$j]]) {
return MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]>(
method, object$for j [[, p$j]]);
}
#undef FP_T
#define FP_T(x) R (*x)($for j , [[P$j]])
template <class R$for j [[,
class P$j]]>
Functor$i<FP_T(NONAME), R$for j [[, P$j]]>
Bind(FP_T(function)$for j [[,
typename detail::identity<P$j>::type p$j]]) {
return Functor$i<FP_T(NONAME), R$for j [[, P$j]]>(
function$for j [[, p$j]]);
}
#undef FP_T
]]
} // namespace rtc
#undef NONAME
#endif // WEBRTC_BASE_BIND_H_

Просмотреть файл

@ -0,0 +1,67 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/bind.h"
#include "webrtc/base/gunit.h"
namespace rtc {
namespace {
struct MethodBindTester {
void NullaryVoid() { ++call_count; }
int NullaryInt() { ++call_count; return 1; }
int NullaryConst() const { ++call_count; return 2; }
void UnaryVoid(int dummy) { ++call_count; }
template <class T> T Identity(T value) { ++call_count; return value; }
int UnaryByRef(int& value) const { ++call_count; return ++value; } // NOLINT
int Multiply(int a, int b) const { ++call_count; return a * b; }
mutable int call_count;
};
int Return42() { return 42; }
int Negate(int a) { return -a; }
int Multiply(int a, int b) { return a * b; }
} // namespace
TEST(BindTest, BindToMethod) {
MethodBindTester object = {0};
EXPECT_EQ(0, object.call_count);
Bind(&MethodBindTester::NullaryVoid, &object)();
EXPECT_EQ(1, object.call_count);
EXPECT_EQ(1, Bind(&MethodBindTester::NullaryInt, &object)());
EXPECT_EQ(2, object.call_count);
EXPECT_EQ(2, Bind(&MethodBindTester::NullaryConst,
static_cast<const MethodBindTester*>(&object))());
EXPECT_EQ(3, object.call_count);
Bind(&MethodBindTester::UnaryVoid, &object, 5)();
EXPECT_EQ(4, object.call_count);
EXPECT_EQ(100, Bind(&MethodBindTester::Identity<int>, &object, 100)());
EXPECT_EQ(5, object.call_count);
const std::string string_value("test string");
EXPECT_EQ(string_value, Bind(&MethodBindTester::Identity<std::string>,
&object, string_value)());
EXPECT_EQ(6, object.call_count);
int value = 11;
EXPECT_EQ(12, Bind(&MethodBindTester::UnaryByRef, &object, value)());
EXPECT_EQ(12, value);
EXPECT_EQ(7, object.call_count);
EXPECT_EQ(56, Bind(&MethodBindTester::Multiply, &object, 7, 8)());
EXPECT_EQ(8, object.call_count);
}
TEST(BindTest, BindToFunction) {
EXPECT_EQ(42, Bind(&Return42)());
EXPECT_EQ(3, Bind(&Negate, -3)());
EXPECT_EQ(56, Bind(&Multiply, 8, 7)());
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,102 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_BUFFER_H_
#define WEBRTC_BASE_BUFFER_H_
#include <string.h>
#include "webrtc/base/scoped_ptr.h"
namespace rtc {
// Basic buffer class, can be grown and shrunk dynamically.
// Unlike std::string/vector, does not initialize data when expanding capacity.
class Buffer {
public:
Buffer() {
Construct(NULL, 0, 0);
}
Buffer(const void* data, size_t length) {
Construct(data, length, length);
}
Buffer(const void* data, size_t length, size_t capacity) {
Construct(data, length, capacity);
}
Buffer(const Buffer& buf) {
Construct(buf.data(), buf.length(), buf.length());
}
const char* data() const { return data_.get(); }
char* data() { return data_.get(); }
// TODO: should this be size(), like STL?
size_t length() const { return length_; }
size_t capacity() const { return capacity_; }
Buffer& operator=(const Buffer& buf) {
if (&buf != this) {
Construct(buf.data(), buf.length(), buf.length());
}
return *this;
}
bool operator==(const Buffer& buf) const {
return (length_ == buf.length() &&
memcmp(data_.get(), buf.data(), length_) == 0);
}
bool operator!=(const Buffer& buf) const {
return !operator==(buf);
}
void SetData(const void* data, size_t length) {
ASSERT(data != NULL || length == 0);
SetLength(length);
memcpy(data_.get(), data, length);
}
void AppendData(const void* data, size_t length) {
ASSERT(data != NULL || length == 0);
size_t old_length = length_;
SetLength(length_ + length);
memcpy(data_.get() + old_length, data, length);
}
void SetLength(size_t length) {
SetCapacity(length);
length_ = length;
}
void SetCapacity(size_t capacity) {
if (capacity > capacity_) {
rtc::scoped_ptr<char[]> data(new char[capacity]);
memcpy(data.get(), data_.get(), length_);
data_.swap(data);
capacity_ = capacity;
}
}
void TransferTo(Buffer* buf) {
ASSERT(buf != NULL);
buf->data_.reset(data_.release());
buf->length_ = length_;
buf->capacity_ = capacity_;
Construct(NULL, 0, 0);
}
protected:
void Construct(const void* data, size_t length, size_t capacity) {
data_.reset(new char[capacity_ = capacity]);
SetData(data, length);
}
scoped_ptr<char[]> data_;
size_t length_;
size_t capacity_;
};
} // namespace rtc
#endif // WEBRTC_BASE_BUFFER_H_

Просмотреть файл

@ -0,0 +1,143 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/buffer.h"
#include "webrtc/base/gunit.h"
namespace rtc {
static const char kTestData[] = {
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF
};
TEST(BufferTest, TestConstructDefault) {
Buffer buf;
EXPECT_EQ(0U, buf.length());
EXPECT_EQ(0U, buf.capacity());
EXPECT_EQ(Buffer(), buf);
}
TEST(BufferTest, TestConstructEmptyWithCapacity) {
Buffer buf(NULL, 0, 256U);
EXPECT_EQ(0U, buf.length());
EXPECT_EQ(256U, buf.capacity());
EXPECT_EQ(Buffer(), buf);
}
TEST(BufferTest, TestConstructData) {
Buffer buf(kTestData, sizeof(kTestData));
EXPECT_EQ(sizeof(kTestData), buf.length());
EXPECT_EQ(sizeof(kTestData), buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData)));
EXPECT_EQ(Buffer(kTestData, sizeof(kTestData)), buf);
}
TEST(BufferTest, TestConstructDataWithCapacity) {
Buffer buf(kTestData, sizeof(kTestData), 256U);
EXPECT_EQ(sizeof(kTestData), buf.length());
EXPECT_EQ(256U, buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData)));
EXPECT_EQ(Buffer(kTestData, sizeof(kTestData)), buf);
}
TEST(BufferTest, TestConstructCopy) {
Buffer buf1(kTestData, sizeof(kTestData), 256), buf2(buf1);
EXPECT_EQ(sizeof(kTestData), buf2.length());
EXPECT_EQ(sizeof(kTestData), buf2.capacity()); // capacity isn't copied
EXPECT_EQ(0, memcmp(buf2.data(), kTestData, sizeof(kTestData)));
EXPECT_EQ(buf1, buf2);
}
TEST(BufferTest, TestAssign) {
Buffer buf1, buf2(kTestData, sizeof(kTestData), 256);
EXPECT_NE(buf1, buf2);
buf1 = buf2;
EXPECT_EQ(sizeof(kTestData), buf1.length());
EXPECT_EQ(sizeof(kTestData), buf1.capacity()); // capacity isn't copied
EXPECT_EQ(0, memcmp(buf1.data(), kTestData, sizeof(kTestData)));
EXPECT_EQ(buf1, buf2);
}
TEST(BufferTest, TestSetData) {
Buffer buf;
buf.SetData(kTestData, sizeof(kTestData));
EXPECT_EQ(sizeof(kTestData), buf.length());
EXPECT_EQ(sizeof(kTestData), buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData)));
}
TEST(BufferTest, TestAppendData) {
Buffer buf(kTestData, sizeof(kTestData));
buf.AppendData(kTestData, sizeof(kTestData));
EXPECT_EQ(2 * sizeof(kTestData), buf.length());
EXPECT_EQ(2 * sizeof(kTestData), buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData)));
EXPECT_EQ(0, memcmp(buf.data() + sizeof(kTestData),
kTestData, sizeof(kTestData)));
}
TEST(BufferTest, TestSetLengthSmaller) {
Buffer buf;
buf.SetData(kTestData, sizeof(kTestData));
buf.SetLength(sizeof(kTestData) / 2);
EXPECT_EQ(sizeof(kTestData) / 2, buf.length());
EXPECT_EQ(sizeof(kTestData), buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData) / 2));
}
TEST(BufferTest, TestSetLengthLarger) {
Buffer buf;
buf.SetData(kTestData, sizeof(kTestData));
buf.SetLength(sizeof(kTestData) * 2);
EXPECT_EQ(sizeof(kTestData) * 2, buf.length());
EXPECT_EQ(sizeof(kTestData) * 2, buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData)));
}
TEST(BufferTest, TestSetCapacitySmaller) {
Buffer buf;
buf.SetData(kTestData, sizeof(kTestData));
buf.SetCapacity(sizeof(kTestData) / 2); // should be ignored
EXPECT_EQ(sizeof(kTestData), buf.length());
EXPECT_EQ(sizeof(kTestData), buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData)));
}
TEST(BufferTest, TestSetCapacityLarger) {
Buffer buf(kTestData, sizeof(kTestData));
buf.SetCapacity(sizeof(kTestData) * 2);
EXPECT_EQ(sizeof(kTestData), buf.length());
EXPECT_EQ(sizeof(kTestData) * 2, buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData)));
}
TEST(BufferTest, TestSetCapacityThenSetLength) {
Buffer buf(kTestData, sizeof(kTestData));
buf.SetCapacity(sizeof(kTestData) * 4);
memcpy(buf.data() + sizeof(kTestData), kTestData, sizeof(kTestData));
buf.SetLength(sizeof(kTestData) * 2);
EXPECT_EQ(sizeof(kTestData) * 2, buf.length());
EXPECT_EQ(sizeof(kTestData) * 4, buf.capacity());
EXPECT_EQ(0, memcmp(buf.data(), kTestData, sizeof(kTestData)));
EXPECT_EQ(0, memcmp(buf.data() + sizeof(kTestData),
kTestData, sizeof(kTestData)));
}
TEST(BufferTest, TestTransfer) {
Buffer buf1(kTestData, sizeof(kTestData), 256U), buf2;
buf1.TransferTo(&buf2);
EXPECT_EQ(0U, buf1.length());
EXPECT_EQ(0U, buf1.capacity());
EXPECT_EQ(sizeof(kTestData), buf2.length());
EXPECT_EQ(256U, buf2.capacity()); // capacity does transfer
EXPECT_EQ(0, memcmp(buf2.data(), kTestData, sizeof(kTestData)));
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,234 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/bytebuffer.h"
#include <assert.h>
#include <string.h>
#include <algorithm>
#include "webrtc/base/basictypes.h"
#include "webrtc/base/byteorder.h"
namespace rtc {
static const int DEFAULT_SIZE = 4096;
ByteBuffer::ByteBuffer() {
Construct(NULL, DEFAULT_SIZE, ORDER_NETWORK);
}
ByteBuffer::ByteBuffer(ByteOrder byte_order) {
Construct(NULL, DEFAULT_SIZE, byte_order);
}
ByteBuffer::ByteBuffer(const char* bytes, size_t len) {
Construct(bytes, len, ORDER_NETWORK);
}
ByteBuffer::ByteBuffer(const char* bytes, size_t len, ByteOrder byte_order) {
Construct(bytes, len, byte_order);
}
ByteBuffer::ByteBuffer(const char* bytes) {
Construct(bytes, strlen(bytes), ORDER_NETWORK);
}
void ByteBuffer::Construct(const char* bytes, size_t len,
ByteOrder byte_order) {
version_ = 0;
start_ = 0;
size_ = len;
byte_order_ = byte_order;
bytes_ = new char[size_];
if (bytes) {
end_ = len;
memcpy(bytes_, bytes, end_);
} else {
end_ = 0;
}
}
ByteBuffer::~ByteBuffer() {
delete[] bytes_;
}
bool ByteBuffer::ReadUInt8(uint8* val) {
if (!val) return false;
return ReadBytes(reinterpret_cast<char*>(val), 1);
}
bool ByteBuffer::ReadUInt16(uint16* val) {
if (!val) return false;
uint16 v;
if (!ReadBytes(reinterpret_cast<char*>(&v), 2)) {
return false;
} else {
*val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost16(v) : v;
return true;
}
}
bool ByteBuffer::ReadUInt24(uint32* val) {
if (!val) return false;
uint32 v = 0;
char* read_into = reinterpret_cast<char*>(&v);
if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) {
++read_into;
}
if (!ReadBytes(read_into, 3)) {
return false;
} else {
*val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v;
return true;
}
}
bool ByteBuffer::ReadUInt32(uint32* val) {
if (!val) return false;
uint32 v;
if (!ReadBytes(reinterpret_cast<char*>(&v), 4)) {
return false;
} else {
*val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v;
return true;
}
}
bool ByteBuffer::ReadUInt64(uint64* val) {
if (!val) return false;
uint64 v;
if (!ReadBytes(reinterpret_cast<char*>(&v), 8)) {
return false;
} else {
*val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost64(v) : v;
return true;
}
}
bool ByteBuffer::ReadString(std::string* val, size_t len) {
if (!val) return false;
if (len > Length()) {
return false;
} else {
val->append(bytes_ + start_, len);
start_ += len;
return true;
}
}
bool ByteBuffer::ReadBytes(char* val, size_t len) {
if (len > Length()) {
return false;
} else {
memcpy(val, bytes_ + start_, len);
start_ += len;
return true;
}
}
void ByteBuffer::WriteUInt8(uint8 val) {
WriteBytes(reinterpret_cast<const char*>(&val), 1);
}
void ByteBuffer::WriteUInt16(uint16 val) {
uint16 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork16(val) : val;
WriteBytes(reinterpret_cast<const char*>(&v), 2);
}
void ByteBuffer::WriteUInt24(uint32 val) {
uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val;
char* start = reinterpret_cast<char*>(&v);
if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) {
++start;
}
WriteBytes(start, 3);
}
void ByteBuffer::WriteUInt32(uint32 val) {
uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val;
WriteBytes(reinterpret_cast<const char*>(&v), 4);
}
void ByteBuffer::WriteUInt64(uint64 val) {
uint64 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork64(val) : val;
WriteBytes(reinterpret_cast<const char*>(&v), 8);
}
void ByteBuffer::WriteString(const std::string& val) {
WriteBytes(val.c_str(), val.size());
}
void ByteBuffer::WriteBytes(const char* val, size_t len) {
memcpy(ReserveWriteBuffer(len), val, len);
}
char* ByteBuffer::ReserveWriteBuffer(size_t len) {
if (Length() + len > Capacity())
Resize(Length() + len);
char* start = bytes_ + end_;
end_ += len;
return start;
}
void ByteBuffer::Resize(size_t size) {
size_t len = _min(end_ - start_, size);
if (size <= size_) {
// Don't reallocate, just move data backwards
memmove(bytes_, bytes_ + start_, len);
} else {
// Reallocate a larger buffer.
size_ = _max(size, 3 * size_ / 2);
char* new_bytes = new char[size_];
memcpy(new_bytes, bytes_ + start_, len);
delete [] bytes_;
bytes_ = new_bytes;
}
start_ = 0;
end_ = len;
++version_;
}
bool ByteBuffer::Consume(size_t size) {
if (size > Length())
return false;
start_ += size;
return true;
}
ByteBuffer::ReadPosition ByteBuffer::GetReadPosition() const {
return ReadPosition(start_, version_);
}
bool ByteBuffer::SetReadPosition(const ReadPosition &position) {
if (position.version_ != version_) {
return false;
}
start_ = position.start_;
return true;
}
void ByteBuffer::Clear() {
memset(bytes_, 0, size_);
start_ = end_ = 0;
++version_;
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,119 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_BYTEBUFFER_H_
#define WEBRTC_BASE_BYTEBUFFER_H_
#include <string>
#include "webrtc/base/basictypes.h"
#include "webrtc/base/constructormagic.h"
namespace rtc {
class ByteBuffer {
public:
enum ByteOrder {
ORDER_NETWORK = 0, // Default, use network byte order (big endian).
ORDER_HOST, // Use the native order of the host.
};
// |byte_order| defines order of bytes in the buffer.
ByteBuffer();
explicit ByteBuffer(ByteOrder byte_order);
ByteBuffer(const char* bytes, size_t len);
ByteBuffer(const char* bytes, size_t len, ByteOrder byte_order);
// Initializes buffer from a zero-terminated string.
explicit ByteBuffer(const char* bytes);
~ByteBuffer();
const char* Data() const { return bytes_ + start_; }
size_t Length() const { return end_ - start_; }
size_t Capacity() const { return size_ - start_; }
ByteOrder Order() const { return byte_order_; }
// Read a next value from the buffer. Return false if there isn't
// enough data left for the specified type.
bool ReadUInt8(uint8* val);
bool ReadUInt16(uint16* val);
bool ReadUInt24(uint32* val);
bool ReadUInt32(uint32* val);
bool ReadUInt64(uint64* val);
bool ReadBytes(char* val, size_t len);
// Appends next |len| bytes from the buffer to |val|. Returns false
// if there is less than |len| bytes left.
bool ReadString(std::string* val, size_t len);
// Write value to the buffer. Resizes the buffer when it is
// neccessary.
void WriteUInt8(uint8 val);
void WriteUInt16(uint16 val);
void WriteUInt24(uint32 val);
void WriteUInt32(uint32 val);
void WriteUInt64(uint64 val);
void WriteString(const std::string& val);
void WriteBytes(const char* val, size_t len);
// Reserves the given number of bytes and returns a char* that can be written
// into. Useful for functions that require a char* buffer and not a
// ByteBuffer.
char* ReserveWriteBuffer(size_t len);
// Resize the buffer to the specified |size|. This invalidates any remembered
// seek positions.
void Resize(size_t size);
// Moves current position |size| bytes forward. Returns false if
// there is less than |size| bytes left in the buffer. Consume doesn't
// permanently remove data, so remembered read positions are still valid
// after this call.
bool Consume(size_t size);
// Clears the contents of the buffer. After this, Length() will be 0.
void Clear();
// Used with GetReadPosition/SetReadPosition.
class ReadPosition {
friend class ByteBuffer;
ReadPosition(size_t start, int version)
: start_(start), version_(version) { }
size_t start_;
int version_;
};
// Remembers the current read position for a future SetReadPosition. Any
// calls to Shift or Resize in the interim will invalidate the position.
ReadPosition GetReadPosition() const;
// If the given position is still valid, restores that read position.
bool SetReadPosition(const ReadPosition &position);
private:
void Construct(const char* bytes, size_t size, ByteOrder byte_order);
char* bytes_;
size_t size_;
size_t start_;
size_t end_;
int version_;
ByteOrder byte_order_;
// There are sensible ways to define these, but they aren't needed in our code
// base.
DISALLOW_COPY_AND_ASSIGN(ByteBuffer);
};
} // namespace rtc
#endif // WEBRTC_BASE_BYTEBUFFER_H_

Просмотреть файл

@ -0,0 +1,211 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/bytebuffer.h"
#include "webrtc/base/byteorder.h"
#include "webrtc/base/common.h"
#include "webrtc/base/gunit.h"
namespace rtc {
TEST(ByteBufferTest, TestByteOrder) {
uint16 n16 = 1;
uint32 n32 = 1;
uint64 n64 = 1;
EXPECT_EQ(n16, NetworkToHost16(HostToNetwork16(n16)));
EXPECT_EQ(n32, NetworkToHost32(HostToNetwork32(n32)));
EXPECT_EQ(n64, NetworkToHost64(HostToNetwork64(n64)));
if (IsHostBigEndian()) {
// The host is the network (big) endian.
EXPECT_EQ(n16, HostToNetwork16(n16));
EXPECT_EQ(n32, HostToNetwork32(n32));
EXPECT_EQ(n64, HostToNetwork64(n64));
// GetBE converts big endian to little endian here.
EXPECT_EQ(n16 >> 8, GetBE16(&n16));
EXPECT_EQ(n32 >> 24, GetBE32(&n32));
EXPECT_EQ(n64 >> 56, GetBE64(&n64));
} else {
// The host is little endian.
EXPECT_NE(n16, HostToNetwork16(n16));
EXPECT_NE(n32, HostToNetwork32(n32));
EXPECT_NE(n64, HostToNetwork64(n64));
// GetBE converts little endian to big endian here.
EXPECT_EQ(GetBE16(&n16), HostToNetwork16(n16));
EXPECT_EQ(GetBE32(&n32), HostToNetwork32(n32));
EXPECT_EQ(GetBE64(&n64), HostToNetwork64(n64));
// GetBE converts little endian to big endian here.
EXPECT_EQ(n16 << 8, GetBE16(&n16));
EXPECT_EQ(n32 << 24, GetBE32(&n32));
EXPECT_EQ(n64 << 56, GetBE64(&n64));
}
}
TEST(ByteBufferTest, TestBufferLength) {
ByteBuffer buffer;
size_t size = 0;
EXPECT_EQ(size, buffer.Length());
buffer.WriteUInt8(1);
++size;
EXPECT_EQ(size, buffer.Length());
buffer.WriteUInt16(1);
size += 2;
EXPECT_EQ(size, buffer.Length());
buffer.WriteUInt24(1);
size += 3;
EXPECT_EQ(size, buffer.Length());
buffer.WriteUInt32(1);
size += 4;
EXPECT_EQ(size, buffer.Length());
buffer.WriteUInt64(1);
size += 8;
EXPECT_EQ(size, buffer.Length());
EXPECT_TRUE(buffer.Consume(0));
EXPECT_EQ(size, buffer.Length());
EXPECT_TRUE(buffer.Consume(4));
size -= 4;
EXPECT_EQ(size, buffer.Length());
}
TEST(ByteBufferTest, TestGetSetReadPosition) {
ByteBuffer buffer("ABCDEF", 6);
EXPECT_EQ(6U, buffer.Length());
ByteBuffer::ReadPosition pos(buffer.GetReadPosition());
EXPECT_TRUE(buffer.SetReadPosition(pos));
EXPECT_EQ(6U, buffer.Length());
std::string read;
EXPECT_TRUE(buffer.ReadString(&read, 3));
EXPECT_EQ("ABC", read);
EXPECT_EQ(3U, buffer.Length());
EXPECT_TRUE(buffer.SetReadPosition(pos));
EXPECT_EQ(6U, buffer.Length());
read.clear();
EXPECT_TRUE(buffer.ReadString(&read, 3));
EXPECT_EQ("ABC", read);
EXPECT_EQ(3U, buffer.Length());
// For a resize by writing Capacity() number of bytes.
size_t capacity = buffer.Capacity();
buffer.ReserveWriteBuffer(buffer.Capacity());
EXPECT_EQ(capacity + 3U, buffer.Length());
EXPECT_FALSE(buffer.SetReadPosition(pos));
read.clear();
EXPECT_TRUE(buffer.ReadString(&read, 3));
EXPECT_EQ("DEF", read);
}
TEST(ByteBufferTest, TestReadWriteBuffer) {
ByteBuffer::ByteOrder orders[2] = { ByteBuffer::ORDER_HOST,
ByteBuffer::ORDER_NETWORK };
for (size_t i = 0; i < ARRAY_SIZE(orders); i++) {
ByteBuffer buffer(orders[i]);
EXPECT_EQ(orders[i], buffer.Order());
uint8 ru8;
EXPECT_FALSE(buffer.ReadUInt8(&ru8));
// Write and read uint8.
uint8 wu8 = 1;
buffer.WriteUInt8(wu8);
EXPECT_TRUE(buffer.ReadUInt8(&ru8));
EXPECT_EQ(wu8, ru8);
EXPECT_EQ(0U, buffer.Length());
// Write and read uint16.
uint16 wu16 = (1 << 8) + 1;
buffer.WriteUInt16(wu16);
uint16 ru16;
EXPECT_TRUE(buffer.ReadUInt16(&ru16));
EXPECT_EQ(wu16, ru16);
EXPECT_EQ(0U, buffer.Length());
// Write and read uint24.
uint32 wu24 = (3 << 16) + (2 << 8) + 1;
buffer.WriteUInt24(wu24);
uint32 ru24;
EXPECT_TRUE(buffer.ReadUInt24(&ru24));
EXPECT_EQ(wu24, ru24);
EXPECT_EQ(0U, buffer.Length());
// Write and read uint32.
uint32 wu32 = (4 << 24) + (3 << 16) + (2 << 8) + 1;
buffer.WriteUInt32(wu32);
uint32 ru32;
EXPECT_TRUE(buffer.ReadUInt32(&ru32));
EXPECT_EQ(wu32, ru32);
EXPECT_EQ(0U, buffer.Length());
// Write and read uint64.
uint32 another32 = (8 << 24) + (7 << 16) + (6 << 8) + 5;
uint64 wu64 = (static_cast<uint64>(another32) << 32) + wu32;
buffer.WriteUInt64(wu64);
uint64 ru64;
EXPECT_TRUE(buffer.ReadUInt64(&ru64));
EXPECT_EQ(wu64, ru64);
EXPECT_EQ(0U, buffer.Length());
// Write and read string.
std::string write_string("hello");
buffer.WriteString(write_string);
std::string read_string;
EXPECT_TRUE(buffer.ReadString(&read_string, write_string.size()));
EXPECT_EQ(write_string, read_string);
EXPECT_EQ(0U, buffer.Length());
// Write and read bytes
char write_bytes[] = "foo";
buffer.WriteBytes(write_bytes, 3);
char read_bytes[3];
EXPECT_TRUE(buffer.ReadBytes(read_bytes, 3));
for (int i = 0; i < 3; ++i) {
EXPECT_EQ(write_bytes[i], read_bytes[i]);
}
EXPECT_EQ(0U, buffer.Length());
// Write and read reserved buffer space
char* write_dst = buffer.ReserveWriteBuffer(3);
memcpy(write_dst, write_bytes, 3);
memset(read_bytes, 0, 3);
EXPECT_TRUE(buffer.ReadBytes(read_bytes, 3));
for (int i = 0; i < 3; ++i) {
EXPECT_EQ(write_bytes[i], read_bytes[i]);
}
EXPECT_EQ(0U, buffer.Length());
// Write and read in order.
buffer.WriteUInt8(wu8);
buffer.WriteUInt16(wu16);
buffer.WriteUInt24(wu24);
buffer.WriteUInt32(wu32);
buffer.WriteUInt64(wu64);
EXPECT_TRUE(buffer.ReadUInt8(&ru8));
EXPECT_EQ(wu8, ru8);
EXPECT_TRUE(buffer.ReadUInt16(&ru16));
EXPECT_EQ(wu16, ru16);
EXPECT_TRUE(buffer.ReadUInt24(&ru24));
EXPECT_EQ(wu24, ru24);
EXPECT_TRUE(buffer.ReadUInt32(&ru32));
EXPECT_EQ(wu32, ru32);
EXPECT_TRUE(buffer.ReadUInt64(&ru64));
EXPECT_EQ(wu64, ru64);
EXPECT_EQ(0U, buffer.Length());
}
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,168 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_BYTEORDER_H_
#define WEBRTC_BASE_BYTEORDER_H_
#if defined(WEBRTC_POSIX) && !defined(__native_client__)
#include <arpa/inet.h>
#endif
#if defined(WEBRTC_WIN)
#include <stdlib.h>
#endif
#include "webrtc/base/basictypes.h"
namespace rtc {
// Reading and writing of little and big-endian numbers from memory
// TODO: Optimized versions, with direct read/writes of
// integers in host-endian format, when the platform supports it.
inline void Set8(void* memory, size_t offset, uint8 v) {
static_cast<uint8*>(memory)[offset] = v;
}
inline uint8 Get8(const void* memory, size_t offset) {
return static_cast<const uint8*>(memory)[offset];
}
inline void SetBE16(void* memory, uint16 v) {
Set8(memory, 0, static_cast<uint8>(v >> 8));
Set8(memory, 1, static_cast<uint8>(v >> 0));
}
inline void SetBE32(void* memory, uint32 v) {
Set8(memory, 0, static_cast<uint8>(v >> 24));
Set8(memory, 1, static_cast<uint8>(v >> 16));
Set8(memory, 2, static_cast<uint8>(v >> 8));
Set8(memory, 3, static_cast<uint8>(v >> 0));
}
inline void SetBE64(void* memory, uint64 v) {
Set8(memory, 0, static_cast<uint8>(v >> 56));
Set8(memory, 1, static_cast<uint8>(v >> 48));
Set8(memory, 2, static_cast<uint8>(v >> 40));
Set8(memory, 3, static_cast<uint8>(v >> 32));
Set8(memory, 4, static_cast<uint8>(v >> 24));
Set8(memory, 5, static_cast<uint8>(v >> 16));
Set8(memory, 6, static_cast<uint8>(v >> 8));
Set8(memory, 7, static_cast<uint8>(v >> 0));
}
inline uint16 GetBE16(const void* memory) {
return static_cast<uint16>((Get8(memory, 0) << 8) |
(Get8(memory, 1) << 0));
}
inline uint32 GetBE32(const void* memory) {
return (static_cast<uint32>(Get8(memory, 0)) << 24) |
(static_cast<uint32>(Get8(memory, 1)) << 16) |
(static_cast<uint32>(Get8(memory, 2)) << 8) |
(static_cast<uint32>(Get8(memory, 3)) << 0);
}
inline uint64 GetBE64(const void* memory) {
return (static_cast<uint64>(Get8(memory, 0)) << 56) |
(static_cast<uint64>(Get8(memory, 1)) << 48) |
(static_cast<uint64>(Get8(memory, 2)) << 40) |
(static_cast<uint64>(Get8(memory, 3)) << 32) |
(static_cast<uint64>(Get8(memory, 4)) << 24) |
(static_cast<uint64>(Get8(memory, 5)) << 16) |
(static_cast<uint64>(Get8(memory, 6)) << 8) |
(static_cast<uint64>(Get8(memory, 7)) << 0);
}
inline void SetLE16(void* memory, uint16 v) {
Set8(memory, 0, static_cast<uint8>(v >> 0));
Set8(memory, 1, static_cast<uint8>(v >> 8));
}
inline void SetLE32(void* memory, uint32 v) {
Set8(memory, 0, static_cast<uint8>(v >> 0));
Set8(memory, 1, static_cast<uint8>(v >> 8));
Set8(memory, 2, static_cast<uint8>(v >> 16));
Set8(memory, 3, static_cast<uint8>(v >> 24));
}
inline void SetLE64(void* memory, uint64 v) {
Set8(memory, 0, static_cast<uint8>(v >> 0));
Set8(memory, 1, static_cast<uint8>(v >> 8));
Set8(memory, 2, static_cast<uint8>(v >> 16));
Set8(memory, 3, static_cast<uint8>(v >> 24));
Set8(memory, 4, static_cast<uint8>(v >> 32));
Set8(memory, 5, static_cast<uint8>(v >> 40));
Set8(memory, 6, static_cast<uint8>(v >> 48));
Set8(memory, 7, static_cast<uint8>(v >> 56));
}
inline uint16 GetLE16(const void* memory) {
return static_cast<uint16>((Get8(memory, 0) << 0) |
(Get8(memory, 1) << 8));
}
inline uint32 GetLE32(const void* memory) {
return (static_cast<uint32>(Get8(memory, 0)) << 0) |
(static_cast<uint32>(Get8(memory, 1)) << 8) |
(static_cast<uint32>(Get8(memory, 2)) << 16) |
(static_cast<uint32>(Get8(memory, 3)) << 24);
}
inline uint64 GetLE64(const void* memory) {
return (static_cast<uint64>(Get8(memory, 0)) << 0) |
(static_cast<uint64>(Get8(memory, 1)) << 8) |
(static_cast<uint64>(Get8(memory, 2)) << 16) |
(static_cast<uint64>(Get8(memory, 3)) << 24) |
(static_cast<uint64>(Get8(memory, 4)) << 32) |
(static_cast<uint64>(Get8(memory, 5)) << 40) |
(static_cast<uint64>(Get8(memory, 6)) << 48) |
(static_cast<uint64>(Get8(memory, 7)) << 56);
}
// Check if the current host is big endian.
inline bool IsHostBigEndian() {
static const int number = 1;
return 0 == *reinterpret_cast<const char*>(&number);
}
inline uint16 HostToNetwork16(uint16 n) {
uint16 result;
SetBE16(&result, n);
return result;
}
inline uint32 HostToNetwork32(uint32 n) {
uint32 result;
SetBE32(&result, n);
return result;
}
inline uint64 HostToNetwork64(uint64 n) {
uint64 result;
SetBE64(&result, n);
return result;
}
inline uint16 NetworkToHost16(uint16 n) {
return GetBE16(&n);
}
inline uint32 NetworkToHost32(uint32 n) {
return GetBE32(&n);
}
inline uint64 NetworkToHost64(uint64 n) {
return GetBE64(&n);
}
} // namespace rtc
#endif // WEBRTC_BASE_BYTEORDER_H_

Просмотреть файл

@ -0,0 +1,83 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/byteorder.h"
#include "webrtc/base/basictypes.h"
#include "webrtc/base/gunit.h"
namespace rtc {
// Test memory set functions put values into memory in expected order.
TEST(ByteOrderTest, TestSet) {
uint8 buf[8] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u };
Set8(buf, 0, 0xfb);
Set8(buf, 1, 0x12);
EXPECT_EQ(0xfb, buf[0]);
EXPECT_EQ(0x12, buf[1]);
SetBE16(buf, 0x1234);
EXPECT_EQ(0x12, buf[0]);
EXPECT_EQ(0x34, buf[1]);
SetLE16(buf, 0x1234);
EXPECT_EQ(0x34, buf[0]);
EXPECT_EQ(0x12, buf[1]);
SetBE32(buf, 0x12345678);
EXPECT_EQ(0x12, buf[0]);
EXPECT_EQ(0x34, buf[1]);
EXPECT_EQ(0x56, buf[2]);
EXPECT_EQ(0x78, buf[3]);
SetLE32(buf, 0x12345678);
EXPECT_EQ(0x78, buf[0]);
EXPECT_EQ(0x56, buf[1]);
EXPECT_EQ(0x34, buf[2]);
EXPECT_EQ(0x12, buf[3]);
SetBE64(buf, UINT64_C(0x0123456789abcdef));
EXPECT_EQ(0x01, buf[0]);
EXPECT_EQ(0x23, buf[1]);
EXPECT_EQ(0x45, buf[2]);
EXPECT_EQ(0x67, buf[3]);
EXPECT_EQ(0x89, buf[4]);
EXPECT_EQ(0xab, buf[5]);
EXPECT_EQ(0xcd, buf[6]);
EXPECT_EQ(0xef, buf[7]);
SetLE64(buf, UINT64_C(0x0123456789abcdef));
EXPECT_EQ(0xef, buf[0]);
EXPECT_EQ(0xcd, buf[1]);
EXPECT_EQ(0xab, buf[2]);
EXPECT_EQ(0x89, buf[3]);
EXPECT_EQ(0x67, buf[4]);
EXPECT_EQ(0x45, buf[5]);
EXPECT_EQ(0x23, buf[6]);
EXPECT_EQ(0x01, buf[7]);
}
// Test memory get functions get values from memory in expected order.
TEST(ByteOrderTest, TestGet) {
uint8 buf[8];
buf[0] = 0x01u;
buf[1] = 0x23u;
buf[2] = 0x45u;
buf[3] = 0x67u;
buf[4] = 0x89u;
buf[5] = 0xabu;
buf[6] = 0xcdu;
buf[7] = 0xefu;
EXPECT_EQ(0x01u, Get8(buf, 0));
EXPECT_EQ(0x23u, Get8(buf, 1));
EXPECT_EQ(0x0123u, GetBE16(buf));
EXPECT_EQ(0x2301u, GetLE16(buf));
EXPECT_EQ(0x01234567u, GetBE32(buf));
EXPECT_EQ(0x67452301u, GetLE32(buf));
EXPECT_EQ(UINT64_C(0x0123456789abcdef), GetBE64(buf));
EXPECT_EQ(UINT64_C(0xefcdab8967452301), GetLE64(buf));
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,261 @@
// This file was GENERATED by command:
// pump.py callback.h.pump
// DO NOT EDIT BY HAND!!!
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// To generate callback.h from callback.h.pump, execute:
// /home/build/google3/third_party/gtest/scripts/pump.py callback.h.pump
// Callbacks are callable object containers. They can hold a function pointer
// or a function object and behave like a value type. Internally, data is
// reference-counted, making copies and pass-by-value inexpensive.
//
// Callbacks are typed using template arguments. The format is:
// CallbackN<ReturnType, ParamType1, ..., ParamTypeN>
// where N is the number of arguments supplied to the callable object.
// Callbacks are invoked using operator(), just like a function or a function
// object. Default-constructed callbacks are "empty," and executing an empty
// callback does nothing. A callback can be made empty by assigning it from
// a default-constructed callback.
//
// Callbacks are similar in purpose to std::function (which isn't available on
// all platforms we support) and a lightweight alternative to sigslots. Since
// they effectively hide the type of the object they call, they're useful in
// breaking dependencies between objects that need to interact with one another.
// Notably, they can hold the results of Bind(), std::bind*, etc, without
// needing
// to know the resulting object type of those calls.
//
// Sigslots, on the other hand, provide a fuller feature set, such as multiple
// subscriptions to a signal, optional thread-safety, and lifetime tracking of
// slots. When these features are needed, choose sigslots.
//
// Example:
// int sqr(int x) { return x * x; }
// struct AddK {
// int k;
// int operator()(int x) const { return x + k; }
// } add_k = {5};
//
// Callback1<int, int> my_callback;
// cout << my_callback.empty() << endl; // true
//
// my_callback = Callback1<int, int>(&sqr);
// cout << my_callback.empty() << endl; // false
// cout << my_callback(3) << endl; // 9
//
// my_callback = Callback1<int, int>(add_k);
// cout << my_callback(10) << endl; // 15
//
// my_callback = Callback1<int, int>();
// cout << my_callback.empty() << endl; // true
#ifndef WEBRTC_BASE_CALLBACK_H_
#define WEBRTC_BASE_CALLBACK_H_
#include "webrtc/base/logging.h"
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ref_ptr.h"
namespace rtc {
template <class R>
class Callback0 {
public:
// Default copy operations are appropriate for this class.
Callback0() {}
template <class T> Callback0(const T& functor)
: helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
R operator()() {
if (empty())
return R();
return helper_->Run();
}
bool empty() const { return !helper_; }
private:
struct Helper : RefCountInterface {
virtual ~Helper() {}
virtual R Run() = 0;
};
template <class T> struct HelperImpl : Helper {
explicit HelperImpl(const T& functor) : functor_(functor) {}
virtual R Run() {
return functor_();
}
T functor_;
};
scoped_refptr<Helper> helper_;
};
template <class R,
class P1>
class Callback1 {
public:
// Default copy operations are appropriate for this class.
Callback1() {}
template <class T> Callback1(const T& functor)
: helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
R operator()(P1 p1) {
if (empty())
return R();
return helper_->Run(p1);
}
bool empty() const { return !helper_; }
private:
struct Helper : RefCountInterface {
virtual ~Helper() {}
virtual R Run(P1 p1) = 0;
};
template <class T> struct HelperImpl : Helper {
explicit HelperImpl(const T& functor) : functor_(functor) {}
virtual R Run(P1 p1) {
return functor_(p1);
}
T functor_;
};
scoped_refptr<Helper> helper_;
};
template <class R,
class P1,
class P2>
class Callback2 {
public:
// Default copy operations are appropriate for this class.
Callback2() {}
template <class T> Callback2(const T& functor)
: helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
R operator()(P1 p1, P2 p2) {
if (empty())
return R();
return helper_->Run(p1, p2);
}
bool empty() const { return !helper_; }
private:
struct Helper : RefCountInterface {
virtual ~Helper() {}
virtual R Run(P1 p1, P2 p2) = 0;
};
template <class T> struct HelperImpl : Helper {
explicit HelperImpl(const T& functor) : functor_(functor) {}
virtual R Run(P1 p1, P2 p2) {
return functor_(p1, p2);
}
T functor_;
};
scoped_refptr<Helper> helper_;
};
template <class R,
class P1,
class P2,
class P3>
class Callback3 {
public:
// Default copy operations are appropriate for this class.
Callback3() {}
template <class T> Callback3(const T& functor)
: helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
R operator()(P1 p1, P2 p2, P3 p3) {
if (empty())
return R();
return helper_->Run(p1, p2, p3);
}
bool empty() const { return !helper_; }
private:
struct Helper : RefCountInterface {
virtual ~Helper() {}
virtual R Run(P1 p1, P2 p2, P3 p3) = 0;
};
template <class T> struct HelperImpl : Helper {
explicit HelperImpl(const T& functor) : functor_(functor) {}
virtual R Run(P1 p1, P2 p2, P3 p3) {
return functor_(p1, p2, p3);
}
T functor_;
};
scoped_refptr<Helper> helper_;
};
template <class R,
class P1,
class P2,
class P3,
class P4>
class Callback4 {
public:
// Default copy operations are appropriate for this class.
Callback4() {}
template <class T> Callback4(const T& functor)
: helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
R operator()(P1 p1, P2 p2, P3 p3, P4 p4) {
if (empty())
return R();
return helper_->Run(p1, p2, p3, p4);
}
bool empty() const { return !helper_; }
private:
struct Helper : RefCountInterface {
virtual ~Helper() {}
virtual R Run(P1 p1, P2 p2, P3 p3, P4 p4) = 0;
};
template <class T> struct HelperImpl : Helper {
explicit HelperImpl(const T& functor) : functor_(functor) {}
virtual R Run(P1 p1, P2 p2, P3 p3, P4 p4) {
return functor_(p1, p2, p3, p4);
}
T functor_;
};
scoped_refptr<Helper> helper_;
};
template <class R,
class P1,
class P2,
class P3,
class P4,
class P5>
class Callback5 {
public:
// Default copy operations are appropriate for this class.
Callback5() {}
template <class T> Callback5(const T& functor)
: helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
if (empty())
return R();
return helper_->Run(p1, p2, p3, p4, p5);
}
bool empty() const { return !helper_; }
private:
struct Helper : RefCountInterface {
virtual ~Helper() {}
virtual R Run(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) = 0;
};
template <class T> struct HelperImpl : Helper {
explicit HelperImpl(const T& functor) : functor_(functor) {}
virtual R Run(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
return functor_(p1, p2, p3, p4, p5);
}
T functor_;
};
scoped_refptr<Helper> helper_;
};
} // namespace rtc
#endif // WEBRTC_BASE_CALLBACK_H_

Просмотреть файл

@ -0,0 +1,103 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// To generate callback.h from callback.h.pump, execute:
// /home/build/google3/third_party/gtest/scripts/pump.py callback.h.pump
// Callbacks are callable object containers. They can hold a function pointer
// or a function object and behave like a value type. Internally, data is
// reference-counted, making copies and pass-by-value inexpensive.
//
// Callbacks are typed using template arguments. The format is:
// CallbackN<ReturnType, ParamType1, ..., ParamTypeN>
// where N is the number of arguments supplied to the callable object.
// Callbacks are invoked using operator(), just like a function or a function
// object. Default-constructed callbacks are "empty," and executing an empty
// callback does nothing. A callback can be made empty by assigning it from
// a default-constructed callback.
//
// Callbacks are similar in purpose to std::function (which isn't available on
// all platforms we support) and a lightweight alternative to sigslots. Since
// they effectively hide the type of the object they call, they're useful in
// breaking dependencies between objects that need to interact with one another.
// Notably, they can hold the results of Bind(), std::bind*, etc, without needing
// to know the resulting object type of those calls.
//
// Sigslots, on the other hand, provide a fuller feature set, such as multiple
// subscriptions to a signal, optional thread-safety, and lifetime tracking of
// slots. When these features are needed, choose sigslots.
//
// Example:
// int sqr(int x) { return x * x; }
// struct AddK {
// int k;
// int operator()(int x) const { return x + k; }
// } add_k = {5};
//
// Callback1<int, int> my_callback;
// cout << my_callback.empty() << endl; // true
//
// my_callback = Callback1<int, int>(&sqr);
// cout << my_callback.empty() << endl; // false
// cout << my_callback(3) << endl; // 9
//
// my_callback = Callback1<int, int>(add_k);
// cout << my_callback(10) << endl; // 15
//
// my_callback = Callback1<int, int>();
// cout << my_callback.empty() << endl; // true
#ifndef WEBRTC_BASE_CALLBACK_H_
#define WEBRTC_BASE_CALLBACK_H_
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ref_ptr.h"
namespace rtc {
$var n = 5
$range i 0..n
$for i [[
$range j 1..i
template <class R$for j [[,
class P$j]]>
class Callback$i {
public:
// Default copy operations are appropriate for this class.
Callback$i() {}
template <class T> Callback$i(const T& functor)
: helper_(new RefCountedObject< HelperImpl<T> >(functor)) {}
R operator()($for j , [[P$j p$j]]) {
if (empty())
return R();
return helper_->Run($for j , [[p$j]]);
}
bool empty() const { return !helper_; }
private:
struct Helper : RefCountInterface {
virtual ~Helper() {}
virtual R Run($for j , [[P$j p$j]]) = 0;
};
template <class T> struct HelperImpl : Helper {
explicit HelperImpl(const T& functor) : functor_(functor) {}
virtual R Run($for j , [[P$j p$j]]) {
return functor_($for j , [[p$j]]);
}
T functor_;
};
scoped_refptr<Helper> helper_;
};
]]
} // namespace rtc
#endif // WEBRTC_BASE_CALLBACK_H_

Просмотреть файл

@ -0,0 +1,81 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/bind.h"
#include "webrtc/base/callback.h"
#include "webrtc/base/gunit.h"
namespace rtc {
namespace {
void f() {}
int g() { return 42; }
int h(int x) { return x * x; }
void i(int& x) { x *= x; } // NOLINT: Testing refs
struct BindTester {
int a() { return 24; }
int b(int x) const { return x * x; }
};
} // namespace
TEST(CallbackTest, VoidReturn) {
Callback0<void> cb;
EXPECT_TRUE(cb.empty());
cb(); // Executing an empty callback should not crash.
cb = Callback0<void>(&f);
EXPECT_FALSE(cb.empty());
cb();
}
TEST(CallbackTest, IntReturn) {
Callback0<int> cb;
EXPECT_TRUE(cb.empty());
cb = Callback0<int>(&g);
EXPECT_FALSE(cb.empty());
EXPECT_EQ(42, cb());
EXPECT_EQ(42, cb());
}
TEST(CallbackTest, OneParam) {
Callback1<int, int> cb1(&h);
EXPECT_FALSE(cb1.empty());
EXPECT_EQ(9, cb1(-3));
EXPECT_EQ(100, cb1(10));
// Try clearing a callback.
cb1 = Callback1<int, int>();
EXPECT_TRUE(cb1.empty());
// Try a callback with a ref parameter.
Callback1<void, int&> cb2(&i);
int x = 3;
cb2(x);
EXPECT_EQ(9, x);
cb2(x);
EXPECT_EQ(81, x);
}
TEST(CallbackTest, WithBind) {
BindTester t;
Callback0<int> cb1 = Bind(&BindTester::a, &t);
EXPECT_EQ(24, cb1());
EXPECT_EQ(24, cb1());
cb1 = Bind(&BindTester::b, &t, 10);
EXPECT_EQ(100, cb1());
EXPECT_EQ(100, cb1());
cb1 = Bind(&BindTester::b, &t, 5);
EXPECT_EQ(25, cb1());
EXPECT_EQ(25, cb1());
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,132 @@
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Most of this was borrowed (with minor modifications) from V8's and Chromium's
// src/base/logging.cc.
// Use the C++ version to provide __GLIBCXX__.
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#if defined(__GLIBCXX__) && !defined(__UCLIBC__)
#include <cxxabi.h>
#include <execinfo.h>
#endif
#if defined(WEBRTC_ANDROID)
#define LOG_TAG "rtc"
#include <android/log.h> // NOLINT
#endif
#include "webrtc/base/checks.h"
#if defined(_MSC_VER)
// Warning C4722: destructor never returns, potential memory leak.
// FatalMessage's dtor very intentionally aborts.
#pragma warning(disable:4722)
#endif
namespace rtc {
void VPrintError(const char* format, va_list args) {
#if defined(WEBRTC_ANDROID)
__android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
#else
vfprintf(stderr, format, args);
#endif
}
void PrintError(const char* format, ...) {
va_list args;
va_start(args, format);
VPrintError(format, args);
va_end(args);
}
// TODO(ajm): This works on Mac (although the parsing fails) but I don't seem
// to get usable symbols on Linux. This is copied from V8. Chromium has a more
// advanced stace trace system; also more difficult to copy.
void DumpBacktrace() {
#if defined(__GLIBCXX__) && !defined(__UCLIBC__)
void* trace[100];
int size = backtrace(trace, sizeof(trace) / sizeof(*trace));
char** symbols = backtrace_symbols(trace, size);
PrintError("\n==== C stack trace ===============================\n\n");
if (size == 0) {
PrintError("(empty)\n");
} else if (symbols == NULL) {
PrintError("(no symbols)\n");
} else {
for (int i = 1; i < size; ++i) {
char mangled[201];
if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT
PrintError("%2d: ", i);
int status;
size_t length;
char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
PrintError("%s\n", demangled != NULL ? demangled : mangled);
free(demangled);
} else {
// If parsing failed, at least print the unparsed symbol.
PrintError("%s\n", symbols[i]);
}
}
}
free(symbols);
#endif
}
FatalMessage::FatalMessage(const char* file, int line) {
Init(file, line);
}
FatalMessage::FatalMessage(const char* file, int line, std::string* result) {
Init(file, line);
stream_ << "Check failed: " << *result << std::endl << "# ";
delete result;
}
NO_RETURN FatalMessage::~FatalMessage() {
fflush(stdout);
fflush(stderr);
stream_ << std::endl << "#" << std::endl;
PrintError(stream_.str().c_str());
DumpBacktrace();
fflush(stderr);
abort();
}
void FatalMessage::Init(const char* file, int line) {
stream_ << std::endl << std::endl << "#" << std::endl << "# Fatal error in "
<< file << ", line " << line << std::endl << "# ";
}
// Refer to comments in checks.h.
#ifndef WEBRTC_CHROMIUM_BUILD
// MSVC doesn't like complex extern templates and DLLs.
#if !defined(COMPILER_MSVC)
// Explicit instantiations for commonly used comparisons.
template std::string* MakeCheckOpString<int, int>(
const int&, const int&, const char* names);
template std::string* MakeCheckOpString<unsigned long, unsigned long>(
const unsigned long&, const unsigned long&, const char* names);
template std::string* MakeCheckOpString<unsigned long, unsigned int>(
const unsigned long&, const unsigned int&, const char* names);
template std::string* MakeCheckOpString<unsigned int, unsigned long>(
const unsigned int&, const unsigned long&, const char* names);
template std::string* MakeCheckOpString<std::string, std::string>(
const std::string&, const std::string&, const char* name);
#endif
#endif // WEBRTC_CHROMIUM_BUILD
} // namespace rtc

Просмотреть файл

@ -0,0 +1,216 @@
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_CHECKS_H_
#define WEBRTC_BASE_CHECKS_H_
#include <sstream>
#include <string>
#ifdef WEBRTC_CHROMIUM_BUILD
// Include logging.h in a Chromium build to enable the overrides mechanism for
// using Chromium's macros. Otherwise, don't depend on logging.h.
// TODO(ajm): Ideally, checks.h would be combined with logging.h, but
// consolidation with system_wrappers/logging.h should happen first.
#include "webrtc/base/logging.h"
#endif
#include "webrtc/typedefs.h"
// The macros here print a message to stderr and abort under various
// conditions. All will accept additional stream messages. For example:
// DCHECK_EQ(foo, bar) << "I'm printed when foo != bar.";
//
// - CHECK(x) is an assertion that x is always true, and that if it isn't, it's
// better to terminate the process than to continue. During development, the
// reason that it's better to terminate might simply be that the error
// handling code isn't in place yet; in production, the reason might be that
// the author of the code truly believes that x will always be true, but that
// she recognizes that if she is wrong, abrupt and unpleasant process
// termination is still better than carrying on with the assumption violated.
//
// CHECK always evaluates its argument, so it's OK for x to have side
// effects.
//
// - DCHECK(x) is the same as CHECK(x)---an assertion that x is always
// true---except that x will only be evaluated in debug builds; in production
// builds, x is simply assumed to be true. This is useful if evaluating x is
// expensive and the expected cost of failing to detect the violated
// assumption is acceptable. You should not handle cases where a production
// build fails to spot a violated condition, even those that would result in
// crashes. If the code needs to cope with the error, make it cope, but don't
// call DCHECK; if the condition really can't occur, but you'd sleep better
// at night knowing that the process will suicide instead of carrying on in
// case you were wrong, use CHECK instead of DCHECK.
//
// DCHECK only evaluates its argument in debug builds, so if x has visible
// side effects, you need to write e.g.
// bool w = x; DCHECK(w);
//
// - CHECK_EQ, _NE, _GT, ..., and DCHECK_EQ, _NE, _GT, ... are specialized
// variants of CHECK and DCHECK that print prettier messages if the condition
// doesn't hold. Prefer them to raw CHECK and DCHECK.
//
// - FATAL() aborts unconditionally.
namespace rtc {
// The use of overrides/webrtc/base/logging.h in a Chromium build results in
// redefined macro errors. Fortunately, Chromium's macros can be used as drop-in
// replacements for the standalone versions.
#ifndef WEBRTC_CHROMIUM_BUILD
// Helper macro which avoids evaluating the arguments to a stream if
// the condition doesn't hold.
#define LAZY_STREAM(stream, condition) \
!(condition) ? static_cast<void>(0) : rtc::FatalMessageVoidify() & (stream)
// The actual stream used isn't important.
#define EAT_STREAM_PARAMETERS \
true ? static_cast<void>(0) \
: rtc::FatalMessageVoidify() & rtc::FatalMessage("", 0).stream()
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode.
//
// We make sure CHECK et al. always evaluates their arguments, as
// doing CHECK(FunctionWithSideEffect()) is a common idiom.
#define CHECK(condition) \
LAZY_STREAM(rtc::FatalMessage(__FILE__, __LINE__).stream(), !(condition)) \
<< "Check failed: " #condition << std::endl << "# "
// Helper macro for binary operators.
// Don't use this macro directly in your code, use CHECK_EQ et al below.
//
// TODO(akalin): Rewrite this so that constructs like if (...)
// CHECK_EQ(...) else { ... } work properly.
#define CHECK_OP(name, op, val1, val2) \
if (std::string* _result = \
rtc::Check##name##Impl((val1), (val2), \
#val1 " " #op " " #val2)) \
rtc::FatalMessage(__FILE__, __LINE__, _result).stream()
// Build the error message string. This is separate from the "Impl"
// function template because it is not performance critical and so can
// be out of line, while the "Impl" code should be inline. Caller
// takes ownership of the returned string.
template<class t1, class t2>
std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
std::ostringstream ss;
ss << names << " (" << v1 << " vs. " << v2 << ")";
std::string* msg = new std::string(ss.str());
return msg;
}
// MSVC doesn't like complex extern templates and DLLs.
#if !defined(COMPILER_MSVC)
// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated
// in logging.cc.
extern template std::string* MakeCheckOpString<int, int>(
const int&, const int&, const char* names);
extern template
std::string* MakeCheckOpString<unsigned long, unsigned long>(
const unsigned long&, const unsigned long&, const char* names);
extern template
std::string* MakeCheckOpString<unsigned long, unsigned int>(
const unsigned long&, const unsigned int&, const char* names);
extern template
std::string* MakeCheckOpString<unsigned int, unsigned long>(
const unsigned int&, const unsigned long&, const char* names);
extern template
std::string* MakeCheckOpString<std::string, std::string>(
const std::string&, const std::string&, const char* name);
#endif
// Helper functions for CHECK_OP macro.
// The (int, int) specialization works around the issue that the compiler
// will not instantiate the template version of the function on values of
// unnamed enum type - see comment below.
#define DEFINE_CHECK_OP_IMPL(name, op) \
template <class t1, class t2> \
inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
const char* names) { \
if (v1 op v2) return NULL; \
else return rtc::MakeCheckOpString(v1, v2, names); \
} \
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
if (v1 op v2) return NULL; \
else return rtc::MakeCheckOpString(v1, v2, names); \
}
DEFINE_CHECK_OP_IMPL(EQ, ==)
DEFINE_CHECK_OP_IMPL(NE, !=)
DEFINE_CHECK_OP_IMPL(LE, <=)
DEFINE_CHECK_OP_IMPL(LT, < )
DEFINE_CHECK_OP_IMPL(GE, >=)
DEFINE_CHECK_OP_IMPL(GT, > )
#undef DEFINE_CHECK_OP_IMPL
#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
// The DCHECK macro is equivalent to CHECK except that it only generates code in
// debug builds.
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
#define DCHECK(condition) CHECK(condition)
#define DCHECK_EQ(v1, v2) CHECK_EQ(v1, v2)
#define DCHECK_NE(v1, v2) CHECK_NE(v1, v2)
#define DCHECK_LE(v1, v2) CHECK_LE(v1, v2)
#define DCHECK_LT(v1, v2) CHECK_LT(v1, v2)
#define DCHECK_GE(v1, v2) CHECK_GE(v1, v2)
#define DCHECK_GT(v1, v2) CHECK_GT(v1, v2)
#else
#define DCHECK(condition) EAT_STREAM_PARAMETERS
#define DCHECK_EQ(v1, v2) EAT_STREAM_PARAMETERS
#define DCHECK_NE(v1, v2) EAT_STREAM_PARAMETERS
#define DCHECK_LE(v1, v2) EAT_STREAM_PARAMETERS
#define DCHECK_LT(v1, v2) EAT_STREAM_PARAMETERS
#define DCHECK_GE(v1, v2) EAT_STREAM_PARAMETERS
#define DCHECK_GT(v1, v2) EAT_STREAM_PARAMETERS
#endif
// This is identical to LogMessageVoidify but in name.
class FatalMessageVoidify {
public:
FatalMessageVoidify() { }
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(std::ostream&) { }
};
#endif // WEBRTC_CHROMIUM_BUILD
#define FATAL() rtc::FatalMessage(__FILE__, __LINE__).stream()
// TODO(ajm): Consider adding NOTIMPLEMENTED and NOTREACHED macros when
// base/logging.h and system_wrappers/logging.h are consolidated such that we
// can match the Chromium behavior.
// Like a stripped-down LogMessage from logging.h, except that it aborts.
class FatalMessage {
public:
FatalMessage(const char* file, int line);
// Used for CHECK_EQ(), etc. Takes ownership of the given string.
FatalMessage(const char* file, int line, std::string* result);
NO_RETURN ~FatalMessage();
std::ostream& stream() { return stream_; }
private:
void Init(const char* file, int line);
std::ostringstream stream_;
};
} // namespace rtc
#endif // WEBRTC_BASE_CHECKS_H_

Просмотреть файл

@ -0,0 +1,72 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if WEBRTC_WIN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif // WEBRTC_WIN
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
#include <CoreServices/CoreServices.h>
#endif // WEBRTC_MAC && !defined(WEBRTC_IOS)
#include <algorithm>
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
//////////////////////////////////////////////////////////////////////
// Assertions
//////////////////////////////////////////////////////////////////////
namespace rtc {
void Break() {
#if WEBRTC_WIN
::DebugBreak();
#else // !WEBRTC_WIN
// On POSIX systems, SIGTRAP signals debuggers to break without killing the
// process. If a debugger isn't attached, the uncaught SIGTRAP will crash the
// app.
raise(SIGTRAP);
#endif
// If a debugger wasn't attached, we will have crashed by this point. If a
// debugger is attached, we'll continue from here.
}
static AssertLogger custom_assert_logger_ = NULL;
void SetCustomAssertLogger(AssertLogger logger) {
custom_assert_logger_ = logger;
}
void LogAssert(const char* function, const char* file, int line,
const char* expression) {
if (custom_assert_logger_) {
custom_assert_logger_(function, file, line, expression);
} else {
LOG(LS_ERROR) << file << "(" << line << ")" << ": ASSERT FAILED: "
<< expression << " @ " << function;
}
}
bool IsOdd(int n) {
return (n & 0x1);
}
bool IsEven(int n) {
return !IsOdd(n);
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,227 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_COMMON_H_ // NOLINT
#define WEBRTC_BASE_COMMON_H_
#include "webrtc/base/basictypes.h"
#include "webrtc/base/constructormagic.h"
#if defined(_MSC_VER)
// warning C4355: 'this' : used in base member initializer list
#pragma warning(disable:4355)
#endif
//////////////////////////////////////////////////////////////////////
// General Utilities
//////////////////////////////////////////////////////////////////////
#ifndef RTC_UNUSED
#define RTC_UNUSED(x) RtcUnused(static_cast<const void*>(&x))
#define RTC_UNUSED2(x, y) RtcUnused(static_cast<const void*>(&x)); \
RtcUnused(static_cast<const void*>(&y))
#define RTC_UNUSED3(x, y, z) RtcUnused(static_cast<const void*>(&x)); \
RtcUnused(static_cast<const void*>(&y)); \
RtcUnused(static_cast<const void*>(&z))
#define RTC_UNUSED4(x, y, z, a) RtcUnused(static_cast<const void*>(&x)); \
RtcUnused(static_cast<const void*>(&y)); \
RtcUnused(static_cast<const void*>(&z)); \
RtcUnused(static_cast<const void*>(&a))
#define RTC_UNUSED5(x, y, z, a, b) RtcUnused(static_cast<const void*>(&x)); \
RtcUnused(static_cast<const void*>(&y)); \
RtcUnused(static_cast<const void*>(&z)); \
RtcUnused(static_cast<const void*>(&a)); \
RtcUnused(static_cast<const void*>(&b))
inline void RtcUnused(const void*) {}
#endif // RTC_UNUSED
#if !defined(WEBRTC_WIN)
#ifndef strnicmp
#define strnicmp(x, y, n) strncasecmp(x, y, n)
#endif
#ifndef stricmp
#define stricmp(x, y) strcasecmp(x, y)
#endif
// TODO(fbarchard): Remove this. std::max should be used everywhere in the code.
// NOMINMAX must be defined where we include <windows.h>.
#define stdmax(x, y) std::max(x, y)
#else
#define stdmax(x, y) rtc::_max(x, y)
#endif
#define ARRAY_SIZE(x) (static_cast<int>(sizeof(x) / sizeof(x[0])))
/////////////////////////////////////////////////////////////////////////////
// Assertions
/////////////////////////////////////////////////////////////////////////////
#ifndef ENABLE_DEBUG
#define ENABLE_DEBUG _DEBUG
#endif // !defined(ENABLE_DEBUG)
// Even for release builds, allow for the override of LogAssert. Though no
// macro is provided, this can still be used for explicit runtime asserts
// and allow applications to override the assert behavior.
namespace rtc {
// If a debugger is attached, triggers a debugger breakpoint. If a debugger is
// not attached, forces program termination.
void Break();
// LogAssert writes information about an assertion to the log. It's called by
// Assert (and from the ASSERT macro in debug mode) before any other action
// is taken (e.g. breaking the debugger, abort()ing, etc.).
void LogAssert(const char* function, const char* file, int line,
const char* expression);
typedef void (*AssertLogger)(const char* function,
const char* file,
int line,
const char* expression);
// Sets a custom assert logger to be used instead of the default LogAssert
// behavior. To clear the custom assert logger, pass NULL for |logger| and the
// default behavior will be restored. Only one custom assert logger can be set
// at a time, so this should generally be set during application startup and
// only by one component.
void SetCustomAssertLogger(AssertLogger logger);
bool IsOdd(int n);
bool IsEven(int n);
} // namespace rtc
#if ENABLE_DEBUG
namespace rtc {
inline bool Assert(bool result, const char* function, const char* file,
int line, const char* expression) {
if (!result) {
LogAssert(function, file, line, expression);
Break();
}
return result;
}
// Same as Assert above, but does not call Break(). Used in assert macros
// that implement their own breaking.
inline bool AssertNoBreak(bool result, const char* function, const char* file,
int line, const char* expression) {
if (!result)
LogAssert(function, file, line, expression);
return result;
}
} // namespace rtc
#if defined(_MSC_VER) && _MSC_VER < 1300
#define __FUNCTION__ ""
#endif
#ifndef ASSERT
#if defined(WIN32)
// Using debugbreak() inline on Windows directly in the ASSERT macro, has the
// benefit of breaking exactly where the failing expression is and not two
// calls up the stack.
#define ASSERT(x) \
(rtc::AssertNoBreak((x), __FUNCTION__, __FILE__, __LINE__, #x) ? \
(void)(1) : __debugbreak())
#else
#define ASSERT(x) \
(void)rtc::Assert((x), __FUNCTION__, __FILE__, __LINE__, #x)
#endif
#endif
#ifndef VERIFY
#if defined(WIN32)
#define VERIFY(x) \
(rtc::AssertNoBreak((x), __FUNCTION__, __FILE__, __LINE__, #x) ? \
true : (__debugbreak(), false))
#else
#define VERIFY(x) rtc::Assert((x), __FUNCTION__, __FILE__, __LINE__, #x)
#endif
#endif
#else // !ENABLE_DEBUG
namespace rtc {
inline bool ImplicitCastToBool(bool result) { return result; }
} // namespace rtc
#ifndef ASSERT
#define ASSERT(x) (void)0
#endif
#ifndef VERIFY
#define VERIFY(x) rtc::ImplicitCastToBool(x)
#endif
#endif // !ENABLE_DEBUG
#define COMPILE_TIME_ASSERT(expr) char CTA_UNIQUE_NAME[expr]
#define CTA_UNIQUE_NAME CTA_MAKE_NAME(__LINE__)
#define CTA_MAKE_NAME(line) CTA_MAKE_NAME2(line)
#define CTA_MAKE_NAME2(line) constraint_ ## line
// Forces compiler to inline, even against its better judgement. Use wisely.
#if defined(__GNUC__)
#define FORCE_INLINE __attribute__((always_inline))
#elif defined(WEBRTC_WIN)
#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE
#endif
// Borrowed from Chromium's base/compiler_specific.h.
// Annotate a virtual method indicating it must be overriding a virtual
// method in the parent class.
// Use like:
// virtual void foo() OVERRIDE;
#if defined(WEBRTC_WIN)
#define OVERRIDE override
#elif defined(__clang__)
// Clang defaults to C++03 and warns about using override. Squelch that.
// Intentionally no push/pop here so all users of OVERRIDE ignore the warning
// too. This is like passing -Wno-c++11-extensions, except that GCC won't die
// (because it won't see this pragma).
#pragma clang diagnostic ignored "-Wc++11-extensions"
#define OVERRIDE override
#elif defined(__GNUC__) && __cplusplus >= 201103 && \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700
// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled.
#define OVERRIDE override
#else
#define OVERRIDE
#endif
// Annotate a function indicating the caller must examine the return value.
// Use like:
// int foo() WARN_UNUSED_RESULT;
// To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>.
// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and
// libjingle are merged.
#if !defined(WARN_UNUSED_RESULT)
#if defined(__GNUC__)
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define WARN_UNUSED_RESULT
#endif
#endif // WARN_UNUSED_RESULT
#endif // WEBRTC_BASE_COMMON_H_ // NOLINT

Просмотреть файл

@ -0,0 +1,82 @@
/*
* Copyright 2013 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// COMPILE_ASSERT macro, borrowed from google3/base/macros.h.
#ifndef WEBRTC_BASE_COMPILE_ASSERT_H_
#define WEBRTC_BASE_COMPILE_ASSERT_H_
// The COMPILE_ASSERT macro can be used to verify that a compile time
// expression is true. For example, you could use it to verify the
// size of a static array:
//
// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
// content_type_names_incorrect_size);
//
// or to make sure a struct is smaller than a certain size:
//
// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
//
// The second argument to the macro is the name of the variable. If
// the expression is false, most compilers will issue a warning/error
// containing the name of the variable.
// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and
// libjingle are merged.
#if !defined(COMPILE_ASSERT)
template <bool>
struct CompileAssert {
};
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] // NOLINT
#endif // COMPILE_ASSERT
// Implementation details of COMPILE_ASSERT:
//
// - COMPILE_ASSERT works by defining an array type that has -1
// elements (and thus is invalid) when the expression is false.
//
// - The simpler definition
//
// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
//
// does not work, as gcc supports variable-length arrays whose sizes
// are determined at run-time (this is gcc's extension and not part
// of the C++ standard). As a result, gcc fails to reject the
// following code with the simple definition:
//
// int foo;
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
// // not a compile-time constant.
//
// - By using the type CompileAssert<(bool(expr))>, we ensures that
// expr is a compile-time constant. (Template arguments must be
// determined at compile-time.)
//
// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
//
// CompileAssert<bool(expr)>
//
// instead, these compilers will refuse to compile
//
// COMPILE_ASSERT(5 > 0, some_message);
//
// (They seem to think the ">" in "5 > 0" marks the end of the
// template argument list.)
//
// - The array size is (bool(expr) ? 1 : -1), instead of simply
//
// ((expr) ? 1 : -1).
//
// This is to avoid running into a bug in MS VC 7.1, which
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
#endif // WEBRTC_BASE_COMPILE_ASSERT_H_

Просмотреть файл

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@ -8,43 +8,38 @@
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* WebRtc
* Copy from third_party/libjingle/source/talk/base/constructormagic.h
*/
#ifndef WEBRTC_BASE_CONSTRUCTORMAGIC_H_
#define WEBRTC_BASE_CONSTRUCTORMAGIC_H_
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_
// Undefine macros first, just in case. Some third-party includes have their own
// version.
#ifndef DISALLOW_ASSIGN
#undef DISALLOW_ASSIGN
#define DISALLOW_ASSIGN(TypeName) \
void operator=(const TypeName&)
#endif
#ifndef DISALLOW_COPY_AND_ASSIGN
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
// This should be used in the private: declarations for a class.
#undef DISALLOW_COPY_AND_ASSIGN
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
DISALLOW_ASSIGN(TypeName)
#endif
#ifndef DISALLOW_EVIL_CONSTRUCTORS
// Alternative, less-accurate legacy name.
#undef DISALLOW_EVIL_CONSTRUCTORS
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
DISALLOW_COPY_AND_ASSIGN(TypeName)
#endif
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#undef DISALLOW_IMPLICIT_CONSTRUCTORS
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
DISALLOW_EVIL_CONSTRUCTORS(TypeName)
#endif
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CONSTRUCTOR_MAGIC_H_
#endif // WEBRTC_BASE_CONSTRUCTORMAGIC_H_

Просмотреть файл

@ -0,0 +1,423 @@
/*
* Copyright 2010 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/cpumonitor.h"
#include <string>
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/systeminfo.h"
#include "webrtc/base/thread.h"
#include "webrtc/base/timeutils.h"
#if defined(WEBRTC_WIN)
#include "webrtc/base/win32.h"
#include <winternl.h>
#endif
#if defined(WEBRTC_POSIX)
#include <sys/time.h>
#endif
#if defined(WEBRTC_MAC)
#include <mach/mach_host.h>
#include <mach/mach_init.h>
#include <mach/mach_port.h>
#include <mach/host_info.h>
#include <mach/task.h>
#endif // defined(WEBRTC_MAC)
#if defined(WEBRTC_LINUX)
#include <sys/resource.h>
#include <errno.h>
#include <stdio.h>
#include "webrtc/base/fileutils.h"
#include "webrtc/base/pathutils.h"
#endif // defined(WEBRTC_LINUX)
#if defined(WEBRTC_MAC)
static uint64 TimeValueTToInt64(const time_value_t &time_value) {
return rtc::kNumMicrosecsPerSec * time_value.seconds +
time_value.microseconds;
}
#endif // defined(WEBRTC_MAC)
// How CpuSampler works
// When threads switch, the time they spent is accumulated to system counters.
// The time can be treated as user, kernel or idle.
// user time is applications.
// kernel time is the OS, including the thread switching code itself.
// typically kernel time indicates IO.
// idle time is a process that wastes time when nothing is ready to run.
//
// User time is broken down by process (application). One of the applications
// is the current process. When you add up all application times, this is
// system time. If only your application is running, system time should be the
// same as process time.
//
// All cores contribute to these accumulators. A dual core process is able to
// process twice as many cycles as a single core. The actual code efficiency
// may be worse, due to contention, but the available cycles is exactly twice
// as many, and the cpu load will reflect the efficiency. Hyperthreads behave
// the same way. The load will reflect 200%, but the actual amount of work
// completed will be much less than a true dual core.
//
// Total available performance is the sum of all accumulators.
// If you tracked this for 1 second, it would essentially give you the clock
// rate - number of cycles per second.
// Speed step / Turbo Boost is not considered, so infact more processing time
// may be available.
namespace rtc {
// Note Tests on Windows show 600 ms is minimum stable interval for Windows 7.
static const int32 kDefaultInterval = 950; // Slightly under 1 second.
CpuSampler::CpuSampler()
: min_load_interval_(kDefaultInterval)
#if defined(WEBRTC_WIN)
, get_system_times_(NULL),
nt_query_system_information_(NULL),
force_fallback_(false)
#endif
{
}
CpuSampler::~CpuSampler() {
}
// Set minimum interval in ms between computing new load values. Default 950.
void CpuSampler::set_load_interval(int min_load_interval) {
min_load_interval_ = min_load_interval;
}
bool CpuSampler::Init() {
sysinfo_.reset(new SystemInfo);
cpus_ = sysinfo_->GetMaxCpus();
if (cpus_ == 0) {
return false;
}
#if defined(WEBRTC_WIN)
// Note that GetSystemTimes is available in Windows XP SP1 or later.
// http://msdn.microsoft.com/en-us/library/ms724400.aspx
// NtQuerySystemInformation is used as a fallback.
if (!force_fallback_) {
get_system_times_ = GetProcAddress(GetModuleHandle(L"kernel32.dll"),
"GetSystemTimes");
}
nt_query_system_information_ = GetProcAddress(GetModuleHandle(L"ntdll.dll"),
"NtQuerySystemInformation");
if ((get_system_times_ == NULL) && (nt_query_system_information_ == NULL)) {
return false;
}
#endif
#if defined(WEBRTC_LINUX)
Pathname sname("/proc/stat");
sfile_.reset(Filesystem::OpenFile(sname, "rb"));
if (!sfile_) {
LOG_ERR(LS_ERROR) << "open proc/stat failed:";
return false;
}
if (!sfile_->DisableBuffering()) {
LOG_ERR(LS_ERROR) << "could not disable buffering for proc/stat";
return false;
}
#endif // defined(WEBRTC_LINUX)
GetProcessLoad(); // Initialize values.
GetSystemLoad();
// Help next user call return valid data by recomputing load.
process_.prev_load_time_ = 0u;
system_.prev_load_time_ = 0u;
return true;
}
float CpuSampler::UpdateCpuLoad(uint64 current_total_times,
uint64 current_cpu_times,
uint64 *prev_total_times,
uint64 *prev_cpu_times) {
float result = 0.f;
if (current_total_times < *prev_total_times ||
current_cpu_times < *prev_cpu_times) {
LOG(LS_ERROR) << "Inconsistent time values are passed. ignored";
} else {
const uint64 cpu_diff = current_cpu_times - *prev_cpu_times;
const uint64 total_diff = current_total_times - *prev_total_times;
result = (total_diff == 0ULL ? 0.f :
static_cast<float>(1.0f * cpu_diff / total_diff));
if (result > static_cast<float>(cpus_)) {
result = static_cast<float>(cpus_);
}
*prev_total_times = current_total_times;
*prev_cpu_times = current_cpu_times;
}
return result;
}
float CpuSampler::GetSystemLoad() {
uint32 timenow = Time();
int elapsed = static_cast<int>(TimeDiff(timenow, system_.prev_load_time_));
if (min_load_interval_ != 0 && system_.prev_load_time_ != 0u &&
elapsed < min_load_interval_) {
return system_.prev_load_;
}
#if defined(WEBRTC_WIN)
uint64 total_times, cpu_times;
typedef BOOL (_stdcall *GST_PROC)(LPFILETIME, LPFILETIME, LPFILETIME);
typedef NTSTATUS (WINAPI *QSI_PROC)(SYSTEM_INFORMATION_CLASS,
PVOID, ULONG, PULONG);
GST_PROC get_system_times = reinterpret_cast<GST_PROC>(get_system_times_);
QSI_PROC nt_query_system_information = reinterpret_cast<QSI_PROC>(
nt_query_system_information_);
if (get_system_times) {
FILETIME idle_time, kernel_time, user_time;
if (!get_system_times(&idle_time, &kernel_time, &user_time)) {
LOG(LS_ERROR) << "::GetSystemTimes() failed: " << ::GetLastError();
return 0.f;
}
// kernel_time includes Kernel idle time, so no need to
// include cpu_time as total_times
total_times = ToUInt64(kernel_time) + ToUInt64(user_time);
cpu_times = total_times - ToUInt64(idle_time);
} else {
if (nt_query_system_information) {
ULONG returned_length = 0;
scoped_ptr<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[]> processor_info(
new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[cpus_]);
nt_query_system_information(
::SystemProcessorPerformanceInformation,
reinterpret_cast<void*>(processor_info.get()),
cpus_ * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
&returned_length);
if (returned_length !=
(cpus_ * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION))) {
LOG(LS_ERROR) << "NtQuerySystemInformation has unexpected size";
return 0.f;
}
uint64 current_idle = 0;
uint64 current_kernel = 0;
uint64 current_user = 0;
for (int ix = 0; ix < cpus_; ++ix) {
current_idle += processor_info[ix].IdleTime.QuadPart;
current_kernel += processor_info[ix].UserTime.QuadPart;
current_user += processor_info[ix].KernelTime.QuadPart;
}
total_times = current_kernel + current_user;
cpu_times = total_times - current_idle;
} else {
return 0.f;
}
}
#endif // WEBRTC_WIN
#if defined(WEBRTC_MAC)
mach_port_t mach_host = mach_host_self();
host_cpu_load_info_data_t cpu_info;
mach_msg_type_number_t info_count = HOST_CPU_LOAD_INFO_COUNT;
kern_return_t kr = host_statistics(mach_host, HOST_CPU_LOAD_INFO,
reinterpret_cast<host_info_t>(&cpu_info),
&info_count);
mach_port_deallocate(mach_task_self(), mach_host);
if (KERN_SUCCESS != kr) {
LOG(LS_ERROR) << "::host_statistics() failed";
return 0.f;
}
const uint64 cpu_times = cpu_info.cpu_ticks[CPU_STATE_NICE] +
cpu_info.cpu_ticks[CPU_STATE_SYSTEM] +
cpu_info.cpu_ticks[CPU_STATE_USER];
const uint64 total_times = cpu_times + cpu_info.cpu_ticks[CPU_STATE_IDLE];
#endif // defined(WEBRTC_MAC)
#if defined(WEBRTC_LINUX)
if (!sfile_) {
LOG(LS_ERROR) << "Invalid handle for proc/stat";
return 0.f;
}
std::string statbuf;
sfile_->SetPosition(0);
if (!sfile_->ReadLine(&statbuf)) {
LOG_ERR(LS_ERROR) << "Could not read proc/stat file";
return 0.f;
}
unsigned long long user;
unsigned long long nice;
unsigned long long system;
unsigned long long idle;
if (sscanf(statbuf.c_str(), "cpu %Lu %Lu %Lu %Lu",
&user, &nice,
&system, &idle) != 4) {
LOG_ERR(LS_ERROR) << "Could not parse cpu info";
return 0.f;
}
const uint64 cpu_times = nice + system + user;
const uint64 total_times = cpu_times + idle;
#endif // defined(WEBRTC_LINUX)
#if defined(__native_client__)
// TODO(ryanpetrie): Implement this via PPAPI when it's available.
const uint64 cpu_times = 0;
const uint64 total_times = 0;
#endif // defined(__native_client__)
system_.prev_load_time_ = timenow;
system_.prev_load_ = UpdateCpuLoad(total_times,
cpu_times * cpus_,
&system_.prev_total_times_,
&system_.prev_cpu_times_);
return system_.prev_load_;
}
float CpuSampler::GetProcessLoad() {
uint32 timenow = Time();
int elapsed = static_cast<int>(TimeDiff(timenow, process_.prev_load_time_));
if (min_load_interval_ != 0 && process_.prev_load_time_ != 0u &&
elapsed < min_load_interval_) {
return process_.prev_load_;
}
#if defined(WEBRTC_WIN)
FILETIME current_file_time;
::GetSystemTimeAsFileTime(&current_file_time);
FILETIME create_time, exit_time, kernel_time, user_time;
if (!::GetProcessTimes(::GetCurrentProcess(),
&create_time, &exit_time, &kernel_time, &user_time)) {
LOG(LS_ERROR) << "::GetProcessTimes() failed: " << ::GetLastError();
return 0.f;
}
const uint64 total_times =
ToUInt64(current_file_time) - ToUInt64(create_time);
const uint64 cpu_times =
(ToUInt64(kernel_time) + ToUInt64(user_time));
#endif // WEBRTC_WIN
#if defined(WEBRTC_POSIX)
// Common to both OSX and Linux.
struct timeval tv;
gettimeofday(&tv, NULL);
const uint64 total_times = tv.tv_sec * kNumMicrosecsPerSec + tv.tv_usec;
#endif
#if defined(WEBRTC_MAC)
// Get live thread usage.
task_thread_times_info task_times_info;
mach_msg_type_number_t info_count = TASK_THREAD_TIMES_INFO_COUNT;
if (KERN_SUCCESS != task_info(mach_task_self(), TASK_THREAD_TIMES_INFO,
reinterpret_cast<task_info_t>(&task_times_info),
&info_count)) {
LOG(LS_ERROR) << "::task_info(TASK_THREAD_TIMES_INFO) failed";
return 0.f;
}
// Get terminated thread usage.
task_basic_info task_term_info;
info_count = TASK_BASIC_INFO_COUNT;
if (KERN_SUCCESS != task_info(mach_task_self(), TASK_BASIC_INFO,
reinterpret_cast<task_info_t>(&task_term_info),
&info_count)) {
LOG(LS_ERROR) << "::task_info(TASK_BASIC_INFO) failed";
return 0.f;
}
const uint64 cpu_times = (TimeValueTToInt64(task_times_info.user_time) +
TimeValueTToInt64(task_times_info.system_time) +
TimeValueTToInt64(task_term_info.user_time) +
TimeValueTToInt64(task_term_info.system_time));
#endif // defined(WEBRTC_MAC)
#if defined(WEBRTC_LINUX)
rusage usage;
if (getrusage(RUSAGE_SELF, &usage) < 0) {
LOG_ERR(LS_ERROR) << "getrusage failed";
return 0.f;
}
const uint64 cpu_times =
(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * kNumMicrosecsPerSec +
usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
#endif // defined(WEBRTC_LINUX)
#if defined(__native_client__)
// TODO(ryanpetrie): Implement this via PPAPI when it's available.
const uint64 cpu_times = 0;
#endif // defined(__native_client__)
process_.prev_load_time_ = timenow;
process_.prev_load_ = UpdateCpuLoad(total_times,
cpu_times,
&process_.prev_total_times_,
&process_.prev_cpu_times_);
return process_.prev_load_;
}
int CpuSampler::GetMaxCpus() const {
return cpus_;
}
int CpuSampler::GetCurrentCpus() {
return sysinfo_->GetCurCpus();
}
///////////////////////////////////////////////////////////////////
// Implementation of class CpuMonitor.
CpuMonitor::CpuMonitor(Thread* thread)
: monitor_thread_(thread) {
}
CpuMonitor::~CpuMonitor() {
Stop();
}
void CpuMonitor::set_thread(Thread* thread) {
ASSERT(monitor_thread_ == NULL || monitor_thread_ == thread);
monitor_thread_ = thread;
}
bool CpuMonitor::Start(int period_ms) {
if (!monitor_thread_ || !sampler_.Init()) return false;
monitor_thread_->SignalQueueDestroyed.connect(
this, &CpuMonitor::OnMessageQueueDestroyed);
period_ms_ = period_ms;
monitor_thread_->PostDelayed(period_ms_, this);
return true;
}
void CpuMonitor::Stop() {
if (monitor_thread_) {
monitor_thread_->Clear(this);
}
}
void CpuMonitor::OnMessage(Message* msg) {
int max_cpus = sampler_.GetMaxCpus();
int current_cpus = sampler_.GetCurrentCpus();
float process_load = sampler_.GetProcessLoad();
float system_load = sampler_.GetSystemLoad();
SignalUpdate(current_cpus, max_cpus, process_load, system_load);
if (monitor_thread_) {
monitor_thread_->PostDelayed(period_ms_, this);
}
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,123 @@
/*
* Copyright 2010 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_CPUMONITOR_H_
#define WEBRTC_BASE_CPUMONITOR_H_
#include "webrtc/base/basictypes.h"
#include "webrtc/base/messagehandler.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/sigslot.h"
#if defined(WEBRTC_LINUX)
#include "webrtc/base/stream.h"
#endif // defined(WEBRTC_LINUX)
namespace rtc {
class Thread;
class SystemInfo;
struct CpuStats {
CpuStats()
: prev_total_times_(0),
prev_cpu_times_(0),
prev_load_(0.f),
prev_load_time_(0u) {
}
uint64 prev_total_times_;
uint64 prev_cpu_times_;
float prev_load_; // Previous load value.
uint32 prev_load_time_; // Time previous load value was taken.
};
// CpuSampler samples the process and system load.
class CpuSampler {
public:
CpuSampler();
~CpuSampler();
// Initialize CpuSampler. Returns true if successful.
bool Init();
// Set minimum interval in ms between computing new load values.
// Default 950 ms. Set to 0 to disable interval.
void set_load_interval(int min_load_interval);
// Return CPU load of current process as a float from 0 to 1.
float GetProcessLoad();
// Return CPU load of current process as a float from 0 to 1.
float GetSystemLoad();
// Return number of cpus. Includes hyperthreads.
int GetMaxCpus() const;
// Return current number of cpus available to this process.
int GetCurrentCpus();
// For testing. Allows forcing of fallback to using NTDLL functions.
void set_force_fallback(bool fallback) {
#if defined(WEBRTC_WIN)
force_fallback_ = fallback;
#endif
}
private:
float UpdateCpuLoad(uint64 current_total_times,
uint64 current_cpu_times,
uint64 *prev_total_times,
uint64 *prev_cpu_times);
CpuStats process_;
CpuStats system_;
int cpus_;
int min_load_interval_; // Minimum time between computing new load.
scoped_ptr<SystemInfo> sysinfo_;
#if defined(WEBRTC_WIN)
void* get_system_times_;
void* nt_query_system_information_;
bool force_fallback_;
#endif
#if defined(WEBRTC_LINUX)
// File for reading /proc/stat
scoped_ptr<FileStream> sfile_;
#endif // defined(WEBRTC_LINUX)
};
// CpuMonitor samples and signals the CPU load periodically.
class CpuMonitor
: public rtc::MessageHandler, public sigslot::has_slots<> {
public:
explicit CpuMonitor(Thread* thread);
virtual ~CpuMonitor();
void set_thread(Thread* thread);
bool Start(int period_ms);
void Stop();
// Signal parameters are current cpus, max cpus, process load and system load.
sigslot::signal4<int, int, float, float> SignalUpdate;
protected:
// Override virtual method of parent MessageHandler.
virtual void OnMessage(rtc::Message* msg);
// Clear the monitor thread and stop sending it messages if the thread goes
// away before our lifetime.
void OnMessageQueueDestroyed() { monitor_thread_ = NULL; }
private:
Thread* monitor_thread_;
CpuSampler sampler_;
int period_ms_;
DISALLOW_COPY_AND_ASSIGN(CpuMonitor);
};
} // namespace rtc
#endif // WEBRTC_BASE_CPUMONITOR_H_

Просмотреть файл

@ -0,0 +1,389 @@
/*
* Copyright 2010 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <iomanip>
#include <iostream>
#include <vector>
#if defined(WEBRTC_WIN)
#include "webrtc/base/win32.h"
#endif
#include "webrtc/base/cpumonitor.h"
#include "webrtc/base/flags.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/base/timing.h"
#include "webrtc/test/testsupport/gtest_disable.h"
namespace rtc {
static const int kMaxCpus = 1024;
static const int kSettleTime = 100; // Amount of time to between tests.
static const int kIdleTime = 500; // Amount of time to be idle in ms.
static const int kBusyTime = 1000; // Amount of time to be busy in ms.
static const int kLongInterval = 2000; // Interval longer than busy times
class BusyThread : public rtc::Thread {
public:
BusyThread(double load, double duration, double interval) :
load_(load), duration_(duration), interval_(interval) {
}
virtual ~BusyThread() {
Stop();
}
void Run() {
Timing time;
double busy_time = interval_ * load_ / 100.0;
for (;;) {
time.BusyWait(busy_time);
time.IdleWait(interval_ - busy_time);
if (duration_) {
duration_ -= interval_;
if (duration_ <= 0) {
break;
}
}
}
}
private:
double load_;
double duration_;
double interval_;
};
class CpuLoadListener : public sigslot::has_slots<> {
public:
CpuLoadListener()
: current_cpus_(0),
cpus_(0),
process_load_(.0f),
system_load_(.0f),
count_(0) {
}
void OnCpuLoad(int current_cpus, int cpus, float proc_load, float sys_load) {
current_cpus_ = current_cpus;
cpus_ = cpus;
process_load_ = proc_load;
system_load_ = sys_load;
++count_;
}
int current_cpus() const { return current_cpus_; }
int cpus() const { return cpus_; }
float process_load() const { return process_load_; }
float system_load() const { return system_load_; }
int count() const { return count_; }
private:
int current_cpus_;
int cpus_;
float process_load_;
float system_load_;
int count_;
};
// Set affinity (which cpu to run on), but respecting FLAG_affinity:
// -1 means no affinity - run on whatever cpu is available.
// 0 .. N means run on specific cpu. The tool will create N threads and call
// SetThreadAffinity on 0 to N - 1 as cpu. FLAG_affinity sets the first cpu
// so the range becomes affinity to affinity + N - 1
// Note that this function affects Windows scheduling, effectively giving
// the thread with affinity for a specified CPU more priority on that CPU.
bool SetThreadAffinity(BusyThread* t, int cpu, int affinity) {
#if defined(WEBRTC_WIN)
if (affinity >= 0) {
return ::SetThreadAffinityMask(t->GetHandle(),
1 << (cpu + affinity)) != FALSE;
}
#endif
return true;
}
bool SetThreadPriority(BusyThread* t, int prio) {
if (!prio) {
return true;
}
bool ok = t->SetPriority(static_cast<rtc::ThreadPriority>(prio));
if (!ok) {
std::cout << "Error setting thread priority." << std::endl;
}
return ok;
}
int CpuLoad(double cpuload, double duration, int numthreads,
int priority, double interval, int affinity) {
int ret = 0;
std::vector<BusyThread*> threads;
for (int i = 0; i < numthreads; ++i) {
threads.push_back(new BusyThread(cpuload, duration, interval));
// NOTE(fbarchard): Priority must be done before Start.
if (!SetThreadPriority(threads[i], priority) ||
!threads[i]->Start() ||
!SetThreadAffinity(threads[i], i, affinity)) {
ret = 1;
break;
}
}
// Wait on each thread
if (ret == 0) {
for (int i = 0; i < numthreads; ++i) {
threads[i]->Stop();
}
}
for (int i = 0; i < numthreads; ++i) {
delete threads[i];
}
return ret;
}
// Make 2 CPUs busy
static void CpuTwoBusyLoop(int busytime) {
CpuLoad(100.0, busytime / 1000.0, 2, 1, 0.050, -1);
}
// Make 1 CPUs busy
static void CpuBusyLoop(int busytime) {
CpuLoad(100.0, busytime / 1000.0, 1, 1, 0.050, -1);
}
// Make 1 use half CPU time.
static void CpuHalfBusyLoop(int busytime) {
CpuLoad(50.0, busytime / 1000.0, 1, 1, 0.050, -1);
}
void TestCpuSampler(bool test_proc, bool test_sys, bool force_fallback) {
CpuSampler sampler;
sampler.set_force_fallback(force_fallback);
EXPECT_TRUE(sampler.Init());
sampler.set_load_interval(100);
int cpus = sampler.GetMaxCpus();
// Test1: CpuSampler under idle situation.
Thread::SleepMs(kSettleTime);
sampler.GetProcessLoad();
sampler.GetSystemLoad();
Thread::SleepMs(kIdleTime);
float proc_idle = 0.f, sys_idle = 0.f;
if (test_proc) {
proc_idle = sampler.GetProcessLoad();
}
if (test_sys) {
sys_idle = sampler.GetSystemLoad();
}
if (test_proc) {
LOG(LS_INFO) << "ProcessLoad Idle: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << proc_idle;
EXPECT_GE(proc_idle, 0.f);
EXPECT_LE(proc_idle, static_cast<float>(cpus));
}
if (test_sys) {
LOG(LS_INFO) << "SystemLoad Idle: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << sys_idle;
EXPECT_GE(sys_idle, 0.f);
EXPECT_LE(sys_idle, static_cast<float>(cpus));
}
// Test2: CpuSampler with main process at 50% busy.
Thread::SleepMs(kSettleTime);
sampler.GetProcessLoad();
sampler.GetSystemLoad();
CpuHalfBusyLoop(kBusyTime);
float proc_halfbusy = 0.f, sys_halfbusy = 0.f;
if (test_proc) {
proc_halfbusy = sampler.GetProcessLoad();
}
if (test_sys) {
sys_halfbusy = sampler.GetSystemLoad();
}
if (test_proc) {
LOG(LS_INFO) << "ProcessLoad Halfbusy: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << proc_halfbusy;
EXPECT_GE(proc_halfbusy, 0.f);
EXPECT_LE(proc_halfbusy, static_cast<float>(cpus));
}
if (test_sys) {
LOG(LS_INFO) << "SystemLoad Halfbusy: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << sys_halfbusy;
EXPECT_GE(sys_halfbusy, 0.f);
EXPECT_LE(sys_halfbusy, static_cast<float>(cpus));
}
// Test3: CpuSampler with main process busy.
Thread::SleepMs(kSettleTime);
sampler.GetProcessLoad();
sampler.GetSystemLoad();
CpuBusyLoop(kBusyTime);
float proc_busy = 0.f, sys_busy = 0.f;
if (test_proc) {
proc_busy = sampler.GetProcessLoad();
}
if (test_sys) {
sys_busy = sampler.GetSystemLoad();
}
if (test_proc) {
LOG(LS_INFO) << "ProcessLoad Busy: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << proc_busy;
EXPECT_GE(proc_busy, 0.f);
EXPECT_LE(proc_busy, static_cast<float>(cpus));
}
if (test_sys) {
LOG(LS_INFO) << "SystemLoad Busy: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << sys_busy;
EXPECT_GE(sys_busy, 0.f);
EXPECT_LE(sys_busy, static_cast<float>(cpus));
}
// Test4: CpuSampler with 2 cpus process busy.
if (cpus >= 2) {
Thread::SleepMs(kSettleTime);
sampler.GetProcessLoad();
sampler.GetSystemLoad();
CpuTwoBusyLoop(kBusyTime);
float proc_twobusy = 0.f, sys_twobusy = 0.f;
if (test_proc) {
proc_twobusy = sampler.GetProcessLoad();
}
if (test_sys) {
sys_twobusy = sampler.GetSystemLoad();
}
if (test_proc) {
LOG(LS_INFO) << "ProcessLoad 2 CPU Busy:"
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << proc_twobusy;
EXPECT_GE(proc_twobusy, 0.f);
EXPECT_LE(proc_twobusy, static_cast<float>(cpus));
}
if (test_sys) {
LOG(LS_INFO) << "SystemLoad 2 CPU Busy: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << sys_twobusy;
EXPECT_GE(sys_twobusy, 0.f);
EXPECT_LE(sys_twobusy, static_cast<float>(cpus));
}
}
// Test5: CpuSampler with idle process after being busy.
Thread::SleepMs(kSettleTime);
sampler.GetProcessLoad();
sampler.GetSystemLoad();
Thread::SleepMs(kIdleTime);
if (test_proc) {
proc_idle = sampler.GetProcessLoad();
}
if (test_sys) {
sys_idle = sampler.GetSystemLoad();
}
if (test_proc) {
LOG(LS_INFO) << "ProcessLoad Idle: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << proc_idle;
EXPECT_GE(proc_idle, 0.f);
EXPECT_LE(proc_idle, proc_busy);
}
if (test_sys) {
LOG(LS_INFO) << "SystemLoad Idle: "
<< std::setiosflags(std::ios_base::fixed)
<< std::setprecision(2) << std::setw(6) << sys_idle;
EXPECT_GE(sys_idle, 0.f);
EXPECT_LE(sys_idle, static_cast<float>(cpus));
}
}
TEST(CpuMonitorTest, TestCpus) {
CpuSampler sampler;
EXPECT_TRUE(sampler.Init());
int current_cpus = sampler.GetCurrentCpus();
int cpus = sampler.GetMaxCpus();
LOG(LS_INFO) << "Current Cpus: " << std::setw(9) << current_cpus;
LOG(LS_INFO) << "Maximum Cpus: " << std::setw(9) << cpus;
EXPECT_GT(cpus, 0);
EXPECT_LE(cpus, kMaxCpus);
EXPECT_GT(current_cpus, 0);
EXPECT_LE(current_cpus, cpus);
}
#if defined(WEBRTC_WIN)
// Tests overall system CpuSampler using legacy OS fallback code if applicable.
TEST(CpuMonitorTest, TestGetSystemLoadForceFallback) {
TestCpuSampler(false, true, true);
}
#endif
// Tests both process and system functions in use at same time.
TEST(CpuMonitorTest, TestGetBothLoad) {
TestCpuSampler(true, true, false);
}
// Tests a query less than the interval produces the same value.
TEST(CpuMonitorTest, TestInterval) {
CpuSampler sampler;
EXPECT_TRUE(sampler.Init());
// Test1: Set interval to large value so sampler will not update.
sampler.set_load_interval(kLongInterval);
sampler.GetProcessLoad();
sampler.GetSystemLoad();
float proc_orig = sampler.GetProcessLoad();
float sys_orig = sampler.GetSystemLoad();
Thread::SleepMs(kIdleTime);
float proc_halftime = sampler.GetProcessLoad();
float sys_halftime = sampler.GetSystemLoad();
EXPECT_EQ(proc_orig, proc_halftime);
EXPECT_EQ(sys_orig, sys_halftime);
}
TEST(CpuMonitorTest, TestCpuMonitor) {
CpuMonitor monitor(Thread::Current());
CpuLoadListener listener;
monitor.SignalUpdate.connect(&listener, &CpuLoadListener::OnCpuLoad);
EXPECT_TRUE(monitor.Start(10));
// We have checked cpu load more than twice.
EXPECT_TRUE_WAIT(listener.count() > 2, 1000);
EXPECT_GT(listener.current_cpus(), 0);
EXPECT_GT(listener.cpus(), 0);
EXPECT_GE(listener.process_load(), .0f);
EXPECT_GE(listener.system_load(), .0f);
monitor.Stop();
// Wait 20 ms to ake sure all signals are delivered.
Thread::Current()->ProcessMessages(20);
int old_count = listener.count();
Thread::Current()->ProcessMessages(20);
// Verfy no more siganls.
EXPECT_EQ(old_count, listener.count());
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,52 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/crc32.h"
#include "webrtc/base/basicdefs.h"
namespace rtc {
// This implementation is based on the sample implementation in RFC 1952.
// CRC32 polynomial, in reversed form.
// See RFC 1952, or http://en.wikipedia.org/wiki/Cyclic_redundancy_check
static const uint32 kCrc32Polynomial = 0xEDB88320;
static uint32 kCrc32Table[256] = { 0 };
static void EnsureCrc32TableInited() {
if (kCrc32Table[ARRAY_SIZE(kCrc32Table) - 1])
return; // already inited
for (uint32 i = 0; i < ARRAY_SIZE(kCrc32Table); ++i) {
uint32 c = i;
for (size_t j = 0; j < 8; ++j) {
if (c & 1) {
c = kCrc32Polynomial ^ (c >> 1);
} else {
c >>= 1;
}
}
kCrc32Table[i] = c;
}
}
uint32 UpdateCrc32(uint32 start, const void* buf, size_t len) {
EnsureCrc32TableInited();
uint32 c = start ^ 0xFFFFFFFF;
const uint8* u = static_cast<const uint8*>(buf);
for (size_t i = 0; i < len; ++i) {
c = kCrc32Table[(c ^ u[i]) & 0xFF] ^ (c >> 8);
}
return c ^ 0xFFFFFFFF;
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,34 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_CRC32_H_
#define WEBRTC_BASE_CRC32_H_
#include <string>
#include "webrtc/base/basictypes.h"
namespace rtc {
// Updates a CRC32 checksum with |len| bytes from |buf|. |initial| holds the
// checksum result from the previous update; for the first call, it should be 0.
uint32 UpdateCrc32(uint32 initial, const void* buf, size_t len);
// Computes a CRC32 checksum using |len| bytes from |buf|.
inline uint32 ComputeCrc32(const void* buf, size_t len) {
return UpdateCrc32(0, buf, len);
}
inline uint32 ComputeCrc32(const std::string& str) {
return ComputeCrc32(str.c_str(), str.size());
}
} // namespace rtc
#endif // WEBRTC_BASE_CRC32_H_

Просмотреть файл

@ -0,0 +1,35 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/crc32.h"
#include "webrtc/base/gunit.h"
#include <string>
namespace rtc {
TEST(Crc32Test, TestBasic) {
EXPECT_EQ(0U, ComputeCrc32(""));
EXPECT_EQ(0x352441C2U, ComputeCrc32("abc"));
EXPECT_EQ(0x171A3F5FU,
ComputeCrc32("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"));
}
TEST(Crc32Test, TestMultipleUpdates) {
std::string input =
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
uint32 c = 0;
for (size_t i = 0; i < input.size(); ++i) {
c = UpdateCrc32(c, &input[i], 1);
}
EXPECT_EQ(0x171A3F5FU, c);
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,180 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_CRITICALSECTION_H__
#define WEBRTC_BASE_CRITICALSECTION_H__
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/thread_annotations.h"
#if defined(WEBRTC_WIN)
#include "webrtc/base/win32.h"
#endif
#if defined(WEBRTC_POSIX)
#include <pthread.h>
#endif
#ifdef _DEBUG
#define CS_TRACK_OWNER 1
#endif // _DEBUG
#if CS_TRACK_OWNER
#define TRACK_OWNER(x) x
#else // !CS_TRACK_OWNER
#define TRACK_OWNER(x)
#endif // !CS_TRACK_OWNER
namespace rtc {
#if defined(WEBRTC_WIN)
class LOCKABLE CriticalSection {
public:
CriticalSection() {
InitializeCriticalSection(&crit_);
// Windows docs say 0 is not a valid thread id
TRACK_OWNER(thread_ = 0);
}
~CriticalSection() {
DeleteCriticalSection(&crit_);
}
void Enter() EXCLUSIVE_LOCK_FUNCTION() {
EnterCriticalSection(&crit_);
TRACK_OWNER(thread_ = GetCurrentThreadId());
}
bool TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
if (TryEnterCriticalSection(&crit_) != FALSE) {
TRACK_OWNER(thread_ = GetCurrentThreadId());
return true;
}
return false;
}
void Leave() UNLOCK_FUNCTION() {
TRACK_OWNER(thread_ = 0);
LeaveCriticalSection(&crit_);
}
#if CS_TRACK_OWNER
bool CurrentThreadIsOwner() const { return thread_ == GetCurrentThreadId(); }
#endif // CS_TRACK_OWNER
private:
CRITICAL_SECTION crit_;
TRACK_OWNER(DWORD thread_); // The section's owning thread id
};
#endif // WEBRTC_WIN
#if defined(WEBRTC_POSIX)
class LOCKABLE CriticalSection {
public:
CriticalSection() {
pthread_mutexattr_t mutex_attribute;
pthread_mutexattr_init(&mutex_attribute);
pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex_, &mutex_attribute);
pthread_mutexattr_destroy(&mutex_attribute);
TRACK_OWNER(thread_ = 0);
}
~CriticalSection() {
pthread_mutex_destroy(&mutex_);
}
void Enter() EXCLUSIVE_LOCK_FUNCTION() {
pthread_mutex_lock(&mutex_);
TRACK_OWNER(thread_ = pthread_self());
}
bool TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
if (pthread_mutex_trylock(&mutex_) == 0) {
TRACK_OWNER(thread_ = pthread_self());
return true;
}
return false;
}
void Leave() UNLOCK_FUNCTION() {
TRACK_OWNER(thread_ = 0);
pthread_mutex_unlock(&mutex_);
}
#if CS_TRACK_OWNER
bool CurrentThreadIsOwner() const { return pthread_equal(thread_, pthread_self()); }
#endif // CS_TRACK_OWNER
private:
pthread_mutex_t mutex_;
TRACK_OWNER(pthread_t thread_);
};
#endif // WEBRTC_POSIX
// CritScope, for serializing execution through a scope.
class SCOPED_LOCKABLE CritScope {
public:
explicit CritScope(CriticalSection *pcrit) EXCLUSIVE_LOCK_FUNCTION(pcrit) {
pcrit_ = pcrit;
pcrit_->Enter();
}
~CritScope() UNLOCK_FUNCTION() {
pcrit_->Leave();
}
private:
CriticalSection *pcrit_;
DISALLOW_COPY_AND_ASSIGN(CritScope);
};
// Tries to lock a critical section on construction via
// CriticalSection::TryEnter, and unlocks on destruction if the
// lock was taken. Never blocks.
//
// IMPORTANT: Unlike CritScope, the lock may not be owned by this thread in
// subsequent code. Users *must* check locked() to determine if the
// lock was taken. If you're not calling locked(), you're doing it wrong!
class TryCritScope {
public:
explicit TryCritScope(CriticalSection *pcrit) {
pcrit_ = pcrit;
locked_ = pcrit_->TryEnter();
}
~TryCritScope() {
if (locked_) {
pcrit_->Leave();
}
}
bool locked() const {
return locked_;
}
private:
CriticalSection *pcrit_;
bool locked_;
DISALLOW_COPY_AND_ASSIGN(TryCritScope);
};
// TODO: Move this to atomicops.h, which can't be done easily because of
// complex compile rules.
class AtomicOps {
public:
#if defined(WEBRTC_WIN)
// Assumes sizeof(int) == sizeof(LONG), which it is on Win32 and Win64.
static int Increment(int* i) {
return ::InterlockedIncrement(reinterpret_cast<LONG*>(i));
}
static int Decrement(int* i) {
return ::InterlockedDecrement(reinterpret_cast<LONG*>(i));
}
#else
static int Increment(int* i) {
return __sync_add_and_fetch(i, 1);
}
static int Decrement(int* i) {
return __sync_sub_and_fetch(i, 1);
}
#endif
};
} // namespace rtc
#endif // WEBRTC_BASE_CRITICALSECTION_H__

Просмотреть файл

@ -0,0 +1,147 @@
/*
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <set>
#include <vector>
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/event.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/scopedptrcollection.h"
#include "webrtc/base/thread.h"
#include "webrtc/test/testsupport/gtest_disable.h"
namespace rtc {
namespace {
const int kLongTime = 10000; // 10 seconds
const int kNumThreads = 16;
const int kOperationsToRun = 1000;
template <class T>
class AtomicOpRunner : public MessageHandler {
public:
explicit AtomicOpRunner(int initial_value)
: value_(initial_value),
threads_active_(0),
start_event_(true, false),
done_event_(true, false) {}
int value() const { return value_; }
bool Run() {
// Signal all threads to start.
start_event_.Set();
// Wait for all threads to finish.
return done_event_.Wait(kLongTime);
}
void SetExpectedThreadCount(int count) {
threads_active_ = count;
}
virtual void OnMessage(Message* msg) {
std::vector<int> values;
values.reserve(kOperationsToRun);
// Wait to start.
ASSERT_TRUE(start_event_.Wait(kLongTime));
// Generate a bunch of values by updating value_ atomically.
for (int i = 0; i < kOperationsToRun; ++i) {
values.push_back(T::AtomicOp(&value_));
}
{ // Add them all to the set.
CritScope cs(&all_values_crit_);
for (size_t i = 0; i < values.size(); ++i) {
std::pair<std::set<int>::iterator, bool> result =
all_values_.insert(values[i]);
// Each value should only be taken by one thread, so if this value
// has already been added, something went wrong.
EXPECT_TRUE(result.second)
<< "Thread=" << Thread::Current() << " value=" << values[i];
}
}
// Signal that we're done.
if (AtomicOps::Decrement(&threads_active_) == 0) {
done_event_.Set();
}
}
private:
int value_;
int threads_active_;
CriticalSection all_values_crit_;
std::set<int> all_values_;
Event start_event_;
Event done_event_;
};
struct IncrementOp {
static int AtomicOp(int* i) { return AtomicOps::Increment(i); }
};
struct DecrementOp {
static int AtomicOp(int* i) { return AtomicOps::Decrement(i); }
};
void StartThreads(ScopedPtrCollection<Thread>* threads,
MessageHandler* handler) {
for (int i = 0; i < kNumThreads; ++i) {
Thread* thread = new Thread();
thread->Start();
thread->Post(handler);
threads->PushBack(thread);
}
}
} // namespace
TEST(AtomicOpsTest, Simple) {
int value = 0;
EXPECT_EQ(1, AtomicOps::Increment(&value));
EXPECT_EQ(1, value);
EXPECT_EQ(2, AtomicOps::Increment(&value));
EXPECT_EQ(2, value);
EXPECT_EQ(1, AtomicOps::Decrement(&value));
EXPECT_EQ(1, value);
EXPECT_EQ(0, AtomicOps::Decrement(&value));
EXPECT_EQ(0, value);
}
TEST(AtomicOpsTest, Increment) {
// Create and start lots of threads.
AtomicOpRunner<IncrementOp> runner(0);
ScopedPtrCollection<Thread> threads;
StartThreads(&threads, &runner);
runner.SetExpectedThreadCount(kNumThreads);
// Release the hounds!
EXPECT_TRUE(runner.Run());
EXPECT_EQ(kOperationsToRun * kNumThreads, runner.value());
}
TEST(AtomicOpsTest, Decrement) {
// Create and start lots of threads.
AtomicOpRunner<DecrementOp> runner(kOperationsToRun * kNumThreads);
ScopedPtrCollection<Thread> threads;
StartThreads(&threads, &runner);
runner.SetExpectedThreadCount(kNumThreads);
// Release the hounds!
EXPECT_TRUE(runner.Run());
EXPECT_EQ(0, runner.value());
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,183 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef _WEBRTC_BASE_CRYPTSTRING_H_
#define _WEBRTC_BASE_CRYPTSTRING_H_
#include <string.h>
#include <string>
#include <vector>
#include "webrtc/base/linked_ptr.h"
#include "webrtc/base/scoped_ptr.h"
namespace rtc {
class CryptStringImpl {
public:
virtual ~CryptStringImpl() {}
virtual size_t GetLength() const = 0;
virtual void CopyTo(char * dest, bool nullterminate) const = 0;
virtual std::string UrlEncode() const = 0;
virtual CryptStringImpl * Copy() const = 0;
virtual void CopyRawTo(std::vector<unsigned char> * dest) const = 0;
};
class EmptyCryptStringImpl : public CryptStringImpl {
public:
virtual ~EmptyCryptStringImpl() {}
virtual size_t GetLength() const { return 0; }
virtual void CopyTo(char * dest, bool nullterminate) const {
if (nullterminate) {
*dest = '\0';
}
}
virtual std::string UrlEncode() const { return ""; }
virtual CryptStringImpl * Copy() const { return new EmptyCryptStringImpl(); }
virtual void CopyRawTo(std::vector<unsigned char> * dest) const {
dest->clear();
}
};
class CryptString {
public:
CryptString() : impl_(new EmptyCryptStringImpl()) {}
size_t GetLength() const { return impl_->GetLength(); }
void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); }
CryptString(const CryptString & other) : impl_(other.impl_->Copy()) {}
explicit CryptString(const CryptStringImpl & impl) : impl_(impl.Copy()) {}
CryptString & operator=(const CryptString & other) {
if (this != &other) {
impl_.reset(other.impl_->Copy());
}
return *this;
}
void Clear() { impl_.reset(new EmptyCryptStringImpl()); }
std::string UrlEncode() const { return impl_->UrlEncode(); }
void CopyRawTo(std::vector<unsigned char> * dest) const {
return impl_->CopyRawTo(dest);
}
private:
scoped_ptr<const CryptStringImpl> impl_;
};
// Used for constructing strings where a password is involved and we
// need to ensure that we zero memory afterwards
class FormatCryptString {
public:
FormatCryptString() {
storage_ = new char[32];
capacity_ = 32;
length_ = 0;
storage_[0] = 0;
}
void Append(const std::string & text) {
Append(text.data(), text.length());
}
void Append(const char * data, size_t length) {
EnsureStorage(length_ + length + 1);
memcpy(storage_ + length_, data, length);
length_ += length;
storage_[length_] = '\0';
}
void Append(const CryptString * password) {
size_t len = password->GetLength();
EnsureStorage(length_ + len + 1);
password->CopyTo(storage_ + length_, true);
length_ += len;
}
size_t GetLength() {
return length_;
}
const char * GetData() {
return storage_;
}
// Ensures storage of at least n bytes
void EnsureStorage(size_t n) {
if (capacity_ >= n) {
return;
}
size_t old_capacity = capacity_;
char * old_storage = storage_;
for (;;) {
capacity_ *= 2;
if (capacity_ >= n)
break;
}
storage_ = new char[capacity_];
if (old_capacity) {
memcpy(storage_, old_storage, length_);
// zero memory in a way that an optimizer won't optimize it out
old_storage[0] = 0;
for (size_t i = 1; i < old_capacity; i++) {
old_storage[i] = old_storage[i - 1];
}
delete[] old_storage;
}
}
~FormatCryptString() {
if (capacity_) {
storage_[0] = 0;
for (size_t i = 1; i < capacity_; i++) {
storage_[i] = storage_[i - 1];
}
}
delete[] storage_;
}
private:
char * storage_;
size_t capacity_;
size_t length_;
};
class InsecureCryptStringImpl : public CryptStringImpl {
public:
std::string& password() { return password_; }
const std::string& password() const { return password_; }
virtual ~InsecureCryptStringImpl() {}
virtual size_t GetLength() const { return password_.size(); }
virtual void CopyTo(char * dest, bool nullterminate) const {
memcpy(dest, password_.data(), password_.size());
if (nullterminate) dest[password_.size()] = 0;
}
virtual std::string UrlEncode() const { return password_; }
virtual CryptStringImpl * Copy() const {
InsecureCryptStringImpl * copy = new InsecureCryptStringImpl;
copy->password() = password_;
return copy;
}
virtual void CopyRawTo(std::vector<unsigned char> * dest) const {
dest->resize(password_.size());
memcpy(&dest->front(), password_.data(), password_.size());
}
private:
std::string password_;
};
}
#endif // _WEBRTC_BASE_CRYPTSTRING_H_

Просмотреть файл

@ -0,0 +1,396 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifdef HAVE_DBUS_GLIB
#include "webrtc/base/dbus.h"
#include <glib.h>
#include "webrtc/base/logging.h"
#include "webrtc/base/thread.h"
namespace rtc {
// Avoid static object construction/destruction on startup/shutdown.
static pthread_once_t g_dbus_init_once = PTHREAD_ONCE_INIT;
static LibDBusGlibSymbolTable *g_dbus_symbol = NULL;
// Releases DBus-Glib symbols.
static void ReleaseDBusGlibSymbol() {
if (g_dbus_symbol != NULL) {
delete g_dbus_symbol;
g_dbus_symbol = NULL;
}
}
// Loads DBus-Glib symbols.
static void InitializeDBusGlibSymbol() {
// This is thread safe.
if (NULL == g_dbus_symbol) {
g_dbus_symbol = new LibDBusGlibSymbolTable();
// Loads dbus-glib
if (NULL == g_dbus_symbol || !g_dbus_symbol->Load()) {
LOG(LS_WARNING) << "Failed to load dbus-glib symbol table.";
ReleaseDBusGlibSymbol();
} else {
// Nothing we can do if atexit() failed. Just ignore its returned value.
atexit(ReleaseDBusGlibSymbol);
}
}
}
inline static LibDBusGlibSymbolTable *GetSymbols() {
return DBusMonitor::GetDBusGlibSymbolTable();
}
// Implementation of class DBusSigMessageData
DBusSigMessageData::DBusSigMessageData(DBusMessage *message)
: TypedMessageData<DBusMessage *>(message) {
GetSymbols()->dbus_message_ref()(data());
}
DBusSigMessageData::~DBusSigMessageData() {
GetSymbols()->dbus_message_unref()(data());
}
// Implementation of class DBusSigFilter
// Builds a DBus filter string from given DBus path, interface and member.
std::string DBusSigFilter::BuildFilterString(const std::string &path,
const std::string &interface,
const std::string &member) {
std::string ret(DBUS_TYPE "='" DBUS_SIGNAL "'");
if (!path.empty()) {
ret += ("," DBUS_PATH "='");
ret += path;
ret += "'";
}
if (!interface.empty()) {
ret += ("," DBUS_INTERFACE "='");
ret += interface;
ret += "'";
}
if (!member.empty()) {
ret += ("," DBUS_MEMBER "='");
ret += member;
ret += "'";
}
return ret;
}
// Forwards the message to the given instance.
DBusHandlerResult DBusSigFilter::DBusCallback(DBusConnection *dbus_conn,
DBusMessage *message,
void *instance) {
ASSERT(instance);
if (instance) {
return static_cast<DBusSigFilter *>(instance)->Callback(message);
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
// Posts a message to caller thread.
DBusHandlerResult DBusSigFilter::Callback(DBusMessage *message) {
if (caller_thread_) {
caller_thread_->Post(this, DSM_SIGNAL, new DBusSigMessageData(message));
}
// Don't "eat" the message here. Let it pop up.
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
// From MessageHandler.
void DBusSigFilter::OnMessage(Message *message) {
if (message != NULL && DSM_SIGNAL == message->message_id) {
DBusSigMessageData *msg =
static_cast<DBusSigMessageData *>(message->pdata);
if (msg) {
ProcessSignal(msg->data());
delete msg;
}
}
}
// Definition of private class DBusMonitoringThread.
// It creates a worker-thread to listen signals on DBus. The worker-thread will
// be running in a priate GMainLoop forever until either Stop() has been invoked
// or it hits an error.
class DBusMonitor::DBusMonitoringThread : public rtc::Thread {
public:
explicit DBusMonitoringThread(DBusMonitor *monitor,
GMainContext *context,
GMainLoop *mainloop,
std::vector<DBusSigFilter *> *filter_list)
: monitor_(monitor),
context_(context),
mainloop_(mainloop),
connection_(NULL),
idle_source_(NULL),
filter_list_(filter_list) {
ASSERT(monitor_);
ASSERT(context_);
ASSERT(mainloop_);
ASSERT(filter_list_);
}
virtual ~DBusMonitoringThread() {
Stop();
}
// Override virtual method of Thread. Context: worker-thread.
virtual void Run() {
ASSERT(NULL == connection_);
// Setup DBus connection and start monitoring.
monitor_->OnMonitoringStatusChanged(DMS_INITIALIZING);
if (!Setup()) {
LOG(LS_ERROR) << "DBus monitoring setup failed.";
monitor_->OnMonitoringStatusChanged(DMS_FAILED);
CleanUp();
return;
}
monitor_->OnMonitoringStatusChanged(DMS_RUNNING);
g_main_loop_run(mainloop_);
monitor_->OnMonitoringStatusChanged(DMS_STOPPED);
// Done normally. Clean up DBus connection.
CleanUp();
return;
}
// Override virtual method of Thread. Context: caller-thread.
virtual void Stop() {
ASSERT(NULL == idle_source_);
// Add an idle source and let the gmainloop quit on idle.
idle_source_ = g_idle_source_new();
if (idle_source_) {
g_source_set_callback(idle_source_, &Idle, this, NULL);
g_source_attach(idle_source_, context_);
} else {
LOG(LS_ERROR) << "g_idle_source_new() failed.";
QuitGMainloop(); // Try to quit anyway.
}
Thread::Stop(); // Wait for the thread.
}
private:
// Registers all DBus filters.
void RegisterAllFilters() {
ASSERT(NULL != GetSymbols()->dbus_g_connection_get_connection()(
connection_));
for (std::vector<DBusSigFilter *>::iterator it = filter_list_->begin();
it != filter_list_->end(); ++it) {
DBusSigFilter *filter = (*it);
if (!filter) {
LOG(LS_ERROR) << "DBusSigFilter list corrupted.";
continue;
}
GetSymbols()->dbus_bus_add_match()(
GetSymbols()->dbus_g_connection_get_connection()(connection_),
filter->filter().c_str(), NULL);
if (!GetSymbols()->dbus_connection_add_filter()(
GetSymbols()->dbus_g_connection_get_connection()(connection_),
&DBusSigFilter::DBusCallback, filter, NULL)) {
LOG(LS_ERROR) << "dbus_connection_add_filter() failed."
<< "Filter: " << filter->filter();
continue;
}
}
}
// Unregisters all DBus filters.
void UnRegisterAllFilters() {
ASSERT(NULL != GetSymbols()->dbus_g_connection_get_connection()(
connection_));
for (std::vector<DBusSigFilter *>::iterator it = filter_list_->begin();
it != filter_list_->end(); ++it) {
DBusSigFilter *filter = (*it);
if (!filter) {
LOG(LS_ERROR) << "DBusSigFilter list corrupted.";
continue;
}
GetSymbols()->dbus_connection_remove_filter()(
GetSymbols()->dbus_g_connection_get_connection()(connection_),
&DBusSigFilter::DBusCallback, filter);
}
}
// Sets up the monitoring thread.
bool Setup() {
g_main_context_push_thread_default(context_);
// Start connection to dbus.
// If dbus daemon is not running, returns false immediately.
connection_ = GetSymbols()->dbus_g_bus_get_private()(monitor_->type_,
context_, NULL);
if (NULL == connection_) {
LOG(LS_ERROR) << "dbus_g_bus_get_private() unable to get connection.";
return false;
}
if (NULL == GetSymbols()->dbus_g_connection_get_connection()(connection_)) {
LOG(LS_ERROR) << "dbus_g_connection_get_connection() returns NULL. "
<< "DBus daemon is probably not running.";
return false;
}
// Application don't exit if DBus daemon die.
GetSymbols()->dbus_connection_set_exit_on_disconnect()(
GetSymbols()->dbus_g_connection_get_connection()(connection_), FALSE);
// Connect all filters.
RegisterAllFilters();
return true;
}
// Cleans up the monitoring thread.
void CleanUp() {
if (idle_source_) {
// We did an attach() with the GSource, so we need to destroy() it.
g_source_destroy(idle_source_);
// We need to unref() the GSource to end the last reference we got.
g_source_unref(idle_source_);
idle_source_ = NULL;
}
if (connection_) {
if (GetSymbols()->dbus_g_connection_get_connection()(connection_)) {
UnRegisterAllFilters();
GetSymbols()->dbus_connection_close()(
GetSymbols()->dbus_g_connection_get_connection()(connection_));
}
GetSymbols()->dbus_g_connection_unref()(connection_);
connection_ = NULL;
}
g_main_loop_unref(mainloop_);
mainloop_ = NULL;
g_main_context_unref(context_);
context_ = NULL;
}
// Handles callback on Idle. We only add this source when ready to stop.
static gboolean Idle(gpointer data) {
static_cast<DBusMonitoringThread *>(data)->QuitGMainloop();
return TRUE;
}
// We only hit this when ready to quit.
void QuitGMainloop() {
g_main_loop_quit(mainloop_);
}
DBusMonitor *monitor_;
GMainContext *context_;
GMainLoop *mainloop_;
DBusGConnection *connection_;
GSource *idle_source_;
std::vector<DBusSigFilter *> *filter_list_;
};
// Implementation of class DBusMonitor
// Returns DBus-Glib symbol handle. Initialize it first if hasn't.
LibDBusGlibSymbolTable *DBusMonitor::GetDBusGlibSymbolTable() {
// This is multi-thread safe.
pthread_once(&g_dbus_init_once, InitializeDBusGlibSymbol);
return g_dbus_symbol;
};
// Creates an instance of DBusMonitor
DBusMonitor *DBusMonitor::Create(DBusBusType type) {
if (NULL == DBusMonitor::GetDBusGlibSymbolTable()) {
return NULL;
}
return new DBusMonitor(type);
}
DBusMonitor::DBusMonitor(DBusBusType type)
: type_(type),
status_(DMS_NOT_INITIALIZED),
monitoring_thread_(NULL) {
ASSERT(type_ == DBUS_BUS_SYSTEM || type_ == DBUS_BUS_SESSION);
}
DBusMonitor::~DBusMonitor() {
StopMonitoring();
}
bool DBusMonitor::AddFilter(DBusSigFilter *filter) {
if (monitoring_thread_) {
return false;
}
if (!filter) {
return false;
}
filter_list_.push_back(filter);
return true;
}
bool DBusMonitor::StartMonitoring() {
if (!monitoring_thread_) {
g_type_init();
g_thread_init(NULL);
GetSymbols()->dbus_g_thread_init()();
GMainContext *context = g_main_context_new();
if (NULL == context) {
LOG(LS_ERROR) << "g_main_context_new() failed.";
return false;
}
GMainLoop *mainloop = g_main_loop_new(context, FALSE);
if (NULL == mainloop) {
LOG(LS_ERROR) << "g_main_loop_new() failed.";
g_main_context_unref(context);
return false;
}
monitoring_thread_ = new DBusMonitoringThread(this, context, mainloop,
&filter_list_);
if (monitoring_thread_ == NULL) {
LOG(LS_ERROR) << "Failed to create DBus monitoring thread.";
g_main_context_unref(context);
g_main_loop_unref(mainloop);
return false;
}
monitoring_thread_->Start();
}
return true;
}
bool DBusMonitor::StopMonitoring() {
if (monitoring_thread_) {
monitoring_thread_->Stop();
monitoring_thread_ = NULL;
}
return true;
}
DBusMonitor::DBusMonitorStatus DBusMonitor::GetStatus() {
return status_;
}
void DBusMonitor::OnMonitoringStatusChanged(DBusMonitorStatus status) {
status_ = status;
}
#undef LATE
} // namespace rtc
#endif // HAVE_DBUS_GLIB

Просмотреть файл

@ -0,0 +1,168 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_DBUS_H_
#define WEBRTC_BASE_DBUS_H_
#ifdef HAVE_DBUS_GLIB
#include <dbus/dbus.h>
#include <string>
#include <vector>
#include "webrtc/base/libdbusglibsymboltable.h"
#include "webrtc/base/messagehandler.h"
#include "webrtc/base/thread.h"
namespace rtc {
#define DBUS_TYPE "type"
#define DBUS_SIGNAL "signal"
#define DBUS_PATH "path"
#define DBUS_INTERFACE "interface"
#define DBUS_MEMBER "member"
#ifdef CHROMEOS
#define CROS_PM_PATH "/"
#define CROS_PM_INTERFACE "org.chromium.PowerManager"
#define CROS_SIG_POWERCHANGED "PowerStateChanged"
#define CROS_VALUE_SLEEP "mem"
#define CROS_VALUE_RESUME "on"
#else
#define UP_PATH "/org/freedesktop/UPower"
#define UP_INTERFACE "org.freedesktop.UPower"
#define UP_SIG_SLEEPING "Sleeping"
#define UP_SIG_RESUMING "Resuming"
#endif // CHROMEOS
// Wraps a DBus messages.
class DBusSigMessageData : public TypedMessageData<DBusMessage *> {
public:
explicit DBusSigMessageData(DBusMessage *message);
~DBusSigMessageData();
};
// DBusSigFilter is an abstract class that defines the interface of DBus
// signal handling.
// The subclasses implement ProcessSignal() for various purposes.
// When a DBus signal comes, a DSM_SIGNAL message is posted to the caller thread
// which will then invokes ProcessSignal().
class DBusSigFilter : protected MessageHandler {
public:
enum DBusSigMessage { DSM_SIGNAL };
// This filter string should ususally come from BuildFilterString()
explicit DBusSigFilter(const std::string &filter)
: caller_thread_(Thread::Current()), filter_(filter) {
}
// Builds a DBus monitor filter string from given DBus path, interface, and
// member.
// See http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html
static std::string BuildFilterString(const std::string &path,
const std::string &interface,
const std::string &member);
// Handles callback on DBus messages by DBus system.
static DBusHandlerResult DBusCallback(DBusConnection *dbus_conn,
DBusMessage *message,
void *instance);
// Handles callback on DBus messages to each DBusSigFilter instance.
DBusHandlerResult Callback(DBusMessage *message);
// From MessageHandler.
virtual void OnMessage(Message *message);
// Returns the DBus monitor filter string.
const std::string &filter() const { return filter_; }
private:
// On caller thread.
virtual void ProcessSignal(DBusMessage *message) = 0;
Thread *caller_thread_;
const std::string filter_;
};
// DBusMonitor is a class for DBus signal monitoring.
//
// The caller-thread calls AddFilter() first to add the signals that it wants to
// monitor and then calls StartMonitoring() to start the monitoring.
// This will create a worker-thread which listens on DBus connection and sends
// DBus signals back through the callback.
// The worker-thread will be running forever until either StopMonitoring() is
// called from the caller-thread or the worker-thread hit some error.
//
// Programming model:
// 1. Caller-thread: Creates an object of DBusMonitor.
// 2. Caller-thread: Calls DBusMonitor::AddFilter() one or several times.
// 3. Caller-thread: StartMonitoring().
// ...
// 4. Worker-thread: DBus signal recieved. Post a message to caller-thread.
// 5. Caller-thread: DBusFilterBase::ProcessSignal() is invoked.
// ...
// 6. Caller-thread: StopMonitoring().
//
// Assumption:
// AddFilter(), StartMonitoring(), and StopMonitoring() methods are called by
// a single thread. Hence, there is no need to make them thread safe.
class DBusMonitor {
public:
// Status of DBus monitoring.
enum DBusMonitorStatus {
DMS_NOT_INITIALIZED, // Not initialized.
DMS_INITIALIZING, // Initializing the monitoring thread.
DMS_RUNNING, // Monitoring.
DMS_STOPPED, // Not monitoring. Stopped normally.
DMS_FAILED, // Not monitoring. Failed.
};
// Returns the DBus-Glib symbol table.
// We should only use this function to access DBus-Glib symbols.
static LibDBusGlibSymbolTable *GetDBusGlibSymbolTable();
// Creates an instance of DBusMonitor.
static DBusMonitor *Create(DBusBusType type);
~DBusMonitor();
// Adds a filter to DBusMonitor.
bool AddFilter(DBusSigFilter *filter);
// Starts DBus message monitoring.
bool StartMonitoring();
// Stops DBus message monitoring.
bool StopMonitoring();
// Gets the status of DBus monitoring.
DBusMonitorStatus GetStatus();
private:
// Forward declaration. Defined in the .cc file.
class DBusMonitoringThread;
explicit DBusMonitor(DBusBusType type);
// Updates status_ when monitoring status has changed.
void OnMonitoringStatusChanged(DBusMonitorStatus status);
DBusBusType type_;
DBusMonitorStatus status_;
DBusMonitoringThread *monitoring_thread_;
std::vector<DBusSigFilter *> filter_list_;
};
} // namespace rtc
#endif // HAVE_DBUS_GLIB
#endif // WEBRTC_BASE_DBUS_H_

Просмотреть файл

@ -0,0 +1,232 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifdef HAVE_DBUS_GLIB
#include "webrtc/base/dbus.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/thread.h"
namespace rtc {
#define SIG_NAME "NameAcquired"
static const uint32 kTimeoutMs = 5000U;
class DBusSigFilterTest : public DBusSigFilter {
public:
// DBusSigFilterTest listens on DBus service itself for "NameAcquired" signal.
// This signal should be received when the application connects to DBus
// service and gains ownership of a name.
// http://dbus.freedesktop.org/doc/dbus-specification.html
DBusSigFilterTest()
: DBusSigFilter(GetFilter()),
message_received_(false) {
}
bool MessageReceived() {
return message_received_;
}
private:
static std::string GetFilter() {
return rtc::DBusSigFilter::BuildFilterString("", "", SIG_NAME);
}
// Implement virtual method of DBusSigFilter. On caller thread.
virtual void ProcessSignal(DBusMessage *message) {
EXPECT_TRUE(message != NULL);
message_received_ = true;
}
bool message_received_;
};
TEST(DBusMonitorTest, StartStopStartStop) {
DBusSigFilterTest filter;
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
if (monitor) {
EXPECT_TRUE(monitor->AddFilter(&filter));
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_NOT_INITIALIZED);
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_RUNNING);
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
} else {
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
}
}
// DBusMonitorTest listens on DBus service itself for "NameAcquired" signal.
// This signal should be received when the application connects to DBus
// service and gains ownership of a name.
// This test is to make sure that we capture the "NameAcquired" signal.
TEST(DBusMonitorTest, ReceivedNameAcquiredSignal) {
DBusSigFilterTest filter;
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
if (monitor) {
EXPECT_TRUE(monitor->AddFilter(&filter));
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
EXPECT_TRUE_WAIT(filter.MessageReceived(), kTimeoutMs);
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
} else {
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
}
}
TEST(DBusMonitorTest, ConcurrentMonitors) {
DBusSigFilterTest filter1;
rtc::scoped_ptr<rtc::DBusMonitor> monitor1;
monitor1.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
if (monitor1) {
EXPECT_TRUE(monitor1->AddFilter(&filter1));
DBusSigFilterTest filter2;
rtc::scoped_ptr<rtc::DBusMonitor> monitor2;
monitor2.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
EXPECT_TRUE(monitor2->AddFilter(&filter2));
EXPECT_TRUE(monitor1->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor1->GetStatus(), kTimeoutMs);
EXPECT_TRUE(monitor2->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor2->GetStatus(), kTimeoutMs);
EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs);
EXPECT_TRUE(monitor2->StopMonitoring());
EXPECT_EQ(monitor2->GetStatus(), DBusMonitor::DMS_STOPPED);
EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs);
EXPECT_TRUE(monitor1->StopMonitoring());
EXPECT_EQ(monitor1->GetStatus(), DBusMonitor::DMS_STOPPED);
} else {
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
}
}
TEST(DBusMonitorTest, ConcurrentFilters) {
DBusSigFilterTest filter1;
DBusSigFilterTest filter2;
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
if (monitor) {
EXPECT_TRUE(monitor->AddFilter(&filter1));
EXPECT_TRUE(monitor->AddFilter(&filter2));
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs);
EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs);
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
} else {
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
}
}
TEST(DBusMonitorTest, NoAddFilterIfRunning) {
DBusSigFilterTest filter1;
DBusSigFilterTest filter2;
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
if (monitor) {
EXPECT_TRUE(monitor->AddFilter(&filter1));
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
EXPECT_FALSE(monitor->AddFilter(&filter2));
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
} else {
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
}
}
TEST(DBusMonitorTest, AddFilterAfterStop) {
DBusSigFilterTest filter1;
DBusSigFilterTest filter2;
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
if (monitor) {
EXPECT_TRUE(monitor->AddFilter(&filter1));
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs);
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
EXPECT_TRUE(monitor->AddFilter(&filter2));
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_EQ_WAIT(DBusMonitor::DMS_RUNNING, monitor->GetStatus(), kTimeoutMs);
EXPECT_TRUE_WAIT(filter1.MessageReceived(), kTimeoutMs);
EXPECT_TRUE_WAIT(filter2.MessageReceived(), kTimeoutMs);
EXPECT_TRUE(monitor->StopMonitoring());
EXPECT_EQ(monitor->GetStatus(), DBusMonitor::DMS_STOPPED);
} else {
LOG(LS_WARNING) << "DBus Monitor not started. Skipping test.";
}
}
TEST(DBusMonitorTest, StopRightAfterStart) {
DBusSigFilterTest filter;
rtc::scoped_ptr<rtc::DBusMonitor> monitor;
monitor.reset(rtc::DBusMonitor::Create(DBUS_BUS_SYSTEM));
if (monitor) {
EXPECT_TRUE(monitor->AddFilter(&filter));
EXPECT_TRUE(monitor->StartMonitoring());
EXPECT_TRUE(monitor->StopMonitoring());
// Stop the monitoring thread right after it had been started.
// If the monitoring thread got a chance to receive a DBus signal, it would
// post a message to the main thread and signal the main thread wakeup.
// This message will be cleaned out automatically when the filter get
// destructed. Here we also consume the wakeup signal (if there is one) so
// that the testing (main) thread is reset to a clean state.
rtc::Thread::Current()->ProcessMessages(1);
} else {
LOG(LS_WARNING) << "DBus Monitor not started.";
}
}
TEST(DBusSigFilter, BuildFilterString) {
EXPECT_EQ(DBusSigFilter::BuildFilterString("", "", ""),
(DBUS_TYPE "='" DBUS_SIGNAL "'"));
EXPECT_EQ(DBusSigFilter::BuildFilterString("p", "", ""),
(DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p'"));
EXPECT_EQ(DBusSigFilter::BuildFilterString("p","i", ""),
(DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p',"
DBUS_INTERFACE "='i'"));
EXPECT_EQ(DBusSigFilter::BuildFilterString("p","i","m"),
(DBUS_TYPE "='" DBUS_SIGNAL "'," DBUS_PATH "='p',"
DBUS_INTERFACE "='i'," DBUS_MEMBER "='m'"));
}
} // namespace rtc
#endif // HAVE_DBUS_GLIB

Просмотреть файл

@ -0,0 +1,347 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <time.h>
#if defined(WEBRTC_WIN)
#include "webrtc/base/win32.h"
#endif
#include "webrtc/base/common.h"
#include "webrtc/base/diskcache.h"
#include "webrtc/base/fileutils.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/base/stream.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/stringutils.h"
#ifdef _DEBUG
#define TRANSPARENT_CACHE_NAMES 1
#else // !_DEBUG
#define TRANSPARENT_CACHE_NAMES 0
#endif // !_DEBUG
namespace rtc {
class DiskCache;
///////////////////////////////////////////////////////////////////////////////
// DiskCacheAdapter
///////////////////////////////////////////////////////////////////////////////
class DiskCacheAdapter : public StreamAdapterInterface {
public:
DiskCacheAdapter(const DiskCache* cache, const std::string& id, size_t index,
StreamInterface* stream)
: StreamAdapterInterface(stream), cache_(cache), id_(id), index_(index)
{ }
virtual ~DiskCacheAdapter() {
Close();
cache_->ReleaseResource(id_, index_);
}
private:
const DiskCache* cache_;
std::string id_;
size_t index_;
};
///////////////////////////////////////////////////////////////////////////////
// DiskCache
///////////////////////////////////////////////////////////////////////////////
DiskCache::DiskCache() : max_cache_(0), total_size_(0), total_accessors_(0) {
}
DiskCache::~DiskCache() {
ASSERT(0 == total_accessors_);
}
bool DiskCache::Initialize(const std::string& folder, size_t size) {
if (!folder_.empty() || !Filesystem::CreateFolder(folder))
return false;
folder_ = folder;
max_cache_ = size;
ASSERT(0 == total_size_);
if (!InitializeEntries())
return false;
return CheckLimit();
}
bool DiskCache::Purge() {
if (folder_.empty())
return false;
if (total_accessors_ > 0) {
LOG_F(LS_WARNING) << "Cache files open";
return false;
}
if (!PurgeFiles())
return false;
map_.clear();
return true;
}
bool DiskCache::LockResource(const std::string& id) {
Entry* entry = GetOrCreateEntry(id, true);
if (LS_LOCKED == entry->lock_state)
return false;
if ((LS_UNLOCKED == entry->lock_state) && (entry->accessors > 0))
return false;
if ((total_size_ > max_cache_) && !CheckLimit()) {
LOG_F(LS_WARNING) << "Cache overfull";
return false;
}
entry->lock_state = LS_LOCKED;
return true;
}
StreamInterface* DiskCache::WriteResource(const std::string& id, size_t index) {
Entry* entry = GetOrCreateEntry(id, false);
if (LS_LOCKED != entry->lock_state)
return NULL;
size_t previous_size = 0;
std::string filename(IdToFilename(id, index));
FileStream::GetSize(filename, &previous_size);
ASSERT(previous_size <= entry->size);
if (previous_size > entry->size) {
previous_size = entry->size;
}
scoped_ptr<FileStream> file(new FileStream);
if (!file->Open(filename, "wb", NULL)) {
LOG_F(LS_ERROR) << "Couldn't create cache file";
return NULL;
}
entry->streams = stdmax(entry->streams, index + 1);
entry->size -= previous_size;
total_size_ -= previous_size;
entry->accessors += 1;
total_accessors_ += 1;
return new DiskCacheAdapter(this, id, index, file.release());
}
bool DiskCache::UnlockResource(const std::string& id) {
Entry* entry = GetOrCreateEntry(id, false);
if (LS_LOCKED != entry->lock_state)
return false;
if (entry->accessors > 0) {
entry->lock_state = LS_UNLOCKING;
} else {
entry->lock_state = LS_UNLOCKED;
entry->last_modified = time(0);
CheckLimit();
}
return true;
}
StreamInterface* DiskCache::ReadResource(const std::string& id,
size_t index) const {
const Entry* entry = GetEntry(id);
if (LS_UNLOCKED != entry->lock_state)
return NULL;
if (index >= entry->streams)
return NULL;
scoped_ptr<FileStream> file(new FileStream);
if (!file->Open(IdToFilename(id, index), "rb", NULL))
return NULL;
entry->accessors += 1;
total_accessors_ += 1;
return new DiskCacheAdapter(this, id, index, file.release());
}
bool DiskCache::HasResource(const std::string& id) const {
const Entry* entry = GetEntry(id);
return (NULL != entry) && (entry->streams > 0);
}
bool DiskCache::HasResourceStream(const std::string& id, size_t index) const {
const Entry* entry = GetEntry(id);
if ((NULL == entry) || (index >= entry->streams))
return false;
std::string filename = IdToFilename(id, index);
return FileExists(filename);
}
bool DiskCache::DeleteResource(const std::string& id) {
Entry* entry = GetOrCreateEntry(id, false);
if (!entry)
return true;
if ((LS_UNLOCKED != entry->lock_state) || (entry->accessors > 0))
return false;
bool success = true;
for (size_t index = 0; index < entry->streams; ++index) {
std::string filename = IdToFilename(id, index);
if (!FileExists(filename))
continue;
if (!DeleteFile(filename)) {
LOG_F(LS_ERROR) << "Couldn't remove cache file: " << filename;
success = false;
}
}
total_size_ -= entry->size;
map_.erase(id);
return success;
}
bool DiskCache::CheckLimit() {
#ifdef _DEBUG
// Temporary check to make sure everything is working correctly.
size_t cache_size = 0;
for (EntryMap::iterator it = map_.begin(); it != map_.end(); ++it) {
cache_size += it->second.size;
}
ASSERT(cache_size == total_size_);
#endif // _DEBUG
// TODO: Replace this with a non-brain-dead algorithm for clearing out the
// oldest resources... something that isn't O(n^2)
while (total_size_ > max_cache_) {
EntryMap::iterator oldest = map_.end();
for (EntryMap::iterator it = map_.begin(); it != map_.end(); ++it) {
if ((LS_UNLOCKED != it->second.lock_state) || (it->second.accessors > 0))
continue;
oldest = it;
break;
}
if (oldest == map_.end()) {
LOG_F(LS_WARNING) << "All resources are locked!";
return false;
}
for (EntryMap::iterator it = oldest++; it != map_.end(); ++it) {
if (it->second.last_modified < oldest->second.last_modified) {
oldest = it;
}
}
if (!DeleteResource(oldest->first)) {
LOG_F(LS_ERROR) << "Couldn't delete from cache!";
return false;
}
}
return true;
}
std::string DiskCache::IdToFilename(const std::string& id, size_t index) const {
#ifdef TRANSPARENT_CACHE_NAMES
// This escapes colons and other filesystem characters, so the user can't open
// special devices (like "COM1:"), or access other directories.
size_t buffer_size = id.length()*3 + 1;
char* buffer = new char[buffer_size];
encode(buffer, buffer_size, id.data(), id.length(),
unsafe_filename_characters(), '%');
// TODO: ASSERT(strlen(buffer) < FileSystem::MaxBasenameLength());
#else // !TRANSPARENT_CACHE_NAMES
// We might want to just use a hash of the filename at some point, both for
// obfuscation, and to avoid both filename length and escaping issues.
ASSERT(false);
#endif // !TRANSPARENT_CACHE_NAMES
char extension[32];
sprintfn(extension, ARRAY_SIZE(extension), ".%u", index);
Pathname pathname;
pathname.SetFolder(folder_);
pathname.SetBasename(buffer);
pathname.SetExtension(extension);
#ifdef TRANSPARENT_CACHE_NAMES
delete [] buffer;
#endif // TRANSPARENT_CACHE_NAMES
return pathname.pathname();
}
bool DiskCache::FilenameToId(const std::string& filename, std::string* id,
size_t* index) const {
Pathname pathname(filename);
unsigned tempdex;
if (1 != sscanf(pathname.extension().c_str(), ".%u", &tempdex))
return false;
*index = static_cast<size_t>(tempdex);
size_t buffer_size = pathname.basename().length() + 1;
char* buffer = new char[buffer_size];
decode(buffer, buffer_size, pathname.basename().data(),
pathname.basename().length(), '%');
id->assign(buffer);
delete [] buffer;
return true;
}
DiskCache::Entry* DiskCache::GetOrCreateEntry(const std::string& id,
bool create) {
EntryMap::iterator it = map_.find(id);
if (it != map_.end())
return &it->second;
if (!create)
return NULL;
Entry e;
e.lock_state = LS_UNLOCKED;
e.accessors = 0;
e.size = 0;
e.streams = 0;
e.last_modified = time(0);
it = map_.insert(EntryMap::value_type(id, e)).first;
return &it->second;
}
void DiskCache::ReleaseResource(const std::string& id, size_t index) const {
const Entry* entry = GetEntry(id);
if (!entry) {
LOG_F(LS_WARNING) << "Missing cache entry";
ASSERT(false);
return;
}
entry->accessors -= 1;
total_accessors_ -= 1;
if (LS_UNLOCKED != entry->lock_state) {
// This is safe, because locked resources only issue WriteResource, which
// is non-const. Think about a better way to handle it.
DiskCache* this2 = const_cast<DiskCache*>(this);
Entry* entry2 = this2->GetOrCreateEntry(id, false);
size_t new_size = 0;
std::string filename(IdToFilename(id, index));
FileStream::GetSize(filename, &new_size);
entry2->size += new_size;
this2->total_size_ += new_size;
if ((LS_UNLOCKING == entry->lock_state) && (0 == entry->accessors)) {
entry2->last_modified = time(0);
entry2->lock_state = LS_UNLOCKED;
this2->CheckLimit();
}
}
}
///////////////////////////////////////////////////////////////////////////////
} // namespace rtc

Просмотреть файл

@ -0,0 +1,125 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_DISKCACHE_H__
#define WEBRTC_BASE_DISKCACHE_H__
#include <map>
#include <string>
#if defined(WEBRTC_WIN)
#undef UnlockResource
#endif // WEBRTC_WIN
namespace rtc {
class StreamInterface;
///////////////////////////////////////////////////////////////////////////////
// DiskCache - An LRU cache of streams, stored on disk.
//
// Streams are identified by a unique resource id. Multiple streams can be
// associated with each resource id, distinguished by an index. When old
// resources are flushed from the cache, all streams associated with those
// resources are removed together.
// DiskCache is designed to persist across executions of the program. It is
// safe for use from an arbitrary number of users on a single thread, but not
// from multiple threads or other processes.
///////////////////////////////////////////////////////////////////////////////
class DiskCache {
public:
DiskCache();
virtual ~DiskCache();
bool Initialize(const std::string& folder, size_t size);
bool Purge();
bool LockResource(const std::string& id);
StreamInterface* WriteResource(const std::string& id, size_t index);
bool UnlockResource(const std::string& id);
StreamInterface* ReadResource(const std::string& id, size_t index) const;
bool HasResource(const std::string& id) const;
bool HasResourceStream(const std::string& id, size_t index) const;
bool DeleteResource(const std::string& id);
protected:
virtual bool InitializeEntries() = 0;
virtual bool PurgeFiles() = 0;
virtual bool FileExists(const std::string& filename) const = 0;
virtual bool DeleteFile(const std::string& filename) const = 0;
enum LockState { LS_UNLOCKED, LS_LOCKED, LS_UNLOCKING };
struct Entry {
LockState lock_state;
mutable size_t accessors;
size_t size;
size_t streams;
time_t last_modified;
};
typedef std::map<std::string, Entry> EntryMap;
friend class DiskCacheAdapter;
bool CheckLimit();
std::string IdToFilename(const std::string& id, size_t index) const;
bool FilenameToId(const std::string& filename, std::string* id,
size_t* index) const;
const Entry* GetEntry(const std::string& id) const {
return const_cast<DiskCache*>(this)->GetOrCreateEntry(id, false);
}
Entry* GetOrCreateEntry(const std::string& id, bool create);
void ReleaseResource(const std::string& id, size_t index) const;
std::string folder_;
size_t max_cache_, total_size_;
EntryMap map_;
mutable size_t total_accessors_;
};
///////////////////////////////////////////////////////////////////////////////
// CacheLock - Automatically manage locking and unlocking, with optional
// rollback semantics
///////////////////////////////////////////////////////////////////////////////
class CacheLock {
public:
CacheLock(DiskCache* cache, const std::string& id, bool rollback = false)
: cache_(cache), id_(id), rollback_(rollback)
{
locked_ = cache_->LockResource(id_);
}
~CacheLock() {
if (locked_) {
cache_->UnlockResource(id_);
if (rollback_) {
cache_->DeleteResource(id_);
}
}
}
bool IsLocked() const { return locked_; }
void Commit() { rollback_ = false; }
private:
DiskCache* cache_;
std::string id_;
bool rollback_, locked_;
};
///////////////////////////////////////////////////////////////////////////////
} // namespace rtc
#endif // WEBRTC_BASE_DISKCACHE_H__

Просмотреть файл

@ -0,0 +1,86 @@
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/win32.h"
#include <shellapi.h>
#include <shlobj.h>
#include <tchar.h>
#include <time.h>
#include "webrtc/base/common.h"
#include "webrtc/base/diskcache.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/base/stream.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/base/diskcache_win32.h"
namespace rtc {
bool DiskCacheWin32::InitializeEntries() {
// Note: We could store the cache information in a separate file, for faster
// initialization. Figuring it out empirically works, too.
std::wstring path16 = ToUtf16(folder_);
path16.append(1, '*');
WIN32_FIND_DATA find_data;
HANDLE find_handle = FindFirstFile(path16.c_str(), &find_data);
if (find_handle != INVALID_HANDLE_VALUE) {
do {
size_t index;
std::string id;
if (!FilenameToId(ToUtf8(find_data.cFileName), &id, &index))
continue;
Entry* entry = GetOrCreateEntry(id, true);
entry->size += find_data.nFileSizeLow;
total_size_ += find_data.nFileSizeLow;
entry->streams = _max(entry->streams, index + 1);
FileTimeToUnixTime(find_data.ftLastWriteTime, &entry->last_modified);
} while (FindNextFile(find_handle, &find_data));
FindClose(find_handle);
}
return true;
}
bool DiskCacheWin32::PurgeFiles() {
std::wstring path16 = ToUtf16(folder_);
path16.append(1, '*');
path16.append(1, '\0');
SHFILEOPSTRUCT file_op = { 0 };
file_op.wFunc = FO_DELETE;
file_op.pFrom = path16.c_str();
file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT
| FOF_NORECURSION | FOF_FILESONLY;
if (0 != SHFileOperation(&file_op)) {
LOG_F(LS_ERROR) << "Couldn't delete cache files";
return false;
}
return true;
}
bool DiskCacheWin32::FileExists(const std::string& filename) const {
DWORD result = ::GetFileAttributes(ToUtf16(filename).c_str());
return (INVALID_FILE_ATTRIBUTES != result);
}
bool DiskCacheWin32::DeleteFile(const std::string& filename) const {
return ::DeleteFile(ToUtf16(filename).c_str()) != 0;
}
}

Просмотреть файл

@ -0,0 +1,29 @@
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_DISKCACHEWIN32_H__
#define WEBRTC_BASE_DISKCACHEWIN32_H__
#include "webrtc/base/diskcache.h"
namespace rtc {
class DiskCacheWin32 : public DiskCache {
protected:
virtual bool InitializeEntries();
virtual bool PurgeFiles();
virtual bool FileExists(const std::string& filename) const;
virtual bool DeleteFile(const std::string& filename) const;
};
}
#endif // WEBRTC_BASE_DISKCACHEWIN32_H__

Просмотреть файл

@ -0,0 +1,45 @@
/*
* Copyright 2013 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_DSCP_H_
#define WEBRTC_BASE_DSCP_H_
namespace rtc {
// Differentiated Services Code Point.
// See http://tools.ietf.org/html/rfc2474 for details.
enum DiffServCodePoint {
DSCP_NO_CHANGE = -1,
DSCP_DEFAULT = 0, // Same as DSCP_CS0
DSCP_CS0 = 0, // The default
DSCP_CS1 = 8, // Bulk/background traffic
DSCP_AF11 = 10,
DSCP_AF12 = 12,
DSCP_AF13 = 14,
DSCP_CS2 = 16,
DSCP_AF21 = 18,
DSCP_AF22 = 20,
DSCP_AF23 = 22,
DSCP_CS3 = 24,
DSCP_AF31 = 26,
DSCP_AF32 = 28,
DSCP_AF33 = 30,
DSCP_CS4 = 32,
DSCP_AF41 = 34, // Video
DSCP_AF42 = 36, // Video
DSCP_AF43 = 38, // Video
DSCP_CS5 = 40, // Video
DSCP_EF = 46, // Voice
DSCP_CS6 = 48, // Voice
DSCP_CS7 = 56, // Control messages
};
} // namespace rtc
#endif // WEBRTC_BASE_DSCP_H_

Просмотреть файл

@ -0,0 +1,135 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/event.h"
#if defined(WEBRTC_WIN)
#include <windows.h>
#elif defined(WEBRTC_POSIX)
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#else
#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
#endif
namespace rtc {
#if defined(WEBRTC_WIN)
Event::Event(bool manual_reset, bool initially_signaled)
: is_manual_reset_(manual_reset),
is_initially_signaled_(initially_signaled) {
event_handle_ = ::CreateEvent(NULL, // Security attributes.
is_manual_reset_,
is_initially_signaled_,
NULL); // Name.
ASSERT(event_handle_ != NULL);
}
Event::~Event() {
CloseHandle(event_handle_);
}
void Event::Set() {
SetEvent(event_handle_);
}
void Event::Reset() {
ResetEvent(event_handle_);
}
bool Event::Wait(int cms) {
DWORD ms = (cms == kForever)? INFINITE : cms;
return (WaitForSingleObject(event_handle_, ms) == WAIT_OBJECT_0);
}
#elif defined(WEBRTC_POSIX)
Event::Event(bool manual_reset, bool initially_signaled)
: is_manual_reset_(manual_reset),
event_status_(initially_signaled) {
VERIFY(pthread_mutex_init(&event_mutex_, NULL) == 0);
VERIFY(pthread_cond_init(&event_cond_, NULL) == 0);
}
Event::~Event() {
pthread_mutex_destroy(&event_mutex_);
pthread_cond_destroy(&event_cond_);
}
void Event::Set() {
pthread_mutex_lock(&event_mutex_);
event_status_ = true;
pthread_cond_broadcast(&event_cond_);
pthread_mutex_unlock(&event_mutex_);
}
void Event::Reset() {
pthread_mutex_lock(&event_mutex_);
event_status_ = false;
pthread_mutex_unlock(&event_mutex_);
}
bool Event::Wait(int cms) {
pthread_mutex_lock(&event_mutex_);
int error = 0;
if (cms != kForever) {
// Converting from seconds and microseconds (1e-6) plus
// milliseconds (1e-3) to seconds and nanoseconds (1e-9).
struct timespec ts;
#if HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
// Use relative time version, which tends to be more efficient for
// pthread implementations where provided (like on Android).
ts.tv_sec = cms / 1000;
ts.tv_nsec = (cms % 1000) * 1000000;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec + (cms / 1000);
ts.tv_nsec = tv.tv_usec * 1000 + (cms % 1000) * 1000000;
// Handle overflow.
if (ts.tv_nsec >= 1000000000) {
ts.tv_sec++;
ts.tv_nsec -= 1000000000;
}
#endif
while (!event_status_ && error == 0) {
#if HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
error = pthread_cond_timedwait_relative_np(
&event_cond_, &event_mutex_, &ts);
#else
error = pthread_cond_timedwait(&event_cond_, &event_mutex_, &ts);
#endif
}
} else {
while (!event_status_ && error == 0)
error = pthread_cond_wait(&event_cond_, &event_mutex_);
}
// NOTE(liulk): Exactly one thread will auto-reset this event. All
// the other threads will think it's unsignaled. This seems to be
// consistent with auto-reset events in WEBRTC_WIN
if (error == 0 && !is_manual_reset_)
event_status_ = false;
pthread_mutex_unlock(&event_mutex_);
return (error == 0);
}
#endif
} // namespace rtc

Просмотреть файл

@ -0,0 +1,51 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_EVENT_H__
#define WEBRTC_BASE_EVENT_H__
#if defined(WEBRTC_WIN)
#include "webrtc/base/win32.h" // NOLINT: consider this a system header.
#elif defined(WEBRTC_POSIX)
#include <pthread.h>
#else
#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
#endif
#include "webrtc/base/basictypes.h"
#include "webrtc/base/common.h"
namespace rtc {
class Event {
public:
Event(bool manual_reset, bool initially_signaled);
~Event();
void Set();
void Reset();
bool Wait(int cms);
private:
bool is_manual_reset_;
#if defined(WEBRTC_WIN)
bool is_initially_signaled_;
HANDLE event_handle_;
#elif defined(WEBRTC_POSIX)
bool event_status_;
pthread_mutex_t event_mutex_;
pthread_cond_t event_cond_;
#endif
};
} // namespace rtc
#endif // WEBRTC_BASE_EVENT_H__

Просмотреть файл

@ -0,0 +1,42 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/event.h"
#include "webrtc/base/gunit.h"
namespace rtc {
TEST(EventTest, InitiallySignaled) {
Event event(false, true);
ASSERT_TRUE(event.Wait(0));
}
TEST(EventTest, ManualReset) {
Event event(true, false);
ASSERT_FALSE(event.Wait(0));
event.Set();
ASSERT_TRUE(event.Wait(0));
ASSERT_TRUE(event.Wait(0));
event.Reset();
ASSERT_FALSE(event.Wait(0));
}
TEST(EventTest, AutoReset) {
Event event(false, false);
ASSERT_FALSE(event.Wait(0));
event.Set();
ASSERT_TRUE(event.Wait(0));
ASSERT_FALSE(event.Wait(0));
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,43 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/exp_filter.h"
#include <math.h>
namespace rtc {
const float ExpFilter::kValueUndefined = -1.0f;
void ExpFilter::Reset(float alpha) {
alpha_ = alpha;
filtered_ = kValueUndefined;
}
float ExpFilter::Apply(float exp, float sample) {
if (filtered_ == kValueUndefined) {
// Initialize filtered value.
filtered_ = sample;
} else if (exp == 1.0) {
filtered_ = alpha_ * filtered_ + (1 - alpha_) * sample;
} else {
float alpha = pow(alpha_, exp);
filtered_ = alpha * filtered_ + (1 - alpha) * sample;
}
if (max_ != kValueUndefined && filtered_ > max_) {
filtered_ = max_;
}
return filtered_;
}
void ExpFilter::UpdateBase(float alpha) {
alpha_ = alpha;
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,49 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_EXP_FILTER_H_
#define WEBRTC_BASE_EXP_FILTER_H_
namespace rtc {
// This class can be used, for example, for smoothing the result of bandwidth
// estimation and packet loss estimation.
class ExpFilter {
public:
static const float kValueUndefined;
explicit ExpFilter(float alpha, float max = kValueUndefined)
: max_(max) {
Reset(alpha);
}
// Resets the filter to its initial state, and resets filter factor base to
// the given value |alpha|.
void Reset(float alpha);
// Applies the filter with a given exponent on the provided sample:
// y(k) = min(alpha_^ exp * y(k-1) + (1 - alpha_^ exp) * sample, max_).
float Apply(float exp, float sample);
// Returns current filtered value.
float filtered() const { return filtered_; }
// Changes the filter factor base to the given value |alpha|.
void UpdateBase(float alpha);
private:
float alpha_; // Filter factor base.
float filtered_; // Current filter output.
const float max_;
};
} // namespace rtc
#endif // WEBRTC_BASE_EXP_FILTER_H_

Просмотреть файл

@ -0,0 +1,71 @@
/*
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "webrtc/base/gunit.h"
#include "webrtc/base/exp_filter.h"
namespace rtc {
TEST(ExpFilterTest, FirstTimeOutputEqualInput) {
// No max value defined.
ExpFilter filter = ExpFilter(0.9f);
filter.Apply(100.0f, 10.0f);
// First time, first argument no effect.
double value = 10.0f;
EXPECT_FLOAT_EQ(value, filter.filtered());
}
TEST(ExpFilterTest, SecondTime) {
double value;
ExpFilter filter = ExpFilter(0.9f);
filter.Apply(100.0f, 10.0f);
// First time, first argument no effect.
value = 10.0f;
filter.Apply(10.0f, 20.0f);
double alpha = pow(0.9f, 10.0f);
value = alpha * value + (1.0f - alpha) * 20.0f;
EXPECT_FLOAT_EQ(value, filter.filtered());
}
TEST(ExpFilterTest, Reset) {
ExpFilter filter = ExpFilter(0.9f);
filter.Apply(100.0f, 10.0f);
filter.Reset(0.8f);
filter.Apply(100.0f, 1.0f);
// Become first time after a reset.
double value = 1.0f;
EXPECT_FLOAT_EQ(value, filter.filtered());
}
TEST(ExpfilterTest, OutputLimitedByMax) {
double value;
// Max value defined.
ExpFilter filter = ExpFilter(0.9f, 1.0f);
filter.Apply(100.0f, 10.0f);
// Limited to max value.
value = 1.0f;
EXPECT_EQ(value, filter.filtered());
filter.Apply(1.0f, 0.0f);
value = 0.9f * value;
EXPECT_FLOAT_EQ(value, filter.filtered());
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,32 @@
/*
* Copyright 2013 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_FAKECPUMONITOR_H_
#define WEBRTC_BASE_FAKECPUMONITOR_H_
#include "webrtc/base/cpumonitor.h"
namespace rtc {
class FakeCpuMonitor : public rtc::CpuMonitor {
public:
explicit FakeCpuMonitor(Thread* thread)
: CpuMonitor(thread) {
}
~FakeCpuMonitor() {
}
virtual void OnMessage(rtc::Message* msg) {
}
};
} // namespace rtc
#endif // WEBRTC_BASE_FAKECPUMONITOR_H_

Просмотреть файл

@ -0,0 +1,119 @@
/*
* Copyright 2009 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_FAKENETWORK_H_
#define WEBRTC_BASE_FAKENETWORK_H_
#include <string>
#include <vector>
#include "webrtc/base/network.h"
#include "webrtc/base/messagehandler.h"
#include "webrtc/base/socketaddress.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/thread.h"
namespace rtc {
const int kFakeIPv4NetworkPrefixLength = 24;
const int kFakeIPv6NetworkPrefixLength = 64;
// Fake network manager that allows us to manually specify the IPs to use.
class FakeNetworkManager : public NetworkManagerBase,
public MessageHandler {
public:
FakeNetworkManager()
: thread_(Thread::Current()),
next_index_(0),
started_(false),
sent_first_update_(false) {
}
typedef std::vector<SocketAddress> IfaceList;
void AddInterface(const SocketAddress& iface) {
// ensure a unique name for the interface
SocketAddress address("test" + rtc::ToString(next_index_++), 0);
address.SetResolvedIP(iface.ipaddr());
ifaces_.push_back(address);
DoUpdateNetworks();
}
void RemoveInterface(const SocketAddress& iface) {
for (IfaceList::iterator it = ifaces_.begin();
it != ifaces_.end(); ++it) {
if (it->EqualIPs(iface)) {
ifaces_.erase(it);
break;
}
}
DoUpdateNetworks();
}
virtual void StartUpdating() {
if (started_) {
if (sent_first_update_)
SignalNetworksChanged();
return;
}
started_ = true;
sent_first_update_ = false;
thread_->Post(this);
}
virtual void StopUpdating() {
started_ = false;
}
// MessageHandler interface.
virtual void OnMessage(Message* msg) {
DoUpdateNetworks();
}
private:
void DoUpdateNetworks() {
if (!started_)
return;
std::vector<Network*> networks;
for (IfaceList::iterator it = ifaces_.begin();
it != ifaces_.end(); ++it) {
int prefix_length = 0;
if (it->ipaddr().family() == AF_INET) {
prefix_length = kFakeIPv4NetworkPrefixLength;
} else if (it->ipaddr().family() == AF_INET6) {
prefix_length = kFakeIPv6NetworkPrefixLength;
}
IPAddress prefix = TruncateIP(it->ipaddr(), prefix_length);
scoped_ptr<Network> net(new Network(it->hostname(),
it->hostname(),
prefix,
prefix_length));
net->AddIP(it->ipaddr());
networks.push_back(net.release());
}
bool changed;
MergeNetworkList(networks, &changed);
if (changed || !sent_first_update_) {
SignalNetworksChanged();
sent_first_update_ = true;
}
}
Thread* thread_;
IfaceList ifaces_;
int next_index_;
bool started_;
bool sent_first_update_;
};
} // namespace rtc
#endif // WEBRTC_BASE_FAKENETWORK_H_

Просмотреть файл

@ -0,0 +1,96 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_FAKESSLIDENTITY_H_
#define WEBRTC_BASE_FAKESSLIDENTITY_H_
#include <algorithm>
#include <vector>
#include "webrtc/base/messagedigest.h"
#include "webrtc/base/sslidentity.h"
namespace rtc {
class FakeSSLCertificate : public rtc::SSLCertificate {
public:
// SHA-1 is the default digest algorithm because it is available in all build
// configurations used for unit testing.
explicit FakeSSLCertificate(const std::string& data)
: data_(data), digest_algorithm_(DIGEST_SHA_1) {}
explicit FakeSSLCertificate(const std::vector<std::string>& certs)
: data_(certs.front()), digest_algorithm_(DIGEST_SHA_1) {
std::vector<std::string>::const_iterator it;
// Skip certs[0].
for (it = certs.begin() + 1; it != certs.end(); ++it) {
certs_.push_back(FakeSSLCertificate(*it));
}
}
virtual FakeSSLCertificate* GetReference() const {
return new FakeSSLCertificate(*this);
}
virtual std::string ToPEMString() const {
return data_;
}
virtual void ToDER(Buffer* der_buffer) const {
std::string der_string;
VERIFY(SSLIdentity::PemToDer(kPemTypeCertificate, data_, &der_string));
der_buffer->SetData(der_string.c_str(), der_string.size());
}
void set_digest_algorithm(const std::string& algorithm) {
digest_algorithm_ = algorithm;
}
virtual bool GetSignatureDigestAlgorithm(std::string* algorithm) const {
*algorithm = digest_algorithm_;
return true;
}
virtual bool ComputeDigest(const std::string& algorithm,
unsigned char* digest,
size_t size,
size_t* length) const {
*length = rtc::ComputeDigest(algorithm, data_.c_str(), data_.size(),
digest, size);
return (*length != 0);
}
virtual bool GetChain(SSLCertChain** chain) const {
if (certs_.empty())
return false;
std::vector<SSLCertificate*> new_certs(certs_.size());
std::transform(certs_.begin(), certs_.end(), new_certs.begin(), DupCert);
*chain = new SSLCertChain(new_certs);
std::for_each(new_certs.begin(), new_certs.end(), DeleteCert);
return true;
}
private:
static FakeSSLCertificate* DupCert(FakeSSLCertificate cert) {
return cert.GetReference();
}
static void DeleteCert(SSLCertificate* cert) { delete cert; }
std::string data_;
std::vector<FakeSSLCertificate> certs_;
std::string digest_algorithm_;
};
class FakeSSLIdentity : public rtc::SSLIdentity {
public:
explicit FakeSSLIdentity(const std::string& data) : cert_(data) {}
explicit FakeSSLIdentity(const FakeSSLCertificate& cert) : cert_(cert) {}
virtual FakeSSLIdentity* GetReference() const {
return new FakeSSLIdentity(*this);
}
virtual const FakeSSLCertificate& certificate() const { return cert_; }
private:
FakeSSLCertificate cert_;
};
} // namespace rtc
#endif // WEBRTC_BASE_FAKESSLIDENTITY_H_

Просмотреть файл

@ -0,0 +1,38 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// A fake TaskRunner for use in unit tests.
#ifndef WEBRTC_BASE_FAKETASKRUNNER_H_
#define WEBRTC_BASE_FAKETASKRUNNER_H_
#include "webrtc/base/taskparent.h"
#include "webrtc/base/taskrunner.h"
namespace rtc {
class FakeTaskRunner : public TaskRunner {
public:
FakeTaskRunner() : current_time_(0) {}
virtual ~FakeTaskRunner() {}
virtual void WakeTasks() { RunTasks(); }
virtual int64 CurrentTime() {
// Implement if needed.
return current_time_++;
}
int64 current_time_;
};
} // namespace rtc
#endif // WEBRTC_BASE_FAKETASKRUNNER_H_

Просмотреть файл

@ -0,0 +1,62 @@
/*
* Copyright 2009 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/filelock.h"
#include "webrtc/base/fileutils.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/base/stream.h"
namespace rtc {
FileLock::FileLock(const std::string& path, FileStream* file)
: path_(path), file_(file) {
}
FileLock::~FileLock() {
MaybeUnlock();
}
void FileLock::Unlock() {
LOG_F(LS_INFO);
MaybeUnlock();
}
void FileLock::MaybeUnlock() {
if (file_) {
LOG(LS_INFO) << "Unlocking:" << path_;
file_->Close();
Filesystem::DeleteFile(path_);
file_.reset();
}
}
FileLock* FileLock::TryLock(const std::string& path) {
FileStream* stream = new FileStream();
bool ok = false;
#if defined(WEBRTC_WIN)
// Open and lock in a single operation.
ok = stream->OpenShare(path, "a", _SH_DENYRW, NULL);
#else // WEBRTC_LINUX && !WEBRTC_ANDROID and WEBRTC_MAC && !defined(WEBRTC_IOS)
ok = stream->Open(path, "a", NULL) && stream->TryLock();
#endif
if (ok) {
return new FileLock(path, stream);
} else {
// Something failed, either we didn't succeed to open the
// file or we failed to lock it. Anyway remove the heap
// allocated object and then return NULL to indicate failure.
delete stream;
return NULL;
}
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,53 @@
/*
* Copyright 2009 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_FILELOCK_H_
#define WEBRTC_BASE_FILELOCK_H_
#include <string>
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/scoped_ptr.h"
namespace rtc {
class FileStream;
// Implements a very simple cross process lock based on a file.
// When Lock(...) is called we try to open/create the file in read/write
// mode without any sharing. (Or locking it with flock(...) on Unix)
// If the process crash the OS will make sure that the file descriptor
// is released and another process can accuire the lock.
// This doesn't work on ancient OSX/Linux versions if used on NFS.
// (Nfs-client before: ~2.6 and Linux Kernel < 2.6.)
class FileLock {
public:
virtual ~FileLock();
// Attempts to lock the file. The caller owns the returned
// lock object. Returns NULL if the file already was locked.
static FileLock* TryLock(const std::string& path);
void Unlock();
protected:
FileLock(const std::string& path, FileStream* file);
private:
void MaybeUnlock();
std::string path_;
scoped_ptr<FileStream> file_;
DISALLOW_EVIL_CONSTRUCTORS(FileLock);
};
} // namespace rtc
#endif // WEBRTC_BASE_FILELOCK_H_

Просмотреть файл

@ -0,0 +1,88 @@
/*
* Copyright 2009 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string>
#include "webrtc/base/event.h"
#include "webrtc/base/filelock.h"
#include "webrtc/base/fileutils.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread.h"
#include "webrtc/test/testsupport/gtest_disable.h"
namespace rtc {
const static std::string kLockFile = "TestLockFile";
const static int kTimeoutMS = 5000;
class FileLockTest : public testing::Test, public Runnable {
public:
FileLockTest() : done_(false, false), thread_lock_failed_(false) {
}
virtual void Run(Thread* t) {
scoped_ptr<FileLock> lock(FileLock::TryLock(temp_file_.pathname()));
// The lock is already owned by the main thread of
// this test, therefore the TryLock(...) call should fail.
thread_lock_failed_ = lock.get() == NULL;
done_.Set();
}
protected:
virtual void SetUp() {
thread_lock_failed_ = false;
Filesystem::GetAppTempFolder(&temp_dir_);
temp_file_ = Pathname(temp_dir_.pathname(), kLockFile);
}
void LockOnThread() {
locker_.Start(this);
done_.Wait(kTimeoutMS);
}
Event done_;
Thread locker_;
bool thread_lock_failed_;
Pathname temp_dir_;
Pathname temp_file_;
};
TEST_F(FileLockTest, TestLockFileDeleted) {
scoped_ptr<FileLock> lock(FileLock::TryLock(temp_file_.pathname()));
EXPECT_TRUE(lock.get() != NULL);
EXPECT_FALSE(Filesystem::IsAbsent(temp_file_.pathname()));
lock->Unlock();
EXPECT_TRUE(Filesystem::IsAbsent(temp_file_.pathname()));
}
TEST_F(FileLockTest, TestLock) {
scoped_ptr<FileLock> lock(FileLock::TryLock(temp_file_.pathname()));
EXPECT_TRUE(lock.get() != NULL);
}
TEST_F(FileLockTest, TestLockX2) {
scoped_ptr<FileLock> lock1(FileLock::TryLock(temp_file_.pathname()));
EXPECT_TRUE(lock1.get() != NULL);
scoped_ptr<FileLock> lock2(FileLock::TryLock(temp_file_.pathname()));
EXPECT_TRUE(lock2.get() == NULL);
}
TEST_F(FileLockTest, TestThreadedLock) {
scoped_ptr<FileLock> lock(FileLock::TryLock(temp_file_.pathname()));
EXPECT_TRUE(lock.get() != NULL);
LockOnThread();
EXPECT_TRUE(thread_lock_failed_);
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,275 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include "webrtc/base/pathutils.h"
#include "webrtc/base/fileutils.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/base/stream.h"
#if defined(WEBRTC_WIN)
#include "webrtc/base/win32filesystem.h"
#else
#include "webrtc/base/unixfilesystem.h"
#endif
#if !defined(WEBRTC_WIN)
#define MAX_PATH 260
#endif
namespace rtc {
//////////////////////////
// Directory Iterator //
//////////////////////////
// A DirectoryIterator is created with a given directory. It originally points
// to the first file in the directory, and can be advanecd with Next(). This
// allows you to get information about each file.
// Constructor
DirectoryIterator::DirectoryIterator()
#ifdef WEBRTC_WIN
: handle_(INVALID_HANDLE_VALUE) {
#else
: dir_(NULL), dirent_(NULL) {
#endif
}
// Destructor
DirectoryIterator::~DirectoryIterator() {
#if defined(WEBRTC_WIN)
if (handle_ != INVALID_HANDLE_VALUE)
::FindClose(handle_);
#else
if (dir_)
closedir(dir_);
#endif
}
// Starts traversing a directory.
// dir is the directory to traverse
// returns true if the directory exists and is valid
bool DirectoryIterator::Iterate(const Pathname &dir) {
directory_ = dir.pathname();
#if defined(WEBRTC_WIN)
if (handle_ != INVALID_HANDLE_VALUE)
::FindClose(handle_);
std::string d = dir.pathname() + '*';
handle_ = ::FindFirstFile(ToUtf16(d).c_str(), &data_);
if (handle_ == INVALID_HANDLE_VALUE)
return false;
#else
if (dir_ != NULL)
closedir(dir_);
dir_ = ::opendir(directory_.c_str());
if (dir_ == NULL)
return false;
dirent_ = readdir(dir_);
if (dirent_ == NULL)
return false;
if (::stat(std::string(directory_ + Name()).c_str(), &stat_) != 0)
return false;
#endif
return true;
}
// Advances to the next file
// returns true if there were more files in the directory.
bool DirectoryIterator::Next() {
#if defined(WEBRTC_WIN)
return ::FindNextFile(handle_, &data_) == TRUE;
#else
dirent_ = ::readdir(dir_);
if (dirent_ == NULL)
return false;
return ::stat(std::string(directory_ + Name()).c_str(), &stat_) == 0;
#endif
}
// returns true if the file currently pointed to is a directory
bool DirectoryIterator::IsDirectory() const {
#if defined(WEBRTC_WIN)
return (data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FALSE;
#else
return S_ISDIR(stat_.st_mode);
#endif
}
// returns the name of the file currently pointed to
std::string DirectoryIterator::Name() const {
#if defined(WEBRTC_WIN)
return ToUtf8(data_.cFileName);
#else
assert(dirent_ != NULL);
return dirent_->d_name;
#endif
}
// returns the size of the file currently pointed to
size_t DirectoryIterator::FileSize() const {
#if !defined(WEBRTC_WIN)
return stat_.st_size;
#else
return data_.nFileSizeLow;
#endif
}
bool DirectoryIterator::OlderThan(int seconds) const {
time_t file_modify_time;
#if defined(WEBRTC_WIN)
FileTimeToUnixTime(data_.ftLastWriteTime, &file_modify_time);
#else
file_modify_time = stat_.st_mtime;
#endif
return TimeDiff(time(NULL), file_modify_time) >= seconds;
}
FilesystemInterface* Filesystem::default_filesystem_ = NULL;
FilesystemInterface *Filesystem::EnsureDefaultFilesystem() {
if (!default_filesystem_) {
#if defined(WEBRTC_WIN)
default_filesystem_ = new Win32Filesystem();
#else
default_filesystem_ = new UnixFilesystem();
#endif
}
return default_filesystem_;
}
bool FilesystemInterface::CopyFolder(const Pathname &old_path,
const Pathname &new_path) {
bool success = true;
VERIFY(IsFolder(old_path));
Pathname new_dir;
new_dir.SetFolder(new_path.pathname());
Pathname old_dir;
old_dir.SetFolder(old_path.pathname());
if (!CreateFolder(new_dir))
return false;
DirectoryIterator *di = IterateDirectory();
if (!di)
return false;
if (di->Iterate(old_dir.pathname())) {
do {
if (di->Name() == "." || di->Name() == "..")
continue;
Pathname source;
Pathname dest;
source.SetFolder(old_dir.pathname());
dest.SetFolder(new_path.pathname());
source.SetFilename(di->Name());
dest.SetFilename(di->Name());
if (!CopyFileOrFolder(source, dest))
success = false;
} while (di->Next());
}
delete di;
return success;
}
bool FilesystemInterface::DeleteFolderContents(const Pathname &folder) {
bool success = true;
VERIFY(IsFolder(folder));
DirectoryIterator *di = IterateDirectory();
if (!di)
return false;
if (di->Iterate(folder)) {
do {
if (di->Name() == "." || di->Name() == "..")
continue;
Pathname subdir;
subdir.SetFolder(folder.pathname());
if (di->IsDirectory()) {
subdir.AppendFolder(di->Name());
if (!DeleteFolderAndContents(subdir)) {
success = false;
}
} else {
subdir.SetFilename(di->Name());
if (!DeleteFile(subdir)) {
success = false;
}
}
} while (di->Next());
}
delete di;
return success;
}
bool FilesystemInterface::CleanAppTempFolder() {
Pathname path;
if (!GetAppTempFolder(&path))
return false;
if (IsAbsent(path))
return true;
if (!IsTemporaryPath(path)) {
ASSERT(false);
return false;
}
return DeleteFolderContents(path);
}
Pathname Filesystem::GetCurrentDirectory() {
return EnsureDefaultFilesystem()->GetCurrentDirectory();
}
bool CreateUniqueFile(Pathname& path, bool create_empty) {
LOG(LS_INFO) << "Path " << path.pathname() << std::endl;
// If no folder is supplied, use the temporary folder
if (path.folder().empty()) {
Pathname temporary_path;
if (!Filesystem::GetTemporaryFolder(temporary_path, true, NULL)) {
printf("Get temp failed\n");
return false;
}
path.SetFolder(temporary_path.pathname());
}
// If no filename is supplied, use a temporary name
if (path.filename().empty()) {
std::string folder(path.folder());
std::string filename = Filesystem::TempFilename(folder, "gt");
path.SetPathname(filename);
if (!create_empty) {
Filesystem::DeleteFile(path.pathname());
}
return true;
}
// Otherwise, create a unique name based on the given filename
// foo.txt -> foo-N.txt
const std::string basename = path.basename();
const size_t MAX_VERSION = 100;
size_t version = 0;
while (version < MAX_VERSION) {
std::string pathname = path.pathname();
if (!Filesystem::IsFile(pathname)) {
if (create_empty) {
FileStream* fs = Filesystem::OpenFile(pathname, "w");
delete fs;
}
return true;
}
version += 1;
char version_base[MAX_PATH];
sprintfn(version_base, ARRAY_SIZE(version_base), "%s-%u",
basename.c_str(), version);
path.SetBasename(version_base);
}
return true;
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,440 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_FILEUTILS_H_
#define WEBRTC_BASE_FILEUTILS_H_
#include <string>
#if !defined(WEBRTC_WIN)
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include "webrtc/base/basictypes.h"
#include "webrtc/base/common.h"
#include "webrtc/base/platform_file.h"
#include "webrtc/base/scoped_ptr.h"
namespace rtc {
class FileStream;
class Pathname;
//////////////////////////
// Directory Iterator //
//////////////////////////
// A DirectoryIterator is created with a given directory. It originally points
// to the first file in the directory, and can be advanecd with Next(). This
// allows you to get information about each file.
class DirectoryIterator {
friend class Filesystem;
public:
// Constructor
DirectoryIterator();
// Destructor
virtual ~DirectoryIterator();
// Starts traversing a directory
// dir is the directory to traverse
// returns true if the directory exists and is valid
// The iterator will point to the first entry in the directory
virtual bool Iterate(const Pathname &path);
// Advances to the next file
// returns true if there were more files in the directory.
virtual bool Next();
// returns true if the file currently pointed to is a directory
virtual bool IsDirectory() const;
// returns the name of the file currently pointed to
virtual std::string Name() const;
// returns the size of the file currently pointed to
virtual size_t FileSize() const;
// returns true if the file is older than seconds
virtual bool OlderThan(int seconds) const;
// checks whether current file is a special directory file "." or ".."
bool IsDots() const {
std::string filename(Name());
return (filename.compare(".") == 0) || (filename.compare("..") == 0);
}
private:
std::string directory_;
#if defined(WEBRTC_WIN)
WIN32_FIND_DATA data_;
HANDLE handle_;
#else
DIR *dir_;
struct dirent *dirent_;
struct stat stat_;
#endif
};
enum FileTimeType { FTT_CREATED, FTT_MODIFIED, FTT_ACCESSED };
class FilesystemInterface {
public:
virtual ~FilesystemInterface() {}
// Returns a DirectoryIterator for a given pathname.
// TODO: Do fancy abstracted stuff
virtual DirectoryIterator *IterateDirectory() {
return new DirectoryIterator();
}
// Opens a file. Returns an open StreamInterface if function succeeds.
// Otherwise, returns NULL.
// TODO: Add an error param to indicate failure reason, similar to
// FileStream::Open
virtual FileStream *OpenFile(const Pathname &filename,
const std::string &mode) = 0;
// Atomically creates an empty file accessible only to the current user if one
// does not already exist at the given path, otherwise fails. This is the only
// secure way to create a file in a shared temp directory (e.g., C:\Temp on
// Windows or /tmp on Linux).
// Note that if it is essential that a file be successfully created then the
// app must generate random names and retry on failure, or else it will be
// vulnerable to a trivial DoS.
virtual bool CreatePrivateFile(const Pathname &filename) = 0;
// This will attempt to delete the path located at filename.
// It ASSERTS and returns false if the path points to a folder or a
// non-existent file.
virtual bool DeleteFile(const Pathname &filename) = 0;
// This will attempt to delete the empty folder located at 'folder'
// It ASSERTS and returns false if the path points to a file or a non-existent
// folder. It fails normally if the folder is not empty or can otherwise
// not be deleted.
virtual bool DeleteEmptyFolder(const Pathname &folder) = 0;
// This will call IterateDirectory, to get a directory iterator, and then
// call DeleteFolderAndContents and DeleteFile on every path contained in this
// folder. If the folder is empty, this returns true.
virtual bool DeleteFolderContents(const Pathname &folder);
// This deletes the contents of a folder, recursively, and then deletes
// the folder itself.
virtual bool DeleteFolderAndContents(const Pathname &folder) {
return DeleteFolderContents(folder) && DeleteEmptyFolder(folder);
}
// This will delete whatever is located at path, be it a file or a folder.
// If it is a folder, it will delete it recursively by calling
// DeleteFolderAndContents
bool DeleteFileOrFolder(const Pathname &path) {
if (IsFolder(path))
return DeleteFolderAndContents(path);
else
return DeleteFile(path);
}
// Creates a directory. This will call itself recursively to create /foo/bar
// even if /foo does not exist. Returns true if the function succeeds.
virtual bool CreateFolder(const Pathname &pathname) = 0;
// This moves a file from old_path to new_path, where "old_path" is a
// plain file. This ASSERTs and returns false if old_path points to a
// directory, and returns true if the function succeeds.
// If the new path is on a different volume than the old path, this function
// will attempt to copy and, if that succeeds, delete the old path.
virtual bool MoveFolder(const Pathname &old_path,
const Pathname &new_path) = 0;
// This moves a directory from old_path to new_path, where "old_path" is a
// directory. This ASSERTs and returns false if old_path points to a plain
// file, and returns true if the function succeeds.
// If the new path is on a different volume, this function will attempt to
// copy and if that succeeds, delete the old path.
virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path) = 0;
// This attempts to move whatever is located at old_path to new_path,
// be it a file or folder.
bool MoveFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
if (IsFile(old_path)) {
return MoveFile(old_path, new_path);
} else {
return MoveFolder(old_path, new_path);
}
}
// This copies a file from old_path to new_path. This method ASSERTs and
// returns false if old_path is a folder, and returns true if the copy
// succeeds.
virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path) = 0;
// This copies a folder from old_path to new_path.
bool CopyFolder(const Pathname &old_path, const Pathname &new_path);
bool CopyFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
if (IsFile(old_path))
return CopyFile(old_path, new_path);
else
return CopyFolder(old_path, new_path);
}
// Returns true if pathname refers to a directory
virtual bool IsFolder(const Pathname& pathname) = 0;
// Returns true if pathname refers to a file
virtual bool IsFile(const Pathname& pathname) = 0;
// Returns true if pathname refers to no filesystem object, every parent
// directory either exists, or is also absent.
virtual bool IsAbsent(const Pathname& pathname) = 0;
// Returns true if pathname represents a temporary location on the system.
virtual bool IsTemporaryPath(const Pathname& pathname) = 0;
// A folder appropriate for storing temporary files (Contents are
// automatically deleted when the program exits)
virtual bool GetTemporaryFolder(Pathname &path, bool create,
const std::string *append) = 0;
virtual std::string TempFilename(const Pathname &dir,
const std::string &prefix) = 0;
// Determines the size of the file indicated by path.
virtual bool GetFileSize(const Pathname& path, size_t* size) = 0;
// Determines a timestamp associated with the file indicated by path.
virtual bool GetFileTime(const Pathname& path, FileTimeType which,
time_t* time) = 0;
// Returns the path to the running application.
// Note: This is not guaranteed to work on all platforms. Be aware of the
// limitations before using it, and robustly handle failure.
virtual bool GetAppPathname(Pathname* path) = 0;
// Get a folder that is unique to the current application, which is suitable
// for sharing data between executions of the app. If the per_user arg is
// true, the folder is also specific to the current user.
virtual bool GetAppDataFolder(Pathname* path, bool per_user) = 0;
// Get a temporary folder that is unique to the current user and application.
// TODO: Re-evaluate the goals of this function. We probably just need any
// directory that won't collide with another existing directory, and which
// will be cleaned up when the program exits.
virtual bool GetAppTempFolder(Pathname* path) = 0;
// Delete the contents of the folder returned by GetAppTempFolder
bool CleanAppTempFolder();
virtual bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) = 0;
// Returns the absolute path of the current directory.
virtual Pathname GetCurrentDirectory() = 0;
// Note: These might go into some shared config section later, but they're
// used by some methods in this interface, so we're leaving them here for now.
void SetOrganizationName(const std::string& organization) {
organization_name_ = organization;
}
void GetOrganizationName(std::string* organization) {
ASSERT(NULL != organization);
*organization = organization_name_;
}
void SetApplicationName(const std::string& application) {
application_name_ = application;
}
void GetApplicationName(std::string* application) {
ASSERT(NULL != application);
*application = application_name_;
}
protected:
std::string organization_name_;
std::string application_name_;
};
class Filesystem {
public:
static FilesystemInterface *default_filesystem() {
ASSERT(default_filesystem_ != NULL);
return default_filesystem_;
}
static void set_default_filesystem(FilesystemInterface *filesystem) {
default_filesystem_ = filesystem;
}
static FilesystemInterface *swap_default_filesystem(
FilesystemInterface *filesystem) {
FilesystemInterface *cur = default_filesystem_;
default_filesystem_ = filesystem;
return cur;
}
static DirectoryIterator *IterateDirectory() {
return EnsureDefaultFilesystem()->IterateDirectory();
}
static bool CreateFolder(const Pathname &pathname) {
return EnsureDefaultFilesystem()->CreateFolder(pathname);
}
static FileStream *OpenFile(const Pathname &filename,
const std::string &mode) {
return EnsureDefaultFilesystem()->OpenFile(filename, mode);
}
static bool CreatePrivateFile(const Pathname &filename) {
return EnsureDefaultFilesystem()->CreatePrivateFile(filename);
}
static bool DeleteFile(const Pathname &filename) {
return EnsureDefaultFilesystem()->DeleteFile(filename);
}
static bool DeleteEmptyFolder(const Pathname &folder) {
return EnsureDefaultFilesystem()->DeleteEmptyFolder(folder);
}
static bool DeleteFolderContents(const Pathname &folder) {
return EnsureDefaultFilesystem()->DeleteFolderContents(folder);
}
static bool DeleteFolderAndContents(const Pathname &folder) {
return EnsureDefaultFilesystem()->DeleteFolderAndContents(folder);
}
static bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
return EnsureDefaultFilesystem()->MoveFolder(old_path, new_path);
}
static bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
return EnsureDefaultFilesystem()->MoveFile(old_path, new_path);
}
static bool CopyFolder(const Pathname &old_path, const Pathname &new_path) {
return EnsureDefaultFilesystem()->CopyFolder(old_path, new_path);
}
static bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
return EnsureDefaultFilesystem()->CopyFile(old_path, new_path);
}
static bool IsFolder(const Pathname& pathname) {
return EnsureDefaultFilesystem()->IsFolder(pathname);
}
static bool IsFile(const Pathname &pathname) {
return EnsureDefaultFilesystem()->IsFile(pathname);
}
static bool IsAbsent(const Pathname &pathname) {
return EnsureDefaultFilesystem()->IsAbsent(pathname);
}
static bool IsTemporaryPath(const Pathname& pathname) {
return EnsureDefaultFilesystem()->IsTemporaryPath(pathname);
}
static bool GetTemporaryFolder(Pathname &path, bool create,
const std::string *append) {
return EnsureDefaultFilesystem()->GetTemporaryFolder(path, create, append);
}
static std::string TempFilename(const Pathname &dir,
const std::string &prefix) {
return EnsureDefaultFilesystem()->TempFilename(dir, prefix);
}
static bool GetFileSize(const Pathname& path, size_t* size) {
return EnsureDefaultFilesystem()->GetFileSize(path, size);
}
static bool GetFileTime(const Pathname& path, FileTimeType which,
time_t* time) {
return EnsureDefaultFilesystem()->GetFileTime(path, which, time);
}
static bool GetAppPathname(Pathname* path) {
return EnsureDefaultFilesystem()->GetAppPathname(path);
}
static bool GetAppDataFolder(Pathname* path, bool per_user) {
return EnsureDefaultFilesystem()->GetAppDataFolder(path, per_user);
}
static bool GetAppTempFolder(Pathname* path) {
return EnsureDefaultFilesystem()->GetAppTempFolder(path);
}
static bool CleanAppTempFolder() {
return EnsureDefaultFilesystem()->CleanAppTempFolder();
}
static bool GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
return EnsureDefaultFilesystem()->GetDiskFreeSpace(path, freebytes);
}
// Definition has to be in the .cc file due to returning forward-declared
// Pathname by value.
static Pathname GetCurrentDirectory();
static void SetOrganizationName(const std::string& organization) {
EnsureDefaultFilesystem()->SetOrganizationName(organization);
}
static void GetOrganizationName(std::string* organization) {
EnsureDefaultFilesystem()->GetOrganizationName(organization);
}
static void SetApplicationName(const std::string& application) {
EnsureDefaultFilesystem()->SetApplicationName(application);
}
static void GetApplicationName(std::string* application) {
EnsureDefaultFilesystem()->GetApplicationName(application);
}
private:
static FilesystemInterface* default_filesystem_;
static FilesystemInterface *EnsureDefaultFilesystem();
DISALLOW_IMPLICIT_CONSTRUCTORS(Filesystem);
};
class FilesystemScope{
public:
explicit FilesystemScope(FilesystemInterface *new_fs) {
old_fs_ = Filesystem::swap_default_filesystem(new_fs);
}
~FilesystemScope() {
Filesystem::set_default_filesystem(old_fs_);
}
private:
FilesystemInterface* old_fs_;
DISALLOW_IMPLICIT_CONSTRUCTORS(FilesystemScope);
};
// Generates a unique filename based on the input path. If no path component
// is specified, it uses the temporary directory. If a filename is provided,
// up to 100 variations of form basename-N.extension are tried. When
// create_empty is true, an empty file of this name is created (which
// decreases the chance of a temporary filename collision with another
// process).
bool CreateUniqueFile(Pathname& path, bool create_empty);
} // namespace rtc
#endif // WEBRTC_BASE_FILEUTILS_H_

Просмотреть файл

@ -0,0 +1,253 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_FILEUTILS_MOCK_H_
#define WEBRTC_BASE_FILEUTILS_MOCK_H_
#include <string>
#include <utility>
#include <vector>
#include "webrtc/base/fileutils.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/base/stream.h"
namespace rtc {
class FakeFileStream : public FileStream {
public:
explicit FakeFileStream(const std::string & contents) :
string_stream_(contents)
{}
virtual StreamResult Read(void* buffer, size_t buffer_len,
size_t* read, int* error) {
return string_stream_.Read(buffer, buffer_len, read, error);
}
virtual void Close() {
return string_stream_.Close();
}
virtual bool GetSize(size_t* size) const {
return string_stream_.GetSize(size);
}
private:
StringStream string_stream_;
};
class FakeDirectoryIterator : public DirectoryIterator {
public:
typedef std::pair<std::string, std::string> File;
/*
* files should be sorted by directory
* put '/' at the end of file if you want it to be a directory
*
* Sample list:
* /var/dir/file1
* /var/dir/file2
* /var/dir/subdir1/
* /var/dir/subdir2/
* /var/dir2/file2
* /var/dir3/
*
* you can call Iterate for any path: /var, /var/dir, /var/dir2
* unrelated files will be ignored
*/
explicit FakeDirectoryIterator(const std::vector<File>& all_files) :
all_files_(all_files) {}
virtual bool Iterate(const Pathname& path) {
path_iterator_ = all_files_.begin();
path_ = path.pathname();
// make sure path ends end with '/'
if (path_.rfind(Pathname::DefaultFolderDelimiter()) != path_.size() - 1)
path_ += Pathname::DefaultFolderDelimiter();
return FakeDirectoryIterator::Search(std::string(""));
}
virtual bool Next() {
std::string current_name = Name();
path_iterator_++;
return FakeDirectoryIterator::Search(current_name);
}
bool Search(const std::string& current_name) {
for (; path_iterator_ != all_files_.end(); path_iterator_++) {
if (path_iterator_->first.find(path_) == 0
&& Name().compare(current_name) != 0) {
return true;
}
}
return false;
}
virtual bool IsDirectory() const {
std::string sub_path = path_iterator_->first;
return std::string::npos !=
sub_path.find(Pathname::DefaultFolderDelimiter(), path_.size());
}
virtual std::string Name() const {
std::string sub_path = path_iterator_->first;
// path - top level path (ex. /var/lib)
// sub_path - subpath under top level path (ex. /var/lib/dir/dir/file )
// find shortest non-trivial common path. (ex. /var/lib/dir)
size_t start = path_.size();
size_t end = sub_path.find(Pathname::DefaultFolderDelimiter(), start);
if (end != std::string::npos) {
return sub_path.substr(start, end - start);
} else {
return sub_path.substr(start);
}
}
private:
const std::vector<File> all_files_;
std::string path_;
std::vector<File>::const_iterator path_iterator_;
};
class FakeFileSystem : public FilesystemInterface {
public:
typedef std::pair<std::string, std::string> File;
explicit FakeFileSystem(const std::vector<File>& all_files) :
all_files_(all_files) {}
virtual DirectoryIterator *IterateDirectory() {
return new FakeDirectoryIterator(all_files_);
}
virtual FileStream * OpenFile(
const Pathname &filename,
const std::string &mode) {
std::vector<File>::const_iterator i_files = all_files_.begin();
std::string path = filename.pathname();
for (; i_files != all_files_.end(); i_files++) {
if (i_files->first.compare(path) == 0) {
return new FakeFileStream(i_files->second);
}
}
return NULL;
}
bool CreatePrivateFile(const Pathname &filename) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool DeleteFile(const Pathname &filename) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool DeleteEmptyFolder(const Pathname &folder) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool DeleteFolderContents(const Pathname &folder) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool DeleteFolderAndContents(const Pathname &folder) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool CreateFolder(const Pathname &pathname) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool IsFolder(const Pathname &pathname) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool IsFile(const Pathname &pathname) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool IsAbsent(const Pathname &pathname) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool IsTemporaryPath(const Pathname &pathname) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool GetTemporaryFolder(Pathname &path, bool create,
const std::string *append) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
std::string TempFilename(const Pathname &dir, const std::string &prefix) {
EXPECT_TRUE(false) << "Unsupported operation";
return std::string();
}
bool GetFileSize(const Pathname &path, size_t *size) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool GetFileTime(const Pathname &path, FileTimeType which,
time_t* time) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool GetAppPathname(Pathname *path) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool GetAppDataFolder(Pathname *path, bool per_user) {
EXPECT_TRUE(per_user) << "Unsupported operation";
#if defined(WEBRTC_WIN)
path->SetPathname("c:\\Users\\test_user", "");
#else
path->SetPathname("/home/user/test_user", "");
#endif
return true;
}
bool GetAppTempFolder(Pathname *path) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
bool GetDiskFreeSpace(const Pathname &path, int64 *freebytes) {
EXPECT_TRUE(false) << "Unsupported operation";
return false;
}
Pathname GetCurrentDirectory() {
return Pathname();
}
private:
const std::vector<File> all_files_;
};
} // namespace rtc
#endif // WEBRTC_BASE_FILEUTILS_MOCK_H_

Просмотреть файл

@ -0,0 +1,131 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/fileutils.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/base/stream.h"
namespace rtc {
// Make sure we can get a temp folder for the later tests.
TEST(FilesystemTest, GetTemporaryFolder) {
Pathname path;
EXPECT_TRUE(Filesystem::GetTemporaryFolder(path, true, NULL));
}
// Test creating a temp file, reading it back in, and deleting it.
TEST(FilesystemTest, TestOpenFile) {
Pathname path;
EXPECT_TRUE(Filesystem::GetTemporaryFolder(path, true, NULL));
path.SetPathname(Filesystem::TempFilename(path, "ut"));
FileStream* fs;
char buf[256];
size_t bytes;
fs = Filesystem::OpenFile(path, "wb");
ASSERT_TRUE(fs != NULL);
EXPECT_EQ(SR_SUCCESS, fs->Write("test", 4, &bytes, NULL));
EXPECT_EQ(4U, bytes);
delete fs;
EXPECT_TRUE(Filesystem::IsFile(path));
fs = Filesystem::OpenFile(path, "rb");
ASSERT_TRUE(fs != NULL);
EXPECT_EQ(SR_SUCCESS, fs->Read(buf, sizeof(buf), &bytes, NULL));
EXPECT_EQ(4U, bytes);
delete fs;
EXPECT_TRUE(Filesystem::DeleteFile(path));
EXPECT_FALSE(Filesystem::IsFile(path));
}
// Test opening a non-existent file.
TEST(FilesystemTest, TestOpenBadFile) {
Pathname path;
EXPECT_TRUE(Filesystem::GetTemporaryFolder(path, true, NULL));
path.SetFilename("not an actual file");
EXPECT_FALSE(Filesystem::IsFile(path));
FileStream* fs = Filesystem::OpenFile(path, "rb");
EXPECT_FALSE(fs != NULL);
}
// Test that CreatePrivateFile fails for existing files and succeeds for
// non-existent ones.
TEST(FilesystemTest, TestCreatePrivateFile) {
Pathname path;
EXPECT_TRUE(Filesystem::GetTemporaryFolder(path, true, NULL));
path.SetFilename("private_file_test");
// First call should succeed because the file doesn't exist yet.
EXPECT_TRUE(Filesystem::CreatePrivateFile(path));
// Next call should fail, because now it exists.
EXPECT_FALSE(Filesystem::CreatePrivateFile(path));
// Verify that we have permission to open the file for reading and writing.
scoped_ptr<FileStream> fs(Filesystem::OpenFile(path, "wb"));
EXPECT_TRUE(fs.get() != NULL);
// Have to close the file on Windows before it will let us delete it.
fs.reset();
// Verify that we have permission to delete the file.
EXPECT_TRUE(Filesystem::DeleteFile(path));
}
// Test checking for free disk space.
TEST(FilesystemTest, TestGetDiskFreeSpace) {
// Note that we should avoid picking any file/folder which could be located
// at the remotely mounted drive/device.
Pathname path;
ASSERT_TRUE(Filesystem::GetAppDataFolder(&path, true));
int64 free1 = 0;
EXPECT_TRUE(Filesystem::IsFolder(path));
EXPECT_FALSE(Filesystem::IsFile(path));
EXPECT_TRUE(Filesystem::GetDiskFreeSpace(path, &free1));
EXPECT_GT(free1, 0);
int64 free2 = 0;
path.AppendFolder("this_folder_doesnt_exist");
EXPECT_FALSE(Filesystem::IsFolder(path));
EXPECT_TRUE(Filesystem::IsAbsent(path));
EXPECT_TRUE(Filesystem::GetDiskFreeSpace(path, &free2));
// These should be the same disk, and disk free space should not have changed
// by more than 1% between the two calls.
EXPECT_LT(static_cast<int64>(free1 * .9), free2);
EXPECT_LT(free2, static_cast<int64>(free1 * 1.1));
int64 free3 = 0;
path.clear();
EXPECT_TRUE(path.empty());
EXPECT_TRUE(Filesystem::GetDiskFreeSpace(path, &free3));
// Current working directory may not be where exe is.
// EXPECT_LT(static_cast<int64>(free1 * .9), free3);
// EXPECT_LT(free3, static_cast<int64>(free1 * 1.1));
EXPECT_GT(free3, 0);
}
// Tests that GetCurrentDirectory() returns something.
TEST(FilesystemTest, TestGetCurrentDirectory) {
EXPECT_FALSE(Filesystem::GetCurrentDirectory().empty());
}
// Tests that GetAppPathname returns something.
TEST(FilesystemTest, TestGetAppPathname) {
Pathname path;
EXPECT_TRUE(Filesystem::GetAppPathname(&path));
EXPECT_FALSE(path.empty());
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,239 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/firewallsocketserver.h"
#include <assert.h>
#include <algorithm>
#include "webrtc/base/asyncsocket.h"
#include "webrtc/base/logging.h"
namespace rtc {
class FirewallSocket : public AsyncSocketAdapter {
public:
FirewallSocket(FirewallSocketServer* server, AsyncSocket* socket, int type)
: AsyncSocketAdapter(socket), server_(server), type_(type) {
}
virtual int Connect(const SocketAddress& addr) {
if (type_ == SOCK_STREAM) {
if (!server_->Check(FP_TCP, GetLocalAddress(), addr)) {
LOG(LS_VERBOSE) << "FirewallSocket outbound TCP connection from "
<< GetLocalAddress().ToSensitiveString() << " to "
<< addr.ToSensitiveString() << " denied";
// TODO: Handle this asynchronously.
SetError(EHOSTUNREACH);
return SOCKET_ERROR;
}
}
return AsyncSocketAdapter::Connect(addr);
}
virtual int Send(const void* pv, size_t cb) {
return SendTo(pv, cb, GetRemoteAddress());
}
virtual int SendTo(const void* pv, size_t cb, const SocketAddress& addr) {
if (type_ == SOCK_DGRAM) {
if (!server_->Check(FP_UDP, GetLocalAddress(), addr)) {
LOG(LS_VERBOSE) << "FirewallSocket outbound UDP packet from "
<< GetLocalAddress().ToSensitiveString() << " to "
<< addr.ToSensitiveString() << " dropped";
return static_cast<int>(cb);
}
}
return AsyncSocketAdapter::SendTo(pv, cb, addr);
}
virtual int Recv(void* pv, size_t cb) {
SocketAddress addr;
return RecvFrom(pv, cb, &addr);
}
virtual int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) {
if (type_ == SOCK_DGRAM) {
while (true) {
int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
if (res <= 0)
return res;
if (server_->Check(FP_UDP, *paddr, GetLocalAddress()))
return res;
LOG(LS_VERBOSE) << "FirewallSocket inbound UDP packet from "
<< paddr->ToSensitiveString() << " to "
<< GetLocalAddress().ToSensitiveString() << " dropped";
}
}
return AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
}
virtual int Listen(int backlog) {
if (!server_->tcp_listen_enabled()) {
LOG(LS_VERBOSE) << "FirewallSocket listen attempt denied";
return -1;
}
return AsyncSocketAdapter::Listen(backlog);
}
virtual AsyncSocket* Accept(SocketAddress* paddr) {
SocketAddress addr;
while (AsyncSocket* sock = AsyncSocketAdapter::Accept(&addr)) {
if (server_->Check(FP_TCP, addr, GetLocalAddress())) {
if (paddr)
*paddr = addr;
return sock;
}
sock->Close();
delete sock;
LOG(LS_VERBOSE) << "FirewallSocket inbound TCP connection from "
<< addr.ToSensitiveString() << " to "
<< GetLocalAddress().ToSensitiveString() << " denied";
}
return 0;
}
private:
FirewallSocketServer* server_;
int type_;
};
FirewallSocketServer::FirewallSocketServer(SocketServer* server,
FirewallManager* manager,
bool should_delete_server)
: server_(server), manager_(manager),
should_delete_server_(should_delete_server),
udp_sockets_enabled_(true), tcp_sockets_enabled_(true),
tcp_listen_enabled_(true) {
if (manager_)
manager_->AddServer(this);
}
FirewallSocketServer::~FirewallSocketServer() {
if (manager_)
manager_->RemoveServer(this);
if (server_ && should_delete_server_) {
delete server_;
server_ = NULL;
}
}
void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p,
FirewallDirection d,
const SocketAddress& addr) {
SocketAddress src, dst;
if (d == FD_IN) {
dst = addr;
} else {
src = addr;
}
AddRule(allow, p, src, dst);
}
void FirewallSocketServer::AddRule(bool allow, FirewallProtocol p,
const SocketAddress& src,
const SocketAddress& dst) {
Rule r;
r.allow = allow;
r.p = p;
r.src = src;
r.dst = dst;
CritScope scope(&crit_);
rules_.push_back(r);
}
void FirewallSocketServer::ClearRules() {
CritScope scope(&crit_);
rules_.clear();
}
bool FirewallSocketServer::Check(FirewallProtocol p,
const SocketAddress& src,
const SocketAddress& dst) {
CritScope scope(&crit_);
for (size_t i = 0; i < rules_.size(); ++i) {
const Rule& r = rules_[i];
if ((r.p != p) && (r.p != FP_ANY))
continue;
if ((r.src.ipaddr() != src.ipaddr()) && !r.src.IsNil())
continue;
if ((r.src.port() != src.port()) && (r.src.port() != 0))
continue;
if ((r.dst.ipaddr() != dst.ipaddr()) && !r.dst.IsNil())
continue;
if ((r.dst.port() != dst.port()) && (r.dst.port() != 0))
continue;
return r.allow;
}
return true;
}
Socket* FirewallSocketServer::CreateSocket(int type) {
return CreateSocket(AF_INET, type);
}
Socket* FirewallSocketServer::CreateSocket(int family, int type) {
return WrapSocket(server_->CreateAsyncSocket(family, type), type);
}
AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int type) {
return CreateAsyncSocket(AF_INET, type);
}
AsyncSocket* FirewallSocketServer::CreateAsyncSocket(int family, int type) {
return WrapSocket(server_->CreateAsyncSocket(family, type), type);
}
AsyncSocket* FirewallSocketServer::WrapSocket(AsyncSocket* sock, int type) {
if (!sock ||
(type == SOCK_STREAM && !tcp_sockets_enabled_) ||
(type == SOCK_DGRAM && !udp_sockets_enabled_)) {
LOG(LS_VERBOSE) << "FirewallSocketServer socket creation denied";
delete sock;
return NULL;
}
return new FirewallSocket(this, sock, type);
}
FirewallManager::FirewallManager() {
}
FirewallManager::~FirewallManager() {
assert(servers_.empty());
}
void FirewallManager::AddServer(FirewallSocketServer* server) {
CritScope scope(&crit_);
servers_.push_back(server);
}
void FirewallManager::RemoveServer(FirewallSocketServer* server) {
CritScope scope(&crit_);
servers_.erase(std::remove(servers_.begin(), servers_.end(), server),
servers_.end());
}
void FirewallManager::AddRule(bool allow, FirewallProtocol p,
FirewallDirection d, const SocketAddress& addr) {
CritScope scope(&crit_);
for (std::vector<FirewallSocketServer*>::const_iterator it =
servers_.begin(); it != servers_.end(); ++it) {
(*it)->AddRule(allow, p, d, addr);
}
}
void FirewallManager::ClearRules() {
CritScope scope(&crit_);
for (std::vector<FirewallSocketServer*>::const_iterator it =
servers_.begin(); it != servers_.end(); ++it) {
(*it)->ClearRules();
}
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,120 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_FIREWALLSOCKETSERVER_H_
#define WEBRTC_BASE_FIREWALLSOCKETSERVER_H_
#include <vector>
#include "webrtc/base/socketserver.h"
#include "webrtc/base/criticalsection.h"
namespace rtc {
class FirewallManager;
// This SocketServer shim simulates a rule-based firewall server.
enum FirewallProtocol { FP_UDP, FP_TCP, FP_ANY };
enum FirewallDirection { FD_IN, FD_OUT, FD_ANY };
class FirewallSocketServer : public SocketServer {
public:
FirewallSocketServer(SocketServer * server,
FirewallManager * manager = NULL,
bool should_delete_server = false);
virtual ~FirewallSocketServer();
SocketServer* socketserver() const { return server_; }
void set_socketserver(SocketServer* server) {
if (server_ && should_delete_server_) {
delete server_;
server_ = NULL;
should_delete_server_ = false;
}
server_ = server;
}
// Settings to control whether CreateSocket or Socket::Listen succeed.
void set_udp_sockets_enabled(bool enabled) { udp_sockets_enabled_ = enabled; }
void set_tcp_sockets_enabled(bool enabled) { tcp_sockets_enabled_ = enabled; }
bool tcp_listen_enabled() const { return tcp_listen_enabled_; }
void set_tcp_listen_enabled(bool enabled) { tcp_listen_enabled_ = enabled; }
// Rules govern the behavior of Connect/Accept/Send/Recv attempts.
void AddRule(bool allow, FirewallProtocol p = FP_ANY,
FirewallDirection d = FD_ANY,
const SocketAddress& addr = SocketAddress());
void AddRule(bool allow, FirewallProtocol p,
const SocketAddress& src, const SocketAddress& dst);
void ClearRules();
bool Check(FirewallProtocol p,
const SocketAddress& src, const SocketAddress& dst);
virtual Socket* CreateSocket(int type);
virtual Socket* CreateSocket(int family, int type);
virtual AsyncSocket* CreateAsyncSocket(int type);
virtual AsyncSocket* CreateAsyncSocket(int family, int type);
virtual void SetMessageQueue(MessageQueue* queue) {
server_->SetMessageQueue(queue);
}
virtual bool Wait(int cms, bool process_io) {
return server_->Wait(cms, process_io);
}
virtual void WakeUp() {
return server_->WakeUp();
}
Socket * WrapSocket(Socket * sock, int type);
AsyncSocket * WrapSocket(AsyncSocket * sock, int type);
private:
SocketServer * server_;
FirewallManager * manager_;
CriticalSection crit_;
struct Rule {
bool allow;
FirewallProtocol p;
FirewallDirection d;
SocketAddress src;
SocketAddress dst;
};
std::vector<Rule> rules_;
bool should_delete_server_;
bool udp_sockets_enabled_;
bool tcp_sockets_enabled_;
bool tcp_listen_enabled_;
};
// FirewallManager allows you to manage firewalls in multiple threads together
class FirewallManager {
public:
FirewallManager();
~FirewallManager();
void AddServer(FirewallSocketServer * server);
void RemoveServer(FirewallSocketServer * server);
void AddRule(bool allow, FirewallProtocol p = FP_ANY,
FirewallDirection d = FD_ANY,
const SocketAddress& addr = SocketAddress());
void ClearRules();
private:
CriticalSection crit_;
std::vector<FirewallSocketServer *> servers_;
};
} // namespace rtc
#endif // WEBRTC_BASE_FIREWALLSOCKETSERVER_H_

Просмотреть файл

@ -0,0 +1,296 @@
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(WEBRTC_WIN)
#include "webrtc/base/win32.h"
#include <shellapi.h>
#endif
#include "webrtc/base/flags.h"
namespace rtc {
// -----------------------------------------------------------------------------
// Implementation of Flag
Flag::Flag(const char* file, const char* name, const char* comment,
Type type, void* variable, FlagValue default__)
: file_(file),
name_(name),
comment_(comment),
type_(type),
variable_(reinterpret_cast<FlagValue*>(variable)),
default_(default__) {
FlagList::Register(this);
}
void Flag::SetToDefault() {
// Note that we cannot simply do '*variable_ = default_;' since
// flag variables are not really of type FlagValue and thus may
// be smaller! The FlagValue union is simply 'overlayed' on top
// of a flag variable for convenient access. Since union members
// are guarantee to be aligned at the beginning, this works.
switch (type_) {
case Flag::BOOL:
variable_->b = default_.b;
return;
case Flag::INT:
variable_->i = default_.i;
return;
case Flag::FLOAT:
variable_->f = default_.f;
return;
case Flag::STRING:
variable_->s = default_.s;
return;
}
FATAL() << "unreachable code";
}
static const char* Type2String(Flag::Type type) {
switch (type) {
case Flag::BOOL: return "bool";
case Flag::INT: return "int";
case Flag::FLOAT: return "float";
case Flag::STRING: return "string";
}
FATAL() << "unreachable code";
}
static void PrintFlagValue(Flag::Type type, FlagValue* p) {
switch (type) {
case Flag::BOOL:
printf("%s", (p->b ? "true" : "false"));
return;
case Flag::INT:
printf("%d", p->i);
return;
case Flag::FLOAT:
printf("%f", p->f);
return;
case Flag::STRING:
printf("%s", p->s);
return;
}
FATAL() << "unreachable code";
}
void Flag::Print(bool print_current_value) {
printf(" --%s (%s) type: %s default: ", name_, comment_,
Type2String(type_));
PrintFlagValue(type_, &default_);
if (print_current_value) {
printf(" current value: ");
PrintFlagValue(type_, variable_);
}
printf("\n");
}
// -----------------------------------------------------------------------------
// Implementation of FlagList
Flag* FlagList::list_ = NULL;
FlagList::FlagList() {
list_ = NULL;
}
void FlagList::Print(const char* file, bool print_current_value) {
// Since flag registration is likely by file (= C++ file),
// we don't need to sort by file and still get grouped output.
const char* current = NULL;
for (Flag* f = list_; f != NULL; f = f->next()) {
if (file == NULL || file == f->file()) {
if (current != f->file()) {
printf("Flags from %s:\n", f->file());
current = f->file();
}
f->Print(print_current_value);
}
}
}
Flag* FlagList::Lookup(const char* name) {
Flag* f = list_;
while (f != NULL && strcmp(name, f->name()) != 0)
f = f->next();
return f;
}
void FlagList::SplitArgument(const char* arg,
char* buffer, int buffer_size,
const char** name, const char** value,
bool* is_bool) {
*name = NULL;
*value = NULL;
*is_bool = false;
if (*arg == '-') {
// find the begin of the flag name
arg++; // remove 1st '-'
if (*arg == '-')
arg++; // remove 2nd '-'
if (arg[0] == 'n' && arg[1] == 'o') {
arg += 2; // remove "no"
*is_bool = true;
}
*name = arg;
// find the end of the flag name
while (*arg != '\0' && *arg != '=')
arg++;
// get the value if any
if (*arg == '=') {
// make a copy so we can NUL-terminate flag name
int n = static_cast<int>(arg - *name);
CHECK_LT(n, buffer_size);
memcpy(buffer, *name, n * sizeof(char));
buffer[n] = '\0';
*name = buffer;
// get the value
*value = arg + 1;
}
}
}
int FlagList::SetFlagsFromCommandLine(int* argc, const char** argv,
bool remove_flags) {
// parse arguments
for (int i = 1; i < *argc; /* see below */) {
int j = i; // j > 0
const char* arg = argv[i++];
// split arg into flag components
char buffer[1024];
const char* name;
const char* value;
bool is_bool;
SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
if (name != NULL) {
// lookup the flag
Flag* flag = Lookup(name);
if (flag == NULL) {
fprintf(stderr, "Error: unrecognized flag %s\n", arg);
return j;
}
// if we still need a flag value, use the next argument if available
if (flag->type() != Flag::BOOL && value == NULL) {
if (i < *argc) {
value = argv[i++];
} else {
fprintf(stderr, "Error: missing value for flag %s of type %s\n",
arg, Type2String(flag->type()));
return j;
}
}
// set the flag
char empty[] = { '\0' };
char* endp = empty;
switch (flag->type()) {
case Flag::BOOL:
*flag->bool_variable() = !is_bool;
break;
case Flag::INT:
*flag->int_variable() = strtol(value, &endp, 10);
break;
case Flag::FLOAT:
*flag->float_variable() = strtod(value, &endp);
break;
case Flag::STRING:
*flag->string_variable() = value;
break;
}
// handle errors
if ((flag->type() == Flag::BOOL && value != NULL) ||
(flag->type() != Flag::BOOL && is_bool) ||
*endp != '\0') {
fprintf(stderr, "Error: illegal value for flag %s of type %s\n",
arg, Type2String(flag->type()));
return j;
}
// remove the flag & value from the command
if (remove_flags)
while (j < i)
argv[j++] = NULL;
}
}
// shrink the argument list
if (remove_flags) {
int j = 1;
for (int i = 1; i < *argc; i++) {
if (argv[i] != NULL)
argv[j++] = argv[i];
}
*argc = j;
}
// parsed all flags successfully
return 0;
}
void FlagList::Register(Flag* flag) {
assert(flag != NULL && strlen(flag->name()) > 0);
CHECK(!Lookup(flag->name())) << "flag " << flag->name() << " declared twice";
flag->next_ = list_;
list_ = flag;
}
#if defined(WEBRTC_WIN)
WindowsCommandLineArguments::WindowsCommandLineArguments() {
// start by getting the command line.
LPTSTR command_line = ::GetCommandLine();
// now, convert it to a list of wide char strings.
LPWSTR *wide_argv = ::CommandLineToArgvW(command_line, &argc_);
// now allocate an array big enough to hold that many string pointers.
argv_ = new char*[argc_];
// iterate over the returned wide strings;
for(int i = 0; i < argc_; ++i) {
std::string s = rtc::ToUtf8(wide_argv[i], wcslen(wide_argv[i]));
char *buffer = new char[s.length() + 1];
rtc::strcpyn(buffer, s.length() + 1, s.c_str());
// make sure the argv array has the right string at this point.
argv_[i] = buffer;
}
LocalFree(wide_argv);
}
WindowsCommandLineArguments::~WindowsCommandLineArguments() {
// need to free each string in the array, and then the array.
for(int i = 0; i < argc_; i++) {
delete[] argv_[i];
}
delete[] argv_;
}
#endif // WEBRTC_WIN
} // namespace rtc

Просмотреть файл

@ -0,0 +1,270 @@
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Originally comes from shared/commandlineflags/flags.h
// Flags are defined and declared using DEFINE_xxx and DECLARE_xxx macros,
// where xxx is the flag type. Flags are referred to via FLAG_yyy,
// where yyy is the flag name. For intialization and iteration of flags,
// see the FlagList class. For full programmatic access to any
// flag, see the Flag class.
//
// The implementation only relies and basic C++ functionality
// and needs no special library or STL support.
#ifndef WEBRTC_BASE_FLAGS_H__
#define WEBRTC_BASE_FLAGS_H__
#include <assert.h>
#include "webrtc/base/checks.h"
#include "webrtc/base/common.h"
namespace rtc {
// Internal use only.
union FlagValue {
// Note: Because in C++ non-bool values are silently converted into
// bool values ('bool b = "false";' results in b == true!), we pass
// and int argument to New_BOOL as this appears to be safer - sigh.
// In particular, it prevents the (not uncommon!) bug where a bool
// flag is defined via: DEFINE_bool(flag, "false", "some comment");.
static FlagValue New_BOOL(int b) {
FlagValue v;
v.b = (b != 0);
return v;
}
static FlagValue New_INT(int i) {
FlagValue v;
v.i = i;
return v;
}
static FlagValue New_FLOAT(float f) {
FlagValue v;
v.f = f;
return v;
}
static FlagValue New_STRING(const char* s) {
FlagValue v;
v.s = s;
return v;
}
bool b;
int i;
double f;
const char* s;
};
// Each flag can be accessed programmatically via a Flag object.
class Flag {
public:
enum Type { BOOL, INT, FLOAT, STRING };
// Internal use only.
Flag(const char* file, const char* name, const char* comment,
Type type, void* variable, FlagValue default_);
// General flag information
const char* file() const { return file_; }
const char* name() const { return name_; }
const char* comment() const { return comment_; }
// Flag type
Type type() const { return type_; }
// Flag variables
bool* bool_variable() const {
assert(type_ == BOOL);
return &variable_->b;
}
int* int_variable() const {
assert(type_ == INT);
return &variable_->i;
}
double* float_variable() const {
assert(type_ == FLOAT);
return &variable_->f;
}
const char** string_variable() const {
assert(type_ == STRING);
return &variable_->s;
}
// Default values
bool bool_default() const {
assert(type_ == BOOL);
return default_.b;
}
int int_default() const {
assert(type_ == INT);
return default_.i;
}
double float_default() const {
assert(type_ == FLOAT);
return default_.f;
}
const char* string_default() const {
assert(type_ == STRING);
return default_.s;
}
// Resets a flag to its default value
void SetToDefault();
// Iteration support
Flag* next() const { return next_; }
// Prints flag information. The current flag value is only printed
// if print_current_value is set.
void Print(bool print_current_value);
private:
const char* file_;
const char* name_;
const char* comment_;
Type type_;
FlagValue* variable_;
FlagValue default_;
Flag* next_;
friend class FlagList; // accesses next_
};
// Internal use only.
#define DEFINE_FLAG(type, c_type, name, default, comment) \
/* define and initialize the flag */ \
c_type FLAG_##name = (default); \
/* register the flag */ \
static rtc::Flag Flag_##name(__FILE__, #name, (comment), \
rtc::Flag::type, &FLAG_##name, \
rtc::FlagValue::New_##type(default))
// Internal use only.
#define DECLARE_FLAG(c_type, name) \
/* declare the external flag */ \
extern c_type FLAG_##name
// Use the following macros to define a new flag:
#define DEFINE_bool(name, default, comment) \
DEFINE_FLAG(BOOL, bool, name, default, comment)
#define DEFINE_int(name, default, comment) \
DEFINE_FLAG(INT, int, name, default, comment)
#define DEFINE_float(name, default, comment) \
DEFINE_FLAG(FLOAT, double, name, default, comment)
#define DEFINE_string(name, default, comment) \
DEFINE_FLAG(STRING, const char*, name, default, comment)
// Use the following macros to declare a flag defined elsewhere:
#define DECLARE_bool(name) DECLARE_FLAG(bool, name)
#define DECLARE_int(name) DECLARE_FLAG(int, name)
#define DECLARE_float(name) DECLARE_FLAG(double, name)
#define DECLARE_string(name) DECLARE_FLAG(const char*, name)
// The global list of all flags.
class FlagList {
public:
FlagList();
// The NULL-terminated list of all flags. Traverse with Flag::next().
static Flag* list() { return list_; }
// If file != NULL, prints information for all flags defined in file;
// otherwise prints information for all flags in all files. The current
// flag value is only printed if print_current_value is set.
static void Print(const char* file, bool print_current_value);
// Lookup a flag by name. Returns the matching flag or NULL.
static Flag* Lookup(const char* name);
// Helper function to parse flags: Takes an argument arg and splits it into
// a flag name and flag value (or NULL if they are missing). is_bool is set
// if the arg started with "-no" or "--no". The buffer may be used to NUL-
// terminate the name, it must be large enough to hold any possible name.
static void SplitArgument(const char* arg,
char* buffer, int buffer_size,
const char** name, const char** value,
bool* is_bool);
// Set the flag values by parsing the command line. If remove_flags
// is set, the flags and associated values are removed from (argc,
// argv). Returns 0 if no error occurred. Otherwise, returns the
// argv index > 0 for the argument where an error occurred. In that
// case, (argc, argv) will remain unchanged indepdendent of the
// remove_flags value, and no assumptions about flag settings should
// be made.
//
// The following syntax for flags is accepted (both '-' and '--' are ok):
//
// --flag (bool flags only)
// --noflag (bool flags only)
// --flag=value (non-bool flags only, no spaces around '=')
// --flag value (non-bool flags only)
static int SetFlagsFromCommandLine(int* argc,
const char** argv,
bool remove_flags);
static inline int SetFlagsFromCommandLine(int* argc,
char** argv,
bool remove_flags) {
return SetFlagsFromCommandLine(argc, const_cast<const char**>(argv),
remove_flags);
}
// Registers a new flag. Called during program initialization. Not
// thread-safe.
static void Register(Flag* flag);
private:
static Flag* list_;
};
#if defined(WEBRTC_WIN)
// A helper class to translate Windows command line arguments into UTF8,
// which then allows us to just pass them to the flags system.
// This encapsulates all the work of getting the command line and translating
// it to an array of 8-bit strings; all you have to do is create one of these,
// and then call argc() and argv().
class WindowsCommandLineArguments {
public:
WindowsCommandLineArguments();
~WindowsCommandLineArguments();
int argc() { return argc_; }
char **argv() { return argv_; }
private:
int argc_;
char **argv_;
private:
DISALLOW_EVIL_CONSTRUCTORS(WindowsCommandLineArguments);
};
#endif // WEBRTC_WIN
} // namespace rtc
#endif // SHARED_COMMANDLINEFLAGS_FLAGS_H__

Просмотреть файл

@ -0,0 +1,88 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_GUNIT_H_
#define WEBRTC_BASE_GUNIT_H_
#include "webrtc/base/logging.h"
#include "webrtc/base/thread.h"
#if defined(WEBRTC_ANDROID) || defined(GTEST_RELATIVE_PATH)
#include "testing/gtest/include/gtest/gtest.h"
#else
#include "testing/base/public/gunit.h"
#endif
// Wait until "ex" is true, or "timeout" expires.
#define WAIT(ex, timeout) \
for (uint32 start = rtc::Time(); \
!(ex) && rtc::Time() < start + timeout;) \
rtc::Thread::Current()->ProcessMessages(1);
// This returns the result of the test in res, so that we don't re-evaluate
// the expression in the XXXX_WAIT macros below, since that causes problems
// when the expression is only true the first time you check it.
#define WAIT_(ex, timeout, res) \
do { \
uint32 start = rtc::Time(); \
res = (ex); \
while (!res && rtc::Time() < start + timeout) { \
rtc::Thread::Current()->ProcessMessages(1); \
res = (ex); \
} \
} while (0);
// The typical EXPECT_XXXX and ASSERT_XXXXs, but done until true or a timeout.
#define EXPECT_TRUE_WAIT(ex, timeout) \
do { \
bool res; \
WAIT_(ex, timeout, res); \
if (!res) EXPECT_TRUE(ex); \
} while (0);
#define EXPECT_EQ_WAIT(v1, v2, timeout) \
do { \
bool res; \
WAIT_(v1 == v2, timeout, res); \
if (!res) EXPECT_EQ(v1, v2); \
} while (0);
#define ASSERT_TRUE_WAIT(ex, timeout) \
do { \
bool res; \
WAIT_(ex, timeout, res); \
if (!res) ASSERT_TRUE(ex); \
} while (0);
#define ASSERT_EQ_WAIT(v1, v2, timeout) \
do { \
bool res; \
WAIT_(v1 == v2, timeout, res); \
if (!res) ASSERT_EQ(v1, v2); \
} while (0);
// Version with a "soft" timeout and a margin. This logs if the timeout is
// exceeded, but it only fails if the expression still isn't true after the
// margin time passes.
#define EXPECT_TRUE_WAIT_MARGIN(ex, timeout, margin) \
do { \
bool res; \
WAIT_(ex, timeout, res); \
if (res) { \
break; \
} \
LOG(LS_WARNING) << "Expression " << #ex << " still not true after " << \
timeout << "ms; waiting an additional " << margin << "ms"; \
WAIT_(ex, margin, res); \
if (!res) { \
EXPECT_TRUE(ex); \
} \
} while (0);
#endif // WEBRTC_BASE_GUNIT_H_

Просмотреть файл

@ -0,0 +1,24 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_GUNIT_PROD_H_
#define WEBRTC_BASE_GUNIT_PROD_H_
#if defined(WEBRTC_ANDROID)
// Android doesn't use gtest at all, so anything that relies on gtest should
// check this define first.
#define NO_GTEST
#elif defined (GTEST_RELATIVE_PATH)
#include "gtest/gtest_prod.h"
#else
#include "testing/base/gunit_prod.h"
#endif
#endif // WEBRTC_BASE_GUNIT_PROD_H_

Просмотреть файл

@ -0,0 +1,277 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/helpers.h"
#include <limits>
#if defined(FEATURE_ENABLE_SSL)
#include "webrtc/base/sslconfig.h"
#if defined(SSL_USE_OPENSSL)
#include <openssl/rand.h>
#elif defined(SSL_USE_NSS_RNG)
#include "pk11func.h"
#else
#if defined(WEBRTC_WIN)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ntsecapi.h>
#endif // WEBRTC_WIN
#endif // else
#endif // FEATURE_ENABLED_SSL
#include "webrtc/base/base64.h"
#include "webrtc/base/basictypes.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/timeutils.h"
// Protect against max macro inclusion.
#undef max
namespace rtc {
// Base class for RNG implementations.
class RandomGenerator {
public:
virtual ~RandomGenerator() {}
virtual bool Init(const void* seed, size_t len) = 0;
virtual bool Generate(void* buf, size_t len) = 0;
};
#if defined(SSL_USE_OPENSSL)
// The OpenSSL RNG.
class SecureRandomGenerator : public RandomGenerator {
public:
SecureRandomGenerator() {}
~SecureRandomGenerator() {}
virtual bool Init(const void* seed, size_t len) {
return true;
}
virtual bool Generate(void* buf, size_t len) {
return (RAND_bytes(reinterpret_cast<unsigned char*>(buf), len) > 0);
}
};
#elif defined(SSL_USE_NSS_RNG)
// The NSS RNG.
class SecureRandomGenerator : public RandomGenerator {
public:
SecureRandomGenerator() {}
~SecureRandomGenerator() {}
virtual bool Init(const void* seed, size_t len) {
return true;
}
virtual bool Generate(void* buf, size_t len) {
return (PK11_GenerateRandom(reinterpret_cast<unsigned char*>(buf),
static_cast<int>(len)) == SECSuccess);
}
};
#else
#if defined(WEBRTC_WIN)
class SecureRandomGenerator : public RandomGenerator {
public:
SecureRandomGenerator() : advapi32_(NULL), rtl_gen_random_(NULL) {}
~SecureRandomGenerator() {
FreeLibrary(advapi32_);
}
virtual bool Init(const void* seed, size_t seed_len) {
// We don't do any additional seeding on Win32, we just use the CryptoAPI
// RNG (which is exposed as a hidden function off of ADVAPI32 so that we
// don't need to drag in all of CryptoAPI)
if (rtl_gen_random_) {
return true;
}
advapi32_ = LoadLibrary(L"advapi32.dll");
if (!advapi32_) {
return false;
}
rtl_gen_random_ = reinterpret_cast<RtlGenRandomProc>(
GetProcAddress(advapi32_, "SystemFunction036"));
if (!rtl_gen_random_) {
FreeLibrary(advapi32_);
return false;
}
return true;
}
virtual bool Generate(void* buf, size_t len) {
if (!rtl_gen_random_ && !Init(NULL, 0)) {
return false;
}
return (rtl_gen_random_(buf, static_cast<int>(len)) != FALSE);
}
private:
typedef BOOL (WINAPI *RtlGenRandomProc)(PVOID, ULONG);
HINSTANCE advapi32_;
RtlGenRandomProc rtl_gen_random_;
};
#elif !defined(FEATURE_ENABLE_SSL)
// No SSL implementation -- use rand()
class SecureRandomGenerator : public RandomGenerator {
public:
virtual bool Init(const void* seed, size_t len) {
if (len >= 4) {
srand(*reinterpret_cast<const int*>(seed));
} else {
srand(*reinterpret_cast<const char*>(seed));
}
return true;
}
virtual bool Generate(void* buf, size_t len) {
char* bytes = reinterpret_cast<char*>(buf);
for (size_t i = 0; i < len; ++i) {
bytes[i] = static_cast<char>(rand());
}
return true;
}
};
#else
#error No SSL implementation has been selected!
#endif // WEBRTC_WIN
#endif
// A test random generator, for predictable output.
class TestRandomGenerator : public RandomGenerator {
public:
TestRandomGenerator() : seed_(7) {
}
~TestRandomGenerator() {
}
virtual bool Init(const void* seed, size_t len) {
return true;
}
virtual bool Generate(void* buf, size_t len) {
for (size_t i = 0; i < len; ++i) {
static_cast<uint8*>(buf)[i] = static_cast<uint8>(GetRandom());
}
return true;
}
private:
int GetRandom() {
return ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff;
}
int seed_;
};
// TODO: Use Base64::Base64Table instead.
static const char BASE64[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
namespace {
// This round about way of creating a global RNG is to safe-guard against
// indeterminant static initialization order.
scoped_ptr<RandomGenerator>& GetGlobalRng() {
LIBJINGLE_DEFINE_STATIC_LOCAL(scoped_ptr<RandomGenerator>, global_rng,
(new SecureRandomGenerator()));
return global_rng;
}
RandomGenerator& Rng() {
return *GetGlobalRng();
}
} // namespace
void SetRandomTestMode(bool test) {
if (!test) {
GetGlobalRng().reset(new SecureRandomGenerator());
} else {
GetGlobalRng().reset(new TestRandomGenerator());
}
}
bool InitRandom(int seed) {
return InitRandom(reinterpret_cast<const char*>(&seed), sizeof(seed));
}
bool InitRandom(const char* seed, size_t len) {
if (!Rng().Init(seed, len)) {
LOG(LS_ERROR) << "Failed to init random generator!";
return false;
}
return true;
}
std::string CreateRandomString(size_t len) {
std::string str;
CreateRandomString(len, &str);
return str;
}
bool CreateRandomString(size_t len,
const char* table, int table_size,
std::string* str) {
str->clear();
scoped_ptr<uint8[]> bytes(new uint8[len]);
if (!Rng().Generate(bytes.get(), len)) {
LOG(LS_ERROR) << "Failed to generate random string!";
return false;
}
str->reserve(len);
for (size_t i = 0; i < len; ++i) {
str->push_back(table[bytes[i] % table_size]);
}
return true;
}
bool CreateRandomString(size_t len, std::string* str) {
return CreateRandomString(len, BASE64, 64, str);
}
bool CreateRandomString(size_t len, const std::string& table,
std::string* str) {
return CreateRandomString(len, table.c_str(),
static_cast<int>(table.size()), str);
}
uint32 CreateRandomId() {
uint32 id;
if (!Rng().Generate(&id, sizeof(id))) {
LOG(LS_ERROR) << "Failed to generate random id!";
}
return id;
}
uint64 CreateRandomId64() {
return static_cast<uint64>(CreateRandomId()) << 32 | CreateRandomId();
}
uint32 CreateRandomNonZeroId() {
uint32 id;
do {
id = CreateRandomId();
} while (id == 0);
return id;
}
double CreateRandomDouble() {
return CreateRandomId() / (std::numeric_limits<uint32>::max() +
std::numeric_limits<double>::epsilon());
}
} // namespace rtc

Просмотреть файл

@ -0,0 +1,56 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_HELPERS_H_
#define WEBRTC_BASE_HELPERS_H_
#include <string>
#include "webrtc/base/basictypes.h"
namespace rtc {
// For testing, we can return predictable data.
void SetRandomTestMode(bool test);
// Initializes the RNG, and seeds it with the specified entropy.
bool InitRandom(int seed);
bool InitRandom(const char* seed, size_t len);
// Generates a (cryptographically) random string of the given length.
// We generate base64 values so that they will be printable.
// WARNING: could silently fail. Use the version below instead.
std::string CreateRandomString(size_t length);
// Generates a (cryptographically) random string of the given length.
// We generate base64 values so that they will be printable.
// Return false if the random number generator failed.
bool CreateRandomString(size_t length, std::string* str);
// Generates a (cryptographically) random string of the given length,
// with characters from the given table. Return false if the random
// number generator failed.
bool CreateRandomString(size_t length, const std::string& table,
std::string* str);
// Generates a random id.
uint32 CreateRandomId();
// Generates a 64 bit random id.
uint64 CreateRandomId64();
// Generates a random id > 0.
uint32 CreateRandomNonZeroId();
// Generates a random double between 0.0 (inclusive) and 1.0 (exclusive).
double CreateRandomDouble();
} // namespace rtc
#endif // WEBRTC_BASE_HELPERS_H_

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше