private TRTrackerAnnouncerHelper create( TOTorrent torrent, String[] networks, TOTorrentAnnounceURLSet[] sets) throws TRTrackerAnnouncerException { TRTrackerAnnouncerHelper announcer; boolean decentralised; if (sets.length == 0) { decentralised = TorrentUtils.isDecentralised(torrent.getAnnounceURL()); } else { decentralised = TorrentUtils.isDecentralised(sets[0].getAnnounceURLs()[0]); } if (decentralised) { announcer = new TRTrackerDHTAnnouncerImpl(torrent, networks, is_manual, getHelper()); } else { announcer = new TRTrackerBTAnnouncerImpl(torrent, sets, networks, is_manual, getHelper()); } for (TOTorrentAnnounceURLSet set : sets) { URL[] urls = set.getAnnounceURLs(); for (URL u : urls) { String key = u.toExternalForm(); StatusSummary summary = recent_responses.get(key); if (summary == null) { summary = new StatusSummary(announcer, u); recent_responses.put(key, summary); } else { summary.setHelper(announcer); } } } if (provider != null) { announcer.setAnnounceDataProvider(provider); } if (ip_override != null) { announcer.setIPOverride(ip_override); } return (announcer); }
private String getString(TOTorrentAnnounceURLSet[] sets) { StringBuffer str = new StringBuffer(); str.append("["); int num1 = 0; for (TOTorrentAnnounceURLSet s : sets) { if (num1++ > 0) { str.append(", "); } str.append("["); URL[] urls = s.getAnnounceURLs(); int num2 = 0; for (URL u : urls) { if (num2++ > 0) { str.append(", "); } str.append(u.toExternalForm()); } str.append("]"); } str.append("]"); return (str.toString()); }
public TrackerPeerSource getTrackerPeerSource(final TOTorrentAnnounceURLSet set) { URL[] urls = set.getAnnounceURLs(); final String[] url_strs = new String[urls.length]; for (int i = 0; i < urls.length; i++) { url_strs[i] = urls[i].toExternalForm(); } return (new TrackerPeerSource() { private StatusSummary _summary; private boolean enabled; private long fixup_time; private StatusSummary fixup() { long now = SystemTime.getMonotonousTime(); if (now - fixup_time > 1000) { long most_recent = 0; StatusSummary summary = null; synchronized (TRTrackerAnnouncerMuxer.this) { for (String str : url_strs) { StatusSummary s = recent_responses.get(str); if (s != null) { if (summary == null || s.getTime() > most_recent) { summary = s; most_recent = s.getTime(); } } } } if (provider != null) { enabled = provider.isPeerSourceEnabled(PEPeerSource.PS_BT_TRACKER); } if (summary != null) { _summary = summary; } fixup_time = now; } return (_summary); } public int getType() { return (TrackerPeerSource.TP_TRACKER); } public String getName() { StatusSummary summary = fixup(); if (summary != null) { String str = summary.getURL().toExternalForm(); int pos = str.indexOf('?'); if (pos != -1) { str = str.substring(0, pos); } return (str); } return (url_strs[0]); } public int getStatus() { StatusSummary summary = fixup(); if (!enabled) { return (ST_DISABLED); } if (summary != null) { return (summary.getStatus()); } return (ST_QUEUED); } public String getStatusString() { StatusSummary summary = fixup(); if (summary != null && enabled) { return (summary.getStatusString()); } return (null); } public int getSeedCount() { StatusSummary summary = fixup(); if (summary != null) { return (summary.getSeedCount()); } return (-1); } public int getLeecherCount() { StatusSummary summary = fixup(); if (summary != null) { return (summary.getLeecherCount()); } return (-1); } public int getCompletedCount() { StatusSummary summary = fixup(); if (summary != null) { return (summary.getCompletedCount()); } return (-1); } public int getPeers() { StatusSummary summary = fixup(); if (summary != null) { return (summary.getPeers()); } return (-1); } public int getLastUpdate() { StatusSummary summary = fixup(); if (summary != null) { long time = summary.getTime(); if (time == 0) { return (0); } long elapsed = SystemTime.getMonotonousTime() - time; return ((int) ((SystemTime.getCurrentTime() - elapsed) / 1000)); } return (0); } public int getSecondsToUpdate() { StatusSummary summary = fixup(); if (summary != null) { return (summary.getSecondsToUpdate()); } return (-1); } public int getInterval() { StatusSummary summary = fixup(); if (summary != null) { return (summary.getInterval()); } return (-1); } public int getMinInterval() { StatusSummary summary = fixup(); if (summary != null && enabled) { return (summary.getMinInterval()); } return (-1); } public boolean isUpdating() { StatusSummary summary = fixup(); if (summary != null && enabled) { return (summary.isUpdating()); } return (false); } public boolean canManuallyUpdate() { StatusSummary summary = fixup(); if (summary == null) { return (false); } return (summary.canManuallyUpdate()); } public void manualUpdate() { StatusSummary summary = fixup(); if (summary != null) { summary.manualUpdate(); } } }); }
protected void split() throws TRTrackerAnnouncerException { String[] networks = f_provider == null ? null : f_provider.getNetworks(); TRTrackerAnnouncerHelper to_activate = null; synchronized (this) { if (stopped || destroyed) { return; } TOTorrent torrent = getTorrent(); TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets(); // sanitise dht entries if (sets.length == 0) { sets = new TOTorrentAnnounceURLSet[] { torrent .getAnnounceURLGroup() .createAnnounceURLSet(new URL[] {torrent.getAnnounceURL()}) }; } else { boolean found_decentralised = false; boolean modified = false; for (int i = 0; i < sets.length; i++) { TOTorrentAnnounceURLSet set = sets[i]; URL[] urls = set.getAnnounceURLs().clone(); for (int j = 0; j < urls.length; j++) { URL u = urls[j]; if (u != null && TorrentUtils.isDecentralised(u)) { if (found_decentralised) { modified = true; urls[j] = null; } else { found_decentralised = true; } } } } if (modified) { List<TOTorrentAnnounceURLSet> s_list = new ArrayList<TOTorrentAnnounceURLSet>(); for (TOTorrentAnnounceURLSet set : sets) { URL[] urls = set.getAnnounceURLs(); List<URL> u_list = new ArrayList<URL>(urls.length); for (URL u : urls) { if (u != null) { u_list.add(u); } } if (u_list.size() > 0) { s_list.add( torrent .getAnnounceURLGroup() .createAnnounceURLSet(u_list.toArray(new URL[u_list.size()]))); } } sets = s_list.toArray(new TOTorrentAnnounceURLSet[s_list.size()]); } } List<TOTorrentAnnounceURLSet[]> new_sets = new ArrayList<TOTorrentAnnounceURLSet[]>(); if (is_manual || sets.length < 2) { new_sets.add(sets); } else { List<TOTorrentAnnounceURLSet> list = new ArrayList<TOTorrentAnnounceURLSet>(Arrays.asList(sets)); // often we have http:/xxxx/ and udp:/xxxx/ as separate groups - keep these together while (list.size() > 0) { TOTorrentAnnounceURLSet set1 = list.remove(0); boolean done = false; URL[] urls1 = set1.getAnnounceURLs(); if (urls1.length == 1) { URL url1 = urls1[0]; String prot1 = url1.getProtocol().toLowerCase(); String host1 = url1.getHost(); for (int i = 0; i < list.size(); i++) { TOTorrentAnnounceURLSet set2 = list.get(i); URL[] urls2 = set2.getAnnounceURLs(); if (urls2.length == 1) { URL url2 = urls2[0]; String prot2 = url2.getProtocol().toLowerCase(); String host2 = url2.getHost(); if (host1.equals(host2)) { if ((prot1.equals("udp") && prot2.startsWith("http")) || (prot2.equals("udp") && prot1.startsWith("http"))) { list.remove(i); new_sets.add(new TOTorrentAnnounceURLSet[] {set1, set2}); done = true; } } } } } if (!done) { new_sets.add(new TOTorrentAnnounceURLSet[] {set1}); } } } // work out the difference Iterator<TOTorrentAnnounceURLSet[]> ns_it = new_sets.iterator(); // need to copy list as we modify it and returned list ain't thread safe List<TRTrackerAnnouncerHelper> existing_announcers = new ArrayList<TRTrackerAnnouncerHelper>(announcers.getList()); List<TRTrackerAnnouncerHelper> new_announcers = new ArrayList<TRTrackerAnnouncerHelper>(); // first look for unchanged sets while (ns_it.hasNext()) { TOTorrentAnnounceURLSet[] ns = ns_it.next(); Iterator<TRTrackerAnnouncerHelper> a_it = existing_announcers.iterator(); while (a_it.hasNext()) { TRTrackerAnnouncerHelper a = a_it.next(); TOTorrentAnnounceURLSet[] os = a.getAnnounceSets(); if (same(ns, os)) { ns_it.remove(); a_it.remove(); new_announcers.add(a); break; } } } // reuse existing announcers // first remove dht ones from the equation TRTrackerAnnouncerHelper existing_dht_announcer = null; TOTorrentAnnounceURLSet[] new_dht_set = null; ns_it = new_sets.iterator(); while (ns_it.hasNext()) { TOTorrentAnnounceURLSet[] x = ns_it.next(); if (TorrentUtils.isDecentralised(x[0].getAnnounceURLs()[0])) { new_dht_set = x; ns_it.remove(); break; } } Iterator<TRTrackerAnnouncerHelper> an_it = existing_announcers.iterator(); while (an_it.hasNext()) { TRTrackerAnnouncerHelper a = an_it.next(); TOTorrentAnnounceURLSet[] x = a.getAnnounceSets(); if (TorrentUtils.isDecentralised(x[0].getAnnounceURLs()[0])) { existing_dht_announcer = a; an_it.remove(); break; } } if (existing_dht_announcer != null && new_dht_set != null) { new_announcers.add(existing_dht_announcer); } else if (existing_dht_announcer != null) { activated.remove(existing_dht_announcer); existing_dht_announcer.destroy(); } else if (new_dht_set != null) { TRTrackerAnnouncerHelper a = create(torrent, networks, new_dht_set); new_announcers.add(a); } // now do the non-dht ones ns_it = new_sets.iterator(); while (ns_it.hasNext() && existing_announcers.size() > 0) { TRTrackerAnnouncerHelper a = existing_announcers.remove(0); TOTorrentAnnounceURLSet[] s = ns_it.next(); ns_it.remove(); if (activated.contains(a) && torrent.getPrivate() && a instanceof TRTrackerBTAnnouncerImpl) { URL url = a.getTrackerURL(); if (url != null) { forceStop((TRTrackerBTAnnouncerImpl) a, networks, url); } } a.setAnnounceSets(s, networks); new_announcers.add(a); } // create any new ones required ns_it = new_sets.iterator(); while (ns_it.hasNext()) { TOTorrentAnnounceURLSet[] s = ns_it.next(); TRTrackerAnnouncerHelper a = create(torrent, networks, s); new_announcers.add(a); } // finally fix up the announcer list to represent the new state Iterator<TRTrackerAnnouncerHelper> a_it = announcers.iterator(); while (a_it.hasNext()) { TRTrackerAnnouncerHelper a = a_it.next(); if (!new_announcers.contains(a)) { a_it.remove(); try { if (activated.contains(a) && torrent.getPrivate() && a instanceof TRTrackerBTAnnouncerImpl) { URL url = a.getTrackerURL(); if (url != null) { forceStop((TRTrackerBTAnnouncerImpl) a, networks, url); } } } finally { if (Logger.isEnabled()) { Logger.log( new LogEvent( getTorrent(), LOGID, "Deactivating " + getString(a.getAnnounceSets()))); } activated.remove(a); a.destroy(); } } } a_it = new_announcers.iterator(); while (a_it.hasNext()) { TRTrackerAnnouncerHelper a = a_it.next(); if (!announcers.contains(a)) { announcers.add(a); } } if (!is_manual && announcers.size() > 0) { if (activated.size() == 0) { TRTrackerAnnouncerHelper a = announcers.get(0); if (Logger.isEnabled()) { Logger.log( new LogEvent(getTorrent(), LOGID, "Activating " + getString(a.getAnnounceSets()))); } activated.add(a); last_activation_time = SystemTime.getMonotonousTime(); if (provider != null) { to_activate = a; } } setupActivationCheck(ACT_CHECK_INIT_DELAY); } } if (to_activate != null) { if (complete) { to_activate.complete(true); } else { to_activate.update(false); } } }