async recv()

in src/recordlayer.js [238:292]


  async recv(data) {
    if (this._recvError !== null) {
      throw this._recvError;
    }
    // For simplicity, we assume that the given data contains exactly one record.
    // Peers using this library will send one record at a time over the websocket
    // connection, and we can assume that the server-side websocket bridge will split
    // up any traffic into individual records if we ever start interoperating with
    // peers using a different TLS implementation.
    // Similarly, we assume that handshake messages will not be fragmented across
    // multiple records. This should be trivially true for the PSK-only mode used
    // by this library, but we may want to relax it in future for interoperability
    // with e.g. large ClientHello messages that contain lots of different options.
    const buf = new BufferReader(data);
    // The data to read is either a TLSPlaintext or TLSCiphertext struct,
    // depending on whether record protection has been enabled yet:
    //
    //    struct {
    //        ContentType type;
    //        ProtocolVersion legacy_record_version;
    //        uint16 length;
    //        opaque fragment[TLSPlaintext.length];
    //    } TLSPlaintext;
    //
    //    struct {
    //        ContentType opaque_type = application_data; /* 23 */
    //        ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
    //        uint16 length;
    //        opaque encrypted_record[TLSCiphertext.length];
    //    } TLSCiphertext;
    //
    let type = buf.readUint8();
    // The spec says legacy_record_version "MUST be ignored for all purposes",
    // but we know TLS1.3 implementations will only ever emit two possible values,
    // so it seems useful to bail out early if we receive anything else.
    const version = buf.readUint16();
    if (version !== VERSION_TLS_1_2) {
      // TLS1.0 is only acceptable on initial plaintext records.
      if (this._recvDecryptState !== null || version !== VERSION_TLS_1_0) {
        throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
      }
    }
    const length = buf.readUint16();
    let plaintext;
    if (this._recvDecryptState === null || type === RECORD_TYPE.CHANGE_CIPHER_SPEC) {
      [type, plaintext] = await this._readPlaintextRecord(type, length, buf);
    } else {
      [type, plaintext] = await this._readEncryptedRecord(type, length, buf);
    }
    // Sanity-check that we received exactly one record.
    if (buf.hasMoreBytes()) {
      throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
    }
    return [type, plaintext];
  }