* Certificate: Use a single static null cert in place of

tens of thousands of them
This commit is contained in:
zzz
2010-12-24 17:39:31 +00:00
parent 63c6613261
commit 82e344055b
6 changed files with 100 additions and 12 deletions

View File

@ -26,8 +26,10 @@ import java.io.OutputStream;
* @author jrandom
*/
public class Certificate extends DataStructureImpl {
private int _type;
private byte[] _payload;
public final static Certificate NULL_CERT = new NullCert();
protected int _type;
protected byte[] _payload;
/** Specifies a null certificate type with no payload */
public final static int CERTIFICATE_TYPE_NULL = 0;
@ -41,6 +43,25 @@ public class Certificate extends DataStructureImpl {
/** Contains multiple certs */
public final static int CERTIFICATE_TYPE_MULTIPLE = 4;
/**
* If null cert, return immutable static instance, else create new
* @since 0.8.3
*/
public static Certificate create(InputStream in) throws DataFormatException, IOException {
int type = (int) DataHelper.readLong(in, 1);
int length = (int) DataHelper.readLong(in, 2);
if (type == 0 && length == 0)
return NULL_CERT;
// from here down roughly the same as readBytes() below
if (length == 0)
return new Certificate(type, null);
byte[] payload = new byte[length];
int read = DataHelper.read(in, payload);
if (read != length)
throw new DataFormatException("Not enough bytes for the payload (read: " + read + " length: " + length + ')');
return new Certificate(type, payload);
}
public Certificate() {
}
@ -140,10 +161,12 @@ public class Certificate extends DataStructureImpl {
Certificate cert = (Certificate) object;
return _type == cert.getCertificateType() && DataHelper.eq(_payload, cert.getPayload());
}
@Override
public int hashCode() {
return _type + DataHelper.hashCode(_payload);
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(64);
@ -177,4 +200,67 @@ public class Certificate extends DataStructureImpl {
buf.append("]");
return buf.toString();
}
/**
* An immutable null certificate.
* @since 0.8.3
*/
private static final class NullCert extends Certificate {
private static final int NULL_LENGTH = 1 + 2;
private static final byte[] NULL_DATA = new byte[NULL_LENGTH];
public NullCert() {
// zero already
//_type = CERTIFICATE_TYPE_NULL;
}
/** @throws RuntimeException always */
@Override
public void setCertificateType(int type) {
throw new RuntimeException("Data already set");
}
/** @throws RuntimeException always */
@Override
public void setPayload(byte[] payload) {
throw new RuntimeException("Data already set");
}
/** @throws RuntimeException always */
@Override
public void readBytes(InputStream in) throws DataFormatException, IOException {
throw new RuntimeException("Data already set");
}
/** Overridden for efficiency */
@Override
public void writeBytes(OutputStream out) throws IOException {
out.write(NULL_DATA);
}
/** Overridden for efficiency */
@Override
public int writeBytes(byte target[], int offset) {
System.arraycopy(NULL_DATA, 0, target, offset, NULL_LENGTH);
return offset + NULL_LENGTH;
}
/** @throws RuntimeException always */
@Override
public int readBytes(byte source[], int offset) throws DataFormatException {
throw new RuntimeException("Data already set");
}
/** Overridden for efficiency */
@Override
public int size() {
return NULL_LENGTH;
}
/** Overridden for efficiency */
@Override
public int hashCode() {
return 99999;
}
}
}

View File

@ -65,8 +65,9 @@ public class KeysAndCert extends DataStructureImpl {
_publicKey.readBytes(in);
_signingKey = new SigningPublicKey();
_signingKey.readBytes(in);
_certificate = new Certificate();
_certificate.readBytes(in);
//_certificate = new Certificate();
//_certificate.readBytes(in);
_certificate = Certificate.create(in);
__calculatedHash = null;
}

View File

@ -68,8 +68,9 @@ public class GarlicClove extends DataStructureImpl {
_expiration = DataHelper.readDate(in);
if (_log.shouldLog(Log.DEBUG))
_log.debug("CloveID read: " + _cloveId + " expiration read: " + _expiration);
_certificate = new Certificate();
_certificate.readBytes(in);
//_certificate = new Certificate();
//_certificate.readBytes(in);
_certificate = Certificate.create(in);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Read cert: " + _certificate);
}

View File

@ -115,7 +115,7 @@ class OutboundClientMessageJobHelper {
instructions.setRouter(null);
instructions.setTunnelId(null);
config.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
config.setCertificate(Certificate.NULL_CERT);
config.setDeliveryInstructions(instructions);
config.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
config.setExpiration(expiration); // +2*Router.CLOCK_FUDGE_FACTOR);
@ -165,7 +165,7 @@ class OutboundClientMessageJobHelper {
if (log.shouldLog(Log.DEBUG))
log.debug("Delivery status message key: " + replyToken + " arrival: " + msg.getArrival());
ackClove.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
ackClove.setCertificate(Certificate.NULL_CERT);
ackClove.setDeliveryInstructions(ackInstructions);
ackClove.setExpiration(expiration);
ackClove.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
@ -196,7 +196,7 @@ class OutboundClientMessageJobHelper {
instructions.setDelaySeconds(0);
instructions.setEncrypted(false);
clove.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
clove.setCertificate(Certificate.NULL_CERT);
clove.setDeliveryInstructions(instructions);
clove.setExpiration(expiration);
clove.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
@ -222,7 +222,7 @@ class OutboundClientMessageJobHelper {
instructions.setDelaySeconds(0);
instructions.setEncrypted(false);
clove.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
clove.setCertificate(Certificate.NULL_CERT);
clove.setDeliveryInstructions(instructions);
clove.setExpiration(expiration);
clove.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));

View File

@ -872,7 +872,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
instructions.setDelaySeconds(0);
instructions.setEncrypted(false);
clove.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
clove.setCertificate(Certificate.NULL_CERT);
clove.setDeliveryInstructions(instructions);
clove.setExpiration(OVERALL_TIMEOUT_MS_DEFAULT+getContext().clock().now());
clove.setId(getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE));

View File

@ -46,7 +46,7 @@ class MessageWrapper {
instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_LOCAL);
PayloadGarlicConfig payload = new PayloadGarlicConfig();
payload.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
payload.setCertificate(Certificate.NULL_CERT);
payload.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
payload.setPayload(m);
payload.setRecipient(to);