/* * Create and size the buffers appropriately. */ private void createBuffers() { /* * We'll assume the buffer sizes are the same * between client and server. */ SSLSession session = clientEngine.getSession(); int appBufferMax = session.getApplicationBufferSize(); int netBufferMax = session.getPacketBufferSize(); /* * We'll make the input buffers a bit bigger than the max needed * size, so that unwrap()s following a successful data transfer * won't generate BUFFER_OVERFLOWS. * * We'll use a mix of direct and indirect ByteBuffers for * tutorial purposes only. In reality, only use direct * ByteBuffers when they give a clear performance enhancement. */ clientIn = ByteBuffer.allocate(appBufferMax + 50); serverIn = ByteBuffer.allocate(appBufferMax + 50); cTOs = ByteBuffer.allocateDirect(netBufferMax); sTOc = ByteBuffer.allocateDirect(netBufferMax); clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes()); serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes()); }
private void createBuffers() { SSLSession session = sslStateMachine.sslEngine.getSession(); appBufferMax = session.getApplicationBufferSize(); netBufferMax = session.getPacketBufferSize(); if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug("appBufferMax=" + appBufferMax + " netBufferMax=" + netBufferMax); } }
public SSLSocketChannelWrapper(SSLContext sslContext, SocketChannel sc, boolean client) throws Exception { super(sc); sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(client); sslEngine.setEnableSessionCreation(true); SSLSession session = sslEngine.getSession(); in = ByteBuffer.allocate(64 * 1024); emptyBuffer = ByteBuffer.allocate(0); int netBufferMax = session.getPacketBufferSize(); netOutBuffer = ByteBuffer.allocate(netBufferMax); netInBuffer = ByteBuffer.allocate(netBufferMax); }
/** * Close the {@link SSLEngine} attached to this channel * * @throws Exception */ private void handleClose() throws Exception { if (sslEngine.isOutboundDone()) { return; } sslEngine.closeOutbound(); SSLSession session = getSSLSession(); int packetBufferSize = Math.max(session.getPacketBufferSize(), MIN_BUFFER_SIZE); this.netOutBuffer = (this.netOutBuffer == null) ? ByteBuffer.allocateDirect(packetBufferSize) : this.netOutBuffer.compact(); this.netInBuffer = (this.netInBuffer == null) ? ByteBuffer.allocateDirect(packetBufferSize) : this.netInBuffer.compact(); while (!sslEngine.isOutboundDone()) { // Get close message SSLEngineResult res = sslEngine.wrap(this.netInBuffer, this.netOutBuffer); switch (res.getStatus()) { case OK: // Execute tasks if we need to tryTasks(); while (this.netOutBuffer.hasRemaining()) { if (this.channel.write(this.netOutBuffer).get() < 0) { break; } this.netOutBuffer.compact(); } break; case BUFFER_OVERFLOW: ByteBuffer tmp = ByteBuffer.allocateDirect(packetBufferSize + this.netOutBuffer.capacity()); this.netOutBuffer.flip(); tmp.put(this.netOutBuffer); this.netOutBuffer = tmp; break; case BUFFER_UNDERFLOW: // Cannot happens in case of wrap case CLOSED: // Already closed, so return break; } } }
/** * Execute a handshake with the client socket channel * * @throws Exception */ private void doHandshake() throws Exception { SSLSession session = getSSLSession(); int packetBufferSize = Math.max(session.getPacketBufferSize(), MIN_BUFFER_SIZE); // Create byte buffers to use for holding application data initBuffers(packetBufferSize); ByteBuffer clientNetData = ByteBuffer.allocateDirect(packetBufferSize); ByteBuffer clientAppData = ByteBuffer.allocateDirect(packetBufferSize); // Begin handshake sslEngine.beginHandshake(); handshakeStatus = sslEngine.getHandshakeStatus(); int i = 1; boolean read = true; // Process handshaking message while (!handshakeComplete) { switch (handshakeStatus) { case NEED_UNWRAP: int nBytes = 0; if (read) { clientAppData.clear(); nBytes = this.channel.read(this.netInBuffer).get(); } if (nBytes < 0) { throw new IOException(MESSAGES.errorUnwrappingHandshake()); } else { boolean cont = false; // Loop while we can perform pure SSLEngine data do { // Prepare the buffer with the incoming data this.netInBuffer.flip(); // Call unwrap SSLEngineResult res = sslEngine.unwrap(this.netInBuffer, clientAppData); // Compact the buffer, this is an optional method, // wonder what would happen if we didn't this.netInBuffer.compact(); // Read in the status handshakeStatus = res.getHandshakeStatus(); if (res.getStatus() == SSLEngineResult.Status.OK) { // Execute tasks if we need to tryTasks(); read = true; } else if (res.getStatus() == Status.BUFFER_UNDERFLOW) { read = true; } else if (res.getStatus() == Status.BUFFER_OVERFLOW) { ByteBuffer tmp = ByteBuffer.allocateDirect(packetBufferSize * (++i)); if (clientAppData.position() > 0) { clientAppData.flip(); } tmp.put(clientAppData); clientAppData = tmp; read = false; } // Perform another unwrap? cont = res.getStatus() == SSLEngineResult.Status.OK && handshakeStatus == HandshakeStatus.NEED_UNWRAP; } while (cont); } break; case NEED_WRAP: clientNetData.compact(); this.netOutBuffer.clear(); SSLEngineResult res = sslEngine.wrap(clientNetData, this.netOutBuffer); handshakeStatus = res.getHandshakeStatus(); this.netOutBuffer.flip(); if (res.getStatus() == Status.OK) { // Execute tasks if we need to tryTasks(); // Send the handshaking data to client while (this.netOutBuffer.hasRemaining()) { if (this.channel.write(this.netOutBuffer).get() < 0) { // Handle closed channel throw new IOException(MESSAGES.errorWrappingHandshake()); } } } else { // Wrap should always work with our buffers throw new IOException( MESSAGES.errorWrappingHandshakeStatus(res.getStatus().toString())); } break; case NEED_TASK: handshakeStatus = tasks(); break; case NOT_HANDSHAKING: throw new SSLHandshakeException(MESSAGES.notHandshaking()); case FINISHED: handshakeComplete = true; break; } } this.handshakeComplete = (handshakeStatus == HandshakeStatus.FINISHED); }