Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2012 Red Hat, Inc., and individual contributors
   * as indicated by the @author tags.
   *
   * 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 org.apache.tomcat.util.net.jsse;
 
 import static org.jboss.web.CoyoteMessages.MESSAGES;
 
 import  java.nio.channels.AsynchronousSocketChannel;
 import  java.nio.channels.CompletionHandler;
 
 
SecureNioChannel

This class is an extension of the class NioChannel to allow using secure communication channels.

Created on Jan 3, 2012 at 3:43:44 PM

Author(s):
Nabil Benothman
See also:
javax.net.ssl.SSLEngine
 
 public class SecureNioChannel extends NioChannel {
 
 	private static final int MIN_BUFFER_SIZE = 16 * 1024;
 
 	protected SSLEngine sslEngine;
 	protected boolean handshakeComplete = false;
 	// To save the handshake status for each operation
Create a new instance of SecureNioChannel

Parameters:
channel the java.nio.channels.AsynchronousSocketChannel
engine The javax.net.ssl.SSLEngine linked to this channel
Throws:
NullPointerException if the one at least one of the parameters is null
 
 	protected SecureNioChannel(AsynchronousSocketChannel channelSSLEngine engine) {
 		super(channel);
 		if (engine == null) {
 		}
 
 		this. = engine;
 	}
 
 	/*
 	 * (non-Javadoc)
 	 * 
 	 * @see org.apache.tomcat.util.net.NioChannel#isSecure()
 	 */
 	public boolean isSecure() {
 		return true;
 	}
 
 	/*
 	 * (non-Javadoc)
 	 * 
 	 * @see org.apache.tomcat.util.net.NioChannel#read(java.nio.ByteBuffer)
 	 * 
 	 * @deprecated (use readBytes(...) instead)
	 */
	public Future<Integerread(ByteBuffer dst) {
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#readBytes(java.nio.ByteBuffer)
	 */
	public int readBytes(ByteBuffer dstthrows Exception {
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#readBytes(java.nio.ByteBuffer,
	 * long, java.util.concurrent.TimeUnit)
	 */
	public int readBytes(ByteBuffer dstlong timeoutTimeUnit unitthrows Exception {
		// The handshake is completed
		if (this..position() == 0) {
			this.reset(this.);
			int x = this..read(this.).get(timeoutunit);
			if (x < 0) {
			}
		}
		// Unwrap the data read, and return the number of unwrapped bytes
		return this.unwrap(this.dst);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#read(java.nio.ByteBuffer,
	 * java.lang.Object, java.nio.channels.CompletionHandler)
	 */
	public <A> void read(final ByteBuffer dst, A attachment,
			CompletionHandler<Integer, ? super A> handler) {
		this.read(dst..attachmenthandler);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#read(java.nio.ByteBuffer,
	 * long, java.util.concurrent.TimeUnit, java.lang.Object,
	 * java.nio.channels.CompletionHandler)
	 */
	public <A> void read(final ByteBuffer dstlong timeoutTimeUnit unit, A attachment,
			final CompletionHandler<Integer, ? super A> handler) {
		// The handshake is completed
		// Retrieve bytes in the internal buffer
		this.reset(this.);
		// perform read operation
		this..read(this.timeoutunitattachment,
				new CompletionHandler<Integer, A>() {
					public void completed(Integer nBytes, A attach) {
						if (nBytes < 0) {
							handler.failed(new ClosedChannelException(), attach);
							return;
						}
						try {
							// Unwrap the data
							int read = unwrap(dst);
							// If everything is OK, so complete
							handler.completed(readattach);
catch (Exception e) {
							// The operation must fails
							handler.failed(eattach);
						}
					}
					public void failed(Throwable exc, A attach) {
						handler.failed(excattach);
					}
				});
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#read(java.nio.ByteBuffer[],
	 * int, int, long, java.util.concurrent.TimeUnit, java.lang.Object,
	 * java.nio.channels.CompletionHandler)
	 */
	public <A> void read(final ByteBuffer[] dstsfinal int offsetfinal int lengthlong timeout,
			TimeUnit unit, A attachmentfinal CompletionHandler<Long, ? super A> handler) {
		// The handshake is completed
		if (handler == null) {
		}
		if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) {
		}
		final ByteBuffer netInBuffers[] = new ByteBuffer[length];
		for (int i = 0; i < lengthi++) {
			netInBuffers[i] = ByteBuffer.allocate(getSSLSession().getPacketBufferSize());
		}
		this.reset(netInBuffers[0]);
		this..read(netInBuffers, 0, lengthtimeoutunitattachment,
				new CompletionHandler<Long, A>() {
					public void completed(Long nBytes, A attach) {
						if (nBytes < 0) {
							return;
						}
						long read = 0;
						for (int i = 0; i < lengthi++) {
							try {
								read += unwrap(netInBuffers[i], dsts[offset + i]);
catch (Exception e) {
								handler.failed(eattach);
								return;
							}
						}
						handler.completed(readattach);
					}
					public void failed(Throwable exc, A attach) {
						handler.failed(excattach);
					}
				});
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#write(java.nio.ByteBuffer)
	 * 
	 * @deprecated (use writeBytes(...) instead)
	 */
	public Future<Integerwrite(ByteBuffer src) {
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.tomcat.util.net.NioChannel#writeBytes(java.nio.ByteBuffer)
	 */
	public int writeBytes(ByteBuffer srcthrows Exception {
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.tomcat.util.net.NioChannel#writeBytes(java.nio.ByteBuffer,
	 * long, java.util.concurrent.TimeUnit)
	 */
	public int writeBytes(ByteBuffer srclong timeoutTimeUnit unitthrows Exception {
		// The handshake is completed
		// Clear the output buffer
		// the number of bytes written
		int written = wrap(srcthis.);
		// write bytes to the channel
		while (this..hasRemaining()) {
			int x = this..write().get(timeoutunit);
			if (x < 0) {
			}
		}
		return written;
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#write(java.nio.ByteBuffer,
	 * java.lang.Object, java.nio.channels.CompletionHandler)
	 */
	public <A> void write(ByteBuffer src, A attachment,
			CompletionHandler<Integer, ? super A> handler) {
		this.write(src..attachmenthandler);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#write(java.nio.ByteBuffer,
	 * long, java.util.concurrent.TimeUnit, java.lang.Object,
	 * java.nio.channels.CompletionHandler)
	 */
	public <A> void write(final ByteBuffer srcfinal long timeoutfinal TimeUnit unitfinal A attachment,
			final CompletionHandler<Integer, ? super A> handler) {
		// The handshake is completed
		try {
			// Prepare the output buffer
			// Wrap the source data into the internal buffer
			final int written = wrap(srcthis.);
			// Write data to the channel
			this..write(this.timeoutunitattachment,
					new CompletionHandler<Integer, A>() {
						public void completed(Integer nBytes, A attach) {
	                        if (nBytes.intValue() < 0) {
	                            failed(new EOFException(), attach);
	                        } else if (.hasRemaining()) {
	                            .write(timeoutunitattachmentthis);
	                        } else if (written == 0) {
	                            // Special case, start over to avoid code duplication
	                            write(srctimeoutunitattachmenthandler);
	                        } else {
	                            // Call the handler completed method with the
	                            // consumed bytes number
	                            handler.completed(Integer.valueOf(written), attach);
	                        }
						}
						public void failed(Throwable exc, A attach) {
							handler.failed(excattach);
						}
					});
catch (Throwable exp) {
			handler.failed(expattachment);
		}
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#write(java.nio.ByteBuffer[],
	 * int, int, long, java.util.concurrent.TimeUnit, java.lang.Object,
	 * java.nio.channels.CompletionHandler)
	 */
	public <A> void write(final ByteBuffer[] srcsint offsetint lengthlong timeout,
			TimeUnit unit, A attachmentfinal CompletionHandler<Long, ? super A> handler) {
		// The handshake is completed
		if (handler == null) {
		}
		if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) {
		}
		ByteBuffer[] netOutBuffers = new ByteBuffer[length];
		long written = 0;
		for (int i = 0; i < lengthi++) {
			try {
				// Prepare the output buffer
				netOutBuffers[i] = ByteBuffer.allocate(size);
				// Wrap the source data into the internal buffer
				written += wrap(srcs[offset + i], netOutBuffers[i]);
				netOutBuffers[i].flip();
catch (Throwable exp) {
				handler.failed(expattachment);
				return;
			}
		}
		final long res = written;
		this..write(netOutBuffers, 0, lengthtimeoutunitattachment,
				new CompletionHandler<Long, A>() {
					public void completed(Long nBytes, A attach) {
						if (nBytes < 0) {
							handler.failed(new ClosedChannelException(), attach);
else {
							// If everything is OK, so complete
							handler.completed(resattach);
						}
					}
					public void failed(Throwable exc, A attach) {
						handler.failed(excattach);
					}
				});
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tomcat.util.net.NioChannel#close()
	 */
	public synchronized void close() throws IOException {
		if (isClosed()) {
			return;
		}
		try {
			// Handle closing the SSL Engine
			this..close();
catch (Exception e) {
			throw new IOException(e);
		}
	}

Close the SSLEngine attached to this channel

Throws:
Exception
	private void handleClose() throws Exception {
			return;
		}
		SSLSession session = getSSLSession();
		int packetBufferSize = Math.max(session.getPacketBufferSize(), );
		this. = (this. == null) ? ByteBuffer
				.allocate(packetBufferSize) : this..compact();
		this. = (this. == null) ? ByteBuffer.allocate(packetBufferSize)
			// Get close message
			switch (res.getStatus()) {
			case :
				// Execute tasks if we need to
				while (this..hasRemaining()) {
					if (this..write(this.).get() < 0) {
						break;
					}
				}
				break;
				ByteBuffer tmp = ByteBuffer.allocate(packetBufferSize
				tmp.put(this.);
				this. = tmp;
				break;
				// Cannot happens in case of wrap
			case :
				// Already closed, so return
				break;
			}
		}
	}

Getter for sslEngine

Returns:
the sslEngine
	public SSLEngine getSslEngine() {
		return this.;
	}

Setter for the sslEngine

Parameters:
sslEngine the sslEngine to set
	protected void setSslEngine(SSLEngine sslEngine) {
		this. = sslEngine;
	}

Attempts to encode a buffer of plaintext application data into SSL/TLS network data.

Parameters:
src a ByteBuffer containing outbound application data
dst a ByteBuffer to hold outbound network data
Returns:
the number of bytes consumed
Throws:
Exception if the wrap status is not OK
	private int wrap(ByteBuffer srcByteBuffer dstthrows Exception {
		// Wrap the source data into the destination buffer
		SSLEngineResult result = .wrap(srcdst);
		// the number of bytes written
		int written = result.bytesConsumed();
		switch (result.getStatus()) {
		case :
			// Execute tasks if we need to
			break;
		case :
			// We can't do encryption any more
			written = -1;
			// This case should not happen for a wrap method
			break;
		}
		return written;
	}

Attempts to decode SSL/TLS network data into a plaintext application data buffer.

Parameters:
src a ByteBuffer containing inbound network data.
dst a ByteBuffer to hold inbound application data.
Returns:
the number of bytes produced
Throws:
Exception
	private int unwrap(ByteBuffer srcByteBuffer dstthrows Exception {
		int read = 0;
		do {
			// prepare the input buffer
			src.flip();
			// unwrap the data
			result = .unwrap(srcdst);
			// compact the buffer
			src.compact();
			if (result.getStatus() == . || result.getStatus() == .) {
				// we did receive some data, add it to our total
				read += result.bytesProduced();
				// perform any tasks if needed
				// if we need more network data, then bail out for now.
				if (result.getStatus() == .) {
					break;
				}
else if (result.getStatus() == . && read > 0) {
				// buffer overflow can happen, if we have read data, then
				// empty out the destination buffer before we do another read
				break;
else if (result.getStatus() == .) {
				return -1;
else {
				// here we should trap BUFFER_OVERFLOW and call expand on the
				// buffer for now, throw an exception, as we initialized the
				// buffers in the constructor
			}
			// continue to unwrapping as long as the input buffer has stuff
while (src.position() != 0);
		return read;
	}

Initiates handshaking (initial or renegotiation) on this SSLEngine.

This method is not needed for the initial handshake, as the wrap() and unwrap() methods will implicitly call this method if handshaking has not already begun.

Note that the client may also request a session renegotiation with this SSLEngine by sending the appropriate session renegotiate handshake message.

Unlike the SSLSocket.startHandshake() method, this method does not block until handshaking is completed.

To force a complete SSL/TLS session renegotiation, the current session should be invalidated prior to calling this method.

Some protocols may not support multiple handshakes on an existing engine and may throw an SSLException.

Throws:
SSLException if a problem was encountered while signaling the SSLEngine to begin a new handshake. See the class description for more information on engine closure.
IllegalStateException if the client/server mode has not yet been set.
See also:
javax.net.ssl.SSLEngine.beginHandshake()
javax.net.ssl.SSLSession.invalidate()
	protected void handshake() throws SSLException {
			return;
		}
		try {
catch (Exception e) {
			throw new SSLException(e);
		}
	}

Check whether the handshake is already complete or not
	private void checkHandshake() {
		}
	}

Start a new handshake operation for this channel.

Throws:
SSLException
See also:
handshake()
	protected void reHandshake() throws SSLException {
        if (.getWantClientAuth()) {
            ..debug("No client cert sent for want");
        } else {
            if (!.getNeedClientAuth()) {
                .setNeedClientAuth(true);
            } else {
                ..debug("Already need client cert");
            }
        }
		try {
catch (Exception e) {
			throw new SSLException(e);
		}
	}

Execute a handshake with the client socket channel

Throws:
Exception
	private void doHandshake() throws Exception {
		SSLSession session = getSSLSession();
		int packetBufferSize = Math.max(session.getPacketBufferSize(), );
		// Create byte buffers to use for holding application data
		initBuffers(packetBufferSize);
		ByteBuffer clientNetData = ByteBuffer.allocate(packetBufferSize);
		ByteBuffer clientAppData = ByteBuffer.allocate(packetBufferSize);
		// Begin handshake
		int i = 1;
		boolean read = true;
		// Process handshaking message
		while (!) {
			switch () {
				int nBytes = 0;
				if (read) {
					clientAppData.clear();
					nBytes = this..read(this.).get();
				}
				if (nBytes < 0) {
else {
					boolean cont = false;
					// Loop while we can perform pure SSLEngine data
					do {
						// Prepare the buffer with the incoming data
						// Call unwrap
						SSLEngineResult res = .unwrap(this.clientAppData);
						// Compact the buffer, this is an optional method,
						// wonder what would happen if we didn't
						// Read in the status
						if (res.getStatus() == ..) {
							// Execute tasks if we need to
							read = true;
else if (res.getStatus() == .) {
							read = true;
else if (res.getStatus() == .) {
							ByteBuffer tmp = ByteBuffer.allocate(packetBufferSize * (++i));
							if (clientAppData.position() > 0) {
								clientAppData.flip();
							}
							tmp.put(clientAppData);
							clientAppData = tmp;
							read = false;
						}
						// Perform another unwrap?
						cont = res.getStatus() == ..
while (cont);
				}
				break;
			case :
				clientNetData.compact();
				SSLEngineResult res = .wrap(clientNetDatathis.);
				if (res.getStatus() == .) {
					// Execute tasks if we need to
					// Send the handshaking data to client
					while (this..hasRemaining()) {
						if (this..write(this.).get() < 0) {
							// Handle closed channel
						}
					}
else {
					// Wrap should always work with our buffers
				}
				break;
			case :
				break;
			case :
				break;
			}
		}
	}

Perform tasks, if any, during the handshake phase

Returns:
The handshake status ( javax.net.ssl.SSLEngineResult.HandshakeStatus)
		Runnable task = null;
		while ((task = .getDelegatedTask()) != null) {
			// Run the task in blocking mode
			task.run();
		}
	}

Try to run tasks if any.
	private void tryTasks() {
		}
	}

Parameters:
capacity
	private void initBuffers(int capacity) {
		if (this. == null) {
			this. = ByteBuffer.allocate(capacity);
else {
		}
		if (this. == null) {
			this. = ByteBuffer.allocate(capacity);
else {
		}
	}

Check if the handshake was done or not yet

Returns:
true if the handshake was already done, else false
	protected boolean handshakeComplete() {
		return this.;
	}

Returns:
The SSL Session of the channel
		return this..getSession();
	}
New to GrepCode? Check out our FAQ X