下面列出了java.nio.ByteBuffer#duplicate ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public void validateForNativeProtocol(ByteBuffer bytes, int version)
{
try
{
ByteBuffer input = bytes.duplicate();
int n = readCollectionSize(input, version);
for (int i = 0; i < n; i++)
elements.validate(readValue(input, version));
if (input.hasRemaining())
throw new MarshalException("Unexpected extraneous bytes after set value");
}
catch (BufferUnderflowException e)
{
throw new MarshalException("Not enough bytes to read a set");
}
}
static byte[] getLine(ByteBuffer bfr) {
// note: duplicate copies only bytebuffer metadata (such as position,
// limit, capicity) and not the actual content
ByteBuffer buffer = bfr.duplicate();
int last = buffer.position();
buffer.flip();
int nPos = -1; // position of \n in the buffer
for (int i=0; i < last; i++) {
int currChar = buffer.get();
// 0x0a = \n; 0x0D = \r
if (currChar == 0x0A) {
nPos = i;
break;
}
}
if (nPos == -1) {
return null;
} else {
byte[] ret = new byte[nPos+1];
// we want to use the ORIGINAL buffer here
bfr.flip();
bfr.get(ret);
bfr.compact();
return ret;
}
}
/**
* Returns the required number of bytes in the {@code source}
* {@link ByteBuffer} necessary to explore SSL/TLS connection.
* <P>
* This method tries to parse as few bytes as possible from
* {@code source} byte buffer to get the length of an
* SSL/TLS record.
* <P>
* This method accesses the {@code source} parameter in read-only
* mode, and does not update the buffer's properties such as capacity,
* limit, position, and mark values.
*
* @param source
* a {@link ByteBuffer} containing
* inbound or outbound network data for an SSL/TLS connection.
* @throws BufferUnderflowException if less than {@code RECORD_HEADER_SIZE}
* bytes remaining in {@code source}
* @return the required size in byte to explore an SSL/TLS connection
*/
public final static int getRequiredSize(ByteBuffer source) {
ByteBuffer input = source.duplicate();
// Do we have a complete header?
if (input.remaining() < RECORD_HEADER_SIZE) {
throw new BufferUnderflowException();
}
// Is it a handshake message?
byte firstByte = input.get();
byte secondByte = input.get();
byte thirdByte = input.get();
if ((firstByte & 0x80) != 0 && thirdByte == 0x01) {
// looks like a V2ClientHello
// return (((firstByte & 0x7F) << 8) | (secondByte & 0xFF)) + 2;
return RECORD_HEADER_SIZE; // Only need the header fields
} else {
return (((input.get() & 0xFF) << 8) | (input.get() & 0xFF)) + 5;
}
}
private static List<Integer> exploreHandshake(
ByteBuffer input, byte recordMajorVersion,
byte recordMinorVersion, int recordLength) throws SSLException {
// What is the handshake type?
byte handshakeType = input.get();
if (handshakeType != 0x01) { // 0x01: client_hello message
throw UndertowMessages.MESSAGES.expectedClientHello();
}
// What is the handshake body length?
int handshakeLength = getInt24(input);
// Theoretically, a single handshake message might span multiple
// records, but in practice this does not occur.
if (handshakeLength > recordLength - 4) { // 4: handshake header size
throw UndertowMessages.MESSAGES.multiRecordSSLHandshake();
}
input = input.duplicate();
input.limit(handshakeLength + input.position());
return exploreRecord(input);
}
@Override
protected void onSpsPpsVpsRtp(ByteBuffer sps, ByteBuffer pps, ByteBuffer vps) {
ByteBuffer newSps = sps.duplicate();
ByteBuffer newPps = pps.duplicate();
ByteBuffer newVps = vps != null ? vps.duplicate() : null;
rtspClient.setSPSandPPS(newSps, newPps, newVps);
rtspClient.connect();
}
/**
* Construct a PerfDataBufferPrologue instance.
*
* @param byteBuffer buffer containing the instrumentation data
*/
public AbstractPerfDataBufferPrologue(ByteBuffer byteBuffer)
throws MonitorException {
this.byteBuffer = byteBuffer.duplicate();
// the magic number is always stored in big-endian format
if (getMagic() != PERFDATA_MAGIC) {
throw new MonitorVersionException(
"Bad Magic: " + Integer.toHexString(getMagic()));
}
// set the byte order
this.byteBuffer.order(getByteOrder());
}
@Override
public void _parseDetails(ByteBuffer content) {
parseVersionAndFlags(content);
if ((getFlags() & 0x1) > 0) {
algorithmId = IsoTypeReader.readUInt24(content);
ivSize = IsoTypeReader.readUInt8(content);
kid = new byte[16];
content.get(kid);
}
long numOfEntries = IsoTypeReader.readUInt32(content);
ByteBuffer parseEight = content.duplicate();
ByteBuffer parseSixteen = content.duplicate();
ByteBuffer parseZero = content.duplicate();
entries = parseEntries(parseEight, numOfEntries, 8);
if (entries != null) {
((Buffer)content).position(content.position() + content.remaining() - parseEight.remaining());
return;
}
entries = parseEntries(parseSixteen, numOfEntries, 16);
if (entries != null) {
((Buffer)content).position(content.position() + content.remaining() - parseSixteen.remaining());
return;
}
entries = parseEntries(parseZero, numOfEntries, 0);
if (entries != null) {
((Buffer)content).position(content.position() + content.remaining() - parseZero.remaining());
return;
}
throw new RuntimeException("Cannot parse SampleEncryptionBox");
}
/**
* Construct a PerfDataBufferPrologue instance.
*
* @param byteBuffer buffer containing the instrumentation data
*/
public AbstractPerfDataBufferPrologue(ByteBuffer byteBuffer)
throws MonitorException {
this.byteBuffer = byteBuffer.duplicate();
// the magic number is always stored in big-endian format
if (getMagic() != PERFDATA_MAGIC) {
throw new MonitorVersionException(
"Bad Magic: " + Integer.toHexString(getMagic()));
}
// set the byte order
this.byteBuffer.order(getByteOrder());
}
public int compare(ByteBuffer o1, ByteBuffer o2)
{
if (!o1.hasRemaining() || !o2.hasRemaining())
return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;
ByteBuffer bb1 = o1.duplicate();
ByteBuffer bb2 = o2.duplicate();
for (int i = 0; bb1.remaining() > 0 && bb2.remaining() > 0; i++)
{
AbstractType<?> comparator = types.get(i);
int size1 = bb1.getInt();
int size2 = bb2.getInt();
// Handle nulls
if (size1 < 0)
{
if (size2 < 0)
continue;
return -1;
}
if (size2 < 0)
return 1;
ByteBuffer value1 = ByteBufferUtil.readBytes(bb1, size1);
ByteBuffer value2 = ByteBufferUtil.readBytes(bb2, size2);
int cmp = comparator.compare(value1, value2);
if (cmp != 0)
return cmp;
}
if (bb1.remaining() == 0)
return bb2.remaining() == 0 ? 0 : -1;
// bb1.remaining() > 0 && bb2.remaining() == 0
return 1;
}
@Override
public ByteBuf setBytes(int index, ByteBuffer src) {
checkIndex(index, src.remaining());
ByteBuffer tmpBuf = internalNioBuffer();
if (src == tmpBuf) {
src = src.duplicate();
}
index = idx(index);
tmpBuf.clear().position(index).limit(index + src.remaining());
tmpBuf.put(src);
return this;
}
@Override
public Plaintext decrypt(byte contentType, ByteBuffer bb,
byte[] sequence) throws GeneralSecurityException {
int len = bb.remaining();
int pos = bb.position();
ByteBuffer dup = bb.duplicate();
try {
if (len != cipher.update(dup, bb)) {
// catch BouncyCastle buffering error
throw new RuntimeException(
"Unexpected number of plaintext bytes");
}
if (bb.position() != dup.position()) {
throw new RuntimeException(
"Unexpected ByteBuffer position");
}
} catch (ShortBufferException sbe) {
// catch BouncyCastle buffering error
throw new RuntimeException("Cipher buffering error in " +
"JCE provider " + cipher.getProvider().getName(), sbe);
}
bb.position(pos);
if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
SSLLogger.fine(
"Plaintext after DECRYPTION", bb.duplicate());
}
MAC signer = (MAC)authenticator;
if (signer.macAlg().size != 0) {
checkStreamMac(signer, bb, contentType, sequence);
} else {
authenticator.increaseSequenceNumber();
}
return new Plaintext(contentType,
ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
-1, -1L, bb.slice());
}
private void runGCMWithSameBuffer(int mode, ByteBuffer buffer,
int txtOffset, int length, AlgorithmParameters params)
throws Exception {
// allocate a separate buffer
Cipher cipher = createCipher(mode, params);
ByteBuffer outBB = ByteBuffer.allocateDirect(
cipher.getOutputSize(length));
// first, generate the cipher text at an allocated buffer
buffer.flip();
buffer.limit(AADLength);
cipher.updateAAD(buffer);
buffer.limit(AADLength + txtOffset + length);
buffer.position(AADLength + txtOffset);
cipher.doFinal(buffer, outBB);
outBB.flip(); // cipher text in outBB
// next, generate cipherText again in the same buffer
Cipher anotherCipher = createCipher(mode, params);
buffer.flip();
buffer.limit(AADLength);
anotherCipher.updateAAD(buffer);
buffer.limit(AADLength + txtOffset + length);
buffer.position(AADLength + txtOffset);
// share textBuf context
ByteBuffer buf2 = buffer.duplicate();
buf2.limit(AADLength + txtOffset + anotherCipher.getOutputSize(length));
int dataProcessed2 = anotherCipher.doFinal(buffer, buf2);
buf2.position(AADLength + txtOffset);
buf2.limit(AADLength + txtOffset + dataProcessed2);
if (!buf2.equals(outBB)) {
throw new RuntimeException(
"Two results are not equal, mode:" + mode);
}
}
/**
* Create a new ByteBuffer and copy all the content of {@code source}
* ByteBuffer to the new ByteBuffer. The new ByteBuffer's limit and
* capacity will be source.capacity(), and its position will be 0.
* Note that the state of {@code source} ByteBuffer won't be changed.
*/
public static ByteBuffer copyByteBuffer(ByteBuffer source) {
// Make a duplicate of the source ByteBuffer and read data from the
// duplicate. This is to avoid affecting the source ByteBuffer's state.
ByteBuffer temp = source.duplicate();
// We want to copy all the data in the source ByteBuffer, not just the
// remaining bytes.
temp.clear();
ByteBuffer result = ByteBuffer.allocate(temp.capacity());
result.put(temp);
result.clear();
return result;
}
@Override
public ByteBuffer apply(ByteBuffer value) {
ByteBuffer ret = value.duplicate();
ret.limit(Math.min(value.limit(), value.position() + L));
return ret;
}
public NSFCompiledFormula(final ByteBuffer data) {
ByteBuffer localData = data.duplicate();
int length = localData.limit() - localData.position();
data_ = new byte[length];
localData.get(data_);
}
public ResourceTableParser(ByteBuffer buffer) {
this.buffer = buffer.duplicate();
this.buffer.order(byteOrder);
this.locales = new HashSet<>();
}
public BlobDatum(ByteBuffer val) {
super(Blob);
this.val = val.array();
this.bb = val.duplicate();
bb.flip();
}
@Test
public void testPartialPacketUnwrapJDKCompatabilityModeOff() throws Exception {
SelfSignedCertificate cert = new SelfSignedCertificate();
clientSslCtx = SslContextBuilder
.forClient()
.trustManager(cert.cert())
.sslProvider(sslClientProvider())
.build();
SSLEngine client = clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine();
serverSslCtx = SslContextBuilder
.forServer(cert.certificate(), cert.privateKey())
.sslProvider(sslServerProvider())
.build();
SSLEngine server = serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine();
try {
ByteBuffer plainClient = allocateBuffer(1024);
ByteBuffer plainClient2 = allocateBuffer(512);
ByteBuffer plainClientTotal = allocateBuffer(plainClient.capacity() + plainClient2.capacity());
plainClientTotal.put(plainClient);
plainClientTotal.put(plainClient2);
plainClient.clear();
plainClient2.clear();
plainClientTotal.flip();
ByteBuffer encClientToServer = allocateBuffer(client.getSession().getPacketBufferSize());
ByteBuffer plainServer = allocateBuffer(server.getSession().getApplicationBufferSize());
handshake(client, server);
SSLEngineResult result = client.wrap(plainClient, encClientToServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), plainClient.capacity());
final int encClientLen = result.bytesProduced();
result = client.wrap(plainClient2, encClientToServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), plainClient2.capacity());
final int encClientLen2 = result.bytesProduced();
// Flip so we can read it.
encClientToServer.flip();
// Consume a partial TLS packet.
ByteBuffer encClientFirstHalf = encClientToServer.duplicate();
encClientFirstHalf.limit(encClientLen / 2);
result = server.unwrap(encClientFirstHalf, plainServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), encClientLen / 2);
encClientToServer.position(result.bytesConsumed());
// We now have half of the first packet and the whole second packet, so lets decode all but the last byte.
ByteBuffer encClientAllButLastByte = encClientToServer.duplicate();
final int encClientAllButLastByteLen = encClientAllButLastByte.remaining() - 1;
encClientAllButLastByte.limit(encClientAllButLastByte.limit() - 1);
result = server.unwrap(encClientAllButLastByte, plainServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), encClientAllButLastByteLen);
encClientToServer.position(encClientToServer.position() + result.bytesConsumed());
// Read the last byte and verify the original content has been decrypted.
result = server.unwrap(encClientToServer, plainServer);
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
assertEquals(result.bytesConsumed(), 1);
plainServer.flip();
assertEquals(plainClientTotal, plainServer);
} finally {
cert.delete();
cleanupClientSslEngine(client);
cleanupServerSslEngine(server);
}
}
ServerHelloMessage(HandshakeContext context,
ByteBuffer m) throws IOException {
super(context);
// Reserve for HelloRetryRequest consumer if needed.
this.handshakeRecord = m.duplicate();
byte major = m.get();
byte minor = m.get();
this.serverVersion = ProtocolVersion.valueOf(major, minor);
if (this.serverVersion == null) {
// The client should only request for known protocol versions.
throw context.conContext.fatal(Alert.PROTOCOL_VERSION,
"Unsupported protocol version: " +
ProtocolVersion.nameOf(major, minor));
}
this.serverRandom = new RandomCookie(m);
this.sessionId = new SessionId(Record.getBytes8(m));
try {
sessionId.checkLength(serverVersion.id);
} catch (SSLProtocolException ex) {
throw handshakeContext.conContext.fatal(
Alert.ILLEGAL_PARAMETER, ex);
}
int cipherSuiteId = Record.getInt16(m);
this.cipherSuite = CipherSuite.valueOf(cipherSuiteId);
if (cipherSuite == null || !context.isNegotiable(cipherSuite)) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Server selected improper ciphersuite " +
CipherSuite.nameOf(cipherSuiteId));
}
this.compressionMethod = m.get();
if (compressionMethod != 0) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"compression type not supported, " + compressionMethod);
}
SSLExtension[] supportedExtensions;
if (serverRandom.isHelloRetryRequest()) {
supportedExtensions = context.sslConfig.getEnabledExtensions(
SSLHandshake.HELLO_RETRY_REQUEST);
} else {
supportedExtensions = context.sslConfig.getEnabledExtensions(
SSLHandshake.SERVER_HELLO);
}
if (m.hasRemaining()) {
this.extensions =
new SSLExtensions(this, m, supportedExtensions);
} else {
this.extensions = new SSLExtensions(this);
}
// The clientHello field is used for HelloRetryRequest producer
// only. It's fine to set it to null for receiving side of
// ServerHello/HelloRetryRequest message.
this.clientHello = null; // not used, let it be null;
}
/**
* Flush the writes to the backing channel but DOES NOT sync the channel and
* DOES NOT {@link #reset()} the {@link WriteCache}. {@link #reset()} is a
* separate operation because a common use is to retain recently flushed
* instances for read-back.
*
* @param force
* When <code>true</code>, the data will be forced to stable
* media.
*
* @throws IOException
* @throws TimeoutException
* @throws InterruptedException
*/
public boolean flush(final boolean force, final long timeout,
final TimeUnit unit) throws IOException, TimeoutException,
InterruptedException {
if(!m_closedForWrites)
closeForWrites();
// start time
final long begin = System.nanoTime();
// total nanoseconds to wait.
final long nanos = unit.toNanos(timeout);
// remaining nanoseconds to wait.
long remaining = nanos;
// final WriteCacheCounters counters = this.counters.get();
final Lock writeLock = lock.writeLock();
if (!writeLock.tryLock(remaining, TimeUnit.NANOSECONDS)) {
return false;
}
try {
final ByteBuffer tmp = this.buf.get().buffer();
if (tmp == null)
throw new IllegalStateException();
// #of bytes to write on the disk.
final int nbytes = tmp.position();
if (log.isTraceEnabled())
log.trace("nbytes=" + nbytes + ", firstOffset="
+ getFirstOffset());// + ", nflush=" + counters.nflush);
if (nbytes == 0) {
// NOP.
return true;
}
/*
* Create a view with same offset, limit and position.
*
* Note: The writeOnChannel method is given the view. This prevents
* it from adjusting the position() on the backing buffer.
*/
{
final ByteBuffer view = tmp.duplicate();
// adjust the view to just the dirty record.
view.limit(nbytes);
view.position(0);
// remaining := (total - elapsed).
remaining = nanos - (System.nanoTime() - begin);
// write the data on the disk file.
final boolean ret = writeOnChannel(view, getFirstOffset(),
Collections.unmodifiableMap(recordMap), remaining);
if (!ret) {
throw new TimeoutException("Unable to flush WriteCache");
}
// counters.nflush++;
return ret;
}
} finally {
writeLock.unlock();
}
}