private SSLEngineResult writeAppRecord(EngineArgs ea) throws IOException {

        Status status = null;
        HandshakeStatus hsStatus = null;

        /*
         * See if the handshaker needs to report back some SSLException.
         */
        checkTaskThrown();

        /*
         * short circuit if we're closed/closing.
         */
        if (writer.isOutboundDone()) {
            return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
        }

        /*
         * If we're still in cs_HANDSHAKE, make sure it's been
         * started.
         */
        synchronized (this) {
            if ((connectionState == cs_HANDSHAKE) ||
                    (connectionState == cs_START)) {
                kickstartHandshake();

                /*
                 * If there's no HS data available to write, we can return
                 * without trying to wrap anything.
                 */
                hsStatus = getHSStatus(null);

                if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
                    return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
                }
            }
        }

        /*
         * Grab a copy of this if it doesn't already exist,
         * and we can use it several places before anything major
         * happens on this side.  Races aren't critical
         * here.
         */
        if (hsStatus == null) {
            hsStatus = getHSStatus(null);
        }

        /*
         * If we have a task outstanding, this *MUST* be done before
         * doing any more wrapping, because we could be in the middle
         * of receiving a handshake message, for example, a finished
         * message which would change the ciphers.
         */
        if (hsStatus == HandshakeStatus.NEED_TASK) {
            return new SSLEngineResult(
                Status.OK, hsStatus, 0, 0);
        }

        /*
         * This will obtain any waiting outbound data, or will
         * process the outbound appData.
         */
        try {
            synchronized (writeLock) {
                hsStatus = writeRecord(outputRecord, ea);
            }
        } catch (SSLException e) {
            throw e;
        } catch (IOException e) {
            SSLException ex = new SSLException("Write problems");
            ex.initCause(e);
            throw ex;
        }

        /*
         * writeRecord might have reported some status.
         * Now check for the remaining cases.
         *
         * status above should cover:  NEED_WRAP/FINISHED
         */
        status = (isOutboundDone() ? Status.CLOSED : Status.OK);
        hsStatus = getHSStatus(hsStatus);

        return new SSLEngineResult(status, hsStatus,
            ea.deltaApp(), ea.deltaNet());
    }
private SSLEngineResult writeAppRecord ( EngineArgs ea ) throws IOException { Status status = null ; HandshakeStatus hsStatus = null ; checkTaskThrown ( ) ; if ( writer . isOutboundDone ( ) ) { return new SSLEngineResult ( Status . CLOSED , getHSStatus ( null ) , 0 , 0 ) ; } synchronized ( this ) { if ( ( connectionState == cs_HANDSHAKE ) || ( connectionState == cs_START ) ) { kickstartHandshake ( ) ; hsStatus = getHSStatus ( null ) ; if ( hsStatus == HandshakeStatus . NEED_UNWRAP ) { return new SSLEngineResult ( Status . OK , hsStatus , 0 , 0 ) ; } } } if ( hsStatus == null ) { hsStatus = getHSStatus ( null ) ; } if ( hsStatus == HandshakeStatus . NEED_TASK ) { return new SSLEngineResult ( Status . OK , hsStatus , 0 , 0 ) ; } try { synchronized ( writeLock ) { hsStatus = writeRecord ( outputRecord , ea ) ; } } catch ( SSLException e ) { throw e ; } catch ( IOException e ) { SSLException ex = new SSLException ( "Write problems" ) ; ex . initCause ( e ) ; throw ex ; } status = ( isOutboundDone ( ) ? Status . CLOSED : Status . OK ) ; hsStatus = getHSStatus ( hsStatus ) ; return new SSLEngineResult ( status , hsStatus , ea . deltaApp ( ) , ea . deltaNet ( ) ) ; }
/*
Makes additional checks for unwrap, but this time more
specific to this packet and the current state of the machine.