use of com.biglybt.pif.torrent.Torrent in project BiglyBT by BiglySoftware.
the class BuddyPlugin method initialize.
@Override
public void initialize(final PluginInterface _plugin_interface) {
plugin_interface = _plugin_interface;
ta_category = plugin_interface.getTorrentManager().getAttribute(TorrentAttribute.TA_CATEGORY);
logger = plugin_interface.getLogger().getChannel("Friends");
logger.setDiagnostic();
plugin_networks = new BuddyPluginNetwork[] { new BuddyPluginNetwork(plugin_interface, this, AENetworkClassifier.AT_PUBLIC), new BuddyPluginNetwork(plugin_interface, this, AENetworkClassifier.AT_I2P) };
final LocaleUtilities lu = plugin_interface.getUtilities().getLocaleUtilities();
Properties l10n_constants = new Properties();
l10n_constants.put("azbuddy.classic.link.url", Wiki.FRIENDS);
l10n_constants.put("azbuddy.dchat.link.url", Wiki.DECENTRALIZED_CHAT);
l10n_constants.put("azbuddy.profile.info.url", Wiki.FRIENDS_PUBLIC_PROFILE);
lu.integrateLocalisedMessageBundle(l10n_constants);
lu.addListener(new LocaleListener() {
@Override
public void localeChanged(Locale l) {
updateLocale(lu);
}
});
updateLocale(lu);
BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel("Views.plugins." + VIEW_ID + ".title");
// enabled
classic_enabled_param = config.addBooleanParameter2("azbuddy.enabled", "azbuddy.enabled", false);
ParameterTabFolder network_tab = config.createTabFolder();
ParameterGroup network_anon_item = null;
for (int i = 0; i < 2; i++) {
boolean is_pub_tab = i == 0;
String suffix = is_pub_tab ? "" : ".anon";
// nickname
StringParameter nick_param = config.addStringParameter2("azbuddy.nickname" + suffix, "azbuddy.nickname", "");
nick_param.setGenerateIntermediateEvents(false);
nick_param.addListener(new ParameterListener() {
@Override
public void parameterChanged(Parameter param) {
updateNickName(is_pub_tab, nick_param.getValue());
}
});
// online status
String[] os_values = STATUS_VALUES;
String[] os_labels = STATUS_STRINGS;
StringListParameter os_param = config.addStringListParameter2("azbuddy.online_status" + suffix, "azbuddy.online_status", os_values, os_labels, os_values[0]);
os_param.addListener(new ParameterListener() {
@Override
public void parameterChanged(Parameter param) {
updateOnlineStatus(is_pub_tab, Integer.parseInt(os_param.getValue()));
}
});
// If we add this then use proper message texts in the STATUS_STRINGS
os_param.setVisible(SUPPORT_ONLINE_STATUS);
StringParameter profile_param = config.addStringParameter2("azbuddy.profile.info" + suffix, "", "");
profile_param.setLabelText("<a href=\"" + MessageText.getString("azbuddy.profile.info.url") + "\">" + MessageText.getString("azbuddy.profile.info") + "</a>");
profile_param.setMultiLine(5);
profile_param.setGenerateIntermediateEvents(false);
profile_param.addListener(new ParameterListener() {
@Override
public void parameterChanged(Parameter param) {
updateProfiles();
}
});
ParameterGroup profile_group = config.createGroup(is_pub_tab ? "azbuddy.public.profile" : "azbuddy.anon.profile", new Parameter[] { profile_param });
ParameterGroup network_item = config.createGroup(is_pub_tab ? "label.public" : "label.anon", new Parameter[] { nick_param, os_param, profile_group });
if (is_pub_tab) {
nick_name_public_param = nick_param;
online_status_public_param = os_param;
profile_public_param = profile_param;
} else {
nick_name_anon_param = nick_param;
online_status_anon_param = os_param;
profile_anon_param = profile_param;
network_anon_item = network_item;
}
network_tab.addTab(network_item);
}
updateProfiles();
// protocol speed
final IntParameter protocol_speed = config.addIntParameter2("azbuddy.protocolspeed", "azbuddy.protocolspeed", 32);
protocol_speed.setMinimumRequiredUserMode(Parameter.MODE_ADVANCED);
ConnectionManager cman = plugin_interface.getConnectionManager();
int inbound_limit = protocol_speed.getValue() * 1024;
inbound_limiter = cman.createRateLimiter("buddy_up", inbound_limit);
outbound_limiter = cman.createRateLimiter("buddy_down", 0);
protocol_speed.addListener(new ParameterListener() {
@Override
public void parameterChanged(Parameter param) {
inbound_limiter.setRateLimitBytesPerSecond(protocol_speed.getValue() * 1024);
}
});
// chat notifications
enable_chat_notifications = config.addBooleanParameter2("azbuddy.enable_chat_notif", "azbuddy.enable_chat_notif", true);
// default published tags or cats
cat_pub = config.addStringParameter2("azbuddy.enable_cat_pub", "azbuddy.enable_cat_pub", "");
cat_pub.setGenerateIntermediateEvents(false);
setPublicTagsOrCategories(cat_pub.getValue(), false);
final BooleanParameter tracker_enable = config.addBooleanParameter2("azbuddy.tracker.enabled", "azbuddy.tracker.enabled", true);
final BooleanParameter tracker_so_enable = config.addBooleanParameter2("azbuddy.tracker.seeding.only.enabled", "azbuddy.tracker.seeding.only.enabled", false);
// nasty hack but the existing text has a \t prefix that causes UI weirdness but I don't want to change it and
// end up with missing translations...
tracker_so_enable.setLabelText(MessageText.getString("azbuddy.tracker.seeding.only.enabled").trim());
tracker_so_enable.setIndent(1, true);
final BooleanParameter buddies_lan_local = config.addBooleanParameter2("azbuddy.tracker.con.lan.local", "azbuddy.tracker.con.lan.local", true);
buddies_lan_local.addListener(new ParameterListener() {
@Override
public void parameterChanged(Parameter param) {
lan_local_peers = buddies_lan_local.getValue();
}
});
lan_local_peers = buddies_lan_local.getValue();
final BooleanParameter buddies_fp_enable = config.addBooleanParameter2("azbuddy.tracker.fp.enable", "azbuddy.tracker.fp.enable", true);
buddies_fp_enable.addListener(new ParameterListener() {
@Override
public void parameterChanged(Parameter param) {
fp_enable = buddies_fp_enable.getValue();
}
});
fp_enable = buddies_fp_enable.getValue();
cat_pub.addListener(new ParameterListener() {
@Override
public void parameterChanged(Parameter param) {
setPublicTagsOrCategories(cat_pub.getValue(), false);
}
});
config.createGroup("label.friends", new Parameter[] { classic_enabled_param, network_tab, protocol_speed, enable_chat_notifications, cat_pub, tracker_enable, tracker_so_enable, buddies_lan_local, buddies_fp_enable });
// decentralised stuff
beta_enabled_param = config.addBooleanParameter2("azbuddy.dchat.decentralized.enabled", "azbuddy.dchat.decentralized.enabled", true);
config.createGroup("azbuddy.dchat.decentralized", new Parameter[] { beta_enabled_param });
config.addLabelParameter2("azbuddy.dchat.more.settings");
// config end
beta_plugin = new BuddyPluginBeta(plugin_interface, this, beta_enabled_param);
for (String table_id : TableManager.TABLE_MYTORRENTS_ALL) {
TableContextMenuItem menu_item = plugin_interface.getUIManager().getTableManager().addContextMenuItem(table_id, "azbuddy.contextmenu");
menu_item.setStyle(TableContextMenuItem.STYLE_MENU);
menu_item.setHeaderCategory(MenuItem.HEADER_SOCIAL);
MenuItemFillListener menu_fill_listener = new MenuItemFillListener() {
@Override
public void menuWillBeShown(MenuItem menu, Object _target) {
menu.removeAllChildItems();
if (!(isClassicEnabled() && isAvailable())) {
menu.setEnabled(false);
return;
}
final List<Torrent> torrents = new ArrayList<>();
if (_target instanceof TableRow) {
addDownload(torrents, (TableRow) _target);
} else {
TableRow[] rows = (TableRow[]) _target;
for (TableRow row : rows) {
addDownload(torrents, row);
}
}
if (torrents.size() == 0) {
menu.setEnabled(false);
} else {
List<BuddyPluginBuddy> buddies = getBuddies();
for (int i = 0; i < buddies.size(); i++) {
final BuddyPluginBuddy buddy = (BuddyPluginBuddy) buddies.get(i);
boolean online = buddy.isOnline(true);
TableContextMenuItem item = plugin_interface.getUIManager().getTableManager().addContextMenuItem(menu_item, "!" + (buddy.getName() + (buddy.isPublicNetwork() ? "" : (" (" + MessageText.getString("label.anon.medium") + ")"))) + (online ? "" : (" - " + MessageText.getString("label.disconnected"))) + "!");
item.addMultiListener(new MenuItemListener() {
@Override
public void selected(MenuItem menu, Object target) {
for (Torrent torrent : torrents) {
buddy.getPluginNetwork().getAZ2Handler().sendAZ2Torrent(torrent, buddy);
}
}
});
item.setEnabled(online);
}
menu.setEnabled(true);
}
}
protected void addDownload(List<Torrent> torrents, TableRow row) {
Object obj = row.getDataSource();
Download download;
if (obj instanceof Download) {
download = (Download) obj;
} else {
DiskManagerFileInfo file = (DiskManagerFileInfo) obj;
try {
download = file.getDownload();
} catch (DownloadException e) {
Debug.printStackTrace(e);
return;
}
}
Torrent torrent = download.getTorrent();
if (torrent != null && !TorrentUtils.isReallyPrivate(PluginCoreUtils.unwrap(torrent))) {
torrents.add(torrent);
}
}
};
menu_item.addFillListener(menu_fill_listener);
}
buddy_tracker = new BuddyPluginTracker(this, tracker_enable, tracker_so_enable);
plugin_interface.getUIManager().addUIListener(new UIManagerListener() {
@Override
public void UIAttached(final UIInstance instance) {
if (instance.getUIType().equals(UIInstance.UIT_SWT)) {
try {
synchronized (swt_ui_waiters) {
swt_ui = (BuddyPluginViewInterface) Class.forName("com.biglybt.plugin.net.buddy.swt.BuddyPluginView").getConstructor(new Class[] { BuddyPlugin.class, UIInstance.class }).newInstance(new Object[] { BuddyPlugin.this, instance });
for (Runnable r : swt_ui_waiters) {
try {
r.run();
} catch (Throwable e) {
Debug.out(e);
}
}
swt_ui_waiters.clear();
}
} catch (Throwable e) {
Debug.out(e);
}
}
setupDisablePrompt(instance);
}
@Override
public void UIDetached(UIInstance instance) {
if (instance.getUIType().equals(UIInstance.UIT_SWT) && swt_ui != null) {
swt_ui.destroy();
swt_ui = null;
}
}
});
final ParameterGroup f_network_anon_item = network_anon_item;
ParameterListener enabled_listener = new ParameterListener() {
@Override
public void parameterChanged(Parameter param) {
boolean classic_enabled = classic_enabled_param.getValue();
nick_name_public_param.setEnabled(classic_enabled);
online_status_public_param.setEnabled(classic_enabled);
nick_name_anon_param.setEnabled(classic_enabled);
online_status_anon_param.setEnabled(classic_enabled);
protocol_speed.setEnabled(classic_enabled);
enable_chat_notifications.setEnabled(classic_enabled);
cat_pub.setEnabled(classic_enabled);
tracker_enable.setEnabled(classic_enabled);
tracker_so_enable.setEnabled(classic_enabled && tracker_enable.getValue());
buddies_lan_local.setEnabled(classic_enabled);
buddies_fp_enable.setEnabled(classic_enabled);
network_tab.setEnabled(classic_enabled);
f_network_anon_item.setEnabled(classic_enabled && I2PHelpers.isI2PInstalled());
if (param != null) {
for (BuddyPluginNetwork pn : plugin_networks) {
pn.setClassicEnabledInternal(classic_enabled);
}
fireEnabledStateChanged();
}
}
};
classic_enabled_param.addListener(enabled_listener);
beta_enabled_param.addListener(enabled_listener);
tracker_enable.addListener(enabled_listener);
for (BuddyPluginNetwork pn : plugin_networks) {
pn.loadConfig();
pn.registerMessageHandler();
}
plugin_interface.addListener(new PluginListener() {
@Override
public void initializationComplete() {
enabled_listener.parameterChanged(null);
final DelayedTask dt = plugin_interface.getUtilities().createDelayedTask(new Runnable() {
@Override
public void run() {
new AEThread2("BuddyPlugin:init", true) {
@Override
public void run() {
startup();
beta_plugin.startup();
initialization_complete.set(true);
}
}.start();
}
});
dt.queue();
}
@Override
public void closedownInitiated() {
// meh, moved this to core listener below as we need to closedown before
// i2p plugin so connections aren't torn down before we can tidily close
}
@Override
public void closedownComplete() {
}
});
CoreFactory.getSingleton().addLifecycleListener(new CoreLifecycleAdapter() {
@Override
public boolean syncInvokeRequired() {
return (true);
}
@Override
public void stopping(Core core) {
for (BuddyPluginNetwork pn : plugin_networks) {
pn.saveConfig(true);
pn.closedown();
}
beta_plugin.closedown();
}
});
}
use of com.biglybt.pif.torrent.Torrent in project BiglyBT by BiglySoftware.
the class BuddyPlugin method getRSS.
public FeedDetails getRSS(BuddyPluginBuddy buddy, String tag_or_category, String if_mod) throws BuddyPluginException {
if (!buddy.isLocalRSSTagOrCategoryAuthorised(tag_or_category)) {
throw (new BuddyPluginException("Unauthorised tag/category '" + tag_or_category + "'"));
}
buddy.localRSSTagOrCategoryRead(tag_or_category);
Download[] downloads = plugin_interface.getDownloadManager().getDownloads();
List<Download> selected_dls = new ArrayList<>();
long fingerprint = 0;
for (int i = 0; i < downloads.length; i++) {
Download download = downloads[i];
Torrent torrent = download.getTorrent();
if (torrent == null) {
continue;
}
boolean match = tag_or_category.equalsIgnoreCase("all");
if (!match) {
String dl_cat = download.getAttribute(ta_category);
match = dl_cat != null && dl_cat.equals(tag_or_category);
}
if (!match) {
try {
List<Tag> tags = TagManagerFactory.getTagManager().getTagsForTaggable(TagType.TT_DOWNLOAD_MANUAL, PluginCoreUtils.unwrap(download));
for (Tag tag : tags) {
if (tag.getTagName(true).equals(tag_or_category)) {
match = true;
break;
}
}
} catch (Throwable e) {
}
}
if (match) {
if (!TorrentUtils.isReallyPrivate(PluginCoreUtils.unwrap(torrent))) {
selected_dls.add(download);
byte[] hash = torrent.getHash();
int num = (hash[0] << 24) & 0xff000000 | (hash[1] << 16) & 0x00ff0000 | (hash[2] << 8) & 0x0000ff00 | hash[3] & 0x000000ff;
fingerprint += num;
}
}
}
PluginConfig pc = plugin_interface.getPluginconfig();
String feed_finger_key = "feed_finger.category." + tag_or_category;
String feed_date_key = "feed_date.category." + tag_or_category;
long existing_fingerprint = pc.getPluginLongParameter(feed_finger_key, 0);
long feed_date = pc.getPluginLongParameter(feed_date_key, 0);
long now = SystemTime.getCurrentTime();
if (existing_fingerprint == fingerprint) {
if (selected_dls.size() > 0) {
if (now < feed_date || now - feed_date > FEED_UPDATE_MIN_MILLIS) {
feed_date = now;
pc.setPluginParameter(feed_date_key, feed_date);
}
}
} else {
pc.setPluginParameter(feed_finger_key, fingerprint);
if (now <= feed_date) {
feed_date++;
} else {
feed_date = now;
}
pc.setPluginParameter(feed_date_key, feed_date);
}
String last_modified = TimeFormatter.getHTTPDate(feed_date);
if (if_mod != null && if_mod.equals(last_modified)) {
return (new FeedDetails(new byte[0], last_modified));
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
pw.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
pw.println("<rss version=\"2.0\" xmlns:vuze=\"http://www.vuze.com\">");
pw.println("<channel>");
pw.println("<title>" + escape(tag_or_category) + "</title>");
Collections.sort(selected_dls, new Comparator<Download>() {
@Override
public int compare(Download d1, Download d2) {
long added1 = getAddedTime(d1) / 1000;
long added2 = getAddedTime(d2) / 1000;
return ((int) (added2 - added1));
}
});
pw.println("<pubDate>" + last_modified + "</pubDate>");
for (int i = 0; i < selected_dls.size(); i++) {
Download download = (Download) selected_dls.get(i);
DownloadManager core_download = PluginCoreUtils.unwrap(download);
Torrent torrent = download.getTorrent();
String hash_str = Base32.encode(torrent.getHash());
pw.println("<item>");
pw.println("<title>" + escape(download.getName()) + "</title>");
pw.println("<guid>" + hash_str + "</guid>");
long added = core_download.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME);
pw.println("<pubDate>" + TimeFormatter.getHTTPDate(added) + "</pubDate>");
pw.println("<vuze:size>" + torrent.getSize() + "</vuze:size>");
pw.println("<vuze:assethash>" + hash_str + "</vuze:assethash>");
String url = "azplug:?id=azbuddy&name=Friends&arg=";
String arg = "pk=" + buddy.getPluginNetwork().getPublicKey() + "&cat=" + tag_or_category + "&hash=" + Base32.encode(torrent.getHash());
url += URLEncoder.encode(arg, "UTF-8");
pw.println("<vuze:downloadurl>" + escape(url) + "</vuze:downloadurl>");
DownloadScrapeResult scrape = download.getLastScrapeResult();
if (scrape != null && scrape.getResponseType() == DownloadScrapeResult.RT_SUCCESS) {
pw.println("<vuze:seeds>" + scrape.getSeedCount() + "</vuze:seeds>");
pw.println("<vuze:peers>" + scrape.getNonSeedCount() + "</vuze:peers>");
}
pw.println("</item>");
}
pw.println("</channel>");
pw.println("</rss>");
pw.flush();
return (new FeedDetails(os.toByteArray(), last_modified));
} catch (IOException e) {
throw (new BuddyPluginException("", e));
}
}
use of com.biglybt.pif.torrent.Torrent in project BiglyBT by BiglySoftware.
the class DHTTrackerPlugin method checkDownloadForRegistration.
protected void checkDownloadForRegistration(Download download, boolean first_time) {
if (download == null) {
return;
}
boolean skip_log = false;
int state = download.getState();
int register_type = REG_TYPE_NONE;
String register_reason;
Random random = new Random();
if (state == Download.ST_DOWNLOADING || state == Download.ST_SEEDING || // state == Download.ST_QUEUED ||
download.isPaused()) {
// pause is a transitory state, don't dereg
String[] networks = download.getListAttribute(ta_networks);
Torrent torrent = download.getTorrent();
if (torrent != null && networks != null) {
boolean public_net = false;
for (int i = 0; i < networks.length; i++) {
if (networks[i].equalsIgnoreCase("Public")) {
public_net = true;
break;
}
}
if (public_net && !torrent.isPrivate()) {
if (torrent.isDecentralised()) {
// peer source not relevant for decentralised torrents
register_type = REG_TYPE_FULL;
register_reason = "Decentralised";
} else {
if (torrent.isDecentralisedBackupEnabled() || TEST_ALWAYS_TRACK) {
String[] sources = download.getListAttribute(ta_peer_sources);
boolean ok = false;
if (sources != null) {
for (int i = 0; i < sources.length; i++) {
if (sources[i].equalsIgnoreCase("DHT")) {
ok = true;
break;
}
}
}
if (!(ok || TEST_ALWAYS_TRACK)) {
register_reason = "Decentralised peer source disabled";
} else {
// this will always be true since change to exclude queued...
boolean is_active = state == Download.ST_DOWNLOADING || state == Download.ST_SEEDING || download.isPaused();
if (is_active) {
register_type = REG_TYPE_DERIVED;
}
if (torrent.isDecentralisedBackupRequested() || TEST_ALWAYS_TRACK) {
register_type = REG_TYPE_FULL;
register_reason = TEST_ALWAYS_TRACK ? "Testing always track" : "Torrent requests decentralised tracking";
} else if (track_normal_when_offline.getValue()) {
if (is_active) {
DownloadAnnounceResult result = download.getLastAnnounceResult();
if (result == null || result.getResponseType() == DownloadAnnounceResult.RT_ERROR || TorrentUtils.isDecentralised(result.getURL())) {
register_type = REG_TYPE_FULL;
register_reason = "Tracker unavailable (announce)";
} else {
register_reason = "Tracker available (announce: " + result.getURL() + ")";
}
} else {
DownloadScrapeResult result = download.getLastScrapeResult();
if (result == null || result.getResponseType() == DownloadScrapeResult.RT_ERROR || TorrentUtils.isDecentralised(result.getURL())) {
register_type = REG_TYPE_FULL;
register_reason = "Tracker unavailable (scrape)";
} else {
register_reason = "Tracker available (scrape: " + result.getURL() + ")";
}
}
if (register_type != REG_TYPE_FULL && track_limited_when_online.getValue()) {
Boolean existing = (Boolean) limited_online_tracking.get(download);
boolean track_it = false;
if (existing != null) {
track_it = existing.booleanValue();
} else {
DownloadScrapeResult result = download.getLastScrapeResult();
if (result != null && result.getResponseType() == DownloadScrapeResult.RT_SUCCESS) {
int seeds = result.getSeedCount();
int leechers = result.getNonSeedCount();
int swarm_size = seeds + leechers;
if (swarm_size <= LIMITED_TRACK_SIZE) {
track_it = true;
} else {
track_it = random.nextInt(swarm_size) < LIMITED_TRACK_SIZE;
}
if (track_it) {
limited_online_tracking.put(download, Boolean.valueOf(track_it));
}
}
}
if (track_it) {
register_type = REG_TYPE_FULL;
register_reason = "Limited online tracking";
}
}
} else {
register_type = REG_TYPE_FULL;
register_reason = "Peer source enabled";
}
}
} else {
register_reason = "Decentralised backup disabled for the torrent";
}
}
} else {
if (public_net) {
register_reason = MessageText.getString("label.private");
} else {
register_reason = MessageText.getString("Scrape.status.networkdisabled");
}
}
} else {
register_reason = "Torrent is broken";
}
if (register_type == REG_TYPE_DERIVED) {
if (register_reason.length() == 0) {
register_reason = "Derived";
} else {
register_reason = "Derived (overriding ' " + register_reason + "')";
}
}
} else if (state == Download.ST_STOPPED || state == Download.ST_ERROR) {
register_reason = "Not running";
skip_log = true;
} else if (state == Download.ST_QUEUED) {
// leave in whatever state it current is (reg or not reg) to avoid thrashing
// registrations when seeding rules are start/queueing downloads
register_reason = "";
} else {
register_reason = "";
}
download.setUserData(LATEST_REGISTER_REASON, register_reason);
if (register_reason.length() > 0) {
try {
this_mon.enter();
int[] run_data = running_downloads.get(download);
if (register_type != REG_TYPE_NONE) {
if (run_data == null) {
log(download, "Monitoring: " + register_reason);
int[] cache = run_data_cache.remove(download);
if (cache == null) {
running_downloads.put(download, new int[] { register_type, 0, 0, 0, 0 });
} else {
cache[0] = register_type;
running_downloads.put(download, cache);
}
query_map.put(download, new Long(SystemTime.getCurrentTime()));
} else {
Integer existing_type = run_data[0];
if (existing_type.intValue() == REG_TYPE_DERIVED && register_type == REG_TYPE_FULL) {
// upgrade
run_data[0] = register_type;
}
}
} else {
if (run_data != null) {
if (!skip_log) {
log(download, "Not monitoring: " + register_reason);
}
running_downloads.remove(download);
run_data_cache.put(download, run_data);
// add back to interesting downloads for monitoring
interesting_downloads.put(download, new Long(plugin_interface.getUtilities().getCurrentSystemTime() + INTERESTING_INIT_MIN_OTHERS));
} else {
if (first_time && !skip_log) {
log(download, "Not monitoring: " + register_reason);
}
}
}
} finally {
this_mon.exit();
}
}
}
use of com.biglybt.pif.torrent.Torrent in project BiglyBT by BiglySoftware.
the class DHTTrackerPlugin method trackerGet.
protected int trackerGet(final Download download, final RegistrationDetails details, final boolean derived_only) {
final long start = SystemTime.getCurrentTime();
final Torrent torrent = download.getTorrent();
final URL url_to_report = torrent.isDecentralised() ? torrent.getAnnounceURL() : DEFAULT_URL;
trackerTarget[] targets = details.getTargets(false);
final long[] max_retry = { 0 };
boolean metadata_download = download.getFlag(Download.FLAG_METADATA_DOWNLOAD);
boolean do_alt = alt_lookup_handler != null && (metadata_download || (!(download.getFlag(Download.FLAG_LOW_NOISE) || download.getFlag(Download.FLAG_LIGHT_WEIGHT))));
int num_done = 0;
for (int i = 0; i < targets.length; i++) {
final trackerTarget target = targets[i];
int target_type = target.getType();
if (target_type == REG_TYPE_FULL && derived_only) {
continue;
} else if (target_type == REG_TYPE_DERIVED && dht.isSleeping()) {
continue;
}
increaseActive(download);
num_done++;
final boolean is_complete = isComplete(download);
dht.get(target.getHash(), download.getName() + ": " + target.getDesc("Announce"), is_complete ? DHTPlugin.FLAG_SEEDING : DHTPlugin.FLAG_DOWNLOADING, NUM_WANT, target_type == REG_TYPE_FULL ? ANNOUNCE_TIMEOUT : ANNOUNCE_DERIVED_TIMEOUT, false, false, new DHTPluginOperationListener() {
List<String> addresses = new ArrayList<>();
List<Integer> ports = new ArrayList<>();
List<Integer> udp_ports = new ArrayList<>();
List<Boolean> is_seeds = new ArrayList<>();
List<String> flags = new ArrayList<>();
int seed_count;
int leecher_count;
int i2p_seed_count;
int i2p_leecher_count;
volatile boolean complete;
{
if (do_alt) {
alt_lookup_handler.get(target.getHash(), is_complete, new DHTTrackerPluginAlt.LookupListener() {
@Override
public void foundPeer(InetSocketAddress address) {
alternativePeerRead(address);
}
@Override
public boolean isComplete() {
return (complete && addresses.size() > 5);
}
@Override
public void completed() {
}
});
}
}
@Override
public boolean diversified() {
return (true);
}
@Override
public void starts(byte[] key) {
}
private void alternativePeerRead(InetSocketAddress peer) {
boolean try_injection = metadata_download;
synchronized (this) {
if (complete) {
try_injection |= addresses.size() < 5;
} else {
try {
addresses.add(peer.getAddress().getHostAddress());
ports.add(peer.getPort());
udp_ports.add(peer.getPort());
flags.add(null);
is_seeds.add(false);
leecher_count++;
} catch (Throwable e) {
}
}
}
if (try_injection) {
PeerManager pm = download.getPeerManager();
if (pm != null) {
pm.peerDiscovered(PEPeerSource.PS_DHT, peer.getAddress().getHostAddress(), peer.getPort(), peer.getPort(), NetworkManager.getCryptoRequired(NetworkManager.CRYPTO_OVERRIDE_NONE));
}
}
}
@Override
public void valueRead(DHTPluginContact originator, DHTPluginValue value) {
String peer_ip = null;
int peer_tcp_port = 0;
int peer_udp_port = 0;
synchronized (this) {
if (complete) {
return;
}
try {
String[] tokens = new String(value.getValue()).split(";");
String tcp_part = tokens[0].trim();
int sep = tcp_part.indexOf(':');
String ip_str = null;
String tcp_port_str;
if (sep == -1) {
tcp_port_str = tcp_part;
} else {
ip_str = tcp_part.substring(0, sep);
tcp_port_str = tcp_part.substring(sep + 1);
}
int tcp_port = Integer.parseInt(tcp_port_str);
if (tcp_port > 0 && tcp_port < 65536) {
String flag_str = null;
int udp_port = -1;
boolean has_i2p = false;
try {
for (int i = 1; i < tokens.length; i++) {
String token = tokens[i].trim();
if (token.length() > 0) {
if (Character.isDigit(token.charAt(0))) {
udp_port = Integer.parseInt(token);
if (udp_port <= 0 || udp_port >= 65536) {
udp_port = -1;
}
} else {
flag_str = token;
if (flag_str.contains("I")) {
has_i2p = true;
}
}
}
}
} catch (Throwable e) {
}
peer_ip = ip_str == null ? originator.getAddress().getAddress().getHostAddress() : ip_str;
peer_tcp_port = tcp_port;
peer_udp_port = udp_port == -1 ? originator.getAddress().getPort() : udp_port;
addresses.add(peer_ip);
ports.add(peer_tcp_port);
udp_ports.add(peer_udp_port);
flags.add(flag_str);
if ((value.getFlags() & DHTPlugin.FLAG_DOWNLOADING) == 1) {
leecher_count++;
is_seeds.add(Boolean.FALSE);
if (has_i2p) {
i2p_leecher_count++;
}
} else {
is_seeds.add(Boolean.TRUE);
seed_count++;
if (has_i2p) {
i2p_seed_count++;
}
}
}
} catch (Throwable e) {
// in case we get crap back (someone spamming the DHT) just
// silently ignore
}
}
if (metadata_download && peer_ip != null) {
PeerManager pm = download.getPeerManager();
if (pm != null) {
pm.peerDiscovered(PEPeerSource.PS_DHT, peer_ip, peer_tcp_port, peer_udp_port, NetworkManager.getCryptoRequired(NetworkManager.CRYPTO_OVERRIDE_NONE));
}
}
}
@Override
public void valueWritten(DHTPluginContact target, DHTPluginValue value) {
}
@Override
public void complete(byte[] key, boolean timeout_occurred) {
synchronized (this) {
if (complete) {
return;
}
complete = true;
}
if (target.getType() == REG_TYPE_FULL || (target.getType() == REG_TYPE_DERIVED && seed_count + leecher_count > 1)) {
log(download, target.getDesc("Announce") + " completed (elapsed=" + TimeFormatter.formatColonMillis(SystemTime.getCurrentTime() - start) + "), addresses=" + addresses.size() + ", seeds=" + seed_count + ", leechers=" + leecher_count);
}
decreaseActive(download);
int peers_found = addresses.size();
List<DownloadAnnounceResultPeer> peers_for_announce = new ArrayList<>();
// scale min and max based on number of active torrents
// we don't want more than a few announces a minute
int announce_per_min = 4;
int num_active = query_map.size();
int announce_min = Math.max(ANNOUNCE_MIN_DEFAULT, (num_active / announce_per_min) * 60 * 1000);
int announce_max = derived_only ? ANNOUNCE_MAX_DERIVED_ONLY : ANNOUNCE_MAX;
announce_min = Math.min(announce_min, announce_max);
current_announce_interval = announce_min;
final long retry = announce_min + peers_found * (long) (announce_max - announce_min) / NUM_WANT;
int download_state = download.getState();
boolean we_are_seeding = download_state == Download.ST_SEEDING;
try {
this_mon.enter();
int[] run_data = running_downloads.get(download);
if (run_data != null) {
boolean full = target.getType() == REG_TYPE_FULL;
int peer_count = we_are_seeding ? leecher_count : (seed_count + leecher_count);
run_data[1] = full ? seed_count : Math.max(run_data[1], seed_count);
run_data[2] = full ? leecher_count : Math.max(run_data[2], leecher_count);
run_data[3] = full ? peer_count : Math.max(run_data[3], peer_count);
run_data[4] = (int) (SystemTime.getCurrentTime() / 1000);
long absolute_retry = SystemTime.getCurrentTime() + retry;
if (absolute_retry > max_retry[0]) {
// only update next query time if none set yet
// or we appear to have set the existing one. If we
// don't do this then we'll overwrite any rescheduled
// announces
Long existing = (Long) query_map.get(download);
if (existing == null || existing.longValue() == max_retry[0]) {
max_retry[0] = absolute_retry;
query_map.put(download, new Long(absolute_retry));
}
}
}
} finally {
this_mon.exit();
}
putDetails put_details = details.getPutDetails();
String ext_address = put_details.getIPOverride();
if (ext_address == null) {
ext_address = dht.getLocalAddress().getAddress().getAddress().getHostAddress();
}
if (put_details.hasI2P()) {
if (we_are_seeding) {
if (i2p_seed_count > 0) {
i2p_seed_count--;
}
} else {
if (i2p_leecher_count > 0) {
i2p_leecher_count--;
}
}
}
if (i2p_seed_count + i2p_leecher_count > 0) {
download.setUserData(DOWNLOAD_USER_DATA_I2P_SCRAPE_KEY, new int[] { i2p_seed_count, i2p_leecher_count });
} else {
download.setUserData(DOWNLOAD_USER_DATA_I2P_SCRAPE_KEY, null);
}
for (int i = 0; i < addresses.size(); i++) {
if (we_are_seeding && ((Boolean) is_seeds.get(i)).booleanValue()) {
continue;
}
// remove ourselves
String ip = (String) addresses.get(i);
if (ip.equals(ext_address)) {
if (((Integer) ports.get(i)).intValue() == put_details.getTCPPort() && ((Integer) udp_ports.get(i)).intValue() == put_details.getUDPPort()) {
continue;
}
}
final int f_i = i;
peers_for_announce.add(new DownloadAnnounceResultPeer() {
@Override
public String getSource() {
return (PEPeerSource.PS_DHT);
}
@Override
public String getAddress() {
return ((String) addresses.get(f_i));
}
@Override
public int getPort() {
return (((Integer) ports.get(f_i)).intValue());
}
@Override
public int getUDPPort() {
return (((Integer) udp_ports.get(f_i)).intValue());
}
@Override
public byte[] getPeerID() {
return (null);
}
@Override
public short getProtocol() {
String flag = (String) flags.get(f_i);
short protocol = DownloadAnnounceResultPeer.PROTOCOL_NORMAL;
if (flag != null) {
if (flag.contains("C")) {
protocol = DownloadAnnounceResultPeer.PROTOCOL_CRYPT;
}
}
return (protocol);
}
});
}
if (target.getType() == REG_TYPE_DERIVED && peers_for_announce.size() > 0) {
PeerManager pm = download.getPeerManager();
if (pm != null) {
// try some limited direct injection
List<DownloadAnnounceResultPeer> temp = new ArrayList<>(peers_for_announce);
Random rand = new Random();
for (int i = 0; i < DIRECT_INJECT_PEER_MAX && temp.size() > 0; i++) {
DownloadAnnounceResultPeer peer = temp.remove(rand.nextInt(temp.size()));
log(download, "Injecting derived peer " + peer.getAddress());
Map<Object, Object> user_data = new HashMap<>();
user_data.put(Peer.PR_PRIORITY_CONNECTION, Boolean.TRUE);
pm.addPeer(peer.getAddress(), peer.getPort(), peer.getUDPPort(), peer.getProtocol() == DownloadAnnounceResultPeer.PROTOCOL_CRYPT, user_data);
}
}
}
if (download_state == Download.ST_DOWNLOADING || download_state == Download.ST_SEEDING) {
final DownloadAnnounceResultPeer[] peers = new DownloadAnnounceResultPeer[peers_for_announce.size()];
peers_for_announce.toArray(peers);
download.setAnnounceResult(new DownloadAnnounceResult() {
@Override
public Download getDownload() {
return (download);
}
@Override
public int getResponseType() {
return (DownloadAnnounceResult.RT_SUCCESS);
}
@Override
public int getReportedPeerCount() {
return (peers.length);
}
@Override
public int getSeedCount() {
return (seed_count);
}
@Override
public int getNonSeedCount() {
return (leecher_count);
}
@Override
public String getError() {
return (null);
}
@Override
public URL getURL() {
return (url_to_report);
}
@Override
public DownloadAnnounceResultPeer[] getPeers() {
return (peers);
}
@Override
public long getTimeToWait() {
return (retry / 1000);
}
@Override
public Map getExtensions() {
return (null);
}
});
}
// only inject the scrape result if the torrent is decentralised. If we do this for
// "normal" torrents then it can have unwanted side-effects, such as stopping the torrent
// due to ignore rules if there are no downloaders in the DHT - bthub backup, for example,
// isn't scrapable...
// hmm, ok, try being a bit more relaxed about this, inject the scrape if
// we have any peers.
boolean inject_scrape = leecher_count > 0;
DownloadScrapeResult result = download.getLastScrapeResult();
if (result == null || result.getResponseType() == DownloadScrapeResult.RT_ERROR) {
} else {
synchronized (scrape_injection_map) {
int[] prev = (int[]) scrape_injection_map.get(download);
if (prev != null && prev[0] == result.getSeedCount() && prev[1] == result.getNonSeedCount()) {
inject_scrape = true;
}
}
}
if (torrent.isDecentralised() || inject_scrape) {
// make sure that the injected scrape values are consistent
// with our currently connected peers
PeerManager pm = download.getPeerManager();
int local_seeds = 0;
int local_leechers = 0;
if (pm != null) {
Peer[] dl_peers = pm.getPeers();
for (int i = 0; i < dl_peers.length; i++) {
Peer dl_peer = dl_peers[i];
if (dl_peer.getPercentDoneInThousandNotation() == 1000) {
local_seeds++;
} else {
local_leechers++;
}
}
}
final int f_adj_seeds = Math.max(seed_count, local_seeds);
final int f_adj_leechers = Math.max(leecher_count, local_leechers);
synchronized (scrape_injection_map) {
scrape_injection_map.put(download, new int[] { f_adj_seeds, f_adj_leechers });
}
try {
this_mon.enter();
int[] run_data = running_downloads.get(download);
if (run_data == null) {
run_data = run_data_cache.get(download);
}
if (run_data != null) {
run_data[1] = f_adj_seeds;
run_data[2] = f_adj_leechers;
run_data[4] = (int) (SystemTime.getCurrentTime() / 1000);
}
} finally {
this_mon.exit();
}
download.setScrapeResult(new DownloadScrapeResult() {
@Override
public Download getDownload() {
return (download);
}
@Override
public int getResponseType() {
return (DownloadScrapeResult.RT_SUCCESS);
}
@Override
public int getSeedCount() {
return (f_adj_seeds);
}
@Override
public int getNonSeedCount() {
return (f_adj_leechers);
}
@Override
public long getScrapeStartTime() {
return (start);
}
@Override
public void setNextScrapeStartTime(long nextScrapeStartTime) {
}
@Override
public long getNextScrapeStartTime() {
return (SystemTime.getCurrentTime() + retry);
}
@Override
public String getStatus() {
return ("OK");
}
@Override
public URL getURL() {
return (url_to_report);
}
});
}
}
});
}
return (num_done);
}
use of com.biglybt.pif.torrent.Torrent in project BiglyBT by BiglySoftware.
the class ExternalSeedPlugin method downloadAdded.
public void downloadAdded(Download download, boolean changed) {
Torrent torrent = download.getTorrent();
if (torrent == null) {
return;
}
List peers = new ArrayList();
for (int i = 0; i < factories.length; i++) {
String attributeID = "no-ext-seeds-1-" + factories[i].getClass().getSimpleName();
TorrentAttribute attribute = plugin_interface.getTorrentManager().getPluginAttribute(attributeID);
if (!changed) {
boolean noExternalSeeds = download.getBooleanAttribute(attribute);
if (noExternalSeeds) {
continue;
}
}
ExternalSeedReader[] x = factories[i].getSeedReaders(this, download);
if (x.length == 0) {
download.setBooleanAttribute(attribute, true);
} else {
for (int j = 0; j < x.length; j++) {
ExternalSeedReader reader = x[j];
ExternalSeedPeer peer = new ExternalSeedPeer(this, download, reader);
peers.add(peer);
}
}
}
addPeers(download, peers);
}
Aggregations