2005-12-16 jrandom
* Added some I2PSnark sanity checks, an OOMListener when running standalone, and a guard against keeping memory tied up indefinitely. * Sanity check on the watchdog (thanks zzz!) * Handle invalid HTTP requests in I2PTunnel a little better
This commit is contained in:
@ -26,6 +26,7 @@ import java.util.*;
|
||||
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
|
||||
class PeerConnectionOut implements Runnable
|
||||
{
|
||||
@ -94,6 +95,8 @@ class PeerConnectionOut implements Runnable
|
||||
// being send even if we get unchoked a little later.
|
||||
// (Since we will resent them anyway in that case.)
|
||||
// And remove piece messages if we are choking.
|
||||
|
||||
// this should get fixed for starvation
|
||||
Iterator it = sendQueue.iterator();
|
||||
while (m == null && it.hasNext())
|
||||
{
|
||||
@ -177,10 +180,30 @@ class PeerConnectionOut implements Runnable
|
||||
*/
|
||||
private void addMessage(Message m)
|
||||
{
|
||||
SimpleTimer.getInstance().addEvent(new RemoveTooSlow(m), SEND_TIMEOUT);
|
||||
synchronized(sendQueue)
|
||||
{
|
||||
sendQueue.add(m);
|
||||
sendQueue.notify();
|
||||
sendQueue.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/** remove messages not sent in 30s */
|
||||
private static final int SEND_TIMEOUT = 30*1000;
|
||||
private class RemoveTooSlow implements SimpleTimer.TimedEvent {
|
||||
private Message _m;
|
||||
public RemoveTooSlow(Message m) {
|
||||
_m = m;
|
||||
}
|
||||
|
||||
public void timeReached() {
|
||||
boolean removed = false;
|
||||
synchronized (sendQueue) {
|
||||
removed = sendQueue.remove(_m);
|
||||
sendQueue.notifyAll();
|
||||
}
|
||||
if (removed)
|
||||
_log.info("Took too long to send " + _m + " to " + peer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,6 +229,7 @@ class PeerConnectionOut implements Runnable
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
sendQueue.notifyAll();
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.klomp.snark.bencode.*;
|
||||
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.util.I2PThread;
|
||||
|
||||
/**
|
||||
* Main Snark program startup class.
|
||||
@ -87,12 +88,26 @@ public class Snark
|
||||
// String indicating main activity
|
||||
String activity = "Not started";
|
||||
|
||||
private static class OOMListener implements I2PThread.OOMEventListener {
|
||||
public void outOfMemory(OutOfMemoryError err) {
|
||||
try {
|
||||
err.printStackTrace();
|
||||
I2PSnarkUtil.instance().debug("OOM in the snark", Snark.ERROR, err);
|
||||
} catch (Throwable t) {
|
||||
System.out.println("OOM in the OOM");
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
System.out.println(copyright);
|
||||
System.out.println();
|
||||
|
||||
if ( (args.length > 0) && ("--config".equals(args[0])) ) {
|
||||
I2PThread.addOOMEventListener(new OOMListener());
|
||||
SnarkManager sm = SnarkManager.instance();
|
||||
if (args.length > 1)
|
||||
sm.loadConfig(args[1]);
|
||||
|
@ -281,10 +281,10 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
fis.close();
|
||||
fis = null;
|
||||
|
||||
List files = info.getFiles();
|
||||
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
|
||||
String rejectMessage = locked_validateTorrent(info);
|
||||
if (rejectMessage != null) {
|
||||
sfile.delete();
|
||||
addMessage("Too many files in " + sfile.getName() + " (" + files.size() + "), deleting it");
|
||||
addMessage(rejectMessage);
|
||||
return;
|
||||
} else {
|
||||
torrent = new Snark(filename, null, -1, null, null, false, dataDir.getPath());
|
||||
@ -313,6 +313,28 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
|
||||
private String locked_validateTorrent(MetaInfo info) throws IOException {
|
||||
List files = info.getFiles();
|
||||
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
|
||||
return "Too many files in " + info.getName() + " (" + files.size() + "), deleting it";
|
||||
} else if (info.getPieces() <= 0) {
|
||||
return "No pieces in " + info.getName() + "? deleting it";
|
||||
} else if (info.getPieceLength(0) > 1024*1024) {
|
||||
return "Pieces are too large in " + info.getName() + " (" + info.getPieceLength(0)/1024 + "KB, deleting it";
|
||||
} else if (info.getTotalLength() > 10*1024*1024*1024l) {
|
||||
System.out.println("torrent info: " + info.toString());
|
||||
List lengths = info.getLengths();
|
||||
if (lengths != null)
|
||||
for (int i = 0; i < lengths.size(); i++)
|
||||
System.out.println("File " + i + " is " + lengths.get(i) + " long");
|
||||
|
||||
return "Torrents larger than 10GB are not supported yet (because we're paranoid): " + info.getName() + ", deleting it";
|
||||
} else {
|
||||
// ok
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the torrent, leaving it on the list of torrents unless told to remove it
|
||||
*/
|
||||
|
@ -172,6 +172,10 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if ( (snark != null) && (DataHelper.eq(infoHash, snark.meta.getInfoHash())) ) {
|
||||
_manager.stopTorrent(name, true);
|
||||
// should we delete the torrent file?
|
||||
// yeah, need to, otherwise it'll get autoadded again (at the moment
|
||||
File f = new File(name);
|
||||
f.delete();
|
||||
_manager.addMessage("Torrent file deleted: " + f.getAbsolutePath());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -386,6 +386,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
} else {
|
||||
request = request.substring(pos + 1);
|
||||
pos = request.indexOf("/");
|
||||
if (pos < 0) {
|
||||
l.log("Invalid request url [" + request + "]");
|
||||
if (out != null) {
|
||||
out.write(ERR_REQUEST_DENIED);
|
||||
out.write("<p /><i>Generated on: ".getBytes());
|
||||
out.write(new Date().toString().getBytes());
|
||||
out.write("</i></body></html>\n".getBytes());
|
||||
out.flush();
|
||||
}
|
||||
s.close();
|
||||
return;
|
||||
}
|
||||
destination = request.substring(0, pos);
|
||||
line = method + " " + request.substring(pos);
|
||||
}
|
||||
|
@ -1,4 +1,10 @@
|
||||
$Id: history.txt,v 1.359 2005/12/16 06:01:20 jrandom Exp $
|
||||
$Id: history.txt,v 1.360 2005/12/16 18:18:56 jrandom Exp $
|
||||
|
||||
2005-12-16 jrandom
|
||||
* Added some I2PSnark sanity checks, an OOMListener when running
|
||||
standalone, and a guard against keeping memory tied up indefinitely.
|
||||
* Sanity check on the watchdog (thanks zzz!)
|
||||
* Handle invalid HTTP requests in I2PTunnel a little better
|
||||
|
||||
2005-12-16 jrandom
|
||||
* Moved I2PSnark from using Threads to I2PThreads, so we handle OOMs
|
||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.310 $ $Date: 2005/12/13 16:56:42 $";
|
||||
public final static String ID = "$Revision: 1.311 $ $Date: 2005/12/14 04:32:51 $";
|
||||
public final static String VERSION = "0.6.1.7";
|
||||
public final static long BUILD = 4;
|
||||
public final static long BUILD = 5;
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
@ -91,7 +91,14 @@ class RouterWatchdog implements Runnable {
|
||||
public void monitorRouter() {
|
||||
boolean ok = verifyJobQueueLiveliness();
|
||||
// If we aren't connected to the network that's why there's nobody to talk to
|
||||
int netErrors = (int) _context.statManager().getRate("udp.sendException").getRate(60*1000).getLastEventCount();
|
||||
long netErrors = 0;
|
||||
RateStat rs = _context.statManager().getRate("udp.sendException");
|
||||
if (rs != null) {
|
||||
Rate r = rs.getRate(60*1000);
|
||||
if (r != null)
|
||||
netErrors = r.getLastEventCount();
|
||||
}
|
||||
|
||||
ok = ok && (verifyClientLiveliness() || netErrors >= 5);
|
||||
|
||||
if (!ok) {
|
||||
|
Reference in New Issue
Block a user