summaryrefslogtreecommitdiff
path: root/chromium/third_party/libjingle
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2014-03-18 13:16:26 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-03-20 15:55:39 +0100
commit3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch)
tree92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/third_party/libjingle
parente90d7c4b152c56919d963987e2503f9909a666d2 (diff)
downloadqtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies needed on Windows. Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42 Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu> Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/third_party/libjingle')
-rw-r--r--chromium/third_party/libjingle/README.chromium2
-rw-r--r--chromium/third_party/libjingle/libjingle.gyp9
-rw-r--r--chromium/third_party/libjingle/overrides/init_webrtc.cc11
-rw-r--r--chromium/third_party/libjingle/overrides/init_webrtc.h6
-rw-r--r--chromium/third_party/libjingle/overrides/initialize_module.cc6
-rw-r--r--chromium/third_party/libjingle/overrides/talk/base/logging.cc12
-rw-r--r--chromium/third_party/libjingle/overrides/talk/base/logging.h5
-rw-r--r--chromium/third_party/libjingle/source/talk/OWNERS4
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.cc227
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.h103
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/datachannel_unittest.cc228
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.cc20
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.h5
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource_unittest.cc16
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h11
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.cc282
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.h24
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling_unittest.cc92
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objc/README6
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICECandidate.mm10
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICEServer.mm4
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPair.m3
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnection.mm6
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnectionFactory.mm2
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCSessionDescription.mm8
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCVideoRenderer.mm2
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/objctests/RTCSessionDescriptionSyncObserver.m6
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection.cc137
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection_unittest.cc41
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionendtoend_unittest.cc224
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.h6
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory_unittest.cc76
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h13
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface_unittest.cc40
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.cc258
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.h21
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc501
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/statstypes.h34
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp.cc53
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp_unittest.cc70
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.cc273
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.h43
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession_unittest.cc316
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.cc88
-rw-r--r--chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.h13
-rw-r--r--chromium/third_party/libjingle/source/talk/base/asyncpacketsocket.h26
-rw-r--r--chromium/third_party/libjingle/source/talk/base/asyncresolverinterface.h64
-rw-r--r--chromium/third_party/libjingle/source/talk/base/asyncsocket.h12
-rw-r--r--chromium/third_party/libjingle/source/talk/base/asynctcpsocket.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/asyncudpsocket.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/atomicops.h4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/autodetectproxy.cc35
-rw-r--r--chromium/third_party/libjingle/source/talk/base/autodetectproxy.h9
-rw-r--r--chromium/third_party/libjingle/source/talk/base/autodetectproxy_unittest.cc13
-rw-r--r--chromium/third_party/libjingle/source/talk/base/base64.cc9
-rw-r--r--chromium/third_party/libjingle/source/talk/base/buffer.h4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/common.h29
-rw-r--r--chromium/third_party/libjingle/source/talk/base/compile_assert.h99
-rw-r--r--chromium/third_party/libjingle/source/talk/base/constructormagic.h19
-rw-r--r--chromium/third_party/libjingle/source/talk/base/cpumonitor.cc15
-rw-r--r--chromium/third_party/libjingle/source/talk/base/cpumonitor_unittest.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/dbus.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/fakesslidentity.h36
-rw-r--r--chromium/third_party/libjingle/source/talk/base/helpers.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/base/httpclient.cc11
-rw-r--r--chromium/third_party/libjingle/source/talk/base/httpclient.h4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.cc18
-rw-r--r--chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/libdbusglibsymboltable.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/base/linuxwindowpicker_unittest.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/logging.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/logging.h8
-rw-r--r--chromium/third_party/libjingle/source/talk/base/logging_unittest.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/base/macasyncsocket.cc5
-rw-r--r--chromium/third_party/libjingle/source/talk/base/maccocoasocketserver_unittest.mm3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/macsocketserver_unittest.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/macutils.cc33
-rw-r--r--chromium/third_party/libjingle/source/talk/base/macutils.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/macutils_unittest.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/base/md5digest_unittest.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/base/messagedigest.cc10
-rw-r--r--chromium/third_party/libjingle/source/talk/base/move.h207
-rw-r--r--chromium/third_party/libjingle/source/talk/base/natserver.cc25
-rw-r--r--chromium/third_party/libjingle/source/talk/base/natserver.h26
-rw-r--r--chromium/third_party/libjingle/source/talk/base/natsocketfactory.cc5
-rw-r--r--chromium/third_party/libjingle/source/talk/base/nethelpers.cc28
-rw-r--r--chromium/third_party/libjingle/source/talk/base/nethelpers.h17
-rw-r--r--chromium/third_party/libjingle/source/talk/base/network.cc59
-rw-r--r--chromium/third_party/libjingle/source/talk/base/network.h16
-rw-r--r--chromium/third_party/libjingle/source/talk/base/network_unittest.cc84
-rw-r--r--chromium/third_party/libjingle/source/talk/base/nssidentity.cc115
-rw-r--r--chromium/third_party/libjingle/source/talk/base/nssidentity.h15
-rw-r--r--chromium/third_party/libjingle/source/talk/base/nssstreamadapter.cc7
-rw-r--r--chromium/third_party/libjingle/source/talk/base/openssldigest.cc28
-rw-r--r--chromium/third_party/libjingle/source/talk/base/openssldigest.h19
-rw-r--r--chromium/third_party/libjingle/source/talk/base/opensslidentity.cc52
-rw-r--r--chromium/third_party/libjingle/source/talk/base/opensslidentity.h26
-rw-r--r--chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.cc11
-rw-r--r--chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.h6
-rw-r--r--chromium/third_party/libjingle/source/talk/base/physicalsocketserver.cc58
-rw-r--r--chromium/third_party/libjingle/source/talk/base/profiler.cc60
-rw-r--r--chromium/third_party/libjingle/source/talk/base/profiler.h11
-rw-r--r--chromium/third_party/libjingle/source/talk/base/scoped_ptr.h679
-rw-r--r--chromium/third_party/libjingle/source/talk/base/sha1digest_unittest.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/base/signalthread.h1
-rw-r--r--chromium/third_party/libjingle/source/talk/base/signalthread_unittest.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/socket_unittest.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/base/ssladapter.cc1
-rw-r--r--chromium/third_party/libjingle/source/talk/base/ssladapter.h4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/sslfingerprint.h7
-rw-r--r--chromium/third_party/libjingle/source/talk/base/sslidentity.h68
-rw-r--r--chromium/third_party/libjingle/source/talk/base/sslidentity_unittest.cc22
-rw-r--r--chromium/third_party/libjingle/source/talk/base/sslstreamadapter.h19
-rw-r--r--chromium/third_party/libjingle/source/talk/base/sslstreamadapter_unittest.cc49
-rw-r--r--chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.cc8
-rw-r--r--chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.h15
-rw-r--r--chromium/third_party/libjingle/source/talk/base/stream.cc102
-rw-r--r--chromium/third_party/libjingle/source/talk/base/stream.h31
-rw-r--r--chromium/third_party/libjingle/source/talk/base/systeminfo.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/template_util.h106
-rw-r--r--chromium/third_party/libjingle/source/talk/base/testclient.cc14
-rw-r--r--chromium/third_party/libjingle/source/talk/base/testclient.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/testechoserver.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/testutils.h39
-rw-r--r--chromium/third_party/libjingle/source/talk/base/thread.cc13
-rw-r--r--chromium/third_party/libjingle/source/talk/base/thread.h8
-rw-r--r--chromium/third_party/libjingle/source/talk/base/thread_unittest.cc10
-rw-r--r--chromium/third_party/libjingle/source/talk/base/timeutils.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/timeutils.h4
-rw-r--r--chromium/third_party/libjingle/source/talk/base/virtualsocket_unittest.cc12
-rw-r--r--chromium/third_party/libjingle/source/talk/base/win32filesystem.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/base/win32regkey.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/base/win32socketserver.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/base/win32socketserver.h1
-rw-r--r--chromium/third_party/libjingle/source/talk/base/windowpicker_unittest.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/build/isolate.gypi136
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/android/AndroidManifest.xml1
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/android/project.properties4
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/call/callclient.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/chat/chatapp.cc8
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m13
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m8
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCViewController.m4
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/GAEChannelClient.m3
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/peerconnection/client/linux/main_wnd.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/peerconnection/client/main_wnd.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.cc11
-rw-r--r--chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.h2
-rwxr-xr-xchromium/third_party/libjingle/source/talk/libjingle.gyp7
-rw-r--r--chromium/third_party/libjingle/source/talk/libjingle.scons2
-rwxr-xr-xchromium/third_party/libjingle/source/talk/libjingle_examples.gyp39
-rw-r--r--chromium/third_party/libjingle/source/talk/libjingle_media_unittest.isolate46
-rw-r--r--chromium/third_party/libjingle/source/talk/libjingle_p2p_unittest.isolate45
-rw-r--r--chromium/third_party/libjingle/source/talk/libjingle_peerconnection_unittest.isolate45
-rw-r--r--chromium/third_party/libjingle/source/talk/libjingle_sound_unittest.isolate45
-rwxr-xr-xchromium/third_party/libjingle/source/talk/libjingle_tests.gyp81
-rw-r--r--chromium/third_party/libjingle/source/talk/libjingle_unittest.isolate45
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/capturemanager.h16
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/constants.cc43
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/constants.h45
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/cpuid.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/fakemediaengine.h41
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/fakenetworkinterface.h14
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/fakevideocapturer.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/filemediaengine.cc66
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/filemediaengine.h33
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/filemediaengine_unittest.cc9
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.cc10
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.h24
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/mediachannel.h362
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/mediaengine.h56
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.cc29
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.h6
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/rtpdataengine_unittest.cc19
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/streamparams.cc47
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/streamparams.h19
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/streamparams_unittest.cc129
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/testutils.cc26
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/testutils.h45
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/videoadapter.cc18
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/videoadapter.h8
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/videocapturer.cc21
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/videocapturer.h5
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/videocommon.cc38
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/videocommon_unittest.cc9
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/videoengine_unittest.h59
-rw-r--r--chromium/third_party/libjingle/source/talk/media/base/videoframe_unittest.h47
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/carbonvideorenderer.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/devicemanager.cc16
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer.cc15
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer_unittest.cc3
-rwxr-xr-xchromium/third_party/libjingle/source/talk/media/devices/gdivideorenderer.cc6
-rwxr-xr-xchromium/third_party/libjingle/source/talk/media/devices/gtkvideorenderer.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.cc32
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.h8
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/linuxdeviceinfo.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/linuxdevicemanager.cc5
-rw-r--r--chromium/third_party/libjingle/source/talk/media/devices/macdevicemanager.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.cc65
-rw-r--r--chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.h19
-rw-r--r--chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine_unittest.cc46
-rw-r--r--chromium/third_party/libjingle/source/talk/media/sctp/sctputils.cc176
-rw-r--r--chromium/third_party/libjingle/source/talk/media/sctp/sctputils.h53
-rw-r--r--chromium/third_party/libjingle/source/talk/media/sctp/sctputils_unittest.cc153
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/dummyinstantiation.cc37
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvideoengine.h124
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvoiceengine.h113
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcmediaengine.h10
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.cc12
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.cc481
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.h32
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine_unittest.cc185
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.cc118
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h43
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe_unittest.cc31
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.cc377
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.h35
-rw-r--r--chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine_unittest.cc356
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket_unittest.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.cc7
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/dtlstransport.h7
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.cc69
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.h7
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel_unittest.cc57
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/fakesession.h46
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc32
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h15
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel_unittest.cc36
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/packetsocketfactory.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/port.cc11
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/port.h18
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/port_unittest.cc21
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/pseudotcp.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.h9
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/relayport.cc27
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/relayport.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/relayport_unittest.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/relayserver.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/relayserver.h6
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/session.cc64
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/session.h30
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/session_unittest.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/stun.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/stunport.cc45
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/stunport.h25
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/stunport_unittest.cc23
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/stunserver.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/stunserver.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/stunserver_unittest.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/tcpport.cc12
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/tcpport.h6
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/testturnserver.h20
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transport.cc23
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transport.h12
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportchannel.h15
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportchannelimpl.h5
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.cc38
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.h4
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.cc20
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.cc18
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.h3
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory_unittest.cc38
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/turnport.cc52
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/turnport.h22
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/turnport_unittest.cc67
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/turnserver.cc9
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/base/turnserver.h5
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/client/basicportallocator.cc15
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/client/fakeportallocator.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/p2p/client/portallocator_unittest.cc32
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/call.cc8
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/call.h6
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/channel.cc119
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/channel.h54
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/channel_unittest.cc32
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/channelmanager.cc37
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/channelmanager.h20
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/channelmanager_unittest.cc100
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/currentspeakermonitor_unittest.cc3
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/mediasession.cc128
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/mediasession.h17
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/mediasession_unittest.cc64
-rw-r--r--chromium/third_party/libjingle/source/talk/session/media/mediasessionclient.h4
-rw-r--r--chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.h2
-rw-r--r--chromium/third_party/libjingle/source/talk/sound/alsasoundsystem.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/xmllite/xmlbuilder.cc2
-rw-r--r--chromium/third_party/libjingle/source/talk/xmllite/xmlelement_unittest.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/xmpp/mucroomdiscoverytask.cc6
-rw-r--r--chromium/third_party/libjingle/source/talk/xmpp/xmppclient.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/xmpp/xmppengineimpl.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/xmpp/xmpplogintask.cc4
-rw-r--r--chromium/third_party/libjingle/source/talk/xmpp/xmppthread.cc1
299 files changed, 9205 insertions, 2767 deletions
diff --git a/chromium/third_party/libjingle/README.chromium b/chromium/third_party/libjingle/README.chromium
index afa121db25f..f6b4983d65a 100644
--- a/chromium/third_party/libjingle/README.chromium
+++ b/chromium/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@
Name: libjingle
URL: http://code.google.com/p/webrtc/
Version: unknown
-Revision: 4819
+Revision: 5301
License: BSD
License File: source/talk/COPYING
Security Critical: yes
diff --git a/chromium/third_party/libjingle/libjingle.gyp b/chromium/third_party/libjingle/libjingle.gyp
index c56638a82ad..11bb9bb3c93 100644
--- a/chromium/third_party/libjingle/libjingle.gyp
+++ b/chromium/third_party/libjingle/libjingle.gyp
@@ -274,6 +274,7 @@
'<(libjingle_source)/talk/base/checks.h',
'<(libjingle_source)/talk/base/common.cc',
'<(libjingle_source)/talk/base/common.h',
+ '<(libjingle_source)/talk/base/compile_assert.h',
'<(libjingle_source)/talk/base/cpumonitor.cc',
'<(libjingle_source)/talk/base/cpumonitor.h',
'<(libjingle_source)/talk/base/crc32.cc',
@@ -316,6 +317,7 @@
'<(libjingle_source)/talk/base/messagehandler.h',
'<(libjingle_source)/talk/base/messagequeue.cc',
'<(libjingle_source)/talk/base/messagequeue.h',
+ '<(libjingle_source)/talk/base/move.h',
'<(libjingle_source)/talk/base/nethelpers.cc',
'<(libjingle_source)/talk/base/nethelpers.h',
'<(libjingle_source)/talk/base/network.cc',
@@ -383,6 +385,7 @@
'<(libjingle_source)/talk/base/taskparent.h',
'<(libjingle_source)/talk/base/taskrunner.cc',
'<(libjingle_source)/talk/base/taskrunner.h',
+ '<(libjingle_source)/talk/base/template_util.h',
'<(libjingle_source)/talk/base/thread.cc',
'<(libjingle_source)/talk/base/thread.h',
'<(libjingle_source)/talk/base/timeutils.cc',
@@ -730,6 +733,8 @@
'<(libjingle_source)/talk/media/devices/dummydevicemanager.h',
'<(libjingle_source)/talk/media/devices/filevideocapturer.cc',
'<(libjingle_source)/talk/media/devices/filevideocapturer.h',
+ '<(libjingle_source)/talk/media/sctp/sctputils.cc',
+ '<(libjingle_source)/talk/media/sctp/sctputils.h',
'<(libjingle_source)/talk/media/webrtc/webrtccommon.h',
'<(libjingle_source)/talk/media/webrtc/webrtcpassthroughrender.cc',
'<(libjingle_source)/talk/media/webrtc/webrtcpassthroughrender.h',
@@ -784,8 +789,8 @@
'overrides/allocator_shim/allocator_stub.h',
],
}],
- # TODO(mallinath) - Enable SCTP for Android and iOS platforms.
- ['OS!="android" and OS!="ios"', {
+ # TODO(mallinath) - Enable SCTP for iOS.
+ ['OS!="ios"', {
'defines': [
'HAVE_SCTP',
],
diff --git a/chromium/third_party/libjingle/overrides/init_webrtc.cc b/chromium/third_party/libjingle/overrides/init_webrtc.cc
index 746f8831cd1..e0e05321f97 100644
--- a/chromium/third_party/libjingle/overrides/init_webrtc.cc
+++ b/chromium/third_party/libjingle/overrides/init_webrtc.cc
@@ -10,6 +10,7 @@
#include "base/native_library.h"
#include "base/path_service.h"
#include "talk/base/basictypes.h"
+#include "third_party/libjingle/overrides/talk/base/logging.h"
const unsigned char* GetCategoryGroupEnabled(const char* category_group) {
return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
@@ -95,13 +96,19 @@ bool InitializeWebRtcModule() {
// the alloc/dealloc functions.
// PS: This function is actually implemented in allocator_proxy.cc with the
// new/delete overrides.
- return initialize_module(*CommandLine::ForCurrentProcess(),
+ InitDiagnosticLoggingDelegateFunctionFunction init_diagnostic_logging = NULL;
+ bool init_ok = initialize_module(*CommandLine::ForCurrentProcess(),
#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
&Allocate, &Dellocate,
#endif
logging::GetLogMessageHandler(),
&GetCategoryGroupEnabled, &AddTraceEvent,
- &g_create_webrtc_media_engine, &g_destroy_webrtc_media_engine);
+ &g_create_webrtc_media_engine, &g_destroy_webrtc_media_engine,
+ &init_diagnostic_logging);
+
+ if (init_ok)
+ talk_base::SetExtraLoggingInit(init_diagnostic_logging);
+ return init_ok;
}
cricket::MediaEngineInterface* CreateWebRtcMediaEngine(
diff --git a/chromium/third_party/libjingle/overrides/init_webrtc.h b/chromium/third_party/libjingle/overrides/init_webrtc.h
index 5bba57a12d3..acafe50e508 100644
--- a/chromium/third_party/libjingle/overrides/init_webrtc.h
+++ b/chromium/third_party/libjingle/overrides/init_webrtc.h
@@ -30,6 +30,9 @@ typedef cricket::MediaEngineInterface* (*CreateWebRtcMediaEngineFunction)(
typedef void (*DestroyWebRtcMediaEngineFunction)(
cricket::MediaEngineInterface* media_engine);
+typedef void (*InitDiagnosticLoggingDelegateFunctionFunction)(
+ void (*DelegateFunction)(const std::string&));
+
// A typedef for the main initialize function in libpeerconnection.
// This will initialize logging in the module with the proper arguments
// as well as provide pointers back to a couple webrtc factory functions.
@@ -45,7 +48,8 @@ typedef bool (*InitializeModuleFunction)(
webrtc::GetCategoryEnabledPtr trace_get_category_enabled,
webrtc::AddTraceEventPtr trace_add_trace_event,
CreateWebRtcMediaEngineFunction* create_media_engine,
- DestroyWebRtcMediaEngineFunction* destroy_media_engine);
+ DestroyWebRtcMediaEngineFunction* destroy_media_engine,
+ InitDiagnosticLoggingDelegateFunctionFunction* init_diagnostic_logging);
#if !defined(LIBPEERCONNECTION_IMPLEMENTATION)
// Load and initialize the shared WebRTC module (libpeerconnection).
diff --git a/chromium/third_party/libjingle/overrides/initialize_module.cc b/chromium/third_party/libjingle/overrides/initialize_module.cc
index a2528b8c84a..fd1af1196bb 100644
--- a/chromium/third_party/libjingle/overrides/initialize_module.cc
+++ b/chromium/third_party/libjingle/overrides/initialize_module.cc
@@ -9,6 +9,7 @@
#include "init_webrtc.h"
#include "talk/base/basictypes.h"
#include "talk/media/webrtc/webrtcmediaengine.h"
+#include "third_party/libjingle/overrides/talk/base/logging.h"
#if !defined(LIBPEERCONNECTION_IMPLEMENTATION) || defined(LIBPEERCONNECTION_LIB)
#error "Only compile the allocator proxy with the shared_library implementation"
@@ -52,7 +53,9 @@ bool InitializeModule(const CommandLine& command_line,
webrtc::GetCategoryEnabledPtr trace_get_category_enabled,
webrtc::AddTraceEventPtr trace_add_trace_event,
CreateWebRtcMediaEngineFunction* create_media_engine,
- DestroyWebRtcMediaEngineFunction* destroy_media_engine) {
+ DestroyWebRtcMediaEngineFunction* destroy_media_engine,
+ InitDiagnosticLoggingDelegateFunctionFunction*
+ init_diagnostic_logging) {
#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
g_alloc = alloc;
g_dealloc = dealloc;
@@ -60,6 +63,7 @@ bool InitializeModule(const CommandLine& command_line,
*create_media_engine = &CreateWebRtcMediaEngine;
*destroy_media_engine = &DestroyWebRtcMediaEngine;
+ *init_diagnostic_logging = &talk_base::InitDiagnosticLoggingDelegateFunction;
if (CommandLine::Init(0, NULL)) {
#if !defined(OS_WIN)
diff --git a/chromium/third_party/libjingle/overrides/talk/base/logging.cc b/chromium/third_party/libjingle/overrides/talk/base/logging.cc
index e3acfc39e74..3e471817d73 100644
--- a/chromium/third_party/libjingle/overrides/talk/base/logging.cc
+++ b/chromium/third_party/libjingle/overrides/talk/base/logging.cc
@@ -31,6 +31,8 @@
namespace talk_base {
void (*g_logging_delegate_function)(const std::string&) = NULL;
+void (*g_extra_logging_init_function)(
+ void (*logging_delegate_function)(const std::string&)) = NULL;
#ifndef NDEBUG
COMPILE_ASSERT(sizeof(base::subtle::Atomic32) == sizeof(base::PlatformThreadId),
atomic32_not_same_size_as_platformthreadid);
@@ -308,6 +310,16 @@ void InitDiagnosticLoggingDelegateFunction(
IPAddress::set_strip_sensitive(true);
#endif
g_logging_delegate_function = delegate;
+
+ if (g_extra_logging_init_function)
+ g_extra_logging_init_function(delegate);
+}
+
+void SetExtraLoggingInit(
+ void (*function)(void (*delegate)(const std::string&))) {
+ CHECK(function);
+ CHECK(!g_extra_logging_init_function);
+ g_extra_logging_init_function = function;
}
} // namespace talk_base
diff --git a/chromium/third_party/libjingle/overrides/talk/base/logging.h b/chromium/third_party/libjingle/overrides/talk/base/logging.h
index cbc9317b7ae..a474985ce71 100644
--- a/chromium/third_party/libjingle/overrides/talk/base/logging.h
+++ b/chromium/third_party/libjingle/overrides/talk/base/logging.h
@@ -151,9 +151,14 @@ void LogMultiline(LoggingSeverity level, const char* label, bool input,
const void* data, size_t len, bool hex_mode,
LogMultilineState* state);
+// TODO(grunell): Change name to InitDiagnosticLoggingDelegate or
+// InitDiagnosticLogging. Change also in init_webrtc.h/cc.
+// TODO(grunell): typedef the delegate function.
void InitDiagnosticLoggingDelegateFunction(
void (*delegate)(const std::string&));
+void SetExtraLoggingInit(
+ void (*function)(void (*delegate)(const std::string&)));
} // namespace talk_base
//////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/libjingle/source/talk/OWNERS b/chromium/third_party/libjingle/source/talk/OWNERS
index b55b3a38416..ddb55cf3daa 100644
--- a/chromium/third_party/libjingle/source/talk/OWNERS
+++ b/chromium/third_party/libjingle/source/talk/OWNERS
@@ -7,4 +7,6 @@ mallinath@webrtc.org
perkj@webrtc.org
sergeyu@chromium.org
tommi@webrtc.org
-wu@webrtc.org \ No newline at end of file
+wu@webrtc.org
+per-file *.isolate=kjellander@webrtc.org
+
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.cc
index 9409fd7a210..6c9e0bc43ff 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.cc
@@ -28,34 +28,44 @@
#include <string>
-#include "talk/app/webrtc/webrtcsession.h"
+#include "talk/app/webrtc/mediastreamprovider.h"
#include "talk/base/logging.h"
#include "talk/base/refcount.h"
+#include "talk/media/sctp/sctputils.h"
namespace webrtc {
static size_t kMaxQueuedReceivedDataPackets = 100;
static size_t kMaxQueuedSendDataPackets = 100;
+enum {
+ MSG_CHANNELREADY,
+};
+
talk_base::scoped_refptr<DataChannel> DataChannel::Create(
- WebRtcSession* session,
+ DataChannelProviderInterface* provider,
+ cricket::DataChannelType dct,
const std::string& label,
const DataChannelInit* config) {
talk_base::scoped_refptr<DataChannel> channel(
- new talk_base::RefCountedObject<DataChannel>(session, label));
+ new talk_base::RefCountedObject<DataChannel>(provider, dct, label));
if (!channel->Init(config)) {
return NULL;
}
return channel;
}
-DataChannel::DataChannel(WebRtcSession* session, const std::string& label)
+DataChannel::DataChannel(
+ DataChannelProviderInterface* provider,
+ cricket::DataChannelType dct,
+ const std::string& label)
: label_(label),
observer_(NULL),
state_(kConnecting),
was_ever_writable_(false),
- session_(session),
- data_session_(NULL),
+ connected_to_provider_(false),
+ data_channel_type_(dct),
+ provider_(provider),
send_ssrc_set_(false),
send_ssrc_(0),
receive_ssrc_set_(false),
@@ -63,36 +73,44 @@ DataChannel::DataChannel(WebRtcSession* session, const std::string& label)
}
bool DataChannel::Init(const DataChannelInit* config) {
- if (config) {
- if (session_->data_channel_type() == cricket::DCT_RTP &&
- (config->reliable ||
- config->id != -1 ||
- config->maxRetransmits != -1 ||
- config->maxRetransmitTime != -1)) {
- LOG(LS_ERROR) << "Failed to initialize the RTP data channel due to "
+ if (data_channel_type_ == cricket::DCT_RTP &&
+ (config->reliable ||
+ config->id != -1 ||
+ config->maxRetransmits != -1 ||
+ config->maxRetransmitTime != -1)) {
+ LOG(LS_ERROR) << "Failed to initialize the RTP data channel due to "
+ << "invalid DataChannelInit.";
+ return false;
+ } else if (data_channel_type_ == cricket::DCT_SCTP) {
+ if (config->id < -1 ||
+ config->maxRetransmits < -1 ||
+ config->maxRetransmitTime < -1) {
+ LOG(LS_ERROR) << "Failed to initialize the SCTP data channel due to "
<< "invalid DataChannelInit.";
return false;
- } else if (session_->data_channel_type() == cricket::DCT_SCTP) {
- if (config->id < -1 ||
- config->maxRetransmits < -1 ||
- config->maxRetransmitTime < -1) {
- LOG(LS_ERROR) << "Failed to initialize the SCTP data channel due to "
- << "invalid DataChannelInit.";
- return false;
- }
- if (config->maxRetransmits != -1 && config->maxRetransmitTime != -1) {
- LOG(LS_ERROR) <<
- "maxRetransmits and maxRetransmitTime should not be both set.";
- return false;
- }
+ }
+ if (config->maxRetransmits != -1 && config->maxRetransmitTime != -1) {
+ LOG(LS_ERROR) <<
+ "maxRetransmits and maxRetransmitTime should not be both set.";
+ return false;
}
config_ = *config;
+
+ // Try to connect to the transport in case the transport channel already
+ // exists.
+ OnTransportChannelCreated();
+
+ // Checks if the transport is ready to send because the initial channel
+ // ready signal may have been sent before the DataChannel creation.
+ // This has to be done async because the upper layer objects (e.g.
+ // Chrome glue and WebKit) are not wired up properly until after this
+ // function returns.
+ if (provider_->ReadyToSendData()) {
+ talk_base::Thread::Current()->Post(this, MSG_CHANNELREADY, NULL);
+ }
}
- return true;
-}
-bool DataChannel::HasNegotiationCompleted() {
- return send_ssrc_set_ == receive_ssrc_set_;
+ return true;
}
DataChannel::~DataChannel() {
@@ -111,7 +129,7 @@ void DataChannel::UnregisterObserver() {
}
bool DataChannel::reliable() const {
- if (session_->data_channel_type() == cricket::DCT_RTP) {
+ if (data_channel_type_ == cricket::DCT_RTP) {
return false;
} else {
return config_.maxRetransmits == -1 &&
@@ -164,15 +182,13 @@ void DataChannel::QueueControl(const talk_base::Buffer* buffer) {
queued_control_data_.push(buffer);
}
-bool DataChannel::SendControl(const talk_base::Buffer* buffer) {
- if (state_ != kOpen) {
- QueueControl(buffer);
- return true;
- }
- if (session_->data_channel_type() == cricket::DCT_RTP) {
- delete buffer;
- return false;
- }
+bool DataChannel::SendOpenMessage(const talk_base::Buffer* raw_buffer) {
+ ASSERT(data_channel_type_ == cricket::DCT_SCTP &&
+ was_ever_writable_ &&
+ config_.id >= 0 &&
+ !config_.negotiated);
+
+ talk_base::scoped_ptr<const talk_base::Buffer> buffer(raw_buffer);
cricket::SendDataParams send_params;
send_params.ssrc = config_.id;
@@ -180,22 +196,18 @@ bool DataChannel::SendControl(const talk_base::Buffer* buffer) {
send_params.type = cricket::DMT_CONTROL;
cricket::SendDataResult send_result;
- bool retval = session_->data_channel()->SendData(
- send_params, *buffer, &send_result);
+ bool retval = provider_->SendData(send_params, *buffer, &send_result);
if (!retval && send_result == cricket::SDR_BLOCK) {
// Link is congested. Queue for later.
- QueueControl(buffer);
- } else {
- delete buffer;
+ QueueControl(buffer.release());
}
return retval;
}
void DataChannel::SetReceiveSsrc(uint32 receive_ssrc) {
+ ASSERT(data_channel_type_ == cricket::DCT_RTP);
+
if (receive_ssrc_set_) {
- ASSERT(session_->data_channel_type() == cricket::DCT_RTP ||
- !send_ssrc_set_ ||
- receive_ssrc_ == send_ssrc_);
return;
}
receive_ssrc_ = receive_ssrc;
@@ -209,10 +221,8 @@ void DataChannel::RemotePeerRequestClose() {
}
void DataChannel::SetSendSsrc(uint32 send_ssrc) {
+ ASSERT(data_channel_type_ == cricket::DCT_RTP);
if (send_ssrc_set_) {
- ASSERT(session_->data_channel_type() == cricket::DCT_RTP ||
- !receive_ssrc_set_ ||
- receive_ssrc_ == send_ssrc_);
return;
}
send_ssrc_ = send_ssrc;
@@ -220,8 +230,16 @@ void DataChannel::SetSendSsrc(uint32 send_ssrc) {
UpdateState();
}
+void DataChannel::OnMessage(talk_base::Message* msg) {
+ switch (msg->message_id) {
+ case MSG_CHANNELREADY:
+ OnChannelReady(true);
+ break;
+ }
+}
+
// The underlaying data engine is closing.
-// This function make sure the DataChannel is disconneced and change state to
+// This function makes sure the DataChannel is disconnected and changes state to
// kClosed.
void DataChannel::OnDataEngineClose() {
DoClose();
@@ -230,7 +248,9 @@ void DataChannel::OnDataEngineClose() {
void DataChannel::OnDataReceived(cricket::DataChannel* channel,
const cricket::ReceiveDataParams& params,
const talk_base::Buffer& payload) {
- if (params.ssrc != receive_ssrc_) {
+ uint32 expected_ssrc =
+ (data_channel_type_ == cricket::DCT_RTP) ? receive_ssrc_ : config_.id;
+ if (params.ssrc != expected_ssrc) {
return;
}
@@ -258,8 +278,18 @@ void DataChannel::OnChannelReady(bool writable) {
// for sending and now unblocked, so send the queued data now.
if (!was_ever_writable_) {
was_ever_writable_ = true;
+
+ if (data_channel_type_ == cricket::DCT_SCTP && !config_.negotiated) {
+ talk_base::Buffer* payload = new talk_base::Buffer;
+ if (!cricket::WriteDataChannelOpenMessage(label_, config_, payload)) {
+ // TODO(jiayl): close the data channel on this error.
+ LOG(LS_ERROR) << "Could not write data channel OPEN message";
+ return;
+ }
+ SendOpenMessage(payload);
+ }
+
UpdateState();
- DeliverQueuedControlData();
ASSERT(queued_send_data_.empty());
} else if (state_ == kOpen) {
DeliverQueuedSendData();
@@ -276,11 +306,14 @@ void DataChannel::DoClose() {
void DataChannel::UpdateState() {
switch (state_) {
case kConnecting: {
- if (HasNegotiationCompleted()) {
- if (!IsConnectedToDataSession()) {
- ConnectToDataSession();
+ if (send_ssrc_set_ == receive_ssrc_set_) {
+ if (data_channel_type_ == cricket::DCT_RTP && !connected_to_provider_) {
+ connected_to_provider_ = provider_->ConnectDataChannel(this);
}
if (was_ever_writable_) {
+ // TODO(jiayl): Do not transition to kOpen if we failed to send the
+ // OPEN message.
+ DeliverQueuedControlData();
SetState(kOpen);
// If we have received buffers before the channel got writable.
// Deliver them now.
@@ -293,10 +326,9 @@ void DataChannel::UpdateState() {
break;
}
case kClosing: {
- if (IsConnectedToDataSession()) {
- DisconnectFromDataSession();
- }
- if (HasNegotiationCompleted()) {
+ DisconnectFromTransport();
+
+ if (!send_ssrc_set_ && !receive_ssrc_set_) {
SetState(kClosed);
}
break;
@@ -313,29 +345,16 @@ void DataChannel::SetState(DataState state) {
}
}
-void DataChannel::ConnectToDataSession() {
- if (!session_->data_channel()) {
- LOG(LS_ERROR) << "The DataEngine does not exist.";
- ASSERT(session_->data_channel() != NULL);
+void DataChannel::DisconnectFromTransport() {
+ if (!connected_to_provider_)
return;
- }
- data_session_ = session_->data_channel();
- data_session_->SignalReadyToSendData.connect(this,
- &DataChannel::OnChannelReady);
- data_session_->SignalDataReceived.connect(this, &DataChannel::OnDataReceived);
- cricket::StreamParams params =
- cricket::StreamParams::CreateLegacy(id());
- data_session_->AddRecvStream(params);
- data_session_->AddSendStream(params);
-}
+ provider_->DisconnectDataChannel(this);
+ connected_to_provider_ = false;
-void DataChannel::DisconnectFromDataSession() {
- data_session_->RemoveSendStream(id());
- data_session_->RemoveRecvStream(id());
- data_session_->SignalReadyToSendData.disconnect(this);
- data_session_->SignalDataReceived.disconnect(this);
- data_session_ = NULL;
+ if (data_channel_type_ == cricket::DCT_SCTP) {
+ provider_->RemoveSctpDataStream(config_.id);
+ }
}
void DataChannel::DeliverQueuedReceivedData() {
@@ -360,10 +379,12 @@ void DataChannel::ClearQueuedReceivedData() {
}
void DataChannel::DeliverQueuedSendData() {
+ ASSERT(was_ever_writable_ && state_ == kOpen);
+
+ // TODO(jiayl): Sending OPEN message here contradicts with the pre-condition
+ // that the readyState is open. According to the standard, the channel should
+ // not become open before the OPEN message is sent.
DeliverQueuedControlData();
- if (!was_ever_writable_) {
- return;
- }
while (!queued_send_data_.empty()) {
DataBuffer* buffer = queued_send_data_.front();
@@ -387,12 +408,11 @@ void DataChannel::ClearQueuedControlData() {
}
void DataChannel::DeliverQueuedControlData() {
- if (was_ever_writable_) {
- while (!queued_control_data_.empty()) {
- const talk_base::Buffer *buf = queued_control_data_.front();
- queued_control_data_.pop();
- SendControl(buf);
- }
+ ASSERT(was_ever_writable_);
+ while (!queued_control_data_.empty()) {
+ const talk_base::Buffer* buf = queued_control_data_.front();
+ queued_control_data_.pop();
+ SendOpenMessage(buf);
}
}
@@ -408,16 +428,17 @@ bool DataChannel::InternalSendWithoutQueueing(
const DataBuffer& buffer, cricket::SendDataResult* send_result) {
cricket::SendDataParams send_params;
- send_params.ssrc = send_ssrc_;
- if (session_->data_channel_type() == cricket::DCT_SCTP) {
+ if (data_channel_type_ == cricket::DCT_SCTP) {
send_params.ordered = config_.ordered;
send_params.max_rtx_count = config_.maxRetransmits;
send_params.max_rtx_ms = config_.maxRetransmitTime;
+ send_params.ssrc = config_.id;
+ } else {
+ send_params.ssrc = send_ssrc_;
}
send_params.type = buffer.binary ? cricket::DMT_BINARY : cricket::DMT_TEXT;
- return session_->data_channel()->SendData(send_params, buffer.data,
- send_result);
+ return provider_->SendData(send_params, buffer.data, send_result);
}
bool DataChannel::QueueSendData(const DataBuffer& buffer) {
@@ -429,4 +450,22 @@ bool DataChannel::QueueSendData(const DataBuffer& buffer) {
return true;
}
+void DataChannel::SetSctpSid(int sid) {
+ ASSERT(config_.id < 0 && sid >= 0 && data_channel_type_ == cricket::DCT_SCTP);
+ config_.id = sid;
+ provider_->AddSctpDataStream(sid);
+}
+
+void DataChannel::OnTransportChannelCreated() {
+ ASSERT(data_channel_type_ == cricket::DCT_SCTP);
+ if (!connected_to_provider_) {
+ connected_to_provider_ = provider_->ConnectDataChannel(this);
+ }
+ // The sid may have been unassigned when provider_->ConnectDataChannel was
+ // done. So always add the streams even if connected_to_provider_ is true.
+ if (config_.id >= 0) {
+ provider_->AddSctpDataStream(config_.id);
+ }
+}
+
} // namespace webrtc
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.h b/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.h
index 3ce3c1b5b4e..bf31aed5d53 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel.h
@@ -33,22 +33,45 @@
#include "talk/app/webrtc/datachannelinterface.h"
#include "talk/app/webrtc/proxy.h"
+#include "talk/base/messagehandler.h"
#include "talk/base/scoped_ref_ptr.h"
#include "talk/base/sigslot.h"
+#include "talk/media/base/mediachannel.h"
#include "talk/session/media/channel.h"
namespace webrtc {
-class WebRtcSession;
+class DataChannel;
+
+class DataChannelProviderInterface {
+ public:
+ // Sends the data to the transport.
+ virtual bool SendData(const cricket::SendDataParams& params,
+ const talk_base::Buffer& payload,
+ cricket::SendDataResult* result) = 0;
+ // Connects to the transport signals.
+ virtual bool ConnectDataChannel(DataChannel* data_channel) = 0;
+ // Disconnects from the transport signals.
+ virtual void DisconnectDataChannel(DataChannel* data_channel) = 0;
+ // Adds the data channel SID to the transport for SCTP.
+ virtual void AddSctpDataStream(uint32 sid) = 0;
+ // Removes the data channel SID from the transport for SCTP.
+ virtual void RemoveSctpDataStream(uint32 sid) = 0;
+ // Returns true if the transport channel is ready to send data.
+ virtual bool ReadyToSendData() const = 0;
+
+ protected:
+ virtual ~DataChannelProviderInterface() {}
+};
// DataChannel is a an implementation of the DataChannelInterface based on
-// libjingle's data engine. It provides an implementation of unreliable data
-// channels. Currently this class is specifically designed to use RtpDataEngine,
-// and will changed to use SCTP in the future.
+// libjingle's data engine. It provides an implementation of unreliable or
+// reliabledata channels. Currently this class is specifically designed to use
+// both RtpDataEngine and SctpDataEngine.
// DataChannel states:
-// kConnecting: The channel has been created but SSRC for sending and receiving
-// has not yet been set and the transport might not yet be ready.
+// kConnecting: The channel has been created the transport might not yet be
+// ready.
// kOpen: The channel have a local SSRC set by a call to UpdateSendSsrc
// and a remote SSRC set by call to UpdateReceiveSsrc and the transport
// has been writable once.
@@ -57,10 +80,12 @@ class WebRtcSession;
// kClosed: Both UpdateReceiveSsrc and UpdateSendSsrc has been called with
// SSRC==0.
class DataChannel : public DataChannelInterface,
- public sigslot::has_slots<> {
+ public sigslot::has_slots<>,
+ public talk_base::MessageHandler {
public:
static talk_base::scoped_refptr<DataChannel> Create(
- WebRtcSession* session,
+ DataChannelProviderInterface* provider,
+ cricket::DataChannelType dct,
const std::string& label,
const DataChannelInit* config);
@@ -83,20 +108,9 @@ class DataChannel : public DataChannelInterface,
virtual void Close();
virtual DataState state() const { return state_; }
virtual bool Send(const DataBuffer& buffer);
- // Send a control message right now, or queue for later.
- virtual bool SendControl(const talk_base::Buffer* buffer);
- void ConnectToDataSession();
-
- // Set the SSRC this channel should use to receive data from the
- // underlying data engine.
- void SetReceiveSsrc(uint32 receive_ssrc);
- // The remote peer request that this channel should be closed.
- void RemotePeerRequestClose();
- // Set the SSRC this channel should use to send data on the
- // underlying data engine. |send_ssrc| == 0 means that the channel is no
- // longer part of the session negotiation.
- void SetSendSsrc(uint32 send_ssrc);
+ // talk_base::MessageHandler override.
+ virtual void OnMessage(talk_base::Message* msg);
// Called if the underlying data engine is closing.
void OnDataEngineClose();
@@ -105,24 +119,48 @@ class DataChannel : public DataChannelInterface,
// underlying DataMediaChannel becomes ready, or when this channel is a new
// stream on an existing DataMediaChannel, and we've finished negotiation.
void OnChannelReady(bool writable);
- protected:
- DataChannel(WebRtcSession* session, const std::string& label);
- virtual ~DataChannel();
-
- bool Init(const DataChannelInit* config);
- bool HasNegotiationCompleted();
// Sigslots from cricket::DataChannel
void OnDataReceived(cricket::DataChannel* channel,
const cricket::ReceiveDataParams& params,
const talk_base::Buffer& payload);
+ // The remote peer request that this channel should be closed.
+ void RemotePeerRequestClose();
+
+ // The following methods are for SCTP only.
+
+ // Sets the SCTP sid and adds to transport layer if not set yet.
+ void SetSctpSid(int sid);
+ // Called when the transport channel is created.
+ void OnTransportChannelCreated();
+
+ // The following methods are for RTP only.
+
+ // Set the SSRC this channel should use to send data on the
+ // underlying data engine. |send_ssrc| == 0 means that the channel is no
+ // longer part of the session negotiation.
+ void SetSendSsrc(uint32 send_ssrc);
+ // Set the SSRC this channel should use to receive data from the
+ // underlying data engine.
+ void SetReceiveSsrc(uint32 receive_ssrc);
+
+ cricket::DataChannelType data_channel_type() const {
+ return data_channel_type_;
+ }
+
+ protected:
+ DataChannel(DataChannelProviderInterface* client,
+ cricket::DataChannelType dct,
+ const std::string& label);
+ virtual ~DataChannel();
+
private:
+ bool Init(const DataChannelInit* config);
void DoClose();
void UpdateState();
void SetState(DataState state);
- void DisconnectFromDataSession();
- bool IsConnectedToDataSession() { return data_session_ != NULL; }
+ void DisconnectFromTransport();
void DeliverQueuedControlData();
void QueueControl(const talk_base::Buffer* buffer);
void ClearQueuedControlData();
@@ -133,14 +171,17 @@ class DataChannel : public DataChannelInterface,
bool InternalSendWithoutQueueing(const DataBuffer& buffer,
cricket::SendDataResult* send_result);
bool QueueSendData(const DataBuffer& buffer);
+ bool SendOpenMessage(const talk_base::Buffer* buffer);
+
std::string label_;
DataChannelInit config_;
DataChannelObserver* observer_;
DataState state_;
bool was_ever_writable_;
- WebRtcSession* session_;
- cricket::DataChannel* data_session_;
+ bool connected_to_provider_;
+ cricket::DataChannelType data_channel_type_;
+ DataChannelProviderInterface* provider_;
bool send_ssrc_set_;
uint32 send_ssrc_;
bool receive_ssrc_set_;
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel_unittest.cc
index 2b0a9fe5a65..fdcd2f2cd11 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/datachannel_unittest.cc
@@ -26,118 +26,96 @@
*/
#include "talk/app/webrtc/datachannel.h"
-#include "talk/app/webrtc/jsep.h"
-#include "talk/app/webrtc/mediastreamsignaling.h"
-#include "talk/app/webrtc/test/fakeconstraints.h"
-#include "talk/app/webrtc/test/fakedtlsidentityservice.h"
-#include "talk/app/webrtc/webrtcsession.h"
+#include "talk/app/webrtc/test/fakedatachannelprovider.h"
#include "talk/base/gunit.h"
-#include "talk/media/base/fakemediaengine.h"
-#include "talk/media/devices/fakedevicemanager.h"
-#include "talk/session/media/channelmanager.h"
+#include "testing/base/public/gmock.h"
-using webrtc::CreateSessionDescriptionObserver;
-using webrtc::MediaConstraintsInterface;
-using webrtc::SessionDescriptionInterface;
+using webrtc::DataChannel;
-const uint32 kFakeSsrc = 1;
-
-class CreateSessionDescriptionObserverForTest
- : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
+class FakeDataChannelObserver : public webrtc::DataChannelObserver {
public:
- virtual void OnSuccess(SessionDescriptionInterface* desc) {
- description_.reset(desc);
- }
- virtual void OnFailure(const std::string& error) {}
-
- SessionDescriptionInterface* description() { return description_.get(); }
-
- SessionDescriptionInterface* ReleaseDescription() {
- return description_.release();
- }
-
- protected:
- ~CreateSessionDescriptionObserverForTest() {}
-
- private:
- talk_base::scoped_ptr<SessionDescriptionInterface> description_;
+ MOCK_METHOD0(OnStateChange, void());
+ MOCK_METHOD1(OnMessage, void(const webrtc::DataBuffer& buffer));
};
class SctpDataChannelTest : public testing::Test {
protected:
SctpDataChannelTest()
- : media_engine_(new cricket::FakeMediaEngine),
- data_engine_(new cricket::FakeDataEngine),
- channel_manager_(
- new cricket::ChannelManager(media_engine_,
- data_engine_,
- new cricket::FakeDeviceManager(),
- new cricket::CaptureManager(),
- talk_base::Thread::Current())),
- media_stream_signaling_(
- new webrtc::MediaStreamSignaling(talk_base::Thread::Current(),
- NULL, channel_manager_.get())),
- session_(channel_manager_.get(),
- talk_base::Thread::Current(),
- talk_base::Thread::Current(),
- NULL,
- media_stream_signaling_.get()),
- webrtc_data_channel_(NULL) {}
-
- virtual void SetUp() {
- if (!talk_base::SSLStreamAdapter::HaveDtlsSrtp()) {
- return;
- }
- channel_manager_->Init();
- webrtc::FakeConstraints constraints;
- constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true);
- constraints.AddMandatory(MediaConstraintsInterface::kEnableSctpDataChannels,
- true);
- ASSERT_TRUE(session_.Initialize(&constraints,
- new FakeIdentityService()));
- webrtc_data_channel_ = webrtc::DataChannel::Create(&session_, "test", NULL);
- ASSERT_TRUE(media_stream_signaling_->AddDataChannel(webrtc_data_channel_));
-
- talk_base::scoped_refptr<CreateSessionDescriptionObserverForTest> observer
- = new CreateSessionDescriptionObserverForTest();
- session_.CreateOffer(observer.get(), NULL);
- EXPECT_TRUE_WAIT(observer->description() != NULL, 2000);
- ASSERT_TRUE(observer->description() != NULL);
- ASSERT_TRUE(session_.SetLocalDescription(observer->ReleaseDescription(),
- NULL));
- // Connect to the media channel.
- webrtc_data_channel_->SetSendSsrc(kFakeSsrc);
- webrtc_data_channel_->SetReceiveSsrc(kFakeSsrc);
- session_.data_channel()->SignalReadyToSendData(true);
+ : webrtc_data_channel_(
+ DataChannel::Create(&provider_, cricket::DCT_SCTP, "test", &init_)) {
}
- void SetSendBlocked(bool blocked) {
- bool was_blocked = data_engine_->GetChannel(0)->is_send_blocked();
- data_engine_->GetChannel(0)->set_send_blocked(blocked);
- if (!blocked && was_blocked) {
- session_.data_channel()->SignalReadyToSendData(true);
+ void SetChannelReady() {
+ provider_.set_transport_available(true);
+ webrtc_data_channel_->OnTransportChannelCreated();
+ if (webrtc_data_channel_->id() < 0) {
+ webrtc_data_channel_->SetSctpSid(0);
}
+ provider_.set_ready_to_send(true);
+ }
+
+ void AddObserver() {
+ observer_.reset(new FakeDataChannelObserver());
+ webrtc_data_channel_->RegisterObserver(observer_.get());
}
- cricket::FakeMediaEngine* media_engine_;
- cricket::FakeDataEngine* data_engine_;
- talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
- talk_base::scoped_ptr<webrtc::MediaStreamSignaling> media_stream_signaling_;
- webrtc::WebRtcSession session_;
- talk_base::scoped_refptr<webrtc::DataChannel> webrtc_data_channel_;
+
+ webrtc::DataChannelInit init_;
+ FakeDataChannelProvider provider_;
+ talk_base::scoped_ptr<FakeDataChannelObserver> observer_;
+ talk_base::scoped_refptr<DataChannel> webrtc_data_channel_;
};
+// Verifies that the data channel is connected to the transport after creation.
+TEST_F(SctpDataChannelTest, ConnectedToTransportOnCreated) {
+ provider_.set_transport_available(true);
+ talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
+ &provider_, cricket::DCT_SCTP, "test1", &init_);
+
+ EXPECT_TRUE(provider_.IsConnected(dc.get()));
+ // The sid is not set yet, so it should not have added the streams.
+ EXPECT_FALSE(provider_.IsSendStreamAdded(dc->id()));
+ EXPECT_FALSE(provider_.IsRecvStreamAdded(dc->id()));
+
+ dc->SetSctpSid(0);
+ EXPECT_TRUE(provider_.IsSendStreamAdded(dc->id()));
+ EXPECT_TRUE(provider_.IsRecvStreamAdded(dc->id()));
+}
+
+// Verifies that the data channel is connected to the transport if the transport
+// is not available initially and becomes available later.
+TEST_F(SctpDataChannelTest, ConnectedAfterTransportBecomesAvailable) {
+ EXPECT_FALSE(provider_.IsConnected(webrtc_data_channel_.get()));
+
+ provider_.set_transport_available(true);
+ webrtc_data_channel_->OnTransportChannelCreated();
+ EXPECT_TRUE(provider_.IsConnected(webrtc_data_channel_.get()));
+}
+
+// Tests the state of the data channel.
+TEST_F(SctpDataChannelTest, StateTransition) {
+ EXPECT_EQ(webrtc::DataChannelInterface::kConnecting,
+ webrtc_data_channel_->state());
+ SetChannelReady();
+
+ EXPECT_EQ(webrtc::DataChannelInterface::kOpen, webrtc_data_channel_->state());
+ webrtc_data_channel_->Close();
+ EXPECT_EQ(webrtc::DataChannelInterface::kClosed,
+ webrtc_data_channel_->state());
+ // Verifies that it's disconnected from the transport.
+ EXPECT_FALSE(provider_.IsConnected(webrtc_data_channel_.get()));
+}
+
// Tests that DataChannel::buffered_amount() is correct after the channel is
// blocked.
TEST_F(SctpDataChannelTest, BufferedAmountWhenBlocked) {
- if (!talk_base::SSLStreamAdapter::HaveDtlsSrtp()) {
- return;
- }
+ SetChannelReady();
webrtc::DataBuffer buffer("abcd");
EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
EXPECT_EQ(0U, webrtc_data_channel_->buffered_amount());
- SetSendBlocked(true);
+ provider_.set_send_blocked(true);
+
const int number_of_packets = 3;
for (int i = 0; i < number_of_packets; ++i) {
EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
@@ -149,13 +127,75 @@ TEST_F(SctpDataChannelTest, BufferedAmountWhenBlocked) {
// Tests that the queued data are sent when the channel transitions from blocked
// to unblocked.
TEST_F(SctpDataChannelTest, QueuedDataSentWhenUnblocked) {
- if (!talk_base::SSLStreamAdapter::HaveDtlsSrtp()) {
- return;
- }
+ SetChannelReady();
webrtc::DataBuffer buffer("abcd");
- SetSendBlocked(true);
+ provider_.set_send_blocked(true);
EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
- SetSendBlocked(false);
+ provider_.set_send_blocked(false);
+ SetChannelReady();
EXPECT_EQ(0U, webrtc_data_channel_->buffered_amount());
}
+
+// Tests that the queued control message is sent when channel is ready.
+TEST_F(SctpDataChannelTest, OpenMessageSent) {
+ // Initially the id is unassigned.
+ EXPECT_EQ(-1, webrtc_data_channel_->id());
+
+ SetChannelReady();
+ EXPECT_GE(webrtc_data_channel_->id(), 0);
+ EXPECT_EQ(cricket::DMT_CONTROL, provider_.last_send_data_params().type);
+ EXPECT_EQ(provider_.last_send_data_params().ssrc,
+ static_cast<uint32>(webrtc_data_channel_->id()));
+}
+
+// Tests that the DataChannel created after transport gets ready can enter OPEN
+// state.
+TEST_F(SctpDataChannelTest, LateCreatedChannelTransitionToOpen) {
+ SetChannelReady();
+ webrtc::DataChannelInit init;
+ init.id = 1;
+ talk_base::scoped_refptr<DataChannel> dc =
+ DataChannel::Create(&provider_, cricket::DCT_SCTP, "test1", &init);
+ EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, dc->state());
+ EXPECT_TRUE_WAIT(webrtc::DataChannelInterface::kOpen == dc->state(),
+ 1000);
+}
+
+// Tests that messages are sent with the right ssrc.
+TEST_F(SctpDataChannelTest, SendDataSsrc) {
+ webrtc_data_channel_->SetSctpSid(1);
+ SetChannelReady();
+ webrtc::DataBuffer buffer("data");
+ EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
+ EXPECT_EQ(1U, provider_.last_send_data_params().ssrc);
+}
+
+// Tests that the incoming messages with wrong ssrcs are rejected.
+TEST_F(SctpDataChannelTest, ReceiveDataWithInvalidSsrc) {
+ webrtc_data_channel_->SetSctpSid(1);
+ SetChannelReady();
+
+ AddObserver();
+ EXPECT_CALL(*(observer_.get()), OnMessage(testing::_)).Times(0);
+
+ cricket::ReceiveDataParams params;
+ params.ssrc = 0;
+ webrtc::DataBuffer buffer("abcd");
+ webrtc_data_channel_->OnDataReceived(NULL, params, buffer.data);
+}
+
+// Tests that the incoming messages with right ssrcs are acceted.
+TEST_F(SctpDataChannelTest, ReceiveDataWithValidSsrc) {
+ webrtc_data_channel_->SetSctpSid(1);
+ SetChannelReady();
+
+ AddObserver();
+ EXPECT_CALL(*(observer_.get()), OnMessage(testing::_)).Times(1);
+
+ cricket::ReceiveDataParams params;
+ params.ssrc = 1;
+ webrtc::DataBuffer buffer("abcd");
+
+ webrtc_data_channel_->OnDataReceived(NULL, params, buffer.data);
+}
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.cc
index 3663aace528..2cd472a5a01 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.cc
@@ -53,7 +53,9 @@ const char MediaConstraintsInterface::kHighpassFilter[] =
"googHighpassFilter";
const char MediaConstraintsInterface::kTypingNoiseDetection[] =
"googTypingNoiseDetection";
-const char MediaConstraintsInterface::kInternalAecDump[] = "internalAecDump";
+const char MediaConstraintsInterface::kAudioMirroring[] = "googAudioMirroring";
+// TODO(perkj): Remove kInternalAecDump once its not used by Chrome.
+const char MediaConstraintsInterface::kInternalAecDump[] = "deprecatedAecDump";
namespace {
@@ -90,10 +92,10 @@ bool FromConstraints(const MediaConstraintsInterface::Constraints& constraints,
options->noise_suppression.Set(value);
else if (iter->key == MediaConstraintsInterface::kHighpassFilter)
options->highpass_filter.Set(value);
- else if (iter->key == MediaConstraintsInterface::kInternalAecDump)
- options->aec_dump.Set(value);
else if (iter->key == MediaConstraintsInterface::kTypingNoiseDetection)
options->typing_detection.Set(value);
+ else if (iter->key == MediaConstraintsInterface::kAudioMirroring)
+ options->stereo_swapping.Set(value);
else
success = false;
}
@@ -103,14 +105,16 @@ bool FromConstraints(const MediaConstraintsInterface::Constraints& constraints,
} // namespace
talk_base::scoped_refptr<LocalAudioSource> LocalAudioSource::Create(
+ const PeerConnectionFactoryInterface::Options& options,
const MediaConstraintsInterface* constraints) {
talk_base::scoped_refptr<LocalAudioSource> source(
new talk_base::RefCountedObject<LocalAudioSource>());
- source->Initialize(constraints);
+ source->Initialize(options, constraints);
return source;
}
void LocalAudioSource::Initialize(
+ const PeerConnectionFactoryInterface::Options& options,
const MediaConstraintsInterface* constraints) {
if (!constraints)
return;
@@ -119,12 +123,14 @@ void LocalAudioSource::Initialize(
// constraints.
FromConstraints(constraints->GetOptional(), &options_);
- cricket::AudioOptions options;
- if (!FromConstraints(constraints->GetMandatory(), &options)) {
+ cricket::AudioOptions audio_options;
+ if (!FromConstraints(constraints->GetMandatory(), &audio_options)) {
source_state_ = kEnded;
return;
}
- options_.SetAll(options);
+ options_.SetAll(audio_options);
+ if (options.enable_aec_dump)
+ options_.aec_dump.Set(true);
source_state_ = kLive;
}
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.h b/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.h
index e0fda03d7f1..fb769ed621d 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource.h
@@ -30,6 +30,7 @@
#include "talk/app/webrtc/mediastreaminterface.h"
#include "talk/app/webrtc/notifier.h"
+#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/base/scoped_ptr.h"
#include "talk/media/base/mediachannel.h"
@@ -44,6 +45,7 @@ class LocalAudioSource : public Notifier<AudioSourceInterface> {
public:
// Creates an instance of LocalAudioSource.
static talk_base::scoped_refptr<LocalAudioSource> Create(
+ const PeerConnectionFactoryInterface::Options& options,
const MediaConstraintsInterface* constraints);
virtual SourceState state() const { return source_state_; }
@@ -58,7 +60,8 @@ class LocalAudioSource : public Notifier<AudioSourceInterface> {
}
private:
- void Initialize(const MediaConstraintsInterface* constraints);
+ void Initialize(const PeerConnectionFactoryInterface::Options& options,
+ const MediaConstraintsInterface* constraints);
cricket::AudioOptions options_;
SourceState source_state_;
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource_unittest.cc
index ae077878d41..f8880e0f691 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/localaudiosource_unittest.cc
@@ -39,6 +39,7 @@
using webrtc::LocalAudioSource;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaSourceInterface;
+using webrtc::PeerConnectionFactoryInterface;
TEST(LocalAudioSourceTest, SetValidOptions) {
webrtc::FakeConstraints constraints;
@@ -52,7 +53,8 @@ TEST(LocalAudioSourceTest, SetValidOptions) {
constraints.AddOptional(MediaConstraintsInterface::kHighpassFilter, true);
talk_base::scoped_refptr<LocalAudioSource> source =
- LocalAudioSource::Create(&constraints);
+ LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
+ &constraints);
bool value;
EXPECT_TRUE(source->options().echo_cancellation.Get(&value));
@@ -72,7 +74,8 @@ TEST(LocalAudioSourceTest, SetValidOptions) {
TEST(LocalAudioSourceTest, OptionNotSet) {
webrtc::FakeConstraints constraints;
talk_base::scoped_refptr<LocalAudioSource> source =
- LocalAudioSource::Create(&constraints);
+ LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
+ &constraints);
bool value;
EXPECT_FALSE(source->options().highpass_filter.Get(&value));
}
@@ -83,7 +86,8 @@ TEST(LocalAudioSourceTest, MandatoryOverridesOptional) {
constraints.AddOptional(MediaConstraintsInterface::kEchoCancellation, true);
talk_base::scoped_refptr<LocalAudioSource> source =
- LocalAudioSource::Create(&constraints);
+ LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
+ &constraints);
bool value;
EXPECT_TRUE(source->options().echo_cancellation.Get(&value));
@@ -96,7 +100,8 @@ TEST(LocalAudioSourceTest, InvalidOptional) {
constraints.AddOptional("invalidKey", false);
talk_base::scoped_refptr<LocalAudioSource> source =
- LocalAudioSource::Create(&constraints);
+ LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
+ &constraints);
EXPECT_EQ(MediaSourceInterface::kLive, source->state());
bool value;
@@ -110,7 +115,8 @@ TEST(LocalAudioSourceTest, InvalidMandatory) {
constraints.AddMandatory("invalidKey", false);
talk_base::scoped_refptr<LocalAudioSource> source =
- LocalAudioSource::Create(&constraints);
+ LocalAudioSource::Create(PeerConnectionFactoryInterface::Options(),
+ &constraints);
EXPECT_EQ(MediaSourceInterface::kEnded, source->state());
bool value;
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h b/chromium/third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h
index bc3872ce472..ba6b09be910 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h
@@ -81,6 +81,7 @@ class MediaConstraintsInterface {
static const char kNoiseSuppression[]; // googNoiseSuppression
static const char kHighpassFilter[]; // googHighpassFilter
static const char kTypingNoiseDetection[]; // googTypingNoiseDetection
+ static const char kAudioMirroring[]; // googAudioMirroring
// Google-specific constraint keys for a local video source
static const char kNoiseReduction[]; // googNoiseReduction
@@ -106,15 +107,21 @@ class MediaConstraintsInterface {
static const char kEnableDtlsSrtp[]; // Enable DTLS-SRTP
// Temporary pseudo-constraints used to enable DataChannels
static const char kEnableRtpDataChannels[]; // Enable RTP DataChannels
+ // TODO(perkj): Remove kEnableSctpDataChannels once Chrome use
+ // PeerConnectionFactory::SetOptions.
static const char kEnableSctpDataChannels[]; // Enable SCTP DataChannels
+ // Temporary pseudo-constraint for enabling DSCP through JS.
+ static const char kEnableDscp[];
// The prefix of internal-only constraints whose JS set values should be
// stripped by Chrome before passed down to Libjingle.
static const char kInternalConstraintPrefix[];
- // This constraint is for internal use only, representing the Chrome command
- // line flag. So it is prefixed with "internal" so JS values will be removed.
+ // These constraints are for internal use only, representing Chrome command
+ // line flags. So they are prefixed with "internal" so JS values will be
+ // removed.
// Used by a local audio source.
+ // TODO(perkj): Remove once Chrome use PeerConnectionFactory::SetOptions.
static const char kInternalAecDump[]; // internalAecDump
protected:
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.cc
index a23799f7369..7586938ce60 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.cc
@@ -37,6 +37,7 @@
#include "talk/app/webrtc/videosource.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/base/bytebuffer.h"
+#include "talk/base/stringutils.h"
#include "talk/media/sctp/sctpdataengine.h"
static const char kDefaultStreamLabel[] = "default";
@@ -189,7 +190,8 @@ MediaStreamSignaling::MediaStreamSignaling(
remote_streams_(StreamCollection::Create()),
remote_stream_factory_(new RemoteMediaStreamFactory(signaling_thread,
channel_manager)),
- last_allocated_sctp_id_(0) {
+ last_allocated_sctp_even_sid_(-2),
+ last_allocated_sctp_odd_sid_(-1) {
options_.has_video = false;
options_.has_audio = false;
}
@@ -203,51 +205,58 @@ void MediaStreamSignaling::TearDown() {
OnDataChannelClose();
}
-bool MediaStreamSignaling::IsSctpIdAvailable(int id) const {
- if (id < 0 || id > static_cast<int>(cricket::kMaxSctpSid))
+bool MediaStreamSignaling::IsSctpSidAvailable(int sid) const {
+ if (sid < 0 || sid > static_cast<int>(cricket::kMaxSctpSid))
return false;
- for (DataChannels::const_iterator iter = data_channels_.begin();
- iter != data_channels_.end();
+ for (SctpDataChannels::const_iterator iter = sctp_data_channels_.begin();
+ iter != sctp_data_channels_.end();
++iter) {
- if (iter->second->id() == id) {
+ if ((*iter)->id() == sid) {
return false;
}
}
return true;
}
-// Gets the first id that has not been taken by existing data
-// channels. Starting from 1.
-// Returns false if no id can be allocated.
-// TODO(jiayl): Update to some kind of even/odd random number selection when the
-// rules are fully standardized.
-bool MediaStreamSignaling::AllocateSctpId(int* id) {
+// Gets the first unused odd/even id based on the DTLS role. If |role| is
+// SSL_CLIENT, the allocated id starts from 0 and takes even numbers; otherwise,
+// the id starts from 1 and takes odd numbers. Returns false if no id can be
+// allocated.
+bool MediaStreamSignaling::AllocateSctpSid(talk_base::SSLRole role, int* sid) {
+ int& last_id = (role == talk_base::SSL_CLIENT) ?
+ last_allocated_sctp_even_sid_ : last_allocated_sctp_odd_sid_;
+
do {
- last_allocated_sctp_id_++;
- } while (last_allocated_sctp_id_ <= static_cast<int>(cricket::kMaxSctpSid) &&
- !IsSctpIdAvailable(last_allocated_sctp_id_));
+ last_id += 2;
+ } while (last_id <= static_cast<int>(cricket::kMaxSctpSid) &&
+ !IsSctpSidAvailable(last_id));
- if (last_allocated_sctp_id_ > static_cast<int>(cricket::kMaxSctpSid)) {
- last_allocated_sctp_id_ = cricket::kMaxSctpSid;
+ if (last_id > static_cast<int>(cricket::kMaxSctpSid)) {
return false;
}
- *id = last_allocated_sctp_id_;
+ *sid = last_id;
return true;
}
bool MediaStreamSignaling::HasDataChannels() const {
- return !data_channels_.empty();
+ return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
}
bool MediaStreamSignaling::AddDataChannel(DataChannel* data_channel) {
ASSERT(data_channel != NULL);
- if (data_channels_.find(data_channel->label()) != data_channels_.end()) {
- LOG(LS_ERROR) << "DataChannel with label " << data_channel->label()
- << " already exists.";
- return false;
+ if (data_channel->data_channel_type() == cricket::DCT_RTP) {
+ if (rtp_data_channels_.find(data_channel->label()) !=
+ rtp_data_channels_.end()) {
+ LOG(LS_ERROR) << "DataChannel with label " << data_channel->label()
+ << " already exists.";
+ return false;
+ }
+ rtp_data_channels_[data_channel->label()] = data_channel;
+ } else {
+ ASSERT(data_channel->data_channel_type() == cricket::DCT_SCTP);
+ sctp_data_channels_.push_back(data_channel);
}
- data_channels_[data_channel->label()] = data_channel;
return true;
}
@@ -259,18 +268,14 @@ bool MediaStreamSignaling::AddDataChannelFromOpenMessage(
<< "are not supported.";
return false;
}
-
- if (data_channels_.find(label) != data_channels_.end()) {
- LOG(LS_ERROR) << "DataChannel with label " << label
- << " already exists.";
- return false;
- }
scoped_refptr<DataChannel> channel(
data_channel_factory_->CreateDataChannel(label, &config));
- data_channels_[label] = channel;
+ if (!channel.get()) {
+ LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
+ return false;
+ }
+ sctp_data_channels_.push_back(channel);
stream_observer_->OnAddDataChannel(channel);
- // It's immediately ready to use.
- channel->OnChannelReady(true);
return true;
}
@@ -388,9 +393,8 @@ void MediaStreamSignaling::OnRemoteDescriptionChanged(
const cricket::DataContentDescription* data_desc =
static_cast<const cricket::DataContentDescription*>(
data_content->description);
- if (data_desc->protocol() == cricket::kMediaProtocolDtlsSctp) {
- UpdateRemoteSctpDataChannels();
- } else {
+ if (talk_base::starts_with(
+ data_desc->protocol().data(), cricket::kMediaProtocolRtpPrefix)) {
UpdateRemoteRtpDataChannels(data_desc->streams());
}
}
@@ -444,9 +448,8 @@ void MediaStreamSignaling::OnLocalDescriptionChanged(
const cricket::DataContentDescription* data_desc =
static_cast<const cricket::DataContentDescription*>(
data_content->description);
- if (data_desc->protocol() == cricket::kMediaProtocolDtlsSctp) {
- UpdateLocalSctpDataChannels();
- } else {
+ if (talk_base::starts_with(
+ data_desc->protocol().data(), cricket::kMediaProtocolRtpPrefix)) {
UpdateLocalRtpDataChannels(data_desc->streams());
}
}
@@ -461,10 +464,13 @@ void MediaStreamSignaling::OnVideoChannelClose() {
}
void MediaStreamSignaling::OnDataChannelClose() {
- DataChannels::iterator it = data_channels_.begin();
- for (; it != data_channels_.end(); ++it) {
- DataChannel* data_channel = it->second;
- data_channel->OnDataEngineClose();
+ RtpDataChannels::iterator it1 = rtp_data_channels_.begin();
+ for (; it1 != rtp_data_channels_.end(); ++it1) {
+ it1->second->OnDataEngineClose();
+ }
+ SctpDataChannels::iterator it2 = sctp_data_channels_.begin();
+ for (; it2 != sctp_data_channels_.end(); ++it2) {
+ (*it2)->OnDataEngineClose();
}
}
@@ -522,8 +528,8 @@ void MediaStreamSignaling::UpdateSessionOptions() {
}
// Check for data channels.
- DataChannels::const_iterator data_channel_it = data_channels_.begin();
- for (; data_channel_it != data_channels_.end(); ++data_channel_it) {
+ RtpDataChannels::const_iterator data_channel_it = rtp_data_channels_.begin();
+ for (; data_channel_it != rtp_data_channels_.end(); ++data_channel_it) {
const DataChannel* channel = data_channel_it->second;
if (channel->state() == DataChannel::kConnecting ||
channel->state() == DataChannel::kOpen) {
@@ -840,8 +846,9 @@ void MediaStreamSignaling::UpdateLocalRtpDataChannels(
// For MediaStreams, the sync_label is the MediaStream label and the
// track label is the same as |streamid|.
const std::string& channel_label = it->sync_label;
- DataChannels::iterator data_channel_it = data_channels_.find(channel_label);
- if (!VERIFY(data_channel_it != data_channels_.end())) {
+ RtpDataChannels::iterator data_channel_it =
+ rtp_data_channels_.find(channel_label);
+ if (!VERIFY(data_channel_it != rtp_data_channels_.end())) {
continue;
}
// Set the SSRC the data channel should use for sending.
@@ -863,9 +870,9 @@ void MediaStreamSignaling::UpdateRemoteRtpDataChannels(
// does not exist. Ex a=ssrc:444330170 mslabel:test1.
std::string label = it->sync_label.empty() ?
talk_base::ToString(it->first_ssrc()) : it->sync_label;
- DataChannels::iterator data_channel_it =
- data_channels_.find(label);
- if (data_channel_it == data_channels_.end()) {
+ RtpDataChannels::iterator data_channel_it =
+ rtp_data_channels_.find(label);
+ if (data_channel_it == rtp_data_channels_.end()) {
// This is a new data channel.
CreateRemoteDataChannel(label, it->first_ssrc());
} else {
@@ -879,8 +886,8 @@ void MediaStreamSignaling::UpdateRemoteRtpDataChannels(
void MediaStreamSignaling::UpdateClosingDataChannels(
const std::vector<std::string>& active_channels, bool is_local_update) {
- DataChannels::iterator it = data_channels_.begin();
- while (it != data_channels_.end()) {
+ RtpDataChannels::iterator it = rtp_data_channels_.begin();
+ while (it != rtp_data_channels_.end()) {
DataChannel* data_channel = it->second;
if (std::find(active_channels.begin(), active_channels.end(),
data_channel->label()) != active_channels.end()) {
@@ -894,8 +901,8 @@ void MediaStreamSignaling::UpdateClosingDataChannels(
data_channel->RemotePeerRequestClose();
if (data_channel->state() == DataChannel::kClosed) {
- data_channels_.erase(it);
- it = data_channels_.begin();
+ rtp_data_channels_.erase(it);
+ it = rtp_data_channels_.begin();
} else {
++it;
}
@@ -911,163 +918,34 @@ void MediaStreamSignaling::CreateRemoteDataChannel(const std::string& label,
}
scoped_refptr<DataChannel> channel(
data_channel_factory_->CreateDataChannel(label, NULL));
+ if (!channel.get()) {
+ LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
+ << "CreateDataChannel failed.";
+ return;
+ }
channel->SetReceiveSsrc(remote_ssrc);
stream_observer_->OnAddDataChannel(channel);
}
-
-// Format defined at
-// http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
-const uint8 DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03;
-
-enum DataChannelOpenMessageChannelType {
- DCOMCT_ORDERED_RELIABLE = 0x00,
- DCOMCT_ORDERED_PARTIAL_RTXS = 0x01,
- DCOMCT_ORDERED_PARTIAL_TIME = 0x02,
- DCOMCT_UNORDERED_RELIABLE = 0x80,
- DCOMCT_UNORDERED_PARTIAL_RTXS = 0x81,
- DCOMCT_UNORDERED_PARTIAL_TIME = 0x82,
-};
-
-bool MediaStreamSignaling::ParseDataChannelOpenMessage(
- const talk_base::Buffer& payload,
- std::string* label,
- DataChannelInit* config) {
- // Format defined at
- // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
-
- talk_base::ByteBuffer buffer(payload.data(), payload.length());
-
- uint8 message_type;
- if (!buffer.ReadUInt8(&message_type)) {
- LOG(LS_WARNING) << "Could not read OPEN message type.";
- return false;
- }
- if (message_type != DATA_CHANNEL_OPEN_MESSAGE_TYPE) {
- LOG(LS_WARNING) << "Data Channel OPEN message of unexpected type: "
- << message_type;
- return false;
- }
-
- uint8 channel_type;
- if (!buffer.ReadUInt8(&channel_type)) {
- LOG(LS_WARNING) << "Could not read OPEN message channel type.";
- return false;
- }
- uint16 priority;
- if (!buffer.ReadUInt16(&priority)) {
- LOG(LS_WARNING) << "Could not read OPEN message reliabilility prioirty.";
- return false;
- }
- uint32 reliability_param;
- if (!buffer.ReadUInt32(&reliability_param)) {
- LOG(LS_WARNING) << "Could not read OPEN message reliabilility param.";
- return false;
+void MediaStreamSignaling::OnDataTransportCreatedForSctp() {
+ SctpDataChannels::iterator it = sctp_data_channels_.begin();
+ for (; it != sctp_data_channels_.end(); ++it) {
+ (*it)->OnTransportChannelCreated();
}
- uint16 label_length;
- if (!buffer.ReadUInt16(&label_length)) {
- LOG(LS_WARNING) << "Could not read OPEN message label length.";
- return false;
- }
- uint16 protocol_length;
- if (!buffer.ReadUInt16(&protocol_length)) {
- LOG(LS_WARNING) << "Could not read OPEN message protocol length.";
- return false;
- }
- if (!buffer.ReadString(label, (size_t) label_length)) {
- LOG(LS_WARNING) << "Could not read OPEN message label";
- return false;
- }
- if (!buffer.ReadString(&config->protocol, protocol_length)) {
- LOG(LS_WARNING) << "Could not read OPEN message protocol.";
- return false;
- }
-
- config->ordered = true;
- switch (channel_type) {
- case DCOMCT_UNORDERED_RELIABLE:
- case DCOMCT_UNORDERED_PARTIAL_RTXS:
- case DCOMCT_UNORDERED_PARTIAL_TIME:
- config->ordered = false;
- }
-
- config->maxRetransmits = -1;
- config->maxRetransmitTime = -1;
- switch (channel_type) {
- case DCOMCT_ORDERED_PARTIAL_RTXS:
- case DCOMCT_UNORDERED_PARTIAL_RTXS:
- config->maxRetransmits = reliability_param;
-
- case DCOMCT_ORDERED_PARTIAL_TIME:
- case DCOMCT_UNORDERED_PARTIAL_TIME:
- config->maxRetransmitTime = reliability_param;
- }
-
- return true;
}
-bool MediaStreamSignaling::WriteDataChannelOpenMessage(
- const std::string& label,
- const DataChannelInit& config,
- talk_base::Buffer* payload) {
- // Format defined at
- // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
- // TODO(pthatcher)
-
- uint8 channel_type = 0;
- uint32 reliability_param = 0;
- uint16 priority = 0;
- if (config.ordered) {
- if (config.maxRetransmits > -1) {
- channel_type = DCOMCT_ORDERED_PARTIAL_RTXS;
- reliability_param = config.maxRetransmits;
- } else if (config.maxRetransmitTime > -1) {
- channel_type = DCOMCT_ORDERED_PARTIAL_TIME;
- reliability_param = config.maxRetransmitTime;
- } else {
- channel_type = DCOMCT_ORDERED_RELIABLE;
- }
- } else {
- if (config.maxRetransmits > -1) {
- channel_type = DCOMCT_UNORDERED_PARTIAL_RTXS;
- reliability_param = config.maxRetransmits;
- } else if (config.maxRetransmitTime > -1) {
- channel_type = DCOMCT_UNORDERED_PARTIAL_TIME;
- reliability_param = config.maxRetransmitTime;
- } else {
- channel_type = DCOMCT_UNORDERED_RELIABLE;
+void MediaStreamSignaling::OnDtlsRoleReadyForSctp(talk_base::SSLRole role) {
+ SctpDataChannels::iterator it = sctp_data_channels_.begin();
+ for (; it != sctp_data_channels_.end(); ++it) {
+ if ((*it)->id() < 0) {
+ int sid;
+ if (!AllocateSctpSid(role, &sid)) {
+ LOG(LS_ERROR) << "Failed to allocate SCTP sid.";
+ continue;
+ }
+ (*it)->SetSctpSid(sid);
}
}
-
- talk_base::ByteBuffer buffer(
- NULL, 20 + label.length() + config.protocol.length(),
- talk_base::ByteBuffer::ORDER_NETWORK);
- buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE);
- buffer.WriteUInt8(channel_type);
- buffer.WriteUInt16(priority);
- buffer.WriteUInt32(reliability_param);
- buffer.WriteUInt16(static_cast<uint16>(label.length()));
- buffer.WriteUInt16(static_cast<uint16>(config.protocol.length()));
- buffer.WriteString(label);
- buffer.WriteString(config.protocol);
- payload->SetData(buffer.Data(), buffer.Length());
- return true;
-}
-
-void MediaStreamSignaling::UpdateLocalSctpDataChannels() {
- DataChannels::iterator it = data_channels_.begin();
- for (; it != data_channels_.end(); ++it) {
- DataChannel* data_channel = it->second;
- data_channel->SetSendSsrc(data_channel->id());
- }
-}
-
-void MediaStreamSignaling::UpdateRemoteSctpDataChannels() {
- DataChannels::iterator it = data_channels_.begin();
- for (; it != data_channels_.end(); ++it) {
- DataChannel* data_channel = it->second;
- data_channel->SetReceiveSsrc(data_channel->id());
- }
}
} // namespace webrtc
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.h b/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.h
index f64bf978ffc..c600f066285 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling.h
@@ -174,11 +174,11 @@ class MediaStreamSignaling {
}
// Checks if |id| is available to be assigned to a new SCTP data channel.
- bool IsSctpIdAvailable(int id) const;
+ bool IsSctpSidAvailable(int sid) const;
// Gets the first available SCTP id that is not assigned to any existing
// data channels.
- bool AllocateSctpId(int* id);
+ bool AllocateSctpSid(talk_base::SSLRole role, int* sid);
// Adds |local_stream| to the collection of known MediaStreams that will be
// offered in a SessionDescription.
@@ -196,12 +196,6 @@ class MediaStreamSignaling {
// After we receive an OPEN message, create a data channel and add it.
bool AddDataChannelFromOpenMessage(
const std::string& label, const DataChannelInit& config);
- bool ParseDataChannelOpenMessage(
- const talk_base::Buffer& payload, std::string* label,
- DataChannelInit* config);
- bool WriteDataChannelOpenMessage(
- const std::string& label, const DataChannelInit& config,
- talk_base::Buffer* payload);
// Returns a MediaSessionOptions struct with options decided by |constraints|,
// the local MediaStreams and DataChannels.
@@ -255,8 +249,8 @@ class MediaStreamSignaling {
StreamCollectionInterface* remote_streams() const {
return remote_streams_.get();
}
- void UpdateLocalSctpDataChannels();
- void UpdateRemoteSctpDataChannels();
+ void OnDataTransportCreatedForSctp();
+ void OnDtlsRoleReadyForSctp(talk_base::SSLRole role);
private:
struct RemotePeerInfo {
@@ -386,10 +380,14 @@ class MediaStreamSignaling {
TrackInfos local_audio_tracks_;
TrackInfos local_video_tracks_;
- int last_allocated_sctp_id_;
+ int last_allocated_sctp_even_sid_;
+ int last_allocated_sctp_odd_sid_;
+
typedef std::map<std::string, talk_base::scoped_refptr<DataChannel> >
- DataChannels;
- DataChannels data_channels_;
+ RtpDataChannels;
+ typedef std::vector<talk_base::scoped_refptr<DataChannel> > SctpDataChannels;
+ RtpDataChannels rtp_data_channels_;
+ SctpDataChannels sctp_data_channels_;
};
} // namespace webrtc
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling_unittest.cc
index ea1336450da..5b88aa0c53f 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/mediastreamsignaling_unittest.cc
@@ -32,6 +32,7 @@
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/streamcollection.h"
#include "talk/app/webrtc/test/fakeconstraints.h"
+#include "talk/app/webrtc/test/fakedatachannelprovider.h"
#include "talk/app/webrtc/videotrack.h"
#include "talk/base/gunit.h"
#include "talk/base/scoped_ptr.h"
@@ -127,7 +128,7 @@ static const char kSdpStringWithMsidWithoutStreams[] =
"o=- 0 0 IN IP4 127.0.0.1\r\n"
"s=-\r\n"
"t=0 0\r\n"
- "a:msid-semantic: WMS\r\n"
+ "a=msid-semantic: WMS\r\n"
"m=audio 1 RTP/AVPF 103\r\n"
"a=mid:audio\r\n"
"a=rtpmap:103 ISAC/16000\r\n"
@@ -237,6 +238,23 @@ static bool CompareStreamCollections(StreamCollectionInterface* s1,
return true;
}
+class FakeDataChannelFactory : public webrtc::DataChannelFactory {
+ public:
+ FakeDataChannelFactory(FakeDataChannelProvider* provider,
+ cricket::DataChannelType dct)
+ : provider_(provider), type_(dct) {}
+
+ virtual talk_base::scoped_refptr<webrtc::DataChannel> CreateDataChannel(
+ const std::string& label,
+ const webrtc::DataChannelInit* config) {
+ return webrtc::DataChannel::Create(provider_, type_, label, config);
+ }
+
+ private:
+ FakeDataChannelProvider* provider_;
+ cricket::DataChannelType type_;
+};
+
class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver {
public:
MockSignalingObserver()
@@ -417,6 +435,7 @@ class MediaStreamSignalingTest: public testing::Test {
talk_base::Thread::Current()));
signaling_.reset(new MediaStreamSignalingForTest(observer_.get(),
channel_manager_.get()));
+ data_channel_provider_.reset(new FakeDataChannelProvider());
}
// Create a collection of streams.
@@ -507,12 +526,25 @@ class MediaStreamSignalingTest: public testing::Test {
ASSERT_TRUE(stream->AddTrack(video_track));
}
+ talk_base::scoped_refptr<webrtc::DataChannel> AddDataChannel(
+ cricket::DataChannelType type, const std::string& label, int id) {
+ webrtc::DataChannelInit config;
+ config.id = id;
+ talk_base::scoped_refptr<webrtc::DataChannel> data_channel(
+ webrtc::DataChannel::Create(
+ data_channel_provider_.get(), type, label, &config));
+ EXPECT_TRUE(data_channel.get() != NULL);
+ EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get()));
+ return data_channel;
+ }
+
// ChannelManager is used by VideoSource, so it should be released after all
// the video tracks. Put it as the first private variable should ensure that.
talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
talk_base::scoped_refptr<StreamCollection> reference_collection_;
talk_base::scoped_ptr<MockSignalingObserver> observer_;
talk_base::scoped_ptr<MediaStreamSignalingForTest> signaling_;
+ talk_base::scoped_ptr<FakeDataChannelProvider> data_channel_provider_;
};
// Test that a MediaSessionOptions is created for an offer if
@@ -1012,4 +1044,62 @@ TEST_F(MediaStreamSignalingTest, ChangeSsrcOnTrackInLocalSessionDescription) {
observer_->VerifyLocalVideoTrack(kStreams[0], kVideoTracks[0], 98);
}
+// Verifies that an even SCTP id is allocated for SSL_CLIENT and an odd id for
+// SSL_SERVER.
+TEST_F(MediaStreamSignalingTest, SctpIdAllocationBasedOnRole) {
+ int id;
+ ASSERT_TRUE(signaling_->AllocateSctpSid(talk_base::SSL_SERVER, &id));
+ EXPECT_EQ(1, id);
+ ASSERT_TRUE(signaling_->AllocateSctpSid(talk_base::SSL_CLIENT, &id));
+ EXPECT_EQ(0, id);
+ ASSERT_TRUE(signaling_->AllocateSctpSid(talk_base::SSL_SERVER, &id));
+ EXPECT_EQ(3, id);
+ ASSERT_TRUE(signaling_->AllocateSctpSid(talk_base::SSL_CLIENT, &id));
+ EXPECT_EQ(2, id);
+}
+
+// Verifies that SCTP ids of existing DataChannels are not reused.
+TEST_F(MediaStreamSignalingTest, SctpIdAllocationNoReuse) {
+ int old_id = 1;
+ AddDataChannel(cricket::DCT_SCTP, "a", old_id);
+ int new_id;
+ ASSERT_TRUE(signaling_->AllocateSctpSid(talk_base::SSL_SERVER, &new_id));
+ EXPECT_NE(old_id, new_id);
+
+ // Creates a DataChannel with id 0.
+ old_id = 0;
+ AddDataChannel(cricket::DCT_SCTP, "a", old_id);
+ ASSERT_TRUE(signaling_->AllocateSctpSid(talk_base::SSL_CLIENT, &new_id));
+ EXPECT_NE(old_id, new_id);
+}
+
+// Verifies that duplicated label is not allowed for RTP data channel.
+TEST_F(MediaStreamSignalingTest, RtpDuplicatedLabelNotAllowed) {
+ AddDataChannel(cricket::DCT_RTP, "a", -1);
+
+ webrtc::DataChannelInit config;
+ talk_base::scoped_refptr<webrtc::DataChannel> data_channel =
+ webrtc::DataChannel::Create(
+ data_channel_provider_.get(), cricket::DCT_RTP, "a", &config);
+ ASSERT_TRUE(data_channel.get() != NULL);
+ EXPECT_FALSE(signaling_->AddDataChannel(data_channel.get()));
+}
+
+// Verifies that duplicated label is allowed for SCTP data channel.
+TEST_F(MediaStreamSignalingTest, SctpDuplicatedLabelAllowed) {
+ AddDataChannel(cricket::DCT_SCTP, "a", -1);
+ AddDataChannel(cricket::DCT_SCTP, "a", -1);
+}
+
+// Verifies that duplicated label from OPEN message is allowed.
+TEST_F(MediaStreamSignalingTest, DuplicatedLabelFromOpenMessageAllowed) {
+ AddDataChannel(cricket::DCT_SCTP, "a", -1);
+
+ FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
+ cricket::DCT_SCTP);
+ signaling_->SetDataChannelFactory(&fake_factory);
+ webrtc::DataChannelInit config;
+ config.id = 0;
+ EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage("a", config));
+}
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/README b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/README
index 22789bb42c2..761338fc9c4 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/README
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/README
@@ -52,16 +52,16 @@ Example of building & using the unittest & app:
./out_sim/Debug/iossim out_sim/Debug/AppRTCDemo.app
- To build & sign the sample app for an iOS device:
- wrios && gclient runhooks && ninja -C out_ios/Debug AppRTCDemo
+ wrios && gclient runhooks && ninja -C out_ios/Debug-iphoneos AppRTCDemo
- To install the sample app on an iOS device:
- ideviceinstaller -i out_ios/Debug/AppRTCDemo.app
+ ideviceinstaller -i out_ios/Debug-iphoneos/AppRTCDemo.app
(if installing ideviceinstaller from brew, use --HEAD to get support
for .app directories)
- Alternatively, use iPhone Configuration Utility:
- Open "iPhone Configuration Utility" (http://support.apple.com/kb/DL1465)
- Click the "Add" icon (command-o)
- - Open the app under out_ios/Debug/AppRTCDemo (should be added to the Applications tab)
+ - Open the app under out_ios/Debug-iphoneos/AppRTCDemo (should be added to the Applications tab)
- Click the device's name in the left-hand panel and select the Applications tab
- Click Install on the AppRTCDemo line.
(If you have any problems deploying for the first time, check
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICECandidate.mm b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICECandidate.mm
index a6d79354915..07a29ee4565 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICECandidate.mm
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICECandidate.mm
@@ -31,11 +31,11 @@
#import "RTCICECandidate+internal.h"
-@implementation RTCICECandidate {
- NSString *_sdpMid;
- NSInteger _sdpMLineIndex;
- NSString *_sdp;
-}
+@implementation RTCICECandidate
+
+@synthesize sdpMid = _sdpMid;
+@synthesize sdpMLineIndex = _sdpMLineIndex;
+@synthesize sdp = _sdp;
- (id)initWithMid:(NSString *)sdpMid
index:(NSInteger)sdpMLineIndex
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICEServer.mm b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICEServer.mm
index cc5a84a41fb..f01ed32358e 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICEServer.mm
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCICEServer.mm
@@ -33,6 +33,10 @@
@implementation RTCICEServer
+@synthesize URI = _URI;
+@synthesize username = _username;
+@synthesize password = _password;
+
- (id)initWithURI:(NSURL *)URI
username:(NSString *)username
password:(NSString *)password {
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPair.m b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPair.m
index ee2ba1b1eef..31ac53ac105 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPair.m
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPair.m
@@ -29,6 +29,9 @@
@implementation RTCPair
+@synthesize key = _key;
+@synthesize value = _value;
+
- (id)initWithKey:(NSString *)key value:(NSString *)value {
if ((self = [super init])) {
_key = [key copy];
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnection.mm b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnection.mm
index 73dce36f0aa..ae9d1583dc7 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnection.mm
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnection.mm
@@ -117,9 +117,9 @@ class RTCSetSessionDescriptionObserver : public SetSessionDescriptionObserver {
}
- (BOOL)addICECandidate:(RTCICECandidate *)candidate {
- const webrtc::IceCandidateInterface *iceCandidate = candidate.candidate;
- return self.peerConnection->AddIceCandidate(iceCandidate);
- delete iceCandidate;
+ talk_base::scoped_ptr<const webrtc::IceCandidateInterface> iceCandidate(
+ candidate.candidate);
+ return self.peerConnection->AddIceCandidate(iceCandidate.get());
}
- (BOOL)addStream:(RTCMediaStream *)stream
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnectionFactory.mm b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnectionFactory.mm
index 1c6e7e7bc0e..325110fb36a 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnectionFactory.mm
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCPeerConnectionFactory.mm
@@ -64,6 +64,8 @@
@implementation RTCPeerConnectionFactory
+@synthesize nativeFactory = _nativeFactory;
+
+ (void)initializeSSL {
BOOL initialized = talk_base::InitializeSSL();
NSAssert(initialized, @"Failed to initialize SSL library");
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCSessionDescription.mm b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCSessionDescription.mm
index 4bd9b1447d5..dd2bbdc1410 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCSessionDescription.mm
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCSessionDescription.mm
@@ -31,10 +31,10 @@
#import "RTCSessionDescription+internal.h"
-@implementation RTCSessionDescription {
- NSString *_description;
- NSString *_type;
-}
+@implementation RTCSessionDescription
+
+@synthesize description = _description;
+@synthesize type = _type;
- (id)initWithType:(NSString *)type sdp:(NSString *)sdp {
if (!type || !sdp) {
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCVideoRenderer.mm b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCVideoRenderer.mm
index 3d3b10e2bed..23136152109 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCVideoRenderer.mm
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objc/RTCVideoRenderer.mm
@@ -40,6 +40,8 @@
@implementation RTCVideoRenderer
+@synthesize delegate = _delegate;
+
+ (RTCVideoRenderer *)videoRenderGUIWithFrame:(CGRect)frame {
// TODO (hughv): Implement.
return nil;
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/objctests/RTCSessionDescriptionSyncObserver.m b/chromium/third_party/libjingle/source/talk/app/webrtc/objctests/RTCSessionDescriptionSyncObserver.m
index c04c1c39ce6..85a4482b89e 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/objctests/RTCSessionDescriptionSyncObserver.m
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/objctests/RTCSessionDescriptionSyncObserver.m
@@ -44,6 +44,12 @@
@implementation RTCSessionDescriptionSyncObserver
+@synthesize error = _error;
+@synthesize sessionDescription = _sessionDescription;
+@synthesize success = _success;
+@synthesize condition = _condition;
+@synthesize signaled = _signaled;
+
- (id)init {
if ((self = [super init])) {
if (!(_condition = [[NSCondition alloc] init]))
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection.cc
index 9eaf915c395..e10e8fc953a 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection.cc
@@ -42,8 +42,6 @@ namespace {
using webrtc::PeerConnectionInterface;
-// The min number of tokens in the ice uri.
-static const size_t kMinIceUriTokens = 2;
// The min number of tokens must present in Turn host uri.
// e.g. user@turn.example.org
static const size_t kTurnHostTokensNum = 2;
@@ -103,6 +101,73 @@ struct GetStatsMsg : public talk_base::MessageData {
talk_base::scoped_refptr<webrtc::StatsObserver> observer;
};
+// |in_str| should be of format
+// stunURI = scheme ":" stun-host [ ":" stun-port ]
+// scheme = "stun" / "stuns"
+// stun-host = IP-literal / IPv4address / reg-name
+// stun-port = *DIGIT
+
+// draft-petithuguenin-behave-turn-uris-01
+// turnURI = scheme ":" turn-host [ ":" turn-port ]
+// turn-host = username@IP-literal / IPv4address / reg-name
+bool GetServiceTypeAndHostnameFromUri(const std::string& in_str,
+ ServiceType* service_type,
+ std::string* hostname) {
+ std::string::size_type colonpos = in_str.find(':');
+ if (colonpos == std::string::npos) {
+ return false;
+ }
+ std::string type = in_str.substr(0, colonpos);
+ for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) {
+ if (type.compare(kValidIceServiceTypes[i]) == 0) {
+ *service_type = static_cast<ServiceType>(i);
+ break;
+ }
+ }
+ if (*service_type == INVALID) {
+ return false;
+ }
+ *hostname = in_str.substr(colonpos + 1, std::string::npos);
+ return true;
+}
+
+// This method parses IPv6 and IPv4 literal strings, along with hostnames in
+// standard hostname:port format.
+// Consider following formats as correct.
+// |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port,
+// |hostname|, |[IPv6 address]|, |IPv4 address|
+bool ParseHostnameAndPortFromString(const std::string& in_str,
+ std::string* host,
+ int* port) {
+ if (in_str.at(0) == '[') {
+ std::string::size_type closebracket = in_str.rfind(']');
+ if (closebracket != std::string::npos) {
+ *host = in_str.substr(1, closebracket - 1);
+ std::string::size_type colonpos = in_str.find(':', closebracket);
+ if (std::string::npos != colonpos) {
+ if (!talk_base::FromString(
+ in_str.substr(closebracket + 2, std::string::npos), port)) {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ } else {
+ std::string::size_type colonpos = in_str.find(':');
+ if (std::string::npos != colonpos) {
+ *host = in_str.substr(0, colonpos);
+ if (!talk_base::FromString(
+ in_str.substr(colonpos + 1, std::string::npos), port)) {
+ return false;
+ }
+ } else {
+ *host = in_str;
+ }
+ }
+ return true;
+}
+
typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration
StunConfiguration;
typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration
@@ -125,8 +190,6 @@ bool ParseIceServers(const PeerConnectionInterface::IceServers& configuration,
// transport-ext = 1*unreserved
// turn-host = IP-literal / IPv4address / reg-name
// turn-port = *DIGIT
-
- // TODO(ronghuawu): Handle IPV6 address
for (size_t i = 0; i < configuration.size(); ++i) {
webrtc::PeerConnectionInterface::IceServer server = configuration[i];
if (server.uri.empty()) {
@@ -152,39 +215,41 @@ bool ParseIceServers(const PeerConnectionInterface::IceServers& configuration,
}
}
- tokens.clear();
- talk_base::tokenize(uri_without_transport, ':', &tokens);
- if (tokens.size() < kMinIceUriTokens) {
- LOG(WARNING) << "Invalid uri: " << server.uri;
- continue;
- }
+ std::string hoststring;
ServiceType service_type = INVALID;
- const std::string& type = tokens[0];
- for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) {
- if (type.compare(kValidIceServiceTypes[i]) == 0) {
- service_type = static_cast<ServiceType>(i);
- break;
- }
- }
- if (service_type == INVALID) {
- LOG(WARNING) << "Invalid service type: " << type;
+ if (!GetServiceTypeAndHostnameFromUri(uri_without_transport,
+ &service_type,
+ &hoststring)) {
+ LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: "
+ << uri_without_transport;
continue;
}
- std::string address = tokens[1];
+
+ // Let's break hostname.
+ tokens.clear();
+ talk_base::tokenize(hoststring, '@', &tokens);
+ hoststring = tokens[0];
+ if (tokens.size() == kTurnHostTokensNum) {
+ server.username = talk_base::s_url_decode(tokens[0]);
+ hoststring = tokens[1];
+ }
+
int port = kDefaultStunPort;
- if (service_type == TURNS)
+ if (service_type == TURNS) {
port = kDefaultStunTlsPort;
+ turn_transport_type = kTcpTransportType;
+ }
- if (tokens.size() > kMinIceUriTokens) {
- if (!talk_base::FromString(tokens[2], &port)) {
- LOG(LS_WARNING) << "Failed to parse port string: " << tokens[2];
- continue;
- }
+ std::string address;
+ if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) {
+ LOG(WARNING) << "Invalid Hostname format: " << uri_without_transport;
+ continue;
+ }
- if (port <= 0 || port > 0xffff) {
- LOG(WARNING) << "Invalid port: " << port;
- continue;
- }
+
+ if (port <= 0 || port > 0xffff) {
+ LOG(WARNING) << "Invalid port: " << port;
+ continue;
}
switch (service_type) {
@@ -315,7 +380,8 @@ bool PeerConnection::DoInitialize(
stats_.set_session(session_.get());
// Initialize the WebRtcSession. It creates transport channels etc.
- if (!session_->Initialize(constraints, dtls_identity_service))
+ if (!session_->Initialize(factory_->options(), constraints,
+ dtls_identity_service))
return false;
// Register PeerConnection as receiver of local ice candidates.
@@ -424,14 +490,6 @@ PeerConnection::CreateDataChannel(
if (!channel.get())
return NULL;
- // If we've already passed the underlying channel's setup phase, have the
- // MediaStreamSignaling update data channels manually.
- if (session_->data_channel() != NULL &&
- session_->data_channel_type() == cricket::DCT_SCTP) {
- mediastream_signaling_->UpdateLocalSctpDataChannels();
- mediastream_signaling_->UpdateRemoteSctpDataChannels();
- }
-
observer_->OnRenegotiationNeeded();
return DataChannelProxy::Create(signaling_thread(), channel.get());
@@ -543,6 +601,7 @@ void PeerConnection::OnSessionStateChange(cricket::BaseSession* /*session*/,
switch (state) {
case cricket::BaseSession::STATE_INIT:
ChangeSignalingState(PeerConnectionInterface::kStable);
+ break;
case cricket::BaseSession::STATE_SENTINITIATE:
ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer);
break;
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection_unittest.cc
index 522d528020c..76d9cd73cf0 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnection_unittest.cc
@@ -157,8 +157,8 @@ class PeerConnectionTestClientBase
// Disable highpass filter so that we can get all the test audio frames.
constraints.AddMandatory(
MediaConstraintsInterface::kHighpassFilter, false);
- talk_base::scoped_refptr<webrtc::LocalAudioSource> source =
- webrtc::LocalAudioSource::Create(&constraints);
+ talk_base::scoped_refptr<webrtc::AudioSourceInterface> source =
+ peer_connection_factory_->CreateAudioSource(&constraints);
// TODO(perkj): Test audio source when it is implemented. Currently audio
// always use the default input.
talk_base::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
@@ -633,12 +633,24 @@ class JsepTestClient
}
void SetReceiveAudioVideo(bool audio, bool video) {
- session_description_constraints_.SetMandatoryReceiveAudio(audio);
- session_description_constraints_.SetMandatoryReceiveVideo(video);
+ SetReceiveAudio(audio);
+ SetReceiveVideo(video);
ASSERT_EQ(audio, can_receive_audio());
ASSERT_EQ(video, can_receive_video());
}
+ void SetReceiveAudio(bool audio) {
+ if (audio && can_receive_audio())
+ return;
+ session_description_constraints_.SetMandatoryReceiveAudio(audio);
+ }
+
+ void SetReceiveVideo(bool video) {
+ if (video && can_receive_video())
+ return;
+ session_description_constraints_.SetMandatoryReceiveVideo(video);
+ }
+
void RemoveMsidFromReceivedSdp(bool remove) {
remove_msid_ = remove;
}
@@ -989,6 +1001,10 @@ class P2PTestConductor : public testing::Test {
};
typedef P2PTestConductor<JsepTestClient> JsepPeerConnectionP2PTestClient;
+// Disable for TSan v2, see
+// https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
+#if !defined(THREAD_SANITIZER)
+
// This test sets up a Jsep call between two parties and test Dtmf.
// TODO(holmer): Disabled due to sometimes crashing on buildbots.
// See issue webrtc/2378.
@@ -1047,6 +1063,20 @@ TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestDtls) {
VerifyRenderedSize(640, 480);
}
+// This test sets up a audio call initially and then upgrades to audio/video,
+// using DTLS.
+TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsRenegotiate) {
+ MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
+ FakeConstraints setup_constraints;
+ setup_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
+ true);
+ ASSERT_TRUE(CreateTestClients(&setup_constraints, &setup_constraints));
+ receiving_client()->SetReceiveAudioVideo(true, false);
+ LocalP2PTest();
+ receiving_client()->SetReceiveAudioVideo(true, true);
+ receiving_client()->Negotiate();
+}
+
// This test sets up a call between an endpoint configured to use either SDES or
// DTLS (the offerer) and just SDES (the answerer). As a result, SDES is used
// instead of DTLS.
@@ -1380,3 +1410,6 @@ TEST_F(JsepPeerConnectionP2PTestClient,
EnableVideoDecoderFactory();
LocalP2PTest();
}
+
+#endif // if !defined(THREAD_SANITIZER)
+
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionendtoend_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionendtoend_unittest.cc
new file mode 100644
index 00000000000..da3c03da4eb
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionendtoend_unittest.cc
@@ -0,0 +1,224 @@
+/*
+ * libjingle
+ * Copyright 2013, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/app/webrtc/test/peerconnectiontestwrapper.h"
+#include "talk/base/gunit.h"
+#include "talk/base/logging.h"
+#include "talk/base/ssladapter.h"
+#include "talk/base/sslstreamadapter.h"
+#include "talk/base/stringencode.h"
+#include "talk/base/stringutils.h"
+
+using webrtc::FakeConstraints;
+using webrtc::MediaConstraintsInterface;
+using webrtc::MediaStreamInterface;
+using webrtc::PeerConnectionInterface;
+
+namespace {
+
+const char kExternalGiceUfrag[] = "1234567890123456";
+const char kExternalGicePwd[] = "123456789012345678901234";
+
+void RemoveLinesFromSdp(const std::string& line_start,
+ std::string* sdp) {
+ const char kSdpLineEnd[] = "\r\n";
+ size_t ssrc_pos = 0;
+ while ((ssrc_pos = sdp->find(line_start, ssrc_pos)) !=
+ std::string::npos) {
+ size_t end_ssrc = sdp->find(kSdpLineEnd, ssrc_pos);
+ sdp->erase(ssrc_pos, end_ssrc - ssrc_pos + strlen(kSdpLineEnd));
+ }
+}
+
+// Add |newlines| to the |message| after |line|.
+void InjectAfter(const std::string& line,
+ const std::string& newlines,
+ std::string* message) {
+ const std::string tmp = line + newlines;
+ talk_base::replace_substrs(line.c_str(), line.length(),
+ tmp.c_str(), tmp.length(), message);
+}
+
+void Replace(const std::string& line,
+ const std::string& newlines,
+ std::string* message) {
+ talk_base::replace_substrs(line.c_str(), line.length(),
+ newlines.c_str(), newlines.length(), message);
+}
+
+void UseExternalSdes(std::string* sdp) {
+ // Remove current crypto specification.
+ RemoveLinesFromSdp("a=crypto", sdp);
+ RemoveLinesFromSdp("a=fingerprint", sdp);
+ // Add external crypto.
+ const char kAudioSdes[] =
+ "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
+ "inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR\r\n";
+ const char kVideoSdes[] =
+ "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
+ "inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj\r\n";
+ const char kDataSdes[] =
+ "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
+ "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj\r\n";
+ InjectAfter("a=mid:audio\r\n", kAudioSdes, sdp);
+ InjectAfter("a=mid:video\r\n", kVideoSdes, sdp);
+ InjectAfter("a=mid:data\r\n", kDataSdes, sdp);
+}
+
+void UseGice(std::string* sdp) {
+ InjectAfter("t=0 0\r\n", "a=ice-options:google-ice\r\n", sdp);
+
+ std::string ufragline = "a=ice-ufrag:";
+ std::string pwdline = "a=ice-pwd:";
+ RemoveLinesFromSdp(ufragline, sdp);
+ RemoveLinesFromSdp(pwdline, sdp);
+ ufragline.append(kExternalGiceUfrag);
+ ufragline.append("\r\n");
+ pwdline.append(kExternalGicePwd);
+ pwdline.append("\r\n");
+ const std::string ufrag_pwd = ufragline + pwdline;
+
+ InjectAfter("a=mid:audio\r\n", ufrag_pwd, sdp);
+ InjectAfter("a=mid:video\r\n", ufrag_pwd, sdp);
+ InjectAfter("a=mid:data\r\n", ufrag_pwd, sdp);
+}
+
+void RemoveBundle(std::string* sdp) {
+ RemoveLinesFromSdp("a=group:BUNDLE", sdp);
+}
+
+} // namespace
+
+class PeerConnectionEndToEndTest
+ : public sigslot::has_slots<>,
+ public testing::Test {
+ public:
+ PeerConnectionEndToEndTest()
+ : caller_(new talk_base::RefCountedObject<PeerConnectionTestWrapper>(
+ "caller")),
+ callee_(new talk_base::RefCountedObject<PeerConnectionTestWrapper>(
+ "callee")) {
+ talk_base::InitializeSSL(NULL);
+ }
+
+ void CreatePcs() {
+ CreatePcs(NULL);
+ }
+
+ void CreatePcs(const MediaConstraintsInterface* pc_constraints) {
+ EXPECT_TRUE(caller_->CreatePc(pc_constraints));
+ EXPECT_TRUE(callee_->CreatePc(pc_constraints));
+ PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get());
+ }
+
+ void GetAndAddUserMedia() {
+ FakeConstraints audio_constraints;
+ FakeConstraints video_constraints;
+ GetAndAddUserMedia(true, audio_constraints, true, video_constraints);
+ }
+
+ void GetAndAddUserMedia(bool audio, FakeConstraints audio_constraints,
+ bool video, FakeConstraints video_constraints) {
+ caller_->GetAndAddUserMedia(audio, audio_constraints,
+ video, video_constraints);
+ callee_->GetAndAddUserMedia(audio, audio_constraints,
+ video, video_constraints);
+ }
+
+ void Negotiate() {
+ caller_->CreateOffer(NULL);
+ }
+
+ void WaitForCallEstablished() {
+ caller_->WaitForCallEstablished();
+ callee_->WaitForCallEstablished();
+ }
+
+ void SetupLegacySdpConverter() {
+ caller_->SignalOnSdpCreated.connect(
+ this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
+ callee_->SignalOnSdpCreated.connect(
+ this, &PeerConnectionEndToEndTest::ConvertToLegacySdp);
+ }
+
+ void ConvertToLegacySdp(std::string* sdp) {
+ UseExternalSdes(sdp);
+ UseGice(sdp);
+ RemoveBundle(sdp);
+ LOG(LS_INFO) << "ConvertToLegacySdp: " << *sdp;
+ }
+
+ void SetupGiceConverter() {
+ caller_->SignalOnIceCandidateCreated.connect(
+ this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
+ callee_->SignalOnIceCandidateCreated.connect(
+ this, &PeerConnectionEndToEndTest::AddGiceCredsToCandidate);
+ }
+
+ void AddGiceCredsToCandidate(std::string* sdp) {
+ std::string gice_creds = " username ";
+ gice_creds.append(kExternalGiceUfrag);
+ gice_creds.append(" password ");
+ gice_creds.append(kExternalGicePwd);
+ gice_creds.append("\r\n");
+ Replace("\r\n", gice_creds, sdp);
+ LOG(LS_INFO) << "AddGiceCredsToCandidate: " << *sdp;
+ }
+
+ ~PeerConnectionEndToEndTest() {
+ talk_base::CleanupSSL();
+ }
+
+ protected:
+ talk_base::scoped_refptr<PeerConnectionTestWrapper> caller_;
+ talk_base::scoped_refptr<PeerConnectionTestWrapper> callee_;
+};
+
+// Disable for TSan v2, see
+// https://code.google.com/p/webrtc/issues/detail?id=1205 for details.
+#if !defined(THREAD_SANITIZER)
+
+TEST_F(PeerConnectionEndToEndTest, Call) {
+ CreatePcs();
+ GetAndAddUserMedia();
+ Negotiate();
+ WaitForCallEstablished();
+}
+
+TEST_F(PeerConnectionEndToEndTest, CallWithLegacySdp) {
+ FakeConstraints pc_constraints;
+ pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
+ false);
+ CreatePcs(&pc_constraints);
+ SetupLegacySdpConverter();
+ SetupGiceConverter();
+ GetAndAddUserMedia();
+ Negotiate();
+ WaitForCallEstablished();
+}
+
+#endif // if !defined(THREAD_SANITIZER)
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.cc
index 7d30fab8ec1..e8b8f63169c 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.cc
@@ -261,7 +261,7 @@ talk_base::scoped_refptr<AudioSourceInterface>
PeerConnectionFactory::CreateAudioSource_s(
const MediaConstraintsInterface* constraints) {
talk_base::scoped_refptr<LocalAudioSource> source(
- LocalAudioSource::Create(constraints));
+ LocalAudioSource::Create(options_, constraints));
return source;
}
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.h b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.h
index 7faf6094244..dff885dfe95 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.h
@@ -40,6 +40,10 @@ namespace webrtc {
class PeerConnectionFactory : public PeerConnectionFactoryInterface,
public talk_base::MessageHandler {
public:
+ virtual void SetOptions(const Options& options) {
+ options_ = options;
+ }
+
virtual talk_base::scoped_refptr<PeerConnectionInterface>
CreatePeerConnection(
const PeerConnectionInterface::IceServers& configuration,
@@ -77,6 +81,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface,
virtual cricket::ChannelManager* channel_manager();
virtual talk_base::Thread* signaling_thread();
virtual talk_base::Thread* worker_thread();
+ const Options& options() const { return options_; }
protected:
PeerConnectionFactory();
@@ -109,6 +114,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface,
bool owns_ptrs_;
talk_base::Thread* signaling_thread_;
talk_base::Thread* worker_thread_;
+ Options options_;
talk_base::scoped_refptr<PortAllocatorFactoryInterface> allocator_factory_;
// External Audio device used for audio playback.
talk_base::scoped_refptr<AudioDeviceModule> default_adm_;
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory_unittest.cc
index 182c01c46d5..4ab9e35c891 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory_unittest.cc
@@ -61,12 +61,25 @@ static const char kTurnIceServerWithTransport[] =
"turn:test@hello.com?transport=tcp";
static const char kSecureTurnIceServer[] =
"turns:test@hello.com?transport=tcp";
+static const char kSecureTurnIceServerWithoutTransportParam[] =
+ "turns:test_no_transport@hello.com:443";
+static const char kSecureTurnIceServerWithoutTransportAndPortParam[] =
+ "turns:test_no_transport@hello.com";
static const char kTurnIceServerWithNoUsernameInUri[] =
"turn:test.com:1234";
static const char kTurnPassword[] = "turnpassword";
static const int kDefaultStunPort = 3478;
static const int kDefaultStunTlsPort = 5349;
static const char kTurnUsername[] = "test";
+static const char kStunIceServerWithIPv4Address[] = "stun:1.2.3.4:1234";
+static const char kStunIceServerWithIPv4AddressWithoutPort[] = "stun:1.2.3.4";
+static const char kStunIceServerWithIPv6Address[] = "stun:[2401:fa00:4::]:1234";
+static const char kStunIceServerWithIPv6AddressWithoutPort[] =
+ "stun:[2401:fa00:4::]";
+static const char kStunIceServerWithInvalidIPv6Address[] =
+ "stun:[2401:fa00:4:::3478";
+static const char kTurnIceServerWithIPv6Address[] =
+ "turn:test@[2401:fa00:4::]:1234";
class NullPeerConnectionObserver : public PeerConnectionObserver {
public:
@@ -242,6 +255,12 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingSecureTurnUrl) {
ice_server.uri = kSecureTurnIceServer;
ice_server.password = kTurnPassword;
ice_servers.push_back(ice_server);
+ ice_server.uri = kSecureTurnIceServerWithoutTransportParam;
+ ice_server.password = kTurnPassword;
+ ice_servers.push_back(ice_server);
+ ice_server.uri = kSecureTurnIceServerWithoutTransportAndPortParam;
+ ice_server.password = kTurnPassword;
+ ice_servers.push_back(ice_server);
talk_base::scoped_refptr<PeerConnectionInterface> pc(
factory_->CreatePeerConnection(ice_servers, NULL,
allocator_factory_.get(),
@@ -249,9 +268,62 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingSecureTurnUrl) {
&observer_));
EXPECT_TRUE(pc.get() != NULL);
TurnConfigurations turn_configs;
- webrtc::PortAllocatorFactoryInterface::TurnConfiguration turn(
+ webrtc::PortAllocatorFactoryInterface::TurnConfiguration turn1(
"hello.com", kDefaultStunTlsPort, "test", kTurnPassword, "tcp", true);
- turn_configs.push_back(turn);
+ turn_configs.push_back(turn1);
+ // TURNS with transport param should be default to tcp.
+ webrtc::PortAllocatorFactoryInterface::TurnConfiguration turn2(
+ "hello.com", 443, "test_no_transport", kTurnPassword, "tcp", true);
+ turn_configs.push_back(turn2);
+ webrtc::PortAllocatorFactoryInterface::TurnConfiguration turn3(
+ "hello.com", kDefaultStunTlsPort, "test_no_transport",
+ kTurnPassword, "tcp", true);
+ turn_configs.push_back(turn3);
+ VerifyTurnConfigurations(turn_configs);
+}
+
+TEST_F(PeerConnectionFactoryTest, CreatePCUsingIPLiteralAddress) {
+ webrtc::PeerConnectionInterface::IceServers ice_servers;
+ webrtc::PeerConnectionInterface::IceServer ice_server;
+ ice_server.uri = kStunIceServerWithIPv4Address;
+ ice_servers.push_back(ice_server);
+ ice_server.uri = kStunIceServerWithIPv4AddressWithoutPort;
+ ice_servers.push_back(ice_server);
+ ice_server.uri = kStunIceServerWithIPv6Address;
+ ice_servers.push_back(ice_server);
+ ice_server.uri = kStunIceServerWithIPv6AddressWithoutPort;
+ ice_servers.push_back(ice_server);
+ ice_server.uri = kStunIceServerWithInvalidIPv6Address;
+ ice_servers.push_back(ice_server);
+ ice_server.uri = kTurnIceServerWithIPv6Address;
+ ice_server.password = kTurnPassword;
+ ice_servers.push_back(ice_server);
+ talk_base::scoped_refptr<PeerConnectionInterface> pc(
+ factory_->CreatePeerConnection(ice_servers, NULL,
+ allocator_factory_.get(),
+ NULL,
+ &observer_));
+ EXPECT_TRUE(pc.get() != NULL);
+ StunConfigurations stun_configs;
+ webrtc::PortAllocatorFactoryInterface::StunConfiguration stun1(
+ "1.2.3.4", 1234);
+ stun_configs.push_back(stun1);
+ webrtc::PortAllocatorFactoryInterface::StunConfiguration stun2(
+ "1.2.3.4", 3478);
+ stun_configs.push_back(stun2); // Default port
+ webrtc::PortAllocatorFactoryInterface::StunConfiguration stun3(
+ "2401:fa00:4::", 1234);
+ stun_configs.push_back(stun3);
+ webrtc::PortAllocatorFactoryInterface::StunConfiguration stun4(
+ "2401:fa00:4::", 3478);
+ stun_configs.push_back(stun4); // Default port
+ // Turn Address has the same host information as |stun3|.
+ stun_configs.push_back(stun3);
+ VerifyStunConfigurations(stun_configs);
+ TurnConfigurations turn_configs;
+ webrtc::PortAllocatorFactoryInterface::TurnConfiguration turn1(
+ "2401:fa00:4::", 1234, "test", kTurnPassword, "udp", false);
+ turn_configs.push_back(turn1);
VerifyTurnConfigurations(turn_configs);
}
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h
index bd86f3ed2f7..a127dad3a9d 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h
@@ -390,6 +390,19 @@ class DTLSIdentityServiceInterface {
// argument.
class PeerConnectionFactoryInterface : public talk_base::RefCountInterface {
public:
+ class Options {
+ public:
+ Options() :
+ enable_aec_dump(false),
+ disable_encryption(false),
+ disable_sctp_data_channels(false) {
+ }
+ bool enable_aec_dump;
+ bool disable_encryption;
+ bool disable_sctp_data_channels;
+ };
+
+ virtual void SetOptions(const Options& options) = 0;
virtual talk_base::scoped_refptr<PeerConnectionInterface>
CreatePeerConnection(
const PeerConnectionInterface::IceServers& configuration,
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface_unittest.cc
index 7aa06ef4248..093b8426856 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface_unittest.cc
@@ -37,6 +37,7 @@
#include "talk/app/webrtc/videosource.h"
#include "talk/base/gunit.h"
#include "talk/base/scoped_ptr.h"
+#include "talk/base/ssladapter.h"
#include "talk/base/sslstreamadapter.h"
#include "talk/base/stringutils.h"
#include "talk/base/thread.h"
@@ -227,12 +228,17 @@ class MockPeerConnectionObserver : public PeerConnectionObserver {
class PeerConnectionInterfaceTest : public testing::Test {
protected:
virtual void SetUp() {
+ talk_base::InitializeSSL(NULL);
pc_factory_ = webrtc::CreatePeerConnectionFactory(
talk_base::Thread::Current(), talk_base::Thread::Current(), NULL, NULL,
NULL);
ASSERT_TRUE(pc_factory_.get() != NULL);
}
+ virtual void TearDown() {
+ talk_base::CleanupSSL();
+ }
+
void CreatePeerConnection() {
CreatePeerConnection("", "", NULL);
}
@@ -981,31 +987,6 @@ TEST_F(PeerConnectionInterfaceTest,
EXPECT_TRUE(channel == NULL);
}
-// The test verifies that the first id not used by existing data channels is
-// assigned to a new data channel if no id is specified.
-TEST_F(PeerConnectionInterfaceTest, AssignSctpDataChannelId) {
- FakeConstraints constraints;
- constraints.SetAllowDtlsSctpDataChannels();
- CreatePeerConnection(&constraints);
-
- webrtc::DataChannelInit config;
-
- scoped_refptr<DataChannelInterface> channel =
- pc_->CreateDataChannel("1", &config);
- EXPECT_TRUE(channel != NULL);
- EXPECT_EQ(1, channel->id());
-
- config.id = 4;
- channel = pc_->CreateDataChannel("4", &config);
- EXPECT_TRUE(channel != NULL);
- EXPECT_EQ(config.id, channel->id());
-
- config.id = -1;
- channel = pc_->CreateDataChannel("2", &config);
- EXPECT_TRUE(channel != NULL);
- EXPECT_EQ(2, channel->id());
-}
-
// The test verifies that creating a SCTP data channel with an id already in use
// or out of range should fail.
TEST_F(PeerConnectionInterfaceTest,
@@ -1015,13 +996,13 @@ TEST_F(PeerConnectionInterfaceTest,
CreatePeerConnection(&constraints);
webrtc::DataChannelInit config;
+ scoped_refptr<DataChannelInterface> channel;
- scoped_refptr<DataChannelInterface> channel =
- pc_->CreateDataChannel("1", &config);
+ config.id = 1;
+ channel = pc_->CreateDataChannel("1", &config);
EXPECT_TRUE(channel != NULL);
EXPECT_EQ(1, channel->id());
- config.id = 1;
channel = pc_->CreateDataChannel("x", &config);
EXPECT_TRUE(channel == NULL);
@@ -1119,11 +1100,12 @@ TEST_F(PeerConnectionInterfaceTest, ReceiveFireFoxOffer) {
cricket::GetFirstVideoContent(pc_->local_description()->description());
ASSERT_TRUE(content != NULL);
EXPECT_FALSE(content->rejected);
-
+#ifdef HAVE_SCTP
content =
cricket::GetFirstDataContent(pc_->local_description()->description());
ASSERT_TRUE(content != NULL);
EXPECT_TRUE(content->rejected);
+#endif
}
// Test that we can create an audio only offer and receive an answer with a
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.cc
index 06c4b44b082..7e1e7eec662 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.cc
@@ -30,6 +30,8 @@
#include <utility>
#include <vector>
+#include "talk/base/base64.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/session/media/channel.h"
namespace webrtc {
@@ -45,13 +47,23 @@ const char StatsReport::kStatsValueNameAvailableReceiveBandwidth[] =
"googAvailableReceiveBandwidth";
const char StatsReport::kStatsValueNameAvailableSendBandwidth[] =
"googAvailableSendBandwidth";
+const char StatsReport::kStatsValueNameAvgEncodeMs[] = "googAvgEncodeMs";
const char StatsReport::kStatsValueNameBucketDelay[] = "googBucketDelay";
const char StatsReport::kStatsValueNameBytesReceived[] = "bytesReceived";
const char StatsReport::kStatsValueNameBytesSent[] = "bytesSent";
+const char StatsReport::kStatsValueNameBandwidthLimitedResolution[] =
+ "googBandwidthLimitedResolution";
+const char StatsReport::kStatsValueNameCaptureJitterMs[] =
+ "googCaptureJitterMs";
+const char StatsReport::kStatsValueNameCaptureQueueDelayMsPerS[] =
+ "googCaptureQueueDelayMsPerS";
const char StatsReport::kStatsValueNameChannelId[] = "googChannelId";
const char StatsReport::kStatsValueNameCodecName[] = "googCodecName";
const char StatsReport::kStatsValueNameComponent[] = "googComponent";
const char StatsReport::kStatsValueNameContentName[] = "googContentName";
+const char StatsReport::kStatsValueNameCpuLimitedResolution[] =
+ "googCpuLimitedResolution";
+const char StatsReport::kStatsValueNameDer[] = "googDerBase64";
// Echo metrics from the audio processing module.
const char StatsReport::kStatsValueNameEchoCancellationQualityMin[] =
"googEchoCancellationQualityMin";
@@ -64,6 +76,11 @@ const char StatsReport::kStatsValueNameEchoReturnLoss[] =
const char StatsReport::kStatsValueNameEchoReturnLossEnhancement[] =
"googEchoCancellationReturnLossEnhancement";
+const char StatsReport::kStatsValueNameEncodeUsagePercent[] =
+ "googEncodeUsagePercent";
+const char StatsReport::kStatsValueNameFingerprint[] = "googFingerprint";
+const char StatsReport::kStatsValueNameFingerprintAlgorithm[] =
+ "googFingerprintAlgorithm";
const char StatsReport::kStatsValueNameFirsReceived[] = "googFirsReceived";
const char StatsReport::kStatsValueNameFirsSent[] = "googFirsSent";
const char StatsReport::kStatsValueNameFrameHeightReceived[] =
@@ -76,14 +93,28 @@ const char StatsReport::kStatsValueNameFrameRateDecoded[] =
"googFrameRateDecoded";
const char StatsReport::kStatsValueNameFrameRateOutput[] =
"googFrameRateOutput";
+const char StatsReport::kStatsValueNameDecodeMs[] = "googDecodeMs";
+const char StatsReport::kStatsValueNameMaxDecodeMs[] = "googMaxDecodeMs";
+const char StatsReport::kStatsValueNameCurrentDelayMs[] = "googCurrentDelayMs";
+const char StatsReport::kStatsValueNameTargetDelayMs[] = "googTargetDelayMs";
+const char StatsReport::kStatsValueNameJitterBufferMs[] = "googJitterBufferMs";
+const char StatsReport::kStatsValueNameMinPlayoutDelayMs[] =
+ "googMinPlayoutDelayMs";
+const char StatsReport::kStatsValueNameRenderDelayMs[] = "googRenderDelayMs";
+
const char StatsReport::kStatsValueNameFrameRateInput[] = "googFrameRateInput";
const char StatsReport::kStatsValueNameFrameRateSent[] = "googFrameRateSent";
const char StatsReport::kStatsValueNameFrameWidthReceived[] =
"googFrameWidthReceived";
const char StatsReport::kStatsValueNameFrameWidthSent[] = "googFrameWidthSent";
const char StatsReport::kStatsValueNameInitiator[] = "googInitiator";
+const char StatsReport::kStatsValueNameIssuerId[] = "googIssuerId";
const char StatsReport::kStatsValueNameJitterReceived[] = "googJitterReceived";
const char StatsReport::kStatsValueNameLocalAddress[] = "googLocalAddress";
+const char StatsReport::kStatsValueNameLocalCandidateType[] =
+ "googLocalCandidateType";
+const char StatsReport::kStatsValueNameLocalCertificateId[] =
+ "googLocalCertificateId";
const char StatsReport::kStatsValueNameNacksReceived[] = "googNacksReceived";
const char StatsReport::kStatsValueNameNacksSent[] = "googNacksSent";
const char StatsReport::kStatsValueNamePacketsReceived[] = "packetsReceived";
@@ -91,6 +122,10 @@ const char StatsReport::kStatsValueNamePacketsSent[] = "packetsSent";
const char StatsReport::kStatsValueNamePacketsLost[] = "packetsLost";
const char StatsReport::kStatsValueNameReadable[] = "googReadable";
const char StatsReport::kStatsValueNameRemoteAddress[] = "googRemoteAddress";
+const char StatsReport::kStatsValueNameRemoteCandidateType[] =
+ "googRemoteCandidateType";
+const char StatsReport::kStatsValueNameRemoteCertificateId[] =
+ "googRemoteCertificateId";
const char StatsReport::kStatsValueNameRetransmitBitrate[] =
"googRetransmitBitrate";
const char StatsReport::kStatsValueNameRtt[] = "googRtt";
@@ -104,16 +139,20 @@ const char StatsReport::kStatsValueNameTransportType[] = "googTransportType";
const char StatsReport::kStatsValueNameTrackId[] = "googTrackId";
const char StatsReport::kStatsValueNameTypingNoiseState[] =
"googTypingNoiseState";
+const char StatsReport::kStatsValueNameViewLimitedResolution[] =
+ "googViewLimitedResolution";
const char StatsReport::kStatsValueNameWritable[] = "googWritable";
const char StatsReport::kStatsReportTypeSession[] = "googLibjingleSession";
const char StatsReport::kStatsReportTypeBwe[] = "VideoBwe";
+const char StatsReport::kStatsReportTypeRemoteSsrc[] = "remoteSsrc";
const char StatsReport::kStatsReportTypeSsrc[] = "ssrc";
const char StatsReport::kStatsReportTypeTrack[] = "googTrack";
const char StatsReport::kStatsReportTypeIceCandidate[] = "iceCandidate";
const char StatsReport::kStatsReportTypeTransport[] = "googTransport";
const char StatsReport::kStatsReportTypeComponent[] = "googComponent";
const char StatsReport::kStatsReportTypeCandidatePair[] = "googCandidatePair";
+const char StatsReport::kStatsReportTypeCertificate[] = "googCertificate";
const char StatsReport::kStatsReportVideoBweId[] = "bweforvideo";
@@ -229,6 +268,21 @@ void ExtractStats(const cricket::VideoReceiverInfo& info, StatsReport* report) {
info.framerate_decoded);
report->AddValue(StatsReport::kStatsValueNameFrameRateOutput,
info.framerate_output);
+
+ report->AddValue(StatsReport::kStatsValueNameDecodeMs,
+ info.decode_ms);
+ report->AddValue(StatsReport::kStatsValueNameMaxDecodeMs,
+ info.max_decode_ms);
+ report->AddValue(StatsReport::kStatsValueNameCurrentDelayMs,
+ info.current_delay_ms);
+ report->AddValue(StatsReport::kStatsValueNameTargetDelayMs,
+ info.target_delay_ms);
+ report->AddValue(StatsReport::kStatsValueNameJitterBufferMs,
+ info.jitter_buffer_ms);
+ report->AddValue(StatsReport::kStatsValueNameMinPlayoutDelayMs,
+ info.min_playout_delay_ms);
+ report->AddValue(StatsReport::kStatsValueNameRenderDelayMs,
+ info.render_delay_ms);
}
void ExtractStats(const cricket::VideoSenderInfo& info, StatsReport* report) {
@@ -251,6 +305,19 @@ void ExtractStats(const cricket::VideoSenderInfo& info, StatsReport* report) {
info.framerate_sent);
report->AddValue(StatsReport::kStatsValueNameRtt, info.rtt_ms);
report->AddValue(StatsReport::kStatsValueNameCodecName, info.codec_name);
+ report->AddBoolean(StatsReport::kStatsValueNameCpuLimitedResolution,
+ (info.adapt_reason & 0x1) > 0);
+ report->AddBoolean(StatsReport::kStatsValueNameBandwidthLimitedResolution,
+ (info.adapt_reason & 0x2) > 0);
+ report->AddBoolean(StatsReport::kStatsValueNameViewLimitedResolution,
+ (info.adapt_reason & 0x4) > 0);
+ report->AddValue(StatsReport::kStatsValueNameAvgEncodeMs, info.avg_encode_ms);
+ report->AddValue(StatsReport::kStatsValueNameCaptureJitterMs,
+ info.capture_jitter_ms);
+ report->AddValue(StatsReport::kStatsValueNameCaptureQueueDelayMsPerS,
+ info.capture_queue_delay_ms_per_s);
+ report->AddValue(StatsReport::kStatsValueNameEncodeUsagePercent,
+ info.encode_usage_percent);
}
void ExtractStats(const cricket::BandwidthEstimationInfo& info,
@@ -281,24 +348,22 @@ void ExtractStats(const cricket::BandwidthEstimationInfo& info,
info.bucket_delay);
}
-uint32 ExtractSsrc(const cricket::VoiceReceiverInfo& info) {
- return info.ssrc;
-}
-
-uint32 ExtractSsrc(const cricket::VoiceSenderInfo& info) {
- return info.ssrc;
+void ExtractRemoteStats(const cricket::MediaSenderInfo& info,
+ StatsReport* report) {
+ report->timestamp = info.remote_stats[0].timestamp;
+ // TODO(hta): Extract some stats here.
}
-uint32 ExtractSsrc(const cricket::VideoReceiverInfo& info) {
- return info.ssrcs[0];
-}
-
-uint32 ExtractSsrc(const cricket::VideoSenderInfo& info) {
- return info.ssrcs[0];
+void ExtractRemoteStats(const cricket::MediaReceiverInfo& info,
+ StatsReport* report) {
+ report->timestamp = info.remote_stats[0].timestamp;
+ // TODO(hta): Extract some stats here.
}
// Template to extract stats from a data vector.
-// ExtractSsrc and ExtractStats must be defined and overloaded for each type.
+// In order to use the template, the functions that are called from it,
+// ExtractStats and ExtractRemoteStats, must be defined and overloaded
+// for each type.
template<typename T>
void ExtractStatsFromList(const std::vector<T>& data,
const std::string& transport_id,
@@ -306,12 +371,21 @@ void ExtractStatsFromList(const std::vector<T>& data,
typename std::vector<T>::const_iterator it = data.begin();
for (; it != data.end(); ++it) {
std::string id;
- uint32 ssrc = ExtractSsrc(*it);
- StatsReport* report = collector->PrepareReport(ssrc, transport_id);
+ uint32 ssrc = it->ssrc();
+ // Each object can result in 2 objects, a local and a remote object.
+ // TODO(hta): Handle the case of multiple SSRCs per object.
+ StatsReport* report = collector->PrepareLocalReport(ssrc, transport_id);
if (!report) {
continue;
}
ExtractStats(*it, report);
+ if (it->remote_stats.size() > 0) {
+ report = collector->PrepareRemoteReport(ssrc, transport_id);
+ if (!report) {
+ continue;
+ }
+ ExtractRemoteStats(*it, report);
+ }
}
};
@@ -394,8 +468,9 @@ void StatsCollector::UpdateStats() {
}
}
-StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
- const std::string& transport_id) {
+StatsReport* StatsCollector::PrepareLocalReport(
+ uint32 ssrc,
+ const std::string& transport_id) {
std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
StatsMap::iterator it = reports_.find(StatsId(
StatsReport::kStatsReportTypeSsrc, ssrc_id));
@@ -415,10 +490,8 @@ StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
&track_id);
}
- StatsReport* report = &reports_[
- StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id)];
- report->id = StatsId(StatsReport::kStatsReportTypeSsrc, ssrc_id);
- report->type = StatsReport::kStatsReportTypeSsrc;
+ StatsReport* report = GetOrCreateReport(StatsReport::kStatsReportTypeSsrc,
+ ssrc_id);
// Clear out stats from previous GatherStats calls if any.
if (report->timestamp != stats_gathering_started_) {
@@ -434,6 +507,103 @@ StatsReport* StatsCollector::PrepareReport(uint32 ssrc,
return report;
}
+StatsReport* StatsCollector::PrepareRemoteReport(
+ uint32 ssrc,
+ const std::string& transport_id) {
+ std::string ssrc_id = talk_base::ToString<uint32>(ssrc);
+ StatsMap::iterator it = reports_.find(StatsId(
+ StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id));
+
+ std::string track_id;
+ if (it == reports_.end()) {
+ if (!session()->GetTrackIdBySsrc(ssrc, &track_id)) {
+ LOG(LS_WARNING) << "The SSRC " << ssrc
+ << " is not associated with a track";
+ return NULL;
+ }
+ } else {
+ // Keeps the old track id since we want to report the stats for inactive
+ // tracks.
+ ExtractValueFromReport(it->second,
+ StatsReport::kStatsValueNameTrackId,
+ &track_id);
+ }
+
+ StatsReport* report = GetOrCreateReport(
+ StatsReport::kStatsReportTypeRemoteSsrc, ssrc_id);
+
+ // Clear out stats from previous GatherStats calls if any.
+ // The timestamp will be added later. Zero it for debugging.
+ report->values.clear();
+ report->timestamp = 0;
+
+ report->AddValue(StatsReport::kStatsValueNameSsrc, ssrc_id);
+ report->AddValue(StatsReport::kStatsValueNameTrackId, track_id);
+ // Add the mapping of SSRC to transport.
+ report->AddValue(StatsReport::kStatsValueNameTransportId,
+ transport_id);
+ return report;
+}
+
+std::string StatsCollector::AddOneCertificateReport(
+ const talk_base::SSLCertificate* cert, const std::string& issuer_id) {
+ // TODO(bemasc): Move this computation to a helper class that caches these
+ // values to reduce CPU use in GetStats. This will require adding a fast
+ // SSLCertificate::Equals() method to detect certificate changes.
+
+ std::string digest_algorithm;
+ if (!cert->GetSignatureDigestAlgorithm(&digest_algorithm))
+ return std::string();
+
+ talk_base::scoped_ptr<talk_base::SSLFingerprint> ssl_fingerprint(
+ talk_base::SSLFingerprint::Create(digest_algorithm, cert));
+ std::string fingerprint = ssl_fingerprint->GetRfc4572Fingerprint();
+
+ talk_base::Buffer der_buffer;
+ cert->ToDER(&der_buffer);
+ std::string der_base64;
+ talk_base::Base64::EncodeFromArray(
+ der_buffer.data(), der_buffer.length(), &der_base64);
+
+ StatsReport report;
+ report.type = StatsReport::kStatsReportTypeCertificate;
+ report.id = StatsId(report.type, fingerprint);
+ report.timestamp = stats_gathering_started_;
+ report.AddValue(StatsReport::kStatsValueNameFingerprint, fingerprint);
+ report.AddValue(StatsReport::kStatsValueNameFingerprintAlgorithm,
+ digest_algorithm);
+ report.AddValue(StatsReport::kStatsValueNameDer, der_base64);
+ if (!issuer_id.empty())
+ report.AddValue(StatsReport::kStatsValueNameIssuerId, issuer_id);
+ reports_[report.id] = report;
+ return report.id;
+}
+
+std::string StatsCollector::AddCertificateReports(
+ const talk_base::SSLCertificate* cert) {
+ // Produces a chain of StatsReports representing this certificate and the rest
+ // of its chain, and adds those reports to |reports_|. The return value is
+ // the id of the leaf report. The provided cert must be non-null, so at least
+ // one report will always be provided and the returned string will never be
+ // empty.
+ ASSERT(cert != NULL);
+
+ std::string issuer_id;
+ talk_base::scoped_ptr<talk_base::SSLCertChain> chain;
+ if (cert->GetChain(chain.accept())) {
+ // This loop runs in reverse, i.e. from root to leaf, so that each
+ // certificate's issuer's report ID is known before the child certificate's
+ // report is generated. The root certificate does not have an issuer ID
+ // value.
+ for (ptrdiff_t i = chain->GetSize() - 1; i >= 0; --i) {
+ const talk_base::SSLCertificate& cert_i = chain->Get(i);
+ issuer_id = AddOneCertificateReport(&cert_i, issuer_id);
+ }
+ }
+ // Add the leaf certificate.
+ return AddOneCertificateReport(cert, issuer_id);
+}
+
void StatsCollector::ExtractSessionInfo() {
// Extract information from the base session.
StatsReport report;
@@ -454,6 +624,22 @@ void StatsCollector::ExtractSessionInfo() {
for (cricket::TransportStatsMap::iterator transport_iter
= stats.transport_stats.begin();
transport_iter != stats.transport_stats.end(); ++transport_iter) {
+ // Attempt to get a copy of the certificates from the transport and
+ // expose them in stats reports. All channels in a transport share the
+ // same local and remote certificates.
+ std::string local_cert_report_id, remote_cert_report_id;
+ cricket::Transport* transport =
+ session_->GetTransport(transport_iter->second.content_name);
+ if (transport) {
+ talk_base::scoped_ptr<talk_base::SSLIdentity> identity;
+ if (transport->GetIdentity(identity.accept()))
+ local_cert_report_id = AddCertificateReports(
+ &(identity->certificate()));
+
+ talk_base::scoped_ptr<talk_base::SSLCertificate> cert;
+ if (transport->GetRemoteCertificate(cert.accept()))
+ remote_cert_report_id = AddCertificateReports(cert.get());
+ }
for (cricket::TransportChannelStatsList::iterator channel_iter
= transport_iter->second.channel_stats.begin();
channel_iter != transport_iter->second.channel_stats.end();
@@ -467,6 +653,14 @@ void StatsCollector::ExtractSessionInfo() {
channel_report.timestamp = stats_gathering_started_;
channel_report.AddValue(StatsReport::kStatsValueNameComponent,
channel_iter->component);
+ if (!local_cert_report_id.empty())
+ channel_report.AddValue(
+ StatsReport::kStatsValueNameLocalCertificateId,
+ local_cert_report_id);
+ if (!remote_cert_report_id.empty())
+ channel_report.AddValue(
+ StatsReport::kStatsValueNameRemoteCertificateId,
+ remote_cert_report_id);
reports_[channel_report.id] = channel_report;
for (size_t i = 0;
i < channel_iter->connection_infos.size();
@@ -497,6 +691,13 @@ void StatsCollector::ExtractSessionInfo() {
info.local_candidate.address().ToString());
report.AddValue(StatsReport::kStatsValueNameRemoteAddress,
info.remote_candidate.address().ToString());
+ report.AddValue(StatsReport::kStatsValueNameRtt, info.rtt);
+ report.AddValue(StatsReport::kStatsValueNameTransportType,
+ info.local_candidate.protocol());
+ report.AddValue(StatsReport::kStatsValueNameLocalCandidateType,
+ info.local_candidate.type());
+ report.AddValue(StatsReport::kStatsValueNameRemoteCandidateType,
+ info.remote_candidate.type());
reports_[report.id] = report;
}
}
@@ -573,4 +774,19 @@ bool StatsCollector::GetTransportIdFromProxy(const std::string& proxy,
return true;
}
+StatsReport* StatsCollector::GetOrCreateReport(const std::string& type,
+ const std::string& id) {
+ std::string statsid = StatsId(type, id);
+ StatsReport* report = NULL;
+ std::map<std::string, StatsReport>::iterator it = reports_.find(statsid);
+ if (it == reports_.end()) {
+ report = &reports_[statsid]; // Create new element.
+ report->id = statsid;
+ report->type = type;
+ } else {
+ report = &(it->second);
+ }
+ return report;
+}
+
} // namespace webrtc
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.h b/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.h
index 03a32c49348..01da059b510 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector.h
@@ -65,9 +65,11 @@ class StatsCollector {
// |reports|.
bool GetStats(MediaStreamTrackInterface* track, StatsReports* reports);
- WebRtcSession* session() { return session_; }
- // Prepare an SSRC report for the given ssrc. Used internally.
- StatsReport* PrepareReport(uint32 ssrc, const std::string& transport);
+ // Prepare an SSRC report for the given ssrc. Used internally
+ // in the ExtractStatsFromList template.
+ StatsReport* PrepareLocalReport(uint32 ssrc, const std::string& transport);
+ // Prepare an SSRC report for the given remote ssrc. Used internally.
+ StatsReport* PrepareRemoteReport(uint32 ssrc, const std::string& transport);
// Extracts the ID of a Transport belonging to an SSRC. Used internally.
bool GetTransportIdFromProxy(const std::string& proxy,
std::string* transport_id);
@@ -75,14 +77,25 @@ class StatsCollector {
private:
bool CopySelectedReports(const std::string& selector, StatsReports* reports);
+ // Helper method for AddCertificateReports.
+ std::string AddOneCertificateReport(
+ const talk_base::SSLCertificate* cert, const std::string& issuer_id);
+
+ // Adds a report for this certificate and every certificate in its chain, and
+ // returns the leaf certificate's report's ID.
+ std::string AddCertificateReports(const talk_base::SSLCertificate* cert);
+
void ExtractSessionInfo();
void ExtractVoiceInfo();
void ExtractVideoInfo();
double GetTimeNow();
void BuildSsrcToTransportId();
+ WebRtcSession* session() { return session_; }
+ webrtc::StatsReport* GetOrCreateReport(const std::string& type,
+ const std::string& id);
// A map from the report id to the report.
- std::map<std::string, webrtc::StatsReport> reports_;
+ std::map<std::string, StatsReport> reports_;
// Raw pointer to the session the statistics are gathered from.
WebRtcSession* session_;
double stats_gathering_started_;
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc
index cce1645bcab..1adcb0e20aa 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc
@@ -30,6 +30,8 @@
#include "talk/app/webrtc/mediastream.h"
#include "talk/app/webrtc/videotrack.h"
+#include "talk/base/base64.h"
+#include "talk/base/fakesslidentity.h"
#include "talk/base/gunit.h"
#include "talk/media/base/fakemediaengine.h"
#include "talk/media/devices/fakedevicemanager.h"
@@ -56,15 +58,20 @@ namespace {
const char kNotFound[] = "NOT FOUND";
const char kNoReports[] = "NO REPORTS";
+// Constant names for track identification.
+const char kTrackId[] = "somename";
+const uint32 kSsrcOfTrack = 1234;
+
class MockWebRtcSession : public webrtc::WebRtcSession {
public:
explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
: WebRtcSession(channel_manager, talk_base::Thread::Current(),
- NULL, NULL, NULL) {
+ talk_base::Thread::Current(), NULL, NULL) {
}
MOCK_METHOD0(video_channel, cricket::VideoChannel*());
MOCK_METHOD2(GetTrackIdBySsrc, bool(uint32, std::string*));
MOCK_METHOD1(GetStats, bool(cricket::SessionStats*));
+ MOCK_METHOD1(GetTransport, cricket::Transport*(const std::string&));
};
class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
@@ -76,8 +83,21 @@ class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
MOCK_METHOD1(GetStats, bool(cricket::VideoMediaInfo*));
};
+bool GetValue(const webrtc::StatsReport* report,
+ const std::string& name,
+ std::string* value) {
+ webrtc::StatsReport::Values::const_iterator it = report->values.begin();
+ for (; it != report->values.end(); ++it) {
+ if (it->name == name) {
+ *value = it->value;
+ return true;
+ }
+ }
+ return false;
+}
+
std::string ExtractStatsValue(const std::string& type,
- webrtc::StatsReports reports,
+ const webrtc::StatsReports& reports,
const std::string name) {
if (reports.empty()) {
return kNoReports;
@@ -85,12 +105,9 @@ std::string ExtractStatsValue(const std::string& type,
for (size_t i = 0; i < reports.size(); ++i) {
if (reports[i].type != type)
continue;
- webrtc::StatsReport::Values::const_iterator it =
- reports[i].values.begin();
- for (; it != reports[i].values.end(); ++it) {
- if (it->name == name) {
- return it->value;
- }
+ std::string ret;
+ if (GetValue(&reports[i], name, &ret)) {
+ return ret;
}
}
@@ -99,9 +116,8 @@ std::string ExtractStatsValue(const std::string& type,
// Finds the |n|-th report of type |type| in |reports|.
// |n| starts from 1 for finding the first report.
-const webrtc::StatsReport* FindNthReportByType(webrtc::StatsReports reports,
- const std::string& type,
- int n) {
+const webrtc::StatsReport* FindNthReportByType(
+ const webrtc::StatsReports& reports, const std::string& type, int n) {
for (size_t i = 0; i < reports.size(); ++i) {
if (reports[i].type == type) {
n--;
@@ -112,7 +128,7 @@ const webrtc::StatsReport* FindNthReportByType(webrtc::StatsReports reports,
return NULL;
}
-const webrtc::StatsReport* FindReportById(webrtc::StatsReports reports,
+const webrtc::StatsReport* FindReportById(const webrtc::StatsReports& reports,
const std::string& id) {
for (size_t i = 0; i < reports.size(); ++i) {
if (reports[i].id == id) {
@@ -134,6 +150,59 @@ std::string ExtractBweStatsValue(webrtc::StatsReports reports,
webrtc::StatsReport::kStatsReportTypeBwe, reports, name);
}
+std::string DerToPem(const std::string& der) {
+ return talk_base::SSLIdentity::DerToPem(
+ talk_base::kPemTypeCertificate,
+ reinterpret_cast<const unsigned char*>(der.c_str()),
+ der.length());
+}
+
+std::vector<std::string> DersToPems(
+ const std::vector<std::string>& ders) {
+ std::vector<std::string> pems(ders.size());
+ std::transform(ders.begin(), ders.end(), pems.begin(), DerToPem);
+ return pems;
+}
+
+void CheckCertChainReports(const webrtc::StatsReports& reports,
+ const std::vector<std::string>& ders,
+ const std::string& start_id) {
+ std::string certificate_id = start_id;
+ size_t i = 0;
+ while (true) {
+ const webrtc::StatsReport* report = FindReportById(reports, certificate_id);
+ ASSERT_TRUE(report != NULL);
+
+ std::string der_base64;
+ EXPECT_TRUE(GetValue(
+ report, webrtc::StatsReport::kStatsValueNameDer, &der_base64));
+ std::string der = talk_base::Base64::Decode(der_base64,
+ talk_base::Base64::DO_STRICT);
+ EXPECT_EQ(ders[i], der);
+
+ std::string fingerprint_algorithm;
+ EXPECT_TRUE(GetValue(
+ report,
+ webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm,
+ &fingerprint_algorithm));
+ // The digest algorithm for a FakeSSLCertificate is always SHA-1.
+ std::string sha_1_str = talk_base::DIGEST_SHA_1;
+ EXPECT_EQ(sha_1_str, fingerprint_algorithm);
+
+ std::string dummy_fingerprint; // Value is not checked.
+ EXPECT_TRUE(GetValue(
+ report,
+ webrtc::StatsReport::kStatsValueNameFingerprint,
+ &dummy_fingerprint));
+
+ ++i;
+ if (!GetValue(
+ report, webrtc::StatsReport::kStatsValueNameIssuerId, &certificate_id))
+ break;
+ }
+ EXPECT_EQ(ders.size(), i);
+}
+
class StatsCollectorTest : public testing::Test {
protected:
StatsCollectorTest()
@@ -142,14 +211,116 @@ class StatsCollectorTest : public testing::Test {
new cricket::ChannelManager(media_engine_,
new cricket::FakeDeviceManager(),
talk_base::Thread::Current())),
- session_(channel_manager_.get()) {
+ session_(channel_manager_.get()),
+ track_id_(kTrackId) {
// By default, we ignore session GetStats calls.
EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
}
+ // This creates a standard setup with a transport called "trspname"
+ // having one transport channel
+ // and the specified virtual connection name.
+ void InitSessionStats(const std::string vc_name) {
+ const std::string kTransportName("trspname");
+ cricket::TransportStats transport_stats;
+ cricket::TransportChannelStats channel_stats;
+ channel_stats.component = 1;
+ transport_stats.content_name = kTransportName;
+ transport_stats.channel_stats.push_back(channel_stats);
+
+ session_stats_.transport_stats[kTransportName] = transport_stats;
+ session_stats_.proxy_to_transport[vc_name] = kTransportName;
+ }
+
+ // Adds a track with a given SSRC into the stats.
+ void AddVideoTrackStats() {
+ stream_ = webrtc::MediaStream::Create("streamlabel");
+ track_= webrtc::VideoTrack::Create(kTrackId, NULL);
+ stream_->AddTrack(track_);
+ EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(track_id_),
+ Return(true)));
+ }
+
+ void TestCertificateReports(const talk_base::FakeSSLCertificate& local_cert,
+ const std::vector<std::string>& local_ders,
+ const talk_base::FakeSSLCertificate& remote_cert,
+ const std::vector<std::string>& remote_ders) {
+ webrtc::StatsCollector stats; // Implementation under test.
+ webrtc::StatsReports reports; // returned values.
+ stats.set_session(&session_);
+
+ // Fake stats to process.
+ cricket::TransportChannelStats channel_stats;
+ channel_stats.component = 1;
+
+ cricket::TransportStats transport_stats;
+ transport_stats.content_name = "audio";
+ transport_stats.channel_stats.push_back(channel_stats);
+
+ cricket::SessionStats session_stats;
+ session_stats.transport_stats[transport_stats.content_name] =
+ transport_stats;
+
+ // Fake certificates to report.
+ talk_base::FakeSSLIdentity local_identity(local_cert);
+ talk_base::scoped_ptr<talk_base::FakeSSLCertificate> remote_cert_copy(
+ remote_cert.GetReference());
+
+ // Fake transport object.
+ talk_base::scoped_ptr<cricket::FakeTransport> transport(
+ new cricket::FakeTransport(
+ session_.signaling_thread(),
+ session_.worker_thread(),
+ transport_stats.content_name));
+ transport->SetIdentity(&local_identity);
+ cricket::FakeTransportChannel* channel =
+ static_cast<cricket::FakeTransportChannel*>(
+ transport->CreateChannel(channel_stats.component));
+ EXPECT_FALSE(channel == NULL);
+ channel->SetRemoteCertificate(remote_cert_copy.get());
+
+ // Configure MockWebRtcSession
+ EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
+ .WillOnce(Return(transport.get()));
+ EXPECT_CALL(session_, GetStats(_))
+ .WillOnce(DoAll(SetArgPointee<0>(session_stats),
+ Return(true)));
+ EXPECT_CALL(session_, video_channel())
+ .WillRepeatedly(ReturnNull());
+
+ stats.UpdateStats();
+
+ stats.GetStats(NULL, &reports);
+
+ const webrtc::StatsReport* channel_report = FindNthReportByType(
+ reports, webrtc::StatsReport::kStatsReportTypeComponent, 1);
+ EXPECT_TRUE(channel_report != NULL);
+
+ // Check local certificate chain.
+ std::string local_certificate_id = ExtractStatsValue(
+ webrtc::StatsReport::kStatsReportTypeComponent,
+ reports,
+ webrtc::StatsReport::kStatsValueNameLocalCertificateId);
+ EXPECT_NE(kNotFound, local_certificate_id);
+ CheckCertChainReports(reports, local_ders, local_certificate_id);
+
+ // Check remote certificate chain.
+ std::string remote_certificate_id = ExtractStatsValue(
+ webrtc::StatsReport::kStatsReportTypeComponent,
+ reports,
+ webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
+ EXPECT_NE(kNotFound, remote_certificate_id);
+ CheckCertChainReports(reports, remote_ders, remote_certificate_id);
+ }
+
cricket::FakeMediaEngine* media_engine_;
talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
MockWebRtcSession session_;
+ cricket::SessionStats session_stats_;
+ talk_base::scoped_refptr<webrtc::MediaStream> stream_;
+ talk_base::scoped_refptr<webrtc::VideoTrack> track_;
+ std::string track_id_;
};
// This test verifies that 64-bit counters are passed successfully.
@@ -161,20 +332,16 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
webrtc::StatsReports reports; // returned values.
cricket::VideoSenderInfo video_sender_info;
cricket::VideoMediaInfo stats_read;
- const uint32 kSsrcOfTrack = 1234;
- const std::string kNameOfTrack("somename");
// The number of bytes must be larger than 0xFFFFFFFF for this test.
const int64 kBytesSent = 12345678901234LL;
const std::string kBytesSentString("12345678901234");
stats.set_session(&session_);
- talk_base::scoped_refptr<webrtc::MediaStream> stream(
- webrtc::MediaStream::Create("streamlabel"));
- stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
- stats.AddStream(stream);
+ AddVideoTrackStats();
+ stats.AddStream(stream_);
// Construct a stats value to read.
- video_sender_info.ssrcs.push_back(1234);
+ video_sender_info.add_ssrc(1234);
video_sender_info.bytes_sent = kBytesSent;
stats_read.senders.push_back(video_sender_info);
@@ -183,9 +350,6 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
EXPECT_CALL(*media_channel, GetStats(_))
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
Return(true)));
- EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
- .WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
- Return(true)));
stats.UpdateStats();
stats.GetStats(NULL, &reports);
std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
@@ -203,19 +367,15 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
cricket::VideoMediaInfo stats_read;
// Set up an SSRC just to test that we get both kinds of stats back: SSRC and
// BWE.
- const uint32 kSsrcOfTrack = 1234;
- const std::string kNameOfTrack("somename");
const int64 kBytesSent = 12345678901234LL;
const std::string kBytesSentString("12345678901234");
stats.set_session(&session_);
- talk_base::scoped_refptr<webrtc::MediaStream> stream(
- webrtc::MediaStream::Create("streamlabel"));
- stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
- stats.AddStream(stream);
+ AddVideoTrackStats();
+ stats.AddStream(stream_);
// Construct a stats value to read.
- video_sender_info.ssrcs.push_back(1234);
+ video_sender_info.add_ssrc(1234);
video_sender_info.bytes_sent = kBytesSent;
stats_read.senders.push_back(video_sender_info);
cricket::BandwidthEstimationInfo bwe;
@@ -229,9 +389,7 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
EXPECT_CALL(*media_channel, GetStats(_))
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
Return(true)));
- EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
- .WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
- Return(true)));
+
stats.UpdateStats();
stats.GetStats(NULL, &reports);
std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
@@ -281,13 +439,8 @@ TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
media_engine_, media_channel, &session_, "", false, NULL);
- const std::string kTrackId("somename");
- talk_base::scoped_refptr<webrtc::MediaStream> stream(
- webrtc::MediaStream::Create("streamlabel"));
- talk_base::scoped_refptr<webrtc::VideoTrack> track =
- webrtc::VideoTrack::Create(kTrackId, NULL);
- stream->AddTrack(track);
- stats.AddStream(stream);
+ AddVideoTrackStats();
+ stats.AddStream(stream_);
stats.set_session(&session_);
@@ -313,13 +466,8 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
media_engine_, media_channel, &session_, "", false, NULL);
- const std::string kTrackId("somename");
- talk_base::scoped_refptr<webrtc::MediaStream> stream(
- webrtc::MediaStream::Create("streamlabel"));
- talk_base::scoped_refptr<webrtc::VideoTrack> track =
- webrtc::VideoTrack::Create(kTrackId, NULL);
- stream->AddTrack(track);
- stats.AddStream(stream);
+ AddVideoTrackStats();
+ stats.AddStream(stream_);
stats.set_session(&session_);
@@ -328,11 +476,10 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
// Constructs an ssrc stats update.
cricket::VideoSenderInfo video_sender_info;
cricket::VideoMediaInfo stats_read;
- const uint32 kSsrcOfTrack = 1234;
const int64 kBytesSent = 12345678901234LL;
// Construct a stats value to read.
- video_sender_info.ssrcs.push_back(1234);
+ video_sender_info.add_ssrc(1234);
video_sender_info.bytes_sent = kBytesSent;
stats_read.senders.push_back(video_sender_info);
@@ -341,23 +488,20 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
EXPECT_CALL(*media_channel, GetStats(_))
.WillOnce(DoAll(SetArgPointee<0>(stats_read),
Return(true)));
- EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
- .WillOnce(DoAll(SetArgPointee<1>(kTrackId),
- Return(true)));
stats.UpdateStats();
stats.GetStats(NULL, &reports);
- // |reports| should contain one session report, one track report, and one ssrc
- // report.
- EXPECT_EQ((size_t)3, reports.size());
+ // |reports| should contain at least one session report, one track report,
+ // and one ssrc report.
+ EXPECT_LE((size_t)3, reports.size());
const webrtc::StatsReport* track_report = FindNthReportByType(
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
EXPECT_FALSE(track_report == NULL);
- stats.GetStats(track, &reports);
- // |reports| should contain one session report, one track report, and one ssrc
- // report.
- EXPECT_EQ((size_t)3, reports.size());
+ stats.GetStats(track_, &reports);
+ // |reports| should contain at least one session report, one track report,
+ // and one ssrc report.
+ EXPECT_LE((size_t)3, reports.size());
track_report = FindNthReportByType(
reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
EXPECT_FALSE(track_report == NULL);
@@ -380,13 +524,8 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
const std::string kVcName("vcname");
cricket::VideoChannel video_channel(talk_base::Thread::Current(),
media_engine_, media_channel, &session_, kVcName, false, NULL);
- const std::string kTrackId("somename");
- talk_base::scoped_refptr<webrtc::MediaStream> stream(
- webrtc::MediaStream::Create("streamlabel"));
- talk_base::scoped_refptr<webrtc::VideoTrack> track =
- webrtc::VideoTrack::Create(kTrackId, NULL);
- stream->AddTrack(track);
- stats.AddStream(stream);
+ AddVideoTrackStats();
+ stats.AddStream(stream_);
stats.set_session(&session_);
@@ -395,11 +534,10 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
// Constructs an ssrc stats update.
cricket::VideoSenderInfo video_sender_info;
cricket::VideoMediaInfo stats_read;
- const uint32 kSsrcOfTrack = 1234;
const int64 kBytesSent = 12345678901234LL;
// Construct a stats value to read.
- video_sender_info.ssrcs.push_back(1234);
+ video_sender_info.add_ssrc(1234);
video_sender_info.bytes_sent = kBytesSent;
stats_read.senders.push_back(video_sender_info);
@@ -408,23 +546,10 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
EXPECT_CALL(*media_channel, GetStats(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
Return(true)));
- EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
- .WillOnce(DoAll(SetArgPointee<1>(kTrackId),
- Return(true)));
- // Instruct the session to return stats containing the transport channel.
- const std::string kTransportName("trspname");
- cricket::SessionStats session_stats;
- cricket::TransportStats transport_stats;
- cricket::TransportChannelStats channel_stats;
- channel_stats.component = 1;
- transport_stats.content_name = kTransportName;
- transport_stats.channel_stats.push_back(channel_stats);
-
- session_stats.transport_stats[kTransportName] = transport_stats;
- session_stats.proxy_to_transport[kVcName] = kTransportName;
+ InitSessionStats(kVcName);
EXPECT_CALL(session_, GetStats(_))
- .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats),
+ .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
Return(true)));
stats.UpdateStats();
@@ -439,4 +564,214 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
ASSERT_FALSE(transport_report == NULL);
}
+// This test verifies that a remote stats object will not be created for
+// an outgoing SSRC where remote stats are not returned.
+TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
+ webrtc::StatsCollector stats; // Implementation under test.
+ MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
+ // The content_name known by the video channel.
+ const std::string kVcName("vcname");
+ cricket::VideoChannel video_channel(talk_base::Thread::Current(),
+ media_engine_, media_channel, &session_, kVcName, false, NULL);
+ AddVideoTrackStats();
+ stats.AddStream(stream_);
+
+ stats.set_session(&session_);
+
+ EXPECT_CALL(session_, video_channel())
+ .WillRepeatedly(ReturnNull());
+
+ stats.UpdateStats();
+ webrtc::StatsReports reports;
+ stats.GetStats(NULL, &reports);
+ const webrtc::StatsReport* remote_report = FindNthReportByType(reports,
+ webrtc::StatsReport::kStatsReportTypeRemoteSsrc, 1);
+ EXPECT_TRUE(remote_report == NULL);
+}
+
+// This test verifies that a remote stats object will be created for
+// an outgoing SSRC where stats are returned.
+TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
+ webrtc::StatsCollector stats; // Implementation under test.
+ MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
+ // The content_name known by the video channel.
+ const std::string kVcName("vcname");
+ cricket::VideoChannel video_channel(talk_base::Thread::Current(),
+ media_engine_, media_channel, &session_, kVcName, false, NULL);
+ AddVideoTrackStats();
+ stats.AddStream(stream_);
+
+ stats.set_session(&session_);
+
+ webrtc::StatsReports reports;
+
+ // Instruct the session to return stats containing the transport channel.
+ InitSessionStats(kVcName);
+ EXPECT_CALL(session_, GetStats(_))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
+ Return(true)));
+
+ // Constructs an ssrc stats update.
+ cricket::VideoMediaInfo stats_read;
+
+ cricket::SsrcReceiverInfo remote_ssrc_stats;
+ remote_ssrc_stats.timestamp = 12345.678;
+ remote_ssrc_stats.ssrc = kSsrcOfTrack;
+ cricket::VideoSenderInfo video_sender_info;
+ video_sender_info.add_ssrc(kSsrcOfTrack);
+ video_sender_info.remote_stats.push_back(remote_ssrc_stats);
+ stats_read.senders.push_back(video_sender_info);
+
+ EXPECT_CALL(session_, video_channel())
+ .WillRepeatedly(Return(&video_channel));
+ EXPECT_CALL(*media_channel, GetStats(_))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
+ Return(true)));
+
+ stats.UpdateStats();
+ stats.GetStats(NULL, &reports);
+ const webrtc::StatsReport* remote_report = FindNthReportByType(reports,
+ webrtc::StatsReport::kStatsReportTypeRemoteSsrc, 1);
+ EXPECT_FALSE(remote_report == NULL);
+ EXPECT_NE(0, remote_report->timestamp);
+}
+
+// This test verifies that all chained certificates are correctly
+// reported
+TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
+ // Build local certificate chain.
+ std::vector<std::string> local_ders(5);
+ local_ders[0] = "These";
+ local_ders[1] = "are";
+ local_ders[2] = "some";
+ local_ders[3] = "der";
+ local_ders[4] = "values";
+ talk_base::FakeSSLCertificate local_cert(DersToPems(local_ders));
+
+ // Build remote certificate chain
+ std::vector<std::string> remote_ders(4);
+ remote_ders[0] = "A";
+ remote_ders[1] = "non-";
+ remote_ders[2] = "intersecting";
+ remote_ders[3] = "set";
+ talk_base::FakeSSLCertificate remote_cert(DersToPems(remote_ders));
+
+ TestCertificateReports(local_cert, local_ders, remote_cert, remote_ders);
+}
+
+// This test verifies that all certificates without chains are correctly
+// reported.
+TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
+ // Build local certificate.
+ std::string local_der = "This is the local der.";
+ talk_base::FakeSSLCertificate local_cert(DerToPem(local_der));
+
+ // Build remote certificate.
+ std::string remote_der = "This is somebody else's der.";
+ talk_base::FakeSSLCertificate remote_cert(DerToPem(remote_der));
+
+ TestCertificateReports(local_cert, std::vector<std::string>(1, local_der),
+ remote_cert, std::vector<std::string>(1, remote_der));
+}
+
+// This test verifies that the stats are generated correctly when no
+// transport is present.
+TEST_F(StatsCollectorTest, NoTransport) {
+ webrtc::StatsCollector stats; // Implementation under test.
+ webrtc::StatsReports reports; // returned values.
+ stats.set_session(&session_);
+
+ // Fake stats to process.
+ cricket::TransportChannelStats channel_stats;
+ channel_stats.component = 1;
+
+ cricket::TransportStats transport_stats;
+ transport_stats.content_name = "audio";
+ transport_stats.channel_stats.push_back(channel_stats);
+
+ cricket::SessionStats session_stats;
+ session_stats.transport_stats[transport_stats.content_name] =
+ transport_stats;
+
+ // Configure MockWebRtcSession
+ EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
+ .WillOnce(ReturnNull());
+ EXPECT_CALL(session_, GetStats(_))
+ .WillOnce(DoAll(SetArgPointee<0>(session_stats),
+ Return(true)));
+
+ EXPECT_CALL(session_, video_channel())
+ .WillRepeatedly(ReturnNull());
+
+ stats.UpdateStats();
+ stats.GetStats(NULL, &reports);
+
+ // Check that the local certificate is absent.
+ std::string local_certificate_id = ExtractStatsValue(
+ webrtc::StatsReport::kStatsReportTypeComponent,
+ reports,
+ webrtc::StatsReport::kStatsValueNameLocalCertificateId);
+ ASSERT_EQ(kNotFound, local_certificate_id);
+
+ // Check that the remote certificate is absent.
+ std::string remote_certificate_id = ExtractStatsValue(
+ webrtc::StatsReport::kStatsReportTypeComponent,
+ reports,
+ webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
+ ASSERT_EQ(kNotFound, remote_certificate_id);
+}
+
+// This test verifies that the stats are generated correctly when the transport
+// does not have any certificates.
+TEST_F(StatsCollectorTest, NoCertificates) {
+ webrtc::StatsCollector stats; // Implementation under test.
+ webrtc::StatsReports reports; // returned values.
+ stats.set_session(&session_);
+
+ // Fake stats to process.
+ cricket::TransportChannelStats channel_stats;
+ channel_stats.component = 1;
+
+ cricket::TransportStats transport_stats;
+ transport_stats.content_name = "audio";
+ transport_stats.channel_stats.push_back(channel_stats);
+
+ cricket::SessionStats session_stats;
+ session_stats.transport_stats[transport_stats.content_name] =
+ transport_stats;
+
+ // Fake transport object.
+ talk_base::scoped_ptr<cricket::FakeTransport> transport(
+ new cricket::FakeTransport(
+ session_.signaling_thread(),
+ session_.worker_thread(),
+ transport_stats.content_name));
+
+ // Configure MockWebRtcSession
+ EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
+ .WillOnce(Return(transport.get()));
+ EXPECT_CALL(session_, GetStats(_))
+ .WillOnce(DoAll(SetArgPointee<0>(session_stats),
+ Return(true)));
+ EXPECT_CALL(session_, video_channel())
+ .WillRepeatedly(ReturnNull());
+
+ stats.UpdateStats();
+ stats.GetStats(NULL, &reports);
+
+ // Check that the local certificate is absent.
+ std::string local_certificate_id = ExtractStatsValue(
+ webrtc::StatsReport::kStatsReportTypeComponent,
+ reports,
+ webrtc::StatsReport::kStatsValueNameLocalCertificateId);
+ ASSERT_EQ(kNotFound, local_certificate_id);
+
+ // Check that the remote certificate is absent.
+ std::string remote_certificate_id = ExtractStatsValue(
+ webrtc::StatsReport::kStatsReportTypeComponent,
+ reports,
+ webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
+ ASSERT_EQ(kNotFound, remote_certificate_id);
+}
+
} // namespace
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/statstypes.h b/chromium/third_party/libjingle/source/talk/app/webrtc/statstypes.h
index 30a8b84165c..6890f9e017a 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/statstypes.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/statstypes.h
@@ -88,6 +88,10 @@ class StatsReport {
// The |id| field is the SSRC in decimal form of the rtp stream.
static const char kStatsReportTypeSsrc[];
+ // StatsReport of |type| = "remoteSsrc" is statistics for a specific
+ // rtp stream, generated by the remote end of the connection.
+ static const char kStatsReportTypeRemoteSsrc[];
+
// StatsReport of |type| = "googTrack" is statistics for a specific media
// track. The |id| field is the track id.
static const char kStatsReportTypeTrack[];
@@ -99,6 +103,14 @@ class StatsReport {
// The id of StatsReport of type VideoBWE.
static const char kStatsReportVideoBweId[];
+ // A StatsReport of |type| = "googCertificate" contains an SSL certificate
+ // transmitted by one of the endpoints of this connection. The |id| is
+ // controlled by the fingerprint, and is used to identify the certificate in
+ // the Channel stats (as "googLocalCertificateId" or
+ // "googRemoteCertificateId") and in any child certificates (as
+ // "googIssuerId").
+ static const char kStatsReportTypeCertificate[];
+
// StatsValue names
static const char kStatsValueNameAudioOutputLevel[];
static const char kStatsValueNameAudioInputLevel[];
@@ -116,7 +128,14 @@ class StatsReport {
// Internal StatsValue names
+ static const char kStatsValueNameAvgEncodeMs[];
+ static const char kStatsValueNameEncodeUsagePercent[];
+ static const char kStatsValueNameCaptureJitterMs[];
+ static const char kStatsValueNameCaptureQueueDelayMsPerS[];
static const char kStatsValueNameCodecName[];
+ static const char kStatsValueNameBandwidthLimitedResolution[];
+ static const char kStatsValueNameCpuLimitedResolution[];
+ static const char kStatsValueNameViewLimitedResolution[];
static const char kStatsValueNameEchoCancellationQualityMin[];
static const char kStatsValueNameEchoDelayMedian[];
static const char kStatsValueNameEchoDelayStdDev[];
@@ -129,6 +148,13 @@ class StatsReport {
static const char kStatsValueNameFrameRateReceived[];
static const char kStatsValueNameFrameRateDecoded[];
static const char kStatsValueNameFrameRateOutput[];
+ static const char kStatsValueNameDecodeMs[];
+ static const char kStatsValueNameMaxDecodeMs[];
+ static const char kStatsValueNameCurrentDelayMs[];
+ static const char kStatsValueNameTargetDelayMs[];
+ static const char kStatsValueNameJitterBufferMs[];
+ static const char kStatsValueNameMinPlayoutDelayMs[];
+ static const char kStatsValueNameRenderDelayMs[];
static const char kStatsValueNameFrameRateInput[];
static const char kStatsValueNameFrameRateSent[];
static const char kStatsValueNameFrameWidthReceived[];
@@ -152,6 +178,14 @@ class StatsReport {
static const char kStatsValueNameTrackId[];
static const char kStatsValueNameSsrc[];
static const char kStatsValueNameTypingNoiseState[];
+ static const char kStatsValueNameDer[];
+ static const char kStatsValueNameFingerprint[];
+ static const char kStatsValueNameFingerprintAlgorithm[];
+ static const char kStatsValueNameIssuerId[];
+ static const char kStatsValueNameLocalCertificateId[];
+ static const char kStatsValueNameRemoteCertificateId[];
+ static const char kStatsValueNameLocalCandidateType[];
+ static const char kStatsValueNameRemoteCandidateType[];
};
typedef std::vector<StatsReport> StatsReports;
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp.cc
index 60c427d16f1..79f94fe3b4e 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp.cc
@@ -145,6 +145,7 @@ static const char kAttributeFingerprint[] = "fingerprint";
static const char kAttributeSetup[] = "setup";
static const char kAttributeFmtp[] = "fmtp";
static const char kAttributeRtpmap[] = "rtpmap";
+static const char kAttributeSctpmap[] = "sctpmap";
static const char kAttributeRtcp[] = "rtcp";
static const char kAttributeIceUfrag[] = "ice-ufrag";
static const char kAttributeIcePwd[] = "ice-pwd";
@@ -210,7 +211,7 @@ static const int kIsacWbDefaultRate = 32000; // From acm_common_defs.h
static const int kIsacSwbDefaultRate = 56000; // From acm_common_defs.h
static const int kDefaultSctpFmt = 5000;
-static const char kDefaultSctpFmtProtocol[] = "webrtc-datachannel";
+static const char kDefaultSctpmapProtocol[] = "webrtc-datachannel";
struct SsrcInfo {
SsrcInfo()
@@ -340,13 +341,15 @@ static bool ParseFailed(const std::string& message,
const std::string& description,
SdpParseError* error) {
// Get the first line of |message| from |line_start|.
- std::string first_line = message;
+ std::string first_line;
size_t line_end = message.find(kNewLine, line_start);
if (line_end != std::string::npos) {
if (line_end > 0 && (message.at(line_end - 1) == kReturn)) {
--line_end;
}
first_line = message.substr(line_start, (line_end - line_start));
+ } else {
+ first_line = message.substr(line_start);
}
if (error) {
@@ -1240,12 +1243,9 @@ void BuildMediaDescription(const ContentInfo* content_info,
// Making sure we are not using "passive" mode.
cricket::ConnectionRole role =
transport_info->description.connection_role;
- ASSERT(role == cricket::CONNECTIONROLE_ACTIVE ||
- role == cricket::CONNECTIONROLE_ACTPASS);
+ std::string dtls_role_str;
+ VERIFY(cricket::ConnectionRoleToString(role, &dtls_role_str));
InitAttrLine(kAttributeSetup, &os);
- std::string dtls_role_str = role == cricket::CONNECTIONROLE_ACTPASS ?
- cricket::CONNECTIONROLE_ACTPASS_STR :
- cricket::CONNECTIONROLE_ACTIVE_STR;
os << kSdpDelimiterColon << dtls_role_str;
AddLine(os.str(), message);
}
@@ -1268,10 +1268,14 @@ void BuildMediaDescription(const ContentInfo* content_info,
}
void BuildSctpContentAttributes(std::string* message) {
- cricket::DataCodec sctp_codec(kDefaultSctpFmt, kDefaultSctpFmtProtocol, 0);
- sctp_codec.SetParam(kCodecParamSctpProtocol, kDefaultSctpFmtProtocol);
- sctp_codec.SetParam(kCodecParamSctpStreams, cricket::kMaxSctpSid + 1);
- AddFmtpLine(sctp_codec, message);
+ // draft-ietf-mmusic-sctp-sdp-04
+ // a=sctpmap:sctpmap-number protocol [streams]
+ std::ostringstream os;
+ InitAttrLine(kAttributeSctpmap, &os);
+ os << kSdpDelimiterColon << kDefaultSctpFmt << kSdpDelimiterSpace
+ << kDefaultSctpmapProtocol << kSdpDelimiterSpace
+ << (cricket::kMaxSctpSid + 1);
+ AddLine(os.str(), message);
}
void BuildRtpContentAttributes(
@@ -2111,10 +2115,25 @@ bool ParseMediaDescription(const std::string& message,
codec_preference,
static_cast<AudioContentDescription*>(content.get()));
} else if (HasAttribute(line, kMediaTypeData)) {
- content.reset(ParseContentDescription<DataContentDescription>(
+ DataContentDescription* desc =
+ ParseContentDescription<DataContentDescription>(
message, cricket::MEDIA_TYPE_DATA, mline_index, protocol,
codec_preference, pos, &content_name,
- &transport, candidates, error));
+ &transport, candidates, error);
+
+ if (protocol == cricket::kMediaProtocolDtlsSctp) {
+ // Add the SCTP Port number as a pseudo-codec "port" parameter
+ cricket::DataCodec codec_port(
+ cricket::kGoogleSctpDataCodecId, cricket::kGoogleSctpDataCodecName,
+ 0);
+ codec_port.SetParam(cricket::kCodecParamPort, fields[3]);
+ LOG(INFO) << "ParseMediaDescription: Got SCTP Port Number "
+ << fields[3];
+ desc->AddCodec(codec_port);
+ }
+
+ content.reset(desc);
+
// We should always use the default bandwidth for RTP-based data
// channels. Don't allow SDP to set the bandwidth, because that
// would give JS the opportunity to "break the Internet".
@@ -2171,6 +2190,12 @@ bool ParseMediaDescription(const std::string& message,
return ParseFailed("", description.str(), error);
}
}
+
+ size_t end_of_message = message.size();
+ if (mline_index == -1 && *pos != end_of_message) {
+ ParseFailed(message, *pos, "Expects m line.", error);
+ return false;
+ }
return true;
}
@@ -2364,7 +2389,7 @@ bool ParseContent(const std::string& message,
if (*pos >= message.size()) {
break; // Done parsing
} else {
- return ParseFailed(message, *pos, "Can't find valid SDP line.", error);
+ return ParseFailed(message, *pos, "Invalid SDP line.", error);
}
}
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp_unittest.cc
index b1505aae7df..541868314c7 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsdp_unittest.cc
@@ -76,6 +76,7 @@ using webrtc::SessionDescriptionInterface;
typedef std::vector<AudioCodec> AudioCodecs;
typedef std::vector<Candidate> Candidates;
+static const uint32 kDefaultSctpPort = 5000;
static const char kSessionTime[] = "t=0 0\r\n";
static const uint32 kCandidatePriority = 2130706432U; // pref = 1.0
static const char kCandidateUfragVoice[] = "ufrag_voice";
@@ -281,7 +282,7 @@ static const char kSdpSctpDataChannelString[] =
"a=ice-ufrag:ufrag_data\r\n"
"a=ice-pwd:pwd_data\r\n"
"a=mid:data_content_name\r\n"
- "a=fmtp:5000 protocol=webrtc-datachannel; streams=65536\r\n";
+ "a=sctpmap:5000 webrtc-datachannel 1024\r\n";
static const char kSdpSctpDataChannelWithCandidatesString[] =
"m=application 2345 DTLS/SCTP 5000\r\n"
@@ -296,7 +297,7 @@ static const char kSdpSctpDataChannelWithCandidatesString[] =
"a=ice-ufrag:ufrag_data\r\n"
"a=ice-pwd:pwd_data\r\n"
"a=mid:data_content_name\r\n"
- "a=fmtp:5000 protocol=webrtc-datachannel; streams=65536\r\n";
+ "a=sctpmap:5000 webrtc-datachannel 1024\r\n";
// One candidate reference string as per W3c spec.
@@ -974,6 +975,10 @@ class WebRtcSdpTest : public testing::Test {
new DataContentDescription());
data_desc_ = data.get();
data_desc_->set_protocol(cricket::kMediaProtocolDtlsSctp);
+ DataCodec codec(cricket::kGoogleSctpDataCodecId,
+ cricket::kGoogleSctpDataCodecName, 0);
+ codec.SetParam(cricket::kCodecParamPort, kDefaultSctpPort);
+ data_desc_->AddCodec(codec);
desc_.AddContent(kDataContentName, NS_JINGLE_DRAFT_SCTP, data.release());
EXPECT_TRUE(desc_.AddTransportInfo(
TransportInfo(kDataContentName,
@@ -1479,6 +1484,19 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescription) {
EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc));
}
+TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutMline) {
+ JsepSessionDescription jdesc(kDummyString);
+ const char kSdpWithoutMline[] =
+ "v=0\r\n"
+ "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
+ "s=-\r\n"
+ "t=0 0\r\n"
+ "a=msid-semantic: WMS local_stream_1 local_stream_2\r\n";
+ // Deserialize
+ EXPECT_TRUE(SdpDeserialize(kSdpWithoutMline, &jdesc));
+ EXPECT_EQ(0u, jdesc.description()->contents().size());
+}
+
TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutCarriageReturn) {
JsepSessionDescription jdesc(kDummyString);
std::string sdp_without_carriage_return = kSdpFullString;
@@ -1761,6 +1779,41 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannels) {
EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
}
+TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelAndNewPort) {
+ AddSctpDataChannel();
+ const uint16 kUnusualSctpPort = 9556;
+ char default_portstr[16];
+ char unusual_portstr[16];
+ talk_base::sprintfn(default_portstr, sizeof(default_portstr), "%d",
+ kDefaultSctpPort);
+ talk_base::sprintfn(unusual_portstr, sizeof(unusual_portstr), "%d",
+ kUnusualSctpPort);
+
+ JsepSessionDescription jdesc(kDummyString);
+ // take our pre-built session description and change the SCTP port.
+ cricket::SessionDescription* mutant = desc_.Copy();
+ DataContentDescription* dcdesc = static_cast<DataContentDescription*>(
+ mutant->GetContentDescriptionByName(kDataContentName));
+ std::vector<cricket::DataCodec> codecs(dcdesc->codecs());
+ EXPECT_EQ(codecs.size(), 1UL);
+ EXPECT_EQ(codecs[0].id, cricket::kGoogleSctpDataCodecId);
+ codecs[0].SetParam(cricket::kCodecParamPort, kUnusualSctpPort);
+
+ // note: mutant's owned by jdesc now.
+ ASSERT_TRUE(jdesc.Initialize(mutant, kSessionId, kSessionVersion));
+ mutant = NULL;
+
+ std::string sdp_with_data = kSdpString;
+ sdp_with_data.append(kSdpSctpDataChannelString);
+ talk_base::replace_substrs(default_portstr, strlen(default_portstr),
+ unusual_portstr, strlen(unusual_portstr),
+ &sdp_with_data);
+ JsepSessionDescription jdesc_output(kDummyString);
+
+ EXPECT_TRUE(SdpDeserialize(sdp_with_data, &jdesc_output));
+ EXPECT_TRUE(CompareSessionDescription(jdesc, jdesc_output));
+}
+
TEST_F(WebRtcSdpTest, DeserializeSdpWithRtpDataChannelsAndBandwidth) {
AddRtpDataChannel();
JsepSessionDescription jdesc(kDummyString);
@@ -1799,6 +1852,18 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithInvalidExtmap) {
TestDeserializeExtmap(true, true);
}
+TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithoutEndLineBreak) {
+ JsepSessionDescription jdesc(kDummyString);
+ std::string sdp = kSdpFullString;
+ sdp = sdp.substr(0, sdp.size() - 2); // Remove \r\n at the end.
+ // Deserialize
+ SdpParseError error;
+ EXPECT_FALSE(webrtc::SdpDeserialize(sdp, &jdesc, &error));
+ const std::string lastline = "a=ssrc:6 label:video_track_id_3";
+ EXPECT_EQ(lastline, error.line);
+ EXPECT_EQ("Invalid SDP line.", error.description);
+}
+
TEST_F(WebRtcSdpTest, DeserializeCandidateWithDifferentTransport) {
JsepIceCandidate jcandidate(kDummyMid, kDummyIndex);
std::string new_sdp = kSdpOneCandidate;
@@ -1846,6 +1911,7 @@ TEST_F(WebRtcSdpTest, DeserializeBrokenSdp) {
ReplaceAndTryToParse("t=", kSdpDestroyer);
// Broken media description
+ ReplaceAndTryToParse("m=audio", "c=IN IP4 74.125.224.39");
ReplaceAndTryToParse("m=video", kSdpDestroyer);
// Invalid lines
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.cc
index f1fb40d51a0..7e153b3ffd1 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.cc
@@ -54,9 +54,11 @@ using cricket::TransportInfo;
namespace webrtc {
-const char kInternalConstraintPrefix[] = "internal";
+const char MediaConstraintsInterface::kInternalConstraintPrefix[] = "internal";
// Supported MediaConstraints.
+// DSCP constraints.
+const char MediaConstraintsInterface::kEnableDscp[] = "googDscp";
// DTLS-SRTP pseudo-constraints.
const char MediaConstraintsInterface::kEnableDtlsSrtp[] =
"DtlsSrtpKeyAgreement";
@@ -67,7 +69,7 @@ const char MediaConstraintsInterface::kEnableRtpDataChannels[] =
// line flag. So it is prefixed with kInternalConstraintPrefix so JS values
// will be removed.
const char MediaConstraintsInterface::kEnableSctpDataChannels[] =
- "internalSctpDataChannels";
+ "deprecatedSctpDataChannels";
// Error messages
const char kSetLocalSdpFailed[] = "SetLocalDescription failed: ";
@@ -81,6 +83,10 @@ const char kMlineMismatch[] =
"Offer and answer descriptions m-lines are not matching. "
"Rejecting answer.";
const char kSdpWithoutCrypto[] = "Called with a SDP without crypto enabled.";
+const char kSdpWithoutSdesAndDtlsDisabled[] =
+ "Called with an SDP without SDES crypto and DTLS disabled locally.";
+const char kSdpWithoutIceUfragPwd[] =
+ "Called with an SDP without ice-ufrag and ice-pwd.";
const char kSessionError[] = "Session error code: ";
const char kUpdateStateFailed[] = "Failed to update session state: ";
const char kPushDownOfferTDFailed[] =
@@ -110,10 +116,9 @@ static bool VerifyMediaDescriptions(
// fingerprint. Mismatches, such as replying with a DTLS fingerprint to SDES
// keys, will be caught in Transport negotiation, and backstopped by Channel's
// |secure_required| check.
-static bool VerifyCrypto(const SessionDescription* desc) {
- if (!desc) {
- return false;
- }
+static bool VerifyCrypto(const SessionDescription* desc,
+ bool dtls_enabled,
+ std::string* error) {
const ContentInfos& contents = desc->contents();
for (size_t index = 0; index < contents.size(); ++index) {
const ContentInfo* cinfo = &contents[index];
@@ -128,19 +133,53 @@ static bool VerifyCrypto(const SessionDescription* desc) {
if (!media || !tinfo) {
// Something is not right.
LOG(LS_ERROR) << kInvalidSdp;
+ *error = kInvalidSdp;
return false;
}
- if (media->cryptos().empty() &&
- !tinfo->description.identity_fingerprint) {
- // Crypto must be supplied.
- LOG(LS_WARNING) << "Session description must have SDES or DTLS-SRTP.";
- return false;
+ if (media->cryptos().empty()) {
+ if (!tinfo->description.identity_fingerprint) {
+ // Crypto must be supplied.
+ LOG(LS_WARNING) << "Session description must have SDES or DTLS-SRTP.";
+ *error = kSdpWithoutCrypto;
+ return false;
+ }
+ if (!dtls_enabled) {
+ LOG(LS_WARNING) <<
+ "Session description must have SDES when DTLS disabled.";
+ *error = kSdpWithoutSdesAndDtlsDisabled;
+ return false;
+ }
}
}
return true;
}
+// Checks that each non-rejected content has ice-ufrag and ice-pwd set.
+static bool VerifyIceUfragPwdPresent(const SessionDescription* desc) {
+ const ContentInfos& contents = desc->contents();
+ for (size_t index = 0; index < contents.size(); ++index) {
+ const ContentInfo* cinfo = &contents[index];
+ if (cinfo->rejected) {
+ continue;
+ }
+
+ // If the content isn't rejected, ice-ufrag and ice-pwd must be present.
+ const TransportInfo* tinfo = desc->GetTransportInfoByName(cinfo->name);
+ if (!tinfo) {
+ // Something is not right.
+ LOG(LS_ERROR) << kInvalidSdp;
+ return false;
+ }
+ if (tinfo->description.ice_ufrag.empty() ||
+ tinfo->description.ice_pwd.empty()) {
+ LOG(LS_ERROR) << "Session description must have ice ufrag and pwd.";
+ return false;
+ }
+ }
+ return true;
+}
+
// Forces |sdesc->crypto_required| to the appropriate state based on the
// current security policy, to ensure a failure occurs if there is an error
// in crypto negotiation.
@@ -392,6 +431,8 @@ WebRtcSession::WebRtcSession(
ice_observer_(NULL),
ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
older_version_remote_peer_(false),
+ dtls_enabled_(false),
+ dscp_enabled_(false),
data_channel_type_(cricket::DCT_NONE),
ice_restart_latch_(new IceRestartAnswerLatch) {
}
@@ -416,6 +457,7 @@ WebRtcSession::~WebRtcSession() {
}
bool WebRtcSession::Initialize(
+ const PeerConnectionFactoryInterface::Options& options,
const MediaConstraintsInterface* constraints,
DTLSIdentityServiceInterface* dtls_identity_service) {
// TODO(perkj): Take |constraints| into consideration. Return false if not all
@@ -424,29 +466,26 @@ bool WebRtcSession::Initialize(
bool value;
// Enable DTLS by default if |dtls_identity_service| is valid.
- bool dtls_enabled = (dtls_identity_service != NULL);
- // |constraints| can override the default |dtls_enabled| value.
+ dtls_enabled_ = (dtls_identity_service != NULL);
+ // |constraints| can override the default |dtls_enabled_| value.
if (FindConstraint(
constraints,
MediaConstraintsInterface::kEnableDtlsSrtp,
&value, NULL)) {
- dtls_enabled = value;
+ dtls_enabled_ = value;
}
// Enable creation of RTP data channels if the kEnableRtpDataChannels is set.
- // It takes precendence over the kEnableSctpDataChannels constraint.
+ // It takes precendence over the disable_sctp_data_channels
+ // PeerConnectionFactoryInterface::Options.
if (FindConstraint(
constraints, MediaConstraintsInterface::kEnableRtpDataChannels,
&value, NULL) && value) {
LOG(LS_INFO) << "Allowing RTP data engine.";
data_channel_type_ = cricket::DCT_RTP;
} else {
- bool sctp_enabled = FindConstraint(
- constraints,
- MediaConstraintsInterface::kEnableSctpDataChannels,
- &value, NULL) && value;
// DTLS has to be enabled to use SCTP.
- if (sctp_enabled && dtls_enabled) {
+ if (!options.disable_sctp_data_channels && dtls_enabled_) {
LOG(LS_INFO) << "Allowing SCTP data engine.";
data_channel_type_ = cricket::DCT_SCTP;
}
@@ -455,6 +494,14 @@ bool WebRtcSession::Initialize(
mediastream_signaling_->SetDataChannelFactory(this);
}
+ // Find DSCP constraint.
+ if (FindConstraint(
+ constraints,
+ MediaConstraintsInterface::kEnableDscp,
+ &value, NULL)) {
+ dscp_enabled_ = value;
+ }
+
const cricket::VideoCodec default_codec(
JsepSessionDescription::kDefaultVideoCodecId,
JsepSessionDescription::kDefaultVideoCodecName,
@@ -473,10 +520,15 @@ bool WebRtcSession::Initialize(
this,
id(),
data_channel_type_,
- dtls_enabled));
+ dtls_enabled_));
webrtc_session_desc_factory_->SignalIdentityReady.connect(
this, &WebRtcSession::OnIdentityReady);
+
+ if (options.disable_encryption) {
+ webrtc_session_desc_factory_->SetSecure(cricket::SEC_DISABLED);
+ }
+
return true;
}
@@ -502,13 +554,13 @@ bool WebRtcSession::StartCandidatesAllocation() {
return true;
}
-void WebRtcSession::set_secure_policy(
+void WebRtcSession::SetSecurePolicy(
cricket::SecureMediaPolicy secure_policy) {
- webrtc_session_desc_factory_->set_secure(secure_policy);
+ webrtc_session_desc_factory_->SetSecure(secure_policy);
}
-cricket::SecureMediaPolicy WebRtcSession::secure_policy() const {
- return webrtc_session_desc_factory_->secure();
+cricket::SecureMediaPolicy WebRtcSession::SecurePolicy() const {
+ return webrtc_session_desc_factory_->Secure();
}
bool WebRtcSession::GetSslRole(talk_base::SSLRole* role) {
@@ -558,7 +610,7 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
}
cricket::SecureMediaPolicy secure_policy =
- webrtc_session_desc_factory_->secure();
+ webrtc_session_desc_factory_->Secure();
// Update the MediaContentDescription crypto settings as per the policy set.
UpdateSessionDescriptionSecurePolicy(secure_policy, desc->description());
@@ -587,6 +639,10 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
// local session description.
mediastream_signaling_->OnLocalDescriptionChanged(local_desc_.get());
+ talk_base::SSLRole role;
+ if (data_channel_type_ == cricket::DCT_SCTP && GetSslRole(&role)) {
+ mediastream_signaling_->OnDtlsRoleReadyForSctp(role);
+ }
if (error() != cricket::BaseSession::ERROR_NONE) {
return BadLocalSdp(SessionErrorMsg(error()), err_desc);
}
@@ -639,6 +695,12 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
ice_restart_latch_->CheckForRemoteIceRestart(remote_desc_.get(),
desc);
remote_desc_.reset(desc_temp.release());
+
+ talk_base::SSLRole role;
+ if (data_channel_type_ == cricket::DCT_SCTP && GetSslRole(&role)) {
+ mediastream_signaling_->OnDtlsRoleReadyForSctp(role);
+ }
+
if (error() != cricket::BaseSession::ERROR_NONE) {
return BadRemoteSdp(SessionErrorMsg(error()), err_desc);
}
@@ -904,9 +966,63 @@ sigslot::signal0<>* WebRtcSession::GetOnDestroyedSignal() {
return &SignalVoiceChannelDestroyed;
}
+bool WebRtcSession::SendData(const cricket::SendDataParams& params,
+ const talk_base::Buffer& payload,
+ cricket::SendDataResult* result) {
+ if (!data_channel_.get()) {
+ LOG(LS_ERROR) << "SendData called when data_channel_ is NULL.";
+ return false;
+ }
+ return data_channel_->SendData(params, payload, result);
+}
+
+bool WebRtcSession::ConnectDataChannel(DataChannel* webrtc_data_channel) {
+ if (!data_channel_.get()) {
+ LOG(LS_ERROR) << "ConnectDataChannel called when data_channel_ is NULL.";
+ return false;
+ }
+ data_channel_->SignalReadyToSendData.connect(webrtc_data_channel,
+ &DataChannel::OnChannelReady);
+ data_channel_->SignalDataReceived.connect(webrtc_data_channel,
+ &DataChannel::OnDataReceived);
+ return true;
+}
+
+void WebRtcSession::DisconnectDataChannel(DataChannel* webrtc_data_channel) {
+ if (!data_channel_.get()) {
+ LOG(LS_ERROR) << "DisconnectDataChannel called when data_channel_ is NULL.";
+ return;
+ }
+ data_channel_->SignalReadyToSendData.disconnect(webrtc_data_channel);
+ data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
+}
+
+void WebRtcSession::AddSctpDataStream(uint32 sid) {
+ if (!data_channel_.get()) {
+ LOG(LS_ERROR) << "AddDataChannelStreams called when data_channel_ is NULL.";
+ return;
+ }
+ data_channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(sid));
+ data_channel_->AddSendStream(cricket::StreamParams::CreateLegacy(sid));
+}
+
+void WebRtcSession::RemoveSctpDataStream(uint32 sid) {
+ if (!data_channel_.get()) {
+ LOG(LS_ERROR) << "RemoveDataChannelStreams called when data_channel_ is "
+ << "NULL.";
+ return;
+ }
+ data_channel_->RemoveRecvStream(sid);
+ data_channel_->RemoveSendStream(sid);
+}
+
+bool WebRtcSession::ReadyToSendData() const {
+ return data_channel_.get() && data_channel_->ready_to_send_data();
+}
+
talk_base::scoped_refptr<DataChannel> WebRtcSession::CreateDataChannel(
- const std::string& label,
- const DataChannelInit* config) {
+ const std::string& label,
+ const DataChannelInit* config) {
if (state() == STATE_RECEIVEDTERMINATE) {
return NULL;
}
@@ -918,11 +1034,13 @@ talk_base::scoped_refptr<DataChannel> WebRtcSession::CreateDataChannel(
if (data_channel_type_ == cricket::DCT_SCTP) {
if (new_config.id < 0) {
- if (!mediastream_signaling_->AllocateSctpId(&new_config.id)) {
+ talk_base::SSLRole role;
+ if (GetSslRole(&role) &&
+ !mediastream_signaling_->AllocateSctpSid(role, &new_config.id)) {
LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
return NULL;
}
- } else if (!mediastream_signaling_->IsSctpIdAvailable(new_config.id)) {
+ } else if (!mediastream_signaling_->IsSctpSidAvailable(new_config.id)) {
LOG(LS_ERROR) << "Failed to create a SCTP data channel "
<< "because the id is already in use or out of range.";
return NULL;
@@ -930,32 +1048,10 @@ talk_base::scoped_refptr<DataChannel> WebRtcSession::CreateDataChannel(
}
talk_base::scoped_refptr<DataChannel> channel(
- DataChannel::Create(this, label, &new_config));
- if (channel == NULL)
- return NULL;
- if (!mediastream_signaling_->AddDataChannel(channel))
+ DataChannel::Create(this, data_channel_type_, label, &new_config));
+ if (channel && !mediastream_signaling_->AddDataChannel(channel))
return NULL;
- if (data_channel_type_ == cricket::DCT_SCTP) {
- if (config == NULL) {
- LOG(LS_WARNING) << "Could not send data channel OPEN message"
- << " because of NULL config.";
- return NULL;
- }
- if (data_channel_.get()) {
- channel->SetReceiveSsrc(new_config.id);
- channel->SetSendSsrc(new_config.id);
- }
- if (!config->negotiated) {
- talk_base::Buffer *payload = new talk_base::Buffer;
- if (!mediastream_signaling_->WriteDataChannelOpenMessage(
- label, *config, payload)) {
- LOG(LS_WARNING) << "Could not write data channel OPEN message";
- }
- // SendControl may queue the message until the data channel's set up,
- // or congestion clears.
- channel->SendControl(payload);
- }
- }
+
return channel;
}
@@ -1268,24 +1364,43 @@ bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
voice_channel_.reset(channel_manager_->CreateVoiceChannel(
this, content->name, true));
- return (voice_channel_ != NULL);
+ if (!voice_channel_.get())
+ return false;
+
+ if (dscp_enabled_) {
+ cricket::AudioOptions options;
+ options.dscp.Set(true);
+ voice_channel_->SetChannelOptions(options);
+ }
+ return true;
}
bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
video_channel_.reset(channel_manager_->CreateVideoChannel(
this, content->name, true, voice_channel_.get()));
- return (video_channel_ != NULL);
+ if (!video_channel_.get())
+ return false;
+
+ if (dscp_enabled_) {
+ cricket::VideoOptions options;
+ options.dscp.Set(true);
+ video_channel_->SetChannelOptions(options);
+ }
+ return true;
}
bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) {
- bool rtcp = (data_channel_type_ == cricket::DCT_RTP);
+ bool sctp = (data_channel_type_ == cricket::DCT_SCTP);
data_channel_.reset(channel_manager_->CreateDataChannel(
- this, content->name, rtcp, data_channel_type_));
+ this, content->name, !sctp, data_channel_type_));
if (!data_channel_.get()) {
return false;
}
- data_channel_->SignalDataReceived.connect(
- this, &WebRtcSession::OnDataReceived);
+ if (sctp) {
+ mediastream_signaling_->OnDataTransportCreatedForSctp();
+ data_channel_->SignalNewStreamReceived.connect(
+ this, &WebRtcSession::OnNewDataChannelReceived);
+ }
return true;
}
@@ -1302,27 +1417,11 @@ void WebRtcSession::CopySavedCandidates(
saved_candidates_.clear();
}
-// Look for OPEN messages and set up data channels in response.
-void WebRtcSession::OnDataReceived(
- cricket::DataChannel* channel,
- const cricket::ReceiveDataParams& params,
- const talk_base::Buffer& payload) {
- if (params.type != cricket::DMT_CONTROL) {
- return;
- }
-
- std::string label;
- DataChannelInit config;
- if (!mediastream_signaling_->ParseDataChannelOpenMessage(
- payload, &label, &config)) {
- LOG(LS_WARNING) << "Failed to parse data channel OPEN message.";
- return;
- }
-
- config.negotiated = true; // This is the negotiation.
-
+void WebRtcSession::OnNewDataChannelReceived(
+ const std::string& label, const DataChannelInit& init) {
+ ASSERT(data_channel_type_ == cricket::DCT_SCTP);
if (!mediastream_signaling_->AddDataChannelFromOpenMessage(
- label, config)) {
+ label, init)) {
LOG(LS_WARNING) << "Failed to create data channel from OPEN message.";
return;
}
@@ -1383,9 +1482,15 @@ bool WebRtcSession::ValidateSessionDescription(
}
// Verify crypto settings.
- if (webrtc_session_desc_factory_->secure() == cricket::SEC_REQUIRED &&
- !VerifyCrypto(sdesc->description())) {
- return BadSdp(source, kSdpWithoutCrypto, error_desc);
+ std::string crypto_error;
+ if (webrtc_session_desc_factory_->Secure() == cricket::SEC_REQUIRED &&
+ !VerifyCrypto(sdesc->description(), dtls_enabled_, &crypto_error)) {
+ return BadSdp(source, crypto_error, error_desc);
+ }
+
+ // Verify ice-ufrag and ice-pwd.
+ if (!VerifyIceUfragPwdPresent(sdesc->description())) {
+ return BadSdp(source, kSdpWithoutIceUfragPwd, error_desc);
}
if (!ValidateBundleSettings(sdesc->description())) {
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.h b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.h
index 0cb049f4983..4c83906ae98 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession.h
@@ -42,20 +42,17 @@
#include "talk/session/media/mediasession.h"
namespace cricket {
-
+class BaseChannel;
class ChannelManager;
class DataChannel;
class StatsReport;
class Transport;
class VideoCapturer;
-class BaseChannel;
class VideoChannel;
class VoiceChannel;
-
} // namespace cricket
namespace webrtc {
-
class IceRestartAnswerLatch;
class MediaStreamSignaling;
class WebRtcSessionDescriptionFactory;
@@ -68,6 +65,8 @@ extern const char kInvalidCandidates[];
extern const char kInvalidSdp[];
extern const char kMlineMismatch[];
extern const char kSdpWithoutCrypto[];
+extern const char kSdpWithoutSdesAndDtlsDisabled[];
+extern const char kSdpWithoutIceUfragPwd[];
extern const char kSessionError[];
extern const char kUpdateStateFailed[];
extern const char kPushDownOfferTDFailed[];
@@ -77,6 +76,7 @@ extern const char kPushDownAnswerTDFailed[];
// ICE state callback interface.
class IceObserver {
public:
+ IceObserver() {}
// Called any time the IceConnectionState changes
virtual void OnIceConnectionChange(
PeerConnectionInterface::IceConnectionState new_state) {}
@@ -92,13 +92,17 @@ class IceObserver {
protected:
~IceObserver() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IceObserver);
};
class WebRtcSession : public cricket::BaseSession,
public AudioProviderInterface,
public DataChannelFactory,
public VideoProviderInterface,
- public DtmfProviderInterface {
+ public DtmfProviderInterface,
+ public DataChannelProviderInterface {
public:
WebRtcSession(cricket::ChannelManager* channel_manager,
talk_base::Thread* signaling_thread,
@@ -107,7 +111,8 @@ class WebRtcSession : public cricket::BaseSession,
MediaStreamSignaling* mediastream_signaling);
virtual ~WebRtcSession();
- bool Initialize(const MediaConstraintsInterface* constraints,
+ bool Initialize(const PeerConnectionFactoryInterface::Options& options,
+ const MediaConstraintsInterface* constraints,
DTLSIdentityServiceInterface* dtls_identity_service);
// Deletes the voice, video and data channel and changes the session state
// to STATE_RECEIVEDTERMINATE.
@@ -127,8 +132,8 @@ class WebRtcSession : public cricket::BaseSession,
return data_channel_.get();
}
- void set_secure_policy(cricket::SecureMediaPolicy secure_policy);
- cricket::SecureMediaPolicy secure_policy() const;
+ void SetSecurePolicy(cricket::SecureMediaPolicy secure_policy);
+ cricket::SecureMediaPolicy SecurePolicy() const;
// Get current ssl role from transport.
bool GetSslRole(talk_base::SSLRole* role);
@@ -180,6 +185,16 @@ class WebRtcSession : public cricket::BaseSession,
int code, int duration);
virtual sigslot::signal0<>* GetOnDestroyedSignal();
+ // Implements DataChannelProviderInterface.
+ virtual bool SendData(const cricket::SendDataParams& params,
+ const talk_base::Buffer& payload,
+ cricket::SendDataResult* result) OVERRIDE;
+ virtual bool ConnectDataChannel(DataChannel* webrtc_data_channel) OVERRIDE;
+ virtual void DisconnectDataChannel(DataChannel* webrtc_data_channel) OVERRIDE;
+ virtual void AddSctpDataStream(uint32 sid) OVERRIDE;
+ virtual void RemoveSctpDataStream(uint32 sid) OVERRIDE;
+ virtual bool ReadyToSendData() const OVERRIDE;
+
talk_base::scoped_refptr<DataChannel> CreateDataChannel(
const std::string& label,
const DataChannelInit* config);
@@ -260,10 +275,8 @@ class WebRtcSession : public cricket::BaseSession,
// The |saved_candidates_| will be cleared after this function call.
void CopySavedCandidates(SessionDescriptionInterface* dest_desc);
- void OnDataReceived(
- cricket::DataChannel* channel,
- const cricket::ReceiveDataParams& params,
- const talk_base::Buffer& payload);
+ void OnNewDataChannelReceived(const std::string& label,
+ const DataChannelInit& init);
bool GetLocalTrackId(uint32 ssrc, std::string* track_id);
bool GetRemoteTrackId(uint32 ssrc, std::string* track_id);
@@ -299,6 +312,9 @@ class WebRtcSession : public cricket::BaseSession,
std::vector<IceCandidateInterface*> saved_candidates_;
// If the remote peer is using a older version of implementation.
bool older_version_remote_peer_;
+ bool dtls_enabled_;
+ // Flag will be set based on the constraint value.
+ bool dscp_enabled_;
// Specifies which kind of data channel is allowed. This is controlled
// by the chrome command-line flag and constraints:
// 1. If chrome command-line switch 'enable-sctp-data-channels' is enabled,
@@ -315,8 +331,9 @@ class WebRtcSession : public cricket::BaseSession,
sigslot::signal0<> SignalVoiceChannelDestroyed;
sigslot::signal0<> SignalVideoChannelDestroyed;
sigslot::signal0<> SignalDataChannelDestroyed;
-};
+ DISALLOW_COPY_AND_ASSIGN(WebRtcSession);
+};
} // namespace webrtc
#endif // TALK_APP_WEBRTC_WEBRTCSESSION_H_
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession_unittest.cc
index 1531e0efc1a..5ec880a1db2 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsession_unittest.cc
@@ -42,6 +42,7 @@
#include "talk/base/logging.h"
#include "talk/base/network.h"
#include "talk/base/physicalsocketserver.h"
+#include "talk/base/ssladapter.h"
#include "talk/base/sslstreamadapter.h"
#include "talk/base/stringutils.h"
#include "talk/base/thread.h"
@@ -80,22 +81,26 @@ using webrtc::FakeConstraints;
using webrtc::IceCandidateCollection;
using webrtc::JsepIceCandidate;
using webrtc::JsepSessionDescription;
+using webrtc::PeerConnectionFactoryInterface;
using webrtc::PeerConnectionInterface;
using webrtc::SessionDescriptionInterface;
using webrtc::StreamCollection;
using webrtc::WebRtcSession;
+using webrtc::kBundleWithoutRtcpMux;
using webrtc::kMlineMismatch;
+using webrtc::kPushDownAnswerTDFailed;
+using webrtc::kPushDownPranswerTDFailed;
using webrtc::kSdpWithoutCrypto;
+using webrtc::kSdpWithoutIceUfragPwd;
+using webrtc::kSdpWithoutSdesAndDtlsDisabled;
using webrtc::kSessionError;
using webrtc::kSetLocalSdpFailed;
using webrtc::kSetRemoteSdpFailed;
-using webrtc::kPushDownAnswerTDFailed;
-using webrtc::kPushDownPranswerTDFailed;
-using webrtc::kBundleWithoutRtcpMux;
-static const SocketAddress kClientAddr1("11.11.11.11", 0);
-static const SocketAddress kClientAddr2("22.22.22.22", 0);
-static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
+static const int kClientAddrPort = 0;
+static const char kClientAddrHost1[] = "11.11.11.11";
+static const char kClientAddrHost2[] = "22.22.22.22";
+static const char kStunAddrHost[] = "99.99.99.1";
static const char kSessionVersion[] = "1";
@@ -109,10 +114,9 @@ static const char kMediaContentName1[] = "video";
static const int kIceCandidatesTimeout = 10000;
-static const cricket::AudioCodec
- kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0);
-static const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
-static const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
+static const char kFakeDtlsFingerprint[] =
+ "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
+ "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
// Add some extra |newlines| to the |message| after |line|.
static void InjectAfter(const std::string& line,
@@ -151,11 +155,17 @@ class MockIceObserver : public webrtc::IceObserver {
// Found a new candidate.
virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
- if (candidate->sdp_mline_index() == kMediaContentIndex0) {
- mline_0_candidates_.push_back(candidate->candidate());
- } else if (candidate->sdp_mline_index() == kMediaContentIndex1) {
- mline_1_candidates_.push_back(candidate->candidate());
+ switch (candidate->sdp_mline_index()) {
+ case kMediaContentIndex0:
+ mline_0_candidates_.push_back(candidate->candidate());
+ break;
+ case kMediaContentIndex1:
+ mline_1_candidates_.push_back(candidate->candidate());
+ break;
+ default:
+ ASSERT(false);
}
+
// The ICE gathering state should always be Gathering when a candidate is
// received (or possibly Completed in the case of the final candidate).
EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
@@ -273,8 +283,10 @@ class WebRtcSessionTest : public testing::Test {
vss_(new talk_base::VirtualSocketServer(pss_.get())),
fss_(new talk_base::FirewallSocketServer(vss_.get())),
ss_scope_(fss_.get()),
- stun_server_(talk_base::Thread::Current(), kStunAddr),
- allocator_(&network_manager_, kStunAddr,
+ stun_socket_addr_(talk_base::SocketAddress(kStunAddrHost,
+ cricket::STUN_SERVER_PORT)),
+ stun_server_(talk_base::Thread::Current(), stun_socket_addr_),
+ allocator_(&network_manager_, stun_socket_addr_,
SocketAddress(), SocketAddress(), SocketAddress()),
mediastream_signaling_(channel_manager_.get()) {
tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
@@ -285,6 +297,14 @@ class WebRtcSessionTest : public testing::Test {
desc_factory_->set_add_legacy_streams(false);
}
+ static void SetUpTestCase() {
+ talk_base::InitializeSSL();
+ }
+
+ static void TearDownTestCase() {
+ talk_base::CleanupSSL();
+ }
+
void AddInterface(const SocketAddress& addr) {
network_manager_.AddInterface(addr);
}
@@ -302,11 +322,14 @@ class WebRtcSessionTest : public testing::Test {
EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
observer_.ice_gathering_state_);
- EXPECT_TRUE(session_->Initialize(constraints_.get(), identity_service));
+ EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
+ identity_service));
}
void InitWithDtmfCodec() {
// Add kTelephoneEventCodec for dtmf test.
+ const cricket::AudioCodec kTelephoneEventCodec(
+ 106, "telephone-event", 8000, 0, 1, 0);
std::vector<cricket::AudioCodec> codecs;
codecs.push_back(kTelephoneEventCodec);
media_engine_->SetAudioCodecs(codecs);
@@ -353,12 +376,12 @@ class WebRtcSessionTest : public testing::Test {
return observer->ReleaseDescription();
}
- bool ChannelsExist() {
+ bool ChannelsExist() const {
return (session_->voice_channel() != NULL &&
session_->video_channel() != NULL);
}
- void CheckTransportChannels() {
+ void CheckTransportChannels() const {
EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
@@ -431,7 +454,6 @@ class WebRtcSessionTest : public testing::Test {
talk_base::ToString(talk_base::CreateRandomId());
identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
tdesc_factory_->set_identity(identity_.get());
- tdesc_factory_->set_digest_algorithm(talk_base::DIGEST_SHA_256);
tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
}
@@ -440,17 +462,9 @@ class WebRtcSessionTest : public testing::Test {
const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
ASSERT_TRUE(audio != NULL);
ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
- if (expected) {
- ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), audio->description.
- identity_fingerprint->algorithm);
- }
const TransportInfo* video = sdp->GetTransportInfoByName("video");
ASSERT_TRUE(video != NULL);
ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
- if (expected) {
- ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), video->description.
- identity_fingerprint->algorithm);
- }
}
void VerifyAnswerFromNonCryptoOffer() {
@@ -510,6 +524,31 @@ class WebRtcSessionTest : public testing::Test {
}
EXPECT_TRUE(expect_equal);
}
+
+ void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
+ std::string *sdp) {
+ const cricket::SessionDescription* desc = current_desc->description();
+ EXPECT_TRUE(current_desc->ToString(sdp));
+
+ const cricket::ContentInfos& contents = desc->contents();
+ cricket::ContentInfos::const_iterator it = contents.begin();
+ // Replace ufrag and pwd lines with empty strings.
+ for (; it != contents.end(); ++it) {
+ const cricket::TransportDescription* transport_desc =
+ desc->GetTransportDescriptionByName(it->name);
+ std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
+ + "\r\n";
+ std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
+ + "\r\n";
+ talk_base::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
+ "", 0,
+ sdp);
+ talk_base::replace_substrs(pwd_line.c_str(), pwd_line.length(),
+ "", 0,
+ sdp);
+ }
+ }
+
// Creates a remote offer and and applies it as a remote description,
// creates a local answer and applies is as a local description.
// Call mediastream_signaling_.UseOptionsWithStreamX() before this function
@@ -604,6 +643,35 @@ class WebRtcSessionTest : public testing::Test {
kSessionVersion, current_desc);
}
+ JsepSessionDescription* CreateRemoteOfferWithSctpPort(
+ const char* sctp_stream_name, int new_port,
+ cricket::MediaSessionOptions options) {
+ options.data_channel_type = cricket::DCT_SCTP;
+ options.AddStream(cricket::MEDIA_TYPE_DATA, "datachannel",
+ sctp_stream_name);
+ return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
+ }
+
+ // Takes ownership of offer_basis (and deletes it).
+ JsepSessionDescription* ChangeSDPSctpPort(
+ int new_port, webrtc::SessionDescriptionInterface *offer_basis) {
+ // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
+ // SessionDescription from the mutated string.
+ const char* default_port_str = "5000";
+ char new_port_str[16];
+ talk_base::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
+ std::string offer_str;
+ offer_basis->ToString(&offer_str);
+ talk_base::replace_substrs(default_port_str, strlen(default_port_str),
+ new_port_str, strlen(new_port_str),
+ &offer_str);
+ JsepSessionDescription* offer = new JsepSessionDescription(
+ offer_basis->type());
+ delete offer_basis;
+ offer->Initialize(offer_str, NULL);
+ return offer;
+ }
+
// Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
// before this function to decide which streams to create.
JsepSessionDescription* CreateRemoteOffer() {
@@ -648,7 +716,7 @@ class WebRtcSessionTest : public testing::Test {
}
void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
- AddInterface(kClientAddr1);
+ AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL);
mediastream_signaling_.SendAudioVideoStream1();
FakeConstraints constraints;
@@ -718,7 +786,7 @@ class WebRtcSessionTest : public testing::Test {
// New -> Checking -> Connected -> Disconnected -> Connected.
// The Gathering state should go: New -> Gathering -> Completed.
void TestLoopbackCall() {
- AddInterface(kClientAddr1);
+ AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL);
mediastream_signaling_.SendAudioVideoStream1();
SessionDescriptionInterface* offer = CreateOffer(NULL);
@@ -753,7 +821,10 @@ class WebRtcSessionTest : public testing::Test {
// Adding firewall rule to block ping requests, which should cause
// transport channel failure.
- fss_->AddRule(false, talk_base::FP_ANY, talk_base::FD_ANY, kClientAddr1);
+ fss_->AddRule(false,
+ talk_base::FP_ANY,
+ talk_base::FD_ANY,
+ talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
observer_.ice_connection_state_,
kIceCandidatesTimeout);
@@ -778,7 +849,10 @@ class WebRtcSessionTest : public testing::Test {
// Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
void AddCNCodecs() {
- // Add kTelephoneEventCodec for dtmf test.
+ const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
+ const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
+
+ // Add kCNCodec for dtmf test.
std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
codecs.push_back(kCNCodec1);
codecs.push_back(kCNCodec2);
@@ -856,9 +930,11 @@ class WebRtcSessionTest : public testing::Test {
talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
talk_base::SocketServerScope ss_scope_;
+ talk_base::SocketAddress stun_socket_addr_;
cricket::TestStunServer stun_server_;
talk_base::FakeNetworkManager network_manager_;
cricket::BasicPortAllocator allocator_;
+ PeerConnectionFactoryInterface::Options options_;
talk_base::scoped_ptr<FakeConstraints> constraints_;
FakeMediaStreamSignaling mediastream_signaling_;
talk_base::scoped_ptr<WebRtcSessionForTest> session_;
@@ -878,7 +954,7 @@ TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
// Verifies that WebRtcSession uses SEC_REQUIRED by default.
TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) {
Init(NULL);
- EXPECT_EQ(cricket::SEC_REQUIRED, session_->secure_policy());
+ EXPECT_EQ(cricket::SEC_REQUIRED, session_->SecurePolicy());
}
TEST_F(WebRtcSessionTest, TestSessionCandidates) {
@@ -896,8 +972,8 @@ TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
}
TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
- AddInterface(kClientAddr1);
- AddInterface(kClientAddr2);
+ AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
+ AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
Init(NULL);
mediastream_signaling_.SendAudioVideoStream1();
InitiateCall();
@@ -907,13 +983,16 @@ TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
}
TEST_F(WebRtcSessionTest, TestStunError) {
- AddInterface(kClientAddr1);
- AddInterface(kClientAddr2);
- fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1);
+ AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
+ AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
+ fss_->AddRule(false,
+ talk_base::FP_UDP,
+ talk_base::FD_ANY,
+ talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL);
mediastream_signaling_.SendAudioVideoStream1();
InitiateCall();
- // Since kClientAddr1 is blocked, not expecting stun candidates for it.
+ // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
@@ -1357,7 +1436,7 @@ TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
// Test that local candidates are added to the local session description and
// that they are retained if the local session description is changed.
TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
- AddInterface(kClientAddr1);
+ AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL);
mediastream_signaling_.SendAudioVideoStream1();
CreateAndSetRemoteOfferAndLocalAnswer();
@@ -1421,7 +1500,7 @@ TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
// Test that offers and answers contains ice candidates when Ice candidates have
// been gathered.
TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
- AddInterface(kClientAddr1);
+ AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
Init(NULL);
mediastream_signaling_.SendAudioVideoStream1();
// Ice is started but candidates are not provided until SetLocalDescription
@@ -1872,8 +1951,8 @@ TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
}
TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
+ options_.disable_encryption = true;
Init(NULL);
- session_->set_secure_policy(cricket::SEC_DISABLED);
mediastream_signaling_.SendAudioVideoStream1();
scoped_ptr<SessionDescriptionInterface> offer(
CreateOffer(NULL));
@@ -1890,6 +1969,31 @@ TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
VerifyAnswerFromCryptoOffer();
}
+// This test verifies that setLocalDescription fails if
+// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
+TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
+ Init(NULL);
+ mediastream_signaling_.SendAudioVideoStream1();
+ talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
+ std::string sdp;
+ RemoveIceUfragPwdLines(offer.get(), &sdp);
+ SessionDescriptionInterface* modified_offer =
+ CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
+ SetLocalDescriptionExpectError(kSdpWithoutIceUfragPwd, modified_offer);
+}
+
+// This test verifies that setRemoteDescription fails if
+// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
+TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
+ Init(NULL);
+ talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
+ std::string sdp;
+ RemoveIceUfragPwdLines(offer.get(), &sdp);
+ SessionDescriptionInterface* modified_offer =
+ CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
+ SetRemoteDescriptionExpectError(kSdpWithoutIceUfragPwd, modified_offer);
+}
+
TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
// This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
// local description is removed by the application, BUNDLE flag should be
@@ -2337,9 +2441,9 @@ TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
// This test verifies the crypto parameter when security is disabled.
TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
+ options_.disable_encryption = true;
Init(NULL);
mediastream_signaling_.SendAudioVideoStream1();
- session_->set_secure_policy(cricket::SEC_DISABLED);
talk_base::scoped_ptr<SessionDescriptionInterface> offer(
CreateOffer(NULL));
@@ -2478,8 +2582,8 @@ TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
constraints_.reset(new FakeConstraints());
constraints_->AddOptional(
webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
- constraints_->AddOptional(
- webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
+ options_.disable_sctp_data_channels = false;
+
InitWithDtls(false);
SetLocalDescriptionWithDataChannel();
@@ -2489,9 +2593,6 @@ TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
- constraints_.reset(new FakeConstraints());
- constraints_->AddOptional(
- webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
InitWithDtls(false);
talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
@@ -2502,9 +2603,6 @@ TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
SetFactoryDtlsSrtp();
- constraints_.reset(new FakeConstraints());
- constraints_->AddOptional(
- webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
InitWithDtls(false);
// Create remote offer with SCTP.
@@ -2524,8 +2622,6 @@ TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
constraints_.reset(new FakeConstraints());
constraints_->AddOptional(
- webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
- constraints_->AddOptional(
webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
InitWithDtls(false);
@@ -2536,15 +2632,75 @@ TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
- constraints_.reset(new FakeConstraints());
- constraints_->AddOptional(
- webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
InitWithDtls(false);
SetLocalDescriptionWithDataChannel();
EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
}
+TEST_F(WebRtcSessionTest, TestDisableSctpDataChannels) {
+ MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
+ options_.disable_sctp_data_channels = true;
+ InitWithDtls(false);
+
+ SetLocalDescriptionWithDataChannel();
+ EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
+}
+
+TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
+ MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
+ const int new_send_port = 9998;
+ const int new_recv_port = 7775;
+
+ InitWithDtls(false);
+ SetFactoryDtlsSrtp();
+
+ // By default, don't actually add the codecs to desc_factory_; they don't
+ // actually get serialized for SCTP in BuildMediaDescription(). Instead,
+ // let the session description get parsed. That'll get the proper codecs
+ // into the stream.
+ cricket::MediaSessionOptions options;
+ JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort(
+ "stream1", new_send_port, options);
+
+ // SetRemoteDescription will take the ownership of the offer.
+ SetRemoteDescriptionWithoutError(offer);
+
+ SessionDescriptionInterface* answer = ChangeSDPSctpPort(
+ new_recv_port, CreateAnswer(NULL));
+ ASSERT_TRUE(answer != NULL);
+
+ // Now set the local description, which'll take ownership of the answer.
+ SetLocalDescriptionWithoutError(answer);
+
+ // TEST PLAN: Set the port number to something new, set it in the SDP,
+ // and pass it all the way down.
+ webrtc::DataChannelInit dci;
+ dci.reliable = true;
+ EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
+ talk_base::scoped_refptr<webrtc::DataChannel> dc =
+ session_->CreateDataChannel("datachannel", &dci);
+
+ cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0);
+ int portnum = -1;
+ ASSERT_TRUE(ch != NULL);
+ ASSERT_EQ(1UL, ch->send_codecs().size());
+ EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id);
+ EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
+ ch->send_codecs()[0].name.c_str()));
+ EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort,
+ &portnum));
+ EXPECT_EQ(new_send_port, portnum);
+
+ ASSERT_EQ(1UL, ch->recv_codecs().size());
+ EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id);
+ EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
+ ch->recv_codecs()[0].name.c_str()));
+ EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort,
+ &portnum));
+ EXPECT_EQ(new_recv_port, portnum);
+}
+
// Verifies that CreateOffer succeeds when CreateOffer is called before async
// identity generation is finished.
TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
@@ -2629,6 +2785,54 @@ TEST_F(WebRtcSessionTest,
VerifyMultipleAsyncCreateDescription(
false, CreateSessionDescriptionRequest::kAnswer);
}
+
+// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
+// offer has no SDES crypto but only DTLS fingerprint.
+TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
+ // Init without DTLS.
+ Init(NULL);
+ // Create a remote offer with secured transport disabled.
+ cricket::MediaSessionOptions options;
+ JsepSessionDescription* offer(CreateRemoteOffer(
+ options, cricket::SEC_DISABLED));
+ // Adds a DTLS fingerprint to the remote offer.
+ cricket::SessionDescription* sdp = offer->description();
+ TransportInfo* audio = sdp->GetTransportInfoByName("audio");
+ ASSERT_TRUE(audio != NULL);
+ ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
+ audio->description.identity_fingerprint.reset(
+ talk_base::SSLFingerprint::CreateFromRfc4572(
+ talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint));
+ SetRemoteDescriptionExpectError(kSdpWithoutSdesAndDtlsDisabled,
+ offer);
+}
+
+// This test verifies DSCP is properly applied on the media channels.
+TEST_F(WebRtcSessionTest, TestDscpConstraint) {
+ constraints_.reset(new FakeConstraints());
+ constraints_->AddOptional(
+ webrtc::MediaConstraintsInterface::kEnableDscp, true);
+ Init(NULL);
+ mediastream_signaling_.SendAudioVideoStream1();
+ SessionDescriptionInterface* offer = CreateOffer(NULL);
+
+ SetLocalDescriptionWithoutError(offer);
+
+ video_channel_ = media_engine_->GetVideoChannel(0);
+ voice_channel_ = media_engine_->GetVoiceChannel(0);
+
+ ASSERT_TRUE(video_channel_ != NULL);
+ ASSERT_TRUE(voice_channel_ != NULL);
+ cricket::AudioOptions audio_options;
+ EXPECT_TRUE(voice_channel_->GetOptions(&audio_options));
+ cricket::VideoOptions video_options;
+ EXPECT_TRUE(video_channel_->GetOptions(&video_options));
+ EXPECT_TRUE(audio_options.dscp.IsSet());
+ EXPECT_TRUE(audio_options.dscp.GetWithDefaultIfUnset(false));
+ EXPECT_TRUE(video_options.dscp.IsSet());
+ EXPECT_TRUE(video_options.dscp.GetWithDefaultIfUnset(false));
+}
+
// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
// currently fails because upon disconnection and reconnection OnIceComplete is
// called more than once without returning to IceGatheringGathering.
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
index 30c49a718ad..b6f523ce0cf 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
@@ -33,10 +33,10 @@
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/webrtcsession.h"
-namespace webrtc {
+using cricket::MediaSessionOptions;
+namespace webrtc {
namespace {
-
static const char kFailedDueToIdentityFailed[] =
" failed because DTLS identity request failed";
@@ -46,25 +46,24 @@ static const char kWebRTCIdentityName[] = "WebRTC";
static const uint64 kInitSessionVersion = 2;
-typedef cricket::MediaSessionOptions::Stream Stream;
-typedef cricket::MediaSessionOptions::Streams Streams;
-
-static bool CompareStream(const Stream& stream1, const Stream& stream2) {
- return (stream1.id < stream2.id);
+static bool CompareStream(const MediaSessionOptions::Stream& stream1,
+ const MediaSessionOptions::Stream& stream2) {
+ return stream1.id < stream2.id;
}
-static bool SameId(const Stream& stream1, const Stream& stream2) {
- return (stream1.id == stream2.id);
+static bool SameId(const MediaSessionOptions::Stream& stream1,
+ const MediaSessionOptions::Stream& stream2) {
+ return stream1.id == stream2.id;
}
// Checks if each Stream within the |streams| has unique id.
-static bool ValidStreams(const Streams& streams) {
- Streams sorted_streams = streams;
+static bool ValidStreams(const MediaSessionOptions::Streams& streams) {
+ MediaSessionOptions::Streams sorted_streams = streams;
std::sort(sorted_streams.begin(), sorted_streams.end(), CompareStream);
- Streams::iterator it =
+ MediaSessionOptions::Streams::iterator it =
std::adjacent_find(sorted_streams.begin(), sorted_streams.end(),
SameId);
- return (it == sorted_streams.end());
+ return it == sorted_streams.end();
}
enum {
@@ -83,7 +82,6 @@ struct CreateSessionDescriptionMsg : public talk_base::MessageData {
std::string error;
talk_base::scoped_ptr<webrtc::SessionDescriptionInterface> description;
};
-
} // namespace
// static
@@ -130,33 +128,35 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
transport_desc_factory_.set_protocol(cricket::ICEPROTO_HYBRID);
session_desc_factory_.set_add_legacy_streams(false);
// By default SRTP-SDES is enabled in WebRtc.
- set_secure(cricket::SEC_REQUIRED);
-
- if (dtls_enabled) {
- if (identity_service_.get()) {
- identity_request_observer_ =
- new talk_base::RefCountedObject<WebRtcIdentityRequestObserver>();
-
- identity_request_observer_->SignalRequestFailed.connect(
- this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed);
- identity_request_observer_->SignalIdentityReady.connect(
- this, &WebRtcSessionDescriptionFactory::OnIdentityReady);
-
- if (identity_service_->RequestIdentity(kWebRTCIdentityName,
- kWebRTCIdentityName,
- identity_request_observer_)) {
- LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sent DTLS identity request.";
- identity_request_state_ = IDENTITY_WAITING;
- } else {
- LOG(LS_ERROR) << "Failed to send DTLS identity request.";
- identity_request_state_ = IDENTITY_FAILED;
- }
- } else {
+ SetSecure(cricket::SEC_REQUIRED);
+
+ if (!dtls_enabled) {
+ return;
+ }
+
+ if (identity_service_.get()) {
+ identity_request_observer_ =
+ new talk_base::RefCountedObject<WebRtcIdentityRequestObserver>();
+
+ identity_request_observer_->SignalRequestFailed.connect(
+ this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed);
+ identity_request_observer_->SignalIdentityReady.connect(
+ this, &WebRtcSessionDescriptionFactory::OnIdentityReady);
+
+ if (identity_service_->RequestIdentity(kWebRTCIdentityName,
+ kWebRTCIdentityName,
+ identity_request_observer_)) {
+ LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sent DTLS identity request.";
identity_request_state_ = IDENTITY_WAITING;
- // Do not generate the identity in the constructor since the caller has
- // not got a chance to connect to SignalIdentityReady.
- signaling_thread_->Post(this, MSG_GENERATE_IDENTITY, NULL);
+ } else {
+ LOG(LS_ERROR) << "Failed to send DTLS identity request.";
+ identity_request_state_ = IDENTITY_FAILED;
}
+ } else {
+ identity_request_state_ = IDENTITY_WAITING;
+ // Do not generate the identity in the constructor since the caller has
+ // not got a chance to connect to SignalIdentityReady.
+ signaling_thread_->Post(this, MSG_GENERATE_IDENTITY, NULL);
}
}
@@ -261,19 +261,15 @@ void WebRtcSessionDescriptionFactory::CreateAnswer(
}
}
-void WebRtcSessionDescriptionFactory::set_secure(
+void WebRtcSessionDescriptionFactory::SetSecure(
cricket::SecureMediaPolicy secure_policy) {
session_desc_factory_.set_secure(secure_policy);
}
-cricket::SecureMediaPolicy WebRtcSessionDescriptionFactory::secure() const {
+cricket::SecureMediaPolicy WebRtcSessionDescriptionFactory::Secure() const {
return session_desc_factory_.secure();
}
-bool WebRtcSessionDescriptionFactory::waiting_for_identity() const {
- return identity_request_state_ == IDENTITY_WAITING;
-}
-
void WebRtcSessionDescriptionFactory::OnMessage(talk_base::Message* msg) {
switch (msg->message_id) {
case MSG_CREATE_SESSIONDESCRIPTION_SUCCESS: {
@@ -438,7 +434,6 @@ void WebRtcSessionDescriptionFactory::SetIdentity(
SignalIdentityReady(identity);
transport_desc_factory_.set_identity(identity);
- transport_desc_factory_.set_digest_algorithm(talk_base::DIGEST_SHA_256);
transport_desc_factory_.set_secure(cricket::SEC_ENABLED);
while (!create_session_description_requests_.empty()) {
@@ -451,5 +446,4 @@ void WebRtcSessionDescriptionFactory::SetIdentity(
create_session_description_requests_.pop();
}
}
-
} // namespace webrtc
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.h b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.h
index ba34e913749..ca614b4356d 100644
--- a/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.h
+++ b/chromium/third_party/libjingle/source/talk/app/webrtc/webrtcsessiondescriptionfactory.h
@@ -34,21 +34,17 @@
#include "talk/session/media/mediasession.h"
namespace cricket {
-
class ChannelManager;
class TransportDescriptionFactory;
-
} // namespace cricket
namespace webrtc {
-
class CreateSessionDescriptionObserver;
class MediaConstraintsInterface;
class MediaStreamSignaling;
class SessionDescriptionInterface;
class WebRtcSession;
-
// DTLS identity request callback class.
class WebRtcIdentityRequestObserver : public DTLSIdentityRequestObserver,
public sigslot::has_slots<> {
@@ -116,13 +112,15 @@ class WebRtcSessionDescriptionFactory : public talk_base::MessageHandler,
CreateSessionDescriptionObserver* observer,
const MediaConstraintsInterface* constraints);
- void set_secure(cricket::SecureMediaPolicy secure_policy);
- cricket::SecureMediaPolicy secure() const;
+ void SetSecure(cricket::SecureMediaPolicy secure_policy);
+ cricket::SecureMediaPolicy Secure() const;
sigslot::signal1<talk_base::SSLIdentity*> SignalIdentityReady;
// For testing.
- bool waiting_for_identity() const;
+ bool waiting_for_identity() const {
+ return identity_request_state_ == IDENTITY_WAITING;
+ }
private:
enum IdentityRequestState {
@@ -166,7 +164,6 @@ class WebRtcSessionDescriptionFactory : public talk_base::MessageHandler,
DISALLOW_COPY_AND_ASSIGN(WebRtcSessionDescriptionFactory);
};
-
} // namespace webrtc
#endif // TALK_APP_WEBRTC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_
diff --git a/chromium/third_party/libjingle/source/talk/base/asyncpacketsocket.h b/chromium/third_party/libjingle/source/talk/base/asyncpacketsocket.h
index 3b4748f510f..29ab55ffc47 100644
--- a/chromium/third_party/libjingle/source/talk/base/asyncpacketsocket.h
+++ b/chromium/third_party/libjingle/source/talk/base/asyncpacketsocket.h
@@ -31,9 +31,30 @@
#include "talk/base/dscp.h"
#include "talk/base/sigslot.h"
#include "talk/base/socket.h"
+#include "talk/base/timeutils.h"
namespace talk_base {
+// 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<> {
@@ -78,8 +99,9 @@ class AsyncPacketSocket : public sigslot::has_slots<> {
// Emitted each time a packet is read. Used only for UDP and
// connected TCP sockets.
- sigslot::signal4<AsyncPacketSocket*, const char*, size_t,
- const SocketAddress&> SignalReadPacket;
+ 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;
diff --git a/chromium/third_party/libjingle/source/talk/base/asyncresolverinterface.h b/chromium/third_party/libjingle/source/talk/base/asyncresolverinterface.h
new file mode 100644
index 00000000000..4d77c4f8881
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/base/asyncresolverinterface.h
@@ -0,0 +1,64 @@
+/*
+ * libjingle
+ * Copyright 2013, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_BASE_ASYNCRESOLVERINTERFACE_H_
+#define TALK_BASE_ASYNCRESOLVERINTERFACE_H_
+
+#include "talk/base/sigslot.h"
+#include "talk/base/socketaddress.h"
+
+namespace talk_base {
+
+// 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 talk_base
+
+#endif
diff --git a/chromium/third_party/libjingle/source/talk/base/asyncsocket.h b/chromium/third_party/libjingle/source/talk/base/asyncsocket.h
index 3d12984b70d..97859a7527a 100644
--- a/chromium/third_party/libjingle/source/talk/base/asyncsocket.h
+++ b/chromium/third_party/libjingle/source/talk/base/asyncsocket.h
@@ -44,8 +44,16 @@ class AsyncSocket : public Socket {
virtual AsyncSocket* Accept(SocketAddress* paddr) = 0;
- sigslot::signal1<AsyncSocket*> SignalReadEvent; // ready to read
- sigslot::signal1<AsyncSocket*> SignalWriteEvent; // ready to write
+ // 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
};
diff --git a/chromium/third_party/libjingle/source/talk/base/asynctcpsocket.cc b/chromium/third_party/libjingle/source/talk/base/asynctcpsocket.cc
index 517e799c422..d2ae513fd57 100644
--- a/chromium/third_party/libjingle/source/talk/base/asynctcpsocket.cc
+++ b/chromium/third_party/libjingle/source/talk/base/asynctcpsocket.cc
@@ -300,7 +300,8 @@ void AsyncTCPSocket::ProcessInput(char * data, size_t* len) {
if (*len < kPacketLenSize + pkt_len)
return;
- SignalReadPacket(this, data + kPacketLenSize, pkt_len, remote_addr);
+ SignalReadPacket(this, data + kPacketLenSize, pkt_len, remote_addr,
+ CreatePacketTime(0));
*len -= kPacketLenSize + pkt_len;
if (*len > 0) {
diff --git a/chromium/third_party/libjingle/source/talk/base/asyncudpsocket.cc b/chromium/third_party/libjingle/source/talk/base/asyncudpsocket.cc
index 97e5dff9836..50052630d99 100644
--- a/chromium/third_party/libjingle/source/talk/base/asyncudpsocket.cc
+++ b/chromium/third_party/libjingle/source/talk/base/asyncudpsocket.cc
@@ -128,7 +128,8 @@ void AsyncUDPSocket::OnReadEvent(AsyncSocket* socket) {
// 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_, (size_t)len, remote_addr);
+ SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr,
+ CreatePacketTime(0));
}
void AsyncUDPSocket::OnWriteEvent(AsyncSocket* socket) {
diff --git a/chromium/third_party/libjingle/source/talk/base/atomicops.h b/chromium/third_party/libjingle/source/talk/base/atomicops.h
index 94ade69730e..068cd5f3dc2 100644
--- a/chromium/third_party/libjingle/source/talk/base/atomicops.h
+++ b/chromium/third_party/libjingle/source/talk/base/atomicops.h
@@ -79,7 +79,7 @@ class FixedSizeLockFreeQueue {
FixedSizeLockFreeQueue() : pushed_count_(0),
popped_count_(0),
capacity_(0),
- data_(NULL) {}
+ data_() {}
// Constructs an empty queue with the given capacity.
FixedSizeLockFreeQueue(size_t capacity) : pushed_count_(0),
popped_count_(0),
@@ -157,7 +157,7 @@ class FixedSizeLockFreeQueue {
volatile Atomic32 pushed_count_;
volatile Atomic32 popped_count_;
size_t capacity_;
- talk_base::scoped_array<T> data_;
+ talk_base::scoped_ptr<T[]> data_;
DISALLOW_COPY_AND_ASSIGN(FixedSizeLockFreeQueue);
};
diff --git a/chromium/third_party/libjingle/source/talk/base/autodetectproxy.cc b/chromium/third_party/libjingle/source/talk/base/autodetectproxy.cc
index 02cbaade517..a32043c1cad 100644
--- a/chromium/third_party/libjingle/source/talk/base/autodetectproxy.cc
+++ b/chromium/third_party/libjingle/source/talk/base/autodetectproxy.cc
@@ -82,7 +82,10 @@ void AutoDetectProxy::DoWork() {
}
void AutoDetectProxy::OnMessage(Message *msg) {
- if (MSG_TIMEOUT == msg->message_id) {
+ 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
@@ -136,22 +139,24 @@ void AutoDetectProxy::OnMessage(Message *msg) {
}
}
-void AutoDetectProxy::OnResolveResult(SignalThread* thread) {
- if (thread != resolver_) {
+void AutoDetectProxy::OnResolveResult(AsyncResolverInterface* resolver) {
+ if (resolver != resolver_) {
return;
}
- int error = resolver_->error();
+ int error = resolver_->GetError();
if (error == 0) {
LOG(LS_VERBOSE) << "Resolved " << proxy_.address << " to "
<< resolver_->address();
proxy_.address = resolver_->address();
- DoConnect();
+ 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_TIMEOUT);
+ Thread::Current()->Post(this, MSG_UNRESOLVABLE);
}
}
@@ -166,6 +171,7 @@ void AutoDetectProxy::Next() {
if (socket_) {
Thread::Current()->Clear(this, MSG_TIMEOUT);
+ Thread::Current()->Clear(this, MSG_UNRESOLVABLE);
socket_->Close();
Thread::Current()->Dispose(socket_);
socket_ = NULL;
@@ -177,17 +183,18 @@ void AutoDetectProxy::Next() {
if (!resolver_) {
resolver_ = new AsyncResolver();
}
- resolver_->set_address(proxy_.address);
- resolver_->SignalWorkDone.connect(this,
- &AutoDetectProxy::OnResolveResult);
- resolver_->Start();
+ resolver_->SignalDone.connect(this, &AutoDetectProxy::OnResolveResult);
+ resolver_->Start(proxy_.address);
} else {
- DoConnect();
+ if (!DoConnect()) {
+ Thread::Current()->Post(this, MSG_TIMEOUT);
+ return;
+ }
}
Thread::Current()->PostDelayed(timeout, this, MSG_TIMEOUT);
}
-void AutoDetectProxy::DoConnect() {
+bool AutoDetectProxy::DoConnect() {
if (resolver_) {
resolver_->Destroy(false);
resolver_ = NULL;
@@ -197,16 +204,18 @@ void AutoDetectProxy::DoConnect() {
proxy_.address.family(), SOCK_STREAM);
if (!socket_) {
LOG(LS_VERBOSE) << "Unable to create socket for " << proxy_.address;
- return;
+ 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();
}
diff --git a/chromium/third_party/libjingle/source/talk/base/autodetectproxy.h b/chromium/third_party/libjingle/source/talk/base/autodetectproxy.h
index a6ad3d1134a..2cbeb82754e 100644
--- a/chromium/third_party/libjingle/source/talk/base/autodetectproxy.h
+++ b/chromium/third_party/libjingle/source/talk/base/autodetectproxy.h
@@ -42,7 +42,7 @@ namespace talk_base {
// AutoDetectProxy
///////////////////////////////////////////////////////////////////////////////
-class AsyncResolver;
+class AsyncResolverInterface;
class AsyncSocket;
class AutoDetectProxy : public SignalThread {
@@ -72,6 +72,7 @@ class AutoDetectProxy : public SignalThread {
return GetProxySettingsForUrl(agent, url, proxy, true);
}
enum { MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE,
+ MSG_UNRESOLVABLE,
ADP_MSG_FIRST_AVAILABLE};
protected:
@@ -87,14 +88,14 @@ class AutoDetectProxy : public SignalThread {
void OnConnectEvent(AsyncSocket * socket);
void OnReadEvent(AsyncSocket * socket);
void OnCloseEvent(AsyncSocket * socket, int error);
- void OnResolveResult(SignalThread* thread);
- void DoConnect();
+ void OnResolveResult(AsyncResolverInterface* resolver);
+ bool DoConnect();
private:
std::string agent_;
std::string server_url_;
ProxyInfo proxy_;
- AsyncResolver* resolver_;
+ AsyncResolverInterface* resolver_;
AsyncSocket* socket_;
int next_;
diff --git a/chromium/third_party/libjingle/source/talk/base/autodetectproxy_unittest.cc b/chromium/third_party/libjingle/source/talk/base/autodetectproxy_unittest.cc
index 3fca4c6b49c..18241a3e815 100644
--- a/chromium/third_party/libjingle/source/talk/base/autodetectproxy_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/autodetectproxy_unittest.cc
@@ -37,9 +37,16 @@ static const char kPath[] = "/";
static const char kHost[] = "relay.google.com";
static const uint16 kPort = 443;
static const bool kSecure = true;
-// Each of the two stages in AutoDetectProxy has a 2-second time-out, so 5
-// seconds total should be enough.
-static const int kTimeoutMs = 5000;
+// 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:
diff --git a/chromium/third_party/libjingle/source/talk/base/base64.cc b/chromium/third_party/libjingle/source/talk/base/base64.cc
index 7765f107e6d..79b045e80e2 100644
--- a/chromium/third_party/libjingle/source/talk/base/base64.cc
+++ b/chromium/third_party/libjingle/source/talk/base/base64.cc
@@ -20,7 +20,6 @@
#include "talk/base/common.h"
-using std::string;
using std::vector;
namespace talk_base {
@@ -96,7 +95,8 @@ bool Base64::IsBase64Encoded(const std::string& str) {
return true;
}
-void Base64::EncodeFromArray(const void* data, size_t len, string* result) {
+void Base64::EncodeFromArray(const void* data, size_t len,
+ std::string* result) {
ASSERT(NULL != result);
result->clear();
result->resize(((len + 2) / 3) * 4);
@@ -190,8 +190,9 @@ size_t Base64::GetNextQuantum(DecodeFlags parse_flags, bool illegal_pads,
}
bool Base64::DecodeFromArray(const char* data, size_t len, DecodeFlags flags,
- string* result, size_t* data_used) {
- return DecodeFromArrayTemplate<string>(data, len, flags, result, data_used);
+ 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,
diff --git a/chromium/third_party/libjingle/source/talk/base/buffer.h b/chromium/third_party/libjingle/source/talk/base/buffer.h
index 311cfad726c..47096332c58 100644
--- a/chromium/third_party/libjingle/source/talk/base/buffer.h
+++ b/chromium/third_party/libjingle/source/talk/base/buffer.h
@@ -88,7 +88,7 @@ class Buffer {
}
void SetCapacity(size_t capacity) {
if (capacity > capacity_) {
- talk_base::scoped_array<char> data(new char[capacity]);
+ talk_base::scoped_ptr<char[]> data(new char[capacity]);
memcpy(data.get(), data_.get(), length_);
data_.swap(data);
capacity_ = capacity;
@@ -109,7 +109,7 @@ class Buffer {
SetData(data, length);
}
- scoped_array<char> data_;
+ scoped_ptr<char[]> data_;
size_t length_;
size_t capacity_;
};
diff --git a/chromium/third_party/libjingle/source/talk/base/common.h b/chromium/third_party/libjingle/source/talk/base/common.h
index b9aeca4f781..a76748b3905 100644
--- a/chromium/third_party/libjingle/source/talk/base/common.h
+++ b/chromium/third_party/libjingle/source/talk/base/common.h
@@ -25,7 +25,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_COMMON_H_
+#ifndef TALK_BASE_COMMON_H_ // NOLINT
#define TALK_BASE_COMMON_H_
#include "talk/base/basictypes.h"
@@ -64,7 +64,7 @@ inline void Unused(const void*) {}
#define strnicmp(x, y, n) strncasecmp(x, y, n)
#define stricmp(x, y) strcasecmp(x, y)
-// TODO: Remove this. std::max should be used everywhere in the code.
+// 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
@@ -181,9 +181,32 @@ inline bool ImplicitCastToBool(bool result) { return result; }
#if defined(WIN32)
#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
-#endif // TALK_BASE_COMMON_H_
+// 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 // TALK_BASE_COMMON_H_ // NOLINT
diff --git a/chromium/third_party/libjingle/source/talk/base/compile_assert.h b/chromium/third_party/libjingle/source/talk/base/compile_assert.h
new file mode 100644
index 00000000000..7252d080049
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/base/compile_assert.h
@@ -0,0 +1,99 @@
+/*
+ * libjingle
+ * Copyright 2013, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// COMPILE_ASSERT macro, borrowed from google3/base/macros.h.
+#ifndef TALK_BASE_COMPILE_ASSERT_H_
+#define TALK_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 // TALK_BASE_COMPILE_ASSERT_H_
diff --git a/chromium/third_party/libjingle/source/talk/base/constructormagic.h b/chromium/third_party/libjingle/source/talk/base/constructormagic.h
index 8b1f7ffacb2..3023044e95d 100644
--- a/chromium/third_party/libjingle/source/talk/base/constructormagic.h
+++ b/chromium/third_party/libjingle/source/talk/base/constructormagic.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -32,7 +32,10 @@
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
+// 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)
diff --git a/chromium/third_party/libjingle/source/talk/base/cpumonitor.cc b/chromium/third_party/libjingle/source/talk/base/cpumonitor.cc
index 0a708874027..e9b481fdbd9 100644
--- a/chromium/third_party/libjingle/source/talk/base/cpumonitor.cc
+++ b/chromium/third_party/libjingle/source/talk/base/cpumonitor.cc
@@ -210,7 +210,7 @@ float CpuSampler::GetSystemLoad() {
} else {
if (nt_query_system_information) {
ULONG returned_length = 0;
- scoped_array<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> processor_info(
+ scoped_ptr<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[]> processor_info(
new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[cpus_]);
nt_query_system_information(
::SystemProcessorPerformanceInformation,
@@ -281,6 +281,13 @@ float CpuSampler::GetSystemLoad() {
const uint64 cpu_times = nice + system + user;
const uint64 total_times = cpu_times + idle;
#endif // defined(LINUX) || defined(ANDROID)
+
+#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_,
@@ -359,6 +366,12 @@ float CpuSampler::GetProcessLoad() {
(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * kNumMicrosecsPerSec +
usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
#endif // defined(LINUX) || defined(ANDROID)
+
+#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,
diff --git a/chromium/third_party/libjingle/source/talk/base/cpumonitor_unittest.cc b/chromium/third_party/libjingle/source/talk/base/cpumonitor_unittest.cc
index 952b89e73ab..b9f5ba33e77 100644
--- a/chromium/third_party/libjingle/source/talk/base/cpumonitor_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/cpumonitor_unittest.cc
@@ -54,6 +54,9 @@ class BusyThread : public talk_base::Thread {
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;
diff --git a/chromium/third_party/libjingle/source/talk/base/dbus.cc b/chromium/third_party/libjingle/source/talk/base/dbus.cc
index 8e071c7c7a8..78e717a646c 100644
--- a/chromium/third_party/libjingle/source/talk/base/dbus.cc
+++ b/chromium/third_party/libjingle/source/talk/base/dbus.cc
@@ -158,6 +158,10 @@ class DBusMonitor::DBusMonitoringThread : public talk_base::Thread {
ASSERT(filter_list_);
}
+ virtual ~DBusMonitoringThread() {
+ Stop();
+ }
+
// Override virtual method of Thread. Context: worker-thread.
virtual void Run() {
ASSERT(NULL == connection_);
diff --git a/chromium/third_party/libjingle/source/talk/base/fakesslidentity.h b/chromium/third_party/libjingle/source/talk/base/fakesslidentity.h
index f3c44e42255..203bb83bf0d 100644
--- a/chromium/third_party/libjingle/source/talk/base/fakesslidentity.h
+++ b/chromium/third_party/libjingle/source/talk/base/fakesslidentity.h
@@ -28,6 +28,9 @@
#ifndef TALK_BASE_FAKESSLIDENTITY_H_
#define TALK_BASE_FAKESSLIDENTITY_H_
+#include <algorithm>
+#include <vector>
+
#include "talk/base/messagedigest.h"
#include "talk/base/sslidentity.h"
@@ -36,12 +39,31 @@ namespace talk_base {
class FakeSSLCertificate : public talk_base::SSLCertificate {
public:
explicit FakeSSLCertificate(const std::string& data) : data_(data) {}
+ explicit FakeSSLCertificate(const std::vector<std::string>& certs)
+ : data_(certs.front()) {
+ 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());
+ }
+ virtual bool GetSignatureDigestAlgorithm(std::string* algorithm) const {
+ // SHA-1 is chosen because it is available in all build configurations
+ // used for unit testing.
+ *algorithm = DIGEST_SHA_1;
+ return true;
+ }
virtual bool ComputeDigest(const std::string &algorithm,
unsigned char *digest, std::size_t size,
std::size_t *length) const {
@@ -49,13 +71,27 @@ class FakeSSLCertificate : public talk_base::SSLCertificate {
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_;
};
class FakeSSLIdentity : public talk_base::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);
}
diff --git a/chromium/third_party/libjingle/source/talk/base/helpers.cc b/chromium/third_party/libjingle/source/talk/base/helpers.cc
index bda940b87e2..b10a3f742a7 100644
--- a/chromium/third_party/libjingle/source/talk/base/helpers.cc
+++ b/chromium/third_party/libjingle/source/talk/base/helpers.cc
@@ -239,7 +239,7 @@ bool CreateRandomString(size_t len,
const char* table, int table_size,
std::string* str) {
str->clear();
- scoped_array<uint8> bytes(new uint8[len]);
+ scoped_ptr<uint8[]> bytes(new uint8[len]);
if (!Rng().Generate(bytes.get(), len)) {
LOG(LS_ERROR) << "Failed to generate random string!";
return false;
diff --git a/chromium/third_party/libjingle/source/talk/base/httpclient.cc b/chromium/third_party/libjingle/source/talk/base/httpclient.cc
index 5a16676a331..5bee9114b83 100644
--- a/chromium/third_party/libjingle/source/talk/base/httpclient.cc
+++ b/chromium/third_party/libjingle/source/talk/base/httpclient.cc
@@ -316,11 +316,11 @@ void HttpClient::reset() {
base_.abort(HE_OPERATION_CANCELLED);
}
-void HttpClient::OnResolveResult(SignalThread* thread) {
- if (thread != resolver_) {
+void HttpClient::OnResolveResult(AsyncResolverInterface* resolver) {
+ if (resolver != resolver_) {
return;
}
- int error = resolver_->error();
+ int error = resolver_->GetError();
server_ = resolver_->address();
resolver_->Destroy(false);
resolver_ = NULL;
@@ -335,9 +335,8 @@ void HttpClient::OnResolveResult(SignalThread* thread) {
void HttpClient::StartDNSLookup() {
resolver_ = new AsyncResolver();
- resolver_->set_address(server_);
- resolver_->SignalWorkDone.connect(this, &HttpClient::OnResolveResult);
- resolver_->Start();
+ resolver_->SignalDone.connect(this, &HttpClient::OnResolveResult);
+ resolver_->Start(server_);
}
void HttpClient::set_server(const SocketAddress& address) {
diff --git a/chromium/third_party/libjingle/source/talk/base/httpclient.h b/chromium/third_party/libjingle/source/talk/base/httpclient.h
index 2e77b0d181e..03deb228639 100644
--- a/chromium/third_party/libjingle/source/talk/base/httpclient.h
+++ b/chromium/third_party/libjingle/source/talk/base/httpclient.h
@@ -175,7 +175,7 @@ protected:
HttpError OnHeaderAvailable(bool ignore_data, bool chunked, size_t data_size);
void StartDNSLookup();
- void OnResolveResult(SignalThread* thread);
+ void OnResolveResult(AsyncResolverInterface* resolver);
// IHttpNotify Interface
virtual HttpError onHttpHeaderComplete(bool chunked, size_t& data_size);
@@ -199,7 +199,7 @@ private:
scoped_ptr<HttpAuthContext> context_;
DiskCache* cache_;
CacheState cache_state_;
- AsyncResolver* resolver_;
+ AsyncResolverInterface* resolver_;
};
//////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.cc b/chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.cc
index 222621904bd..433844ee481 100644
--- a/chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.cc
+++ b/chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.cc
@@ -109,7 +109,23 @@ bool LateBindingSymbolTable::LoadFromPath(const char *dll_path) {
}
#ifdef POSIX
- handle_ = dlopen(dll_path, RTLD_NOW);
+ handle_ = dlopen(dll_path,
+ // RTLD_NOW front-loads symbol resolution so that errors are
+ // caught early instead of causing a process abort later.
+ // RTLD_LOCAL prevents other modules from automatically
+ // seeing symbol definitions in the newly-loaded tree. This
+ // is necessary for same-named symbols in different ABI
+ // versions of the same library to not explode.
+ RTLD_NOW|RTLD_LOCAL
+#ifdef LINUX
+ // RTLD_DEEPBIND makes symbol dependencies in the
+ // newly-loaded tree prefer to resolve to definitions within
+ // that tree (the default on OS X). This is necessary for
+ // same-named symbols in different ABI versions of the same
+ // library to not explode.
+ |RTLD_DEEPBIND
+#endif
+ ); // NOLINT
#else
#error Not implemented
#endif
diff --git a/chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.h b/chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.h
index a53648bfe54..f4ad5a60989 100644
--- a/chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.h
+++ b/chromium/third_party/libjingle/source/talk/base/latebindingsymboltable.h
@@ -67,6 +67,9 @@ class LateBindingSymbolTable {
bool LoadFromPath(const char *dll_path);
void Unload();
+ // Gets the raw OS handle to the DLL. Be careful what you do with it.
+ DllHandle GetDllHandle() const { return handle_; }
+
private:
void ClearSymbols();
diff --git a/chromium/third_party/libjingle/source/talk/base/libdbusglibsymboltable.cc b/chromium/third_party/libjingle/source/talk/base/libdbusglibsymboltable.cc
index 9c4be7f3d31..6a3ebf3b143 100644
--- a/chromium/third_party/libjingle/source/talk/base/libdbusglibsymboltable.cc
+++ b/chromium/third_party/libjingle/source/talk/base/libdbusglibsymboltable.cc
@@ -33,7 +33,7 @@ namespace talk_base {
#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBDBUS_GLIB_CLASS_NAME
#define LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST LIBDBUS_GLIB_SYMBOLS_LIST
-#define LATE_BINDING_SYMBOL_TABLE_DLL_NAME "libdbus-glib-1.so"
+#define LATE_BINDING_SYMBOL_TABLE_DLL_NAME "libdbus-glib-1.so.2"
#include "talk/base/latebindingsymboltable.cc.def"
} // namespace talk_base
diff --git a/chromium/third_party/libjingle/source/talk/base/linuxwindowpicker_unittest.cc b/chromium/third_party/libjingle/source/talk/base/linuxwindowpicker_unittest.cc
index 5ea9c93fde6..c248bbac2f6 100644
--- a/chromium/third_party/libjingle/source/talk/base/linuxwindowpicker_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/linuxwindowpicker_unittest.cc
@@ -28,6 +28,7 @@
#include "talk/base/gunit.h"
#include "talk/base/linuxwindowpicker.h"
#include "talk/base/logging.h"
+#include "talk/base/testutils.h"
#include "talk/base/windowpicker.h"
#ifndef LINUX
@@ -37,6 +38,7 @@
namespace talk_base {
TEST(LinuxWindowPickerTest, TestGetWindowList) {
+ MAYBE_SKIP_SCREENCAST_TEST();
LinuxWindowPicker window_picker;
WindowDescriptionList descriptions;
window_picker.Init();
@@ -44,6 +46,7 @@ TEST(LinuxWindowPickerTest, TestGetWindowList) {
}
TEST(LinuxWindowPickerTest, TestGetDesktopList) {
+ MAYBE_SKIP_SCREENCAST_TEST();
LinuxWindowPicker window_picker;
DesktopDescriptionList descriptions;
EXPECT_TRUE(window_picker.Init());
diff --git a/chromium/third_party/libjingle/source/talk/base/logging.cc b/chromium/third_party/libjingle/source/talk/base/logging.cc
index 6653d345199..4c7eae172e7 100644
--- a/chromium/third_party/libjingle/source/talk/base/logging.cc
+++ b/chromium/third_party/libjingle/source/talk/base/logging.cc
@@ -123,8 +123,6 @@ LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev,
LogErrorContext err_ctx, int err, const char* module)
: severity_(sev),
warn_slow_logs_delay_(WARN_SLOW_LOGS_DELAY) {
- // Android's logging facility keeps track of timestamp and thread.
-#ifndef ANDROID
if (timestamp_) {
uint32 time = TimeSince(LogStartTime());
// Also ensure WallClockStartTime is initialized, so that it matches
@@ -141,7 +139,6 @@ LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev,
print_stream_ << "[" << std::hex << id << std::dec << "] ";
#endif // WIN32
}
-#endif // !ANDROID
if (severity_ >= ctx_sev_) {
print_stream_ << Describe(sev) << "(" << DescribeFile(file)
diff --git a/chromium/third_party/libjingle/source/talk/base/logging.h b/chromium/third_party/libjingle/source/talk/base/logging.h
index 2f341fa784f..49e126bab0c 100644
--- a/chromium/third_party/libjingle/source/talk/base/logging.h
+++ b/chromium/third_party/libjingle/source/talk/base/logging.h
@@ -41,6 +41,8 @@
// LOG_V(sev) Like LOG(), but sev is a run-time variable of the LoggingSeverity
// type (basically, it just doesn't prepend the namespace).
// LOG_F(sev) Like LOG(), but includes the name of the current function.
+// LOG_T(sev) Like LOG(), but includes the this pointer.
+// LOG_T_F(sev) Like LOG_F(), but includes the this pointer.
// LOG_GLE(M)(sev [, mod]) attempt to add a string description of the
// HRESULT returned by GetLastError. The "M" variant allows searching of a
// DLL's string table for the error description.
@@ -310,8 +312,10 @@ class LogMessageVoidify {
// The _F version prefixes the message with the current function name.
#if (defined(__GNUC__) && defined(_DEBUG)) || defined(WANT_PRETTY_LOG_F)
#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
+#define LOG_T_F(sev) LOG(sev) << this << ": " << __PRETTY_FUNCTION__ << ": "
#else
#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
+#define LOG_T_F(sev) LOG(sev) << this << ": " << __FUNCTION__ << ": "
#endif
#define LOG_CHECK_LEVEL(sev) \
@@ -328,6 +332,8 @@ inline bool LogCheckLevel(LoggingSeverity sev) {
talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \
.stream()
+#define LOG_T(sev) LOG(sev) << this << ": "
+
#else // !LOGGING
// Hopefully, the compiler will optimize away some of this code.
@@ -348,6 +354,8 @@ inline bool LogCheckLevel(LoggingSeverity sev) {
talk_base::ERRCTX_ ## ctx, err , ##__VA_ARGS__) \
.stream()
+#define LOG_T(sev) LOG(sev) << this << ": "
+#define LOG_T_F(sev) LOG(sev) << this << ": " << __FUNCTION__ <<
#endif // !LOGGING
#define LOG_ERRNO_EX(sev, err) \
diff --git a/chromium/third_party/libjingle/source/talk/base/logging_unittest.cc b/chromium/third_party/libjingle/source/talk/base/logging_unittest.cc
index b0c219fa3f9..53cab666cc9 100644
--- a/chromium/third_party/libjingle/source/talk/base/logging_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/logging_unittest.cc
@@ -87,6 +87,12 @@ TEST(LogTest, MultipleStreams) {
// Ensure we don't crash when adding/removing streams while threads are going.
// We should restore the correct global state at the end.
class LogThread : public Thread {
+ public:
+ virtual ~LogThread() {
+ Stop();
+ }
+
+ private:
void Run() {
// LS_SENSITIVE to avoid cluttering up any real logging going on
LOG(LS_SENSITIVE) << "LOG";
diff --git a/chromium/third_party/libjingle/source/talk/base/macasyncsocket.cc b/chromium/third_party/libjingle/source/talk/base/macasyncsocket.cc
index 54ad6046160..7841b4bf596 100644
--- a/chromium/third_party/libjingle/source/talk/base/macasyncsocket.cc
+++ b/chromium/third_party/libjingle/source/talk/base/macasyncsocket.cc
@@ -87,7 +87,7 @@ void MacAsyncSocket::OnResolveResult(SignalThread* thread) {
if (thread != resolver_) {
return;
}
- int error = resolver_->error();
+ int error = resolver_->GetError();
if (error == 0) {
error = DoConnect(resolver_->address());
} else {
@@ -109,10 +109,9 @@ int MacAsyncSocket::Connect(const SocketAddress& addr) {
if (addr.IsUnresolved()) {
LOG(LS_VERBOSE) << "Resolving addr in MacAsyncSocket::Connect";
resolver_ = new AsyncResolver();
- resolver_->set_address(addr);
resolver_->SignalWorkDone.connect(this,
&MacAsyncSocket::OnResolveResult);
- resolver_->Start();
+ resolver_->Start(addr);
state_ = CS_CONNECTING;
return 0;
}
diff --git a/chromium/third_party/libjingle/source/talk/base/maccocoasocketserver_unittest.mm b/chromium/third_party/libjingle/source/talk/base/maccocoasocketserver_unittest.mm
index d6f4b2c11c9..818c30d860c 100644
--- a/chromium/third_party/libjingle/source/talk/base/maccocoasocketserver_unittest.mm
+++ b/chromium/third_party/libjingle/source/talk/base/maccocoasocketserver_unittest.mm
@@ -36,6 +36,9 @@ class WakeThread : public Thread {
public:
WakeThread(SocketServer* ss) : ss_(ss) {
}
+ virtual ~WakeThread() {
+ Stop();
+ }
void Run() {
ss_->WakeUp();
}
diff --git a/chromium/third_party/libjingle/source/talk/base/macsocketserver_unittest.cc b/chromium/third_party/libjingle/source/talk/base/macsocketserver_unittest.cc
index a4a71019dd6..f10aebcde34 100644
--- a/chromium/third_party/libjingle/source/talk/base/macsocketserver_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/macsocketserver_unittest.cc
@@ -37,6 +37,9 @@ class WakeThread : public Thread {
public:
WakeThread(SocketServer* ss) : ss_(ss) {
}
+ virtual ~WakeThread() {
+ Stop();
+ }
void Run() {
ss_->WakeUp();
}
diff --git a/chromium/third_party/libjingle/source/talk/base/macutils.cc b/chromium/third_party/libjingle/source/talk/base/macutils.cc
index c73b0fa6f9d..a1dcc04d424 100644
--- a/chromium/third_party/libjingle/source/talk/base/macutils.cc
+++ b/chromium/third_party/libjingle/source/talk/base/macutils.cc
@@ -38,27 +38,29 @@ namespace talk_base {
///////////////////////////////////////////////////////////////////////////////
bool ToUtf8(const CFStringRef str16, std::string* str8) {
- if ((NULL == str16) || (NULL == str8))
+ if ((NULL == str16) || (NULL == str8)) {
return false;
+ }
size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
- kCFStringEncodingUTF8)
- + 1;
- scoped_array<char> buffer(new char[maxlen]);
+ kCFStringEncodingUTF8) + 1;
+ scoped_ptr<char[]> buffer(new char[maxlen]);
if (!buffer || !CFStringGetCString(str16, buffer.get(), maxlen,
- kCFStringEncodingUTF8))
+ kCFStringEncodingUTF8)) {
return false;
+ }
str8->assign(buffer.get());
return true;
}
bool ToUtf16(const std::string& str8, CFStringRef* str16) {
- if (NULL == str16)
+ if (NULL == str16) {
return false;
+ }
*str16 = CFStringCreateWithBytes(kCFAllocatorDefault,
reinterpret_cast<const UInt8*>(str8.data()),
str8.length(), kCFStringEncodingUTF8,
false);
- return (NULL != *str16);
+ return NULL != *str16;
}
#ifdef OSX
@@ -100,23 +102,25 @@ static bool GetGestalt(OSType ostype, int* value) {
bool GetOSVersion(int* major, int* minor, int* bugfix) {
ASSERT(major && minor && bugfix);
- if (!GetGestalt(gestaltSystemVersion, major))
+ if (!GetGestalt(gestaltSystemVersion, major)) {
return false;
+ }
if (*major < 0x1040) {
*bugfix = *major & 0xF;
*minor = (*major >> 4) & 0xF;
*major = (*major >> 8);
return true;
}
- return GetGestalt(gestaltSystemVersionMajor, major)
- && GetGestalt(gestaltSystemVersionMinor, minor)
- && GetGestalt(gestaltSystemVersionBugFix, bugfix);
+ return GetGestalt(gestaltSystemVersionMajor, major) &&
+ GetGestalt(gestaltSystemVersionMinor, minor) &&
+ GetGestalt(gestaltSystemVersionBugFix, bugfix);
}
MacOSVersionName GetOSVersionName() {
int major = 0, minor = 0, bugfix = 0;
- if (!GetOSVersion(&major, &minor, &bugfix))
+ if (!GetOSVersion(&major, &minor, &bugfix)) {
return kMacOSUnknown;
+ }
if (major > 10) {
return kMacOSNewer;
}
@@ -136,14 +140,17 @@ MacOSVersionName GetOSVersionName() {
return kMacOSLion;
case 8:
return kMacOSMountainLion;
+ case 9:
+ return kMacOSMavericks;
}
return kMacOSNewer;
}
bool GetQuickTimeVersion(std::string* out) {
int ver;
- if (!GetGestalt(gestaltQuickTimeVersion, &ver))
+ if (!GetGestalt(gestaltQuickTimeVersion, &ver)) {
return false;
+ }
std::stringstream ss;
ss << std::hex << ver;
diff --git a/chromium/third_party/libjingle/source/talk/base/macutils.h b/chromium/third_party/libjingle/source/talk/base/macutils.h
index ad5e7ad2be7..17c09ed413c 100644
--- a/chromium/third_party/libjingle/source/talk/base/macutils.h
+++ b/chromium/third_party/libjingle/source/talk/base/macutils.h
@@ -56,7 +56,8 @@ enum MacOSVersionName {
kMacOSSnowLeopard, // 10.6
kMacOSLion, // 10.7
kMacOSMountainLion, // 10.8
- kMacOSNewer, // 10.9+
+ kMacOSMavericks, // 10.9
+ kMacOSNewer, // 10.10+
};
bool GetOSVersion(int* major, int* minor, int* bugfix);
diff --git a/chromium/third_party/libjingle/source/talk/base/macutils_unittest.cc b/chromium/third_party/libjingle/source/talk/base/macutils_unittest.cc
index 25858a27775..dfc211a05b5 100644
--- a/chromium/third_party/libjingle/source/talk/base/macutils_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/macutils_unittest.cc
@@ -30,12 +30,14 @@
TEST(MacUtilsTest, GetOsVersionName) {
talk_base::MacOSVersionName ver = talk_base::GetOSVersionName();
+ LOG(LS_INFO) << "GetOsVersionName " << ver;
EXPECT_NE(talk_base::kMacOSUnknown, ver);
}
TEST(MacUtilsTest, GetQuickTimeVersion) {
std::string version;
EXPECT_TRUE(talk_base::GetQuickTimeVersion(&version));
+ LOG(LS_INFO) << "GetQuickTimeVersion " << version;
}
TEST(MacUtilsTest, RunAppleScriptCompileError) {
diff --git a/chromium/third_party/libjingle/source/talk/base/md5digest_unittest.cc b/chromium/third_party/libjingle/source/talk/base/md5digest_unittest.cc
index 40b19e5a3f2..9232b40aefd 100644
--- a/chromium/third_party/libjingle/source/talk/base/md5digest_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/md5digest_unittest.cc
@@ -38,7 +38,7 @@ std::string Md5(const std::string& input) {
TEST(Md5DigestTest, TestSize) {
Md5Digest md5;
- EXPECT_EQ(16U, Md5Digest::kSize);
+ EXPECT_EQ(16, static_cast<int>(Md5Digest::kSize));
EXPECT_EQ(16U, md5.Size());
}
diff --git a/chromium/third_party/libjingle/source/talk/base/messagedigest.cc b/chromium/third_party/libjingle/source/talk/base/messagedigest.cc
index 6136ae28b3e..d91d0674b5f 100644
--- a/chromium/third_party/libjingle/source/talk/base/messagedigest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/messagedigest.cc
@@ -85,7 +85,7 @@ size_t ComputeDigest(const std::string& alg, const void* input, size_t in_len,
}
std::string ComputeDigest(MessageDigest* digest, const std::string& input) {
- scoped_array<char> output(new char[digest->Size()]);
+ scoped_ptr<char[]> output(new char[digest->Size()]);
ComputeDigest(digest, input.data(), input.size(),
output.get(), digest->Size());
return hex_encode(output.get(), digest->Size());
@@ -120,7 +120,7 @@ size_t ComputeHmac(MessageDigest* digest,
}
// Copy the key to a block-sized buffer to simplify padding.
// If the key is longer than a block, hash it and use the result instead.
- scoped_array<uint8> new_key(new uint8[block_len]);
+ scoped_ptr<uint8[]> new_key(new uint8[block_len]);
if (key_len > block_len) {
ComputeDigest(digest, key, key_len, new_key.get(), block_len);
memset(new_key.get() + digest->Size(), 0, block_len - digest->Size());
@@ -129,13 +129,13 @@ size_t ComputeHmac(MessageDigest* digest,
memset(new_key.get() + key_len, 0, block_len - key_len);
}
// Set up the padding from the key, salting appropriately for each padding.
- scoped_array<uint8> o_pad(new uint8[block_len]), i_pad(new uint8[block_len]);
+ scoped_ptr<uint8[]> o_pad(new uint8[block_len]), i_pad(new uint8[block_len]);
for (size_t i = 0; i < block_len; ++i) {
o_pad[i] = 0x5c ^ new_key[i];
i_pad[i] = 0x36 ^ new_key[i];
}
// Inner hash; hash the inner padding, and then the input buffer.
- scoped_array<uint8> inner(new uint8[digest->Size()]);
+ scoped_ptr<uint8[]> inner(new uint8[digest->Size()]);
digest->Update(i_pad.get(), block_len);
digest->Update(input, in_len);
digest->Finish(inner.get(), digest->Size());
@@ -158,7 +158,7 @@ size_t ComputeHmac(const std::string& alg, const void* key, size_t key_len,
std::string ComputeHmac(MessageDigest* digest, const std::string& key,
const std::string& input) {
- scoped_array<char> output(new char[digest->Size()]);
+ scoped_ptr<char[]> output(new char[digest->Size()]);
ComputeHmac(digest, key.data(), key.size(),
input.data(), input.size(), output.get(), digest->Size());
return hex_encode(output.get(), digest->Size());
diff --git a/chromium/third_party/libjingle/source/talk/base/move.h b/chromium/third_party/libjingle/source/talk/base/move.h
new file mode 100644
index 00000000000..a04b7c897a8
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/base/move.h
@@ -0,0 +1,207 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_
+#define THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_
+
+// Macro with the boilerplate that makes a type move-only in C++03.
+//
+// USAGE
+//
+// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create
+// a "move-only" type. Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be
+// the first line in a class declaration.
+//
+// A class using this macro must call .Pass() (or somehow be an r-value already)
+// before it can be:
+//
+// * Passed as a function argument
+// * Used as the right-hand side of an assignment
+// * Returned from a function
+//
+// Each class will still need to define their own "move constructor" and "move
+// operator=" to make this useful. Here's an example of the macro, the move
+// constructor, and the move operator= from the scoped_ptr class:
+//
+// template <typename T>
+// class scoped_ptr {
+// TALK_MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
+// public:
+// scoped_ptr(RValue& other) : ptr_(other.release()) { }
+// scoped_ptr& operator=(RValue& other) {
+// swap(other);
+// return *this;
+// }
+// };
+//
+// Note that the constructor must NOT be marked explicit.
+//
+// For consistency, the second parameter to the macro should always be RValue
+// unless you have a strong reason to do otherwise. It is only exposed as a
+// macro parameter so that the move constructor and move operator= don't look
+// like they're using a phantom type.
+//
+//
+// HOW THIS WORKS
+//
+// For a thorough explanation of this technique, see:
+//
+// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor
+//
+// The summary is that we take advantage of 2 properties:
+//
+// 1) non-const references will not bind to r-values.
+// 2) C++ can apply one user-defined conversion when initializing a
+// variable.
+//
+// The first lets us disable the copy constructor and assignment operator
+// by declaring private version of them with a non-const reference parameter.
+//
+// For l-values, direct initialization still fails like in
+// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment
+// operators are private.
+//
+// For r-values, the situation is different. The copy constructor and
+// assignment operator are not viable due to (1), so we are trying to call
+// a non-existent constructor and non-existing operator= rather than a private
+// one. Since we have not committed an error quite yet, we can provide an
+// alternate conversion sequence and a constructor. We add
+//
+// * a private struct named "RValue"
+// * a user-defined conversion "operator RValue()"
+// * a "move constructor" and "move operator=" that take the RValue& as
+// their sole parameter.
+//
+// Only r-values will trigger this sequence and execute our "move constructor"
+// or "move operator=." L-values will match the private copy constructor and
+// operator= first giving a "private in this context" error. This combination
+// gives us a move-only type.
+//
+// For signaling a destructive transfer of data from an l-value, we provide a
+// method named Pass() which creates an r-value for the current instance
+// triggering the move constructor or move operator=.
+//
+// Other ways to get r-values is to use the result of an expression like a
+// function call.
+//
+// Here's an example with comments explaining what gets triggered where:
+//
+// class Foo {
+// TALK_MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue);
+//
+// public:
+// ... API ...
+// Foo(RValue other); // Move constructor.
+// Foo& operator=(RValue rhs); // Move operator=
+// };
+//
+// Foo MakeFoo(); // Function that returns a Foo.
+//
+// Foo f;
+// Foo f_copy(f); // ERROR: Foo(Foo&) is private in this context.
+// Foo f_assign;
+// f_assign = f; // ERROR: operator=(Foo&) is private in this context.
+//
+//
+// Foo f(MakeFoo()); // R-value so alternate conversion executed.
+// Foo f_copy(f.Pass()); // R-value so alternate conversion executed.
+// f = f_copy.Pass(); // R-value so alternate conversion executed.
+//
+//
+// IMPLEMENTATION SUBTLETIES WITH RValue
+//
+// The RValue struct is just a container for a pointer back to the original
+// object. It should only ever be created as a temporary, and no external
+// class should ever declare it or use it in a parameter.
+//
+// It is tempting to want to use the RValue type in function parameters, but
+// excluding the limited usage here for the move constructor and move
+// operator=, doing so would mean that the function could take both r-values
+// and l-values equially which is unexpected. See COMPARED To Boost.Move for
+// more details.
+//
+// An alternate, and incorrect, implementation of the RValue class used by
+// Boost.Move makes RValue a fieldless child of the move-only type. RValue&
+// is then used in place of RValue in the various operators. The RValue& is
+// "created" by doing *reinterpret_cast<RValue*>(this). This has the appeal
+// of never creating a temporary RValue struct even with optimizations
+// disabled. Also, by virtue of inheritance you can treat the RValue
+// reference as if it were the move-only type itself. Unfortunately,
+// using the result of this reinterpret_cast<> is actually undefined behavior
+// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer
+// will generate non-working code.
+//
+// In optimized builds, both implementations generate the same assembly so we
+// choose the one that adheres to the standard.
+//
+//
+// COMPARED TO C++11
+//
+// In C++11, you would implement this functionality using an r-value reference
+// and our .Pass() method would be replaced with a call to std::move().
+//
+// This emulation also has a deficiency where it uses up the single
+// user-defined conversion allowed by C++ during initialization. This can
+// cause problems in some API edge cases. For instance, in scoped_ptr, it is
+// impossible to make a function "void Foo(scoped_ptr<Parent> p)" accept a
+// value of type scoped_ptr<Child> even if you add a constructor to
+// scoped_ptr<> that would make it look like it should work. C++11 does not
+// have this deficiency.
+//
+//
+// COMPARED TO Boost.Move
+//
+// Our implementation similar to Boost.Move, but we keep the RValue struct
+// private to the move-only type, and we don't use the reinterpret_cast<> hack.
+//
+// In Boost.Move, RValue is the boost::rv<> template. This type can be used
+// when writing APIs like:
+//
+// void MyFunc(boost::rv<Foo>& f)
+//
+// that can take advantage of rv<> to avoid extra copies of a type. However you
+// would still be able to call this version of MyFunc with an l-value:
+//
+// Foo f;
+// MyFunc(f); // Uh oh, we probably just destroyed |f| w/o calling Pass().
+//
+// unless someone is very careful to also declare a parallel override like:
+//
+// void MyFunc(const Foo& f)
+//
+// that would catch the l-values first. This was declared unsafe in C++11 and
+// a C++11 compiler will explicitly fail MyFunc(f). Unfortunately, we cannot
+// ensure this in C++03.
+//
+// Since we have no need for writing such APIs yet, our implementation keeps
+// RValue private and uses a .Pass() method to do the conversion instead of
+// trying to write a version of "std::move()." Writing an API like std::move()
+// would require the RValue struct to be public.
+//
+//
+// CAVEATS
+//
+// If you include a move-only type as a field inside a class that does not
+// explicitly declare a copy constructor, the containing class's implicit
+// copy constructor will change from Containing(const Containing&) to
+// Containing(Containing&). This can cause some unexpected errors.
+//
+// http://llvm.org/bugs/show_bug.cgi?id=11528
+//
+// The workaround is to explicitly declare your copy constructor.
+//
+#define TALK_MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \
+ private: \
+ struct rvalue_type { \
+ explicit rvalue_type(type* object) : object(object) {} \
+ type* object; \
+ }; \
+ type(type&); \
+ void operator=(type&); \
+ public: \
+ operator rvalue_type() { return rvalue_type(this); } \
+ type Pass() { return type(rvalue_type(this)); } \
+ private:
+
+#endif // THIRD_PARTY_WEBRTC_FILES_TALK_BASE_MOVE_H_
diff --git a/chromium/third_party/libjingle/source/talk/base/natserver.cc b/chromium/third_party/libjingle/source/talk/base/natserver.cc
index 483542591e4..46980487175 100644
--- a/chromium/third_party/libjingle/source/talk/base/natserver.cc
+++ b/chromium/third_party/libjingle/source/talk/base/natserver.cc
@@ -107,7 +107,7 @@ NATServer::~NATServer() {
void NATServer::OnInternalPacket(
AsyncPacketSocket* socket, const char* buf, size_t size,
- const SocketAddress& addr) {
+ const SocketAddress& addr, const PacketTime& packet_time) {
// Read the intended destination from the wire.
SocketAddress dest_addr;
@@ -123,7 +123,7 @@ void NATServer::OnInternalPacket(
ASSERT(iter != int_map_->end());
// Allow the destination to send packets back to the source.
- iter->second->whitelist->insert(dest_addr);
+ iter->second->WhitelistInsert(dest_addr);
// Send the packet to its intended destination.
iter->second->socket->SendTo(buf + length, size - length, dest_addr,
@@ -132,7 +132,7 @@ void NATServer::OnInternalPacket(
void NATServer::OnExternalPacket(
AsyncPacketSocket* socket, const char* buf, size_t size,
- const SocketAddress& remote_addr) {
+ const SocketAddress& remote_addr, const PacketTime& packet_time) {
SocketAddress local_addr = socket->GetLocalAddress();
@@ -141,7 +141,7 @@ void NATServer::OnExternalPacket(
ASSERT(iter != ext_map_->end());
// Allow the NAT to reject this packet.
- if (Filter(iter->second, remote_addr)) {
+ if (ShouldFilterOut(iter->second, remote_addr)) {
LOG(LS_INFO) << "Packet from " << remote_addr.ToSensitiveString()
<< " was filtered out by the NAT.";
return;
@@ -149,7 +149,7 @@ void NATServer::OnExternalPacket(
// Forward this packet to the internal address.
// First prepend the address in a quasi-STUN format.
- scoped_array<char> real_buf(new char[size + kNATEncodedIPv6AddressSize]);
+ scoped_ptr<char[]> real_buf(new char[size + kNATEncodedIPv6AddressSize]);
size_t addrlength = PackAddressForNAT(real_buf.get(),
size + kNATEncodedIPv6AddressSize,
remote_addr);
@@ -173,8 +173,9 @@ void NATServer::Translate(const SocketAddressPair& route) {
socket->SignalReadPacket.connect(this, &NATServer::OnExternalPacket);
}
-bool NATServer::Filter(TransEntry* entry, const SocketAddress& ext_addr) {
- return entry->whitelist->find(ext_addr) == entry->whitelist->end();
+bool NATServer::ShouldFilterOut(TransEntry* entry,
+ const SocketAddress& ext_addr) {
+ return entry->WhitelistContains(ext_addr);
}
NATServer::TransEntry::TransEntry(
@@ -188,4 +189,14 @@ NATServer::TransEntry::~TransEntry() {
delete socket;
}
+void NATServer::TransEntry::WhitelistInsert(const SocketAddress& addr) {
+ CritScope cs(&crit_);
+ whitelist->insert(addr);
+}
+
+bool NATServer::TransEntry::WhitelistContains(const SocketAddress& ext_addr) {
+ CritScope cs(&crit_);
+ return whitelist->find(ext_addr) == whitelist->end();
+}
+
} // namespace talk_base
diff --git a/chromium/third_party/libjingle/source/talk/base/natserver.h b/chromium/third_party/libjingle/source/talk/base/natserver.h
index 0a6083cbbdc..05d3475c92d 100644
--- a/chromium/third_party/libjingle/source/talk/base/natserver.h
+++ b/chromium/third_party/libjingle/source/talk/base/natserver.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2005, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -79,9 +79,11 @@ class NATServer : public sigslot::has_slots<> {
// Packets received on one of the networks.
void OnInternalPacket(AsyncPacketSocket* socket, const char* buf,
- size_t size, const SocketAddress& addr);
+ size_t size, const SocketAddress& addr,
+ const PacketTime& packet_time);
void OnExternalPacket(AsyncPacketSocket* socket, const char* buf,
- size_t size, const SocketAddress& remote_addr);
+ size_t size, const SocketAddress& remote_addr,
+ const PacketTime& packet_time);
private:
typedef std::set<SocketAddress, AddrCmp> AddressSet;
@@ -91,9 +93,13 @@ class NATServer : public sigslot::has_slots<> {
TransEntry(const SocketAddressPair& r, AsyncUDPSocket* s, NAT* nat);
~TransEntry();
+ void WhitelistInsert(const SocketAddress& addr);
+ bool WhitelistContains(const SocketAddress& ext_addr);
+
SocketAddressPair route;
AsyncUDPSocket* socket;
AddressSet* whitelist;
+ CriticalSection crit_;
};
typedef std::map<SocketAddressPair, TransEntry*, RouteCmp> InternalMap;
@@ -103,7 +109,7 @@ class NATServer : public sigslot::has_slots<> {
void Translate(const SocketAddressPair& route);
/* Determines whether the NAT would filter out a packet from this address. */
- bool Filter(TransEntry* entry, const SocketAddress& ext_addr);
+ bool ShouldFilterOut(TransEntry* entry, const SocketAddress& ext_addr);
NAT* nat_;
SocketFactory* internal_;
diff --git a/chromium/third_party/libjingle/source/talk/base/natsocketfactory.cc b/chromium/third_party/libjingle/source/talk/base/natsocketfactory.cc
index a7c4240b3e9..395069e6658 100644
--- a/chromium/third_party/libjingle/source/talk/base/natsocketfactory.cc
+++ b/chromium/third_party/libjingle/source/talk/base/natsocketfactory.cc
@@ -85,7 +85,7 @@ size_t UnpackAddressFromNAT(const char* buf, size_t buf_size,
class NATSocket : public AsyncSocket, public sigslot::has_slots<> {
public:
explicit NATSocket(NATInternalSocketFactory* sf, int family, int type)
- : sf_(sf), family_(family), type_(type), async_(true), connected_(false),
+ : sf_(sf), family_(family), type_(type), connected_(false),
socket_(NULL), buf_(NULL), size_(0) {
}
@@ -154,7 +154,7 @@ class NATSocket : public AsyncSocket, public sigslot::has_slots<> {
return socket_->SendTo(data, size, addr);
}
// This array will be too large for IPv4 packets, but only by 12 bytes.
- scoped_array<char> buf(new char[size + kNATEncodedIPv6AddressSize]);
+ scoped_ptr<char[]> buf(new char[size + kNATEncodedIPv6AddressSize]);
size_t addrlength = PackAddressForNAT(buf.get(),
size + kNATEncodedIPv6AddressSize,
addr);
@@ -312,7 +312,6 @@ class NATSocket : public AsyncSocket, public sigslot::has_slots<> {
NATInternalSocketFactory* sf_;
int family_;
int type_;
- bool async_;
bool connected_;
SocketAddress remote_addr_;
SocketAddress server_addr_; // address of the NAT server
diff --git a/chromium/third_party/libjingle/source/talk/base/nethelpers.cc b/chromium/third_party/libjingle/source/talk/base/nethelpers.cc
index eebc6cfa7ea..e6310ac45fe 100644
--- a/chromium/third_party/libjingle/source/talk/base/nethelpers.cc
+++ b/chromium/third_party/libjingle/source/talk/base/nethelpers.cc
@@ -67,7 +67,27 @@ int ResolveHostname(const std::string& hostname, int family,
}
// AsyncResolver
-AsyncResolver::AsyncResolver() : error_(0) {
+AsyncResolver::AsyncResolver() : error_(-1) {
+}
+
+void AsyncResolver::Start(const SocketAddress& addr) {
+ addr_ = addr;
+ // SignalThred Start will kickoff the resolve process.
+ SignalThread::Start();
+}
+
+bool AsyncResolver::GetResolvedAddress(int family, SocketAddress* addr) const {
+ if (error_ != 0 || addresses_.empty())
+ return false;
+
+ *addr = addr_;
+ for (size_t i = 0; i < addresses_.size(); ++i) {
+ if (family == addresses_[i].family()) {
+ addr->SetIP(addresses_[i]);
+ return true;
+ }
+ }
+ return false;
}
void AsyncResolver::DoWork() {
@@ -76,9 +96,7 @@ void AsyncResolver::DoWork() {
}
void AsyncResolver::OnWorkDone() {
- if (addresses_.size() > 0) {
- addr_.SetIP(addresses_[0]);
- }
+ SignalDone(this);
}
const char* inet_ntop(int af, const void *src, char* dst, socklen_t size) {
@@ -109,7 +127,7 @@ bool HasIPv6Enabled() {
return false;
}
DWORD protbuff_size = 4096;
- scoped_array<char> protocols;
+ scoped_ptr<char[]> protocols;
LPWSAPROTOCOL_INFOW protocol_infos = NULL;
int requested_protocols[2] = {AF_INET6, 0};
diff --git a/chromium/third_party/libjingle/source/talk/base/nethelpers.h b/chromium/third_party/libjingle/source/talk/base/nethelpers.h
index 66f79108f31..a49f48ac7cd 100644
--- a/chromium/third_party/libjingle/source/talk/base/nethelpers.h
+++ b/chromium/third_party/libjingle/source/talk/base/nethelpers.h
@@ -37,25 +37,30 @@
#include <list>
+#include "talk/base/asyncresolverinterface.h"
#include "talk/base/signalthread.h"
#include "talk/base/sigslot.h"
#include "talk/base/socketaddress.h"
namespace talk_base {
+class AsyncResolverTest;
+
// AsyncResolver will perform async DNS resolution, signaling the result on
-// the inherited SignalWorkDone when the operation completes.
-class AsyncResolver : public SignalThread {
+// the SignalDone from AsyncResolverInterface when the operation completes.
+class AsyncResolver : public SignalThread, public AsyncResolverInterface {
public:
AsyncResolver();
+ virtual ~AsyncResolver() {}
+
+ virtual void Start(const SocketAddress& addr);
+ virtual bool GetResolvedAddress(int family, SocketAddress* addr) const;
+ virtual int GetError() const { return error_; }
+ virtual void Destroy(bool wait) { SignalThread::Destroy(wait); }
- const SocketAddress& address() const { return addr_; }
const std::vector<IPAddress>& addresses() const { return addresses_; }
- void set_address(const SocketAddress& addr) { addr_ = addr; }
- int error() const { return error_; }
void set_error(int error) { error_ = error; }
-
protected:
virtual void DoWork();
virtual void OnWorkDone();
diff --git a/chromium/third_party/libjingle/source/talk/base/network.cc b/chromium/third_party/libjingle/source/talk/base/network.cc
index d6367c32b37..d4dda138135 100644
--- a/chromium/third_party/libjingle/source/talk/base/network.cc
+++ b/chromium/third_party/libjingle/source/talk/base/network.cc
@@ -32,10 +32,18 @@
#include "talk/base/network.h"
#ifdef POSIX
+// linux/if.h can't be included at the same time as the posix sys/if.h, and
+// it's transitively required by linux/route.h, so include that version on
+// linux instead of the standard posix one.
+#if defined(ANDROID) || defined(LINUX)
+#include <linux/if.h>
+#include <linux/route.h>
+#else
+#include <net/if.h>
+#endif
#include <sys/socket.h>
#include <sys/utsname.h>
#include <sys/ioctl.h>
-#include <net/if.h>
#include <unistd.h>
#include <errno.h>
#ifdef ANDROID
@@ -173,7 +181,8 @@ void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
}
BasicNetworkManager::BasicNetworkManager()
- : thread_(NULL), sent_first_update_(false), start_count_(0) {
+ : thread_(NULL), sent_first_update_(false), start_count_(0),
+ ignore_non_default_routes_(false) {
}
BasicNetworkManager::~BasicNetworkManager() {
@@ -307,7 +316,7 @@ bool BasicNetworkManager::CreateNetworks(bool include_ignored,
NetworkMap current_networks;
// MSDN recommends a 15KB buffer for the first try at GetAdaptersAddresses.
size_t buffer_size = 16384;
- scoped_array<char> adapter_info(new char[buffer_size]);
+ scoped_ptr<char[]> adapter_info(new char[buffer_size]);
PIP_ADAPTER_ADDRESSES adapter_addrs =
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info.get());
int adapter_flags = (GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST |
@@ -397,14 +406,52 @@ bool BasicNetworkManager::CreateNetworks(bool include_ignored,
}
#endif // WIN32
-bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) {
+#if defined(ANDROID) || defined(LINUX)
+bool IsDefaultRoute(const std::string& network_name) {
+ FileStream fs;
+ if (!fs.Open("/proc/net/route", "r", NULL)) {
+ LOG(LS_WARNING) << "Couldn't read /proc/net/route, skipping default "
+ << "route check (assuming everything is a default route).";
+ return true;
+ } else {
+ std::string line;
+ while (fs.ReadLine(&line) == SR_SUCCESS) {
+ char iface_name[256];
+ unsigned int iface_ip, iface_gw, iface_mask, iface_flags;
+ if (sscanf(line.c_str(),
+ "%255s %8X %8X %4X %*d %*u %*d %8X",
+ iface_name, &iface_ip, &iface_gw,
+ &iface_flags, &iface_mask) == 5 &&
+ network_name == iface_name &&
+ iface_mask == 0 &&
+ (iface_flags & (RTF_UP | RTF_HOST)) == RTF_UP) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+#endif
+
+bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const {
+ // Ignore networks on the explicit ignore list.
+ for (size_t i = 0; i < network_ignore_list_.size(); ++i) {
+ if (network.name() == network_ignore_list_[i]) {
+ return true;
+ }
+ }
#ifdef POSIX
- // Ignore local networks (lo, lo0, etc)
- // Also filter out VMware interfaces, typically named vmnet1 and vmnet8
+ // Filter out VMware interfaces, typically named vmnet1 and vmnet8
if (strncmp(network.name().c_str(), "vmnet", 5) == 0 ||
strncmp(network.name().c_str(), "vnic", 4) == 0) {
return true;
}
+#if defined(ANDROID) || defined(LINUX)
+ // Make sure this is a default route, if we're ignoring non-defaults.
+ if (ignore_non_default_routes_ && !IsDefaultRoute(network.name())) {
+ return true;
+ }
+#endif
#elif defined(WIN32)
// Ignore any HOST side vmware adapters with a description like:
// VMware Virtual Ethernet Adapter for VMnet1
diff --git a/chromium/third_party/libjingle/source/talk/base/network.h b/chromium/third_party/libjingle/source/talk/base/network.h
index f87063da5db..63f3e732fd9 100644
--- a/chromium/third_party/libjingle/source/talk/base/network.h
+++ b/chromium/third_party/libjingle/source/talk/base/network.h
@@ -127,6 +127,18 @@ class BasicNetworkManager : public NetworkManagerBase,
virtual void OnMessage(Message* msg);
bool started() { return start_count_ > 0; }
+ // Sets the network ignore list, which is empty by default. Any network on
+ // the ignore list will be filtered from network enumeration results.
+ void set_network_ignore_list(const std::vector<std::string>& list) {
+ network_ignore_list_ = list;
+ }
+#if defined(ANDROID) || defined(LINUX)
+ // Sets the flag for ignoring non-default routes.
+ void set_ignore_non_default_routes(bool value) {
+ ignore_non_default_routes_ = true;
+ }
+#endif
+
protected:
#if defined(POSIX)
// Separated from CreateNetworks for tests.
@@ -139,7 +151,7 @@ class BasicNetworkManager : public NetworkManagerBase,
bool CreateNetworks(bool include_ignored, NetworkList* networks) const;
// Determines if a network should be ignored.
- static bool IsIgnoredNetwork(const Network& network);
+ bool IsIgnoredNetwork(const Network& network) const;
private:
friend class NetworkTest;
@@ -149,6 +161,8 @@ class BasicNetworkManager : public NetworkManagerBase,
Thread* thread_;
bool sent_first_update_;
int start_count_;
+ std::vector<std::string> network_ignore_list_;
+ bool ignore_non_default_routes_;
};
// Represents a Unix-type network interface, with a name and single address.
diff --git a/chromium/third_party/libjingle/source/talk/base/network_unittest.cc b/chromium/third_party/libjingle/source/talk/base/network_unittest.cc
index ee0f0aa09ea..e11e78daa4a 100644
--- a/chromium/third_party/libjingle/source/talk/base/network_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/network_unittest.cc
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2011, Google Inc.
+ * Copyright 2004 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -37,6 +37,9 @@
#endif
#endif
#include "talk/base/gunit.h"
+#ifdef WIN32
+#include "talk/base/logging.h" // For LOG_GLE
+#endif
namespace talk_base {
@@ -54,8 +57,9 @@ class NetworkTest : public testing::Test, public sigslot::has_slots<> {
network_manager.MergeNetworkList(list, changed);
}
- bool IsIgnoredNetwork(const Network& network) {
- return BasicNetworkManager::IsIgnoredNetwork(network);
+ bool IsIgnoredNetwork(BasicNetworkManager& network_manager,
+ const Network& network) {
+ return network_manager.IsIgnoredNetwork(network);
}
NetworkManager::NetworkList GetNetworks(
@@ -96,11 +100,28 @@ TEST_F(NetworkTest, TestNetworkIgnore) {
IPAddress(0x12345600U), 24);
Network ipv4_network2("test_eth1", "Test Network Adapter 2",
IPAddress(0x00010000U), 16);
- EXPECT_FALSE(IsIgnoredNetwork(ipv4_network1));
- EXPECT_TRUE(IsIgnoredNetwork(ipv4_network2));
+ BasicNetworkManager network_manager;
+ EXPECT_FALSE(IsIgnoredNetwork(network_manager, ipv4_network1));
+ EXPECT_TRUE(IsIgnoredNetwork(network_manager, ipv4_network2));
+}
+
+TEST_F(NetworkTest, TestIgnoreList) {
+ Network ignore_me("ignore_me", "Ignore me please!",
+ IPAddress(0x12345600U), 24);
+ Network include_me("include_me", "Include me please!",
+ IPAddress(0x12345600U), 24);
+ BasicNetworkManager network_manager;
+ EXPECT_FALSE(IsIgnoredNetwork(network_manager, ignore_me));
+ EXPECT_FALSE(IsIgnoredNetwork(network_manager, include_me));
+ std::vector<std::string> ignore_list;
+ ignore_list.push_back("ignore_me");
+ network_manager.set_network_ignore_list(ignore_list);
+ EXPECT_TRUE(IsIgnoredNetwork(network_manager, ignore_me));
+ EXPECT_FALSE(IsIgnoredNetwork(network_manager, include_me));
}
-TEST_F(NetworkTest, TestCreateNetworks) {
+// Test is failing on Windows opt: b/11288214
+TEST_F(NetworkTest, DISABLED_TestCreateNetworks) {
BasicNetworkManager manager;
NetworkManager::NetworkList result = GetNetworks(manager, true);
// We should be able to bind to any addresses we find.
@@ -113,7 +134,7 @@ TEST_F(NetworkTest, TestCreateNetworks) {
IPAddress ip = (*it)->ip();
SocketAddress bindaddress(ip, 0);
bindaddress.SetScopeID((*it)->scope_id());
- // TODO: Make this use talk_base::AsyncSocket once it supports IPv6.
+ // TODO(thaloun): Use talk_base::AsyncSocket once it supports IPv6.
int fd = static_cast<int>(socket(ip.family(), SOCK_STREAM, IPPROTO_TCP));
if (fd > 0) {
size_t ipsize = bindaddress.ToSockAddrStorage(&storage);
@@ -121,6 +142,9 @@ TEST_F(NetworkTest, TestCreateNetworks) {
int success = ::bind(fd,
reinterpret_cast<sockaddr*>(&storage),
static_cast<int>(ipsize));
+#ifdef WIN32
+ if (success) LOG_GLE(LS_ERROR) << "Socket bind failed.";
+#endif
EXPECT_EQ(0, success);
#ifdef WIN32
closesocket(fd);
@@ -469,7 +493,7 @@ TEST_F(NetworkTest, TestIPv6Toggle) {
NetworkManager::NetworkList list;
#ifndef WIN32
// There should be at least one IPv6 network (fe80::/64 should be in there).
- // TODO: Disabling this test on windows for the moment as the test
+ // TODO(thaloun): Disabling this test on windows for the moment as the test
// machines don't seem to have IPv6 installed on them at all.
manager.set_ipv6_enabled(true);
list = GetNetworks(manager, true);
@@ -517,5 +541,49 @@ TEST_F(NetworkTest, TestConvertIfAddrsNoAddress) {
}
#endif // defined(POSIX)
+#if defined(LINUX)
+// If you want to test non-default routes, you can do the following on a linux
+// machine:
+// 1) Load the dummy network driver:
+// sudo modprobe dummy
+// sudo ifconfig dummy0 127.0.0.1
+// 2) Run this test and confirm the output says it found a dummy route (and
+// passes).
+// 3) When done:
+// sudo rmmmod dummy
+TEST_F(NetworkTest, TestIgnoreNonDefaultRoutes) {
+ BasicNetworkManager manager;
+ NetworkManager::NetworkList list;
+ list = GetNetworks(manager, false);
+ bool found_dummy = false;
+ LOG(LS_INFO) << "Looking for dummy network: ";
+ for (NetworkManager::NetworkList::iterator it = list.begin();
+ it != list.end(); ++it) {
+ LOG(LS_INFO) << " Network name: " << (*it)->name();
+ found_dummy |= (*it)->name().find("dummy0") != std::string::npos;
+ }
+ for (NetworkManager::NetworkList::iterator it = list.begin();
+ it != list.end(); ++it) {
+ delete (*it);
+ }
+ if (!found_dummy) {
+ LOG(LS_INFO) << "No dummy found, quitting.";
+ return;
+ }
+ LOG(LS_INFO) << "Found dummy, running again while ignoring non-default "
+ << "routes.";
+ manager.set_ignore_non_default_routes(true);
+ list = GetNetworks(manager, false);
+ for (NetworkManager::NetworkList::iterator it = list.begin();
+ it != list.end(); ++it) {
+ LOG(LS_INFO) << " Network name: " << (*it)->name();
+ EXPECT_TRUE((*it)->name().find("dummy0") == std::string::npos);
+ }
+ for (NetworkManager::NetworkList::iterator it = list.begin();
+ it != list.end(); ++it) {
+ delete (*it);
+ }
+}
+#endif
} // namespace talk_base
diff --git a/chromium/third_party/libjingle/source/talk/base/nssidentity.cc b/chromium/third_party/libjingle/source/talk/base/nssidentity.cc
index c660aee0a51..053035e562e 100644
--- a/chromium/third_party/libjingle/source/talk/base/nssidentity.cc
+++ b/chromium/third_party/libjingle/source/talk/base/nssidentity.cc
@@ -26,6 +26,10 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <algorithm>
+#include <string>
+#include <vector>
+
#if HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
@@ -34,8 +38,6 @@
#include "talk/base/nssidentity.h"
-#include <string>
-
#include "cert.h"
#include "cryptohi.h"
#include "keyhi.h"
@@ -90,6 +92,43 @@ NSSKeyPair *NSSKeyPair::GetReference() {
return new NSSKeyPair(privkey, pubkey);
}
+NSSCertificate::NSSCertificate(CERTCertificate* cert)
+ : certificate_(CERT_DupCertificate(cert)) {
+ ASSERT(certificate_ != NULL);
+}
+
+static void DeleteCert(SSLCertificate* cert) {
+ delete cert;
+}
+
+NSSCertificate::NSSCertificate(CERTCertList* cert_list) {
+ // Copy the first cert into certificate_.
+ CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
+ certificate_ = CERT_DupCertificate(node->cert);
+
+ // Put any remaining certificates into the chain.
+ node = CERT_LIST_NEXT(node);
+ std::vector<SSLCertificate*> certs;
+ for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) {
+ certs.push_back(new NSSCertificate(node->cert));
+ }
+
+ if (!certs.empty())
+ chain_.reset(new SSLCertChain(certs));
+
+ // The SSLCertChain constructor copies its input, so now we have to delete
+ // the originals.
+ std::for_each(certs.begin(), certs.end(), DeleteCert);
+}
+
+NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain)
+ : certificate_(CERT_DupCertificate(cert)) {
+ ASSERT(certificate_ != NULL);
+ if (chain)
+ chain_.reset(chain->Copy());
+}
+
+
NSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) {
std::string der;
if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der))
@@ -105,15 +144,13 @@ NSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) {
if (!cert)
return NULL;
- return new NSSCertificate(cert);
+ NSSCertificate* ret = new NSSCertificate(cert);
+ CERT_DestroyCertificate(cert);
+ return ret;
}
NSSCertificate *NSSCertificate::GetReference() const {
- CERTCertificate *certificate = CERT_DupCertificate(certificate_);
- if (!certificate)
- return NULL;
-
- return new NSSCertificate(certificate);
+ return new NSSCertificate(certificate_, chain_.get());
}
std::string NSSCertificate::ToPEMString() const {
@@ -122,6 +159,10 @@ std::string NSSCertificate::ToPEMString() const {
certificate_->derCert.len);
}
+void NSSCertificate::ToDER(Buffer* der_buffer) const {
+ der_buffer->SetData(certificate_->derCert.data, certificate_->derCert.len);
+}
+
bool NSSCertificate::GetDigestLength(const std::string &algorithm,
std::size_t *length) {
const SECHashObject *ho;
@@ -134,6 +175,54 @@ bool NSSCertificate::GetDigestLength(const std::string &algorithm,
return true;
}
+bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const {
+ // The function sec_DecodeSigAlg in NSS provides this mapping functionality.
+ // Unfortunately it is private, so the functionality must be duplicated here.
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=925165 .
+ SECOidTag sig_alg = SECOID_GetAlgorithmTag(&certificate_->signature);
+ switch (sig_alg) {
+ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
+ *algorithm = DIGEST_MD5;
+ break;
+ case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
+ case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
+ case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
+ case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
+ case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
+ case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
+ case SEC_OID_MISSI_DSS:
+ case SEC_OID_MISSI_KEA_DSS:
+ case SEC_OID_MISSI_KEA_DSS_OLD:
+ case SEC_OID_MISSI_DSS_OLD:
+ *algorithm = DIGEST_SHA_1;
+ break;
+ case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
+ case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
+ case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
+ *algorithm = DIGEST_SHA_224;
+ break;
+ case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
+ case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
+ case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
+ *algorithm = DIGEST_SHA_256;
+ break;
+ case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
+ case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
+ *algorithm = DIGEST_SHA_384;
+ break;
+ case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
+ case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
+ *algorithm = DIGEST_SHA_512;
+ break;
+ default:
+ // Unknown algorithm. There are several unhandled options that are less
+ // common and more complex.
+ algorithm->clear();
+ return false;
+ }
+ return true;
+}
+
bool NSSCertificate::ComputeDigest(const std::string &algorithm,
unsigned char *digest, std::size_t size,
std::size_t *length) const {
@@ -156,6 +245,14 @@ bool NSSCertificate::ComputeDigest(const std::string &algorithm,
return true;
}
+bool NSSCertificate::GetChain(SSLCertChain** chain) const {
+ if (!chain_)
+ return false;
+
+ *chain = chain_->Copy();
+ return true;
+}
+
bool NSSCertificate::Equals(const NSSCertificate *tocompare) const {
if (!certificate_->derCert.len)
return false;
@@ -301,9 +398,9 @@ NSSIdentity *NSSIdentity::Generate(const std::string &common_name) {
fail:
delete keypair;
- CERT_DestroyCertificate(certificate);
done:
+ if (certificate) CERT_DestroyCertificate(certificate);
if (subject_name) CERT_DestroyName(subject_name);
if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki);
if (certreq) CERT_DestroyCertificateRequest(certreq);
diff --git a/chromium/third_party/libjingle/source/talk/base/nssidentity.h b/chromium/third_party/libjingle/source/talk/base/nssidentity.h
index 725c546277c..3f97ebbb619 100644
--- a/chromium/third_party/libjingle/source/talk/base/nssidentity.h
+++ b/chromium/third_party/libjingle/source/talk/base/nssidentity.h
@@ -66,7 +66,10 @@ class NSSKeyPair {
class NSSCertificate : public SSLCertificate {
public:
static NSSCertificate* FromPEMString(const std::string& pem_string);
- explicit NSSCertificate(CERTCertificate* cert) : certificate_(cert) {}
+ // The caller retains ownership of the argument to all the constructors,
+ // and the constructor makes a copy.
+ explicit NSSCertificate(CERTCertificate* cert);
+ explicit NSSCertificate(CERTCertList* cert_list);
virtual ~NSSCertificate() {
if (certificate_)
CERT_DestroyCertificate(certificate_);
@@ -76,24 +79,32 @@ class NSSCertificate : public SSLCertificate {
virtual std::string ToPEMString() const;
+ virtual void ToDER(Buffer* der_buffer) const;
+
+ virtual bool GetSignatureDigestAlgorithm(std::string* algorithm) const;
+
virtual bool ComputeDigest(const std::string& algorithm,
unsigned char* digest, std::size_t size,
std::size_t* length) const;
+ virtual bool GetChain(SSLCertChain** chain) const;
+
CERTCertificate* certificate() { return certificate_; }
// Helper function to get the length of a digest
static bool GetDigestLength(const std::string& algorithm,
std::size_t* length);
- // Comparison
+ // Comparison. Only the certificate itself is considered, not the chain.
bool Equals(const NSSCertificate* tocompare) const;
private:
+ NSSCertificate(CERTCertificate* cert, SSLCertChain* chain);
static bool GetDigestObject(const std::string& algorithm,
const SECHashObject** hash_object);
CERTCertificate* certificate_;
+ scoped_ptr<SSLCertChain> chain_;
DISALLOW_EVIL_CONSTRUCTORS(NSSCertificate);
};
diff --git a/chromium/third_party/libjingle/source/talk/base/nssstreamadapter.cc b/chromium/third_party/libjingle/source/talk/base/nssstreamadapter.cc
index c9a540d521e..185c243f5e5 100644
--- a/chromium/third_party/libjingle/source/talk/base/nssstreamadapter.cc
+++ b/chromium/third_party/libjingle/source/talk/base/nssstreamadapter.cc
@@ -821,6 +821,13 @@ SECStatus NSSStreamAdapter::AuthCertificateHook(void *arg,
if (ok) {
stream->cert_ok_ = true;
+
+ // Record the peer's certificate chain.
+ CERTCertList* cert_list = SSL_PeerCertificateChain(fd);
+ ASSERT(cert_list != NULL);
+
+ stream->peer_certificate_.reset(new NSSCertificate(cert_list));
+ CERT_DestroyCertList(cert_list);
return SECSuccess;
}
diff --git a/chromium/third_party/libjingle/source/talk/base/openssldigest.cc b/chromium/third_party/libjingle/source/talk/base/openssldigest.cc
index bb0e027cfed..3d9276de844 100644
--- a/chromium/third_party/libjingle/source/talk/base/openssldigest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/openssldigest.cc
@@ -98,6 +98,34 @@ bool OpenSSLDigest::GetDigestEVP(const std::string& algorithm,
return true;
}
+bool OpenSSLDigest::GetDigestName(const EVP_MD* md,
+ std::string* algorithm) {
+ ASSERT(md != NULL);
+ ASSERT(algorithm != NULL);
+
+ int md_type = EVP_MD_type(md);
+ if (md_type == NID_md5) {
+ *algorithm = DIGEST_MD5;
+ } else if (md_type == NID_sha1) {
+ *algorithm = DIGEST_SHA_1;
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L
+ } else if (md_type == NID_sha224) {
+ *algorithm = DIGEST_SHA_224;
+ } else if (md_type == NID_sha256) {
+ *algorithm = DIGEST_SHA_256;
+ } else if (md_type == NID_sha384) {
+ *algorithm = DIGEST_SHA_384;
+ } else if (md_type == NID_sha512) {
+ *algorithm = DIGEST_SHA_512;
+#endif
+ } else {
+ algorithm->clear();
+ return false;
+ }
+
+ return true;
+}
+
bool OpenSSLDigest::GetDigestSize(const std::string& algorithm,
size_t* length) {
const EVP_MD *md;
diff --git a/chromium/third_party/libjingle/source/talk/base/openssldigest.h b/chromium/third_party/libjingle/source/talk/base/openssldigest.h
index 0a12189d0a1..d5cf878786a 100644
--- a/chromium/third_party/libjingle/source/talk/base/openssldigest.h
+++ b/chromium/third_party/libjingle/source/talk/base/openssldigest.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2012, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -47,9 +47,12 @@ class OpenSSLDigest : public MessageDigest {
// Outputs the digest value to |buf| with length |len|.
virtual size_t Finish(void* buf, size_t len);
- // Helper function to look up a digest.
+ // Helper function to look up a digest's EVP by name.
static bool GetDigestEVP(const std::string &algorithm,
const EVP_MD** md);
+ // Helper function to look up a digest's name by EVP.
+ static bool GetDigestName(const EVP_MD* md,
+ std::string* algorithm);
// Helper function to get the length of a digest.
static bool GetDigestSize(const std::string &algorithm,
size_t* len);
diff --git a/chromium/third_party/libjingle/source/talk/base/opensslidentity.cc b/chromium/third_party/libjingle/source/talk/base/opensslidentity.cc
index a48c94fd753..4ff76016183 100644
--- a/chromium/third_party/libjingle/source/talk/base/opensslidentity.cc
+++ b/chromium/third_party/libjingle/source/talk/base/opensslidentity.cc
@@ -40,6 +40,7 @@
#include <openssl/rsa.h>
#include <openssl/crypto.h>
+#include "talk/base/checks.h"
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/base/openssldigest.h"
@@ -211,7 +212,9 @@ OpenSSLCertificate* OpenSSLCertificate::Generate(
#ifdef _DEBUG
PrintCert(x509);
#endif
- return new OpenSSLCertificate(x509);
+ OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
+ X509_free(x509);
+ return ret;
}
OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
@@ -224,10 +227,20 @@ OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL,
const_cast<char*>("\0"));
BIO_free(bio);
- if (x509)
- return new OpenSSLCertificate(x509);
- else
+ if (!x509)
return NULL;
+
+ OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
+ X509_free(x509);
+ return ret;
+}
+
+// NOTE: This implementation only functions correctly after InitializeSSL
+// and before CleanupSSL.
+bool OpenSSLCertificate::GetSignatureDigestAlgorithm(
+ std::string* algorithm) const {
+ return OpenSSLDigest::GetDigestName(
+ EVP_get_digestbyobj(x509_->sig_alg->algorithm), algorithm);
}
bool OpenSSLCertificate::ComputeDigest(const std::string &algorithm,
@@ -264,11 +277,14 @@ OpenSSLCertificate::~OpenSSLCertificate() {
std::string OpenSSLCertificate::ToPEMString() const {
BIO* bio = BIO_new(BIO_s_mem());
- if (!bio)
- return NULL;
+ if (!bio) {
+ UNREACHABLE();
+ return std::string();
+ }
if (!PEM_write_bio_X509(bio, x509_)) {
BIO_free(bio);
- return NULL;
+ UNREACHABLE();
+ return std::string();
}
BIO_write(bio, "\0", 1);
char* buffer;
@@ -278,7 +294,29 @@ std::string OpenSSLCertificate::ToPEMString() const {
return ret;
}
+void OpenSSLCertificate::ToDER(Buffer* der_buffer) const {
+ // In case of failure, make sure to leave the buffer empty.
+ der_buffer->SetData(NULL, 0);
+
+ // Calculates the DER representation of the certificate, from scratch.
+ BIO* bio = BIO_new(BIO_s_mem());
+ if (!bio) {
+ UNREACHABLE();
+ return;
+ }
+ if (!i2d_X509_bio(bio, x509_)) {
+ BIO_free(bio);
+ UNREACHABLE();
+ return;
+ }
+ char* data;
+ size_t length = BIO_get_mem_data(bio, &data);
+ der_buffer->SetData(data, length);
+ BIO_free(bio);
+}
+
void OpenSSLCertificate::AddReference() const {
+ ASSERT(x509_ != NULL);
CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
}
diff --git a/chromium/third_party/libjingle/source/talk/base/opensslidentity.h b/chromium/third_party/libjingle/source/talk/base/opensslidentity.h
index ca001b5cfa0..af18c5c4d09 100644
--- a/chromium/third_party/libjingle/source/talk/base/opensslidentity.h
+++ b/chromium/third_party/libjingle/source/talk/base/opensslidentity.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_OPENSSLIDENTITY_H__
-#define TALK_BASE_OPENSSLIDENTITY_H__
+#ifndef TALK_BASE_OPENSSLIDENTITY_H_
+#define TALK_BASE_OPENSSLIDENTITY_H_
#include <openssl/evp.h>
#include <openssl/x509.h>
@@ -72,6 +72,11 @@ class OpenSSLKeyPair {
// which is also reference counted inside the OpenSSL library.
class OpenSSLCertificate : public SSLCertificate {
public:
+ // Caller retains ownership of the X509 object.
+ explicit OpenSSLCertificate(X509* x509) : x509_(x509) {
+ AddReference();
+ }
+
static OpenSSLCertificate* Generate(OpenSSLKeyPair* key_pair,
const std::string& common_name);
static OpenSSLCertificate* FromPEMString(const std::string& pem_string);
@@ -79,7 +84,6 @@ class OpenSSLCertificate : public SSLCertificate {
virtual ~OpenSSLCertificate();
virtual OpenSSLCertificate* GetReference() const {
- AddReference();
return new OpenSSLCertificate(x509_);
}
@@ -87,6 +91,8 @@ class OpenSSLCertificate : public SSLCertificate {
virtual std::string ToPEMString() const;
+ virtual void ToDER(Buffer* der_buffer) const;
+
// Compute the digest of the certificate given algorithm
virtual bool ComputeDigest(const std::string &algorithm,
unsigned char *digest, std::size_t size,
@@ -99,10 +105,16 @@ class OpenSSLCertificate : public SSLCertificate {
std::size_t size,
std::size_t *length);
- private:
- explicit OpenSSLCertificate(X509* x509) : x509_(x509) {
- ASSERT(x509_ != NULL);
+ virtual bool GetSignatureDigestAlgorithm(std::string* algorithm) const;
+
+ virtual bool GetChain(SSLCertChain** chain) const {
+ // Chains are not yet supported when using OpenSSL.
+ // OpenSSLStreamAdapter::SSLVerifyCallback currently requires the remote
+ // certificate to be self-signed.
+ return false;
}
+
+ private:
void AddReference() const;
X509* x509_;
@@ -148,4 +160,4 @@ class OpenSSLIdentity : public SSLIdentity {
} // namespace talk_base
-#endif // TALK_BASE_OPENSSLIDENTITY_H__
+#endif // TALK_BASE_OPENSSLIDENTITY_H_
diff --git a/chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.cc b/chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.cc
index 16021a96bd9..034dfcf9266 100644
--- a/chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.cc
+++ b/chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.cc
@@ -217,6 +217,14 @@ void OpenSSLStreamAdapter::SetPeerCertificate(SSLCertificate* cert) {
peer_certificate_.reset(static_cast<OpenSSLCertificate*>(cert));
}
+bool OpenSSLStreamAdapter::GetPeerCertificate(SSLCertificate** cert) const {
+ if (!peer_certificate_)
+ return false;
+
+ *cert = peer_certificate_->GetReference();
+ return true;
+}
+
bool OpenSSLStreamAdapter::SetPeerCertificateDigest(const std::string
&digest_alg,
const unsigned char*
@@ -857,6 +865,9 @@ int OpenSSLStreamAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
LOG(LS_INFO) <<
"Accepted self-signed peer certificate authority";
ok = 1;
+
+ // Record the peer's certificate.
+ stream->peer_certificate_.reset(new OpenSSLCertificate(cert));
}
}
}
diff --git a/chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.h b/chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.h
index 8e92a10a5fa..3c478187fcc 100644
--- a/chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.h
+++ b/chromium/third_party/libjingle/source/talk/base/opensslstreamadapter.h
@@ -86,6 +86,8 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter {
const unsigned char* digest_val,
size_t digest_len);
+ virtual bool GetPeerCertificate(SSLCertificate** cert) const;
+
virtual int StartSSLWithServer(const char* server_name);
virtual int StartSSLWithPeer();
virtual void SetMode(SSLMode mode);
@@ -190,8 +192,8 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter {
// in traditional mode, the server name that the server's certificate
// must specify. Empty in peer-to-peer mode.
std::string ssl_server_name_;
- // In peer-to-peer mode, the certificate that the peer must
- // present. Empty in traditional mode.
+ // The certificate that the peer must present or did present. Initially
+ // null in traditional mode, until the connection is established.
scoped_ptr<OpenSSLCertificate> peer_certificate_;
// In peer-to-peer mode, the digest of the certificate that
// the peer must present.
diff --git a/chromium/third_party/libjingle/source/talk/base/physicalsocketserver.cc b/chromium/third_party/libjingle/source/talk/base/physicalsocketserver.cc
index f14c3bd69c6..43be440e7bd 100644
--- a/chromium/third_party/libjingle/source/talk/base/physicalsocketserver.cc
+++ b/chromium/third_party/libjingle/source/talk/base/physicalsocketserver.cc
@@ -200,9 +200,8 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
if (addr.IsUnresolved()) {
LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
resolver_ = new AsyncResolver();
- resolver_->set_address(addr);
- resolver_->SignalWorkDone.connect(this, &PhysicalSocket::OnResolveResult);
- resolver_->Start();
+ resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
+ resolver_->Start(addr);
state_ = CS_CONNECTING;
return 0;
}
@@ -222,7 +221,7 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
UpdateLastError();
if (err == 0) {
state_ = CS_CONNECTED;
- } else if (IsBlockingError(error_)) {
+ } else if (IsBlockingError(GetError())) {
state_ = CS_CONNECTING;
enabled_events_ |= DE_CONNECT;
} else {
@@ -234,10 +233,12 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
}
int GetError() const {
+ CritScope cs(&crit_);
return error_;
}
void SetError(int error) {
+ CritScope cs(&crit_);
error_ = error;
}
@@ -290,7 +291,7 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
MaybeRemapSendError();
// We have seen minidumps where this may be false.
ASSERT(sent <= static_cast<int>(cb));
- if ((sent < 0) && IsBlockingError(error_)) {
+ if ((sent < 0) && IsBlockingError(GetError())) {
enabled_events_ |= DE_WRITE;
}
return sent;
@@ -312,7 +313,7 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
MaybeRemapSendError();
// We have seen minidumps where this may be false.
ASSERT(sent <= static_cast<int>(length));
- if ((sent < 0) && IsBlockingError(error_)) {
+ if ((sent < 0) && IsBlockingError(GetError())) {
enabled_events_ |= DE_WRITE;
}
return sent;
@@ -329,16 +330,17 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
// Must turn this back on so that the select() loop will notice the close
// event.
enabled_events_ |= DE_READ;
- error_ = EWOULDBLOCK;
+ SetError(EWOULDBLOCK);
return SOCKET_ERROR;
}
UpdateLastError();
- bool success = (received >= 0) || IsBlockingError(error_);
+ int error = GetError();
+ bool success = (received >= 0) || IsBlockingError(error);
if (udp_ || success) {
enabled_events_ |= DE_READ;
}
if (!success) {
- LOG_F(LS_VERBOSE) << "Error = " << error_;
+ LOG_F(LS_VERBOSE) << "Error = " << error;
}
return received;
}
@@ -352,12 +354,13 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
UpdateLastError();
if ((received >= 0) && (out_addr != NULL))
SocketAddressFromSockAddrStorage(addr_storage, out_addr);
- bool success = (received >= 0) || IsBlockingError(error_);
+ int error = GetError();
+ bool success = (received >= 0) || IsBlockingError(error);
if (udp_ || success) {
enabled_events_ |= DE_READ;
}
if (!success) {
- LOG_F(LS_VERBOSE) << "Error = " << error_;
+ LOG_F(LS_VERBOSE) << "Error = " << error;
}
return received;
}
@@ -408,7 +411,7 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
int EstimateMTU(uint16* mtu) {
SocketAddress addr = GetRemoteAddress();
if (addr.IsAny()) {
- error_ = ENOTCONN;
+ SetError(ENOTCONN);
return -1;
}
@@ -416,7 +419,7 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
// Gets the interface MTU (TTL=1) for the interface used to reach |addr|.
WinPing ping;
if (!ping.IsValid()) {
- error_ = EINVAL; // can't think of a better error ID
+ SetError(EINVAL); // can't think of a better error ID
return -1;
}
int header_size = ICMP_HEADER_SIZE;
@@ -432,7 +435,7 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
ICMP_PING_TIMEOUT_MILLIS,
1, false);
if (result == WinPing::PING_FAIL) {
- error_ = EINVAL; // can't think of a better error ID
+ SetError(EINVAL); // can't think of a better error ID
return -1;
} else if (result != WinPing::PING_TOO_LARGE) {
*mtu = PACKET_MAXIMUMS[level];
@@ -447,7 +450,7 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
// SIOCGIFMTU would work if we knew which interface would be used, but
// figuring that out is pretty complicated. For now we'll return an error
// and let the caller pick a default MTU.
- error_ = EINVAL;
+ SetError(EINVAL);
return -1;
#elif defined(LINUX) || defined(ANDROID)
// Gets the path MTU.
@@ -462,18 +465,22 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
ASSERT((0 <= value) && (value <= 65536));
*mtu = value;
return 0;
+#elif defined(__native_client__)
+ // Most socket operations, including this, will fail in NaCl's sandbox.
+ error_ = EACCES;
+ return -1;
#endif
}
SocketServer* socketserver() { return ss_; }
protected:
- void OnResolveResult(SignalThread* thread) {
- if (thread != resolver_) {
+ void OnResolveResult(AsyncResolverInterface* resolver) {
+ if (resolver != resolver_) {
return;
}
- int error = resolver_->error();
+ int error = resolver_->GetError();
if (error == 0) {
error = DoConnect(resolver_->address());
} else {
@@ -481,13 +488,13 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
}
if (error) {
- error_ = error;
- SignalCloseEvent(this, error_);
+ SetError(error);
+ SignalCloseEvent(this, error);
}
}
void UpdateLastError() {
- error_ = LAST_SYSTEM_ERROR;
+ SetError(LAST_SYSTEM_ERROR);
}
void MaybeRemapSendError() {
@@ -497,8 +504,8 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
// ENOBUFS - The output queue for a network interface is full.
// This generally indicates that the interface has stopped sending,
// but may be caused by transient congestion.
- if (error_ == ENOBUFS) {
- error_ = EWOULDBLOCK;
+ if (GetError() == ENOBUFS) {
+ SetError(EWOULDBLOCK);
}
#endif
}
@@ -530,6 +537,9 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
*slevel = IPPROTO_TCP;
*sopt = TCP_NODELAY;
break;
+ case OPT_DSCP:
+ LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
+ return -1;
default:
ASSERT(false);
return -1;
@@ -542,6 +552,8 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
uint8 enabled_events_;
bool udp_;
int error_;
+ // Protects |error_| that is accessed from different threads.
+ mutable CriticalSection crit_;
ConnState state_;
AsyncResolver* resolver_;
diff --git a/chromium/third_party/libjingle/source/talk/base/profiler.cc b/chromium/third_party/libjingle/source/talk/base/profiler.cc
index 9d0f32bb2d4..4c2aac4163b 100644
--- a/chromium/third_party/libjingle/source/talk/base/profiler.cc
+++ b/chromium/third_party/libjingle/source/talk/base/profiler.cc
@@ -71,8 +71,7 @@ void ProfilerEvent::Start() {
++start_count_;
}
-void ProfilerEvent::Stop() {
- uint64 stop_time = TimeNanos();
+void ProfilerEvent::Stop(uint64 stop_time) {
--start_count_;
ASSERT(start_count_ >= 0);
if (start_count_ == 0) {
@@ -94,6 +93,10 @@ void ProfilerEvent::Stop() {
}
}
+void ProfilerEvent::Stop() {
+ Stop(TimeNanos());
+}
+
double ProfilerEvent::standard_deviation() const {
if (event_count_ <= 1) return 0.0;
return sqrt(sum_of_squared_differences_ / (event_count_ - 1.0));
@@ -105,11 +108,29 @@ Profiler* Profiler::Instance() {
}
void Profiler::StartEvent(const std::string& event_name) {
- events_[event_name].Start();
+ lock_.LockShared();
+ EventMap::iterator it = events_.find(event_name);
+ bool needs_insert = (it == events_.end());
+ lock_.UnlockShared();
+
+ if (needs_insert) {
+ // Need an exclusive lock to modify the map.
+ ExclusiveScope scope(&lock_);
+ it = events_.insert(
+ EventMap::value_type(event_name, ProfilerEvent())).first;
+ }
+
+ it->second.Start();
}
void Profiler::StopEvent(const std::string& event_name) {
- events_[event_name].Stop();
+ // Get the time ASAP, then wait for the lock.
+ uint64 stop_time = TimeNanos();
+ SharedScope scope(&lock_);
+ EventMap::iterator it = events_.find(event_name);
+ if (it != events_.end()) {
+ it->second.Stop(stop_time);
+ }
}
void Profiler::ReportToLog(const char* file, int line,
@@ -118,6 +139,9 @@ void Profiler::ReportToLog(const char* file, int line,
if (!LogMessage::Loggable(severity_to_use)) {
return;
}
+
+ SharedScope scope(&lock_);
+
{ // Output first line.
LogMessage msg(file, line, severity_to_use);
msg.stream() << "=== Profile report ";
@@ -126,16 +150,11 @@ void Profiler::ReportToLog(const char* file, int line,
}
msg.stream() << "===";
}
- typedef std::map<std::string, ProfilerEvent>::const_iterator iterator;
- for (iterator it = events_.begin(); it != events_.end(); ++it) {
+ for (EventMap::const_iterator it = events_.begin();
+ it != events_.end(); ++it) {
if (event_prefix.empty() || it->first.find(event_prefix) == 0) {
LogMessage(file, line, severity_to_use).stream()
- << it->first << " count=" << it->second.event_count()
- << " total=" << FormattedTime(it->second.total_time())
- << " mean=" << FormattedTime(it->second.mean())
- << " min=" << FormattedTime(it->second.minimum())
- << " max=" << FormattedTime(it->second.maximum())
- << " sd=" << it->second.standard_deviation();
+ << it->first << " " << it->second;
}
}
LogMessage(file, line, severity_to_use).stream()
@@ -148,15 +167,17 @@ void Profiler::ReportAllToLog(const char* file, int line,
}
const ProfilerEvent* Profiler::GetEvent(const std::string& event_name) const {
- std::map<std::string, ProfilerEvent>::const_iterator it =
+ SharedScope scope(&lock_);
+ EventMap::const_iterator it =
events_.find(event_name);
return (it == events_.end()) ? NULL : &it->second;
}
bool Profiler::Clear() {
+ ExclusiveScope scope(&lock_);
bool result = true;
// Clear all events that aren't started.
- std::map<std::string, ProfilerEvent>::iterator it = events_.begin();
+ EventMap::iterator it = events_.begin();
while (it != events_.end()) {
if (it->second.is_started()) {
++it; // Can't clear started events.
@@ -168,4 +189,15 @@ bool Profiler::Clear() {
return result;
}
+std::ostream& operator<<(std::ostream& stream,
+ const ProfilerEvent& profiler_event) {
+ stream << "count=" << profiler_event.event_count()
+ << " total=" << FormattedTime(profiler_event.total_time())
+ << " mean=" << FormattedTime(profiler_event.mean())
+ << " min=" << FormattedTime(profiler_event.minimum())
+ << " max=" << FormattedTime(profiler_event.maximum())
+ << " sd=" << profiler_event.standard_deviation();
+ return stream;
+}
+
} // namespace talk_base
diff --git a/chromium/third_party/libjingle/source/talk/base/profiler.h b/chromium/third_party/libjingle/source/talk/base/profiler.h
index 1198b8e2630..90c5c722a30 100644
--- a/chromium/third_party/libjingle/source/talk/base/profiler.h
+++ b/chromium/third_party/libjingle/source/talk/base/profiler.h
@@ -37,7 +37,7 @@
// }
// Another example:
// void StartAsyncProcess() {
-// PROFILE_START("My event");
+// PROFILE_START("My async event");
// DoSomethingAsyncAndThenCall(&Callback);
// }
// void Callback() {
@@ -54,6 +54,7 @@
#include "talk/base/basictypes.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
+#include "talk/base/sharedexclusivelock.h"
// Profiling could be switched via a build flag, but for now, it's always on.
#define ENABLE_PROFILING
@@ -105,6 +106,7 @@ class ProfilerEvent {
ProfilerEvent();
void Start();
void Stop();
+ void Stop(uint64 stop_time);
double standard_deviation() const;
double total_time() const { return total_time_; }
double mean() const { return mean_; }
@@ -142,7 +144,9 @@ class Profiler {
private:
Profiler() {}
- std::map<std::string, ProfilerEvent> events_;
+ typedef std::map<std::string, ProfilerEvent> EventMap;
+ EventMap events_;
+ mutable SharedExclusiveLock lock_;
DISALLOW_COPY_AND_ASSIGN(Profiler);
};
@@ -164,6 +168,9 @@ class ProfilerScope {
DISALLOW_COPY_AND_ASSIGN(ProfilerScope);
};
+std::ostream& operator<<(std::ostream& stream,
+ const ProfilerEvent& profiler_event);
+
} // namespace talk_base
#endif // TALK_BASE_PROFILER_H_
diff --git a/chromium/third_party/libjingle/source/talk/base/scoped_ptr.h b/chromium/third_party/libjingle/source/talk/base/scoped_ptr.h
index 5a8364e10b0..90f743c6285 100644
--- a/chromium/third_party/libjingle/source/talk/base/scoped_ptr.h
+++ b/chromium/third_party/libjingle/source/talk/base/scoped_ptr.h
@@ -1,34 +1,102 @@
-// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
-// Copyright (c) 2001, 2002 Peter Dimov
+// Borrowed from chromium.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Scopers help you manage ownership of a pointer, helping you easily manage the
+// a pointer within a scope, and automatically destroying the pointer at the
+// end of a scope. There are two main classes you will use, which correspond
+// to the operators new/delete and new[]/delete[].
//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
+// Example usage (scoped_ptr<T>):
+// {
+// scoped_ptr<Foo> foo(new Foo("wee"));
+// } // foo goes out of scope, releasing the pointer with it.
//
-// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
+// {
+// scoped_ptr<Foo> foo; // No pointer managed.
+// foo.reset(new Foo("wee")); // Now a pointer is managed.
+// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
+// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
+// foo->Method(); // Foo::Method() called.
+// foo.get()->Method(); // Foo::Method() called.
+// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
+// // manages a pointer.
+// foo.reset(new Foo("wee4")); // foo manages a pointer again.
+// foo.reset(); // Foo("wee4") destroyed, foo no longer
+// // manages a pointer.
+// } // foo wasn't managing a pointer, so nothing was destroyed.
//
+// Example usage (scoped_ptr<T[]>):
+// {
+// scoped_ptr<Foo[]> foo(new Foo[100]);
+// foo.get()->Method(); // Foo::Method on the 0th element.
+// foo[10].Method(); // Foo::Method on the 10th element.
+// }
+//
+// These scopers also implement part of the functionality of C++11 unique_ptr
+// in that they are "movable but not copyable." You can use the scopers in
+// the parameter and return types of functions to signify ownership transfer
+// in to and out of a function. When calling a function that has a scoper
+// as the argument type, it must be called with the result of an analogous
+// scoper's Pass() function or another function that generates a temporary;
+// passing by copy will NOT work. Here is an example using scoped_ptr:
+//
+// void TakesOwnership(scoped_ptr<Foo> arg) {
+// // Do something with arg
+// }
+// scoped_ptr<Foo> CreateFoo() {
+// // No need for calling Pass() because we are constructing a temporary
+// // for the return value.
+// return scoped_ptr<Foo>(new Foo("new"));
+// }
+// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
+// return arg.Pass();
+// }
+//
+// {
+// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
+// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
+// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
+// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
+// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL.
+// }
+//
+// Notice that if you do not call Pass() when returning from PassThru(), or
+// when invoking TakesOwnership(), the code will not compile because scopers
+// are not copyable; they only implement move semantics which require calling
+// the Pass() function to signify a destructive transfer of state. CreateFoo()
+// is different though because we are constructing a temporary on the return
+// line and thus can avoid needing to call Pass().
+//
+// Pass() properly handles upcast in initialization, i.e. you can use a
+// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
+//
+// scoped_ptr<Foo> foo(new Foo());
+// scoped_ptr<FooParent> parent(foo.Pass());
+//
+// PassAs<>() should be used to upcast return value in return statement:
+//
+// scoped_ptr<Foo> CreateFoo() {
+// scoped_ptr<FooChild> result(new FooChild());
+// return result.PassAs<Foo>();
+// }
+//
+// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
+// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
-// scoped_ptr mimics a built-in pointer except that it guarantees deletion
-// of the object pointed to, either on destruction of the scoped_ptr or via
-// an explicit reset(). scoped_ptr is a simple solution for simple needs;
-// use shared_ptr or std::auto_ptr if your needs are more complex.
-
-// scoped_ptr_malloc added in by Google. When one of
-// these goes out of scope, instead of doing a delete or delete[], it
-// calls free(). scoped_ptr_malloc<char> is likely to see much more
-// use than any other specializations.
-
-// release() added in by Google. Use this to conditionally
-// transfer ownership of a heap-allocated object to the caller, usually on
-// method success.
#ifndef TALK_BASE_SCOPED_PTR_H__
#define TALK_BASE_SCOPED_PTR_H__
#include <cstddef> // for std::ptrdiff_t
#include <stdlib.h> // for free() decl
+#include <algorithm> // For std::swap().
+
#include "talk/base/common.h" // for ASSERT
+#include "talk/base/compile_assert.h" // for COMPILE_ASSERT
+#include "talk/base/move.h" // for TALK_MOVE_ONLY_TYPE_FOR_CPP_03
+#include "talk/base/template_util.h" // for is_convertible, is_array
#ifdef _WIN32
namespace std { using ::ptrdiff_t; };
@@ -36,242 +104,487 @@ namespace std { using ::ptrdiff_t; };
namespace talk_base {
-template <typename T>
-class scoped_ptr {
- private:
+// Function object which deletes its parameter, which must be a pointer.
+// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
+// invokes 'delete'. The default deleter for scoped_ptr<T>.
+template <class T>
+struct DefaultDeleter {
+ DefaultDeleter() {}
+ template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
+ // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
+ // if U* is implicitly convertible to T* and U is not an array type.
+ //
+ // Correct implementation should use SFINAE to disable this
+ // constructor. However, since there are no other 1-argument constructors,
+ // using a COMPILE_ASSERT() based on is_convertible<> and requiring
+ // complete types is simpler and will cause compile failures for equivalent
+ // misuses.
+ //
+ // Note, the is_convertible<U*, T*> check also ensures that U is not an
+ // array. T is guaranteed to be a non-array, so any U* where U is an array
+ // cannot convert to T*.
+ enum { T_must_be_complete = sizeof(T) };
+ enum { U_must_be_complete = sizeof(U) };
+ COMPILE_ASSERT((talk_base::is_convertible<U*, T*>::value),
+ U_ptr_must_implicitly_convert_to_T_ptr);
+ }
+ inline void operator()(T* ptr) const {
+ enum { type_must_be_complete = sizeof(T) };
+ delete ptr;
+ }
+};
- T* ptr;
+// Specialization of DefaultDeleter for array types.
+template <class T>
+struct DefaultDeleter<T[]> {
+ inline void operator()(T* ptr) const {
+ enum { type_must_be_complete = sizeof(T) };
+ delete[] ptr;
+ }
- scoped_ptr(scoped_ptr const &);
- scoped_ptr & operator=(scoped_ptr const &);
+ private:
+ // Disable this operator for any U != T because it is undefined to execute
+ // an array delete when the static type of the array mismatches the dynamic
+ // type.
+ //
+ // References:
+ // C++98 [expr.delete]p3
+ // http://cplusplus.github.com/LWG/lwg-defects.html#938
+ template <typename U> void operator()(U* array) const;
+};
- public:
+template <class T, int n>
+struct DefaultDeleter<T[n]> {
+ // Never allow someone to declare something like scoped_ptr<int[10]>.
+ COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
+};
- typedef T element_type;
+// Function object which invokes 'free' on its parameter, which must be
+// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
+//
+// scoped_ptr<int, talk_base::FreeDeleter> foo_ptr(
+// static_cast<int*>(malloc(sizeof(int))));
+struct FreeDeleter {
+ inline void operator()(void* ptr) const {
+ free(ptr);
+ }
+};
- explicit scoped_ptr(T* p = NULL): ptr(p) {}
+namespace internal {
- ~scoped_ptr() {
- typedef char type_must_be_complete[sizeof(T)];
- delete ptr;
+// Minimal implementation of the core logic of scoped_ptr, suitable for
+// reuse in both scoped_ptr and its specializations.
+template <class T, class D>
+class scoped_ptr_impl {
+ public:
+ explicit scoped_ptr_impl(T* p) : data_(p) { }
+
+ // Initializer for deleters that have data parameters.
+ scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
+
+ // Templated constructor that destructively takes the value from another
+ // scoped_ptr_impl.
+ template <typename U, typename V>
+ scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
+ : data_(other->release(), other->get_deleter()) {
+ // We do not support move-only deleters. We could modify our move
+ // emulation to have talk_base::subtle::move() and
+ // talk_base::subtle::forward()
+ // functions that are imperfect emulations of their C++11 equivalents,
+ // but until there's a requirement, just assume deleters are copyable.
}
- void reset(T* p = NULL) {
- typedef char type_must_be_complete[sizeof(T)];
+ template <typename U, typename V>
+ void TakeState(scoped_ptr_impl<U, V>* other) {
+ // See comment in templated constructor above regarding lack of support
+ // for move-only deleters.
+ reset(other->release());
+ get_deleter() = other->get_deleter();
+ }
- if (ptr != p) {
- T* obj = ptr;
- ptr = p;
- // Delete last, in case obj destructor indirectly results in ~scoped_ptr
- delete obj;
+ ~scoped_ptr_impl() {
+ if (data_.ptr != NULL) {
+ // Not using get_deleter() saves one function call in non-optimized
+ // builds.
+ static_cast<D&>(data_)(data_.ptr);
}
}
- T& operator*() const {
- ASSERT(ptr != NULL);
- return *ptr;
+ void reset(T* p) {
+ // This is a self-reset, which is no longer allowed: http://crbug.com/162971
+ if (p != NULL && p == data_.ptr)
+ abort();
+
+ // Note that running data_.ptr = p can lead to undefined behavior if
+ // get_deleter()(get()) deletes this. In order to pevent this, reset()
+ // should update the stored pointer before deleting its old value.
+ //
+ // However, changing reset() to use that behavior may cause current code to
+ // break in unexpected ways. If the destruction of the owned object
+ // dereferences the scoped_ptr when it is destroyed by a call to reset(),
+ // then it will incorrectly dispatch calls to |p| rather than the original
+ // value of |data_.ptr|.
+ //
+ // During the transition period, set the stored pointer to NULL while
+ // deleting the object. Eventually, this safety check will be removed to
+ // prevent the scenario initially described from occuring and
+ // http://crbug.com/176091 can be closed.
+ T* old = data_.ptr;
+ data_.ptr = NULL;
+ if (old != NULL)
+ static_cast<D&>(data_)(old);
+ data_.ptr = p;
}
- T* operator->() const {
- ASSERT(ptr != NULL);
- return ptr;
- }
+ T* get() const { return data_.ptr; }
- T* get() const {
- return ptr;
- }
+ D& get_deleter() { return data_; }
+ const D& get_deleter() const { return data_; }
- void swap(scoped_ptr & b) {
- T* tmp = b.ptr;
- b.ptr = ptr;
- ptr = tmp;
+ void swap(scoped_ptr_impl& p2) {
+ // Standard swap idiom: 'using std::swap' ensures that std::swap is
+ // present in the overload set, but we call swap unqualified so that
+ // any more-specific overloads can be used, if available.
+ using std::swap;
+ swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
+ swap(data_.ptr, p2.data_.ptr);
}
T* release() {
- T* tmp = ptr;
- ptr = NULL;
- return tmp;
+ T* old_ptr = data_.ptr;
+ data_.ptr = NULL;
+ return old_ptr;
}
T** accept() {
- if (ptr) {
- delete ptr;
- ptr = NULL;
- }
- return &ptr;
+ reset(NULL);
+ return &(data_.ptr);
}
T** use() {
- return &ptr;
+ return &(data_.ptr);
}
- // Allow scoped_ptr<T> to be used in boolean expressions, but not
- // implicitly convertible to a real bool (which is dangerous).
- // Borrowed from chromium's scoped_ptr implementation.
- typedef T* scoped_ptr::*Testable;
- operator Testable() const { return ptr ? &scoped_ptr::ptr : NULL; }
-
+ private:
+ // Needed to allow type-converting constructor.
+ template <typename U, typename V> friend class scoped_ptr_impl;
+
+ // Use the empty base class optimization to allow us to have a D
+ // member, while avoiding any space overhead for it when D is an
+ // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
+ // discussion of this technique.
+ struct Data : public D {
+ explicit Data(T* ptr_in) : ptr(ptr_in) {}
+ Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
+ T* ptr;
+ };
+
+ Data data_;
+
+ DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
};
-template<typename T> inline
-void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
- a.swap(b);
-}
+} // namespace internal
+// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
+// automatically deletes the pointer it holds (if any).
+// That is, scoped_ptr<T> owns the T object that it points to.
+// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
+// Also like T*, scoped_ptr<T> is thread-compatible, and once you
+// dereference it, you get the thread safety guarantees of T.
+//
+// The size of scoped_ptr is small. On most compilers, when using the
+// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
+// increase the size proportional to whatever state they need to have. See
+// comments inside scoped_ptr_impl<> for details.
+//
+// Current implementation targets having a strict subset of C++11's
+// unique_ptr<> features. Known deficiencies include not supporting move-only
+// deleteres, function pointers as deleters, and deleters with reference
+// types.
+template <class T, class D = talk_base::DefaultDeleter<T> >
+class scoped_ptr {
+ TALK_MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
+ public:
+ // The element and deleter types.
+ typedef T element_type;
+ typedef D deleter_type;
+
+ // Constructor. Defaults to initializing with NULL.
+ scoped_ptr() : impl_(NULL) { }
+
+ // Constructor. Takes ownership of p.
+ explicit scoped_ptr(element_type* p) : impl_(p) { }
+
+ // Constructor. Allows initialization of a stateful deleter.
+ scoped_ptr(element_type* p, const D& d) : impl_(p, d) { }
+
+ // Constructor. Allows construction from a scoped_ptr rvalue for a
+ // convertible type and deleter.
+ //
+ // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
+ // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
+ // has different post-conditions if D is a reference type. Since this
+ // implementation does not support deleters with reference type,
+ // we do not need a separate move constructor allowing us to avoid one
+ // use of SFINAE. You only need to care about this if you modify the
+ // implementation of scoped_ptr.
+ template <typename U, typename V>
+ scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {
+ COMPILE_ASSERT(!talk_base::is_array<U>::value, U_cannot_be_an_array);
+ }
+ // Constructor. Move constructor for C++03 move emulation of this type.
+ scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
+
+ // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
+ // type and deleter.
+ //
+ // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
+ // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
+ // form has different requirements on for move-only Deleters. Since this
+ // implementation does not support move-only Deleters, we do not need a
+ // separate move assignment operator allowing us to avoid one use of SFINAE.
+ // You only need to care about this if you modify the implementation of
+ // scoped_ptr.
+ template <typename U, typename V>
+ scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
+ COMPILE_ASSERT(!talk_base::is_array<U>::value, U_cannot_be_an_array);
+ impl_.TakeState(&rhs.impl_);
+ return *this;
+ }
-// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
-// is guaranteed, either on destruction of the scoped_array or via an explicit
-// reset(). Use shared_array or std::vector if your needs are more complex.
+ // Reset. Deletes the currently owned object, if any.
+ // Then takes ownership of a new object, if given.
+ void reset(element_type* p = NULL) { impl_.reset(p); }
-template<typename T>
-class scoped_array {
- private:
+ // Accessors to get the owned object.
+ // operator* and operator-> will assert() if there is no current object.
+ element_type& operator*() const {
+ ASSERT(impl_.get() != NULL);
+ return *impl_.get();
+ }
+ element_type* operator->() const {
+ ASSERT(impl_.get() != NULL);
+ return impl_.get();
+ }
+ element_type* get() const { return impl_.get(); }
- T* ptr;
+ // Access to the deleter.
+ deleter_type& get_deleter() { return impl_.get_deleter(); }
+ const deleter_type& get_deleter() const { return impl_.get_deleter(); }
- scoped_array(scoped_array const &);
- scoped_array & operator=(scoped_array const &);
+ // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
+ // implicitly convertible to a real bool (which is dangerous).
+ //
+ // Note that this trick is only safe when the == and != operators
+ // are declared explicitly, as otherwise "scoped_ptr1 ==
+ // scoped_ptr2" will compile but do the wrong thing (i.e., convert
+ // to Testable and then do the comparison).
+ private:
+ typedef talk_base::internal::scoped_ptr_impl<element_type, deleter_type>
+ scoped_ptr::*Testable;
public:
+ operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
- typedef T element_type;
-
- explicit scoped_array(T* p = NULL) : ptr(p) {}
-
- ~scoped_array() {
- typedef char type_must_be_complete[sizeof(T)];
- delete[] ptr;
- }
-
- void reset(T* p = NULL) {
- typedef char type_must_be_complete[sizeof(T)];
+ // Comparison operators.
+ // These return whether two scoped_ptr refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(const element_type* p) const { return impl_.get() == p; }
+ bool operator!=(const element_type* p) const { return impl_.get() != p; }
- if (ptr != p) {
- T* arr = ptr;
- ptr = p;
- // Delete last, in case arr destructor indirectly results in ~scoped_array
- delete [] arr;
- }
- }
-
- T& operator[](std::ptrdiff_t i) const {
- ASSERT(ptr != NULL);
- ASSERT(i >= 0);
- return ptr[i];
+ // Swap two scoped pointers.
+ void swap(scoped_ptr& p2) {
+ impl_.swap(p2.impl_);
}
- T* get() const {
- return ptr;
+ // Release a pointer.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ element_type* release() WARN_UNUSED_RESULT {
+ return impl_.release();
}
- void swap(scoped_array & b) {
- T* tmp = b.ptr;
- b.ptr = ptr;
- ptr = tmp;
+ // Delete the currently held pointer and return a pointer
+ // to allow overwriting of the current pointer address.
+ element_type** accept() WARN_UNUSED_RESULT {
+ return impl_.accept();
}
- T* release() {
- T* tmp = ptr;
- ptr = NULL;
- return tmp;
+ // Return a pointer to the current pointer address.
+ element_type** use() WARN_UNUSED_RESULT {
+ return impl_.use();
}
- T** accept() {
- if (ptr) {
- delete [] ptr;
- ptr = NULL;
- }
- return &ptr;
+ // C++98 doesn't support functions templates with default parameters which
+ // makes it hard to write a PassAs() that understands converting the deleter
+ // while preserving simple calling semantics.
+ //
+ // Until there is a use case for PassAs() with custom deleters, just ignore
+ // the custom deleter.
+ template <typename PassAsType>
+ scoped_ptr<PassAsType> PassAs() {
+ return scoped_ptr<PassAsType>(Pass());
}
- // Allow scoped_array<T> to be used in boolean expressions, but not
- // implicitly convertible to a real bool (which is dangerous).
- // Borrowed from chromium's scoped_array implementation.
- typedef T* scoped_array::*Testable;
- operator Testable() const { return ptr ? &scoped_array::ptr : NULL; }
-};
-
-template<class T> inline
-void swap(scoped_array<T>& a, scoped_array<T>& b) {
- a.swap(b);
-}
-
-// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
-// second template argument, the function used to free the object.
-
-template<typename T, void (*FF)(T*) = free> class scoped_ptr_malloc {
private:
+ // Needed to reach into |impl_| in the constructor.
+ template <typename U, typename V> friend class scoped_ptr;
+ talk_base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
+
+ // Forbidden for API compatibility with std::unique_ptr.
+ explicit scoped_ptr(int disallow_construction_from_null);
+
+ // Forbid comparison of scoped_ptr types. If U != T, it totally
+ // doesn't make sense, and if U == T, it still doesn't make sense
+ // because you should never have the same object owned by two different
+ // scoped_ptrs.
+ template <class U> bool operator==(scoped_ptr<U> const& p2) const;
+ template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
+};
- T* ptr;
-
- scoped_ptr_malloc(scoped_ptr_malloc const &);
- scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
+template <class T, class D>
+class scoped_ptr<T[], D> {
+ TALK_MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
public:
-
+ // The element and deleter types.
typedef T element_type;
+ typedef D deleter_type;
+
+ // Constructor. Defaults to initializing with NULL.
+ scoped_ptr() : impl_(NULL) { }
+
+ // Constructor. Stores the given array. Note that the argument's type
+ // must exactly match T*. In particular:
+ // - it cannot be a pointer to a type derived from T, because it is
+ // inherently unsafe in the general case to access an array through a
+ // pointer whose dynamic type does not match its static type (eg., if
+ // T and the derived types had different sizes access would be
+ // incorrectly calculated). Deletion is also always undefined
+ // (C++98 [expr.delete]p3). If you're doing this, fix your code.
+ // - it cannot be NULL, because NULL is an integral expression, not a
+ // pointer to T. Use the no-argument version instead of explicitly
+ // passing NULL.
+ // - it cannot be const-qualified differently from T per unique_ptr spec
+ // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
+ // to work around this may use implicit_cast<const T*>().
+ // However, because of the first bullet in this comment, users MUST
+ // NOT use implicit_cast<Base*>() to upcast the static type of the array.
+ explicit scoped_ptr(element_type* array) : impl_(array) { }
+
+ // Constructor. Move constructor for C++03 move emulation of this type.
+ scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
+
+ // operator=. Move operator= for C++03 move emulation of this type.
+ scoped_ptr& operator=(RValue rhs) {
+ impl_.TakeState(&rhs.object->impl_);
+ return *this;
+ }
- explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
+ // Reset. Deletes the currently owned array, if any.
+ // Then takes ownership of a new object, if given.
+ void reset(element_type* array = NULL) { impl_.reset(array); }
- ~scoped_ptr_malloc() {
- FF(ptr);
+ // Accessors to get the owned array.
+ element_type& operator[](size_t i) const {
+ ASSERT(impl_.get() != NULL);
+ return impl_.get()[i];
}
+ element_type* get() const { return impl_.get(); }
- void reset(T* p = 0) {
- if (ptr != p) {
- FF(ptr);
- ptr = p;
- }
- }
+ // Access to the deleter.
+ deleter_type& get_deleter() { return impl_.get_deleter(); }
+ const deleter_type& get_deleter() const { return impl_.get_deleter(); }
- T& operator*() const {
- ASSERT(ptr != 0);
- return *ptr;
- }
+ // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
+ // implicitly convertible to a real bool (which is dangerous).
+ private:
+ typedef talk_base::internal::scoped_ptr_impl<element_type, deleter_type>
+ scoped_ptr::*Testable;
- T* operator->() const {
- ASSERT(ptr != 0);
- return ptr;
- }
+ public:
+ operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
+
+ // Comparison operators.
+ // These return whether two scoped_ptr refer to the same object, not just to
+ // two different but equal objects.
+ bool operator==(element_type* array) const { return impl_.get() == array; }
+ bool operator!=(element_type* array) const { return impl_.get() != array; }
- T* get() const {
- return ptr;
+ // Swap two scoped pointers.
+ void swap(scoped_ptr& p2) {
+ impl_.swap(p2.impl_);
}
- void swap(scoped_ptr_malloc & b) {
- T* tmp = b.ptr;
- b.ptr = ptr;
- ptr = tmp;
+ // Release a pointer.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ element_type* release() WARN_UNUSED_RESULT {
+ return impl_.release();
}
- T* release() {
- T* tmp = ptr;
- ptr = 0;
- return tmp;
+ // Delete the currently held pointer and return a pointer
+ // to allow overwriting of the current pointer address.
+ element_type** accept() WARN_UNUSED_RESULT {
+ return impl_.accept();
}
- T** accept() {
- if (ptr) {
- FF(ptr);
- ptr = 0;
- }
- return &ptr;
+ // Return a pointer to the current pointer address.
+ element_type** use() WARN_UNUSED_RESULT {
+ return impl_.use();
}
- // Allow scoped_ptr_malloc<T> to be used in boolean expressions, but not
- // implicitly convertible to a real bool (which is dangerous).
- // Borrowed from chromium's scoped_ptr_malloc implementation.
- typedef T* scoped_ptr_malloc::*Testable;
- operator Testable() const { return ptr ? &scoped_ptr_malloc::ptr : NULL; }
+ private:
+ // Force element_type to be a complete type.
+ enum { type_must_be_complete = sizeof(element_type) };
+
+ // Actually hold the data.
+ talk_base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
+
+ // Disable initialization from any type other than element_type*, by
+ // providing a constructor that matches such an initialization, but is
+ // private and has no definition. This is disabled because it is not safe to
+ // call delete[] on an array whose static type does not match its dynamic
+ // type.
+ template <typename U> explicit scoped_ptr(U* array);
+ explicit scoped_ptr(int disallow_construction_from_null);
+
+ // Disable reset() from any type other than element_type*, for the same
+ // reasons as the constructor above.
+ template <typename U> void reset(U* array);
+ void reset(int disallow_reset_from_null);
+
+ // Forbid comparison of scoped_ptr types. If U != T, it totally
+ // doesn't make sense, and if U == T, it still doesn't make sense
+ // because you should never have the same object owned by two different
+ // scoped_ptrs.
+ template <class U> bool operator==(scoped_ptr<U> const& p2) const;
+ template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
};
-template<typename T, void (*FF)(T*)> inline
-void swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& b) {
- a.swap(b);
+} // namespace talk_base
+
+// Free functions
+template <class T, class D>
+void swap(talk_base::scoped_ptr<T, D>& p1, talk_base::scoped_ptr<T, D>& p2) {
+ p1.swap(p2);
}
-} // namespace talk_base
+template <class T, class D>
+bool operator==(T* p1, const talk_base::scoped_ptr<T, D>& p2) {
+ return p1 == p2.get();
+}
+
+template <class T, class D>
+bool operator!=(T* p1, const talk_base::scoped_ptr<T, D>& p2) {
+ return p1 != p2.get();
+}
#endif // #ifndef TALK_BASE_SCOPED_PTR_H__
diff --git a/chromium/third_party/libjingle/source/talk/base/sha1digest_unittest.cc b/chromium/third_party/libjingle/source/talk/base/sha1digest_unittest.cc
index 5ab68192463..d6c14b6d25d 100644
--- a/chromium/third_party/libjingle/source/talk/base/sha1digest_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/sha1digest_unittest.cc
@@ -38,7 +38,7 @@ std::string Sha1(const std::string& input) {
TEST(Sha1DigestTest, TestSize) {
Sha1Digest sha1;
- EXPECT_EQ(20U, Sha1Digest::kSize);
+ EXPECT_EQ(20, static_cast<int>(Sha1Digest::kSize));
EXPECT_EQ(20U, sha1.Size());
}
diff --git a/chromium/third_party/libjingle/source/talk/base/signalthread.h b/chromium/third_party/libjingle/source/talk/base/signalthread.h
index 79c00be3121..46dd0a3bad5 100644
--- a/chromium/third_party/libjingle/source/talk/base/signalthread.h
+++ b/chromium/third_party/libjingle/source/talk/base/signalthread.h
@@ -123,6 +123,7 @@ class SignalThread
class Worker : public Thread {
public:
explicit Worker(SignalThread* parent) : parent_(parent) {}
+ virtual ~Worker() { Stop(); }
virtual void Run() { parent_->Run(); }
private:
diff --git a/chromium/third_party/libjingle/source/talk/base/signalthread_unittest.cc b/chromium/third_party/libjingle/source/talk/base/signalthread_unittest.cc
index 4458f52ef2b..e5734d4df11 100644
--- a/chromium/third_party/libjingle/source/talk/base/signalthread_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/signalthread_unittest.cc
@@ -120,6 +120,10 @@ class OwnerThread : public Thread, public sigslot::has_slots<> {
has_run_(false) {
}
+ virtual ~OwnerThread() {
+ Stop();
+ }
+
virtual void Run() {
SignalThreadTest::SlowSignalThread* signal_thread =
new SignalThreadTest::SlowSignalThread(harness_);
diff --git a/chromium/third_party/libjingle/source/talk/base/socket_unittest.cc b/chromium/third_party/libjingle/source/talk/base/socket_unittest.cc
index eafab81f408..a9c4dbb0de4 100644
--- a/chromium/third_party/libjingle/source/talk/base/socket_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/socket_unittest.cc
@@ -693,8 +693,8 @@ void SocketTest::TcpInternal(const IPAddress& loopback) {
// Create test data.
const size_t kDataSize = 1024 * 1024;
- scoped_array<char> send_buffer(new char[kDataSize]);
- scoped_array<char> recv_buffer(new char[kDataSize]);
+ scoped_ptr<char[]> send_buffer(new char[kDataSize]);
+ scoped_ptr<char[]> recv_buffer(new char[kDataSize]);
size_t send_pos = 0, recv_pos = 0;
for (size_t i = 0; i < kDataSize; ++i) {
send_buffer[i] = static_cast<char>(i % 256);
@@ -934,7 +934,7 @@ void SocketTest::UdpReadyToSend(const IPAddress& loopback) {
scoped_ptr<TestClient> client(
new TestClient(AsyncUDPSocket::Create(ss_, empty)));
int test_packet_size = 1200;
- talk_base::scoped_array<char> test_packet(new char[test_packet_size]);
+ talk_base::scoped_ptr<char[]> test_packet(new char[test_packet_size]);
// Init the test packet just to avoid memcheck warning.
memset(test_packet.get(), 0, test_packet_size);
// Set the send buffer size to the same size as the test packet to have a
diff --git a/chromium/third_party/libjingle/source/talk/base/ssladapter.cc b/chromium/third_party/libjingle/source/talk/base/ssladapter.cc
index b7d82943ac2..5bcb619c2e3 100644
--- a/chromium/third_party/libjingle/source/talk/base/ssladapter.cc
+++ b/chromium/third_party/libjingle/source/talk/base/ssladapter.cc
@@ -58,6 +58,7 @@ SSLAdapter::Create(AsyncSocket* socket) {
#elif SSL_USE_OPENSSL // && !SSL_USE_SCHANNEL
return new OpenSSLAdapter(socket);
#else // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
+ delete socket;
return NULL;
#endif // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL
}
diff --git a/chromium/third_party/libjingle/source/talk/base/ssladapter.h b/chromium/third_party/libjingle/source/talk/base/ssladapter.h
index 1583dc2eb61..4d2dbcde129 100644
--- a/chromium/third_party/libjingle/source/talk/base/ssladapter.h
+++ b/chromium/third_party/libjingle/source/talk/base/ssladapter.h
@@ -47,7 +47,9 @@ class SSLAdapter : public AsyncSocketAdapter {
// negotiation will begin as soon as the socket connects.
virtual int StartSSL(const char* hostname, bool restartable) = 0;
- // Create the default SSL adapter for this platform
+ // Create the default SSL adapter for this platform. On failure, returns NULL
+ // and deletes |socket|. Otherwise, the returned SSLAdapter takes ownership
+ // of |socket|.
static SSLAdapter* Create(AsyncSocket* socket);
private:
diff --git a/chromium/third_party/libjingle/source/talk/base/sslfingerprint.h b/chromium/third_party/libjingle/source/talk/base/sslfingerprint.h
index 4d41156f862..b85778947e6 100644
--- a/chromium/third_party/libjingle/source/talk/base/sslfingerprint.h
+++ b/chromium/third_party/libjingle/source/talk/base/sslfingerprint.h
@@ -47,9 +47,14 @@ struct SSLFingerprint {
return NULL;
}
+ return Create(algorithm, &(identity->certificate()));
+ }
+
+ static SSLFingerprint* Create(const std::string& algorithm,
+ const talk_base::SSLCertificate* cert) {
uint8 digest_val[64];
size_t digest_len;
- bool ret = identity->certificate().ComputeDigest(
+ bool ret = cert->ComputeDigest(
algorithm, digest_val, sizeof(digest_val), &digest_len);
if (!ret) {
return NULL;
diff --git a/chromium/third_party/libjingle/source/talk/base/sslidentity.h b/chromium/third_party/libjingle/source/talk/base/sslidentity.h
index b9425f78fdf..89b1008983c 100644
--- a/chromium/third_party/libjingle/source/talk/base/sslidentity.h
+++ b/chromium/third_party/libjingle/source/talk/base/sslidentity.h
@@ -30,11 +30,18 @@
#ifndef TALK_BASE_SSLIDENTITY_H_
#define TALK_BASE_SSLIDENTITY_H_
+#include <algorithm>
#include <string>
+#include <vector>
+
+#include "talk/base/buffer.h"
#include "talk/base/messagedigest.h"
namespace talk_base {
+// Forward declaration due to circular dependency with SSLCertificate.
+class SSLCertChain;
+
// Abstract interface overridden by SSL library specific
// implementations.
@@ -55,19 +62,76 @@ class SSLCertificate {
virtual ~SSLCertificate() {}
// Returns a new SSLCertificate object instance wrapping the same
- // underlying certificate.
+ // underlying certificate, including its chain if present.
// Caller is responsible for freeing the returned object.
virtual SSLCertificate* GetReference() const = 0;
+ // Provides the cert chain, or returns false. The caller owns the chain.
+ // The chain includes a copy of each certificate, excluding the leaf.
+ virtual bool GetChain(SSLCertChain** chain) const = 0;
+
// Returns a PEM encoded string representation of the certificate.
virtual std::string ToPEMString() const = 0;
+ // Provides a DER encoded binary representation of the certificate.
+ virtual void ToDER(Buffer* der_buffer) const = 0;
+
+ // Gets the name of the digest algorithm that was used to compute this
+ // certificate's signature.
+ virtual bool GetSignatureDigestAlgorithm(std::string* algorithm) const = 0;
+
// Compute the digest of the certificate given algorithm
virtual bool ComputeDigest(const std::string &algorithm,
unsigned char* digest, std::size_t size,
std::size_t* length) const = 0;
};
+// SSLCertChain is a simple wrapper for a vector of SSLCertificates. It serves
+// primarily to ensure proper memory management (especially deletion) of the
+// SSLCertificate pointers.
+class SSLCertChain {
+ public:
+ // These constructors copy the provided SSLCertificate(s), so the caller
+ // retains ownership.
+ explicit SSLCertChain(const std::vector<SSLCertificate*>& certs) {
+ ASSERT(!certs.empty());
+ certs_.resize(certs.size());
+ std::transform(certs.begin(), certs.end(), certs_.begin(), DupCert);
+ }
+ explicit SSLCertChain(const SSLCertificate* cert) {
+ certs_.push_back(cert->GetReference());
+ }
+
+ ~SSLCertChain() {
+ std::for_each(certs_.begin(), certs_.end(), DeleteCert);
+ }
+
+ // Vector access methods.
+ size_t GetSize() const { return certs_.size(); }
+
+ // Returns a temporary reference, only valid until the chain is destroyed.
+ const SSLCertificate& Get(size_t pos) const { return *(certs_[pos]); }
+
+ // Returns a new SSLCertChain object instance wrapping the same underlying
+ // certificate chain. Caller is responsible for freeing the returned object.
+ SSLCertChain* Copy() const {
+ return new SSLCertChain(certs_);
+ }
+
+ private:
+ // Helper function for duplicating a vector of certificates.
+ static SSLCertificate* DupCert(const SSLCertificate* cert) {
+ return cert->GetReference();
+ }
+
+ // Helper function for deleting a vector of certificates.
+ static void DeleteCert(SSLCertificate* cert) { delete cert; }
+
+ std::vector<SSLCertificate*> certs_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLCertChain);
+};
+
// Our identity in an SSL negotiation: a keypair and certificate (both
// with the same public key).
// This too is pretty much immutable once created.
@@ -108,4 +172,4 @@ extern const char kPemTypeRsaPrivateKey[];
} // namespace talk_base
-#endif // TALK_BASE_SSLIDENTITY_H__
+#endif // TALK_BASE_SSLIDENTITY_H_
diff --git a/chromium/third_party/libjingle/source/talk/base/sslidentity_unittest.cc b/chromium/third_party/libjingle/source/talk/base/sslidentity_unittest.cc
index 6970426781d..b63b8b9d439 100644
--- a/chromium/third_party/libjingle/source/talk/base/sslidentity_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/sslidentity_unittest.cc
@@ -57,7 +57,7 @@ const unsigned char kTestCertSha1[] = {0xA6, 0xC8, 0x59, 0xEA,
class SSLIdentityTest : public testing::Test {
public:
SSLIdentityTest() :
- identity1_(NULL), identity2_(NULL) {
+ identity1_(), identity2_() {
}
~SSLIdentityTest() {
@@ -83,6 +83,22 @@ class SSLIdentityTest : public testing::Test {
ASSERT_TRUE(test_cert_);
}
+ void TestGetSignatureDigestAlgorithm() {
+ std::string digest_algorithm;
+ // Both NSSIdentity::Generate and OpenSSLIdentity::Generate are
+ // hard-coded to generate RSA-SHA1 certificates.
+ ASSERT_TRUE(identity1_->certificate().GetSignatureDigestAlgorithm(
+ &digest_algorithm));
+ ASSERT_EQ(talk_base::DIGEST_SHA_1, digest_algorithm);
+ ASSERT_TRUE(identity2_->certificate().GetSignatureDigestAlgorithm(
+ &digest_algorithm));
+ ASSERT_EQ(talk_base::DIGEST_SHA_1, digest_algorithm);
+
+ // The test certificate has an MD5-based signature.
+ ASSERT_TRUE(test_cert_->GetSignatureDigestAlgorithm(&digest_algorithm));
+ ASSERT_EQ(talk_base::DIGEST_MD5, digest_algorithm);
+ }
+
void TestDigest(const std::string &algorithm, size_t expected_len,
const unsigned char *expected_digest = NULL) {
unsigned char digest1[64];
@@ -203,3 +219,7 @@ TEST_F(SSLIdentityTest, PemDerConversion) {
"CERTIFICATE",
reinterpret_cast<const unsigned char*>(der.data()), der.length()));
}
+
+TEST_F(SSLIdentityTest, GetSignatureDigestAlgorithm) {
+ TestGetSignatureDigestAlgorithm();
+}
diff --git a/chromium/third_party/libjingle/source/talk/base/sslstreamadapter.h b/chromium/third_party/libjingle/source/talk/base/sslstreamadapter.h
index 2afe1daf180..3a7797370c3 100644
--- a/chromium/third_party/libjingle/source/talk/base/sslstreamadapter.h
+++ b/chromium/third_party/libjingle/source/talk/base/sslstreamadapter.h
@@ -25,8 +25,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TALK_BASE_SSLSTREAMADAPTER_H__
-#define TALK_BASE_SSLSTREAMADAPTER_H__
+#ifndef TALK_BASE_SSLSTREAMADAPTER_H_
+#define TALK_BASE_SSLSTREAMADAPTER_H_
#include <string>
#include <vector>
@@ -111,9 +111,9 @@ class SSLStreamAdapter : public StreamAdapterInterface {
// mode.
// Generally, SetIdentity() and possibly SetServerRole() should have
// been called before this.
- // SetPeerCertificate() must also be called. It may be called after
- // StartSSLWithPeer() but must be called before the underlying
- // stream opens.
+ // SetPeerCertificate() or SetPeerCertificateDigest() must also be called.
+ // It may be called after StartSSLWithPeer() but must be called before the
+ // underlying stream opens.
virtual int StartSSLWithPeer() = 0;
// Specify the certificate that our peer is expected to use in
@@ -138,6 +138,13 @@ class SSLStreamAdapter : public StreamAdapterInterface {
const unsigned char* digest_val,
size_t digest_len) = 0;
+ // Retrieves the peer's X.509 certificate, if a certificate has been
+ // provided by SetPeerCertificate or a connection has been established. If
+ // a connection has been established, this returns the
+ // certificate transmitted over SSL, including the entire chain.
+ // The returned certificate is owned by the caller.
+ virtual bool GetPeerCertificate(SSLCertificate** cert) const = 0;
+
// Key Exporter interface from RFC 5705
// Arguments are:
// label -- the exporter label.
@@ -182,4 +189,4 @@ class SSLStreamAdapter : public StreamAdapterInterface {
} // namespace talk_base
-#endif // TALK_BASE_SSLSTREAMADAPTER_H__
+#endif // TALK_BASE_SSLSTREAMADAPTER_H_
diff --git a/chromium/third_party/libjingle/source/talk/base/sslstreamadapter_unittest.cc b/chromium/third_party/libjingle/source/talk/base/sslstreamadapter_unittest.cc
index 1fe1a663484..4b2fd6d84c0 100644
--- a/chromium/third_party/libjingle/source/talk/base/sslstreamadapter_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/sslstreamadapter_unittest.cc
@@ -33,6 +33,7 @@
#include "talk/base/gunit.h"
#include "talk/base/helpers.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/base/ssladapter.h"
#include "talk/base/sslconfig.h"
#include "talk/base/sslidentity.h"
@@ -388,6 +389,13 @@ class SSLStreamAdapterTestBase : public testing::Test,
return server_ssl_->GetDtlsSrtpCipher(retval);
}
+ bool GetPeerCertificate(bool client, talk_base::SSLCertificate** cert) {
+ if (client)
+ return client_ssl_->GetPeerCertificate(cert);
+ else
+ return server_ssl_->GetPeerCertificate(cert);
+ }
+
bool ExportKeyingMaterial(const char *label,
const unsigned char *context,
size_t context_len,
@@ -754,7 +762,7 @@ TEST_F(SSLStreamAdapterTestDTLS,
};
// Test a handshake with small MTU
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnectWithSmallMtu) {
+TEST_F(SSLStreamAdapterTestDTLS, DISABLED_TestDTLSConnectWithSmallMtu) {
MAYBE_SKIP_TEST(HaveDtls);
SetMtu(700);
SetHandshakeWait(20000);
@@ -885,3 +893,42 @@ TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestTransfer) {
TestHandshake();
TestTransfer(100);
}
+
+// Test getting the remote certificate.
+TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestDTLSGetPeerCertificate) {
+ MAYBE_SKIP_TEST(HaveDtls);
+
+ // Peer certificates haven't been received yet.
+ talk_base::scoped_ptr<talk_base::SSLCertificate> client_peer_cert;
+ ASSERT_FALSE(GetPeerCertificate(true, client_peer_cert.accept()));
+ ASSERT_FALSE(client_peer_cert != NULL);
+
+ talk_base::scoped_ptr<talk_base::SSLCertificate> server_peer_cert;
+ ASSERT_FALSE(GetPeerCertificate(false, server_peer_cert.accept()));
+ ASSERT_FALSE(server_peer_cert != NULL);
+
+ TestHandshake();
+
+ // The client should have a peer certificate after the handshake.
+ ASSERT_TRUE(GetPeerCertificate(true, client_peer_cert.accept()));
+ ASSERT_TRUE(client_peer_cert != NULL);
+
+ // It's not kCERT_PEM.
+ std::string client_peer_string = client_peer_cert->ToPEMString();
+ ASSERT_NE(kCERT_PEM, client_peer_string);
+
+ // It must not have a chain, because the test certs are self-signed.
+ talk_base::SSLCertChain* client_peer_chain;
+ ASSERT_FALSE(client_peer_cert->GetChain(&client_peer_chain));
+
+ // The server should have a peer certificate after the handshake.
+ ASSERT_TRUE(GetPeerCertificate(false, server_peer_cert.accept()));
+ ASSERT_TRUE(server_peer_cert != NULL);
+
+ // It's kCERT_PEM
+ ASSERT_EQ(kCERT_PEM, server_peer_cert->ToPEMString());
+
+ // It must not have a chain, because the test certs are self-signed.
+ talk_base::SSLCertChain* server_peer_chain;
+ ASSERT_FALSE(server_peer_cert->GetChain(&server_peer_chain));
+}
diff --git a/chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.cc b/chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.cc
index 5a1a255505d..b42faa80c60 100644
--- a/chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.cc
+++ b/chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.cc
@@ -87,6 +87,14 @@ void SSLStreamAdapterHelper::SetPeerCertificate(SSLCertificate* cert) {
peer_certificate_.reset(cert);
}
+bool SSLStreamAdapterHelper::GetPeerCertificate(SSLCertificate** cert) const {
+ if (!peer_certificate_)
+ return false;
+
+ *cert = peer_certificate_->GetReference();
+ return true;
+}
+
bool SSLStreamAdapterHelper::SetPeerCertificateDigest(
const std::string &digest_alg,
const unsigned char* digest_val,
diff --git a/chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.h b/chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.h
index e8cb3b08b1b..7c280566127 100644
--- a/chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.h
+++ b/chromium/third_party/libjingle/source/talk/base/sslstreamadapterhelper.h
@@ -2,26 +2,26 @@
* libjingle
* Copyright 2004--2008, Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
- * 1. Redistributions of source code must retain the above copyright notice,
+ * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -63,6 +63,7 @@ class SSLStreamAdapterHelper : public SSLStreamAdapter {
virtual bool SetPeerCertificateDigest(const std::string& digest_alg,
const unsigned char* digest_val,
size_t digest_len);
+ virtual bool GetPeerCertificate(SSLCertificate** cert) const;
virtual StreamState GetState() const;
virtual void Close();
diff --git a/chromium/third_party/libjingle/source/talk/base/stream.cc b/chromium/third_party/libjingle/source/talk/base/stream.cc
index 20adfcfa903..c1cf90743a0 100644
--- a/chromium/third_party/libjingle/source/talk/base/stream.cc
+++ b/chromium/third_party/libjingle/source/talk/base/stream.cc
@@ -166,7 +166,7 @@ StreamAdapterInterface::~StreamAdapterInterface() {
///////////////////////////////////////////////////////////////////////////////
StreamTap::StreamTap(StreamInterface* stream, StreamInterface* tap)
- : StreamAdapterInterface(stream), tap_(NULL), tap_result_(SR_SUCCESS),
+ : StreamAdapterInterface(stream), tap_(), tap_result_(SR_SUCCESS),
tap_error_(0) {
AttachTap(tap);
}
@@ -523,6 +523,106 @@ void FileStream::DoClose() {
fclose(file_);
}
+CircularFileStream::CircularFileStream(size_t max_size)
+ : max_write_size_(max_size),
+ position_(0),
+ marked_position_(max_size / 2),
+ last_write_position_(0),
+ read_segment_(READ_LATEST),
+ read_segment_available_(0) {
+}
+
+bool CircularFileStream::Open(
+ const std::string& filename, const char* mode, int* error) {
+ if (!FileStream::Open(filename.c_str(), mode, error))
+ return false;
+
+ if (strchr(mode, "r") != NULL) { // Opened in read mode.
+ // Check if the buffer has been overwritten and determine how to read the
+ // log in time sequence.
+ size_t file_size;
+ GetSize(&file_size);
+ if (file_size == position_) {
+ // The buffer has not been overwritten yet. Read 0 .. file_size
+ read_segment_ = READ_LATEST;
+ read_segment_available_ = file_size;
+ } else {
+ // The buffer has been over written. There are three segments: The first
+ // one is 0 .. marked_position_, which is the marked earliest log. The
+ // second one is position_ .. file_size, which is the middle log. The
+ // last one is marked_position_ .. position_, which is the latest log.
+ read_segment_ = READ_MARKED;
+ read_segment_available_ = marked_position_;
+ last_write_position_ = position_;
+ }
+
+ // Read from the beginning.
+ position_ = 0;
+ SetPosition(position_);
+ }
+
+ return true;
+}
+
+StreamResult CircularFileStream::Read(void* buffer, size_t buffer_len,
+ size_t* read, int* error) {
+ if (read_segment_available_ == 0) {
+ size_t file_size;
+ switch (read_segment_) {
+ case READ_MARKED: // Finished READ_MARKED and start READ_MIDDLE.
+ read_segment_ = READ_MIDDLE;
+ position_ = last_write_position_;
+ SetPosition(position_);
+ GetSize(&file_size);
+ read_segment_available_ = file_size - position_;
+ break;
+
+ case READ_MIDDLE: // Finished READ_MIDDLE and start READ_LATEST.
+ read_segment_ = READ_LATEST;
+ position_ = marked_position_;
+ SetPosition(position_);
+ read_segment_available_ = last_write_position_ - position_;
+ break;
+
+ default: // Finished READ_LATEST and return EOS.
+ return talk_base::SR_EOS;
+ }
+ }
+
+ size_t local_read;
+ if (!read) read = &local_read;
+
+ size_t to_read = talk_base::_min(buffer_len, read_segment_available_);
+ talk_base::StreamResult result
+ = talk_base::FileStream::Read(buffer, to_read, read, error);
+ if (result == talk_base::SR_SUCCESS) {
+ read_segment_available_ -= *read;
+ position_ += *read;
+ }
+ return result;
+}
+
+StreamResult CircularFileStream::Write(const void* data, size_t data_len,
+ size_t* written, int* error) {
+ if (position_ >= max_write_size_) {
+ ASSERT(position_ == max_write_size_);
+ position_ = marked_position_;
+ SetPosition(position_);
+ }
+
+ size_t local_written;
+ if (!written) written = &local_written;
+
+ size_t to_eof = max_write_size_ - position_;
+ size_t to_write = talk_base::_min(data_len, to_eof);
+ talk_base::StreamResult result
+ = talk_base::FileStream::Write(data, to_write, written, error);
+ if (result == talk_base::SR_SUCCESS) {
+ position_ += *written;
+ }
+ return result;
+}
+
AsyncWriteStream::~AsyncWriteStream() {
write_thread_->Clear(this, 0, NULL);
ClearBufferAndWrite();
diff --git a/chromium/third_party/libjingle/source/talk/base/stream.h b/chromium/third_party/libjingle/source/talk/base/stream.h
index 6700c402df6..4571def9bb9 100644
--- a/chromium/third_party/libjingle/source/talk/base/stream.h
+++ b/chromium/third_party/libjingle/source/talk/base/stream.h
@@ -468,6 +468,35 @@ class FileStream : public StreamInterface {
DISALLOW_EVIL_CONSTRUCTORS(FileStream);
};
+// A stream that caps the output at a certain size, dropping content from the
+// middle of the logical stream and maintaining equal parts of the start/end of
+// the logical stream.
+class CircularFileStream : public FileStream {
+ public:
+ explicit CircularFileStream(size_t max_size);
+
+ virtual bool Open(const std::string& filename, const char* mode, int* error);
+ virtual StreamResult Read(void* buffer, size_t buffer_len,
+ size_t* read, int* error);
+ virtual StreamResult Write(const void* data, size_t data_len,
+ size_t* written, int* error);
+
+ private:
+ enum ReadSegment {
+ READ_MARKED, // Read 0 .. marked_position_
+ READ_MIDDLE, // Read position_ .. file_size
+ READ_LATEST, // Read marked_position_ .. position_ if the buffer was
+ // overwritten or 0 .. position_ otherwise.
+ };
+
+ size_t max_write_size_;
+ size_t position_;
+ size_t marked_position_;
+ size_t last_write_position_;
+ ReadSegment read_segment_;
+ size_t read_segment_available_;
+};
+
// A stream which pushes writes onto a separate thread and
// returns from the write call immediately.
@@ -662,7 +691,7 @@ class FifoBuffer : public StreamInterface {
size_t offset, size_t* bytes_written);
StreamState state_; // keeps the opened/closed state of the stream
- scoped_array<char> buffer_; // the allocated buffer
+ scoped_ptr<char[]> buffer_; // the allocated buffer
size_t buffer_length_; // size of the allocated buffer
size_t data_length_; // amount of readable data in the buffer
size_t read_position_; // offset to the readable data
diff --git a/chromium/third_party/libjingle/source/talk/base/systeminfo.cc b/chromium/third_party/libjingle/source/talk/base/systeminfo.cc
index ec1865889ec..ff331ac71a6 100644
--- a/chromium/third_party/libjingle/source/talk/base/systeminfo.cc
+++ b/chromium/third_party/libjingle/source/talk/base/systeminfo.cc
@@ -74,7 +74,7 @@ static void GetProcessorInformation(int* physical_cpus, int* cache_size) {
// Determine buffer size, allocate and get processor information.
// Size can change between calls (unlikely), so a loop is done.
DWORD return_length = 0;
- scoped_array<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> infos;
+ scoped_ptr<SYSTEM_LOGICAL_PROCESSOR_INFORMATION[]> infos;
while (!glpi(infos.get(), &return_length)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
infos.reset(new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[
@@ -183,6 +183,8 @@ SystemInfo::SystemInfo()
if (!sysctlbyname("machdep.cpu.stepping", &sysctl_value, &length, NULL, 0)) {
cpu_stepping_ = static_cast<int>(sysctl_value);
}
+#elif defined(__native_client__)
+ // TODO(ryanpetrie): Implement this via PPAPI when it's available.
#else // LINUX || ANDROID
ProcCpuInfo proc_info;
if (proc_info.LoadFromSystem()) {
diff --git a/chromium/third_party/libjingle/source/talk/base/template_util.h b/chromium/third_party/libjingle/source/talk/base/template_util.h
new file mode 100644
index 00000000000..5cc4ba430a2
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/base/template_util.h
@@ -0,0 +1,106 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TALK_BASE_TEMPLATE_UTIL_H_
+#define TALK_BASE_TEMPLATE_UTIL_H_
+
+#include <cstddef> // For size_t.
+
+namespace talk_base {
+
+// template definitions from tr1
+
+template<class T, T v>
+struct integral_constant {
+ static const T value = v;
+ typedef T value_type;
+ typedef integral_constant<T, v> type;
+};
+
+template <class T, T v> const T integral_constant<T, v>::value;
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+template <class T> struct is_pointer : false_type {};
+template <class T> struct is_pointer<T*> : true_type {};
+
+template <class T, class U> struct is_same : public false_type {};
+template <class T> struct is_same<T,T> : true_type {};
+
+template<class> struct is_array : public false_type {};
+template<class T, size_t n> struct is_array<T[n]> : public true_type {};
+template<class T> struct is_array<T[]> : public true_type {};
+
+template <class T> struct is_non_const_reference : false_type {};
+template <class T> struct is_non_const_reference<T&> : true_type {};
+template <class T> struct is_non_const_reference<const T&> : false_type {};
+
+template <class T> struct is_void : false_type {};
+template <> struct is_void<void> : true_type {};
+
+namespace internal {
+
+// Types YesType and NoType are guaranteed such that sizeof(YesType) <
+// sizeof(NoType).
+typedef char YesType;
+
+struct NoType {
+ YesType dummy[2];
+};
+
+// This class is an implementation detail for is_convertible, and you
+// don't need to know how it works to use is_convertible. For those
+// who care: we declare two different functions, one whose argument is
+// of type To and one with a variadic argument list. We give them
+// return types of different size, so we can use sizeof to trick the
+// compiler into telling us which function it would have chosen if we
+// had called it with an argument of type From. See Alexandrescu's
+// _Modern C++ Design_ for more details on this sort of trick.
+
+struct ConvertHelper {
+ template <typename To>
+ static YesType Test(To);
+
+ template <typename To>
+ static NoType Test(...);
+
+ template <typename From>
+ static From& Create();
+};
+
+// Used to determine if a type is a struct/union/class. Inspired by Boost's
+// is_class type_trait implementation.
+struct IsClassHelper {
+ template <typename C>
+ static YesType Test(void(C::*)(void));
+
+ template <typename C>
+ static NoType Test(...);
+};
+
+} // namespace internal
+
+// Inherits from true_type if From is convertible to To, false_type otherwise.
+//
+// Note that if the type is convertible, this will be a true_type REGARDLESS
+// of whether or not the conversion would emit a warning.
+template <typename From, typename To>
+struct is_convertible
+ : integral_constant<bool,
+ sizeof(internal::ConvertHelper::Test<To>(
+ internal::ConvertHelper::Create<From>())) ==
+ sizeof(internal::YesType)> {
+};
+
+template <typename T>
+struct is_class
+ : integral_constant<bool,
+ sizeof(internal::IsClassHelper::Test<T>(0)) ==
+ sizeof(internal::YesType)> {
+};
+
+} // namespace talk_base
+
+#endif // TALK_BASE_TEMPLATE_UTIL_H_
diff --git a/chromium/third_party/libjingle/source/talk/base/testclient.cc b/chromium/third_party/libjingle/source/talk/base/testclient.cc
index 0ef85183117..04d60309963 100644
--- a/chromium/third_party/libjingle/source/talk/base/testclient.cc
+++ b/chromium/third_party/libjingle/source/talk/base/testclient.cc
@@ -80,13 +80,20 @@ TestClient::Packet* TestClient::NextPacket() {
// the wrong thread to non-thread-safe objects.
uint32 end = TimeAfter(kTimeout);
- while (packets_->size() == 0 && TimeUntil(end) > 0)
+ while (TimeUntil(end) > 0) {
+ {
+ CritScope cs(&crit_);
+ if (packets_->size() != 0) {
+ break;
+ }
+ }
Thread::Current()->ProcessMessages(1);
+ }
// Return the first packet placed in the queue.
Packet* packet = NULL;
+ CritScope cs(&crit_);
if (packets_->size() > 0) {
- CritScope cs(&crit_);
packet = packets_->front();
packets_->erase(packets_->begin());
}
@@ -128,7 +135,8 @@ bool TestClient::ready_to_send() const {
}
void TestClient::OnPacket(AsyncPacketSocket* socket, const char* buf,
- size_t size, const SocketAddress& remote_addr) {
+ size_t size, const SocketAddress& remote_addr,
+ const PacketTime& packet_time) {
CritScope cs(&crit_);
packets_->push_back(new Packet(remote_addr, buf, size));
}
diff --git a/chromium/third_party/libjingle/source/talk/base/testclient.h b/chromium/third_party/libjingle/source/talk/base/testclient.h
index 1e1780a2988..87e32df1f46 100644
--- a/chromium/third_party/libjingle/source/talk/base/testclient.h
+++ b/chromium/third_party/libjingle/source/talk/base/testclient.h
@@ -94,7 +94,8 @@ class TestClient : public sigslot::has_slots<> {
Socket::ConnState GetState();
// Slot for packets read on the socket.
void OnPacket(AsyncPacketSocket* socket, const char* buf, size_t len,
- const SocketAddress& remote_addr);
+ const SocketAddress& remote_addr,
+ const PacketTime& packet_time);
void OnReadyToSend(AsyncPacketSocket* socket);
CriticalSection crit_;
diff --git a/chromium/third_party/libjingle/source/talk/base/testechoserver.h b/chromium/third_party/libjingle/source/talk/base/testechoserver.h
index 10466fa4359..5c1045423c3 100644
--- a/chromium/third_party/libjingle/source/talk/base/testechoserver.h
+++ b/chromium/third_party/libjingle/source/talk/base/testechoserver.h
@@ -67,7 +67,8 @@ class TestEchoServer : public sigslot::has_slots<> {
}
}
void OnPacket(AsyncPacketSocket* socket, const char* buf, size_t size,
- const SocketAddress& remote_addr) {
+ const SocketAddress& remote_addr,
+ const PacketTime& packet_time) {
socket->Send(buf, size, DSCP_NO_CHANGE);
}
void OnClose(AsyncPacketSocket* socket, int err) {
diff --git a/chromium/third_party/libjingle/source/talk/base/testutils.h b/chromium/third_party/libjingle/source/talk/base/testutils.h
index 769d95f6464..e8ad7200940 100644
--- a/chromium/third_party/libjingle/source/talk/base/testutils.h
+++ b/chromium/third_party/libjingle/source/talk/base/testutils.h
@@ -30,6 +30,13 @@
// Utilities for testing talk_base infrastructure in unittests
+#ifdef LINUX
+#include <X11/Xlib.h>
+// X defines a few macros that stomp on types that gunit.h uses.
+#undef None
+#undef Bool
+#endif
+
#include <map>
#include <vector>
#include "talk/base/asyncsocket.h"
@@ -565,6 +572,38 @@ inline AssertionResult CmpHelperFileEq(const char* expected_expression,
///////////////////////////////////////////////////////////////////////////////
+// Helpers for determining if X/screencasting is available (on linux).
+
+#define MAYBE_SKIP_SCREENCAST_TEST() \
+ if (!testing::IsScreencastingAvailable()) { \
+ LOG(LS_WARNING) << "Skipping test, since it doesn't have the requisite " \
+ << "X environment for screen capture."; \
+ return; \
+ } \
+
+#ifdef LINUX
+struct XDisplay {
+ XDisplay() : display_(XOpenDisplay(NULL)) { }
+ ~XDisplay() { if (display_) XCloseDisplay(display_); }
+ bool IsValid() const { return display_ != NULL; }
+ operator Display*() { return display_; }
+ private:
+ Display* display_;
+};
+#endif
+
+// Returns true if screencasting is available. When false, anything that uses
+// screencasting features may fail.
+inline bool IsScreencastingAvailable() {
+#ifdef LINUX
+ XDisplay display;
+ if (!display.IsValid()) {
+ LOG(LS_WARNING) << "No X Display available.";
+ return false;
+ }
+#endif
+ return true;
+}
} // namespace testing
#endif // TALK_BASE_TESTUTILS_H__
diff --git a/chromium/third_party/libjingle/source/talk/base/thread.cc b/chromium/third_party/libjingle/source/talk/base/thread.cc
index d21d5f19503..d07efb51568 100644
--- a/chromium/third_party/libjingle/source/talk/base/thread.cc
+++ b/chromium/third_party/libjingle/source/talk/base/thread.cc
@@ -146,7 +146,6 @@ Thread::Thread(SocketServer* ss)
: MessageQueue(ss),
priority_(PRIORITY_NORMAL),
started_(false),
- has_sends_(false),
#if defined(WIN32)
thread_(NULL),
thread_id_(0),
@@ -405,7 +404,6 @@ void Thread::Send(MessageHandler *phandler, uint32 id, MessageData *pdata) {
smsg.msg = msg;
smsg.ready = &ready;
sendlist_.push_back(smsg);
- has_sends_ = true;
}
// Wait for a reply
@@ -413,11 +411,15 @@ void Thread::Send(MessageHandler *phandler, uint32 id, MessageData *pdata) {
ss_->WakeUp();
bool waited = false;
+ crit_.Enter();
while (!ready) {
+ crit_.Leave();
current_thread->ReceiveSends();
current_thread->socketserver()->Wait(kForever, false);
waited = true;
+ crit_.Enter();
}
+ crit_.Leave();
// Our Wait loop above may have consumed some WakeUp events for this
// MessageQueue, that weren't relevant to this Send. Losing these WakeUps can
@@ -436,11 +438,6 @@ void Thread::Send(MessageHandler *phandler, uint32 id, MessageData *pdata) {
}
void Thread::ReceiveSends() {
- // Before entering critical section, check boolean.
-
- if (!has_sends_)
- return;
-
// Receive a sent message. Cleanup scenarios:
// - thread sending exits: We don't allow this, since thread can exit
// only via Join, so Send must complete.
@@ -456,7 +453,6 @@ void Thread::ReceiveSends() {
*smsg.ready = true;
smsg.thread->socketserver()->WakeUp();
}
- has_sends_ = false;
crit_.Leave();
}
@@ -561,6 +557,7 @@ AutoThread::AutoThread(SocketServer* ss) : Thread(ss) {
}
AutoThread::~AutoThread() {
+ Stop();
if (ThreadManager::Instance()->CurrentThread() == this) {
ThreadManager::Instance()->SetCurrentThread(NULL);
}
diff --git a/chromium/third_party/libjingle/source/talk/base/thread.h b/chromium/third_party/libjingle/source/talk/base/thread.h
index 55ec0daf722..4dc09f641d7 100644
--- a/chromium/third_party/libjingle/source/talk/base/thread.h
+++ b/chromium/third_party/libjingle/source/talk/base/thread.h
@@ -111,9 +111,15 @@ class Runnable {
DISALLOW_COPY_AND_ASSIGN(Runnable);
};
+// WARNING! SUBCLASSES MUST CALL Stop() IN THEIR DESTRUCTORS! See ~Thread().
+
class Thread : public MessageQueue {
public:
explicit Thread(SocketServer* ss = NULL);
+ // NOTE: ALL SUBCLASSES OF Thread MUST CALL Stop() IN THEIR DESTRUCTORS (or
+ // guarantee Stop() is explicitly called before the subclass is destroyed).
+ // This is required to avoid a data race between the destructor modifying the
+ // vtable, and the Thread::PreRun calling the virtual method Run().
virtual ~Thread();
static Thread* Current();
@@ -255,7 +261,6 @@ class Thread : public MessageQueue {
std::string name_;
ThreadPriority priority_;
bool started_;
- bool has_sends_;
#ifdef POSIX
pthread_t thread_;
@@ -292,6 +297,7 @@ class AutoThread : public Thread {
class ComThread : public Thread {
public:
ComThread() {}
+ virtual ~ComThread() { Stop(); }
protected:
virtual void Run();
diff --git a/chromium/third_party/libjingle/source/talk/base/thread_unittest.cc b/chromium/third_party/libjingle/source/talk/base/thread_unittest.cc
index 246faa4a53e..896fbabc5fd 100644
--- a/chromium/third_party/libjingle/source/talk/base/thread_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/thread_unittest.cc
@@ -81,7 +81,8 @@ class SocketClient : public TestGenerator, public sigslot::has_slots<> {
SocketAddress address() const { return socket_->GetLocalAddress(); }
void OnPacket(AsyncPacketSocket* socket, const char* buf, size_t size,
- const SocketAddress& remote_addr) {
+ const SocketAddress& remote_addr,
+ const PacketTime& packet_time) {
EXPECT_EQ(size, sizeof(uint32));
uint32 prev = reinterpret_cast<const uint32*>(buf)[0];
uint32 result = Next(prev);
@@ -122,7 +123,7 @@ class MessageClient : public MessageHandler, public TestGenerator {
class CustomThread : public talk_base::Thread {
public:
CustomThread() {}
- virtual ~CustomThread() {}
+ virtual ~CustomThread() { Stop(); }
bool Start() { return false; }
};
@@ -136,6 +137,7 @@ class SignalWhenDestroyedThread : public Thread {
}
virtual ~SignalWhenDestroyedThread() {
+ Stop();
event_->Set();
}
@@ -159,8 +161,8 @@ class Functor2 {
bool* flag_;
};
-
-TEST(ThreadTest, Main) {
+// See: https://code.google.com/p/webrtc/issues/detail?id=2409
+TEST(ThreadTest, DISABLED_Main) {
const SocketAddress addr("127.0.0.1", 0);
// Create the messaging client on its own thread.
diff --git a/chromium/third_party/libjingle/source/talk/base/timeutils.cc b/chromium/third_party/libjingle/source/talk/base/timeutils.cc
index 66b9bf2c7c0..54db3418bbb 100644
--- a/chromium/third_party/libjingle/source/talk/base/timeutils.cc
+++ b/chromium/third_party/libjingle/source/talk/base/timeutils.cc
@@ -94,6 +94,10 @@ uint32 Time() {
return static_cast<uint32>(TimeNanos() / kNumNanosecsPerMillisec);
}
+uint64 TimeMicros() {
+ return static_cast<uint64>(TimeNanos() / kNumNanosecsPerMicrosec);
+}
+
#if defined(WIN32)
static const uint64 kFileTimeToUnixTimeEpochOffset = 116444736000000000ULL;
diff --git a/chromium/third_party/libjingle/source/talk/base/timeutils.h b/chromium/third_party/libjingle/source/talk/base/timeutils.h
index 545e86a1243..f13c3f2ef2d 100644
--- a/chromium/third_party/libjingle/source/talk/base/timeutils.h
+++ b/chromium/third_party/libjingle/source/talk/base/timeutils.h
@@ -42,6 +42,8 @@ static const int64 kNumMicrosecsPerMillisec = kNumMicrosecsPerSec /
kNumMillisecsPerSec;
static const int64 kNumNanosecsPerMillisec = kNumNanosecsPerSec /
kNumMillisecsPerSec;
+static const int64 kNumNanosecsPerMicrosec = kNumNanosecsPerSec /
+ kNumMicrosecsPerSec;
// January 1970, in NTP milliseconds.
static const int64 kJan1970AsNtpMillisecs = INT64_C(2208988800000);
@@ -50,6 +52,8 @@ typedef uint32 TimeStamp;
// Returns the current time in milliseconds.
uint32 Time();
+// Returns the current time in microseconds.
+uint64 TimeMicros();
// Returns the current time in nanoseconds.
uint64 TimeNanos();
diff --git a/chromium/third_party/libjingle/source/talk/base/virtualsocket_unittest.cc b/chromium/third_party/libjingle/source/talk/base/virtualsocket_unittest.cc
index f3b13fc0f62..b31b8c8b074 100644
--- a/chromium/third_party/libjingle/source/talk/base/virtualsocket_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/virtualsocket_unittest.cc
@@ -46,7 +46,7 @@ struct Sender : public MessageHandler {
Sender(Thread* th, AsyncSocket* s, uint32 rt)
: thread(th), socket(new AsyncUDPSocket(s)),
done(false), rate(rt), count(0) {
- last_send = Time();
+ last_send = talk_base::Time();
thread->PostDelayed(NextDelay(), this, 1);
}
@@ -61,7 +61,7 @@ struct Sender : public MessageHandler {
if (done)
return;
- uint32 cur_time = Time();
+ uint32 cur_time = talk_base::Time();
uint32 delay = cur_time - last_send;
uint32 size = rate * delay / 1000;
size = std::min<uint32>(size, 4096);
@@ -97,7 +97,8 @@ struct Receiver : public MessageHandler, public sigslot::has_slots<> {
}
void OnReadPacket(AsyncPacketSocket* s, const char* data, size_t size,
- const SocketAddress& remote_addr) {
+ const SocketAddress& remote_addr,
+ const PacketTime& packet_time) {
ASSERT_EQ(socket.get(), s);
ASSERT_GE(size, 4U);
@@ -105,7 +106,7 @@ struct Receiver : public MessageHandler, public sigslot::has_slots<> {
sec_count += size;
uint32 send_time = *reinterpret_cast<const uint32*>(data);
- uint32 recv_time = Time();
+ uint32 recv_time = talk_base::Time();
uint32 delay = recv_time - send_time;
sum += delay;
sum_sq += delay * delay;
@@ -863,7 +864,8 @@ TEST_F(VirtualSocketServerTest, delay_v4) {
DelayTest(ipv4_test_addr);
}
-TEST_F(VirtualSocketServerTest, delay_v6) {
+// See: https://code.google.com/p/webrtc/issues/detail?id=2409
+TEST_F(VirtualSocketServerTest, DISABLED_delay_v6) {
SocketAddress ipv6_test_addr(IPAddress(in6addr_any), 1000);
DelayTest(ipv6_test_addr);
}
diff --git a/chromium/third_party/libjingle/source/talk/base/win32filesystem.cc b/chromium/third_party/libjingle/source/talk/base/win32filesystem.cc
index 42c03885586..5caeac2a32d 100644
--- a/chromium/third_party/libjingle/source/talk/base/win32filesystem.cc
+++ b/chromium/third_party/libjingle/source/talk/base/win32filesystem.cc
@@ -111,7 +111,7 @@ bool Win32Filesystem::CreatePrivateFile(const Pathname &filename) {
&token_user_size);
// Get the TOKEN_USER structure.
- scoped_array<char> token_user_bytes(new char[token_user_size]);
+ scoped_ptr<char[]> token_user_bytes(new char[token_user_size]);
PTOKEN_USER token_user = reinterpret_cast<PTOKEN_USER>(
token_user_bytes.get());
memset(token_user, 0, token_user_size);
@@ -137,7 +137,7 @@ bool Win32Filesystem::CreatePrivateFile(const Pathname &filename) {
GetLengthSid(token_user->User.Sid);
// Allocate it.
- scoped_array<char> acl_bytes(new char[acl_size]);
+ scoped_ptr<char[]> acl_bytes(new char[acl_size]);
PACL acl = reinterpret_cast<PACL>(acl_bytes.get());
memset(acl, 0, acl_size);
if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) {
@@ -440,7 +440,7 @@ bool Win32Filesystem::GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
Pathname Win32Filesystem::GetCurrentDirectory() {
Pathname cwd;
int path_len = 0;
- scoped_array<wchar_t> path;
+ scoped_ptr<wchar_t[]> path;
do {
int needed = ::GetCurrentDirectory(path_len, path.get());
if (needed == 0) {
diff --git a/chromium/third_party/libjingle/source/talk/base/win32regkey.cc b/chromium/third_party/libjingle/source/talk/base/win32regkey.cc
index cb98cafadeb..403fdc014c0 100644
--- a/chromium/third_party/libjingle/source/talk/base/win32regkey.cc
+++ b/chromium/third_party/libjingle/source/talk/base/win32regkey.cc
@@ -160,7 +160,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
ASSERT(full_key_name != NULL);
DWORD byte_count = 0;
- scoped_array<byte> buffer;
+ scoped_ptr<byte[]> buffer;
HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
REG_BINARY, buffer.accept(), &byte_count);
if (SUCCEEDED(hr)) {
@@ -179,7 +179,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
ASSERT(full_key_name != NULL);
DWORD byte_count = 0;
- scoped_array<byte> buffer;
+ scoped_ptr<byte[]> buffer;
HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
REG_BINARY, buffer.accept(), &byte_count);
if (SUCCEEDED(hr)) {
@@ -206,7 +206,7 @@ HRESULT RegKey::GetValue(const wchar_t* full_key_name,
ASSERT(full_key_name != NULL);
ASSERT(value != NULL);
- scoped_array<wchar_t> buffer;
+ scoped_ptr<wchar_t[]> buffer;
HRESULT hr = RegKey::GetValue(full_key_name, value_name, buffer.accept());
if (SUCCEEDED(hr)) {
value->assign(buffer.get());
diff --git a/chromium/third_party/libjingle/source/talk/base/win32socketserver.cc b/chromium/third_party/libjingle/source/talk/base/win32socketserver.cc
index 55128e7a255..95666697337 100644
--- a/chromium/third_party/libjingle/source/talk/base/win32socketserver.cc
+++ b/chromium/third_party/libjingle/source/talk/base/win32socketserver.cc
@@ -620,6 +620,9 @@ int Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) {
*slevel = IPPROTO_TCP;
*sopt = TCP_NODELAY;
break;
+ case OPT_DSCP:
+ LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
+ return -1;
default:
ASSERT(false);
return -1;
diff --git a/chromium/third_party/libjingle/source/talk/base/win32socketserver.h b/chromium/third_party/libjingle/source/talk/base/win32socketserver.h
index 1fa65235ea1..34598793db0 100644
--- a/chromium/third_party/libjingle/source/talk/base/win32socketserver.h
+++ b/chromium/third_party/libjingle/source/talk/base/win32socketserver.h
@@ -156,6 +156,7 @@ class Win32Thread : public Thread {
set_socketserver(&ss_);
}
virtual ~Win32Thread() {
+ Stop();
set_socketserver(NULL);
}
virtual void Run() {
diff --git a/chromium/third_party/libjingle/source/talk/base/windowpicker_unittest.cc b/chromium/third_party/libjingle/source/talk/base/windowpicker_unittest.cc
index e1a815d4048..436854a3c48 100644
--- a/chromium/third_party/libjingle/source/talk/base/windowpicker_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/base/windowpicker_unittest.cc
@@ -1,4 +1,5 @@
#include "talk/base/gunit.h"
+#include "talk/base/testutils.h"
#include "talk/base/window.h"
#include "talk/base/windowpicker.h"
#include "talk/base/windowpickerfactory.h"
@@ -10,6 +11,7 @@
#endif
TEST(WindowPickerTest, GetWindowList) {
+ MAYBE_SKIP_SCREENCAST_TEST();
if (!talk_base::WindowPickerFactory::IsSupported()) {
LOG(LS_INFO) << "skipping test: window capturing is not supported with "
<< "current configuration.";
@@ -24,6 +26,7 @@ TEST(WindowPickerTest, GetWindowList) {
// TODO(hughv) Investigate why this fails on pulse but not locally after
// upgrading to XCode 4.5. The failure is GetDesktopList returning FALSE.
TEST(WindowPickerTest, DISABLE_ON_MAC(GetDesktopList)) {
+ MAYBE_SKIP_SCREENCAST_TEST();
if (!talk_base::WindowPickerFactory::IsSupported()) {
LOG(LS_INFO) << "skipping test: window capturing is not supported with "
<< "current configuration.";
diff --git a/chromium/third_party/libjingle/source/talk/build/isolate.gypi b/chromium/third_party/libjingle/source/talk/build/isolate.gypi
new file mode 100644
index 00000000000..7b0ac1254d6
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/build/isolate.gypi
@@ -0,0 +1,136 @@
+#
+# libjingle
+# Copyright 2013, Google Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+# Copied from Chromium's src/build/isolate.gypi
+#
+# It was necessary to copy this file to libjingle , because the path to
+# build/common.gypi is different for the standalone and Chromium builds. Gyp
+# doesn't permit conditional inclusion or variable expansion in include paths.
+# http://code.google.com/p/gyp/wiki/InputFormatReference#Including_Other_Files
+
+# This file is meant to be included into a target to provide a rule
+# to "build" .isolate files into a .isolated file.
+#
+# To use this, create a gyp target with the following form:
+# 'conditions': [
+# ['test_isolation_mode != "noop"', {
+# 'targets': [
+# {
+# 'target_name': 'foo_test_run',
+# 'type': 'none',
+# 'dependencies': [
+# 'foo_test',
+# ],
+# 'includes': [
+# '../build/isolate.gypi',
+# 'foo_test.isolate',
+# ],
+# 'sources': [
+# 'foo_test.isolate',
+# ],
+# },
+# ],
+# }],
+# ],
+#
+# Note: foo_test.isolate is included and a source file. It is an inherent
+# property of the .isolate format. This permits to define GYP variables but is
+# a stricter format than GYP so isolate.py can read it.
+#
+# The generated .isolated file will be:
+# <(PRODUCT_DIR)/foo_test.isolated
+
+{
+ 'rules': [
+ {
+ 'rule_name': 'isolate',
+ 'extension': 'isolate',
+ 'inputs': [
+ # Files that are known to be involved in this step.
+ '<(DEPTH)/tools/swarming_client/isolate.py',
+ '<(DEPTH)/tools/swarming_client/run_isolated.py',
+ '<(DEPTH)/tools/swarming_client/googletest/run_test_cases.py',
+
+ # Disable file tracking by the build driver for now. This means the
+ # project must have the proper build-time dependency for their runtime
+ # dependency. This improves the runtime of the build driver since it
+ # doesn't have to stat() all these files.
+ #
+ # More importantly, it means that even if a isolate_dependency_tracked
+ # file is missing, for example if a file was deleted and the .isolate
+ # file was not updated, that won't break the build, especially in the
+ # case where foo_tests_run is not built! This should be reenabled once
+ # the switch-over to running tests on Swarm is completed.
+ #'<@(isolate_dependency_tracked)',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/<(RULE_INPUT_ROOT).isolated',
+ ],
+ 'conditions': [
+ ["test_isolation_outdir==''", {
+ 'action': [
+ 'python',
+ '<(DEPTH)/tools/swarming_client/isolate.py',
+ '<(test_isolation_mode)',
+ # GYP will eliminate duplicate arguments so '<(PRODUCT_DIR)' cannot
+ # be provided twice. To work around this behavior, append '/'.
+ #
+ # Also have a space after <(PRODUCT_DIR) or visual studio will
+ # escape the argument wrappping " with the \ and merge it into
+ # the following arguments.
+ #
+ # Other variables should use the -V FOO=<(FOO) form so frequent
+ # values, like '0' or '1', aren't stripped out by GYP.
+ '--outdir', '<(PRODUCT_DIR)/ ',
+ '--variable', 'PRODUCT_DIR', '<(PRODUCT_DIR) ',
+ '--variable', 'OS=<(OS)',
+ '--result', '<@(_outputs)',
+ '--isolate', '<(RULE_INPUT_PATH)',
+ ],
+ }, {
+ 'action': [
+ 'python',
+ '<(DEPTH)/tools/swarming_client/isolate.py',
+ '<(test_isolation_mode)',
+ '--outdir', '<(test_isolation_outdir)',
+ # See comment above.
+ '--variable', 'PRODUCT_DIR', '<(PRODUCT_DIR) ',
+ '--variable', 'OS=<(OS)',
+ '--result', '<@(_outputs)',
+ '--isolate', '<(RULE_INPUT_PATH)',
+ ],
+ }],
+ ['test_isolation_fail_on_missing == 0', {
+ 'action': ['--ignore_broken_items'],
+ },
+ ],
+ ],
+
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+}
diff --git a/chromium/third_party/libjingle/source/talk/examples/android/AndroidManifest.xml b/chromium/third_party/libjingle/source/talk/examples/android/AndroidManifest.xml
index 52e67a2d2fa..59974f7a834 100644
--- a/chromium/third_party/libjingle/source/talk/examples/android/AndroidManifest.xml
+++ b/chromium/third_party/libjingle/source/talk/examples/android/AndroidManifest.xml
@@ -13,7 +13,6 @@
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:label="@string/app_name"
diff --git a/chromium/third_party/libjingle/source/talk/examples/android/project.properties b/chromium/third_party/libjingle/source/talk/examples/android/project.properties
index a3ee5ab64f5..8459f9b8107 100644
--- a/chromium/third_party/libjingle/source/talk/examples/android/project.properties
+++ b/chromium/third_party/libjingle/source/talk/examples/android/project.properties
@@ -11,4 +11,6 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
-target=android-17
+target=android-19
+
+java.compilerargs=-Xlint:all -Werror
diff --git a/chromium/third_party/libjingle/source/talk/examples/call/callclient.cc b/chromium/third_party/libjingle/source/talk/examples/call/callclient.cc
index 66c4b6fa69f..849455eaa54 100644
--- a/chromium/third_party/libjingle/source/talk/examples/call/callclient.cc
+++ b/chromium/third_party/libjingle/source/talk/examples/call/callclient.cc
@@ -396,7 +396,7 @@ CallClient::CallClient(buzz::XmppClient* xmpp_client,
transport_protocol_(cricket::ICEPROTO_HYBRID),
sdes_policy_(cricket::SEC_DISABLED),
dtls_policy_(cricket::SEC_DISABLED),
- ssl_identity_(NULL),
+ ssl_identity_(),
show_roster_messages_(false) {
xmpp_client_->SignalStateChange.connect(this, &CallClient::OnStateChange);
my_status_.set_caps_node(caps_node);
@@ -1601,7 +1601,7 @@ void CallClient::PrintStats() const {
vmi.senders.begin(); it != vmi.senders.end(); ++it) {
console_->PrintLine("Sender: ssrc=%u codec='%s' bytes=%d packets=%d "
"rtt=%d jitter=%d",
- it->ssrc, it->codec_name.c_str(), it->bytes_sent,
+ it->ssrc(), it->codec_name.c_str(), it->bytes_sent,
it->packets_sent, it->rtt_ms, it->jitter_ms);
}
@@ -1609,7 +1609,7 @@ void CallClient::PrintStats() const {
vmi.receivers.begin(); it != vmi.receivers.end(); ++it) {
console_->PrintLine("Receiver: ssrc=%u bytes=%d packets=%d "
"jitter=%d loss=%.2f",
- it->ssrc, it->bytes_rcvd, it->packets_rcvd,
+ it->ssrc(), it->bytes_rcvd, it->packets_rcvd,
it->jitter_ms, it->fraction_lost);
}
}
diff --git a/chromium/third_party/libjingle/source/talk/examples/chat/chatapp.cc b/chromium/third_party/libjingle/source/talk/examples/chat/chatapp.cc
index 1b59910b0b8..59b1c69fb9a 100644
--- a/chromium/third_party/libjingle/source/talk/examples/chat/chatapp.cc
+++ b/chromium/third_party/libjingle/source/talk/examples/chat/chatapp.cc
@@ -38,10 +38,10 @@
ChatApp::ChatApp(buzz::XmppClient* xmpp_client, talk_base::Thread* main_thread)
: xmpp_client_(xmpp_client),
- presence_out_task_(NULL),
- presence_receive_task_(NULL),
- message_send_task_(NULL),
- message_received_task_(NULL),
+ presence_out_task_(),
+ presence_receive_task_(),
+ message_send_task_(),
+ message_received_task_(),
console_task_(new buzz::ConsoleTask(main_thread)),
ui_state_(STATE_BASE) {
xmpp_client_->SignalStateChange.connect(this, &ChatApp::OnStateChange);
diff --git a/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m b/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m
index 99f5166669b..d6c86d8422f 100644
--- a/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m
+++ b/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m
@@ -49,6 +49,19 @@
@implementation APPRTCAppClient
+@synthesize ICEServerDelegate = _ICEServerDelegate;
+@synthesize messageHandler = _messageHandler;
+
+@synthesize backgroundQueue = _backgroundQueue;
+@synthesize baseURL = _baseURL;
+@synthesize gaeChannel = _gaeChannel;
+@synthesize postMessageUrl = _postMessageUrl;
+@synthesize pcConfig = _pcConfig;
+@synthesize roomHtml = _roomHtml;
+@synthesize sendQueue = _sendQueue;
+@synthesize token = _token;
+@synthesize verboseLogging = _verboseLogging;
+
- (id)init {
if (self = [super init]) {
_backgroundQueue = dispatch_queue_create("RTCBackgroundQueue", NULL);
diff --git a/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m b/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m
index 34aa7520cbf..65cdd097944 100644
--- a/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m
+++ b/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m
@@ -142,6 +142,14 @@
@implementation APPRTCAppDelegate
+@synthesize window = _window;
+@synthesize viewController = _viewController;
+@synthesize client = _client;
+@synthesize pcObserver = _pcObserver;
+@synthesize peerConnection = _peerConnection;
+@synthesize peerConnectionFactory = _peerConnectionFactory;
+@synthesize queuedRemoteCandidates = _queuedRemoteCandidates;
+
#pragma mark - UIApplicationDelegate methods
- (BOOL)application:(UIApplication *)application
diff --git a/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCViewController.m b/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCViewController.m
index ab84c0932b4..bd346efcd3a 100644
--- a/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCViewController.m
+++ b/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/APPRTCViewController.m
@@ -33,6 +33,10 @@
@implementation APPRTCViewController
+@synthesize textField = _textField;
+@synthesize textInstructions = _textInstructions;
+@synthesize textOutput = _textOutput;
+
- (void)viewDidLoad {
[super viewDidLoad];
self.textField.delegate = self;
diff --git a/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/GAEChannelClient.m b/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/GAEChannelClient.m
index 9126f67c70a..e0d9a807692 100644
--- a/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/GAEChannelClient.m
+++ b/chromium/third_party/libjingle/source/talk/examples/ios/AppRTCDemo/GAEChannelClient.m
@@ -38,6 +38,9 @@
@implementation GAEChannelClient
+@synthesize delegate = _delegate;
+@synthesize webView = _webView;
+
- (id)initWithToken:(NSString *)token delegate:(id<GAEMessageHandler>)delegate {
self = [super init];
if (self) {
diff --git a/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/linux/main_wnd.h b/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/linux/main_wnd.h
index c23c1164be6..5a44640e1f3 100644
--- a/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/linux/main_wnd.h
+++ b/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/linux/main_wnd.h
@@ -110,7 +110,7 @@ class GtkMainWnd : public MainWindow {
}
protected:
- talk_base::scoped_array<uint8> image_;
+ talk_base::scoped_ptr<uint8[]> image_;
int width_;
int height_;
GtkMainWnd* main_wnd_;
diff --git a/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/main_wnd.h b/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/main_wnd.h
index 0ed0f1422bf..6d2bf3eeee3 100644
--- a/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/main_wnd.h
+++ b/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/main_wnd.h
@@ -147,7 +147,7 @@ class MainWnd : public MainWindow {
HWND wnd_;
BITMAPINFO bmi_;
- talk_base::scoped_array<uint8> image_;
+ talk_base::scoped_ptr<uint8[]> image_;
CRITICAL_SECTION buffer_lock_;
talk_base::scoped_refptr<webrtc::VideoTrackInterface> rendered_track_;
};
diff --git a/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.cc b/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.cc
index 403fabda182..9cdaedcbf05 100644
--- a/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.cc
+++ b/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.cc
@@ -134,17 +134,16 @@ void PeerConnectionClient::Connect(const std::string& server, int port,
if (server_address_.IsUnresolved()) {
state_ = RESOLVING;
resolver_ = new talk_base::AsyncResolver();
- resolver_->SignalWorkDone.connect(this,
- &PeerConnectionClient::OnResolveResult);
- resolver_->set_address(server_address_);
- resolver_->Start();
+ resolver_->SignalDone.connect(this, &PeerConnectionClient::OnResolveResult);
+ resolver_->Start(server_address_);
} else {
DoConnect();
}
}
-void PeerConnectionClient::OnResolveResult(talk_base::SignalThread *t) {
- if (resolver_->error() != 0) {
+void PeerConnectionClient::OnResolveResult(
+ talk_base::AsyncResolverInterface* resolver) {
+ if (resolver_->GetError() != 0) {
callback_->OnServerConnectionFailure();
resolver_->Destroy(false);
resolver_ = NULL;
diff --git a/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.h b/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.h
index d31262b6767..43fee3456d3 100644
--- a/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.h
+++ b/chromium/third_party/libjingle/source/talk/examples/peerconnection/client/peer_connection_client.h
@@ -121,7 +121,7 @@ class PeerConnectionClient : public sigslot::has_slots<>,
void OnClose(talk_base::AsyncSocket* socket, int err);
- void OnResolveResult(talk_base::SignalThread *t);
+ void OnResolveResult(talk_base::AsyncResolverInterface* resolver);
PeerConnectionClientObserver* callback_;
talk_base::SocketAddress server_address_;
diff --git a/chromium/third_party/libjingle/source/talk/libjingle.gyp b/chromium/third_party/libjingle/source/talk/libjingle.gyp
index 5250eec1b8f..dced3d924be 100755
--- a/chromium/third_party/libjingle/source/talk/libjingle.gyp
+++ b/chromium/third_party/libjingle/source/talk/libjingle.gyp
@@ -105,14 +105,14 @@
# included here, or better yet, build a proper .jar in webrtc
# and include it here.
'android_java_files': [
- '<(webrtc_modules_dir)/audio_device/android/java/src/org/webrtc/voiceengine/WebRTCAudioDevice.java',
'<(webrtc_modules_dir)/audio_device/android/java/src/org/webrtc/voiceengine/AudioManagerAndroid.java',
- '<(webrtc_modules_dir)/video_capture/android/java/src/org/webrtc/videoengine/CaptureCapabilityAndroid.java',
'<(webrtc_modules_dir)/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java',
'<(webrtc_modules_dir)/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java',
'<(webrtc_modules_dir)/video_render/android/java/src/org/webrtc/videoengine/ViEAndroidGLES20.java',
'<(webrtc_modules_dir)/video_render/android/java/src/org/webrtc/videoengine/ViERenderer.java',
'<(webrtc_modules_dir)/video_render/android/java/src/org/webrtc/videoengine/ViESurfaceRenderer.java',
+ '<(webrtc_modules_dir)/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java',
+ '<(webrtc_modules_dir)/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioTrack.java',
],
},
'action_name': 'create_jar',
@@ -258,6 +258,7 @@
'base/asynchttprequest.cc',
'base/asynchttprequest.h',
'base/asyncpacketsocket.h',
+ 'base/asyncresolverinterface.h',
'base/asyncsocket.cc',
'base/asyncsocket.h',
'base/asynctcpsocket.cc',
@@ -842,6 +843,8 @@
# TODO(ronghuawu): Enable when SCTP is ready.
# 'media/sctp/sctpdataengine.cc',
# 'media/sctp/sctpdataengine.h',
+ 'media/sctp/sctputils.cc',
+ 'media/sctp/sctputils.h',
'media/webrtc/webrtccommon.h',
'media/webrtc/webrtcexport.h',
'media/webrtc/webrtcmediaengine.h',
diff --git a/chromium/third_party/libjingle/source/talk/libjingle.scons b/chromium/third_party/libjingle/source/talk/libjingle.scons
index cfc02491d1e..87b43f50ed0 100644
--- a/chromium/third_party/libjingle/source/talk/libjingle.scons
+++ b/chromium/third_party/libjingle/source/talk/libjingle.scons
@@ -290,6 +290,7 @@ talk.Library(env, name = "jingle",
"media/base/videoframe.cc",
"media/devices/devicemanager.cc",
"media/devices/filevideocapturer.cc",
+ "media/sctp/sctputils.cc",
"session/media/audiomonitor.cc",
"session/media/call.cc",
"session/media/channel.cc",
@@ -676,6 +677,7 @@ talk.Unittest(env, name = "media",
"media/base/videocommon_unittest.cc",
"media/devices/devicemanager_unittest.cc",
"media/devices/filevideocapturer_unittest.cc",
+ "media/sctp/sctputils_unittest.cc",
"session/media/channel_unittest.cc",
"session/media/channelmanager_unittest.cc",
"session/media/currentspeakermonitor_unittest.cc",
diff --git a/chromium/third_party/libjingle/source/talk/libjingle_examples.gyp b/chromium/third_party/libjingle/source/talk/libjingle_examples.gyp
index d4aa4a42712..1e2eeb0fb75 100755
--- a/chromium/third_party/libjingle/source/talk/libjingle_examples.gyp
+++ b/chromium/third_party/libjingle/source/talk/libjingle_examples.gyp
@@ -261,35 +261,6 @@
'-framework UIKit',
],
},
- 'postbuilds': [
- {
- # Ideally app signing would be a part of gyp.
- # Delete if/when that comes to pass.
- 'postbuild_name': 'Sign AppRTCDemo',
- 'variables': {
- 'variables': {
- 'key_id%': '<!(security find-identity -p codesigning -v | grep "iPhone Developer" | awk \'{print $2}\')',
- },
- 'key_id%': '<(key_id)',
- # Total HACK to give a more informative message when multiple
- # codesigning keys are present in the default keychain. Ideally
- # we could pick more intelligently among the keys, but as a
- # first cut just tell the developer to specify a key identity
- # explicitly.
- 'ensure_single_key': '<!(python -c "assert \'\\n\' not in \'\'\'<(key_id)\'\'\', \'key_id gyp variable needs to be set explicitly because there are multiple codesigning keys!\'")',
- },
- 'conditions': [
- ['key_id==""', {
- 'action': [ 'echo', 'Skipping signing' ],
- }, {
- 'action': [
- '/usr/bin/codesign', '-v', '--force', '--sign', '<(key_id)',
- '${BUILT_PRODUCTS_DIR}/AppRTCDemo.app',
- ],
- }],
- ],
- },
- ],
}, # target AppRTCDemo
], # targets
}], # OS=="ios"
@@ -325,6 +296,7 @@
'examples/android/res/values/strings.xml',
'examples/android/src/org/appspot/apprtc/AppRTCClient.java',
'examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java',
+ 'examples/android/src/org/appspot/apprtc/UnhandledExceptionHandler.java',
'examples/android/src/org/appspot/apprtc/FramePool.java',
'examples/android/src/org/appspot/apprtc/GAEChannelClient.java',
'examples/android/src/org/appspot/apprtc/VideoStreamsView.java',
@@ -332,6 +304,9 @@
'outputs': [
'<(PRODUCT_DIR)/AppRTCDemo-debug.apk',
],
+ 'variables': {
+ 'ant_log': '<(INTERMEDIATE_DIR)/ant.log',
+ },
'action': [
'bash', '-ec',
'rm -fr <(_outputs) examples/android/{bin,libs} && '
@@ -339,8 +314,10 @@
'cp <(PRODUCT_DIR)/libjingle_peerconnection.jar examples/android/libs/ &&'
'<(android_strip) -o examples/android/libs/<(android_app_abi)/libjingle_peerconnection_so.so <(PRODUCT_DIR)/libjingle_peerconnection_so.so &&'
'cd examples/android && '
- 'ant debug && '
- 'cd - && '
+ 'mkdir -p <(INTERMEDIATE_DIR) && '
+ '{ ant -q -l <(ant_log) debug || '
+ ' { cat <(ant_log) ; exit 1; } } && '
+ 'cd - > /dev/null && '
'cp examples/android/bin/AppRTCDemo-debug.apk <(_outputs)'
],
},
diff --git a/chromium/third_party/libjingle/source/talk/libjingle_media_unittest.isolate b/chromium/third_party/libjingle/source/talk/libjingle_media_unittest.isolate
new file mode 100644
index 00000000000..36b50b5f3aa
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/libjingle_media_unittest.isolate
@@ -0,0 +1,46 @@
+#
+# libjingle
+# Copyright 2013, Google Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+{
+ 'conditions': [
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'command': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_media_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_tracked': [
+ 'media/testdata/captured-320x240-2s-48.frames',
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_media_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_untracked': [
+ '../tools/swarming_client/',
+ ],
+ },
+ }],
+ ],
+}
diff --git a/chromium/third_party/libjingle/source/talk/libjingle_p2p_unittest.isolate b/chromium/third_party/libjingle/source/talk/libjingle_p2p_unittest.isolate
new file mode 100644
index 00000000000..b5ad4ff2d89
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/libjingle_p2p_unittest.isolate
@@ -0,0 +1,45 @@
+#
+# libjingle
+# Copyright 2013, Google Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+{
+ 'conditions': [
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'command': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_p2p_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_tracked': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_p2p_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_untracked': [
+ '../tools/swarming_client/',
+ ],
+ },
+ }],
+ ],
+}
diff --git a/chromium/third_party/libjingle/source/talk/libjingle_peerconnection_unittest.isolate b/chromium/third_party/libjingle/source/talk/libjingle_peerconnection_unittest.isolate
new file mode 100644
index 00000000000..e7dd6878a64
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/libjingle_peerconnection_unittest.isolate
@@ -0,0 +1,45 @@
+#
+# libjingle
+# Copyright 2013, Google Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+{
+ 'conditions': [
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'command': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_peerconnection_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_tracked': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_peerconnection_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_untracked': [
+ '../tools/swarming_client/',
+ ],
+ },
+ }],
+ ],
+}
diff --git a/chromium/third_party/libjingle/source/talk/libjingle_sound_unittest.isolate b/chromium/third_party/libjingle/source/talk/libjingle_sound_unittest.isolate
new file mode 100644
index 00000000000..7166337956c
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/libjingle_sound_unittest.isolate
@@ -0,0 +1,45 @@
+#
+# libjingle
+# Copyright 2013, Google Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+{
+ 'conditions': [
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'command': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_sound_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_tracked': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_sound_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_untracked': [
+ '../tools/swarming_client/',
+ ],
+ },
+ }],
+ ],
+}
diff --git a/chromium/third_party/libjingle/source/talk/libjingle_tests.gyp b/chromium/third_party/libjingle/source/talk/libjingle_tests.gyp
index 546767d1fb5..7bfea590d7d 100755
--- a/chromium/third_party/libjingle/source/talk/libjingle_tests.gyp
+++ b/chromium/third_party/libjingle/source/talk/libjingle_tests.gyp
@@ -88,6 +88,7 @@
'media/base/testutils.cc',
'media/base/testutils.h',
'media/devices/fakedevicemanager.h',
+ 'media/webrtc/dummyinstantiation.cc',
'media/webrtc/fakewebrtccommon.h',
'media/webrtc/fakewebrtcdeviceinfo.h',
'media/webrtc/fakewebrtcvcmfactory.h',
@@ -375,7 +376,7 @@
],
# TODO(ronghuawu): Reenable below unit tests that require gmock.
'sources': [
- 'app/webrtc/datachannel_unittest.cc',
+ # 'app/webrtc/datachannel_unittest.cc',
'app/webrtc/dtmfsender_unittest.cc',
'app/webrtc/jsepsessiondescription_unittest.cc',
'app/webrtc/localaudiosource_unittest.cc',
@@ -383,6 +384,7 @@
# 'app/webrtc/mediastreamhandler_unittest.cc',
'app/webrtc/mediastreamsignaling_unittest.cc',
'app/webrtc/peerconnection_unittest.cc',
+ 'app/webrtc/peerconnectionendtoend_unittest.cc',
'app/webrtc/peerconnectionfactory_unittest.cc',
'app/webrtc/peerconnectioninterface_unittest.cc',
# 'app/webrtc/peerconnectionproxy_unittest.cc',
@@ -391,11 +393,14 @@
'app/webrtc/test/fakeaudiocapturemodule.h',
'app/webrtc/test/fakeaudiocapturemodule_unittest.cc',
'app/webrtc/test/fakeconstraints.h',
+ 'app/webrtc/test/fakedatachannelprovider.h',
'app/webrtc/test/fakedtlsidentityservice.h',
'app/webrtc/test/fakemediastreamsignaling.h',
'app/webrtc/test/fakeperiodicvideocapturer.h',
'app/webrtc/test/fakevideotrackrenderer.h',
'app/webrtc/test/mockpeerconnectionobservers.h',
+ 'app/webrtc/test/peerconnectiontestwrapper.h',
+ 'app/webrtc/test/peerconnectiontestwrapper.cc',
'app/webrtc/test/testsdpstrings.h',
'app/webrtc/videosource_unittest.cc',
'app/webrtc/videotrack_unittest.cc',
@@ -517,5 +522,79 @@
}, # target libjingle_peerconnection_objc_test
],
}],
+ ['test_isolation_mode != "noop"', {
+ 'targets': [
+ {
+ 'target_name': 'libjingle_media_unittest_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'libjingle_media_unittest',
+ ],
+ 'includes': [
+ 'build/isolate.gypi',
+ 'libjingle_media_unittest.isolate',
+ ],
+ 'sources': [
+ 'libjingle_media_unittest.isolate',
+ ],
+ },
+ {
+ 'target_name': 'libjingle_p2p_unittest_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'libjingle_p2p_unittest',
+ ],
+ 'includes': [
+ 'build/isolate.gypi',
+ 'libjingle_p2p_unittest.isolate',
+ ],
+ 'sources': [
+ 'libjingle_p2p_unittest.isolate',
+ ],
+ },
+ {
+ 'target_name': 'libjingle_peerconnection_unittest_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'libjingle_peerconnection_unittest',
+ ],
+ 'includes': [
+ 'build/isolate.gypi',
+ 'libjingle_peerconnection_unittest.isolate',
+ ],
+ 'sources': [
+ 'libjingle_peerconnection_unittest.isolate',
+ ],
+ },
+ {
+ 'target_name': 'libjingle_sound_unittest_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'libjingle_sound_unittest',
+ ],
+ 'includes': [
+ 'build/isolate.gypi',
+ 'libjingle_sound_unittest.isolate',
+ ],
+ 'sources': [
+ 'libjingle_sound_unittest.isolate',
+ ],
+ },
+ {
+ 'target_name': 'libjingle_unittest_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'libjingle_unittest',
+ ],
+ 'includes': [
+ 'build/isolate.gypi',
+ 'libjingle_unittest.isolate',
+ ],
+ 'sources': [
+ 'libjingle_unittest.isolate',
+ ],
+ },
+ ],
+ }],
],
}
diff --git a/chromium/third_party/libjingle/source/talk/libjingle_unittest.isolate b/chromium/third_party/libjingle/source/talk/libjingle_unittest.isolate
new file mode 100644
index 00000000000..e678af013e4
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/libjingle_unittest.isolate
@@ -0,0 +1,45 @@
+#
+# libjingle
+# Copyright 2013, Google Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+{
+ 'conditions': [
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'command': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_tracked': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/libjingle_unittest<(EXECUTABLE_SUFFIX)',
+ ],
+ 'isolate_dependency_untracked': [
+ '../tools/swarming_client/',
+ ],
+ },
+ }],
+ ],
+}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/capturemanager.h b/chromium/third_party/libjingle/source/talk/media/base/capturemanager.h
index 9c443950aff..5226e7b470d 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/capturemanager.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/capturemanager.h
@@ -67,19 +67,19 @@ class CaptureManager : public sigslot::has_slots<> {
CaptureManager() {}
virtual ~CaptureManager();
- bool StartVideoCapture(VideoCapturer* video_capturer,
- const VideoFormat& desired_format);
- bool StopVideoCapture(VideoCapturer* video_capturer,
- const VideoFormat& format);
+ virtual bool StartVideoCapture(VideoCapturer* video_capturer,
+ const VideoFormat& desired_format);
+ virtual bool StopVideoCapture(VideoCapturer* video_capturer,
+ const VideoFormat& format);
// Possibly restarts the capturer. If |options| is set to kRequestRestart,
// the CaptureManager chooses whether this request can be handled with the
// current state or if a restart is actually needed. If |options| is set to
// kForceRestart, the capturer is restarted.
- bool RestartVideoCapture(VideoCapturer* video_capturer,
- const VideoFormat& previous_format,
- const VideoFormat& desired_format,
- RestartOptions options);
+ virtual bool RestartVideoCapture(VideoCapturer* video_capturer,
+ const VideoFormat& previous_format,
+ const VideoFormat& desired_format,
+ RestartOptions options);
virtual bool AddVideoRenderer(VideoCapturer* video_capturer,
VideoRenderer* video_renderer);
diff --git a/chromium/third_party/libjingle/source/talk/media/base/constants.cc b/chromium/third_party/libjingle/source/talk/media/base/constants.cc
index 5529c2abcfa..9162ce4fd12 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/constants.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/constants.cc
@@ -39,30 +39,30 @@ const float kHighSystemCpuThreshold = 0.85f;
const float kLowSystemCpuThreshold = 0.65f;
const float kProcessCpuThreshold = 0.10f;
-const char* kRtxCodecName = "rtx";
+const char kRtxCodecName[] = "rtx";
// RTP payload type is in the 0-127 range. Use 128 to indicate "all" payload
// types.
const int kWildcardPayloadType = -1;
-const char* kCodecParamAssociatedPayloadType = "apt";
+const char kCodecParamAssociatedPayloadType[] = "apt";
-const char* kOpusCodecName = "opus";
+const char kOpusCodecName[] = "opus";
// draft-spittka-payload-rtp-opus-03.txt
-const char* kCodecParamPTime = "ptime";
-const char* kCodecParamMaxPTime = "maxptime";
-const char* kCodecParamMinPTime = "minptime";
-const char* kCodecParamSPropStereo = "sprop-stereo";
-const char* kCodecParamStereo = "stereo";
-const char* kCodecParamUseInbandFec = "useinbandfec";
-const char* kCodecParamMaxAverageBitrate = "maxaveragebitrate";
+const char kCodecParamPTime[] = "ptime";
+const char kCodecParamMaxPTime[] = "maxptime";
+const char kCodecParamMinPTime[] = "minptime";
+const char kCodecParamSPropStereo[] = "sprop-stereo";
+const char kCodecParamStereo[] = "stereo";
+const char kCodecParamUseInbandFec[] = "useinbandfec";
+const char kCodecParamMaxAverageBitrate[] = "maxaveragebitrate";
-const char* kCodecParamSctpProtocol = "protocol";
-const char* kCodecParamSctpStreams = "streams";
+const char kCodecParamSctpProtocol[] = "protocol";
+const char kCodecParamSctpStreams[] = "streams";
-const char* kParamValueTrue = "1";
-const char* kParamValueEmpty = "";
+const char kParamValueTrue[] = "1";
+const char kParamValueEmpty[] = "";
const int kOpusDefaultMaxPTime = 120;
const int kOpusDefaultPTime = 20;
@@ -77,14 +77,15 @@ const int kPreferredSPropStereo = 0;
const int kPreferredStereo = 0;
const int kPreferredUseInbandFec = 0;
-const char* kRtcpFbParamNack = "nack";
-const char* kRtcpFbParamRemb = "goog-remb";
+const char kRtcpFbParamNack[] = "nack";
+const char kRtcpFbParamRemb[] = "goog-remb";
-const char* kRtcpFbParamCcm = "ccm";
-const char* kRtcpFbCcmParamFir = "fir";
-const char* kCodecParamMaxBitrate = "x-google-max-bitrate";
-const char* kCodecParamMinBitrate = "x-google-min-bitrate";
-const char* kCodecParamMaxQuantization = "x-google-max-quantization";
+const char kRtcpFbParamCcm[] = "ccm";
+const char kRtcpFbCcmParamFir[] = "fir";
+const char kCodecParamMaxBitrate[] = "x-google-max-bitrate";
+const char kCodecParamMinBitrate[] = "x-google-min-bitrate";
+const char kCodecParamMaxQuantization[] = "x-google-max-quantization";
+const char kCodecParamPort[] = "x-google-port";
const int kGoogleRtpDataCodecId = 101;
const char kGoogleRtpDataCodecName[] = "google-data";
diff --git a/chromium/third_party/libjingle/source/talk/media/base/constants.h b/chromium/third_party/libjingle/source/talk/media/base/constants.h
index afcfb13ffc1..b80c0fc106c 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/constants.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/constants.h
@@ -43,30 +43,30 @@ extern const float kHighSystemCpuThreshold;
extern const float kLowSystemCpuThreshold;
extern const float kProcessCpuThreshold;
-extern const char* kRtxCodecName;
+extern const char kRtxCodecName[];
// Codec parameters
extern const int kWildcardPayloadType;
-extern const char* kCodecParamAssociatedPayloadType;
+extern const char kCodecParamAssociatedPayloadType[];
-extern const char* kOpusCodecName;
+extern const char kOpusCodecName[];
// Attribute parameters
-extern const char* kCodecParamPTime;
-extern const char* kCodecParamMaxPTime;
+extern const char kCodecParamPTime[];
+extern const char kCodecParamMaxPTime[];
// fmtp parameters
-extern const char* kCodecParamMinPTime;
-extern const char* kCodecParamSPropStereo;
-extern const char* kCodecParamStereo;
-extern const char* kCodecParamUseInbandFec;
-extern const char* kCodecParamMaxAverageBitrate;
-extern const char* kCodecParamSctpProtocol;
-extern const char* kCodecParamSctpStreams;
-
-extern const char* kParamValueTrue;
+extern const char kCodecParamMinPTime[];
+extern const char kCodecParamSPropStereo[];
+extern const char kCodecParamStereo[];
+extern const char kCodecParamUseInbandFec[];
+extern const char kCodecParamMaxAverageBitrate[];
+extern const char kCodecParamSctpProtocol[];
+extern const char kCodecParamSctpStreams[];
+
+extern const char kParamValueTrue[];
// Parameters are stored as parameter/value pairs. For parameters who do not
// have a value, |kParamValueEmpty| should be used as value.
-extern const char* kParamValueEmpty;
+extern const char kParamValueEmpty[];
// opus parameters.
// Default value for maxptime according to
@@ -88,17 +88,18 @@ extern const int kPreferredStereo;
extern const int kPreferredUseInbandFec;
// rtcp-fb messages according to RFC 4585
-extern const char* kRtcpFbParamNack;
+extern const char kRtcpFbParamNack[];
// rtcp-fb messages according to
// http://tools.ietf.org/html/draft-alvestrand-rmcat-remb-00
-extern const char* kRtcpFbParamRemb;
+extern const char kRtcpFbParamRemb[];
// ccm submessages according to RFC 5104
-extern const char* kRtcpFbParamCcm;
-extern const char* kRtcpFbCcmParamFir;
+extern const char kRtcpFbParamCcm[];
+extern const char kRtcpFbCcmParamFir[];
// Google specific parameters
-extern const char* kCodecParamMaxBitrate;
-extern const char* kCodecParamMinBitrate;
-extern const char* kCodecParamMaxQuantization;
+extern const char kCodecParamMaxBitrate[];
+extern const char kCodecParamMinBitrate[];
+extern const char kCodecParamMaxQuantization[];
+extern const char kCodecParamPort[];
// We put the data codec names here so callers of
// DataEngine::CreateChannel don't have to import rtpdataengine.h or
diff --git a/chromium/third_party/libjingle/source/talk/media/base/cpuid.cc b/chromium/third_party/libjingle/source/talk/media/base/cpuid.cc
index 9fd78658899..bd87d2e3cb0 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/cpuid.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/cpuid.cc
@@ -51,8 +51,8 @@ void CpuInfo::MaskCpuFlagsForTest(int enable_flags) {
bool IsCoreIOrBetter() {
#if !defined(DISABLE_YUV) && (defined(__i386__) || defined(__x86_64__) || \
defined(_M_IX86) || defined(_M_X64))
- int cpu_info[4];
- libyuv::CpuId(cpu_info, 0); // Function 0: Vendor ID
+ uint32 cpu_info[4];
+ libyuv::CpuId(0, 0, &cpu_info[0]); // Function 0: Vendor ID
if (cpu_info[1] == 0x756e6547 && cpu_info[3] == 0x49656e69 &&
cpu_info[2] == 0x6c65746e) { // GenuineIntel
// Detect CPU Family and Model
@@ -62,7 +62,7 @@ bool IsCoreIOrBetter() {
// 13:12 - Processor Type
// 19:16 - Extended Model
// 27:20 - Extended Family
- libyuv::CpuId(cpu_info, 1); // Function 1: Family and Model
+ libyuv::CpuId(1, 0, &cpu_info[0]); // Function 1: Family and Model
int family = ((cpu_info[0] >> 8) & 0x0f) | ((cpu_info[0] >> 16) & 0xff0);
int model = ((cpu_info[0] >> 4) & 0x0f) | ((cpu_info[0] >> 12) & 0xf0);
// CpuFamily | CpuModel | Name
diff --git a/chromium/third_party/libjingle/source/talk/media/base/fakemediaengine.h b/chromium/third_party/libjingle/source/talk/media/base/fakemediaengine.h
index 7ef0c9b1ab3..1a4e8aba897 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/fakemediaengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/fakemediaengine.h
@@ -191,10 +191,12 @@ template <class Base> class RtpHelper : public Base {
return true;
}
void set_playout(bool playout) { playout_ = playout; }
- virtual void OnPacketReceived(talk_base::Buffer* packet) {
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) {
rtp_packets_.push_back(std::string(packet->data(), packet->length()));
}
- virtual void OnRtcpReceived(talk_base::Buffer* packet) {
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) {
rtcp_packets_.push_back(std::string(packet->data(), packet->length()));
}
virtual void OnReadyToSend(bool ready) {
@@ -678,18 +680,11 @@ class FakeBaseEngine {
public:
FakeBaseEngine()
: loglevel_(-1),
- options_(0),
options_changed_(false),
fail_create_channel_(false) {}
bool Init(talk_base::Thread* worker_thread) { return true; }
void Terminate() {}
- bool SetOptions(int options) {
- options_ = options;
- options_changed_ = true;
- return true;
- }
-
void SetLogging(int level, const char* filter) {
loglevel_ = level;
logfilter_ = filter;
@@ -704,7 +699,6 @@ class FakeBaseEngine {
protected:
int loglevel_;
std::string logfilter_;
- int options_;
// Flag used by optionsmessagehandler_unittest for checking whether any
// relevant setting has been updated.
// TODO(thaloun): Replace with explicit checks of before & after values.
@@ -725,6 +719,17 @@ class FakeVoiceEngine : public FakeBaseEngine {
codecs_.push_back(AudioCodec(101, "fake_audio_codec", 0, 0, 1, 0));
}
int GetCapabilities() { return AUDIO_SEND | AUDIO_RECV; }
+ AudioOptions GetAudioOptions() const {
+ return options_;
+ }
+ AudioOptions GetOptions() const {
+ return options_;
+ }
+ bool SetOptions(const AudioOptions& options) {
+ options_ = options;
+ options_changed_ = true;
+ return true;
+ }
VoiceMediaChannel* CreateChannel() {
if (fail_create_channel_) {
@@ -808,6 +813,7 @@ class FakeVoiceEngine : public FakeBaseEngine {
std::string out_device_;
VoiceProcessor* rx_processor_;
VoiceProcessor* tx_processor_;
+ AudioOptions options_;
friend class FakeMediaEngine;
};
@@ -819,11 +825,23 @@ class FakeVideoEngine : public FakeBaseEngine {
// sanity checks against that.
codecs_.push_back(VideoCodec(0, "fake_video_codec", 0, 0, 0, 0));
}
+ bool GetOptions(VideoOptions* options) const {
+ *options = options_;
+ return true;
+ }
+ bool SetOptions(const VideoOptions& options) {
+ options_ = options;
+ options_changed_ = true;
+ return true;
+ }
int GetCapabilities() { return VIDEO_SEND | VIDEO_RECV; }
bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) {
default_encoder_config_ = config;
return true;
}
+ VideoEncoderConfig GetDefaultEncoderConfig() const {
+ return default_encoder_config_;
+ }
const VideoEncoderConfig& default_encoder_config() const {
return default_encoder_config_;
}
@@ -883,6 +901,7 @@ class FakeVideoEngine : public FakeBaseEngine {
VideoRenderer* renderer_;
bool capture_;
VideoProcessor* processor_;
+ VideoOptions options_;
friend class FakeMediaEngine;
};
@@ -912,7 +931,7 @@ class FakeMediaEngine :
return video_.GetChannel(index);
}
- int audio_options() const { return voice_.options_; }
+ AudioOptions audio_options() const { return voice_.options_; }
int audio_delay_offset() const { return voice_.delay_offset_; }
int output_volume() const { return voice_.output_volume_; }
const VideoEncoderConfig& default_video_encoder_config() const {
diff --git a/chromium/third_party/libjingle/source/talk/media/base/fakenetworkinterface.h b/chromium/third_party/libjingle/source/talk/media/base/fakenetworkinterface.h
index d0f277e8f42..eb0175b7f82 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/fakenetworkinterface.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/fakenetworkinterface.h
@@ -34,6 +34,7 @@
#include "talk/base/buffer.h"
#include "talk/base/byteorder.h"
#include "talk/base/criticalsection.h"
+#include "talk/base/dscp.h"
#include "talk/base/messagehandler.h"
#include "talk/base/messagequeue.h"
#include "talk/base/thread.h"
@@ -51,7 +52,8 @@ class FakeNetworkInterface : public MediaChannel::NetworkInterface,
dest_(NULL),
conf_(false),
sendbuf_size_(-1),
- recvbuf_size_(-1) {
+ recvbuf_size_(-1),
+ dscp_(talk_base::DSCP_NO_CHANGE) {
}
void SetDestination(MediaChannel* dest) { dest_ = dest; }
@@ -128,6 +130,7 @@ class FakeNetworkInterface : public MediaChannel::NetworkInterface,
int sendbuf_size() const { return sendbuf_size_; }
int recvbuf_size() const { return recvbuf_size_; }
+ talk_base::DiffServCodePoint dscp() const { return dscp_; }
protected:
virtual bool SendPacket(talk_base::Buffer* packet,
@@ -182,6 +185,8 @@ class FakeNetworkInterface : public MediaChannel::NetworkInterface,
sendbuf_size_ = option;
} else if (opt == talk_base::Socket::OPT_RCVBUF) {
recvbuf_size_ = option;
+ } else if (opt == talk_base::Socket::OPT_DSCP) {
+ dscp_ = static_cast<talk_base::DiffServCodePoint>(option);
}
return 0;
}
@@ -196,9 +201,11 @@ class FakeNetworkInterface : public MediaChannel::NetworkInterface,
msg->pdata);
if (dest_) {
if (msg->message_id == ST_RTP) {
- dest_->OnPacketReceived(&msg_data->data());
+ dest_->OnPacketReceived(&msg_data->data(),
+ talk_base::CreatePacketTime(0));
} else {
- dest_->OnRtcpReceived(&msg_data->data());
+ dest_->OnRtcpReceived(&msg_data->data(),
+ talk_base::CreatePacketTime(0));
}
}
delete msg_data;
@@ -244,6 +251,7 @@ class FakeNetworkInterface : public MediaChannel::NetworkInterface,
std::vector<talk_base::Buffer> rtcp_packets_;
int sendbuf_size_;
int recvbuf_size_;
+ talk_base::DiffServCodePoint dscp_;
};
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/media/base/fakevideocapturer.h b/chromium/third_party/libjingle/source/talk/media/base/fakevideocapturer.h
index 5a33265b3ac..8dc69c34546 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/fakevideocapturer.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/fakevideocapturer.h
@@ -101,7 +101,7 @@ class FakeVideoCapturer : public cricket::VideoCapturer {
frame.time_stamp = initial_unix_timestamp_ + next_timestamp_;
next_timestamp_ += 33333333; // 30 fps
- talk_base::scoped_array<char> data(new char[size]);
+ talk_base::scoped_ptr<char[]> data(new char[size]);
frame.data = data.get();
// Copy something non-zero into the buffer so Validate wont complain that
// the frame is all duplicate.
diff --git a/chromium/third_party/libjingle/source/talk/media/base/filemediaengine.cc b/chromium/third_party/libjingle/source/talk/media/base/filemediaengine.cc
index 1a3547c0ce7..dfec607d286 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/filemediaengine.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/filemediaengine.cc
@@ -83,7 +83,8 @@ VoiceMediaChannel* FileMediaEngine::CreateChannel() {
}
}
- return new FileVoiceChannel(input_file_stream, output_file_stream);
+ return new FileVoiceChannel(input_file_stream, output_file_stream,
+ rtp_sender_thread_);
}
VideoMediaChannel* FileMediaEngine::CreateVideoChannel(
@@ -113,18 +114,20 @@ VideoMediaChannel* FileMediaEngine::CreateVideoChannel(
}
}
- return new FileVideoChannel(input_file_stream, output_file_stream);
+ return new FileVideoChannel(input_file_stream, output_file_stream,
+ rtp_sender_thread_);
}
///////////////////////////////////////////////////////////////////////////
// Definition of RtpSenderReceiver.
///////////////////////////////////////////////////////////////////////////
-class RtpSenderReceiver
- : public talk_base::Thread, public talk_base::MessageHandler {
+class RtpSenderReceiver : public talk_base::MessageHandler {
public:
RtpSenderReceiver(MediaChannel* channel,
talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream);
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* sender_thread);
+ virtual ~RtpSenderReceiver();
// Called by media channel. Context: media channel thread.
bool SetSend(bool send);
@@ -148,6 +151,8 @@ class RtpSenderReceiver
talk_base::scoped_ptr<talk_base::StreamInterface> output_stream_;
talk_base::scoped_ptr<RtpDumpLoopReader> rtp_dump_reader_;
talk_base::scoped_ptr<RtpDumpWriter> rtp_dump_writer_;
+ talk_base::Thread* sender_thread_;
+ bool own_sender_thread_;
// RTP dump packet read from the input stream.
RtpDumpPacket rtp_dump_packet_;
uint32 start_send_time_;
@@ -164,30 +169,48 @@ class RtpSenderReceiver
RtpSenderReceiver::RtpSenderReceiver(
MediaChannel* channel,
talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream)
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* sender_thread)
: media_channel_(channel),
+ input_stream_(input_file_stream),
+ output_stream_(output_file_stream),
sending_(false),
first_packet_(true) {
- input_stream_.reset(input_file_stream);
+ if (sender_thread == NULL) {
+ sender_thread_ = new talk_base::Thread();
+ own_sender_thread_ = true;
+ } else {
+ sender_thread_ = sender_thread;
+ own_sender_thread_ = false;
+ }
+
if (input_stream_) {
rtp_dump_reader_.reset(new RtpDumpLoopReader(input_stream_.get()));
// Start the sender thread, which reads rtp dump records, waits based on
// the record timestamps, and sends the RTP packets to the network.
- Thread::Start();
+ if (own_sender_thread_) {
+ sender_thread_->Start();
+ }
}
// Create a rtp dump writer for the output RTP dump stream.
- output_stream_.reset(output_file_stream);
if (output_stream_) {
rtp_dump_writer_.reset(new RtpDumpWriter(output_stream_.get()));
}
}
+RtpSenderReceiver::~RtpSenderReceiver() {
+ if (own_sender_thread_) {
+ sender_thread_->Stop();
+ delete sender_thread_;
+ }
+}
+
bool RtpSenderReceiver::SetSend(bool send) {
bool was_sending = sending_;
sending_ = send;
if (!was_sending && sending_) {
- PostDelayed(0, this); // Wake up the send thread.
+ sender_thread_->PostDelayed(0, this); // Wake up the send thread.
start_send_time_ = talk_base::Time();
}
return true;
@@ -211,7 +234,6 @@ void RtpSenderReceiver::OnMessage(talk_base::Message* pmsg) {
// to sleep until SetSend(true) wakes it up.
return;
}
-
if (!first_packet_) {
// Send the previously read packet.
SendRtpPacket(&rtp_dump_packet_.data[0], rtp_dump_packet_.data.size());
@@ -221,9 +243,9 @@ void RtpSenderReceiver::OnMessage(talk_base::Message* pmsg) {
int wait = talk_base::TimeUntil(
start_send_time_ + rtp_dump_packet_.elapsed_time);
wait = talk_base::_max(0, wait);
- PostDelayed(wait, this);
+ sender_thread_->PostDelayed(wait, this);
} else {
- Quit();
+ sender_thread_->Quit();
}
}
@@ -257,10 +279,12 @@ bool RtpSenderReceiver::SendRtpPacket(const void* data, size_t len) {
///////////////////////////////////////////////////////////////////////////
FileVoiceChannel::FileVoiceChannel(
talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream)
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* rtp_sender_thread)
: send_ssrc_(0),
rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
- output_file_stream)) {}
+ output_file_stream,
+ rtp_sender_thread)) {}
FileVoiceChannel::~FileVoiceChannel() {}
@@ -291,7 +315,8 @@ bool FileVoiceChannel::RemoveSendStream(uint32 ssrc) {
return true;
}
-void FileVoiceChannel::OnPacketReceived(talk_base::Buffer* packet) {
+void FileVoiceChannel::OnPacketReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
rtp_sender_receiver_->OnPacketReceived(packet);
}
@@ -300,10 +325,12 @@ void FileVoiceChannel::OnPacketReceived(talk_base::Buffer* packet) {
///////////////////////////////////////////////////////////////////////////
FileVideoChannel::FileVideoChannel(
talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream)
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* rtp_sender_thread)
: send_ssrc_(0),
rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
- output_file_stream)) {}
+ output_file_stream,
+ rtp_sender_thread)) {}
FileVideoChannel::~FileVideoChannel() {}
@@ -334,7 +361,8 @@ bool FileVideoChannel::RemoveSendStream(uint32 ssrc) {
return true;
}
-void FileVideoChannel::OnPacketReceived(talk_base::Buffer* packet) {
+void FileVideoChannel::OnPacketReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
rtp_sender_receiver_->OnPacketReceived(packet);
}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/filemediaengine.h b/chromium/third_party/libjingle/source/talk/media/base/filemediaengine.h
index 2c8525d9630..dfdb037ab38 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/filemediaengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/filemediaengine.h
@@ -50,7 +50,7 @@ namespace cricket {
// only the RTP dump packets. TODO(whyuan): Enable RTCP packets.
class FileMediaEngine : public MediaEngineInterface {
public:
- FileMediaEngine() {}
+ FileMediaEngine() : rtp_sender_thread_(NULL) {}
virtual ~FileMediaEngine() {}
// Set the file name of the input or output RTP dump for voice or video.
@@ -86,12 +86,16 @@ class FileMediaEngine : public MediaEngineInterface {
virtual VoiceMediaChannel* CreateChannel();
virtual VideoMediaChannel* CreateVideoChannel(VoiceMediaChannel* voice_ch);
virtual SoundclipMedia* CreateSoundclip() { return NULL; }
- virtual bool SetAudioOptions(int options) { return true; }
- virtual bool SetVideoOptions(int options) { return true; }
+ virtual AudioOptions GetAudioOptions() const { return AudioOptions(); }
+ virtual bool SetAudioOptions(const AudioOptions& options) { return true; }
+ virtual bool SetVideoOptions(const VideoOptions& options) { return true; }
virtual bool SetAudioDelayOffset(int offset) { return true; }
virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) {
return true;
}
+ virtual VideoEncoderConfig GetDefaultVideoEncoderConfig() const {
+ return VideoEncoderConfig();
+ }
virtual bool SetSoundDevices(const Device* in_dev, const Device* out_dev) {
return true;
}
@@ -155,6 +159,10 @@ class FileMediaEngine : public MediaEngineInterface {
return signal_state_change_;
}
+ void set_rtp_sender_thread(talk_base::Thread* thread) {
+ rtp_sender_thread_ = thread;
+ }
+
private:
std::string voice_input_filename_;
std::string voice_output_filename_;
@@ -166,6 +174,7 @@ class FileMediaEngine : public MediaEngineInterface {
std::vector<RtpHeaderExtension> video_rtp_header_extensions_;
sigslot::repeater2<VideoCapturer*, CaptureState>
signal_state_change_;
+ talk_base::Thread* rtp_sender_thread_;
DISALLOW_COPY_AND_ASSIGN(FileMediaEngine);
};
@@ -175,7 +184,8 @@ class RtpSenderReceiver; // Forward declaration. Defined in the .cc file.
class FileVoiceChannel : public VoiceMediaChannel {
public:
FileVoiceChannel(talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream);
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* rtp_sender_thread);
virtual ~FileVoiceChannel();
// Implement pure virtual methods of VoiceMediaChannel.
@@ -222,8 +232,10 @@ class FileVoiceChannel : public VoiceMediaChannel {
virtual bool GetStats(VoiceMediaInfo* info) { return true; }
// Implement pure virtual methods of MediaChannel.
- virtual void OnPacketReceived(talk_base::Buffer* packet);
- virtual void OnRtcpReceived(talk_base::Buffer* packet) {}
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) {}
virtual void OnReadyToSend(bool ready) {}
virtual bool AddSendStream(const StreamParams& sp);
virtual bool RemoveSendStream(uint32 ssrc);
@@ -251,7 +263,8 @@ class FileVoiceChannel : public VoiceMediaChannel {
class FileVideoChannel : public VideoMediaChannel {
public:
FileVideoChannel(talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream);
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* rtp_sender_thread);
virtual ~FileVideoChannel();
// Implement pure virtual methods of VideoMediaChannel.
@@ -287,8 +300,10 @@ class FileVideoChannel : public VideoMediaChannel {
virtual bool RequestIntraFrame() { return false; }
// Implement pure virtual methods of MediaChannel.
- virtual void OnPacketReceived(talk_base::Buffer* packet);
- virtual void OnRtcpReceived(talk_base::Buffer* packet) {}
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) {}
virtual void OnReadyToSend(bool ready) {}
virtual bool AddSendStream(const StreamParams& sp);
virtual bool RemoveSendStream(uint32 ssrc);
diff --git a/chromium/third_party/libjingle/source/talk/media/base/filemediaengine_unittest.cc b/chromium/third_party/libjingle/source/talk/media/base/filemediaengine_unittest.cc
index e4d72bbe610..b1b021d090d 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/filemediaengine_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/filemediaengine_unittest.cc
@@ -63,7 +63,7 @@ class FileNetworkInterface : public MediaChannel::NetworkInterface {
if (!packet) return false;
if (media_channel_) {
- media_channel_->OnPacketReceived(packet);
+ media_channel_->OnPacketReceived(packet, talk_base::PacketTime());
}
if (dump_writer_.get() &&
talk_base::SR_SUCCESS != dump_writer_->WriteRtpPacket(
@@ -136,6 +136,7 @@ class FileMediaEngineTest : public testing::Test {
engine_->set_voice_output_filename(voice_out);
engine_->set_video_input_filename(video_in);
engine_->set_video_output_filename(video_out);
+ engine_->set_rtp_sender_thread(talk_base::Thread::Current());
voice_channel_.reset(engine_->CreateChannel());
video_channel_.reset(engine_->CreateVideoChannel(NULL));
@@ -220,8 +221,10 @@ TEST_F(FileMediaEngineTest, TestDefaultImplementation) {
EXPECT_TRUE(NULL == voice_channel_.get());
EXPECT_TRUE(NULL == video_channel_.get());
EXPECT_TRUE(NULL == engine_->CreateSoundclip());
- EXPECT_TRUE(engine_->SetAudioOptions(0));
- EXPECT_TRUE(engine_->SetVideoOptions(0));
+ cricket::AudioOptions audio_options;
+ EXPECT_TRUE(engine_->SetAudioOptions(audio_options));
+ cricket::VideoOptions video_options;
+ EXPECT_TRUE(engine_->SetVideoOptions(video_options));
VideoEncoderConfig video_encoder_config;
EXPECT_TRUE(engine_->SetDefaultVideoEncoderConfig(video_encoder_config));
EXPECT_TRUE(engine_->SetSoundDevices(NULL, NULL));
diff --git a/chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.cc b/chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.cc
index a405f8d28ee..6863311f2dd 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.cc
@@ -276,19 +276,21 @@ bool HybridVideoMediaChannel::GetStats(VideoMediaInfo* info) {
active_channel_->GetStats(info);
}
-void HybridVideoMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
+void HybridVideoMediaChannel::OnPacketReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
// Eat packets until we have an active channel;
if (active_channel_) {
- active_channel_->OnPacketReceived(packet);
+ active_channel_->OnPacketReceived(packet, packet_time);
} else {
LOG(LS_INFO) << "HybridVideoChannel: Eating early RTP packet";
}
}
-void HybridVideoMediaChannel::OnRtcpReceived(talk_base::Buffer* packet) {
+void HybridVideoMediaChannel::OnRtcpReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
// Eat packets until we have an active channel;
if (active_channel_) {
- active_channel_->OnRtcpReceived(packet);
+ active_channel_->OnRtcpReceived(packet, packet_time);
} else {
LOG(LS_INFO) << "HybridVideoChannel: Eating early RTCP packet";
}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.h b/chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.h
index ab638c9e452..a49a1aa2c88 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/hybridvideoengine.h
@@ -87,8 +87,10 @@ class HybridVideoMediaChannel : public VideoMediaChannel {
virtual bool GetStats(VideoMediaInfo* info);
- virtual void OnPacketReceived(talk_base::Buffer* packet);
- virtual void OnRtcpReceived(talk_base::Buffer* packet);
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
virtual void OnReadyToSend(bool ready);
virtual void UpdateAspectRatio(int ratio_w, int ratio_h);
@@ -183,8 +185,8 @@ class HybridVideoEngine : public HybridVideoEngineInterface {
channel1.release(), channel2.release());
}
- bool SetOptions(int o) {
- return video1_.SetOptions(o) && video2_.SetOptions(o);
+ bool SetOptions(const VideoOptions& options) {
+ return video1_.SetOptions(options) && video2_.SetOptions(options);
}
bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) {
VideoEncoderConfig conf = config;
@@ -204,6 +206,20 @@ class HybridVideoEngine : public HybridVideoEngineInterface {
}
return true;
}
+ VideoEncoderConfig GetDefaultEncoderConfig() const {
+ // This looks pretty strange, but, in practice, it'll do sane things if
+ // GetDefaultEncoderConfig is only called after SetDefaultEncoderConfig,
+ // since both engines should be essentially equivalent at that point. If it
+ // hasn't been called, though, we'll use the first meaningful encoder
+ // config, or the config from the second video engine if neither are
+ // meaningful.
+ VideoEncoderConfig config = video1_.GetDefaultEncoderConfig();
+ if (config.max_codec.width != 0) {
+ return config;
+ } else {
+ return video2_.GetDefaultEncoderConfig();
+ }
+ }
const std::vector<VideoCodec>& codecs() const {
return codecs_;
}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/mediachannel.h b/chromium/third_party/libjingle/source/talk/media/base/mediachannel.h
index 7431bc1001f..94ae03f8d80 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/mediachannel.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/mediachannel.h
@@ -50,6 +50,10 @@ class RateLimiter;
class Timing;
}
+namespace webrtc {
+struct DataChannelInit;
+}
+
namespace cricket {
class AudioRenderer;
@@ -158,29 +162,55 @@ struct AudioOptions {
void SetAll(const AudioOptions& change) {
echo_cancellation.SetFrom(change.echo_cancellation);
auto_gain_control.SetFrom(change.auto_gain_control);
+ rx_auto_gain_control.SetFrom(change.rx_auto_gain_control);
noise_suppression.SetFrom(change.noise_suppression);
highpass_filter.SetFrom(change.highpass_filter);
stereo_swapping.SetFrom(change.stereo_swapping);
typing_detection.SetFrom(change.typing_detection);
+ aecm_generate_comfort_noise.SetFrom(change.aecm_generate_comfort_noise);
conference_mode.SetFrom(change.conference_mode);
adjust_agc_delta.SetFrom(change.adjust_agc_delta);
experimental_agc.SetFrom(change.experimental_agc);
experimental_aec.SetFrom(change.experimental_aec);
aec_dump.SetFrom(change.aec_dump);
+ experimental_acm.SetFrom(change.experimental_acm);
+ tx_agc_target_dbov.SetFrom(change.tx_agc_target_dbov);
+ tx_agc_digital_compression_gain.SetFrom(
+ change.tx_agc_digital_compression_gain);
+ tx_agc_limiter.SetFrom(change.tx_agc_limiter);
+ rx_agc_target_dbov.SetFrom(change.rx_agc_target_dbov);
+ rx_agc_digital_compression_gain.SetFrom(
+ change.rx_agc_digital_compression_gain);
+ rx_agc_limiter.SetFrom(change.rx_agc_limiter);
+ recording_sample_rate.SetFrom(change.recording_sample_rate);
+ playout_sample_rate.SetFrom(change.playout_sample_rate);
+ dscp.SetFrom(change.dscp);
}
bool operator==(const AudioOptions& o) const {
return echo_cancellation == o.echo_cancellation &&
auto_gain_control == o.auto_gain_control &&
+ rx_auto_gain_control == o.rx_auto_gain_control &&
noise_suppression == o.noise_suppression &&
highpass_filter == o.highpass_filter &&
stereo_swapping == o.stereo_swapping &&
typing_detection == o.typing_detection &&
+ aecm_generate_comfort_noise == o.aecm_generate_comfort_noise &&
conference_mode == o.conference_mode &&
experimental_agc == o.experimental_agc &&
experimental_aec == o.experimental_aec &&
adjust_agc_delta == o.adjust_agc_delta &&
- aec_dump == o.aec_dump;
+ aec_dump == o.aec_dump &&
+ experimental_acm == o.experimental_acm &&
+ tx_agc_target_dbov == o.tx_agc_target_dbov &&
+ tx_agc_digital_compression_gain == o.tx_agc_digital_compression_gain &&
+ tx_agc_limiter == o.tx_agc_limiter &&
+ rx_agc_target_dbov == o.rx_agc_target_dbov &&
+ rx_agc_digital_compression_gain == o.rx_agc_digital_compression_gain &&
+ rx_agc_limiter == o.rx_agc_limiter &&
+ recording_sample_rate == o.recording_sample_rate &&
+ playout_sample_rate == o.playout_sample_rate &&
+ dscp == o.dscp;
}
std::string ToString() const {
@@ -188,15 +218,29 @@ struct AudioOptions {
ost << "AudioOptions {";
ost << ToStringIfSet("aec", echo_cancellation);
ost << ToStringIfSet("agc", auto_gain_control);
+ ost << ToStringIfSet("rx_agc", rx_auto_gain_control);
ost << ToStringIfSet("ns", noise_suppression);
ost << ToStringIfSet("hf", highpass_filter);
ost << ToStringIfSet("swap", stereo_swapping);
ost << ToStringIfSet("typing", typing_detection);
+ ost << ToStringIfSet("comfort_noise", aecm_generate_comfort_noise);
ost << ToStringIfSet("conference", conference_mode);
ost << ToStringIfSet("agc_delta", adjust_agc_delta);
ost << ToStringIfSet("experimental_agc", experimental_agc);
ost << ToStringIfSet("experimental_aec", experimental_aec);
ost << ToStringIfSet("aec_dump", aec_dump);
+ ost << ToStringIfSet("experimental_acm", experimental_acm);
+ ost << ToStringIfSet("tx_agc_target_dbov", tx_agc_target_dbov);
+ ost << ToStringIfSet("tx_agc_digital_compression_gain",
+ tx_agc_digital_compression_gain);
+ ost << ToStringIfSet("tx_agc_limiter", tx_agc_limiter);
+ ost << ToStringIfSet("rx_agc_target_dbov", rx_agc_target_dbov);
+ ost << ToStringIfSet("rx_agc_digital_compression_gain",
+ rx_agc_digital_compression_gain);
+ ost << ToStringIfSet("rx_agc_limiter", rx_agc_limiter);
+ ost << ToStringIfSet("recording_sample_rate", recording_sample_rate);
+ ost << ToStringIfSet("playout_sample_rate", playout_sample_rate);
+ ost << ToStringIfSet("dscp", dscp);
ost << "}";
return ost.str();
}
@@ -206,6 +250,8 @@ struct AudioOptions {
Settable<bool> echo_cancellation;
// Audio processing to adjust the sensitivity of the local mic dynamically.
Settable<bool> auto_gain_control;
+ // Audio processing to apply gain to the remote audio.
+ Settable<bool> rx_auto_gain_control;
// Audio processing to filter out background noise.
Settable<bool> noise_suppression;
// Audio processing to remove background noise of lower frequencies.
@@ -214,11 +260,24 @@ struct AudioOptions {
Settable<bool> stereo_swapping;
// Audio processing to detect typing.
Settable<bool> typing_detection;
+ Settable<bool> aecm_generate_comfort_noise;
Settable<bool> conference_mode;
Settable<int> adjust_agc_delta;
Settable<bool> experimental_agc;
Settable<bool> experimental_aec;
Settable<bool> aec_dump;
+ Settable<bool> experimental_acm;
+ // Note that tx_agc_* only applies to non-experimental AGC.
+ Settable<uint16> tx_agc_target_dbov;
+ Settable<uint16> tx_agc_digital_compression_gain;
+ Settable<bool> tx_agc_limiter;
+ Settable<uint16> rx_agc_target_dbov;
+ Settable<uint16> rx_agc_digital_compression_gain;
+ Settable<bool> rx_agc_limiter;
+ Settable<uint32> recording_sample_rate;
+ Settable<uint32> playout_sample_rate;
+ // Set DSCP value for packet sent from audio channel.
+ Settable<bool> dscp;
};
// Options that can be applied to a VideoMediaChannel or a VideoMediaEngine.
@@ -239,13 +298,13 @@ struct VideoOptions {
adapt_view_switch.SetFrom(change.adapt_view_switch);
video_adapt_third.SetFrom(change.video_adapt_third);
video_noise_reduction.SetFrom(change.video_noise_reduction);
- video_three_layers.SetFrom(change.video_three_layers);
- video_enable_camera_list.SetFrom(change.video_enable_camera_list);
video_one_layer_screencast.SetFrom(change.video_one_layer_screencast);
video_high_bitrate.SetFrom(change.video_high_bitrate);
video_watermark.SetFrom(change.video_watermark);
video_temporal_layer_screencast.SetFrom(
change.video_temporal_layer_screencast);
+ video_temporal_layer_realtime.SetFrom(
+ change.video_temporal_layer_realtime);
video_leaky_bucket.SetFrom(change.video_leaky_bucket);
cpu_overuse_detection.SetFrom(change.cpu_overuse_detection);
conference_mode.SetFrom(change.conference_mode);
@@ -255,6 +314,9 @@ struct VideoOptions {
system_high_adaptation_threshhold.SetFrom(
change.system_high_adaptation_threshhold);
buffered_mode_latency.SetFrom(change.buffered_mode_latency);
+ lower_min_bitrate.SetFrom(change.lower_min_bitrate);
+ dscp.SetFrom(change.dscp);
+ suspend_below_min_bitrate.SetFrom(change.suspend_below_min_bitrate);
}
bool operator==(const VideoOptions& o) const {
@@ -264,12 +326,11 @@ struct VideoOptions {
adapt_view_switch == o.adapt_view_switch &&
video_adapt_third == o.video_adapt_third &&
video_noise_reduction == o.video_noise_reduction &&
- video_three_layers == o.video_three_layers &&
- video_enable_camera_list == o.video_enable_camera_list &&
video_one_layer_screencast == o.video_one_layer_screencast &&
video_high_bitrate == o.video_high_bitrate &&
video_watermark == o.video_watermark &&
video_temporal_layer_screencast == o.video_temporal_layer_screencast &&
+ video_temporal_layer_realtime == o.video_temporal_layer_realtime &&
video_leaky_bucket == o.video_leaky_bucket &&
cpu_overuse_detection == o.cpu_overuse_detection &&
conference_mode == o.conference_mode &&
@@ -278,7 +339,10 @@ struct VideoOptions {
o.system_low_adaptation_threshhold &&
system_high_adaptation_threshhold ==
o.system_high_adaptation_threshhold &&
- buffered_mode_latency == o.buffered_mode_latency;
+ buffered_mode_latency == o.buffered_mode_latency &&
+ lower_min_bitrate == o.lower_min_bitrate &&
+ dscp == o.dscp &&
+ suspend_below_min_bitrate == o.suspend_below_min_bitrate;
}
std::string ToString() const {
@@ -290,13 +354,13 @@ struct VideoOptions {
ost << ToStringIfSet("adapt view switch", adapt_view_switch);
ost << ToStringIfSet("video adapt third", video_adapt_third);
ost << ToStringIfSet("noise reduction", video_noise_reduction);
- ost << ToStringIfSet("3 layers", video_three_layers);
- ost << ToStringIfSet("camera list", video_enable_camera_list);
ost << ToStringIfSet("1 layer screencast", video_one_layer_screencast);
ost << ToStringIfSet("high bitrate", video_high_bitrate);
ost << ToStringIfSet("watermark", video_watermark);
ost << ToStringIfSet("video temporal layer screencast",
video_temporal_layer_screencast);
+ ost << ToStringIfSet("video temporal layer realtime",
+ video_temporal_layer_realtime);
ost << ToStringIfSet("leaky bucket", video_leaky_bucket);
ost << ToStringIfSet("cpu overuse detection", cpu_overuse_detection);
ost << ToStringIfSet("conference mode", conference_mode);
@@ -304,6 +368,10 @@ struct VideoOptions {
ost << ToStringIfSet("low", system_low_adaptation_threshhold);
ost << ToStringIfSet("high", system_high_adaptation_threshhold);
ost << ToStringIfSet("buffered mode latency", buffered_mode_latency);
+ ost << ToStringIfSet("lower min bitrate", lower_min_bitrate);
+ ost << ToStringIfSet("dscp", dscp);
+ ost << ToStringIfSet("suspend below min bitrate",
+ suspend_below_min_bitrate);
ost << "}";
return ost.str();
}
@@ -320,10 +388,6 @@ struct VideoOptions {
Settable<bool> video_adapt_third;
// Enable denoising?
Settable<bool> video_noise_reduction;
- // Experimental: Enable multi layer?
- Settable<bool> video_three_layers;
- // Experimental: Enable camera list?
- Settable<bool> video_enable_camera_list;
// Experimental: Enable one layer screencast?
Settable<bool> video_one_layer_screencast;
// Experimental: Enable WebRtc higher bitrate?
@@ -332,6 +396,8 @@ struct VideoOptions {
Settable<bool> video_watermark;
// Experimental: Enable WebRTC layered screencast.
Settable<bool> video_temporal_layer_screencast;
+ // Experimental: Enable WebRTC temporal layer strategy for realtime video.
+ Settable<bool> video_temporal_layer_realtime;
// Enable WebRTC leaky bucket when sending media packets.
Settable<bool> video_leaky_bucket;
// Enable WebRTC Cpu Overuse Detection, which is a new version of the CPU
@@ -348,6 +414,13 @@ struct VideoOptions {
SettablePercent system_high_adaptation_threshhold;
// Specify buffered mode latency in milliseconds.
Settable<int> buffered_mode_latency;
+ // Make minimum configured send bitrate even lower than usual, at 30kbit.
+ Settable<bool> lower_min_bitrate;
+ // Set DSCP value for packet sent from video channel.
+ Settable<bool> dscp;
+ // Enable WebRTC suspension of video. No video frames will be sent when the
+ // bitrate is below the configured minimum bitrate.
+ Settable<bool> suspend_below_min_bitrate;
};
// A class for playing out soundclips.
@@ -436,9 +509,11 @@ class MediaChannel : public sigslot::has_slots<> {
}
// Called when a RTP packet is received.
- virtual void OnPacketReceived(talk_base::Buffer* packet) = 0;
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) = 0;
// Called when a RTCP packet is received.
- virtual void OnRtcpReceived(talk_base::Buffer* packet) = 0;
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) = 0;
// Called when the socket's ability to send has changed.
virtual void OnReadyToSend(bool ready) = 0;
// Creates a new outgoing media stream with SSRCs and CNAME as described
@@ -486,6 +561,21 @@ class MediaChannel : public sigslot::has_slots<> {
return network_interface_->SetOption(type, opt, option);
}
+ protected:
+ // This method sets DSCP |value| on both RTP and RTCP channels.
+ int SetDscp(talk_base::DiffServCodePoint value) {
+ int ret;
+ ret = SetOption(NetworkInterface::ST_RTP,
+ talk_base::Socket::OPT_DSCP,
+ value);
+ if (ret == 0) {
+ ret = SetOption(NetworkInterface::ST_RTCP,
+ talk_base::Socket::OPT_DSCP,
+ value);
+ }
+ return ret;
+ }
+
private:
bool DoSendPacket(talk_base::Buffer* packet, bool rtcp) {
talk_base::CritScope cs(&network_interface_crit_);
@@ -509,15 +599,125 @@ enum SendFlags {
SEND_MICROPHONE
};
-struct VoiceSenderInfo {
- VoiceSenderInfo()
+// The stats information is structured as follows:
+// Media are represented by either MediaSenderInfo or MediaReceiverInfo.
+// Media contains a vector of SSRC infos that are exclusively used by this
+// media. (SSRCs shared between media streams can't be represented.)
+
+// Information about an SSRC.
+// This data may be locally recorded, or received in an RTCP SR or RR.
+struct SsrcSenderInfo {
+ SsrcSenderInfo()
: ssrc(0),
- bytes_sent(0),
+ timestamp(0) {
+ }
+ uint32 ssrc;
+ double timestamp; // NTP timestamp, represented as seconds since epoch.
+};
+
+struct SsrcReceiverInfo {
+ SsrcReceiverInfo()
+ : ssrc(0),
+ timestamp(0) {
+ }
+ uint32 ssrc;
+ double timestamp;
+};
+
+struct MediaSenderInfo {
+ MediaSenderInfo()
+ : bytes_sent(0),
packets_sent(0),
packets_lost(0),
fraction_lost(0.0),
- ext_seqnum(0),
- rtt_ms(0),
+ rtt_ms(0) {
+ }
+ void add_ssrc(const SsrcSenderInfo& stat) {
+ local_stats.push_back(stat);
+ }
+ // Temporary utility function for call sites that only provide SSRC.
+ // As more info is added into SsrcSenderInfo, this function should go away.
+ void add_ssrc(uint32 ssrc) {
+ SsrcSenderInfo stat;
+ stat.ssrc = ssrc;
+ add_ssrc(stat);
+ }
+ // Utility accessor for clients that are only interested in ssrc numbers.
+ std::vector<uint32> ssrcs() const {
+ std::vector<uint32> retval;
+ for (std::vector<SsrcSenderInfo>::const_iterator it = local_stats.begin();
+ it != local_stats.end(); ++it) {
+ retval.push_back(it->ssrc);
+ }
+ return retval;
+ }
+ // Utility accessor for clients that make the assumption only one ssrc
+ // exists per media.
+ // This will eventually go away.
+ uint32 ssrc() const {
+ if (local_stats.size() > 0) {
+ return local_stats[0].ssrc;
+ } else {
+ return 0;
+ }
+ }
+ int64 bytes_sent;
+ int packets_sent;
+ int packets_lost;
+ float fraction_lost;
+ int rtt_ms;
+ std::string codec_name;
+ std::vector<SsrcSenderInfo> local_stats;
+ std::vector<SsrcReceiverInfo> remote_stats;
+};
+
+struct MediaReceiverInfo {
+ MediaReceiverInfo()
+ : bytes_rcvd(0),
+ packets_rcvd(0),
+ packets_lost(0),
+ fraction_lost(0.0) {
+ }
+ void add_ssrc(const SsrcReceiverInfo& stat) {
+ local_stats.push_back(stat);
+ }
+ // Temporary utility function for call sites that only provide SSRC.
+ // As more info is added into SsrcSenderInfo, this function should go away.
+ void add_ssrc(uint32 ssrc) {
+ SsrcReceiverInfo stat;
+ stat.ssrc = ssrc;
+ add_ssrc(stat);
+ }
+ std::vector<uint32> ssrcs() const {
+ std::vector<uint32> retval;
+ for (std::vector<SsrcReceiverInfo>::const_iterator it = local_stats.begin();
+ it != local_stats.end(); ++it) {
+ retval.push_back(it->ssrc);
+ }
+ return retval;
+ }
+ // Utility accessor for clients that make the assumption only one ssrc
+ // exists per media.
+ // This will eventually go away.
+ uint32 ssrc() const {
+ if (local_stats.size() > 0) {
+ return local_stats[0].ssrc;
+ } else {
+ return 0;
+ }
+ }
+
+ int64 bytes_rcvd;
+ int packets_rcvd;
+ int packets_lost;
+ float fraction_lost;
+ std::vector<SsrcReceiverInfo> local_stats;
+ std::vector<SsrcSenderInfo> remote_stats;
+};
+
+struct VoiceSenderInfo : public MediaSenderInfo {
+ VoiceSenderInfo()
+ : ext_seqnum(0),
jitter_ms(0),
audio_level(0),
aec_quality_min(0.0),
@@ -528,14 +728,7 @@ struct VoiceSenderInfo {
typing_noise_detected(false) {
}
- uint32 ssrc;
- std::string codec_name;
- int64 bytes_sent;
- int packets_sent;
- int packets_lost;
- float fraction_lost;
int ext_seqnum;
- int rtt_ms;
int jitter_ms;
int audio_level;
float aec_quality_min;
@@ -546,14 +739,9 @@ struct VoiceSenderInfo {
bool typing_noise_detected;
};
-struct VoiceReceiverInfo {
+struct VoiceReceiverInfo : public MediaReceiverInfo {
VoiceReceiverInfo()
- : ssrc(0),
- bytes_rcvd(0),
- packets_rcvd(0),
- packets_lost(0),
- fraction_lost(0.0),
- ext_seqnum(0),
+ : ext_seqnum(0),
jitter_ms(0),
jitter_buffer_ms(0),
jitter_buffer_preferred_ms(0),
@@ -562,11 +750,6 @@ struct VoiceReceiverInfo {
expand_rate(0) {
}
- uint32 ssrc;
- int64 bytes_rcvd;
- int packets_rcvd;
- int packets_lost;
- float fraction_lost;
int ext_seqnum;
int jitter_ms;
int jitter_buffer_ms;
@@ -577,36 +760,28 @@ struct VoiceReceiverInfo {
float expand_rate;
};
-struct VideoSenderInfo {
+struct VideoSenderInfo : public MediaSenderInfo {
VideoSenderInfo()
- : bytes_sent(0),
- packets_sent(0),
- packets_cached(0),
- packets_lost(0),
- fraction_lost(0.0),
+ : packets_cached(0),
firs_rcvd(0),
nacks_rcvd(0),
- rtt_ms(0),
frame_width(0),
frame_height(0),
framerate_input(0),
framerate_sent(0),
nominal_bitrate(0),
preferred_bitrate(0),
- adapt_reason(0) {
+ adapt_reason(0),
+ capture_jitter_ms(0),
+ avg_encode_ms(0),
+ encode_usage_percent(0),
+ capture_queue_delay_ms_per_s(0) {
}
- std::vector<uint32> ssrcs;
std::vector<SsrcGroup> ssrc_groups;
- std::string codec_name;
- int64 bytes_sent;
- int packets_sent;
int packets_cached;
- int packets_lost;
- float fraction_lost;
int firs_rcvd;
int nacks_rcvd;
- int rtt_ms;
int frame_width;
int frame_height;
int framerate_input;
@@ -614,15 +789,15 @@ struct VideoSenderInfo {
int nominal_bitrate;
int preferred_bitrate;
int adapt_reason;
+ int capture_jitter_ms;
+ int avg_encode_ms;
+ int encode_usage_percent;
+ int capture_queue_delay_ms_per_s;
};
-struct VideoReceiverInfo {
+struct VideoReceiverInfo : public MediaReceiverInfo {
VideoReceiverInfo()
- : bytes_rcvd(0),
- packets_rcvd(0),
- packets_lost(0),
- packets_concealed(0),
- fraction_lost(0.0),
+ : packets_concealed(0),
firs_sent(0),
nacks_sent(0),
frame_width(0),
@@ -631,17 +806,18 @@ struct VideoReceiverInfo {
framerate_decoded(0),
framerate_output(0),
framerate_render_input(0),
- framerate_render_output(0) {
+ framerate_render_output(0),
+ decode_ms(0),
+ max_decode_ms(0),
+ jitter_buffer_ms(0),
+ min_playout_delay_ms(0),
+ render_delay_ms(0),
+ target_delay_ms(0),
+ current_delay_ms(0) {
}
- std::vector<uint32> ssrcs;
std::vector<SsrcGroup> ssrc_groups;
- int64 bytes_rcvd;
- // vector<int> layer_bytes_rcvd;
- int packets_rcvd;
- int packets_lost;
int packets_concealed;
- float fraction_lost;
int firs_sent;
int nacks_sent;
int frame_width;
@@ -653,31 +829,42 @@ struct VideoReceiverInfo {
int framerate_render_input;
// Framerate that the renderer reports.
int framerate_render_output;
+
+ // All stats below are gathered per-VideoReceiver, but some will be correlated
+ // across MediaStreamTracks. NOTE(hta): when sinking stats into per-SSRC
+ // structures, reflect this in the new layout.
+
+ // Current frame decode latency.
+ int decode_ms;
+ // Maximum observed frame decode latency.
+ int max_decode_ms;
+ // Jitter (network-related) latency.
+ int jitter_buffer_ms;
+ // Requested minimum playout latency.
+ int min_playout_delay_ms;
+ // Requested latency to account for rendering delay.
+ int render_delay_ms;
+ // Target overall delay: network+decode+render, accounting for
+ // min_playout_delay_ms.
+ int target_delay_ms;
+ // Current overall delay, possibly ramping towards target_delay_ms.
+ int current_delay_ms;
};
-struct DataSenderInfo {
+struct DataSenderInfo : public MediaSenderInfo {
DataSenderInfo()
- : ssrc(0),
- bytes_sent(0),
- packets_sent(0) {
+ : ssrc(0) {
}
uint32 ssrc;
- std::string codec_name;
- int64 bytes_sent;
- int packets_sent;
};
-struct DataReceiverInfo {
+struct DataReceiverInfo : public MediaReceiverInfo {
DataReceiverInfo()
- : ssrc(0),
- bytes_rcvd(0),
- packets_rcvd(0) {
+ : ssrc(0) {
}
uint32 ssrc;
- int64 bytes_rcvd;
- int packets_rcvd;
};
struct BandwidthEstimationInfo {
@@ -946,25 +1133,15 @@ class DataMediaChannel : public MediaChannel {
virtual ~DataMediaChannel() {}
- virtual bool SetSendBandwidth(bool autobw, int bps) = 0;
virtual bool SetSendCodecs(const std::vector<DataCodec>& codecs) = 0;
virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs) = 0;
- virtual bool SetRecvRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& extensions) = 0;
- virtual bool SetSendRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& extensions) = 0;
- virtual bool AddSendStream(const StreamParams& sp) = 0;
- virtual bool RemoveSendStream(uint32 ssrc) = 0;
- virtual bool AddRecvStream(const StreamParams& sp) = 0;
- virtual bool RemoveRecvStream(uint32 ssrc) = 0;
+
virtual bool MuteStream(uint32 ssrc, bool on) { return false; }
// TODO(pthatcher): Implement this.
virtual bool GetStats(DataMediaInfo* info) { return true; }
virtual bool SetSend(bool send) = 0;
virtual bool SetReceive(bool receive) = 0;
- virtual void OnPacketReceived(talk_base::Buffer* packet) = 0;
- virtual void OnRtcpReceived(talk_base::Buffer* packet) = 0;
virtual bool SendData(
const SendDataParams& params,
@@ -980,6 +1157,11 @@ class DataMediaChannel : public MediaChannel {
// Signal when the media channel is ready to send the stream. Arguments are:
// writable(bool)
sigslot::signal1<bool> SignalReadyToSend;
+ // Signal for notifying when a new stream is added from the remote side. Used
+ // for the in-band negotioation through the OPEN message for SCTP data
+ // channel.
+ sigslot::signal2<const std::string&, const webrtc::DataChannelInit&>
+ SignalNewStreamReceived;
};
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/media/base/mediaengine.h b/chromium/third_party/libjingle/source/talk/media/base/mediaengine.h
index 8ebc13b1086..f9165728dde 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/mediaengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/mediaengine.h
@@ -60,30 +60,6 @@ class VideoCapturer;
// proper synchronization between both media types.
class MediaEngineInterface {
public:
- // Bitmask flags for options that may be supported by the media engine
- // implementation. This can be converted to and from an
- // AudioOptions struct for backwards compatibility with calls that
- // use flags until we transition to using structs everywhere.
- enum AudioFlags {
- // Audio processing that attempts to filter away the output signal from
- // later inbound pickup.
- ECHO_CANCELLATION = 1 << 0,
- // Audio processing to adjust the sensitivity of the local mic dynamically.
- AUTO_GAIN_CONTROL = 1 << 1,
- // Audio processing to filter out background noise.
- NOISE_SUPPRESSION = 1 << 2,
- // Audio processing to remove background noise of lower frequencies.
- HIGHPASS_FILTER = 1 << 3,
- // A switch to swap which captured signal is left and right in stereo mode.
- STEREO_FLIPPING = 1 << 4,
- // Controls delegation echo cancellation to use the OS' facility.
- SYSTEM_AEC_MODE = 1 << 5,
-
- ALL_AUDIO_OPTIONS = (1 << 6) - 1,
- DEFAULT_AUDIO_OPTIONS = ECHO_CANCELLATION | AUTO_GAIN_CONTROL |
- NOISE_SUPPRESSION | HIGHPASS_FILTER,
- };
-
// Default value to be used for SetAudioDelayOffset().
static const int kDefaultAudioDelayOffset;
@@ -109,10 +85,12 @@ class MediaEngineInterface {
virtual SoundclipMedia *CreateSoundclip() = 0;
// Configuration
+ // Gets global audio options.
+ virtual AudioOptions GetAudioOptions() const = 0;
// Sets global audio options. "options" are from AudioOptions, above.
- virtual bool SetAudioOptions(int options) = 0;
+ virtual bool SetAudioOptions(const AudioOptions& options) = 0;
// Sets global video options. "options" are from VideoOptions, above.
- virtual bool SetVideoOptions(int options) = 0;
+ virtual bool SetVideoOptions(const VideoOptions& options) = 0;
// Sets the value used by the echo canceller to offset delay values obtained
// from the OS.
virtual bool SetAudioDelayOffset(int offset) = 0;
@@ -120,6 +98,10 @@ class MediaEngineInterface {
// and encode video.
virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config)
= 0;
+ // Gets the default (maximum) codec/resolution and encoder option used to
+ // capture and encode video, as set by SetDefaultVideoEncoderConfig or the
+ // default from the video engine if not previously set.
+ virtual VideoEncoderConfig GetDefaultVideoEncoderConfig() const = 0;
// Device selection
// TODO(tschmelcher): Add method for selecting the soundclip device.
@@ -210,11 +192,14 @@ class CompositeMediaEngine : public MediaEngineInterface {
return voice_.CreateSoundclip();
}
- virtual bool SetAudioOptions(int o) {
- return voice_.SetOptions(o);
+ virtual AudioOptions GetAudioOptions() const {
+ return voice_.GetOptions();
+ }
+ virtual bool SetAudioOptions(const AudioOptions& options) {
+ return voice_.SetOptions(options);
}
- virtual bool SetVideoOptions(int o) {
- return video_.SetOptions(o);
+ virtual bool SetVideoOptions(const VideoOptions& options) {
+ return video_.SetOptions(options);
}
virtual bool SetAudioDelayOffset(int offset) {
return voice_.SetDelayOffset(offset);
@@ -222,6 +207,9 @@ class CompositeMediaEngine : public MediaEngineInterface {
virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) {
return video_.SetDefaultEncoderConfig(config);
}
+ virtual VideoEncoderConfig GetDefaultVideoEncoderConfig() const {
+ return video_.GetDefaultEncoderConfig();
+ }
virtual bool SetSoundDevices(const Device* in_device,
const Device* out_device) {
@@ -304,7 +292,8 @@ class NullVoiceEngine {
return NULL;
}
bool SetDelayOffset(int offset) { return true; }
- bool SetOptions(int opts) { return true; }
+ AudioOptions GetOptions() const { return AudioOptions(); }
+ bool SetOptions(const AudioOptions& options) { return true; }
bool SetDevices(const Device* in_device, const Device* out_device) {
return true;
}
@@ -344,7 +333,10 @@ class NullVideoEngine {
VoiceMediaChannel* voice_media_channel) {
return NULL;
}
- bool SetOptions(int opts) { return true; }
+ bool SetOptions(const VideoOptions& options) { return true; }
+ VideoEncoderConfig GetDefaultEncoderConfig() const {
+ return VideoEncoderConfig();
+ }
bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) {
return true;
}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.cc b/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.cc
index 2a23c100597..0f84c836fc6 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.cc
@@ -230,7 +230,8 @@ bool RtpDataMediaChannel::RemoveRecvStream(uint32 ssrc) {
return true;
}
-void RtpDataMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
+void RtpDataMediaChannel::OnPacketReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
RtpHeader header;
if (!GetRtpHeader(packet->data(), packet->length(), &header)) {
// Don't want to log for every corrupt packet.
@@ -259,10 +260,12 @@ void RtpDataMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
DataCodec codec;
if (!FindCodecById(recv_codecs_, header.payload_type, &codec)) {
- LOG(LS_WARNING) << "Not receiving packet "
- << header.ssrc << ":" << header.seq_num
- << " (" << data_len << ")"
- << " because unknown payload id: " << header.payload_type;
+ // For bundling, this will be logged for every message.
+ // So disable this logging.
+ // LOG(LS_WARNING) << "Not receiving packet "
+ // << header.ssrc << ":" << header.seq_num
+ // << " (" << data_len << ")"
+ // << " because unknown payload id: " << header.payload_type;
return;
}
@@ -342,10 +345,6 @@ bool RtpDataMediaChannel::SendData(
<< "; already sent " << send_limiter_->used_in_period()
<< "/" << send_limiter_->max_per_period();
return false;
- } else {
- LOG(LS_VERBOSE) << "Sending data packet of len=" << packet_len
- << "; already sent " << send_limiter_->used_in_period()
- << "/" << send_limiter_->max_per_period();
}
RtpHeader header;
@@ -363,12 +362,12 @@ bool RtpDataMediaChannel::SendData(
packet.AppendData(&kReservedSpace, sizeof(kReservedSpace));
packet.AppendData(payload.data(), payload.length());
- // Uncomment this for easy debugging.
- // LOG(LS_INFO) << "Sent packet: "
- // << " stream=" << found_stream.id
- // << ", seqnum=" << header.seq_num
- // << ", timestamp=" << header.timestamp
- // << ", len=" << data_len;
+ LOG(LS_VERBOSE) << "Sent RTP data packet: "
+ << " stream=" << found_stream.id
+ << " ssrc=" << header.ssrc
+ << ", seqnum=" << header.seq_num
+ << ", timestamp=" << header.timestamp
+ << ", len=" << payload.length();
MediaChannel::SendPacket(&packet);
send_limiter_->Use(packet_len, now);
diff --git a/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.h b/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.h
index bc7b667eac6..59e6589532d 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine.h
@@ -115,8 +115,10 @@ class RtpDataMediaChannel : public DataMediaChannel {
receiving_ = receive;
return true;
}
- virtual void OnPacketReceived(talk_base::Buffer* packet);
- virtual void OnRtcpReceived(talk_base::Buffer* packet) {}
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) {}
virtual void OnReadyToSend(bool ready) {}
virtual bool SendData(
const SendDataParams& params,
diff --git a/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine_unittest.cc b/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine_unittest.cc
index 4ee072ee782..a86ab3b3125 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/rtpdataengine_unittest.cc
@@ -294,7 +294,8 @@ TEST_F(RtpDataMediaChannelTest, SendData) {
cricket::RtpHeader header1 = GetSentDataHeader(1);
EXPECT_EQ(header1.ssrc, 42U);
EXPECT_EQ(header1.payload_type, 103);
- EXPECT_EQ(header0.seq_num + 1, header1.seq_num);
+ EXPECT_EQ(static_cast<uint16>(header0.seq_num + 1),
+ static_cast<uint16>(header1.seq_num));
EXPECT_EQ(header0.timestamp + 180000, header1.timestamp);
}
@@ -353,9 +354,11 @@ TEST_F(RtpDataMediaChannelTest, SendDataMultipleClocks) {
cricket::RtpHeader header1b = GetSentDataHeader(2);
cricket::RtpHeader header2b = GetSentDataHeader(3);
- EXPECT_EQ(header1a.seq_num + 1, header1b.seq_num);
+ EXPECT_EQ(static_cast<uint16>(header1a.seq_num + 1),
+ static_cast<uint16>(header1b.seq_num));
EXPECT_EQ(header1a.timestamp + 90000, header1b.timestamp);
- EXPECT_EQ(header2a.seq_num + 1, header2b.seq_num);
+ EXPECT_EQ(static_cast<uint16>(header2a.seq_num + 1),
+ static_cast<uint16>(header2b.seq_num));
EXPECT_EQ(header2a.timestamp + 180000, header2b.timestamp);
}
@@ -420,13 +423,13 @@ TEST_F(RtpDataMediaChannelTest, ReceiveData) {
talk_base::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
// SetReceived not called.
- dmc->OnPacketReceived(&packet);
+ dmc->OnPacketReceived(&packet, talk_base::PacketTime());
EXPECT_FALSE(HasReceivedData());
dmc->SetReceive(true);
// Unknown payload id
- dmc->OnPacketReceived(&packet);
+ dmc->OnPacketReceived(&packet, talk_base::PacketTime());
EXPECT_FALSE(HasReceivedData());
cricket::DataCodec codec;
@@ -437,7 +440,7 @@ TEST_F(RtpDataMediaChannelTest, ReceiveData) {
ASSERT_TRUE(dmc->SetRecvCodecs(codecs));
// Unknown stream
- dmc->OnPacketReceived(&packet);
+ dmc->OnPacketReceived(&packet, talk_base::PacketTime());
EXPECT_FALSE(HasReceivedData());
cricket::StreamParams stream;
@@ -445,7 +448,7 @@ TEST_F(RtpDataMediaChannelTest, ReceiveData) {
ASSERT_TRUE(dmc->AddRecvStream(stream));
// Finally works!
- dmc->OnPacketReceived(&packet);
+ dmc->OnPacketReceived(&packet, talk_base::PacketTime());
EXPECT_TRUE(HasReceivedData());
EXPECT_EQ("abcde", GetReceivedData());
EXPECT_EQ(5U, GetReceivedDataLen());
@@ -460,6 +463,6 @@ TEST_F(RtpDataMediaChannelTest, InvalidRtpPackets) {
talk_base::scoped_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
// Too short
- dmc->OnPacketReceived(&packet);
+ dmc->OnPacketReceived(&packet, talk_base::PacketTime());
EXPECT_FALSE(HasReceivedData());
}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/streamparams.cc b/chromium/third_party/libjingle/source/talk/media/base/streamparams.cc
index 08eeea7a42a..19d8269044a 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/streamparams.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/streamparams.cc
@@ -27,12 +27,14 @@
#include "talk/media/base/streamparams.h"
+#include <list>
#include <sstream>
namespace cricket {
const char kFecSsrcGroupSemantics[] = "FEC";
const char kFidSsrcGroupSemantics[] = "FID";
+const char kSimSsrcGroupSemantics[] = "SIM";
static std::string SsrcsToString(const std::vector<uint32>& ssrcs) {
std::ostringstream ost;
@@ -179,4 +181,49 @@ bool RemoveStreamByIds(StreamParamsVec* streams,
return RemoveStream(streams, StreamSelector(groupid, id));
}
+bool IsOneSsrcStream(const StreamParams& sp) {
+ if (sp.ssrcs.size() == 1 && sp.ssrc_groups.empty()) {
+ return true;
+ }
+ if (sp.ssrcs.size() == 2) {
+ const SsrcGroup* fid_group = sp.get_ssrc_group(kFidSsrcGroupSemantics);
+ if (fid_group != NULL) {
+ return (sp.ssrcs == fid_group->ssrcs);
+ }
+ }
+ return false;
+}
+
+static void RemoveFirst(std::list<uint32>* ssrcs, uint32 value) {
+ std::list<uint32>::iterator it =
+ std::find(ssrcs->begin(), ssrcs->end(), value);
+ if (it != ssrcs->end()) {
+ ssrcs->erase(it);
+ }
+}
+
+bool IsSimulcastStream(const StreamParams& sp) {
+ const SsrcGroup* const sg = sp.get_ssrc_group(kSimSsrcGroupSemantics);
+ if (sg == NULL || sg->ssrcs.size() < 2) {
+ return false;
+ }
+ // Start with all StreamParams SSRCs. Remove simulcast SSRCs (from sg) and
+ // RTX SSRCs. If we still have SSRCs left, we don't know what they're for.
+ // Also we remove first-found SSRCs only. So duplicates should lead to errors.
+ std::list<uint32> sp_ssrcs(sp.ssrcs.begin(), sp.ssrcs.end());
+ for (size_t i = 0; i < sg->ssrcs.size(); ++i) {
+ RemoveFirst(&sp_ssrcs, sg->ssrcs[i]);
+ }
+ for (size_t i = 0; i < sp.ssrc_groups.size(); ++i) {
+ const SsrcGroup& group = sp.ssrc_groups[i];
+ if (group.semantics.compare(kFidSsrcGroupSemantics) != 0 ||
+ group.ssrcs.size() != 2) {
+ continue;
+ }
+ RemoveFirst(&sp_ssrcs, group.ssrcs[1]);
+ }
+ // If there's SSRCs left that we don't know how to handle, we bail out.
+ return sp_ssrcs.size() == 0;
+}
+
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/media/base/streamparams.h b/chromium/third_party/libjingle/source/talk/media/base/streamparams.h
index 1561d6f92ea..b57f1f7810f 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/streamparams.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/streamparams.h
@@ -31,6 +31,14 @@
// described by one StreamParams object
// SsrcGroup is used to describe the relationship between the SSRCs that
// are used for this media source.
+// E.x: Consider a source that is sent as 3 simulcast streams
+// Let the simulcast elements have SSRC 10, 20, 30.
+// Let each simulcast element use FEC and let the protection packets have
+// SSRC 11,21,31.
+// To describe this 4 SsrcGroups are needed,
+// StreamParams would then contain ssrc = {10,11,20,21,30,31} and
+// ssrc_groups = {{SIM,{10,20,30}, {FEC,{10,11}, {FEC, {20,21}, {FEC {30,31}}}
+// Please see RFC 5576.
#ifndef TALK_MEDIA_BASE_STREAMPARAMS_H_
#define TALK_MEDIA_BASE_STREAMPARAMS_H_
@@ -46,6 +54,7 @@ namespace cricket {
extern const char kFecSsrcGroupSemantics[];
extern const char kFidSsrcGroupSemantics[];
+extern const char kSimSsrcGroupSemantics[];
struct SsrcGroup {
SsrcGroup(const std::string& usage, const std::vector<uint32>& ssrcs)
@@ -204,6 +213,16 @@ bool RemoveStreamByIds(StreamParamsVec* streams,
const std::string& groupid,
const std::string& id);
+// Checks if |sp| defines parameters for a single primary stream. There may
+// be an RTX stream associated with the primary stream. Leaving as non-static so
+// we can test this function.
+bool IsOneSsrcStream(const StreamParams& sp);
+
+// Checks if |sp| defines parameters for one Simulcast stream. There may be RTX
+// streams associated with the simulcast streams. Leaving as non-static so we
+// can test this function.
+bool IsSimulcastStream(const StreamParams& sp);
+
} // namespace cricket
#endif // TALK_MEDIA_BASE_STREAMPARAMS_H_
diff --git a/chromium/third_party/libjingle/source/talk/media/base/streamparams_unittest.cc b/chromium/third_party/libjingle/source/talk/media/base/streamparams_unittest.cc
index 99d1603e628..f3a03d63635 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/streamparams_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/streamparams_unittest.cc
@@ -29,8 +29,10 @@
#include "talk/media/base/streamparams.h"
#include "talk/media/base/testutils.h"
-static const uint32 kSscrs1[] = {1};
-static const uint32 kSscrs2[] = {1, 2};
+static const uint32 kSsrcs1[] = {1};
+static const uint32 kSsrcs2[] = {1, 2};
+static const uint32 kSsrcs3[] = {1, 2, 3};
+static const uint32 kRtxSsrcs3[] = {4, 5, 6};
static cricket::StreamParams CreateStreamParamsWithSsrcGroup(
const std::string& semantics, const uint32 ssrcs_in[], size_t len) {
@@ -44,10 +46,10 @@ static cricket::StreamParams CreateStreamParamsWithSsrcGroup(
TEST(SsrcGroup, EqualNotEqual) {
cricket::SsrcGroup ssrc_groups[] = {
- cricket::SsrcGroup("ABC", MAKE_VECTOR(kSscrs1)),
- cricket::SsrcGroup("ABC", MAKE_VECTOR(kSscrs2)),
- cricket::SsrcGroup("Abc", MAKE_VECTOR(kSscrs2)),
- cricket::SsrcGroup("abc", MAKE_VECTOR(kSscrs2)),
+ cricket::SsrcGroup("ABC", MAKE_VECTOR(kSsrcs1)),
+ cricket::SsrcGroup("ABC", MAKE_VECTOR(kSsrcs2)),
+ cricket::SsrcGroup("Abc", MAKE_VECTOR(kSsrcs2)),
+ cricket::SsrcGroup("abc", MAKE_VECTOR(kSsrcs2)),
};
for (size_t i = 0; i < ARRAY_SIZE(ssrc_groups); ++i) {
@@ -59,18 +61,18 @@ TEST(SsrcGroup, EqualNotEqual) {
}
TEST(SsrcGroup, HasSemantics) {
- cricket::SsrcGroup sg1("ABC", MAKE_VECTOR(kSscrs1));
+ cricket::SsrcGroup sg1("ABC", MAKE_VECTOR(kSsrcs1));
EXPECT_TRUE(sg1.has_semantics("ABC"));
- cricket::SsrcGroup sg2("Abc", MAKE_VECTOR(kSscrs1));
+ cricket::SsrcGroup sg2("Abc", MAKE_VECTOR(kSsrcs1));
EXPECT_FALSE(sg2.has_semantics("ABC"));
- cricket::SsrcGroup sg3("abc", MAKE_VECTOR(kSscrs1));
+ cricket::SsrcGroup sg3("abc", MAKE_VECTOR(kSsrcs1));
EXPECT_FALSE(sg3.has_semantics("ABC"));
}
TEST(SsrcGroup, ToString) {
- cricket::SsrcGroup sg1("ABC", MAKE_VECTOR(kSscrs1));
+ cricket::SsrcGroup sg1("ABC", MAKE_VECTOR(kSsrcs1));
EXPECT_STREQ("{semantics:ABC;ssrcs:[1]}", sg1.ToString().c_str());
}
@@ -88,22 +90,22 @@ TEST(StreamParams, CreateLegacy) {
TEST(StreamParams, HasSsrcGroup) {
cricket::StreamParams sp =
- CreateStreamParamsWithSsrcGroup("XYZ", kSscrs2, ARRAY_SIZE(kSscrs2));
+ CreateStreamParamsWithSsrcGroup("XYZ", kSsrcs2, ARRAY_SIZE(kSsrcs2));
EXPECT_EQ(2U, sp.ssrcs.size());
- EXPECT_EQ(kSscrs2[0], sp.first_ssrc());
+ EXPECT_EQ(kSsrcs2[0], sp.first_ssrc());
EXPECT_TRUE(sp.has_ssrcs());
- EXPECT_TRUE(sp.has_ssrc(kSscrs2[0]));
- EXPECT_TRUE(sp.has_ssrc(kSscrs2[1]));
+ EXPECT_TRUE(sp.has_ssrc(kSsrcs2[0]));
+ EXPECT_TRUE(sp.has_ssrc(kSsrcs2[1]));
EXPECT_TRUE(sp.has_ssrc_group("XYZ"));
EXPECT_EQ(1U, sp.ssrc_groups.size());
EXPECT_EQ(2U, sp.ssrc_groups[0].ssrcs.size());
- EXPECT_EQ(kSscrs2[0], sp.ssrc_groups[0].ssrcs[0]);
- EXPECT_EQ(kSscrs2[1], sp.ssrc_groups[0].ssrcs[1]);
+ EXPECT_EQ(kSsrcs2[0], sp.ssrc_groups[0].ssrcs[0]);
+ EXPECT_EQ(kSsrcs2[1], sp.ssrc_groups[0].ssrcs[1]);
}
TEST(StreamParams, GetSsrcGroup) {
cricket::StreamParams sp =
- CreateStreamParamsWithSsrcGroup("XYZ", kSscrs2, ARRAY_SIZE(kSscrs2));
+ CreateStreamParamsWithSsrcGroup("XYZ", kSsrcs2, ARRAY_SIZE(kSsrcs2));
EXPECT_EQ(NULL, sp.get_ssrc_group("xyz"));
EXPECT_EQ(&sp.ssrc_groups[0], sp.get_ssrc_group("XYZ"));
}
@@ -112,13 +114,13 @@ TEST(StreamParams, EqualNotEqual) {
cricket::StreamParams l1 = cricket::StreamParams::CreateLegacy(1);
cricket::StreamParams l2 = cricket::StreamParams::CreateLegacy(2);
cricket::StreamParams sg1 =
- CreateStreamParamsWithSsrcGroup("ABC", kSscrs1, ARRAY_SIZE(kSscrs1));
+ CreateStreamParamsWithSsrcGroup("ABC", kSsrcs1, ARRAY_SIZE(kSsrcs1));
cricket::StreamParams sg2 =
- CreateStreamParamsWithSsrcGroup("ABC", kSscrs2, ARRAY_SIZE(kSscrs2));
+ CreateStreamParamsWithSsrcGroup("ABC", kSsrcs2, ARRAY_SIZE(kSsrcs2));
cricket::StreamParams sg3 =
- CreateStreamParamsWithSsrcGroup("Abc", kSscrs2, ARRAY_SIZE(kSscrs2));
+ CreateStreamParamsWithSsrcGroup("Abc", kSsrcs2, ARRAY_SIZE(kSsrcs2));
cricket::StreamParams sg4 =
- CreateStreamParamsWithSsrcGroup("abc", kSscrs2, ARRAY_SIZE(kSscrs2));
+ CreateStreamParamsWithSsrcGroup("abc", kSsrcs2, ARRAY_SIZE(kSsrcs2));
cricket::StreamParams sps[] = {l1, l2, sg1, sg2, sg3, sg4};
for (size_t i = 0; i < ARRAY_SIZE(sps); ++i) {
@@ -159,7 +161,90 @@ TEST(StreamParams, FidFunctions) {
TEST(StreamParams, ToString) {
cricket::StreamParams sp =
- CreateStreamParamsWithSsrcGroup("XYZ", kSscrs2, ARRAY_SIZE(kSscrs2));
+ CreateStreamParamsWithSsrcGroup("XYZ", kSsrcs2, ARRAY_SIZE(kSsrcs2));
EXPECT_STREQ("{ssrcs:[1,2];ssrc_groups:{semantics:XYZ;ssrcs:[1,2]};}",
sp.ToString().c_str());
}
+
+
+TEST(StreamParams, TestIsOneSsrcStream_LegacyStream) {
+ EXPECT_TRUE(
+ cricket::IsOneSsrcStream(cricket::StreamParams::CreateLegacy(13)));
+}
+
+TEST(StreamParams, TestIsOneSsrcStream_SingleRtxStream) {
+ cricket::StreamParams stream;
+ stream.add_ssrc(13);
+ EXPECT_TRUE(stream.AddFidSsrc(13, 14));
+ EXPECT_TRUE(cricket::IsOneSsrcStream(stream));
+}
+
+TEST(StreamParams, TestIsOneSsrcStream_SimulcastStream) {
+ EXPECT_FALSE(cricket::IsOneSsrcStream(
+ cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2))));
+ EXPECT_FALSE(cricket::IsOneSsrcStream(
+ cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3))));
+}
+
+TEST(StreamParams, TestIsOneSsrcStream_SimRtxStream) {
+ cricket::StreamParams stream =
+ cricket::CreateSimWithRtxStreamParams("cname",
+ MAKE_VECTOR(kSsrcs3),
+ MAKE_VECTOR(kRtxSsrcs3));
+ EXPECT_FALSE(cricket::IsOneSsrcStream(stream));
+}
+
+TEST(StreamParams, TestIsSimulcastStream_LegacyStream) {
+ EXPECT_FALSE(
+ cricket::IsSimulcastStream(cricket::StreamParams::CreateLegacy(13)));
+}
+
+TEST(StreamParams, TestIsSimulcastStream_SingleRtxStream) {
+ cricket::StreamParams stream;
+ stream.add_ssrc(13);
+ EXPECT_TRUE(stream.AddFidSsrc(13, 14));
+ EXPECT_FALSE(cricket::IsSimulcastStream(stream));
+}
+
+TEST(StreamParams, TestIsSimulcastStream_SimulcastStream) {
+ EXPECT_TRUE(cricket::IsSimulcastStream(
+ cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2))));
+ EXPECT_TRUE(cricket::IsSimulcastStream(
+ cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3))));
+}
+
+TEST(StreamParams, TestIsSimulcastStream_SimRtxStream) {
+ cricket::StreamParams stream =
+ cricket::CreateSimWithRtxStreamParams("cname",
+ MAKE_VECTOR(kSsrcs3),
+ MAKE_VECTOR(kRtxSsrcs3));
+ EXPECT_TRUE(cricket::IsSimulcastStream(stream));
+}
+
+TEST(StreamParams, TestIsSimulcastStream_InvalidStreams) {
+ // stream1 has extra non-sim, non-fid ssrc.
+ cricket::StreamParams stream1 =
+ cricket::CreateSimWithRtxStreamParams("cname",
+ MAKE_VECTOR(kSsrcs3),
+ MAKE_VECTOR(kRtxSsrcs3));
+ stream1.add_ssrc(25);
+ EXPECT_FALSE(cricket::IsSimulcastStream(stream1));
+
+ // stream2 has invalid fid-group (no primary).
+ cricket::StreamParams stream2;
+ stream2.add_ssrc(13);
+ EXPECT_TRUE(stream2.AddFidSsrc(13, 14));
+ std::remove(stream2.ssrcs.begin(), stream2.ssrcs.end(), 13);
+ EXPECT_FALSE(cricket::IsSimulcastStream(stream2));
+
+ // stream3 has two SIM groups.
+ cricket::StreamParams stream3 =
+ cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs2));
+ std::vector<uint32> sim_ssrcs = MAKE_VECTOR(kRtxSsrcs3);
+ cricket::SsrcGroup sg(cricket::kSimSsrcGroupSemantics, sim_ssrcs);
+ for (size_t i = 0; i < sim_ssrcs.size(); i++) {
+ stream3.add_ssrc(sim_ssrcs[i]);
+ }
+ stream3.ssrc_groups.push_back(sg);
+ EXPECT_FALSE(cricket::IsSimulcastStream(stream3));
+}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/testutils.cc b/chromium/third_party/libjingle/source/talk/media/base/testutils.cc
index 3edb5c7cfbb..9b1b16d21fc 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/testutils.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/testutils.cc
@@ -336,4 +336,30 @@ bool VideoFrameEqual(const VideoFrame* frame0, const VideoFrame* frame1) {
return true;
}
+cricket::StreamParams CreateSimStreamParams(
+ const std::string& cname, const std::vector<uint32>& ssrcs) {
+ cricket::StreamParams sp;
+ cricket::SsrcGroup sg(cricket::kSimSsrcGroupSemantics, ssrcs);
+ sp.ssrcs = ssrcs;
+ sp.ssrc_groups.push_back(sg);
+ sp.cname = cname;
+ return sp;
+}
+
+// There should be an rtx_ssrc per ssrc.
+cricket::StreamParams CreateSimWithRtxStreamParams(
+ const std::string& cname, const std::vector<uint32>& ssrcs,
+ const std::vector<uint32>& rtx_ssrcs) {
+ cricket::StreamParams sp = CreateSimStreamParams(cname, ssrcs);
+ for (size_t i = 0; i < ssrcs.size(); ++i) {
+ sp.ssrcs.push_back(rtx_ssrcs[i]);
+ std::vector<uint32> fid_ssrcs;
+ fid_ssrcs.push_back(ssrcs[i]);
+ fid_ssrcs.push_back(rtx_ssrcs[i]);
+ cricket::SsrcGroup fid_group(cricket::kFidSsrcGroupSemantics, fid_ssrcs);
+ sp.ssrc_groups.push_back(fid_group);
+ }
+ return sp;
+}
+
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/media/base/testutils.h b/chromium/third_party/libjingle/source/talk/media/base/testutils.h
index 4d037b7ba38..dd13d5a0e59 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/testutils.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/testutils.h
@@ -28,13 +28,6 @@
#ifndef TALK_MEDIA_BASE_TESTUTILS_H_
#define TALK_MEDIA_BASE_TESTUTILS_H_
-#ifdef LINUX
-#include <X11/Xlib.h>
-// X defines a few macros that stomp on types that gunit.h uses.
-#undef None
-#undef Bool
-#endif
-
#include <string>
#include <vector>
@@ -245,36 +238,14 @@ bool ContainsMatchingCodec(const std::vector<C>& codecs, const C& codec) {
return false;
}
-#define MAYBE_SKIP_SCREENCAST_TEST() \
- if (!cricket::IsScreencastingAvailable()) { \
- LOG(LS_WARNING) << "Skipping test, since it doesn't have the requisite " \
- << "X environment for screen capture."; \
- return; \
- } \
-
-#ifdef LINUX
-struct XDisplay {
- XDisplay() : display_(XOpenDisplay(NULL)) { }
- ~XDisplay() { if (display_) XCloseDisplay(display_); }
- bool IsValid() const { return display_ != NULL; }
- operator Display*() { return display_; }
- private:
- Display* display_;
-};
-#endif
-
-// Returns true if screencasting is available. When false, anything that uses
-// screencasting features may fail.
-inline bool IsScreencastingAvailable() {
-#ifdef LINUX
- XDisplay display;
- if (!display.IsValid()) {
- LOG(LS_WARNING) << "No X Display available.";
- return false;
- }
-#endif
- return true;
-}
+// Create Simulcast StreamParams with given |ssrcs| and |cname|.
+cricket::StreamParams CreateSimStreamParams(
+ const std::string& cname, const std::vector<uint32>& ssrcs);
+// Create Simulcast stream with given |ssrcs| and |rtx_ssrcs|.
+// The number of |rtx_ssrcs| must match number of |ssrcs|.
+cricket::StreamParams CreateSimWithRtxStreamParams(
+ const std::string& cname, const std::vector<uint32>& ssrcs,
+ const std::vector<uint32>& rtx_ssrcs);
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/media/base/videoadapter.cc b/chromium/third_party/libjingle/source/talk/media/base/videoadapter.cc
index 20114fbd383..22b1f7d8ddb 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/videoadapter.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/videoadapter.cc
@@ -165,8 +165,8 @@ VideoAdapter::VideoAdapter()
frames_(0),
adapted_frames_(0),
adaption_changes_(0),
- previous_width(0),
- previous_height(0),
+ previous_width_(0),
+ previous_height_(0),
black_output_(false),
is_black_(false),
interval_next_frame_(0) {
@@ -240,11 +240,11 @@ int VideoAdapter::GetOutputNumPixels() const {
// TODO(fbarchard): Add AdaptFrameRate function that only drops frames but
// not resolution.
bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
- const VideoFrame** out_frame) {
- talk_base::CritScope cs(&critical_section_);
+ VideoFrame** out_frame) {
if (!in_frame || !out_frame) {
return false;
}
+ talk_base::CritScope cs(&critical_section_);
++frames_;
// Update input to actual frame dimensions.
@@ -306,8 +306,8 @@ bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
// resolution changes as well. Consider dropping the statistics into their
// own class which could be queried publically.
bool changed = false;
- if (previous_width && (previous_width != (*out_frame)->GetWidth() ||
- previous_height != (*out_frame)->GetHeight())) {
+ if (previous_width_ && (previous_width_ != (*out_frame)->GetWidth() ||
+ previous_height_ != (*out_frame)->GetHeight())) {
show = true;
++adaption_changes_;
changed = true;
@@ -325,8 +325,8 @@ bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
<< "x" << (*out_frame)->GetHeight()
<< " Changed: " << (changed ? "true" : "false");
}
- previous_width = (*out_frame)->GetWidth();
- previous_height = (*out_frame)->GetHeight();
+ previous_width_ = (*out_frame)->GetWidth();
+ previous_height_ = (*out_frame)->GetHeight();
return true;
}
@@ -376,7 +376,7 @@ bool VideoAdapter::StretchToOutputFrame(const VideoFrame* in_frame) {
///////////////////////////////////////////////////////////////////////
// Implementation of CoordinatedVideoAdapter
CoordinatedVideoAdapter::CoordinatedVideoAdapter()
- : cpu_adaptation_(false),
+ : cpu_adaptation_(true),
cpu_smoothing_(false),
gd_adaptation_(true),
view_adaptation_(true),
diff --git a/chromium/third_party/libjingle/source/talk/media/base/videoadapter.h b/chromium/third_party/libjingle/source/talk/media/base/videoadapter.h
index 2bd31d5df5c..12be4fab1ab 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/videoadapter.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/videoadapter.h
@@ -62,7 +62,7 @@ class VideoAdapter {
// successfully. Return false otherwise.
// output_frame_ is owned by the VideoAdapter that has the best knowledge on
// the output frame.
- bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame);
+ bool AdaptFrame(const VideoFrame* in_frame, VideoFrame** out_frame);
void set_scale_third(bool enable) {
LOG(LS_INFO) << "Video Adapter third scaling is now "
@@ -90,8 +90,8 @@ class VideoAdapter {
int frames_; // Number of input frames.
int adapted_frames_; // Number of frames scaled.
int adaption_changes_; // Number of changes in scale factor.
- size_t previous_width; // Previous adapter output width.
- size_t previous_height; // Previous adapter output height.
+ size_t previous_width_; // Previous adapter output width.
+ size_t previous_height_; // Previous adapter output height.
bool black_output_; // Flag to tell if we need to black output_frame_.
bool is_black_; // Flag to tell if output_frame_ is currently black.
int64 interval_next_frame_;
@@ -109,7 +109,7 @@ class CoordinatedVideoAdapter
: public VideoAdapter, public sigslot::has_slots<> {
public:
enum AdaptRequest { UPGRADE, KEEP, DOWNGRADE };
- enum {
+ enum AdaptReasonEnum {
ADAPTREASON_CPU = 1,
ADAPTREASON_BANDWIDTH = 2,
ADAPTREASON_VIEW = 4
diff --git a/chromium/third_party/libjingle/source/talk/media/base/videocapturer.cc b/chromium/third_party/libjingle/source/talk/media/base/videocapturer.cc
index acab19d6616..26fcfa9fbb4 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/videocapturer.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/videocapturer.cc
@@ -373,7 +373,7 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
// TODO(fbarchard): Avoid scale and convert if muted.
// Temporary buffer is scoped here so it will persist until i420_frame.Init()
// makes a copy of the frame, converting to I420.
- talk_base::scoped_array<uint8> temp_buffer;
+ talk_base::scoped_ptr<uint8[]> temp_buffer;
// YUY2 can be scaled vertically using an ARGB scaler. Aspect ratio is only
// a problem on OSX. OSX always converts webcams to YUY2 or UYVY.
bool can_scale =
@@ -468,21 +468,32 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
}
VIDEO_FRAME_NAME i420_frame;
- if (!i420_frame.Init(captured_frame, desired_width, desired_height)) {
+ if (!i420_frame.Alias(captured_frame, desired_width, desired_height)) {
// TODO(fbarchard): LOG more information about captured frame attributes.
LOG(LS_ERROR) << "Couldn't convert to I420! "
<< "From " << ToString(captured_frame) << " To "
<< desired_width << " x " << desired_height;
return;
}
- if (!muted_ && !ApplyProcessors(&i420_frame)) {
+
+ VideoFrame* adapted_frame = &i420_frame;
+ if (!SignalAdaptFrame.is_empty() && !IsScreencast()) {
+ VideoFrame* out_frame = NULL;
+ SignalAdaptFrame(this, adapted_frame, &out_frame);
+ if (!out_frame) {
+ return; // VideoAdapter dropped the frame.
+ }
+ adapted_frame = out_frame;
+ }
+
+ if (!muted_ && !ApplyProcessors(adapted_frame)) {
// Processor dropped the frame.
return;
}
if (muted_) {
- i420_frame.SetToBlack();
+ adapted_frame->SetToBlack();
}
- SignalVideoFrame(this, &i420_frame);
+ SignalVideoFrame(this, adapted_frame);
#endif // VIDEO_FRAME_NAME
}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/videocapturer.h b/chromium/third_party/libjingle/source/talk/media/base/videocapturer.h
index 933fc825000..2bd68bca162 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/videocapturer.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/videocapturer.h
@@ -255,6 +255,11 @@ class VideoCapturer
// Signal the captured frame to downstream.
sigslot::signal2<VideoCapturer*, const CapturedFrame*,
sigslot::multi_threaded_local> SignalFrameCaptured;
+ // If slots are connected to SignalAdaptFrame, this signals with parameters
+ // of this capturer instance, the input video frame and output frame
+ // pointer, respectively.
+ sigslot::signal3<VideoCapturer*, const VideoFrame*, VideoFrame**,
+ sigslot::multi_threaded_local> SignalAdaptFrame;
// Signal the captured frame converted to I420 to downstream.
sigslot::signal2<VideoCapturer*, const VideoFrame*,
sigslot::multi_threaded_local> SignalVideoFrame;
diff --git a/chromium/third_party/libjingle/source/talk/media/base/videocommon.cc b/chromium/third_party/libjingle/source/talk/media/base/videocommon.cc
index 5dd45d73075..b051d526a3c 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/videocommon.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/videocommon.cc
@@ -153,12 +153,15 @@ void ComputeScale(int frame_width, int frame_height, int fps,
// Compute size to crop video frame to.
// If cropped_format_* is 0, return the frame_* size as is.
-void ComputeCrop(int cropped_format_width,
- int cropped_format_height,
+void ComputeCrop(int cropped_format_width, int cropped_format_height,
int frame_width, int frame_height,
int pixel_width, int pixel_height,
int rotation,
int* cropped_width, int* cropped_height) {
+ // Transform screen crop to camera space if rotated.
+ if (rotation == 90 || rotation == 270) {
+ std::swap(cropped_format_width, cropped_format_height);
+ }
ASSERT(cropped_format_width >= 0);
ASSERT(cropped_format_height >= 0);
ASSERT(frame_width > 0);
@@ -182,39 +185,26 @@ void ComputeCrop(int cropped_format_width,
static_cast<float>(frame_height * pixel_height);
float crop_aspect = static_cast<float>(cropped_format_width) /
static_cast<float>(cropped_format_height);
- int new_frame_width = frame_width;
- int new_frame_height = frame_height;
- if (rotation == 90 || rotation == 270) {
- frame_aspect = 1.0f / frame_aspect;
- new_frame_width = frame_height;
- new_frame_height = frame_width;
- }
-
// kAspectThresh is the maximum aspect ratio difference that we'll accept
- // for cropping. The value 1.33 is based on 4:3 being cropped to 16:9.
+ // for cropping. The value 1.34 allows cropping from 4:3 to 16:9.
// Set to zero to disable cropping entirely.
// TODO(fbarchard): crop to multiple of 16 width for better performance.
- const float kAspectThresh = 16.f / 9.f / (4.f / 3.f) + 0.01f; // 1.33
+ const float kAspectThresh = 1.34f;
// Wide aspect - crop horizontally
if (frame_aspect > crop_aspect &&
frame_aspect < crop_aspect * kAspectThresh) {
// Round width down to multiple of 4 to avoid odd chroma width.
// Width a multiple of 4 allows a half size image to have chroma channel
- // that avoids rounding errors. lmi and webrtc have odd width limitations.
- new_frame_width = static_cast<int>((crop_aspect * frame_height *
+ // that avoids rounding errors.
+ frame_width = static_cast<int>((crop_aspect * frame_height *
pixel_height) / pixel_width + 0.5f) & ~3;
- } else if (crop_aspect > frame_aspect &&
- crop_aspect < frame_aspect * kAspectThresh) {
- new_frame_height = static_cast<int>((frame_width * pixel_width) /
+ } else if (frame_aspect < crop_aspect &&
+ frame_aspect > crop_aspect / kAspectThresh) {
+ frame_height = static_cast<int>((frame_width * pixel_width) /
(crop_aspect * pixel_height) + 0.5f) & ~1;
}
-
- *cropped_width = new_frame_width;
- *cropped_height = new_frame_height;
- if (rotation == 90 || rotation == 270) {
- *cropped_width = new_frame_height;
- *cropped_height = new_frame_width;
- }
+ *cropped_width = frame_width;
+ *cropped_height = frame_height;
}
// Compute the frame size that makes pixels square pixel aspect ratio.
diff --git a/chromium/third_party/libjingle/source/talk/media/base/videocommon_unittest.cc b/chromium/third_party/libjingle/source/talk/media/base/videocommon_unittest.cc
index 91228437351..455a47b79a0 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/videocommon_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/base/videocommon_unittest.cc
@@ -276,6 +276,15 @@ TEST(VideoCommonTest, TestComputeCrop) {
EXPECT_EQ(640, cropped_width);
EXPECT_EQ(480, cropped_height);
+ // Request 9:16 from VGA rotated (portrait). Expect crop.
+ ComputeCrop(360, 640, // Crop size 9:16
+ 640, 480, // Frame is 3:4 portrait
+ 1, 1, // Normal 1:1 pixels
+ 90,
+ &cropped_width, &cropped_height);
+ EXPECT_EQ(640, cropped_width);
+ EXPECT_EQ(360, cropped_height);
+
// Cropped size 0x0. Expect no cropping.
// This is used when adding multiple capturers
ComputeCrop(0, 0, // Crop size 0x0
diff --git a/chromium/third_party/libjingle/source/talk/media/base/videoengine_unittest.h b/chromium/third_party/libjingle/source/talk/media/base/videoengine_unittest.h
index d8b9bcb2955..d9266f2c4b4 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/videoengine_unittest.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/videoengine_unittest.h
@@ -54,6 +54,12 @@
EXPECT_EQ((h), (r).height()); \
EXPECT_EQ(0, (r).errors()); \
+#define EXPECT_GT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
+ EXPECT_TRUE_WAIT((r).num_rendered_frames() >= (c) && \
+ (w) == (r).width() && \
+ (h) == (r).height(), (t)); \
+ EXPECT_EQ(0, (r).errors()); \
+
static const uint32 kTimeout = 5000U;
static const uint32 kSsrc = 1234u;
static const uint32 kRtxSsrc = 4321u;
@@ -69,11 +75,13 @@ inline bool IsEqualCodec(const cricket::VideoCodec& a,
IsEqualRes(a, b.width, b.height, b.framerate);
}
+namespace std {
inline std::ostream& operator<<(std::ostream& s, const cricket::VideoCodec& c) {
s << "{" << c.name << "(" << c.id << "), "
<< c.width << "x" << c.height << "x" << c.framerate << "}";
return s;
}
+} // namespace std
inline int TimeBetweenSend(const cricket::VideoCodec& codec) {
return static_cast<int>(
@@ -788,9 +796,9 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_GT(info.senders[0].framerate_sent, 0);
ASSERT_EQ(1U, info.receivers.size());
- EXPECT_EQ(1U, info.senders[0].ssrcs.size());
- EXPECT_EQ(1U, info.receivers[0].ssrcs.size());
- EXPECT_EQ(info.senders[0].ssrcs[0], info.receivers[0].ssrcs[0]);
+ EXPECT_EQ(1U, info.senders[0].ssrcs().size());
+ EXPECT_EQ(1U, info.receivers[0].ssrcs().size());
+ EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]);
EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd);
EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd);
EXPECT_EQ(0.0, info.receivers[0].fraction_lost);
@@ -847,8 +855,8 @@ class VideoMediaChannelTest : public testing::Test,
ASSERT_EQ(2U, info.receivers.size());
for (size_t i = 0; i < info.receivers.size(); ++i) {
- EXPECT_EQ(1U, info.receivers[i].ssrcs.size());
- EXPECT_EQ(i + 1, info.receivers[i].ssrcs[0]);
+ EXPECT_EQ(1U, info.receivers[i].ssrcs().size());
+ EXPECT_EQ(i + 1, info.receivers[i].ssrcs()[0]);
EXPECT_EQ(NumRtpBytes(), info.receivers[i].bytes_rcvd);
EXPECT_EQ(NumRtpPackets(), info.receivers[i].packets_rcvd);
EXPECT_EQ(0.0, info.receivers[i].fraction_lost);
@@ -903,12 +911,12 @@ class VideoMediaChannelTest : public testing::Test,
ASSERT_EQ(2U, info.senders.size());
EXPECT_EQ(NumRtpPackets(),
info.senders[0].packets_sent + info.senders[1].packets_sent);
- EXPECT_EQ(1U, info.senders[0].ssrcs.size());
- EXPECT_EQ(1234U, info.senders[0].ssrcs[0]);
+ EXPECT_EQ(1U, info.senders[0].ssrcs().size());
+ EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]);
EXPECT_EQ(DefaultCodec().width, info.senders[0].frame_width);
EXPECT_EQ(DefaultCodec().height, info.senders[0].frame_height);
- EXPECT_EQ(1U, info.senders[1].ssrcs.size());
- EXPECT_EQ(5678U, info.senders[1].ssrcs[0]);
+ EXPECT_EQ(1U, info.senders[1].ssrcs().size());
+ EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]);
EXPECT_EQ(1024, info.senders[1].frame_width);
EXPECT_EQ(768, info.senders[1].frame_height);
// The capturer must be unregistered here as it runs out of it's scope next.
@@ -973,7 +981,7 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_TRUE(SetSend(true));
EXPECT_TRUE(channel_->SetRender(true));
EXPECT_EQ(0, renderer_.num_rendered_frames());
- channel_->OnPacketReceived(&packet1);
+ channel_->OnPacketReceived(&packet1, talk_base::PacketTime());
SetRendererAsDefault();
EXPECT_TRUE(SendFrame());
EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
@@ -1000,7 +1008,8 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_GE(2, NumRtpPackets());
uint32 ssrc = 0;
size_t last_packet = NumRtpPackets() - 1;
- talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(last_packet));
+ talk_base::scoped_ptr<const talk_base::Buffer>
+ p(GetRtpPacket(static_cast<int>(last_packet)));
ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
EXPECT_EQ(kSsrc, ssrc);
@@ -1017,7 +1026,7 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
last_packet = NumRtpPackets() - 1;
- p.reset(GetRtpPacket(last_packet));
+ p.reset(GetRtpPacket(static_cast<int>(last_packet)));
ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
EXPECT_EQ(789u, ssrc);
}
@@ -1165,7 +1174,11 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1));
EXPECT_TRUE(SendFrame());
- EXPECT_FRAME_ON_RENDERER_WAIT(
+ // Because the default channel is used, RemoveRecvStream above is not going
+ // to delete the channel. As a result the engine will continue to receive
+ // and decode the 3 frames sent above. So it is possible we will receive
+ // some (e.g. 1) of these 3 frames after the renderer is set again.
+ EXPECT_GT_FRAME_ON_RENDERER_WAIT(
renderer1, 2, DefaultCodec().width, DefaultCodec().height, kTimeout);
}
@@ -1277,16 +1290,15 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_FRAME_WAIT(1, 640, 400, kTimeout);
// Remove the capturer.
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
+ // Wait for one black frame for removing the capturer.
+ EXPECT_FRAME_WAIT(2, 640, 400, kTimeout);
+
// No capturer was added, so this RemoveCapturer should
// fail.
EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
- // Wait for frames to stop flowing.
talk_base::Thread::Current()->ProcessMessages(300);
- int num_frames = renderer_.num_rendered_frames();
- // Wait to make sure no more frames are sent
- WAIT(renderer_.num_rendered_frames() != num_frames, 300);
// Verify no more frames were sent.
- EXPECT_EQ(num_frames, renderer_.num_rendered_frames());
+ EXPECT_EQ(2, renderer_.num_rendered_frames());
}
// Tests that we can add and remove capturer as unique sources.
@@ -1373,10 +1385,8 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_EQ(0, renderer.num_rendered_frames());
EXPECT_TRUE(SendFrame());
- EXPECT_TRUE_WAIT(renderer.num_rendered_frames() >= 1 &&
- codec.width == renderer.width() &&
- codec.height == renderer.height(), kTimeout);
- EXPECT_EQ(0, renderer.errors());
+ EXPECT_GT_FRAME_ON_RENDERER_WAIT(
+ renderer, 1, codec.width, codec.height, kTimeout);
// Registering an external capturer is currently the same as screen casting
// (update the test when this changes).
@@ -1394,9 +1404,8 @@ class VideoMediaChannelTest : public testing::Test,
EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
cricket::FOURCC_ARGB));
EXPECT_TRUE(capturer->CaptureFrame());
- EXPECT_TRUE_WAIT(renderer.num_rendered_frames() >= 2 &&
- kScaledWidth == renderer.width() &&
- kScaledHeight == renderer.height(), kTimeout);
+ EXPECT_GT_FRAME_ON_RENDERER_WAIT(
+ renderer, 2, kScaledWidth, kScaledHeight, kTimeout);
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
}
diff --git a/chromium/third_party/libjingle/source/talk/media/base/videoframe_unittest.h b/chromium/third_party/libjingle/source/talk/media/base/videoframe_unittest.h
index f70e5675b01..d7be7e38875 100644
--- a/chromium/third_party/libjingle/source/talk/media/base/videoframe_unittest.h
+++ b/chromium/third_party/libjingle/source/talk/media/base/videoframe_unittest.h
@@ -157,7 +157,7 @@ class VideoFrameTest : public testing::Test {
prefix.c_str(), frame.GetWidth(), frame.GetHeight());
size_t out_size = cricket::VideoFrame::SizeOf(frame.GetWidth(),
frame.GetHeight());
- talk_base::scoped_array<uint8> out(new uint8[out_size]);
+ talk_base::scoped_ptr<uint8[]> out(new uint8[out_size]);
frame.CopyToBuffer(out.get(), out_size);
return DumpSample(filename, out.get(), out_size);
}
@@ -514,7 +514,7 @@ class VideoFrameTest : public testing::Test {
T frame1, frame2;
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
size_t buf_size = kWidth * kHeight * 2;
- talk_base::scoped_array<uint8> buf(new uint8[buf_size + kAlignment]);
+ talk_base::scoped_ptr<uint8[]> buf(new uint8[buf_size + kAlignment]);
uint8* y = ALIGNP(buf.get(), kAlignment);
uint8* u = y + kWidth * kHeight;
uint8* v = u + (kWidth / 2) * kHeight;
@@ -527,7 +527,7 @@ class VideoFrameTest : public testing::Test {
kWidth, kHeight));
EXPECT_TRUE(LoadFrame(y, buf_size, cricket::FOURCC_I422,
kWidth, kHeight, &frame2));
- EXPECT_TRUE(IsEqual(frame1, frame2, 0));
+ EXPECT_TRUE(IsEqual(frame1, frame2, 1));
}
// Test constructing an image from a YUY2 buffer.
@@ -535,7 +535,7 @@ class VideoFrameTest : public testing::Test {
T frame1, frame2;
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
size_t buf_size = kWidth * kHeight * 2;
- talk_base::scoped_array<uint8> buf(new uint8[buf_size + kAlignment]);
+ talk_base::scoped_ptr<uint8[]> buf(new uint8[buf_size + kAlignment]);
uint8* yuy2 = ALIGNP(buf.get(), kAlignment);
EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.GetYPlane(), frame1.GetYPitch(),
frame1.GetUPlane(), frame1.GetUPitch(),
@@ -552,7 +552,7 @@ class VideoFrameTest : public testing::Test {
T frame1, frame2;
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
size_t buf_size = kWidth * kHeight * 2;
- talk_base::scoped_array<uint8> buf(new uint8[buf_size + kAlignment + 1]);
+ talk_base::scoped_ptr<uint8[]> buf(new uint8[buf_size + kAlignment + 1]);
uint8* yuy2 = ALIGNP(buf.get(), kAlignment) + 1;
EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.GetYPlane(), frame1.GetYPitch(),
frame1.GetUPlane(), frame1.GetUPitch(),
@@ -718,7 +718,7 @@ class VideoFrameTest : public testing::Test {
void ConstructRGB565() {
T frame1, frame2;
size_t out_size = kWidth * kHeight * 2;
- talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
+ talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
T frame;
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
@@ -734,7 +734,7 @@ class VideoFrameTest : public testing::Test {
void ConstructARGB1555() {
T frame1, frame2;
size_t out_size = kWidth * kHeight * 2;
- talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
+ talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
T frame;
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
@@ -750,7 +750,7 @@ class VideoFrameTest : public testing::Test {
void ConstructARGB4444() {
T frame1, frame2;
size_t out_size = kWidth * kHeight * 2;
- talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
+ talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
T frame;
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
@@ -769,7 +769,7 @@ class VideoFrameTest : public testing::Test {
#define TEST_BYR(NAME, BAYER) \
void NAME() { \
size_t bayer_size = kWidth * kHeight; \
- talk_base::scoped_array<uint8> bayerbuf(new uint8[ \
+ talk_base::scoped_ptr<uint8[]> bayerbuf(new uint8[ \
bayer_size + kAlignment]); \
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment); \
T frame1, frame2; \
@@ -994,7 +994,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
}
// Convert back to ARGB.
size_t out_size = 4;
- talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
+ talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB,
@@ -1031,7 +1031,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
}
// Convert back to ARGB
size_t out_size = 10 * 4;
- talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment]);
+ talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment]);
uint8 *out = ALIGNP(outbuf.get(), kAlignment);
EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB,
@@ -1154,6 +1154,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
int size_adjust, bool expected_result) {
T frame;
talk_base::scoped_ptr<talk_base::MemoryStream> ms(LoadSample(name));
+ ASSERT_TRUE(ms.get() != NULL);
const uint8* sample = reinterpret_cast<const uint8*>(ms.get()->GetBuffer());
size_t sample_size;
ms->GetSize(&sample_size);
@@ -1162,7 +1163,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
// Allocate a buffer with end page aligned.
const int kPadToHeapSized = 16 * 1024 * 1024;
- talk_base::scoped_array<uint8> page_buffer(
+ talk_base::scoped_ptr<uint8[]> page_buffer(
new uint8[((data_size + kPadToHeapSized + 4095) & ~4095)]);
uint8* data_ptr = page_buffer.get();
if (!data_ptr) {
@@ -1393,6 +1394,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
T frame1, frame2;
talk_base::scoped_ptr<talk_base::MemoryStream> ms(
LoadSample(kImageFilename));
+ ASSERT_TRUE(ms.get() != NULL);
size_t data_size;
ms->GetSize(&data_size);
EXPECT_TRUE(frame1.InitToBlack(kWidth, kHeight, 1, 1, 0, 0));
@@ -1427,7 +1429,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
int astride = kWidth * bpp + rowpad;
size_t out_size = astride * kHeight;
- talk_base::scoped_array<uint8> outbuf(new uint8[out_size + kAlignment + 1]);
+ talk_base::scoped_ptr<uint8[]> outbuf(new uint8[out_size + kAlignment + 1]);
memset(outbuf.get(), 0, out_size + kAlignment + 1);
uint8 *outtop = ALIGNP(outbuf.get(), kAlignment);
uint8 *out = outtop;
@@ -1841,7 +1843,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
void ConvertToI422Buffer() {
T frame1, frame2;
size_t out_size = kWidth * kHeight * 2;
- talk_base::scoped_array<uint8> buf(new uint8[out_size + kAlignment]);
+ talk_base::scoped_ptr<uint8[]> buf(new uint8[out_size + kAlignment]);
uint8* y = ALIGNP(buf.get(), kAlignment);
uint8* u = y + kWidth * kHeight;
uint8* v = u + (kWidth / 2) * kHeight;
@@ -1859,13 +1861,13 @@ void Construct##FOURCC##Rotate##ROTATE() { \
kWidth, kHeight, kWidth, kHeight,
y,
out_size, 1, 1, 0, 0, cricket::ROTATION_0));
- EXPECT_TRUE(IsEqual(frame1, frame2, 0));
+ EXPECT_TRUE(IsEqual(frame1, frame2, 1));
}
#define TEST_TOBYR(NAME, BAYER) \
void NAME() { \
size_t bayer_size = kWidth * kHeight; \
- talk_base::scoped_array<uint8> bayerbuf(new uint8[ \
+ talk_base::scoped_ptr<uint8[]> bayerbuf(new uint8[ \
bayer_size + kAlignment]); \
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment); \
T frame; \
@@ -1894,7 +1896,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
} \
void NAME##Unaligned() { \
size_t bayer_size = kWidth * kHeight; \
- talk_base::scoped_array<uint8> bayerbuf(new uint8[ \
+ talk_base::scoped_ptr<uint8[]> bayerbuf(new uint8[ \
bayer_size + 1 + kAlignment]); \
uint8 *bayer = ALIGNP(bayerbuf.get(), kAlignment) + 1; \
T frame; \
@@ -1931,7 +1933,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
#define TEST_BYRTORGB(NAME, BAYER) \
void NAME() { \
size_t bayer_size = kWidth * kHeight; \
- talk_base::scoped_array<uint8> bayerbuf(new uint8[ \
+ talk_base::scoped_ptr<uint8[]> bayerbuf(new uint8[ \
bayer_size + kAlignment]); \
uint8 *bayer1 = ALIGNP(bayerbuf.get(), kAlignment); \
for (int i = 0; i < kWidth * kHeight; ++i) { \
@@ -1947,7 +1949,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
kWidth * 4, \
kWidth, kHeight); \
} \
- talk_base::scoped_array<uint8> bayer2buf(new uint8[ \
+ talk_base::scoped_ptr<uint8[]> bayer2buf(new uint8[ \
bayer_size + kAlignment]); \
uint8 *bayer2 = ALIGNP(bayer2buf.get(), kAlignment); \
libyuv::ARGBToBayer##BAYER(reinterpret_cast<uint8*>(ms->GetBuffer()), \
@@ -2007,10 +2009,11 @@ void Construct##FOURCC##Rotate##ROTATE() { \
T frame;
talk_base::scoped_ptr<talk_base::MemoryStream> ms(
LoadSample(kImageFilename));
+ ASSERT_TRUE(ms.get() != NULL);
ASSERT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_I420, kWidth, kHeight,
&frame));
size_t out_size = kWidth * kHeight * 3 / 2;
- talk_base::scoped_array<uint8> out(new uint8[out_size]);
+ talk_base::scoped_ptr<uint8[]> out(new uint8[out_size]);
for (int i = 0; i < repeat_; ++i) {
EXPECT_EQ(out_size, frame.CopyToBuffer(out.get(), out_size));
}
@@ -2021,6 +2024,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
T source;
talk_base::scoped_ptr<talk_base::MemoryStream> ms(
LoadSample(kImageFilename));
+ ASSERT_TRUE(ms.get() != NULL);
ASSERT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_I420, kWidth, kHeight,
&source));
@@ -2039,6 +2043,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
T frame;
talk_base::scoped_ptr<talk_base::MemoryStream> ms(
LoadSample(kImageFilename));
+ ASSERT_TRUE(ms.get() != NULL);
talk_base::MemoryStream ms2;
size_t size;
ASSERT_TRUE(ms->GetSize(&size));
@@ -2056,7 +2061,7 @@ void Construct##FOURCC##Rotate##ROTATE() { \
void CopyToBuffer1Pixel() {
size_t out_size = 3;
- talk_base::scoped_array<uint8> out(new uint8[out_size + 1]);
+ talk_base::scoped_ptr<uint8[]> out(new uint8[out_size + 1]);
memset(out.get(), 0xfb, out_size + 1); // Fill buffer
uint8 pixel[3] = { 1, 2, 3 };
T frame;
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/carbonvideorenderer.h b/chromium/third_party/libjingle/source/talk/media/devices/carbonvideorenderer.h
index e09118613ba..6c52fcfc69c 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/carbonvideorenderer.h
+++ b/chromium/third_party/libjingle/source/talk/media/devices/carbonvideorenderer.h
@@ -57,7 +57,7 @@ class CarbonVideoRenderer : public VideoRenderer {
static OSStatus DrawEventHandler(EventHandlerCallRef handler,
EventRef event,
void* data);
- talk_base::scoped_array<uint8> image_;
+ talk_base::scoped_ptr<uint8[]> image_;
talk_base::CriticalSection image_crit_;
int image_width_;
int image_height_;
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/devicemanager.cc b/chromium/third_party/libjingle/source/talk/media/devices/devicemanager.cc
index 6f4aa33ffca..150b55855d9 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/devicemanager.cc
+++ b/chromium/third_party/libjingle/source/talk/media/devices/devicemanager.cc
@@ -278,18 +278,14 @@ VideoCapturer* DeviceManager::CreateDesktopCapturer(
bool DeviceManager::GetAudioDevices(bool input,
std::vector<Device>* devs) {
devs->clear();
-#if defined(IOS) || defined(ANDROID)
- // Under Android, we don't access the device file directly.
- // Arbitrary use 0 for the mic and 1 for the output.
- // These ids are used in MediaEngine::SetSoundDevices(in, out);
- // The strings are for human consumption.
- if (input) {
- devs->push_back(Device("audiorecord", 0));
- } else {
- devs->push_back(Device("audiotrack", 1));
- }
+#if defined(ANDROID)
+ // Under Android, 0 is always required for the playout device and 0 is the
+ // default for the recording device.
+ devs->push_back(Device("default-device", 0));
return true;
#else
+ // Other platforms either have their own derived class implementation
+ // (desktop) or don't use device manager for audio devices (iOS).
return false;
#endif
}
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer.cc b/chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer.cc
index 174781624b1..f5c078d3fa4 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer.cc
+++ b/chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer.cc
@@ -28,6 +28,7 @@
#include "talk/media/devices/filevideocapturer.h"
#include "talk/base/bytebuffer.h"
+#include "talk/base/criticalsection.h"
#include "talk/base/logging.h"
#include "talk/base/thread.h"
@@ -108,6 +109,10 @@ class FileVideoCapturer::FileReadThread
finished_(false) {
}
+ virtual ~FileReadThread() {
+ Stop();
+ }
+
// Override virtual method of parent Thread. Context: Worker Thread.
virtual void Run() {
// Read the first frame and start the message pump. The pump runs until
@@ -117,6 +122,8 @@ class FileVideoCapturer::FileReadThread
PostDelayed(waiting_time_ms, this);
Thread::Run();
}
+
+ talk_base::CritScope cs(&crit_);
finished_ = true;
}
@@ -131,10 +138,14 @@ class FileVideoCapturer::FileReadThread
}
// Check if Run() is finished.
- bool Finished() const { return finished_; }
+ bool Finished() const {
+ talk_base::CritScope cs(&crit_);
+ return finished_;
+ }
private:
FileVideoCapturer* capturer_;
+ mutable talk_base::CriticalSection crit_;
bool finished_;
DISALLOW_COPY_AND_ASSIGN(FileReadThread);
@@ -224,9 +235,9 @@ CaptureState FileVideoCapturer::Start(const VideoFormat& capture_format) {
SetCaptureFormat(&capture_format);
// Create a thread to read the file.
file_read_thread_ = new FileReadThread(this);
- bool ret = file_read_thread_->Start();
start_time_ns_ = kNumNanoSecsPerMilliSec *
static_cast<int64>(talk_base::Time());
+ bool ret = file_read_thread_->Start();
if (ret) {
LOG(LS_INFO) << "File video capturer '" << GetId() << "' started";
return CS_RUNNING;
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer_unittest.cc b/chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer_unittest.cc
index 489f98d451a..610d4f120aa 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/devices/filevideocapturer_unittest.cc
@@ -174,7 +174,8 @@ TEST_F(FileVideoCapturerTest, TestRepeatForever) {
EXPECT_EQ(listener.frame_height(), capture_format_.height);
}
-TEST_F(FileVideoCapturerTest, TestPartialFrameHeader) {
+// See: https://code.google.com/p/webrtc/issues/detail?id=2409
+TEST_F(FileVideoCapturerTest, DISABLED_TestPartialFrameHeader) {
EXPECT_TRUE(OpenFile("1.frame_plus_1.byte"));
VideoCapturerListener listener;
capturer_->SignalFrameCaptured.connect(
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/gdivideorenderer.cc b/chromium/third_party/libjingle/source/talk/media/devices/gdivideorenderer.cc
index d5edfc6e43c..9633eb6d8e8 100755
--- a/chromium/third_party/libjingle/source/talk/media/devices/gdivideorenderer.cc
+++ b/chromium/third_party/libjingle/source/talk/media/devices/gdivideorenderer.cc
@@ -69,6 +69,10 @@ class GdiVideoRenderer::VideoWindow : public talk_base::Win32Window {
public:
explicit WindowThread(VideoWindow* window) : window_(window) {}
+ virtual ~WindowThread() {
+ Stop();
+ }
+
// Override virtual method of talk_base::Thread. Context: worker Thread.
virtual void Run() {
// Initialize the window
@@ -94,7 +98,7 @@ class GdiVideoRenderer::VideoWindow : public talk_base::Win32Window {
void OnRenderFrame(const VideoFrame* frame);
BITMAPINFO bmi_;
- talk_base::scoped_array<uint8> image_;
+ talk_base::scoped_ptr<uint8[]> image_;
talk_base::scoped_ptr<WindowThread> window_thread_;
// The initial position of the window.
int initial_x_;
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/gtkvideorenderer.h b/chromium/third_party/libjingle/source/talk/media/devices/gtkvideorenderer.h
index 6276b51c806..744c19f4908 100755
--- a/chromium/third_party/libjingle/source/talk/media/devices/gtkvideorenderer.h
+++ b/chromium/third_party/libjingle/source/talk/media/devices/gtkvideorenderer.h
@@ -56,7 +56,7 @@ class GtkVideoRenderer : public VideoRenderer {
// Check if the window has been closed.
bool IsClosed() const;
- talk_base::scoped_array<uint8> image_;
+ talk_base::scoped_ptr<uint8[]> image_;
GtkWidget* window_;
GtkWidget* draw_area_;
// The initial position of the window.
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.cc b/chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.cc
index b1d9d31e645..20154e1fcad 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.cc
+++ b/chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.cc
@@ -27,6 +27,10 @@
#include "talk/media/devices/libudevsymboltable.h"
+#include <dlfcn.h>
+
+#include "talk/base/logging.h"
+
namespace cricket {
#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBUDEV_SYMBOLS_CLASS_NAME
@@ -37,4 +41,32 @@ namespace cricket {
#undef LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST
#undef LATE_BINDING_SYMBOL_TABLE_DLL_NAME
+bool IsWrongLibUDevAbiVersion(talk_base::DllHandle libudev_0) {
+ talk_base::DllHandle libudev_1 = dlopen("libudev.so.1",
+ RTLD_NOW|RTLD_LOCAL|RTLD_NOLOAD);
+ bool unsafe_symlink = (libudev_0 == libudev_1);
+ if (unsafe_symlink) {
+ // .0 and .1 are distinct ABIs, so if they point to the same thing then one
+ // of them must be wrong. Probably the old has been symlinked to the new in
+ // a misguided attempt at backwards compatibility.
+ LOG(LS_ERROR) << "libudev.so.0 and libudev.so.1 unsafely point to the"
+ " same thing; not using libudev";
+ } else if (libudev_1) {
+ // If libudev.so.1 is resident but distinct from libudev.so.0, then some
+ // system library loaded the new ABI separately. This is not a problem for
+ // LateBindingSymbolTable because its symbol look-ups are restricted to its
+ // DllHandle, but having libudev.so.0 resident may cause problems for that
+ // system library because symbol names are not namespaced by DLL. (Although
+ // our use of RTLD_LOCAL should avoid most problems.)
+ LOG(LS_WARNING)
+ << "libudev.so.1 is resident but distinct from libudev.so.0";
+ }
+ if (libudev_1) {
+ // Release the refcount that we acquired above. (Does not unload the DLL;
+ // whoever loaded it still needs it.)
+ dlclose(libudev_1);
+ }
+ return unsafe_symlink;
+}
+
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.h b/chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.h
index 046a4b0e88b..aa8c590351e 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.h
+++ b/chromium/third_party/libjingle/source/talk/media/devices/libudevsymboltable.h
@@ -66,6 +66,14 @@ namespace cricket {
#undef LATE_BINDING_SYMBOL_TABLE_CLASS_NAME
#undef LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST
+// libudev has changed ABIs to libudev.so.1 in recent distros and lots of users
+// and/or software (including Google Chrome) are symlinking the old to the new.
+// The entire point of ABI versions is that you can't safely do that, and
+// it has caused crashes in the wild. This function checks if the DllHandle that
+// we got back for libudev.so.0 is actually for libudev.so.1. If so, the library
+// cannot safely be used.
+bool IsWrongLibUDevAbiVersion(talk_base::DllHandle libudev_0);
+
} // namespace cricket
#endif // TALK_MEDIA_DEVICES_LIBUDEVSYMBOLTABLE_H_
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/linuxdeviceinfo.cc b/chromium/third_party/libjingle/source/talk/media/devices/linuxdeviceinfo.cc
index 7b5200112c6..b1bc9ddb1f1 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/linuxdeviceinfo.cc
+++ b/chromium/third_party/libjingle/source/talk/media/devices/linuxdeviceinfo.cc
@@ -52,7 +52,8 @@ class ScopedLibUdev {
ScopedLibUdev() {}
bool Init() {
- return libudev_.Load();
+ return libudev_.Load() &&
+ !IsWrongLibUDevAbiVersion(libudev_.GetDllHandle());
}
LibUDevSymbolTable libudev_;
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/linuxdevicemanager.cc b/chromium/third_party/libjingle/source/talk/media/devices/linuxdevicemanager.cc
index 2096eeb274a..e3e55ff7959 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/linuxdevicemanager.cc
+++ b/chromium/third_party/libjingle/source/talk/media/devices/linuxdevicemanager.cc
@@ -306,8 +306,9 @@ bool LinuxDeviceWatcher::Start() {
// We deliberately return true in the failure paths here because libudev is
// not a critical component of a Linux system so it may not be present/usable,
// and we don't want to halt LinuxDeviceManager initialization in such a case.
- if (!libudev_.Load()) {
- LOG(LS_WARNING) << "libudev not present/usable; LinuxDeviceWatcher disabled";
+ if (!libudev_.Load() || IsWrongLibUDevAbiVersion(libudev_.GetDllHandle())) {
+ LOG(LS_WARNING)
+ << "libudev not present/usable; LinuxDeviceWatcher disabled";
return true;
}
udev_ = libudev_.udev_new()();
diff --git a/chromium/third_party/libjingle/source/talk/media/devices/macdevicemanager.cc b/chromium/third_party/libjingle/source/talk/media/devices/macdevicemanager.cc
index 10d85a0f737..e92408e416c 100644
--- a/chromium/third_party/libjingle/source/talk/media/devices/macdevicemanager.cc
+++ b/chromium/third_party/libjingle/source/talk/media/devices/macdevicemanager.cc
@@ -120,7 +120,7 @@ static bool GetAudioDeviceIDs(bool input,
}
size_t num_devices = propsize / sizeof(AudioDeviceID);
- talk_base::scoped_array<AudioDeviceID> device_ids(
+ talk_base::scoped_ptr<AudioDeviceID[]> device_ids(
new AudioDeviceID[num_devices]);
err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
diff --git a/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.cc b/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.cc
index 3d450c6863b..653273bd2e3 100644
--- a/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.cc
+++ b/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.cc
@@ -31,12 +31,14 @@
#include <stdio.h>
#include <vector>
+#include "talk/app/webrtc/datachannelinterface.h"
#include "talk/base/buffer.h"
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/media/base/codec.h"
#include "talk/media/base/constants.h"
#include "talk/media/base/streamparams.h"
+#include "talk/media/sctp/sctputils.h"
#include "usrsctplib/usrsctp.h"
namespace cricket {
@@ -242,8 +244,8 @@ DataMediaChannel* SctpDataEngine::CreateChannel(
SctpDataMediaChannel::SctpDataMediaChannel(talk_base::Thread* thread)
: worker_thread_(thread),
- local_port_(kSctpDefaultPort),
- remote_port_(kSctpDefaultPort),
+ local_port_(-1),
+ remote_port_(-1),
sock_(NULL),
sending_(false),
receiving_(false),
@@ -344,6 +346,12 @@ void SctpDataMediaChannel::CloseSctpSocket() {
bool SctpDataMediaChannel::Connect() {
LOG(LS_VERBOSE) << debug_name_ << "->Connect().";
+ if (remote_port_ < 0) {
+ remote_port_ = kSctpDefaultPort;
+ }
+ if (local_port_ < 0) {
+ local_port_ = kSctpDefaultPort;
+ }
// If we already have a socket connection, just return.
if (sock_) {
@@ -534,7 +542,8 @@ bool SctpDataMediaChannel::SendData(
}
// Called by network interface when a packet has been received.
-void SctpDataMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
+void SctpDataMediaChannel::OnPacketReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): " << " length="
<< packet->length() << ", sending: " << sending_;
// Only give receiving packets to usrsctp after if connected. This enables two
@@ -578,7 +587,23 @@ void SctpDataMediaChannel::OnDataFromSctpToChannel(
StreamParams found_stream;
if (!GetStreamBySsrc(streams_, params.ssrc, &found_stream)) {
if (params.type == DMT_CONTROL) {
- SignalDataReceived(params, buffer->data(), buffer->length());
+ std::string label;
+ webrtc::DataChannelInit config;
+ if (ParseDataChannelOpenMessage(*buffer, &label, &config)) {
+ config.id = params.ssrc;
+ // Do not send the OPEN message for this data channel.
+ config.negotiated = true;
+ SignalNewStreamReceived(label, config);
+
+ // Add the stream immediately.
+ cricket::StreamParams sparams =
+ cricket::StreamParams::CreateLegacy(params.ssrc);
+ AddSendStream(sparams);
+ AddRecvStream(sparams);
+ } else {
+ LOG(LS_ERROR) << debug_name_ << "->OnDataFromSctpToChannel(...): "
+ << "Received malformed control message";
+ }
} else {
LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): "
<< "Received packet for unknown ssrc: " << params.ssrc;
@@ -677,6 +702,38 @@ void SctpDataMediaChannel::OnNotificationAssocChange(
}
}
+// Puts the specified |param| from the codec identified by |id| into |dest|
+// and returns true. Or returns false if it wasn't there, leaving |dest|
+// untouched.
+static bool GetCodecIntParameter(const std::vector<DataCodec>& codecs,
+ int id, const std::string& name,
+ const std::string& param, int* dest) {
+ std::string value;
+ Codec match_pattern;
+ match_pattern.id = id;
+ match_pattern.name = name;
+ for (size_t i = 0; i < codecs.size(); ++i) {
+ if (codecs[i].Matches(match_pattern)) {
+ if (codecs[i].GetParam(param, &value)) {
+ *dest = talk_base::FromString<int>(value);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool SctpDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) {
+ return GetCodecIntParameter(
+ codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort,
+ &remote_port_);
+}
+
+bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) {
+ return GetCodecIntParameter(
+ codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort,
+ &local_port_);
+}
void SctpDataMediaChannel::OnPacketFromSctpToNetwork(
talk_base::Buffer* buffer) {
diff --git a/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.h b/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.h
index 429016e0e6a..4d05cf36e02 100644
--- a/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine.h
@@ -56,7 +56,7 @@ struct socket;
namespace cricket {
// The highest stream ID (Sid) that SCTP allows, and the number of streams we
// tell SCTP we're going to use.
-const uint32 kMaxSctpSid = USHRT_MAX;
+const uint32 kMaxSctpSid = 1023;
// A DataEngine that interacts with usrsctp.
//
@@ -149,7 +149,8 @@ class SctpDataMediaChannel : public DataMediaChannel,
const talk_base::Buffer& payload,
SendDataResult* result = NULL);
// A packet is received from the network interface. Posted to OnMessage.
- virtual void OnPacketReceived(talk_base::Buffer* packet);
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
// Exposed to allow Post call from c-callbacks.
talk_base::Thread* worker_thread() const { return worker_thread_; }
@@ -168,13 +169,10 @@ class SctpDataMediaChannel : public DataMediaChannel,
const std::vector<RtpHeaderExtension>& extensions) { return true; }
virtual bool SetSendRtpHeaderExtensions(
const std::vector<RtpHeaderExtension>& extensions) { return true; }
- virtual bool SetSendCodecs(const std::vector<DataCodec>& codecs) {
- return true;
- }
- virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs) {
- return true;
- }
- virtual void OnRtcpReceived(talk_base::Buffer* packet) {}
+ virtual bool SetSendCodecs(const std::vector<DataCodec>& codecs);
+ virtual bool SetRecvCodecs(const std::vector<DataCodec>& codecs);
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) {}
virtual void OnReadyToSend(bool ready) {}
// Helper for debugging.
@@ -211,7 +209,8 @@ class SctpDataMediaChannel : public DataMediaChannel,
talk_base::Thread* worker_thread_;
// The local and remote SCTP port to use. These are passed along the wire
// and the listener and connector must be using the same port. It is not
- // related to the ports at the IP level.
+ // related to the ports at the IP level. If set to -1, we default to
+ // kSctpDefaultPort.
int local_port_;
int remote_port_;
struct socket* sock_; // The socket created by usrsctp_socket(...).
diff --git a/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine_unittest.cc b/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine_unittest.cc
index 363e7dfeb64..b4ad6ce33e2 100644
--- a/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/sctp/sctpdataengine_unittest.cc
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <string>
+#include "talk/app/webrtc/datachannelinterface.h"
#include "talk/base/buffer.h"
#include "talk/base/criticalsection.h"
#include "talk/base/gunit.h"
@@ -41,6 +42,7 @@
#include "talk/media/base/constants.h"
#include "talk/media/base/mediachannel.h"
#include "talk/media/sctp/sctpdataengine.h"
+#include "talk/media/sctp/sctputils.h"
enum {
MSG_PACKET = 1,
@@ -82,7 +84,7 @@ class SctpFakeNetworkInterface : public cricket::MediaChannel::NetworkInterface,
static_cast<talk_base::TypedMessageData<talk_base::Buffer*>*>(
msg->pdata)->data();
if (dest_) {
- dest_->OnPacketReceived(buffer);
+ dest_->OnPacketReceived(buffer, talk_base::PacketTime());
}
delete buffer;
}
@@ -161,7 +163,8 @@ class SignalReadyToSendObserver : public sigslot::has_slots<> {
};
// SCTP Data Engine testing framework.
-class SctpDataMediaChannelTest : public testing::Test {
+class SctpDataMediaChannelTest : public testing::Test,
+ public sigslot::has_slots<> {
protected:
virtual void SetUp() {
engine_.reset(new cricket::SctpDataEngine());
@@ -212,6 +215,8 @@ class SctpDataMediaChannelTest : public testing::Test {
// When data is received, pass it to the SctpFakeDataReceiver.
channel->SignalDataReceived.connect(
recv, &SctpFakeDataReceiver::OnDataReceived);
+ channel->SignalNewStreamReceived.connect(
+ this, &SctpDataMediaChannelTest::OnNewStreamReceived);
return channel;
}
@@ -246,6 +251,14 @@ class SctpDataMediaChannelTest : public testing::Test {
SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
+ void OnNewStreamReceived(const std::string& label,
+ const webrtc::DataChannelInit& init) {
+ last_label_ = label;
+ last_dc_init_ = init;
+ }
+ std::string last_label() { return last_label_; }
+ webrtc::DataChannelInit last_dc_init() { return last_dc_init_; }
+
private:
talk_base::scoped_ptr<cricket::SctpDataEngine> engine_;
talk_base::scoped_ptr<SctpFakeNetworkInterface> net1_;
@@ -254,6 +267,8 @@ class SctpDataMediaChannelTest : public testing::Test {
talk_base::scoped_ptr<SctpFakeDataReceiver> recv2_;
talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan1_;
talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan2_;
+ std::string last_label_;
+ webrtc::DataChannelInit last_dc_init_;
};
// Verifies that SignalReadyToSend is fired.
@@ -316,3 +331,30 @@ TEST_F(SctpDataMediaChannelTest, SendData) {
channel2()->SetSend(false);
LOG(LS_VERBOSE) << "Cleaning up. -----------------------------";
}
+
+TEST_F(SctpDataMediaChannelTest, SendReceiveOpenMessage) {
+ SetupConnectedChannels();
+
+ std::string label("x");
+ webrtc::DataChannelInit config;
+ config.id = 10;
+
+ // Send the OPEN message on a unknown ssrc.
+ channel1()->AddSendStream(cricket::StreamParams::CreateLegacy(config.id));
+ cricket::SendDataParams params;
+ params.ssrc = config.id;
+ params.type = cricket::DMT_CONTROL;
+ cricket::SendDataResult result;
+ talk_base::Buffer buffer;
+ ASSERT_TRUE(cricket::WriteDataChannelOpenMessage(label, config, &buffer));
+ ASSERT_TRUE(channel1()->SendData(params, buffer, &result));
+ // Send data on the new ssrc immediately after sending the OPEN message.
+ ASSERT_TRUE(SendData(channel1(), config.id, "hi chan2", &result));
+
+ // Verifies the received OPEN message.
+ EXPECT_TRUE_WAIT(last_label() == label, 1000);
+ EXPECT_EQ(config.id, last_dc_init().id);
+ EXPECT_EQ(true, last_dc_init().negotiated);
+ // Verifies the received data.
+ EXPECT_TRUE_WAIT(ReceivedData(receiver2(), config.id, "hi chan2"), 1000);
+}
diff --git a/chromium/third_party/libjingle/source/talk/media/sctp/sctputils.cc b/chromium/third_party/libjingle/source/talk/media/sctp/sctputils.cc
new file mode 100644
index 00000000000..4073905de7e
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/media/sctp/sctputils.cc
@@ -0,0 +1,176 @@
+/*
+ * libjingle
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/media/sctp/sctputils.h"
+
+#include "talk/app/webrtc/datachannelinterface.h"
+#include "talk/base/buffer.h"
+#include "talk/base/bytebuffer.h"
+#include "talk/base/logging.h"
+
+namespace cricket {
+
+// Format defined at
+// http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1
+
+static const uint8 DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03;
+
+enum DataChannelOpenMessageChannelType {
+ DCOMCT_ORDERED_RELIABLE = 0x00,
+ DCOMCT_ORDERED_PARTIAL_RTXS = 0x01,
+ DCOMCT_ORDERED_PARTIAL_TIME = 0x02,
+ DCOMCT_UNORDERED_RELIABLE = 0x80,
+ DCOMCT_UNORDERED_PARTIAL_RTXS = 0x81,
+ DCOMCT_UNORDERED_PARTIAL_TIME = 0x82,
+};
+
+bool ParseDataChannelOpenMessage(
+ const talk_base::Buffer& payload,
+ std::string* label,
+ webrtc::DataChannelInit* config) {
+ // Format defined at
+ // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
+
+ talk_base::ByteBuffer buffer(payload.data(), payload.length());
+
+ uint8 message_type;
+ if (!buffer.ReadUInt8(&message_type)) {
+ LOG(LS_WARNING) << "Could not read OPEN message type.";
+ return false;
+ }
+ if (message_type != DATA_CHANNEL_OPEN_MESSAGE_TYPE) {
+ LOG(LS_WARNING) << "Data Channel OPEN message of unexpected type: "
+ << message_type;
+ return false;
+ }
+
+ uint8 channel_type;
+ if (!buffer.ReadUInt8(&channel_type)) {
+ LOG(LS_WARNING) << "Could not read OPEN message channel type.";
+ return false;
+ }
+
+ uint16 priority;
+ if (!buffer.ReadUInt16(&priority)) {
+ LOG(LS_WARNING) << "Could not read OPEN message reliabilility prioirty.";
+ return false;
+ }
+ uint32 reliability_param;
+ if (!buffer.ReadUInt32(&reliability_param)) {
+ LOG(LS_WARNING) << "Could not read OPEN message reliabilility param.";
+ return false;
+ }
+ uint16 label_length;
+ if (!buffer.ReadUInt16(&label_length)) {
+ LOG(LS_WARNING) << "Could not read OPEN message label length.";
+ return false;
+ }
+ uint16 protocol_length;
+ if (!buffer.ReadUInt16(&protocol_length)) {
+ LOG(LS_WARNING) << "Could not read OPEN message protocol length.";
+ return false;
+ }
+ if (!buffer.ReadString(label, (size_t) label_length)) {
+ LOG(LS_WARNING) << "Could not read OPEN message label";
+ return false;
+ }
+ if (!buffer.ReadString(&config->protocol, protocol_length)) {
+ LOG(LS_WARNING) << "Could not read OPEN message protocol.";
+ return false;
+ }
+
+ config->ordered = true;
+ switch (channel_type) {
+ case DCOMCT_UNORDERED_RELIABLE:
+ case DCOMCT_UNORDERED_PARTIAL_RTXS:
+ case DCOMCT_UNORDERED_PARTIAL_TIME:
+ config->ordered = false;
+ }
+
+ config->maxRetransmits = -1;
+ config->maxRetransmitTime = -1;
+ switch (channel_type) {
+ case DCOMCT_ORDERED_PARTIAL_RTXS:
+ case DCOMCT_UNORDERED_PARTIAL_RTXS:
+ config->maxRetransmits = reliability_param;
+ break;
+ case DCOMCT_ORDERED_PARTIAL_TIME:
+ case DCOMCT_UNORDERED_PARTIAL_TIME:
+ config->maxRetransmitTime = reliability_param;
+ break;
+ }
+
+ return true;
+}
+
+bool WriteDataChannelOpenMessage(
+ const std::string& label,
+ const webrtc::DataChannelInit& config,
+ talk_base::Buffer* payload) {
+ // Format defined at
+ // http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1
+ uint8 channel_type = 0;
+ uint32 reliability_param = 0;
+ uint16 priority = 0;
+ if (config.ordered) {
+ if (config.maxRetransmits > -1) {
+ channel_type = DCOMCT_ORDERED_PARTIAL_RTXS;
+ reliability_param = config.maxRetransmits;
+ } else if (config.maxRetransmitTime > -1) {
+ channel_type = DCOMCT_ORDERED_PARTIAL_TIME;
+ reliability_param = config.maxRetransmitTime;
+ } else {
+ channel_type = DCOMCT_ORDERED_RELIABLE;
+ }
+ } else {
+ if (config.maxRetransmits > -1) {
+ channel_type = DCOMCT_UNORDERED_PARTIAL_RTXS;
+ reliability_param = config.maxRetransmits;
+ } else if (config.maxRetransmitTime > -1) {
+ channel_type = DCOMCT_UNORDERED_PARTIAL_TIME;
+ reliability_param = config.maxRetransmitTime;
+ } else {
+ channel_type = DCOMCT_UNORDERED_RELIABLE;
+ }
+ }
+
+ talk_base::ByteBuffer buffer(
+ NULL, 20 + label.length() + config.protocol.length(),
+ talk_base::ByteBuffer::ORDER_NETWORK);
+ buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE);
+ buffer.WriteUInt8(channel_type);
+ buffer.WriteUInt16(priority);
+ buffer.WriteUInt32(reliability_param);
+ buffer.WriteUInt16(static_cast<uint16>(label.length()));
+ buffer.WriteUInt16(static_cast<uint16>(config.protocol.length()));
+ buffer.WriteString(label);
+ buffer.WriteString(config.protocol);
+ payload->SetData(buffer.Data(), buffer.Length());
+ return true;
+}
+
+} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/media/sctp/sctputils.h b/chromium/third_party/libjingle/source/talk/media/sctp/sctputils.h
new file mode 100644
index 00000000000..d349274a9a6
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/media/sctp/sctputils.h
@@ -0,0 +1,53 @@
+/*
+ * libjingle
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TALK_MEDIA_BASE_SCTPUTILS_H_
+#define TALK_MEDIA_BASE_SCTPUTILS_H_
+
+#include <string>
+
+namespace talk_base {
+class Buffer;
+} // namespace talk_base
+
+namespace webrtc {
+struct DataChannelInit;
+} // namespace webrtc
+
+namespace cricket {
+
+bool ParseDataChannelOpenMessage(const talk_base::Buffer& payload,
+ std::string* label,
+ webrtc::DataChannelInit* config);
+
+bool WriteDataChannelOpenMessage(const std::string& label,
+ const webrtc::DataChannelInit& config,
+ talk_base::Buffer* payload);
+
+} // namespace cricket
+
+#endif // TALK_MEDIA_BASE_SCTPUTILS_H_
diff --git a/chromium/third_party/libjingle/source/talk/media/sctp/sctputils_unittest.cc b/chromium/third_party/libjingle/source/talk/media/sctp/sctputils_unittest.cc
new file mode 100644
index 00000000000..70f67b8b581
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/media/sctp/sctputils_unittest.cc
@@ -0,0 +1,153 @@
+/*
+ * libjingle
+ * Copyright 2013 Google Inc
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/app/webrtc/datachannelinterface.h"
+#include "talk/base/bytebuffer.h"
+#include "talk/base/gunit.h"
+#include "talk/media/sctp/sctputils.h"
+
+class SctpUtilsTest : public testing::Test {
+ public:
+ void VerifyOpenMessageFormat(const talk_base::Buffer& packet,
+ const std::string& label,
+ const webrtc::DataChannelInit& config) {
+ uint8 message_type;
+ uint8 channel_type;
+ uint32 reliability;
+ uint16 priority;
+ uint16 label_length;
+ uint16 protocol_length;
+
+ talk_base::ByteBuffer buffer(packet.data(), packet.length());
+ ASSERT_TRUE(buffer.ReadUInt8(&message_type));
+ EXPECT_EQ(0x03, message_type);
+
+ ASSERT_TRUE(buffer.ReadUInt8(&channel_type));
+ if (config.ordered) {
+ EXPECT_EQ(config.maxRetransmits > -1 ?
+ 0x01 : (config.maxRetransmitTime > -1 ? 0x02 : 0),
+ channel_type);
+ } else {
+ EXPECT_EQ(config.maxRetransmits > -1 ?
+ 0x81 : (config.maxRetransmitTime > -1 ? 0x82 : 0x80),
+ channel_type);
+ }
+
+ ASSERT_TRUE(buffer.ReadUInt16(&priority));
+
+ ASSERT_TRUE(buffer.ReadUInt32(&reliability));
+ if (config.maxRetransmits > -1 || config.maxRetransmitTime > -1) {
+ EXPECT_EQ(config.maxRetransmits > -1 ?
+ config.maxRetransmits : config.maxRetransmitTime,
+ static_cast<int>(reliability));
+ }
+
+ ASSERT_TRUE(buffer.ReadUInt16(&label_length));
+ ASSERT_TRUE(buffer.ReadUInt16(&protocol_length));
+ EXPECT_EQ(label.size(), label_length);
+ EXPECT_EQ(config.protocol.size(), protocol_length);
+
+ std::string label_output;
+ ASSERT_TRUE(buffer.ReadString(&label_output, label_length));
+ EXPECT_EQ(label, label_output);
+ std::string protocol_output;
+ ASSERT_TRUE(buffer.ReadString(&protocol_output, protocol_length));
+ EXPECT_EQ(config.protocol, protocol_output);
+ }
+};
+
+TEST_F(SctpUtilsTest, WriteParseMessageWithOrderedReliable) {
+ std::string input_label = "abc";
+ webrtc::DataChannelInit config;
+ config.protocol = "y";
+
+ talk_base::Buffer packet;
+ ASSERT_TRUE(
+ cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
+
+ VerifyOpenMessageFormat(packet, input_label, config);
+
+ std::string output_label;
+ webrtc::DataChannelInit output_config;
+ ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
+ packet, &output_label, &output_config));
+
+ EXPECT_EQ(input_label, output_label);
+ EXPECT_EQ(config.protocol, output_config.protocol);
+ EXPECT_EQ(config.ordered, output_config.ordered);
+ EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime);
+ EXPECT_EQ(config.maxRetransmits, output_config.maxRetransmits);
+}
+
+TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmitTime) {
+ std::string input_label = "abc";
+ webrtc::DataChannelInit config;
+ config.ordered = false;
+ config.maxRetransmitTime = 10;
+ config.protocol = "y";
+
+ talk_base::Buffer packet;
+ ASSERT_TRUE(
+ cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
+
+ VerifyOpenMessageFormat(packet, input_label, config);
+
+ std::string output_label;
+ webrtc::DataChannelInit output_config;
+ ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
+ packet, &output_label, &output_config));
+
+ EXPECT_EQ(input_label, output_label);
+ EXPECT_EQ(config.protocol, output_config.protocol);
+ EXPECT_EQ(config.ordered, output_config.ordered);
+ EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime);
+ EXPECT_EQ(-1, output_config.maxRetransmits);
+}
+
+TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) {
+ std::string input_label = "abc";
+ webrtc::DataChannelInit config;
+ config.maxRetransmits = 10;
+ config.protocol = "y";
+
+ talk_base::Buffer packet;
+ ASSERT_TRUE(
+ cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
+
+ VerifyOpenMessageFormat(packet, input_label, config);
+
+ std::string output_label;
+ webrtc::DataChannelInit output_config;
+ ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
+ packet, &output_label, &output_config));
+
+ EXPECT_EQ(input_label, output_label);
+ EXPECT_EQ(config.protocol, output_config.protocol);
+ EXPECT_EQ(config.ordered, output_config.ordered);
+ EXPECT_EQ(config.maxRetransmits, output_config.maxRetransmits);
+ EXPECT_EQ(-1, output_config.maxRetransmitTime);
+}
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/dummyinstantiation.cc b/chromium/third_party/libjingle/source/talk/media/webrtc/dummyinstantiation.cc
new file mode 100644
index 00000000000..7d27967099b
--- /dev/null
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/dummyinstantiation.cc
@@ -0,0 +1,37 @@
+/*
+ * libjingle
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/media/webrtc/fakewebrtcvideoengine.h"
+#include "talk/media/webrtc/fakewebrtcvoiceengine.h"
+
+static void EnsureAPIMatch() {
+ new cricket::FakeWebRtcVoiceEngine(NULL, 0);
+ new cricket::FakeWebRtcVideoDecoder();
+ new cricket::FakeWebRtcVideoEncoder();
+ new cricket::FakeWebRtcVideoEngine(NULL, 0);
+ new cricket::FakeWebRtcVideoEngine::Capturer();
+}
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvideoengine.h b/chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvideoengine.h
index 31de172a211..bb75c2a7feb 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvideoengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvideoengine.h
@@ -33,6 +33,7 @@
#include <vector>
#include "talk/base/basictypes.h"
+#include "talk/base/gunit.h"
#include "talk/base/stringutils.h"
#include "talk/media/base/codec.h"
#include "talk/media/webrtc/fakewebrtccommon.h"
@@ -276,6 +277,8 @@ class FakeWebRtcVideoEngine
send(false),
receive_(false),
can_transmit_(true),
+ remote_rtx_ssrc_(-1),
+ rtx_send_payload_type(-1),
rtcp_status_(webrtc::kRtcpNone),
key_frame_request_method_(webrtc::kViEKeyFrameRequestNone),
tmmbr_(false),
@@ -306,6 +309,9 @@ class FakeWebRtcVideoEngine
bool receive_;
bool can_transmit_;
std::map<int, int> ssrcs_;
+ std::map<int, int> rtx_ssrcs_;
+ int remote_rtx_ssrc_;
+ int rtx_send_payload_type;
std::string cname_;
webrtc::ViERTCPMode rtcp_status_;
webrtc::ViEKeyFrameRequestMethod key_frame_request_method_;
@@ -333,12 +339,14 @@ class FakeWebRtcVideoEngine
};
class Capturer : public webrtc::ViEExternalCapture {
public:
- Capturer() : channel_id_(-1), denoising_(false), last_capture_time_(0) { }
+ Capturer() : channel_id_(-1), denoising_(false),
+ last_capture_time_(0), incoming_frame_num_(0) { }
int channel_id() const { return channel_id_; }
void set_channel_id(int channel_id) { channel_id_ = channel_id; }
bool denoising() const { return denoising_; }
void set_denoising(bool denoising) { denoising_ = denoising; }
- int64 last_capture_time() { return last_capture_time_; }
+ int64 last_capture_time() const { return last_capture_time_; }
+ int incoming_frame_num() const { return incoming_frame_num_; }
// From ViEExternalCapture
virtual int IncomingFrame(unsigned char* videoFrame,
@@ -353,6 +361,7 @@ class FakeWebRtcVideoEngine
const webrtc::ViEVideoFrameI420& video_frame,
unsigned long long captureTime) {
last_capture_time_ = captureTime;
+ ++incoming_frame_num_;
return 0;
}
@@ -360,6 +369,7 @@ class FakeWebRtcVideoEngine
int channel_id_;
bool denoising_;
int64 last_capture_time_;
+ int incoming_frame_num_;
};
FakeWebRtcVideoEngine(const cricket::VideoCodec* const* codecs,
@@ -402,6 +412,16 @@ class FakeWebRtcVideoEngine
int GetLastCapturer() const { return last_capturer_; }
int GetNumCapturers() const { return static_cast<int>(capturers_.size()); }
+ int GetIncomingFrameNum(int channel_id) const {
+ for (std::map<int, Capturer*>::const_iterator iter = capturers_.begin();
+ iter != capturers_.end(); ++iter) {
+ Capturer* capturer = iter->second;
+ if (capturer->channel_id() == channel_id) {
+ return capturer->incoming_frame_num();
+ }
+ }
+ return -1;
+ }
void set_fail_alloc_capturer(bool fail_alloc_capturer) {
fail_alloc_capturer_ = fail_alloc_capturer;
}
@@ -500,10 +520,23 @@ class FakeWebRtcVideoEngine
return static_cast<int>(
channels_.find(channel)->second->ssrcs_.size());
}
+ int GetNumRtxSsrcs(int channel) const {
+ WEBRTC_ASSERT_CHANNEL(channel);
+ return static_cast<int>(
+ channels_.find(channel)->second->rtx_ssrcs_.size());
+ }
bool GetIsTransmitting(int channel) const {
WEBRTC_ASSERT_CHANNEL(channel);
return channels_.find(channel)->second->can_transmit_;
}
+ int GetRtxSsrc(int channel, int simulcast_idx) const {
+ WEBRTC_ASSERT_CHANNEL(channel);
+ if (channels_.find(channel)->second->rtx_ssrcs_.find(simulcast_idx) ==
+ channels_.find(channel)->second->rtx_ssrcs_.end()) {
+ return -1;
+ }
+ return channels_.find(channel)->second->rtx_ssrcs_[simulcast_idx];
+ }
bool ReceiveCodecRegistered(int channel,
const webrtc::VideoCodec& codec) const {
WEBRTC_ASSERT_CHANNEL(channel);
@@ -557,6 +590,14 @@ class FakeWebRtcVideoEngine
WEBRTC_ASSERT_CHANNEL(channel);
channels_[channel]->receive_bandwidth_ = receive_bandwidth;
};
+ int GetRtxSendPayloadType(int channel) {
+ WEBRTC_CHECK_CHANNEL(channel);
+ return channels_[channel]->rtx_send_payload_type;
+ }
+ int GetRemoteRtxSsrc(int channel) {
+ WEBRTC_CHECK_CHANNEL(channel);
+ return channels_.find(channel)->second->remote_rtx_ssrc_;
+ }
WEBRTC_STUB(Release, ());
@@ -599,6 +640,9 @@ class FakeWebRtcVideoEngine
}
WEBRTC_STUB(RegisterCpuOveruseObserver,
(int channel, webrtc::CpuOveruseObserver* observer));
+#ifdef USE_WEBRTC_DEV_BRANCH
+ WEBRTC_STUB(CpuOveruseMeasures, (int, int*, int*, int*, int*));
+#endif
WEBRTC_STUB(ConnectAudioChannel, (const int, const int));
WEBRTC_STUB(DisconnectAudioChannel, (const int));
WEBRTC_FUNC(StartSend, (const int channel)) {
@@ -716,6 +760,7 @@ class FakeWebRtcVideoEngine
WEBRTC_STUB(WaitForFirstKeyFrame, (const int, const bool));
WEBRTC_STUB(StartDebugRecording, (int, const char*));
WEBRTC_STUB(StopDebugRecording, (int));
+ WEBRTC_VOID_STUB(SuspendBelowMinBitrate, (int));
// webrtc::ViECapture
WEBRTC_STUB(NumberOfCaptureDevices, ());
@@ -782,7 +827,12 @@ class FakeWebRtcVideoEngine
}
WEBRTC_STUB(RegisterSendTransport, (const int, webrtc::Transport&));
WEBRTC_STUB(DeregisterSendTransport, (const int));
+#ifdef USE_WEBRTC_DEV_BRANCH
+ WEBRTC_STUB(ReceivedRTPPacket, (const int, const void*, const int,
+ const webrtc::PacketTime&));
+#else
WEBRTC_STUB(ReceivedRTPPacket, (const int, const void*, const int));
+#endif
WEBRTC_STUB(ReceivedRTCPPacket, (const int, const void*, const int));
// Not using WEBRTC_STUB due to bool return value
virtual bool IsIPv6Enabled(int channel) { return true; }
@@ -851,11 +901,28 @@ class FakeWebRtcVideoEngine
const webrtc::StreamType usage,
const unsigned char idx)) {
WEBRTC_CHECK_CHANNEL(channel);
- channels_[channel]->ssrcs_[idx] = ssrc;
+ switch (usage) {
+ case webrtc::kViEStreamTypeNormal:
+ channels_[channel]->ssrcs_[idx] = ssrc;
+ break;
+ case webrtc::kViEStreamTypeRtx:
+ channels_[channel]->rtx_ssrcs_[idx] = ssrc;
+ break;
+ default:
+ return -1;
+ }
return 0;
}
- WEBRTC_STUB_CONST(SetRemoteSSRCType, (const int,
- const webrtc::StreamType, const unsigned int));
+
+ WEBRTC_FUNC_CONST(SetRemoteSSRCType, (const int channel,
+ const webrtc::StreamType usage, const unsigned int ssrc)) {
+ WEBRTC_CHECK_CHANNEL(channel);
+ if (usage == webrtc::kViEStreamTypeRtx) {
+ channels_.find(channel)->second->remote_rtx_ssrc_ = ssrc;
+ return 0;
+ }
+ return -1;
+ }
WEBRTC_FUNC_CONST(GetLocalSSRC, (const int channel,
unsigned int& ssrc)) {
@@ -867,7 +934,12 @@ class FakeWebRtcVideoEngine
WEBRTC_STUB_CONST(GetRemoteSSRC, (const int, unsigned int&));
WEBRTC_STUB_CONST(GetRemoteCSRCs, (const int, unsigned int*));
- WEBRTC_STUB(SetRtxSendPayloadType, (const int, const uint8));
+ WEBRTC_FUNC(SetRtxSendPayloadType, (const int channel,
+ const uint8 payload_type)) {
+ WEBRTC_CHECK_CHANNEL(channel);
+ channels_[channel]->rtx_send_payload_type = payload_type;
+ return 0;
+ }
WEBRTC_STUB(SetRtxReceivePayloadType, (const int, const uint8));
WEBRTC_STUB(SetStartSequenceNumber, (const int, unsigned short));
@@ -968,6 +1040,9 @@ class FakeWebRtcVideoEngine
channels_[channel]->rtp_absolute_send_time_receive_id_ = (enable) ? id : 0;
return 0;
}
+#ifdef USE_WEBRTC_DEV_BRANCH
+ WEBRTC_STUB(SetRtcpXrRrtrStatus, (int, bool));
+#endif
WEBRTC_FUNC(SetTransmissionSmoothingStatus, (int channel, bool enable)) {
WEBRTC_CHECK_CHANNEL(channel);
channels_[channel]->transmission_smoothing_ = enable;
@@ -979,6 +1054,12 @@ class FakeWebRtcVideoEngine
unsigned int&, unsigned int&, unsigned int&, int&));
WEBRTC_STUB_CONST(GetRTPStatistics, (const int, unsigned int&, unsigned int&,
unsigned int&, unsigned int&));
+ WEBRTC_STUB_CONST(GetReceiveChannelRtcpStatistics, (const int,
+ webrtc::RtcpStatistics&, int&));
+ WEBRTC_STUB_CONST(GetSendChannelRtcpStatistics, (const int,
+ webrtc::RtcpStatistics&, int&));
+ WEBRTC_STUB_CONST(GetRtpStatistics, (const int, webrtc::StreamDataCounters&,
+ webrtc::StreamDataCounters&));
WEBRTC_FUNC_CONST(GetBandwidthUsage, (const int channel,
unsigned int& total_bitrate, unsigned int& video_bitrate,
unsigned int& fec_bitrate, unsigned int& nack_bitrate)) {
@@ -1021,6 +1102,30 @@ class FakeWebRtcVideoEngine
}
return 0;
}
+ WEBRTC_STUB(RegisterSendChannelRtcpStatisticsCallback,
+ (int, webrtc::RtcpStatisticsCallback*));
+ WEBRTC_STUB(DeregisterSendChannelRtcpStatisticsCallback,
+ (int, webrtc::RtcpStatisticsCallback*));
+ WEBRTC_STUB(RegisterReceiveChannelRtcpStatisticsCallback,
+ (int, webrtc::RtcpStatisticsCallback*));
+ WEBRTC_STUB(DeregisterReceiveChannelRtcpStatisticsCallback,
+ (int, webrtc::RtcpStatisticsCallback*));
+ WEBRTC_STUB(RegisterSendChannelRtpStatisticsCallback,
+ (int, webrtc::StreamDataCountersCallback*));
+ WEBRTC_STUB(DeregisterSendChannelRtpStatisticsCallback,
+ (int, webrtc::StreamDataCountersCallback*));
+ WEBRTC_STUB(RegisterReceiveChannelRtpStatisticsCallback,
+ (int, webrtc::StreamDataCountersCallback*));
+ WEBRTC_STUB(DeregisterReceiveChannelRtpStatisticsCallback,
+ (int, webrtc::StreamDataCountersCallback*));
+ WEBRTC_STUB(RegisterSendBitrateObserver,
+ (int, webrtc::BitrateStatisticsObserver*));
+ WEBRTC_STUB(DeregisterSendBitrateObserver,
+ (int, webrtc::BitrateStatisticsObserver*));
+ WEBRTC_STUB(RegisterSendFrameCountObserver,
+ (int, webrtc::FrameCountObserver*));
+ WEBRTC_STUB(DeregisterSendFrameCountObserver,
+ (int, webrtc::FrameCountObserver*));
WEBRTC_STUB(StartRTPDump, (const int, const char*, webrtc::RTPDirections));
WEBRTC_STUB(StopRTPDump, (const int, webrtc::RTPDirections));
@@ -1046,7 +1151,12 @@ class FakeWebRtcVideoEngine
return 0;
}
WEBRTC_STUB(EnableColorEnhancement, (const int, const bool));
-
+ WEBRTC_VOID_STUB(RegisterPreEncodeCallback,
+ (int, webrtc::I420FrameCallback*));
+ WEBRTC_VOID_STUB(DeRegisterPreEncodeCallback, (int));
+ WEBRTC_VOID_STUB(RegisterPreRenderCallback,
+ (int, webrtc::I420FrameCallback*));
+ WEBRTC_VOID_STUB(DeRegisterPreRenderCallback, (int));
// webrtc::ViEExternalCodec
WEBRTC_FUNC(RegisterExternalSendCodec,
(const int channel, const unsigned char pl_type, webrtc::VideoEncoder*,
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvoiceengine.h b/chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvoiceengine.h
index c3cd786009d..a68d65ef750 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvoiceengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/fakewebrtcvoiceengine.h
@@ -34,11 +34,14 @@
#include "talk/base/basictypes.h"
+#include "talk/base/gunit.h"
#include "talk/base/stringutils.h"
#include "talk/media/base/codec.h"
#include "talk/media/base/voiceprocessor.h"
#include "talk/media/webrtc/fakewebrtccommon.h"
#include "talk/media/webrtc/webrtcvoe.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
+#include "webrtc/common.h"
namespace cricket {
@@ -75,7 +78,7 @@ class FakeWebRtcVoiceEngine
int dtmf_length_ms;
};
struct Channel {
- Channel()
+ explicit Channel(bool use_experimental_acm)
: external_transport(false),
send(false),
playout(false),
@@ -87,14 +90,18 @@ class FakeWebRtcVoiceEngine
fec(false),
nack(false),
media_processor_registered(false),
+ rx_agc_enabled(false),
+ rx_agc_mode(webrtc::kAgcDefault),
cn8_type(13),
cn16_type(105),
dtmf_type(106),
fec_type(117),
nack_max_packets(0),
send_ssrc(0),
- level_header_ext_(-1) {
+ level_header_ext_(-1),
+ using_experimental_acm(use_experimental_acm) {
memset(&send_codec, 0, sizeof(send_codec));
+ memset(&rx_agc_config, 0, sizeof(rx_agc_config));
}
bool external_transport;
bool send;
@@ -107,6 +114,9 @@ class FakeWebRtcVoiceEngine
bool fec;
bool nack;
bool media_processor_registered;
+ bool rx_agc_enabled;
+ webrtc::AgcModes rx_agc_mode;
+ webrtc::AgcConfig rx_agc_config;
int cn8_type;
int cn16_type;
int dtmf_type;
@@ -118,6 +128,7 @@ class FakeWebRtcVoiceEngine
std::vector<webrtc::CodecInst> recv_codecs;
webrtc::CodecInst send_codec;
std::list<std::string> packets;
+ bool using_experimental_acm;
};
FakeWebRtcVoiceEngine(const cricket::AudioCodec* const* codecs,
@@ -144,6 +155,8 @@ class FakeWebRtcVoiceEngine
send_fail_channel_(-1),
fail_start_recording_microphone_(false),
recording_microphone_(false),
+ recording_sample_rate_(-1),
+ playout_sample_rate_(-1),
media_processor_(NULL) {
memset(&agc_config_, 0, sizeof(agc_config_));
}
@@ -169,7 +182,7 @@ class FakeWebRtcVoiceEngine
}
return -1;
}
- int GetNumChannels() const { return channels_.size(); }
+ int GetNumChannels() const { return static_cast<int>(channels_.size()); }
bool GetPlayout(int channel) {
return channels_[channel]->playout;
}
@@ -191,6 +204,10 @@ class FakeWebRtcVoiceEngine
int GetNACKMaxPackets(int channel) {
return channels_[channel]->nack_max_packets;
}
+ bool IsUsingExperimentalAcm(int channel) {
+ WEBRTC_ASSERT_CHANNEL(channel);
+ return channels_[channel]->using_experimental_acm;
+ }
int GetSendCNPayloadType(int channel, bool wideband) {
return (wideband) ?
channels_[channel]->cn16_type :
@@ -244,6 +261,19 @@ class FakeWebRtcVoiceEngine
true);
}
}
+ int AddChannel(bool use_experimental_acm) {
+ if (fail_create_channel_) {
+ return -1;
+ }
+ Channel* ch = new Channel(use_experimental_acm);
+ for (int i = 0; i < NumOfCodecs(); ++i) {
+ webrtc::CodecInst codec;
+ GetCodec(i, codec);
+ ch->recv_codecs.push_back(codec);
+ }
+ channels_[++last_channel_] = ch;
+ return last_channel_;
+ }
WEBRTC_STUB(Release, ());
@@ -267,17 +297,13 @@ class FakeWebRtcVoiceEngine
return NULL;
}
WEBRTC_FUNC(CreateChannel, ()) {
- if (fail_create_channel_) {
- return -1;
- }
- Channel* ch = new Channel();
- for (int i = 0; i < NumOfCodecs(); ++i) {
- webrtc::CodecInst codec;
- GetCodec(i, codec);
- ch->recv_codecs.push_back(codec);
- }
- channels_[++last_channel_] = ch;
- return last_channel_;
+ return AddChannel(false);
+ }
+ WEBRTC_FUNC(CreateChannel, (const webrtc::Config& config)) {
+ talk_base::scoped_ptr<webrtc::AudioCodingModule> acm(
+ config.Get<webrtc::AudioCodingModuleFactory>().Create(0));
+ return AddChannel(strcmp(acm->Version(), webrtc::kExperimentalAcmVersion)
+ == 0);
}
WEBRTC_FUNC(DeleteChannel, (int channel)) {
WEBRTC_CHECK_CHANNEL(channel);
@@ -584,15 +610,34 @@ class FakeWebRtcVoiceEngine
WEBRTC_STUB(AudioDeviceControl, (unsigned int, unsigned int, unsigned int));
WEBRTC_STUB(SetLoudspeakerStatus, (bool enable));
WEBRTC_STUB(GetLoudspeakerStatus, (bool& enabled));
- WEBRTC_STUB(SetRecordingSampleRate, (unsigned int samples_per_sec));
- WEBRTC_STUB_CONST(RecordingSampleRate, (unsigned int* samples_per_sec));
- WEBRTC_STUB(SetPlayoutSampleRate, (unsigned int samples_per_sec));
- WEBRTC_STUB_CONST(PlayoutSampleRate, (unsigned int* samples_per_sec));
+ WEBRTC_FUNC(SetRecordingSampleRate, (unsigned int samples_per_sec)) {
+ recording_sample_rate_ = samples_per_sec;
+ return 0;
+ }
+ WEBRTC_FUNC_CONST(RecordingSampleRate, (unsigned int* samples_per_sec)) {
+ *samples_per_sec = recording_sample_rate_;
+ return 0;
+ }
+ WEBRTC_FUNC(SetPlayoutSampleRate, (unsigned int samples_per_sec)) {
+ playout_sample_rate_ = samples_per_sec;
+ return 0;
+ }
+ WEBRTC_FUNC_CONST(PlayoutSampleRate, (unsigned int* samples_per_sec)) {
+ *samples_per_sec = playout_sample_rate_;
+ return 0;
+ }
WEBRTC_STUB(EnableBuiltInAEC, (bool enable));
virtual bool BuiltInAECIsEnabled() const { return true; }
// webrtc::VoENetEqStats
WEBRTC_STUB(GetNetworkStatistics, (int, webrtc::NetworkStatistics&));
+#ifdef USE_WEBRTC_DEV_BRANCH
+ WEBRTC_FUNC_CONST(GetDecodingCallStatistics, (int channel,
+ webrtc::AudioDecodingCallStats*)) {
+ WEBRTC_CHECK_CHANNEL(channel);
+ return 0;
+ }
+#endif
// webrtc::VoENetwork
WEBRTC_FUNC(RegisterExternalTransport, (int channel,
@@ -841,12 +886,27 @@ class FakeWebRtcVoiceEngine
WEBRTC_STUB(SetRxNsStatus, (int channel, bool enable, webrtc::NsModes mode));
WEBRTC_STUB(GetRxNsStatus, (int channel, bool& enabled,
webrtc::NsModes& mode));
- WEBRTC_STUB(SetRxAgcStatus, (int channel, bool enable,
- webrtc::AgcModes mode));
- WEBRTC_STUB(GetRxAgcStatus, (int channel, bool& enabled,
- webrtc::AgcModes& mode));
- WEBRTC_STUB(SetRxAgcConfig, (int channel, webrtc::AgcConfig config));
- WEBRTC_STUB(GetRxAgcConfig, (int channel, webrtc::AgcConfig& config));
+ WEBRTC_FUNC(SetRxAgcStatus, (int channel, bool enable,
+ webrtc::AgcModes mode)) {
+ channels_[channel]->rx_agc_enabled = enable;
+ channels_[channel]->rx_agc_mode = mode;
+ return 0;
+ }
+ WEBRTC_FUNC(GetRxAgcStatus, (int channel, bool& enabled,
+ webrtc::AgcModes& mode)) {
+ enabled = channels_[channel]->rx_agc_enabled;
+ mode = channels_[channel]->rx_agc_mode;
+ return 0;
+ }
+
+ WEBRTC_FUNC(SetRxAgcConfig, (int channel, webrtc::AgcConfig config)) {
+ channels_[channel]->rx_agc_config = config;
+ return 0;
+ }
+ WEBRTC_FUNC(GetRxAgcConfig, (int channel, webrtc::AgcConfig& config)) {
+ config = channels_[channel]->rx_agc_config;
+ return 0;
+ }
WEBRTC_STUB(RegisterRxVadObserver, (int, webrtc::VoERxVadCallback&));
WEBRTC_STUB(DeRegisterRxVadObserver, (int channel));
@@ -863,6 +923,9 @@ class FakeWebRtcVoiceEngine
WEBRTC_STUB(GetEcDelayMetrics, (int& delay_median, int& delay_std));
WEBRTC_STUB(StartDebugRecording, (const char* fileNameUTF8));
+#ifdef USE_WEBRTC_DEV_BRANCH
+ WEBRTC_STUB(StartDebugRecording, (FILE* handle));
+#endif
WEBRTC_STUB(StopDebugRecording, ());
WEBRTC_FUNC(SetTypingDetectionStatus, (bool enable)) {
@@ -996,6 +1059,8 @@ class FakeWebRtcVoiceEngine
int send_fail_channel_;
bool fail_start_recording_microphone_;
bool recording_microphone_;
+ int recording_sample_rate_;
+ int playout_sample_rate_;
DtmfInfo dtmf_info_;
webrtc::VoEMediaProcess* media_processor_;
};
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcmediaengine.h b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcmediaengine.h
index a2ee6587610..94e7a99d826 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcmediaengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcmediaengine.h
@@ -87,10 +87,13 @@ class WebRtcMediaEngine : public cricket::MediaEngineInterface {
virtual SoundclipMedia* CreateSoundclip() OVERRIDE {
return delegate_->CreateSoundclip();
}
- virtual bool SetAudioOptions(int options) OVERRIDE {
+ virtual AudioOptions GetAudioOptions() const OVERRIDE {
+ return delegate_->GetAudioOptions();
+ }
+ virtual bool SetAudioOptions(const AudioOptions& options) OVERRIDE {
return delegate_->SetAudioOptions(options);
}
- virtual bool SetVideoOptions(int options) OVERRIDE {
+ virtual bool SetVideoOptions(const VideoOptions& options) OVERRIDE {
return delegate_->SetVideoOptions(options);
}
virtual bool SetAudioDelayOffset(int offset) OVERRIDE {
@@ -100,6 +103,9 @@ class WebRtcMediaEngine : public cricket::MediaEngineInterface {
const VideoEncoderConfig& config) OVERRIDE {
return delegate_->SetDefaultVideoEncoderConfig(config);
}
+ virtual VideoEncoderConfig GetDefaultVideoEncoderConfig() const OVERRIDE {
+ return delegate_->GetDefaultVideoEncoderConfig();
+ }
virtual bool SetSoundDevices(
const Device* in_device, const Device* out_device) OVERRIDE {
return delegate_->SetSoundDevices(in_device, out_device);
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.cc b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.cc
index bcfda4e84e8..6e81b401613 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.cc
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.cc
@@ -328,14 +328,10 @@ void WebRtcVideoCapturer::OnIncomingCapturedFrame(const int32_t id,
// to one block for it.
int length = webrtc::CalcBufferSize(webrtc::kI420,
sample.width(), sample.height());
- if (!captured_frame_.get() ||
- captured_frame_->length() != static_cast<size_t>(length)) {
- captured_frame_.reset(new FrameBuffer(length));
- }
- // TODO(ronghuawu): Refactor the WebRtcVideoFrame to avoid memory copy.
- webrtc::ExtractBuffer(sample, length,
- reinterpret_cast<uint8_t*>(captured_frame_->data()));
- WebRtcCapturedFrame frame(sample, captured_frame_->data(), length);
+ capture_buffer_.resize(length);
+ // TODO(ronghuawu): Refactor the WebRtcCapturedFrame to avoid memory copy.
+ webrtc::ExtractBuffer(sample, length, &capture_buffer_[0]);
+ WebRtcCapturedFrame frame(sample, &capture_buffer_[0], length);
SignalFrameCaptured(this, &frame);
}
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.h b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.h
index eb999564409..c20a05919e0 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.h
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideocapturer.h
@@ -88,7 +88,7 @@ class WebRtcVideoCapturer : public VideoCapturer,
talk_base::scoped_ptr<WebRtcVcmFactoryInterface> factory_;
webrtc::VideoCaptureModule* module_;
int captured_frames_;
- talk_base::scoped_ptr<FrameBuffer> captured_frame_;
+ std::vector<uint8_t> capture_buffer_;
};
struct WebRtcCapturedFrame : public CapturedFrame {
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.cc b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.cc
index fd7e5bfa3f6..88e09fc3842 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.cc
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.cc
@@ -93,6 +93,9 @@ static const int kStartVideoBitrate = 300;
static const int kMaxVideoBitrate = 2000;
static const int kDefaultConferenceModeMaxVideoBitrate = 500;
+// Controlled by exp, try a super low minimum bitrate for poor connections.
+static const int kLowerMinBitrate = 30;
+
static const int kVideoMtu = 1200;
static const int kVideoRtpBufferSize = 65536;
@@ -153,6 +156,11 @@ static const int kRtpTimeOffsetExtensionId = 2;
static const char kRtpAbsoluteSendTimeHeaderExtension[] =
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
static const int kRtpAbsoluteSendTimeExtensionId = 3;
+// Default video dscp value.
+// See http://tools.ietf.org/html/rfc2474 for details
+// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
+static const talk_base::DiffServCodePoint kVideoDscpValue =
+ talk_base::DSCP_AF41;
static bool IsNackEnabled(const VideoCodec& codec) {
return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack,
@@ -220,9 +228,8 @@ class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
}
virtual int DeliverFrame(unsigned char* buffer, int buffer_size,
- uint32_t time_stamp, int64_t render_time
- , void* handle
- ) {
+ uint32_t time_stamp, int64_t render_time,
+ void* handle) {
talk_base::CritScope cs(&crit_);
frame_rate_tracker_.Update(1);
if (renderer_ == NULL) {
@@ -250,8 +257,8 @@ class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
int DeliverBufferFrame(unsigned char* buffer, int buffer_size,
int64 elapsed_time, int64 time_stamp) {
WebRtcVideoFrame video_frame;
- video_frame.Attach(buffer, buffer_size, width_, height_,
- 1, 1, elapsed_time, time_stamp, 0);
+ video_frame.Alias(buffer, buffer_size, width_, height_,
+ 1, 1, elapsed_time, time_stamp, 0);
// Sanity check on decoded frame size.
@@ -261,9 +268,6 @@ class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
}
int ret = renderer_->RenderFrame(&video_frame) ? 0 : -1;
- uint8* buffer_temp;
- size_t buffer_size_temp;
- video_frame.Detach(&buffer_temp, &buffer_size_temp);
return ret;
}
@@ -309,6 +313,13 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
: video_channel_(video_channel),
framerate_(0),
bitrate_(0),
+ decode_ms_(0),
+ max_decode_ms_(0),
+ current_delay_ms_(0),
+ target_delay_ms_(0),
+ jitter_buffer_ms_(0),
+ min_playout_delay_ms_(0),
+ render_delay_ms_(0),
firs_requested_(0) {
}
@@ -318,23 +329,61 @@ class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
virtual void IncomingRate(const int videoChannel,
const unsigned int framerate,
const unsigned int bitrate) {
+ talk_base::CritScope cs(&crit_);
ASSERT(video_channel_ == videoChannel);
framerate_ = framerate;
bitrate_ = bitrate;
}
+
+ virtual void DecoderTiming(int decode_ms,
+ int max_decode_ms,
+ int current_delay_ms,
+ int target_delay_ms,
+ int jitter_buffer_ms,
+ int min_playout_delay_ms,
+ int render_delay_ms) {
+ talk_base::CritScope cs(&crit_);
+ decode_ms_ = decode_ms;
+ max_decode_ms_ = max_decode_ms;
+ current_delay_ms_ = current_delay_ms;
+ target_delay_ms_ = target_delay_ms;
+ jitter_buffer_ms_ = jitter_buffer_ms;
+ min_playout_delay_ms_ = min_playout_delay_ms;
+ render_delay_ms_ = render_delay_ms;
+ }
+
virtual void RequestNewKeyFrame(const int videoChannel) {
+ talk_base::CritScope cs(&crit_);
ASSERT(video_channel_ == videoChannel);
++firs_requested_;
}
- int framerate() const { return framerate_; }
- int bitrate() const { return bitrate_; }
- int firs_requested() const { return firs_requested_; }
+ // Populate |rinfo| based on previously-set data in |*this|.
+ void ExportTo(VideoReceiverInfo* rinfo) {
+ talk_base::CritScope cs(&crit_);
+ rinfo->firs_sent = firs_requested_;
+ rinfo->framerate_rcvd = framerate_;
+ rinfo->decode_ms = decode_ms_;
+ rinfo->max_decode_ms = max_decode_ms_;
+ rinfo->current_delay_ms = current_delay_ms_;
+ rinfo->target_delay_ms = target_delay_ms_;
+ rinfo->jitter_buffer_ms = jitter_buffer_ms_;
+ rinfo->min_playout_delay_ms = min_playout_delay_ms_;
+ rinfo->render_delay_ms = render_delay_ms_;
+ }
private:
+ mutable talk_base::CriticalSection crit_;
int video_channel_;
int framerate_;
int bitrate_;
+ int decode_ms_;
+ int max_decode_ms_;
+ int current_delay_ms_;
+ int target_delay_ms_;
+ int jitter_buffer_ms_;
+ int min_playout_delay_ms_;
+ int render_delay_ms_;
int firs_requested_;
};
@@ -343,25 +392,45 @@ class WebRtcEncoderObserver : public webrtc::ViEEncoderObserver {
explicit WebRtcEncoderObserver(int video_channel)
: video_channel_(video_channel),
framerate_(0),
- bitrate_(0) {
+ bitrate_(0),
+ suspended_(false) {
}
// virtual functions from VieEncoderObserver.
virtual void OutgoingRate(const int videoChannel,
const unsigned int framerate,
const unsigned int bitrate) {
+ talk_base::CritScope cs(&crit_);
ASSERT(video_channel_ == videoChannel);
framerate_ = framerate;
bitrate_ = bitrate;
}
- int framerate() const { return framerate_; }
- int bitrate() const { return bitrate_; }
+ virtual void SuspendChange(int video_channel, bool is_suspended) {
+ talk_base::CritScope cs(&crit_);
+ ASSERT(video_channel_ == video_channel);
+ suspended_ = is_suspended;
+ }
+
+ int framerate() const {
+ talk_base::CritScope cs(&crit_);
+ return framerate_;
+ }
+ int bitrate() const {
+ talk_base::CritScope cs(&crit_);
+ return bitrate_;
+ }
+ bool suspended() const {
+ talk_base::CritScope cs(&crit_);
+ return suspended_;
+ }
private:
+ mutable talk_base::CriticalSection crit_;
int video_channel_;
int framerate_;
int bitrate_;
+ bool suspended_;
};
class WebRtcLocalStreamInfo {
@@ -514,7 +583,8 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
external_capture_(external_capture),
capturer_updated_(false),
interval_(0),
- video_adapter_(new CoordinatedVideoAdapter) {
+ video_adapter_(new CoordinatedVideoAdapter),
+ cpu_monitor_(cpu_monitor) {
overuse_observer_.reset(new WebRtcOveruseObserver(video_adapter_.get()));
SignalCpuAdaptationUnable.repeat(video_adapter_->SignalCpuAdaptationUnable);
if (cpu_monitor) {
@@ -562,10 +632,6 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
}
}
- bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame) {
- *out_frame = NULL;
- return video_adapter_->AdaptFrame(in_frame, out_frame);
- }
int CurrentAdaptReason() const {
return video_adapter_->adapt_reason();
}
@@ -606,9 +672,18 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
// video capturer.
video_adapter_->SetInputFormat(*capture_format);
}
+ // TODO(thorcarpenter): When the adapter supports "only frame dropping"
+ // mode, also hook it up to screencast capturers.
+ video_capturer->SignalAdaptFrame.connect(
+ this, &WebRtcVideoChannelSendInfo::AdaptFrame);
}
}
+ void AdaptFrame(VideoCapturer* capturer, const VideoFrame* input,
+ VideoFrame** adapted) {
+ video_adapter_->AdaptFrame(input, adapted);
+ }
+
void ApplyCpuOptions(const VideoOptions& options) {
bool cpu_adapt, cpu_smoothing, adapt_third;
float low, med, high;
@@ -633,6 +708,9 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
}
void SetCpuOveruseDetection(bool enable) {
+ if (cpu_monitor_ && enable) {
+ cpu_monitor_->SignalUpdate.disconnect(video_adapter_.get());
+ }
overuse_observer_->Enable(enable);
video_adapter_->set_cpu_adaptation(enable);
}
@@ -689,14 +767,16 @@ class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
int64 interval_;
talk_base::scoped_ptr<CoordinatedVideoAdapter> video_adapter_;
+ talk_base::CpuMonitor* cpu_monitor_;
talk_base::scoped_ptr<WebRtcOveruseObserver> overuse_observer_;
};
const WebRtcVideoEngine::VideoCodecPref
WebRtcVideoEngine::kVideoCodecPrefs[] = {
- {kVp8PayloadName, 100, 0},
- {kRedPayloadName, 116, 1},
- {kFecPayloadName, 117, 2},
+ {kVp8PayloadName, 100, -1, 0},
+ {kRedPayloadName, 116, -1, 1},
+ {kFecPayloadName, 117, -1, 2},
+ {kRtxCodecName, 96, 100, 3},
};
// The formats are sorted by the descending order of width. We use the order to
@@ -900,7 +980,7 @@ int WebRtcVideoEngine::GetCapabilities() {
return VIDEO_RECV | VIDEO_SEND;
}
-bool WebRtcVideoEngine::SetOptions(int options) {
+bool WebRtcVideoEngine::SetOptions(const VideoOptions &options) {
return true;
}
@@ -909,6 +989,17 @@ bool WebRtcVideoEngine::SetDefaultEncoderConfig(
return SetDefaultCodec(config.max_codec);
}
+VideoEncoderConfig WebRtcVideoEngine::GetDefaultEncoderConfig() const {
+ ASSERT(!video_codecs_.empty());
+ VideoCodec max_codec(kVideoCodecPrefs[0].payload_type,
+ kVideoCodecPrefs[0].name,
+ video_codecs_[0].width,
+ video_codecs_[0].height,
+ video_codecs_[0].framerate,
+ 0);
+ return VideoEncoderConfig(max_codec);
+}
+
// SetDefaultCodec may be called while the capturer is running. For example, a
// test call is started in a page with QVGA default codec, and then a real call
// is started in another page with VGA default codec. This is the corner case
@@ -919,6 +1010,7 @@ bool WebRtcVideoEngine::SetDefaultCodec(const VideoCodec& codec) {
return false;
}
+ ASSERT(!video_codecs_.empty());
default_codec_format_ = VideoFormat(
video_codecs_[0].width,
video_codecs_[0].height,
@@ -1223,7 +1315,8 @@ static void AddDefaultFeedbackParams(VideoCodec* codec) {
}
// Rebuilds the codec list to be only those that are less intensive
-// than the specified codec. Prefers internal codec over external.
+// than the specified codec. Prefers internal codec over external with
+// higher preference field.
bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) {
if (!FindCodec(in_codec))
return false;
@@ -1243,6 +1336,10 @@ bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) {
if (_stricmp(kVp8PayloadName, codec.name.c_str()) == 0) {
AddDefaultFeedbackParams(&codec);
}
+ if (pref.associated_payload_type != -1) {
+ codec.SetParam(kCodecParamAssociatedPayloadType,
+ pref.associated_payload_type);
+ }
video_codecs_.push_back(codec);
internal_codec_names.insert(codec.name);
}
@@ -1262,7 +1359,9 @@ bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) {
codecs[i].max_width,
codecs[i].max_height,
codecs[i].max_fps,
- static_cast<int>(codecs.size() + ARRAY_SIZE(kVideoCodecPrefs) - i));
+ // Use negative preference on external codec to ensure the internal
+ // codec is preferred.
+ static_cast<int>(0 - i));
AddDefaultFeedbackParams(&codec);
video_codecs_.push_back(codec);
}
@@ -1410,6 +1509,7 @@ WebRtcVideoMediaChannel::WebRtcVideoMediaChannel(
remb_enabled_(false),
render_started_(false),
first_receive_ssrc_(0),
+ send_rtx_type_(-1),
send_red_type_(-1),
send_fec_type_(-1),
send_min_bitrate_(kMinVideoBitrate),
@@ -1486,12 +1586,19 @@ bool WebRtcVideoMediaChannel::SetSendCodecs(
if (sending_) {
ConvertToCricketVideoCodec(*send_codec_, &current);
}
+ std::map<int, int> primary_rtx_pt_mapping;
for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
iter != codecs.end(); ++iter) {
if (_stricmp(iter->name.c_str(), kRedPayloadName) == 0) {
send_red_type_ = iter->id;
} else if (_stricmp(iter->name.c_str(), kFecPayloadName) == 0) {
send_fec_type_ = iter->id;
+ } else if (_stricmp(iter->name.c_str(), kRtxCodecName) == 0) {
+ int rtx_type = iter->id;
+ int rtx_primary_type = -1;
+ if (iter->GetParam(kCodecParamAssociatedPayloadType, &rtx_primary_type)) {
+ primary_rtx_pt_mapping[rtx_primary_type] = rtx_type;
+ }
} else if (engine()->CanSendCodec(*iter, current, &checked_codec)) {
webrtc::VideoCodec wcodec;
if (engine()->ConvertFromCricketVideoCodec(checked_codec, &wcodec)) {
@@ -1547,6 +1654,14 @@ bool WebRtcVideoMediaChannel::SetSendCodecs(
// Select the first matched codec.
webrtc::VideoCodec& codec(send_codecs[0]);
+ // Set RTX payload type if primary now active. This value will be used in
+ // SetSendCodec.
+ std::map<int, int>::const_iterator rtx_it =
+ primary_rtx_pt_mapping.find(static_cast<int>(codec.plType));
+ if (rtx_it != primary_rtx_pt_mapping.end()) {
+ send_rtx_type_ = rtx_it->second;
+ }
+
if (!SetSendCodec(
codec, codec.minBitrate, codec.startBitrate, codec.maxBitrate)) {
return false;
@@ -1648,9 +1763,9 @@ bool WebRtcVideoMediaChannel::SetSend(bool send) {
bool WebRtcVideoMediaChannel::AddSendStream(const StreamParams& sp) {
LOG(LS_INFO) << "AddSendStream " << sp.ToString();
- if (!IsOneSsrcStream(sp)) {
- LOG(LS_ERROR) << "AddSendStream: bad local stream parameters";
- return false;
+ if (!IsOneSsrcStream(sp) && !IsSimulcastStream(sp)) {
+ LOG(LS_ERROR) << "AddSendStream: bad local stream parameters";
+ return false;
}
uint32 ssrc_key;
@@ -1680,6 +1795,11 @@ bool WebRtcVideoMediaChannel::AddSendStream(const StreamParams& sp) {
return false;
}
+ // Set the corresponding RTX SSRC.
+ if (!SetLocalRtxSsrc(channel_id, sp, sp.first_ssrc(), 0)) {
+ return false;
+ }
+
// Set RTCP CName.
if (engine()->vie()->rtp()->SetRTCPCName(channel_id,
sp.cname.c_str()) != 0) {
@@ -1784,10 +1904,11 @@ bool WebRtcVideoMediaChannel::AddRecvStream(const StreamParams& sp) {
return false;
}
- // TODO(perkj): Implement recv media from multiple SSRCs per stream.
- if (sp.ssrcs.size() != 1) {
- LOG(LS_ERROR) << "WebRtcVideoMediaChannel supports one receiving SSRC per"
- << " stream";
+ // TODO(perkj): Implement recv media from multiple media SSRCs per stream.
+ // NOTE: We have two SSRCs per stream when RTX is enabled.
+ if (!IsOneSsrcStream(sp)) {
+ LOG(LS_ERROR) << "WebRtcVideoMediaChannel supports one primary SSRC per"
+ << " stream and one FID SSRC per primary SSRC.";
return false;
}
@@ -1800,6 +1921,16 @@ bool WebRtcVideoMediaChannel::AddRecvStream(const StreamParams& sp) {
return false;
}
+ // Set the corresponding RTX SSRC.
+ uint32 rtx_ssrc;
+ bool has_rtx = sp.GetFidSsrc(sp.first_ssrc(), &rtx_ssrc);
+ if (has_rtx && engine()->vie()->rtp()->SetRemoteSSRCType(
+ channel_id, webrtc::kViEStreamTypeRtx, rtx_ssrc) != 0) {
+ LOG_RTCERR3(SetRemoteSSRCType, channel_id, webrtc::kViEStreamTypeRtx,
+ rtx_ssrc);
+ return false;
+ }
+
// Get the default renderer.
VideoRenderer* default_renderer = NULL;
if (InConferenceMode()) {
@@ -1877,17 +2008,15 @@ bool WebRtcVideoMediaChannel::RemoveRecvStream(uint32 ssrc) {
LOG(LS_INFO) << "Removing video stream " << ssrc
<< " with VideoEngine channel #"
<< channel_id;
+ bool ret = true;
if (engine()->vie()->base()->DeleteChannel(channel_id) == -1) {
LOG_RTCERR1(DeleteChannel, channel_id);
- // Leak the WebRtcVideoChannelRecvInfo owned by |it| but remove the channel
- // from recv_channels_.
- recv_channels_.erase(it);
- return false;
+ ret = false;
}
// Delete the WebRtcVideoChannelRecvInfo pointed to by it->second.
delete info;
recv_channels_.erase(it);
- return true;
+ return ret;
}
bool WebRtcVideoMediaChannel::StartSend() {
@@ -1952,10 +2081,6 @@ bool WebRtcVideoMediaChannel::SendIntraFrame() {
return success;
}
-bool WebRtcVideoMediaChannel::IsOneSsrcStream(const StreamParams& sp) {
- return (sp.ssrcs.size() == 1 && sp.ssrc_groups.size() == 0);
-}
-
bool WebRtcVideoMediaChannel::HasReadySendChannels() {
return !send_channels_.empty() &&
((send_channels_.size() > 1) ||
@@ -1994,18 +2119,6 @@ bool WebRtcVideoMediaChannel::GetSendChannelKey(uint32 local_ssrc,
}
WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
- VideoCapturer* video_capturer) {
- for (SendChannelMap::iterator iter = send_channels_.begin();
- iter != send_channels_.end(); ++iter) {
- WebRtcVideoChannelSendInfo* send_channel = iter->second;
- if (send_channel->video_capturer() == video_capturer) {
- return send_channel;
- }
- }
- return NULL;
-}
-
-WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
uint32 local_ssrc) {
uint32 key;
if (!GetSendChannelKey(local_ssrc, &key)) {
@@ -2034,6 +2147,18 @@ bool WebRtcVideoMediaChannel::CreateSendChannelKey(uint32 local_ssrc,
return true;
}
+int WebRtcVideoMediaChannel::GetSendChannelNum(VideoCapturer* capturer) {
+ int num = 0;
+ for (SendChannelMap::iterator iter = send_channels_.begin();
+ iter != send_channels_.end(); ++iter) {
+ WebRtcVideoChannelSendInfo* send_channel = iter->second;
+ if (send_channel->video_capturer() == capturer) {
+ ++num;
+ }
+ }
+ return num;
+}
+
uint32 WebRtcVideoMediaChannel::GetDefaultChannelSsrc() {
WebRtcVideoChannelSendInfo* send_channel = send_channels_[0];
const StreamParams* sp = send_channel->stream_params();
@@ -2049,11 +2174,8 @@ bool WebRtcVideoMediaChannel::DeleteSendChannel(uint32 ssrc_key) {
return false;
}
WebRtcVideoChannelSendInfo* send_channel = send_channels_[ssrc_key];
- VideoCapturer* capturer = send_channel->video_capturer();
- if (capturer != NULL) {
- capturer->SignalVideoFrame.disconnect(this);
- send_channel->set_video_capturer(NULL);
- }
+ MaybeDisconnectCapturer(send_channel->video_capturer());
+ send_channel->set_video_capturer(NULL);
int channel_id = send_channel->channel_id();
int capture_id = send_channel->capture_id();
@@ -2092,7 +2214,7 @@ bool WebRtcVideoMediaChannel::RemoveCapturer(uint32 ssrc) {
if (capturer == NULL) {
return false;
}
- capturer->SignalVideoFrame.disconnect(this);
+ MaybeDisconnectCapturer(capturer);
send_channel->set_video_capturer(NULL);
const int64 timestamp = send_channel->local_stream_info()->time_stamp();
if (send_codec_) {
@@ -2157,7 +2279,9 @@ bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) {
WebRtcLocalStreamInfo* channel_stream_info =
send_channel->local_stream_info();
- sinfo.ssrcs = send_params->ssrcs;
+ for (size_t i = 0; i < send_params->ssrcs.size(); ++i) {
+ sinfo.add_ssrc(send_params->ssrcs[i]);
+ }
sinfo.codec_name = send_codec_->plName;
sinfo.bytes_sent = bytes_sent;
sinfo.packets_sent = packets_sent;
@@ -2174,26 +2298,45 @@ bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) {
sinfo.nominal_bitrate = send_channel->encoder_observer()->bitrate();
sinfo.preferred_bitrate = send_max_bitrate_;
sinfo.adapt_reason = send_channel->CurrentAdaptReason();
+ sinfo.capture_jitter_ms = -1;
+ sinfo.avg_encode_ms = -1;
+ sinfo.encode_usage_percent = -1;
+ sinfo.capture_queue_delay_ms_per_s = -1;
+
+#ifdef USE_WEBRTC_DEV_BRANCH
+ int capture_jitter_ms = 0;
+ int avg_encode_time_ms = 0;
+ int encode_usage_percent = 0;
+ int capture_queue_delay_ms_per_s = 0;
+ if (engine()->vie()->base()->CpuOveruseMeasures(
+ channel_id,
+ &capture_jitter_ms,
+ &avg_encode_time_ms,
+ &encode_usage_percent,
+ &capture_queue_delay_ms_per_s) == 0) {
+ sinfo.capture_jitter_ms = capture_jitter_ms;
+ sinfo.avg_encode_ms = avg_encode_time_ms;
+ sinfo.encode_usage_percent = encode_usage_percent;
+ sinfo.capture_queue_delay_ms_per_s = capture_queue_delay_ms_per_s;
+ }
+#endif
- // Get received RTCP statistics for the sender, if available.
+ // Get received RTCP statistics for the sender (reported by the remote
+ // client in a RTCP packet), if available.
// It's not a fatal error if we can't, since RTCP may not have arrived
// yet.
- uint16 r_fraction_lost;
- unsigned int r_cumulative_lost;
- unsigned int r_extended_max;
- unsigned int r_jitter;
- int r_rtt_ms;
-
- if (engine_->vie()->rtp()->GetSentRTCPStatistics(
- channel_id,
- r_fraction_lost,
- r_cumulative_lost,
- r_extended_max,
- r_jitter, r_rtt_ms) == 0) {
+ webrtc::RtcpStatistics outgoing_stream_rtcp_stats;
+ int outgoing_stream_rtt_ms;
+
+ if (engine_->vie()->rtp()->GetSendChannelRtcpStatistics(
+ channel_id,
+ outgoing_stream_rtcp_stats,
+ outgoing_stream_rtt_ms) == 0) {
// Convert Q8 to float.
- sinfo.packets_lost = r_cumulative_lost;
- sinfo.fraction_lost = static_cast<float>(r_fraction_lost) / (1 << 8);
- sinfo.rtt_ms = r_rtt_ms;
+ sinfo.packets_lost = outgoing_stream_rtcp_stats.cumulative_lost;
+ sinfo.fraction_lost = static_cast<float>(
+ outgoing_stream_rtcp_stats.fraction_lost) / (1 << 8);
+ sinfo.rtt_ms = outgoing_stream_rtt_ms;
}
info->senders.push_back(sinfo);
@@ -2249,41 +2392,39 @@ bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) {
ssrc == 0)
continue;
- unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv;
- if (engine_->vie()->rtp()->GetRTPStatistics(
- channel->channel_id(), bytes_sent, packets_sent, bytes_recv,
- packets_recv) != 0) {
+ webrtc::StreamDataCounters sent;
+ webrtc::StreamDataCounters received;
+ if (engine_->vie()->rtp()->GetRtpStatistics(channel->channel_id(),
+ sent, received) != 0) {
LOG_RTCERR1(GetRTPStatistics, channel->channel_id());
return false;
}
VideoReceiverInfo rinfo;
- rinfo.ssrcs.push_back(ssrc);
- rinfo.bytes_rcvd = bytes_recv;
- rinfo.packets_rcvd = packets_recv;
+ rinfo.add_ssrc(ssrc);
+ rinfo.bytes_rcvd = received.bytes;
+ rinfo.packets_rcvd = received.packets;
rinfo.packets_lost = -1;
rinfo.packets_concealed = -1;
rinfo.fraction_lost = -1; // from SentRTCP
- rinfo.firs_sent = channel->decoder_observer()->firs_requested();
rinfo.nacks_sent = -1;
rinfo.frame_width = channel->render_adapter()->width();
rinfo.frame_height = channel->render_adapter()->height();
- rinfo.framerate_rcvd = channel->decoder_observer()->framerate();
int fps = channel->render_adapter()->framerate();
rinfo.framerate_decoded = fps;
rinfo.framerate_output = fps;
-
- // Get sent RTCP statistics.
- uint16 s_fraction_lost;
- unsigned int s_cumulative_lost;
- unsigned int s_extended_max;
- unsigned int s_jitter;
- int s_rtt_ms;
- if (engine_->vie()->rtp()->GetReceivedRTCPStatistics(channel->channel_id(),
- s_fraction_lost, s_cumulative_lost, s_extended_max,
- s_jitter, s_rtt_ms) == 0) {
+ channel->decoder_observer()->ExportTo(&rinfo);
+
+ // Get our locally created statistics of the received RTP stream.
+ webrtc::RtcpStatistics incoming_stream_rtcp_stats;
+ int incoming_stream_rtt_ms;
+ if (engine_->vie()->rtp()->GetReceiveChannelRtcpStatistics(
+ channel->channel_id(),
+ incoming_stream_rtcp_stats,
+ incoming_stream_rtt_ms) == 0) {
// Convert Q8 to float.
- rinfo.packets_lost = s_cumulative_lost;
- rinfo.fraction_lost = static_cast<float>(s_fraction_lost) / (1 << 8);
+ rinfo.packets_lost = incoming_stream_rtcp_stats.cumulative_lost;
+ rinfo.fraction_lost = static_cast<float>(
+ incoming_stream_rtcp_stats.fraction_lost) / (1 << 8);
}
info->receivers.push_back(rinfo);
@@ -2324,14 +2465,10 @@ bool WebRtcVideoMediaChannel::SetCapturer(uint32 ssrc,
return false;
}
VideoCapturer* old_capturer = send_channel->video_capturer();
- if (old_capturer) {
- old_capturer->SignalVideoFrame.disconnect(this);
- }
+ MaybeDisconnectCapturer(old_capturer);
send_channel->set_video_capturer(capturer);
- capturer->SignalVideoFrame.connect(
- this,
- &WebRtcVideoMediaChannel::AdaptAndSendFrame);
+ MaybeConnectCapturer(capturer);
if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) {
capturer->UpdateAspectRatio(ratio_w_, ratio_h_);
}
@@ -2348,7 +2485,8 @@ bool WebRtcVideoMediaChannel::RequestIntraFrame() {
return false;
}
-void WebRtcVideoMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
+void WebRtcVideoMediaChannel::OnPacketReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
// Pick which channel to send this packet to. If this packet doesn't match
// any multiplexed streams, just send it to the default channel. Otherwise,
// send it to the specific decoder instance for that stream.
@@ -2363,10 +2501,16 @@ void WebRtcVideoMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
engine()->vie()->network()->ReceivedRTPPacket(
which_channel,
packet->data(),
+#ifdef USE_WEBRTC_DEV_BRANCH
+ static_cast<int>(packet->length()),
+ webrtc::PacketTime(packet_time.timestamp, packet_time.not_before));
+#else
static_cast<int>(packet->length()));
+#endif
}
-void WebRtcVideoMediaChannel::OnRtcpReceived(talk_base::Buffer* packet) {
+void WebRtcVideoMediaChannel::OnRtcpReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
// Sending channels need all RTCP packets with feedback information.
// Even sender reports can contain attached report blocks.
// Receiving channels need sender reports in order to create
@@ -2496,7 +2640,7 @@ bool WebRtcVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) {
int max_bitrate;
if (autobw) {
// Use the default values for min bitrate.
- min_bitrate = kMinVideoBitrate;
+ min_bitrate = send_min_bitrate_;
// Use the default value or the bps for the max
max_bitrate = (bps <= 0) ? send_max_bitrate_ : (bps / 1000);
// Maximum start bitrate can be kStartVideoBitrate.
@@ -2537,6 +2681,12 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
bool cpu_overuse_detection_changed = options.cpu_overuse_detection.IsSet() &&
(options_.cpu_overuse_detection != options.cpu_overuse_detection);
+ bool dscp_option_changed = (options_.dscp != options.dscp);
+
+ bool suspend_below_min_bitrate_changed =
+ options.suspend_below_min_bitrate.IsSet() &&
+ (options_.suspend_below_min_bitrate != options.suspend_below_min_bitrate);
+
bool conference_mode_turned_off = false;
if (options_.conference_mode.IsSet() && options.conference_mode.IsSet() &&
options_.conference_mode.GetWithDefaultIfUnset(false) &&
@@ -2559,6 +2709,17 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
// Adjust send codec bitrate if needed.
int conf_max_bitrate = kDefaultConferenceModeMaxVideoBitrate;
+ // Save altered min_bitrate level and apply if necessary.
+ bool adjusted_min_bitrate = false;
+ if (options.lower_min_bitrate.IsSet()) {
+ bool lower;
+ options.lower_min_bitrate.Get(&lower);
+
+ int new_send_min_bitrate = lower ? kLowerMinBitrate : kMinVideoBitrate;
+ adjusted_min_bitrate = (new_send_min_bitrate != send_min_bitrate_);
+ send_min_bitrate_ = new_send_min_bitrate;
+ }
+
int expected_bitrate = send_max_bitrate_;
if (InConferenceMode()) {
expected_bitrate = conf_max_bitrate;
@@ -2570,7 +2731,8 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
}
if (send_codec_ &&
- (send_max_bitrate_ != expected_bitrate || denoiser_changed)) {
+ (send_max_bitrate_ != expected_bitrate || denoiser_changed ||
+ adjusted_min_bitrate)) {
// On success, SetSendCodec() will reset send_max_bitrate_ to
// expected_bitrate.
if (!SetSendCodec(*send_codec_,
@@ -2623,6 +2785,25 @@ bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
send_channel->SetCpuOveruseDetection(cpu_overuse_detection);
}
}
+ if (dscp_option_changed) {
+ talk_base::DiffServCodePoint dscp = talk_base::DSCP_DEFAULT;
+ if (options.dscp.GetWithDefaultIfUnset(false))
+ dscp = kVideoDscpValue;
+ if (MediaChannel::SetDscp(dscp) != 0) {
+ LOG(LS_WARNING) << "Failed to set DSCP settings for video channel";
+ }
+ }
+ if (suspend_below_min_bitrate_changed) {
+ if (options_.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)) {
+ for (SendChannelMap::iterator it = send_channels_.begin();
+ it != send_channels_.end(); ++it) {
+ engine()->vie()->codec()->SuspendBelowMinBitrate(
+ it->second->channel_id());
+ }
+ } else {
+ LOG(LS_WARNING) << "Cannot disable video suspension once it is enabled";
+ }
+ }
return true;
}
@@ -2677,39 +2858,23 @@ bool WebRtcVideoMediaChannel::GetRenderer(uint32 ssrc,
return true;
}
-void WebRtcVideoMediaChannel::AdaptAndSendFrame(VideoCapturer* capturer,
- const VideoFrame* frame) {
- if (capturer->IsScreencast()) {
- // Do not adapt frames that are screencast.
- SendFrame(capturer, frame);
- return;
- }
- // TODO(thorcarpenter): This is broken. One capturer registered on two ssrc
- // will not send any video to the second ssrc send channel. We should remove
- // GetSendChannel(capturer) and pass in an ssrc here.
- WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(capturer);
- if (!send_channel) {
- SendFrame(capturer, frame);
- return;
- }
- const VideoFrame* output_frame = NULL;
- send_channel->AdaptFrame(frame, &output_frame);
- if (output_frame) {
- SendFrame(send_channel, output_frame, capturer->IsScreencast());
- }
-}
-
-// TODO(zhurunz): Add unittests to test this function.
void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer,
const VideoFrame* frame) {
- // If there's send channel registers to the |capturer|, then only send the
- // frame to that channel and return. Otherwise send the frame to the default
- // channel, which currently taking frames from the engine.
- WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(capturer);
- if (send_channel) {
- SendFrame(send_channel, frame, capturer->IsScreencast());
+ // If the |capturer| is registered to any send channel, then send the frame
+ // to those send channels.
+ bool capturer_is_channel_owned = false;
+ for (SendChannelMap::iterator iter = send_channels_.begin();
+ iter != send_channels_.end(); ++iter) {
+ WebRtcVideoChannelSendInfo* send_channel = iter->second;
+ if (send_channel->video_capturer() == capturer) {
+ SendFrame(send_channel, frame, capturer->IsScreencast());
+ capturer_is_channel_owned = true;
+ }
+ }
+ if (capturer_is_channel_owned) {
return;
}
+
// TODO(hellner): Remove below for loop once the captured frame no longer
// come from the engine, i.e. the engine no longer owns a capturer.
for (SendChannelMap::iterator iter = send_channels_.begin();
@@ -3120,7 +3285,8 @@ bool WebRtcVideoMediaChannel::SetNackFec(int channel_id,
LOG_RTCERR1(SetNACKStatus, channel_id);
return false;
}
- LOG(LS_INFO) << "NACK enabled for channel " << channel_id;
+ std::string enabled = nack_enabled ? "enabled" : "disabled";
+ LOG(LS_INFO) << "NACK " << enabled << " for channel " << channel_id;
}
return true;
}
@@ -3217,6 +3383,15 @@ bool WebRtcVideoMediaChannel::SetSendCodec(
return false;
}
+ // NOTE: SetRtxSendPayloadType must be called after all simulcast SSRCs
+ // are configured. Otherwise ssrc's configured after this point will use
+ // the primary PT for RTX.
+ if (send_rtx_type_ != -1 &&
+ engine()->vie()->rtp()->SetRtxSendPayloadType(channel_id,
+ send_rtx_type_) != 0) {
+ LOG_RTCERR2(SetRtxSendPayloadType, channel_id, send_rtx_type_);
+ return false;
+ }
}
send_channel->set_interval(
cricket::VideoFormat::FpsToInterval(target_codec.maxFramerate));
@@ -3292,6 +3467,9 @@ void WebRtcVideoMediaChannel::LogSendCodecChange(const std::string& reason) {
<< vie_codec.codecSpecific.VP8.keyFrameInterval;
}
+ if (send_rtx_type_ != -1) {
+ LOG(LS_INFO) << "RTX payload type: " << send_rtx_type_;
+ }
}
bool WebRtcVideoMediaChannel::SetReceiveCodecs(
@@ -3556,6 +3734,35 @@ bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
header_extension_uri);
return SetHeaderExtension(setter, channel_id, extension);
}
+
+bool WebRtcVideoMediaChannel::SetLocalRtxSsrc(int channel_id,
+ const StreamParams& send_params,
+ uint32 primary_ssrc,
+ int stream_idx) {
+ uint32 rtx_ssrc = 0;
+ bool has_rtx = send_params.GetFidSsrc(primary_ssrc, &rtx_ssrc);
+ if (has_rtx && engine()->vie()->rtp()->SetLocalSSRC(
+ channel_id, rtx_ssrc, webrtc::kViEStreamTypeRtx, stream_idx) != 0) {
+ LOG_RTCERR4(SetLocalSSRC, channel_id, rtx_ssrc,
+ webrtc::kViEStreamTypeRtx, stream_idx);
+ return false;
+ }
+ return true;
+}
+
+void WebRtcVideoMediaChannel::MaybeConnectCapturer(VideoCapturer* capturer) {
+ if (capturer != NULL && GetSendChannelNum(capturer) == 1) {
+ capturer->SignalVideoFrame.connect(this,
+ &WebRtcVideoMediaChannel::SendFrame);
+ }
+}
+
+void WebRtcVideoMediaChannel::MaybeDisconnectCapturer(VideoCapturer* capturer) {
+ if (capturer != NULL && GetSendChannelNum(capturer) == 1) {
+ capturer->SignalVideoFrame.disconnect(this);
+ }
+}
+
} // namespace cricket
#endif // HAVE_WEBRTC_VIDEO
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.h b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.h
index f0293bb5d41..289903a0722 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine.h
@@ -104,8 +104,9 @@ class WebRtcVideoEngine : public sigslot::has_slots<>,
void Terminate();
int GetCapabilities();
- bool SetOptions(int options);
+ bool SetOptions(const VideoOptions &options);
bool SetDefaultEncoderConfig(const VideoEncoderConfig& config);
+ VideoEncoderConfig GetDefaultEncoderConfig() const;
WebRtcVideoMediaChannel* CreateChannel(VoiceMediaChannel* voice_channel);
@@ -179,6 +180,9 @@ class WebRtcVideoEngine : public sigslot::has_slots<>,
struct VideoCodecPref {
const char* name;
int payload_type;
+ // For RTX, this field is the payload-type that RTX applies to.
+ // For other codecs, it should be set to -1.
+ int associated_payload_type;
int pref;
};
@@ -262,8 +266,10 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
virtual bool SendIntraFrame();
virtual bool RequestIntraFrame();
- virtual void OnPacketReceived(talk_base::Buffer* packet);
- virtual void OnRtcpReceived(talk_base::Buffer* packet);
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
virtual void OnReadyToSend(bool ready);
virtual bool MuteStream(uint32 ssrc, bool on);
virtual bool SetRecvRtpHeaderExtensions(
@@ -286,8 +292,6 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
bool SendFrame(WebRtcVideoChannelSendInfo* channel_info,
const VideoFrame* frame, bool is_screencast);
- void AdaptAndSendFrame(VideoCapturer* capturer, const VideoFrame* frame);
-
// Thunk functions for use with HybridVideoEngine
void OnLocalFrame(VideoCapturer* capturer, const VideoFrame* frame) {
SendFrame(0u, frame, capturer->IsScreencast());
@@ -355,9 +359,6 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
bool StopSend(WebRtcVideoChannelSendInfo* send_channel);
bool SendIntraFrame(int channel_id);
- // Send with one local SSRC. Normal case.
- bool IsOneSsrcStream(const StreamParams& sp);
-
bool HasReadySendChannels();
// Send channel key returns the key corresponding to the provided local SSRC
@@ -365,11 +366,12 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
// If the local ssrc correspond to that of the default channel the key is 0.
// For all other channels the returned key will be the same as the local ssrc.
bool GetSendChannelKey(uint32 local_ssrc, uint32* key);
- WebRtcVideoChannelSendInfo* GetSendChannel(VideoCapturer* video_capturer);
WebRtcVideoChannelSendInfo* GetSendChannel(uint32 local_ssrc);
// Creates a new unique key that can be used for inserting a new send channel
// into |send_channels_|
bool CreateSendChannelKey(uint32 local_ssrc, uint32* key);
+ // Get the number of the send channels |capturer| registered with.
+ int GetSendChannelNum(VideoCapturer* capturer);
bool IsDefaultChannel(int channel_id) const {
return channel_id == vie_channel_;
@@ -399,6 +401,17 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
// Signal when cpu adaptation has no further scope to adapt.
void OnCpuAdaptationUnable();
+ // Set the local (send-side) RTX SSRC corresponding to primary_ssrc.
+ bool SetLocalRtxSsrc(int channel_id, const StreamParams& send_params,
+ uint32 primary_ssrc, int stream_idx);
+
+ // Connect |capturer| to WebRtcVideoMediaChannel if it is only registered
+ // to one send channel, i.e. the first send channel.
+ void MaybeConnectCapturer(VideoCapturer* capturer);
+ // Disconnect |capturer| from WebRtcVideoMediaChannel if it is only registered
+ // to one send channel, i.e. the last send channel.
+ void MaybeDisconnectCapturer(VideoCapturer* capturer);
+
// Global state.
WebRtcVideoEngine* engine_;
VoiceMediaChannel* voice_channel_;
@@ -422,6 +435,7 @@ class WebRtcVideoMediaChannel : public talk_base::MessageHandler,
// Global send side state.
SendChannelMap send_channels_;
talk_base::scoped_ptr<webrtc::VideoCodec> send_codec_;
+ int send_rtx_type_;
int send_red_type_;
int send_fec_type_;
int send_min_bitrate_;
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine_unittest.cc b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine_unittest.cc
index 04662caf7c1..d5886a13822 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoengine_unittest.cc
@@ -69,6 +69,12 @@ static const unsigned int kMaxBandwidthKbps = 2000;
static const unsigned int kNumberOfTemporalLayers = 1;
+static const uint32 kSsrcs1[] = {1};
+static const uint32 kSsrcs2[] = {1, 2};
+static const uint32 kSsrcs3[] = {1, 2, 3};
+static const uint32 kRtxSsrc1[] = {4};
+static const uint32 kRtxSsrcs3[] = {4, 5, 6};
+
class FakeViEWrapper : public cricket::ViEWrapper {
public:
@@ -117,11 +123,7 @@ class WebRtcVideoEngineTestFake : public testing::Test,
return false;
}
cricket::WebRtcVideoFrame frame;
- size_t size = width * height * 3 / 2; // I420
- talk_base::scoped_array<uint8> pixel(new uint8[size]);
- if (!frame.Init(cricket::FOURCC_I420,
- width, height, width, height,
- pixel.get(), size, 1, 1, 0, 0, 0)) {
+ if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) {
return false;
}
cricket::FakeVideoCapturer capturer;
@@ -137,11 +139,7 @@ class WebRtcVideoEngineTestFake : public testing::Test,
return false;
}
cricket::WebRtcVideoFrame frame;
- size_t size = width * height * 3 / 2; // I420
- talk_base::scoped_array<uint8> pixel(new uint8[size]);
- if (!frame.Init(cricket::FOURCC_I420,
- width, height, width, height,
- pixel.get(), size, 1, 1, 0, timestamp, 0)) {
+ if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) {
return false;
}
cricket::FakeVideoCapturer capturer;
@@ -380,6 +378,25 @@ TEST_F(WebRtcVideoEngineTestFake, SetOptionsWithMaxBitrate) {
channel_num, kVP8Codec.width, kVP8Codec.height, 0, 20, 10, 20);
}
+TEST_F(WebRtcVideoEngineTestFake, SetOptionsWithLoweredBitrate) {
+ EXPECT_TRUE(SetupEngine());
+ int channel_num = vie_.GetLastChannel();
+ std::vector<cricket::VideoCodec> codecs(engine_.codecs());
+ codecs[0].params[cricket::kCodecParamMinBitrate] = "50";
+ codecs[0].params[cricket::kCodecParamMaxBitrate] = "100";
+ EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+ VerifyVP8SendCodec(
+ channel_num, kVP8Codec.width, kVP8Codec.height, 0, 100, 50, 100);
+
+ // Verify that min bitrate changes after SetOptions().
+ cricket::VideoOptions options;
+ options.lower_min_bitrate.Set(true);
+ EXPECT_TRUE(channel_->SetOptions(options));
+ VerifyVP8SendCodec(
+ channel_num, kVP8Codec.width, kVP8Codec.height, 0, 100, 30, 100);
+}
+
TEST_F(WebRtcVideoEngineTestFake, MaxBitrateResetWithConferenceMode) {
EXPECT_TRUE(SetupEngine());
int channel_num = vie_.GetLastChannel();
@@ -637,6 +654,45 @@ TEST_F(WebRtcVideoEngineTestFake, RembEnabledOnReceiveChannels) {
EXPECT_TRUE(vie_.GetRembStatusContribute(new_channel_num));
}
+TEST_F(WebRtcVideoEngineTestFake, RecvStreamWithRtx) {
+ EXPECT_TRUE(SetupEngine());
+ int default_channel = vie_.GetLastChannel();
+ cricket::VideoOptions options;
+ options.conference_mode.Set(true);
+ EXPECT_TRUE(channel_->SetOptions(options));
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::CreateSimWithRtxStreamParams("cname",
+ MAKE_VECTOR(kSsrcs3),
+ MAKE_VECTOR(kRtxSsrcs3))));
+ EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
+ EXPECT_TRUE(channel_->SetSend(true));
+ EXPECT_TRUE(channel_->AddRecvStream(
+ cricket::CreateSimWithRtxStreamParams("cname",
+ MAKE_VECTOR(kSsrcs1),
+ MAKE_VECTOR(kRtxSsrc1))));
+ int new_channel_num = vie_.GetLastChannel();
+ EXPECT_NE(default_channel, new_channel_num);
+ EXPECT_EQ(4, vie_.GetRemoteRtxSsrc(new_channel_num));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, RecvStreamNoRtx) {
+ EXPECT_TRUE(SetupEngine());
+ int default_channel = vie_.GetLastChannel();
+ cricket::VideoOptions options;
+ options.conference_mode.Set(true);
+ EXPECT_TRUE(channel_->SetOptions(options));
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::CreateSimWithRtxStreamParams("cname",
+ MAKE_VECTOR(kSsrcs3),
+ MAKE_VECTOR(kRtxSsrcs3))));
+ EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
+ EXPECT_TRUE(channel_->SetSend(true));
+ EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+ int new_channel_num = vie_.GetLastChannel();
+ EXPECT_NE(default_channel, new_channel_num);
+ EXPECT_EQ(-1, vie_.GetRemoteRtxSsrc(new_channel_num));
+}
+
// Test support for RTP timestamp offset header extension.
TEST_F(WebRtcVideoEngineTestFake, RtpTimestampOffsetHeaderExtensions) {
EXPECT_TRUE(SetupEngine());
@@ -1160,8 +1216,56 @@ TEST_F(WebRtcVideoEngineTestFake, SetOptionsWithDenoising) {
EXPECT_FALSE(vie_.GetCaptureDenoising(capture_id));
}
+TEST_F(WebRtcVideoEngineTestFake, MultipleSendStreamsWithOneCapturer) {
+ EXPECT_TRUE(SetupEngine());
+
+ // Start the capturer
+ cricket::FakeVideoCapturer capturer;
+ cricket::VideoFormat capture_format_vga = cricket::VideoFormat(640, 480,
+ cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420);
+ EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_vga));
+
+ // Add send streams and connect the capturer
+ for (unsigned int i = 0; i < sizeof(kSsrcs2)/sizeof(kSsrcs2[0]); ++i) {
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrcs2[i])));
+ // Register the capturer to the ssrc.
+ EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[i], &capturer));
+ }
+
+ const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs2[0]);
+ ASSERT_NE(-1, channel0);
+ const int channel1 = vie_.GetChannelFromLocalSsrc(kSsrcs2[1]);
+ ASSERT_NE(-1, channel1);
+ ASSERT_NE(channel0, channel1);
+
+ // Set send codec.
+ std::vector<cricket::VideoCodec> codecs;
+ cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0);
+ codecs.push_back(send_codec);
+ EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+ EXPECT_TRUE(capturer.CaptureFrame());
+ EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel0));
+ EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel1));
+
+ EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs2[0]));
+ EXPECT_TRUE(capturer.CaptureFrame());
+ // channel0 is the default channel, so it won't be deleted.
+ // But it should be disconnected from the capturer.
+ EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel0));
+ EXPECT_EQ(2, vie_.GetIncomingFrameNum(channel1));
+
+ EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs2[1]));
+ EXPECT_TRUE(capturer.CaptureFrame());
+ EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel0));
+ // channel1 has already been deleted.
+ EXPECT_EQ(-1, vie_.GetIncomingFrameNum(channel1));
+}
+
-TEST_F(WebRtcVideoEngineTestFake, SendReceiveBitratesStats) {
+// Disabled since its flaky: b/11288120
+TEST_F(WebRtcVideoEngineTestFake, DISABLED_SendReceiveBitratesStats) {
EXPECT_TRUE(SetupEngine());
cricket::VideoOptions options;
options.conference_mode.Set(true);
@@ -1299,7 +1403,7 @@ TEST_F(WebRtcVideoEngineTestFake, TestSetInvalidCpuThreshold) {
TEST_F(WebRtcVideoEngineTest, FindCodec) {
// We should not need to init engine in order to get codecs.
const std::vector<cricket::VideoCodec>& c = engine_.codecs();
- EXPECT_EQ(3U, c.size());
+ EXPECT_EQ(4U, c.size());
cricket::VideoCodec vp8(104, "VP8", 320, 200, 30, 0);
EXPECT_TRUE(engine_.FindCodec(vp8));
@@ -1334,6 +1438,24 @@ TEST_F(WebRtcVideoEngineTest, FindCodec) {
cricket::VideoCodec fec_ci(102, "ulpfec", 0, 0, 30, 0);
EXPECT_TRUE(engine_.FindCodec(fec));
+
+ cricket::VideoCodec rtx(96, "rtx", 0, 0, 30, 0);
+ EXPECT_TRUE(engine_.FindCodec(rtx));
+}
+
+TEST_F(WebRtcVideoEngineTest, RtxCodecHasAptSet) {
+ std::vector<cricket::VideoCodec>::const_iterator it;
+ bool apt_checked = false;
+ for (it = engine_.codecs().begin(); it != engine_.codecs().end(); ++it) {
+ if (_stricmp(cricket::kRtxCodecName, it->name.c_str()) && it->id != 96) {
+ continue;
+ }
+ int apt;
+ EXPECT_TRUE(it->GetParam("apt", &apt));
+ EXPECT_EQ(100, apt);
+ apt_checked = true;
+ }
+ EXPECT_TRUE(apt_checked);
}
TEST_F(WebRtcVideoEngineTest, StartupShutdown) {
@@ -1488,6 +1610,21 @@ TEST_F(WebRtcVideoMediaChannelTest, AddRemoveCapturerMultipleSources) {
Base::AddRemoveCapturerMultipleSources();
}
+// This test verifies DSCP settings are properly applied on video media channel.
+TEST_F(WebRtcVideoMediaChannelTest, TestSetDscpOptions) {
+ talk_base::scoped_ptr<cricket::FakeNetworkInterface> network_interface(
+ new cricket::FakeNetworkInterface);
+ channel_->SetInterface(network_interface.get());
+ cricket::VideoOptions options;
+ options.dscp.Set(true);
+ EXPECT_TRUE(channel_->SetOptions(options));
+ EXPECT_EQ(talk_base::DSCP_AF41, network_interface->dscp());
+ options.dscp.Set(false);
+ EXPECT_TRUE(channel_->SetOptions(options));
+ EXPECT_EQ(talk_base::DSCP_DEFAULT, network_interface->dscp());
+ channel_->SetInterface(NULL);
+}
+
TEST_F(WebRtcVideoMediaChannelTest, SetOptionsSucceedsWhenSending) {
cricket::VideoOptions options;
@@ -1672,8 +1809,14 @@ TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderIfFactoryIsGiven) {
codecs.push_back(kVP8Codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrc)));
+
EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+
+ // Remove stream previously added to free the external encoder instance.
+ EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
}
TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderMultipleTimes) {
@@ -1686,6 +1829,9 @@ TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderMultipleTimes) {
codecs.push_back(kVP8Codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrc)));
+
EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
@@ -1693,6 +1839,9 @@ TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderMultipleTimes) {
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+ // Remove stream previously added to free the external encoder instance.
+ EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
}
TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderWithMultipleSendStreams) {
@@ -1785,8 +1934,12 @@ TEST_F(WebRtcVideoEngineTestFake, ExternalCodecAddedToTheEnd) {
encoder_factory_.NotifyCodecsAvailable();
codecs = engine_.codecs();
+ cricket::VideoCodec internal_codec = codecs[0];
+ cricket::VideoCodec external_codec = codecs[codecs.size() - 1];
// The external codec will appear at last.
- EXPECT_EQ("GENERIC", codecs[codecs.size() - 1].name);
+ EXPECT_EQ("GENERIC", external_codec.name);
+ // The internal codec is preferred.
+ EXPECT_GE(internal_codec.preference, external_codec.preference);
}
// Test that external codec with be ignored if it has the same name as one of
@@ -1820,9 +1973,15 @@ TEST_F(WebRtcVideoEngineTestFake, UpdateEncoderCodecsAfterSetFactory) {
codecs.push_back(kVP8Codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrc)));
+
EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+ // Remove stream previously added to free the external encoder instance.
+ EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
}
// Tests that OnReadyToSend will be propagated into ViE.
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.cc b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.cc
index 584aac0c3f3..16aa4cdcebc 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.cc
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.cc
@@ -42,49 +42,74 @@ static const int kWatermarkOffsetFromLeft = 8;
static const int kWatermarkOffsetFromBottom = 8;
static const unsigned char kWatermarkMaxYValue = 64;
-FrameBuffer::FrameBuffer() : length_(0) {}
-
-FrameBuffer::FrameBuffer(size_t length) : length_(0) {
- char* buffer = new char[length];
- SetData(buffer, length);
+// Class that wraps ownerhip semantics of a buffer passed to it.
+// * Buffers passed using Attach() become owned by this FrameBuffer and will be
+// destroyed on FrameBuffer destruction.
+// * Buffers passed using Alias() are not owned and will not be destroyed on
+// FrameBuffer destruction, The buffer then must outlive the FrameBuffer.
+class WebRtcVideoFrame::FrameBuffer {
+ public:
+ FrameBuffer();
+ explicit FrameBuffer(size_t length);
+ ~FrameBuffer();
+
+ void Attach(uint8* data, size_t length);
+ void Alias(uint8* data, size_t length);
+ uint8* data();
+ size_t length() const;
+
+ webrtc::VideoFrame* frame();
+ const webrtc::VideoFrame* frame() const;
+
+ private:
+ talk_base::scoped_ptr<uint8[]> owned_data_;
+ webrtc::VideoFrame video_frame_;
+};
+
+WebRtcVideoFrame::FrameBuffer::FrameBuffer() {}
+
+WebRtcVideoFrame::FrameBuffer::FrameBuffer(size_t length) {
+ uint8* buffer = new uint8[length];
+ Attach(buffer, length);
}
-FrameBuffer::~FrameBuffer() {
- // Make sure that the video_frame_ doesn't delete the buffer as it may be
- // shared between multiple WebRtcVideoFrame.
+WebRtcVideoFrame::FrameBuffer::~FrameBuffer() {
+ // Make sure that |video_frame_| doesn't delete the buffer, as |owned_data_|
+ // will release the buffer if this FrameBuffer owns it.
uint8_t* new_memory = NULL;
uint32_t new_length = 0;
uint32_t new_size = 0;
video_frame_.Swap(new_memory, new_length, new_size);
}
-void FrameBuffer::SetData(char* data, size_t length) {
- data_.reset(data);
- length_ = length;
+void WebRtcVideoFrame::FrameBuffer::Attach(uint8* data, size_t length) {
+ Alias(data, length);
+ owned_data_.reset(data);
+}
+
+void WebRtcVideoFrame::FrameBuffer::Alias(uint8* data, size_t length) {
+ owned_data_.reset();
uint8_t* new_memory = reinterpret_cast<uint8_t*>(data);
- uint32_t new_length = static_cast<int>(length);
- uint32_t new_size = static_cast<int>(length);
+ uint32_t new_length = static_cast<uint32_t>(length);
+ uint32_t new_size = static_cast<uint32_t>(length);
video_frame_.Swap(new_memory, new_length, new_size);
}
-void FrameBuffer::ReturnData(char** data, size_t* length) {
- uint8_t* old_memory = NULL;
- uint32_t old_length = 0;
- uint32_t old_size = 0;
- video_frame_.Swap(old_memory, old_length, old_size);
- data_.release();
- length_ = 0;
- *length = old_length;
- *data = reinterpret_cast<char*>(old_memory);
+uint8* WebRtcVideoFrame::FrameBuffer::data() {
+ return video_frame_.Buffer();
}
-char* FrameBuffer::data() { return data_.get(); }
-
-size_t FrameBuffer::length() const { return length_; }
+size_t WebRtcVideoFrame::FrameBuffer::length() const {
+ return video_frame_.Length();
+}
-webrtc::VideoFrame* FrameBuffer::frame() { return &video_frame_; }
+webrtc::VideoFrame* WebRtcVideoFrame::FrameBuffer::frame() {
+ return &video_frame_;
+}
-const webrtc::VideoFrame* FrameBuffer::frame() const { return &video_frame_; }
+const webrtc::VideoFrame* WebRtcVideoFrame::FrameBuffer::frame() const {
+ return &video_frame_;
+}
WebRtcVideoFrame::WebRtcVideoFrame()
: video_buffer_(new RefCountedBuffer()), is_black_(false) {}
@@ -106,6 +131,25 @@ bool WebRtcVideoFrame::Init(const CapturedFrame* frame, int dw, int dh) {
frame->time_stamp, frame->rotation);
}
+bool WebRtcVideoFrame::Alias(const CapturedFrame* frame, int dw, int dh) {
+ if (CanonicalFourCC(frame->fourcc) != FOURCC_I420 || frame->rotation != 0 ||
+ frame->width != dw || frame->height != dh) {
+ // TODO(fbarchard): Enable aliasing of more formats.
+ return Init(frame, dw, dh);
+ } else {
+ Alias(static_cast<uint8*>(frame->data),
+ frame->data_size,
+ frame->width,
+ frame->height,
+ frame->pixel_width,
+ frame->pixel_height,
+ frame->elapsed_time,
+ frame->time_stamp,
+ frame->rotation);
+ return true;
+ }
+}
+
bool WebRtcVideoFrame::InitToBlack(int w, int h, size_t pixel_width,
size_t pixel_height, int64 elapsed_time,
int64 time_stamp) {
@@ -116,20 +160,16 @@ bool WebRtcVideoFrame::InitToBlack(int w, int h, size_t pixel_width,
return true;
}
-void WebRtcVideoFrame::Attach(
+void WebRtcVideoFrame::Alias(
uint8* buffer, size_t buffer_size, int w, int h, size_t pixel_width,
size_t pixel_height, int64 elapsed_time, int64 time_stamp, int rotation) {
talk_base::scoped_refptr<RefCountedBuffer> video_buffer(
new RefCountedBuffer());
- video_buffer->SetData(reinterpret_cast<char*>(buffer), buffer_size);
+ video_buffer->Alias(buffer, buffer_size);
Attach(video_buffer.get(), buffer_size, w, h, pixel_width, pixel_height,
elapsed_time, time_stamp, rotation);
}
-void WebRtcVideoFrame::Detach(uint8** data, size_t* length) {
- video_buffer_->ReturnData(reinterpret_cast<char**>(data), length);
-}
-
size_t WebRtcVideoFrame::GetWidth() const { return frame()->Width(); }
size_t WebRtcVideoFrame::GetHeight() const { return frame()->Height(); }
@@ -179,7 +219,7 @@ uint8* WebRtcVideoFrame::GetVPlane() {
}
VideoFrame* WebRtcVideoFrame::Copy() const {
- const char* old_buffer = video_buffer_->data();
+ uint8* old_buffer = video_buffer_->data();
if (!old_buffer)
return NULL;
size_t new_buffer_size = video_buffer_->length();
@@ -192,7 +232,7 @@ VideoFrame* WebRtcVideoFrame::Copy() const {
}
bool WebRtcVideoFrame::MakeExclusive() {
- const int length = static_cast<int>(video_buffer_->length());
+ const size_t length = video_buffer_->length();
RefCountedBuffer* exclusive_buffer = new RefCountedBuffer(length);
memcpy(exclusive_buffer->data(), video_buffer_->data(), length);
Attach(exclusive_buffer, length, frame()->Width(), frame()->Height(),
@@ -279,6 +319,14 @@ bool WebRtcVideoFrame::AddWatermark() {
return true;
}
+webrtc::VideoFrame* WebRtcVideoFrame::frame() {
+ return video_buffer_->frame();
+}
+
+const webrtc::VideoFrame* WebRtcVideoFrame::frame() const {
+ return video_buffer_->frame();
+}
+
bool WebRtcVideoFrame::Reset(
uint32 format, int w, int h, int dw, int dh, uint8* sample,
size_t sample_size, size_t pixel_width, size_t pixel_height,
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h
index 18475a69775..8191a58d875 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h
@@ -39,31 +39,8 @@ namespace cricket {
struct CapturedFrame;
-// Class that takes ownership of the frame passed to it.
-class FrameBuffer {
- public:
- FrameBuffer();
- explicit FrameBuffer(size_t length);
- ~FrameBuffer();
-
- void SetData(char* data, size_t length);
- void ReturnData(char** data, size_t* length);
- char* data();
- size_t length() const;
-
- webrtc::VideoFrame* frame();
- const webrtc::VideoFrame* frame() const;
-
- private:
- talk_base::scoped_array<char> data_;
- size_t length_;
- webrtc::VideoFrame video_frame_;
-};
-
class WebRtcVideoFrame : public VideoFrame {
public:
- typedef talk_base::RefCountedObject<FrameBuffer> RefCountedBuffer;
-
WebRtcVideoFrame();
~WebRtcVideoFrame();
@@ -77,17 +54,22 @@ class WebRtcVideoFrame : public VideoFrame {
bool Init(const CapturedFrame* frame, int dw, int dh);
+ // Aliases this WebRtcVideoFrame to a CapturedFrame. |frame| must outlive
+ // this WebRtcVideoFrame.
+ bool Alias(const CapturedFrame* frame, int dw, int dh);
+
bool InitToBlack(int w, int h, size_t pixel_width, size_t pixel_height,
int64 elapsed_time, int64 time_stamp);
- void Attach(uint8* buffer, size_t buffer_size, int w, int h,
- size_t pixel_width, size_t pixel_height, int64 elapsed_time,
- int64 time_stamp, int rotation);
+ // Aliases this WebRtcVideoFrame to a memory buffer. |buffer| must outlive
+ // this WebRtcVideoFrame.
+ void Alias(uint8* buffer, size_t buffer_size, int w, int h,
+ size_t pixel_width, size_t pixel_height, int64 elapsed_time,
+ int64 time_stamp, int rotation);
- void Detach(uint8** data, size_t* length);
bool AddWatermark();
- webrtc::VideoFrame* frame() { return video_buffer_->frame(); }
- webrtc::VideoFrame* frame() const { return video_buffer_->frame(); }
+ webrtc::VideoFrame* frame();
+ const webrtc::VideoFrame* frame() const;
// From base class VideoFrame.
virtual bool Reset(uint32 format, int w, int h, int dw, int dh, uint8* sample,
@@ -126,6 +108,9 @@ class WebRtcVideoFrame : public VideoFrame {
size_t size, int stride_rgb) const;
private:
+ class FrameBuffer;
+ typedef talk_base::RefCountedObject<FrameBuffer> RefCountedBuffer;
+
void Attach(RefCountedBuffer* video_buffer, size_t buffer_size, int w, int h,
size_t pixel_width, size_t pixel_height, int64 elapsed_time,
int64 time_stamp, int rotation);
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe_unittest.cc b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe_unittest.cc
index 2f0decb2898..e63c5d5e561 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe_unittest.cc
@@ -53,7 +53,7 @@ class WebRtcVideoFrameTest : public VideoFrameTest<cricket::WebRtcVideoFrame> {
captured_frame.height = frame_height;
captured_frame.data_size = (frame_width * frame_height) +
((frame_width + 1) / 2) * ((frame_height + 1) / 2) * 2;
- talk_base::scoped_array<uint8> captured_frame_buffer(
+ talk_base::scoped_ptr<uint8[]> captured_frame_buffer(
new uint8[captured_frame.data_size]);
captured_frame.data = captured_frame_buffer.get();
@@ -264,35 +264,16 @@ TEST_WEBRTCVIDEOFRAME(CopyIsRef)
TEST_WEBRTCVIDEOFRAME(MakeExclusive)
// These functions test implementation-specific details.
-TEST_F(WebRtcVideoFrameTest, AttachAndRelease) {
+TEST_F(WebRtcVideoFrameTest, Alias) {
cricket::WebRtcVideoFrame frame1, frame2;
ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
- const int64 time_stamp = 0x7FFFFFFFFFFFFFF0LL;
+ const int64 time_stamp = INT64_C(0x7FFFFFFFFFFFFFF0);
frame1.SetTimeStamp(time_stamp);
EXPECT_EQ(time_stamp, frame1.GetTimeStamp());
- frame2.Attach(frame1.frame()->Buffer(), frame1.frame()->Size(),
- kWidth, kHeight, 1, 1,
- frame1.GetElapsedTime(), frame1.GetTimeStamp(), 0);
+ frame2.Alias(frame1.frame()->Buffer(), frame1.frame()->Size(),
+ kWidth, kHeight, 1, 1,
+ frame1.GetElapsedTime(), frame1.GetTimeStamp(), 0);
EXPECT_TRUE(IsEqual(frame1, frame2, 0));
- uint8* buffer;
- size_t size;
- frame2.Detach(&buffer, &size);
- EXPECT_EQ(frame1.frame()->Buffer(), buffer);
- EXPECT_EQ(frame1.frame()->Size(), size);
- EXPECT_TRUE(IsNull(frame2));
- EXPECT_TRUE(IsSize(frame1, kWidth, kHeight));
-}
-
-TEST_F(WebRtcVideoFrameTest, Transfer) {
- cricket::WebRtcVideoFrame frame1, frame2;
- ASSERT_TRUE(LoadFrameNoRepeat(&frame1));
- uint8* buffer;
- size_t size;
- frame1.Detach(&buffer, &size);
- frame2.Attach(buffer, size, kWidth, kHeight, 1, 1,
- frame1.GetElapsedTime(), frame1.GetTimeStamp(), 0);
- EXPECT_TRUE(IsNull(frame1));
- EXPECT_TRUE(IsSize(frame2, kWidth, kHeight));
}
// Tests the Init function with different cropped size.
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.cc b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.cc
index 86860389314..3bdc4039c85 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.cc
@@ -50,6 +50,7 @@
#include "talk/media/base/streamparams.h"
#include "talk/media/base/voiceprocessor.h"
#include "talk/media/webrtc/webrtcvoe.h"
+#include "webrtc/common.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#ifdef WIN32
@@ -124,6 +125,10 @@ static const int kOpusStereoBitrate = 64000;
// Opus bitrate should be in the range between 6000 and 510000.
static const int kOpusMinBitrate = 6000;
static const int kOpusMaxBitrate = 510000;
+// Default audio dscp value.
+// See http://tools.ietf.org/html/rfc2474 for details.
+// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
+static const talk_base::DiffServCodePoint kAudioDscpValue = talk_base::DSCP_EF;
// Ensure we open the file in a writeable path on ChromeOS and Android. This
// workaround can be removed when it's possible to specify a filename for audio
@@ -203,11 +208,31 @@ static bool FindCodec(const std::vector<AudioCodec>& codecs,
}
return false;
}
+
static bool IsNackEnabled(const AudioCodec& codec) {
return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack,
kParamValueEmpty));
}
+// Gets the default set of options applied to the engine. Historically, these
+// were supplied as a combination of flags from the channel manager (ec, agc,
+// ns, and highpass) and the rest hardcoded in InitInternal.
+static AudioOptions GetDefaultEngineOptions() {
+ AudioOptions options;
+ options.echo_cancellation.Set(true);
+ options.auto_gain_control.Set(true);
+ options.noise_suppression.Set(true);
+ options.highpass_filter.Set(true);
+ options.stereo_swapping.Set(false);
+ options.typing_detection.Set(true);
+ options.conference_mode.Set(false);
+ options.adjust_agc_delta.Set(0);
+ options.experimental_agc.Set(false);
+ options.experimental_aec.Set(false);
+ options.aec_dump.Set(false);
+ options.experimental_acm.Set(false);
+ return options;
+}
class WebRtcSoundclipMedia : public SoundclipMedia {
public:
@@ -233,7 +258,10 @@ class WebRtcSoundclipMedia : public SoundclipMedia {
}
bool Init() {
- webrtc_channel_ = engine_->voe_sc()->base()->CreateChannel();
+ if (!engine_->voe_sc()) {
+ return false;
+ }
+ webrtc_channel_ = engine_->CreateSoundclipVoiceChannel();
if (webrtc_channel_ == -1) {
LOG_RTCERR0(CreateChannel);
return false;
@@ -299,12 +327,14 @@ class WebRtcSoundclipMedia : public SoundclipMedia {
WebRtcVoiceEngine::WebRtcVoiceEngine()
: voe_wrapper_(new VoEWrapper()),
voe_wrapper_sc_(new VoEWrapper()),
+ voe_wrapper_sc_initialized_(false),
tracing_(new VoETraceWrapper()),
adm_(NULL),
adm_sc_(NULL),
log_filter_(SeverityToFilter(kDefaultLogSeverity)),
is_dumping_aec_(false),
desired_local_monitor_enable_(false),
+ use_experimental_acm_(false),
tx_processor_ssrc_(0),
rx_processor_ssrc_(0) {
Construct();
@@ -315,12 +345,14 @@ WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper,
VoETraceWrapper* tracing)
: voe_wrapper_(voe_wrapper),
voe_wrapper_sc_(voe_wrapper_sc),
+ voe_wrapper_sc_initialized_(false),
tracing_(tracing),
adm_(NULL),
adm_sc_(NULL),
log_filter_(SeverityToFilter(kDefaultLogSeverity)),
is_dumping_aec_(false),
desired_local_monitor_enable_(false),
+ use_experimental_acm_(false),
tx_processor_ssrc_(0),
rx_processor_ssrc_(0) {
Construct();
@@ -347,6 +379,11 @@ void WebRtcVoiceEngine::Construct() {
rtp_header_extensions_.push_back(
RtpHeaderExtension(kRtpAudioLevelHeaderExtension,
kRtpAudioLevelHeaderExtensionId));
+ options_ = GetDefaultEngineOptions();
+
+ // Initialize the VoE Configuration to the default ACM.
+ voe_config_.Set<webrtc::AudioCodingModuleFactory>(
+ new webrtc::AudioCodingModuleFactory);
}
static bool IsOpus(const AudioCodec& codec) {
@@ -502,11 +539,14 @@ bool WebRtcVoiceEngine::InitInternal() {
// Save the default AGC configuration settings. This must happen before
// calling SetOptions or the default will be overwritten.
if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) {
- LOG_RTCERR0(GetAGCConfig);
+ LOG_RTCERR0(GetAgcConfig);
return false;
}
- if (!SetOptions(MediaEngineInterface::DEFAULT_AUDIO_OPTIONS)) {
+ // Set defaults for options, so that ApplyOptions applies them explicitly
+ // when we clear option (channel) overrides. External clients can still
+ // modify the defaults via SetOptions (on the media engine).
+ if (!SetOptions(GetDefaultEngineOptions())) {
return false;
}
@@ -517,6 +557,23 @@ bool WebRtcVoiceEngine::InitInternal() {
LOG(LS_INFO) << ToString(*it);
}
+ // Disable the DTMF playout when a tone is sent.
+ // PlayDtmfTone will be used if local playout is needed.
+ if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) {
+ LOG_RTCERR1(SetDtmfFeedbackStatus, false);
+ }
+
+ initialized_ = true;
+ return true;
+}
+
+bool WebRtcVoiceEngine::EnsureSoundclipEngineInit() {
+ if (voe_wrapper_sc_initialized_) {
+ return true;
+ }
+ // Note that, if initialization fails, voe_wrapper_sc_initialized_ will still
+ // be false, so subsequent calls to EnsureSoundclipEngineInit will
+ // probably just fail again. That's acceptable behavior.
#if defined(LINUX) && !defined(HAVE_LIBPULSE)
voe_wrapper_sc_->hw()->SetAudioDeviceLayer(webrtc::kAudioLinuxAlsa);
#endif
@@ -550,14 +607,8 @@ bool WebRtcVoiceEngine::InitInternal() {
}
}
#endif
-
- // Disable the DTMF playout when a tone is sent.
- // PlayDtmfTone will be used if local playout is needed.
- if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) {
- LOG_RTCERR1(SetDtmfFeedbackStatus, false);
- }
-
- initialized_ = true;
+ voe_wrapper_sc_initialized_ = true;
+ LOG(LS_INFO) << "Initialized WebRtc soundclip engine.";
return true;
}
@@ -567,7 +618,10 @@ void WebRtcVoiceEngine::Terminate() {
StopAecDump();
- voe_wrapper_sc_->base()->Terminate();
+ if (voe_wrapper_sc_) {
+ voe_wrapper_sc_initialized_ = false;
+ voe_wrapper_sc_->base()->Terminate();
+ }
voe_wrapper_->base()->Terminate();
desired_local_monitor_enable_ = false;
}
@@ -586,6 +640,11 @@ VoiceMediaChannel *WebRtcVoiceEngine::CreateChannel() {
}
SoundclipMedia *WebRtcVoiceEngine::CreateSoundclip() {
+ if (!EnsureSoundclipEngineInit()) {
+ LOG(LS_ERROR) << "Unable to create soundclip: soundclip engine failed to "
+ << "initialize.";
+ return NULL;
+ }
WebRtcSoundclipMedia *soundclip = new WebRtcSoundclipMedia(this);
if (!soundclip->Init() || !soundclip->Enable()) {
delete soundclip;
@@ -594,35 +653,7 @@ SoundclipMedia *WebRtcVoiceEngine::CreateSoundclip() {
return soundclip;
}
-// TODO(zhurunz): Add a comprehensive unittests for SetOptions().
-bool WebRtcVoiceEngine::SetOptions(int flags) {
- AudioOptions options;
-
- // Convert flags to AudioOptions.
- options.echo_cancellation.Set(
- ((flags & MediaEngineInterface::ECHO_CANCELLATION) != 0));
- options.auto_gain_control.Set(
- ((flags & MediaEngineInterface::AUTO_GAIN_CONTROL) != 0));
- options.noise_suppression.Set(
- ((flags & MediaEngineInterface::NOISE_SUPPRESSION) != 0));
- options.highpass_filter.Set(
- ((flags & MediaEngineInterface::HIGHPASS_FILTER) != 0));
- options.stereo_swapping.Set(
- ((flags & MediaEngineInterface::STEREO_FLIPPING) != 0));
-
- // Set defaults for flagless options here. Make sure they are all set so that
- // ApplyOptions applies all of them when we clear overrides.
- options.typing_detection.Set(true);
- options.conference_mode.Set(false);
- options.adjust_agc_delta.Set(0);
- options.experimental_agc.Set(false);
- options.experimental_aec.Set(false);
- options.aec_dump.Set(false);
-
- return SetAudioOptions(options);
-}
-
-bool WebRtcVoiceEngine::SetAudioOptions(const AudioOptions& options) {
+bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) {
if (!ApplyOptions(options)) {
return false;
}
@@ -666,6 +697,10 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
webrtc::NsModes ns_mode = webrtc::kNsHighSuppression;
bool aecm_comfort_noise = false;
+ if (options.aecm_generate_comfort_noise.Get(&aecm_comfort_noise)) {
+ LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
+ << aecm_comfort_noise << " (default is false).";
+ }
#if defined(IOS)
// On iOS, VPIO provides built-in EC and AGC.
@@ -684,9 +719,14 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
options.experimental_aec.Set(false);
#endif
-
LOG(LS_INFO) << "Applying audio options: " << options.ToString();
+ // Configure whether ACM1 or ACM2 is used.
+ bool enable_acm2 = false;
+ if (options.experimental_acm.Get(&enable_acm2)) {
+ EnableExperimentalAcm(enable_acm2);
+ }
+
webrtc::VoEAudioProcessing* voep = voe_wrapper_->processing();
bool echo_cancellation;
@@ -694,6 +734,9 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
if (voep->SetEcStatus(echo_cancellation, ec_mode) == -1) {
LOG_RTCERR2(SetEcStatus, echo_cancellation, ec_mode);
return false;
+ } else {
+ LOG(LS_VERBOSE) << "Echo control set to " << echo_cancellation
+ << " with mode " << ec_mode;
}
#if !defined(ANDROID)
// TODO(ajm): Remove the error return on Android from webrtc.
@@ -715,6 +758,38 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
if (voep->SetAgcStatus(auto_gain_control, agc_mode) == -1) {
LOG_RTCERR2(SetAgcStatus, auto_gain_control, agc_mode);
return false;
+ } else {
+ LOG(LS_VERBOSE) << "Auto gain set to " << auto_gain_control
+ << " with mode " << agc_mode;
+ }
+ }
+
+ if (options.tx_agc_target_dbov.IsSet() ||
+ options.tx_agc_digital_compression_gain.IsSet() ||
+ options.tx_agc_limiter.IsSet()) {
+ // Override default_agc_config_. Generally, an unset option means "leave
+ // the VoE bits alone" in this function, so we want whatever is set to be
+ // stored as the new "default". If we didn't, then setting e.g.
+ // tx_agc_target_dbov would reset digital compression gain and limiter
+ // settings.
+ // Also, if we don't update default_agc_config_, then adjust_agc_delta
+ // would be an offset from the original values, and not whatever was set
+ // explicitly.
+ default_agc_config_.targetLeveldBOv =
+ options.tx_agc_target_dbov.GetWithDefaultIfUnset(
+ default_agc_config_.targetLeveldBOv);
+ default_agc_config_.digitalCompressionGaindB =
+ options.tx_agc_digital_compression_gain.GetWithDefaultIfUnset(
+ default_agc_config_.digitalCompressionGaindB);
+ default_agc_config_.limiterEnable =
+ options.tx_agc_limiter.GetWithDefaultIfUnset(
+ default_agc_config_.limiterEnable);
+ if (voe_wrapper_->processing()->SetAgcConfig(default_agc_config_) == -1) {
+ LOG_RTCERR3(SetAgcConfig,
+ default_agc_config_.targetLeveldBOv,
+ default_agc_config_.digitalCompressionGaindB,
+ default_agc_config_.limiterEnable);
+ return false;
}
}
@@ -723,6 +798,9 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
if (voep->SetNsStatus(noise_suppression, ns_mode) == -1) {
LOG_RTCERR2(SetNsStatus, noise_suppression, ns_mode);
return false;
+ } else {
+ LOG(LS_VERBOSE) << "Noise suppression set to " << noise_suppression
+ << " with mode " << ns_mode;
}
}
@@ -766,6 +844,34 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
StopAecDump();
}
+ bool experimental_aec;
+ if (options.experimental_aec.Get(&experimental_aec)) {
+ webrtc::AudioProcessing* audioproc =
+ voe_wrapper_->base()->audio_processing();
+ // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
+ // returns NULL on audio_processing().
+ if (audioproc) {
+ webrtc::Config config;
+ config.Set<webrtc::DelayCorrection>(
+ new webrtc::DelayCorrection(experimental_aec));
+ audioproc->SetExtraOptions(config);
+ }
+ }
+
+ uint32 recording_sample_rate;
+ if (options.recording_sample_rate.Get(&recording_sample_rate)) {
+ if (voe_wrapper_->hw()->SetRecordingSampleRate(recording_sample_rate)) {
+ LOG_RTCERR1(SetRecordingSampleRate, recording_sample_rate);
+ }
+ }
+
+ uint32 playout_sample_rate;
+ if (options.playout_sample_rate.Get(&playout_sample_rate)) {
+ if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) {
+ LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate);
+ }
+ }
+
return true;
}
@@ -796,7 +902,7 @@ struct ResumeEntry {
// soundclip device. At that time, reinstate the soundclip pause/resume code.
bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
const Device* out_device) {
-#if !defined(IOS) && !defined(ANDROID)
+#if !defined(IOS)
int in_id = in_device ? talk_base::FromString<int>(in_device->id) :
kDefaultAudioDeviceId;
int out_id = out_device ? talk_base::FromString<int>(out_device->id) :
@@ -847,7 +953,7 @@ bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
}
if (ret) {
if (voe_wrapper_->hw()->SetRecordingDevice(in_id) == -1) {
- LOG_RTCERR2(SetRecordingDevice, in_device->name, in_id);
+ LOG_RTCERR2(SetRecordingDevice, in_name, in_id);
ret = false;
}
}
@@ -859,7 +965,7 @@ bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
}
if (ret) {
if (voe_wrapper_->hw()->SetPlayoutDevice(out_id) == -1) {
- LOG_RTCERR2(SetPlayoutDevice, out_device->name, out_id);
+ LOG_RTCERR2(SetPlayoutDevice, out_name, out_id);
ret = false;
}
}
@@ -893,13 +999,13 @@ bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
return ret;
#else
return true;
-#endif // !IOS && !ANDROID
+#endif // !IOS
}
bool WebRtcVoiceEngine::FindWebRtcAudioDeviceId(
bool is_input, const std::string& dev_name, int dev_id, int* rtc_id) {
// In Linux, VoiceEngine uses the same device dev_id as the device manager.
-#ifdef LINUX
+#if defined(LINUX) || defined(ANDROID)
*rtc_id = dev_id;
return true;
#else
@@ -1103,6 +1209,18 @@ void WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
}
}
+ // Allow trace options to override the trace filter. We default
+ // it to log_filter_ (as a translation of libjingle log levels)
+ // elsewhere, but this allows clients to explicitly set webrtc
+ // log levels.
+ std::vector<std::string>::iterator tracefilter =
+ std::find(opts.begin(), opts.end(), "tracefilter");
+ if (tracefilter != opts.end() && ++tracefilter != opts.end()) {
+ if (!tracing_->SetTraceFilter(talk_base::FromString<int>(*tracefilter))) {
+ LOG_RTCERR1(SetTraceFilter, *tracefilter);
+ }
+ }
+
// Set AEC dump file
std::vector<std::string>::iterator recordEC =
std::find(opts.begin(), opts.end(), "recordEC");
@@ -1143,6 +1261,21 @@ bool WebRtcVoiceEngine::ShouldIgnoreTrace(const std::string& trace) {
return false;
}
+void WebRtcVoiceEngine::EnableExperimentalAcm(bool enable) {
+ if (enable == use_experimental_acm_)
+ return;
+ if (enable) {
+ LOG(LS_INFO) << "VoiceEngine is set to use new ACM (ACM2 + NetEq4).";
+ voe_config_.Set<webrtc::AudioCodingModuleFactory>(
+ new webrtc::NewAudioCodingModuleFactory());
+ } else {
+ LOG(LS_INFO) << "VoiceEngine is set to use legacy ACM (ACM1 + Neteq3).";
+ voe_config_.Set<webrtc::AudioCodingModuleFactory>(
+ new webrtc::AudioCodingModuleFactory());
+ }
+ use_experimental_acm_ = enable;
+}
+
void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
int length) {
talk_base::LoggingSeverity sev = talk_base::LS_VERBOSE;
@@ -1475,11 +1608,26 @@ void WebRtcVoiceEngine::StopAecDump() {
}
}
+int WebRtcVoiceEngine::CreateVoiceChannel(VoEWrapper* voice_engine_wrapper) {
+ return voice_engine_wrapper->base()->CreateChannel(voe_config_);
+}
+
+int WebRtcVoiceEngine::CreateMediaVoiceChannel() {
+ return CreateVoiceChannel(voe_wrapper_.get());
+}
+
+int WebRtcVoiceEngine::CreateSoundclipVoiceChannel() {
+ return CreateVoiceChannel(voe_wrapper_sc_.get());
+}
+
// WebRtcVoiceMediaChannel
WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine)
: WebRtcMediaChannel<VoiceMediaChannel, WebRtcVoiceEngine>(
engine,
- engine->voe()->base()->CreateChannel()),
+ engine->CreateMediaVoiceChannel()),
+ send_bw_setting_(false),
+ send_autobw_(false),
+ send_bw_bps_(0),
options_(),
dtmf_allowed_(false),
desired_playout_(false),
@@ -1520,6 +1668,9 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
LOG(LS_INFO) << "Setting voice channel options: "
<< options.ToString();
+ // Check if DSCP value is changed from previous.
+ bool dscp_option_changed = (options_.dscp != options.dscp);
+
// TODO(xians): Add support to set different options for different send
// streams after we support multiple APMs.
@@ -1538,6 +1689,64 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
// Will be interpreted when appropriate.
}
+ // Receiver-side auto gain control happens per channel, so set it here from
+ // options. Note that, like conference mode, setting it on the engine won't
+ // have the desired effect, since voice channels don't inherit options from
+ // the media engine when those options are applied per-channel.
+ bool rx_auto_gain_control;
+ if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) {
+ if (engine()->voe()->processing()->SetRxAgcStatus(
+ voe_channel(), rx_auto_gain_control,
+ webrtc::kAgcFixedDigital) == -1) {
+ LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control);
+ return false;
+ } else {
+ LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control
+ << " with mode " << webrtc::kAgcFixedDigital;
+ }
+ }
+ if (options.rx_agc_target_dbov.IsSet() ||
+ options.rx_agc_digital_compression_gain.IsSet() ||
+ options.rx_agc_limiter.IsSet()) {
+ webrtc::AgcConfig config;
+ // If only some of the options are being overridden, get the current
+ // settings for the channel and bail if they aren't available.
+ if (!options.rx_agc_target_dbov.IsSet() ||
+ !options.rx_agc_digital_compression_gain.IsSet() ||
+ !options.rx_agc_limiter.IsSet()) {
+ if (engine()->voe()->processing()->GetRxAgcConfig(
+ voe_channel(), config) != 0) {
+ LOG(LS_ERROR) << "Failed to get default rx agc configuration for "
+ << "channel " << voe_channel() << ". Since not all rx "
+ << "agc options are specified, unable to safely set rx "
+ << "agc options.";
+ return false;
+ }
+ }
+ config.targetLeveldBOv =
+ options.rx_agc_target_dbov.GetWithDefaultIfUnset(
+ config.targetLeveldBOv);
+ config.digitalCompressionGaindB =
+ options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset(
+ config.digitalCompressionGaindB);
+ config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset(
+ config.limiterEnable);
+ if (engine()->voe()->processing()->SetRxAgcConfig(
+ voe_channel(), config) == -1) {
+ LOG_RTCERR4(SetRxAgcConfig, voe_channel(), config.targetLeveldBOv,
+ config.digitalCompressionGaindB, config.limiterEnable);
+ return false;
+ }
+ }
+ if (dscp_option_changed) {
+ talk_base::DiffServCodePoint dscp = talk_base::DSCP_DEFAULT;
+ if (options.dscp.GetWithDefaultIfUnset(false))
+ dscp = kAudioDscpValue;
+ if (MediaChannel::SetDscp(dscp) != 0) {
+ LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel";
+ }
+ }
+
LOG(LS_INFO) << "Set voice channel options. Current options: "
<< options_.ToString();
return true;
@@ -1784,6 +1993,10 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
// Always update the |send_codec_| to the currently set send codec.
send_codec_.reset(new webrtc::CodecInst(send_codec));
+ if (send_bw_setting_) {
+ SetSendBandwidthInternal(send_autobw_, send_bw_bps_);
+ }
+
return true;
}
@@ -2045,7 +2258,7 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
channel = voe_channel();
} else {
// Create a new channel for sending audio data.
- channel = engine()->voe()->base()->CreateChannel();
+ channel = engine()->CreateMediaVoiceChannel();
if (channel == -1) {
LOG_RTCERR0(CreateChannel);
return false;
@@ -2138,6 +2351,11 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
return false;
uint32 ssrc = sp.first_ssrc();
+ if (ssrc == 0) {
+ LOG(LS_WARNING) << "AddRecvStream with 0 ssrc is not supported.";
+ return false;
+ }
+
if (receive_channels_.find(ssrc) != receive_channels_.end()) {
LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
return false;
@@ -2155,12 +2373,27 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
}
// Create a new channel for receiving audio data.
- int channel = engine()->voe()->base()->CreateChannel();
+ int channel = engine()->CreateMediaVoiceChannel();
if (channel == -1) {
LOG_RTCERR0(CreateChannel);
return false;
}
+ if (!ConfigureRecvChannel(channel)) {
+ DeleteChannel(channel);
+ return false;
+ }
+
+ receive_channels_.insert(
+ std::make_pair(ssrc, WebRtcVoiceChannelInfo(channel, NULL)));
+
+ LOG(LS_INFO) << "New audio stream " << ssrc
+ << " registered to VoiceEngine channel #"
+ << channel << ".";
+ return true;
+}
+
+bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
// Configure to use external transport, like our default channel.
if (engine()->voe()->network()->RegisterExternalTransport(
channel, *this) == -1) {
@@ -2217,13 +2450,6 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
}
SetNack(channel, nack_enabled_);
- receive_channels_.insert(
- std::make_pair(ssrc, WebRtcVoiceChannelInfo(channel, NULL)));
-
- // TODO(juberti): We should rollback the add if SetPlayout fails.
- LOG(LS_INFO) << "New audio stream " << ssrc
- << " registered to VoiceEngine channel #"
- << channel << ".";
return SetPlayout(channel, playout_);
}
@@ -2582,7 +2808,8 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32 ssrc, int event,
return true;
}
-void WebRtcVoiceMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
+void WebRtcVoiceMediaChannel::OnPacketReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
// Pick which channel to send this packet to. If this packet doesn't match
// any multiplexed streams, just send it to the default channel. Otherwise,
// send it to the specific decoder instance for that stream.
@@ -2615,7 +2842,8 @@ void WebRtcVoiceMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
static_cast<unsigned int>(packet->length()));
}
-void WebRtcVoiceMediaChannel::OnRtcpReceived(talk_base::Buffer* packet) {
+void WebRtcVoiceMediaChannel::OnRtcpReceived(
+ talk_base::Buffer* packet, const talk_base::PacketTime& packet_time) {
// Sending channels need all RTCP packets with feedback information.
// Even sender reports can contain attached report blocks.
// Receiving channels need sender reports in order to create
@@ -2674,9 +2902,20 @@ bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) {
bool WebRtcVoiceMediaChannel::SetSendBandwidth(bool autobw, int bps) {
LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidth.";
+ send_bw_setting_ = true;
+ send_autobw_ = autobw;
+ send_bw_bps_ = bps;
+
+ return SetSendBandwidthInternal(send_autobw_, send_bw_bps_);
+}
+
+bool WebRtcVoiceMediaChannel::SetSendBandwidthInternal(bool autobw, int bps) {
+ LOG(LS_INFO) << "WebRtcVoiceMediaChanne::SetSendBandwidthInternal.";
+
if (!send_codec_) {
- LOG(LS_INFO) << "The send codec has not been set up yet.";
- return false;
+ LOG(LS_INFO) << "The send codec has not been set up yet. "
+ << "The send bandwidth setting will be applied later.";
+ return true;
}
// Bandwidth is auto by default.
@@ -2738,7 +2977,6 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
}
}
-
webrtc::CallStatistics cs;
unsigned int ssrc;
webrtc::CodecInst codec;
@@ -2757,7 +2995,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
continue;
}
- sinfo.ssrc = ssrc;
+ sinfo.add_ssrc(ssrc);
sinfo.codec_name = send_codec_.get() ? send_codec_->plname : "";
sinfo.bytes_sent = cs.bytesSent;
sinfo.packets_sent = cs.packetsSent;
@@ -2779,7 +3017,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
for (iter = receive_blocks.begin(); iter != receive_blocks.end();
++iter) {
// Lookup report for send ssrc only.
- if (iter->source_SSRC == sinfo.ssrc) {
+ if (iter->source_SSRC == sinfo.ssrc()) {
// Convert Q8 to floating point.
sinfo.fraction_lost = static_cast<float>(iter->fraction_lost) / 256;
// Convert samples to milliseconds.
@@ -2806,6 +3044,8 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement;
sinfo.echo_delay_median_ms = echo_delay_median_ms;
sinfo.echo_delay_std_ms = echo_delay_std_ms;
+ // TODO(ajm): Re-enable this metric once we have a reliable implementation.
+ sinfo.aec_quality_min = -1;
sinfo.typing_noise_detected = typing_noise_detected_;
info->senders.push_back(sinfo);
@@ -2830,7 +3070,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
engine()->voe()->rtp()->GetRTCPStatistics(*it, cs) != -1 &&
engine()->voe()->codec()->GetRecCodec(*it, codec) != -1) {
VoiceReceiverInfo rinfo;
- rinfo.ssrc = ssrc;
+ rinfo.add_ssrc(ssrc);
rinfo.bytes_rcvd = cs.bytesReceived;
rinfo.packets_rcvd = cs.packetsReceived;
// The next four fields are from the most recently sent RTCP report.
@@ -2854,9 +3094,12 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
static_cast<float>(ns.currentExpandRate) / (1 << 14);
}
if (engine()->voe()->sync()) {
+ int jitter_buffer_delay_ms = 0;
int playout_buffer_delay_ms = 0;
engine()->voe()->sync()->GetDelayEstimate(
- *it, &rinfo.delay_estimate_ms, &playout_buffer_delay_ms);
+ *it, &jitter_buffer_delay_ms, &playout_buffer_delay_ms);
+ rinfo.delay_estimate_ms = jitter_buffer_delay_ms +
+ playout_buffer_delay_ms;
}
// Get speech level.
@@ -2915,13 +3158,11 @@ bool WebRtcVoiceMediaChannel::FindSsrc(int channel_num, uint32* ssrc) {
}
void WebRtcVoiceMediaChannel::OnError(uint32 ssrc, int error) {
-#ifdef USE_WEBRTC_DEV_BRANCH
if (error == VE_TYPING_NOISE_WARNING) {
typing_noise_detected_ = true;
} else if (error == VE_TYPING_NOISE_OFF_WARNING) {
typing_noise_detected_ = false;
}
-#endif
SignalMediaError(ssrc, WebRtcErrorToChannelError(error));
}
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.h b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.h
index 62d3bc10a25..6a2c6d80f8f 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.h
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine.h
@@ -43,6 +43,8 @@
#include "talk/media/webrtc/webrtcexport.h"
#include "talk/media/webrtc/webrtcvoe.h"
#include "talk/session/media/channel.h"
+#include "webrtc/common.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
#if !defined(LIBPEERCONNECTION_LIB) && \
!defined(LIBPEERCONNECTION_IMPLEMENTATION)
@@ -105,12 +107,8 @@ class WebRtcVoiceEngine
SoundclipMedia* CreateSoundclip();
- // TODO(pthatcher): Rename to SetOptions and replace the old
- // flags-based SetOptions.
- bool SetAudioOptions(const AudioOptions& options);
- // Eventually, we will replace them with AudioOptions.
- // In the meantime, we leave this here for backwards compat.
- bool SetOptions(int flags);
+ AudioOptions GetOptions() const { return options_; }
+ bool SetOptions(const AudioOptions& options);
// Overrides, when set, take precedence over the options on a
// per-option basis. For example, if AGC is set in options and AEC
// is set in overrides, AGC and AEC will be both be set. Overrides
@@ -179,6 +177,10 @@ class WebRtcVoiceEngine
// Check whether the supplied trace should be ignored.
bool ShouldIgnoreTrace(const std::string& trace);
+ // Create a VoiceEngine Channel.
+ int CreateMediaVoiceChannel();
+ int CreateSoundclipVoiceChannel();
+
private:
typedef std::vector<WebRtcSoundclipMedia *> SoundclipList;
typedef std::vector<WebRtcVoiceMediaChannel *> ChannelList;
@@ -188,6 +190,7 @@ class WebRtcVoiceEngine
void Construct();
void ConstructCodecs();
bool InitInternal();
+ bool EnsureSoundclipEngineInit();
void SetTraceFilter(int filter);
void SetTraceOptions(const std::string& options);
// Applies either options or overrides. Every option that is "set"
@@ -195,6 +198,9 @@ class WebRtcVoiceEngine
// allows us to selectively turn on and off different options easily
// at any time.
bool ApplyOptions(const AudioOptions& options);
+ // Configure for using ACM2, if |enable| is true, otherwise configure for
+ // ACM1.
+ void EnableExperimentalAcm(bool enable);
virtual void Print(webrtc::TraceLevel level, const char* trace, int length);
virtual void CallbackOnError(int channel, int errCode);
// Given the device type, name, and id, find device id. Return true and
@@ -218,6 +224,7 @@ class WebRtcVoiceEngine
void StartAecDump(const std::string& filename);
void StopAecDump();
+ int CreateVoiceChannel(VoEWrapper* voe);
// When a voice processor registers with the engine, it is connected
// to either the Rx or Tx signals, based on the direction parameter.
@@ -231,6 +238,7 @@ class WebRtcVoiceEngine
talk_base::scoped_ptr<VoEWrapper> voe_wrapper_;
// A secondary instance, for playing out soundclips (on the 'ring' device).
talk_base::scoped_ptr<VoEWrapper> voe_wrapper_sc_;
+ bool voe_wrapper_sc_initialized_;
talk_base::scoped_ptr<VoETraceWrapper> tracing_;
// The external audio device manager
webrtc::AudioDeviceModule* adm_;
@@ -248,6 +256,10 @@ class WebRtcVoiceEngine
// callback as well as the RegisterChannel/UnregisterChannel.
talk_base::CriticalSection channels_cs_;
webrtc::AgcConfig default_agc_config_;
+
+ webrtc::Config voe_config_;
+ bool use_experimental_acm_;
+
bool initialized_;
// See SetOptions and SetOptionOverrides for a description of the
// difference between options and overrides.
@@ -344,8 +356,10 @@ class WebRtcVoiceMediaChannel
virtual bool CanInsertDtmf();
virtual bool InsertDtmf(uint32 ssrc, int event, int duration, int flags);
- virtual void OnPacketReceived(talk_base::Buffer* packet);
- virtual void OnRtcpReceived(talk_base::Buffer* packet);
+ virtual void OnPacketReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
+ virtual void OnRtcpReceived(talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
virtual void OnReadyToSend(bool ready) {}
virtual bool MuteStream(uint32 ssrc, bool on);
virtual bool SetSendBandwidth(bool autobw, int bps);
@@ -396,6 +410,7 @@ class WebRtcVoiceMediaChannel
bool ChangeSend(SendFlags send);
bool ChangeSend(int channel, SendFlags send);
void ConfigureSendChannel(int channel);
+ bool ConfigureRecvChannel(int channel);
bool DeleteChannel(int channel);
bool InConferenceMode() const {
return options_.conference_mode.GetWithDefaultIfUnset(false);
@@ -404,12 +419,16 @@ class WebRtcVoiceMediaChannel
return channel_id == voe_channel();
}
bool SetSendCodecs(int channel, const std::vector<AudioCodec>& codecs);
+ bool SetSendBandwidthInternal(bool autobw, int bps);
talk_base::scoped_ptr<WebRtcSoundclipStream> ringback_tone_;
std::set<int> ringback_channels_; // channels playing ringback
std::vector<AudioCodec> recv_codecs_;
std::vector<AudioCodec> send_codecs_;
talk_base::scoped_ptr<webrtc::CodecInst> send_codec_;
+ bool send_bw_setting_;
+ bool send_autobw_;
+ int send_bw_bps_;
AudioOptions options_;
bool dtmf_allowed_;
bool desired_playout_;
diff --git a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine_unittest.cc
index 3710e7ebc93..9bb681a895c 100644
--- a/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -12,6 +12,7 @@
#include "talk/media/base/constants.h"
#include "talk/media/base/fakemediaengine.h"
#include "talk/media/base/fakemediaprocessor.h"
+#include "talk/media/base/fakenetworkinterface.h"
#include "talk/media/base/fakertp.h"
#include "talk/media/webrtc/fakewebrtcvoiceengine.h"
#include "talk/media/webrtc/webrtcvoiceengine.h"
@@ -55,9 +56,10 @@ class FakeVoEWrapper : public cricket::VoEWrapper {
}
};
-class NullVoETraceWrapper : public cricket::VoETraceWrapper {
+class FakeVoETraceWrapper : public cricket::VoETraceWrapper {
public:
virtual int SetTraceFilter(const unsigned int filter) {
+ filter_ = filter;
return 0;
}
virtual int SetTraceFile(const char* fileNameUTF8) {
@@ -66,6 +68,7 @@ class NullVoETraceWrapper : public cricket::VoETraceWrapper {
virtual int SetTraceCallback(webrtc::TraceCallback* callback) {
return 0;
}
+ unsigned int filter_;
};
class WebRtcVoiceEngineTestFake : public testing::Test {
@@ -102,9 +105,10 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
WebRtcVoiceEngineTestFake()
: voe_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
voe_sc_(kAudioCodecs, ARRAY_SIZE(kAudioCodecs)),
+ trace_wrapper_(new FakeVoETraceWrapper()),
engine_(new FakeVoEWrapper(&voe_),
new FakeVoEWrapper(&voe_sc_),
- new NullVoETraceWrapper()),
+ trace_wrapper_),
channel_(NULL), soundclip_(NULL) {
options_conference_.conference_mode.Set(true);
options_adjust_agc_.adjust_agc_delta.Set(-10);
@@ -135,7 +139,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
}
void DeliverPacket(const void* data, int len) {
talk_base::Buffer packet(data, len);
- channel_->OnPacketReceived(&packet);
+ channel_->OnPacketReceived(&packet, talk_base::PacketTime());
}
virtual void TearDown() {
delete soundclip_;
@@ -212,13 +216,10 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
codecs.push_back(codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
- webrtc::CodecInst temp_codec;
- EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec));
- EXPECT_EQ(default_bitrate, temp_codec.rate);
-
bool result = channel_->SetSendBandwidth(auto_bitrate, desired_bitrate);
EXPECT_EQ(expected_result, result);
+ webrtc::CodecInst temp_codec;
EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec));
if (result) {
@@ -280,6 +281,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
protected:
cricket::FakeWebRtcVoiceEngine voe_;
cricket::FakeWebRtcVoiceEngine voe_sc_;
+ FakeVoETraceWrapper* trace_wrapper_;
cricket::WebRtcVoiceEngine engine_;
cricket::VoiceMediaChannel* channel_;
cricket::SoundclipMedia* soundclip_;
@@ -294,7 +296,8 @@ TEST_F(WebRtcVoiceEngineTestFake, StartupShutdown) {
EXPECT_FALSE(voe_sc_.IsInited());
EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
EXPECT_TRUE(voe_.IsInited());
- EXPECT_TRUE(voe_sc_.IsInited());
+ // The soundclip engine is lazily initialized.
+ EXPECT_FALSE(voe_sc_.IsInited());
engine_.Terminate();
EXPECT_FALSE(voe_.IsInited());
EXPECT_FALSE(voe_sc_.IsInited());
@@ -588,7 +591,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthAuto) {
TestSendBandwidth(kOpusCodec, 64000, true, 96000, true);
}
-TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRate) {
+TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCaller) {
EXPECT_TRUE(SetupEngine());
EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
@@ -605,6 +608,24 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRate) {
TestSendBandwidth(kOpusCodec, 64000, false, 96000, true);
}
+TEST_F(WebRtcVoiceEngineTestFake, SetSendBandwidthFixedMultiRateAsCallee) {
+ EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
+ channel_ = engine_.CreateChannel();
+ EXPECT_TRUE(channel_ != NULL);
+ EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
+
+ int desired_bitrate = 128000;
+ EXPECT_TRUE(channel_->SetSendBandwidth(false, desired_bitrate));
+
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrc1)));
+
+ int channel_num = voe_.GetLastChannel();
+ webrtc::CodecInst codec;
+ EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec));
+ EXPECT_EQ(desired_bitrate, codec.rate);
+}
+
// Test that bitrate cannot be set for CBR codecs.
// Bitrate is ignored if it is higher than the fixed bitrate.
// Bitrate less then the fixed bitrate is an error.
@@ -1632,7 +1653,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
// Verify the statistic information is correct.
for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
- EXPECT_EQ(kSsrcs4[i], info.senders[i].ssrc);
+ EXPECT_EQ(kSsrcs4[i], info.senders[i].ssrc());
EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name);
EXPECT_EQ(cricket::kIntStatValue, info.senders[i].bytes_sent);
EXPECT_EQ(cricket::kIntStatValue, info.senders[i].packets_sent);
@@ -1857,6 +1878,84 @@ TEST_F(WebRtcVoiceEngineTestFake, CodianSendAndPlayout) {
EXPECT_FALSE(voe_.GetPlayout(channel_num));
}
+TEST_F(WebRtcVoiceEngineTestFake, TxAgcConfigViaOptions) {
+ EXPECT_TRUE(SetupEngine());
+ webrtc::AgcConfig agc_config;
+ EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
+ EXPECT_EQ(0, agc_config.targetLeveldBOv);
+
+ cricket::AudioOptions options;
+ options.tx_agc_target_dbov.Set(3);
+ options.tx_agc_digital_compression_gain.Set(9);
+ options.tx_agc_limiter.Set(true);
+ options.auto_gain_control.Set(true);
+ EXPECT_TRUE(engine_.SetOptions(options));
+
+ EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
+ EXPECT_EQ(3, agc_config.targetLeveldBOv);
+ EXPECT_EQ(9, agc_config.digitalCompressionGaindB);
+ EXPECT_TRUE(agc_config.limiterEnable);
+
+ // Check interaction with adjust_agc_delta. Both should be respected, for
+ // backwards compatibility.
+ options.adjust_agc_delta.Set(-10);
+ EXPECT_TRUE(engine_.SetOptions(options));
+
+ EXPECT_EQ(0, voe_.GetAgcConfig(agc_config));
+ EXPECT_EQ(13, agc_config.targetLeveldBOv);
+}
+
+TEST_F(WebRtcVoiceEngineTestFake, RxAgcConfigViaOptions) {
+ EXPECT_TRUE(SetupEngine());
+ int channel_num = voe_.GetLastChannel();
+ cricket::AudioOptions options;
+ options.rx_agc_target_dbov.Set(6);
+ options.rx_agc_digital_compression_gain.Set(0);
+ options.rx_agc_limiter.Set(true);
+ options.rx_auto_gain_control.Set(true);
+ EXPECT_TRUE(channel_->SetOptions(options));
+
+ webrtc::AgcConfig agc_config;
+ EXPECT_EQ(0, engine_.voe()->processing()->GetRxAgcConfig(
+ channel_num, agc_config));
+ EXPECT_EQ(6, agc_config.targetLeveldBOv);
+ EXPECT_EQ(0, agc_config.digitalCompressionGaindB);
+ EXPECT_TRUE(agc_config.limiterEnable);
+}
+
+TEST_F(WebRtcVoiceEngineTestFake, SampleRatesViaOptions) {
+ EXPECT_TRUE(SetupEngine());
+ cricket::AudioOptions options;
+ options.recording_sample_rate.Set(48000u);
+ options.playout_sample_rate.Set(44100u);
+ EXPECT_TRUE(engine_.SetOptions(options));
+
+ unsigned int recording_sample_rate, playout_sample_rate;
+ EXPECT_EQ(0, voe_.RecordingSampleRate(&recording_sample_rate));
+ EXPECT_EQ(0, voe_.PlayoutSampleRate(&playout_sample_rate));
+ EXPECT_EQ(48000u, recording_sample_rate);
+ EXPECT_EQ(44100u, playout_sample_rate);
+}
+
+TEST_F(WebRtcVoiceEngineTestFake, TraceFilterViaTraceOptions) {
+ EXPECT_TRUE(SetupEngine());
+ engine_.SetLogging(talk_base::LS_INFO, "");
+ EXPECT_EQ(
+ // Info:
+ webrtc::kTraceStateInfo | webrtc::kTraceInfo |
+ // Warning:
+ webrtc::kTraceTerseInfo | webrtc::kTraceWarning |
+ // Error:
+ webrtc::kTraceError | webrtc::kTraceCritical,
+ static_cast<int>(trace_wrapper_->filter_));
+ // Now set it explicitly
+ std::string filter =
+ "tracefilter " + talk_base::ToString(webrtc::kTraceDefault);
+ engine_.SetLogging(talk_base::LS_VERBOSE, filter.c_str());
+ EXPECT_EQ(static_cast<unsigned int>(webrtc::kTraceDefault),
+ trace_wrapper_->filter_);
+}
+
// Test that we can set the outgoing SSRC properly.
// SSRC is set in SetupEngine by calling AddSendStream.
TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrc) {
@@ -1879,7 +1978,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
cricket::VoiceMediaInfo info;
EXPECT_EQ(true, channel_->GetStats(&info));
EXPECT_EQ(1u, info.senders.size());
- EXPECT_EQ(kSsrc1, info.senders[0].ssrc);
+ EXPECT_EQ(kSsrc1, info.senders[0].ssrc());
EXPECT_EQ(kPcmuCodec.name, info.senders[0].codec_name);
EXPECT_EQ(cricket::kIntStatValue, info.senders[0].bytes_sent);
EXPECT_EQ(cricket::kIntStatValue, info.senders[0].packets_sent);
@@ -1961,7 +2060,7 @@ TEST_F(WebRtcVoiceEngineTestFake, RecvWithMultipleStreams) {
char packets[4][sizeof(kPcmuFrame)];
for (size_t i = 0; i < ARRAY_SIZE(packets); ++i) {
memcpy(packets[i], kPcmuFrame, sizeof(kPcmuFrame));
- talk_base::SetBE32(packets[i] + 8, i);
+ talk_base::SetBE32(packets[i] + 8, static_cast<uint32>(i));
}
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
@@ -2044,6 +2143,26 @@ TEST_F(WebRtcVoiceEngineTestFake, StreamCleanup) {
EXPECT_EQ(0, voe_.GetNumChannels());
}
+TEST_F(WebRtcVoiceEngineTestFake, TestAddRecvStreamFailWithZeroSsrc) {
+ EXPECT_TRUE(SetupEngine());
+ EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(0)));
+}
+
+TEST_F(WebRtcVoiceEngineTestFake, TestNoLeakingWhenAddRecvStreamFail) {
+ EXPECT_TRUE(SetupEngine());
+ // Stream 1 reuses default channel.
+ EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+ // Manually delete default channel to simulate a failure.
+ int default_channel = voe_.GetLastChannel();
+ EXPECT_EQ(0, voe_.DeleteChannel(default_channel));
+ // Add recv stream 2 should fail because default channel is gone.
+ EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
+ int new_channel = voe_.GetLastChannel();
+ EXPECT_NE(default_channel, new_channel);
+ // The last created channel should have already been deleted.
+ EXPECT_EQ(-1, voe_.DeleteChannel(new_channel));
+}
+
// Test the InsertDtmf on default send stream as caller.
TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnDefaultSendStreamAsCaller) {
TestInsertDtmf(0, true);
@@ -2073,7 +2192,8 @@ TEST_F(WebRtcVoiceEngineTestFake, PlayRingback) {
EXPECT_FALSE(channel_->PlayRingbackTone(0, true, true));
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
// Check we can set and play a ringback tone.
- EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
+ EXPECT_TRUE(channel_->SetRingbackTone(
+ kRingbackTone, static_cast<int>(strlen(kRingbackTone))));
EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true));
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
// Check we can stop the tone manually.
@@ -2098,7 +2218,8 @@ TEST_F(WebRtcVoiceEngineTestFake, PlayRingbackWithMultipleStreams) {
EXPECT_FALSE(channel_->PlayRingbackTone(2, true, true));
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
// Check we can set and play a ringback tone on the correct ssrc.
- EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
+ EXPECT_TRUE(channel_->SetRingbackTone(
+ kRingbackTone, static_cast<int>(strlen(kRingbackTone))));
EXPECT_FALSE(channel_->PlayRingbackTone(77, true, true));
EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true));
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
@@ -2122,7 +2243,9 @@ TEST_F(WebRtcVoiceEngineTestFake, PlayRingbackWithMultipleStreams) {
// Tests creating soundclips, and make sure they come from the right engine.
TEST_F(WebRtcVoiceEngineTestFake, CreateSoundclip) {
EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
+ EXPECT_FALSE(voe_sc_.IsInited());
soundclip_ = engine_.CreateSoundclip();
+ EXPECT_TRUE(voe_sc_.IsInited());
ASSERT_TRUE(soundclip_ != NULL);
EXPECT_EQ(0, voe_.GetNumChannels());
EXPECT_EQ(1, voe_sc_.GetNumChannels());
@@ -2131,6 +2254,10 @@ TEST_F(WebRtcVoiceEngineTestFake, CreateSoundclip) {
delete soundclip_;
soundclip_ = NULL;
EXPECT_EQ(0, voe_sc_.GetNumChannels());
+ // Make sure the soundclip engine is uninitialized on shutdown, now that
+ // we've initialized it by creating a soundclip.
+ engine_.Terminate();
+ EXPECT_FALSE(voe_sc_.IsInited());
}
// Tests playing out a fake sound.
@@ -2321,7 +2448,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
// Nothing set, so all ignored.
cricket::AudioOptions options;
- ASSERT_TRUE(engine_.SetAudioOptions(options));
+ ASSERT_TRUE(engine_.SetOptions(options));
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetEcMetricsStatus(ec_metrics_enabled);
voe_.GetAecmMode(aecm_mode, cng_enabled);
@@ -2345,14 +2472,14 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
// Turn echo cancellation off
options.echo_cancellation.Set(false);
- ASSERT_TRUE(engine_.SetAudioOptions(options));
+ ASSERT_TRUE(engine_.SetOptions(options));
voe_.GetEcStatus(ec_enabled, ec_mode);
EXPECT_FALSE(ec_enabled);
// Turn echo cancellation back on, with settings, and make sure
// nothing else changed.
options.echo_cancellation.Set(true);
- ASSERT_TRUE(engine_.SetAudioOptions(options));
+ ASSERT_TRUE(engine_.SetOptions(options));
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetEcMetricsStatus(ec_metrics_enabled);
voe_.GetAecmMode(aecm_mode, cng_enabled);
@@ -2375,14 +2502,14 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
// Turn off AGC
options.auto_gain_control.Set(false);
- ASSERT_TRUE(engine_.SetAudioOptions(options));
+ ASSERT_TRUE(engine_.SetOptions(options));
voe_.GetAgcStatus(agc_enabled, agc_mode);
EXPECT_FALSE(agc_enabled);
// Turn AGC back on
options.auto_gain_control.Set(true);
options.adjust_agc_delta.Clear();
- ASSERT_TRUE(engine_.SetAudioOptions(options));
+ ASSERT_TRUE(engine_.SetOptions(options));
voe_.GetAgcStatus(agc_enabled, agc_mode);
EXPECT_TRUE(agc_enabled);
voe_.GetAgcConfig(agc_config);
@@ -2393,7 +2520,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
options.highpass_filter.Set(false);
options.typing_detection.Set(false);
options.stereo_swapping.Set(true);
- ASSERT_TRUE(engine_.SetAudioOptions(options));
+ ASSERT_TRUE(engine_.SetOptions(options));
voe_.GetNsStatus(ns_enabled, ns_mode);
highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
@@ -2405,7 +2532,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
// Turn on "conference mode" to ensure it has no impact.
options.conference_mode.Set(true);
- ASSERT_TRUE(engine_.SetAudioOptions(options));
+ ASSERT_TRUE(engine_.SetOptions(options));
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetNsStatus(ns_enabled, ns_mode);
EXPECT_TRUE(ec_enabled);
@@ -2414,7 +2541,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) {
EXPECT_EQ(webrtc::kNsHighSuppression, ns_mode);
}
-TEST_F(WebRtcVoiceEngineTestFake, SetOptions) {
+TEST_F(WebRtcVoiceEngineTestFake, DefaultOptions) {
EXPECT_TRUE(SetupEngine());
bool ec_enabled;
@@ -2428,23 +2555,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptions) {
bool stereo_swapping_enabled;
bool typing_detection_enabled;
- ASSERT_TRUE(engine_.SetOptions(0));
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetEcMetricsStatus(ec_metrics_enabled);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
- stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
- voe_.GetTypingDetectionStatus(typing_detection_enabled);
- EXPECT_FALSE(ec_enabled);
- EXPECT_FALSE(agc_enabled);
- EXPECT_FALSE(ns_enabled);
- EXPECT_FALSE(highpass_filter_enabled);
- EXPECT_FALSE(stereo_swapping_enabled);
- EXPECT_TRUE(typing_detection_enabled);
-
- ASSERT_TRUE(engine_.SetOptions(
- cricket::MediaEngineInterface::ECHO_CANCELLATION));
voe_.GetEcStatus(ec_enabled, ec_mode);
voe_.GetEcMetricsStatus(ec_metrics_enabled);
voe_.GetAgcStatus(agc_enabled, agc_mode);
@@ -2453,107 +2563,11 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptions) {
stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
voe_.GetTypingDetectionStatus(typing_detection_enabled);
EXPECT_TRUE(ec_enabled);
- EXPECT_FALSE(agc_enabled);
- EXPECT_FALSE(ns_enabled);
- EXPECT_FALSE(highpass_filter_enabled);
- EXPECT_FALSE(stereo_swapping_enabled);
- EXPECT_TRUE(typing_detection_enabled);
-
- ASSERT_TRUE(engine_.SetOptions(
- cricket::MediaEngineInterface::AUTO_GAIN_CONTROL));
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetEcMetricsStatus(ec_metrics_enabled);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
- stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
- voe_.GetTypingDetectionStatus(typing_detection_enabled);
- EXPECT_FALSE(ec_enabled);
EXPECT_TRUE(agc_enabled);
- EXPECT_FALSE(ns_enabled);
- EXPECT_FALSE(highpass_filter_enabled);
- EXPECT_FALSE(stereo_swapping_enabled);
- EXPECT_TRUE(typing_detection_enabled);
-
- ASSERT_TRUE(engine_.SetOptions(
- cricket::MediaEngineInterface::NOISE_SUPPRESSION));
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetEcMetricsStatus(ec_metrics_enabled);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
- stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
- voe_.GetTypingDetectionStatus(typing_detection_enabled);
- EXPECT_FALSE(ec_enabled);
- EXPECT_FALSE(agc_enabled);
EXPECT_TRUE(ns_enabled);
- EXPECT_FALSE(highpass_filter_enabled);
- EXPECT_FALSE(stereo_swapping_enabled);
- EXPECT_TRUE(typing_detection_enabled);
-
- ASSERT_TRUE(engine_.SetOptions(
- cricket::MediaEngineInterface::HIGHPASS_FILTER));
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetEcMetricsStatus(ec_metrics_enabled);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
- stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
- voe_.GetTypingDetectionStatus(typing_detection_enabled);
- EXPECT_FALSE(ec_enabled);
- EXPECT_FALSE(agc_enabled);
- EXPECT_FALSE(ns_enabled);
EXPECT_TRUE(highpass_filter_enabled);
- EXPECT_FALSE(stereo_swapping_enabled);
- EXPECT_TRUE(typing_detection_enabled);
-
- ASSERT_TRUE(engine_.SetOptions(
- cricket::MediaEngineInterface::STEREO_FLIPPING));
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetEcMetricsStatus(ec_metrics_enabled);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
- stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
- voe_.GetTypingDetectionStatus(typing_detection_enabled);
- EXPECT_FALSE(ec_enabled);
- EXPECT_FALSE(agc_enabled);
- EXPECT_FALSE(ns_enabled);
- EXPECT_FALSE(highpass_filter_enabled);
- EXPECT_TRUE(stereo_swapping_enabled);
EXPECT_TRUE(typing_detection_enabled);
-
- ASSERT_TRUE(engine_.SetOptions(
- cricket::MediaEngineInterface::DEFAULT_AUDIO_OPTIONS));
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetEcMetricsStatus(ec_metrics_enabled);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
- stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
- voe_.GetTypingDetectionStatus(typing_detection_enabled);
- EXPECT_TRUE(ec_enabled);
- EXPECT_TRUE(agc_enabled);
- EXPECT_TRUE(ns_enabled);
- EXPECT_TRUE(highpass_filter_enabled);
EXPECT_FALSE(stereo_swapping_enabled);
- EXPECT_TRUE(typing_detection_enabled);
-
- ASSERT_TRUE(engine_.SetOptions(
- cricket::MediaEngineInterface::ALL_AUDIO_OPTIONS));
- voe_.GetEcStatus(ec_enabled, ec_mode);
- voe_.GetEcMetricsStatus(ec_metrics_enabled);
- voe_.GetAgcStatus(agc_enabled, agc_mode);
- voe_.GetNsStatus(ns_enabled, ns_mode);
- highpass_filter_enabled = voe_.IsHighPassFilterEnabled();
- stereo_swapping_enabled = voe_.IsStereoChannelSwappingEnabled();
- voe_.GetTypingDetectionStatus(typing_detection_enabled);
- EXPECT_TRUE(ec_enabled);
- EXPECT_TRUE(agc_enabled);
- EXPECT_TRUE(ns_enabled);
- EXPECT_TRUE(highpass_filter_enabled);
- EXPECT_TRUE(stereo_swapping_enabled);
- EXPECT_TRUE(typing_detection_enabled);
}
TEST_F(WebRtcVoiceEngineTestFake, InitDoesNotOverwriteDefaultAgcConfig) {
@@ -2625,7 +2639,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
ASSERT_TRUE(channel2->GetOptions(&actual_options));
EXPECT_EQ(expected_options, actual_options);
- ASSERT_TRUE(engine_.SetAudioOptions(options_all));
+ ASSERT_TRUE(engine_.SetOptions(options_all));
bool ec_enabled;
webrtc::EcModes ec_mode;
bool agc_enabled;
@@ -2672,7 +2686,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
EXPECT_TRUE(ns_enabled);
// Make sure settings take effect while we are sending.
- ASSERT_TRUE(engine_.SetAudioOptions(options_all));
+ ASSERT_TRUE(engine_.SetOptions(options_all));
cricket::AudioOptions options_no_agc_nor_ns;
options_no_agc_nor_ns.auto_gain_control.Set(false);
options_no_agc_nor_ns.noise_suppression.Set(false);
@@ -2692,6 +2706,33 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) {
EXPECT_FALSE(ns_enabled);
}
+// This test verifies DSCP settings are properly applied on voice media channel.
+TEST_F(WebRtcVoiceEngineTestFake, TestSetDscpOptions) {
+ EXPECT_TRUE(SetupEngine());
+ talk_base::scoped_ptr<cricket::VoiceMediaChannel> channel(
+ engine_.CreateChannel());
+ talk_base::scoped_ptr<cricket::FakeNetworkInterface> network_interface(
+ new cricket::FakeNetworkInterface);
+ channel->SetInterface(network_interface.get());
+ cricket::AudioOptions options;
+ options.dscp.Set(true);
+ EXPECT_TRUE(channel->SetOptions(options));
+ EXPECT_EQ(talk_base::DSCP_EF, network_interface->dscp());
+ options.dscp.Set(false);
+ EXPECT_TRUE(channel->SetOptions(options));
+ EXPECT_EQ(talk_base::DSCP_DEFAULT, network_interface->dscp());
+}
+
+TEST(WebRtcVoiceEngineTest, TestDefaultOptionsBeforeInit) {
+ cricket::WebRtcVoiceEngine engine;
+ cricket::AudioOptions options = engine.GetOptions();
+ // The default options should have at least a few things set. We purposefully
+ // don't check the option values here, though.
+ EXPECT_TRUE(options.echo_cancellation.IsSet());
+ EXPECT_TRUE(options.auto_gain_control.IsSet());
+ EXPECT_TRUE(options.noise_suppression.IsSet());
+}
+
// Test that GetReceiveChannelNum returns the default channel for the first
// recv stream in 1-1 calls.
TEST_F(WebRtcVoiceEngineTestFake, TestGetReceiveChannelNumIn1To1Calls) {
@@ -2797,7 +2838,7 @@ TEST(WebRtcVoiceEngineTest, HasNoMonitorThread) {
size_t size = 0;
EXPECT_TRUE(stream->GetSize(&size));
EXPECT_GT(size, 0U);
- const std::string logs(stream->GetBuffer());
+ const std::string logs(stream->GetBuffer(), size);
EXPECT_NE(std::string::npos, logs.find("ProcessThread"));
}
@@ -2871,9 +2912,9 @@ TEST(WebRtcVoiceEngineTest, HasCorrectCodecs) {
EXPECT_EQ(127, it->id);
} else if (it->name == "opus") {
EXPECT_EQ(111, it->id);
- ASSERT_NE(it->params.find("minptime"), it->params.end());
+ ASSERT_TRUE(it->params.find("minptime") != it->params.end());
EXPECT_EQ("10", it->params.find("minptime")->second);
- ASSERT_NE(it->params.find("maxptime"), it->params.end());
+ ASSERT_TRUE(it->params.find("maxptime") != it->params.end());
EXPECT_EQ("60", it->params.find("maxptime")->second);
}
}
@@ -2943,3 +2984,38 @@ TEST(WebRtcVoiceEngineTest, CoInitialize) {
#endif
+TEST_F(WebRtcVoiceEngineTestFake, SetExperimentalAcm) {
+ EXPECT_TRUE(SetupEngine());
+
+ // By default experimental ACM should not be used.
+ int media_channel = engine_.CreateMediaVoiceChannel();
+ ASSERT_GE(media_channel, 0);
+ EXPECT_FALSE(voe_.IsUsingExperimentalAcm(media_channel));
+
+ int soundclip_channel = engine_.CreateSoundclipVoiceChannel();
+ ASSERT_GE(soundclip_channel, 0);
+ EXPECT_FALSE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel));
+
+ // Set options to use experimental ACM.
+ cricket::AudioOptions options;
+ options.experimental_acm.Set(true);
+ ASSERT_TRUE(engine_.SetOptions(options));
+ media_channel = engine_.CreateMediaVoiceChannel();
+ ASSERT_GE(media_channel, 0);
+ EXPECT_TRUE(voe_.IsUsingExperimentalAcm(media_channel));
+
+ soundclip_channel = engine_.CreateSoundclipVoiceChannel();
+ ASSERT_GE(soundclip_channel, 0);
+ EXPECT_TRUE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel));
+
+ // Set option to use legacy ACM.
+ options.experimental_acm.Set(false);
+ ASSERT_TRUE(engine_.SetOptions(options));
+ media_channel = engine_.CreateMediaVoiceChannel();
+ ASSERT_GE(media_channel, 0);
+ EXPECT_FALSE(voe_.IsUsingExperimentalAcm(media_channel));
+
+ soundclip_channel = engine_.CreateSoundclipVoiceChannel();
+ ASSERT_GE(soundclip_channel, 0);
+ EXPECT_FALSE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel));
+}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket.cc b/chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket.cc
index ec00c048288..67178f4985e 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket.cc
@@ -126,7 +126,8 @@ void AsyncStunTCPSocket::ProcessInput(char* data, size_t* len) {
return;
}
- SignalReadPacket(this, data, expected_pkt_len, remote_addr);
+ SignalReadPacket(this, data, expected_pkt_len, remote_addr,
+ talk_base::CreatePacketTime(0));
*len -= actual_length;
if (*len > 0) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket_unittest.cc
index 7cb380b0aa4..c6a7b1b6fbc 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket_unittest.cc
@@ -109,7 +109,8 @@ class AsyncStunTCPSocketTest : public testing::Test,
}
void OnReadPacket(talk_base::AsyncPacketSocket* socket, const char* data,
- size_t len, const talk_base::SocketAddress& remote_addr) {
+ size_t len, const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
recv_packets_.push_back(std::string(data, len));
}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.cc b/chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.cc
index 565aed3c04e..758d4928995 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.cc
@@ -30,6 +30,9 @@
#include "talk/base/asyncudpsocket.h"
#include "talk/base/asynctcpsocket.h"
#include "talk/base/logging.h"
+#include "talk/base/nethelpers.h"
+#include "talk/base/physicalsocketserver.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/base/socketadapters.h"
#include "talk/base/thread.h"
#include "talk/p2p/base/asyncstuntcpsocket.h"
@@ -174,6 +177,10 @@ AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
return tcp_socket;
}
+AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
+ return new talk_base::AsyncResolver();
+}
+
int BasicPacketSocketFactory::BindSocket(
AsyncSocket* socket, const SocketAddress& local_address,
int min_port, int max_port) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.h b/chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.h
index d4e76e7145a..27963c9f454 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.h
@@ -51,6 +51,8 @@ class BasicPacketSocketFactory : public PacketSocketFactory {
const SocketAddress& local_address, const SocketAddress& remote_address,
const ProxyInfo& proxy_info, const std::string& user_agent, int opts);
+ virtual AsyncResolverInterface* CreateAsyncResolver();
+
private:
int BindSocket(AsyncSocket* socket, const SocketAddress& local_address,
int min_port, int max_port);
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransport.h b/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransport.h
index 93da1033e8b..7492171ee1e 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransport.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransport.h
@@ -58,6 +58,13 @@ class DtlsTransport : public Base {
virtual void SetIdentity_w(talk_base::SSLIdentity* identity) {
identity_ = identity;
}
+ virtual bool GetIdentity_w(talk_base::SSLIdentity** identity) {
+ if (!identity_)
+ return false;
+
+ *identity = identity_->GetReference();
+ return true;
+ }
virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl*
channel) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.cc b/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.cc
index dead3a550be..472299959a0 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.cc
@@ -42,6 +42,7 @@ namespace cricket {
static const size_t kDtlsRecordHeaderLen = 13;
static const size_t kMaxDtlsPacketLen = 2048;
static const size_t kMinRtpPacketLen = 12;
+static const size_t kDefaultVideoAndDataCryptos = 1;
static bool IsDtlsPacket(const char* data, size_t len) {
const uint8* u = reinterpret_cast<const uint8*>(data);
@@ -173,6 +174,15 @@ bool DtlsTransportChannelWrapper::SetLocalIdentity(
return true;
}
+bool DtlsTransportChannelWrapper::GetLocalIdentity(
+ talk_base::SSLIdentity** identity) const {
+ if (!local_identity_)
+ return false;
+
+ *identity = local_identity_->GetReference();
+ return true;
+}
+
bool DtlsTransportChannelWrapper::SetSslRole(talk_base::SSLRole role) {
if (dtls_state_ == STATE_OPEN) {
if (ssl_role_ != role) {
@@ -230,6 +240,14 @@ bool DtlsTransportChannelWrapper::SetRemoteFingerprint(
return true;
}
+bool DtlsTransportChannelWrapper::GetRemoteCertificate(
+ talk_base::SSLCertificate** cert) const {
+ if (!dtls_)
+ return false;
+
+ return dtls_->GetPeerCertificate(cert);
+}
+
bool DtlsTransportChannelWrapper::SetupDtls() {
StreamInterfaceChannel* downward =
new StreamInterfaceChannel(worker_thread_, channel_);
@@ -269,14 +287,37 @@ bool DtlsTransportChannelWrapper::SetupDtls() {
return true;
}
-bool DtlsTransportChannelWrapper::SetSrtpCiphers(const std::vector<std::string>&
- ciphers) {
- // SRTP ciphers must be set before the DTLS handshake starts.
- // TODO(juberti): In multiplex situations, we may end up calling this function
- // once for each muxed channel. Depending on the order of calls, this may
- // result in slightly undesired results, e.g. 32 vs 80-bit MAC. The right way to
- // fix this would be for the TransportProxyChannels to intersect the ciphers
- // instead of overwriting, so that "80" followed by "32, 80" results in "80".
+bool DtlsTransportChannelWrapper::SetSrtpCiphers(
+ const std::vector<std::string>& ciphers) {
+ if (srtp_ciphers_ == ciphers)
+ return true;
+
+ if (dtls_state_ == STATE_OPEN) {
+ // We don't support DTLS renegotiation currently. If new set of srtp ciphers
+ // are different than what's being used currently, we will not use it.
+ // So for now, let's be happy (or sad) with a warning message.
+ std::string current_srtp_cipher;
+ if (!dtls_->GetDtlsSrtpCipher(&current_srtp_cipher)) {
+ LOG(LS_ERROR) << "Failed to get the current SRTP cipher for DTLS channel";
+ return false;
+ }
+ const std::vector<std::string>::const_iterator iter =
+ std::find(ciphers.begin(), ciphers.end(), current_srtp_cipher);
+ if (iter == ciphers.end()) {
+ std::string requested_str;
+ for (size_t i = 0; i < ciphers.size(); ++i) {
+ requested_str.append(" ");
+ requested_str.append(ciphers[i]);
+ requested_str.append(" ");
+ }
+ LOG(LS_WARNING) << "Ignoring new set of SRTP ciphers, as DTLS "
+ << "renegotiation is not supported currently "
+ << "current cipher = " << current_srtp_cipher << " and "
+ << "requested = " << "[" << requested_str << "]";
+ }
+ return true;
+ }
+
if (dtls_state_ != STATE_NONE &&
dtls_state_ != STATE_OFFERED &&
dtls_state_ != STATE_ACCEPTED) {
@@ -405,9 +446,9 @@ void DtlsTransportChannelWrapper::OnWritableState(TransportChannel* channel) {
}
}
-void DtlsTransportChannelWrapper::OnReadPacket(TransportChannel* channel,
- const char* data, size_t size,
- int flags) {
+void DtlsTransportChannelWrapper::OnReadPacket(
+ TransportChannel* channel, const char* data, size_t size,
+ const talk_base::PacketTime& packet_time, int flags) {
ASSERT(talk_base::Thread::Current() == worker_thread_);
ASSERT(channel == channel_);
ASSERT(flags == 0);
@@ -415,7 +456,7 @@ void DtlsTransportChannelWrapper::OnReadPacket(TransportChannel* channel,
switch (dtls_state_) {
case STATE_NONE:
// We are not doing DTLS
- SignalReadPacket(this, data, size, 0);
+ SignalReadPacket(this, data, size, packet_time, 0);
break;
case STATE_OFFERED:
@@ -459,7 +500,7 @@ void DtlsTransportChannelWrapper::OnReadPacket(TransportChannel* channel,
ASSERT(!srtp_ciphers_.empty());
// Signal this upwards as a bypass packet.
- SignalReadPacket(this, data, size, PF_SRTP_BYPASS);
+ SignalReadPacket(this, data, size, packet_time, PF_SRTP_BYPASS);
}
break;
case STATE_CLOSED:
@@ -494,7 +535,7 @@ void DtlsTransportChannelWrapper::OnDtlsEvent(talk_base::StreamInterface* dtls,
char buf[kMaxDtlsPacketLen];
size_t read;
if (dtls_->Read(buf, sizeof(buf), &read, NULL) == talk_base::SR_SUCCESS) {
- SignalReadPacket(this, buf, read, 0);
+ SignalReadPacket(this, buf, read, talk_base::CreatePacketTime(0), 0);
}
}
if (sig & talk_base::SE_CLOSE) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.h b/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.h
index aec8c7ac428..d6b73467486 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.h
@@ -128,6 +128,7 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl {
return channel_->GetIceRole();
}
virtual bool SetLocalIdentity(talk_base::SSLIdentity *identity);
+ virtual bool GetLocalIdentity(talk_base::SSLIdentity** identity) const;
virtual bool SetRemoteFingerprint(const std::string& digest_alg,
const uint8* digest,
@@ -164,6 +165,10 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl {
virtual bool GetSslRole(talk_base::SSLRole* role) const;
virtual bool SetSslRole(talk_base::SSLRole role);
+ // Once DTLS has been established, this method retrieves the certificate in
+ // use by the remote peer, for use in external identity verification.
+ virtual bool GetRemoteCertificate(talk_base::SSLCertificate** cert) const;
+
// Once DTLS has established (i.e., this channel is writable), this method
// extracts the keys negotiated during the DTLS handshake, for use in external
// encryption. DTLS-SRTP uses this to extract the needed SRTP keys.
@@ -220,7 +225,7 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl {
void OnReadableState(TransportChannel* channel);
void OnWritableState(TransportChannel* channel);
void OnReadPacket(TransportChannel* channel, const char* data, size_t size,
- int flags);
+ const talk_base::PacketTime& packet_time, int flags);
void OnReadyToSend(TransportChannel* channel);
void OnDtlsEvent(talk_base::StreamInterface* stream_, int sig, int err);
bool SetupDtls();
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel_unittest.cc
index 267d60be167..1fd82d71073 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/dtlstransportchannel_unittest.cc
@@ -233,7 +233,7 @@ class DtlsTestClient : public sigslot::has_slots<> {
void SendPackets(size_t channel, size_t size, size_t count, bool srtp) {
ASSERT(channel < channels_.size());
- talk_base::scoped_array<char> packet(new char[size]);
+ talk_base::scoped_ptr<char[]> packet(new char[size]);
size_t sent = 0;
do {
// Fill the packet with a known value and a sequence number to check
@@ -307,6 +307,7 @@ class DtlsTestClient : public sigslot::has_slots<> {
void OnTransportChannelReadPacket(cricket::TransportChannel* channel,
const char* data, size_t size,
+ const talk_base::PacketTime& packet_time,
int flags) {
uint32 packet_num = 0;
ASSERT_TRUE(VerifyPacket(data, size, &packet_num));
@@ -320,6 +321,7 @@ class DtlsTestClient : public sigslot::has_slots<> {
// Hook into the raw packet stream to make sure DTLS packets are encrypted.
void OnFakeTransportChannelReadPacket(cricket::TransportChannel* channel,
const char* data, size_t size,
+ const talk_base::PacketTime& time,
int flags) {
// Flags shouldn't be set on the underlying TransportChannel packets.
ASSERT_EQ(0, flags);
@@ -751,3 +753,56 @@ TEST_F(DtlsTransportChannelTest, TestDtlsReOfferWithDifferentSetupAttr) {
TestTransfer(0, 1000, 100, true);
TestTransfer(1, 1000, 100, true);
}
+
+// Test Certificates state after negotiation but before connection.
+TEST_F(DtlsTransportChannelTest, TestCertificatesBeforeConnect) {
+ MAYBE_SKIP_TEST(HaveDtls);
+ PrepareDtls(true, true);
+ Negotiate();
+
+ talk_base::scoped_ptr<talk_base::SSLIdentity> identity1;
+ talk_base::scoped_ptr<talk_base::SSLIdentity> identity2;
+ talk_base::scoped_ptr<talk_base::SSLCertificate> remote_cert1;
+ talk_base::scoped_ptr<talk_base::SSLCertificate> remote_cert2;
+
+ // After negotiation, each side has a distinct local certificate, but still no
+ // remote certificate, because connection has not yet occurred.
+ ASSERT_TRUE(client1_.transport()->GetIdentity(identity1.accept()));
+ ASSERT_TRUE(client2_.transport()->GetIdentity(identity2.accept()));
+ ASSERT_NE(identity1->certificate().ToPEMString(),
+ identity2->certificate().ToPEMString());
+ ASSERT_FALSE(
+ client1_.transport()->GetRemoteCertificate(remote_cert1.accept()));
+ ASSERT_FALSE(remote_cert1 != NULL);
+ ASSERT_FALSE(
+ client2_.transport()->GetRemoteCertificate(remote_cert2.accept()));
+ ASSERT_FALSE(remote_cert2 != NULL);
+}
+
+// Test Certificates state after connection.
+TEST_F(DtlsTransportChannelTest, TestCertificatesAfterConnect) {
+ MAYBE_SKIP_TEST(HaveDtls);
+ PrepareDtls(true, true);
+ ASSERT_TRUE(Connect());
+
+ talk_base::scoped_ptr<talk_base::SSLIdentity> identity1;
+ talk_base::scoped_ptr<talk_base::SSLIdentity> identity2;
+ talk_base::scoped_ptr<talk_base::SSLCertificate> remote_cert1;
+ talk_base::scoped_ptr<talk_base::SSLCertificate> remote_cert2;
+
+ // After connection, each side has a distinct local certificate.
+ ASSERT_TRUE(client1_.transport()->GetIdentity(identity1.accept()));
+ ASSERT_TRUE(client2_.transport()->GetIdentity(identity2.accept()));
+ ASSERT_NE(identity1->certificate().ToPEMString(),
+ identity2->certificate().ToPEMString());
+
+ // Each side's remote certificate is the other side's local certificate.
+ ASSERT_TRUE(
+ client1_.transport()->GetRemoteCertificate(remote_cert1.accept()));
+ ASSERT_EQ(remote_cert1->ToPEMString(),
+ identity2->certificate().ToPEMString());
+ ASSERT_TRUE(
+ client2_.transport()->GetRemoteCertificate(remote_cert2.accept()));
+ ASSERT_EQ(remote_cert2->ToPEMString(),
+ identity1->certificate().ToPEMString());
+}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/fakesession.h b/chromium/third_party/libjingle/source/talk/p2p/base/fakesession.h
index d162950a3bb..2615f50dffe 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/fakesession.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/fakesession.h
@@ -33,6 +33,7 @@
#include <vector>
#include "talk/base/buffer.h"
+#include "talk/base/fakesslidentity.h"
#include "talk/base/sigslot.h"
#include "talk/base/sslfingerprint.h"
#include "talk/base/messagequeue.h"
@@ -203,7 +204,8 @@ class FakeTransportChannel : public TransportChannelImpl,
PacketMessageData* data = static_cast<PacketMessageData*>(
msg->pdata);
dest_->SignalReadPacket(dest_, data->packet.data(),
- data->packet.length(), 0);
+ data->packet.length(),
+ talk_base::CreatePacketTime(0), 0);
delete data;
}
@@ -212,11 +214,16 @@ class FakeTransportChannel : public TransportChannelImpl,
return true;
}
- bool IsDtlsActive() const {
+
+ void SetRemoteCertificate(talk_base::FakeSSLCertificate* cert) {
+ remote_cert_ = cert;
+ }
+
+ virtual bool IsDtlsActive() const {
return do_dtls_;
}
- bool SetSrtpCiphers(const std::vector<std::string>& ciphers) {
+ virtual bool SetSrtpCiphers(const std::vector<std::string>& ciphers) {
srtp_ciphers_ = ciphers;
return true;
}
@@ -229,6 +236,22 @@ class FakeTransportChannel : public TransportChannelImpl,
return false;
}
+ virtual bool GetLocalIdentity(talk_base::SSLIdentity** identity) const {
+ if (!identity_)
+ return false;
+
+ *identity = identity_->GetReference();
+ return true;
+ }
+
+ virtual bool GetRemoteCertificate(talk_base::SSLCertificate** cert) const {
+ if (!remote_cert_)
+ return false;
+
+ *cert = remote_cert_->GetReference();
+ return true;
+ }
+
virtual bool ExportKeyingMaterial(const std::string& label,
const uint8* context,
size_t context_len,
@@ -272,6 +295,7 @@ class FakeTransportChannel : public TransportChannelImpl,
State state_;
bool async_;
talk_base::SSLIdentity* identity_;
+ talk_base::FakeSSLCertificate* remote_cert_;
bool do_dtls_;
std::vector<std::string> srtp_ciphers_;
std::string chosen_srtp_cipher_;
@@ -349,6 +373,16 @@ class FakeTransport : public Transport {
channels_.erase(channel->component());
delete channel;
}
+ virtual void SetIdentity_w(talk_base::SSLIdentity* identity) {
+ identity_ = identity;
+ }
+ virtual bool GetIdentity_w(talk_base::SSLIdentity** identity) {
+ if (!identity_)
+ return false;
+
+ *identity = identity_->GetReference();
+ return true;
+ }
private:
FakeTransportChannel* GetFakeChannel(int component) {
@@ -391,6 +425,12 @@ class FakeSession : public BaseSession {
NULL, "", "", initiator),
fail_create_channel_(false) {
}
+ FakeSession(talk_base::Thread* worker_thread, bool initiator)
+ : BaseSession(talk_base::Thread::Current(),
+ worker_thread,
+ NULL, "", "", initiator),
+ fail_create_channel_(false) {
+ }
FakeTransport* GetTransport(const std::string& content_name) {
return static_cast<FakeTransport*>(
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc b/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc
index d45a66c40b6..38cc35445ea 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc
@@ -518,19 +518,21 @@ void P2PTransportChannel::OnUnknownAddress(
// request came from.
// There shouldn't be an existing connection with this remote address.
- // When ports are muxed, this channel might get multiple unknown addres
+ // When ports are muxed, this channel might get multiple unknown address
// signals. In that case if the connection is already exists, we should
// simply ignore the signal othewise send server error.
- if (port->GetConnection(new_remote_candidate.address()) && port_muxed) {
- LOG(LS_INFO) << "Connection already exist for PeerReflexive candidate: "
- << new_remote_candidate.ToString();
- return;
- } else if (port->GetConnection(new_remote_candidate.address())) {
- ASSERT(false);
- port->SendBindingErrorResponse(stun_msg, address,
- STUN_ERROR_SERVER_ERROR,
- STUN_ERROR_REASON_SERVER_ERROR);
- return;
+ if (port->GetConnection(new_remote_candidate.address())) {
+ if (port_muxed) {
+ LOG(LS_INFO) << "Connection already exists for peer reflexive "
+ << "candidate: " << new_remote_candidate.ToString();
+ return;
+ } else {
+ ASSERT(false);
+ port->SendBindingErrorResponse(stun_msg, address,
+ STUN_ERROR_SERVER_ERROR,
+ STUN_ERROR_REASON_SERVER_ERROR);
+ return;
+ }
}
Connection* connection = port->CreateConnection(
@@ -798,6 +800,7 @@ int P2PTransportChannel::SendPacket(const char *data, size_t len,
error_ = EWOULDBLOCK;
return -1;
}
+
int sent = best_connection_->Send(data, len, dscp);
if (sent <= 0) {
ASSERT(sent < 0);
@@ -1224,8 +1227,9 @@ void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
}
// We data is available, let listeners know
-void P2PTransportChannel::OnReadPacket(Connection *connection, const char *data,
- size_t len) {
+void P2PTransportChannel::OnReadPacket(
+ Connection *connection, const char *data, size_t len,
+ const talk_base::PacketTime& packet_time) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
// Do not deliver, if packet doesn't belong to the correct transport channel.
@@ -1233,7 +1237,7 @@ void P2PTransportChannel::OnReadPacket(Connection *connection, const char *data,
return;
// Let the client know of an incoming packet
- SignalReadPacket(this, data, len, 0);
+ SignalReadPacket(this, data, len, packet_time, 0);
}
void P2PTransportChannel::OnReadyToSend(Connection* connection) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h b/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h
index 2fc718641fb..6f287f369c6 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h
@@ -40,6 +40,7 @@
#include <map>
#include <vector>
#include <string>
+#include "talk/base/asyncpacketsocket.h"
#include "talk/base/sigslot.h"
#include "talk/p2p/base/candidate.h"
#include "talk/p2p/base/portinterface.h"
@@ -127,6 +128,15 @@ class P2PTransportChannel : public TransportChannelImpl,
return false;
}
+ // Returns false because the channel is not encrypted by default.
+ virtual bool GetLocalIdentity(talk_base::SSLIdentity** identity) const {
+ return false;
+ }
+
+ virtual bool GetRemoteCertificate(talk_base::SSLCertificate** cert) const {
+ return false;
+ }
+
// Allows key material to be extracted for external encryption.
virtual bool ExportKeyingMaterial(
const std::string& label,
@@ -198,8 +208,9 @@ class P2PTransportChannel : public TransportChannelImpl,
void OnPortDestroyed(PortInterface* port);
void OnRoleConflict(PortInterface* port);
- void OnConnectionStateChange(Connection *connection);
- void OnReadPacket(Connection *connection, const char *data, size_t len);
+ void OnConnectionStateChange(Connection* connection);
+ void OnReadPacket(Connection *connection, const char *data, size_t len,
+ const talk_base::PacketTime& packet_time);
void OnReadyToSend(Connection* connection);
void OnConnectionDestroyed(Connection *connection);
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel_unittest.cc
index e3cddc0e22e..3c24ded632a 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel_unittest.cc
@@ -57,6 +57,11 @@ static const int kOnlyLocalPorts = cricket::PORTALLOCATOR_DISABLE_STUN |
// Addresses on the public internet.
static const SocketAddress kPublicAddrs[2] =
{ SocketAddress("11.11.11.11", 0), SocketAddress("22.22.22.22", 0) };
+// IPv6 Addresses on the public internet.
+static const SocketAddress kIPv6PublicAddrs[2] = {
+ SocketAddress("2400:4030:1:2c00:be30:abcd:efab:cdef", 0),
+ SocketAddress("2620:0:1000:1b03:2e41:38ff:fea6:f2a4", 0)
+};
// For configuring multihomed clients.
static const SocketAddress kAlternateAddrs[2] =
{ SocketAddress("11.11.11.101", 0), SocketAddress("22.22.22.202", 0) };
@@ -608,7 +613,8 @@ class P2PTransportChannelTestBase : public testing::Test,
rch->OnCandidate(c);
}
void OnReadPacket(cricket::TransportChannel* channel, const char* data,
- size_t len, int flags) {
+ size_t len, const talk_base::PacketTime& packet_time,
+ int flags) {
std::list<std::string>& packets = GetPacketList(channel);
packets.push_front(std::string(data, len));
}
@@ -1413,6 +1419,34 @@ TEST_F(P2PTransportChannelTest, TestDefaultDscpValue) {
GetEndpoint(1)->cd1_.ch_->DefaultDscpValue());
}
+// Verify IPv6 connection is preferred over IPv4.
+TEST_F(P2PTransportChannelTest, TestIPv6Connections) {
+ AddAddress(0, kIPv6PublicAddrs[0]);
+ AddAddress(0, kPublicAddrs[0]);
+ AddAddress(1, kIPv6PublicAddrs[1]);
+ AddAddress(1, kPublicAddrs[1]);
+
+ SetAllocationStepDelay(0, kMinimumStepDelay);
+ SetAllocationStepDelay(1, kMinimumStepDelay);
+
+ // Enable IPv6
+ SetAllocatorFlags(0, cricket::PORTALLOCATOR_ENABLE_IPV6);
+ SetAllocatorFlags(1, cricket::PORTALLOCATOR_ENABLE_IPV6);
+
+ CreateChannels(1);
+
+ EXPECT_TRUE_WAIT(ep1_ch1()->readable() && ep1_ch1()->writable() &&
+ ep2_ch1()->readable() && ep2_ch1()->writable(),
+ 1000);
+ EXPECT_TRUE(
+ ep1_ch1()->best_connection() && ep2_ch1()->best_connection() &&
+ LocalCandidate(ep1_ch1())->address().EqualIPs(kIPv6PublicAddrs[0]) &&
+ RemoteCandidate(ep1_ch1())->address().EqualIPs(kIPv6PublicAddrs[1]));
+
+ TestSendRecv(1);
+ DestroyChannels();
+}
+
// Test what happens when we have 2 users behind the same NAT. This can lead
// to interesting behavior because the STUN server will only give out the
// address of the outermost NAT.
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/packetsocketfactory.h b/chromium/third_party/libjingle/source/talk/p2p/base/packetsocketfactory.h
index 882a974173b..e985b37faa6 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/packetsocketfactory.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/packetsocketfactory.h
@@ -33,6 +33,7 @@
namespace talk_base {
class AsyncPacketSocket;
+class AsyncResolverInterface;
class PacketSocketFactory {
public:
@@ -57,6 +58,8 @@ class PacketSocketFactory {
const SocketAddress& local_address, const SocketAddress& remote_address,
const ProxyInfo& proxy_info, const std::string& user_agent, int opts) = 0;
+ virtual AsyncResolverInterface* CreateAsyncResolver() = 0;
+
private:
DISALLOW_EVIL_CONSTRUCTORS(PacketSocketFactory);
};
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/port.cc b/chromium/third_party/libjingle/source/talk/p2p/base/port.cc
index 6e688dace56..24ef4271fb6 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/port.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/port.cc
@@ -162,11 +162,11 @@ static std::string ComputeFoundation(
return talk_base::ToString<uint32>(talk_base::ComputeCrc32(ost.str()));
}
-Port::Port(talk_base::Thread* thread, talk_base::Network* network,
- const talk_base::IPAddress& ip,
+Port::Port(talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
+ talk_base::Network* network, const talk_base::IPAddress& ip,
const std::string& username_fragment, const std::string& password)
: thread_(thread),
- factory_(NULL),
+ factory_(factory),
send_retransmit_count_attribute_(false),
network_(network),
ip_(ip),
@@ -924,7 +924,8 @@ void Connection::OnSendStunPacket(const void* data, size_t size,
}
}
-void Connection::OnReadPacket(const char* data, size_t size) {
+void Connection::OnReadPacket(
+ const char* data, size_t size, const talk_base::PacketTime& packet_time) {
talk_base::scoped_ptr<IceMessage> msg;
std::string remote_ufrag;
const talk_base::SocketAddress& addr(remote_candidate_.address());
@@ -938,7 +939,7 @@ void Connection::OnReadPacket(const char* data, size_t size) {
last_data_received_ = talk_base::Time();
recv_rate_tracker_.Update(size);
- SignalReadPacket(this, data, size);
+ SignalReadPacket(this, data, size, packet_time);
// If timed out sending writability checks, start up again
if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT)) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/port.h b/chromium/third_party/libjingle/source/talk/p2p/base/port.h
index 7b89e5546e8..9ea3f0c37aa 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/port.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/port.h
@@ -32,6 +32,7 @@
#include <vector>
#include <map>
+#include "talk/base/asyncpacketsocket.h"
#include "talk/base/network.h"
#include "talk/base/proxyinfo.h"
#include "talk/base/ratetracker.h"
@@ -45,10 +46,6 @@
#include "talk/p2p/base/stunrequest.h"
#include "talk/p2p/base/transport.h"
-namespace talk_base {
-class AsyncPacketSocket;
-}
-
namespace cricket {
class Connection;
@@ -118,8 +115,8 @@ struct ProtocolAddress {
class Port : public PortInterface, public talk_base::MessageHandler,
public sigslot::has_slots<> {
public:
- Port(talk_base::Thread* thread, talk_base::Network* network,
- const talk_base::IPAddress& ip,
+ Port(talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
+ talk_base::Network* network, const talk_base::IPAddress& ip,
const std::string& username_fragment, const std::string& password);
Port(talk_base::Thread* thread, const std::string& type,
talk_base::PacketSocketFactory* factory,
@@ -240,7 +237,8 @@ class Port : public PortInterface, public talk_base::MessageHandler,
// TODO(mallinath) - Make it pure virtual.
virtual bool HandleIncomingPacket(
talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
ASSERT(false);
return false;
}
@@ -470,12 +468,14 @@ class Connection : public talk_base::MessageHandler,
// Error if Send() returns < 0
virtual int GetError() = 0;
- sigslot::signal3<Connection*, const char*, size_t> SignalReadPacket;
+ sigslot::signal4<Connection*, const char*, size_t,
+ const talk_base::PacketTime&> SignalReadPacket;
sigslot::signal1<Connection*> SignalReadyToSend;
// Called when a packet is received on this connection.
- void OnReadPacket(const char* data, size_t size);
+ void OnReadPacket(const char* data, size_t size,
+ const talk_base::PacketTime& packet_time);
// Called when the socket is currently able to send.
void OnReadyToSend();
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/port_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/port_unittest.cc
index d3e02ac9f58..1122d8aea01 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/port_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/port_unittest.cc
@@ -215,7 +215,7 @@ class TestChannel : public sigslot::has_slots<> {
public:
TestChannel(Port* p1, Port* p2)
: ice_mode_(ICEMODE_FULL), src_(p1), dst_(p2), complete_count_(0),
- conn_(NULL), remote_request_(NULL), nominated_(false) {
+ conn_(NULL), remote_request_(), nominated_(false) {
src_->SignalPortComplete.connect(
this, &TestChannel::OnPortComplete);
src_->SignalUnknownAddress.connect(this, &TestChannel::OnUnknownAddress);
@@ -766,6 +766,9 @@ class FakePacketSocketFactory : public talk_base::PacketSocketFactory {
void set_next_client_tcp_socket(AsyncPacketSocket* next_client_tcp_socket) {
next_client_tcp_socket_ = next_client_tcp_socket;
}
+ talk_base::AsyncResolverInterface* CreateAsyncResolver() {
+ return NULL;
+ }
private:
AsyncPacketSocket* next_udp_socket_;
@@ -1046,7 +1049,8 @@ TEST_F(PortTest, TestLoopbackCallAsIce) {
IceMessage* msg = lport->last_stun_msg();
EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
conn->OnReadPacket(lport->last_stun_buf()->Data(),
- lport->last_stun_buf()->Length());
+ lport->last_stun_buf()->Length(),
+ talk_base::PacketTime());
ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
msg = lport->last_stun_msg();
EXPECT_EQ(STUN_BINDING_RESPONSE, msg->type());
@@ -1079,7 +1083,7 @@ TEST_F(PortTest, TestLoopbackCallAsIce) {
lport->Reset();
talk_base::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
WriteStunMessage(modified_req.get(), buf.get());
- conn1->OnReadPacket(buf->Data(), buf->Length());
+ conn1->OnReadPacket(buf->Data(), buf->Length(), talk_base::PacketTime());
ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
msg = lport->last_stun_msg();
EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, msg->type());
@@ -1117,7 +1121,8 @@ TEST_F(PortTest, TestIceRoleConflict) {
EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
// Send rport binding request to lport.
lconn->OnReadPacket(rport->last_stun_buf()->Data(),
- rport->last_stun_buf()->Length());
+ rport->last_stun_buf()->Length(),
+ talk_base::PacketTime());
ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
EXPECT_EQ(STUN_BINDING_RESPONSE, lport->last_stun_msg()->type());
@@ -1899,7 +1904,8 @@ TEST_F(PortTest, TestHandleStunBindingIndication) {
EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
// Send rport binding request to lport.
lconn->OnReadPacket(rport->last_stun_buf()->Data(),
- rport->last_stun_buf()->Length());
+ rport->last_stun_buf()->Length(),
+ talk_base::PacketTime());
ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
EXPECT_EQ(STUN_BINDING_RESPONSE, lport->last_stun_msg()->type());
uint32 last_ping_received1 = lconn->last_ping_received();
@@ -1907,7 +1913,7 @@ TEST_F(PortTest, TestHandleStunBindingIndication) {
// Adding a delay of 100ms.
talk_base::Thread::Current()->ProcessMessages(100);
// Pinging lconn using stun indication message.
- lconn->OnReadPacket(buf->Data(), buf->Length());
+ lconn->OnReadPacket(buf->Data(), buf->Length(), talk_base::PacketTime());
uint32 last_ping_received2 = lconn->last_ping_received();
EXPECT_GT(last_ping_received2, last_ping_received1);
}
@@ -2269,7 +2275,8 @@ TEST_F(PortTest, TestIceLiteConnectivity) {
// Feeding the respone message from litemode to the full mode connection.
ch1.conn()->OnReadPacket(ice_lite_port->last_stun_buf()->Data(),
- ice_lite_port->last_stun_buf()->Length());
+ ice_lite_port->last_stun_buf()->Length(),
+ talk_base::PacketTime());
// Verifying full mode connection becomes writable from the response.
EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
kTimeout);
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/pseudotcp.cc b/chromium/third_party/libjingle/source/talk/p2p/base/pseudotcp.cc
index b647fbf3dec..56aa5b019a0 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/pseudotcp.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/pseudotcp.cc
@@ -539,7 +539,7 @@ IPseudoTcpNotify::WriteResult PseudoTcp::packet(uint32 seq, uint8 flags,
uint32 now = Now();
- talk_base::scoped_array<uint8> buffer(new uint8[MAX_PACKET]);
+ talk_base::scoped_ptr<uint8[]> buffer(new uint8[MAX_PACKET]);
long_to_bytes(m_conv, buffer.get());
long_to_bytes(seq, buffer.get() + 4);
long_to_bytes(m_rcv_nxt, buffer.get() + 8);
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.cc b/chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.cc
index ec225029b8b..2baef4245ab 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.cc
@@ -257,7 +257,7 @@ void RawTransportChannel::OnReadPacket(
PortInterface* port, const char* data, size_t size,
const talk_base::SocketAddress& addr) {
ASSERT(port_ == port);
- SignalReadPacket(this, data, size, 0);
+ SignalReadPacket(this, data, size, talk_base::CreatePacketTime(0), 0);
}
void RawTransportChannel::OnMessage(talk_base::Message* msg) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.h b/chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.h
index 2aac2b5edf6..ed38952d561 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/rawtransportchannel.h
@@ -128,6 +128,15 @@ class RawTransportChannel : public TransportChannelImpl,
return false;
}
+ // Returns false because the channel is not DTLS.
+ virtual bool GetLocalIdentity(talk_base::SSLIdentity** identity) const {
+ return false;
+ }
+
+ virtual bool GetRemoteCertificate(talk_base::SSLCertificate** cert) const {
+ return false;
+ }
+
// Allows key material to be extracted for external encryption.
virtual bool ExportKeyingMaterial(
const std::string& label,
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/relayport.cc b/chromium/third_party/libjingle/source/talk/p2p/base/relayport.cc
index ff8c07c5514..ddfca7114ca 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/relayport.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/relayport.cc
@@ -155,10 +155,11 @@ class RelayEntry : public talk_base::MessageHandler,
void OnSocketClose(talk_base::AsyncPacketSocket* socket, int error);
// Called when a packet is received on this socket.
- void OnReadPacket(talk_base::AsyncPacketSocket* socket,
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr);
-
+ void OnReadPacket(
+ talk_base::AsyncPacketSocket* socket,
+ const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
// Called when the socket is currently able to send.
void OnReadyToSend(talk_base::AsyncPacketSocket* socket);
@@ -393,9 +394,11 @@ int RelayPort::GetError() {
void RelayPort::OnReadPacket(
const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr, ProtocolType proto) {
+ const talk_base::SocketAddress& remote_addr,
+ ProtocolType proto,
+ const talk_base::PacketTime& packet_time) {
if (Connection* conn = GetConnection(remote_addr)) {
- conn->OnReadPacket(data, size);
+ conn->OnReadPacket(data, size, packet_time);
} else {
Port::OnReadPacket(data, size, remote_addr, proto);
}
@@ -682,9 +685,11 @@ void RelayEntry::OnSocketClose(talk_base::AsyncPacketSocket* socket,
HandleConnectFailure(socket);
}
-void RelayEntry::OnReadPacket(talk_base::AsyncPacketSocket* socket,
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+void RelayEntry::OnReadPacket(
+ talk_base::AsyncPacketSocket* socket,
+ const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
// ASSERT(remote_addr == port_->server_addr());
// TODO: are we worried about this?
@@ -698,7 +703,7 @@ void RelayEntry::OnReadPacket(talk_base::AsyncPacketSocket* socket,
// by the server, The actual remote address is the one we recorded.
if (!port_->HasMagicCookie(data, size)) {
if (locked_) {
- port_->OnReadPacket(data, size, ext_addr_, PROTO_UDP);
+ port_->OnReadPacket(data, size, ext_addr_, PROTO_UDP, packet_time);
} else {
LOG(WARNING) << "Dropping packet: entry not locked";
}
@@ -751,7 +756,7 @@ void RelayEntry::OnReadPacket(talk_base::AsyncPacketSocket* socket,
// Process the actual data and remote address in the normal manner.
port_->OnReadPacket(data_attr->bytes(), data_attr->length(), remote_addr2,
- PROTO_UDP);
+ PROTO_UDP, packet_time);
}
void RelayEntry::OnReadyToSend(talk_base::AsyncPacketSocket* socket) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/relayport.h b/chromium/third_party/libjingle/source/talk/p2p/base/relayport.h
index c15e7e01069..08df12f9d28 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/relayport.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/relayport.h
@@ -99,7 +99,8 @@ class RelayPort : public Port {
// Dispatches the given packet to the port or connection as appropriate.
void OnReadPacket(const char* data, size_t size,
const talk_base::SocketAddress& remote_addr,
- ProtocolType proto);
+ ProtocolType proto,
+ const talk_base::PacketTime& packet_time);
private:
friend class RelayEntry;
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/relayport_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/relayport_unittest.cc
index ced8c589b5c..bd00af86de0 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/relayport_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/relayport_unittest.cc
@@ -78,7 +78,8 @@ class RelayPortTest : public testing::Test,
void OnReadPacket(talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
received_packet_count_[socket]++;
}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/relayserver.cc b/chromium/third_party/libjingle/source/talk/p2p/base/relayserver.cc
index c2cf472d3ba..c2619c03feb 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/relayserver.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/relayserver.cc
@@ -198,7 +198,8 @@ void RelayServer::OnReadEvent(talk_base::AsyncSocket* socket) {
void RelayServer::OnInternalPacket(
talk_base::AsyncPacketSocket* socket, const char* bytes, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
// Get the address of the connection we just received on.
talk_base::SocketAddressPair ap(remote_addr, socket->GetLocalAddress());
@@ -242,7 +243,8 @@ void RelayServer::OnInternalPacket(
void RelayServer::OnExternalPacket(
talk_base::AsyncPacketSocket* socket, const char* bytes, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
// Get the address of the connection we just received on.
talk_base::SocketAddressPair ap(remote_addr, socket->GetLocalAddress());
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/relayserver.h b/chromium/third_party/libjingle/source/talk/p2p/base/relayserver.h
index f3bee7eca8d..922a2562211 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/relayserver.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/relayserver.h
@@ -104,10 +104,12 @@ class RelayServer : public talk_base::MessageHandler,
// Called when a packet is received by the server on one of its sockets.
void OnInternalPacket(talk_base::AsyncPacketSocket* socket,
const char* bytes, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
void OnExternalPacket(talk_base::AsyncPacketSocket* socket,
const char* bytes, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
void OnReadEvent(talk_base::AsyncSocket* socket);
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/session.cc b/chromium/third_party/libjingle/source/talk/p2p/base/session.cc
index 3128393c349..e0f8dd3f4f8 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/session.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/session.cc
@@ -26,6 +26,8 @@
*/
#include "talk/p2p/base/session.h"
+
+#include "talk/base/bind.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
#include "talk/base/helpers.h"
@@ -44,6 +46,8 @@
namespace cricket {
+using talk_base::Bind;
+
bool BadMessage(const buzz::QName type,
const std::string& text,
MessageError* err) {
@@ -65,11 +69,13 @@ std::string TransportProxy::type() const {
}
TransportChannel* TransportProxy::GetChannel(int component) {
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
return GetChannelProxy(component);
}
TransportChannel* TransportProxy::CreateChannel(
const std::string& name, int component) {
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
ASSERT(GetChannel(component) == NULL);
ASSERT(!transport_->get()->HasChannel(component));
@@ -81,9 +87,9 @@ TransportChannel* TransportProxy::CreateChannel(
// If we're already negotiated, create an impl and hook it up to the proxy
// channel. If we're connecting, create an impl but don't hook it up yet.
if (negotiated_) {
- SetChannelProxyImpl(component, channel);
+ SetupChannelProxy_w(component, channel);
} else if (connecting_) {
- GetOrCreateChannelProxyImpl(component);
+ GetOrCreateChannelProxyImpl_w(component);
}
return channel;
}
@@ -93,6 +99,7 @@ bool TransportProxy::HasChannel(int component) {
}
void TransportProxy::DestroyChannel(int component) {
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
TransportChannel* channel = GetChannel(component);
if (channel) {
// If the state of TransportProxy is not NEGOTIATED
@@ -100,7 +107,7 @@ void TransportProxy::DestroyChannel(int component) {
// connected. Both must be connected before
// deletion.
if (!negotiated_) {
- SetChannelProxyImpl(component, GetChannelProxy(component));
+ SetupChannelProxy_w(component, GetChannelProxy(component));
}
channels_.erase(component);
@@ -130,7 +137,7 @@ void TransportProxy::CompleteNegotiation() {
if (!negotiated_) {
for (ChannelMap::iterator iter = channels_.begin();
iter != channels_.end(); ++iter) {
- SetChannelProxyImpl(iter->first, iter->second);
+ SetupChannelProxy(iter->first, iter->second);
}
negotiated_ = true;
}
@@ -191,6 +198,13 @@ TransportChannelProxy* TransportProxy::GetChannelProxyByName(
TransportChannelImpl* TransportProxy::GetOrCreateChannelProxyImpl(
int component) {
+ return worker_thread_->Invoke<TransportChannelImpl*>(Bind(
+ &TransportProxy::GetOrCreateChannelProxyImpl_w, this, component));
+}
+
+TransportChannelImpl* TransportProxy::GetOrCreateChannelProxyImpl_w(
+ int component) {
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
TransportChannelImpl* impl = transport_->get()->GetChannel(component);
if (impl == NULL) {
impl = transport_->get()->CreateChannel(component);
@@ -198,13 +212,33 @@ TransportChannelImpl* TransportProxy::GetOrCreateChannelProxyImpl(
return impl;
}
-void TransportProxy::SetChannelProxyImpl(
+void TransportProxy::SetupChannelProxy(
+ int component, TransportChannelProxy* transproxy) {
+ worker_thread_->Invoke<void>(Bind(
+ &TransportProxy::SetupChannelProxy_w, this, component, transproxy));
+}
+
+void TransportProxy::SetupChannelProxy_w(
int component, TransportChannelProxy* transproxy) {
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
TransportChannelImpl* impl = GetOrCreateChannelProxyImpl(component);
ASSERT(impl != NULL);
transproxy->SetImplementation(impl);
}
+void TransportProxy::ReplaceChannelProxyImpl(TransportChannelProxy* proxy,
+ TransportChannelImpl* impl) {
+ worker_thread_->Invoke<void>(Bind(
+ &TransportProxy::ReplaceChannelProxyImpl_w, this, proxy, impl));
+}
+
+void TransportProxy::ReplaceChannelProxyImpl_w(TransportChannelProxy* proxy,
+ TransportChannelImpl* impl) {
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
+ ASSERT(proxy != NULL);
+ proxy->SetImplementation(impl);
+}
+
// This function muxes |this| onto |target| by repointing |this| at
// |target|'s transport and setting our TransportChannelProxies
// to point to |target|'s underlying implementations.
@@ -220,12 +254,12 @@ bool TransportProxy::SetupMux(TransportProxy* target) {
iter != channels_.end(); ++iter) {
if (!target->transport_->get()->HasChannel(iter->first)) {
// Remove if channel doesn't exist in |transport_|.
- iter->second->SetImplementation(NULL);
+ ReplaceChannelProxyImpl(iter->second, NULL);
} else {
// Replace the impl for all the TransportProxyChannels with the channels
// from |target|'s transport. Fail if there's not an exact match.
- iter->second->SetImplementation(
- target->transport_->get()->CreateChannel(iter->first));
+ ReplaceChannelProxyImpl(
+ iter->second, target->transport_->get()->CreateChannel(iter->first));
}
}
@@ -489,7 +523,7 @@ TransportProxy* BaseSession::GetOrCreateTransportProxy(
transport->SignalRoleConflict.connect(
this, &BaseSession::OnRoleConflict);
- transproxy = new TransportProxy(sid_, content_name,
+ transproxy = new TransportProxy(worker_thread_, sid_, content_name,
new TransportWrapper(transport));
transproxy->SignalCandidatesReady.connect(
this, &BaseSession::OnTransportProxyCandidatesReady);
@@ -964,10 +998,11 @@ bool Session::TerminateWithReason(const std::string& reason) {
return true;
}
-bool Session::SendInfoMessage(const XmlElements& elems) {
+bool Session::SendInfoMessage(const XmlElements& elems,
+ const std::string& remote_name) {
ASSERT(signaling_thread()->IsCurrent());
SessionError error;
- if (!SendMessage(ACTION_SESSION_INFO, elems, &error)) {
+ if (!SendMessage(ACTION_SESSION_INFO, elems, remote_name, &error)) {
LOG(LS_ERROR) << "Could not send info message " << error.text;
return false;
}
@@ -1610,11 +1645,16 @@ bool Session::SendAllUnsentTransportInfoMessages(SessionError* error) {
bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
SessionError* error) {
+ return SendMessage(type, action_elems, remote_name(), error);
+}
+
+bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
+ const std::string& remote_name, SessionError* error) {
talk_base::scoped_ptr<buzz::XmlElement> stanza(
new buzz::XmlElement(buzz::QN_IQ));
SessionMessage msg(current_protocol_, type, id(), initiator_name());
- msg.to = remote_name();
+ msg.to = remote_name;
WriteSessionMessage(msg, action_elems, stanza.get());
SignalOutgoingMessage(this, stanza.get());
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/session.h b/chromium/third_party/libjingle/source/talk/p2p/base/session.h
index e05e3c0ace6..637c9424b7b 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/session.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/session.h
@@ -91,10 +91,12 @@ class TransportProxy : public sigslot::has_slots<>,
public CandidateTranslator {
public:
TransportProxy(
+ talk_base::Thread* worker_thread,
const std::string& sid,
const std::string& content_name,
TransportWrapper* transport)
- : sid_(sid),
+ : worker_thread_(worker_thread),
+ sid_(sid),
content_name_(content_name),
transport_(transport),
connecting_(false),
@@ -168,12 +170,21 @@ class TransportProxy : public sigslot::has_slots<>,
private:
TransportChannelProxy* GetChannelProxy(int component) const;
TransportChannelProxy* GetChannelProxyByName(const std::string& name) const;
- void ReplaceChannelProxyImpl(TransportChannelProxy* channel_proxy,
- size_t index);
+
TransportChannelImpl* GetOrCreateChannelProxyImpl(int component);
- void SetChannelProxyImpl(int component,
+ TransportChannelImpl* GetOrCreateChannelProxyImpl_w(int component);
+
+ // Manipulators of transportchannelimpl in channel proxy.
+ void SetupChannelProxy(int component,
TransportChannelProxy* proxy);
+ void SetupChannelProxy_w(int component,
+ TransportChannelProxy* proxy);
+ void ReplaceChannelProxyImpl(TransportChannelProxy* proxy,
+ TransportChannelImpl* impl);
+ void ReplaceChannelProxyImpl_w(TransportChannelProxy* proxy,
+ TransportChannelImpl* impl);
+ talk_base::Thread* worker_thread_;
std::string sid_;
std::string content_name_;
talk_base::scoped_refptr<TransportWrapper> transport_;
@@ -339,7 +350,7 @@ class BaseSession : public sigslot::has_slots<>,
// Returns the transport that has been negotiated or NULL if
// negotiation is still in progress.
- Transport* GetTransport(const std::string& content_name);
+ virtual Transport* GetTransport(const std::string& content_name);
// Creates a new channel with the given names. This method may be called
// immediately after creating the session. However, the actual
@@ -573,7 +584,8 @@ class Session : public BaseSession {
// arbitrary XML messages, which are called "info" messages. Sending
// takes ownership of the given elements. The signal does not; the
// parent element will be deleted after the signal.
- bool SendInfoMessage(const XmlElements& elems);
+ bool SendInfoMessage(const XmlElements& elems,
+ const std::string& remote_name);
bool SendDescriptionInfoMessage(const ContentInfos& contents);
sigslot::signal2<Session*, const buzz::XmlElement*> SignalInfoMessage;
@@ -627,7 +639,7 @@ class Session : public BaseSession {
bool ResendAllTransportInfoMessages(SessionError* error);
bool SendAllUnsentTransportInfoMessages(SessionError* error);
- // Both versions of SendMessage send a message of the given type to
+ // All versions of SendMessage send a message of the given type to
// the other client. Can pass either a set of elements or an
// "action", which must have a WriteSessionAction method to go along
// with it. Sending with an action supports sending a "hybrid"
@@ -637,6 +649,10 @@ class Session : public BaseSession {
// Takes ownership of action_elems.
bool SendMessage(ActionType type, const XmlElements& action_elems,
SessionError* error);
+ // Sends a messge, but overrides the remote name.
+ bool SendMessage(ActionType type, const XmlElements& action_elems,
+ const std::string& remote_name,
+ SessionError* error);
// When passing an action, may be Hybrid protocol.
template <typename Action>
bool SendMessage(ActionType type, const Action& action,
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/session_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/session_unittest.cc
index b64e7374221..ab4620f879e 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/session_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/session_unittest.cc
@@ -814,7 +814,7 @@ struct ChannelHandler : sigslot::has_slots<> {
}
void OnReadPacket(cricket::TransportChannel* p, const char* buf,
- size_t size, int flags) {
+ size_t size, const talk_base::PacketTime& time, int flags) {
if (memcmp(buf, name.c_str(), name.size()) != 0)
return; // drop packet if packet doesn't belong to this channel. This
// can happen when transport channels are muxed together.
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/stun.cc b/chromium/third_party/libjingle/source/talk/p2p/base/stun.cc
index 2a0f6d97830..38fc96ee1a4 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/stun.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/stun.cc
@@ -188,7 +188,7 @@ bool StunMessage::ValidateMessageIntegrity(const char* data, size_t size,
// Getting length of the message to calculate Message Integrity.
size_t mi_pos = current_pos;
- talk_base::scoped_array<char> temp_data(new char[current_pos]);
+ talk_base::scoped_ptr<char[]> temp_data(new char[current_pos]);
memcpy(temp_data.get(), data, current_pos);
if (size > mi_pos + kStunAttributeHeaderSize + kStunMessageIntegritySize) {
// Stun message has other attributes after message integrity.
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/stunport.cc b/chromium/third_party/libjingle/source/talk/p2p/base/stunport.cc
index 5e0e5002970..913f9af5f5b 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/stunport.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/stunport.cc
@@ -125,10 +125,11 @@ class StunBindingRequest : public StunRequest {
};
UDPPort::UDPPort(talk_base::Thread* thread,
+ talk_base::PacketSocketFactory* factory,
talk_base::Network* network,
talk_base::AsyncPacketSocket* socket,
const std::string& username, const std::string& password)
- : Port(thread, network, socket->GetLocalAddress().ipaddr(),
+ : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
username, password),
requests_(thread),
socket_(socket),
@@ -139,10 +140,10 @@ UDPPort::UDPPort(talk_base::Thread* thread,
}
UDPPort::UDPPort(talk_base::Thread* thread,
- talk_base::PacketSocketFactory* factory,
- talk_base::Network* network,
- const talk_base::IPAddress& ip, int min_port, int max_port,
- const std::string& username, const std::string& password)
+ talk_base::PacketSocketFactory* factory,
+ talk_base::Network* network,
+ const talk_base::IPAddress& ip, int min_port, int max_port,
+ const std::string& username, const std::string& password)
: Port(thread, LOCAL_PORT_TYPE, factory, network, ip, min_port, max_port,
username, password),
requests_(thread),
@@ -253,9 +254,10 @@ void UDPPort::OnLocalAddressReady(talk_base::AsyncPacketSocket* socket,
MaybePrepareStunCandidate();
}
-void UDPPort::OnReadPacket(talk_base::AsyncPacketSocket* socket,
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+void UDPPort::OnReadPacket(
+ talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
ASSERT(socket == socket_);
// Look for a response from the STUN server.
@@ -268,7 +270,7 @@ void UDPPort::OnReadPacket(talk_base::AsyncPacketSocket* socket,
}
if (Connection* conn = GetConnection(remote_addr)) {
- conn->OnReadPacket(data, size);
+ conn->OnReadPacket(data, size, packet_time);
} else {
Port::OnReadPacket(data, size, remote_addr, PROTO_UDP);
}
@@ -287,8 +289,13 @@ void UDPPort::SendStunBindingRequest() {
if (server_addr_.IsUnresolved()) {
ResolveStunAddress();
} else if (socket_->GetState() == talk_base::AsyncPacketSocket::STATE_BOUND) {
- if (server_addr_.family() == ip().family()) {
+ // Check if |server_addr_| is compatible with the port's ip.
+ if (IsCompatibleAddress(server_addr_)) {
requests_.Send(new StunBindingRequest(this, true, server_addr_));
+ } else {
+ // Since we can't send stun messages to the server, we should mark this
+ // port ready.
+ OnStunBindingOrResolveRequestFailed();
}
}
}
@@ -297,21 +304,21 @@ void UDPPort::ResolveStunAddress() {
if (resolver_)
return;
- resolver_ = new talk_base::AsyncResolver();
- resolver_->SignalWorkDone.connect(this, &UDPPort::OnResolveResult);
- resolver_->set_address(server_addr_);
- resolver_->Start();
+ resolver_ = socket_factory()->CreateAsyncResolver();
+ resolver_->SignalDone.connect(this, &UDPPort::OnResolveResult);
+ resolver_->Start(server_addr_);
}
-void UDPPort::OnResolveResult(talk_base::SignalThread* t) {
- ASSERT(t == resolver_);
- if (resolver_->error() != 0) {
+void UDPPort::OnResolveResult(talk_base::AsyncResolverInterface* resolver) {
+ ASSERT(resolver == resolver_);
+ if (resolver_->GetError() != 0 ||
+ !resolver_->GetResolvedAddress(ip().family(), &server_addr_)) {
LOG_J(LS_WARNING, this) << "StunPort: stun host lookup received error "
- << resolver_->error();
+ << resolver_->GetError();
OnStunBindingOrResolveRequestFailed();
+ return;
}
- server_addr_ = resolver_->address();
SendStunBindingRequest();
}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/stunport.h b/chromium/third_party/libjingle/source/talk/p2p/base/stunport.h
index 7cfed4b7cb8..a8b89c3be5d 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/stunport.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/stunport.h
@@ -46,11 +46,13 @@ namespace cricket {
class UDPPort : public Port {
public:
static UDPPort* Create(talk_base::Thread* thread,
+ talk_base::PacketSocketFactory* factory,
talk_base::Network* network,
talk_base::AsyncPacketSocket* socket,
const std::string& username,
const std::string& password) {
- UDPPort* port = new UDPPort(thread, network, socket, username, password);
+ UDPPort* port = new UDPPort(thread, factory, network, socket,
+ username, password);
if (!port->Init()) {
delete port;
port = NULL;
@@ -66,8 +68,8 @@ class UDPPort : public Port {
const std::string& username,
const std::string& password) {
UDPPort* port = new UDPPort(thread, factory, network,
- ip, min_port, max_port,
- username, password);
+ ip, min_port, max_port,
+ username, password);
if (!port->Init()) {
delete port;
port = NULL;
@@ -95,9 +97,10 @@ class UDPPort : public Port {
virtual bool HandleIncomingPacket(
talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
// All packets given to UDP port will be consumed.
- OnReadPacket(socket, data, size, remote_addr);
+ OnReadPacket(socket, data, size, remote_addr, packet_time);
return true;
}
@@ -114,8 +117,8 @@ class UDPPort : public Port {
int min_port, int max_port,
const std::string& username, const std::string& password);
- UDPPort(talk_base::Thread* thread, talk_base::Network* network,
- talk_base::AsyncPacketSocket* socket,
+ UDPPort(talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
+ talk_base::Network* network, talk_base::AsyncPacketSocket* socket,
const std::string& username, const std::string& password);
bool Init();
@@ -129,7 +132,9 @@ class UDPPort : public Port {
const talk_base::SocketAddress& address);
void OnReadPacket(talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
+
void OnReadyToSend(talk_base::AsyncPacketSocket* socket);
// This method will send STUN binding request if STUN server address is set.
@@ -141,7 +146,7 @@ class UDPPort : public Port {
private:
// DNS resolution of the STUN server.
void ResolveStunAddress();
- void OnResolveResult(talk_base::SignalThread* thread);
+ void OnResolveResult(talk_base::AsyncResolverInterface* resolver);
// Below methods handles binding request responses.
void OnStunBindingRequestSucceeded(const talk_base::SocketAddress& stun_addr);
@@ -158,7 +163,7 @@ class UDPPort : public Port {
StunRequestManager requests_;
talk_base::AsyncPacketSocket* socket_;
int error_;
- talk_base::AsyncResolver* resolver_;
+ talk_base::AsyncResolverInterface* resolver_;
bool ready_;
int stun_keepalive_delay_;
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/stunport_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/stunport_unittest.cc
index 3c1c6836f52..2a98a9fdb8b 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/stunport_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/stunport_unittest.cc
@@ -27,7 +27,10 @@
#include "talk/base/gunit.h"
#include "talk/base/helpers.h"
+#include "talk/base/physicalsocketserver.h"
+#include "talk/base/scoped_ptr.h"
#include "talk/base/socketaddress.h"
+#include "talk/base/virtualsocketserver.h"
#include "talk/p2p/base/basicpacketsocketfactory.h"
#include "talk/p2p/base/stunport.h"
#include "talk/p2p/base/teststunserver.h"
@@ -48,7 +51,10 @@ class StunPortTest : public testing::Test,
public sigslot::has_slots<> {
public:
StunPortTest()
- : network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32),
+ : pss_(new talk_base::PhysicalSocketServer),
+ ss_(new talk_base::VirtualSocketServer(pss_.get())),
+ ss_scope_(ss_.get()),
+ network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32),
socket_factory_(talk_base::Thread::Current()),
stun_server_(new cricket::TestStunServer(
talk_base::Thread::Current(), kStunAddr)),
@@ -77,7 +83,8 @@ class StunPortTest : public testing::Test,
ASSERT_TRUE(socket_ != NULL);
socket_->SignalReadPacket.connect(this, &StunPortTest::OnReadPacket);
stun_port_.reset(cricket::UDPPort::Create(
- talk_base::Thread::Current(), &network_, socket_.get(),
+ talk_base::Thread::Current(), &socket_factory_,
+ &network_, socket_.get(),
talk_base::CreateRandomString(16), talk_base::CreateRandomString(22)));
ASSERT_TRUE(stun_port_ != NULL);
stun_port_->set_server_addr(server_addr);
@@ -92,13 +99,16 @@ class StunPortTest : public testing::Test,
}
void OnReadPacket(talk_base::AsyncPacketSocket* socket, const char* data,
- size_t size, const talk_base::SocketAddress& remote_addr) {
- stun_port_->HandleIncomingPacket(socket, data, size, remote_addr);
+ size_t size, const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
+ stun_port_->HandleIncomingPacket(
+ socket, data, size, remote_addr, talk_base::PacketTime());
}
void SendData(const char* data, size_t len) {
stun_port_->HandleIncomingPacket(
- socket_.get(), data, len, talk_base::SocketAddress("22.22.22.22", 0));
+ socket_.get(), data, len, talk_base::SocketAddress("22.22.22.22", 0),
+ talk_base::PacketTime());
}
protected:
@@ -120,6 +130,9 @@ class StunPortTest : public testing::Test,
}
private:
+ talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
+ talk_base::scoped_ptr<talk_base::VirtualSocketServer> ss_;
+ talk_base::SocketServerScope ss_scope_;
talk_base::Network network_;
talk_base::BasicPacketSocketFactory socket_factory_;
talk_base::scoped_ptr<cricket::UDPPort> stun_port_;
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/stunserver.cc b/chromium/third_party/libjingle/source/talk/p2p/base/stunserver.cc
index 80719b4aa5e..062be206876 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/stunserver.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/stunserver.cc
@@ -42,7 +42,8 @@ StunServer::~StunServer() {
void StunServer::OnPacket(
talk_base::AsyncPacketSocket* socket, const char* buf, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
// Parse the STUN message; eat any messages that fail to parse.
talk_base::ByteBuffer bbuf(buf, size);
StunMessage msg;
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/stunserver.h b/chromium/third_party/libjingle/source/talk/p2p/base/stunserver.h
index 6e51ad184be..c5d12e1d15c 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/stunserver.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/stunserver.h
@@ -47,7 +47,8 @@ class StunServer : public sigslot::has_slots<> {
// Slot for AsyncSocket.PacketRead:
void OnPacket(
talk_base::AsyncPacketSocket* socket, const char* buf, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
// Handlers for the different types of STUN/TURN requests:
void OnBindingRequest(StunMessage* msg,
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/stunserver_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/stunserver_unittest.cc
index 7f4db3b7212..abb19578696 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/stunserver_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/stunserver_unittest.cc
@@ -82,6 +82,10 @@ class StunServerTest : public testing::Test {
talk_base::scoped_ptr<talk_base::TestClient> client_;
};
+// Disable for TSan v2, see
+// https://code.google.com/p/webrtc/issues/detail?id=2517 for details.
+#if !defined(THREAD_SANITIZER)
+
TEST_F(StunServerTest, TestGood) {
StunMessage req;
std::string transaction_id = "0123456789ab";
@@ -109,6 +113,8 @@ TEST_F(StunServerTest, TestGood) {
delete msg;
}
+#endif // if !defined(THREAD_SANITIZER)
+
TEST_F(StunServerTest, TestBad) {
const char* bad = "this is a completely nonsensical message whose only "
"purpose is to make the parser go 'ack'. it doesn't "
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/tcpport.cc b/chromium/third_party/libjingle/source/talk/p2p/base/tcpport.cc
index 11334c6225e..2cca82f1946 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/tcpport.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/tcpport.cc
@@ -218,7 +218,8 @@ talk_base::AsyncPacketSocket* TCPPort::GetIncoming(
void TCPPort::OnReadPacket(talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
Port::OnReadPacket(data, size, remote_addr, PROTO_TCP);
}
@@ -310,11 +311,12 @@ void TCPConnection::OnClose(talk_base::AsyncPacketSocket* socket, int error) {
set_write_state(STATE_WRITE_TIMEOUT);
}
-void TCPConnection::OnReadPacket(talk_base::AsyncPacketSocket* socket,
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+void TCPConnection::OnReadPacket(
+ talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
ASSERT(socket == socket_);
- Connection::OnReadPacket(data, size);
+ Connection::OnReadPacket(data, size, packet_time);
}
void TCPConnection::OnReadyToSend(talk_base::AsyncPacketSocket* socket) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/tcpport.h b/chromium/third_party/libjingle/source/talk/p2p/base/tcpport.h
index 599d3c66bef..77b177a2d51 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/tcpport.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/tcpport.h
@@ -102,7 +102,8 @@ class TCPPort : public Port {
// Receives packet signal from the local TCP Socket.
void OnReadPacket(talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
void OnReadyToSend(talk_base::AsyncPacketSocket* socket);
@@ -137,7 +138,8 @@ class TCPConnection : public Connection {
void OnClose(talk_base::AsyncPacketSocket* socket, int error);
void OnReadPacket(talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
void OnReadyToSend(talk_base::AsyncPacketSocket* socket);
talk_base::AsyncPacketSocket* socket_;
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/testturnserver.h b/chromium/third_party/libjingle/source/talk/p2p/base/testturnserver.h
index 32251c82c3d..7a3c83f3fa0 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/testturnserver.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/testturnserver.h
@@ -47,8 +47,7 @@ class TestTurnServer : public TurnAuthInterface {
const talk_base::SocketAddress& udp_int_addr,
const talk_base::SocketAddress& udp_ext_addr)
: server_(thread) {
- server_.AddInternalSocket(talk_base::AsyncUDPSocket::Create(
- thread->socketserver(), udp_int_addr), PROTO_UDP);
+ AddInternalSocket(udp_int_addr, cricket::PROTO_UDP);
server_.SetExternalSocketFactory(new talk_base::BasicPacketSocketFactory(),
udp_ext_addr);
server_.set_realm(kTestRealm);
@@ -62,6 +61,23 @@ class TestTurnServer : public TurnAuthInterface {
TurnServer* server() { return &server_; }
+ void AddInternalSocket(const talk_base::SocketAddress& int_addr,
+ ProtocolType proto) {
+ talk_base::Thread* thread = talk_base::Thread::Current();
+ if (proto == cricket::PROTO_UDP) {
+ server_.AddInternalSocket(talk_base::AsyncUDPSocket::Create(
+ thread->socketserver(), int_addr), proto);
+ } else if (proto == cricket::PROTO_TCP) {
+ // For TCP we need to create a server socket which can listen for incoming
+ // new connections.
+ talk_base::AsyncSocket* socket =
+ thread->socketserver()->CreateAsyncSocket(SOCK_STREAM);
+ socket->Bind(int_addr);
+ socket->Listen(5);
+ server_.AddInternalServerSocket(socket, proto);
+ }
+ }
+
private:
// For this test server, succeed if the password is the same as the username.
// Obviously, do not use this in a production environment.
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transport.cc b/chromium/third_party/libjingle/source/talk/p2p/base/transport.cc
index 3e4ad704068..4404c081a83 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transport.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transport.cc
@@ -107,6 +107,29 @@ void Transport::SetIdentity(talk_base::SSLIdentity* identity) {
worker_thread_->Invoke<void>(Bind(&Transport::SetIdentity_w, this, identity));
}
+bool Transport::GetIdentity(talk_base::SSLIdentity** identity) {
+ // The identity is set on the worker thread, so for safety it must also be
+ // acquired on the worker thread.
+ return worker_thread_->Invoke<bool>(
+ Bind(&Transport::GetIdentity_w, this, identity));
+}
+
+bool Transport::GetRemoteCertificate(talk_base::SSLCertificate** cert) {
+ // Channels can be deleted on the worker thread, so for safety the remote
+ // certificate is acquired on the worker thread.
+ return worker_thread_->Invoke<bool>(
+ Bind(&Transport::GetRemoteCertificate_w, this, cert));
+}
+
+bool Transport::GetRemoteCertificate_w(talk_base::SSLCertificate** cert) {
+ ASSERT(worker_thread()->IsCurrent());
+ if (channels_.empty())
+ return false;
+
+ ChannelMap::iterator iter = channels_.begin();
+ return iter->second->GetRemoteCertificate(cert);
+}
+
bool Transport::SetLocalTransportDescription(
const TransportDescription& description, ContentAction action) {
return worker_thread_->Invoke<bool>(Bind(
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transport.h b/chromium/third_party/libjingle/source/talk/p2p/base/transport.h
index 381215f5d1c..f9e9d887457 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transport.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transport.h
@@ -247,6 +247,12 @@ class Transport : public talk_base::MessageHandler,
// Must be called before applying local session description.
void SetIdentity(talk_base::SSLIdentity* identity);
+ // Get a copy of the local identity provided by SetIdentity.
+ bool GetIdentity(talk_base::SSLIdentity** identity);
+
+ // Get a copy of the remote certificate in use by the specified channel.
+ bool GetRemoteCertificate(talk_base::SSLCertificate** cert);
+
TransportProtocol protocol() const { return protocol_; }
// Create, destroy, and lookup the channels of this type by their components.
@@ -349,6 +355,10 @@ class Transport : public talk_base::MessageHandler,
virtual void SetIdentity_w(talk_base::SSLIdentity* identity) {}
+ virtual bool GetIdentity_w(talk_base::SSLIdentity** identity) {
+ return false;
+ }
+
// Pushes down the transport parameters from the local description, such
// as the ICE ufrag and pwd.
// Derived classes can override, but must call the base as well.
@@ -462,6 +472,8 @@ class Transport : public talk_base::MessageHandler,
bool SetRemoteTransportDescription_w(const TransportDescription& desc,
ContentAction action);
bool GetStats_w(TransportStats* infos);
+ bool GetRemoteCertificate_w(talk_base::SSLCertificate** cert);
+
talk_base::Thread* signaling_thread_;
talk_base::Thread* worker_thread_;
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportchannel.h b/chromium/third_party/libjingle/source/talk/p2p/base/transportchannel.h
index 85fff7a9f92..47ba990f35f 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportchannel.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportchannel.h
@@ -31,6 +31,7 @@
#include <string>
#include <vector>
+#include "talk/base/asyncpacketsocket.h"
#include "talk/base/basictypes.h"
#include "talk/base/dscp.h"
#include "talk/base/sigslot.h"
@@ -101,12 +102,18 @@ class TransportChannel : public sigslot::has_slots<> {
// Default implementation.
virtual bool GetSslRole(talk_base::SSLRole* role) const = 0;
- // Set up the ciphers to use for DTLS-SRTP.
+ // Sets up the ciphers to use for DTLS-SRTP.
virtual bool SetSrtpCiphers(const std::vector<std::string>& ciphers) = 0;
- // Find out which DTLS-SRTP cipher was negotiated
+ // Finds out which DTLS-SRTP cipher was negotiated
virtual bool GetSrtpCipher(std::string* cipher) = 0;
+ // Gets a copy of the local SSL identity, owned by the caller.
+ virtual bool GetLocalIdentity(talk_base::SSLIdentity** identity) const = 0;
+
+ // Gets a copy of the remote side's SSL certificate, owned by the caller.
+ virtual bool GetRemoteCertificate(talk_base::SSLCertificate** cert) const = 0;
+
// Allows key material to be extracted for external encryption.
virtual bool ExportKeyingMaterial(const std::string& label,
const uint8* context,
@@ -116,8 +123,8 @@ class TransportChannel : public sigslot::has_slots<> {
size_t result_len) = 0;
// Signalled each time a packet is received on this channel.
- sigslot::signal4<TransportChannel*, const char*,
- size_t, int> SignalReadPacket;
+ sigslot::signal5<TransportChannel*, const char*,
+ size_t, const talk_base::PacketTime&, int> SignalReadPacket;
// This signal occurs when there is a change in the way that packets are
// being routed, i.e. to a different remote location. The candidate
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelimpl.h b/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelimpl.h
index cde2441307b..d8432b73233 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelimpl.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelimpl.h
@@ -93,7 +93,10 @@ class TransportChannelImpl : public TransportChannel {
virtual void OnCandidate(const Candidate& candidate) = 0;
// DTLS methods
- // Set DTLS local identity.
+ // Set DTLS local identity. The identity object is not copied, but the caller
+ // retains ownership and must delete it after this TransportChannelImpl is
+ // destroyed.
+ // TODO(bemasc): Fix the ownership semantics of this method.
virtual bool SetLocalIdentity(talk_base::SSLIdentity* identity) = 0;
// Set DTLS Remote fingerprint. Must be after local identity set.
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.cc b/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.cc
index 04b32ce6499..0d8cace2a86 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.cc
@@ -27,6 +27,7 @@
#include "talk/p2p/base/transportchannelproxy.h"
#include "talk/base/common.h"
+#include "talk/base/logging.h"
#include "talk/base/thread.h"
#include "talk/p2p/base/transport.h"
#include "talk/p2p/base/transportchannelimpl.h"
@@ -54,8 +55,15 @@ TransportChannelProxy::~TransportChannelProxy() {
}
void TransportChannelProxy::SetImplementation(TransportChannelImpl* impl) {
- // TODO(juberti): Fix this to occur on the correct thread.
- // ASSERT(talk_base::Thread::Current() == worker_thread_);
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
+
+ if (impl == impl_) {
+ ASSERT(false);
+ // Ignore if the |impl| has already been set.
+ LOG(LS_WARNING) << "Ignored TransportChannelProxy::SetImplementation call "
+ << "with a same impl as the existing one.";
+ return;
+ }
// Destroy any existing impl_.
if (impl_) {
@@ -172,6 +180,24 @@ bool TransportChannelProxy::GetSrtpCipher(std::string* cipher) {
return impl_->GetSrtpCipher(cipher);
}
+bool TransportChannelProxy::GetLocalIdentity(
+ talk_base::SSLIdentity** identity) const {
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
+ if (!impl_) {
+ return false;
+ }
+ return impl_->GetLocalIdentity(identity);
+}
+
+bool TransportChannelProxy::GetRemoteCertificate(
+ talk_base::SSLCertificate** cert) const {
+ ASSERT(talk_base::Thread::Current() == worker_thread_);
+ if (!impl_) {
+ return false;
+ }
+ return impl_->GetRemoteCertificate(cert);
+}
+
bool TransportChannelProxy::ExportKeyingMaterial(const std::string& label,
const uint8* context,
size_t context_len,
@@ -208,12 +234,12 @@ void TransportChannelProxy::OnWritableState(TransportChannel* channel) {
// Note: SignalWritableState fired by set_readable.
}
-void TransportChannelProxy::OnReadPacket(TransportChannel* channel,
- const char* data, size_t size,
- int flags) {
+void TransportChannelProxy::OnReadPacket(
+ TransportChannel* channel, const char* data, size_t size,
+ const talk_base::PacketTime& packet_time, int flags) {
ASSERT(talk_base::Thread::Current() == worker_thread_);
ASSERT(channel == impl_);
- SignalReadPacket(this, data, size, flags);
+ SignalReadPacket(this, data, size, packet_time, flags);
}
void TransportChannelProxy::OnReadyToSend(TransportChannel* channel) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.h b/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.h
index 29f46634198..196d0f6cfab 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportchannelproxy.h
@@ -75,6 +75,8 @@ class TransportChannelProxy : public TransportChannel,
virtual bool SetSslRole(talk_base::SSLRole role);
virtual bool SetSrtpCiphers(const std::vector<std::string>& ciphers);
virtual bool GetSrtpCipher(std::string* cipher);
+ virtual bool GetLocalIdentity(talk_base::SSLIdentity** identity) const;
+ virtual bool GetRemoteCertificate(talk_base::SSLCertificate** cert) const;
virtual bool ExportKeyingMaterial(const std::string& label,
const uint8* context,
size_t context_len,
@@ -88,7 +90,7 @@ class TransportChannelProxy : public TransportChannel,
void OnReadableState(TransportChannel* channel);
void OnWritableState(TransportChannel* channel);
void OnReadPacket(TransportChannel* channel, const char* data, size_t size,
- int flags);
+ const talk_base::PacketTime& packet_time, int flags);
void OnReadyToSend(TransportChannel* channel);
void OnRouteChange(TransportChannel* channel, const Candidate& candidate);
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.cc b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.cc
index 56873427284..2793d6c617a 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.cc
@@ -48,5 +48,25 @@ bool StringToConnectionRole(const std::string& role_str, ConnectionRole* role) {
return false;
}
+bool ConnectionRoleToString(const ConnectionRole& role, std::string* role_str) {
+ switch (role) {
+ case cricket::CONNECTIONROLE_ACTIVE:
+ *role_str = cricket::CONNECTIONROLE_ACTIVE_STR;
+ break;
+ case cricket::CONNECTIONROLE_ACTPASS:
+ *role_str = cricket::CONNECTIONROLE_ACTPASS_STR;
+ break;
+ case cricket::CONNECTIONROLE_PASSIVE:
+ *role_str = cricket::CONNECTIONROLE_PASSIVE_STR;
+ break;
+ case cricket::CONNECTIONROLE_HOLDCONN:
+ *role_str = cricket::CONNECTIONROLE_HOLDCONN_STR;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.h b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.h
index 64fbb89a808..59dfa0b47de 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescription.h
@@ -94,6 +94,7 @@ extern const char CONNECTIONROLE_ACTPASS_STR[];
extern const char CONNECTIONROLE_HOLDCONN_STR[];
bool StringToConnectionRole(const std::string& role_str, ConnectionRole* role);
+bool ConnectionRoleToString(const ConnectionRole& role, std::string* role_str);
typedef std::vector<Candidate> Candidates;
@@ -159,7 +160,7 @@ struct TransportDescription {
void AddOption(const std::string& option) {
transport_options.push_back(option);
}
- bool secure() { return identity_fingerprint != NULL; }
+ bool secure() const { return identity_fingerprint != NULL; }
static talk_base::SSLFingerprint* CopyFingerprint(
const talk_base::SSLFingerprint* from) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.cc b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.cc
index 0c129437ccb..c8fb0b34f87 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.cc
@@ -37,13 +37,11 @@
namespace cricket {
static TransportProtocol kDefaultProtocol = ICEPROTO_GOOGLE;
-static const char* kDefaultDigestAlg = talk_base::DIGEST_SHA_1;
TransportDescriptionFactory::TransportDescriptionFactory()
: protocol_(kDefaultProtocol),
secure_(SEC_DISABLED),
- identity_(NULL),
- digest_alg_(kDefaultDigestAlg) {
+ identity_(NULL) {
}
TransportDescription* TransportDescriptionFactory::CreateOffer(
@@ -153,10 +151,20 @@ bool TransportDescriptionFactory::SetSecurityInfo(
return false;
}
+ // This digest algorithm is used to produce the a=fingerprint lines in SDP.
+ // RFC 4572 Section 5 requires that those lines use the same hash function as
+ // the certificate's signature.
+ std::string digest_alg;
+ if (!identity_->certificate().GetSignatureDigestAlgorithm(&digest_alg)) {
+ LOG(LS_ERROR) << "Failed to retrieve the certificate's digest algorithm";
+ return false;
+ }
+
desc->identity_fingerprint.reset(
- talk_base::SSLFingerprint::Create(digest_alg_, identity_));
+ talk_base::SSLFingerprint::Create(digest_alg, identity_));
if (!desc->identity_fingerprint.get()) {
- LOG(LS_ERROR) << "Failed to create identity digest, alg=" << digest_alg_;
+ LOG(LS_ERROR) << "Failed to create identity fingerprint, alg="
+ << digest_alg;
return false;
}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.h b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.h
index ddf27998188..53dd238dbe0 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.h
@@ -59,8 +59,6 @@ class TransportDescriptionFactory {
void set_secure(SecurePolicy s) { secure_ = s; }
// Specifies the identity to use (only used when secure is not SEC_DISABLED).
void set_identity(talk_base::SSLIdentity* identity) { identity_ = identity; }
- // Specifies the algorithm to use when creating an identity digest.
- void set_digest_algorithm(const std::string& alg) { digest_alg_ = alg; }
// Creates a transport description suitable for use in an offer.
TransportDescription* CreateOffer(const TransportOptions& options,
@@ -78,7 +76,6 @@ class TransportDescriptionFactory {
TransportProtocol protocol_;
SecurePolicy secure_;
talk_base::SSLIdentity* identity_;
- std::string digest_alg_;
};
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory_unittest.cc
index c0c88297f0c..8d9a73f56fc 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory_unittest.cc
@@ -39,16 +39,11 @@ using cricket::TransportDescriptionFactory;
using cricket::TransportDescription;
using cricket::TransportOptions;
-// TODO(juberti): Change this to SHA-256 once we have Win32 using OpenSSL.
-static const char* kDefaultDigestAlg = talk_base::DIGEST_SHA_1;
-
class TransportDescriptionFactoryTest : public testing::Test {
public:
TransportDescriptionFactoryTest()
: id1_(new talk_base::FakeSSLIdentity("User1")),
id2_(new talk_base::FakeSSLIdentity("User2")) {
- f1_.set_digest_algorithm(kDefaultDigestAlg);
- f2_.set_digest_algorithm(kDefaultDigestAlg);
}
void CheckDesc(const TransportDescription* desc, const std::string& type,
const std::string& opt, const std::string& ice_ufrag,
@@ -167,15 +162,17 @@ TEST_F(TransportDescriptionFactoryTest, TestOfferHybridDtls) {
f1_.set_protocol(cricket::ICEPROTO_HYBRID);
f1_.set_secure(cricket::SEC_ENABLED);
f1_.set_identity(id1_.get());
+ std::string digest_alg;
+ ASSERT_TRUE(id1_->certificate().GetSignatureDigestAlgorithm(&digest_alg));
scoped_ptr<TransportDescription> desc(f1_.CreateOffer(
TransportOptions(), NULL));
CheckDesc(desc.get(), cricket::NS_JINGLE_ICE_UDP, "google-ice", "", "",
- kDefaultDigestAlg);
+ digest_alg);
// Ensure it also works with SEC_REQUIRED.
f1_.set_secure(cricket::SEC_REQUIRED);
desc.reset(f1_.CreateOffer(TransportOptions(), NULL));
CheckDesc(desc.get(), cricket::NS_JINGLE_ICE_UDP, "google-ice", "", "",
- kDefaultDigestAlg);
+ digest_alg);
}
// Test generating a hybrid offer with DTLS fails with no identity.
@@ -187,23 +184,14 @@ TEST_F(TransportDescriptionFactoryTest, TestOfferHybridDtlsWithNoIdentity) {
ASSERT_TRUE(desc.get() == NULL);
}
-// Test generating a hybrid offer with DTLS fails with an unsupported digest.
-TEST_F(TransportDescriptionFactoryTest, TestOfferHybridDtlsWithBadDigestAlg) {
- f1_.set_protocol(cricket::ICEPROTO_HYBRID);
- f1_.set_secure(cricket::SEC_ENABLED);
- f1_.set_identity(id1_.get());
- f1_.set_digest_algorithm("bogus");
- scoped_ptr<TransportDescription> desc(f1_.CreateOffer(
- TransportOptions(), NULL));
- ASSERT_TRUE(desc.get() == NULL);
-}
-
// Test updating a hybrid offer with DTLS to pick ICE.
// The ICE credentials should stay the same in the new offer.
TEST_F(TransportDescriptionFactoryTest, TestOfferHybridDtlsReofferIceDtls) {
f1_.set_protocol(cricket::ICEPROTO_HYBRID);
f1_.set_secure(cricket::SEC_ENABLED);
f1_.set_identity(id1_.get());
+ std::string digest_alg;
+ ASSERT_TRUE(id1_->certificate().GetSignatureDigestAlgorithm(&digest_alg));
scoped_ptr<TransportDescription> old_desc(f1_.CreateOffer(
TransportOptions(), NULL));
ASSERT_TRUE(old_desc.get() != NULL);
@@ -211,7 +199,7 @@ TEST_F(TransportDescriptionFactoryTest, TestOfferHybridDtlsReofferIceDtls) {
scoped_ptr<TransportDescription> desc(
f1_.CreateOffer(TransportOptions(), old_desc.get()));
CheckDesc(desc.get(), cricket::NS_JINGLE_ICE_UDP, "",
- old_desc->ice_ufrag, old_desc->ice_pwd, kDefaultDigestAlg);
+ old_desc->ice_ufrag, old_desc->ice_pwd, digest_alg);
}
// Test that we can answer a GICE offer with GICE.
@@ -358,21 +346,25 @@ TEST_F(TransportDescriptionFactoryTest, TestAnswerHybridDtlsToHybridDtls) {
f1_.set_protocol(cricket::ICEPROTO_HYBRID);
f1_.set_secure(cricket::SEC_ENABLED);
f1_.set_identity(id1_.get());
+
f2_.set_protocol(cricket::ICEPROTO_HYBRID);
f2_.set_secure(cricket::SEC_ENABLED);
f2_.set_identity(id2_.get());
+ // f2_ produces the answer that is being checked in this test, so the
+ // answer must contain fingerprint lines with id2_'s digest algorithm.
+ std::string digest_alg2;
+ ASSERT_TRUE(id2_->certificate().GetSignatureDigestAlgorithm(&digest_alg2));
+
scoped_ptr<TransportDescription> offer(
f1_.CreateOffer(TransportOptions(), NULL));
ASSERT_TRUE(offer.get() != NULL);
scoped_ptr<TransportDescription> desc(
f2_.CreateAnswer(offer.get(), TransportOptions(), NULL));
- CheckDesc(desc.get(), cricket::NS_JINGLE_ICE_UDP, "", "", "",
- kDefaultDigestAlg);
+ CheckDesc(desc.get(), cricket::NS_JINGLE_ICE_UDP, "", "", "", digest_alg2);
f2_.set_secure(cricket::SEC_REQUIRED);
desc.reset(f2_.CreateAnswer(offer.get(), TransportOptions(),
NULL));
- CheckDesc(desc.get(), cricket::NS_JINGLE_ICE_UDP, "", "", "",
- kDefaultDigestAlg);
+ CheckDesc(desc.get(), cricket::NS_JINGLE_ICE_UDP, "", "", "", digest_alg2);
}
// Test that ice ufrag and password is changed in an updated offer and answer
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/turnport.cc b/chromium/third_party/libjingle/source/talk/p2p/base/turnport.cc
index 35e51fc2da8..01d7f9c8998 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/turnport.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/turnport.cc
@@ -214,6 +214,14 @@ void TurnPort::PrepareAddress() {
if (server_address_.address.IsUnresolved()) {
ResolveTurnAddress(server_address_.address);
} else {
+ // If protocol family of server address doesn't match with local, return.
+ if (!IsCompatibleAddress(server_address_.address)) {
+ LOG(LS_ERROR) << "Server IP address family does not match with "
+ << "local host address family type";
+ OnAllocateError();
+ return;
+ }
+
LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
<< ProtoToString(server_address_.proto) << " @ "
<< server_address_.address.ToSensitiveString();
@@ -348,9 +356,10 @@ int TurnPort::SendTo(const void* data, size_t size,
return static_cast<int>(size);
}
-void TurnPort::OnReadPacket(talk_base::AsyncPacketSocket* socket,
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+void TurnPort::OnReadPacket(
+ talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
ASSERT(socket == socket_.get());
ASSERT(remote_addr == server_address_.address);
@@ -365,9 +374,9 @@ void TurnPort::OnReadPacket(talk_base::AsyncPacketSocket* socket,
// a response to a previous request.
uint16 msg_type = talk_base::GetBE16(data);
if (IsTurnChannelData(msg_type)) {
- HandleChannelData(msg_type, data, size);
+ HandleChannelData(msg_type, data, size, packet_time);
} else if (msg_type == TURN_DATA_INDICATION) {
- HandleDataIndication(data, size);
+ HandleDataIndication(data, size, packet_time);
} else {
// This must be a response for one of our requests.
// Check success responses, but not errors, for MESSAGE-INTEGRITY.
@@ -391,22 +400,21 @@ void TurnPort::ResolveTurnAddress(const talk_base::SocketAddress& address) {
if (resolver_)
return;
- resolver_ = new talk_base::AsyncResolver();
- resolver_->SignalWorkDone.connect(this, &TurnPort::OnResolveResult);
- resolver_->set_address(address);
- resolver_->Start();
+ resolver_ = socket_factory()->CreateAsyncResolver();
+ resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult);
+ resolver_->Start(address);
}
-void TurnPort::OnResolveResult(talk_base::SignalThread* signal_thread) {
- ASSERT(signal_thread == resolver_);
- if (resolver_->error() != 0) {
+void TurnPort::OnResolveResult(talk_base::AsyncResolverInterface* resolver) {
+ ASSERT(resolver == resolver_);
+ if (resolver_->GetError() != 0 ||
+ !resolver_->GetResolvedAddress(ip().family(), &server_address_.address)) {
LOG_J(LS_WARNING, this) << "TURN host lookup received error "
- << resolver_->error();
+ << resolver_->GetError();
OnAllocateError();
return;
}
- server_address_.address = resolver_->address();
PrepareAddress();
}
@@ -453,7 +461,8 @@ void TurnPort::OnAllocateRequestTimeout() {
OnAllocateError();
}
-void TurnPort::HandleDataIndication(const char* data, size_t size) {
+void TurnPort::HandleDataIndication(const char* data, size_t size,
+ const talk_base::PacketTime& packet_time) {
// Read in the message, and process according to RFC5766, Section 10.4.
talk_base::ByteBuffer buf(data, size);
TurnMessage msg;
@@ -488,11 +497,13 @@ void TurnPort::HandleDataIndication(const char* data, size_t size) {
return;
}
- DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr, PROTO_UDP);
+ DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr,
+ PROTO_UDP, packet_time);
}
void TurnPort::HandleChannelData(int channel_id, const char* data,
- size_t size) {
+ size_t size,
+ const talk_base::PacketTime& packet_time) {
// Read the message, and process according to RFC5766, Section 11.6.
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -524,13 +535,14 @@ void TurnPort::HandleChannelData(int channel_id, const char* data,
}
DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(),
- PROTO_UDP);
+ PROTO_UDP, packet_time);
}
void TurnPort::DispatchPacket(const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr, ProtocolType proto) {
+ const talk_base::SocketAddress& remote_addr,
+ ProtocolType proto, const talk_base::PacketTime& packet_time) {
if (Connection* conn = GetConnection(remote_addr)) {
- conn->OnReadPacket(data, size);
+ conn->OnReadPacket(data, size, packet_time);
} else {
Port::OnReadPacket(data, size, remote_addr, proto);
}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/turnport.h b/chromium/third_party/libjingle/source/talk/p2p/base/turnport.h
index 4462b0c8c99..e380a8912f7 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/turnport.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/turnport.h
@@ -32,11 +32,11 @@
#include <string>
#include <list>
+#include "talk/base/asyncpacketsocket.h"
#include "talk/p2p/base/port.h"
#include "talk/p2p/client/basicportallocator.h"
namespace talk_base {
-class AsyncPacketSocket;
class AsyncResolver;
class SignalThread;
}
@@ -79,9 +79,10 @@ class TurnPort : public Port {
virtual int SetOption(talk_base::Socket::Option opt, int value);
virtual int GetOption(talk_base::Socket::Option opt, int* value);
virtual int GetError();
- virtual void OnReadPacket(talk_base::AsyncPacketSocket* socket,
- const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ virtual void OnReadPacket(
+ talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
virtual void OnReadyToSend(talk_base::AsyncPacketSocket* socket);
void OnSocketConnect(talk_base::AsyncPacketSocket* socket);
@@ -123,7 +124,7 @@ class TurnPort : public Port {
}
void ResolveTurnAddress(const talk_base::SocketAddress& address);
- void OnResolveResult(talk_base::SignalThread* signal_thread);
+ void OnResolveResult(talk_base::AsyncResolverInterface* resolver);
void AddRequestAuthInfo(StunMessage* msg);
void OnSendStunPacket(const void* data, size_t size, StunRequest* request);
@@ -134,10 +135,13 @@ class TurnPort : public Port {
void OnAllocateError();
void OnAllocateRequestTimeout();
- void HandleDataIndication(const char* data, size_t size);
- void HandleChannelData(int channel_id, const char* data, size_t size);
+ void HandleDataIndication(const char* data, size_t size,
+ const talk_base::PacketTime& packet_time);
+ void HandleChannelData(int channel_id, const char* data, size_t size,
+ const talk_base::PacketTime& packet_time);
void DispatchPacket(const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr, ProtocolType proto);
+ const talk_base::SocketAddress& remote_addr,
+ ProtocolType proto, const talk_base::PacketTime& packet_time);
bool ScheduleRefresh(int lifetime);
void SendRequest(StunRequest* request, int delay);
@@ -157,7 +161,7 @@ class TurnPort : public Port {
talk_base::scoped_ptr<talk_base::AsyncPacketSocket> socket_;
SocketOptionsMap socket_options_;
- talk_base::AsyncResolver* resolver_;
+ talk_base::AsyncResolverInterface* resolver_;
int error_;
StunRequestManager request_manager_;
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/turnport_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/base/turnport_unittest.cc
index 726175c5c2f..d559894ac56 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/turnport_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/turnport_unittest.cc
@@ -53,11 +53,17 @@ using cricket::UDPPort;
static const SocketAddress kLocalAddr1("11.11.11.11", 0);
static const SocketAddress kLocalAddr2("22.22.22.22", 0);
+static const SocketAddress kLocalIPv6Addr(
+ "2401:fa00:4:1000:be30:5bff:fee5:c3", 0);
static const SocketAddress kTurnUdpIntAddr("99.99.99.3",
cricket::TURN_SERVER_PORT);
static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
cricket::TURN_SERVER_PORT);
static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
+static const SocketAddress kTurnUdpIPv6IntAddr(
+ "2400:4030:1:2c00:be30:abcd:efab:cdef", cricket::TURN_SERVER_PORT);
+static const SocketAddress kTurnUdpIPv6ExtAddr(
+ "2620:0:1000:1b03:2e41:38ff:fea6:f2a4", 0);
static const char kIceUfrag1[] = "TESTICEUFRAG0001";
static const char kIceUfrag2[] = "TESTICEUFRAG0002";
@@ -71,6 +77,8 @@ static const cricket::ProtocolAddress kTurnUdpProtoAddr(
kTurnUdpIntAddr, cricket::PROTO_UDP);
static const cricket::ProtocolAddress kTurnTcpProtoAddr(
kTurnTcpIntAddr, cricket::PROTO_TCP);
+static const cricket::ProtocolAddress kTurnUdpIPv6ProtoAddr(
+ kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
class TurnPortTest : public testing::Test,
public sigslot::has_slots<> {
@@ -110,13 +118,15 @@ class TurnPortTest : public testing::Test,
turn_create_permission_success_ = true;
}
}
- void OnTurnReadPacket(Connection* conn, const char* data, size_t size) {
+ void OnTurnReadPacket(Connection* conn, const char* data, size_t size,
+ const talk_base::PacketTime& packet_time) {
turn_packets_.push_back(talk_base::Buffer(data, size));
}
void OnUdpPortComplete(Port* port) {
udp_ready_ = true;
}
- void OnUdpReadPacket(Connection* conn, const char* data, size_t size) {
+ void OnUdpReadPacket(Connection* conn, const char* data, size_t size,
+ const talk_base::PacketTime& packet_time) {
udp_packets_.push_back(talk_base::Buffer(data, size));
}
@@ -130,9 +140,15 @@ class TurnPortTest : public testing::Test,
void CreateTurnPort(const std::string& username,
const std::string& password,
const cricket::ProtocolAddress& server_address) {
+ CreateTurnPort(kLocalAddr1, username, password, server_address);
+ }
+ void CreateTurnPort(const talk_base::SocketAddress& local_address,
+ const std::string& username,
+ const std::string& password,
+ const cricket::ProtocolAddress& server_address) {
cricket::RelayCredentials credentials(username, password);
turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
- kLocalAddr1.ipaddr(), 0, 0,
+ local_address.ipaddr(), 0, 0,
kIceUfrag1, kIcePwd1,
server_address, credentials));
turn_port_->SignalPortComplete.connect(this,
@@ -265,10 +281,7 @@ TEST_F(TurnPortTest, TestTurnAllocate) {
}
TEST_F(TurnPortTest, TestTurnTcpAllocate) {
- talk_base::AsyncSocket* tcp_server_socket =
- CreateServerSocket(kTurnTcpIntAddr);
- turn_server_.server()->AddInternalServerSocket(
- tcp_server_socket, cricket::PROTO_TCP);
+ turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
EXPECT_EQ(0, turn_port_->SetOption(talk_base::Socket::OPT_SNDBUF, 10*1024));
turn_port_->PrepareAddress();
@@ -298,10 +311,7 @@ TEST_F(TurnPortTest, TestTurnConnection) {
// Test that we can establish a TCP connection with TURN server.
TEST_F(TurnPortTest, TestTurnTcpConnection) {
- talk_base::AsyncSocket* tcp_server_socket =
- CreateServerSocket(kTurnTcpIntAddr);
- turn_server_.server()->AddInternalServerSocket(
- tcp_server_socket, cricket::PROTO_TCP);
+ turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
TestTurnConnection();
}
@@ -327,19 +337,44 @@ TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) {
TestTurnConnection();
}
-// Do a TURN allocation, establish a connection, and send some data.
+// Do a TURN allocation, establish a UDP connection, and send some data.
TEST_F(TurnPortTest, TestTurnSendDataTurnUdpToUdp) {
// Create ports and prepare addresses.
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
TestTurnSendData();
}
+// Do a TURN allocation, establish a TCP connection, and send some data.
TEST_F(TurnPortTest, TestTurnSendDataTurnTcpToUdp) {
- talk_base::AsyncSocket* tcp_server_socket =
- CreateServerSocket(kTurnTcpIntAddr);
- turn_server_.server()->AddInternalServerSocket(
- tcp_server_socket, cricket::PROTO_TCP);
+ turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
// Create ports and prepare addresses.
CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
TestTurnSendData();
}
+
+// Test TURN fails to make a connection from IPv6 address to a server which has
+// IPv4 address.
+TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv4) {
+ turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
+ CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
+ kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+ ASSERT_TRUE_WAIT(turn_error_, kTimeout);
+ EXPECT_TRUE(turn_port_->Candidates().empty());
+}
+
+// Test TURN make a connection from IPv6 address to a server which has
+// IPv6 intenal address. But in this test external address is a IPv4 address,
+// hence allocated address will be a IPv4 address.
+TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv6ExtenalIPv4) {
+ turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
+ CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
+ kTurnUdpIPv6ProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ ASSERT_EQ(1U, turn_port_->Candidates().size());
+ EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
+ turn_port_->Candidates()[0].address().ipaddr());
+ EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
+}
+
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/turnserver.cc b/chromium/third_party/libjingle/source/talk/p2p/base/turnserver.cc
index 17ecf3507c6..0bd903abe22 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/turnserver.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/turnserver.cc
@@ -109,7 +109,8 @@ class TurnServer::Allocation : public talk_base::MessageHandler,
void OnExternalPacket(talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& addr);
+ const talk_base::SocketAddress& addr,
+ const talk_base::PacketTime& packet_time);
static int ComputeLifetime(const TurnMessage* msg);
bool HasPermission(const talk_base::IPAddress& addr);
@@ -280,7 +281,8 @@ void TurnServer::OnInternalSocketClose(talk_base::AsyncPacketSocket* socket,
void TurnServer::OnInternalPacket(talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& addr) {
+ const talk_base::SocketAddress& addr,
+ const talk_base::PacketTime& packet_time) {
// Fail if the packet is too small to even contain a channel header.
if (size < TURN_CHANNEL_HEADER_SIZE) {
return;
@@ -838,7 +840,8 @@ void TurnServer::Allocation::HandleChannelData(const char* data, size_t size) {
void TurnServer::Allocation::OnExternalPacket(
talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& addr) {
+ const talk_base::SocketAddress& addr,
+ const talk_base::PacketTime& packet_time) {
ASSERT(external_socket_.get() == socket);
Channel* channel = FindChannel(addr);
if (channel) {
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/turnserver.h b/chromium/third_party/libjingle/source/talk/p2p/base/turnserver.h
index 56ce2fcb071..2c33cdb4b7b 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/base/turnserver.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/base/turnserver.h
@@ -33,13 +33,13 @@
#include <set>
#include <string>
+#include "talk/base/asyncpacketsocket.h"
#include "talk/base/messagequeue.h"
#include "talk/base/sigslot.h"
#include "talk/base/socketaddress.h"
#include "talk/p2p/base/portinterface.h"
namespace talk_base {
-class AsyncPacketSocket;
class ByteBuffer;
class PacketSocketFactory;
class Thread;
@@ -123,7 +123,8 @@ class TurnServer : public sigslot::has_slots<> {
typedef std::map<Connection, Allocation*> AllocationMap;
void OnInternalPacket(talk_base::AsyncPacketSocket* socket, const char* data,
- size_t size, const talk_base::SocketAddress& address);
+ size_t size, const talk_base::SocketAddress& address,
+ const talk_base::PacketTime& packet_time);
void OnNewInternalConnection(talk_base::AsyncSocket* socket);
diff --git a/chromium/third_party/libjingle/source/talk/p2p/client/basicportallocator.cc b/chromium/third_party/libjingle/source/talk/p2p/client/basicportallocator.cc
index a728d989b1b..dbc2e3342ee 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/client/basicportallocator.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/client/basicportallocator.cc
@@ -149,7 +149,9 @@ class AllocationSequence : public talk_base::MessageHandler,
void OnReadPacket(talk_base::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr);
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time);
+
void OnPortDestroyed(PortInterface* port);
BasicPortAllocatorSession* session_;
@@ -708,7 +710,7 @@ AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
config_(config),
state_(kInit),
flags_(flags),
- udp_socket_(NULL),
+ udp_socket_(),
phase_(0) {
}
@@ -857,7 +859,8 @@ void AllocationSequence::CreateUDPPorts() {
// is enabled completely.
UDPPort* port = NULL;
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
- port = UDPPort::Create(session_->network_thread(), network_,
+ port = UDPPort::Create(session_->network_thread(),
+ session_->socket_factory(), network_,
udp_socket_.get(),
session_->username(), session_->password());
} else {
@@ -1023,13 +1026,15 @@ void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
void AllocationSequence::OnReadPacket(
talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr) {
+ const talk_base::SocketAddress& remote_addr,
+ const talk_base::PacketTime& packet_time) {
ASSERT(socket == udp_socket_.get());
for (std::deque<Port*>::iterator iter = ports.begin();
iter != ports.end(); ++iter) {
// We have only one port in the queue.
// TODO(mallinath) - Add shared socket support to Relay and Turn ports.
- if ((*iter)->HandleIncomingPacket(socket, data, size, remote_addr)) {
+ if ((*iter)->HandleIncomingPacket(
+ socket, data, size, remote_addr, packet_time)) {
break;
}
}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/client/fakeportallocator.h b/chromium/third_party/libjingle/source/talk/p2p/client/fakeportallocator.h
index 2368948b073..5375e50156d 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/client/fakeportallocator.h
+++ b/chromium/third_party/libjingle/source/talk/p2p/client/fakeportallocator.h
@@ -32,7 +32,7 @@ class FakePortAllocatorSession : public PortAllocatorSession {
factory_(factory),
network_("network", "unittest",
talk_base::IPAddress(INADDR_LOOPBACK), 8),
- port_(NULL), running_(false),
+ port_(), running_(false),
port_config_count_(0) {
network_.AddIP(talk_base::IPAddress(INADDR_LOOPBACK));
}
diff --git a/chromium/third_party/libjingle/source/talk/p2p/client/portallocator_unittest.cc b/chromium/third_party/libjingle/source/talk/p2p/client/portallocator_unittest.cc
index 1ee97f11113..6966e44d04e 100644
--- a/chromium/third_party/libjingle/source/talk/p2p/client/portallocator_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/p2p/client/portallocator_unittest.cc
@@ -50,6 +50,8 @@ using talk_base::SocketAddress;
using talk_base::Thread;
static const SocketAddress kClientAddr("11.11.11.11", 0);
+static const SocketAddress kClientIPv6Addr(
+ "2401:fa00:4:1000:be30:5bff:fee5:c3", 0);
static const SocketAddress kNatAddr("77.77.77.77", talk_base::NAT_SERVER_PORT);
static const SocketAddress kRemoteClientAddr("22.22.22.22", 0);
static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
@@ -740,6 +742,36 @@ TEST_F(PortAllocatorTest, TestEnableSharedSocketNoUdpAllowed) {
EXPECT_EQ(1U, candidates_.size());
}
+// This test verifies allocator can use IPv6 addresses along with IPv4.
+TEST_F(PortAllocatorTest, TestEnableIPv6Addresses) {
+ allocator().set_flags(allocator().flags() |
+ cricket::PORTALLOCATOR_DISABLE_RELAY |
+ cricket::PORTALLOCATOR_ENABLE_IPV6 |
+ cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
+ cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET);
+ AddInterface(kClientIPv6Addr);
+ AddInterface(kClientAddr);
+ allocator_->set_step_delay(cricket::kMinimumStepDelay);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->StartGettingPorts();
+ ASSERT_EQ_WAIT(4U, ports_.size(), kDefaultAllocationTimeout);
+ EXPECT_EQ(4U, candidates_.size());
+ EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout);
+ EXPECT_PRED5(CheckCandidate, candidates_[0],
+ cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp",
+ kClientIPv6Addr);
+ EXPECT_PRED5(CheckCandidate, candidates_[1],
+ cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp",
+ kClientAddr);
+ EXPECT_PRED5(CheckCandidate, candidates_[2],
+ cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp",
+ kClientIPv6Addr);
+ EXPECT_PRED5(CheckCandidate, candidates_[3],
+ cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp",
+ kClientAddr);
+ EXPECT_EQ(4U, candidates_.size());
+}
+
// Test that the httpportallocator correctly maintains its lists of stun and
// relay servers, by never allowing an empty list.
TEST(HttpPortAllocatorTest, TestHttpPortAllocatorHostLists) {
diff --git a/chromium/third_party/libjingle/source/talk/session/media/call.cc b/chromium/third_party/libjingle/source/talk/session/media/call.cc
index c963c36ec36..967846bd214 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/call.cc
+++ b/chromium/third_party/libjingle/source/talk/session/media/call.cc
@@ -186,7 +186,7 @@ bool Call::SendViewRequest(Session* session,
return false;
}
- return session->SendInfoMessage(elems);
+ return session->SendInfoMessage(elems, session->remote_name());
}
void Call::SetLocalRenderer(VideoRenderer* renderer) {
@@ -1079,7 +1079,11 @@ Session* Call::InternalInitiateSession(const std::string& id,
const SessionDescription* offer = session_client_->CreateOffer(options);
Session* session = session_client_->CreateSession(id, this);
- session->set_initiator_name(initiator_name);
+ // Only override the initiator_name if it was manually supplied. Otherwise,
+ // session_client_ will supply the local jid as initiator in CreateOffer.
+ if (!initiator_name.empty()) {
+ session->set_initiator_name(initiator_name);
+ }
AddSession(session, offer);
session->Initiate(to.Str(), offer);
diff --git a/chromium/third_party/libjingle/source/talk/session/media/call.h b/chromium/third_party/libjingle/source/talk/session/media/call.h
index 9b0a6c9c4a1..efb4ea396f4 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/call.h
+++ b/chromium/third_party/libjingle/source/talk/session/media/call.h
@@ -117,6 +117,9 @@ class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
MediaStreams* recv_streams = GetMediaStreams(session);
return recv_streams ? &recv_streams->audio() : NULL;
}
+ VoiceChannel* GetVoiceChannel(Session* session) const;
+ VideoChannel* GetVideoChannel(Session* session) const;
+ DataChannel* GetDataChannel(Session* session) const;
// Public just for unit tests
VideoContentDescription* CreateVideoStreamUpdate(const StreamParams& stream);
// Takes ownership of video.
@@ -193,9 +196,6 @@ class Call : public talk_base::MessageHandler, public sigslot::has_slots<> {
void OnDataReceived(DataChannel* channel,
const ReceiveDataParams& params,
const talk_base::Buffer& payload);
- VoiceChannel* GetVoiceChannel(Session* session) const;
- VideoChannel* GetVideoChannel(Session* session) const;
- DataChannel* GetDataChannel(Session* session) const;
MediaStreams* GetMediaStreams(Session* session) const;
void UpdateRemoteMediaStreams(Session* session,
const ContentInfos& updated_contents,
diff --git a/chromium/third_party/libjingle/source/talk/session/media/channel.cc b/chromium/third_party/libjingle/source/talk/session/media/channel.cc
index f6259e9a34b..9a8559a5b05 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/channel.cc
+++ b/chromium/third_party/libjingle/source/talk/session/media/channel.cc
@@ -81,6 +81,7 @@ enum {
MSG_SETSCREENCASTFACTORY,
MSG_FIRSTPACKETRECEIVED,
MSG_SESSION_ERROR,
+ MSG_NEWSTREAMRECEIVED,
};
// Value specified in RFC 5764.
@@ -398,7 +399,6 @@ BaseChannel::BaseChannel(talk_base::Thread* thread,
writable_(false),
rtp_ready_to_send_(false),
rtcp_ready_to_send_(false),
- optimistic_data_send_(false),
was_ever_writable_(false),
local_content_direction_(MD_INACTIVE),
remote_content_direction_(MD_INACTIVE),
@@ -411,6 +411,7 @@ BaseChannel::BaseChannel(talk_base::Thread* thread,
BaseChannel::~BaseChannel() {
ASSERT(worker_thread_ == talk_base::Thread::Current());
+ Deinit();
StopConnectionMonitor();
FlushRtcpMessages(); // Send any outstanding RTCP packets.
Clear(); // eats any outstanding messages or packets
@@ -438,7 +439,6 @@ bool BaseChannel::Init(TransportChannel* transport_channel,
return false;
}
- media_channel_->SetInterface(this);
transport_channel_->SignalWritableState.connect(
this, &BaseChannel::OnWritableState);
transport_channel_->SignalReadPacket.connect(
@@ -452,9 +452,16 @@ bool BaseChannel::Init(TransportChannel* transport_channel,
this, &BaseChannel::OnNewRemoteDescription);
set_rtcp_transport_channel(rtcp_transport_channel);
+ // Both RTP and RTCP channels are set, we can call SetInterface on
+ // media channel and it can set network options.
+ media_channel_->SetInterface(this);
return true;
}
+void BaseChannel::Deinit() {
+ media_channel_->SetInterface(NULL);
+}
+
// Can be called from thread other than worker thread
bool BaseChannel::Enable(bool enable) {
Send(enable ? MSG_ENABLE : MSG_DISABLE);
@@ -580,11 +587,16 @@ bool BaseChannel::SendRtcp(talk_base::Buffer* packet,
int BaseChannel::SetOption(SocketType type, talk_base::Socket::Option opt,
int value) {
+ TransportChannel* channel = NULL;
switch (type) {
- case ST_RTP: return transport_channel_->SetOption(opt, value);
- case ST_RTCP: return rtcp_transport_channel_->SetOption(opt, value);
- default: return -1;
+ case ST_RTP:
+ channel = transport_channel_;
+ break;
+ case ST_RTCP:
+ channel = rtcp_transport_channel_;
+ break;
}
+ return channel ? channel->SetOption(opt, value) : -1;
}
void BaseChannel::OnWritableState(TransportChannel* channel) {
@@ -598,7 +610,9 @@ void BaseChannel::OnWritableState(TransportChannel* channel) {
}
void BaseChannel::OnChannelRead(TransportChannel* channel,
- const char* data, size_t len, int flags) {
+ const char* data, size_t len,
+ const talk_base::PacketTime& packet_time,
+ int flags) {
// OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
ASSERT(worker_thread_ == talk_base::Thread::Current());
@@ -606,7 +620,7 @@ void BaseChannel::OnChannelRead(TransportChannel* channel,
// transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
bool rtcp = PacketIsRtcp(channel, data, len);
talk_base::Buffer packet(data, len);
- HandlePacket(rtcp, &packet);
+ HandlePacket(rtcp, &packet, packet_time);
}
void BaseChannel::OnReadyToSend(TransportChannel* channel) {
@@ -641,12 +655,6 @@ bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
bool BaseChannel::SendPacket(bool rtcp, talk_base::Buffer* packet,
talk_base::DiffServCodePoint dscp) {
- // Unless we're sending optimistically, we only allow packets through when we
- // are completely writable.
- if (!optimistic_data_send_ && !writable_) {
- return false;
- }
-
// SendPacket gets called from MediaEngine, typically on an encoder thread.
// If the thread is not our worker thread, we will post to our worker
// so that the real work happens on our worker. This avoids us having to
@@ -670,7 +678,7 @@ bool BaseChannel::SendPacket(bool rtcp, talk_base::Buffer* packet,
// transport.
TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
transport_channel_ : rtcp_transport_channel_;
- if (!channel || (!optimistic_data_send_ && !channel->writable())) {
+ if (!channel || !channel->writable()) {
return false;
}
@@ -768,7 +776,8 @@ bool BaseChannel::WantsPacket(bool rtcp, talk_base::Buffer* packet) {
return true;
}
-void BaseChannel::HandlePacket(bool rtcp, talk_base::Buffer* packet) {
+void BaseChannel::HandlePacket(bool rtcp, talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time) {
if (!WantsPacket(rtcp, packet)) {
return;
}
@@ -837,9 +846,9 @@ void BaseChannel::HandlePacket(bool rtcp, talk_base::Buffer* packet) {
// Push it down to the media channel.
if (!rtcp) {
- media_channel_->OnPacketReceived(packet);
+ media_channel_->OnPacketReceived(packet, packet_time);
} else {
- media_channel_->OnRtcpReceived(packet);
+ media_channel_->OnRtcpReceived(packet, packet_time);
}
}
@@ -1082,32 +1091,42 @@ bool BaseChannel::SetMaxSendBandwidth_w(int max_bandwidth) {
return media_channel()->SetSendBandwidth(true, max_bandwidth);
}
+// |dtls| will be set to true if DTLS is active for transport channel and
+// crypto is empty.
+bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
+ bool* dtls) {
+ *dtls = transport_channel_->IsDtlsActive();
+ if (*dtls && !cryptos.empty()) {
+ LOG(LS_WARNING) << "Cryptos must be empty when DTLS is active.";
+ return false;
+ }
+ return true;
+}
+
bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
ContentAction action, ContentSource src) {
bool ret = false;
+ bool dtls = false;
+ ret = CheckSrtpConfig(cryptos, &dtls);
switch (action) {
case CA_OFFER:
- ret = srtp_filter_.SetOffer(cryptos, src);
+ // If DTLS is already active on the channel, we could be renegotiating
+ // here. We don't update the srtp filter.
+ if (ret && !dtls) {
+ ret = srtp_filter_.SetOffer(cryptos, src);
+ }
break;
case CA_PRANSWER:
// If we're doing DTLS-SRTP, we don't want to update the filter
// with an answer, because we already have SRTP parameters.
- if (transport_channel_->IsDtlsActive()) {
- LOG(LS_INFO) <<
- "Ignoring SDES answer parameters because we are using DTLS-SRTP";
- ret = true;
- } else {
+ if (ret && !dtls) {
ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
}
break;
case CA_ANSWER:
// If we're doing DTLS-SRTP, we don't want to update the filter
// with an answer, because we already have SRTP parameters.
- if (transport_channel_->IsDtlsActive()) {
- LOG(LS_INFO) <<
- "Ignoring SDES answer parameters because we are using DTLS-SRTP";
- ret = true;
- } else {
+ if (ret && !dtls) {
ret = srtp_filter_.SetAnswer(cryptos, src);
}
break;
@@ -1472,6 +1491,7 @@ VoiceChannel::~VoiceChannel() {
StopMediaMonitor();
// this can't be done in the base class, since it calls a virtual
DisableMedia_w();
+ Deinit();
}
bool VoiceChannel::Init() {
@@ -1628,8 +1648,10 @@ void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
}
void VoiceChannel::OnChannelRead(TransportChannel* channel,
- const char* data, size_t len, int flags) {
- BaseChannel::OnChannelRead(channel, data, len, flags);
+ const char* data, size_t len,
+ const talk_base::PacketTime& packet_time,
+ int flags) {
+ BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
// Set a flag when we've received an RTP packet. If we're waiting for early
// media, this will disable the timeout.
@@ -1967,6 +1989,8 @@ VideoChannel::~VideoChannel() {
StopMediaMonitor();
// this can't be done in the base class, since it calls a virtual
DisableMedia_w();
+
+ Deinit();
}
bool VideoChannel::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
@@ -2138,7 +2162,9 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
// Tweak our video processing settings, if needed.
VideoOptions video_options;
media_channel()->GetOptions(&video_options);
- video_options.conference_mode.Set(video->conference_mode());
+ if (video->conference_mode()) {
+ video_options.conference_mode.Set(true);
+ }
video_options.buffered_mode_latency.Set(video->buffered_mode_latency());
if (!media_channel()->SetOptions(video_options)) {
@@ -2463,13 +2489,16 @@ DataChannel::DataChannel(talk_base::Thread* thread,
bool rtcp)
// MediaEngine is NULL
: BaseChannel(thread, NULL, media_channel, session, content_name, rtcp),
- data_channel_type_(cricket::DCT_NONE) {
+ data_channel_type_(cricket::DCT_NONE),
+ ready_to_send_data_(false) {
}
DataChannel::~DataChannel() {
StopMediaMonitor();
// this can't be done in the base class, since it calls a virtual
DisableMedia_w();
+
+ Deinit();
}
bool DataChannel::Init() {
@@ -2486,6 +2515,8 @@ bool DataChannel::Init() {
this, &DataChannel::OnDataChannelError);
media_channel()->SignalReadyToSend.connect(
this, &DataChannel::OnDataChannelReadyToSend);
+ media_channel()->SignalNewStreamReceived.connect(
+ this, &DataChannel::OnDataChannelNewStreamReceived);
srtp_filter()->SignalSrtpError.connect(
this, &DataChannel::OnSrtpError);
return true;
@@ -2578,6 +2609,9 @@ bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
ret = UpdateLocalStreams_w(data->streams(), action);
if (ret) {
set_local_content_direction(content->direction());
+ // As in SetRemoteContent_w, make sure we set the local SCTP port
+ // number as specified in our DataContentDescription.
+ ret = media_channel()->SetRecvCodecs(data->codecs());
}
} else {
ret = SetBaseLocalContent_w(content, action);
@@ -2616,6 +2650,9 @@ bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
ret = UpdateRemoteStreams_w(content->streams(), action);
if (ret) {
set_remote_content_direction(content->direction());
+ // We send the SCTP port number (not to be confused with the underlying
+ // UDP port number) as a codec parameter. Make sure it gets there.
+ ret = media_channel()->SetSendCodecs(data->codecs());
}
} else {
// If the remote data doesn't have codecs and isn't an update, it
@@ -2677,7 +2714,8 @@ void DataChannel::OnMessage(talk_base::Message *pmsg) {
case MSG_READYTOSENDDATA: {
DataChannelReadyToSendMessageData* data =
static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
- SignalReadyToSendData(data->data());
+ ready_to_send_data_ = data->data();
+ SignalReadyToSendData(ready_to_send_data_);
delete data;
break;
}
@@ -2702,6 +2740,13 @@ void DataChannel::OnMessage(talk_base::Message *pmsg) {
delete data;
break;
}
+ case MSG_NEWSTREAMRECEIVED: {
+ DataChannelNewStreamReceivedMessageData* data =
+ static_cast<DataChannelNewStreamReceivedMessageData*>(pmsg->pdata);
+ SignalNewStreamReceived(data->label, data->init);
+ delete data;
+ break;
+ }
default:
BaseChannel::OnMessage(pmsg);
break;
@@ -2757,6 +2802,14 @@ void DataChannel::OnDataChannelReadyToSend(bool writable) {
new DataChannelReadyToSendMessageData(writable));
}
+void DataChannel::OnDataChannelNewStreamReceived(
+ const std::string& label, const webrtc::DataChannelInit& init) {
+ signaling_thread()->Post(
+ this,
+ MSG_NEWSTREAMRECEIVED,
+ new DataChannelNewStreamReceivedMessageData(label, init));
+}
+
void DataChannel::OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode,
SrtpFilter::Error error) {
switch (error) {
diff --git a/chromium/third_party/libjingle/source/talk/session/media/channel.h b/chromium/third_party/libjingle/source/talk/session/media/channel.h
index 0d66be9a90d..d297ee4b8fd 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/channel.h
+++ b/chromium/third_party/libjingle/source/talk/session/media/channel.h
@@ -31,6 +31,7 @@
#include <string>
#include <vector>
+#include "talk/app/webrtc/datachannelinterface.h"
#include "talk/base/asyncudpsocket.h"
#include "talk/base/criticalsection.h"
#include "talk/base/network.h"
@@ -66,6 +67,12 @@ enum SinkType {
// BaseChannel contains logic common to voice and video, including
// enable/mute, marshaling calls to a worker thread, and
// connection and media monitors.
+//
+// WARNING! SUBCLASSES MUST CALL Deinit() IN THEIR DESTRUCTORS!
+// This is required to avoid a data race between the destructor modifying the
+// vtable, and the media channel's thread using BaseChannel as the
+// NetworkInterface.
+
class BaseChannel
: public talk_base::MessageHandler, public sigslot::has_slots<>,
public MediaChannel::NetworkInterface {
@@ -76,6 +83,9 @@ class BaseChannel
virtual ~BaseChannel();
bool Init(TransportChannel* transport_channel,
TransportChannel* rtcp_transport_channel);
+ // Deinit may be called multiple times and is simply ignored if it's alreay
+ // done.
+ void Deinit();
talk_base::Thread* worker_thread() const { return worker_thread_; }
BaseSession* session() const { return session_; }
@@ -87,10 +97,6 @@ class BaseChannel
return rtcp_transport_channel_;
}
bool enabled() const { return enabled_; }
- // Set to true to have the channel optimistically allow data to be sent even
- // when the channel isn't fully writable.
- void set_optimistic_data_send(bool value) { optimistic_data_send_ = value; }
- bool optimistic_data_send() const { return optimistic_data_send_; }
// This function returns true if we are using SRTP.
bool secure() const { return srtp_filter_.IsActive(); }
@@ -259,8 +265,11 @@ class BaseChannel
// From TransportChannel
void OnWritableState(TransportChannel* channel);
- virtual void OnChannelRead(TransportChannel* channel, const char* data,
- size_t len, int flags);
+ virtual void OnChannelRead(TransportChannel* channel,
+ const char* data,
+ size_t len,
+ const talk_base::PacketTime& packet_time,
+ int flags);
void OnReadyToSend(TransportChannel* channel);
bool PacketIsRtcp(const TransportChannel* channel, const char* data,
@@ -268,7 +277,8 @@ class BaseChannel
bool SendPacket(bool rtcp, talk_base::Buffer* packet,
talk_base::DiffServCodePoint dscp);
virtual bool WantsPacket(bool rtcp, talk_base::Buffer* packet);
- void HandlePacket(bool rtcp, talk_base::Buffer* packet);
+ void HandlePacket(bool rtcp, talk_base::Buffer* packet,
+ const talk_base::PacketTime& packet_time);
// Apply the new local/remote session description.
void OnNewLocalDescription(BaseSession* session, ContentAction action);
@@ -309,6 +319,7 @@ class BaseChannel
virtual bool SetRemoteContent_w(const MediaContentDescription* content,
ContentAction action) = 0;
+ bool CheckSrtpConfig(const std::vector<CryptoParams>& cryptos, bool* dtls);
bool SetSrtp_w(const std::vector<CryptoParams>& params, ContentAction action,
ContentSource src);
bool SetRtcpMux_w(bool enable, ContentAction action, ContentSource src);
@@ -351,7 +362,6 @@ class BaseChannel
bool writable_;
bool rtp_ready_to_send_;
bool rtcp_ready_to_send_;
- bool optimistic_data_send_;
bool was_ever_writable_;
MediaContentDirection local_content_direction_;
MediaContentDirection remote_content_direction_;
@@ -435,7 +445,9 @@ class VoiceChannel : public BaseChannel {
private:
// overrides from BaseChannel
virtual void OnChannelRead(TransportChannel* channel,
- const char* data, size_t len, int flags);
+ const char* data, size_t len,
+ const talk_base::PacketTime& packet_time,
+ int flags);
virtual void ChangeState();
virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc);
virtual bool SetLocalContent_w(const MediaContentDescription* content,
@@ -604,6 +616,11 @@ class DataChannel : public BaseChannel {
void StartMediaMonitor(int cms);
void StopMediaMonitor();
+ // Should be called on the signaling thread only.
+ bool ready_to_send_data() const {
+ return ready_to_send_data_;
+ }
+
sigslot::signal2<DataChannel*, const DataMediaInfo&> SignalMediaMonitor;
sigslot::signal2<DataChannel*, const std::vector<ConnectionInfo>&>
SignalConnectionMonitor;
@@ -617,6 +634,11 @@ class DataChannel : public BaseChannel {
// That occurs when the channel is enabled, the transport is writable,
// both local and remote descriptions are set, and the channel is unblocked.
sigslot::signal1<bool> SignalReadyToSendData;
+ // Signal for notifying when a new stream is added from the remote side. Used
+ // for the in-band negotioation through the OPEN message for SCTP data
+ // channel.
+ sigslot::signal2<const std::string&, const webrtc::DataChannelInit&>
+ SignalNewStreamReceived;
protected:
// downcasts a MediaChannel.
@@ -656,6 +678,17 @@ class DataChannel : public BaseChannel {
typedef talk_base::TypedMessageData<bool> DataChannelReadyToSendMessageData;
+ struct DataChannelNewStreamReceivedMessageData
+ : public talk_base::MessageData {
+ DataChannelNewStreamReceivedMessageData(
+ const std::string& label, const webrtc::DataChannelInit& init)
+ : label(label),
+ init(init) {
+ }
+ const std::string label;
+ const webrtc::DataChannelInit init;
+ };
+
// overrides from BaseChannel
virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc);
// If data_channel_type_ is DCT_NONE, set it. Otherwise, check that
@@ -684,12 +717,15 @@ class DataChannel : public BaseChannel {
const ReceiveDataParams& params, const char* data, size_t len);
void OnDataChannelError(uint32 ssrc, DataMediaChannel::Error error);
void OnDataChannelReadyToSend(bool writable);
+ void OnDataChannelNewStreamReceived(const std::string& label,
+ const webrtc::DataChannelInit& init);
void OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode, SrtpFilter::Error error);
talk_base::scoped_ptr<DataMediaMonitor> media_monitor_;
// TODO(pthatcher): Make a separate SctpDataChannel and
// RtpDataChannel instead of using this.
DataChannelType data_channel_type_;
+ bool ready_to_send_data_;
};
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/session/media/channel_unittest.cc b/chromium/third_party/libjingle/source/talk/session/media/channel_unittest.cc
index fda89b3c6ed..48a9bdef563 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/channel_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/session/media/channel_unittest.cc
@@ -233,6 +233,10 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
this, &ChannelTest<T>::OnMediaChannelError);
channel1_->SignalAutoMuted.connect(
this, &ChannelTest<T>::OnMediaMuted);
+ if ((flags1 & DTLS) && (flags2 & DTLS)) {
+ flags1 = (flags1 & ~SECURE);
+ flags2 = (flags2 & ~SECURE);
+ }
CreateContent(flags1, kPcmuCodec, kH264Codec,
&local_media_content1_);
CreateContent(flags2, kPcmuCodec, kH264Codec,
@@ -492,11 +496,6 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
// overridden in specialized classes
}
- void SetOptimisticDataSend(bool optimistic_data_send) {
- channel1_->set_optimistic_data_send(optimistic_data_send);
- channel2_->set_optimistic_data_send(optimistic_data_send);
- }
-
// Creates a cricket::SessionDescription with one MediaContent and one stream.
// kPcmuCodec is used as audio codec and kH264Codec is used as video codec.
cricket::SessionDescription* CreateSessionDescriptionWithStream(uint32 ssrc) {
@@ -1390,19 +1389,8 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
EXPECT_TRUE(CheckNoRtp1());
EXPECT_TRUE(CheckNoRtp2());
- // Lose writability, with optimistic send
- SetOptimisticDataSend(true);
+ // Lose writability, which should fail.
GetTransport1()->SetWritable(false);
- EXPECT_TRUE(media_channel1_->sending());
- EXPECT_TRUE(SendRtp1());
- EXPECT_TRUE(SendRtp2());
- EXPECT_TRUE(CheckRtp1());
- EXPECT_TRUE(CheckRtp2());
- EXPECT_TRUE(CheckNoRtp1());
- EXPECT_TRUE(CheckNoRtp2());
-
- // Check again with optimistic send off, which should fail.
- SetOptimisticDataSend(false);
EXPECT_FALSE(SendRtp1());
EXPECT_TRUE(SendRtp2());
EXPECT_TRUE(CheckRtp1());
@@ -1422,13 +1410,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
GetTransport1()->SetDestination(NULL);
EXPECT_TRUE(media_channel1_->sending());
- // Should fail regardless of optimistic send at this point.
- SetOptimisticDataSend(true);
- EXPECT_FALSE(SendRtp1());
- EXPECT_TRUE(SendRtp2());
- EXPECT_TRUE(CheckRtp1());
- EXPECT_TRUE(CheckNoRtp2());
- SetOptimisticDataSend(false);
+ // Should fail also.
EXPECT_FALSE(SendRtp1());
EXPECT_TRUE(SendRtp2());
EXPECT_TRUE(CheckRtp1());
@@ -1793,7 +1775,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> {
channel2_->transport_channel();
transport_channel->SignalReadPacket(
transport_channel, reinterpret_cast<const char*>(kBadPacket),
- sizeof(kBadPacket), 0);
+ sizeof(kBadPacket), talk_base::PacketTime(), 0);
EXPECT_EQ_WAIT(T::MediaChannel::ERROR_PLAY_SRTP_ERROR, error_, 500);
}
diff --git a/chromium/third_party/libjingle/source/talk/session/media/channelmanager.cc b/chromium/third_party/libjingle/source/talk/session/media/channelmanager.cc
index 36c71832da3..d4fcc79dfa7 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/channelmanager.cc
+++ b/chromium/third_party/libjingle/source/talk/session/media/channelmanager.cc
@@ -116,9 +116,10 @@ void ChannelManager::Construct(MediaEngineInterface* me,
initialized_ = false;
main_thread_ = talk_base::Thread::Current();
worker_thread_ = worker_thread;
+ // Get the default audio options from the media engine.
+ audio_options_ = media_engine_->GetAudioOptions();
audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
- audio_options_ = MediaEngineInterface::DEFAULT_AUDIO_OPTIONS;
audio_delay_offset_ = MediaEngineInterface::kDefaultAudioDelayOffset;
audio_output_volume_ = kNotSetOutputVolume;
local_renderer_ = NULL;
@@ -251,7 +252,7 @@ bool ChannelManager::Init() {
LOG(LS_WARNING) << "Failed to SetAudioOptions with"
<< " microphone: " << audio_in_device_
<< " speaker: " << audio_out_device_
- << " options: " << audio_options_
+ << " options: " << audio_options_.ToString()
<< " delay: " << audio_delay_offset_;
}
@@ -502,23 +503,26 @@ void ChannelManager::DestroySoundclip_w(Soundclip* soundclip) {
}
bool ChannelManager::GetAudioOptions(std::string* in_name,
- std::string* out_name, int* opts) {
+ std::string* out_name,
+ AudioOptions* options) {
if (in_name)
*in_name = audio_in_device_;
if (out_name)
*out_name = audio_out_device_;
- if (opts)
- *opts = audio_options_;
+ if (options)
+ *options = audio_options_;
return true;
}
bool ChannelManager::SetAudioOptions(const std::string& in_name,
- const std::string& out_name, int opts) {
- return SetAudioOptions(in_name, out_name, opts, audio_delay_offset_);
+ const std::string& out_name,
+ const AudioOptions& options) {
+ return SetAudioOptions(in_name, out_name, options, audio_delay_offset_);
}
bool ChannelManager::SetAudioOptions(const std::string& in_name,
- const std::string& out_name, int opts,
+ const std::string& out_name,
+ const AudioOptions& options,
int delay_offset) {
// Get device ids from DeviceManager.
Device in_dev, out_dev;
@@ -536,12 +540,12 @@ bool ChannelManager::SetAudioOptions(const std::string& in_name,
if (initialized_) {
ret = worker_thread_->Invoke<bool>(
Bind(&ChannelManager::SetAudioOptions_w, this,
- opts, delay_offset, &in_dev, &out_dev));
+ options, delay_offset, &in_dev, &out_dev));
}
// If all worked well, save the values for use in GetAudioOptions.
if (ret) {
- audio_options_ = opts;
+ audio_options_ = options;
audio_in_device_ = in_name;
audio_out_device_ = out_name;
audio_delay_offset_ = delay_offset;
@@ -549,13 +553,14 @@ bool ChannelManager::SetAudioOptions(const std::string& in_name,
return ret;
}
-bool ChannelManager::SetAudioOptions_w(int opts, int delay_offset,
+bool ChannelManager::SetAudioOptions_w(
+ const AudioOptions& options, int delay_offset,
const Device* in_dev, const Device* out_dev) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
// Set audio options
- bool ret = media_engine_->SetAudioOptions(opts);
+ bool ret = media_engine_->SetAudioOptions(options);
if (ret) {
ret = media_engine_->SetAudioDelayOffset(delay_offset);
@@ -934,4 +939,12 @@ VideoFormat ChannelManager::GetStartCaptureFormat() {
Bind(&MediaEngineInterface::GetStartCaptureFormat, media_engine_.get()));
}
+bool ChannelManager::SetAudioOptions(const AudioOptions& options) {
+ if (!media_engine_->SetAudioOptions(options)) {
+ return false;
+ }
+ audio_options_ = options;
+ return true;
+}
+
} // namespace cricket
diff --git a/chromium/third_party/libjingle/source/talk/session/media/channelmanager.h b/chromium/third_party/libjingle/source/talk/session/media/channelmanager.h
index 04af5e19632..fdb8f733624 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/channelmanager.h
+++ b/chromium/third_party/libjingle/source/talk/session/media/channelmanager.h
@@ -137,9 +137,11 @@ class ChannelManager : public talk_base::MessageHandler,
// Configures the audio and video devices. A null pointer can be passed to
// GetAudioOptions() for any parameter of no interest.
bool GetAudioOptions(std::string* wave_in_device,
- std::string* wave_out_device, int* opts);
+ std::string* wave_out_device,
+ AudioOptions* options);
bool SetAudioOptions(const std::string& wave_in_device,
- const std::string& wave_out_device, int opts);
+ const std::string& wave_out_device,
+ const AudioOptions& options);
bool GetOutputVolume(int* level);
bool SetOutputVolume(int level);
bool IsSameCapturer(const std::string& capturer_name,
@@ -223,11 +225,17 @@ class ChannelManager : public talk_base::MessageHandler,
// TODO(hellner): Remove this function once the engine capturer has been
// removed.
VideoFormat GetStartCaptureFormat();
+
+ // TODO(turajs): Remove this function when ACM2 is in use. Used mainly to
+ // choose between ACM1 and ACM2.
+ bool SetAudioOptions(const AudioOptions& options);
+
protected:
// Adds non-transient parameters which can only be changed through the
// options store.
bool SetAudioOptions(const std::string& wave_in_device,
- const std::string& wave_out_device, int opts,
+ const std::string& wave_out_device,
+ const AudioOptions& options,
int delay_offset);
int audio_delay_offset() const { return audio_delay_offset_; }
@@ -256,8 +264,8 @@ class ChannelManager : public talk_base::MessageHandler,
void DestroyDataChannel_w(DataChannel* data_channel);
Soundclip* CreateSoundclip_w();
void DestroySoundclip_w(Soundclip* soundclip);
- bool SetAudioOptions_w(int opts, int delay_offset, const Device* in_dev,
- const Device* out_dev);
+ bool SetAudioOptions_w(const AudioOptions& options, int delay_offset,
+ const Device* in_dev, const Device* out_dev);
bool SetCaptureDevice_w(const Device* cam_device);
void OnVideoCaptureStateChange(VideoCapturer* capturer,
CaptureState result);
@@ -283,7 +291,7 @@ class ChannelManager : public talk_base::MessageHandler,
std::string audio_in_device_;
std::string audio_out_device_;
- int audio_options_;
+ AudioOptions audio_options_;
int audio_delay_offset_;
int audio_output_volume_;
std::string camera_device_;
diff --git a/chromium/third_party/libjingle/source/talk/session/media/channelmanager_unittest.cc b/chromium/third_party/libjingle/source/talk/session/media/channelmanager_unittest.cc
index 6f7c7687154..d0d380d3eb8 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/channelmanager_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/session/media/channelmanager_unittest.cc
@@ -149,11 +149,12 @@ TEST_F(ChannelManagerTest, CreateDestroyChannels) {
}
// Test that we can create and destroy a voice and video channel with a worker.
-// BUG=https://code.google.com/p/webrtc/issues/detail?id=2355
-TEST_F(ChannelManagerTest, DISABLED_CreateDestroyChannelsOnThread) {
+TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) {
worker_.Start();
EXPECT_TRUE(cm_->set_worker_thread(&worker_));
EXPECT_TRUE(cm_->Init());
+ delete session_;
+ session_ = new cricket::FakeSession(&worker_, true);
cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel(
session_, cricket::CN_AUDIO, false);
EXPECT_TRUE(voice_channel != NULL);
@@ -254,44 +255,43 @@ TEST_F(ChannelManagerTest, SetDefaultVideoCodecBeforeInit) {
TEST_F(ChannelManagerTest, SetAudioOptionsBeforeInit) {
// Test that values that we set before Init are applied.
- EXPECT_TRUE(cm_->SetAudioOptions("audio-in1", "audio-out1", 0x2));
- EXPECT_TRUE(cm_->Init());
- EXPECT_EQ("audio-in1", fme_->audio_in_device());
- EXPECT_EQ("audio-out1", fme_->audio_out_device());
- EXPECT_EQ(0x2, fme_->audio_options());
- EXPECT_EQ(0, fme_->audio_delay_offset());
- EXPECT_EQ(cricket::MediaEngineInterface::kDefaultAudioDelayOffset,
- fme_->audio_delay_offset());
-}
-
-TEST_F(ChannelManagerTest, GetAudioOptionsBeforeInit) {
+ AudioOptions options;
+ options.auto_gain_control.Set(true);
+ options.echo_cancellation.Set(false);
+ EXPECT_TRUE(cm_->SetAudioOptions("audio-in1", "audio-out1", options));
std::string audio_in, audio_out;
- int opts;
- // Test that GetAudioOptions works before Init.
- EXPECT_TRUE(cm_->SetAudioOptions("audio-in2", "audio-out2", 0x1));
- EXPECT_TRUE(cm_->GetAudioOptions(&audio_in, &audio_out, &opts));
- EXPECT_EQ("audio-in2", audio_in);
- EXPECT_EQ("audio-out2", audio_out);
- EXPECT_EQ(0x1, opts);
- // Test that options set before Init can be gotten after Init.
- EXPECT_TRUE(cm_->SetAudioOptions("audio-in1", "audio-out1", 0x2));
+ AudioOptions set_options;
+ // Check options before Init.
+ EXPECT_TRUE(cm_->GetAudioOptions(&audio_in, &audio_out, &set_options));
+ EXPECT_EQ("audio-in1", audio_in);
+ EXPECT_EQ("audio-out1", audio_out);
+ EXPECT_EQ(options, set_options);
EXPECT_TRUE(cm_->Init());
- EXPECT_TRUE(cm_->GetAudioOptions(&audio_in, &audio_out, &opts));
+ // Check options after Init.
+ EXPECT_TRUE(cm_->GetAudioOptions(&audio_in, &audio_out, &set_options));
EXPECT_EQ("audio-in1", audio_in);
EXPECT_EQ("audio-out1", audio_out);
- EXPECT_EQ(0x2, opts);
+ EXPECT_EQ(options, set_options);
+ // At this point, the media engine should also be initialized.
+ EXPECT_EQ(options, fme_->audio_options());
+ EXPECT_EQ(cricket::MediaEngineInterface::kDefaultAudioDelayOffset,
+ fme_->audio_delay_offset());
}
TEST_F(ChannelManagerTest, GetAudioOptionsWithNullParameters) {
std::string audio_in, audio_out;
- int opts;
- EXPECT_TRUE(cm_->SetAudioOptions("audio-in2", "audio-out2", 0x1));
+ AudioOptions options;
+ options.echo_cancellation.Set(true);
+ EXPECT_TRUE(cm_->SetAudioOptions("audio-in2", "audio-out2", options));
EXPECT_TRUE(cm_->GetAudioOptions(&audio_in, NULL, NULL));
EXPECT_EQ("audio-in2", audio_in);
EXPECT_TRUE(cm_->GetAudioOptions(NULL, &audio_out, NULL));
EXPECT_EQ("audio-out2", audio_out);
- EXPECT_TRUE(cm_->GetAudioOptions(NULL, NULL, &opts));
- EXPECT_EQ(0x1, opts);
+ AudioOptions out_options;
+ EXPECT_TRUE(cm_->GetAudioOptions(NULL, NULL, &out_options));
+ bool echo_cancellation = false;
+ EXPECT_TRUE(out_options.echo_cancellation.Get(&echo_cancellation));
+ EXPECT_TRUE(echo_cancellation);
}
TEST_F(ChannelManagerTest, SetAudioOptions) {
@@ -301,47 +301,22 @@ TEST_F(ChannelManagerTest, SetAudioOptions) {
fme_->audio_in_device());
EXPECT_EQ(std::string(cricket::DeviceManagerInterface::kDefaultDeviceName),
fme_->audio_out_device());
- EXPECT_EQ(cricket::MediaEngineInterface::DEFAULT_AUDIO_OPTIONS,
- fme_->audio_options());
- EXPECT_EQ(cricket::MediaEngineInterface::kDefaultAudioDelayOffset,
- fme_->audio_delay_offset());
- // Test setting defaults.
- EXPECT_TRUE(cm_->SetAudioOptions("", "",
- cricket::MediaEngineInterface::DEFAULT_AUDIO_OPTIONS));
- EXPECT_EQ("", fme_->audio_in_device());
- EXPECT_EQ("", fme_->audio_out_device());
- EXPECT_EQ(cricket::MediaEngineInterface::DEFAULT_AUDIO_OPTIONS,
- fme_->audio_options());
EXPECT_EQ(cricket::MediaEngineInterface::kDefaultAudioDelayOffset,
fme_->audio_delay_offset());
// Test setting specific values.
- EXPECT_TRUE(cm_->SetAudioOptions("audio-in1", "audio-out1", 0x2));
+ AudioOptions options;
+ options.auto_gain_control.Set(true);
+ EXPECT_TRUE(cm_->SetAudioOptions("audio-in1", "audio-out1", options));
EXPECT_EQ("audio-in1", fme_->audio_in_device());
EXPECT_EQ("audio-out1", fme_->audio_out_device());
- EXPECT_EQ(0x2, fme_->audio_options());
+ bool auto_gain_control = false;
+ EXPECT_TRUE(
+ fme_->audio_options().auto_gain_control.Get(&auto_gain_control));
+ EXPECT_TRUE(auto_gain_control);
EXPECT_EQ(cricket::MediaEngineInterface::kDefaultAudioDelayOffset,
fme_->audio_delay_offset());
// Test setting bad values.
- EXPECT_FALSE(cm_->SetAudioOptions("audio-in9", "audio-out2", 0x1));
-}
-
-TEST_F(ChannelManagerTest, GetAudioOptions) {
- std::string audio_in, audio_out;
- int opts;
- // Test initial state.
- EXPECT_TRUE(cm_->Init());
- EXPECT_TRUE(cm_->GetAudioOptions(&audio_in, &audio_out, &opts));
- EXPECT_EQ(std::string(cricket::DeviceManagerInterface::kDefaultDeviceName),
- audio_in);
- EXPECT_EQ(std::string(cricket::DeviceManagerInterface::kDefaultDeviceName),
- audio_out);
- EXPECT_EQ(cricket::MediaEngineInterface::DEFAULT_AUDIO_OPTIONS, opts);
- // Test that we get back specific values that we set.
- EXPECT_TRUE(cm_->SetAudioOptions("audio-in1", "audio-out1", 0x2));
- EXPECT_TRUE(cm_->GetAudioOptions(&audio_in, &audio_out, &opts));
- EXPECT_EQ("audio-in1", audio_in);
- EXPECT_EQ("audio-out1", audio_out);
- EXPECT_EQ(0x2, opts);
+ EXPECT_FALSE(cm_->SetAudioOptions("audio-in9", "audio-out2", options));
}
TEST_F(ChannelManagerTest, SetCaptureDeviceBeforeInit) {
@@ -380,7 +355,8 @@ TEST_F(ChannelManagerTest, SetCaptureDevice) {
// device is plugged back, we use it.
TEST_F(ChannelManagerTest, SetAudioOptionsUnplugPlug) {
// Set preferences "audio-in1" and "audio-out1" before init.
- EXPECT_TRUE(cm_->SetAudioOptions("audio-in1", "audio-out1", 0x2));
+ AudioOptions options;
+ EXPECT_TRUE(cm_->SetAudioOptions("audio-in1", "audio-out1", options));
// Unplug device "audio-in1" and "audio-out1".
std::vector<std::string> in_device_list, out_device_list;
in_device_list.push_back("audio-in2");
diff --git a/chromium/third_party/libjingle/source/talk/session/media/currentspeakermonitor_unittest.cc b/chromium/third_party/libjingle/source/talk/session/media/currentspeakermonitor_unittest.cc
index 1306f894043..84c76185545 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/currentspeakermonitor_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/session/media/currentspeakermonitor_unittest.cc
@@ -118,7 +118,8 @@ TEST_F(CurrentSpeakerMonitorTest, MultipleActiveStreams) {
EXPECT_EQ(num_changes_, 1);
}
-TEST_F(CurrentSpeakerMonitorTest, RapidSpeakerChange) {
+// See: https://code.google.com/p/webrtc/issues/detail?id=2409
+TEST_F(CurrentSpeakerMonitorTest, DISABLED_RapidSpeakerChange) {
AudioInfo info;
InitAudioInfo(&info, 0, 0);
diff --git a/chromium/third_party/libjingle/source/talk/session/media/mediasession.cc b/chromium/third_party/libjingle/source/talk/session/media/mediasession.cc
index 85612308211..ba510b94150 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/mediasession.cc
+++ b/chromium/third_party/libjingle/source/talk/session/media/mediasession.cc
@@ -38,12 +38,17 @@
#include "talk/base/stringutils.h"
#include "talk/media/base/constants.h"
#include "talk/media/base/cryptoparams.h"
-#include "talk/media/sctp/sctpdataengine.h"
#include "talk/p2p/base/constants.h"
#include "talk/session/media/channelmanager.h"
#include "talk/session/media/srtpfilter.h"
#include "talk/xmpp/constants.h"
+#ifdef HAVE_SCTP
+#include "talk/media/sctp/sctpdataengine.h"
+#else
+static const uint32 kMaxSctpSid = 1023;
+#endif
+
namespace {
const char kInline[] = "inline:";
}
@@ -237,13 +242,12 @@ static bool GenerateCname(const StreamParamsVec& params_vec,
}
// Generate random SSRC values that are not already present in |params_vec|.
-// Either 2 or 1 ssrcs will be generated based on |include_rtx_stream| being
-// true or false. The generated values are added to |ssrcs|.
+// The generated values are added to |ssrcs|.
+// |num_ssrcs| is the number of the SSRC will be generated.
static void GenerateSsrcs(const StreamParamsVec& params_vec,
- bool include_rtx_stream,
+ int num_ssrcs,
std::vector<uint32>* ssrcs) {
- unsigned int num_ssrcs = include_rtx_stream ? 2 : 1;
- for (unsigned int i = 0; i < num_ssrcs; i++) {
+ for (int i = 0; i < num_ssrcs; i++) {
uint32 candidate;
do {
candidate = talk_base::CreateRandomNonZeroId();
@@ -423,7 +427,8 @@ static bool AddStreamParams(
if (IsSctp(content_description)) {
GenerateSctpSids(*current_streams, &ssrcs);
} else {
- GenerateSsrcs(*current_streams, include_rtx_stream, &ssrcs);
+ int num_ssrcs = include_rtx_stream ? 2 : 1;
+ GenerateSsrcs(*current_streams, num_ssrcs, &ssrcs);
}
if (include_rtx_stream) {
content_description->AddLegacyStream(ssrcs[0], ssrcs[1]);
@@ -457,13 +462,23 @@ static bool AddStreamParams(
if (IsSctp(content_description)) {
GenerateSctpSids(*current_streams, &ssrcs);
} else {
- GenerateSsrcs(*current_streams, include_rtx_stream, &ssrcs);
+ GenerateSsrcs(*current_streams, stream_it->num_sim_layers, &ssrcs);
}
StreamParams stream_param;
stream_param.id = stream_it->id;
- stream_param.ssrcs.push_back(ssrcs[0]);
+ // Add the generated ssrc.
+ for (size_t i = 0; i < ssrcs.size(); ++i) {
+ stream_param.ssrcs.push_back(ssrcs[i]);
+ }
+ if (stream_it->num_sim_layers > 1) {
+ SsrcGroup group(kSimSsrcGroupSemantics, stream_param.ssrcs);
+ stream_param.ssrc_groups.push_back(group);
+ }
+ // Generate an extra ssrc for include_rtx_stream case.
if (include_rtx_stream) {
- stream_param.AddFidSsrc(ssrcs[0], ssrcs[1]);
+ std::vector<uint32> rtx_ssrc;
+ GenerateSsrcs(*current_streams, 1, &rtx_ssrc);
+ stream_param.AddFidSsrc(ssrcs[0], rtx_ssrc[0]);
content_description->set_multistream(true);
}
stream_param.cname = cname;
@@ -594,6 +609,7 @@ static bool UpdateCryptoParamsForBundle(const ContentGroup& bundle_group,
return false;
}
+ bool common_cryptos_needed = false;
// Get the common cryptos.
const ContentNames& content_names = bundle_group.content_names();
CryptoParamsVec common_cryptos;
@@ -602,6 +618,11 @@ static bool UpdateCryptoParamsForBundle(const ContentGroup& bundle_group,
if (!IsRtpContent(sdesc, *it)) {
continue;
}
+ // The common cryptos are needed if any of the content does not have DTLS
+ // enabled.
+ if (!sdesc->GetTransportInfoByName(*it)->description.secure()) {
+ common_cryptos_needed = true;
+ }
if (it == content_names.begin()) {
// Initial the common_cryptos with the first content in the bundle group.
if (!GetCryptosByName(sdesc, *it, &common_cryptos)) {
@@ -620,7 +641,7 @@ static bool UpdateCryptoParamsForBundle(const ContentGroup& bundle_group,
}
}
- if (common_cryptos.empty()) {
+ if (common_cryptos.empty() && common_cryptos_needed) {
return false;
}
@@ -967,10 +988,61 @@ static void SetMediaProtocol(bool secure_transport,
desc->set_protocol(kMediaProtocolAvpf);
}
+// Gets the TransportInfo of the given |content_name| from the
+// |current_description|. If doesn't exist, returns a new one.
+static const TransportDescription* GetTransportDescription(
+ const std::string& content_name,
+ const SessionDescription* current_description) {
+ const TransportDescription* desc = NULL;
+ if (current_description) {
+ const TransportInfo* info =
+ current_description->GetTransportInfoByName(content_name);
+ if (info) {
+ desc = &info->description;
+ }
+ }
+ return desc;
+}
+
+// Gets the current DTLS state from the transport description.
+static bool IsDtlsActive(
+ const std::string& content_name,
+ const SessionDescription* current_description) {
+ if (!current_description)
+ return false;
+
+ const ContentInfo* content =
+ current_description->GetContentByName(content_name);
+ if (!content)
+ return false;
+
+ const TransportDescription* current_tdesc =
+ GetTransportDescription(content_name, current_description);
+ if (!current_tdesc)
+ return false;
+
+ return current_tdesc->secure();
+}
+
void MediaSessionOptions::AddStream(MediaType type,
const std::string& id,
const std::string& sync_label) {
- streams.push_back(Stream(type, id, sync_label));
+ AddStreamInternal(type, id, sync_label, 1);
+}
+
+void MediaSessionOptions::AddVideoStream(
+ const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers) {
+ AddStreamInternal(MEDIA_TYPE_VIDEO, id, sync_label, num_sim_layers);
+}
+
+void MediaSessionOptions::AddStreamInternal(
+ MediaType type,
+ const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers) {
+ streams.push_back(Stream(type, id, sync_label, num_sim_layers));
if (type == MEDIA_TYPE_VIDEO)
has_video = true;
@@ -1042,13 +1114,17 @@ SessionDescription* MediaSessionDescriptionFactory::CreateOffer(
// Handle m=audio.
if (options.has_audio) {
+ cricket::SecurePolicy sdes_policy =
+ IsDtlsActive(CN_AUDIO, current_description) ?
+ cricket::SEC_DISABLED : secure();
+
scoped_ptr<AudioContentDescription> audio(new AudioContentDescription());
std::vector<std::string> crypto_suites;
GetSupportedAudioCryptoSuites(&crypto_suites);
if (!CreateMediaContentOffer(
options,
audio_codecs,
- secure(),
+ sdes_policy,
GetCryptos(GetFirstAudioContentDescription(current_description)),
crypto_suites,
audio_rtp_extensions,
@@ -1069,13 +1145,17 @@ SessionDescription* MediaSessionDescriptionFactory::CreateOffer(
// Handle m=video.
if (options.has_video) {
+ cricket::SecurePolicy sdes_policy =
+ IsDtlsActive(CN_VIDEO, current_description) ?
+ cricket::SEC_DISABLED : secure();
+
scoped_ptr<VideoContentDescription> video(new VideoContentDescription());
std::vector<std::string> crypto_suites;
GetSupportedVideoCryptoSuites(&crypto_suites);
if (!CreateMediaContentOffer(
options,
video_codecs,
- secure(),
+ sdes_policy,
GetCryptos(GetFirstVideoContentDescription(current_description)),
crypto_suites,
video_rtp_extensions,
@@ -1099,8 +1179,10 @@ SessionDescription* MediaSessionDescriptionFactory::CreateOffer(
scoped_ptr<DataContentDescription> data(new DataContentDescription());
bool is_sctp = (options.data_channel_type == DCT_SCTP);
+ cricket::SecurePolicy sdes_policy =
+ IsDtlsActive(CN_DATA, current_description) ?
+ cricket::SEC_DISABLED : secure();
std::vector<std::string> crypto_suites;
- cricket::SecurePolicy sdes_policy = secure();
if (is_sctp) {
// SDES doesn't make sense for SCTP, so we disable it, and we only
// get SDES crypto suites for RTP-based data channels.
@@ -1360,22 +1442,6 @@ SessionDescription* MediaSessionDescriptionFactory::CreateAnswer(
return answer.release();
}
-// Gets the TransportInfo of the given |content_name| from the
-// |current_description|. If doesn't exist, returns a new one.
-static const TransportDescription* GetTransportDescription(
- const std::string& content_name,
- const SessionDescription* current_description) {
- const TransportDescription* desc = NULL;
- if (current_description) {
- const TransportInfo* info =
- current_description->GetTransportInfoByName(content_name);
- if (info) {
- desc = &info->description;
- }
- }
- return desc;
-}
-
void MediaSessionDescriptionFactory::GetCodecsToOffer(
const SessionDescription* current_description,
AudioCodecs* audio_codecs,
diff --git a/chromium/third_party/libjingle/source/talk/session/media/mediasession.h b/chromium/third_party/libjingle/source/talk/session/media/mediasession.h
index 5dfc765e7d2..ff25f5a040e 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/mediasession.h
+++ b/chromium/third_party/libjingle/source/talk/session/media/mediasession.h
@@ -105,8 +105,18 @@ struct MediaSessionOptions {
void AddStream(MediaType type,
const std::string& id,
const std::string& sync_label);
+ void AddVideoStream(const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers);
void RemoveStream(MediaType type, const std::string& id);
+
+ // Helper function.
+ void AddStreamInternal(MediaType type,
+ const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers);
+
bool has_audio;
bool has_video;
DataChannelType data_channel_type;
@@ -122,12 +132,15 @@ struct MediaSessionOptions {
struct Stream {
Stream(MediaType type,
const std::string& id,
- const std::string& sync_label)
- : type(type), id(id), sync_label(sync_label) {
+ const std::string& sync_label,
+ int num_sim_layers)
+ : type(type), id(id), sync_label(sync_label),
+ num_sim_layers(num_sim_layers) {
}
MediaType type;
std::string id;
std::string sync_label;
+ int num_sim_layers;
};
typedef std::vector<Stream> Streams;
diff --git a/chromium/third_party/libjingle/source/talk/session/media/mediasession_unittest.cc b/chromium/third_party/libjingle/source/talk/session/media/mediasession_unittest.cc
index f2e576ca92c..0e645667162 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/mediasession_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/session/media/mediasession_unittest.cc
@@ -536,8 +536,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
}
-// Create a typical data offer, and ensure it matches what we expect.
-TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataOffer) {
+// Create a RTP data offer, and ensure it matches what we expect.
+TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
MediaSessionOptions opts;
opts.data_channel_type = cricket::DCT_RTP;
f1_.set_secure(SEC_ENABLED);
@@ -571,6 +571,18 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataOffer) {
EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
}
+// Create an SCTP data offer with bundle without error.
+TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
+ MediaSessionOptions opts;
+ opts.has_audio = false;
+ opts.bundle_enabled = true;
+ opts.data_channel_type = cricket::DCT_SCTP;
+ f1_.set_secure(SEC_ENABLED);
+ talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+ EXPECT_TRUE(offer.get() != NULL);
+ EXPECT_TRUE(offer->GetContentByName("data") != NULL);
+}
+
// Create an audio, video offer without legacy StreamParams.
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateOfferWithoutLegacyStreams) {
@@ -870,8 +882,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
answer_opts.data_channel_type = cricket::DCT_RTP;
offer_opts.data_channel_type = cricket::DCT_RTP;
- talk_base::scoped_ptr<SessionDescription> offer(NULL);
- talk_base::scoped_ptr<SessionDescription> answer(NULL);
+ talk_base::scoped_ptr<SessionDescription> offer;
+ talk_base::scoped_ptr<SessionDescription> answer;
offer_opts.rtcp_mux_enabled = true;
answer_opts.rtcp_mux_enabled = true;
@@ -1150,6 +1162,28 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
}
+// Create an offer with simulcast video stream.
+TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
+ MediaSessionOptions opts;
+ const int num_sim_layers = 3;
+ opts.AddVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
+ talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+
+ ASSERT_TRUE(offer.get() != NULL);
+ const ContentInfo* vc = offer->GetContentByName("video");
+ ASSERT_TRUE(vc != NULL);
+ const VideoContentDescription* vcd =
+ static_cast<const VideoContentDescription*>(vc->description);
+
+ const StreamParamsVec& video_streams = vcd->streams();
+ ASSERT_EQ(1U, video_streams.size());
+ EXPECT_EQ(kVideoTrack1, video_streams[0].id);
+ const SsrcGroup* sim_ssrc_group =
+ video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
+ ASSERT_TRUE(sim_ssrc_group != NULL);
+ EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
+}
+
// Create an audio and video answer to a standard video offer with:
// - one video track
// - two audio tracks
@@ -1458,7 +1492,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
GetFirstVideoContentDescription(updated_answer.get());
ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
- ASSERT_EQ(cricket::kRtxCodecName, updated_vcd->codecs()[1].name);
+ ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
int new_h264_pl_type = updated_vcd->codecs()[0].id;
EXPECT_NE(used_pl_type, new_h264_pl_type);
VideoCodec rtx = updated_vcd->codecs()[1];
@@ -1802,6 +1836,26 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
ASSERT_TRUE(video_trans_desc != NULL);
ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
+
+ // Try creating offer again. DTLS enabled now, crypto's should be empty
+ // in new offer.
+ offer.reset(f1_.CreateOffer(options, offer.get()));
+ ASSERT_TRUE(offer.get() != NULL);
+ audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
+ offer->GetContentDescriptionByName("audio"));
+ ASSERT_TRUE(audio_media_desc != NULL);
+ video_media_desc = static_cast<const cricket::MediaContentDescription*>(
+ offer->GetContentDescriptionByName("video"));
+ ASSERT_TRUE(video_media_desc != NULL);
+ EXPECT_TRUE(audio_media_desc->cryptos().empty());
+ EXPECT_TRUE(video_media_desc->cryptos().empty());
+
+ audio_trans_desc = offer->GetTransportDescriptionByName("audio");
+ ASSERT_TRUE(audio_trans_desc != NULL);
+ video_trans_desc = offer->GetTransportDescriptionByName("video");
+ ASSERT_TRUE(video_trans_desc != NULL);
+ ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
+ ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
}
// Test that an answer can't be created if cryptos are required but the offer is
diff --git a/chromium/third_party/libjingle/source/talk/session/media/mediasessionclient.h b/chromium/third_party/libjingle/source/talk/session/media/mediasessionclient.h
index 1ade753f955..d0034cafeb2 100644
--- a/chromium/third_party/libjingle/source/talk/session/media/mediasessionclient.h
+++ b/chromium/third_party/libjingle/source/talk/session/media/mediasessionclient.h
@@ -112,8 +112,8 @@ class MediaSessionClient : public SessionClient, public sigslot::has_slots<> {
}
bool SetAudioOptions(const std::string& in_name, const std::string& out_name,
- int opts) {
- return channel_manager_->SetAudioOptions(in_name, out_name, opts);
+ const AudioOptions& options) {
+ return channel_manager_->SetAudioOptions(in_name, out_name, options);
}
bool SetOutputVolume(int level) {
return channel_manager_->SetOutputVolume(level);
diff --git a/chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.cc b/chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.cc
index 92e9e0ea5d0..ee88797c1a1 100644
--- a/chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.cc
+++ b/chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.cc
@@ -340,7 +340,9 @@ void PseudoTcpChannel::OnChannelWritableState(TransportChannel* channel) {
}
void PseudoTcpChannel::OnChannelRead(TransportChannel* channel,
- const char* data, size_t size, int flags) {
+ const char* data, size_t size,
+ const talk_base::PacketTime& packet_time,
+ int flags) {
//LOG_F(LS_VERBOSE) << "(" << size << ")";
ASSERT(worker_thread_->IsCurrent());
CritScope lock(&cs_);
diff --git a/chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.h b/chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.h
index a540699a5c7..31cd9a18b64 100644
--- a/chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.h
+++ b/chromium/third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.h
@@ -111,7 +111,7 @@ class PseudoTcpChannel
// Worker thread methods
void OnChannelWritableState(TransportChannel* channel);
void OnChannelRead(TransportChannel* channel, const char* data, size_t size,
- int flags);
+ const talk_base::PacketTime& packet_time, int flags);
void OnChannelConnectionChanged(TransportChannel* channel,
const Candidate& candidate);
diff --git a/chromium/third_party/libjingle/source/talk/sound/alsasoundsystem.cc b/chromium/third_party/libjingle/source/talk/sound/alsasoundsystem.cc
index de9e2d67fca..7a8857cdf11 100644
--- a/chromium/third_party/libjingle/source/talk/sound/alsasoundsystem.cc
+++ b/chromium/third_party/libjingle/source/talk/sound/alsasoundsystem.cc
@@ -342,7 +342,7 @@ class AlsaInputStream :
}
AlsaStream stream_;
- talk_base::scoped_array<char> buffer_;
+ talk_base::scoped_ptr<char[]> buffer_;
size_t buffer_size_;
DISALLOW_COPY_AND_ASSIGN(AlsaInputStream);
diff --git a/chromium/third_party/libjingle/source/talk/xmllite/xmlbuilder.cc b/chromium/third_party/libjingle/source/talk/xmllite/xmlbuilder.cc
index 486b6d54eae..f71e542d678 100644
--- a/chromium/third_party/libjingle/source/talk/xmllite/xmlbuilder.cc
+++ b/chromium/third_party/libjingle/source/talk/xmllite/xmlbuilder.cc
@@ -37,7 +37,7 @@ namespace buzz {
XmlBuilder::XmlBuilder() :
pelCurrent_(NULL),
- pelRoot_(NULL),
+ pelRoot_(),
pvParents_(new std::vector<XmlElement *>()) {
}
diff --git a/chromium/third_party/libjingle/source/talk/xmllite/xmlelement_unittest.cc b/chromium/third_party/libjingle/source/talk/xmllite/xmlelement_unittest.cc
index 6d488fa75e4..3c31ce491ce 100644
--- a/chromium/third_party/libjingle/source/talk/xmllite/xmlelement_unittest.cc
+++ b/chromium/third_party/libjingle/source/talk/xmllite/xmlelement_unittest.cc
@@ -235,6 +235,10 @@ class XmlElementCreatorThread : public talk_base::Thread {
XmlElementCreatorThread(int count, buzz::QName qname) :
count_(count), qname_(qname) {}
+ virtual ~XmlElementCreatorThread() {
+ Stop();
+ }
+
virtual void Run() {
std::vector<buzz::XmlElement*> elems;
for (int i = 0; i < count_; i++) {
diff --git a/chromium/third_party/libjingle/source/talk/xmpp/mucroomdiscoverytask.cc b/chromium/third_party/libjingle/source/talk/xmpp/mucroomdiscoverytask.cc
index a5055d2dab0..c7477ae3ee6 100644
--- a/chromium/third_party/libjingle/source/talk/xmpp/mucroomdiscoverytask.cc
+++ b/chromium/third_party/libjingle/source/talk/xmpp/mucroomdiscoverytask.cc
@@ -56,11 +56,11 @@ void MucRoomDiscoveryTask::HandleResult(const XmlElement* stanza) {
const std::string name(identity->Attr(QN_NAME));
// Get the conversation id
- const XmlElement* convIdElement =
+ const XmlElement* conversation =
identity->FirstNamed(QN_GOOGLE_MUC_HANGOUT_CONVERSATION_ID);
std::string conversation_id;
- if (convIdElement != NULL) {
- conversation_id = convIdElement->BodyText();
+ if (conversation != NULL) {
+ conversation_id = conversation->BodyText();
}
for (const XmlElement* feature = query->FirstNamed(QN_DISCO_FEATURE);
diff --git a/chromium/third_party/libjingle/source/talk/xmpp/xmppclient.cc b/chromium/third_party/libjingle/source/talk/xmpp/xmppclient.cc
index 9c49a9cae9d..8927dad4e4b 100644
--- a/chromium/third_party/libjingle/source/talk/xmpp/xmppclient.cc
+++ b/chromium/third_party/libjingle/source/talk/xmpp/xmppclient.cc
@@ -46,8 +46,8 @@ public:
explicit Private(XmppClient* client) :
client_(client),
- socket_(NULL),
- engine_(NULL),
+ socket_(),
+ engine_(),
proxy_port_(0),
pre_engine_error_(XmppEngine::ERROR_NONE),
pre_engine_subcode_(0),
diff --git a/chromium/third_party/libjingle/source/talk/xmpp/xmppengineimpl.cc b/chromium/third_party/libjingle/source/talk/xmpp/xmppengineimpl.cc
index 8bcea029a30..d4c9c7d5f67 100644
--- a/chromium/third_party/libjingle/source/talk/xmpp/xmppengineimpl.cc
+++ b/chromium/third_party/libjingle/source/talk/xmpp/xmppengineimpl.cc
@@ -58,12 +58,12 @@ XmppEngineImpl::XmppEngineImpl()
encrypted_(false),
error_code_(ERROR_NONE),
subcode_(0),
- stream_error_(NULL),
+ stream_error_(),
raised_reset_(false),
output_handler_(NULL),
session_handler_(NULL),
iq_entries_(new IqEntryVector()),
- sasl_handler_(NULL),
+ sasl_handler_(),
output_(new std::stringstream()) {
for (int i = 0; i < HL_COUNT; i+= 1) {
stanza_handlers_[i].reset(new StanzaHandlerVector());
diff --git a/chromium/third_party/libjingle/source/talk/xmpp/xmpplogintask.cc b/chromium/third_party/libjingle/source/talk/xmpp/xmpplogintask.cc
index eec943bec6d..b3a2047cfe9 100644
--- a/chromium/third_party/libjingle/source/talk/xmpp/xmpplogintask.cc
+++ b/chromium/third_party/libjingle/source/talk/xmpp/xmpplogintask.cc
@@ -66,11 +66,11 @@ XmppLoginTask::XmppLoginTask(XmppEngineImpl * pctx) :
pelStanza_(NULL),
isStart_(false),
iqId_(STR_EMPTY),
- pelFeatures_(NULL),
+ pelFeatures_(),
fullJid_(STR_EMPTY),
streamId_(STR_EMPTY),
pvecQueuedStanzas_(new std::vector<XmlElement *>()),
- sasl_mech_(NULL) {
+ sasl_mech_() {
}
XmppLoginTask::~XmppLoginTask() {
diff --git a/chromium/third_party/libjingle/source/talk/xmpp/xmppthread.cc b/chromium/third_party/libjingle/source/talk/xmpp/xmppthread.cc
index 43dded866c3..716aaf83639 100644
--- a/chromium/third_party/libjingle/source/talk/xmpp/xmppthread.cc
+++ b/chromium/third_party/libjingle/source/talk/xmpp/xmppthread.cc
@@ -50,6 +50,7 @@ XmppThread::XmppThread() {
}
XmppThread::~XmppThread() {
+ Stop();
delete pump_;
}