I2CP: Add option for forcing gzip on/off per-message

Use option in streaming SYN and CLOSE packets
This commit is contained in:
zzz
2018-07-15 13:50:31 +00:00
parent 4ff62c291e
commit 6c3cf9bf77
3 changed files with 56 additions and 5 deletions

View File

@ -147,6 +147,10 @@ class PacketQueue implements SendMessageStatusListener, Closeable {
} }
options.setTagsToSend(sendTags); options.setTagsToSend(sendTags);
options.setTagThreshold(tagThresh); options.setTagThreshold(tagThresh);
// CLOSE, RESET, and PING packets unlikely to have a large payload
// and most of the rest of the packet is
// uncompressible: stream ids, signature
options.setGzip(packet.getPayloadSize() > 50);
} else if (packet.isFlagSet(FLAGS_INITIAL_TAGS)) { } else if (packet.isFlagSet(FLAGS_INITIAL_TAGS)) {
if (con != null) { if (con != null) {
if (con.isInbound()) if (con.isInbound())
@ -167,6 +171,11 @@ class PacketQueue implements SendMessageStatusListener, Closeable {
} }
options.setTagsToSend(sendTags); options.setTagsToSend(sendTags);
options.setTagThreshold(tagThresh); options.setTagThreshold(tagThresh);
// SYN packets are likely to have compressible payload, even if
// conn gzip option is false (e.g. snark bitfield, HTTP headers).
// If they don't have a large payload, most of the rest of the packet
// is uncompressible: stream ids, destination and signature
options.setGzip(packet.getPayloadSize() > 50);
} else { } else {
if (con != null) { if (con != null) {
if (con.isInbound() && con.getLifetime() < 2*60*1000) if (con.isInbound() && con.getLifetime() < 2*60*1000)

View File

@ -12,10 +12,15 @@ import net.i2p.data.DateAndFlags;
* Static methods are for OutboundClientMessageOneShotJob to decode the * Static methods are for OutboundClientMessageOneShotJob to decode the
* flags field on the router side. * flags field on the router side.
* *
* GzipOption flags are as of 0.9.36, are client-side only, and are
* not included in the flags field or sent to the router.
*
* @since 0.9.2 * @since 0.9.2
*/ */
public class SendMessageOptions extends DateAndFlags { public class SendMessageOptions extends DateAndFlags {
private GzipOption _gzip = GzipOption.DEFAULT;
/** all subject to change */ /** all subject to change */
/** /**
@ -205,4 +210,33 @@ public class SendMessageOptions extends DateAndFlags {
return Reliability.DEFAULT; return Reliability.DEFAULT;
} }
} }
/**
* Overrides i2cp.gzip session option and size threshold
* for this message only.
*
* @since 0.9.36
*/
public enum GzipOption { DEFAULT, GZIP_OFF, GZIP_ON }
/**
* Overrides i2cp.gzip session option and size threshold
* for this message only.
*
* @return non-null, DEFAULT unless setGzip() was called
* @since 0.9.36
*/
public GzipOption getGzip() {
return _gzip;
}
/**
* Overrides i2cp.gzip session option and size threshold
* for this message only.
*
* @since 0.9.36
*/
public void setGzip(boolean yes) {
_gzip = yes? GzipOption.GZIP_ON : GzipOption.GZIP_OFF;
}
} }

View File

@ -217,7 +217,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 {
SessionKey keyUsed, Set<SessionTag> tagsSent, long expires, SessionKey keyUsed, Set<SessionTag> tagsSent, long expires,
int proto, int fromPort, int toPort, int flags) int proto, int fromPort, int toPort, int flags)
throws I2PSessionException { throws I2PSessionException {
payload = prepPayload(payload, offset, size, proto, fromPort, toPort); payload = prepPayload(payload, offset, size, proto, fromPort, toPort, SendMessageOptions.GzipOption.DEFAULT);
if (_noEffort) if (_noEffort)
return sendNoEffort(dest, payload, expires, flags); return sendNoEffort(dest, payload, expires, flags);
else else
@ -242,7 +242,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 {
@Override @Override
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, public boolean sendMessage(Destination dest, byte[] payload, int offset, int size,
int proto, int fromPort, int toPort, SendMessageOptions options) throws I2PSessionException { int proto, int fromPort, int toPort, SendMessageOptions options) throws I2PSessionException {
payload = prepPayload(payload, offset, size, proto, fromPort, toPort); payload = prepPayload(payload, offset, size, proto, fromPort, toPort, options.getGzip());
//if (_noEffort) { //if (_noEffort) {
sendNoEffort(dest, payload, options); sendNoEffort(dest, payload, options);
return true; return true;
@ -266,7 +266,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 {
public long sendMessage(Destination dest, byte[] payload, int offset, int size, public long sendMessage(Destination dest, byte[] payload, int offset, int size,
int proto, int fromPort, int toPort, int proto, int fromPort, int toPort,
SendMessageOptions options, SendMessageStatusListener listener) throws I2PSessionException { SendMessageOptions options, SendMessageStatusListener listener) throws I2PSessionException {
payload = prepPayload(payload, offset, size, proto, fromPort, toPort); payload = prepPayload(payload, offset, size, proto, fromPort, toPort, options.getGzip());
long nonce = _sendMessageNonce.incrementAndGet(); long nonce = _sendMessageNonce.incrementAndGet();
long expires = Math.max(_context.clock().now() + 60*1000L, options.getTime()); long expires = Math.max(_context.clock().now() + 60*1000L, options.getTime());
MessageState state = new MessageState(_context, nonce, this, expires, listener); MessageState state = new MessageState(_context, nonce, this, expires, listener);
@ -279,11 +279,19 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 {
* @return gzip compressed payload, ready to send * @return gzip compressed payload, ready to send
* @since 0.9.14 * @since 0.9.14
*/ */
private byte[] prepPayload(byte[] payload, int offset, int size, int proto, int fromPort, int toPort) throws I2PSessionException { private byte[] prepPayload(byte[] payload, int offset, int size, int proto,
int fromPort, int toPort,
SendMessageOptions.GzipOption gzo) throws I2PSessionException {
verifyOpen(); verifyOpen();
updateActivity(); updateActivity();
if (shouldCompress(size)) boolean docompress;
if (gzo == SendMessageOptions.GzipOption.DEFAULT)
docompress = shouldCompress(size);
else
docompress = gzo == SendMessageOptions.GzipOption.GZIP_ON;
if (docompress)
payload = DataHelper.compress(payload, offset, size); payload = DataHelper.compress(payload, offset, size);
else else
payload = DataHelper.compress(payload, offset, size, DataHelper.NO_COMPRESSION); payload = DataHelper.compress(payload, offset, size, DataHelper.NO_COMPRESSION);