mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-19 18:00:39 +01:00
Buffers: new utils class for common operations on P2P message ByteBuffer
This commit is contained in:
parent
1869fa197e
commit
ce39967d83
89
core/src/main/java/org/bitcoinj/base/internal/Buffers.java
Normal file
89
core/src/main/java/org/bitcoinj/base/internal/Buffers.java
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright by the original author or 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 org.bitcoinj.base.internal;
|
||||
|
||||
import org.bitcoinj.base.VarInt;
|
||||
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.bitcoinj.base.internal.Preconditions.check;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkState;
|
||||
|
||||
/**
|
||||
* Utility methods for common operations on Bitcoin P2P message buffers.
|
||||
*/
|
||||
public class Buffers {
|
||||
/**
|
||||
* Read given number of bytes from the buffer.
|
||||
*
|
||||
* @param buf buffer to read from
|
||||
* @param length number of bytes to read
|
||||
* @return bytes read
|
||||
* @throws BufferUnderflowException if the read value extends beyond the remaining bytes of the buffer
|
||||
*/
|
||||
public static byte[] readBytes(ByteBuffer buf, int length) throws BufferUnderflowException {
|
||||
// defensive check against cheap memory exhaustion attack
|
||||
check(length <= buf.remaining(), BufferUnderflowException::new);
|
||||
byte[] b = new byte[length];
|
||||
buf.get(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* First read a {@link VarInt} from the buffer and use it to determine the number of bytes to be read. Then read
|
||||
* that many bytes into the byte array to be returned. This construct is frequently used by Bitcoin protocols.
|
||||
*
|
||||
* @param buf buffer to read from
|
||||
* @return read bytes
|
||||
* @throws BufferUnderflowException if the read value extends beyond the remaining bytes of the buffer
|
||||
*/
|
||||
public static byte[] readLengthPrefixedBytes(ByteBuffer buf) throws BufferUnderflowException {
|
||||
int length = VarInt.read(buf).intValue();
|
||||
return readBytes(buf, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* First read a {@link VarInt} from the buffer and use it to determine the number of bytes to read. Then read
|
||||
* that many bytes and interpret it as an UTF-8 encoded string to be returned. This construct is frequently used
|
||||
* by Bitcoin protocols.
|
||||
*
|
||||
* @param buf buffer to read from
|
||||
* @return read string
|
||||
* @throws BufferUnderflowException if the read value extends beyond the remaining bytes of the buffer
|
||||
*/
|
||||
public static String readLengthPrefixedString(ByteBuffer buf) throws BufferUnderflowException {
|
||||
return new String(readLengthPrefixedBytes(buf), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance buffer position by a given number of bytes.
|
||||
*
|
||||
* @param buf buffer to skip bytes on
|
||||
* @param numBytes number of bytes to skip
|
||||
* @return the buffer
|
||||
* @throws BufferUnderflowException if the read value extends beyond the remaining bytes of the buffer
|
||||
*/
|
||||
public static ByteBuffer skipBytes(ByteBuffer buf, int numBytes) throws BufferUnderflowException {
|
||||
checkArgument(numBytes >= 0);
|
||||
check(numBytes <= buf.remaining(), BufferUnderflowException::new);
|
||||
buf.position(buf.position() + numBytes);
|
||||
return buf;
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ package org.bitcoinj.core;
|
||||
|
||||
import org.bitcoinj.base.Sha256Hash;
|
||||
import org.bitcoinj.base.VarInt;
|
||||
import org.bitcoinj.base.internal.Buffers;
|
||||
import org.bitcoinj.base.internal.ByteUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -30,11 +31,6 @@ import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.bitcoinj.base.internal.Preconditions.check;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkState;
|
||||
|
||||
/**
|
||||
* <p>A Message is a data structure that can be serialized/deserialized using the Bitcoin serialization format.
|
||||
@ -174,15 +170,8 @@ public abstract class Message {
|
||||
return VarInt.read(payload);
|
||||
}
|
||||
|
||||
private void checkReadLength(int length) throws BufferUnderflowException {
|
||||
check(length <= payload.remaining(), BufferUnderflowException::new);
|
||||
}
|
||||
|
||||
protected byte[] readBytes(int length) throws BufferUnderflowException {
|
||||
checkReadLength(length);
|
||||
byte[] b = new byte[length];
|
||||
payload.get(b);
|
||||
return b;
|
||||
return Buffers.readBytes(payload, length);
|
||||
}
|
||||
|
||||
protected byte readByte() throws BufferUnderflowException {
|
||||
@ -190,13 +179,11 @@ public abstract class Message {
|
||||
}
|
||||
|
||||
protected byte[] readByteArray() throws BufferUnderflowException {
|
||||
final int length = readVarInt().intValue();
|
||||
return readBytes(length);
|
||||
return Buffers.readLengthPrefixedBytes(payload);
|
||||
}
|
||||
|
||||
protected String readStr() throws BufferUnderflowException {
|
||||
int length = readVarInt().intValue();
|
||||
return length == 0 ? "" : new String(readBytes(length), StandardCharsets.UTF_8); // optimization for empty strings
|
||||
return Buffers.readLengthPrefixedString(payload);
|
||||
}
|
||||
|
||||
protected Sha256Hash readHash() throws BufferUnderflowException {
|
||||
@ -204,9 +191,7 @@ public abstract class Message {
|
||||
}
|
||||
|
||||
protected void skipBytes(int numBytes) throws BufferUnderflowException {
|
||||
checkArgument(numBytes >= 0);
|
||||
checkReadLength(numBytes);
|
||||
payload.position(payload.position() + numBytes);
|
||||
Buffers.skipBytes(payload, numBytes);
|
||||
}
|
||||
|
||||
/** Network parameters this message was created with. */
|
||||
|
Loading…
Reference in New Issue
Block a user