forked from I2P_Developers/i2p.i2p
i2psnark: Enhancements to support RPC plugin
This commit is contained in:
@ -70,6 +70,7 @@ public class I2PSnarkUtil {
|
||||
private boolean _areFilesPublic;
|
||||
private List<String> _openTrackers;
|
||||
private DHT _dht;
|
||||
private long _startedTime;
|
||||
|
||||
private static final int EEPGET_CONNECT_TIMEOUT = 45*1000;
|
||||
private static final int EEPGET_CONNECT_TIMEOUT_SHORT = 5*1000;
|
||||
@ -260,6 +261,8 @@ public class I2PSnarkUtil {
|
||||
if (opts.getProperty(I2PClient.PROP_SIGTYPE) == null)
|
||||
opts.setProperty(I2PClient.PROP_SIGTYPE, "EdDSA_SHA512_Ed25519");
|
||||
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
||||
if (_manager != null)
|
||||
_startedTime = _context.clock().now();
|
||||
_connecting = false;
|
||||
}
|
||||
if (_shouldUseDHT && _manager != null && _dht == null)
|
||||
@ -295,6 +298,7 @@ public class I2PSnarkUtil {
|
||||
_dht.stop();
|
||||
_dht = null;
|
||||
}
|
||||
_startedTime = 0;
|
||||
I2PSocketManager mgr = _manager;
|
||||
// FIXME this can cause race NPEs elsewhere
|
||||
_manager = null;
|
||||
@ -310,6 +314,16 @@ public class I2PSnarkUtil {
|
||||
_tmpDir.mkdirs();
|
||||
}
|
||||
|
||||
/**
|
||||
* When did we connect to the network?
|
||||
* For RPC
|
||||
* @return 0 if not connected
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public long getStartedTime() {
|
||||
return _startedTime;
|
||||
}
|
||||
|
||||
/** connect to the given destination */
|
||||
I2PSocket connect(PeerID peer) throws IOException {
|
||||
I2PSocketManager mgr = _manager;
|
||||
|
@ -89,6 +89,7 @@ public class Peer implements Comparable<Peer>
|
||||
*/
|
||||
//private static final long OPTION_AZMP = 0x1000000000000000l;
|
||||
private long options;
|
||||
private final boolean _isIncoming;
|
||||
|
||||
/**
|
||||
* Outgoing connection.
|
||||
@ -103,6 +104,7 @@ public class Peer implements Comparable<Peer>
|
||||
this.infohash = infohash;
|
||||
this.metainfo = metainfo;
|
||||
_id = __id.incrementAndGet();
|
||||
_isIncoming = false;
|
||||
//_log.debug("Creating a new peer with " + peerID.toString(), new Exception("creating"));
|
||||
}
|
||||
|
||||
@ -130,6 +132,16 @@ public class Peer implements Comparable<Peer>
|
||||
_id = __id.incrementAndGet();
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Creating a new peer " + peerID.toString(), new Exception("creating " + _id));
|
||||
_isIncoming = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this an incoming connection?
|
||||
* For RPC
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public boolean isIncoming() {
|
||||
return _isIncoming;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,6 +28,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
@ -238,7 +239,8 @@ public class Snark
|
||||
// String indicating main activity
|
||||
private volatile String activity = "Not started";
|
||||
private final long savedUploaded;
|
||||
|
||||
private static final AtomicInteger __RPCID = new AtomicInteger();
|
||||
private final int _rpcID = __RPCID.incrementAndGet();
|
||||
|
||||
/**
|
||||
* from main() via parseArguments() single torrent
|
||||
@ -1364,4 +1366,13 @@ public class Snark
|
||||
long limit = 1024l * _util.getMaxUpBW();
|
||||
return total > limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* A unique ID for this torrent, useful for RPC
|
||||
* @return positive value unless you wrap around
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public int getRPCID() {
|
||||
return _rpcID;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.app.ClientApp;
|
||||
import net.i2p.app.ClientAppManager;
|
||||
import net.i2p.app.ClientAppState;
|
||||
import net.i2p.crypto.SHA1Hash;
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.data.Base64;
|
||||
@ -51,7 +53,7 @@ import org.klomp.snark.dht.KRPC;
|
||||
/**
|
||||
* Manage multiple snarks
|
||||
*/
|
||||
public class SnarkManager implements CompleteListener {
|
||||
public class SnarkManager implements CompleteListener, ClientApp {
|
||||
|
||||
/**
|
||||
* Map of (canonical) filename of the .torrent file to Snark instance.
|
||||
@ -246,6 +248,13 @@ public class SnarkManager implements CompleteListener {
|
||||
*/
|
||||
public void start() {
|
||||
_running = true;
|
||||
if ("i2psnark".equals(_contextName)) {
|
||||
// Register with the ClientAppManager so the rpc plugin can find us
|
||||
// only if default instance
|
||||
ClientAppManager cmgr = _context.clientAppManager();
|
||||
if (cmgr != null)
|
||||
cmgr.register(this);
|
||||
}
|
||||
_peerCoordinatorSet = new PeerCoordinatorSet();
|
||||
_connectionAcceptor = new ConnectionAcceptor(_util, _peerCoordinatorSet);
|
||||
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
|
||||
@ -315,6 +324,12 @@ public class SnarkManager implements CompleteListener {
|
||||
_connectionAcceptor.halt();
|
||||
_idleChecker.cancel();
|
||||
stopAllTorrents(true);
|
||||
if ("i2psnark".equals(_contextName)) {
|
||||
// only if default instance
|
||||
ClientAppManager cmgr = _context.clientAppManager();
|
||||
if (cmgr != null)
|
||||
cmgr.unregister(this);
|
||||
}
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Snark stop() end");
|
||||
}
|
||||
@ -322,6 +337,46 @@ public class SnarkManager implements CompleteListener {
|
||||
/** @since 0.9.1 */
|
||||
public boolean isStopping() { return _stopping; }
|
||||
|
||||
/**
|
||||
* ClientApp method. Does nothing.
|
||||
* Doesn't matter, we are only registering.
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public void startup() {}
|
||||
|
||||
/**
|
||||
* ClientApp method. Does nothing.
|
||||
* Doesn't matter, we are only registering.
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public void shutdown(String[] args) {}
|
||||
|
||||
/**
|
||||
* ClientApp method.
|
||||
* Doesn't matter, we are only registering.
|
||||
* @return INITIALIZED always.
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public ClientAppState getState() {
|
||||
return ClientAppState.INITIALIZED;
|
||||
}
|
||||
|
||||
/**
|
||||
* ClientApp method.
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public String getName() {
|
||||
return "i2psnark";
|
||||
}
|
||||
|
||||
/**
|
||||
* ClientApp method.
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return "i2psnark: " + _contextPath;
|
||||
}
|
||||
|
||||
/** hook to I2PSnarkUtil for the servlet */
|
||||
public I2PSnarkUtil util() { return _util; }
|
||||
|
||||
@ -440,6 +495,14 @@ public class SnarkManager implements CompleteListener {
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* For RPC
|
||||
* @since 0.9.30
|
||||
*/
|
||||
public File getConfigDir() {
|
||||
return _configDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate the old flat config file to the new config dir
|
||||
* containing the config file minus the per-torrent entries,
|
||||
@ -1526,9 +1589,9 @@ public class SnarkManager implements CompleteListener {
|
||||
* Called from servlet. This is only for the 'create torrent' form.
|
||||
*
|
||||
* @param metainfo the metainfo for the torrent
|
||||
* @param bitfield the current completion status of the torrent
|
||||
* @param bitfield the current completion status of the torrent, or null
|
||||
* @param filename the absolute path to save the metainfo to, generally ending in ".torrent", which is also the name of the torrent
|
||||
* Must be a filesystem-safe name.
|
||||
* Must be a filesystem-safe name. If null, will generate a name from the metainfo.
|
||||
* @param baseFile may be null, if so look in rootDataDir
|
||||
* @throws RuntimeException via Snark.fatal()
|
||||
* @return success
|
||||
@ -1542,10 +1605,18 @@ public class SnarkManager implements CompleteListener {
|
||||
if (snark != null) {
|
||||
addMessage(_t("Torrent with this info hash is already running: {0}", snark.getBaseName()));
|
||||
return false;
|
||||
} else {
|
||||
} else if (bitfield != null) {
|
||||
saveTorrentStatus(metainfo, bitfield, null, baseFile, true, 0, true); // no file priorities
|
||||
}
|
||||
// so addTorrent won't recheck
|
||||
if (filename == null) {
|
||||
File f = new File(getDataDir(), Storage.filterName(metainfo.getName()) + ".torrent");
|
||||
if (f.exists()) {
|
||||
addMessage(_t("Failed to copy torrent file to {0}", f.getAbsolutePath()));
|
||||
_log.error("Torrent file already exists: " + f);
|
||||
}
|
||||
filename = f.getAbsolutePath();
|
||||
}
|
||||
try {
|
||||
locked_writeMetaInfo(metainfo, filename, areFilesPublic());
|
||||
// hold the lock for a long time
|
||||
|
Reference in New Issue
Block a user