Search in sources :

Example 1 with MessageSelector

use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.

the class OutboundMessageRegistry method registerPending.

/**
 *  @param allowEmpty is msg.getMessage() allowed to be null?
 */
@SuppressWarnings("unchecked")
private void registerPending(OutNetMessage msg, boolean allowEmpty) {
    if ((!allowEmpty) && (msg.getMessage() == null))
        throw new IllegalArgumentException("OutNetMessage doesn't contain an I2NPMessage? Impossible?");
    MessageSelector sel = msg.getReplySelector();
    if (sel == null)
        throw new IllegalArgumentException("No reply selector? Impossible?");
    if (!_activeMessages.add(msg))
        // dont add dups
        return;
    synchronized (_selectorToMessage) {
        Object oldMsg = _selectorToMessage.put(sel, msg);
        if (oldMsg != null) {
            List<OutNetMessage> multi = null;
            if (oldMsg instanceof OutNetMessage) {
                // multi = Collections.synchronizedList(new ArrayList(4));
                multi = new ArrayList<OutNetMessage>(4);
                multi.add((OutNetMessage) oldMsg);
                multi.add(msg);
                _selectorToMessage.put(sel, multi);
            } else if (oldMsg instanceof List) {
                multi = (List<OutNetMessage>) oldMsg;
                multi.add(msg);
                _selectorToMessage.put(sel, multi);
            }
            if (_log.shouldLog(Log.WARN))
                _log.warn("a single message selector [" + sel + "] with multiple messages (" + multi + ")");
        }
    }
    synchronized (_selectors) {
        _selectors.add(sel);
    }
    _cleanupTask.scheduleExpiration(sel);
}
Also used : OutNetMessage(net.i2p.router.OutNetMessage) ArrayList(java.util.ArrayList) List(java.util.List) MessageSelector(net.i2p.router.MessageSelector)

Example 2 with MessageSelector

use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.

the class OutboundMessageRegistry method getOriginalMessages.

/**
 * Retrieve all messages that are waiting for the specified message.  In
 * addition, those matches may include instructions to either continue or not
 * continue waiting for further replies - if it should continue, the matched
 * message remains in the registry, but if it shouldn't continue, the matched
 * message is removed from the registry.
 *
 * This is called only by InNetMessagePool.
 *
 * TODO this calls isMatch() in the selectors from inside the lock, which
 * can lead to deadlocks if the selector does too much in isMatch().
 * Remove the lock if possible.
 *
 * @param message Payload received that may be a reply to something we sent
 * @return non-null List of OutNetMessage describing messages that were waiting for
 *         the payload
 */
@SuppressWarnings("unchecked")
public List<OutNetMessage> getOriginalMessages(I2NPMessage message) {
    List<MessageSelector> matchedSelectors = null;
    List<MessageSelector> removedSelectors = null;
    synchronized (_selectors) {
        // MessageSelector sel = iter.next();
        for (int i = 0; i < _selectors.size(); i++) {
            MessageSelector sel = _selectors.get(i);
            boolean isMatch = sel.isMatch(message);
            if (isMatch) {
                if (matchedSelectors == null)
                    matchedSelectors = new ArrayList<MessageSelector>(1);
                matchedSelectors.add(sel);
                if (!sel.continueMatching()) {
                    if (removedSelectors == null)
                        removedSelectors = new ArrayList<MessageSelector>(1);
                    removedSelectors.add(sel);
                    // iter.remove();
                    _selectors.remove(i);
                    i--;
                }
            }
        }
    }
    List<OutNetMessage> rv;
    if (matchedSelectors != null) {
        rv = new ArrayList<OutNetMessage>(matchedSelectors.size());
        for (MessageSelector sel : matchedSelectors) {
            boolean removed = false;
            OutNetMessage msg = null;
            List<OutNetMessage> msgs = null;
            synchronized (_selectorToMessage) {
                Object o = null;
                if ((removedSelectors != null) && (removedSelectors.contains(sel))) {
                    o = _selectorToMessage.remove(sel);
                    removed = true;
                } else {
                    o = _selectorToMessage.get(sel);
                }
                if (o instanceof OutNetMessage) {
                    msg = (OutNetMessage) o;
                    rv.add(msg);
                } else if (o instanceof List) {
                    msgs = (List<OutNetMessage>) o;
                    rv.addAll(msgs);
                }
            }
            if (removed) {
                if (msg != null) {
                    _activeMessages.remove(msg);
                } else if (msgs != null) {
                    _activeMessages.removeAll(msgs);
                }
            }
        }
    } else {
        rv = Collections.emptyList();
    }
    return rv;
}
Also used : OutNetMessage(net.i2p.router.OutNetMessage) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) MessageSelector(net.i2p.router.MessageSelector)

Example 3 with MessageSelector

use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.

the class TransportImpl method afterSend.

/**
 * The transport is done sending this message.  This is the method that actually
 * does all of the cleanup - firing off jobs, requeueing, updating stats, etc.
 *
 * @param msg message in question
 * @param sendSuccessful true if the peer received it
 * @param msToSend how long it took to transfer the data to the peer
 * @param allowRequeue true if we should try other transports if available
 */
protected void afterSend(OutNetMessage msg, boolean sendSuccessful, boolean allowRequeue, long msToSend) {
    if (msg.getTarget() == null) {
        // Bail out now as it will NPE in a dozen places below.
        return;
    }
    boolean log = false;
    if (sendSuccessful)
        msg.timestamp("afterSend(successful)");
    else
        msg.timestamp("afterSend(failed)");
    if (!sendSuccessful)
        msg.transportFailed(getStyle());
    if (msToSend > 1500) {
        if (_log.shouldLog(Log.INFO))
            _log.info(getStyle() + " afterSend slow: " + (sendSuccessful ? "success " : "FAIL ") + msg.getMessageSize() + " byte " + msg.getMessageType() + ' ' + msg.getMessageId() + " to " + msg.getTarget().getIdentity().calculateHash().toBase64().substring(0, 6) + " took " + msToSend + " ms");
    }
    // if (true)
    // _log.error("(not error) I2NP message sent? " + sendSuccessful + " " + msg.getMessageId() + " after " + msToSend + "/" + msg.getTransmissionTime());
    long lifetime = msg.getLifetime();
    if (lifetime > 3000) {
        int level = Log.INFO;
        if (!sendSuccessful)
            level = Log.DEBUG;
        if (_log.shouldLog(level))
            _log.log(level, getStyle() + " afterSend slow (" + (sendSuccessful ? "success " : "FAIL ") + lifetime + "/" + msToSend + "): " + msg.getMessageSize() + " byte " + msg.getMessageType() + " " + msg.getMessageId() + " from " + _context.routerHash().toBase64().substring(0, 6) + " to " + msg.getTarget().getIdentity().calculateHash().toBase64().substring(0, 6) + ": " + msg.toString());
    } else {
        if (_log.shouldLog(Log.INFO))
            _log.info(getStyle() + " afterSend: " + (sendSuccessful ? "success " : "FAIL ") + msg.getMessageSize() + " byte " + msg.getMessageType() + " " + msg.getMessageId() + " from " + _context.routerHash().toBase64().substring(0, 6) + " to " + msg.getTarget().getIdentity().calculateHash().toBase64().substring(0, 6) + "\n" + msg.toString());
    }
    if (sendSuccessful) {
        if (_log.shouldLog(Log.DEBUG))
            _log.debug(getStyle() + " Sent " + msg.getMessageType() + " successfully to " + msg.getTarget().getIdentity().getHash().toBase64());
        Job j = msg.getOnSendJob();
        if (j != null)
            _context.jobQueue().addJob(j);
        log = true;
        msg.discardData();
    } else {
        if (_log.shouldLog(Log.INFO))
            _log.info(getStyle() + " Failed to send " + msg.getMessageType() + " to " + msg.getTarget().getIdentity().getHash().toBase64() + " (details: " + msg + ')');
        if (msg.getExpiration() < _context.clock().now())
            _context.statManager().addRateData("transport.expiredOnQueueLifetime", lifetime);
        if (allowRequeue) {
            if (((msg.getExpiration() <= 0) || (msg.getExpiration() > _context.clock().now())) && (msg.getMessage() != null)) {
                // this may not be the last transport available - keep going
                _context.outNetMessagePool().add(msg);
            // don't discard the data yet!
            } else {
                if (_log.shouldLog(Log.INFO))
                    _log.info("No more time left (" + new Date(msg.getExpiration()) + ", expiring without sending successfully the " + msg.getMessageType());
                if (msg.getOnFailedSendJob() != null)
                    _context.jobQueue().addJob(msg.getOnFailedSendJob());
                MessageSelector selector = msg.getReplySelector();
                if (selector != null) {
                    _context.messageRegistry().unregisterPending(msg);
                }
                log = true;
                msg.discardData();
            }
        } else {
            MessageSelector selector = msg.getReplySelector();
            if (_log.shouldLog(Log.INFO))
                _log.info("Failed and no requeue allowed for a " + msg.getMessageSize() + " byte " + msg.getMessageType() + " message with selector " + selector, new Exception("fail cause"));
            if (msg.getOnFailedSendJob() != null)
                _context.jobQueue().addJob(msg.getOnFailedSendJob());
            if (msg.getOnFailedReplyJob() != null)
                _context.jobQueue().addJob(msg.getOnFailedReplyJob());
            if (selector != null)
                _context.messageRegistry().unregisterPending(msg);
            log = true;
            msg.discardData();
        }
    }
    if (log) {
    /*
            String type = msg.getMessageType();
            // the udp transport logs some further details
            _context.messageHistory().sendMessage(type, msg.getMessageId(),
                                                  msg.getExpiration(),
                                                  msg.getTarget().getIdentity().getHash(),
                                                  sendSuccessful);
             */
    }
    long now = _context.clock().now();
    long sendTime = now - msg.getSendBegin();
    long allTime = now - msg.getCreated();
    if (allTime > 5 * 1000) {
        if (_log.shouldLog(Log.INFO))
            _log.info("Took too long from preparation to afterSend(ok? " + sendSuccessful + "): " + allTime + "ms/" + sendTime + "ms after failing on: " + msg.getFailedTransports() + " and succeeding on " + getStyle());
        if ((allTime > 60 * 1000) && (sendSuccessful)) {
            // VERY slow
            if (_log.shouldLog(Log.WARN))
                _log.warn("Severe latency? More than a minute slow? " + msg.getMessageType() + " of id " + msg.getMessageId() + " (send begin on " + new Date(msg.getSendBegin()) + " / created on " + new Date(msg.getCreated()) + "): " + msg);
            _context.messageHistory().messageProcessingError(msg.getMessageId(), msg.getMessageType(), "Took too long to send [" + allTime + "ms]");
        }
    }
    if (sendSuccessful) {
        // TODO fix this stat for SSU ticket #698
        _context.statManager().addRateData("transport.sendProcessingTime", lifetime);
        // object churn. 33 ms for NTCP and 788 for SSU, but meaningless due to
        // differences in how it's computed (immediate vs. round trip)
        // _context.statManager().addRateData("transport.sendProcessingTime." + getStyle(), lifetime, 0);
        _context.profileManager().messageSent(msg.getTarget().getIdentity().getHash(), getStyle(), sendTime, msg.getMessageSize());
        _context.statManager().addRateData("transport.sendMessageSize", msg.getMessageSize(), sendTime);
    } else {
        _context.profileManager().messageFailed(msg.getTarget().getIdentity().getHash(), getStyle());
        _context.statManager().addRateData("transport.sendMessageFailureLifetime", lifetime);
    }
}
Also used : MessageSelector(net.i2p.router.MessageSelector) Job(net.i2p.router.Job) Date(java.util.Date) IOException(java.io.IOException)

Example 4 with MessageSelector

use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.

the class OutboundMessageRegistry method unregisterPending.

/**
 *  @param msg may be be null
 */
@SuppressWarnings("unchecked")
public void unregisterPending(OutNetMessage msg) {
    if (msg == null)
        return;
    MessageSelector sel = msg.getReplySelector();
    boolean stillActive = false;
    synchronized (_selectorToMessage) {
        Object old = _selectorToMessage.remove(sel);
        if (old != null) {
            if (old instanceof List) {
                List<OutNetMessage> l = (List<OutNetMessage>) old;
                l.remove(msg);
                if (!l.isEmpty()) {
                    _selectorToMessage.put(sel, l);
                    stillActive = true;
                }
            }
        }
    }
    if (!stillActive)
        synchronized (_selectors) {
            _selectors.remove(sel);
        }
    _activeMessages.remove(msg);
}
Also used : OutNetMessage(net.i2p.router.OutNetMessage) ArrayList(java.util.ArrayList) List(java.util.List) MessageSelector(net.i2p.router.MessageSelector)

Example 5 with MessageSelector

use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.

the class GetBidsJob method fail.

static void fail(RouterContext context, OutNetMessage msg) {
    if (msg.getOnFailedSendJob() != null) {
        context.jobQueue().addJob(msg.getOnFailedSendJob());
    }
    if (msg.getOnFailedReplyJob() != null) {
        context.jobQueue().addJob(msg.getOnFailedReplyJob());
    }
    MessageSelector selector = msg.getReplySelector();
    if (selector != null) {
        context.messageRegistry().unregisterPending(msg);
    }
    context.profileManager().messageFailed(msg.getTarget().getIdentity().getHash());
    msg.discardData();
}
Also used : MessageSelector(net.i2p.router.MessageSelector)

Aggregations

MessageSelector (net.i2p.router.MessageSelector)7 ArrayList (java.util.ArrayList)4 List (java.util.List)3 OutNetMessage (net.i2p.router.OutNetMessage)3 Job (net.i2p.router.Job)2 ReplyJob (net.i2p.router.ReplyJob)2 IOException (java.io.IOException)1 Date (java.util.Date)1 Hash (net.i2p.data.Hash)1 SessionTag (net.i2p.data.SessionTag)1 RandomIterator (net.i2p.router.util.RandomIterator)1