1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128

content / test / data / media / webrtc_test_common.js [blame]

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Default transform functions, overridden by some test cases.
var transformSdp = function(sdp) { return sdp; };
var transformRemoteSdp = function(sdp) { return sdp; };

// Provide functions to set the transform functions.
function setOfferSdpTransform(newTransform) {
  transformSdp = newTransform;
}
function setRemoteSdpTransform(newTransform) {
  transformRemoteSdp = newTransform;
}

/**
 * Negotiate a call between two peer connections.
 *
 * Offer/Answer will be created and SDP candidates exchanged;
 * the functions verifiy the peer connections reach a steady
 * state.
 *
 * Offer and Answer SDP can be modified by setting one of
 * the transform functions above.
 *
 * Args:
 *   caller, callee: RTCPeerConnection instances.
 */
async function negotiateBetween(caller, callee) {
  console.log("Negotiating call...");
  // Not stable = negotiation is ongoing. The behavior of re-negotiating while
  // a negotiation is ongoing is more or less undefined, so avoid this.
  if (caller.signalingState != 'stable' || callee.signalingState != 'stable')
    throw 'You can only negotiate when the connection is stable!';

  connectOnIceCandidate_(caller, callee);

  const offer = await new Promise((resolve, reject) => {
    caller.createOffer(resolve, reject);
  })
  return onOfferCreated_(offer, caller, callee);
}

/**
 * @private
 */
async function onOfferCreated_(offer, caller, callee) {
  offer.sdp = transformSdp(offer.sdp);
  console.log('Offer:\n' + offer.sdp);
  await new Promise((resolve, reject) => {
    caller.setLocalDescription(offer, resolve, reject);
  });
  assertEquals('have-local-offer', caller.signalingState);
  return receiveOffer_(offer.sdp, caller, callee);
}

/**
 * @private
 */
async function receiveOffer_(offerSdp, caller, callee) {
  console.log("Receiving offer...");
  offerSdp = transformRemoteSdp(offerSdp);

  var parsedOffer = new RTCSessionDescription({ type: 'offer',
                                                sdp: offerSdp });
  await new Promise((resolve, reject) => {
    callee.setRemoteDescription(parsedOffer, resolve, reject);
  });
  assertEquals('have-remote-offer', callee.signalingState);
  const answer = await new Promise((resolve, reject) => {
    callee.createAnswer(resolve, reject);
  });
  return onAnswerCreated_(answer, caller, callee);
}

/**
 * @private
 */
async function onAnswerCreated_(answer, caller, callee) {
  answer.sdp = transformSdp(answer.sdp);
  console.log('Answer:\n' + answer.sdp);
  await new Promise((resolve, reject) => {
    callee.setLocalDescription(answer, resolve, reject);
  });
  assertEquals('stable', callee.signalingState);
  return receiveAnswer_(answer.sdp, caller);
}

/**
 * @private
 */
async function receiveAnswer_(answerSdp, caller) {
  console.log("Receiving answer...");
  answerSdp = transformRemoteSdp(answerSdp);
  var parsedAnswer = new RTCSessionDescription({ type: 'answer',
                                                 sdp: answerSdp });
  await new Promise((resolve, reject) => {
    caller.setRemoteDescription(parsedAnswer, resolve, reject);
  });
  assertEquals('stable', caller.signalingState);
}

/**
 * @private
 */
function connectOnIceCandidate_(caller, callee) {
  caller.onicecandidate = function(event) {
    onIceCandidate_(event, caller, callee);
  }
  callee.onicecandidate = function(event) {
    onIceCandidate_(event, callee, caller);
  }
}

/**
 * @private
 */
async function onIceCandidate_(event, originator, target) {
  if (event.candidate) {
    var candidate = new RTCIceCandidate(event.candidate);
    target.addIceCandidate(candidate);
  } else {
    // The spec guarantees that the special "null" candidate will be fired
    // *after* changing the gathering state to "complete".
    assertEquals('complete', originator.iceGatheringState);
  }
}