Java tutorial
/* * Copyright 2018 The gRPC Authors * * 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 io.grpc.alts.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import java.nio.ByteBuffer; import java.security.GeneralSecurityException; /** * A wrapper for a {@link io.grpc.alts.internal.TsiHandshaker} that accepts netty {@link ByteBuf}s. */ public final class NettyTsiHandshaker { private BufUnwrapper unwrapper = new BufUnwrapper(); private final TsiHandshaker internalHandshaker; public NettyTsiHandshaker(TsiHandshaker handshaker) { internalHandshaker = checkNotNull(handshaker); } /** * Gets data that is ready to be sent to the to the remote peer. This should be called in a loop * until no bytes are written to the output buffer. * * @param out the buffer to receive the bytes. */ void getBytesToSendToPeer(ByteBuf out) throws GeneralSecurityException { checkState(unwrapper != null, "protector already created"); try (BufUnwrapper unwrapper = this.unwrapper) { // Write as many bytes as possible into the buffer. int bytesWritten = 0; for (ByteBuffer nioBuffer : unwrapper.writableNioBuffers(out)) { if (!nioBuffer.hasRemaining()) { // This buffer doesn't have any more space to write, go to the next buffer. continue; } int prevPos = nioBuffer.position(); internalHandshaker.getBytesToSendToPeer(nioBuffer); bytesWritten += nioBuffer.position() - prevPos; // If the buffer position was not changed, the frame has been completely read into the // buffers. if (nioBuffer.position() == prevPos) { break; } } out.writerIndex(out.writerIndex() + bytesWritten); } } /** * Process handshake data received from the remote peer. * * @return {@code true}, if the handshake has all the data it needs to process and {@code false}, * if the method must be called again to complete processing. */ boolean processBytesFromPeer(ByteBuf data) throws GeneralSecurityException { checkState(unwrapper != null, "protector already created"); try (BufUnwrapper unwrapper = this.unwrapper) { int bytesRead = 0; boolean done = false; for (ByteBuffer nioBuffer : unwrapper.readableNioBuffers(data)) { if (!nioBuffer.hasRemaining()) { // This buffer has been fully read, continue to the next buffer. continue; } int prevPos = nioBuffer.position(); done = internalHandshaker.processBytesFromPeer(nioBuffer); bytesRead += nioBuffer.position() - prevPos; if (done) { break; } } data.readerIndex(data.readerIndex() + bytesRead); return done; } } /** * Returns true if and only if the handshake is still in progress * * @return true, if the handshake is still in progress, false otherwise. */ boolean isInProgress() { return internalHandshaker.isInProgress(); } /** * Returns the peer extracted from a completed handshake. * * @return the extracted peer. */ TsiPeer extractPeer() throws GeneralSecurityException { checkState(!internalHandshaker.isInProgress()); return internalHandshaker.extractPeer(); } /** * Returns the peer extracted from a completed handshake. * * @return the extracted peer. */ Object extractPeerObject() throws GeneralSecurityException { checkState(!internalHandshaker.isInProgress()); return internalHandshaker.extractPeerObject(); } /** * Creates a frame protector from a completed handshake. No other methods may be called after the * frame protector is created. * * @param maxFrameSize the requested max frame size, the callee is free to ignore. * @return a new {@link io.grpc.alts.internal.TsiFrameProtector}. */ TsiFrameProtector createFrameProtector(int maxFrameSize, ByteBufAllocator alloc) { unwrapper = null; return internalHandshaker.createFrameProtector(maxFrameSize, alloc); } /** * Creates a frame protector from a completed handshake. No other methods may be called after the * frame protector is created. * * @return a new {@link io.grpc.alts.internal.TsiFrameProtector}. */ TsiFrameProtector createFrameProtector(ByteBufAllocator alloc) { unwrapper = null; return internalHandshaker.createFrameProtector(alloc); } }