tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

parser_rtp.js (5016B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 /**
      8 * Parses an RTP packet
      9 *
     10 * @param buffer an ArrayBuffer that contains the packet
     11 * @return { type: "rtp", header: {...}, payload: a DataView }
     12 */
     13 var ParseRtpPacket = buffer => {
     14  // DataView.getFooInt returns big endian numbers by default
     15  let view = new DataView(buffer);
     16 
     17  // Standard Header Fields
     18  // https://tools.ietf.org/html/rfc3550#section-5.1
     19  //  0                   1                   2                   3
     20  //  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
     21  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     22  // |V=2|P|X|  CC   |M|     PT      |       sequence number         |
     23  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     24  // |                           timestamp                           |
     25  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     26  // |           synchronization source (SSRC) identifier            |
     27  // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     28  // |            contributing source (CSRC) identifiers             |
     29  // |                             ....                              |
     30  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     31 
     32  let header = {};
     33  let offset = 0;
     34  // Note that incrementing the offset happens as close to reading the data as
     35  // possible. This simplifies ensuring that the number of read bytes and the
     36  // offset increment match. Data may be manipulated between when the offset is
     37  // incremented and before the next read.
     38  let byte = view.getUint8(offset);
     39  offset++;
     40  // Version            2 Bit
     41  header.version = (0xc0 & byte) >> 6;
     42  // Padding            1 Bit
     43  header.padding = (0x30 & byte) >> 5;
     44  // Extension          1 Bit
     45  header.extensionsPresent = (0x10 & byte) >> 4 == 1;
     46  // CSRC count         4 Bit
     47  header.csrcCount = 0xf & byte;
     48 
     49  byte = view.getUint8(offset);
     50  offset++;
     51  // Marker             1 Bit
     52  header.marker = (0x80 & byte) >> 7;
     53  // Payload Type       7 Bit
     54  header.payloadType = 0x7f & byte;
     55  // Sequence Number   16 Bit
     56  header.sequenceNumber = view.getUint16(offset);
     57  offset += 2;
     58  // Timestamp         32 Bit
     59  header.timestamp = view.getUint32(offset);
     60  offset += 4;
     61  // SSRC              32 Bit
     62  header.ssrc = view.getUint32(offset);
     63  offset += 4;
     64 
     65  // CSRC              32 Bit
     66  header.csrcs = [];
     67  for (let c = 0; c < header.csrcCount; c++) {
     68    header.csrcs.push(view.getUint32(offset));
     69    offset += 4;
     70  }
     71 
     72  // Extensions
     73  header.extensions = [];
     74  header.extensionPaddingBytes = 0;
     75  header.extensionsTotalLength = 0;
     76  if (header.extensionsPresent) {
     77    // https://tools.ietf.org/html/rfc3550#section-5.3.1
     78    //  0                   1                   2                   3
     79    //  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
     80    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     81    // |      defined by profile       |           length              |
     82    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     83    // |                        header extension                       |
     84    // |                             ....                              |
     85    let addExtension = (id, len) =>
     86      header.extensions.push({
     87        id,
     88        data: new DataView(buffer, offset, len),
     89      });
     90    let extensionId = view.getUint16(offset);
     91    offset += 2;
     92    // len is in 32 bit units, not bytes
     93    header.extensionsTotalLength = view.getUint16(offset) * 4;
     94    offset += 2;
     95    // Check for https://tools.ietf.org/html/rfc5285
     96    if (extensionId != 0xbede) {
     97      // No rfc5285
     98      addExtension(extensionId, header.extensionsTotalLength);
     99      offset += header.extensionsTotalLength;
    100    } else {
    101      let expectedEnd = offset + header.extensionsTotalLength;
    102      while (offset < expectedEnd) {
    103        // We only support "one-byte" extension headers ATM
    104        // https://tools.ietf.org/html/rfc5285#section-4.2
    105        //  0
    106        //  0 1 2 3 4 5 6 7
    107        // +-+-+-+-+-+-+-+-+
    108        // |  ID   |  len  |
    109        // +-+-+-+-+-+-+-+-+
    110        byte = view.getUint8(offset);
    111        offset++;
    112        // Check for padding which can occur between extensions or at the end
    113        if (byte == 0) {
    114          header.extensionPaddingBytes++;
    115          continue;
    116        }
    117        let id = (byte & 0xf0) >> 4;
    118        // Check for the FORBIDDEN id (15), dun dun dun
    119        if (id == 15) {
    120          // Ignore bytes until until the end of extensions
    121          offset = expectedEnd;
    122          break;
    123        }
    124        // the length of the extention is len + 1
    125        let len = (byte & 0x0f) + 1;
    126        addExtension(id, len);
    127        offset += len;
    128      }
    129    }
    130  }
    131  return { type: "rtp", header, payload: new DataView(buffer, offset) };
    132 };