/*
   * On input, we hash messages one at a time since servers may need
   * to access an intermediate hash to validate a CertificateVerify
   * message.
   *
   * Note that many handshake messages can come in one record (and often
   * do, to reduce network resource utilization), and one message can also
   * require multiple records (e.g. very large Certificate messages).
   */
  void processLoop() throws IOException {

    // need to read off 4 bytes at least to get the handshake
    // message type and length.
    while (input.available() >= 4) {
      byte messageType;
      int messageLen;

      /*
       * See if we can read the handshake message header, and
       * then the entire handshake message.  If not, wait till
       * we can read and process an entire message.
       */
      input.mark(4);

      messageType = (byte) input.getInt8();
      messageLen = input.getInt24();

      if (input.available() < messageLen) {
        input.reset();
        return;
      }

      /*
       * Process the messsage.  We require
       * that processMessage() consumes the entire message.  In
       * lieu of explicit error checks (how?!) we assume that the
       * data will look like garbage on encoding/processing errors,
       * and that other protocol code will detect such errors.
       *
       * Note that digesting is normally deferred till after the
       * message has been processed, though to process at least the
       * client's Finished message (i.e. send the server's) we need
       * to acccelerate that digesting.
       *
       * Also, note that hello request messages are never hashed;
       * that includes the hello request header, too.
       */
      if (messageType == HandshakeMessage.ht_hello_request) {
        input.reset();
        processMessage(messageType, messageLen);
        input.ignore(4 + messageLen);
      } else {
        input.mark(messageLen);
        processMessage(messageType, messageLen);
        input.digestNow();
      }
    }
  }
  /*
   * This routine is fed SSL handshake records when they become available,
   * and processes messages found therein.
   */
  void process_record(InputRecord r, boolean expectingFinished) throws IOException {

    checkThrown();

    /*
     * Store the incoming handshake data, then see if we can
     * now process any completed handshake messages
     */
    input.incomingRecord(r);

    /*
     * We don't need to create a separate delegatable task
     * for finished messages.
     */
    if ((conn != null) || expectingFinished) {
      processLoop();
    } else {
      delegateTask(
          new PrivilegedExceptionAction<Void>() {
            public Void run() throws Exception {
              processLoop();
              return null;
            }
          });
    }
  }