Changeset 8448001


Ignore:
Timestamp:
Dec 11, 2011 9:04:43 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
e117e33
Parents:
032b7d8
Message:
  • I2NP:
    • Deprecate unused stream methods and I2NPMessageReader since all transports provide encapsulation.
    • Don't throw IOE from byte array methods
    • Use cached null cert in GarlicClove?
    • Add method to limit size of buffer to read
    • Don't check checksum at input, in most cases
    • Reuse checksum at output, for unomodified pass-through messages (but recalculating it now and logging on a mismatch for testing)
    • Fix DatabaseLookupMessage? to internally store the don't include peers as a List, not a Set, so it doesn't get reordered and break the checksum
    • Log cleanup
  • NTCP:
    • Zero-copy and limit size when handing buffer to I2NP
    • Log hex dump message on I2NPMessageException, like in SSU
    • Don't close connection on I2NPMessageException
Location:
router/java/src/net/i2p
Files:
1 added
21 edited

Legend:

Unmodified
Added
Removed
  • router/java/src/net/i2p/data/i2np/DataMessage.java

    r032b7d8 r8448001  
    99 */
    1010
    11 import java.io.IOException;
    12 
    1311import net.i2p.I2PAppContext;
    1412import net.i2p.data.DataHelper;
     
    1614/**
    1715 * Defines a message containing arbitrary bytes of data
     16 * This is what goes in a GarlicClove.
     17 * It was also previously used for generating test messages.
    1818 *
    1919 * @author jrandom
    2020 */
    21 public class DataMessage extends I2NPMessageImpl {
     21public class DataMessage extends FastI2NPMessageImpl {
    2222    public final static int MESSAGE_TYPE = 20;
    2323    private byte _data[];
     
    3030        return _data;
    3131    }
     32
     33    /**
     34     *  @throws IllegalStateException if data previously set, to protect saved checksum
     35     */
    3236    public void setData(byte[] data) {
     37        if (_data != null)
     38            throw new IllegalStateException();
    3339        _data = data;
    3440    }
     
    3844    }
    3945   
    40     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     46    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
    4147        if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
    4248        int curIndex = offset;
     
    5662            return 4 + _data.length;
    5763    }
     64
    5865    /** write the message body to the output array, starting at the given index */
    5966    protected int writeMessageBody(byte out[], int curIndex) {
     
    7784    @Override
    7885    public int hashCode() {
    79         return DataHelper.hashCode(getData());
     86        return DataHelper.hashCode(_data);
    8087    }
    8188   
     
    8491        if ( (object != null) && (object instanceof DataMessage) ) {
    8592            DataMessage msg = (DataMessage)object;
    86             return DataHelper.eq(getData(),msg.getData());
     93            return DataHelper.eq(_data, msg._data);
    8794        } else {
    8895            return false;
     
    94101        StringBuilder buf = new StringBuilder();
    95102        buf.append("[DataMessage: ");
    96         buf.append("\n\tData: ").append(DataHelper.toString(getData(), 64));
     103        buf.append("\n\tData: ").append(DataHelper.toString(_data, 64));
    97104        buf.append("]");
    98105        return buf.toString();
  • router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java

    r032b7d8 r8448001  
    99 */
    1010
    11 import java.io.IOException;
     11import java.util.ArrayList;
     12import java.util.Collection;
    1213import java.util.HashSet;
    1314import java.util.Iterator;
     15import java.util.List;
    1416import java.util.Set;
    1517
     
    2628 * @author jrandom
    2729 */
    28 public class DatabaseLookupMessage extends I2NPMessageImpl {
     30public class DatabaseLookupMessage extends FastI2NPMessageImpl {
    2931    //private final static Log _log = new Log(DatabaseLookupMessage.class);
    3032    public final static int MESSAGE_TYPE = 2;
     
    3234    private Hash _fromHash;
    3335    private TunnelId _replyTunnel;
    34     private Set<Hash> _dontIncludePeers;
     36    /** this must be kept as a list to preserve the order and not break the checksum */
     37    private List<Hash> _dontIncludePeers;
    3538   
    3639    //private static volatile long _currentLookupPeriod = 0;
     
    103106     */
    104107    public Hash getSearchKey() { return _key; }
    105     public void setSearchKey(Hash key) { _key = key; }
     108
     109    /**
     110     * @throws IllegalStateException if key previously set, to protect saved checksum
     111     */
     112    public void setSearchKey(Hash key) {
     113        if (_key != null)
     114            throw new IllegalStateException();
     115        _key = key;
     116    }
    106117   
    107118    /**
     
    110121     */
    111122    public Hash getFrom() { return _fromHash; }
    112     public void setFrom(Hash from) { _fromHash = from; }
     123   
     124    /**
     125     * @throws IllegalStateException if from previously set, to protect saved checksum
     126     */
     127    public void setFrom(Hash from) {
     128        if (_fromHash != null)
     129            throw new IllegalStateException();
     130        _fromHash = from;
     131    }
    113132   
    114133    /**
     
    117136     */
    118137    public TunnelId getReplyTunnel() { return _replyTunnel; }
    119     public void setReplyTunnel(TunnelId replyTunnel) { _replyTunnel = replyTunnel; }
    120    
    121     /**
    122      * Set of peers that a lookup reply should NOT include
    123      *
    124      * @return Set of Hash objects, each of which is the H(routerIdentity) to skip
    125      */
    126     public Set<Hash> getDontIncludePeers() { return _dontIncludePeers; }
    127     public void setDontIncludePeers(Set peers) {
     138
     139    /**
     140     * @throws IllegalStateException if tunnel previously set, to protect saved checksum
     141     */
     142    public void setReplyTunnel(TunnelId replyTunnel) {
     143        if (_replyTunnel != null)
     144            throw new IllegalStateException();
     145        _replyTunnel = replyTunnel;
     146    }
     147   
     148    /**
     149     * Set of peers that a lookup reply should NOT include.
     150     * WARNING - returns a copy.
     151     *
     152     * @return Set of Hash objects, each of which is the H(routerIdentity) to skip, or null
     153     */
     154    public Set<Hash> getDontIncludePeers() {
     155        if (_dontIncludePeers == null)
     156            return null;
     157        return new HashSet(_dontIncludePeers);
     158    }
     159
     160    /**
     161     * Replace the dontInclude set with this set.
     162     * WARNING - makes a copy.
     163     * Invalidates the checksum.
     164     *
     165     * @param peers may be null
     166     */
     167    public void setDontIncludePeers(Collection<Hash> peers) {
     168        _hasChecksum = false;
    128169        if (peers != null)
    129             _dontIncludePeers = new HashSet(peers);
     170            _dontIncludePeers = new ArrayList(peers);
    130171        else
    131172            _dontIncludePeers = null;
    132173    }
    133    
    134     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     174
     175    /**
     176     * Add to the set.
     177     * Invalidates the checksum.
     178     *
     179     * @param peer non-null
     180     * @since 0.8.12
     181     */
     182    public void addDontIncludePeer(Hash peer) {
     183        if (_dontIncludePeers == null)
     184            _dontIncludePeers = new ArrayList();
     185        else if (_dontIncludePeers.contains(peer))
     186            return;
     187        _hasChecksum = false;
     188        _dontIncludePeers.add(peer);
     189    }
     190
     191    /**
     192     * Add to the set.
     193     * Invalidates the checksum.
     194     *
     195     * @param peers non-null
     196     * @since 0.8.12
     197     */
     198    public void addDontIncludePeers(Collection<Hash> peers) {
     199        _hasChecksum = false;
     200        if (_dontIncludePeers == null) {
     201            _dontIncludePeers = new ArrayList(peers);
     202        } else {
     203            for (Hash peer : peers) {
     204                if (!_dontIncludePeers.contains(peer))
     205                    _dontIncludePeers.add(peer);
     206            }
     207        }
     208    }
     209   
     210    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
    135211        if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
    136212        int curIndex = offset;
     
    171247        if ( (numPeers < 0) || (numPeers > MAX_NUM_PEERS) )
    172248            throw new I2NPMessageException("Invalid number of peers - " + numPeers);
    173         Set<Hash> peers = new HashSet(numPeers);
     249        List<Hash> peers = new ArrayList(numPeers);
    174250        for (int i = 0; i < numPeers; i++) {
    175251            //byte peer[] = new byte[Hash.HASH_LENGTH];
     
    221297            out[curIndex++] = len[0];
    222298            out[curIndex++] = len[1];
    223             for (Iterator<Hash> iter = _dontIncludePeers.iterator(); iter.hasNext(); ) {
    224                 Hash peer = iter.next();
     299            for (Hash peer : _dontIncludePeers) {
    225300                System.arraycopy(peer.getData(), 0, out, curIndex, Hash.HASH_LENGTH);
    226301                curIndex += Hash.HASH_LENGTH;
     
    234309    @Override
    235310    public int hashCode() {
    236         return DataHelper.hashCode(getSearchKey()) +
    237                DataHelper.hashCode(getFrom()) +
    238                DataHelper.hashCode(getReplyTunnel()) +
     311        return DataHelper.hashCode(_key) +
     312               DataHelper.hashCode(_fromHash) +
     313               DataHelper.hashCode(_replyTunnel) +
    239314               DataHelper.hashCode(_dontIncludePeers);
    240315    }
     
    244319        if ( (object != null) && (object instanceof DatabaseLookupMessage) ) {
    245320            DatabaseLookupMessage msg = (DatabaseLookupMessage)object;
    246             return DataHelper.eq(getSearchKey(),msg.getSearchKey()) &&
    247                    DataHelper.eq(getFrom(),msg.getFrom()) &&
    248                    DataHelper.eq(getReplyTunnel(),msg.getReplyTunnel()) &&
    249                    DataHelper.eq(_dontIncludePeers,msg.getDontIncludePeers());
     321            return DataHelper.eq(_key, msg._key) &&
     322                   DataHelper.eq(_fromHash, msg._fromHash) &&
     323                   DataHelper.eq(_replyTunnel, msg._replyTunnel) &&
     324                   DataHelper.eq(_dontIncludePeers, msg._dontIncludePeers);
    250325        } else {
    251326            return false;
     
    257332        StringBuilder buf = new StringBuilder();
    258333        buf.append("[DatabaseLookupMessage: ");
    259         buf.append("\n\tSearch Key: ").append(getSearchKey());
    260         buf.append("\n\tFrom: ").append(getFrom());
    261         buf.append("\n\tReply Tunnel: ").append(getReplyTunnel());
     334        buf.append("\n\tSearch Key: ").append(_key);
     335        buf.append("\n\tFrom: ").append(_fromHash);
     336        buf.append("\n\tReply Tunnel: ").append(_replyTunnel);
    262337        buf.append("\n\tDont Include Peers: ");
    263338        if (_dontIncludePeers != null)
  • router/java/src/net/i2p/data/i2np/DatabaseSearchReplyMessage.java

    r032b7d8 r8448001  
    99 */
    1010
    11 import java.io.IOException;
    1211import java.util.ArrayList;
    1312import java.util.List;
     
    2423 * @author jrandom
    2524 */
    26 public class DatabaseSearchReplyMessage extends I2NPMessageImpl {
     25public class DatabaseSearchReplyMessage extends FastI2NPMessageImpl {
    2726    public final static int MESSAGE_TYPE = 3;
    2827    private Hash _key;
     
    4241     */
    4342    public Hash getSearchKey() { return _key; }
    44     public void setSearchKey(Hash key) { _key = key; }
     43
     44    /**
     45     * @throws IllegalStateException if key previously set, to protect saved checksum
     46     */
     47    public void setSearchKey(Hash key) {
     48        if (_key != null)
     49            throw new IllegalStateException();
     50        _key = key;
     51    }
    4552   
    4653    public int getNumReplies() { return _peerHashes.size(); }
     
    5259    public void setFromHash(Hash from) { _from = from; }
    5360   
    54     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     61    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
    5562        if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
    5663        int curIndex = offset;
     
    115122        if ( (object != null) && (object instanceof DatabaseSearchReplyMessage) ) {
    116123            DatabaseSearchReplyMessage msg = (DatabaseSearchReplyMessage)object;
    117             return DataHelper.eq(getSearchKey(),msg.getSearchKey()) &&
    118             DataHelper.eq(getFromHash(),msg.getFromHash()) &&
     124            return DataHelper.eq(_key,msg._key) &&
     125            DataHelper.eq(_from,msg._from) &&
    119126            DataHelper.eq(_peerHashes,msg._peerHashes);
    120127        } else {
     
    125132    @Override
    126133    public int hashCode() {
    127         return DataHelper.hashCode(getSearchKey()) +
    128         DataHelper.hashCode(getFromHash()) +
     134        return DataHelper.hashCode(_key) +
     135        DataHelper.hashCode(_from) +
    129136        DataHelper.hashCode(_peerHashes);
    130137    }
     
    134141        StringBuilder buf = new StringBuilder();
    135142        buf.append("[DatabaseSearchReplyMessage: ");
    136         buf.append("\n\tSearch Key: ").append(getSearchKey());
     143        buf.append("\n\tSearch Key: ").append(_key);
    137144        buf.append("\n\tReplies: # = ").append(getNumReplies());
    138145        for (int i = 0; i < getNumReplies(); i++) {
    139146            buf.append("\n\t\tReply [").append(i).append("]: ").append(getReply(i));
    140147        }
    141         buf.append("\n\tFrom: ").append(getFromHash());
     148        buf.append("\n\tFrom: ").append(_from);
    142149        buf.append("]");
    143150        return buf.toString();
  • router/java/src/net/i2p/data/i2np/DatabaseStoreMessage.java

    r032b7d8 r8448001  
    3030 * @author jrandom
    3131 */
    32 public class DatabaseStoreMessage extends I2NPMessageImpl {
     32public class DatabaseStoreMessage extends FastI2NPMessageImpl {
    3333    public final static int MESSAGE_TYPE = 1;
    3434    private Hash _key;
     
    6262    /**
    6363     * This also sets the key
     64     * @throws IllegalStateException if data previously set, to protect saved checksum
    6465     */
    6566    public void setEntry(DatabaseEntry entry) {
     67        if (_dbEntry != null)
     68            throw new IllegalStateException();
    6669        _dbEntry = entry;
    6770    }
     
    9598    public void setReplyGateway(Hash peer) { _replyGateway = peer; }
    9699   
    97     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     100    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
    98101        if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
    99102        int curIndex = offset;
     
    127130            } catch (DataFormatException dfe) {
    128131                throw new I2NPMessageException("Error reading the leaseSet", dfe);
     132            } catch (IOException ioe) {
     133                throw new I2NPMessageException("Error reading the leaseSet", ioe);
    129134            }
    130135        } else if (type == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
     
    132137            int compressedSize = (int)DataHelper.fromLong(data, curIndex, 2);
    133138            curIndex += 2;
    134             if (compressedSize <= 0 || curIndex + compressedSize > data.length || (curIndex - offset) + compressedSize > dataSize)
     139            if (compressedSize <= 0 || curIndex + compressedSize > data.length || curIndex + compressedSize > dataSize + offset)
    135140                throw new I2NPMessageException("Compressed RI length: " + compressedSize +
    136                                                " but remaining bytes: " + Math.min(data.length - curIndex, dataSize - (curIndex - offset)));
     141                                               " but remaining bytes: " + Math.min(data.length - curIndex, dataSize + offset -curIndex));
    137142           
    138143            try {
     
    231236        return DataHelper.hashCode(getKey()) +
    232237               DataHelper.hashCode(_dbEntry) +
    233                (int)getReplyToken() +
    234                DataHelper.hashCode(getReplyTunnel()) +
    235                DataHelper.hashCode(getReplyGateway());
     238               (int) _replyToken +
     239               DataHelper.hashCode(_replyTunnel) +
     240               DataHelper.hashCode(_replyGateway);
    236241    }
    237242   
     
    242247            return DataHelper.eq(getKey(),msg.getKey()) &&
    243248                   DataHelper.eq(_dbEntry,msg.getEntry()) &&
    244                    getReplyToken() == msg.getReplyToken() &&
    245                    DataHelper.eq(getReplyTunnel(), msg.getReplyTunnel()) &&
    246                    DataHelper.eq(getReplyGateway(), msg.getReplyGateway());
     249                   _replyToken == msg._replyToken &&
     250                   DataHelper.eq(_replyTunnel, msg._replyTunnel) &&
     251                   DataHelper.eq(_replyGateway, msg._replyGateway);
    247252        } else {
    248253            return false;
     
    254259        StringBuilder buf = new StringBuilder();
    255260        buf.append("[DatabaseStoreMessage: ");
    256         buf.append("\n\tExpiration: ").append(getMessageExpiration());
    257         buf.append("\n\tUnique ID: ").append(getUniqueId());
     261        buf.append("\n\tExpiration: ").append(_expiration);
     262        buf.append("\n\tUnique ID: ").append(_uniqueId);
    258263        buf.append("\n\tKey: ").append(getKey());
    259264        buf.append("\n\tEntry: ").append(_dbEntry);
    260         buf.append("\n\tReply token: ").append(getReplyToken());
    261         buf.append("\n\tReply tunnel: ").append(getReplyTunnel());
    262         buf.append("\n\tReply gateway: ").append(getReplyGateway());
     265        buf.append("\n\tReply token: ").append(_replyToken);
     266        buf.append("\n\tReply tunnel: ").append(_replyTunnel);
     267        buf.append("\n\tReply gateway: ").append(_replyGateway);
    263268        buf.append("]");
    264269        return buf.toString();
  • router/java/src/net/i2p/data/i2np/DeliveryInstructions.java

    r032b7d8 r8448001  
    1919import net.i2p.data.SessionKey;
    2020import net.i2p.data.TunnelId;
    21 import net.i2p.util.Log;
     21//import net.i2p.util.Log;
    2222
    2323
     
    3333 */
    3434public class DeliveryInstructions extends DataStructureImpl {
    35     private final static Log _log = new Log(DeliveryInstructions.class);
     35    //private final static Log _log = new Log(DeliveryInstructions.class);
    3636    private boolean _encrypted;
    3737    private SessionKey _encryptionKey;
     
    5858   
    5959    public DeliveryInstructions() {
    60         setDeliveryMode(-1);
     60        _deliveryMode = -1;
    6161    }
    6262   
     
    133133    public void setDelaySeconds(long seconds) { _delaySeconds = seconds; }
    134134   
     135    /**
     136     * @deprecated unused
     137     */
    135138    public void readBytes(InputStream in) throws DataFormatException, IOException {
    136139        long flags = DataHelper.readLong(in, 1);
    137         if (_log.shouldLog(Log.DEBUG))
    138             _log.debug("Read flags: " + flags + " mode: " +  flagMode(flags));
     140        //if (_log.shouldLog(Log.DEBUG))
     141        //    _log.debug("Read flags: " + flags + " mode: " +  flagMode(flags));
    139142       
    140143     /****
     
    189192        long flags = DataHelper.fromLong(data, cur, 1);
    190193        cur++;
    191         if (_log.shouldLog(Log.DEBUG))
    192             _log.debug("Read flags: " + flags + " mode: " +  flagMode(flags));
     194        //if (_log.shouldLog(Log.DEBUG))
     195        //    _log.debug("Read flags: " + flags + " mode: " +  flagMode(flags));
    193196       
    194197     /****
     
    290293        if (getDelayRequested())
    291294            val = val | FLAG_DELAY;
    292         if (_log.shouldLog(Log.DEBUG))
    293             _log.debug("getFlags() = " + val);
     295        //if (_log.shouldLog(Log.DEBUG))
     296        //    _log.debug("getFlags() = " + val);
    294297        return val;
    295298    }
     
    305308        switch (getDeliveryMode()) {
    306309            case FLAG_MODE_LOCAL:
    307                 if (_log.shouldLog(Log.DEBUG))
    308                     _log.debug("mode = local");
     310                //if (_log.shouldLog(Log.DEBUG))
     311                //    _log.debug("mode = local");
    309312                break;
    310313            case FLAG_MODE_DESTINATION:
     
    335338        offset += getAdditionalInfo(rv, offset);
    336339        if (offset != additionalSize)
    337             _log.log(Log.CRIT, "wtf, additionalSize = " + additionalSize + ", offset = " + offset);
     340            //_log.log(Log.CRIT, "wtf, additionalSize = " + additionalSize + ", offset = " + offset);
     341            throw new IllegalStateException("wtf, additionalSize = " + additionalSize + ", offset = " + offset);
    338342        return rv;
    339343    }
     
    357361        switch (getDeliveryMode()) {
    358362            case FLAG_MODE_LOCAL:
    359                 if (_log.shouldLog(Log.DEBUG))
    360                     _log.debug("mode = local");
     363                //if (_log.shouldLog(Log.DEBUG))
     364                //    _log.debug("mode = local");
    361365                break;
    362366            case FLAG_MODE_DESTINATION:
     
    364368                System.arraycopy(_destinationHash.getData(), 0, rv, offset, Hash.HASH_LENGTH);
    365369                offset += Hash.HASH_LENGTH;
    366                 if (_log.shouldLog(Log.DEBUG))
    367                     _log.debug("mode = destination, hash = " + _destinationHash);
     370                //if (_log.shouldLog(Log.DEBUG))
     371                //    _log.debug("mode = destination, hash = " + _destinationHash);
    368372                break;
    369373            case FLAG_MODE_ROUTER:
     
    371375                System.arraycopy(_routerHash.getData(), 0, rv, offset, Hash.HASH_LENGTH);
    372376                offset += Hash.HASH_LENGTH;
    373                 if (_log.shouldLog(Log.DEBUG))
    374                     _log.debug("mode = router, routerHash = " + _routerHash);
     377                //if (_log.shouldLog(Log.DEBUG))
     378                //    _log.debug("mode = router, routerHash = " + _routerHash);
    375379                break;
    376380            case FLAG_MODE_TUNNEL:
     
    380384                DataHelper.toLong(rv, offset, 4, _tunnelId.getTunnelId());
    381385                offset += 4;
    382                 if (_log.shouldLog(Log.DEBUG))
    383                     _log.debug("mode = tunnel, tunnelId = " + _tunnelId.getTunnelId()
    384                                + ", routerHash = " + _routerHash);
     386                //if (_log.shouldLog(Log.DEBUG))
     387                //    _log.debug("mode = tunnel, tunnelId = " + _tunnelId.getTunnelId()
     388                //               + ", routerHash = " + _routerHash);
    385389                break;
    386390        }
    387391        if (getDelayRequested()) {
    388             if (_log.shouldLog(Log.DEBUG))
    389                 _log.debug("delay requested: " + getDelaySeconds());
     392            //if (_log.shouldLog(Log.DEBUG))
     393            //    _log.debug("delay requested: " + getDelaySeconds());
    390394            DataHelper.toLong(rv, offset, 4, getDelaySeconds());
    391395            offset += 4;
    392396        } else {
    393             if (_log.shouldLog(Log.DEBUG))
    394                 _log.debug("delay NOT requested");
     397            //if (_log.shouldLog(Log.DEBUG))
     398            //    _log.debug("delay NOT requested");
    395399        }
    396400        return offset - origOffset;
    397401    }
    398402   
     403    /**
     404     * @deprecated unused
     405     */
    399406    public void writeBytes(OutputStream out) throws DataFormatException, IOException {
    400407        if ( (_deliveryMode < 0) || (_deliveryMode > FLAG_MODE_TUNNEL) ) throw new DataFormatException("Invalid data: mode = " + _deliveryMode);
    401408        long flags = getFlags();
    402         if (_log.shouldLog(Log.DEBUG))
    403             _log.debug("Write flags: " + flags + " mode: " + getDeliveryMode()
    404                        + " =?= " + flagMode(flags));
     409        //if (_log.shouldLog(Log.DEBUG))
     410        //    _log.debug("Write flags: " + flags + " mode: " + getDeliveryMode()
     411        //               + " =?= " + flagMode(flags));
    405412        byte additionalInfo[] = getAdditionalInfo();
    406413        DataHelper.writeLong(out, 1, flags);
     
    417424        if ( (_deliveryMode < 0) || (_deliveryMode > FLAG_MODE_TUNNEL) ) throw new IllegalStateException("Invalid data: mode = " + _deliveryMode);
    418425        long flags = getFlags();
    419         if (_log.shouldLog(Log.DEBUG))
    420             _log.debug("Write flags: " + flags + " mode: " + getDeliveryMode()
    421                        + " =?= " + flagMode(flags));
     426        //if (_log.shouldLog(Log.DEBUG))
     427        //    _log.debug("Write flags: " + flags + " mode: " + getDeliveryMode()
     428        //               + " =?= " + flagMode(flags));
    422429        int origOffset = offset;
    423430        DataHelper.toLong(target, offset, 1, flags);
  • router/java/src/net/i2p/data/i2np/DeliveryStatusMessage.java

    r032b7d8 r8448001  
    99 */
    1010
    11 import java.io.IOException;
    12 
    1311import net.i2p.I2PAppContext;
    1412import net.i2p.data.DataHelper;
     
    2018 * @author jrandom
    2119 */
    22 public class DeliveryStatusMessage extends I2NPMessageImpl {
     20public class DeliveryStatusMessage extends FastI2NPMessageImpl {
    2321    public final static int MESSAGE_TYPE = 10;
    2422    private long _id;
     
    2725    public DeliveryStatusMessage(I2PAppContext context) {
    2826        super(context);
    29         setMessageId(-1);
    30         setArrival(-1);
     27        _id = -1;
     28        _arrival = -1;
    3129    }
    3230   
    3331    public long getMessageId() { return _id; }
    34     public void setMessageId(long id) { _id = id; }
     32
     33    /**
     34     *  @throws IllegalStateException if id previously set, to protect saved checksum
     35     */
     36    public void setMessageId(long id) {
     37        if (_id >= 0)
     38            throw new IllegalStateException();
     39        _id = id;
     40    }
    3541   
     42    /**
     43     *  Misnamed, as it is generally (always?) set by the creator to the current time,
     44     *  in some future usage it could be set on arrival
     45     */
    3646    public long getArrival() { return _arrival; }
    37     public void setArrival(long arrival) { _arrival = arrival; }
     47
     48    /**
     49     *  Misnamed, as it is generally (always?) set by the creator to the current time,
     50     *  in some future usage it could be set on arrival
     51     */
     52    public void setArrival(long arrival) {
     53        // To accomodate setting on arrival,
     54        // invalidate the stored checksum instead of throwing ISE
     55        if (_arrival >= 0)
     56            _hasChecksum = false;
     57        _arrival = arrival;
     58    }
    3859   
    39     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     60    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
    4061        if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
    4162        int curIndex = offset;
  • router/java/src/net/i2p/data/i2np/GarlicClove.java

    r032b7d8 r8448001  
    2525 * and a certificate 'paying for' the delivery.
    2626 *
     27 * Note that certificates are always the null certificate at this time, others are unimplemented.
     28 *
    2729 * @author jrandom
    2830 */
    2931public class GarlicClove extends DataStructureImpl {
    30     private Log _log;
    31     private RouterContext _context;
     32    private final Log _log;
     33    //private final RouterContext _context;
    3234    private DeliveryInstructions _instructions;
    3335    private I2NPMessage _msg;
     
    3537    private Date _expiration;
    3638    private Certificate _certificate;
    37     private I2NPMessageHandler _handler;
     39    private final I2NPMessageHandler _handler;
    3840   
    3941    public GarlicClove(RouterContext context) {
    40         _context = context;
     42        //_context = context;
    4143        _log = context.logManager().getLog(GarlicClove.class);
    4244        _handler = new I2NPMessageHandler(context);
    43         setCloveId(-1);
     45        _cloveId = -1;
    4446    }
    4547   
     
    5557    public void setCertificate(Certificate cert) { _certificate = cert; }
    5658   
     59    /**
     60     *  @deprecated unused, use byte array method to avoid copying
     61     */
    5762    public void readBytes(InputStream in) throws DataFormatException, IOException {
    5863        _instructions = new DeliveryInstructions();
     
    8792        } catch (I2NPMessageException ime) {
    8893            throw new DataFormatException("Unable to read the message from a garlic clove", ime);
    89         } catch (IOException ioe) {
    90             throw new DataFormatException("Not enough data to read the clove", ioe);
    9194        }
    9295        _cloveId = DataHelper.fromLong(source, cur, 4);
     
    9699        if (_log.shouldLog(Log.DEBUG))
    97100            _log.debug("CloveID read: " + _cloveId + " expiration read: " + _expiration);
    98         _certificate = new Certificate();
    99         cur += _certificate.readBytes(source, cur);
     101        //_certificate = new Certificate();
     102        //cur += _certificate.readBytes(source, cur);
     103        _certificate = Certificate.create(source, cur);
     104        cur += _certificate.size();
    100105        if (_log.shouldLog(Log.DEBUG))
    101106            _log.debug("Read cert: " + _certificate);
     
    103108    }
    104109
    105    
     110    /**
     111     *  @deprecated unused, use byte array method to avoid copying
     112     */
    106113    public void writeBytes(OutputStream out) throws DataFormatException, IOException {
    107114        StringBuilder error = null;
  • router/java/src/net/i2p/data/i2np/GarlicMessage.java

    r032b7d8 r8448001  
    99 */
    1010
    11 import java.io.IOException;
    12 
    1311import net.i2p.I2PAppContext;
    1412import net.i2p.data.DataHelper;
     
    1917 * @author jrandom
    2018 */
    21 public class GarlicMessage extends I2NPMessageImpl {
     19public class GarlicMessage extends FastI2NPMessageImpl {
    2220    public final static int MESSAGE_TYPE = 11;
    2321    private byte[] _data;
     
    3028        return _data;
    3129    }
     30
     31    /**
     32     *  @throws IllegalStateException if data previously set, to protect saved checksum
     33     */
    3234    public void setData(byte[] data) {
     35        if (_data != null)
     36            throw new IllegalStateException();
    3337        _data = data;
    3438    }
    3539   
    36     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     40    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
    3741        if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
    3842        int curIndex = offset;
  • router/java/src/net/i2p/data/i2np/I2NPMessage.java

    r032b7d8 r8448001  
    2727     * the current class's format as defined by the I2NP specification
    2828     *
     29     * Unused - All transports provide encapsulation and so we have byte arrays available.
     30     *
    2931     * @param in stream to read from
    30      * @param type I2NP message type
     32     *           starting at type if type is < 0 (16 byte header)
     33     *           starting at ID if type is >= 0 (15 byte header)
     34     * @param type I2NP message type. If less than zero, read the type from data
    3135     * @param buffer scratch buffer to be used when reading and parsing
    3236     * @return size of the message read (including headers)
     
    3438     *          that this class can read.
    3539     * @throws IOException if there is a problem reading from the stream
     40     * @deprecated unused
    3641     */
    3742    public int readBytes(InputStream in, int type, byte buffer[]) throws I2NPMessageException, IOException;
    38     public int readBytes(byte data[], int type, int offset) throws I2NPMessageException, IOException;
     43
     44    /**
     45     * Read the body into the data structures, after the initial type byte, using
     46     * the current class's format as defined by the I2NP specification
     47     *
     48     * @param data the data
     49     * @param type I2NP message type. If less than zero, read the type from data
     50     * @param offset where to start
     51     *           starting at type if type is < 0 (16 byte header)
     52     *           starting at ID if type is >= 0 (15 byte header)
     53     * @return size of the message read (including headers)
     54     * @throws I2NPMessageException if there is no valid message
     55     * @throws IOException if there is a problem reading from the stream
     56     */
     57    public int readBytes(byte data[], int type, int offset) throws I2NPMessageException;
     58
     59    /**
     60     * Read the body into the data structures, after the initial type byte, using
     61     * the current class's format as defined by the I2NP specification
     62     *
     63     * @param data the data, may or may not include the type
     64     * @param type I2NP message type. If less than zero, read the type from data
     65     * @param offset where to start
     66     *           starting at type if type is < 0 (16 byte header)
     67     *           starting at ID if type is >= 0 (15 byte header)
     68     * @param maxLen read no more than this many bytes from data starting at offset, even if it is longer
     69     *               This includes the type byte only if type < 0
     70     * @return size of the message read (including headers)
     71     * @throws I2NPMessageException if there is no valid message
     72     * @throws IOException if there is a problem reading from the stream
     73     * @since 0.8.12
     74     */
     75    public int readBytes(byte data[], int type, int offset, int maxLen) throws I2NPMessageException;
    3976
    4077    /**
     
    5188     * @throws IOException if there is a problem reading from the stream
    5289     */
    53     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException;
    54     public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException, IOException;
     90    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException;
     91    public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException;
    5592   
    5693    /**
     
    74111
    75112   
    76     /** How large the message is, including any checksums */
     113    /** How large the message is, including any checksums, i.e. full 16 byte header */
    77114    public int getMessageSize();
    78     /** How large the raw message is */
     115
     116    /** How large the raw message is with the short 5 byte header */
    79117    public int getRawMessageSize();
    80118
    81    
    82119    /**
    83120     * write the message to the buffer, returning the number of bytes written.
    84121     * the data is formatted so as to be self contained, with the type, size,
    85122     * expiration, unique id, as well as a checksum bundled along. 
     123     * Full 16 byte header.
    86124     */
    87125    public int toByteArray(byte buffer[]);
     126
    88127    /**
    89128     * write the message to the buffer, returning the number of bytes written.
    90129     * the data is is not self contained - it does not include the size,
    91130     * unique id, or any checksum, but does include the type and expiration.
     131     * Short 5 byte header.
    92132     */
    93133    public int toRawByteArray(byte buffer[]);
  • router/java/src/net/i2p/data/i2np/I2NPMessageHandler.java

    r032b7d8 r8448001  
    4040     * Read an I2NPMessage from the stream and return the fully populated object.
    4141     *
    42      * @throws IOException if there is an IO problem reading from the stream
     42     * This is only called by I2NPMessageReader which is unused.
     43     * All transports provide encapsulation and so we have byte arrays available.
     44     *
     45     * @deprecated use the byte array method to avoid an extra copy if you have it
     46     *
    4347     * @throws I2NPMessageException if there is a problem handling the particular
    4448     *          message - if it is an unknown type or has improper formatting, etc.
     
    5559            try {
    5660                _lastSize = msg.readBytes(in, type, _messageBuffer);
    57             } catch (IOException ioe) {
    58                 throw ioe;
    5961            } catch (I2NPMessageException ime) {
    6062                throw ime;
     
    6264                if (_log.shouldLog(Log.WARN))
    6365                    _log.warn("Error reading the stream", e);
    64                 throw new IOException("Unknown error reading the " + msg.getClass().getName()
    65                                       + ": " + e.getMessage());
     66                throw new I2NPMessageException("Unknown error reading the " + msg.getClass().getSimpleName(), e);
    6667            }
    6768            _lastReadEnd = System.currentTimeMillis();
     
    8081   
    8182    /**
    82      * Read an I2NPMessage from the stream and return the fully populated object.
     83     * Read an I2NPMessage from the byte array and return the fully populated object.
    8384     *
    84      * @throws IOException if there is an IO problem reading from the stream
    8585     * @throws I2NPMessageException if there is a problem handling the particular
    8686     *          message - if it is an unknown type or has improper formatting, etc.
    8787     */
    88     public I2NPMessage readMessage(byte data[]) throws IOException, I2NPMessageException {
    89         readMessage(data, 0);
     88    public I2NPMessage readMessage(byte data[]) throws I2NPMessageException {
     89        readMessage(data, 0, data.length);
    9090        return lastRead();
    9191    }
    9292
    93     public int readMessage(byte data[], int offset) throws IOException, I2NPMessageException {
     93    public int readMessage(byte data[], int offset) throws I2NPMessageException {
     94        return readMessage(data, offset, data.length - offset);
     95    }
     96
     97    /**
     98     *  Set a limit on the max to read from the data buffer, so that
     99     *  we can use a large buffer but prevent the reader from reading off the end.
     100     *
     101     *  @param maxLen read no more than this many bytes from data starting at offset, even if it is longer
     102     *                must be at least 16
     103     *  @since 0.8.12
     104     */
     105    public int readMessage(byte data[], int offset, int maxLen) throws I2NPMessageException {
    94106        int cur = offset;
     107        // we will assume that maxLen is >= 1 here. It's checked to be >= 16 in readBytes()
    95108        int type = (int)DataHelper.fromLong(data, cur, 1);
    96109        cur++;
     
    111124        //}
    112125        try {
    113             _lastSize = msg.readBytes(data, type, cur);
     126            _lastSize = msg.readBytes(data, type, cur, maxLen - 1);
    114127            cur += _lastSize;
    115         } catch (IOException ioe) {
    116             throw ioe;
    117128        } catch (I2NPMessageException ime) {
    118129            throw ime;
     
    120131            if (_log.shouldLog(Log.WARN))
    121132                _log.warn("Error reading the stream", e);
    122             throw new IOException("Unknown error reading the " + msg.getClass().getName()
    123                                   + ": " + e.getMessage());
     133            throw new I2NPMessageException("Unknown error reading the " + msg.getClass().getSimpleName(), e);
    124134        }
    125135        _lastReadEnd = System.currentTimeMillis();
  • router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java

    r032b7d8 r8448001  
    3131    protected final Log _log;
    3232    protected final I2PAppContext _context;
    33     private long _expiration;
    34     private long _uniqueId;
     33    protected long _expiration;
     34    protected long _uniqueId;
    3535   
    3636    public final static long DEFAULT_EXPIRATION_MS = 1*60*1000; // 1 minute by default
    3737    public final static int CHECKSUM_LENGTH = 1; //Hash.HASH_LENGTH;
    3838   
     39    /** 16 */
     40    public static final int HEADER_LENGTH = 1 // type
     41                        + 4 // uniqueId
     42                        + DataHelper.DATE_LENGTH // expiration
     43                        + 2 // payload length
     44                        + CHECKSUM_LENGTH;
     45
    3946    // Whether SSU used the full header or a truncated header.
    4047    // We are stuck with the short header, can't change it now.
     
    6370   
    6471    /**
    65      *  Read the whole message (including the type) and throw it away.
    66      *  @deprecated Unused, why would you do this
     72     *  Read the whole message but only if it's exactly 1024 bytes.
     73     *  Unused - All transports provide encapsulation and so we have byte arrays available.
     74     *
     75     *  @deprecated unused
    6776     */
    6877    public void readBytes(InputStream in) throws DataFormatException, IOException {
     
    7786     *  Read the header, then read the rest into buffer, then call
    7887     *  readMessage in the implemented message type
     88     *
     89     *  This does a copy from the stream to the buffer, so if you already
     90     *  have a byte array, use the other readBytes() instead.
    7991     *
    8092     *<pre>
     
    88100     *</pre>
    89101     *
     102     *  Unused - All transports provide encapsulation and so we have byte arrays available.
     103     *
    90104     *  @param type the message type or -1 if we should read it here
    91105     *  @param buffer temp buffer to use
    92106     *  @return total length of the message
     107     *  @deprecated unused
    93108     */
    94109    public int readBytes(InputStream in, int type, byte buffer[]) throws I2NPMessageException, IOException {
     
    157172     *  @return total length of the message
    158173     */
    159     public int readBytes(byte data[], int type, int offset) throws I2NPMessageException, IOException {
     174    public int readBytes(byte data[], int type, int offset) throws I2NPMessageException {
     175        return readBytes(data, type, offset, data.length - offset);
     176    }
     177
     178    /**
     179     *  Set a limit on the max to read from the data buffer, so that
     180     *  we can use a large buffer but prevent the reader from reading off the end.
     181     *
     182     *  @param maxLen read no more than this many bytes from data starting at offset, even if it is longer
     183     *                This includes the type byte only if type < 0
     184     *  @since 0.8.12
     185     */
     186    public int readBytes(byte data[], int type, int offset, int maxLen) throws I2NPMessageException {
     187        int headerSize = HEADER_LENGTH;
     188        if (type >= 0)
     189            headerSize--;
     190        if (maxLen < headerSize)
     191            throw new I2NPMessageException("Payload is too short " + maxLen);
    160192        int cur = offset;
    161193        if (type < 0) {
     
    175207        //h.setData(hdata);
    176208
    177         if (cur + size > data.length)
     209        if (cur + size > data.length || headerSize + size > maxLen)
    178210            throw new I2NPMessageException("Payload is too short ["
    179211                                           + "data.len=" + data.length
     212                                           + "maxLen=" + maxLen
    180213                                           + " offset=" + offset
    181214                                           + " cur=" + cur
    182                                            + " wanted=" + size + "]: " + getClass().getName());
    183 
     215                                           + " wanted=" + size + "]: " + getClass().getSimpleName());
     216
     217        int sz = Math.min(size, maxLen - headerSize);
    184218        byte[] calc = SimpleByteCache.acquire(Hash.HASH_LENGTH);
    185         _context.sha().calculateHash(data, cur, size, calc, 0);
     219        _context.sha().calculateHash(data, cur, sz, calc, 0);
    186220        boolean eq = DataHelper.eq(hdata, 0, calc, 0, CHECKSUM_LENGTH);
    187221        SimpleByteCache.release(calc);
     
    192226        if (_log.shouldLog(Log.DEBUG))
    193227            _log.debug("Reading bytes: type = " + type + " / uniqueId : " + _uniqueId + " / expiration : " + _expiration);
    194         readMessage(data, cur, size, type);
    195         cur += size;
     228        readMessage(data, cur, sz, type);
     229        cur += sz;
    196230        //long time = _context.clock().now() - start;
    197231        //if (time > 50)
     
    200234    }
    201235   
     236    /**
     237     *  Don't do this if you need a byte array - use toByteArray()
     238     *
     239     *  @deprecated unused
     240     */
    202241    public void writeBytes(OutputStream out) throws DataFormatException, IOException {
    203242        int size = getMessageSize();
     
    243282        if (written != data.length) {
    244283            _log.log(Log.CRIT, "Error writing out " + data.length + " (written: " + written + ", msgSize: " + getMessageSize() +
    245                                ", writtenLen: " + calculateWrittenLength() + ") for " + getClass().getName());
     284                               ", writtenLen: " + calculateWrittenLength() + ") for " + getClass().getSimpleName());
    246285            return null;
    247286        }
     
    250289   
    251290    public int toByteArray(byte buffer[]) {
    252         //long start = _context.clock().now();
    253 
    254         int prefixLen = 1 // type
    255                         + 4 // uniqueId
    256                         + DataHelper.DATE_LENGTH // expiration
    257                         + 2 // payload length
    258                         + CHECKSUM_LENGTH; // walnuts
    259         //byte prefix[][] = new byte[][] { DataHelper.toLong(1, getType()),
    260         //                                 DataHelper.toLong(4, _uniqueId),
    261         //                                 DataHelper.toLong(DataHelper.DATE_LENGTH, _expiration),
    262         //                                 new byte[2],
    263         //                                 new byte[CHECKSUM_LENGTH]};
    264         //byte suffix[][] = new byte[][] { };
    265         try {
    266             int writtenLen = writeMessageBody(buffer, prefixLen);
    267             int payloadLen = writtenLen - prefixLen;
     291        try {
     292            int writtenLen = writeMessageBody(buffer, HEADER_LENGTH);
     293            int payloadLen = writtenLen - HEADER_LENGTH;
    268294            byte[] h = SimpleByteCache.acquire(Hash.HASH_LENGTH);
    269             _context.sha().calculateHash(buffer, prefixLen, payloadLen, h, 0);
     295            _context.sha().calculateHash(buffer, HEADER_LENGTH, payloadLen, h, 0);
    270296
    271297            int off = 0;
     
    281307            SimpleByteCache.release(h);
    282308
    283             //long time = _context.clock().now() - start;
    284             //if (time > 50)
    285             //    _context.statManager().addRateData("i2np.writeTime", time, time);
    286 
    287309            return writtenLen;                     
    288310        } catch (I2NPMessageException ime) {
    289311            _context.logManager().getLog(getClass()).log(Log.CRIT, "Error writing", ime);
    290             throw new IllegalStateException("Unable to serialize the message (" + getClass().getName()
    291                                             + "): " + ime.getMessage());
     312            throw new IllegalStateException("Unable to serialize the message " + getClass().getSimpleName(), ime);
    292313        }
    293314    }
     
    295316    /** calculate the message body's length (not including the header and footer */
    296317    protected abstract int calculateWrittenLength();
     318
    297319    /**
    298320     * write the message body to the output array, starting at the given index.
     
    300322     */
    301323    protected abstract int writeMessageBody(byte out[], int curIndex) throws I2NPMessageException;
     324
    302325    /*
    303326    protected int toByteArray(byte out[], byte[][] prefix, byte[][] suffix) throws I2NPMessageException {
     
    339362        } catch (I2NPMessageException ime) {
    340363            _context.logManager().getLog(getClass()).log(Log.CRIT, "Error writing", ime);
    341             throw new IllegalStateException("Unable to serialize the message (" + getClass().getName()
    342                                             + "): " + ime.getMessage());
    343         }
    344     }
    345 
    346     public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException, IOException {
     364            throw new IllegalStateException("Unable to serialize the message " + getClass().getSimpleName(), ime);
     365        }
     366    }
     367
     368    public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException {
    347369        // ignore the handler (overridden in subclasses if necessary
    348370        try {
     
    389411            msg.setMessageExpiration(expiration);
    390412            return msg;
    391         } catch (IOException ioe) {
    392             throw new I2NPMessageException("IO error reading raw message", ioe);
    393413        } catch (IllegalArgumentException iae) {
    394414            throw new I2NPMessageException("Corrupt message (negative expiration)", iae);
  • router/java/src/net/i2p/data/i2np/I2NPMessageReader.java

    r032b7d8 r8448001  
    2323 * thrown, or the connection being closed.  Routers should use this rather
    2424 * than read from the stream themselves.
     25 *
     26 * Deprecated - unused.
     27 * This was used by the old TCP transport.
     28 * Both the NTCP and SSU transports provide encapsulation
     29 * of I2NP messages, so they use I2NPMessageHandlers directly.
     30 * If we ever add a transport that does not provide encapsulation,
     31 * this will be useful again.
     32 *
     33 * @deprecated unused
    2534 *
    2635 * @author jrandom
  • router/java/src/net/i2p/data/i2np/TunnelBuildMessage.java

    r032b7d8 r8448001  
    11package net.i2p.data.i2np;
    2 
    3 import java.io.IOException;
    42
    53import net.i2p.I2PAppContext;
  • router/java/src/net/i2p/data/i2np/TunnelBuildMessageBase.java

    r032b7d8 r8448001  
    11package net.i2p.data.i2np;
    2 
    3 import java.io.IOException;
    42
    53import net.i2p.I2PAppContext;
     
    108 *  Retrofitted over them.
    119 *  There's really no difference between the build and build reply.
     10 *
     11 *  TBM and VBTM (but not TBRM and VTBRM?) messages are modified
     12 *  in-place by doing a single setRecord(), and retransmitted.
     13 *  Therefore they are NOT good candidates to use FastI2NPMessageImpl;
     14 *  the checksum would have to be invalidated with every setRecord().
     15 *  Which we could do in TBM and VTBM but not TBRM and VTBRM,
     16 *  but keep it simple for now.
     17 *
    1218 *  @since 0.8.8
    1319 */
     
    4248    protected int calculateWrittenLength() { return RECORD_SIZE * RECORD_COUNT; }
    4349
    44     public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     50    public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException {
    4551        if (type != getType())
    4652            throw new I2NPMessageException("Message type is incorrect for this message");
  • router/java/src/net/i2p/data/i2np/TunnelBuildReplyMessage.java

    r032b7d8 r8448001  
    11package net.i2p.data.i2np;
    2 
    3 import java.io.IOException;
    42
    53import net.i2p.I2PAppContext;
  • router/java/src/net/i2p/data/i2np/TunnelDataMessage.java

    r032b7d8 r8448001  
    99 */
    1010
    11 import java.io.IOException;
    12 
    1311import net.i2p.I2PAppContext;
    1412import net.i2p.data.ByteArray;
     
    2119 * Defines the message sent between routers as part of the tunnel delivery
    2220 *
     21 * The tunnel ID is changed in-place by TunnelParticipant.send(), so
     22 * we can't reuse the checksum on output, but we still subclass
     23 * FastI2NPMessageImpl so we don't verify the checksum on input...
     24 * because this is a high-usage class.
     25 *
    2326 */
    24 public class TunnelDataMessage extends I2NPMessageImpl {
     27public class TunnelDataMessage extends FastI2NPMessageImpl {
    2528    private long _tunnelId;
    2629    private TunnelId _tunnelIdObj;
     
    2932   
    3033    public final static int MESSAGE_TYPE = 18;
    31     private static final int DATA_SIZE = 1024;
     34    public static final int DATA_SIZE = 1024;
    3235    /** if we can't deliver a tunnel message in 10s, fuck it */
    3336    private static final int EXPIRATION_PERIOD = 10*1000;
     
    105108   
    106109    public long getTunnelId() { return _tunnelId; }
    107     public void setTunnelId(long id) { _tunnelId = id; }
     110
     111    /**
     112     *  (correctly) Invalidates stored checksum
     113     */
     114    public void setTunnelId(long id) {
     115        _hasChecksum = false;
     116        _tunnelId = id;
     117    }
     118
    108119    public TunnelId getTunnelIdObj() {
    109120        if (_tunnelIdObj == null)
     
    111122        return _tunnelIdObj;
    112123    }
     124
     125    /**
     126     *  (correctly) Invalidates stored checksum
     127     */
    113128    public void setTunnelId(TunnelId id) {
     129        _hasChecksum = false;
    114130        _tunnelIdObj = id;
    115131        _tunnelId = id.getTunnelId();
     
    125141    }
    126142
     143    /**
     144     *  @throws IllegalStateException if data previously set, to protect saved checksum
     145     */
    127146    public void setData(byte data[]) {
     147        if (_data != null)
     148            throw new IllegalStateException();
    128149        if ( (data == null) || (data.length <= 0) )
    129150            throw new IllegalArgumentException("Empty tunnel payload?");
     
    131152    }
    132153   
    133     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     154    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
    134155        if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
    135156        int curIndex = offset;
     
    215236        StringBuilder buf = new StringBuilder();
    216237        buf.append("[TunnelDataMessage:");
    217         buf.append(" MessageId: ").append(getUniqueId());
    218         buf.append(" Tunnel ID: ").append(getTunnelId());
     238        buf.append(" MessageId: ").append(_uniqueId);
     239        buf.append(" Tunnel ID: ").append(_tunnelId);
    219240        buf.append("]");
    220241        return buf.toString();
  • router/java/src/net/i2p/data/i2np/TunnelGatewayMessage.java

    r032b7d8 r8448001  
    88 *
    99 */
    10 
    11 import java.io.IOException;
    1210
    1311import net.i2p.I2PAppContext;
     
    2119 *
    2220 */
    23 public class TunnelGatewayMessage extends I2NPMessageImpl {
     21public class TunnelGatewayMessage extends FastI2NPMessageImpl {
    2422    private TunnelId _tunnelId;
    2523    private I2NPMessage _msg;
     
    3836   
    3937    public TunnelId getTunnelId() { return _tunnelId; }
    40     public void setTunnelId(TunnelId id) { _tunnelId = id; }
     38
     39    /**
     40     *  @throws IllegalStateException if id previously set, to protect saved checksum
     41     */
     42    public void setTunnelId(TunnelId id) {
     43        if (_tunnelId != null)
     44            throw new IllegalStateException();
     45        _tunnelId = id;
     46    }
    4147   
    4248    /**
     
    4450     *  this will be an UnknownI2NPMessage.
    4551     *  If you need a real message class, use UnknownI2NPMessage.convert().
     52     *
     53     *  Note that if you change the expiration on the embedded message it will
     54     *  mess up the checksum of this message, so don't do that.
    4655     */
    4756    public I2NPMessage getMessage() { return _msg; }
    4857
     58    /**
     59     *  @throws IllegalStateException if msg previously set, to protect saved checksum
     60     */
    4961    public void setMessage(I2NPMessage msg) {
     62        if (_msg != null)
     63            throw new IllegalStateException();
    5064        if (msg == null)
    5165            throw new IllegalArgumentException("wtf, dont set me to null");
     
    91105   
    92106
    93     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     107    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
    94108        //I2NPMessageHandler h = new I2NPMessageHandler(_context);
    95109        //readMessage(data, offset, dataSize, type, h);
     
    104118     */
    105119    @Override
    106     public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException, IOException {
     120    public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException {
    107121        if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
    108122        int curIndex = offset;
     
    138152        int utype = data[curIndex++] & 0xff;
    139153        UnknownI2NPMessage umsg = new UnknownI2NPMessage(_context, utype);
    140         umsg.readBytesIgnoreChecksum(data, curIndex);
     154        umsg.readBytes(data, utype, curIndex);
    141155        _msg = umsg;
    142156    }
  • router/java/src/net/i2p/data/i2np/UnknownI2NPMessage.java

    r032b7d8 r8448001  
    88 *
    99 */
    10 
    11 import java.io.IOException;
    1210
    1311import net.i2p.I2PAppContext;
     
    3331 * @since 0.7.12 but broken before 0.8.12
    3432 */
    35 public class UnknownI2NPMessage extends I2NPMessageImpl {
     33public class UnknownI2NPMessage extends FastI2NPMessageImpl {
    3634    private byte _data[];
    3735    private final int _type;
    38     // we assume CHECKSUM_LENGTH = 1
    39     private byte _checksum;
    4036   
    4137    /** @param type 0-255 */
     
    4541    }
    4642   
    47     public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     43    /**
     44     *  @throws IllegalStateException if data previously set, to protect saved checksum
     45     */
     46    public void readMessage(byte data[], int offset, int dataSize, int type) throws I2NPMessageException {
     47        if (_data != null)
     48            throw new IllegalStateException();
    4849        if (type != _type) throw new I2NPMessageException("Message type is incorrect for this message");
    4950        if (dataSize > MAX_SIZE)
     
    7879    public int getType() { return _type; }
    7980   
    80 
    81     /**
    82      *  Read the full message including the header.
    83      *  This is the same as I2NPMessageImpl.readBytes(), except
    84      *  start after the type field, and
    85      *  do NOT verify the checksum, but simply save it for later
    86      *  so it can be verified in convert() if required.
    87      *
    88      *<pre>
    89      *  Standard message format AFTER the type field
    90      *    4 byte ID
    91      *    8 byte expiration
    92      *    2 byte size
    93      *    1 byte checksum (saved in case we need to check later)
    94      *    size bytes of payload, read by readMessage()
    95      *</pre>
    96      *
    97      *  @param offset starting at the ID (must skip the type)
    98      *  @since 0.8.12
    99      */
    100     public void readBytesIgnoreChecksum(byte data[], int offset) throws I2NPMessageException, IOException {
    101         int cur = offset;
    102         setUniqueId(DataHelper.fromLong(data, cur, 4));
    103         cur += 4;
    104         setMessageExpiration(DataHelper.fromLong(data, cur, DataHelper.DATE_LENGTH));
    105         cur += DataHelper.DATE_LENGTH;
    106         int size = (int)DataHelper.fromLong(data, cur, 2);
    107         cur += 2;
    108         _checksum = data[cur];
    109         cur++;
    110 
    111         if (cur + size > data.length)
    112             throw new I2NPMessageException("Payload is too short ["
    113                                            + "data.len=" + data.length
    114                                            + " offset=" + offset
    115                                            + " cur=" + cur
    116                                            + " wanted=" + size + ']');
    117 
    118         readMessage(data, cur, size, _type);
    119     }
    120    
    12181    /**
    12282     *  Attempt to convert this message to a known message class.
    123      *  Must have been created with readBytesIgnoreChecksum previously,
    124      *  as this does the delayed verification using the saved checksum.
     83     *  This does the delayed verification using the saved checksum.
    12584     *
    12685     *  Used by TunnelGatewayZeroHop.
     
    13089     */
    13190    public I2NPMessage convert() throws I2NPMessageException {
     91        if (_data == null || !_hasChecksum)
     92            throw new I2NPMessageException("Illegal state");
    13293        I2NPMessage msg = I2NPMessageImpl.createMessage(_context, _type);
    13394        if (msg instanceof UnknownI2NPMessage)
     
    139100        if (!eq)
    140101            throw new I2NPMessageException("Bad checksum on " + _data.length + " byte msg type " + _type);
    141         try {
    142             msg.readMessage(_data, 0, _data.length, _type);
    143         } catch (IOException ioe) {
    144             throw new I2NPMessageException("Unable to convert type " + _type, ioe);
    145         }
    146         msg.setUniqueId(getUniqueId());
    147         msg.setMessageExpiration(getMessageExpiration());
     102        msg.readMessage(_data, 0, _data.length, _type);
     103        msg.setUniqueId(_uniqueId);
     104        msg.setMessageExpiration(_expiration);
    148105        return msg;
    149106    }
  • router/java/src/net/i2p/data/i2np/VariableTunnelBuildMessage.java

    r032b7d8 r8448001  
    11package net.i2p.data.i2np;
    2 
    3 import java.io.IOException;
    42
    53import net.i2p.I2PAppContext;
     
    3129
    3230    @Override
    33     public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     31    public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException {
    3432        // message type will be checked in super()
    3533        int r = (int)DataHelper.fromLong(data, offset, 1);
  • router/java/src/net/i2p/data/i2np/VariableTunnelBuildReplyMessage.java

    r032b7d8 r8448001  
    11package net.i2p.data.i2np;
    2 
    3 import java.io.IOException;
    42
    53import net.i2p.I2PAppContext;
     
    3331
    3432    @Override
    35     public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
     33    public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException {
    3634        // message type will be checked in super()
    3735        int r = (int)DataHelper.fromLong(data, offset, 1);
  • router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java

    r032b7d8 r8448001  
    2929import net.i2p.router.transport.FIFOBandwidthLimiter;
    3030import net.i2p.util.ConcurrentHashSet;
     31import net.i2p.util.HexDump;
    3132import net.i2p.util.Log;
    3233
     
    12271228    //public long getReadTime() { return _curReadState.getReadTime(); }
    12281229   
     1230    /**
     1231     *  Just a byte array now (used to have a BAIS in it too,
     1232     *  but that required an extra copy in the message handler)
     1233     */
    12291234    private static class DataBuf {
    12301235        final byte data[];
    1231         final ByteArrayInputStream bais;
    12321236
    12331237        public DataBuf() {
    12341238            data = new byte[BUFFER_SIZE];
    1235             bais = new ByteArrayInputStream(data);
    12361239        }
    12371240    }
     
    12481251
    12491252    private static void releaseReadBuf(DataBuf buf) {
    1250         buf.bais.reset();
    12511253        _dataReadBufs.offer(buf);
    12521254    }
     
    13881390                try {
    13891391                    I2NPMessageHandler h = acquireHandler(_context);
    1390                     //I2NPMessage read = h.readMessage(new ByteArrayInputStream(_data, 0, _size));
    1391                     // the _bais is mark()ed at 0 on construction, and on init() we
    1392                     // reset() it back to that position, so this read always starts
    1393                     // at the beginning of the _data buffer.  the I2NPMessageHandler
    1394                     // also only reads the first I2NP message found, and does not
    1395                     // depend upon EOF to stop reading, so its ok that the _bais could
    1396                     // in theory return more data than _size bytes, since h.readMessage
    1397                     // stops when it should.
    1398                     I2NPMessage read = h.readMessage(_dataBuf.bais);
     1392
     1393                    // Don't do readMessage(InputStream). I2NPMessageImpl.readBytes() copies the data
     1394                    // from a stream to a temp buffer.
     1395                    // We could extend BAIS to adjust the protected count variable to _size
     1396                    // so that readBytes() doesn't read too far, but it could still read too far.
     1397                    // So use the new handler method that limits the size.
     1398                    h.readMessage(_dataBuf.data, 0, _size);
     1399                    I2NPMessage read = h.lastRead();
    13991400                    long timeToRecv = System.currentTimeMillis() - _stateBegin;
    14001401                    releaseHandler(h);
     
    14151416                        _messagesRead++;
    14161417                    }
    1417                     // get it ready for the next I2NP message
    1418                     init();
    1419                 } catch (IOException ioe) {
    1420                     if (_log.shouldLog(Log.WARN))
    1421                         _log.warn("Error parsing I2NP message", ioe);
    1422                     _context.statManager().addRateData("ntcp.corruptI2NPIOE", 1);
    1423                     close();
    1424                     // handler and databuf are lost
    1425                     return;
    14261418                } catch (I2NPMessageException ime) {
    1427                     if (_log.shouldLog(Log.WARN))
     1419                    if (_log.shouldLog(Log.WARN)) {
    14281420                        _log.warn("Error parsing I2NP message", ime);
     1421                        _log.warn("DUMP:\n" + HexDump.dump(_dataBuf.data, 0, _size));
     1422                        _log.warn("RAW:\n" + Base64.encode(_dataBuf.data, 0, _size));
     1423                    }
    14291424                    _context.statManager().addRateData("ntcp.corruptI2NPIME", 1);
    1430                     // FIXME don't close the con, possible attack vector?
    1431                     close();
    1432                     // handler and databuf are lost
    1433                     return;
     1425                    // Don't close the con, possible attack vector, not necessarily the peer's fault,
     1426                    // and should be recoverable
     1427                    // handler and databuf are lost if we do this
     1428                    //close();
     1429                    //return;
    14341430                }
    14351431            } else {
     
    14371433                    _log.warn("CRC incorrect for message " + _messagesRead + " (calc=" + val + " expected=" + _expectedCrc + ") size=" + _size + " blocks " + _blocks);
    14381434                    _context.statManager().addRateData("ntcp.corruptI2NPCRC", 1);
    1439                 // FIXME don't close the con, possible attack vector?
    1440                 close();
    1441                 // databuf is lost
    1442                 return;
    1443             }
     1435                // This probably can't be spoofed from somebody else, but do we really need to close it?
     1436                // This is rare.
     1437                //close();
     1438                // databuf is lost if we do this
     1439                //return;
     1440            }
     1441            // get it ready for the next I2NP message
     1442            init();
    14441443        }
    14451444    }
Note: See TracChangeset for help on using the changeset viewer.