Util: Hook in ByteArrayStream

Set accurate lengths for zero-copy
This commit is contained in:
zzz
2020-11-04 12:04:24 +00:00
parent 35da97936d
commit e242015145
25 changed files with 78 additions and 61 deletions

View File

@ -1,7 +1,6 @@
package net.i2p.client.streaming; package net.i2p.client.streaming;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -15,6 +14,7 @@ import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession; import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException; import net.i2p.client.I2PSessionException;
import net.i2p.crypto.SigType; import net.i2p.crypto.SigType;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.Log; import net.i2p.util.Log;
/** /**
@ -171,10 +171,10 @@ public class I2PSocketManagerFactory {
public static I2PSocketManager createManager(String i2cpHost, int i2cpPort, Properties opts, public static I2PSocketManager createManager(String i2cpHost, int i2cpPort, Properties opts,
IncomingConnectionFilter filter) { IncomingConnectionFilter filter) {
I2PClient client = I2PClientFactory.createClient(); I2PClient client = I2PClientFactory.createClient();
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024); ByteArrayStream keyStream = new ByteArrayStream(1024);
try { try {
client.createDestination(keyStream, getSigType(opts)); client.createDestination(keyStream, getSigType(opts));
ByteArrayInputStream in = new ByteArrayInputStream(keyStream.toByteArray()); ByteArrayInputStream in = keyStream.asInputStream();
return createManager(in, i2cpHost, i2cpPort, opts, filter); return createManager(in, i2cpHost, i2cpPort, opts, filter);
} catch (IOException ioe) { } catch (IOException ioe) {
getLog().error("Error creating the destination for socket manager", ioe); getLog().error("Error creating the destination for socket manager", ioe);
@ -359,7 +359,7 @@ public class I2PSocketManagerFactory {
throws I2PSessionException { throws I2PSessionException {
if (myPrivateKeyStream == null) { if (myPrivateKeyStream == null) {
I2PClient client = I2PClientFactory.createClient(); I2PClient client = I2PClientFactory.createClient();
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024); ByteArrayStream keyStream = new ByteArrayStream(1024);
try { try {
client.createDestination(keyStream, getSigType(opts)); client.createDestination(keyStream, getSigType(opts));
} catch (I2PException e) { } catch (I2PException e) {
@ -367,7 +367,7 @@ public class I2PSocketManagerFactory {
} catch (IOException e) { } catch (IOException e) {
throw new I2PSessionException("Error creating keys", e); throw new I2PSessionException("Error creating keys", e);
} }
myPrivateKeyStream = new ByteArrayInputStream(keyStream.toByteArray()); myPrivateKeyStream = keyStream.asInputStream();
} }
return createManager(myPrivateKeyStream, i2cpHost, i2cpPort, opts, false, filter); return createManager(myPrivateKeyStream, i2cpHost, i2cpPort, opts, false, filter);
} }

View File

@ -1,7 +1,5 @@
package net.i2p.client.streaming.impl; package net.i2p.client.streaming.impl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.ConnectException; import java.net.ConnectException;
@ -38,6 +36,7 @@ import net.i2p.data.Hash;
import net.i2p.data.PrivateKey; import net.i2p.data.PrivateKey;
import net.i2p.data.PublicKey; import net.i2p.data.PublicKey;
import net.i2p.data.SimpleDataStructure; import net.i2p.data.SimpleDataStructure;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.ConvertToHash; import net.i2p.util.ConvertToHash;
import net.i2p.util.ConcurrentHashSet; import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -275,7 +274,7 @@ public class I2PSocketManagerFull implements I2PSocketManager {
// We don't actually need the same pubkey in the dest, just in the LS. // We don't actually need the same pubkey in the dest, just in the LS.
// The dest one is unused. But this is how we find the LS keys // The dest one is unused. But this is how we find the LS keys
// to reuse in RequestLeaseSetMessageHandler. // to reuse in RequestLeaseSetMessageHandler.
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024); ByteArrayStream keyStream = new ByteArrayStream(1024);
try { try {
SigType type = getSigType(opts); SigType type = getSigType(opts);
if (type != SigType.DSA_SHA1) { if (type != SigType.DSA_SHA1) {
@ -299,7 +298,7 @@ public class I2PSocketManagerFull implements I2PSocketManager {
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw new I2PSessionException("Error creating keys", e); throw new I2PSessionException("Error creating keys", e);
} }
privateKeyStream = new ByteArrayInputStream(keyStream.toByteArray()); privateKeyStream = keyStream.asInputStream();
} }
I2PSession rv = _session.addSubsession(privateKeyStream, opts); I2PSession rv = _session.addSubsession(privateKeyStream, opts);
boolean added = _subsessions.add(rv); boolean added = _subsessions.add(rv);

View File

@ -40,6 +40,7 @@ import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey; import net.i2p.data.SigningPublicKey;
import net.i2p.data.SimpleDataStructure; import net.i2p.data.SimpleDataStructure;
import net.i2p.util.Addresses; import net.i2p.util.Addresses;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.HexDump; import net.i2p.util.HexDump;
import net.i2p.util.RandomSource; import net.i2p.util.RandomSource;
import net.i2p.util.SecureFileOutputStream; import net.i2p.util.SecureFileOutputStream;
@ -904,11 +905,11 @@ public final class SelfSignedGenerator {
* @throws IllegalArgumentException * @throws IllegalArgumentException
*/ */
private static byte[] getEncodedOIDSeq(String oid) { private static byte[] getEncodedOIDSeq(String oid) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(16); byte[] b = getEncodedOID(oid);
ByteArrayStream baos = new ByteArrayStream(4 + b.length);
baos.write(0x30); baos.write(0x30);
// len to be filled in later // len to be filled in later
baos.write(0); baos.write(0);
byte[] b = getEncodedOID(oid);
baos.write(b, 0, b.length); baos.write(b, 0, b.length);
// NULL // NULL
baos.write(0x05); baos.write(0x05);

View File

@ -19,6 +19,7 @@ import net.i2p.crypto.KeyPair;
import net.i2p.crypto.SHA256Generator; import net.i2p.crypto.SHA256Generator;
import net.i2p.crypto.SigType; import net.i2p.crypto.SigType;
import net.i2p.crypto.x25519.X25519DH; import net.i2p.crypto.x25519.X25519DH;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.Clock; import net.i2p.util.Clock;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -853,7 +854,7 @@ public class EncryptedLeaseSet extends LeaseSet2 {
_flags = saveFlags; _flags = saveFlags;
SigningPrivateKey bkey = Blinding.blind(key, _alpha); SigningPrivateKey bkey = Blinding.blind(key, _alpha);
int len = size(); int len = size();
ByteArrayOutputStream out = new ByteArrayOutputStream(1 + len); ByteArrayStream out = new ByteArrayStream(1 + len);
try { try {
// unlike LS1, sig covers type // unlike LS1, sig covers type
out.write(getType()); out.write(getType());

View File

@ -9,7 +9,6 @@ package net.i2p.data;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -18,6 +17,7 @@ import java.util.Arrays;
import net.i2p.crypto.EncType; import net.i2p.crypto.EncType;
import net.i2p.crypto.SHA256Generator; import net.i2p.crypto.SHA256Generator;
import net.i2p.crypto.SigType; import net.i2p.crypto.SigType;
import net.i2p.util.ByteArrayStream;
/** /**
* KeysAndCert has a public key, a signing key, and a certificate. * KeysAndCert has a public key, a signing key, and a certificate.
@ -239,7 +239,9 @@ public class KeysAndCert extends DataStructureImpl {
return __calculatedHash; return __calculatedHash;
byte identBytes[]; byte identBytes[];
try { try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(400); if (_certificate == null)
throw new IllegalStateException("KAC hash error");
ByteArrayStream baos = new ByteArrayStream(384 + _certificate.size());
writeBytes(baos); writeBytes(baos);
identBytes = baos.toByteArray(); identBytes = baos.toByteArray();
} catch (IOException ioe) { } catch (IOException ioe) {

View File

@ -10,7 +10,6 @@ package net.i2p.data;
*/ */
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -22,6 +21,7 @@ import net.i2p.I2PAppContext;
import net.i2p.crypto.DSAEngine; import net.i2p.crypto.DSAEngine;
import net.i2p.crypto.EncType; import net.i2p.crypto.EncType;
import net.i2p.crypto.SigType; import net.i2p.crypto.SigType;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.Clock; import net.i2p.util.Clock;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.RandomSource; import net.i2p.util.RandomSource;
@ -335,7 +335,7 @@ public class LeaseSet extends DatabaseEntry {
if ((_destination == null) || (_encryptionKey == null) || (_signingKey == null)) if ((_destination == null) || (_encryptionKey == null) || (_signingKey == null))
return null; return null;
int len = size(); int len = size();
ByteArrayOutputStream out = new ByteArrayOutputStream(len); ByteArrayStream out = new ByteArrayStream(len);
try { try {
_destination.writeBytes(out); _destination.writeBytes(out);
_encryptionKey.writeBytes(out); _encryptionKey.writeBytes(out);
@ -497,7 +497,7 @@ public class LeaseSet extends DatabaseEntry {
if (size < 1 || size > MAX_LEASES-1) if (size < 1 || size > MAX_LEASES-1)
throw new IllegalArgumentException("Bad number of leases for encryption"); throw new IllegalArgumentException("Bad number of leases for encryption");
int datalen = ((DATA_LEN * size / 16) + 1) * 16; int datalen = ((DATA_LEN * size / 16) + 1) * 16;
ByteArrayOutputStream baos = new ByteArrayOutputStream(datalen); ByteArrayStream baos = new ByteArrayStream(datalen);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
_leases.get(i).getGateway().writeBytes(baos); _leases.get(i).getGateway().writeBytes(baos);
_leases.get(i).getTunnelId().writeBytes(baos); _leases.get(i).getTunnelId().writeBytes(baos);
@ -545,7 +545,7 @@ public class LeaseSet extends DatabaseEntry {
throw new DataFormatException("Bad number of leases decrypting " + _destination.toBase32() + throw new DataFormatException("Bad number of leases decrypting " + _destination.toBase32() +
" - is this destination encrypted?"); " - is this destination encrypted?");
int datalen = DATA_LEN * size; int datalen = DATA_LEN * size;
ByteArrayOutputStream baos = new ByteArrayOutputStream(datalen); ByteArrayStream baos = new ByteArrayStream(datalen);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
_leases.get(i).getGateway().writeBytes(baos); _leases.get(i).getGateway().writeBytes(baos);
_leases.get(i).getTunnelId().writeBytes(baos); _leases.get(i).getTunnelId().writeBytes(baos);

View File

@ -1,6 +1,5 @@
package net.i2p.data; package net.i2p.data;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -16,6 +15,7 @@ import net.i2p.crypto.DSAEngine;
import net.i2p.crypto.EncType; import net.i2p.crypto.EncType;
import net.i2p.crypto.SigAlgo; import net.i2p.crypto.SigAlgo;
import net.i2p.crypto.SigType; import net.i2p.crypto.SigType;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.Clock; import net.i2p.util.Clock;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.OrderedProperties; import net.i2p.util.OrderedProperties;
@ -289,7 +289,7 @@ public class LeaseSet2 extends LeaseSet {
* @return null on error * @return null on error
*/ */
public static Signature offlineSign(long expires, SigningPublicKey transientSPK, SigningPrivateKey priv) { public static Signature offlineSign(long expires, SigningPublicKey transientSPK, SigningPrivateKey priv) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(128); ByteArrayStream baos = new ByteArrayStream(4 + 2 + transientSPK.length());
try { try {
DataHelper.writeLong(baos, 4, expires / 1000); DataHelper.writeLong(baos, 4, expires / 1000);
DataHelper.writeLong(baos, 2, transientSPK.getType().getCode()); DataHelper.writeLong(baos, 2, transientSPK.getType().getCode());
@ -314,7 +314,7 @@ public class LeaseSet2 extends LeaseSet {
I2PAppContext ctx = I2PAppContext.getGlobalContext(); I2PAppContext ctx = I2PAppContext.getGlobalContext();
if (_transientExpires < ctx.clock().now()) if (_transientExpires < ctx.clock().now())
return false; return false;
ByteArrayOutputStream baos = new ByteArrayOutputStream(6 + _transientSigningPublicKey.length()); ByteArrayStream baos = new ByteArrayStream(4 + 2 + _transientSigningPublicKey.length());
try { try {
DataHelper.writeLong(baos, 4, _transientExpires / 1000); DataHelper.writeLong(baos, 4, _transientExpires / 1000);
DataHelper.writeLong(baos, 2, _transientSigningPublicKey.getType().getCode()); DataHelper.writeLong(baos, 2, _transientSigningPublicKey.getType().getCode());
@ -387,7 +387,7 @@ public class LeaseSet2 extends LeaseSet {
if (_destination == null) if (_destination == null)
return null; return null;
int len = size(); int len = size();
ByteArrayOutputStream out = new ByteArrayOutputStream(len); ByteArrayStream out = new ByteArrayStream(len);
try { try {
writeBytesWithoutSig(out); writeBytesWithoutSig(out);
} catch (IOException ioe) { } catch (IOException ioe) {
@ -605,7 +605,7 @@ public class LeaseSet2 extends LeaseSet {
if (key == null) if (key == null)
throw new DataFormatException("No signing key"); throw new DataFormatException("No signing key");
int len = size(); int len = size();
ByteArrayOutputStream out = new ByteArrayOutputStream(1 + len); ByteArrayStream out = new ByteArrayStream(1 + len);
try { try {
// unlike LS1, sig covers type // unlike LS1, sig covers type
out.write(getType()); out.write(getType());
@ -647,7 +647,7 @@ public class LeaseSet2 extends LeaseSet {
spk = getSigningPublicKey(); spk = getSigningPublicKey();
} }
int len = size(); int len = size();
ByteArrayOutputStream out = new ByteArrayOutputStream(1 + len); ByteArrayStream out = new ByteArrayStream(1 + len);
try { try {
// unlike LS1, sig covers type // unlike LS1, sig covers type
out.write(getType()); out.write(getType());

View File

@ -5,12 +5,12 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.util.ByteArrayStream;
/** /**
* Tell the other side the limits * Tell the other side the limits
@ -63,7 +63,7 @@ public class BandwidthLimitsMessage extends I2CPMessageImpl {
@Override @Override
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream(64); ByteArrayStream os = new ByteArrayStream(4 * LIMITS);
try { try {
for (int i = 0; i < LIMITS; i++) { for (int i = 0; i < LIMITS; i++) {
DataHelper.writeLong(os, 4, data[i]); DataHelper.writeLong(os, 4, data[i]);

View File

@ -1,6 +1,5 @@
package net.i2p.data.i2cp; package net.i2p.data.i2cp;
import java.io.ByteArrayOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -19,6 +18,7 @@ import net.i2p.data.LeaseSet2;
import net.i2p.data.MetaLeaseSet; import net.i2p.data.MetaLeaseSet;
import net.i2p.data.PrivateKey; import net.i2p.data.PrivateKey;
import net.i2p.data.PublicKey; import net.i2p.data.PublicKey;
import net.i2p.util.ByteArrayStream;
/** /**
* Like CreateLeaseSetMessage, but supports both old * Like CreateLeaseSetMessage, but supports both old
@ -174,7 +174,7 @@ public class CreateLeaseSet2Message extends CreateLeaseSetMessage {
size += pk.length(); size += pk.length();
} }
} }
ByteArrayOutputStream os = new ByteArrayOutputStream(size); ByteArrayStream os = new ByteArrayStream(size);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
os.write(_leaseSet.getType()); os.write(_leaseSet.getType());

View File

@ -9,7 +9,6 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -17,6 +16,7 @@ import net.i2p.data.DataFormatException;
import net.i2p.data.LeaseSet; import net.i2p.data.LeaseSet;
import net.i2p.data.PrivateKey; import net.i2p.data.PrivateKey;
import net.i2p.data.SigningPrivateKey; import net.i2p.data.SigningPrivateKey;
import net.i2p.util.ByteArrayStream;
/** /**
* Defines the message a client sends to a router when authorizing * Defines the message a client sends to a router when authorizing
@ -105,7 +105,7 @@ public class CreateLeaseSetMessage extends I2CPMessageImpl {
+ _signingPrivateKey.length() + _signingPrivateKey.length()
+ PrivateKey.KEYSIZE_BYTES + PrivateKey.KEYSIZE_BYTES
+ _leaseSet.size(); + _leaseSet.size();
ByteArrayOutputStream os = new ByteArrayOutputStream(size); ByteArrayStream os = new ByteArrayStream(size);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
_signingPrivateKey.writeBytes(os); _signingPrivateKey.writeBytes(os);

View File

@ -6,13 +6,13 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.util.ByteArrayStream;
/** /**
* Response to DestLookupMessage. * Response to DestLookupMessage.
@ -76,7 +76,7 @@ public class DestReplyMessage extends I2CPMessageImpl {
return new byte[0]; // null response allowed return new byte[0]; // null response allowed
return _hash.getData(); return _hash.getData();
} }
ByteArrayOutputStream os = new ByteArrayOutputStream(_dest.size()); ByteArrayStream os = new ByteArrayStream(_dest.size());
try { try {
_dest.writeBytes(os); _dest.writeBytes(os);
} catch (DataFormatException dfe) { } catch (DataFormatException dfe) {

View File

@ -9,11 +9,11 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.util.ByteArrayStream;
/** /**
* Defines the message a client sends to a router when destroying * Defines the message a client sends to a router when destroying
@ -61,7 +61,7 @@ public class DestroySessionMessage extends I2CPMessageImpl {
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if (_sessionId == null) if (_sessionId == null)
throw new I2CPMessageException("Unable to write out the message as there is not enough data"); throw new I2CPMessageException("Unable to write out the message as there is not enough data");
ByteArrayOutputStream os = new ByteArrayOutputStream(64); ByteArrayStream os = new ByteArrayStream(2);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
} catch (DataFormatException dfe) { } catch (DataFormatException dfe) {

View File

@ -9,12 +9,12 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.util.ByteArrayStream;
/** /**
* Defines the message a client sends to a router when destroying * Defines the message a client sends to a router when destroying
@ -48,7 +48,10 @@ public class DisconnectMessage extends I2CPMessageImpl {
@Override @Override
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream(64); int len = 1;
if (_reason != null)
len += _reason.length();
ByteArrayStream os = new ByteArrayStream(len);
try { try {
DataHelper.writeString(os, _reason); DataHelper.writeString(os, _reason);
} catch (DataFormatException dfe) { } catch (DataFormatException dfe) {

View File

@ -9,7 +9,6 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Map; import java.util.Map;
@ -17,6 +16,7 @@ import java.util.Properties;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.OrderedProperties; import net.i2p.util.OrderedProperties;
/** /**
@ -99,7 +99,7 @@ public class GetDateMessage extends I2CPMessageImpl {
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if (_version == null) if (_version == null)
return new byte[0]; return new byte[0];
ByteArrayOutputStream os = new ByteArrayOutputStream(_options != null ? 128 : 16); ByteArrayStream os = new ByteArrayStream(_options != null ? 128 : (1 + 6));
try { try {
DataHelper.writeString(os, _version); DataHelper.writeString(os, _version);
if (_options != null && !_options.isEmpty()) if (_options != null && !_options.isEmpty())

View File

@ -5,7 +5,6 @@ package net.i2p.data.i2cp;
* with no warranty of any kind, either expressed or implied. * with no warranty of any kind, either expressed or implied.
*/ */
import java.io.ByteArrayOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -13,6 +12,7 @@ import java.io.InputStream;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.util.ByteArrayStream;
/** /**
* Request the router look up the dest for a hash * Request the router look up the dest for a hash
@ -158,7 +158,7 @@ public class HostLookupMessage extends I2CPMessageImpl {
} else { } else {
throw new I2CPMessageException("bad type"); throw new I2CPMessageException("bad type");
} }
ByteArrayOutputStream os = new ByteArrayOutputStream(len); ByteArrayStream os = new ByteArrayStream(len);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
DataHelper.writeLong(os, 4, _reqID); DataHelper.writeLong(os, 4, _reqID);

View File

@ -6,7 +6,6 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -14,6 +13,7 @@ import java.io.InputStream;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.util.ByteArrayStream;
/** /**
* Response to HostLookupMessage. Replaces DestReplyMessage. * Response to HostLookupMessage. Replaces DestReplyMessage.
@ -135,7 +135,7 @@ public class HostReplyMessage extends I2CPMessageImpl {
throw new I2CPMessageException("Unable to write out the message as there is not enough data"); throw new I2CPMessageException("Unable to write out the message as there is not enough data");
len += _dest.size(); len += _dest.size();
} }
ByteArrayOutputStream os = new ByteArrayOutputStream(len); ByteArrayStream os = new ByteArrayStream(len);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
DataHelper.writeLong(os, 4, _reqID); DataHelper.writeLong(os, 4, _reqID);

View File

@ -9,11 +9,11 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.util.ByteArrayStream;
/** /**
* Defines the message a client sends to a router when asking the * Defines the message a client sends to a router when asking the
@ -93,7 +93,11 @@ public class ReportAbuseMessage extends I2CPMessageImpl {
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if ((_sessionId == null) || (_severity == null) || (_reason == null)) if ((_sessionId == null) || (_severity == null) || (_reason == null))
throw new I2CPMessageException("Not enough information to construct the message"); throw new I2CPMessageException("Not enough information to construct the message");
ByteArrayOutputStream os = new ByteArrayOutputStream(32); int len = 2 + 1 + 4 + 1;
String r = _reason.getReason();
if (r != null)
len += r.length();
ByteArrayStream os = new ByteArrayStream(len);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
_severity.writeBytes(os); _severity.writeBytes(os);

View File

@ -9,7 +9,6 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
@ -21,6 +20,7 @@ import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.data.TunnelId; import net.i2p.data.TunnelId;
import net.i2p.util.ByteArrayStream;
/** /**
* Defines the message a router sends to a client to request that * Defines the message a router sends to a client to request that
@ -38,7 +38,7 @@ public class RequestLeaseSetMessage extends I2CPMessageImpl {
private Date _end; private Date _end;
public RequestLeaseSetMessage() { public RequestLeaseSetMessage() {
_endpoints = new ArrayList<TunnelEndpoint>(); _endpoints = new ArrayList<TunnelEndpoint>(6);
} }
public SessionId getSessionId() { public SessionId getSessionId() {
@ -119,7 +119,8 @@ public class RequestLeaseSetMessage extends I2CPMessageImpl {
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if (_sessionId == null) if (_sessionId == null)
throw new I2CPMessageException("Unable to write out the message as there is not enough data"); throw new I2CPMessageException("Unable to write out the message as there is not enough data");
ByteArrayOutputStream os = new ByteArrayOutputStream(256); int len = 2 + 1 + (_endpoints.size() * (32 + 4)) + 8;
ByteArrayStream os = new ByteArrayStream(len);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
os.write((byte) _endpoints.size()); os.write((byte) _endpoints.size());

View File

@ -9,7 +9,6 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -19,6 +18,7 @@ import java.util.List;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Lease; import net.i2p.data.Lease;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
/** /**
@ -38,7 +38,7 @@ public class RequestVariableLeaseSetMessage extends I2CPMessageImpl {
private static final String MIN_VERSION = "0.9.7"; private static final String MIN_VERSION = "0.9.7";
public RequestVariableLeaseSetMessage() { public RequestVariableLeaseSetMessage() {
_endpoints = new ArrayList<Lease>(); _endpoints = new ArrayList<Lease>(6);
} }
/** /**
@ -109,7 +109,8 @@ public class RequestVariableLeaseSetMessage extends I2CPMessageImpl {
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if (_sessionId == null) if (_sessionId == null)
throw new I2CPMessageException("No data"); throw new I2CPMessageException("No data");
ByteArrayOutputStream os = new ByteArrayOutputStream(256); int len = 2 + 1 + (_endpoints.size() * 44);
ByteArrayStream os = new ByteArrayStream(len);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
os.write((byte) _endpoints.size()); os.write((byte) _endpoints.size());

View File

@ -27,6 +27,7 @@ import net.i2p.data.Destination;
import net.i2p.data.Signature; import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey; import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey; import net.i2p.data.SigningPublicKey;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.Clock; import net.i2p.util.Clock;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.OrderedProperties; import net.i2p.util.OrderedProperties;
@ -278,7 +279,7 @@ public class SessionConfig extends DataStructureImpl {
Signature sig = getOfflineSignature(); Signature sig = getOfflineSignature();
if (sig == null) if (sig == null)
return false; return false;
ByteArrayOutputStream baos = new ByteArrayOutputStream(128); ByteArrayStream baos = new ByteArrayStream(6 + spk.length());
try { try {
DataHelper.writeLong(baos, 4, expires / 1000); DataHelper.writeLong(baos, 4, expires / 1000);
DataHelper.writeLong(baos, 2, spk.getType().getCode()); DataHelper.writeLong(baos, 2, spk.getType().getCode());
@ -323,7 +324,7 @@ public class SessionConfig extends DataStructureImpl {
if (_options == null) return null; if (_options == null) return null;
if (_creationDate == null) return null; if (_creationDate == null) return null;
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream(512);
try { try {
//_log.debug("PubKey size for destination: " + _destination.getPublicKey().getData().length); //_log.debug("PubKey size for destination: " + _destination.getPublicKey().getData().length);
//_log.debug("SigningKey size for destination: " + _destination.getSigningPublicKey().getData().length); //_log.debug("SigningKey size for destination: " + _destination.getSigningPublicKey().getData().length);

View File

@ -9,13 +9,13 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.util.ByteArrayStream;
/** /**
* Defines the message a router sends to a client indicating the * Defines the message a router sends to a client indicating the
@ -87,7 +87,7 @@ public class SessionStatusMessage extends I2CPMessageImpl {
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if (_sessionId == null) if (_sessionId == null)
throw new I2CPMessageException("Unable to write out the message as there is not enough data"); throw new I2CPMessageException("Unable to write out the message as there is not enough data");
ByteArrayOutputStream os = new ByteArrayOutputStream(64); ByteArrayStream os = new ByteArrayStream(3);
try { try {
_sessionId.writeBytes(os); _sessionId.writeBytes(os);
os.write((byte) _status); os.write((byte) _status);

View File

@ -9,13 +9,13 @@ package net.i2p.data.i2cp;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Date; import java.util.Date;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.Clock; import net.i2p.util.Clock;
/** /**
@ -74,7 +74,7 @@ public class SetDateMessage extends I2CPMessageImpl {
protected byte[] doWriteMessage() throws I2CPMessageException, IOException { protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if (_date == null) if (_date == null)
throw new I2CPMessageException("Unable to write out the message as there is not enough data"); throw new I2CPMessageException("Unable to write out the message as there is not enough data");
ByteArrayOutputStream os = new ByteArrayOutputStream(32); ByteArrayStream os = new ByteArrayStream(8 + 1 + 6);
try { try {
DataHelper.writeDate(os, _date); DataHelper.writeDate(os, _date);
if (_version != null) if (_version != null)

View File

@ -18,6 +18,9 @@ public class ByteArrayStream extends ByteArrayOutputStream {
super(); super();
} }
/**
* @param size if accurate, toByteArray() will be zero-copy
*/
public ByteArrayStream(int size) { public ByteArrayStream(int size) {
super(size); super(size);
} }

View File

@ -8,7 +8,6 @@ package net.i2p.router.message;
* *
*/ */
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
@ -37,6 +36,7 @@ import net.i2p.router.crypto.ratchet.MuxedSKM;
import net.i2p.router.crypto.ratchet.RatchetSKM; import net.i2p.router.crypto.ratchet.RatchetSKM;
import net.i2p.router.crypto.ratchet.RatchetSessionTag; import net.i2p.router.crypto.ratchet.RatchetSessionTag;
import net.i2p.router.crypto.ratchet.ReplyCallback; import net.i2p.router.crypto.ratchet.ReplyCallback;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.Log; import net.i2p.util.Log;
/** /**
@ -393,11 +393,11 @@ public class GarlicMessageBuilder {
* @throws IllegalArgumentException on error * @throws IllegalArgumentException on error
*/ */
private static byte[] buildCloveSet(RouterContext ctx, GarlicConfig config) { private static byte[] buildCloveSet(RouterContext ctx, GarlicConfig config) {
ByteArrayOutputStream baos; ByteArrayStream baos;
try { try {
if (config instanceof PayloadGarlicConfig) { if (config instanceof PayloadGarlicConfig) {
byte clove[] = buildClove(ctx, (PayloadGarlicConfig)config); byte clove[] = buildClove(ctx, (PayloadGarlicConfig)config);
baos = new ByteArrayOutputStream(clove.length + 16); baos = new ByteArrayStream(1 + clove.length + 3 + 4 + 8);
baos.write((byte) 1); baos.write((byte) 1);
baos.write(clove); baos.write(clove);
} else { } else {
@ -417,7 +417,7 @@ public class GarlicMessageBuilder {
int len = 1; int len = 1;
for (int i = 0; i < cloves.length; i++) for (int i = 0; i < cloves.length; i++)
len += cloves[i].length; len += cloves[i].length;
baos = new ByteArrayOutputStream(len + 16); baos = new ByteArrayStream(1 + len + 3 + 4 + 8);
baos.write((byte) cloves.length); baos.write((byte) cloves.length);
for (int i = 0; i < cloves.length; i++) for (int i = 0; i < cloves.length; i++)
baos.write(cloves[i]); baos.write(cloves[i]);

View File

@ -33,6 +33,7 @@ import net.i2p.router.RouterContext;
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
import net.i2p.router.transport.crypto.DHSessionKeyBuilder; import net.i2p.router.transport.crypto.DHSessionKeyBuilder;
import static net.i2p.router.transport.ntcp.OutboundNTCP2State.*; import static net.i2p.router.transport.ntcp.OutboundNTCP2State.*;
import net.i2p.util.ByteArrayStream;
import net.i2p.util.ByteCache; import net.i2p.util.ByteCache;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SimpleByteCache; import net.i2p.util.SimpleByteCache;
@ -456,7 +457,7 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
long rtt = now - _con.getCreated(); long rtt = now - _con.getCreated();
_peerSkew = (now - (tsA * 1000) - (rtt / 2) + 500) / 1000; _peerSkew = (now - (tsA * 1000) - (rtt / 2) + 500) / 1000;
ByteArrayOutputStream baos = new ByteArrayOutputStream(768); ByteArrayStream baos = new ByteArrayStream(256 + 256 + 32 + 4 + 4);
baos.write(_X); baos.write(_X);
baos.write(_Y); baos.write(_Y);
baos.write(_context.routerHash().getData()); baos.write(_context.routerHash().getData());