Revert 6107 "Adds a modified copy of talk/base to webrtc/base. I..."
This breaks Chromium FYI builds and prevent roll of webrtc/libjingle to Chrome. http://chromegw.corp.google.com/i/chromium.webrtc.fyi/builders/Win%20Builder/builds/457 > Adds a modified copy of talk/base to webrtc/base. It is the first step in migrating talk/base to webrtc/base. > > BUG=N/A > R=andrew@webrtc.org, wu@webrtc.org > > Review URL: https://webrtc-codereview.appspot.com/12199004 TBR=henrike@webrtc.org Review URL: https://webrtc-codereview.appspot.com/14479004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6116 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
3a5825909d
commit
e9a604accd
@ -180,174 +180,6 @@ name=https://code.google.com/p/webrtc/issues/detail?id=3158 (3)
|
||||
KERNEL32.dll!BaseThreadInitThunk
|
||||
|
||||
# libjingle_unittest, fails on Win DrMemory Full
|
||||
UNINITIALIZED READ
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (4)
|
||||
*!_towlower_l
|
||||
*!towlower
|
||||
*!tolowercase
|
||||
*!rtc::IsDefaultBrowserFirefox
|
||||
*!rtc::GetProxySettingsForUrl
|
||||
*!rtc::AutoDetectProxy::GetProxyForUrl
|
||||
*!rtc::AutoDetectProxy::DoWork
|
||||
*!rtc::SignalThread::Run
|
||||
*!rtc::SignalThread::Worker::Run
|
||||
*!rtc::Thread::PreRun
|
||||
KERNEL32.dll!BaseThreadInitThunk
|
||||
|
||||
UNADDRESSABLE ACCESS
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (12)
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
libjingle_peerconnection_unittes!rtc::CriticalSection::Enter
|
||||
libjingle_peerconnection_unittes!rtc::CritScope::CritScope
|
||||
libjingle_peerconnection_unittes!rtc::LogMessage::~LogMessage
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVideoEngine::Print
|
||||
libjingle_peerconnection_unittes!webrtc::TraceImpl::WriteToFile
|
||||
libjingle_peerconnection_unittes!webrtc::TraceImpl::Process
|
||||
libjingle_peerconnection_unittes!webrtc::TraceImpl::Run
|
||||
libjingle_peerconnection_unittes!webrtc::ThreadWindows::Run
|
||||
libjingle_peerconnection_unittes!webrtc::ThreadWindows::StartThread
|
||||
libjingle_peerconnection_unittes!_callthreadstartex
|
||||
libjingle_peerconnection_unittes!_threadstartex
|
||||
KERNEL32.dll!BaseThreadInitThunk
|
||||
|
||||
UNADDRESSABLE ACCESS
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (14)
|
||||
libjingle_peerconnection_unittes!std::list<>::begin
|
||||
libjingle_peerconnection_unittes!rtc::LogMessage::~LogMessage
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVideoEngine::Construct
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVideoEngine::WebRtcVideoEngine
|
||||
libjingle_peerconnection_unittes!cricket::CompositeMediaEngine<>::CompositeMediaEngine<>
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcMediaEngine::WebRtcMediaEngine
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::Initialize_s
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::OnMessage
|
||||
libjingle_peerconnection_unittes!rtc::Thread::Send
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::Initialize
|
||||
libjingle_peerconnection_unittes!webrtc::CreatePeerConnectionFactory
|
||||
libjingle_peerconnection_unittes!PeerConnectionInterfaceTest::SetUp
|
||||
libjingle_peerconnection_unittes!testing::internal::HandleSehExceptionsInMethodIfSupported<>
|
||||
|
||||
UNADDRESSABLE ACCESS
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (15)
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
libjingle_peerconnection_unittes!rtc::CriticalSection::Enter
|
||||
libjingle_peerconnection_unittes!rtc::CritScope::CritScope
|
||||
libjingle_peerconnection_unittes!rtc::LogMessage::~LogMessage
|
||||
libjingle_peerconnection_unittes!TestInvalidParameterHandler
|
||||
libjingle_peerconnection_unittes!_invalid_parameter
|
||||
...
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVideoEngine::Construct
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVideoEngine::WebRtcVideoEngine
|
||||
libjingle_peerconnection_unittes!cricket::CompositeMediaEngine<>::CompositeMediaEngine<>
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcMediaEngine::WebRtcMediaEngine
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::Initialize_s
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::OnMessage
|
||||
libjingle_peerconnection_unittes!rtc::Thread::Send
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::Initialize
|
||||
libjingle_peerconnection_unittes!webrtc::CreatePeerConnectionFactory
|
||||
libjingle_peerconnection_unittes!PeerConnectionInterfaceTest::SetUp
|
||||
libjingle_peerconnection_unittes!testing::internal::HandleSehExceptionsInMethodIfSupported<>
|
||||
|
||||
UNADDRESSABLE ACCESS
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (16)
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
libjingle_peerconnection_unittes!rtc::CriticalSection::Enter
|
||||
libjingle_peerconnection_unittes!rtc::CritScope::CritScope
|
||||
libjingle_peerconnection_unittes!rtc::LogMessage::~LogMessage
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVoiceEngine::ConstructCodecs
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVoiceEngine::Construct
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVoiceEngine::WebRtcVoiceEngine
|
||||
libjingle_peerconnection_unittes!cricket::CompositeMediaEngine<>::CompositeMediaEngine<>
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcMediaEngine::WebRtcMediaEngine
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::Initialize_s
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::OnMessage
|
||||
libjingle_peerconnection_unittes!rtc::Thread::Send
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::Initialize
|
||||
libjingle_peerconnection_unittes!webrtc::CreatePeerConnectionFactory
|
||||
libjingle_peerconnection_unittes!PeerConnectionInterfaceTest::SetUp
|
||||
libjingle_peerconnection_unittes!testing::internal::HandleSehExceptionsInMethodIfSupported<>
|
||||
|
||||
UNADDRESSABLE ACCESS
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (32)
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
libjingle_peerconnection_unittes!rtc::CriticalSection::Enter
|
||||
libjingle_peerconnection_unittes!rtc::CritScope::CritScope
|
||||
...
|
||||
libjingle_peerconnection_unittes!testing::internal::CountIf<>
|
||||
libjingle_peerconnection_unittes!testing::TestResult::HasFatalFailure
|
||||
libjingle_peerconnection_unittes!testing::Test::HasFatalFailure
|
||||
libjingle_peerconnection_unittes!testing::Test::Run
|
||||
|
||||
UNADDRESSABLE ACCESS
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (34)
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
libjingle_peerconnection_unittes!rtc::CriticalSection::Enter
|
||||
libjingle_peerconnection_unittes!rtc::CritScope::CritScope
|
||||
...
|
||||
libjingle_peerconnection_unittes!TestPureCallHandler
|
||||
libjingle_peerconnection_unittes!_purecall
|
||||
libjingle_peerconnection_unittes!testing::internal::DefaultGlobalTestPartResultReporter::ReportTestPartResult
|
||||
libjingle_peerconnection_unittes!testing::internal::DefaultPerThreadTestPartResultReporter::ReportTestPartResult
|
||||
libjingle_peerconnection_unittes!testing::UnitTest::AddTestPartResult
|
||||
libjingle_peerconnection_unittes!testing::internal::ReportFailureInUnknownLocation
|
||||
libjingle_peerconnection_unittes!testing::internal::HandleSehExceptionsInMethodIfSupported<>
|
||||
|
||||
HANDLE LEAK
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (35)
|
||||
system call NtCreateEvent
|
||||
KERNELBASE.dll!CreateEventExW
|
||||
KERNELBASE.dll!CreateEventW
|
||||
libjingle_peerconnection_unittes!webrtc::EventWindows::EventWindows
|
||||
libjingle_peerconnection_unittes!webrtc::EventWrapper::Create
|
||||
libjingle_peerconnection_unittes!webrtc::ProcessThreadImpl::ProcessThreadImpl
|
||||
libjingle_peerconnection_unittes!webrtc::ProcessThread::CreateProcessThread
|
||||
libjingle_peerconnection_unittes!webrtc::voe::SharedData::SharedData
|
||||
libjingle_peerconnection_unittes!webrtc::VoiceEngineImpl::VoiceEngineImpl
|
||||
libjingle_peerconnection_unittes!webrtc::GetVoiceEngine
|
||||
libjingle_peerconnection_unittes!webrtc::VoiceEngine::Create
|
||||
libjingle_peerconnection_unittes!cricket::VoEWrapper::VoEWrapper
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcVoiceEngine::WebRtcVoiceEngine
|
||||
libjingle_peerconnection_unittes!cricket::CompositeMediaEngine<>::CompositeMediaEngine<>
|
||||
libjingle_peerconnection_unittes!cricket::WebRtcMediaEngine::WebRtcMediaEngine
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::Initialize_s
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::OnMessage
|
||||
libjingle_peerconnection_unittes!rtc::Thread::Send
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionFactory::Initialize
|
||||
libjingle_peerconnection_unittes!webrtc::CreatePeerConnectionFactory
|
||||
libjingle_peerconnection_unittes!PeerConnectionInterfaceTest::SetUp
|
||||
libjingle_peerconnection_unittes!testing::internal::HandleSehExceptionsInMethodIfSupported<>
|
||||
|
||||
UNINITIALIZED READ
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (36)
|
||||
libjingle_peerconnection_unittes!webrtc::WebRtcSessionDescriptionFactory::InternalCreateAnswer
|
||||
libjingle_peerconnection_unittes!webrtc::WebRtcSessionDescriptionFactory::CreateAnswer
|
||||
libjingle_peerconnection_unittes!webrtc::WebRtcSession::CreateAnswer
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnection::CreateAnswer
|
||||
libjingle_peerconnection_unittes!webrtc::ReturnType<>::Invoke<>
|
||||
libjingle_peerconnection_unittes!webrtc::MethodCall2<>::OnMessage
|
||||
libjingle_peerconnection_unittes!rtc::Thread::Send
|
||||
libjingle_peerconnection_unittes!webrtc::MethodCall2<>::Marshal
|
||||
libjingle_peerconnection_unittes!webrtc::PeerConnectionProxy::CreateAnswer
|
||||
libjingle_peerconnection_unittes!PeerConnectionInterfaceTest::DoCreateOfferAnswer
|
||||
libjingle_peerconnection_unittes!PeerConnectionInterfaceTest::DoCreateAnswer
|
||||
libjingle_peerconnection_unittes!PeerConnectionInterfaceTest::CreateAnswerAsLocalDescription
|
||||
libjingle_peerconnection_unittes!PeerConnectionInterfaceTest_ReceiveOfferCreatePrAnswerAndAnswer_Test::TestBody
|
||||
libjingle_peerconnection_unittes!testing::internal::HandleSehExceptionsInMethodIfSupported<>
|
||||
|
||||
UNADDRESSABLE ACCESS
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (37)
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
ntdll.dll!RtlIntegerToUnicodeString
|
||||
libjingle_peerconnection_unittes!rtc::CriticalSection::Enter
|
||||
libjingle_peerconnection_unittes!rtc::CritScope::CritScope
|
||||
libjingle_peerconnection_unittes!rtc::LogMessage::GetLogToStream
|
||||
libjingle_peerconnection_unittes!rtc::LogMessage::ConfigureLogging
|
||||
libjingle_peerconnection_unittes!main
|
||||
|
||||
UNINITIALIZED READ
|
||||
name=https://code.google.com/p/webrtc/issues/detail?id=3158 (4)
|
||||
*!_towlower_l
|
||||
|
@ -9,102 +9,6 @@
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# 1. webrtc stuff
|
||||
{
|
||||
bug_1976_1
|
||||
Memcheck:Unaddressable
|
||||
fun:pthread_mutex_unlock
|
||||
fun:_ZN9rtc15CriticalSection5LeaveEv
|
||||
fun:_ZN9rtc9CritScopeD1Ev
|
||||
...
|
||||
fun:_ZN9rtc6Thread15ProcessMessagesEi
|
||||
fun:_ZN9rtc6Thread3RunEv
|
||||
fun:_ZN9rtc6Thread6PreRunEPv
|
||||
}
|
||||
{
|
||||
bug_1976_2
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
obj:/usr/lib/x86_64-linux-gnu/libnss3.so
|
||||
...
|
||||
fun:NSS_NoDB_Init
|
||||
fun:_ZN9rtc10NSSContext13InitializeSSLEPFbPvE
|
||||
fun:_ZN9rtc13InitializeSSLEPFbPvE
|
||||
fun:_ZN9rtc10RandomTest13SetUpTestCaseEv
|
||||
fun:_ZN7testing8TestCase16RunSetUpTestCaseEv
|
||||
}
|
||||
{
|
||||
bug_2100_3
|
||||
Memcheck:Uninitialized
|
||||
fun:tls1_enc
|
||||
fun:ssl3_get_record
|
||||
fun:ssl3_read_bytes
|
||||
fun:ssl3_read_internal
|
||||
fun:ssl3_read
|
||||
fun:SSL_read
|
||||
fun:_ZN9rtc20OpenSSLStreamAdapter4ReadEPvmPmPi
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2100_4
|
||||
Memcheck:Uninitialized
|
||||
fun:_ZN7testing8internal11CmpHelperEQIjhEENS_15AssertionResultEPKcS4_RKT_RKT0_
|
||||
fun:_ZN7testing8internal8EqHelperILb0EE7CompareIjhEENS_15AssertionResultEPKcS6_RKT_RKT0_
|
||||
fun:_ZN24SSLStreamAdapterTestDTLS8ReadDataEPN9rtc15StreamInterfaceE
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2100_5
|
||||
Memcheck:Uninitialized
|
||||
fun:dtls1_process_record
|
||||
fun:dtls1_get_record
|
||||
fun:dtls1_read_bytes
|
||||
fun:ssl3_read_internal
|
||||
fun:ssl3_read
|
||||
fun:SSL_read
|
||||
fun:_ZN9rtc20OpenSSLStreamAdapter4ReadEPvmPmPi
|
||||
...
|
||||
}
|
||||
{
|
||||
BIO_new_mem_buf_1
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:default_malloc_ex
|
||||
fun:CRYPTO_malloc
|
||||
fun:BUF_MEM_new
|
||||
fun:mem_new
|
||||
fun:BIO_set
|
||||
fun:BIO_new
|
||||
fun:BIO_new_mem_buf
|
||||
fun:_ZN9rtc18OpenSSLCertificate13FromPEMStringERKSs
|
||||
...
|
||||
}
|
||||
{
|
||||
BIO_new_mem_buf_2
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:default_malloc_ex
|
||||
fun:CRYPTO_malloc
|
||||
fun:BUF_MEM_new
|
||||
fun:mem_new
|
||||
fun:BIO_set
|
||||
fun:BIO_new
|
||||
fun:BIO_new_mem_buf
|
||||
fun:_ZN9rtc15OpenSSLIdentity14FromPEMStringsERKSsS2_
|
||||
}
|
||||
{
|
||||
SignalsCloseAfterForcedCloseAll
|
||||
Memcheck:Leak
|
||||
fun:_Znw*
|
||||
fun:_ZN9rtc10HttpServer10Connection12BeginProcessEPNS_15StreamInterfaceE
|
||||
...
|
||||
}
|
||||
{
|
||||
DoNotDeleteTask2
|
||||
Memcheck:Leak
|
||||
fun:_Znw*
|
||||
...
|
||||
fun:_ZN9rtc41unstarted_task_test_DoNotDeleteTask2_Test8TestBodyEv
|
||||
}
|
||||
{
|
||||
bug_716
|
||||
Memcheck:Leak
|
||||
|
@ -9,473 +9,6 @@
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# 1. webrtc stuff
|
||||
{
|
||||
bug_1205_33
|
||||
ThreadSanitizer:Race
|
||||
fun:webrtc::PeerConnectionProxy::~PeerConnectionProxy
|
||||
fun:rtc::RefCountedObject::~RefCountedObject
|
||||
fun:rtc::RefCountedObject::~RefCountedObject
|
||||
fun:rtc::RefCountedObject::Release
|
||||
fun:rtc::scoped_refptr::~scoped_refptr
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_1205_34
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::AtomicOps::Increment
|
||||
fun:rtc::RefCountedObject::AddRef
|
||||
fun:rtc::scoped_refptr::scoped_refptr
|
||||
fun:webrtc::PeerConnectionFactory::CreatePeerConnection
|
||||
fun:webrtc::PeerConnectionFactory::CreatePeerConnection
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_1205_35
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::scoped_refptr::scoped_refptr
|
||||
fun:webrtc::PeerConnectionFactory::CreatePeerConnection
|
||||
fun:webrtc::PeerConnectionFactory::CreatePeerConnection
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_1205_36
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MessageHandler::~MessageHandler
|
||||
fun:FakeAudioCaptureModule::~FakeAudioCaptureModule
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_1205_39
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::Thread::Send
|
||||
fun:FakeAudioCaptureModule::UpdateProcessing
|
||||
fun:FakeAudioCaptureModule::StopRecording
|
||||
fun:webrtc::VoEBaseImpl::StopSend
|
||||
fun:webrtc::VoEBaseImpl::DeleteChannel
|
||||
fun:cricket::WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_1205_41
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::Thread::Send
|
||||
fun:FakeAudioCaptureModule::~FakeAudioCaptureModule
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_2
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:rtc::MemoryStreamBase::Read
|
||||
...
|
||||
fun:cricket::RtpDumpReader::ReadPacket
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_3
|
||||
ThreadSanitizer:Race
|
||||
fun:cricket::RtpSenderReceiver::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:rtc::Thread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2078_4
|
||||
ThreadSanitizer:Race
|
||||
fun:cricket::FileNetworkInterface::SendPacket
|
||||
fun:cricket::RtpSenderReceiver::SendRtpPacket
|
||||
fun:cricket::RtpSenderReceiver::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:rtc::Thread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2078_7
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MemoryStreamBase::~MemoryStreamBase
|
||||
fun:rtc::MemoryStream::~MemoryStream
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_8
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MemoryStreamBase::SetPosition
|
||||
fun:rtc::StreamInterface::Rewind
|
||||
fun:cricket::RtpTestUtility::VerifyTestPacketsFromStream
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_13
|
||||
ThreadSanitizer:Race
|
||||
fun:std::_Vector_base::~_Vector_base
|
||||
fun:std::vector::~vector
|
||||
fun:cricket::RtpDumpPacket::~RtpDumpPacket
|
||||
fun:cricket::RtpSenderReceiver::~RtpSenderReceiver
|
||||
fun:cricket::RtpSenderReceiver::~RtpSenderReceiver
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_14
|
||||
ThreadSanitizer:Race
|
||||
fun:cricket::RtpDumpReader::~RtpDumpReader
|
||||
fun:cricket::RtpDumpLoopReader::~RtpDumpLoopReader
|
||||
fun:cricket::RtpDumpLoopReader::~RtpDumpLoopReader
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
fun:cricket::RtpSenderReceiver::~RtpSenderReceiver
|
||||
fun:cricket::RtpSenderReceiver::~RtpSenderReceiver
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_15
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::FileStream::Close
|
||||
fun:rtc::FileStream::~FileStream
|
||||
fun:rtc::FileStream::~FileStream
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
fun:cricket::RtpSenderReceiver::~RtpSenderReceiver
|
||||
fun:cricket::RtpSenderReceiver::~RtpSenderReceiver
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_16
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::StreamInterface::~StreamInterface
|
||||
fun:rtc::FileStream::~FileStream
|
||||
fun:rtc::FileStream::~FileStream
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
fun:cricket::RtpSenderReceiver::~RtpSenderReceiver
|
||||
fun:cricket::RtpSenderReceiver::~RtpSenderReceiver
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_18
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MemoryStream::~MemoryStream
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_22
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MessageQueue::Quit
|
||||
fun:rtc::Thread::Stop
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_23
|
||||
ThreadSanitizer:Race
|
||||
fun:::FileVideoCapturerTest::VideoCapturerListener::OnFrameCaptured
|
||||
fun:sigslot::_connection2::emit
|
||||
...
|
||||
fun:cricket::FileVideoCapturer::ReadFrame
|
||||
fun:cricket::FileVideoCapturer::FileReadThread::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:rtc::Thread::Run
|
||||
fun:cricket::FileVideoCapturer::FileReadThread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2078_24
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MemoryStreamBase::SetPosition
|
||||
fun:rtc::StreamInterface::Rewind
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2078_25
|
||||
ThreadSanitizer:Race
|
||||
fun:cricket::FileNetworkInterface::SendPacket
|
||||
fun:cricket::MediaChannel::DoSendPacket
|
||||
fun:cricket::MediaChannel::SendPacket
|
||||
fun:cricket::RtpSenderReceiver::SendRtpPacket
|
||||
fun:cricket::RtpSenderReceiver::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:rtc::Thread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2079_1
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::VirtualSocketServer::AddPacketToNetwork
|
||||
fun:rtc::VirtualSocketServer::SendUdp
|
||||
fun:rtc::VirtualSocket::SendUdp
|
||||
fun:rtc::VirtualSocket::SendTo
|
||||
fun:rtc::AsyncUDPSocket::SendTo
|
||||
fun:cricket::StunServer::SendResponse
|
||||
fun:cricket::StunServer::OnBindingRequest
|
||||
fun:cricket::StunServer::OnPacket
|
||||
fun:sigslot::_connection4::emit
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2079_5
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::Thread::Send
|
||||
fun:cricket::Transport::SetRole
|
||||
fun:cricket::BaseSession::GetOrCreateTransportProxy
|
||||
fun:cricket::BaseSession::CreateChannel
|
||||
fun:cricket::FakeSession::CreateChannel
|
||||
fun:cricket::VoiceChannel::Init
|
||||
fun:cricket::ChannelManager::CreateVoiceChannel_w
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2079_6
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::Thread::ReceiveSends
|
||||
fun:rtc::Thread::Send
|
||||
fun:rtc::Thread::Invoke
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2079_8
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::Thread::Invoke
|
||||
fun:cricket::ChannelManager::SetCaptureDevice
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2079_9
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::Thread::Send
|
||||
fun:cricket::Transport::SetIceRole
|
||||
fun:cricket::BaseSession::GetOrCreateTransportProxy
|
||||
fun:cricket::BaseSession::CreateChannel
|
||||
fun:cricket::FakeSession::CreateChannel
|
||||
fun:cricket::VoiceChannel::Init
|
||||
fun:cricket::ChannelManager::CreateVoiceChannel_w
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_1
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MessageQueue::Quit
|
||||
fun:rtc::SignalThread::Destroy
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_2
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MessageQueue::Quit
|
||||
fun:rtc::AsyncHttpRequest::OnComplete
|
||||
fun:sigslot::_connection2::emit
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_3
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::LogMessage::UpdateMinLogSeverity
|
||||
fun:rtc::LogMessage::AddLogToStream
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_8
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:rtc::AsyncUDPSocket::OnReadEvent
|
||||
fun:sigslot::_connection1::emit
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_9
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:rtc::AsyncUDPSocket::OnWriteEvent
|
||||
fun:sigslot::_connection1::emit
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_14
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::IPAddress::IPAddress
|
||||
fun:rtc::SocketAddress::ToSockAddrStorage
|
||||
fun:rtc::PhysicalSocket::SendTo
|
||||
fun:rtc::AsyncUDPSocket::SendTo
|
||||
fun:rtc::NATServer::OnExternalPacket
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_16
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:rtc::IPAddress::operator<
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_18
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::SocketAddress::port
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_19
|
||||
ThreadSanitizer:Race
|
||||
fun:std::vector::_M_insert_aux
|
||||
fun:std::vector::push_back
|
||||
fun:rtc::TestClient::OnPacket
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_20
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::VirtualSocketServer::AddPacketToNetwork
|
||||
fun:rtc::VirtualSocketServer::SendUdp
|
||||
fun:rtc::VirtualSocket::SendUdp
|
||||
fun:rtc::VirtualSocket::SendTo
|
||||
fun:rtc::AsyncUDPSocket::SendTo
|
||||
fun:rtc::TestClient::SendTo
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_21
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::SharedExclusiveTask::waiting_time_in_ms
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_22
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::SharedExclusiveTask::~SharedExclusiveTask
|
||||
fun:rtc::ReadTask::~ReadTask
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_24
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:OwnerThread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2080_25
|
||||
ThreadSanitizer:Race
|
||||
fun:sigslot::has_slots::~has_slots
|
||||
fun:OwnerThread::~OwnerThread
|
||||
fun:OwnerThread::~OwnerThread
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_27
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:std::_Rb_tree::clear
|
||||
fun:std::_Rb_tree::_M_erase_aux
|
||||
fun:std::_Rb_tree::erase
|
||||
fun:std::set::erase
|
||||
fun:sigslot::has_slots::disconnect_all
|
||||
fun:sigslot::has_slots::~has_slots
|
||||
fun:OwnerThread::~OwnerThread
|
||||
fun:OwnerThread::~OwnerThread
|
||||
fun:rtc::scoped_ptr::~scoped_ptr
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_29
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::Thread::Release
|
||||
fun:ThreadTest_Release_Test::TestBody
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_30
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::Thread::Invoke
|
||||
fun:MessageQueueTest::IsLocked
|
||||
fun:DeletedLockChecker::~DeletedLockChecker
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_31
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::MessageHandler::~MessageHandler
|
||||
fun:rtc::Thread::FunctorMessageHandler::~FunctorMessageHandler
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_32
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::ReadTask::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_2080_33
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::SharedExclusiveLockTest_TestSharedShared_Test::TestBody
|
||||
fun:testing::internal::HandleSehExceptionsInMethodIfSupported
|
||||
}
|
||||
{
|
||||
bug_2080_34
|
||||
ThreadSanitizer:Race
|
||||
fun:rtc::WriteTask::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:rtc::Thread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2080_35
|
||||
ThreadSanitizer:UnlockNonLocked
|
||||
fun:pthread_mutex_unlock
|
||||
fun:rtc::CriticalSection::Leave
|
||||
fun:rtc::CritScope::~CritScope
|
||||
...
|
||||
fun:rtc::AsyncFunctorMessageHandler::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:rtc::Thread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2080_36
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:rtc::FunctorMessageHandler::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:rtc::Thread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2931_1
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:rtc::FireAndForgetAsyncClosure::Execute
|
||||
fun:rtc::AsyncInvoker::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:rtc::Thread::Run
|
||||
fun:rtc::Thread::PreRun
|
||||
}
|
||||
{
|
||||
bug_2931_2
|
||||
ThreadSanitizer:Race
|
||||
...
|
||||
fun:rtc::Callback0::HelperImpl::~HelperImpl
|
||||
fun:rtc::RefCountedObject::~RefCountedObject
|
||||
fun:rtc::RefCountedObject::~RefCountedObject
|
||||
fun:rtc::RefCountedObject::Release
|
||||
fun:rtc::scoped_refptr::~scoped_refptr
|
||||
fun:rtc::Callback0::~Callback0
|
||||
fun:rtc::FireAndForgetAsyncClosure::~FireAndForgetAsyncClosure
|
||||
fun:rtc::RefCountedObject::~RefCountedObject
|
||||
fun:rtc::RefCountedObject::~RefCountedObject
|
||||
fun:rtc::RefCountedObject::Release
|
||||
fun:rtc::scoped_refptr::~scoped_refptr
|
||||
fun:rtc::AsyncInvoker::OnMessage
|
||||
fun:rtc::MessageQueue::Dispatch
|
||||
fun:rtc::Thread::ProcessMessages
|
||||
fun:AsyncInvokeTest_WithCallback_Test::TestBody
|
||||
...
|
||||
}
|
||||
{
|
||||
bug_300
|
||||
ThreadSanitizer:Race
|
||||
|
@ -13,9 +13,6 @@ race:webrtc/modules/audio_processing/aec/aec_rdft.c
|
||||
|
||||
# libjingle_p2p_unittest
|
||||
# See https://code.google.com/p/webrtc/issues/detail?id=2079
|
||||
race:webrtc/base/messagequeue.cc
|
||||
race:webrtc/base/testclient.cc
|
||||
race:webrtc/base/virtualsocketserver.cc
|
||||
race:talk/base/messagequeue.cc
|
||||
race:talk/base/testclient.cc
|
||||
race:talk/base/virtualsocketserver.cc
|
||||
@ -23,10 +20,6 @@ race:talk/p2p/base/stunserver_unittest.cc
|
||||
|
||||
# libjingle_unittest
|
||||
# See https://code.google.com/p/webrtc/issues/detail?id=2080
|
||||
race:webrtc/base/logging.cc
|
||||
race:webrtc/base/sharedexclusivelock_unittest.cc
|
||||
race:webrtc/base/signalthread_unittest.cc
|
||||
race:webrtc/base/thread.cc
|
||||
race:talk/base/logging.cc
|
||||
race:talk/base/sharedexclusivelock_unittest.cc
|
||||
race:talk/base/signalthread_unittest.cc
|
||||
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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/asyncfile.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
AsyncFile::AsyncFile() {
|
||||
}
|
||||
|
||||
AsyncFile::~AsyncFile() {
|
||||
}
|
||||
|
||||
} // namespace rtc
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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__
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,233 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,299 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,149 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
@ -1,282 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,708 +0,0 @@
|
||||
# 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': [
|
||||
{
|
||||
'target_name': 'webrtc_base',
|
||||
'type': 'static_library',
|
||||
'defines': [
|
||||
'FEATURE_ENABLE_SSL',
|
||||
'GTEST_RELATIVE_PATH',
|
||||
'LOGGING=1',
|
||||
'USE_WEBRTC_DEV_BRANCH',
|
||||
],
|
||||
'sources': [
|
||||
'asyncfile.cc',
|
||||
'asyncfile.h',
|
||||
'asynchttprequest.cc',
|
||||
'asynchttprequest.h',
|
||||
'asyncinvoker.cc',
|
||||
'asyncinvoker.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',
|
||||
'buffer.h',
|
||||
'bytebuffer.cc',
|
||||
'bytebuffer.h',
|
||||
'byteorder.h',
|
||||
'callback.h',
|
||||
'checks.cc',
|
||||
'checks.h',
|
||||
'common.cc',
|
||||
'common.h',
|
||||
'constructormagic.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.h',
|
||||
'libdbusglibsymboltable.cc',
|
||||
'libdbusglibsymboltable.h',
|
||||
'linux.cc',
|
||||
'linux.h',
|
||||
'linuxfdwalk.c',
|
||||
'linuxwindowpicker.cc',
|
||||
'linuxwindowpicker.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',
|
||||
'md5.cc',
|
||||
'md5.h',
|
||||
'md5digest.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',
|
||||
'nssidentity.cc',
|
||||
'nssidentity.h',
|
||||
'nssstreamadapter.cc',
|
||||
'nssstreamadapter.h',
|
||||
'nullsocketserver.h',
|
||||
'openssl.h',
|
||||
'openssladapter.cc',
|
||||
'openssladapter.h',
|
||||
'openssldigest.cc',
|
||||
'openssldigest.h',
|
||||
'opensslidentity.cc',
|
||||
'opensslidentity.h',
|
||||
'opensslstreamadapter.cc',
|
||||
'opensslstreamadapter.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',
|
||||
'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',
|
||||
'stringencode.cc',
|
||||
'stringencode.h',
|
||||
'stringutils.cc',
|
||||
'stringutils.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',
|
||||
'timeutils.cc',
|
||||
'timeutils.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',
|
||||
'../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 webrtc_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',
|
||||
'GTEST_RELATIVE_PATH',
|
||||
],
|
||||
},
|
||||
'include_dirs': [
|
||||
'../../third_party/jsoncpp/overrides/include',
|
||||
'../../third_party/jsoncpp/source/include',
|
||||
],
|
||||
'conditions': [
|
||||
['build_with_chromium==1', {
|
||||
'include_dirs': [
|
||||
'../overrides',
|
||||
'../../openssl/openssl/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',
|
||||
'fakecpumonitor.h',
|
||||
'fakenetwork.h',
|
||||
'fakesslidentity.h',
|
||||
'faketaskrunner.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',
|
||||
'linuxwindowpicker.cc',
|
||||
'linuxwindowpicker.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',
|
||||
'natserver_main.cc',
|
||||
'natsocketfactory.cc',
|
||||
'natsocketfactory.h',
|
||||
'nattypes.cc',
|
||||
'nattypes.h',
|
||||
'openssl.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',
|
||||
'testechoserver.h',
|
||||
'testutils.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',
|
||||
'win32toolhelp.h',
|
||||
'window.h',
|
||||
'windowpickerfactory.h',
|
||||
'windowpicker.h',
|
||||
],
|
||||
'defines': [
|
||||
'NO_MAIN_THREAD_WRAPPING',
|
||||
'SSL_USE_NSS',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [
|
||||
'NO_MAIN_THREAD_WRAPPING',
|
||||
'SSL_USE_NSS',
|
||||
],
|
||||
},
|
||||
}, {
|
||||
'dependencies': [
|
||||
'<(DEPTH)/third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
|
||||
],
|
||||
'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',
|
||||
],
|
||||
},
|
||||
'dependencies': [
|
||||
'<(DEPTH)/third_party/openssl/openssl.gyp:openssl',
|
||||
],
|
||||
}, {
|
||||
'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',
|
||||
],
|
||||
},
|
||||
}],
|
||||
['OS == "android"', {
|
||||
'defines': [
|
||||
'HAVE_OPENSSL_SSL_H'
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [
|
||||
'HAVE_OPENSSL_SSL_H'
|
||||
],
|
||||
},
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-llog',
|
||||
'-lGLESv2',
|
||||
],
|
||||
},
|
||||
}, {
|
||||
'defines': [
|
||||
'HAVE_NSS_SSL_H'
|
||||
'SSL_USE_NSS_RNG',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [
|
||||
'HAVE_NSS_SSL_H'
|
||||
'SSL_USE_NSS_RNG',
|
||||
],
|
||||
},
|
||||
'sources!': [
|
||||
'ifaddrs-android.cc',
|
||||
'ifaddrs-android.h',
|
||||
],
|
||||
}],
|
||||
['OS=="ios"', {
|
||||
'all_dependent_settings': {
|
||||
'xcode_settings': {
|
||||
'OTHER_LDFLAGS': [
|
||||
'-framework Foundation',
|
||||
'-framework IOKit',
|
||||
'-framework Security',
|
||||
'-framework SystemConfiguration',
|
||||
'-framework UIKit',
|
||||
],
|
||||
},
|
||||
},
|
||||
'dependencies': [
|
||||
'<(DEPTH)/net/third_party/nss/ssl.gyp:libssl',
|
||||
],
|
||||
}],
|
||||
['OS=="linux"', {
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-lcrypto',
|
||||
'-ldl',
|
||||
'-lrt',
|
||||
'-lXext',
|
||||
'-lX11',
|
||||
'-lXcomposite',
|
||||
'-lXrender',
|
||||
'<!@(<(pkg-config) --libs-only-l nss | sed -e "s/-lssl3//")',
|
||||
],
|
||||
},
|
||||
'cflags': [
|
||||
'<!@(<(pkg-config) --cflags nss)',
|
||||
],
|
||||
'ldflags': [
|
||||
'<!@(<(pkg-config) --libs-only-L --libs-only-other nss)',
|
||||
],
|
||||
}, {
|
||||
'sources!': [
|
||||
'dbus.cc',
|
||||
'dbus.h',
|
||||
'libdbusglibsymboltable.cc',
|
||||
'libdbusglibsymboltable.h',
|
||||
'linuxfdwalk.c',
|
||||
'linuxwindowpicker.cc',
|
||||
'linuxwindowpicker.h',
|
||||
],
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'$(SDKROOT)/usr/lib/libcrypto.dylib',
|
||||
'$(SDKROOT)/usr/lib/libssl.dylib',
|
||||
],
|
||||
},
|
||||
'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=="ios" or os_posix==0', {
|
||||
'sources!': [
|
||||
'openssl.h',
|
||||
'openssladapter.cc',
|
||||
'openssladapter.h',
|
||||
'openssldigest.cc',
|
||||
'openssldigest.h',
|
||||
'opensslidentity.cc',
|
||||
'opensslidentity.h',
|
||||
'opensslstreamadapter.cc',
|
||||
'opensslstreamadapter.h',
|
||||
],
|
||||
}],
|
||||
['OS!="linux" and OS!="android"', {
|
||||
'sources!': [
|
||||
'linux.cc',
|
||||
'linux.h',
|
||||
],
|
||||
}],
|
||||
['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',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
@ -1,260 +0,0 @@
|
||||
|
||||
//*********************************************************************
|
||||
//* 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
|
@ -1,104 +0,0 @@
|
||||
|
||||
//*********************************************************************
|
||||
//* 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__
|
File diff suppressed because it is too large
Load Diff
@ -1,152 +0,0 @@
|
||||
# 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': 'webrtc_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',
|
||||
'win32toolhelp.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'base.gyp:webrtc_base',
|
||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'webrtc_base_tests',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||
'base.gyp:webrtc_base',
|
||||
'webrtc_base_tests_utils',
|
||||
],
|
||||
'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',
|
||||
'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',
|
||||
'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_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': [
|
||||
'sslidentity_unittest.cc',
|
||||
'sslstreamadapter_unittest.cc',
|
||||
],
|
||||
}],
|
||||
['OS=="ios" or (OS=="mac" and target_arch!="ia32")', {
|
||||
'defines': [
|
||||
'CARBON_DEPRECATED=YES',
|
||||
],
|
||||
}],
|
||||
], # conditions
|
||||
},
|
||||
],
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* 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 IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a) - 1)))
|
||||
|
||||
// Note: UNUSED is also defined in common.h
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) Unused(static_cast<const void*>(&x))
|
||||
#define UNUSED2(x, y) Unused(static_cast<const void*>(&x)); \
|
||||
Unused(static_cast<const void*>(&y))
|
||||
#define UNUSED3(x, y, z) Unused(static_cast<const void*>(&x)); \
|
||||
Unused(static_cast<const void*>(&y)); \
|
||||
Unused(static_cast<const void*>(&z))
|
||||
#define UNUSED4(x, y, z, a) Unused(static_cast<const void*>(&x)); \
|
||||
Unused(static_cast<const void*>(&y)); \
|
||||
Unused(static_cast<const void*>(&z)); \
|
||||
Unused(static_cast<const void*>(&a))
|
||||
#define UNUSED5(x, y, z, a, b) Unused(static_cast<const void*>(&x)); \
|
||||
Unused(static_cast<const void*>(&y)); \
|
||||
Unused(static_cast<const void*>(&z)); \
|
||||
Unused(static_cast<const void*>(&a)); \
|
||||
Unused(static_cast<const void*>(&b))
|
||||
inline void Unused(const void*) {}
|
||||
#endif // UNUSED
|
||||
|
||||
// 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_
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,587 +0,0 @@
|
||||
// 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_
|
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,234 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,211 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
@ -1,261 +0,0 @@
|
||||
// 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_
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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 <stdarg.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
|
||||
void Fatal(const char* file, int line, const char* format, ...) {
|
||||
char msg[256];
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
vsnprintf(msg, sizeof(msg), format, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
LOG(LS_ERROR) << "\n\n#\n# Fatal error in " << file
|
||||
<< ", line " << line << "\n#" << msg
|
||||
<< "\n#\n";
|
||||
abort();
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This module contains some basic debugging facilities.
|
||||
// Originally comes from shared/commandlineflags/checks.h
|
||||
|
||||
#ifndef WEBRTC_BASE_CHECKS_H_
|
||||
#define WEBRTC_BASE_CHECKS_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Prints an error message to stderr and aborts execution.
|
||||
void Fatal(const char* file, int line, const char* format, ...);
|
||||
|
||||
|
||||
// The UNREACHABLE macro is very useful during development.
|
||||
#define UNREACHABLE() \
|
||||
Fatal(__FILE__, __LINE__, "unreachable code")
|
||||
|
||||
#endif // WEBRTC_BASE_CHECKS_H_
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rtc
|
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Note: UNUSED is also defined in basictypes.h
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) Unused(static_cast<const void*>(&x))
|
||||
#define UNUSED2(x, y) Unused(static_cast<const void*>(&x)); \
|
||||
Unused(static_cast<const void*>(&y))
|
||||
#define UNUSED3(x, y, z) Unused(static_cast<const void*>(&x)); \
|
||||
Unused(static_cast<const void*>(&y)); \
|
||||
Unused(static_cast<const void*>(&z))
|
||||
#define UNUSED4(x, y, z, a) Unused(static_cast<const void*>(&x)); \
|
||||
Unused(static_cast<const void*>(&y)); \
|
||||
Unused(static_cast<const void*>(&z)); \
|
||||
Unused(static_cast<const void*>(&a))
|
||||
#define UNUSED5(x, y, z, a, b) Unused(static_cast<const void*>(&x)); \
|
||||
Unused(static_cast<const void*>(&y)); \
|
||||
Unused(static_cast<const void*>(&z)); \
|
||||
Unused(static_cast<const void*>(&a)); \
|
||||
Unused(static_cast<const void*>(&b))
|
||||
inline void Unused(const void*) {}
|
||||
#endif // 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);
|
||||
|
||||
} // 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 false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
#define __FUNCTION__ ""
|
||||
#endif
|
||||
|
||||
#ifndef ASSERT
|
||||
#define ASSERT(x) \
|
||||
(void)rtc::Assert((x), __FUNCTION__, __FILE__, __LINE__, #x)
|
||||
#endif
|
||||
|
||||
#ifndef VERIFY
|
||||
#define VERIFY(x) rtc::Assert((x), __FUNCTION__, __FILE__, __LINE__, #x)
|
||||
#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
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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,41 +0,0 @@
|
||||
/*
|
||||
* 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_CONSTRUCTORMAGIC_H_
|
||||
#define WEBRTC_BASE_CONSTRUCTORMAGIC_H_
|
||||
|
||||
#define DISALLOW_ASSIGN(TypeName) \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
// A macro to disallow the evil copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class.
|
||||
// Undefine this, just in case. Some third-party includes have their own
|
||||
// version.
|
||||
#undef DISALLOW_COPY_AND_ASSIGN
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
DISALLOW_ASSIGN(TypeName)
|
||||
|
||||
// Alternative, less-accurate legacy name.
|
||||
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
|
||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
|
||||
// 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.
|
||||
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TypeName)
|
||||
|
||||
|
||||
#endif // WEBRTC_BASE_CONSTRUCTORMAGIC_H_
|
@ -1,419 +0,0 @@
|
||||
/*
|
||||
* 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/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)
|
||||
host_cpu_load_info_data_t cpu_info;
|
||||
mach_msg_type_number_t info_count = HOST_CPU_LOAD_INFO_COUNT;
|
||||
if (KERN_SUCCESS != host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO,
|
||||
reinterpret_cast<host_info_t>(&cpu_info),
|
||||
&info_count)) {
|
||||
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(¤t_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
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,388 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#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 CriticalSection {
|
||||
public:
|
||||
CriticalSection() {
|
||||
InitializeCriticalSection(&crit_);
|
||||
// Windows docs say 0 is not a valid thread id
|
||||
TRACK_OWNER(thread_ = 0);
|
||||
}
|
||||
~CriticalSection() {
|
||||
DeleteCriticalSection(&crit_);
|
||||
}
|
||||
void Enter() {
|
||||
EnterCriticalSection(&crit_);
|
||||
TRACK_OWNER(thread_ = GetCurrentThreadId());
|
||||
}
|
||||
bool TryEnter() {
|
||||
if (TryEnterCriticalSection(&crit_) != FALSE) {
|
||||
TRACK_OWNER(thread_ = GetCurrentThreadId());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Leave() {
|
||||
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 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() {
|
||||
pthread_mutex_lock(&mutex_);
|
||||
TRACK_OWNER(thread_ = pthread_self());
|
||||
}
|
||||
bool TryEnter() {
|
||||
if (pthread_mutex_trylock(&mutex_) == 0) {
|
||||
TRACK_OWNER(thread_ = pthread_self());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Leave() {
|
||||
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 CritScope {
|
||||
public:
|
||||
explicit CritScope(CriticalSection *pcrit) {
|
||||
pcrit_ = pcrit;
|
||||
pcrit_->Enter();
|
||||
}
|
||||
~CritScope() {
|
||||
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__
|
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,396 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,232 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,347 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* 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__
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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__
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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__
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static FakeSSLCertificate* DupCert(FakeSSLCertificate cert) {
|
||||
return cert.GetReference();
|
||||
}
|
||||
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_
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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
|
@ -1,307 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
// TODO(grunell): Remove io.h includes when Chromium has started
|
||||
// to use AEC in each source. http://crbug.com/264611.
|
||||
#include <io.h>
|
||||
#include "webrtc/base/win32.h"
|
||||
#endif
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
// returns the last modified time of this file
|
||||
time_t DirectoryIterator::FileModifyTime() const {
|
||||
#if defined(WEBRTC_WIN)
|
||||
time_t val;
|
||||
FileTimeToUnixTime(data_.ftLastWriteTime, &val);
|
||||
return val;
|
||||
#else
|
||||
return stat_.st_mtime;
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Taken from Chromium's base/platform_file_*.cc.
|
||||
// TODO(grunell): Remove when Chromium has started to use AEC in each source.
|
||||
// http://crbug.com/264611.
|
||||
FILE* FdopenPlatformFileForWriting(PlatformFile file) {
|
||||
#if defined(WEBRTC_WIN)
|
||||
if (file == kInvalidPlatformFileValue)
|
||||
return NULL;
|
||||
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file), 0);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
return _fdopen(fd, "w");
|
||||
#else
|
||||
return fdopen(file, "w");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ClosePlatformFile(PlatformFile file) {
|
||||
#if defined(WEBRTC_WIN)
|
||||
return CloseHandle(file) != 0;
|
||||
#else
|
||||
return close(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace rtc
|
@ -1,459 +0,0 @@
|
||||
/*
|
||||
* 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 "webrtc/base/win32.h"
|
||||
#else
|
||||
#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/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 the last modified time of the file currently pointed to
|
||||
virtual time_t FileModifyTime() 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);
|
||||
|
||||
// Taken from Chromium's base/platform_file.h.
|
||||
// Don't use ClosePlatformFile to close a file opened with FdopenPlatformFile.
|
||||
// Use fclose instead.
|
||||
// TODO(grunell): Remove when Chromium has started to use AEC in each source.
|
||||
// http://crbug.com/264611.
|
||||
#if defined(WEBRTC_WIN)
|
||||
typedef HANDLE PlatformFile;
|
||||
const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
typedef int PlatformFile;
|
||||
const PlatformFile kInvalidPlatformFileValue = -1;
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
||||
|
||||
FILE* FdopenPlatformFileForWriting(PlatformFile file);
|
||||
bool ClosePlatformFile(PlatformFile file);
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_FILEUTILS_H_
|
@ -1,253 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,239 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,298 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
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";
|
||||
}
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
if (n >= buffer_size)
|
||||
Fatal(__FILE__, __LINE__, "CHECK(%s) failed", "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);
|
||||
if (Lookup(flag->name()) != NULL)
|
||||
Fatal(flag->file(), 0, "flag %s declared twice", flag->name());
|
||||
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
|
||||
|
@ -1,267 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
// 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 Flag Flag_##name(__FILE__, #name, (comment), \
|
||||
Flag::type, &FLAG_##name, \
|
||||
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
|
||||
|
||||
|
||||
#endif // SHARED_COMMANDLINEFLAGS_FLAGS_H__
|
@ -1,241 +0,0 @@
|
||||
// This file was GENERATED by command:
|
||||
// pump.py genericslot.h.pump
|
||||
// DO NOT EDIT BY HAND!!!
|
||||
|
||||
/*
|
||||
* 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_GENERICSLOT_H_
|
||||
#define WEBRTC_BASE_GENERICSLOT_H_
|
||||
|
||||
// To generate genericslot.h from genericslot.h.pump, execute:
|
||||
// /home/build/google3/third_party/gtest/scripts/pump.py genericslot.h.pump
|
||||
|
||||
// Generic-slots are pure slots that can be hooked up to signals. They're
|
||||
// mainly intended to be used in tests where we want to check if a signal
|
||||
// was invoked and what arguments were passed. NOTE: They do not do any
|
||||
// lifetime management of the arguments received via callbacks.
|
||||
//
|
||||
// Example:
|
||||
// /* Some signal */
|
||||
// sigslot::signal1<int> foo;
|
||||
//
|
||||
// /* We want to monitor foo in some test */
|
||||
// rtc::GenericSlot1<int> slot(&foo, 0);
|
||||
// foo.emit(5);
|
||||
// EXPECT_TRUE(slot.callback_received());
|
||||
// EXPECT_EQ(5, *(slot.arg1()));
|
||||
//
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/sigslot.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
template <class A1>
|
||||
class GenericSlot1 : public sigslot::has_slots<> {
|
||||
public:
|
||||
GenericSlot1(sigslot::signal1<A1>* signal,
|
||||
const A1& arg1_initial)
|
||||
: arg1_initial_(arg1_initial) {
|
||||
Reset();
|
||||
signal->connect(this, &GenericSlot1::OnSignalCallback);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
callback_received_ = false;
|
||||
arg1_ = arg1_initial_;
|
||||
}
|
||||
|
||||
bool callback_received() const { return callback_received_; }
|
||||
const A1& arg1() const { return arg1_; }
|
||||
|
||||
private:
|
||||
void OnSignalCallback(A1 arg1) {
|
||||
callback_received_ = true;
|
||||
arg1_ = arg1;
|
||||
}
|
||||
|
||||
bool callback_received_;
|
||||
A1 arg1_initial_, arg1_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GenericSlot1);
|
||||
};
|
||||
|
||||
template <class A1, class A2>
|
||||
class GenericSlot2 : public sigslot::has_slots<> {
|
||||
public:
|
||||
GenericSlot2(sigslot::signal2<A1, A2>* signal,
|
||||
const A1& arg1_initial, const A2& arg2_initial)
|
||||
: arg1_initial_(arg1_initial), arg2_initial_(arg2_initial) {
|
||||
Reset();
|
||||
signal->connect(this, &GenericSlot2::OnSignalCallback);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
callback_received_ = false;
|
||||
arg1_ = arg1_initial_;
|
||||
arg2_ = arg2_initial_;
|
||||
}
|
||||
|
||||
bool callback_received() const { return callback_received_; }
|
||||
const A1& arg1() const { return arg1_; }
|
||||
const A2& arg2() const { return arg2_; }
|
||||
|
||||
private:
|
||||
void OnSignalCallback(A1 arg1, A2 arg2) {
|
||||
callback_received_ = true;
|
||||
arg1_ = arg1;
|
||||
arg2_ = arg2;
|
||||
}
|
||||
|
||||
bool callback_received_;
|
||||
A1 arg1_initial_, arg1_;
|
||||
A2 arg2_initial_, arg2_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GenericSlot2);
|
||||
};
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
class GenericSlot3 : public sigslot::has_slots<> {
|
||||
public:
|
||||
GenericSlot3(sigslot::signal3<A1, A2, A3>* signal,
|
||||
const A1& arg1_initial, const A2& arg2_initial,
|
||||
const A3& arg3_initial)
|
||||
: arg1_initial_(arg1_initial), arg2_initial_(arg2_initial),
|
||||
arg3_initial_(arg3_initial) {
|
||||
Reset();
|
||||
signal->connect(this, &GenericSlot3::OnSignalCallback);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
callback_received_ = false;
|
||||
arg1_ = arg1_initial_;
|
||||
arg2_ = arg2_initial_;
|
||||
arg3_ = arg3_initial_;
|
||||
}
|
||||
|
||||
bool callback_received() const { return callback_received_; }
|
||||
const A1& arg1() const { return arg1_; }
|
||||
const A2& arg2() const { return arg2_; }
|
||||
const A3& arg3() const { return arg3_; }
|
||||
|
||||
private:
|
||||
void OnSignalCallback(A1 arg1, A2 arg2, A3 arg3) {
|
||||
callback_received_ = true;
|
||||
arg1_ = arg1;
|
||||
arg2_ = arg2;
|
||||
arg3_ = arg3;
|
||||
}
|
||||
|
||||
bool callback_received_;
|
||||
A1 arg1_initial_, arg1_;
|
||||
A2 arg2_initial_, arg2_;
|
||||
A3 arg3_initial_, arg3_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GenericSlot3);
|
||||
};
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
class GenericSlot4 : public sigslot::has_slots<> {
|
||||
public:
|
||||
GenericSlot4(sigslot::signal4<A1, A2, A3, A4>* signal,
|
||||
const A1& arg1_initial, const A2& arg2_initial,
|
||||
const A3& arg3_initial, const A4& arg4_initial)
|
||||
: arg1_initial_(arg1_initial), arg2_initial_(arg2_initial),
|
||||
arg3_initial_(arg3_initial), arg4_initial_(arg4_initial) {
|
||||
Reset();
|
||||
signal->connect(this, &GenericSlot4::OnSignalCallback);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
callback_received_ = false;
|
||||
arg1_ = arg1_initial_;
|
||||
arg2_ = arg2_initial_;
|
||||
arg3_ = arg3_initial_;
|
||||
arg4_ = arg4_initial_;
|
||||
}
|
||||
|
||||
bool callback_received() const { return callback_received_; }
|
||||
const A1& arg1() const { return arg1_; }
|
||||
const A2& arg2() const { return arg2_; }
|
||||
const A3& arg3() const { return arg3_; }
|
||||
const A4& arg4() const { return arg4_; }
|
||||
|
||||
private:
|
||||
void OnSignalCallback(A1 arg1, A2 arg2, A3 arg3, A4 arg4) {
|
||||
callback_received_ = true;
|
||||
arg1_ = arg1;
|
||||
arg2_ = arg2;
|
||||
arg3_ = arg3;
|
||||
arg4_ = arg4;
|
||||
}
|
||||
|
||||
bool callback_received_;
|
||||
A1 arg1_initial_, arg1_;
|
||||
A2 arg2_initial_, arg2_;
|
||||
A3 arg3_initial_, arg3_;
|
||||
A4 arg4_initial_, arg4_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GenericSlot4);
|
||||
};
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
class GenericSlot5 : public sigslot::has_slots<> {
|
||||
public:
|
||||
GenericSlot5(sigslot::signal5<A1, A2, A3, A4, A5>* signal,
|
||||
const A1& arg1_initial, const A2& arg2_initial,
|
||||
const A3& arg3_initial, const A4& arg4_initial,
|
||||
const A5& arg5_initial)
|
||||
: arg1_initial_(arg1_initial), arg2_initial_(arg2_initial),
|
||||
arg3_initial_(arg3_initial), arg4_initial_(arg4_initial),
|
||||
arg5_initial_(arg5_initial) {
|
||||
Reset();
|
||||
signal->connect(this, &GenericSlot5::OnSignalCallback);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
callback_received_ = false;
|
||||
arg1_ = arg1_initial_;
|
||||
arg2_ = arg2_initial_;
|
||||
arg3_ = arg3_initial_;
|
||||
arg4_ = arg4_initial_;
|
||||
arg5_ = arg5_initial_;
|
||||
}
|
||||
|
||||
bool callback_received() const { return callback_received_; }
|
||||
const A1& arg1() const { return arg1_; }
|
||||
const A2& arg2() const { return arg2_; }
|
||||
const A3& arg3() const { return arg3_; }
|
||||
const A4& arg4() const { return arg4_; }
|
||||
const A5& arg5() const { return arg5_; }
|
||||
|
||||
private:
|
||||
void OnSignalCallback(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) {
|
||||
callback_received_ = true;
|
||||
arg1_ = arg1;
|
||||
arg2_ = arg2;
|
||||
arg3_ = arg3;
|
||||
arg4_ = arg4;
|
||||
arg5_ = arg5;
|
||||
}
|
||||
|
||||
bool callback_received_;
|
||||
A1 arg1_initial_, arg1_;
|
||||
A2 arg2_initial_, arg2_;
|
||||
A3 arg3_initial_, arg3_;
|
||||
A4 arg4_initial_, arg4_;
|
||||
A5 arg5_initial_, arg5_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GenericSlot5);
|
||||
};
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_GENERICSLOT_H_
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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_GENERICSLOT_H_
|
||||
#define WEBRTC_BASE_GENERICSLOT_H_
|
||||
|
||||
// To generate genericslot.h from genericslot.h.pump, execute:
|
||||
// /home/build/google3/third_party/gtest/scripts/pump.py genericslot.h.pump
|
||||
|
||||
// Generic-slots are pure slots that can be hooked up to signals. They're
|
||||
// mainly intended to be used in tests where we want to check if a signal
|
||||
// was invoked and what arguments were passed. NOTE: They do not do any
|
||||
// lifetime management of the arguments received via callbacks.
|
||||
//
|
||||
// Example:
|
||||
// /* Some signal */
|
||||
// sigslot::signal1<int> foo;
|
||||
//
|
||||
// /* We want to monitor foo in some test */
|
||||
// rtc::GenericSlot1<int> slot(&foo, 0);
|
||||
// foo.emit(5);
|
||||
// EXPECT_TRUE(slot.callback_received());
|
||||
// EXPECT_EQ(5, *(slot.arg1()));
|
||||
//
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/sigslot.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
$var n = 5
|
||||
$range i 1..n
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
|
||||
template <$for j , [[class A$j]]>
|
||||
class GenericSlot$i : public sigslot::has_slots<> {
|
||||
public:
|
||||
GenericSlot$i(sigslot::signal$i<$for j , [[A$j]]>* signal,
|
||||
$for j , [[const A$j& arg$j[[]]_initial]])
|
||||
: $for j , [[arg$j[[]]_initial_(arg$j[[]]_initial)]] {
|
||||
Reset();
|
||||
signal->connect(this, &GenericSlot$i::OnSignalCallback);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
callback_received_ = false;$for j [[
|
||||
|
||||
arg$j[[]]_ = arg$j[[]]_initial_; ]]
|
||||
|
||||
}
|
||||
|
||||
bool callback_received() const { return callback_received_; }$for j [[
|
||||
|
||||
const A$j& arg$j() const { return arg$j[[]]_; }]]
|
||||
|
||||
|
||||
private:
|
||||
void OnSignalCallback($for j , [[A$j arg$j]]) {
|
||||
callback_received_ = true;$for j [[
|
||||
|
||||
arg$j[[]]_ = arg$j;]]
|
||||
|
||||
}
|
||||
|
||||
bool callback_received_;$for j [[
|
||||
|
||||
A$j arg$j[[]]_initial_, arg$j[[]]_;]]
|
||||
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GenericSlot$i);
|
||||
};
|
||||
|
||||
]]
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_GENERICSLOT_H_
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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/genericslot.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/sigslot.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
TEST(GenericSlotTest, TestSlot1) {
|
||||
sigslot::signal1<int> source1;
|
||||
GenericSlot1<int> slot1(&source1, 1);
|
||||
EXPECT_FALSE(slot1.callback_received());
|
||||
source1.emit(10);
|
||||
EXPECT_TRUE(slot1.callback_received());
|
||||
EXPECT_EQ(10, slot1.arg1());
|
||||
}
|
||||
|
||||
TEST(GenericSlotTest, TestSlot2) {
|
||||
sigslot::signal2<int, char> source2;
|
||||
GenericSlot2<int, char> slot2(&source2, 1, '0');
|
||||
EXPECT_FALSE(slot2.callback_received());
|
||||
source2.emit(10, 'x');
|
||||
EXPECT_TRUE(slot2.callback_received());
|
||||
EXPECT_EQ(10, slot2.arg1());
|
||||
EXPECT_EQ('x', slot2.arg2());
|
||||
}
|
||||
|
||||
// By induction we assume the rest work too...
|
||||
|
||||
} // namespace rtc
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* 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 "gtest/gtest.h"
|
||||
#else
|
||||
#include "testing/base/public/gunit.h"
|
||||
#endif
|
||||
|
||||
// forward declarations
|
||||
namespace rtc {
|
||||
class Pathname;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
rtc::Pathname GetTalkDirectory();
|
||||
|
||||
#endif // WEBRTC_BASE_GUNIT_H_
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,296 +0,0 @@
|
||||
/*
|
||||
* 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. Need to make sure it doesn't run out of entropy.
|
||||
class SecureRandomGenerator : public RandomGenerator {
|
||||
public:
|
||||
SecureRandomGenerator() : inited_(false) {
|
||||
}
|
||||
~SecureRandomGenerator() {
|
||||
}
|
||||
virtual bool Init(const void* seed, size_t len) {
|
||||
// By default, seed from the system state.
|
||||
if (!inited_) {
|
||||
if (RAND_poll() <= 0) {
|
||||
return false;
|
||||
}
|
||||
inited_ = true;
|
||||
}
|
||||
// Allow app data to be mixed in, if provided.
|
||||
if (seed) {
|
||||
RAND_seed(seed, len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool Generate(void* buf, size_t len) {
|
||||
if (!inited_ && !Init(NULL, 0)) {
|
||||
return false;
|
||||
}
|
||||
return (RAND_bytes(reinterpret_cast<unsigned char*>(buf), len) > 0);
|
||||
}
|
||||
|
||||
private:
|
||||
bool inited_;
|
||||
};
|
||||
|
||||
#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
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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_
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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/gunit.h"
|
||||
#include "webrtc/base/helpers.h"
|
||||
#include "webrtc/base/ssladapter.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
class RandomTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase() {
|
||||
rtc::InitializeSSL();
|
||||
}
|
||||
|
||||
static void TearDownTestCase() {
|
||||
rtc::CleanupSSL();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(RandomTest, TestCreateRandomId) {
|
||||
CreateRandomId();
|
||||
}
|
||||
|
||||
TEST_F(RandomTest, TestCreateRandomDouble) {
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
double r = CreateRandomDouble();
|
||||
EXPECT_GE(r, 0.0);
|
||||
EXPECT_LT(r, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(RandomTest, TestCreateNonZeroRandomId) {
|
||||
EXPECT_NE(0U, CreateRandomNonZeroId());
|
||||
}
|
||||
|
||||
TEST_F(RandomTest, TestCreateRandomString) {
|
||||
std::string random = CreateRandomString(256);
|
||||
EXPECT_EQ(256U, random.size());
|
||||
std::string random2;
|
||||
EXPECT_TRUE(CreateRandomString(256, &random2));
|
||||
EXPECT_NE(random, random2);
|
||||
EXPECT_EQ(256U, random2.size());
|
||||
}
|
||||
|
||||
TEST_F(RandomTest, TestCreateRandomForTest) {
|
||||
// Make sure we get the output we expect.
|
||||
SetRandomTestMode(true);
|
||||
EXPECT_EQ(2154761789U, CreateRandomId());
|
||||
EXPECT_EQ("h0ISP4S5SJKH/9EY", CreateRandomString(16));
|
||||
|
||||
// Reset and make sure we get the same output.
|
||||
SetRandomTestMode(true);
|
||||
EXPECT_EQ(2154761789U, CreateRandomId());
|
||||
EXPECT_EQ("h0ISP4S5SJKH/9EY", CreateRandomString(16));
|
||||
|
||||
// Test different character sets.
|
||||
SetRandomTestMode(true);
|
||||
std::string str;
|
||||
EXPECT_TRUE(CreateRandomString(16, "a", &str));
|
||||
EXPECT_EQ("aaaaaaaaaaaaaaaa", str);
|
||||
EXPECT_TRUE(CreateRandomString(16, "abc", &str));
|
||||
EXPECT_EQ("acbccaaaabbaacbb", str);
|
||||
|
||||
// Turn off test mode for other tests.
|
||||
SetRandomTestMode(false);
|
||||
}
|
||||
|
||||
} // namespace rtc
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user