package net.i2p.router.tunnel; import java.util.List; import java.util.Properties; import net.i2p.router.RouterContext; /** * Honor the 'batchFrequency' tunnel pool setting or the 'router.batchFrequency' * router config setting, and track fragmentation. * */ class BatchedRouterPreprocessor extends BatchedPreprocessor { private final TunnelCreatorConfig _config; protected final HopConfig _hopConfig; private final long _sendDelay; /** * How frequently should we flush non-full messages, in milliseconds * This goes in I2CP custom options for the pool. * Only applies to OBGWs. */ public static final String PROP_BATCH_FREQUENCY = "batchFrequency"; /** This goes in router advanced config */ public static final String PROP_ROUTER_BATCH_FREQUENCY = "router.batchFrequency"; /** for client OBGWs only (our data) */ public static final int OB_CLIENT_BATCH_FREQ = 75; /** for exploratory OBGWs only (our tunnel tests and build messages) */ public static final int OB_EXPL_BATCH_FREQ = 100; /** for IBGWs for efficiency (not our data) */ public static final int DEFAULT_BATCH_FREQUENCY = 175; /** for OBGWs */ public BatchedRouterPreprocessor(RouterContext ctx, TunnelCreatorConfig cfg) { super(ctx, getName(cfg)); _config = cfg; _hopConfig = null; _sendDelay = initialSendDelay(); } /** for IBGWs */ public BatchedRouterPreprocessor(RouterContext ctx, HopConfig cfg) { super(ctx, getName(cfg)); _config = null; _hopConfig = cfg; _sendDelay = initialSendDelay(); } private static String getName(HopConfig cfg) { if (cfg == null) return "IB??"; if (cfg.getReceiveTunnel() != null) return "IB " + cfg.getReceiveTunnel().getTunnelId(); else if (cfg.getSendTunnel() != null) return "IB " + cfg.getSendTunnel().getTunnelId(); else return "IB??"; } private static String getName(TunnelCreatorConfig cfg) { if (cfg == null) return "OB??"; if (cfg.getReceiveTunnelId(0) != null) return "OB " + cfg.getReceiveTunnelId(0).getTunnelId(); else if (cfg.getSendTunnelId(0) != null) return "OB " + cfg.getSendTunnelId(0).getTunnelId(); else return "OB??"; } /** * how long should we wait before flushing */ @Override protected long getSendDelay() { return _sendDelay; } /* * Extend the batching time for exploratory OBGWs, they have a lot of small * tunnel test messages, and build messages that don't fit perfectly. * And these are not as delay-sensitive. * * We won't pick up config changes after the preprocessor is created, * but a preprocessor lifetime is only 10 minutes, so just wait... */ private long initialSendDelay() { if (_config != null) { Properties opts = _config.getOptions(); if (opts != null) { String freq = opts.getProperty(PROP_BATCH_FREQUENCY); if (freq != null) { try { return Integer.parseInt(freq); } catch (NumberFormatException nfe) {} } } } int def; if (_config != null) { if (_config.getDestination() != null) def = OB_CLIENT_BATCH_FREQ; else def = OB_EXPL_BATCH_FREQ; } else { def = DEFAULT_BATCH_FREQUENCY; } return _context.getProperty(PROP_ROUTER_BATCH_FREQUENCY, def); } @Override protected void notePreprocessing(long messageId, int numFragments, int totalLength, List<Long> messageIds, String msg) { if (_config != null) _context.messageHistory().fragmentMessage(messageId, numFragments, totalLength, messageIds, _config, msg); else _context.messageHistory().fragmentMessage(messageId, numFragments, totalLength, messageIds, _hopConfig, msg); } }