Search in sources :

Example 1 with I2NPMessage

use of net.i2p.data.i2np.I2NPMessage in project i2p.i2p by i2p.

the class MessageReceiver method readMessage.

/**
 *  Assemble all the fragments into an I2NP message.
 *  This calls state.releaseResources(), do not access state after calling this.
 *
 *  @param buf temp buffer for convenience
 *  @return null on error
 */
private I2NPMessage readMessage(ByteArray buf, InboundMessageState state, I2NPMessageHandler handler) {
    try {
        // byte buf[] = new byte[state.getCompleteSize()];
        I2NPMessage m;
        int numFragments = state.getFragmentCount();
        if (numFragments > 1) {
            ByteArray[] fragments = state.getFragments();
            int off = 0;
            for (int i = 0; i < numFragments; i++) {
                System.arraycopy(fragments[i].getData(), 0, buf.getData(), off, fragments[i].getValid());
                // if (_log.shouldLog(Log.DEBUG))
                // _log.debug("Raw fragment[" + i + "] for " + state.getMessageId() + ": "
                // + Base64.encode(fragments[i].getData(), 0, fragments[i].getValid())
                // + " (valid: " + fragments[i].getValid()
                // + " raw: " + Base64.encode(fragments[i].getData()) + ")");
                off += fragments[i].getValid();
            }
            if (off != state.getCompleteSize()) {
                if (_log.shouldLog(Log.WARN))
                    _log.warn("Hmm, offset of the fragments = " + off + " while the state says " + state.getCompleteSize());
                return null;
            }
            // if (_log.shouldLog(Log.DEBUG))
            // _log.debug("Raw byte array for " + state.getMessageId() + ": " + HexDump.dump(buf.getData(), 0, state.getCompleteSize()));
            m = I2NPMessageImpl.fromRawByteArray(_context, buf.getData(), 0, state.getCompleteSize(), handler);
        } else {
            // zero copy for single fragment
            m = I2NPMessageImpl.fromRawByteArray(_context, state.getFragments()[0].getData(), 0, state.getCompleteSize(), handler);
        }
        m.setUniqueId(state.getMessageId());
        return m;
    } catch (I2NPMessageException ime) {
        if (_log.shouldLog(Log.WARN)) {
            ByteArray ba;
            if (state.getFragmentCount() > 1)
                ba = buf;
            else
                ba = state.getFragments()[0];
            byte[] data = ba.getData();
            _log.warn("Message invalid: " + state + " PeerState: " + _transport.getPeerState(state.getFrom()) + "\nDUMP:\n" + HexDump.dump(data, 0, state.getCompleteSize()) + "\nRAW:\n" + Base64.encode(data, 0, state.getCompleteSize()), ime);
        }
        if (state.getFragments()[0].getData()[0] == DatabaseStoreMessage.MESSAGE_TYPE) {
            PeerState ps = _transport.getPeerState(state.getFrom());
            if (ps != null && ps.getRemotePort() == 65520) {
                // distinct port of buggy router
                _transport.sendDestroy(ps);
                _transport.dropPeer(ps, true, "Corrupt DSM");
                _context.banlist().banlistRouterForever(state.getFrom(), _x("Sent corrupt DSM"));
            }
        }
        _context.messageHistory().droppedInboundMessage(state.getMessageId(), state.getFrom(), "error: " + ime.toString() + ": " + state.toString());
        return null;
    } catch (RuntimeException e) {
        // e.g. AIOOBE
        if (_log.shouldLog(Log.WARN))
            _log.warn("Error handling a message: " + state, e);
        _context.messageHistory().droppedInboundMessage(state.getMessageId(), state.getFrom(), "error: " + e.toString() + ": " + state.toString());
        return null;
    } finally {
        state.releaseResources();
    }
}
Also used : I2NPMessageException(net.i2p.data.i2np.I2NPMessageException) I2NPMessage(net.i2p.data.i2np.I2NPMessage) ByteArray(net.i2p.data.ByteArray)

Example 2 with I2NPMessage

use of net.i2p.data.i2np.I2NPMessage in project i2p.i2p by i2p.

the class MessageReceiver method loop.

public void loop(I2NPMessageHandler handler) {
    InboundMessageState message = null;
    // ByteArray buf = _cache.acquire();
    ByteArray buf = new ByteArray(new byte[I2NPMessage.MAX_SIZE]);
    while (_alive) {
        int expired = 0;
        long expiredLifetime = 0;
        try {
            while (message == null) {
                message = _completeMessages.take();
                if ((message != null) && (message.getMessageId() == POISON_IMS)) {
                    message = null;
                    break;
                }
                if ((message != null) && (message.isExpired())) {
                    expiredLifetime += message.getLifetime();
                    // message.releaseResources() ??
                    message = null;
                    expired++;
                }
            // remaining = _completeMessages.size();
            }
        } catch (InterruptedException ie) {
        }
        if (expired > 0)
            _context.statManager().addRateData("udp.inboundExpired", expired, expiredLifetime);
        if (message != null) {
            // long before = System.currentTimeMillis();
            // if (remaining > 0)
            // _context.statManager().addRateData("udp.inboundRemaining", remaining, 0);
            int size = message.getCompleteSize();
            // long afterRead = -1;
            try {
                I2NPMessage msg = readMessage(buf, message, handler);
                // afterRead = System.currentTimeMillis();
                if (msg != null)
                    _transport.messageReceived(msg, null, message.getFrom(), message.getLifetime(), size);
            } catch (RuntimeException re) {
                _log.error("b0rked receiving a message.. wazza huzza hmm?", re);
                continue;
            }
            message = null;
        // long after = System.currentTimeMillis();
        // if (afterRead - before > 100)
        // _context.statManager().addRateData("udp.inboundReadTime", afterRead - before, remaining);
        // if (after - afterRead > 100)
        // _context.statManager().addRateData("udp.inboundReceiveProcessTime", after - afterRead, remaining);
        }
    }
// no need to zero it out, as these buffers are only used with an explicit getCompleteSize
// _cache.release(buf, false);
}
Also used : I2NPMessage(net.i2p.data.i2np.I2NPMessage) ByteArray(net.i2p.data.ByteArray)

Example 3 with I2NPMessage

use of net.i2p.data.i2np.I2NPMessage in project i2p.i2p by i2p.

the class NTCPConnection method bufferedPrepare.

/**
 * Serialize the message/checksum/padding/etc for transmission, but leave off
 * the encryption.  This should be called from a Writer thread
 *
 * @param msg message to send
 * @param buf PrepBuffer to use as scratch space
 */
private void bufferedPrepare(OutNetMessage msg, PrepBuffer buf) {
    // if (!_isInbound && !_established)
    // return;
    // long begin = System.currentTimeMillis();
    // long alloc = System.currentTimeMillis();
    I2NPMessage m = msg.getMessage();
    buf.baseLength = m.toByteArray(buf.base);
    int sz = buf.baseLength;
    // int sz = m.getMessageSize();
    int min = 2 + sz + 4;
    int rem = min % 16;
    int padding = 0;
    if (rem > 0)
        padding = 16 - rem;
    buf.unencryptedLength = min + padding;
    DataHelper.toLong(buf.unencrypted, 0, 2, sz);
    System.arraycopy(buf.base, 0, buf.unencrypted, 2, buf.baseLength);
    if (padding > 0) {
        _context.random().nextBytes(buf.unencrypted, 2 + sz, padding);
    }
    // long serialized = System.currentTimeMillis();
    buf.crc.update(buf.unencrypted, 0, buf.unencryptedLength - 4);
    long val = buf.crc.getValue();
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Outbound message " + _messagesWritten + " has crc " + val + " sz=" + sz + " rem=" + rem + " padding=" + padding);
    DataHelper.toLong(buf.unencrypted, buf.unencryptedLength - 4, 4, val);
    // TODO object churn
    // 1) store the length only
    // 2) in prepareNextWriteFast(), pull a byte buffer off a queue and encrypt to that
    // 3) change EventPumper.wantsWrite() to take a ByteBuffer arg
    // 4) in EventPumper.processWrite(), release the byte buffer
    buf.encrypted = new byte[buf.unencryptedLength];
// long crced = System.currentTimeMillis();
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Buffered prepare took " + (crced-begin) + ", alloc=" + (alloc-begin)
// + " serialize=" + (serialized-alloc) + " crc=" + (crced-serialized));
}
Also used : I2NPMessage(net.i2p.data.i2np.I2NPMessage)

Example 4 with I2NPMessage

use of net.i2p.data.i2np.I2NPMessage in project i2p.i2p by i2p.

the class FloodfillVerifyStoreJob method runJob.

/**
 *  Query a random floodfill for the leaseset or routerinfo
 *  that we just stored to a (hopefully different) floodfill peer.
 *
 *  If it fails (after a timeout period), resend the data.
 *  If the queried data is older than what we stored, that counts as a fail.
 */
public void runJob() {
    _target = pickTarget();
    if (_target == null) {
        _facade.verifyFinished(_key);
        return;
    }
    boolean isInboundExploratory;
    TunnelInfo replyTunnelInfo;
    if (_isRouterInfo || getContext().keyRing().get(_key) != null) {
        replyTunnelInfo = getContext().tunnelManager().selectInboundExploratoryTunnel(_target);
        isInboundExploratory = true;
    } else {
        replyTunnelInfo = getContext().tunnelManager().selectInboundTunnel(_key, _target);
        isInboundExploratory = false;
    }
    if (replyTunnelInfo == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("No inbound tunnels to get a reply from!");
        return;
    }
    DatabaseLookupMessage lookup = buildLookup(replyTunnelInfo);
    // If we are verifying a leaseset, use the destination's own tunnels,
    // to avoid association by the exploratory tunnel OBEP.
    // Unless it is an encrypted leaseset.
    TunnelInfo outTunnel;
    if (_isRouterInfo || getContext().keyRing().get(_key) != null)
        outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(_target);
    else
        outTunnel = getContext().tunnelManager().selectOutboundTunnel(_key, _target);
    if (outTunnel == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("No outbound tunnels to verify a store");
        _facade.verifyFinished(_key);
        return;
    }
    // garlic encrypt to hide contents from the OBEP
    RouterInfo peer = _facade.lookupRouterInfoLocally(_target);
    if (peer == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Fail finding target RI");
        _facade.verifyFinished(_key);
        return;
    }
    if (DatabaseLookupMessage.supportsEncryptedReplies(peer)) {
        // register the session with the right SKM
        MessageWrapper.OneTimeSession sess;
        if (isInboundExploratory) {
            sess = MessageWrapper.generateSession(getContext());
        } else {
            sess = MessageWrapper.generateSession(getContext(), _key);
            if (sess == null) {
                if (_log.shouldLog(Log.WARN))
                    _log.warn("No SKM to reply to");
                _facade.verifyFinished(_key);
                return;
            }
        }
        if (_log.shouldLog(Log.INFO))
            _log.info("Requesting encrypted reply from " + _target + ' ' + sess.key + ' ' + sess.tag);
        lookup.setReplySession(sess.key, sess.tag);
    }
    Hash fromKey;
    if (_isRouterInfo)
        fromKey = null;
    else
        fromKey = _key;
    _wrappedMessage = MessageWrapper.wrap(getContext(), lookup, fromKey, peer);
    if (_wrappedMessage == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Fail Garlic encrypting");
        _facade.verifyFinished(_key);
        return;
    }
    I2NPMessage sent = _wrappedMessage.getMessage();
    if (_log.shouldLog(Log.INFO))
        _log.info("Starting verify (stored " + _key + " to " + _sentTo + "), asking " + _target);
    _sendTime = getContext().clock().now();
    _expiration = _sendTime + VERIFY_TIMEOUT;
    getContext().messageRegistry().registerPending(new VerifyReplySelector(), new VerifyReplyJob(getContext()), new VerifyTimeoutJob(getContext()));
    getContext().tunnelDispatcher().dispatchOutbound(sent, outTunnel.getSendTunnelId(0), _target);
}
Also used : DatabaseLookupMessage(net.i2p.data.i2np.DatabaseLookupMessage) RouterInfo(net.i2p.data.router.RouterInfo) I2NPMessage(net.i2p.data.i2np.I2NPMessage) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash)

Example 5 with I2NPMessage

use of net.i2p.data.i2np.I2NPMessage in project i2p.i2p by i2p.

the class VMCommSystem method processMessage.

/**
 * The router wants us to send the given message to the peer.  Do so, or fire
 * off the failing job.
 */
public void processMessage(OutNetMessage msg) {
    Hash peer = msg.getTarget().getIdentity().getHash();
    VMCommSystem peerSys = _commSystemFacades.get(peer);
    long now = _context.clock().now();
    long sendTime = now - msg.getSendBegin();
    boolean sendSuccessful = false;
    if (peerSys == null) {
        _context.jobQueue().addJob(msg.getOnFailedSendJob());
        _context.statManager().updateFrequency("transport.sendMessageFailureFrequency");
        _context.profileManager().messageFailed(msg.getTarget().getIdentity().getHash(), "vm");
    } else {
        _context.jobQueue().addJob(msg.getOnSendJob());
        _context.profileManager().messageSent(msg.getTarget().getIdentity().getHash(), "vm", sendTime, msg.getMessageSize());
        byte[] data = new byte[(int) msg.getMessageSize()];
        msg.getMessageData(data);
        _context.statManager().addRateData("transport.sendMessageSize", data.length, sendTime);
        if (data.length < 1024)
            _context.statManager().addRateData("transport.sendMessageSmall", 1, sendTime);
        else if (data.length <= 4096)
            _context.statManager().addRateData("transport.sendMessageMedium", 1, sendTime);
        else
            _context.statManager().addRateData("transport.sendMessageLarge", 1, sendTime);
        peerSys.receive(data, _context.routerHash());
        // _context.jobQueue().addJob(new SendJob(peerSys, msg.getMessage(), _context));
        sendSuccessful = true;
    }
    if (true) {
        I2NPMessage dmsg = msg.getMessage();
        String type = dmsg.getClass().getName();
        _context.messageHistory().sendMessage(type, dmsg.getUniqueId(), dmsg.getMessageExpiration(), msg.getTarget().getIdentity().getHash(), sendSuccessful, null);
    }
    msg.discardData();
    _context.statManager().addRateData("transport.sendProcessingTime", msg.getLifetime(), msg.getLifetime());
}
Also used : I2NPMessage(net.i2p.data.i2np.I2NPMessage) Hash(net.i2p.data.Hash)

Aggregations

I2NPMessage (net.i2p.data.i2np.I2NPMessage)21 Hash (net.i2p.data.Hash)9 ArrayList (java.util.ArrayList)5 DataMessage (net.i2p.data.i2np.DataMessage)4 I2NPMessageException (net.i2p.data.i2np.I2NPMessageException)4 TunnelInfo (net.i2p.router.TunnelInfo)4 Test (org.junit.Test)4 TunnelId (net.i2p.data.TunnelId)3 DatabaseLookupMessage (net.i2p.data.i2np.DatabaseLookupMessage)3 DatabaseStoreMessage (net.i2p.data.i2np.DatabaseStoreMessage)3 RouterInfo (net.i2p.data.router.RouterInfo)3 OutNetMessage (net.i2p.router.OutNetMessage)3 ByteArray (net.i2p.data.ByteArray)2 I2NPMessageHandler (net.i2p.data.i2np.I2NPMessageHandler)2 Job (net.i2p.router.Job)2 ReplyJob (net.i2p.router.ReplyJob)2 IOException (java.io.IOException)1 ServerSocketChannel (java.nio.channels.ServerSocketChannel)1 SocketChannel (java.nio.channels.SocketChannel)1 HashSet (java.util.HashSet)1