diff --git a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java index 76f677b7c3ee311443f7635e15106adf0aa029c0..855b5a61207d940a31bf0875294ff8dbb9099bf0 100644 --- a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java +++ b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java @@ -363,14 +363,14 @@ class FragmentHandler { synchronized (_fragmentedMessages) { msg = _fragmentedMessages.get(Long.valueOf(messageId)); if (msg == null) { - msg = new FragmentedMessage(_context); + msg = new FragmentedMessage(_context, messageId); _fragmentedMessages.put(Long.valueOf(messageId), msg); } } // synchronized is required, fragments may be arriving in different threads synchronized(msg) { - boolean ok = msg.receive(messageId, preprocessed, offset, size, false, router, tunnelId); + boolean ok = msg.receive(preprocessed, offset, size, false, router, tunnelId); if (!ok) return -1; if (msg.isComplete()) { synchronized (_fragmentedMessages) { @@ -430,14 +430,14 @@ class FragmentHandler { synchronized (_fragmentedMessages) { msg = _fragmentedMessages.get(Long.valueOf(messageId)); if (msg == null) { - msg = new FragmentedMessage(_context); + msg = new FragmentedMessage(_context, messageId); _fragmentedMessages.put(Long.valueOf(messageId), msg); } } // synchronized is required, fragments may be arriving in different threads synchronized(msg) { - boolean ok = msg.receive(messageId, fragmentNum, preprocessed, offset, size, isLast); + boolean ok = msg.receive(fragmentNum, preprocessed, offset, size, isLast); if (!ok) return -1; if (msg.isComplete()) { diff --git a/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java b/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java index 2a0c59e9134803a8585b995712d6f87bc146e486..e257e326ffbdf6c22f33b42ee5a23be201744f5d 100644 --- a/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java +++ b/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java @@ -19,7 +19,7 @@ import net.i2p.util.SimpleTimer2; class FragmentedMessage { private final I2PAppContext _context; private final Log _log; - private long _messageId; + private final long _messageId; private Hash _toRouter; private TunnelId _toTunnel; private final ByteArray _fragments[]; @@ -33,11 +33,12 @@ class FragmentedMessage { private static final ByteCache _cache = ByteCache.getInstance(512, TrivialPreprocessor.PREPROCESSED_SIZE); // 64 is pretty absurd, 32 is too, most likely private static final int MAX_FRAGMENTS = 64; + private static final int MAX_FRAGMENT_SIZE = 996; - public FragmentedMessage(I2PAppContext ctx) { + public FragmentedMessage(I2PAppContext ctx, long messageId) { _context = ctx; _log = ctx.logManager().getLog(FragmentedMessage.class); - _messageId = -1; + _messageId = messageId; _fragments = new ByteArray[MAX_FRAGMENTS]; _highFragmentNum = -1; _releasedAfter = -1; @@ -48,37 +49,30 @@ class FragmentedMessage { * Receive a followup fragment, though one of these may arrive at the endpoint * prior to the fragment # 0. * - * @param messageId what messageId is this fragment a part of - * @param fragmentNum sequence number within the message (must be greater than 1) - * @param payload data for the fragment + * @param fragmentNum sequence number within the message (1 - 63) + * @param payload data for the fragment non-null * @param offset index into the payload where the fragment data starts (past headers/etc) * @param length how much past the offset should we snag? * @param isLast is this the last fragment in the message? */ - public boolean receive(long messageId, int fragmentNum, byte payload[], int offset, int length, boolean isLast) { - if (fragmentNum < 0) { + public boolean receive(int fragmentNum, byte payload[], int offset, int length, boolean isLast) { + if (fragmentNum <= 0 || fragmentNum >= MAX_FRAGMENTS) { if (_log.shouldLog(Log.ERROR)) - _log.error("Fragment # == " + fragmentNum + " for messageId " + messageId); + _log.error("Fragment # == " + fragmentNum + " for messageId " + _messageId); return false; } - if (payload == null) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Payload is null for messageId " + messageId); - return false; - } - if (length <= 0) { + if (length <= 0 || length > MAX_FRAGMENT_SIZE) { if (_log.shouldLog(Log.WARN)) - _log.warn("Length is impossible (" + length + ") for messageId " + messageId); + _log.warn("Length is impossible (" + length + ") for messageId " + _messageId); return false; } if (offset + length > payload.length) { if (_log.shouldLog(Log.WARN)) - _log.warn("Length is impossible (" + length + "/" + offset + " out of " + payload.length + ") for messageId " + messageId); + _log.warn("Length is impossible (" + length + "/" + offset + " out of " + payload.length + ") for messageId " + _messageId); return false; } if (_log.shouldLog(Log.DEBUG)) - _log.debug("Receive message " + messageId + " fragment " + fragmentNum + " with " + length + " bytes (last? " + isLast + ") offset = " + offset); - _messageId = messageId; + _log.debug("Receive message " + _messageId + " fragment " + fragmentNum + " with " + length + " bytes (last? " + isLast + ") offset = " + offset); // we should just use payload[] and use an offset/length on it ByteArray ba = _cache.acquire(); //new ByteArray(payload, offset, length); //new byte[length]); System.arraycopy(payload, offset, ba.getData(), 0, length); @@ -95,43 +89,36 @@ class FragmentedMessage { _highFragmentNum = fragmentNum; if (isLast && fragmentNum <= 0) { if (_log.shouldLog(Log.ERROR)) - _log.error("hmm, isLast and fragmentNum=" + fragmentNum + " for message " + messageId); + _log.error("hmm, isLast and fragmentNum=" + fragmentNum + " for message " + _messageId); return false; } return true; } /** - * Receive the first fragment and related metadata. This may not be the first + * Receive the first fragment (#0) and related metadata. This may not be the first * one to arrive at the endpoint however. * - * @param messageId what messageId is this fragment a part of - * @param payload data for the fragment + * @param payload data for the fragment non-null * @param offset index into the payload where the fragment data starts (past headers/etc) * @param length how much past the offset should we snag? * @param isLast is this the last fragment in the message? * @param toRouter what router is this destined for (may be null) * @param toTunnel what tunnel is this destined for (may be null) */ - public boolean receive(long messageId, byte payload[], int offset, int length, boolean isLast, Hash toRouter, TunnelId toTunnel) { - if (payload == null) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Payload is null for messageId " + messageId); - return false; - } - if (length <= 0) { + public boolean receive(byte payload[], int offset, int length, boolean isLast, Hash toRouter, TunnelId toTunnel) { + if (length <= 0 || length > MAX_FRAGMENT_SIZE) { if (_log.shouldLog(Log.WARN)) - _log.warn("Length is impossible (" + length + ") for messageId " + messageId); + _log.warn("Length is impossible (" + length + ") for messageId " + _messageId); return false; } if (offset + length > payload.length) { if (_log.shouldLog(Log.WARN)) - _log.warn("Length is impossible (" + length + "/" + offset + " out of " + payload.length + ") for messageId " + messageId); + _log.warn("Length is impossible (" + length + "/" + offset + " out of " + payload.length + ") for messageId " + _messageId); return false; } if (_log.shouldLog(Log.DEBUG)) - _log.debug("Receive message " + messageId + " with " + length + " bytes (last? " + isLast + ") targetting " + toRouter + " / " + toTunnel + " offset=" + offset); - _messageId = messageId; + _log.debug("Receive message " + _messageId + " with " + length + " bytes (last? " + isLast + ") targetting " + toRouter + " / " + toTunnel + " offset=" + offset); ByteArray ba = _cache.acquire(); // new ByteArray(payload, offset, length); // new byte[length]); System.arraycopy(payload, offset, ba.getData(), 0, length); ba.setValid(length);