/* * TrackerInfo - Holds information returned by a tracker, mainly the peer list. * Copyright (C) 2003 Mark J. Wielaard * * This file is part of Snark. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * * Revised by Stephen L. Reed, Dec 22, 2009. * Reformatted, fixed Checkstyle, Findbugs and PMD violations, and substituted Log4J logger * for consistency with the Texai project. */ package org.texai.torrent; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.jboss.netty.buffer.ChannelBuffer; import org.texai.torrent.bencode.BDecoder; import org.texai.torrent.bencode.BEValue; import org.texai.torrent.bencode.InvalidBEncodingException; /** Holds information returned by a tracker, mainly the peer list */ public final class TrackerInfo { /** the logger */ private static final Logger LOGGER = Logger.getLogger(TrackerInfo.class); /** the failure reason */ private final String failure_reason; /** the tracking interval */ private final int interval; /** the tracked peer infos */ private final Set<TrackedPeerInfo> trackedPeerInfos; /** Constructs a new TrackerInfo instance. * * @param trackerResponseContent the tracker response content * @throws IOException when an input/output error occurs */ public TrackerInfo(final ChannelBuffer trackerResponseContent) throws IOException { //Preconditions assert trackerResponseContent != null : "trackerReponseContent must not be null"; assert trackerResponseContent.readableBytes() > 0 : "trackerResponseContent must not be empty"; final byte[] trackerResponseBytes = new byte[trackerResponseContent.readableBytes()]; trackerResponseContent.getBytes(0, trackerResponseBytes); final InputStream inputStream = new ByteArrayInputStream(trackerResponseBytes); final Map<String, BEValue> map = new BDecoder(inputStream).bdecodeMap().getMap(); LOGGER.info("map: " + map); final BEValue reason = map.get("failure reason"); if (reason == null) { failure_reason = null; final BEValue beInterval = map.get("interval"); if (beInterval == null) { throw new InvalidBEncodingException("No interval given"); } else { interval = beInterval.getInt(); } final BEValue bePeers = map.get("peers"); if (bePeers == null) { throw new InvalidBEncodingException("No peer list"); } else { assert bePeers.getValue() instanceof List<?>; trackedPeerInfos = getTrackedPeerInfos(bePeers.getList()); } } else { failure_reason = reason.getString(); interval = -1; trackedPeerInfos = null; } } /** Gets the tracked peer infos. * * @param beValueList the list of BEValues * @return tthe tracked peer infos * @throws IOException when an error occurs */ public static Set<TrackedPeerInfo> getTrackedPeerInfos(final List<BEValue> beValueList) throws IOException { //Preconditions assert beValueList != null : "beValueList must not be null"; final Set<TrackedPeerInfo> trackedPeerInfos = new HashSet<>(beValueList.size()); final Iterator<BEValue> beValueList_iter = beValueList.iterator(); while (beValueList_iter.hasNext()) { final TrackedPeerInfo trackedPeerInfo = new TrackedPeerInfo((beValueList_iter.next()).getMap()); trackedPeerInfos.add(trackedPeerInfo); } return trackedPeerInfos; } /** Gets the tracked peer infos. * * @return the tracked peer infos */ public Set<TrackedPeerInfo> getTrackedPeerInfos() { return trackedPeerInfos; } /** Gets the failure reason. * * @return the failure reason */ public String getFailureReason() { return failure_reason; } /** Gets the tracking interval. * * @return the tracking interval */ public int getInterval() { return interval; } /** Returns a string representation of this object. * * @return a string representation of this object */ @Override public String toString() { if (failure_reason == null) { return "[TrackerInfo interval: " + interval + ", tracked peer infos: " + trackedPeerInfos + "]"; } else { return "[TrackerInfo FAILED: " + failure_reason + "]"; } } }