/* GENERATED SOURCE. DO NOT MODIFY. */
/*
 * Copyright 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.org.conscrypt;

import static javax.net.ssl.SSLEngineResult.Status.OK;
import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_CLOSED;
import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_HANDSHAKE_COMPLETED;
import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_HANDSHAKE_STARTED;
import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_NEW;
import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_READY;
import static com.android.org.conscrypt.SSLUtils.EngineStates.STATE_READY_HANDSHAKE_CUT_THROUGH;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * Implements crypto handling by delegating to {@link ConscryptEngine}.
 */
class ConscryptEngineSocket extends OpenSSLSocketImpl {
    private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);

    private final ConscryptEngine engine;
    private final Object stateLock = new Object();
    private final Object handshakeLock = new Object();

    private SSLOutputStream out;
    private SSLInputStream in;

    private BufferAllocator bufferAllocator = ConscryptEngine.getDefaultBufferAllocator();

    // @GuardedBy("stateLock");
    private int state = STATE_NEW;

    // The constructors should not be called except from the Platform class, because we may
    // want to construct a subclass instead.
    ConscryptEngineSocket(SSLParametersImpl sslParameters) throws IOException {
        engine = newEngine(sslParameters, this);
    }

    ConscryptEngineSocket(String hostname, int port, SSLParametersImpl sslParameters)
            throws IOException {
        super(hostname, port);
        engine = newEngine(sslParameters, this);
    }

    ConscryptEngineSocket(InetAddress address, int port, SSLParametersImpl sslParameters)
            throws IOException {
        super(address, port);
        engine = newEngine(sslParameters, this);
    }

    ConscryptEngineSocket(String hostname, int port, InetAddress clientAddress, int clientPort,
            SSLParametersImpl sslParameters) throws IOException {
        super(hostname, port, clientAddress, clientPort);
        engine = newEngine(sslParameters, this);
    }

    ConscryptEngineSocket(InetAddress address, int port, InetAddress clientAddress, int clientPort,
            SSLParametersImpl sslParameters) throws IOException {
        super(address, port, clientAddress, clientPort);
        engine = newEngine(sslParameters, this);
    }

    ConscryptEngineSocket(Socket socket, String hostname, int port, boolean autoClose,
            SSLParametersImpl sslParameters) throws IOException {
        super(socket, hostname, port, autoClose);
        engine = newEngine(sslParameters, this);
    }

    private static ConscryptEngine newEngine(
            SSLParametersImpl sslParameters, final ConscryptEngineSocket socket) {
        SSLParametersImpl modifiedParams;
        if (Platform.supportsX509ExtendedTrustManager()) {
            modifiedParams = sslParameters.cloneWithTrustManager(
                    getDelegatingTrustManager(sslParameters.getX509TrustManager(), socket));
        } else {
            modifiedParams = sslParameters;
        }
        ConscryptEngine engine = new ConscryptEngine(modifiedParams, socket.peerInfoProvider());

        // When the handshake completes, notify any listeners.
        engine.setHandshakeListener(new HandshakeListener() {
            /**
             * Protected by {@code stateLock}
             */
            @Override
            public void onHandshakeFinished() {
                // Just call the outer class method.
                socket.onHandshakeFinished();
            }
        });

        // Transition the engine state to MODE_SET
        engine.setUseClientMode(sslParameters.getUseClientMode());
        return engine;
    }

    // Returns a trust manager that delegates to the given trust manager, but maps SSLEngine
    // references to the given ConscryptEngineSocket.  Our internal engine will call
    // the SSLEngine-receiving methods, but our callers expect the SSLSocket-receiving
    // methods to get called.
    private static X509TrustManager getDelegatingTrustManager(
            final X509TrustManager delegate, final ConscryptEngineSocket socket) {
        if (delegate instanceof X509ExtendedTrustManager) {
            final X509ExtendedTrustManager extendedDelegate = (X509ExtendedTrustManager) delegate;
            return new X509ExtendedTrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s,
                        Socket socket) throws CertificateException {
                    throw new AssertionError("Should not be called");
                }
                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s,
                        Socket socket) throws CertificateException {
                    throw new AssertionError("Should not be called");
                }
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s,
                        SSLEngine sslEngine) throws CertificateException {
                    extendedDelegate.checkClientTrusted(x509Certificates, s, socket);
                }
                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s,
                        SSLEngine sslEngine) throws CertificateException {
                    extendedDelegate.checkServerTrusted(x509Certificates, s, socket);
                }
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
                        throws CertificateException {
                    extendedDelegate.checkClientTrusted(x509Certificates, s);
                }
                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
                        throws CertificateException {
                    extendedDelegate.checkServerTrusted(x509Certificates, s);
                }
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return extendedDelegate.getAcceptedIssuers();
                }
            };
        }
        return delegate;
    }

    @Override
    public final SSLParameters getSSLParameters() {
        return engine.getSSLParameters();
    }

    @Override
    public final void setSSLParameters(SSLParameters sslParameters) {
        engine.setSSLParameters(sslParameters);
    }

    @Override
    public final void startHandshake() throws IOException {
        checkOpen();

        try {
            synchronized (handshakeLock) {
                // Only lock stateLock when we begin the handshake. This is done so that we don't
                // hold the stateLock when we invoke the handshake completion listeners.
                synchronized (stateLock) {
                    // Initialize the handshake if we haven't already.
                    if (state == STATE_NEW) {
                        state = STATE_HANDSHAKE_STARTED;
                        engine.beginHandshake();
                        in = new SSLInputStream();
                        out = new SSLOutputStream();
                    } else {
                        // We've either started the handshake already or have been closed.
                        // Do nothing in both cases.
                        //
                        // NOTE: BoringSSL does not support initiating renegotiation, so we always
                        // ignore addition handshake calls.
                        return;
                    }
                }

                doHandshake();
            }
        } catch (SSLException e) {
            close();
            throw e;
        } catch (IOException e) {
            close();
            throw e;
        } catch (Exception e) {
            close();
            // Convert anything else to a handshake exception.
            throw SSLUtils.toSSLHandshakeException(e);
        }
    }

    private void doHandshake() throws IOException {
        try {
            boolean finished = false;
            while (!finished) {
                switch (engine.getHandshakeStatus()) {
                    case NEED_UNWRAP:
                        if (in.processDataFromSocket(EmptyArray.BYTE, 0, 0) < 0) {
                            // Can't complete the handshake due to EOF.
                            throw SSLUtils.toSSLHandshakeException(new EOFException());
                        }
                        break;
                    case NEED_WRAP: {
                        out.writeInternal(EMPTY_BUFFER);
                        // Always flush handshake frames immediately.
                        out.flushInternal();
                        break;
                    }
                    case NEED_TASK: {
                        // Should never get here, since our engine never provides tasks.
                        throw new IllegalStateException("Engine tasks are unsupported");
                    }
                    case NOT_HANDSHAKING:
                    case FINISHED: {
                        // Handshake is complete.
                        finished = true;
                        break;
                    }
                    default: {
                        throw new IllegalStateException(
                            "Unknown handshake status: " + engine.getHandshakeStatus());
                    }
                }
            }
        } catch (SSLException e) {
            drainOutgoingQueue();
            close();
            throw e;
        } catch (IOException e) {
            close();
            throw e;
        } catch (Exception e) {
            close();
            // Convert anything else to a handshake exception.
            throw SSLUtils.toSSLHandshakeException(e);
        }
    }

    @Override
    public final InputStream getInputStream() throws IOException {
        checkOpen();

        // Block waiting for a handshake without a lock held. It's possible that the socket
        // is closed at this point. If that happens, we'll still return the input stream but
        // all reads on it will throw.
        waitForHandshake();
        return in;
    }

    @Override
    public final OutputStream getOutputStream() throws IOException {
        checkOpen();

        // Block waiting for a handshake without a lock held. It's possible that the socket
        // is closed at this point. If that happens, we'll still return the input stream but
        // all reads on it will throw.
        waitForHandshake();

        return out;
    }

    @Override
    public final SSLSession getHandshakeSession() {
        return engine.handshakeSession();
    }

    @Override
    public final SSLSession getSession() {
        if (isConnected()) {
            try {
                waitForHandshake();
            } catch (IOException e) {
                // Fall through
            }
        }
        return engine.getSession();
    }

    @Override
    final SSLSession getActiveSession() {
        return engine.getSession();
    }

    @Override
    public final boolean getEnableSessionCreation() {
        return engine.getEnableSessionCreation();
    }

    @Override
    public final void setEnableSessionCreation(boolean flag) {
        engine.setEnableSessionCreation(flag);
    }

    @Override
    public final String[] getSupportedCipherSuites() {
        return engine.getSupportedCipherSuites();
    }

    @Override
    public final String[] getEnabledCipherSuites() {
        return engine.getEnabledCipherSuites();
    }

    @Override
    public final void setEnabledCipherSuites(String[] suites) {
        engine.setEnabledCipherSuites(suites);
    }

    @Override
    public final String[] getSupportedProtocols() {
        return engine.getSupportedProtocols();
    }

    @Override
    public final String[] getEnabledProtocols() {
        return engine.getEnabledProtocols();
    }

    @Override
    public final void setEnabledProtocols(String[] protocols) {
        engine.setEnabledProtocols(protocols);
    }

    /**
     * This method enables Server Name Indication.  If the hostname is not a valid SNI hostname,
     * the SNI extension will be omitted from the handshake.
     *
     * @param hostname the desired SNI hostname, or null to disable
     */
    @Override
    public final void setHostname(String hostname) {
        engine.setHostname(hostname);
        super.setHostname(hostname);
    }

    @Override
    public final void setUseSessionTickets(boolean useSessionTickets) {
        engine.setUseSessionTickets(useSessionTickets);
    }

    @Override
    public final void setChannelIdEnabled(boolean enabled) {
        engine.setChannelIdEnabled(enabled);
    }

    @Override
    public final byte[] getChannelId() throws SSLException {
        return engine.getChannelId();
    }

    @Override
    public final void setChannelIdPrivateKey(PrivateKey privateKey) {
        engine.setChannelIdPrivateKey(privateKey);
    }

    @Override
    byte[] getTlsUnique() {
        return engine.getTlsUnique();
    }

    @Override
    byte[] exportKeyingMaterial(String label, byte[] context, int length) throws SSLException {
        return engine.exportKeyingMaterial(label, context, length);
    }

    @Override
    public final boolean getUseClientMode() {
        return engine.getUseClientMode();
    }

    @Override
    public final void setUseClientMode(boolean mode) {
        engine.setUseClientMode(mode);
    }

    @Override
    public final boolean getWantClientAuth() {
        return engine.getWantClientAuth();
    }

    @Override
    public final boolean getNeedClientAuth() {
        return engine.getNeedClientAuth();
    }

    @Override
    public final void setNeedClientAuth(boolean need) {
        engine.setNeedClientAuth(need);
    }

    @Override
    public final void setWantClientAuth(boolean want) {
        engine.setWantClientAuth(want);
    }

    @Override
    @SuppressWarnings("UnsynchronizedOverridesSynchronized")
    public final void close() throws IOException {
        // TODO: Close SSL sockets using a background thread so they close gracefully.

        if (stateLock == null) {
            // close() has been called before we've initialized the socket, so just
            // return.
            return;
        }

        synchronized (stateLock) {
            if (state == STATE_CLOSED) {
                // close() has already been called, so do nothing and return.
                return;
            }

            state = STATE_CLOSED;

            stateLock.notifyAll();
        }

        try {
            // Close the underlying socket.
            super.close();
        } finally {
            // Close the engine.
            engine.closeInbound();
            engine.closeOutbound();
            
            // Release any resources we're holding
            if (in != null) {
                in.release();
            }
        }
    }

    @Override
    final void setApplicationProtocols(String[] protocols) {
        engine.setApplicationProtocols(protocols);
    }

    @Override
    final String[] getApplicationProtocols() {
        return engine.getApplicationProtocols();
    }

    @Override
    public final String getApplicationProtocol() {
        return engine.getApplicationProtocol();
    }

    @Override
    public final String getHandshakeApplicationProtocol() {
        return engine.getHandshakeApplicationProtocol();
    }

    @Override
    public final void setApplicationProtocolSelector(ApplicationProtocolSelector selector) {
        setApplicationProtocolSelector(
                selector == null ? null : new ApplicationProtocolSelectorAdapter(this, selector));
    }

    @Override
    final void setApplicationProtocolSelector(ApplicationProtocolSelectorAdapter selector) {
        engine.setApplicationProtocolSelector(selector);
    }

    void setBufferAllocator(BufferAllocator bufferAllocator) {
        engine.setBufferAllocator(bufferAllocator);
        this.bufferAllocator = bufferAllocator;
    }

    private void onHandshakeFinished() {
        boolean notify = false;
        synchronized (stateLock) {
            if (state != STATE_CLOSED) {
                if (state == STATE_HANDSHAKE_STARTED) {
                    state = STATE_READY_HANDSHAKE_CUT_THROUGH;
                } else if (state == STATE_HANDSHAKE_COMPLETED) {
                    state = STATE_READY;
                }

                // Unblock threads that are waiting for our state to transition
                // into STATE_READY or STATE_READY_HANDSHAKE_CUT_THROUGH.
                stateLock.notifyAll();
                notify = true;
            }
        }

        if (notify) {
            notifyHandshakeCompletedListeners();
        }
    }

    /**
     * Waits for the handshake to complete.
     */
    private void waitForHandshake() throws IOException {
        startHandshake();

        synchronized (stateLock) {
            while (state != STATE_READY && state != STATE_READY_HANDSHAKE_CUT_THROUGH
                    && state != STATE_CLOSED) {
                try {
                    stateLock.wait();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new IOException("Interrupted waiting for handshake", e);
                }
            }

            if (state == STATE_CLOSED) {
                throw new SocketException("Socket is closed");
            }
        }
    }

    private void drainOutgoingQueue() {
        try {
            while (engine.pendingOutboundEncryptedBytes() > 0) {
                out.writeInternal(EMPTY_BUFFER);
                // Always flush handshake frames immediately.
                out.flushInternal();
            }
        } catch (IOException e) {
            // Ignore
        }
    }

    private OutputStream getUnderlyingOutputStream() throws IOException {
        return super.getOutputStream();
    }

    private InputStream getUnderlyingInputStream() throws IOException {
        return super.getInputStream();
    }

    /**
     * Wrap bytes written to the underlying socket.
     */
    private final class SSLOutputStream extends OutputStream {
        private final Object writeLock = new Object();
        private final ByteBuffer target;
        private final int targetArrayOffset;
        private OutputStream socketOutputStream;

        SSLOutputStream() {
            target = ByteBuffer.allocate(engine.getSession().getPacketBufferSize());
            targetArrayOffset = target.arrayOffset();
        }

        @Override
        public void close() throws IOException {
            ConscryptEngineSocket.this.close();
        }

        @Override
        public void write(int b) throws IOException {
            startHandshake();
            synchronized (writeLock) {
                write(new byte[] {(byte) b});
            }
        }

        @Override
        public void write(byte[] b) throws IOException {
            startHandshake();
            synchronized (writeLock) {
                writeInternal(ByteBuffer.wrap(b));
            }
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            startHandshake();
            synchronized (writeLock) {
                writeInternal(ByteBuffer.wrap(b, off, len));
            }
        }

        private void writeInternal(ByteBuffer buffer) throws IOException {
            Platform.blockGuardOnNetwork();
            checkOpen();
            init();

            // Need to loop through at least once to enable handshaking where no application
            // bytes are
            // processed.
            int len = buffer.remaining();
            SSLEngineResult engineResult;
            do {
                target.clear();
                engineResult = engine.wrap(buffer, target);
                if (engineResult.getStatus() != OK) {
                    throw new SSLException("Unexpected engine result " + engineResult.getStatus());
                }
                if (target.position() != engineResult.bytesProduced()) {
                    throw new SSLException("Engine bytesProduced " + engineResult.bytesProduced()
                            + " does not match bytes written " + target.position());
                }
                len -= engineResult.bytesConsumed();
                if (len != buffer.remaining()) {
                    throw new SSLException("Engine did not read the correct number of bytes");
                }

                target.flip();

                // Write the data to the socket.
                writeToSocket();
            } while (len > 0);
        }

        @Override
        public void flush() throws IOException {
            startHandshake();
            synchronized (writeLock) {
                flushInternal();
            }
        }

        private void flushInternal() throws IOException {
            checkOpen();
            init();
            socketOutputStream.flush();
        }

        private void init() throws IOException {
            if (socketOutputStream == null) {
                socketOutputStream = getUnderlyingOutputStream();
            }
        }

        private void writeToSocket() throws IOException {
            // Write the data to the socket.
            socketOutputStream.write(target.array(), targetArrayOffset, target.limit());
        }
    }

    /**
     * Unwrap bytes read from the underlying socket.
     */
    private final class SSLInputStream extends InputStream {
        private final Object readLock = new Object();
        private final byte[] singleByte = new byte[1];
        private final ByteBuffer fromEngine;
        private final ByteBuffer fromSocket;
        private final int fromSocketArrayOffset;
        private final AllocatedBuffer allocatedBuffer;
        private InputStream socketInputStream;

        SSLInputStream() {
            if (bufferAllocator != null) {
                allocatedBuffer = bufferAllocator.allocateDirectBuffer(
                        engine.getSession().getApplicationBufferSize());
                fromEngine = allocatedBuffer.nioBuffer();
            } else {
                allocatedBuffer = null;
                fromEngine = ByteBuffer.allocateDirect(engine.getSession().getApplicationBufferSize());
            }
            // Initially fromEngine.remaining() == 0.
            fromEngine.flip();
            fromSocket = ByteBuffer.allocate(engine.getSession().getPacketBufferSize());
            fromSocketArrayOffset = fromSocket.arrayOffset();
        }

        @Override
        public void close() throws IOException {
            ConscryptEngineSocket.this.close();
        }

        void release() {
            synchronized (readLock) {
                if (allocatedBuffer != null) {
                    allocatedBuffer.release();
                }
            }
        }

        @Override
        public int read() throws IOException {
            startHandshake();
            synchronized (readLock) {
                // Handle returning of -1 if EOF is reached.
                int count = read(singleByte, 0, 1);
                if (count == -1) {
                    // Handle EOF.
                    return -1;
                }
                if (count != 1) {
                    throw new SSLException("read incorrect number of bytes " + count);
                }
                return (int) singleByte[0];
            }
        }

        @Override
        public int read(byte[] b) throws IOException {
            startHandshake();
            synchronized (readLock) {
                return read(b, 0, b.length);
            }
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            startHandshake();
            synchronized (readLock) {
                return readUntilDataAvailable(b, off, len);
            }
        }

        @Override
        public int available() throws IOException {
            startHandshake();
            synchronized (readLock) {
                init();
                return fromEngine.remaining()
                        + (fromSocket.hasRemaining() || socketInputStream.available() > 0 ? 1 : 0);
            }
        }

        private boolean isHandshaking(HandshakeStatus status) {
            switch(status) {
                case NEED_TASK:
                case NEED_WRAP:
                case NEED_UNWRAP:
                    return true;
                default:
                    return false;
            }
        }

        private int readUntilDataAvailable(byte[] b, int off, int len) throws IOException {
            int count;
            do {
                count = processDataFromSocket(b, off, len);
            } while (count == 0);
            return count;
        }

        // Returns any decrypted data from the engine.  If no data is currently present in the
        // engine's output buffer, reads from the input socket until the engine has processed
        // at least one TLS record, then returns any data in the output buffer or 0 if no
        // data is available.  This is used both during handshaking (in which case, the records
        // will produce no data and this method will return 0) and by the InputStream read()
        // methods that expect records to produce application data.
        private int processDataFromSocket(byte[] b, int off, int len) throws IOException {
            Platform.blockGuardOnNetwork();
            checkOpen();

            // Make sure the input stream has been created.
            init();

            for (;;) {
                // Serve any remaining data from the engine first.
                if (fromEngine.remaining() > 0) {
                    int readFromEngine = Math.min(fromEngine.remaining(), len);
                    fromEngine.get(b, off, readFromEngine);
                    return readFromEngine;
                }

                // Try to unwrap any data already in the socket buffer.
                boolean needMoreDataFromSocket = true;

                // Unwrap the unencrypted bytes into the engine buffer.
                fromSocket.flip();
                fromEngine.clear();

                boolean engineHandshaking = isHandshaking(engine.getHandshakeStatus());
                SSLEngineResult engineResult = engine.unwrap(fromSocket, fromEngine);

                // Shift any remaining data to the beginning of the buffer so that
                // we can accommodate the next full packet. After this is called,
                // limit will be restored to capacity and position will point just
                // past the end of the data.
                fromSocket.compact();
                fromEngine.flip();

                switch (engineResult.getStatus()) {
                    case BUFFER_UNDERFLOW: {
                        if (engineResult.bytesProduced() == 0) {
                            // Need to read more data from the socket.
                            break;
                        }
                        // Also serve the data that was produced.
                        needMoreDataFromSocket = false;
                        break;
                    }
                    case OK: {
                        // We processed the entire packet successfully...

                        if (!engineHandshaking && isHandshaking(engineResult.getHandshakeStatus())
                            && isHandshakeFinished()) {
                            // The received packet is the beginning of a renegotiation handshake.
                            // Perform another handshake.
                            renegotiate();
                            return 0;
                        }

                        needMoreDataFromSocket = false;
                        break;
                    }
                    case CLOSED: {
                        // EOF
                        return -1;
                    }
                    default: {
                        // Anything else is an error.
                        throw new SSLException(
                                "Unexpected engine result " + engineResult.getStatus());
                    }
                }

                if (!needMoreDataFromSocket && engineResult.bytesProduced() == 0) {
                    // Read successfully, but produced no data. Possibly part of a
                    // handshake.
                    return 0;
                }

                // Read more data from the socket.
                if (needMoreDataFromSocket && readFromSocket() == -1) {
                    // Failed to read the next encrypted packet before reaching EOF.
                    return -1;
                }

                // Continue the loop and return the data from the engine buffer.
            }
        }

        private boolean isHandshakeFinished() {
            synchronized (stateLock) {
                return state >= STATE_READY_HANDSHAKE_CUT_THROUGH;
            }
        }

        /**
         * Processes a renegotiation received from the remote peer.
         */
        private void renegotiate() throws IOException {
            synchronized (handshakeLock) {
                doHandshake();
            }
        }

        private void init() throws IOException {
            if (socketInputStream == null) {
                socketInputStream = getUnderlyingInputStream();
            }
        }

        private int readFromSocket() throws IOException {
            try {
                // Read directly to the underlying array and increment the buffer position if
                // appropriate.
                int pos = fromSocket.position();
                int lim = fromSocket.limit();
                int read = socketInputStream.read(
                    fromSocket.array(), fromSocketArrayOffset + pos, lim - pos);

                if (read > 0) {
                    fromSocket.position(pos + read);
                }
                return read;
            } catch (EOFException e) {
                return -1;
            }
        }
    }
}
