OLD | NEW |
1 <html> | 1 <html> |
2 <head> | 2 <head> |
3 <script type="text/javascript" src="webrtc_test_utilities.js"></script> | 3 <script type="text/javascript" src="webrtc_test_utilities.js"></script> |
4 <script type="text/javascript"> | 4 <script type="text/javascript"> |
5 $ = function(id) { | 5 $ = function(id) { |
6 return document.getElementById(id); | 6 return document.getElementById(id); |
7 }; | 7 }; |
8 | 8 |
9 var gFirstConnection = null; | 9 var gFirstConnection = null; |
10 var gSecondConnection = null; | 10 var gSecondConnection = null; |
11 var gTestWithoutMsidAndBundle = false; | 11 var gTestWithoutMsid = false; |
12 | 12 |
13 var gLocalStream = null; | 13 var gLocalStream = null; |
14 var gSentTones = ''; | 14 var gSentTones = ''; |
15 | 15 |
16 var gRemoteStreams = {}; | 16 var gRemoteStreams = {}; |
17 | 17 |
| 18 // Default transform functions, overridden by some test cases. |
| 19 var transformSdp = function(sdp) { return sdp; }; |
| 20 var transformRemoteSdp = function(sdp) { return sdp; }; |
| 21 var transformCandidate = function(candidate) { return candidate; }; |
| 22 |
| 23 // When using external SDES, the crypto key is chosen by javascript. |
| 24 var EXTERNAL_SDES_LINES = { |
| 25 'audio': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + |
| 26 'inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR', |
| 27 'video': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + |
| 28 'inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj', |
| 29 'data': 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + |
| 30 'inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj' |
| 31 }; |
| 32 |
| 33 // When using GICE, the ICE credentials can be chosen by javascript. |
| 34 var EXTERNAL_GICE_UFRAG = '1234567890123456'; |
| 35 var EXTERNAL_GICE_PWD = '123456789012345678901234'; |
| 36 |
18 setAllEventsOccuredHandler(function() { | 37 setAllEventsOccuredHandler(function() { |
19 document.title = 'OK'; | 38 document.title = 'OK'; |
20 }); | 39 }); |
21 | 40 |
22 // Test that we can setup call with an audio and video track. | 41 // Test that we can setup call with an audio and video track. |
23 function call(constraints) { | 42 function call(constraints) { |
24 createConnections(null); | 43 createConnections(null); |
25 navigator.webkitGetUserMedia(constraints, | 44 navigator.webkitGetUserMedia(constraints, |
26 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 45 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
27 waitForVideo('remote-view-1'); | 46 waitForVideo('remote-view-1'); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 | 103 |
85 // Do the forwarding after we have received video. | 104 // Do the forwarding after we have received video. |
86 detectVideoIn('remote-view-1', onRemoteStream1); | 105 detectVideoIn('remote-view-1', onRemoteStream1); |
87 detectVideoIn('remote-view-2', onRemoteStream2); | 106 detectVideoIn('remote-view-2', onRemoteStream2); |
88 } | 107 } |
89 | 108 |
90 // Test that we can setup call with an audio and video track and | 109 // Test that we can setup call with an audio and video track and |
91 // simulate that the remote peer don't support MSID. | 110 // simulate that the remote peer don't support MSID. |
92 function callWithoutMsidAndBundle() { | 111 function callWithoutMsidAndBundle() { |
93 createConnections(null); | 112 createConnections(null); |
94 gTestWithoutMsidAndBundle = true; | 113 transformSdp = removeBundle; |
| 114 transformRemoteSdp = removeMsid; |
| 115 gTestWithoutMsid = true; |
95 navigator.webkitGetUserMedia({audio: true, video: true}, | 116 navigator.webkitGetUserMedia({audio: true, video: true}, |
96 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); | 117 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
97 waitForVideo('remote-view-1'); | 118 waitForVideo('remote-view-1'); |
98 waitForVideo('remote-view-2'); | 119 waitForVideo('remote-view-2'); |
99 } | 120 } |
100 | 121 |
| 122 // Test that we can setup call with legacy settings. |
| 123 function callWithLegacySdp() { |
| 124 transformSdp = function(sdp) { |
| 125 return removeBundle(useGice(useExternalSdes(sdp))); |
| 126 }; |
| 127 transformCandidate = addGiceCredsToCandidate; |
| 128 createConnections({ |
| 129 'mandatory': {'RtpDataChannels': true, 'DtlsSrtpKeyAgreement': false} |
| 130 }); |
| 131 setupDataChannel({reliable: false}); |
| 132 navigator.webkitGetUserMedia({audio: true, video: true}, |
| 133 addStreamToBothConnectionsAndNegotiate, printGetUserMediaError); |
| 134 waitForVideo('remote-view-1'); |
| 135 waitForVideo('remote-view-2'); |
| 136 } |
| 137 |
101 // Test only a data channel. | 138 // Test only a data channel. |
102 function callWithDataOnly() { | 139 function callWithDataOnly() { |
103 createConnections({optional:[{RtpDataChannels: true}]}); | 140 createConnections({optional:[{RtpDataChannels: true}]}); |
104 setupDataChannel({reliable: false}); | 141 setupDataChannel({reliable: false}); |
105 negotiate(); | 142 negotiate(); |
106 } | 143 } |
107 | 144 |
108 function callWithSctpDataOnly() { | 145 function callWithSctpDataOnly() { |
109 createConnections({optional: [{DtlsSrtpKeyAgreement: true}]}); | 146 createConnections({optional: [{DtlsSrtpKeyAgreement: true}]}); |
110 setupSctpDataChannel({reliable: true}); | 147 setupSctpDataChannel({reliable: true}); |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 function negotiateBetween(caller, callee) { | 497 function negotiateBetween(caller, callee) { |
461 // Not stable = negotiation is ongoing. The behavior of re-negotiating while | 498 // Not stable = negotiation is ongoing. The behavior of re-negotiating while |
462 // a negotiation is ongoing is more or less undefined, so avoid this. | 499 // a negotiation is ongoing is more or less undefined, so avoid this. |
463 if (caller.signalingState != 'stable') | 500 if (caller.signalingState != 'stable') |
464 throw 'You can only negotiate when the connection is stable!'; | 501 throw 'You can only negotiate when the connection is stable!'; |
465 | 502 |
466 connectOnIceCandidate(caller, callee); | 503 connectOnIceCandidate(caller, callee); |
467 | 504 |
468 caller.createOffer( | 505 caller.createOffer( |
469 function (offer) { | 506 function (offer) { |
470 caller.setLocalDescription(offer); | 507 onOfferCreated(offer, caller, callee); |
471 expectEquals('have-local-offer', caller.signalingState); | |
472 receiveOffer(offer.sdp, caller, callee); | |
473 }); | 508 }); |
474 } | 509 } |
475 | 510 |
| 511 function onOfferCreated(offer, caller, callee) { |
| 512 offer.sdp = transformSdp(offer.sdp); |
| 513 caller.setLocalDescription(offer); |
| 514 expectEquals('have-local-offer', caller.signalingState); |
| 515 receiveOffer(offer.sdp, caller, callee); |
| 516 } |
| 517 |
476 function receiveOffer(offerSdp, caller, callee) { | 518 function receiveOffer(offerSdp, caller, callee) { |
477 if (gTestWithoutMsidAndBundle) { | 519 offerSdp = transformRemoteSdp(offerSdp); |
478 offerSdp = removeMsidAndBundle(offerSdp); | |
479 } | |
480 | 520 |
481 var parsedOffer = new RTCSessionDescription({ type: 'offer', | 521 var parsedOffer = new RTCSessionDescription({ type: 'offer', |
482 sdp: offerSdp }); | 522 sdp: offerSdp }); |
483 callee.setRemoteDescription(parsedOffer); | 523 callee.setRemoteDescription(parsedOffer); |
484 callee.createAnswer(function (answer) { | 524 callee.createAnswer(function (answer) { |
485 onAnswerCreated(answer, caller, callee); | 525 onAnswerCreated(answer, caller, callee); |
486 }); | 526 }); |
487 expectEquals('have-remote-offer', callee.signalingState); | 527 expectEquals('have-remote-offer', callee.signalingState); |
488 } | 528 } |
489 | 529 |
490 function removeMsidAndBundle(offerSdp) { | 530 function removeMsid(offerSdp) { |
491 offerSdp = offerSdp.replace(/a=msid-semantic.*\r\n/g, ''); | 531 offerSdp = offerSdp.replace(/a=msid-semantic.*\r\n/g, ''); |
492 offerSdp = offerSdp.replace('a=group:BUNDLE audio video\r\n', ''); | |
493 offerSdp = offerSdp.replace('a=mid:audio\r\n', ''); | 532 offerSdp = offerSdp.replace('a=mid:audio\r\n', ''); |
494 offerSdp = offerSdp.replace('a=mid:video\r\n', ''); | 533 offerSdp = offerSdp.replace('a=mid:video\r\n', ''); |
495 offerSdp = offerSdp.replace(/a=ssrc.*\r\n/g, ''); | 534 offerSdp = offerSdp.replace(/a=ssrc.*\r\n/g, ''); |
496 return offerSdp; | 535 return offerSdp; |
497 } | 536 } |
498 | 537 |
| 538 function removeBundle(sdp) { |
| 539 return sdp.replace(/a=group:BUNDLE .*\r\n/g, ''); |
| 540 } |
| 541 |
| 542 function useGice(sdp) { |
| 543 sdp = sdp.replace(/t=.*\r\n/g, function(subString) { |
| 544 return subString + 'a=ice-options:google-ice\r\n'; |
| 545 }); |
| 546 sdp = sdp.replace(/a=ice-ufrag:.*\r\n/g, |
| 547 'a=ice-ufrag:' + EXTERNAL_GICE_UFRAG + '\r\n'); |
| 548 sdp = sdp.replace(/a=ice-pwd:.*\r\n/g, |
| 549 'a=ice-pwd:' + EXTERNAL_GICE_PWD + '\r\n'); |
| 550 return sdp; |
| 551 } |
| 552 |
| 553 function useExternalSdes(sdp) { |
| 554 // Remove current crypto specification. |
| 555 sdp = sdp.replace(/a=crypto.*\r\n/g, ''); |
| 556 sdp = sdp.replace(/a=fingerprint.*\r\n/g, ''); |
| 557 // Add external crypto. This is not compatible with |removeMsid|. |
| 558 sdp = sdp.replace(/a=mid:(\w+)\r\n/g, function(subString, group) { |
| 559 return subString + EXTERNAL_SDES_LINES[group] + '\r\n'; |
| 560 }); |
| 561 return sdp; |
| 562 } |
| 563 |
499 function onAnswerCreated(answer, caller, callee) { | 564 function onAnswerCreated(answer, caller, callee) { |
| 565 answer.sdp = transformSdp(answer.sdp); |
500 callee.setLocalDescription(answer); | 566 callee.setLocalDescription(answer); |
501 expectEquals('stable', callee.signalingState); | 567 expectEquals('stable', callee.signalingState); |
502 receiveAnswer(answer.sdp, caller); | 568 receiveAnswer(answer.sdp, caller); |
503 } | 569 } |
504 | 570 |
505 function receiveAnswer(answerSdp, caller) { | 571 function receiveAnswer(answerSdp, caller) { |
506 if (gTestWithoutMsidAndBundle) { | 572 answerSdp = transformRemoteSdp(answerSdp); |
507 answerSdp = removeMsidAndBundle(answerSdp); | |
508 } | |
509 var parsedAnswer = new RTCSessionDescription({ type: 'answer', | 573 var parsedAnswer = new RTCSessionDescription({ type: 'answer', |
510 sdp: answerSdp }); | 574 sdp: answerSdp }); |
511 caller.setRemoteDescription(parsedAnswer); | 575 caller.setRemoteDescription(parsedAnswer); |
512 expectEquals('stable', caller.signalingState); | 576 expectEquals('stable', caller.signalingState); |
513 } | 577 } |
514 | 578 |
515 function connectOnIceCandidate(caller, callee) { | 579 function connectOnIceCandidate(caller, callee) { |
516 caller.onicecandidate = function(event) { onIceCandidate(event, callee); } | 580 caller.onicecandidate = function(event) { onIceCandidate(event, callee); } |
517 callee.onicecandidate = function(event) { onIceCandidate(event, caller); } | 581 callee.onicecandidate = function(event) { onIceCandidate(event, caller); } |
518 } | 582 } |
519 | 583 |
| 584 function addGiceCredsToCandidate(candidate) { |
| 585 return candidate.trimRight() + |
| 586 ' username ' + EXTERNAL_GICE_UFRAG + ' password ' + EXTERNAL_GICE_PWD; |
| 587 } |
| 588 |
520 function onIceCandidate(event, target) { | 589 function onIceCandidate(event, target) { |
521 if (event.candidate) { | 590 if (event.candidate) { |
522 var candidate = new RTCIceCandidate(event.candidate); | 591 var candidate = new RTCIceCandidate(event.candidate); |
| 592 candidate.candidate = transformCandidate(candidate.candidate); |
523 target.addIceCandidate(candidate); | 593 target.addIceCandidate(candidate); |
524 } | 594 } |
525 } | 595 } |
526 | 596 |
527 function onRemoteStream(e, target) { | 597 function onRemoteStream(e, target) { |
528 if (gTestWithoutMsidAndBundle && e.stream.id != "default") { | 598 if (gTestWithoutMsid && e.stream.id != "default") { |
529 document.title = 'a default remote stream was expected but instead ' + | 599 document.title = 'a default remote stream was expected but instead ' + |
530 e.stream.id + ' was received.'; | 600 e.stream.id + ' was received.'; |
531 return; | 601 return; |
532 } | 602 } |
533 gRemoteStreams[target] = e.stream; | 603 gRemoteStreams[target] = e.stream; |
534 var remoteStreamUrl = webkitURL.createObjectURL(e.stream); | 604 var remoteStreamUrl = webkitURL.createObjectURL(e.stream); |
535 var remoteVideo = $(target); | 605 var remoteVideo = $(target); |
536 remoteVideo.src = remoteStreamUrl; | 606 remoteVideo.src = remoteStreamUrl; |
537 } | 607 } |
538 | 608 |
(...skipping 25 matching lines...) Expand all Loading... |
564 <td><canvas width="320" height="240" id="remote-view-2-canvas" | 634 <td><canvas width="320" height="240" id="remote-view-2-canvas" |
565 style="display:none"></canvas></td> | 635 style="display:none"></canvas></td> |
566 <td><canvas width="320" height="240" id="remote-view-3-canvas" | 636 <td><canvas width="320" height="240" id="remote-view-3-canvas" |
567 style="display:none"></canvas></td> | 637 style="display:none"></canvas></td> |
568 <td><canvas width="320" height="240" id="remote-view-4-canvas" | 638 <td><canvas width="320" height="240" id="remote-view-4-canvas" |
569 style="display:none"></canvas></td> | 639 style="display:none"></canvas></td> |
570 </tr> | 640 </tr> |
571 </table> | 641 </table> |
572 </body> | 642 </body> |
573 </html> | 643 </html> |
OLD | NEW |