⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sslhandler.java

📁 mina是以Java实现的一个开源的网络程序框架
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* *  Licensed to the Apache Software Foundation (ASF) under one *  or more contributor license agreements.  See the NOTICE file *  distributed with this work for additional information *  regarding copyright ownership.  The ASF licenses this file *  to you 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 org.apache.mina.filter.ssl;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.util.Queue;import java.util.concurrent.ConcurrentLinkedQueue;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLEngine;import javax.net.ssl.SSLEngineResult;import javax.net.ssl.SSLException;import javax.net.ssl.SSLHandshakeException;import org.apache.mina.core.buffer.IoBuffer;import org.apache.mina.core.filterchain.IoFilterEvent;import org.apache.mina.core.filterchain.IoFilter.NextFilter;import org.apache.mina.core.future.DefaultWriteFuture;import org.apache.mina.core.future.WriteFuture;import org.apache.mina.core.session.IoEventType;import org.apache.mina.core.session.IoSession;import org.apache.mina.core.write.DefaultWriteRequest;import org.apache.mina.core.write.WriteRequest;import org.apache.mina.util.CircularQueue;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * A helper class using the SSLEngine API to decrypt/encrypt data. * <p/> * Each connection has a SSLEngine that is used through the lifetime of the connection. * We allocate buffers for use as the outbound and inbound network buffers. * These buffers handle all of the intermediary data for the SSL connection. To make things easy, * we'll require outNetBuffer be completely flushed before trying to wrap any more data. * * @author The Apache MINA Project (dev@mina.apache.org) * @version $Rev: 713364 $, $Date: 2008-11-12 14:35:51 +0100 (Wed, 12 Nov 2008) $ */class SslHandler {    private final Logger logger = LoggerFactory.getLogger(getClass());    private final SslFilter parent;    private final SSLContext sslContext;    private final IoSession session;    private final Queue<IoFilterEvent> preHandshakeEventQueue = new CircularQueue<IoFilterEvent>();    private final Queue<IoFilterEvent> filterWriteEventQueue = new ConcurrentLinkedQueue<IoFilterEvent>();    private final Queue<IoFilterEvent> messageReceivedEventQueue = new ConcurrentLinkedQueue<IoFilterEvent>();    private SSLEngine sslEngine;    /**     * Encrypted data from the net     */    private IoBuffer inNetBuffer;    /**     * Encrypted data to be written to the net     */    private IoBuffer outNetBuffer;    /**     * Applicaton cleartext data to be read by application     */    private IoBuffer appBuffer;    /**     * Empty buffer used during initial handshake and close operations     */    private final IoBuffer emptyBuffer = IoBuffer.allocate(0);    private SSLEngineResult.HandshakeStatus handshakeStatus;    private boolean initialHandshakeComplete;    private boolean handshakeComplete;    private boolean writingEncryptedData;    /**     * Constuctor.     *     * @param sslc     * @throws SSLException     */    public SslHandler(SslFilter parent, SSLContext sslContext, IoSession session)            throws SSLException {        this.parent = parent;        this.session = session;        this.sslContext = sslContext;        init();    }    /**     * Initialize the SSL handshake.     *     * @throws SSLException     */    public void init() throws SSLException {        if (sslEngine != null) {            // We already have a SSL engine created, no need to create a new one            return;        }        InetSocketAddress peer = (InetSocketAddress) session                .getAttribute(SslFilter.PEER_ADDRESS);                // Create the SSL engine here        if (peer == null) {            sslEngine = sslContext.createSSLEngine();        } else {            sslEngine = sslContext.createSSLEngine(peer.getHostName(), peer.getPort());        }                // Initialize the engine in client mode if necessary        sslEngine.setUseClientMode(parent.isUseClientMode());        // Initialize the different SslEngine modes        if (parent.isWantClientAuth()) {            sslEngine.setWantClientAuth(true);        }        if (parent.isNeedClientAuth()) {            sslEngine.setNeedClientAuth(true);        }        if (parent.getEnabledCipherSuites() != null) {            sslEngine.setEnabledCipherSuites(parent.getEnabledCipherSuites());        }        if (parent.getEnabledProtocols() != null) {            sslEngine.setEnabledProtocols(parent.getEnabledProtocols());        }        // TODO : we may not need to call this method...        sslEngine.beginHandshake();                        handshakeStatus = sslEngine.getHandshakeStatus();        handshakeComplete = false;        initialHandshakeComplete = false;        writingEncryptedData = false;    }    /**     * Release allocated buffers.     */    public void destroy() {        if (sslEngine == null) {            return;        }        // Close inbound and flush all remaining data if available.        try {            sslEngine.closeInbound();        } catch (SSLException e) {            logger.debug(                    "Unexpected exception from SSLEngine.closeInbound().", e);        }        if (outNetBuffer != null) {            outNetBuffer.capacity(sslEngine.getSession().getPacketBufferSize());        } else {            createOutNetBuffer(0);        }        try {            do {                outNetBuffer.clear();            } while (sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf()).bytesProduced() > 0);        } catch (SSLException e) {            // Ignore.        } finally {            destroyOutNetBuffer();        }        sslEngine.closeOutbound();        sslEngine = null;        preHandshakeEventQueue.clear();    }    private void destroyOutNetBuffer() {        outNetBuffer.free();        outNetBuffer = null;    }    public SslFilter getParent() {        return parent;    }    public IoSession getSession() {        return session;    }    /**     * Check we are writing encrypted data.     */    public boolean isWritingEncryptedData() {        return writingEncryptedData;    }    /**     * Check if handshake is completed.     */    public boolean isHandshakeComplete() {        return handshakeComplete;    }    public boolean isInboundDone() {        return sslEngine == null || sslEngine.isInboundDone();    }    public boolean isOutboundDone() {        return sslEngine == null || sslEngine.isOutboundDone();    }    /**     * Check if there is any need to complete handshake.     */    public boolean needToCompleteHandshake() {        return handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP && !isInboundDone();    }    public void schedulePreHandshakeWriteRequest(NextFilter nextFilter,                                                 WriteRequest writeRequest) {        preHandshakeEventQueue.add(new IoFilterEvent(nextFilter,                IoEventType.WRITE, session, writeRequest));    }    public void flushPreHandshakeEvents() throws SSLException {        IoFilterEvent scheduledWrite;        while ((scheduledWrite = preHandshakeEventQueue.poll()) != null) {            parent.filterWrite(scheduledWrite.getNextFilter(), session,                    (WriteRequest) scheduledWrite.getParameter());        }    }    public void scheduleFilterWrite(NextFilter nextFilter, WriteRequest writeRequest) {        filterWriteEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.WRITE, session, writeRequest));    }    public void scheduleMessageReceived(NextFilter nextFilter, Object message) {        messageReceivedEventQueue.add(new IoFilterEvent(nextFilter, IoEventType.MESSAGE_RECEIVED, session, message));    }    public void flushScheduledEvents() {        // Fire events only when no lock is hold for this handler.        if (Thread.holdsLock(this)) {            return;        }        IoFilterEvent e;        // We need synchronization here inevitably because filterWrite can be        // called simultaneously and cause 'bad record MAC' integrity error.        synchronized (this) {            while ((e = filterWriteEventQueue.poll()) != null) {                e.getNextFilter().filterWrite(session, (WriteRequest) e.getParameter());            }        }        while ((e = messageReceivedEventQueue.poll()) != null) {            e.getNextFilter().messageReceived(session, e.getParameter());        }    }    /**     * Call when data read from net. Will perform inial hanshake or decrypt provided     * Buffer.     * Decrytpted data reurned by getAppBuffer(), if any.     *     * @param buf        buffer to decrypt     * @param nextFilter Next filter in chain     * @throws SSLException on errors     */    public void messageReceived(NextFilter nextFilter, ByteBuffer buf) throws SSLException {        // append buf to inNetBuffer        if (inNetBuffer == null) {            inNetBuffer = IoBuffer.allocate(buf.remaining()).setAutoExpand(true);        }        inNetBuffer.put(buf);        if (!handshakeComplete) {            handshake(nextFilter);        } else {            decrypt(nextFilter);        }        if (isInboundDone()) {            // Rewind the MINA buffer if not all data is processed and inbound is finished.            int inNetBufferPosition = inNetBuffer == null? 0 : inNetBuffer.position();            buf.position(buf.position() - inNetBufferPosition);            inNetBuffer = null;        }    }    /**     * Get decrypted application data.     *     * @return buffer with data     */    public IoBuffer fetchAppBuffer() {        IoBuffer appBuffer = this.appBuffer.flip();        this.appBuffer = null;        return appBuffer;    }    /**     * Get encrypted data to be sent.     *     * @return buffer with data     */    public IoBuffer fetchOutNetBuffer() {        IoBuffer answer = outNetBuffer;        if (answer == null) {            return emptyBuffer;        }        outNetBuffer = null;        return answer.shrink();    }    /**     * Encrypt provided buffer. Encrypted data returned by getOutNetBuffer().     *     * @param src data to encrypt     * @throws SSLException on errors     */    public void encrypt(ByteBuffer src) throws SSLException {        if (!handshakeComplete) {            throw new IllegalStateException();        }        if (!src.hasRemaining()) {            if (outNetBuffer == null) {                outNetBuffer = emptyBuffer;            }            return;        }        createOutNetBuffer(src.remaining());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -