Changeset c6d1c55


Ignore:
Timestamp:
Jun 19, 2012 11:31:53 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
f8e470c
Parents:
c2137a2 (diff), e383477 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

propagate from branch 'i2p.i2p' (head 9ca94e960929c6af5dea1085105278d2f33217f2)

to branch 'i2p.i2p.zzz.dhtsnark' (head 1f23a71b0fa5169c220f3f21dd705e1fcfbb1b5d)

Files:
1 added
41 edited

Legend:

Unmodified
Added
Removed
  • apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java

    rc2137a2 rc6d1c55  
    326326            BEValue bev = dec.bdecodeMap();
    327327            Map<String, BEValue> map = bev.getMap();
    328             byte[] ids = map.get("added").getBytes();
     328            bev = map.get("added");
     329            if (bev == null)
     330                return;
     331            byte[] ids = bev.getBytes();
    329332            if (ids.length < HASH_LENGTH)
    330333                return;
  • apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java

    rc2137a2 rc6d1c55  
    5656    private int _i2cpPort;
    5757    private final Map<String, String> _opts;
    58     private I2PSocketManager _manager;
     58    private volatile I2PSocketManager _manager;
    5959    private boolean _configured;
     60    private volatile boolean _connecting;
    6061    private final Set<Hash> _shitlist;
    6162    private int _maxUploaders;
     
    201202    synchronized public boolean connect() {
    202203        if (_manager == null) {
     204            _connecting = true;
    203205            // try to find why reconnecting after stop
    204206            if (_log.shouldLog(Log.DEBUG))
     
    240242                opts.setProperty("i2p.streaming.maxConnsPerHour", "20");
    241243            _manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
     244            _connecting = false;
    242245        }
    243246        // FIXME this only instantiates krpc once, left stuck with old manager
     
    255258    public boolean connected() { return _manager != null; }
    256259
     260    /** @since 0.9.1 */
     261    public boolean isConnecting() { return _manager == null && _connecting; }
     262
    257263    /**
    258264     *  For FetchAndAdd
     
    276282        _manager = null;
    277283        _shitlist.clear();
    278         if (mgr != null)
     284        if (mgr != null) {
     285            if (_log.shouldLog(Log.DEBUG))
     286                _log.debug("Disconnecting from I2P", new Exception("I did it"));
    279287            mgr.destroySocketManager();
     288        }
    280289        // this will delete a .torrent file d/l in progress so don't do that...
    281290        FileUtil.rmdir(_tmpDir, false);
  • apps/i2psnark/java/src/org/klomp/snark/PeerState.java

    rc2137a2 rc6d1c55  
    4040  // Interesting and choking describes whether we are interested in or
    4141  // are choking the other side.
    42   boolean interesting = false;
    43   boolean choking = true;
     42  volatile boolean interesting;
     43  volatile boolean choking = true;
    4444
    4545  // Interested and choked describes whether the other side is
    4646  // interested in us or choked us.
    47   boolean interested = false;
    48   boolean choked = true;
     47  volatile boolean interested;
     48  volatile boolean choked = true;
    4949
    5050  /** the pieces the peer has */
  • apps/i2psnark/java/src/org/klomp/snark/Snark.java

    rc2137a2 rc6d1c55  
    251251  private final CompleteListener completeListener;
    252252  private boolean stopped;
     253  private boolean starting;
    253254  private byte[] id;
    254255  private byte[] infoHash;
     
    510511
    511512  /**
    512    * Start up contacting peers and querying the tracker
     513   * Start up contacting peers and querying the tracker.
     514   * Blocks if tunnel is not yet open.
    513515   */
    514   public void startTorrent() {
     516  public synchronized void startTorrent() {
     517      starting = true;
     518      try {
     519          x_startTorrent();
     520      } finally {
     521          starting = false;
     522      }
     523  }
     524
     525  private void x_startTorrent() {
    515526    boolean ok = _util.connect();
    516527    if (!ok) fatal("Unable to connect to I2P");
     
    573584    }
    574585  }
     586
    575587  /**
    576588   * Stop contacting the tracker and talking with peers
    577589   */
    578590  public void stopTorrent() {
     591      stopTorrent(false);
     592  }
     593
     594  /**
     595   * Stop contacting the tracker and talking with peers
     596   * @param fast if true, limit the life of the unannounce threads
     597   * @since 0.9.1
     598   */
     599  public synchronized void stopTorrent(boolean fast) {
    579600    stopped = true;
    580601    TrackerClient tc = trackerclient;
    581602    if (tc != null)
    582         tc.halt();
     603        tc.halt(fast);
    583604    PeerCoordinator pc = coordinator;
    584605    if (pc != null)
     
    669690    public boolean isStopped() {
    670691        return stopped;
     692    }
     693
     694    /**
     695     *  Startup in progress.
     696     *  @since 0.9.1
     697     */
     698    public boolean isStarting() {
     699        return starting && stopped;
     700    }
     701
     702    /**
     703     *  Set startup in progress.
     704     *  @since 0.9.1
     705     */
     706    public void setStarting() {
     707        starting = true;
    671708    }
    672709
  • apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java

    rc2137a2 rc6d1c55  
    3535import net.i2p.util.SecureDirectory;
    3636import net.i2p.util.SecureFileOutputStream;
     37import net.i2p.util.SimpleScheduler;
     38import net.i2p.util.SimpleTimer;
    3739
    3840/**
     
    6062    private Thread _monitor;
    6163    private volatile boolean _running;
     64    private volatile boolean _stopping;
    6265    private final Map<String, Tracker> _trackerMap;
    6366   
     
    147150        _monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
    148151        _monitor.start();
    149         _context.addShutdownTask(new SnarkManagerShutdown());
    150     }
    151 
     152        // Not required, Jetty has a shutdown hook
     153        //_context.addShutdownTask(new SnarkManagerShutdown());
     154    }
     155
     156    /*
     157     *  Called by the webapp at Jetty shutdown.
     158     *  Stops all torrents. Does not close the tunnel, so the announces have a chance.
     159     *  Fix this so an individual webaapp stop will close the tunnel.
     160     *  Runs inline.
     161     */
    152162    public void stop() {
    153163        _running = false;
    154164        _monitor.interrupt();
    155165        _connectionAcceptor.halt();
    156         (new SnarkManagerShutdown()).run();
    157     }
    158    
     166        stopAllTorrents(true);
     167    }
     168   
     169    /** @since 0.9.1 */
     170    public boolean isStopping() { return _stopping; }
     171
    159172    /** hook to I2PSnarkUtil for the servlet */
    160173    public I2PSnarkUtil util() { return _util; }
     
    872885            addMessage(_("Fetching {0}", name));
    873886            boolean haveSavedPeers = false;
    874             if ((!util().connected()) && !haveSavedPeers) {
     887            if ((_util.connected()) && !haveSavedPeers) {
    875888                addMessage(_("We have no saved peers and no other torrents are running. " +
    876889                             "Fetch of {0} will not succeed until you start another torrent.", name));
     
    16041617    }
    16051618
    1606     private class SnarkManagerShutdown extends I2PAppThread {
    1607         @Override
     1619    /**
     1620     *  If not connected, thread it, otherwise inline
     1621     *  @since 0.9.1
     1622     */
     1623    public void startTorrent(byte[] infoHash) {
     1624        for (Snark snark : _snarks.values()) {
     1625            if (DataHelper.eq(infoHash, snark.getInfoHash())) {
     1626                if (snark.isStarting() || !snark.isStopped()) {
     1627                    addMessage("Torrent already started");
     1628                    return;
     1629                }
     1630                boolean connected = _util.connected();
     1631                if ((!connected) && !_util.isConnecting())
     1632                    addMessage(_("Opening the I2P tunnel"));
     1633                addMessage(_("Starting up torrent {0}", snark.getBaseName()));
     1634                if (connected) {
     1635                    snark.startTorrent();
     1636                } else {
     1637                    // mark it for the UI
     1638                    snark.setStarting();
     1639                    (new I2PAppThread(new ThreadedStarter(snark), "TorrentStarter", true)).start();
     1640                    try { Thread.sleep(200); } catch (InterruptedException ie) {}
     1641                }
     1642                return;
     1643            }
     1644        }
     1645        addMessage("Torrent not found?");
     1646    }
     1647
     1648    /**
     1649     *  If not connected, thread it, otherwise inline
     1650     *  @since 0.9.1
     1651     */
     1652    public void startAllTorrents() {
     1653        if (_util.connected()) {
     1654            startAll();
     1655        } else {
     1656            addMessage(_("Opening the I2P tunnel and starting all torrents."));
     1657            for (Snark snark : _snarks.values()) {
     1658                // mark it for the UI
     1659                snark.setStarting();
     1660            }
     1661            (new I2PAppThread(new ThreadedStarter(null), "TorrentStarterAll", true)).start();
     1662            try { Thread.sleep(200); } catch (InterruptedException ie) {}
     1663        }
     1664    }
     1665
     1666    /**
     1667     *  Use null constructor param for all
     1668     *  @since 0.9.1
     1669     */
     1670    private class ThreadedStarter implements Runnable {
     1671        private final Snark snark;
     1672        public ThreadedStarter(Snark s) { snark = s; }
    16081673        public void run() {
    1609             Set names = listTorrentFiles();
    1610             int running = 0;
    1611             for (Iterator iter = names.iterator(); iter.hasNext(); ) {
    1612                 Snark snark = getTorrent((String)iter.next());
    1613                 if (snark != null && !snark.isStopped()) {
    1614                     snark.stopTorrent();
    1615                     try { Thread.sleep(50); } catch (InterruptedException ie) {}
    1616                 }
    1617             }
    1618         }
    1619     }
    1620 
     1674            if (snark != null) {
     1675                if (snark.isStopped())
     1676                    snark.startTorrent();
     1677            } else {
     1678                startAll();
     1679            }
     1680        }
     1681    }
     1682
     1683    /**
     1684     *  Inline
     1685     *  @since 0.9.1
     1686     */
     1687    private void startAll() {
     1688        for (Snark snark : _snarks.values()) {
     1689            if (snark.isStopped())
     1690                snark.startTorrent();
     1691        }
     1692    }
     1693
     1694    /**
     1695     * Stop all running torrents, and close the tunnel after a delay
     1696     * to allow for announces.
     1697     * If called at router shutdown via Jetty shutdown hook -> webapp destroy() -> stop(),
     1698     * the tunnel won't actually be closed as the SimpleScheduler is already shutdown
     1699     * or will be soon, so we delay a few seconds inline.
     1700     * @param finalShutdown if true, sleep at the end if any torrents were running
     1701     * @since 0.9.1
     1702     */
     1703    public void stopAllTorrents(boolean finalShutdown) {
     1704        _stopping = true;
     1705        if (finalShutdown && _log.shouldLog(Log.WARN))
     1706            _log.warn("SnarkManager final shutdown");
     1707        int count = 0;
     1708        for (Snark snark : _snarks.values()) {
     1709            if (!snark.isStopped()) {
     1710                if (count == 0)
     1711                    addMessage(_("Stopping all torrents and closing the I2P tunnel."));
     1712                count++;
     1713                if (finalShutdown)
     1714                    snark.stopTorrent(true);
     1715                else
     1716                    stopTorrent(snark, false);
     1717                // Throttle since every unannounce is now threaded.
     1718                // How to do this without creating a ton of threads?
     1719                try { Thread.sleep(20); } catch (InterruptedException ie) {}
     1720            }
     1721        }
     1722        if (_util.connected()) {
     1723            if (count > 0) {
     1724                // Schedule this even for final shutdown, as there's a chance
     1725                // that it's just this webapp that is stopping.
     1726                SimpleScheduler.getInstance().addEvent(new Disconnector(), 60*1000);
     1727                addMessage(_("Closing I2P tunnel after notifying trackers."));
     1728                if (finalShutdown) {
     1729                    try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
     1730                }
     1731            } else {
     1732                _util.disconnect();
     1733                _stopping = false;
     1734                addMessage(_("I2P tunnel closed."));
     1735            }
     1736        }
     1737    }
     1738
     1739    /** @since 0.9.1 */
     1740    private class Disconnector implements SimpleTimer.TimedEvent {
     1741        public void timeReached() {
     1742            if (_util.connected()) {
     1743                _util.disconnect();
     1744                _stopping = false;
     1745                addMessage(_("I2P tunnel closed."));
     1746            }
     1747        }
     1748    }
     1749   
    16211750    /**
    16221751     *  ignore case, current locale
  • apps/i2psnark/java/src/org/klomp/snark/SnarkShutdown.java

    rc2137a2 rc6d1c55  
    2727/**
    2828 * Makes sure everything ends correctly when shutting down.
     29 * @deprecated unused
    2930 */
    3031public class SnarkShutdown extends I2PAppThread
     
    6263    //Snark.debug("Halting TrackerClient...", Snark.INFO);
    6364    if (trackerclient != null)
    64       trackerclient.halt();
     65      trackerclient.halt(true);
    6566
    6667    //Snark.debug("Halting PeerCoordinator...", Snark.INFO);
  • apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java

    rc2137a2 rc6d1c55  
    2929import java.util.ArrayList;
    3030import java.util.Collections;
     31import java.util.Date;
    3132import java.util.Iterator;
    3233import java.util.List;
     
    9899  private volatile boolean runStarted;
    99100  private volatile  int consecutiveFails;
     101  private volatile boolean _fastUnannounce;
    100102
    101103  private final List<Tracker> trackers;
     
    135137      consecutiveFails = 0;
    136138      runStarted = false;
     139      _fastUnannounce = false;
    137140      _thread = new I2PAppThread(this, _threadName + " #" + (++_runCount), true);
    138141      _thread.start();
     
    145148  /**
    146149   * Interrupts this Thread to stop it.
    147    */
    148   public synchronized void halt() {
     150   * @param fast if true, limit the life of the unannounce threads
     151   */
     152  public synchronized void halt(boolean fast) {
    149153    boolean wasStopped = stop;
    150154    if (wasStopped) {
     
    169173        t.interrupt();
    170174    }
     175    _fastUnannounce = true;
    171176    if (!wasStopped)
    172177        unannounce();
     
    237242   *  @since 0.9.1
    238243   */
    239   public void setup() {
     244  private void setup() {
    240245    // Construct the list of trackers for this torrent,
    241246    // starting with the primary one listed in the metainfo,
     
    416421                    }
    417422                  }
     423              } else {
     424                  _util.debug("Not announcing to " + tr.announce + " last announce was " +
     425                               new Date(tr.lastRequestTime) + " interval is " + DataHelper.formatDuration(tr.interval), Snark.INFO);
    418426              }
    419427              if ((!tr.stop) && maxSeenPeers < tr.seenPeers)
     
    440448                    }
    441449                }
     450            } else {
     451                _util.debug("Not getting PEX peers", Snark.INFO);
    442452            }
    443453
     
    477487                    }
    478488                }
     489            } else {
     490                _util.debug("Not getting DHT peers", Snark.INFO);
    479491            }
    480492
     
    535547              tr.started && (!tr.stop) && tr.trackerProblems == null) {
    536548              try {
    537                   (new I2PAppThread(new Unannouncer(tr), _threadName + " Unannounce " + (++i), true)).start();
     549                  (new I2PAppThread(new Unannouncer(tr), _threadName + " U" + (++i), true)).start();
    538550              } catch (OutOfMemoryError oom) {
    539551                  // probably ran out of threads, ignore
     
    612624     
    613625    tr.lastRequestTime = System.currentTimeMillis();
    614     // Don't wait for a response to stopped.
    615     File fetched = _util.get(s, true, event.equals(STOPPED_EVENT) ? -1 : 0);
     626    // Don't wait for a response to stopped when shutting down
     627    boolean fast = _fastUnannounce && event.equals(STOPPED_EVENT);
     628    File fetched = _util.get(s, true, fast ? -1 : 0);
    616629    if (fetched == null) {
    617630        throw new IOException("Error fetching " + s);
     
    672685   *  @since 0.7.12
    673686   */
    674   static boolean isValidAnnounce(String ann) {
     687  public static boolean isValidAnnounce(String ann) {
    675688    URL url;
    676689    try {
  • apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java

    rc2137a2 rc6d1c55  
    7575        _log = _context.logManager().getLog(I2PSnarkServlet.class);
    7676        _nonce = _context.random().nextLong();
     77        // FIXME instantiate new one every time
    7778        _manager = SnarkManager.instance();
    7879        String configFile = _context.getProperty(PROP_CONFIG_FILE);
     
    323324        String peerParam = req.getParameter("p");
    324325
    325         List snarks = getSortedSnarks(req);
     326        List<Snark> snarks = getSortedSnarks(req);
    326327        boolean isForm = _manager.util().connected() || !snarks.isEmpty();
    327328        if (isForm) {
     
    408409
    409410        boolean noThinsp = isDegraded || (ua != null && ua.startsWith("Opera"));
    410         if (_manager.util().connected()) {
     411        if (_manager.isStopping()) {
     412            out.write("&nbsp;");
     413        } else if (_manager.util().connected()) {
    411414            if (isDegraded)
    412415                out.write("<a href=\"/i2psnark/?action=StopAll&amp;nonce=" + _nonce + "\"><img title=\"");
     
    422425            if (isDegraded)
    423426                out.write("</a>");
    424         } else if (!snarks.isEmpty()) {
     427        } else if ((!_manager.util().isConnecting()) && !snarks.isEmpty()) {
    425428            if (isDegraded)
    426429                out.write("<a href=\"/i2psnark/?action=StartAll&amp;nonce=" + _nonce + "\"><img title=\"");
     
    573576                byte infoHash[] = Base64.decode(torrent);
    574577                if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1
    575                     for (String name : _manager.listTorrentFiles()) {
    576                         Snark snark = _manager.getTorrent(name);
    577                         if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
    578                             snark.startTorrent();
    579                             _manager.addMessage(_("Starting up torrent {0}", snark.getBaseName()));
    580                             break;
    581                         }
    582                     }
     578                    _manager.startTorrent(infoHash);
    583579                }
    584580            }
     
    645641                                // each of those lists just contain a single file afaict...
    646642                                File df = Storage.getFileFromNames(f, files.get(i));
    647                                 if (df.delete())
    648                                     _manager.addMessage(_("Data file deleted: {0}", df.getAbsolutePath()));
    649                                 else
     643                                if (df.delete()) {
     644                                    //_manager.addMessage(_("Data file deleted: {0}", df.getAbsolutePath()));
     645                                } else {
    650646                                    _manager.addMessage(_("Data file could not be deleted: {0}", df.getAbsolutePath()));
     647                                }
    651648                            }
    652649                            // step 2 make Set of dirs with reverse sort
     
    660657                            for (File df : dirs) {
    661658                                if (df.delete()) {
    662                                     _manager.addMessage(_("Data dir deleted: {0}", df.getAbsolutePath()));
    663                                 } else if (_log.shouldLog(Log.WARN)) {
    664                                     _log.warn("Could not delete dir " + df);
     659                                    //_manager.addMessage(_("Data dir deleted: {0}", df.getAbsolutePath()));
     660                                } else {
     661                                    _manager.addMessage(_("Directory could not be deleted: {0}", df.getAbsolutePath()));
     662                                    if (_log.shouldLog(Log.WARN))
     663                                        _log.warn("Could not delete dir " + df);
    665664                                }
    666665                            }
    667666                            // step 4 delete base
    668667                            if (f.delete()) {
    669                                 _manager.addMessage(_("Data dir deleted: {0}", f.getAbsolutePath()));
    670                             } else if (_log.shouldLog(Log.WARN)) {
    671                                 _log.warn("Could not delete dir " + f);
     668                                _manager.addMessage(_("Directory deleted: {0}", f.getAbsolutePath()));
     669                            } else {
     670                                _manager.addMessage(_("Directory could not be deleted: {0}", f.getAbsolutePath()));
     671                                if (_log.shouldLog(Log.WARN))
     672                                    _log.warn("Could not delete dir " + f);
    672673                            }
    673674                            break;
     
    741742            }
    742743        } else if ("StopAll".equals(action)) {
    743             _manager.addMessage(_("Stopping all torrents and closing the I2P tunnel."));
    744             List snarks = getSortedSnarks(req);
    745             for (int i = 0; i < snarks.size(); i++) {
    746                 Snark snark = (Snark)snarks.get(i);
    747                 if (!snark.isStopped()) {
    748                     _manager.stopTorrent(snark, false);
    749                     try { Thread.sleep(50); } catch (InterruptedException ie) {}
    750                 }
    751             }
    752             if (_manager.util().connected()) {
    753                 // Give the stopped announces time to get out
    754                 try { Thread.sleep(2000); } catch (InterruptedException ie) {}
    755                 _manager.util().disconnect();
    756                 _manager.addMessage(_("I2P tunnel closed."));
    757             }
     744            _manager.stopAllTorrents(false);
    758745        } else if ("StartAll".equals(action)) {
    759             _manager.addMessage(_("Opening the I2P tunnel and starting all torrents."));
    760             List snarks = getSortedSnarks(req);
    761             for (int i = 0; i < snarks.size(); i++) {
    762                 Snark snark = (Snark)snarks.get(i);
    763                 if (snark.isStopped())
    764                     snark.startTorrent();
    765             }
     746            _manager.startAllTorrents();
    766747        } else if ("Clear".equals(action)) {
    767748            _manager.clearMessages();
     
    827808                hurl = hurl.trim();
    828809                aurl = aurl.trim().replace("=", "&#61;");
    829                 if (name.length() > 0 && hurl.startsWith("http://") && aurl.startsWith("http://")) {
     810                if (name.length() > 0 && hurl.startsWith("http://") && TrackerClient.isValidAnnounce(aurl)) {
    830811                    Map<String, Tracker> trackers = _manager.getTrackerMap();
    831812                    trackers.put(name, new Tracker(name, aurl, hurl));
     
    999980                "<br>" + err;
    1000981            }
     982        } else if (snark.isStarting()) {
     983            statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Starting");
    1001984        } else if (remaining == 0 || needed == 0) {  // < 0 means no meta size yet
    1002985            // partial complete or seeding
     
    11511134            parameters = parameters + "&p=1";
    11521135        if (isRunning) {
     1136            // Stop Button
    11531137            if (isDegraded)
    11541138                out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
     
    11611145            if (isDegraded)
    11621146                out.write("</a>");
    1163         } else {
     1147        } else if (!snark.isStarting()) {
     1148            if (!_manager.isStopping()) {
     1149                // Start Button
    11641150                // This works in Opera but it's displayed a little differently, so use noThinsp here too so all 3 icons are consistent
    11651151                if (noThinsp)
     
    11731159                if (isDegraded)
    11741160                    out.write("</a>");
    1175 
     1161            }
    11761162            if (isValid) {
     1163                // Remove Button
    11771164                // Doesnt work with Opera so use noThinsp instead of isDegraded
    11781165                if (noThinsp)
     
    11941181            }
    11951182
     1183            // Delete Button
    11961184            // Doesnt work with Opera so use noThinsp instead of isDegraded
    11971185            if (noThinsp)
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java

    rc2137a2 rc6d1c55  
    4747import java.util.List;
    4848import java.util.Locale;
     49import java.util.Map;
    4950import java.util.Properties;
    5051import java.util.Set;
     
    193194    }
    194195
    195     /** @return non-null */
     196    /** @return A copy, non-null */
    196197    List<I2PSession> getSessions() {
    197198            return new ArrayList(_sessions);
     
    208209    }
    209210   
     211    /**
     212     *  Generic options used for clients and servers.
     213     *  NOT a copy, Do NOT modify for per-connection options, make a copy.
     214     *  @return NOT a copy, do NOT modify for per-connection options
     215     */
    210216    public Properties getClientOptions() { return _clientOptions; }
    211217   
     
    327333    /**
    328334     * Configure the extra I2CP options to use in any subsequent I2CP sessions.
     335     * Generic options used for clients and servers
    329336     * Usage: "clientoptions[ key=value]*" . 
    330337     *
    331338     * Sets the event "clientoptions_onResult" = "ok" after completion.
     339     *
     340     * Deprecated To be made private, use setClientOptions().
     341     * This does NOT update a running TunnelTask.
    332342     *
    333343     * @param args each args[i] is a key=value pair to add to the options
     
    344354                _clientOptions.setProperty(key, val);
    345355            }
     356        }
     357        notifyEvent("clientoptions_onResult", "ok");
     358    }
     359
     360    /**
     361     * Generic options used for clients and servers.
     362     * This DOES update a running TunnelTask, but NOT the session.
     363     * A more efficient runClientOptions().
     364     *
     365     * @param opts non-null
     366     * @since 0.9.1
     367     */
     368    public void setClientOptions(Properties opts) {
     369        for (Iterator iter = _clientOptions.keySet().iterator(); iter.hasNext();) {
     370            Object key = iter.next();
     371            if (!opts.containsKey(key))
     372                iter.remove();
     373        }
     374        _clientOptions.putAll(opts);
     375        for (I2PTunnelTask task : tasks) {
     376            task.optionsUpdated(this);
    346377        }
    347378        notifyEvent("clientoptions_onResult", "ok");
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java

    rc2137a2 rc6d1c55  
    472472
    473473    /**
    474      * create the default options (using the default timeout, etc)
    475      *
     474     * Create the default options (using the default timeout, etc).
     475     * Warning, this does not make a copy of I2PTunnel's client options,
     476     * it modifies them directly.
    476477     */
    477478    protected I2PSocketOptions getDefaultOptions() {
     
    484485   
    485486    /**
    486      * create the default options (using the default timeout, etc)
    487      *
     487     * Create the default options (using the default timeout, etc).
     488     * Warning, this does not make a copy of I2PTunnel's client options,
     489     * it modifies them directly.
     490     * Do not use overrides for per-socket options.
    488491     */
    489492    protected I2PSocketOptions getDefaultOptions(Properties overrides) {
     
    494497            opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
    495498        return opts;
     499    }
     500
     501    /**
     502     *  Update the I2PSocketManager.
     503     *
     504     *  @since 0.9.1
     505     */
     506    @Override
     507    public void optionsUpdated(I2PTunnel tunnel) {
     508        if (getTunnel() != tunnel)
     509            return;
     510        I2PSocketManager sm = _ownDest ? sockMgr : socketManager;
     511        if (sm == null)
     512            return;
     513        Properties props = tunnel.getClientOptions();
     514        sm.setDefaultOptions(sockMgr.buildOptions(props));
    496515    }
    497516
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java

    rc2137a2 rc6d1c55  
    133133
    134134    /**
    135      * create the default options (using the default timeout, etc)
    136      *
     135     * Create the default options (using the default timeout, etc).
     136     * Warning, this does not make a copy of I2PTunnel's client options,
     137     * it modifies them directly.
    137138     */
    138139    @Override
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java

    rc2137a2 rc6d1c55  
    226226
    227227    /**
    228      * create the default options (using the default timeout, etc)
     228     * Create the default options (using the default timeout, etc).
     229     * Warning, this does not make a copy of I2PTunnel's client options,
     230     * it modifies them directly.
    229231     * unused?
    230232     */
     
    245247
    246248    /**
    247      * create the default options (using the default timeout, etc)
    248      *
     249     * Create the default options (using the default timeout, etc).
     250     * Warning, this does not make a copy of I2PTunnel's client options,
     251     * it modifies them directly.
     252     * Do not use overrides for per-socket options.
    249253     */
    250254    @Override
     
    331335            String userAgent = null;
    332336            String authorization = null;
     337            int remotePort = 0;
    333338            while((line = reader.readLine(method)) != null) {
    334339                line = line.trim();
     
    487492                        host = getHostName(destination);
    488493
    489                         if(requestURI.getPort() >= 0) {
    490                             // TODO support I2P ports someday
    491                             //if (port >= 0)
    492                             //    host = host + ':' + port;
     494                        int rPort = requestURI.getPort();
     495                        if (rPort > 0) {
     496                            // Save it to put in the I2PSocketOptions,
     497                            remotePort = rPort;
     498                         /********
     499                            // but strip it from the URL
    493500                            if(_log.shouldLog(Log.WARN)) {
    494501                                _log.warn(getPrefix(requestId) + "Removing port from [" + request + "]");
     
    501508                                break;
    502509                            }
     510                          ******/
     511                        } else {
     512                            remotePort = 80;
    503513                        }
    504514
     
    960970            }
    961971
    962             Properties opts = new Properties();
     972            //Properties opts = new Properties();
    963973            //opts.setProperty("i2p.streaming.inactivityTimeout", ""+120*1000);
    964974            // 1 == disconnect.  see ConnectionOptions in the new streaming lib, which i
    965975            // dont want to hard link to here
    966976            //opts.setProperty("i2p.streaming.inactivityTimeoutAction", ""+1);
    967             I2PSocket i2ps = createI2PSocket(clientDest, getDefaultOptions(opts));
     977            //I2PSocketOptions sktOpts = getDefaultOptions(opts);
     978            I2PSocketOptions sktOpts = getDefaultOptions();
     979            if (remotePort > 0)
     980                sktOpts.setPort(remotePort);
     981            I2PSocket i2ps = createI2PSocket(clientDest, sktOpts);
    968982            byte[] data = newRequest.toString().getBytes("ISO-8859-1");
    969983            Runnable onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
     
    11751189    public static final String DEFAULT_JUMP_SERVERS =
    11761190                               "http://i2host.i2p/cgi-bin/i2hostjump?," +
    1177             "http://stats.i2p/cgi-bin/jump.cgi?a=," +
    1178             "http://i2jump.i2p/";
     1191            "http://stats.i2p/cgi-bin/jump.cgi?a=";
     1192            //"http://i2jump.i2p/";
    11791193
    11801194    /**
     
    12081222                    while(tok.hasMoreTokens()) {
    12091223                        String jurl = tok.nextToken();
    1210                         if(!jurl.startsWith("http://")) {
     1224                        String jumphost;
     1225                        try {
     1226                            URI jURI = new URI(jurl);
     1227                            String proto = jURI.getScheme();
     1228                            jumphost = jURI.getHost();
     1229                            if (proto == null || jumphost == null ||
     1230                                !proto.toLowerCase(Locale.US).equals("http"))
     1231                                continue;
     1232                            jumphost = jumphost.toLowerCase(Locale.US);
     1233                            if (!jumphost.endsWith(".i2p"))
     1234                                continue;
     1235                        } catch(URISyntaxException use) {
    12111236                            continue;
    12121237                        }
    12131238                        // Skip jump servers we don't know
    1214                         String jumphost = jurl.substring(7);  // "http://"
    1215                         jumphost = jumphost.substring(0, jumphost.indexOf('/'));
    1216                         if(!jumphost.endsWith(".i2p")) {
    1217                             continue;
    1218                         }
    12191239                        if(!jumphost.endsWith(".b32.i2p")) {
    12201240                            Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(jumphost);
     
    12281248                        out.write(uri.getBytes());
    12291249                        out.write("\">".getBytes());
    1230                         out.write(jurl.substring(7).getBytes());
    1231                         out.write(uri.getBytes());
     1250                        // Translators: parameter is a host name
     1251                        out.write(_("{0} jump service", jumphost).getBytes());
    12321252                        out.write("</a>\n".getBytes());
    12331253                    }
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java

    rc2137a2 rc6d1c55  
    7878
    7979    private void setupI2PTunnelHTTPServer(String spoofHost) {
    80         _spoofHost = spoofHost;
     80        _spoofHost = (spoofHost != null && spoofHost.trim().length() > 0) ? spoofHost.trim() : null;
    8181        getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 });
    8282        getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000 });
     
    9797    @Override
    9898    protected void blockingHandle(I2PSocket socket) {
     99        if (_log.shouldLog(Log.INFO))
     100            _log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() +
     101                      " from: " + socket.getPeerDestination().calculateHash() + " port " + socket.getPort());
    99102        long afterAccept = getTunnel().getContext().clock().now();
    100103        long afterSocket = -1;
     
    116119            addEntry(headers, DEST64_HEADER, socket.getPeerDestination().toBase64());
    117120
    118             if ( (_spoofHost != null) && (_spoofHost.trim().length() > 0) )
    119                 setEntry(headers, "Host", _spoofHost);
     121            // Port-specific spoofhost
     122            Properties opts = getTunnel().getClientOptions();
     123            String spoofHost;
     124            int ourPort = socket.getLocalPort();
     125            if (ourPort != 80 && ourPort > 0 && ourPort <= 65535 && opts != null) {
     126                String portSpoof = opts.getProperty("spoofedHost." + ourPort);
     127                if (portSpoof != null)
     128                    spoofHost = portSpoof.trim();
     129                else
     130                    spoofHost = _spoofHost;
     131            } else {
     132                spoofHost = _spoofHost;
     133            }
     134            if (spoofHost != null)
     135                setEntry(headers, "Host", spoofHost);
    120136            setEntry(headers, "Connection", "close");
    121137            // we keep the enc sent by the browser before clobbering it, since it may have
     
    135151            // server, reads the response headers, rewriting to include Content-encoding: x-i2p-gzip
    136152            // if it was one of the Accept-encoding: values, and gzip the payload       
    137             Properties opts = getTunnel().getClientOptions();
    138153            boolean allowGZIP = true;
    139154            if (opts != null) {
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java

    rc2137a2 rc6d1c55  
    112112    @Override
    113113    protected void blockingHandle(I2PSocket socket) {
     114        if (_log.shouldLog(Log.INFO))
     115            _log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() +
     116                      " from: " + socket.getPeerDestination().calculateHash() + " port " + socket.getPort());
    114117        try {
    115118                        String modifiedRegistration;
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java

    rc2137a2 rc6d1c55  
    294294            return true;
    295295        }
     296    }
     297
     298    /**
     299     *  Update the I2PSocketManager.
     300     *
     301     *  @since 0.9.1
     302     */
     303    @Override
     304    public void optionsUpdated(I2PTunnel tunnel) {
     305        if (getTunnel() != tunnel || sockMgr == null)
     306            return;
     307        Properties props = tunnel.getClientOptions();
     308        sockMgr.setDefaultOptions(sockMgr.buildOptions(props));
    296309    }
    297310
     
    409422    protected void blockingHandle(I2PSocket socket) {
    410423        if (_log.shouldLog(Log.INFO))
    411             _log.info("Incoming connection to '" + toString() + "' from: " + socket.getPeerDestination().calculateHash().toBase64());
     424            _log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() +
     425                      " from: " + socket.getPeerDestination().calculateHash() + " port " + socket.getPort());
    412426        long afterAccept = I2PAppContext.getGlobalContext().clock().now();
    413427        long afterSocket = -1;
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelTask.java

    rc2137a2 rc6d1c55  
    6060
    6161    /**
     62     *  Notify the task that I2PTunnel's options have been updated.
     63     *  Extending classes should override and call I2PTunnel.getClientOptions(),
     64     *  then update the I2PSocketManager.
     65     *
     66     *  @since 0.9.1
     67     */
     68    public void optionsUpdated(I2PTunnel tunnel) {}
     69
     70    /**
    6271     *  For tasks that don't call I2PTunnel.addSession() directly
    6372     *  @since 0.8.13
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java

    rc2137a2 rc6d1c55  
    55import java.io.IOException;
    66import java.util.ArrayList;
     7import java.util.HashMap;
    78import java.util.Iterator;
    89import java.util.List;
     10import java.util.Map;
    911import java.util.Properties;
    1012import java.util.Random;
     
    327329                TunnelControllerGroup.getInstance().release(this, s);
    328330            }
     331            // _sessions.clear() ????
    329332        } else {
    330333            if (_log.shouldLog(Log.WARN))
     
    385388    }
    386389   
    387     private void setSessionOptions() {
    388         List opts = new ArrayList();
    389         for (Iterator iter = _config.keySet().iterator(); iter.hasNext(); ) {
    390             String key = (String)iter.next();
    391             String val = _config.getProperty(key);
     390    /**
     391     *  These are the ones stored with a prefix of "option."
     392     *
     393     *  @return keys with the "option." prefix stripped
     394     *  @since 0.9.1 Much better than getClientOptions()
     395     */
     396    public Properties getClientOptionProps() {
     397        Properties opts = new Properties();
     398        for (Map.Entry e : _config.entrySet()) {
     399            String key = (String) e.getKey();
    392400            if (key.startsWith("option.")) {
    393401                key = key.substring("option.".length());
    394                 opts.add(key + "=" + val);
    395             }
    396         }
    397         String args[] = new String[opts.size()];
    398         for (int i = 0; i < opts.size(); i++)
    399             args[i] = (String)opts.get(i);
    400         _tunnel.runClientOptions(args, this);
     402                String val = (String) e.getValue();
     403                opts.setProperty(key, val);
     404            }
     405        }
     406        return opts;
     407    }
     408
     409    private void setSessionOptions() {
     410        _tunnel.setClientOptions(getClientOptionProps());
    401411    }
    402412   
     
    432442    }
    433443   
     444    /**
     445     *  As of 0.9.1, updates the options on an existing session
     446     */
    434447    public void setConfig(Properties config, String prefix) {
    435448        Properties props = new Properties();
    436         for (Iterator iter = config.keySet().iterator(); iter.hasNext(); ) {
    437             String key = (String)iter.next();
    438             String val = config.getProperty(key);
     449        for (Map.Entry e : config.entrySet()) {
     450            String key = (String) e.getKey();
    439451            if (key.startsWith(prefix)) {
    440452                key = key.substring(prefix.length());
     453                String val = (String) e.getValue();
    441454                props.setProperty(key, val);
    442                 if (_log.shouldLog(Log.DEBUG))
    443                     _log.debug("Set prop [" + key + "] to [" + val + "]");
    444455            }
    445456        }
    446457        _config = props;
    447     }
     458        // tell i2ptunnel, who will tell the TunnelTask, who will tell the SocketManager
     459        setSessionOptions();
     460        if (_running && _sessions != null) {
     461            for (I2PSession s : _sessions) {
     462                // tell the router via the session
     463                if (!s.isClosed()) {
     464                    s.updateOptions(_tunnel.getClientOptions());
     465                }
     466            }
     467        }
     468    }
     469
    448470    public Properties getConfig(String prefix) {
    449471        Properties rv = new Properties();
    450         for (Iterator iter = _config.keySet().iterator(); iter.hasNext(); ) {
    451             String key = (String)iter.next();
    452             String val = _config.getProperty(key);
     472        for (Map.Entry e : _config.entrySet()) {
     473            String key = (String) e.getKey();
     474            String val = (String) e.getValue();
    453475            rv.setProperty(prefix + key, val);
    454476        }
     
    461483    public String getI2CPHost() { return _config.getProperty("i2cpHost"); }
    462484    public String getI2CPPort() { return _config.getProperty("i2cpPort"); }
     485
     486    /**
     487     *  These are the ones with a prefix of "option."
     488     *
     489     *  @return one big string of "key=val key=val ..."
     490     *  @deprecated why would you want this? Use getClientOptionProps() instead
     491     */
    463492    public String getClientOptions() {
    464493        StringBuilder opts = new StringBuilder(64);
    465         for (Iterator iter = _config.keySet().iterator(); iter.hasNext(); ) {
    466             String key = (String)iter.next();
    467             String val = _config.getProperty(key);
     494        for (Map.Entry e : _config.entrySet()) {
     495            String key = (String) e.getKey();
    468496            if (key.startsWith("option.")) {
    469497                key = key.substring("option.".length());
     498                String val = (String) e.getValue();
    470499                if (opts.length() > 0) opts.append(' ');
    471500                opts.append(key).append('=').append(val);
     
    474503        return opts.toString();
    475504    }
     505
    476506    public String getListenOnInterface() { return _config.getProperty("interface"); }
    477507    public String getTargetHost() { return _config.getProperty("targetHost"); }
     
    487517    public boolean getStartOnLoad() { return Boolean.valueOf(_config.getProperty("startOnLoad", "true")).booleanValue(); }
    488518    public boolean getPersistentClientKey() { return Boolean.valueOf(_config.getProperty("option.persistentClientKey")).booleanValue(); }
     519
    489520    public String getMyDestination() {
    490521        if (_tunnel != null) {
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java

    rc2137a2 rc6d1c55  
    1616import java.util.List;
    1717import java.util.Locale;
     18import java.util.Properties;
    1819
    1920import net.i2p.I2PAppContext;
    2021import net.i2p.I2PException;
    2122import net.i2p.client.streaming.I2PSocket;
     23import net.i2p.client.streaming.I2PSocketOptions;
    2224import net.i2p.data.DataFormatException;
    2325import net.i2p.util.HexDump;
     
    204206                //I2PSocketManager sm = I2PSocketManagerFactory.createManager();
    205207                //destSock = sm.connect(I2PTunnel.destFromName(connHostName), null);
    206                 destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName));
     208                Properties overrides = new Properties();
     209                I2PSocketOptions sktOpts = t.buildOptions(overrides);
     210                sktOpts.setPort(connPort);
     211                destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName), sktOpts);
    207212            } else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) {
    208213                String err = "No localhost accesses allowed through the Socks Proxy";
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java

    rc2137a2 rc6d1c55  
    367367                    throw new SOCKSException("Host not found");
    368368                }
    369                 destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName));
     369                Properties overrides = new Properties();
     370                I2PSocketOptions sktOpts = t.buildOptions(overrides);
     371                sktOpts.setPort(connPort);
     372                destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName), sktOpts);
    370373            } else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) {
    371374                String err = "No localhost accesses allowed through the Socks Proxy";
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java

    rc2137a2 rc6d1c55  
    377377    private static Properties getOptions(TunnelController controller) {
    378378        if (controller == null) return null;
    379         String opts = controller.getClientOptions();
    380         StringTokenizer tok = new StringTokenizer(opts);
    381         Properties props = new Properties();
    382         while (tok.hasMoreTokens()) {
    383             String pair = tok.nextToken();
    384             int eq = pair.indexOf('=');
    385             if ( (eq <= 0) || (eq >= pair.length()) )
    386                 continue;
    387             String key = pair.substring(0, eq);
    388             String val = pair.substring(eq+1);
    389             props.setProperty(key, val);
    390         }
    391         return props;
     379        return controller.getClientOptionProps();
    392380    }
    393381}
  • apps/i2ptunnel/jsp/editClient.jsp

    rc2137a2 rc6d1c55  
    498498            <div class="footer">
    499499                <div class="toolbox">
    500                     <span class="comment"><%=intl._("NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted.")%></span>
    501                      <div class="separator"><hr /></div>
    502500                    <input type="hidden" value="true" name="removeConfirm" />
    503501                    <button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel"><%=intl._("Cancel")%></button>
  • apps/i2ptunnel/jsp/editServer.jsp

    rc2137a2 rc6d1c55  
    508508            <div class="footer">
    509509                <div class="toolbox">
    510                     <span class="comment"><%=intl._("NOTE: If tunnel is currently running, most changes will not take effect until tunnel is stopped and restarted.")%></span>
    511                     <div class="separator"><hr /></div>
    512510                    <input type="hidden" value="true" name="removeConfirm" />
    513511                    <button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel"><%=intl._("Cancel")%></button>
  • apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java

    rc2137a2 rc6d1c55  
    88
    99/**
     10 *  As this does not (yet) extend ServerSocketChannel it cannot be returned by StandardServerSocket.getChannel(),
     11 *  until we implement an I2P SocketAddress class.             
     12 *
     13 *  Warning, this interface and implementation is preliminary and subject to change without notice.
     14 *
    1015 *  @since 0.8.11
    1116 */
    1217public abstract class AcceptingChannel extends SelectableChannel {
     18
    1319    abstract I2PSocket accept() throws I2PException, ConnectException;
    14     I2PSocketManager _socketManager;
     20
     21    protected final I2PSocketManager _socketManager;
     22
    1523    AcceptingChannel(I2PSocketManager manager) {
    1624        this._socketManager = manager;
  • apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketEepGet.java

    rc2137a2 rc6d1c55  
    112112                String host = url.getHost();
    113113                int port = url.getPort();
    114                 if (port != -1)
    115                     throw new IOException("Ports not supported in i2p: " + _actualURL);
     114                if (port <= 0 || port > 65535)
     115                    port = 80;
    116116
    117117                // HTTP Proxy compatibility http://i2p/B64KEY/blah
     
    144144                props.setProperty(PROP_CONNECT_DELAY, CONNECT_DELAY);
    145145                I2PSocketOptions opts = _socketManager.buildOptions(props);
     146                opts.setPort(port);
    146147                _socket = _socketManager.connect(dest, opts);
    147148            } else {
  • apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManager.java

    rc2137a2 rc6d1c55  
    3939    public void setAcceptTimeout(long ms);
    4040    public long getAcceptTimeout();
     41
     42    /**
     43     *  Update the options on a running socket manager.
     44     *  Parameters in the I2PSocketOptions interface may be changed directly
     45     *  with the setters; no need to use this method for those.
     46     *  This does NOT update the underlying I2CP or tunnel options; use getSession().updateOptions() for that.
     47     *  @param options as created from a call to buildOptions(properties), non-null
     48     */
    4149    public void setDefaultOptions(I2PSocketOptions options);
     50
     51    /**
     52     *  Current options, not a copy, setters may be used to make changes.
     53     */
    4254    public I2PSocketOptions getDefaultOptions();
     55
    4356    public I2PServerSocket getServerSocket();
    4457   
     58    /**
     59     *  Create a copy of the current options, to be used in a setDefaultOptions() call.
     60     */
    4561    public I2PSocketOptions buildOptions();
     62
     63    /**
     64     *  Create a modified copy of the current options, to be used in a setDefaultOptions() call.
     65     *  @param opts The new options, may be null
     66     */
    4667    public I2PSocketOptions buildOptions(Properties opts);
    4768
     
    103124    public void setName(String name);
    104125
     126    /**
     127     * Deprecated - Factory will initialize.
     128     * @throws UnsupportedOperationException always
     129     */
    105130    public void init(I2PAppContext context, I2PSession session, Properties opts, String name);
    106131   
  • apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerFactory.java

    rc2137a2 rc6d1c55  
    55import java.io.IOException;
    66import java.io.InputStream;
     7import java.lang.reflect.Constructor;
    78import java.util.Iterator;
    89import java.util.Properties;
     
    162163
    163164    private static I2PSocketManager createManager(I2PSession session, Properties opts, String name) {
    164         //if (false) {
    165             //I2PSocketManagerImpl mgr = new I2PSocketManagerImpl();
    166             //mgr.setSession(session);
    167             //mgr.setDefaultOptions(new I2PSocketOptions());
    168             //return mgr;
    169         //} else {
    170             String classname = opts.getProperty(PROP_MANAGER, DEFAULT_MANAGER);
    171             if (classname != null) {
    172                 try {
    173                     Class cls = Class.forName(classname);
    174                     Object obj = cls.newInstance();
    175                     if (obj instanceof I2PSocketManager) {
    176                         I2PSocketManager mgr = (I2PSocketManager)obj;
    177                         I2PAppContext context = I2PAppContext.getGlobalContext();
    178                         mgr.init(context, session, opts, name);
    179                         return mgr;
    180                     } else {
    181                         throw new IllegalStateException("Invalid manager class [" + classname + "]");
    182                     }
    183                 } catch (ClassNotFoundException cnfe) {
    184                     _log.error("Error loading " + classname, cnfe);
    185                     throw new IllegalStateException("Invalid manager class [" + classname + "] - not found");
    186                 } catch (InstantiationException ie) {
    187                     _log.error("Error loading " + classname, ie);
    188                     throw new IllegalStateException("Invalid manager class [" + classname + "] - unable to instantiate");
    189                 } catch (IllegalAccessException iae) {
    190                     _log.error("Error loading " + classname, iae);
    191                     throw new IllegalStateException("Invalid manager class [" + classname + "] - illegal access");
    192                 }
    193             } else {
    194                 throw new IllegalStateException("No manager class specified");
    195             }
    196         //}
    197        
     165        I2PAppContext context = I2PAppContext.getGlobalContext();
     166        String classname = opts.getProperty(PROP_MANAGER, DEFAULT_MANAGER);
     167        try {
     168            Class cls = Class.forName(classname);
     169            Constructor<I2PSocketManager> con = (Constructor<I2PSocketManager>)
     170                  cls.getConstructor(new Class[] {I2PAppContext.class, I2PSession.class, Properties.class, String.class});
     171            I2PSocketManager mgr = con.newInstance(new Object[] {context, session, opts, name});
     172            return mgr;
     173        } catch (Throwable t) {
     174            _log.log(Log.CRIT, "Error loading " + classname, t);
     175            throw new IllegalStateException(t);
     176        }
     177
    198178    }
    199179
  • apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketOptions.java

    rc2137a2 rc6d1c55  
    106106    /**
    107107     *  The local port.
     108     *  Zero (default) means you will receive traffic on all ports.
     109     *  Nonzero means you will get traffic ONLY for that port, use with care,
     110     *  as most applications do not specify a remote port.
    108111     *  @param port 0 - 65535
    109112     *  @since 0.8.9
  • apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketOptionsImpl.java

    rc2137a2 rc6d1c55  
    201201    /**
    202202     *  The local port.
     203     *  Zero (default) means you will receive traffic on all ports.
     204     *  Nonzero means you will get traffic ONLY for that port, use with care,
     205     *  as most applications do not specify a remote port.
    203206     *  @param port 0 - 65535
    204207     *  @since 0.8.9
  • apps/streaming/java/src/net/i2p/client/streaming/AcceptingChannelImpl.java

    rc2137a2 rc6d1c55  
    1414
    1515/**
     16 *  As this does not (yet) extend ServerSocketChannel it cannot be returned by StandardServerSocket.getChannel(),
     17 *  until we implement an I2P SocketAddress class.             
     18 *
     19 *  Warning, this interface and implementation is preliminary and subject to change without notice.
     20 *
    1621 *  @since 0.8.11
    1722 */
    18 public class AcceptingChannelImpl extends AcceptingChannel {
    19     boolean _isRegistered = false;
    20     SelectionKey whichKey = null;
    21     SelectorProvider provider = null;
    22     Selector sel = null;
    23     Object lock = null;
    24     I2PSocket next = null;
    25     I2PServerSocket socket;
     23class AcceptingChannelImpl extends AcceptingChannel {
     24    private boolean _isRegistered;
     25    private SelectionKey whichKey;
     26    private SelectorProvider provider;
     27    private Selector sel;
     28    private Object lock;
     29    private volatile I2PSocket next;
     30    private final I2PServerSocket socket;
    2631
    2732    I2PSocket accept() throws I2PException, ConnectException {
     
    3237            return null;
    3338        }
    34         I2PSocket temp = next;
    35         next = sock;
    36         return temp;
     39        synchronized (this) {
     40            I2PSocket temp = next;
     41            next = sock;
     42            return temp;
     43        }
    3744    }
    3845
     
    97104            @Override
    98105            public int readyOps() {
    99                 if((operations & OP_ACCEPT) != 0)
     106                if((operations & OP_ACCEPT) != 0) {
    100107                    if(next != null) {
    101108                        return OP_ACCEPT;
     
    108115                            return OP_ACCEPT;
    109116                    }
     117                }
    110118                return 0;
    111119            }
     
    137145    @Override
    138146    protected void implCloseChannel() throws IOException {
    139         if(next != null) {
    140             next.close();
     147        I2PSocket nxt = next;
     148        if(nxt != null) {
     149            nxt.close();
    141150        }
    142151        _socketManager.destroySocketManager();
  • apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java

    rc2137a2 rc6d1c55  
    6868        // Right now we get everything, and rely on Datagram to specify PROTO_UDP.
    6969        // PacketQueue has sent PROTO_STREAMING since the beginning of mux support (0.7.1)
    70         _session.addMuxedSessionListener(_messageHandler, I2PSession.PROTO_ANY, I2PSession.PORT_ANY);
     70        // As of 0.9.1, new option to enforce streaming protocol, off by default
     71        // As of 0.9.1, listen on configured port (default 0 = all)
     72        int protocol = defaultOptions.getEnforceProtocol() ? I2PSession.PROTO_STREAMING : I2PSession.PROTO_ANY;
     73        _session.addMuxedSessionListener(_messageHandler, protocol, defaultOptions.getLocalPort());
    7174        _outboundQueue = new PacketQueue(_context, _session, this);
    7275        /** Socket timeout for accept() */
  • apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java

    rc2137a2 rc6d1c55  
    2020    private boolean _fullySigned;
    2121    private boolean _answerPings;
     22    private boolean _enforceProto;
    2223    private volatile int _windowSize;
    2324    private int _receiveWindow;
     
    8889    public static final String PROP_MAX_TOTAL_CONNS_HOUR = "i2p.streaming.maxTotalConnsPerHour";
    8990    public static final String PROP_MAX_TOTAL_CONNS_DAY = "i2p.streaming.maxTotalConnsPerDay";
     91    /** @since 0.9.1 */
     92    public static final String PROP_ENFORCE_PROTO = "i2p.streaming.enforceProtocol";
    9093   
    9194    private static final int TREND_COUNT = 3;
     
    9699    static final int MIN_WINDOW_SIZE = 1;
    97100    private static final boolean DEFAULT_ANSWER_PINGS = true;
     101    /**
     102     *  If PROTO is enforced, we cannot communicate with destinations earlier than version 0.7.1.
     103     *  @since 0.9.1
     104     */
     105    private static final boolean DEFAULT_ENFORCE_PROTO = true;
    98106
    99107    // Syncronization fix, but doing it this way causes NPE...
     
    238246    public ConnectionOptions(ConnectionOptions opts) {
    239247        super(opts);
    240         if (opts != null) {
     248        if (opts != null)
     249            update(opts);
     250    }
     251   
     252    /**
     253     *  Update everything by copying over from opts
     254     *  @param opts non-null
     255     *  @since 0.9.1
     256     */
     257    public void updateAll(ConnectionOptions opts) {
     258        // user is unlikely to change these 6 between buildOptions() and setDefaultOptions(),
     259        // since they may be updated directly, but just in case...
     260        setConnectTimeout(opts.getConnectTimeout());
     261        setReadTimeout(opts.getReadTimeout());
     262        setWriteTimeout(opts.getWriteTimeout());
     263        setMaxBufferSize(opts.getMaxBufferSize());
     264        setLocalPort(opts.getLocalPort());
     265        setPort(opts.getPort());
     266        update(opts);
     267    }
     268   
     269    /**
     270     *  Update everything (except super) by copying over from opts
     271     *  @param opts non-null
     272     *  @since 0.9.1
     273     */
     274    private void update(ConnectionOptions opts) {
    241275            setMaxWindowSize(opts.getMaxWindowSize());
    242276            setConnectDelay(opts.getConnectDelay());
     
    259293            //setReadTimeout(opts.getReadTimeout());
    260294            setAnswerPings(opts.getAnswerPings());
     295            setEnforceProtocol(opts.getEnforceProtocol());
    261296            initLists(opts);
    262297            _maxConnsPerMinute = opts.getMaxConnsPerMinute();
     
    266301            _maxTotalConnsPerHour = opts.getMaxTotalConnsPerHour();
    267302            _maxTotalConnsPerDay = opts.getMaxTotalConnsPerDay();
    268         }
    269303    }
    270304   
     
    293327        setConnectTimeout(getInt(opts, PROP_CONNECT_TIMEOUT, Connection.DISCONNECT_TIMEOUT));
    294328        setAnswerPings(getBool(opts, PROP_ANSWER_PINGS, DEFAULT_ANSWER_PINGS));
     329        setEnforceProtocol(getBool(opts, PROP_ENFORCE_PROTO, DEFAULT_ENFORCE_PROTO));
    295330        initLists(opts);
    296331        _maxConnsPerMinute = getInt(opts, PROP_MAX_CONNS_MIN, 0);
     
    302337    }
    303338   
     339    /**
     340     *  Note: NOT part of the interface
     341     */
    304342    @Override
    305343    public void setProperties(Properties opts) {
     
    344382        if (opts.containsKey(PROP_ANSWER_PINGS))
    345383            setAnswerPings(getBool(opts, PROP_ANSWER_PINGS, DEFAULT_ANSWER_PINGS));
     384        if (opts.containsKey(PROP_ENFORCE_PROTO))
     385            setEnforceProtocol(getBool(opts, PROP_ENFORCE_PROTO, DEFAULT_ENFORCE_PROTO));
    346386        initLists(opts);
    347387        if (opts.containsKey(PROP_MAX_CONNS_MIN))
     
    392432    public boolean getAnswerPings() { return _answerPings; }
    393433    public void setAnswerPings(boolean yes) { _answerPings = yes; }
     434   
     435    /**
     436     * Do we receive all traffic, or only traffic marked with I2PSession.PROTO_STREAMING (6) ?
     437     * Default false.
     438     * If PROTO is enforced, we cannot communicate with destinations earlier than version 0.7.1
     439     * (released March 2009), which is when streaming started sending the PROTO_STREAMING indication.
     440     * Set to true if you are running multiple protocols on a single Destination.
     441     *
     442     * @return if we do
     443     * @since 0.9.1
     444     */
     445    public boolean getEnforceProtocol() { return _enforceProto; }
     446    public void setEnforceProtocol(boolean yes) { _enforceProto = yes; }
    394447   
    395448    /**
     
    612665        _accessListEnabled = getBool(opts, PROP_ENABLE_ACCESS_LIST, false);
    613666        _blackListEnabled = getBool(opts, PROP_ENABLE_BLACKLIST, false);
     667        // Don't think these would ever be accessed simultaneously,
     668        // but avoid concurrent modification just in case
     669        Set<Hash> accessList, blackList;
    614670        if (_accessListEnabled)
    615             _accessList = new HashSet();
     671            accessList = new HashSet();
    616672        else
    617             _accessList = Collections.EMPTY_SET;
     673            accessList = Collections.EMPTY_SET;
    618674        if (_blackListEnabled)
    619             _blackList = new HashSet();
     675            blackList = new HashSet();
    620676        else
    621             _blackList = Collections.EMPTY_SET;
    622         if (!(_accessListEnabled || _blackListEnabled))
    623             return;
    624         String hashes = opts.getProperty(PROP_ACCESS_LIST);
    625         if (hashes == null)
    626             return;
    627         StringTokenizer tok = new StringTokenizer(hashes, ", ");
    628         while (tok.hasMoreTokens()) {
    629             String hashstr = tok.nextToken();
    630             Hash h = ConvertToHash.getHash(hashstr);
    631             if (h == null)
    632                 error("bad list hash: " + hashstr);
    633             else if (_blackListEnabled)
    634                 _blackList.add(h);
    635             else
    636                 _accessList.add(h);
     677            blackList = Collections.EMPTY_SET;
     678        if (_accessListEnabled || _blackListEnabled) {
     679            String hashes = opts.getProperty(PROP_ACCESS_LIST);
     680            if (hashes == null)
     681                return;
     682            StringTokenizer tok = new StringTokenizer(hashes, ", ");
     683            while (tok.hasMoreTokens()) {
     684                String hashstr = tok.nextToken();
     685                Hash h = ConvertToHash.getHash(hashstr);
     686                if (h == null)
     687                    error("bad list hash: " + hashstr);
     688                else if (_blackListEnabled)
     689                    blackList.add(h);
     690                else
     691                    accessList.add(h);
     692            }
    637693        }
     694        _accessList = accessList;
     695        _blackList = blackList;
    638696        if (_accessListEnabled && _accessList.isEmpty())
    639697            error("Connection access list enabled but no valid entries; no peers can connect");
     
    648706    }
    649707
    650         @Override
     708    /** doesn't include everything */
     709    @Override
    651710    public String toString() {
    652         StringBuilder buf = new StringBuilder(128);
     711        StringBuilder buf = new StringBuilder(256);
    653712        buf.append("conDelay=").append(_connectDelay);
    654713        buf.append(" maxSize=").append(_maxMessageSize);
     
    664723        buf.append(" inboundBuffer=").append(_inboundBufferSize);
    665724        buf.append(" maxWindowSize=").append(_maxWindowSize);
     725        buf.append(" blacklistSize=").append(_blackList.size());
     726        buf.append(" whitelistSize=").append(_accessList.size());
     727        buf.append(" maxConns=").append(_maxConnsPerMinute).append('/')
     728                                .append(_maxConnsPerHour).append('/')
     729                                .append(_maxConnsPerDay);
     730        buf.append(" maxTotalConns=").append(_maxTotalConnsPerMinute).append('/')
     731                                .append(_maxTotalConnsPerHour).append('/')
     732                                .append(_maxTotalConnsPerDay);
    666733        return buf.toString();
    667734    }
  • apps/streaming/java/src/net/i2p/client/streaming/I2PServerSocketFull.java

    rc2137a2 rc6d1c55  
    1010class I2PServerSocketFull implements I2PServerSocket {
    1111    private final I2PSocketManagerFull _socketManager;
     12    private volatile AcceptingChannel _channel;
    1213   
    1314    public I2PServerSocketFull(I2PSocketManagerFull mgr) {
     
    2930     *  @since 0.8.11
    3031     */
    31     public AcceptingChannel getChannel() {
    32         return new AcceptingChannelImpl(_socketManager);
     32    public synchronized AcceptingChannel getChannel() {
     33        if (_channel == null)
     34            _channel = new AcceptingChannelImpl(_socketManager);
     35        return _channel;
    3336    }
    3437   
  • apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java

    rc2137a2 rc6d1c55  
    1717    private Destination _remotePeer;
    1818    private Destination _localPeer;
     19    private volatile MessageChannel _channel;
    1920   
    2021    public I2PSocketFull(Connection con) {
     
    7172     *  @since 0.8.9
    7273     */
    73     public SelectableChannel getChannel() {
    74         return new MessageChannel(this);
     74    public synchronized SelectableChannel getChannel() {
     75        if (_channel == null)
     76            _channel = new MessageChannel(this);
     77        return _channel;
    7578    }
    7679   
  • apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java

    rc2137a2 rc6d1c55  
    2929 */
    3030public class I2PSocketManagerFull implements I2PSocketManager {
    31     private I2PAppContext _context;
    32     private Log _log;
    33     private I2PSession _session;
    34     private I2PServerSocketFull _serverSocket;
     31    private final I2PAppContext _context;
     32    private final Log _log;
     33    private final I2PSession _session;
     34    private final I2PServerSocketFull _serverSocket;
    3535    private StandardServerSocket _realServerSocket;
    36     private ConnectionOptions _defaultOptions;
     36    private final ConnectionOptions _defaultOptions;
    3737    private long _acceptTimeout;
    3838    private String _name;
    3939    private int _maxStreams;
    4040    private static int __managerId = 0;
    41     private ConnectionManager _connectionManager;
     41    private final ConnectionManager _connectionManager;
    4242   
    4343    /**
     
    4646     */
    4747    private static final long ACCEPT_TIMEOUT_DEFAULT = 5*1000;
    48    
     48
     49    /**
     50     * @deprecated use 4-arg constructor
     51     * @throws UnsupportedOperationException always
     52     */
    4953    public I2PSocketManagerFull() {
    50     }
    51 
    52     /**
     54        throw new UnsupportedOperationException();
     55    }
     56   
     57    /** how many streams will we allow at once?  */
     58    public static final String PROP_MAX_STREAMS = "i2p.streaming.maxConcurrentStreams";
     59   
     60    /**
     61     * @deprecated use 4-arg constructor
     62     * @throws UnsupportedOperationException always
     63     */
     64    public void init(I2PAppContext context, I2PSession session, Properties opts, String name) {
     65        throw new UnsupportedOperationException();
     66    }
     67
     68    /**
     69     * This is what I2PSocketManagerFactory.createManager() returns.
     70     * Direct instantiation by others is deprecated.
    5371     *
    5472     * @param context
     
    5876     */
    5977    public I2PSocketManagerFull(I2PAppContext context, I2PSession session, Properties opts, String name) {
    60         this();
    61         init(context, session, opts, name);
    62     }
    63    
    64     /** how many streams will we allow at once?  */
    65     public static final String PROP_MAX_STREAMS = "i2p.streaming.maxConcurrentStreams";
    66    
    67     /**
    68      *
    69      *
    70      * @param context
    71      * @param session
    72      * @param opts
    73      * @param name
    74      */
    75     public void init(I2PAppContext context, I2PSession session, Properties opts, String name) {
    7678        _context = context;
    7779        _session = session;
     
    99101    }
    100102
     103    /**
     104     *  Create a copy of the current options, to be used in a setDefaultOptions() call.
     105     */
    101106    public I2PSocketOptions buildOptions() { return buildOptions(null); }
     107
     108    /**
     109     *  Create a modified copy of the current options, to be used in a setDefaultOptions() call.
     110     *  @param opts The new options, may be null
     111     */
    102112    public I2PSocketOptions buildOptions(Properties opts) {
    103113        ConnectionOptions curOpts = new ConnectionOptions(_defaultOptions);
     
    160170    public long getAcceptTimeout() { return _acceptTimeout; }
    161171
     172    /**
     173     *  Update the options on a running socket manager.
     174     *  Parameters in the I2PSocketOptions interface may be changed directly
     175     *  with the setters; no need to use this method for those.
     176     *  This does NOT update the underlying I2CP or tunnel options; use getSession().updateOptions() for that.
     177     *  @param options as created from a call to buildOptions(properties), non-null
     178     */
    162179    public void setDefaultOptions(I2PSocketOptions options) {
    163         _defaultOptions = new ConnectionOptions((ConnectionOptions) options);
    164     }
    165 
     180        if (!(options instanceof ConnectionOptions))
     181            throw new IllegalArgumentException();
     182        if (_log.shouldLog(Log.WARN))
     183            _log.warn("Changing options from:\n " + _defaultOptions + "\nto:\n " + options);
     184        _defaultOptions.updateAll((ConnectionOptions) options);
     185    }
     186
     187    /**
     188     *  Current options, not a copy, setters may be used to make changes.
     189     */
    166190    public I2PSocketOptions getDefaultOptions() {
    167191        return _defaultOptions;
  • apps/streaming/java/src/net/i2p/client/streaming/MessageChannel.java

    rc2137a2 rc6d1c55  
    1616
    1717/**
     18 *  As this does not (yet) extend SocketChannel it cannot be returned by StandardSocket.getChannel(),
     19 *  until we implement an I2P SocketAddress class.             
     20 *
     21 *  Warning, this interface and implementation is preliminary and subject to change without notice.
     22 *
    1823 *  @since 0.8.9
    1924 */
    2025public class MessageChannel extends SelectableChannel implements ReadableByteChannel, WritableByteChannel {
    2126
    22     final MessageInputStream in;
    23     final MessageOutputStream out;
    24     boolean _isRegistered = false;
    25     SelectionKey whichKey = null;
    26     SelectorProvider provider = null;
    27     Selector sel = null;
    28     Object lock = null;
    29     I2PSocket socket;
     27    private final MessageInputStream in;
     28    private final MessageOutputStream out;
     29    private boolean _isRegistered;
     30    private SelectionKey whichKey;
     31    private SelectorProvider provider;
     32    private Selector sel;
     33    private Object lock;
     34    private final I2PSocket socket;
    3035
    3136    MessageChannel(I2PSocket socket) {
     
    146151     * no more data available.
    147152     */
    148 
    149153    public int read(ByteBuffer buf) throws IOException {
    150154        int amount = 0;
    151155        for (;;) {
     156            // TODO if buf.hasArray() ... getArray() ... getArrayOffset() ...
    152157            byte[] lbuf = new byte[buf.remaining()];
    153158            int samount = in.read(lbuf);
     
    168173     * (wait timeout is 0) then put the bytes back and return.
    169174     */
    170 
    171175    public int write(ByteBuffer buf) throws IOException {
    172176        int written = 0;
     
    174178            if(buf.remaining()==0)
    175179                return written;
     180            // TODO if buf.hasArray() ... getArray() ... getArrayOffset() ...
    176181            byte[] lbuf = new byte[Math.min(buf.remaining(), 0x1000)];
    177182            buf.get(lbuf);
  • apps/streaming/java/src/net/i2p/client/streaming/StandardServerSocket.java

    rc2137a2 rc6d1c55  
    7373
    7474    /**
    75      *  @return null always
     75     *  @return null always, see AcceptingChannelImpl for more info
    7676     */
    7777    @Override
    7878    public ServerSocketChannel getChannel() {
     79        //return _socket.getChannel();
    7980        return null;
    8081    }
  • apps/streaming/java/src/net/i2p/client/streaming/StandardSocket.java

    rc2137a2 rc6d1c55  
    6666
    6767    /**
    68      *  @return null always
     68     *  @return null always, see MessageChannel for more info
    6969     */
    7070    @Override
    7171    public SocketChannel getChannel() {
     72        //return _socket.getChannel();
    7273        return null;
    7374    }
  • core/java/src/net/i2p/client/I2PSession.java

    rc2137a2 rc6d1c55  
    3939     * payload, returning true if the router feels confident that the message
    4040     * was delivered.
     41     *
     42     * WARNING: It is recommended that you use a method that specifies the protocol and ports.
     43     *
    4144     * @param dest location to send the message
    4245     * @param payload body of the message to be sent (unencrypted)
     
    150153
    151154    /** Instruct the I2PSession where it should send event notifications
     155     *
     156     *  WARNING: It is recommended that you use a method that specifies the protocol and ports.
     157     *
    152158     * @param lsnr listener to retrieve events
    153159     */
  • history.txt

    rc2137a2 rc6d1c55  
     12012-06-18 zzz
     2 * i2psnark:
     3   - Improve torrent shutdown handling to maximize chance of
     4     announces getting to tracker
     5   - Thread task to open tunnel and improve UI feedback while open is pending
     6   - Clean up delete-torrent messages
     7   - Remove redundant shutdown hook
     8   - Avoid NPE in PEX message handling
     9   - Log tweaks
     10
     112012-06-15 zzz
     12 * I2PSocketEepGet: Use specified port
     13 * I2PTunnel:
     14   - Don't strip port from an I2P URL
     15   - More client options cleanups
     16   - Options changes now propagate to running
     17     socket managers and sessions, and through to the router
     18   - Better parsing of jump server URLs
     19 * NetDB: Only publish stats every so often, to improve
     20   anonymity while preserving the ability to monitor
     21   the network (effective next release)
     22 * SocketManager:
     23   - Simplify factory, use 4-arg constructor,
     24     make fields final, deprecate 0-arg constructor
     25   - Improve how options are updated
     26   - Javadocs
     27
     282012-06-13 zzz
     29 * I2PSocketEepGet: Set port to 80
     30 * I2PTunnel:
     31   - Pass port through HTTP client proxy
     32   - HTTP server proxy sets host header to
     33     the value of "spoofedhost.xx" option for port xx
     34   - Set client options more efficiently
     35 * i2psnark: Possible fix for piece-after-choke
     36 * Streaming:
     37   - Channel cleanups and comments
     38   - New I2PSocketAddress
     39
    1402012-06-11 zzz
    241 * i2psnark:
     
    948   - Thread the announces and reduce timeout when stopping
    1049 * NativeBigInteger: Workaround for Raspberry Pi to load the correct lib
    11  * Router: Don't let shutdown tasks hang the shutdown
     50 * Router: Don't let shutdown tasks hang the shutdown (tickets #564, #566)
    1251
    13522012-06-08 zzz
  • router/java/src/net/i2p/router/RouterVersion.java

    rc2137a2 rc6d1c55  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 13;
     21    public final static long BUILD = 16;
    2222
    2323    /** for example "-test" */
  • router/java/src/net/i2p/router/StatisticsManager.java

    rc2137a2 rc6d1c55  
    3131   
    3232    public final static String PROP_PUBLISH_RANKINGS = "router.publishPeerRankings";
     33    /** enhance anonymity by only including build stats one out of this many times */
     34    private static final int RANDOM_INCLUDE_STATS = 4;
    3335
    3436    private final DecimalFormat _fmt;
     
    8385***/
    8486       
    85         if (_context.getBooleanPropertyDefaultTrue(PROP_PUBLISH_RANKINGS)) {
     87        if (_context.getBooleanPropertyDefaultTrue(PROP_PUBLISH_RANKINGS) &&
     88            (CoreVersion.VERSION.equals("0.9") || _context.random().nextInt(RANDOM_INCLUDE_STATS) == 0)) {
    8689            long publishedUptime = _context.router().getUptime();
    8790            // Don't publish these for first hour
    88             if (publishedUptime > 62*60*1000 && CoreVersion.VERSION.equals("0.8.13"))
    89                 includeAverageThroughput(stats);
     91            // Disabled in 0.9
     92            //if (publishedUptime > 62*60*1000)
     93            //    includeAverageThroughput(stats);
    9094            //includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 });
    9195            //includeRate("router.duplicateMessageId", stats, new long[] { 24*60*60*1000 });
Note: See TracChangeset for help on using the changeset viewer.