async recv()

in src/tlsconnection.js [95:135]


  async recv(data) {
    assertIsBytes(data);
    return await this._synchronized(async () => {
      // Decrypt the data using the record layer.
      // We expect to receive precisely one record at a time.
      const [type, bytes] = await this._recordlayer.recv(data);
      // Dispatch based on the type of the record.
      switch (type) {
        case RECORD_TYPE.CHANGE_CIPHER_SPEC:
          await this._state.recvChangeCipherSpec(bytes);
          return null;
        case RECORD_TYPE.ALERT:
          await this._state.recvAlertMessage(TLSAlert.fromBytes(bytes));
          return null;
        case RECORD_TYPE.APPLICATION_DATA:
          return await this._state.recvApplicationData(bytes);
        case RECORD_TYPE.HANDSHAKE:
          // Multiple handshake messages may be coalesced into a single record.
          // Store the in-progress record buffer on `this` so that we can guard
          // against handshake messages that span a change in keys.
          this._handshakeRecvBuffer = new BufferReader(bytes);
          if (! this._handshakeRecvBuffer.hasMoreBytes()) {
            throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
          }
          do {
            // Each handshake messages has a type and length prefix, per
            // https://tools.ietf.org/html/rfc8446#appendix-B.3
            this._handshakeRecvBuffer.incr(1);
            const mlength = this._handshakeRecvBuffer.readUint24();
            this._handshakeRecvBuffer.incr(-4);
            const messageBytes = this._handshakeRecvBuffer.readBytes(mlength + 4);
            this._keyschedule.addToTranscript(messageBytes);
            await this._state.recvHandshakeMessage(HandshakeMessage.fromBytes(messageBytes));
          } while (this._handshakeRecvBuffer.hasMoreBytes());
          this._handshakeRecvBuffer = null;
          return null;
        default:
          throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
      }
    });
  }