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);
  }
  @Override
  protected void informResponse(
      TRTrackerAnnouncerHelper helper, TRTrackerAnnouncerResponse response) {
    URL url = response.getURL();

    // can be null for external plugins (e.g. mldht...)

    if (url != null) {

      synchronized (this) {
        String key = url.toExternalForm();

        StatusSummary summary = recent_responses.get(key);

        if (summary != null) {

          summary.updateFrom(response);
        }
      }
    }

    last_response_informed = response;

    // force recalc of best active next time

    last_best_active_set_time = 0;

    super.informResponse(helper, response);

    if (response.getStatus() != TRTrackerAnnouncerResponse.ST_ONLINE) {

      URL u = response.getURL();

      if (u != null) {

        String s = u.toExternalForm();

        synchronized (failed_urls) {
          if (failed_urls.contains(s)) {

            return;
          }

          failed_urls.add(s);
        }
      }

      checkActivation(true);
    }
  }