Compare commits

..

21 Commits

Author SHA1 Message Date
bd1f4c9f6a CI: when a new tag is pushed, wait until the mirror is updated, download the files from the mirror, and then move the files to the github release corresponding to the tag. Use the i2p.newsxml source to generate the text for the release 2024-06-27 19:39:42 -04:00
zzz
ddfe816d80 I2CP: Increase % of router bandwidth reported to clients 2024-06-27 17:07:44 -04:00
zzz
d765f85515 Console: Fix typo in Permissions-Policy header
causing Chrome to complain
2024-06-26 11:45:29 -04:00
zzz
f8394ac82a Data: Add LeaseSet2.getOptions()
Currently unused but useful for testing.
Remove useless null check.
2024-06-25 12:28:30 -04:00
zzz
e4aab76045 Graphs: Skip the X axis arrowhead also
put the check in the right place
2024-06-24 13:52:44 -04:00
zzz
a2dc80e089 susimail: Update size limits to match current postman limits 2024-06-22 16:47:10 -04:00
zzz
b573fe461f i2ptunnel: Reduce severity of access filter errors (Gitlab #483)
So they don't prevent the tunnel from starting
Log tweaks
2024-06-20 11:21:42 -04:00
zzz
d4f580ee39 Build: Put JspC wrapper in its own jar, used only at build time
remove from jetty-i2p.jar, not required at runtime
2024-06-11 07:49:50 -04:00
zzz
88fbf0f82a i2psnark: CSS tweaks
soften linear gradients
2024-06-10 11:12:28 -04:00
zzz
14db2f3642 Router: Increase min version for floodfills, tunnels, reseed 2024-06-10 07:07:50 -04:00
zzz
c15b29cd4d javadoc fix 2024-06-10 06:51:11 -04:00
zzz
a0f92b2e28 CLI: Fix getopt program names
these are output by getopt in error messages
2024-06-05 09:05:51 -04:00
zzz
5c8ddbe26a bump -5 2024-06-04 08:50:59 -04:00
zzz
07cf02e969 Reseed: Increase min version when creating bundles
exclude K and G caps from bundles
improve CLI output to count old versions and unreachables
allow specifying hostname only on CLI, not just full URL
2024-06-04 08:49:32 -04:00
zzz
a2dd0a756d Router: Add synthetic stats for client and expl. build success rate
derived from event counts of existing stats
requires full stats setting
2024-06-04 08:31:32 -04:00
zzz
aedcd02506 i2psnark: Make PEX more efficient
by only sending new peers, as in ut_pex.
Track connected time and last pex sent time, and only send
peers connected since the last sent time.
Usually, there are no new peers, so now we don't send a message at all.
Also, don't send PEX to seeds after the handshake.
2024-06-04 08:27:12 -04:00
zzz
2f0ed24356 Merge branch 'snark-partials' into 'master'
i2psnark: Fix leaked requests and partial pieces with data

See merge request i2p-hackers/i2p.i2p!203
2024-06-04 11:32:57 +00:00
zzz
4659a922b8 i2psnark: Fix leaked requests and partial pieces with data 2024-06-04 11:32:57 +00:00
zzz
774fd4c2ca Merge branch 'graphs-js' into 'master'
Console: js refresh of graphs

See merge request i2p-hackers/i2p.i2p!199
2024-06-04 11:30:05 +00:00
zzz
02141473ad Console: js refresh of graphs 2024-06-04 11:30:04 +00:00
zzz
d7fbc79533 Router: Don't update rates for full stats when not enabled 2024-06-01 10:49:32 -04:00
40 changed files with 400 additions and 132 deletions

64
.github/workflows/mirror-release.yml vendored Normal file
View File

@ -0,0 +1,64 @@
name: mirror
on:
push:
tags:
- 'i2p-*.*.*'
jobs:
dl:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: |
changelog.txt
- name: download release artifacts
run: |
sudo apt-get install wget ca-certificates gpg sed curl
while true; do wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')_windows.exe && break; done
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/I2P-Easy-Install-Bundle-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')-signed.exe
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/I2P-Easy-Install-Bundle-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').exe
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').jar
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').jar.sig
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')_windows.exe
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pinstall_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')_windows.exe.sig
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2psource_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').tar.bz2
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2psource_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').tar.bz2.sig
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').su3
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate-$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').su3.torrent
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate.su3
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').zip
wget -v https://files.i2p-projekt.de/$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')/i2pupdate_$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||').zip.sig'
echo "$(git describe --abbrev=0 | sed 's|i2p-||g' |sed 's|-.*||')" > CHANGES.md
echo "===========" >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
curl https://raw.githubusercontent.com/i2p/i2p.newsxml/master/data/entries.html | sed -n '/<article/,/<\/article/p' | sed -n '1,/<\/article>/p' | sed -n '/<\/details>/,$p' | sed '1d' | sed 's/<\/\{0,1\}p>//g' | sed 's|<\/article>||g' >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
echo '```' >> CHANGES.md
head -n 25 changelog.txt >> CHANGES.md
echo '```' >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
echo "## Checksums" >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
echo '```' >> CHANGES.md
sha256sum * >> CHANGES.md
echo '```' >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
echo '```' >> CHANGES.md
file * >> CHANGES.md
echo '```' >> CHANGES.md
echo "" >> CHANGES.md
echo "" >> CHANGES.md
cat CHANGES.md
- name: Upload artifacts
uses: ncipollo/release-action@v1
with:
artifacts: "*"
skipIfReleaseExists: true
bodyFile: "CHANGES.md"

View File

@ -856,7 +856,7 @@ public class MetaInfo
String announce = null;
List<String> url_list = null;
String comment = null;
Getopt g = new Getopt("Storage", args, "a:c:m:w:");
Getopt g = new Getopt("MetaInfo", args, "a:c:m:w:");
try {
int c;
while ((c = g.getopt()) != -1) {

View File

@ -140,15 +140,40 @@ class PartialPiece implements Comparable<PartialPiece> {
* @since 0.9.62
*/
public synchronized boolean isComplete() {
return bitfield.complete();
return bitfield.complete();
}
/**
* How many consecutive bytes are good - as set by read().
* There may be more good bytes after "holes".
* Have any chunks been downloaded?
*
* @since 0.9.63
*/
public synchronized boolean hasData() {
return bitfield.count() > 0;
}
/**
* Has this chunk been downloaded?
*
* @since 0.9.63
*/
public synchronized boolean hasChunk(int chunk) {
return bitfield.get(chunk);
}
/**
* How many bytes are good - as set by read().
* As of 0.9.63, accurately counts good bytes after "holes".
*/
public synchronized int getDownloaded() {
return this.off;
if (bitfield.complete())
return pclen;
int sz = bitfield.count();
int rv = sz * PeerState.PARTSIZE;
int rem = pclen % PeerState.PARTSIZE;
if (rem != 0 && bitfield.get(sz - 1))
rv -= PeerState.PARTSIZE - rem;
return rv;
}
/**
@ -348,8 +373,10 @@ class PartialPiece implements Comparable<PartialPiece> {
public void release() {
if (bs == null) {
synchronized (this) {
if (raf != null)
if (raf != null) {
locked_release();
raf = null;
}
}
//if (raf != null)
// I2PAppContext.getGlobalContext().logManager().getLog(PartialPiece.class).warn("Released " + tempfile);
@ -378,7 +405,7 @@ class PartialPiece implements Comparable<PartialPiece> {
int d = this.piece.compareTo(opp.piece);
if (d != 0)
return d;
return opp.off - this.off; // reverse
return opp.getDownloaded() - getDownloaded(); // reverse
}
@Override
@ -401,7 +428,7 @@ class PartialPiece implements Comparable<PartialPiece> {
@Override
public String toString() {
return "Partial(" + piece.getId() + ',' + off + ',' + pclen + ')';
return "Partial(" + piece.getId() + ',' + off + ',' + getDownloaded() + ',' + pclen + ')';
}
/**

View File

@ -96,6 +96,8 @@ public class Peer implements Comparable<Peer>, BandwidthListener
private final boolean _isIncoming;
private int _totalCommentsSent;
private int _maxPipeline = PeerState.MIN_PIPELINE;
private long connected;
private long pexLastSent;
/**
* Outgoing connection.
@ -307,6 +309,7 @@ public class Peer implements Comparable<Peer>, BandwidthListener
// We are up and running!
state = s;
magnetState = mState;
connected = util.getContext().clock().now();
listener.connected(this);
if (_log.shouldLog(Log.DEBUG))
@ -888,4 +891,28 @@ public class Peer implements Comparable<Peer>, BandwidthListener
public boolean isWebPeer() {
return false;
}
/**
* when did handshake complete?
* @since 0.9.63
*/
public long getWhenConnected() {
return connected;
}
/**
* when did we last send pex peers?
* @since 0.9.63
*/
public long getPexLastSent() {
return pexLastSent;
}
/**
* when did we last send pex peers?
* @since 0.9.63
*/
public void setPexLastSent(long now) {
pexLastSent = now;
}
}

View File

@ -1370,14 +1370,14 @@ class PeerCoordinator implements PeerListener, BandwidthListener
synchronized(wantedPieces) {
for (Request req : partials) {
PartialPiece pp = req.getPartialPiece();
if (req.off > 0) {
if (pp.hasData()) {
// PartialPiece.equals() only compares piece number, which is what we want
int idx = partialPieces.indexOf(pp);
if (idx < 0) {
partialPieces.add(pp);
if (_log.shouldLog(Log.INFO))
_log.info("Saving orphaned partial piece (new) " + pp);
} else if (idx >= 0 && pp.getDownloaded() > partialPieces.get(idx).getDownloaded()) {
} else if (pp.getDownloaded() > partialPieces.get(idx).getDownloaded()) {
// replace what's there now
partialPieces.get(idx).release();
partialPieces.set(idx, pp);
@ -1434,7 +1434,9 @@ class PeerCoordinator implements PeerListener, BandwidthListener
for(Piece piece : wantedPieces) {
if (piece.getId() == savedPiece) {
if (peer.isCompleted() && piece.getPeerCount() > 1 &&
wantedPieces.size() > 2*END_GAME_THRESHOLD) {
wantedPieces.size() > 2*END_GAME_THRESHOLD &&
partialPieces.size() < 4 &&
_random.nextInt(4) != 0) {
// Try to preserve rarest-first
// by not requesting a partial piece that at least two non-seeders also have
// from a seeder
@ -1462,7 +1464,7 @@ class PeerCoordinator implements PeerListener, BandwidthListener
iter.remove();
piece.setRequested(peer, true);
if (_log.shouldLog(Log.INFO)) {
_log.info("Restoring orphaned partial piece " + pp +
_log.info("Restoring orphaned partial piece " + pp + " to " + peer +
" Partial list size now: " + partialPieces.size());
}
return pp;
@ -1574,7 +1576,9 @@ class PeerCoordinator implements PeerListener, BandwidthListener
}
}
} else if (id == ExtensionHandler.ID_HANDSHAKE) {
sendPeers(peer);
// We may not have the bitfield yet, but if we do, don't send PEX to seeds
if (!peer.isCompleted())
sendPeers(peer);
sendDHT(peer);
if (_util.utCommentsEnabled())
sendCommentReq(peer);
@ -1583,8 +1587,8 @@ class PeerCoordinator implements PeerListener, BandwidthListener
/**
* Send a PEX message to the peer, if he supports PEX.
* This just sends everybody we are connected to, we don't
* track new vs. old peers yet.
* This sends everybody we have connected to since the
* last time we sent PEX to him.
* @since 0.8.4
*/
void sendPeers(Peer peer) {
@ -1598,14 +1602,25 @@ class PeerCoordinator implements PeerListener, BandwidthListener
return;
try {
if (bev.getMap().get(ExtensionHandler.TYPE_PEX) != null) {
List<Peer> pList = peerList();
pList.remove(peer);
for (Iterator<Peer> iter = pList.iterator(); iter.hasNext(); ) {
if (iter.next().isWebPeer())
iter.remove();
List<Peer> pList = new ArrayList<Peer>();
long t = peer.getPexLastSent();
for (Peer p : peers) {
if (p.equals(peer))
continue;
if (p.isWebPeer())
continue;
if (p.getWhenConnected() > t)
pList.add(p);
}
if (!pList.isEmpty())
if (!pList.isEmpty()) {
ExtensionHandler.sendPEX(peer, pList);
peer.setPexLastSent(_util.getContext().clock().now());
//if (_log.shouldDebug())
// _log.debug("Pex: sent " + pList.size() + " new peers to " + peer);
//} else {
//if (_log.shouldDebug())
// _log.debug("Pex: no new peers to send to " + peer);
}
}
} catch (InvalidBEncodingException ibee) {}
}

View File

@ -67,7 +67,7 @@ class PeerState implements DataLoader
// Outstanding request
private final List<Request> outstandingRequests = new ArrayList<Request>();
/** the tail (NOT the head) of the request queue */
private Request lastRequest = null;
private Request lastRequest;
private int currentMaxPipeline;
// FIXME if piece size < PARTSIZE, pipeline could be bigger
@ -425,7 +425,8 @@ class PeerState implements DataLoader
// Last chunk needed for this piece?
PartialPiece pp = req.getPartialPiece();
if (pp.isComplete())
boolean complete = pp.isComplete();
if (complete)
{
// warning - may block here for a while
if (listener.gotPiece(peer, pp))
@ -449,6 +450,25 @@ class PeerState implements DataLoader
synchronized(this) {
pendingRequest = null;
}
// getOutstandingRequest() was called by PeerConnectionIn at the start of the chunk;
// if the bandwidth limiter throttled us to zero requests then, try again now
if (outstandingRequests.isEmpty()) {
addRequest();
if (!complete) {
synchronized(this) {
if (outstandingRequests.isEmpty()) {
// we MUST return the partial piece to PeerCoordinator,
// or else we will lose it and leak the data
if (_log.shouldWarn())
_log.warn("Throttled, returned to coord. w/ data " + req);
List<Request> pcs = Collections.singletonList(req);
listener.savePartialPieces(this.peer, pcs);
lastRequest = null;
}
}
}
}
}
/**
@ -577,15 +597,8 @@ class PeerState implements DataLoader
List<Request> rv = new ArrayList<Request>(pcs.size());
for (Integer p : pcs) {
Request req = getLowestOutstandingRequest(p.intValue());
if (req != null) {
PartialPiece pp = req.getPartialPiece();
synchronized(pp) {
int dl = pp.getDownloaded();
if (req.off != dl)
req = new Request(pp, dl);
}
if (req != null)
rv.add(req);
}
}
outstandingRequests.clear();
pendingRequest = null;
@ -709,12 +722,6 @@ class PeerState implements DataLoader
/**
* BEP 6
* If the peer rejects lower chunks but not higher ones, thus creating holes,
* we won't figure it out and the piece will fail, since we don't currently
* keep a chunk bitmap in PartialPiece.
* As long as the peer rejects all the chunks, or rejects only the last chunks,
* no holes are created and we will be fine. The reject messages may be in any order,
* just don't make a hole when it's over.
*
* @since 0.9.21
*/
@ -738,19 +745,10 @@ class PeerState implements DataLoader
}
}
if (deletedRequest != null && !haveMoreRequests) {
// We must return the piece to the coordinator
// Create a new fake request so we can set the offset correctly
PartialPiece pp = deletedRequest.getPartialPiece();
int downloaded = pp.getDownloaded();
Request req;
if (deletedRequest.off == downloaded)
req = deletedRequest;
else
req = new Request(pp, downloaded, 1);
List<Request> pcs = Collections.singletonList(req);
List<Request> pcs = Collections.singletonList(deletedRequest);
listener.savePartialPieces(this.peer, pcs);
if (_log.shouldWarn())
_log.warn("Returned to coord. w/ offset " + pp.getDownloaded() + " due to reject(" + piece + ',' + begin + ',' + length + ") from " + peer);
_log.warn("Returned to coord. w/ data " + deletedRequest.getPartialPiece().getDownloaded() + " due to reject(" + piece + ',' + begin + ',' + length + ") from " + peer);
}
if (lastRequest != null && lastRequest.getPiece() == piece &&
lastRequest.off == begin && lastRequest.len == length)
@ -876,7 +874,7 @@ class PeerState implements DataLoader
*
* This is called from several places:
*<pre>
* By getOustandingRequest() when the first part of a chunk comes in
* By getOutstandingRequest() when the first part of a chunk comes in
* By havePiece() when somebody got a new piece completed
* By chokeMessage() when we receive an unchoke
* By setInteresting() when we are now interested
@ -952,22 +950,32 @@ class PeerState implements DataLoader
isLastChunk = lastRequest.off + lastRequest.len == pieceLength;
// Last part of a piece?
if (isLastChunk)
more_pieces = requestNextPiece();
else
{
PartialPiece nextPiece = lastRequest.getPartialPiece();
int nextBegin = lastRequest.off + PARTSIZE;
int maxLength = pieceLength - nextBegin;
int nextLength = maxLength > PARTSIZE ? PARTSIZE
if (isLastChunk) {
more_pieces = requestNextPiece();
} else {
PartialPiece nextPiece = lastRequest.getPartialPiece();
int nextBegin = lastRequest.off + PARTSIZE;
while (true) {
// don't rerequest chunks we already have
if (!nextPiece.hasChunk(nextBegin / PARTSIZE)) {
int maxLength = pieceLength - nextBegin;
int nextLength = maxLength > PARTSIZE ? PARTSIZE
: maxLength;
Request req
= new Request(nextPiece,nextBegin, nextLength);
outstandingRequests.add(req);
if (!choked)
out.sendRequest(req);
lastRequest = req;
}
Request req = new Request(nextPiece,nextBegin, nextLength);
outstandingRequests.add(req);
if (!choked)
out.sendRequest(req);
lastRequest = req;
break;
} else {
nextBegin += PARTSIZE;
if (nextBegin >= pieceLength) {
more_pieces = requestNextPiece();
break;
}
}
}
}
}
}
}

View File

@ -371,7 +371,7 @@ class WebPeer extends Peer implements EepGet.StatusListener {
PartialPiece pp = last.getPartialPiece();
synchronized(pp) {
// Last chunk needed for this piece?
if (pp.getLength() == pp.getDownloaded()) {
if (pp.isComplete()) {
if (listener.gotPiece(this, pp)) {
if (_log.shouldDebug())
_log.debug("Got " + piece + ": " + this);
@ -650,15 +650,8 @@ class WebPeer extends Peer implements EepGet.StatusListener {
List<Request> rv = new ArrayList<Request>(pcs.size());
for (Integer p : pcs) {
Request req = getLowestOutstandingRequest(p.intValue());
if (req != null) {
PartialPiece pp = req.getPartialPiece();
synchronized(pp) {
int dl = pp.getDownloaded();
if (req.off != dl)
req = new Request(pp, dl);
}
if (req != null)
rv.add(req);
}
}
outstandingRequests.clear();
return rv;

View File

@ -98,7 +98,7 @@ button::-moz-focus-inner, input::-moz-focus-inner {
width: auto;
width: calc(100% - 22px);
text-align: center;
background: linear-gradient(to bottom, #fafaff 50%, #eef 51%, #eef 100%);
background: linear-gradient(to bottom, #fafaff 10%, #eef 70%, #eef 100%);
}
.iframed .snarknavbar {
@ -983,7 +983,7 @@ tr:hover .percentBarText {
border-top: 0;
border-radius: 0 0 3px 3px;
background: url(/themes/console/light/images/header.png) repeat-x scroll center center;
background: linear-gradient(to bottom, #fff 50%, #eef 51%) !important;
background: linear-gradient(to bottom, #fff 10%, #eef 70%) !important;
font-variant: small-caps !important;
box-shadow: 0 1px 2px #ccf, inset 0 0 0 1px #fff, inset 0 0 0 1px #fff;
display: inline-block;
@ -1000,7 +1000,7 @@ tr:hover .percentBarText {
}
.snarkConfigTitle:hover, .toggleview:hover, .snarkConfigTitle:active, .toggleview:active, input.toggle_input:focus + .toggleview {
background: linear-gradient(to bottom, #fcfaf7 50%, #ffe8bf 50%, #efd9b3 100%) !important;
background: linear-gradient(to bottom, #fcfaf7 10%, #ffe8bf 70%, #efd9b3 100%) !important;
}
@media screen and (-webkit-min-device-pixel-ratio:0) {

View File

@ -177,7 +177,7 @@ _:-ms-lang(x), .snarkNav:link, .snarkNav:visited {
.snarkNav:link:first-child, .snarkNav:last-child[href="/i2psnark/"] {
background: #310 url(images/button_snark.png) 11px center no-repeat;
background: url(images/button_snark.png) 11px center no-repeat, linear-gradient(to bottom, #a68058 1%, #7a6045 27%, #5e4730 50%, #2e1700 51%, #1f0f00 100%);
background: url(images/button_snark.png) 11px center no-repeat, linear-gradient(to bottom, #a68058 1%, #7a6045 10%, #5e4730 40%, #2e1700 90%, #1f0f00 100%);
background-size: 18px auto, 100% 100%;
padding-left: 28px !important;
}
@ -1286,7 +1286,7 @@ th.headerpriority br, .snarkTorrents thead th br {
}
.snarkConfigTitle:hover, .snarkConfigTitle:focus, label.toggleview:hover, label.toggleview:focus, .toggle_input:focus + label {
background: linear-gradient(to bottom, #5f475d 0%, #4f3b4f 50%, #1f001f 50%, #1f001f 100%) !important;
background: linear-gradient(to bottom, #5f475d 0%, #4f3b4f 20%, #1f001f 100%) !important;
box-shadow: inset 0 0 1px #3f173f;
color: #d2baff !important;
transition: ease all 0.1s;
@ -1305,7 +1305,7 @@ th.headerpriority br, .snarkTorrents thead th br {
border: 1px solid #101;
border-top: none;
background: #101 url(images/snarknav.png) repeat-x scroll center center;
background: linear-gradient(to bottom, #4a3d49 0%, #3d303d 50%, #0d000d 50%, #0d000d 100%) !important;
background: linear-gradient(to bottom, #4a3d49 0%, #3d303d 20%, #0d000d 100%) !important;
box-shadow: inset 0 0 1px 0 #313, 0 0 0 1px rgba(16, 0, 16, 0.4);
transition: ease all 0.1s;
}

View File

@ -141,7 +141,7 @@ th a:active, th a:visited:active, td a:active, td a:visited:active {
box-shadow: inset 0 0 0 1px #fff5ef, 0 0 1px 0 #4f3d36;
box-shadow: inset 0 0 0 1px #fff5ef, 0 0 0 1px rgba(111, 96, 90, 0.3), 0 0 1px 1px rgba(79, 61, 54, 0.5);
background: #efefef;
background: linear-gradient(to bottom, #efefef 50%, #cfc7c2 53%);
background: linear-gradient(to bottom, #efefef 15%, #cfc7c2 85%);
text-align: center;
transition: ease width 0.5s 0.5s;
}
@ -202,7 +202,7 @@ _:-ms-lang(x), .snarkNav:link, .snarkNav:visited {
.nav_main:link {
background: #fff7ef url(images/button_snark.png) 11px center no-repeat !important;
background: url(images/button_snark.png) 11px center no-repeat, linear-gradient(to bottom, #fff7ef 47%, rgba(207, 193, 181, 0.6) 50%), repeating-linear-gradient(45deg, #75604e 1px, #a09286 1px, #bfafa2 2px) !important;
background: url(images/button_snark.png) 11px center no-repeat, linear-gradient(to bottom, #fff7ef 20%, rgba(207, 193, 181, 0.6) 80%), repeating-linear-gradient(45deg, #75604e 1px, #a09286 1px, #bfafa2 2px) !important;
background-size: 18px auto, 100% 100%, 100% 100% !important;
}
@ -219,7 +219,7 @@ _:-ms-lang(x), .snarkNav:link, .snarkNav:visited {
.nav_main:hover, .nav_main:focus {
background: #ffeadf url(images/button_snark_hover.png) 11px center no-repeat !important;
background: url(images/button_snark_hover.png) 11px center no-repeat, linear-gradient(to bottom, #ffeadf 47%, #cfb6a8 50%) !important;
background: url(images/button_snark_hover.png) 11px center no-repeat, linear-gradient(to bottom, #ffeadf 20%, #cfb6a8 80%) !important;
background-size: 18px auto, 100% 100%, 100% 100% !important;
}
@ -235,7 +235,7 @@ _:-ms-lang(x), .snarkNav:link, .snarkNav:visited {
.nav_main:active {
background: #dfb899 url(images/button_snark_active.png) 11px center no-repeat !important;
background: url(images/button_snark_active.png) 11px center no-repeat, linear-gradient(to bottom, #dfb899 47%, #af9178 50%) !important;
background: url(images/button_snark_active.png) 11px center no-repeat, linear-gradient(to bottom, #dfb899 20%, #af9178 80%) !important;
background-size: 18px auto, 100% 100%, 100% 100% !important;
}
@ -1287,7 +1287,7 @@ input[type="submit"], .trackerconfig input[type="submit"], input[name="savepri"]
border: 1px solid #111;
border-top: 0;
background: #fff7ef;
background: linear-gradient(to bottom, #fff7ef 50%, rgba(207, 193, 181, 0.6) 50%), repeating-linear-gradient(135deg, #75604e 1px, #a09286 1px, #bfafa2 2px);
background: linear-gradient(to bottom, #fff7ef 20%, rgba(207, 193, 181, 0.6) 80%), repeating-linear-gradient(135deg, #75604e 1px, #a09286 1px, #bfafa2 2px);
color: #444039 !important;
box-shadow: 0 0 2px #4d453e, inset 0 0 0 1px #efe6e0;
display: inline-block;

View File

@ -372,6 +372,7 @@
<pathelement location="../../../core/java/build/i2p.jar" />
<!-- required for multipart form handling in register.jsp -->
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
<pathelement location="../../jetty/jettylib/jspc.jar" />
</classpath>
<arg value="-d" />
<arg value="../jsp/WEB-INF/classes" />

View File

@ -234,7 +234,10 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
try {
_filter = FilterFactory.createFilter(context, filterDefinition);
} catch (IOException | InvalidDefinitionException bad) {
throw new IllegalArgumentException("Bad filter definition file: " + bad.getMessage(), bad);
String msg = "Bad filter definition file: " + filterDefinition + " - filtering disabled: " + bad.getMessage();
_log.error(msg, bad);
l.log(msg);
_filter = null;
}
}

View File

@ -95,7 +95,7 @@ public class I2Ping extends I2PTunnelClientBase {
int remotePort = 0;
boolean error = false;
String[] argv = DataHelper.split(cmd, " ");
Getopt g = new Getopt("ping", argv, "t:m:n:chl:f:p:");
Getopt g = new Getopt("i2ping", argv, "t:m:n:chl:f:p:");
int c;
while ((c = g.getopt()) != -1) {
switch (c) {

View File

@ -236,7 +236,7 @@ class AccessFilter implements StatefulConnectionFilter {
syncer.schedule(SYNC_INTERVAL);
} catch (IOException bad) {
Log log = context.logManager().getLog(AccessFilter.class);
log.log(Log.CRIT, "syncing access list failed", bad);
log.error("syncing access list failed", bad);
}
}
});

View File

@ -8,7 +8,9 @@ import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.util.Log;
/**
* An element of filter definition that reads hashes of remote destinations
@ -55,7 +57,16 @@ class FileFilterDefinitionElement extends FilterDefinitionElement {
reader = new BufferedReader(new FileReader(file));
String b32;
while((b32 = reader.readLine()) != null) {
Hash hash = fromBase32(b32);
if (b32.length() == 0)
continue;
Hash hash;
try {
hash = fromBase32(b32);
} catch (InvalidDefinitionException bad32) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(FileFilterDefinitionElement.class);
log.error("Invalid access list entry \"" + b32 + "\" in " + file, bad32);
continue;
}
if (map.containsKey(hash))
continue;
DestTracker newTracker = new DestTracker(hash, threshold);
@ -64,8 +75,6 @@ class FileFilterDefinitionElement extends FilterDefinitionElement {
lastLoaded.put(hash, newTracker);
}
}
} catch (InvalidDefinitionException bad32) {
throw new IOException("invalid access list entry", bad32);
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException ignored) {}

View File

@ -451,7 +451,7 @@
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<copy todir="build/obj" file="resources/log4j.properties" />
<jar destfile="./jettylib/jetty-i2p.jar" basedir="./build/obj" includes="**/*.class log4j.properties" >
<jar destfile="./jettylib/jetty-i2p.jar" basedir="./build/obj" includes="**/*.class log4j.properties" excludes="**/JspC.class">
<manifest>
<attribute name="Implementation-Version" value="${full.version}" />
<attribute name="Built-By" value="${build.built-by}" />
@ -464,6 +464,9 @@
<attribute name="X-Compile-Target-JDK" value="${javac.version}" />
</manifest>
</jar>
<!-- separate jar for JspC wrapper used only in build, not included in jetty-i2p.jar -->
<jar destfile="./jettylib/jspc.jar" basedir="./build/obj" includes="**/JspC.class" >
</jar>
</target>
<target name="jarUpToDate">

View File

@ -32,6 +32,8 @@ import net.i2p.util.VersionComparator;
* https://bz.apache.org/bugzilla/show_bug.cgi?id=62674
*
* We could set fork=false in build.xml, but then the paths are all wrong.
*
* Warning - used in build process only, not included in runtime jars, not for external use.
* Only for use in build scripts, obviously not a public API.
* See apps/routerconsole/java/build.xml for more information.
*

View File

@ -392,6 +392,11 @@ public class RrdGraph implements RrdGraphConstants {
xaxisColor, stroke);
worker.drawLine(im.xorigin, im.yorigin + 4, im.xorigin, im.yorigin - im.ysize - 4,
yaxisColor, stroke);
// I2P skip arrowheads if transparent
if (((Color)arrowColor).getAlpha() == 0)
return;
//Do X axis arrow
double[] Xarrow_x = {
im.xorigin + im.xsize + 4,
@ -404,10 +409,6 @@ public class RrdGraph implements RrdGraphConstants {
};
worker.fillPolygon(Xarrow_x, im.yorigin + 3.0, Xarrow_y, arrowColor);
// I2P skip arrowheads if transparent
if (((Color)arrowColor).getAlpha() == 0)
return;
//Do y axis arrow
double[] Yarrow_x = {
im.xorigin - 3,

View File

@ -492,6 +492,7 @@
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
<pathelement location="${ant.home}/lib/ant.jar" />
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
<pathelement location="../../jetty/jettylib/jspc.jar" />
<pathelement location="../../systray/java/build/obj" />
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
<pathelement location="../../../installer/lib/wrapper/all/wrapper.jar" />

View File

@ -70,7 +70,15 @@ public class GraphHelper extends FormHandler {
ConfigRestartBean.getRestartTimeRemaining() < (1000 * (_refreshDelaySeconds + 30)))
return "";
// shorten the refresh by 3 seconds so we beat the iframe
return "<meta http-equiv=\"refresh\" content=\"" + (_refreshDelaySeconds - 3) + "\">";
return "<noscript><meta http-equiv=\"refresh\" content=\"" + (_refreshDelaySeconds - 3) + ";url=/graphs\" /></noscript>";
}
/**
* @since 0.9.63
*/
public int getRefresh() {
// shorten the refresh by 3 seconds so we beat the iframe
return _refreshDelaySeconds - 3;
}
public void setPeriodCount(String str) {

View File

@ -46,7 +46,7 @@
}
response.setHeader("X-XSS-Protection", "1; mode=block");
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture(), fullscreen=(self), geolocation=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), vibrate=(), vr=()");
response.setHeader("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=(), fullscreen=(self), geolocation=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), vibrate=(), vr=()");
// https://www.w3.org/TR/referrer-policy/
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
// As of Chrome 56, Firefox 50, Opera 43. "same-origin" not widely supported.

View File

@ -16,6 +16,12 @@
boolean allowRefresh = intl.allowIFrame(request.getHeader("User-Agent"));
if (allowRefresh) {
out.print(graphHelper.getRefreshMeta());
%>
<script nonce="<%=cspNonce%>" type="text/javascript">
var graphRefreshInterval = "<%=graphHelper.getRefresh()%>";
</script>
<script src="/js/graphs.js?<%=net.i2p.CoreVersion.VERSION%>" type="text/javascript"></script>
<%
}
%>
<%@include file="summaryajax.jsi" %>

View File

@ -0,0 +1,31 @@
/* I2P+ graphs.js by dr|z3d */
/* Ajax graph refresh and configuration toggle */
/* Adapted from I2P+, licensed to I2P under our license */
var __graphs_counter = 0;
function initGraphs() {
if (graphRefreshInterval > 0) {
setTimeout(updateGraphs, graphRefreshInterval * 1000);
}
}
function updateGraphs() {
const param = '&g=' + (++__graphs_counter);
var images = document.getElementsByClassName("statimage");
for (var i = 0; i < images.length; i++) {
let image = images[i];
// https://stackoverflow.com/questions/1077041/refresh-image-with-a-new-one-at-the-same-url
let idx = image.src.indexOf('&g=');
if (idx > 0) {
image.src = image.src.substring(0, idx) + param;
} else {
image.src = image.src + param;
}
}
setTimeout(updateGraphs, graphRefreshInterval * 1000);
}
document.addEventListener("DOMContentLoaded", function() {
initGraphs();
});

View File

@ -31,6 +31,7 @@
<pathelement location="${lib}/jasper-runtime.jar" />
<pathelement location="${lib}/jetty-util.jar" />
<pathelement location="${lib}/jetty-i2p.jar" />
<pathelement location="${lib}/jspc.jar" />
<pathelement location="${ant.home}/lib/ant.jar" />
<pathelement location="../../../core/java/build/i2p.jar" />
<pathelement location="../../addressbook/dist/addressbook.jar" />

View File

@ -17,9 +17,9 @@
<servlet-name>SusiMail</servlet-name>
<servlet-class>i2p.susi.webmail.WebMail</servlet-class>
<multipart-config>
<!-- 23 MB. See SMTPClient for discussion -->
<max-file-size>24117248</max-file-size>
<max-request-size>24117248</max-request-size>
<!-- 7.27 MB. See SMTPClient for discussion -->
<max-file-size>7629902</max-file-size>
<max-request-size>7629902</max-request-size>
<file-size-threshold>131072</file-size-threshold>
</multipart-config>
</servlet>

View File

@ -2278,7 +2278,7 @@ public class WebMail extends HttpServlet
response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self'; script-src 'self'; form-action 'self'; frame-ancestors 'self'; object-src 'none'; media-src 'none'; img-src 'self'");
response.setCharacterEncoding("UTF-8");
}
response.setHeader("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture(), fullscreen=(self), geolocation=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), vibrate=(), vr=()");
response.setHeader("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), display-capture=(), fullscreen=(self), geolocation=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), vibrate=(), vr=()");
response.setHeader("X-XSS-Protection", "1; mode=block");
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader("Referrer-Policy", "no-referrer");

View File

@ -51,14 +51,14 @@ import net.i2p.util.Log;
public class SMTPClient {
/**
* 31.84 MB
* smtp.postman.i2p as of 2017-12.
* 10.00 MB
* smtp.postman.i2p as of 2024-06-22.
* @since 0.9.33
*/
public static final long DEFAULT_MAX_SIZE = 33388608;
public static final long DEFAULT_MAX_SIZE = 10485760;
/**
* About 23.25 MB.
* 7629902 ~= 7.27 MB
* Base64 encodes 57 chars to 76 + \r\n on a line
* @since 0.9.33
*/

View File

@ -391,7 +391,7 @@
<target name="buildJetty" depends="buildCore" >
<ant dir="apps/jetty" target="build" />
<copy todir="build/" >
<fileset dir="apps/jetty/jettylib" excludes="ant.jar" />
<fileset dir="apps/jetty/jettylib" excludes="jspc.jar" />
</copy>
</target>

View File

@ -134,6 +134,14 @@ public class LeaseSet2 extends LeaseSet {
return _options.getProperty(opt);
}
/**
* @return not a copy, do not modify, or null
* @since 0.9.63
*/
public Properties getOptions() {
return _options;
}
/**
* If more than one key, return the first supported one.
* If none supported, return the first one.
@ -237,8 +245,7 @@ public class LeaseSet2 extends LeaseSet {
_options.clear();
else
_options = new OrderedProperties();
if (options != null)
_options.putAll(options);
_options.putAll(options);
}
public boolean isOffline() {

View File

@ -119,7 +119,7 @@ public class PrivateKeyFile {
double days = 365;
int mode = 0;
boolean error = false;
Getopt g = new Getopt("pkf", args, "t:nuxhse:c:a:o:d:r:p:b:y:z:w:");
Getopt g = new Getopt("PrivateKeyFile", args, "t:nuxhse:c:a:o:d:r:p:b:y:z:w:v:V:");
int c;
while ((c = g.getopt()) != -1) {
switch (c) {

View File

@ -1,5 +1,14 @@
2024-06-04 zzz
* Console: Add js refresh on /graphs (Gitlab MR !199)
* i2psnark:
- Fix leaked requests, partial pieces, and temp files (Gitlab MR !203)
- Make PEX more efficient
* Reseed: Increase min version when creating bundles; CLI improvements
* Router: Add synthetic stats for client and expl. build success rate
2024-06-01 zzz
* I2CP: Store local destination in lookup cache (Gitlab #482)
* Router: Don't update rates for full stats when not enabled
* Transport: Remove SSU1 code from UDPTransport (Gitlab MR !197)
2024-05-29 zzz

View File

@ -46,7 +46,7 @@ import net.i2p.util.FileUtil;
public class BundleRouterInfos {
/**
* Usage: PersistentDataStore -i configDir -o toDir -c count
* Usage: BundleRouterInfos -i configDir -o toDir -c count
*
* Copy a random selection of 'count' router infos from configDir/netDb
* to 'toDir'. Skip your own router info, and old, hidden, unreachable, and
@ -55,7 +55,7 @@ public class BundleRouterInfos {
* @since 0.9.15
*/
public static void main(String[] args) {
Getopt g = new Getopt("PersistentDataStore", args, "i:o:c:");
Getopt g = new Getopt("BundleRouterInfos", args, "i:o:c:");
String in = System.getProperty("user.home") + "/.i2p";
String out = "netDb";
int count = 200;

View File

@ -20,7 +20,7 @@ public class RouterVersion {
public final static String VERSION = CoreVersion.VERSION;
/** for example: "beta", "alpha", "rc" */
public final static String QUALIFIER = "";
public final static long BUILD = 4;
public final static long BUILD = 5;
/** for example "-test" */
public final static String EXTRA = "";
public final static String FULL_VERSION = VERSION + "-" + BUILD + QUALIFIER + EXTRA;

View File

@ -820,7 +820,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
}
/**
* Divide router limit by 1.75 for overhead.
* Divide router limit by 1.5 for overhead.
* This could someday give a different answer to each client.
* But it's not enforced anywhere.
*
@ -833,7 +833,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
int out = _context.bandwidthLimiter().getOutboundKBytesPerSecond();
int inb = _context.bandwidthLimiter().getInboundBurstKBytesPerSecond();
int outb = _context.bandwidthLimiter().getOutboundBurstKBytesPerSecond();
BandwidthLimitsMessage msg = new BandwidthLimitsMessage(in * 4 / 7, out * 4 / 7, in, inb, out, outb, 1);
BandwidthLimitsMessage msg = new BandwidthLimitsMessage(in * 2 / 3, out * 2 / 3, in, inb, out, outb, 1);
try {
_runner.doSend(msg);
} catch (I2CPMessageException ime) {

View File

@ -762,7 +762,7 @@ abstract class StoreJob extends JobImpl {
* Short ECIES tunnel build messages (1.5.0)
* @since 0.9.28
*/
public static final String MIN_STORE_VERSION = "0.9.51";
public static final String MIN_STORE_VERSION = "0.9.59";
/**
* Is it new enough?
@ -782,7 +782,7 @@ abstract class StoreJob extends JobImpl {
}
/** @since 0.9.38 */
public static final String MIN_STORE_LS2_VERSION = "0.9.51";
public static final String MIN_STORE_LS2_VERSION = "0.9.59";
/**
* Is it new enough?
@ -797,7 +797,7 @@ abstract class StoreJob extends JobImpl {
* Was supported in 38, but they're now sigtype 11 which wasn't added until 39
* @since 0.9.39
*/
public static final String MIN_STORE_ENCLS2_VERSION = "0.9.51";
public static final String MIN_STORE_ENCLS2_VERSION = "0.9.59";
/**
* Is it new enough?

View File

@ -47,8 +47,8 @@ public class ReseedBundler {
private final static String ROUTERINFO_PREFIX = "routerInfo-";
private final static String ROUTERINFO_SUFFIX = ".dat";
private static final int MINIMUM = 50;
/** NTCP2 */
private static final String MIN_VERSION = "0.9.36";
/** Same as in TunnelPeerSelector */
private static final String MIN_VERSION = "0.9.59";
public ReseedBundler(RouterContext ctx) {
_context = ctx;
@ -82,9 +82,12 @@ public class ReseedBundler {
}
if (ri.getPublished() < tooOld)
continue;
if (ri.getCapabilities().contains("U"))
String caps = ri.getCapabilities();
if (caps.contains("U"))
continue;
if (ri.getCapabilities().contains("K"))
if (caps.contains("K"))
continue;
if (caps.contains("G"))
continue;
if (VersionComparator.comp(ri.getVersion(), MIN_VERSION) < 0)
continue;

View File

@ -39,6 +39,7 @@ import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SSLEepGet;
import net.i2p.util.SystemVersion;
import net.i2p.util.Translate;
import net.i2p.util.VersionComparator;
/**
* Moved from ReseedHandler in routerconsole. See ReseedChecker for additional comments.
@ -69,6 +70,8 @@ public class Reseeder {
private static final int MIN_RESEED_SERVERS = 2;
// network ID cross-check, proposal 147, as of 0.9.42
private static final String NETID_PARAM = "?netid=";
/** Same as in TunnelPeerSelector */
private static final String MIN_VERSION = "0.9.59";
/**
* NOTE - URLs that are in both the standard and SSL groups must use the same hostname,
@ -1242,6 +1245,10 @@ public class Reseeder {
SSLEepGet.SSLState sslState = null;
I2PAppContext ctx = I2PAppContext.getGlobalContext();
for (String url : urls) {
if (!url.startsWith("https://"))
url = "https://" + url;
if (!url.endsWith("/"))
url += "/";
url += SU3_FILENAME + NETID_PARAM + '2';
URI uri = new URI(url);
String host = uri.getHost();
@ -1273,9 +1280,10 @@ public class Reseeder {
java.util.zip.ZipFile zipf = new java.util.zip.ZipFile(zip);
java.util.Enumeration<? extends java.util.zip.ZipEntry> entries = zipf.entries();
int ri = 0, old = 0;
int oldver = 0, unreach = 0;
while (entries.hasMoreElements()) {
java.util.zip.ZipEntry entry = (java.util.zip.ZipEntry) entries.nextElement();
net.i2p.data.router.RouterInfo r = new net.i2p.data.router.RouterInfo();
RouterInfo r = new RouterInfo();
InputStream in = zipf.getInputStream(entry);
r.readBytes(in);
in.close();
@ -1283,6 +1291,10 @@ public class Reseeder {
ri++;
else
old++;
if (VersionComparator.comp(r.getVersion(), MIN_VERSION) < 0)
oldver++;
if (r.getCapabilities().indexOf('U') >= 0)
unreach++;
}
zipf.close();
if (old > 0) {
@ -1300,6 +1312,7 @@ public class Reseeder {
System.out.println("Test failed for " + host + ", returned only " + ri + " router infos");
fail++;
}
System.out.println("Router infos included " + oldver + " with versions before " + MIN_VERSION + " and " + unreach + " unreachable");
} else {
System.out.println("Test failed for " + host + " return code: " + rc);
su3.delete();

View File

@ -44,6 +44,8 @@ public class CoalesceStatsEvent implements SimpleTimer.TimedEvent {
sm.createRateStat("router.integratedPeers", "Known integrated (floodfill) peers", "NetworkDatabase", new long[] { 60*1000 });
sm.createRateStat("router.knownPeers", "Known peers", "NetworkDatabase", new long[] { 60*1000 });
sm.createRequiredRateStat("router.tunnelBacklog", _x("Size of tunnel acceptor backlog"), "Tunnels", new long[] { 60*60*1000 });
sm.createRateStat("tunnel.buildClientSuccessRate", "Percent success", "Tunnels", new long[] { 60*1000 });
sm.createRateStat("tunnel.buildExploratorySuccessRate", "Percent success", "Tunnels", new long[] { 60*1000 });
_maxMemory = Runtime.getRuntime().maxMemory();
String legend = "(Bytes)";
if (_maxMemory < Long.MAX_VALUE)
@ -57,20 +59,12 @@ public class CoalesceStatsEvent implements SimpleTimer.TimedEvent {
int active = _ctx.commSystem().countActivePeers();
sm.addRateData("router.activePeers", active);
int activeSend = _ctx.commSystem().countActiveSendPeers();
sm.addRateData("router.activeSendPeers", activeSend);
int fast = _ctx.profileOrganizer().countFastPeers();
sm.addRateData("router.fastPeers", fast);
int highCap = _ctx.profileOrganizer().countHighCapacityPeers();
sm.addRateData("router.highCapacityPeers", highCap);
int integrated = _ctx.peerManager().countPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL);
sm.addRateData("router.integratedPeers", integrated);
sm.addRateData("router.knownPeers", _ctx.netDb().getKnownRouters());
sm.addRateData("bw.sendRate", (long)_ctx.bandwidthLimiter().getSendBps());
sm.addRateData("bw.recvRate", (long)_ctx.bandwidthLimiter().getReceiveBps());
@ -103,6 +97,48 @@ public class CoalesceStatsEvent implements SimpleTimer.TimedEvent {
sm.addRateData("bw.sendBps", (long)bps, 60*1000);
}
}
if (_ctx.getBooleanProperty("stat.full")) {
int activeSend = _ctx.commSystem().countActiveSendPeers();
sm.addRateData("router.activeSendPeers", activeSend);
int integrated = _ctx.peerManager().countPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL);
sm.addRateData("router.integratedPeers", integrated);
sm.addRateData("router.knownPeers", _ctx.netDb().getKnownRouters());
RateStat s1 = sm.getRate("tunnel.buildExploratorySuccess");
RateStat s2 = sm.getRate("tunnel.buildExploratoryExpire");
RateStat s3 = sm.getRate("tunnel.buildExploratoryReject");
if (s1 != null && s2 != null && s3 != null) {
Rate r1 = s1.getRate(10*60*1000);
Rate r2 = s2.getRate(10*60*1000);
Rate r3 = s3.getRate(10*60*1000);
if (r1 != null && r2 != null && r3 != null) {
long s = r1.getCurrentEventCount() + r1.getLastEventCount();
long t = s + r2.getCurrentEventCount() + r2.getLastEventCount() +
r3.getCurrentEventCount() + r3.getLastEventCount();
if (t > 0)
sm.addRateData("tunnel.buildExploratorySuccessRate", 100 * s / t, 60*1000);
}
}
s1 = sm.getRate("tunnel.buildClientSuccess");
s2 = sm.getRate("tunnel.buildClientExpire");
s3 = sm.getRate("tunnel.buildClientReject");
if (s1 != null && s2 != null && s3 != null) {
Rate r1 = s1.getRate(10*60*1000);
Rate r2 = s2.getRate(10*60*1000);
Rate r3 = s3.getRate(10*60*1000);
if (r1 != null && r2 != null && r3 != null) {
long s = r1.getCurrentEventCount() + r1.getLastEventCount();
long t = s + r2.getCurrentEventCount() + r2.getLastEventCount() +
r3.getCurrentEventCount() + r3.getLastEventCount();
if (t > 0)
sm.addRateData("tunnel.buildClientSuccessRate", 100 * s / t, 60*1000);
}
}
}
}
/**

View File

@ -352,7 +352,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
}
/** SSU2 fixes (2.1.0), Congestion fixes (2.2.0) */
private static final String MIN_VERSION = "0.9.58";
private static final String MIN_VERSION = "0.9.59";
/**
* Should the peer be excluded based on its published caps?

View File

@ -116,7 +116,7 @@ class LocalClientManager extends ClientManager {
int dropX1000 = 0, jitter = 0, latency = 0;
int port = ClientManagerFacadeImpl.DEFAULT_PORT;
boolean error = false;
Getopt g = new Getopt("router", args, "d:j:l:p:");
Getopt g = new Getopt("LocalClientManager", args, "d:j:l:p:");
try {
int c;
while ((c = g.getopt()) != -1) {