Package com.turn.ttorrent.tracker

Source Code of com.turn.ttorrent.tracker.TrackedPeer

/**
* Copyright (C) 2011-2012 Turn, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.turn.ttorrent.tracker;

import com.turn.ttorrent.bcodec.BEValue;
import com.turn.ttorrent.common.Peer;
import com.turn.ttorrent.common.Torrent;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* A BitTorrent tracker peer.
*
* <p>
* Represents a peer exchanging on a given torrent. In this implementation,
* we don't really care about the status of the peers and how much they
* have downloaded / exchanged because we are not a torrent exchange and
* don't need to keep track of what peers are doing while they're
* downloading. We only care about when they start, and when they are done.
* </p>
*
* <p>
* We also never expire peers automatically. Unless peers send a STOPPED
* announce request, they remain as long as the torrent object they are a
* part of.
* </p>
*/
public class TrackedPeer extends Peer {

  private static final Logger logger =
    LoggerFactory.getLogger(TrackedPeer.class);

  private static final int FRESH_TIME_SECONDS = 30;

  private long uploaded;
  private long downloaded;
  private long left;
  private Torrent torrent;

  /**
   * Represents the state of a peer exchanging on this torrent.
   *
   * <p>
   * Peers can be in the STARTED state, meaning they have announced
   * themselves to us and are eventually exchanging data with other peers.
   * Note that a peer starting with a completed file will also be in the
   * started state and will never notify as being in the completed state.
   * This information can be inferred from the fact that the peer reports 0
   * bytes left to download.
   * </p>
   *
   * <p>
   * Peers enter the COMPLETED state when they announce they have entirely
   * downloaded the file. As stated above, we may also elect them for this
   * state if they report 0 bytes left to download.
   * </p>
   *
   * <p>
   * Peers enter the STOPPED state very briefly before being removed. We
   * still pass them to the STOPPED state in case someone else kept a
   * reference on them.
   * </p>
   */
  public enum PeerState {
    UNKNOWN,
    STARTED,
    COMPLETED,
    STOPPED;
  };

  private PeerState state;
  private Date lastAnnounce;

  /**
   * Instantiate a new tracked peer for the given torrent.
   *
   * @param torrent The torrent this peer exchanges on.
   * @param ip The peer's IP address.
   * @param port The peer's port.
   * @param peerId The byte-encoded peer ID.
   */
  public TrackedPeer(Torrent torrent, String ip, int port,
      ByteBuffer peerId) {
    super(ip, port, peerId);
    this.torrent = torrent;

    // Instantiated peers start in the UNKNOWN state.
    this.state = PeerState.UNKNOWN;
    this.lastAnnounce = null;

    this.uploaded = 0;
    this.downloaded = 0;
    this.left = 0;
  }

  /**
   * Update this peer's state and information.
   *
   * <p>
   * <b>Note:</b> if the peer reports 0 bytes left to download, its state will
   * be automatically be set to COMPLETED.
   * </p>
   *
   * @param state The peer's state.
   * @param uploaded Uploaded byte count, as reported by the peer.
   * @param downloaded Downloaded byte count, as reported by the peer.
   * @param left Left-to-download byte count, as reported by the peer.
   */
  public void update(PeerState state, long uploaded, long downloaded,
      long left) {
    if (PeerState.STARTED.equals(state) && left == 0) {
      state = PeerState.COMPLETED;
    }

    if (!state.equals(this.state)) {
      logger.info("Peer {} {} download of {}.",
        new Object[] {
          this,
          state.name().toLowerCase(),
          this.torrent,
        });
    }

    this.state = state;
    this.lastAnnounce = new Date();
    this.uploaded = uploaded;
    this.downloaded = downloaded;
    this.left = left;
  }

  /**
   * Tells whether this peer has completed its download and can thus be
   * considered a seeder.
   */
  public boolean isCompleted() {
    return PeerState.COMPLETED.equals(this.state);
  }

  /**
   * Returns how many bytes the peer reported it has uploaded so far.
   */
  public long getUploaded() {
    return this.uploaded;
  }

  /**
   * Returns how many bytes the peer reported it has downloaded so far.
   */
  public long getDownloaded() {
    return this.downloaded;
  }

  /**
   * Returns how many bytes the peer reported it needs to retrieve before
   * its download is complete.
   */
  public long getLeft() {
    return this.left;
  }

  /**
   * Tells whether this peer has checked in with the tracker recently.
   *
   * <p>
   * Non-fresh peers are automatically terminated and collected by the
   * Tracker.
   * </p>
   */
  public boolean isFresh() {
    return (this.lastAnnounce != null &&
        (this.lastAnnounce.getTime() + (FRESH_TIME_SECONDS * 1000) >
         new Date().getTime()));
  }

  /**
   * Returns a BEValue representing this peer for inclusion in an
   * announce reply from the tracker.
   *
   * The returned BEValue is a dictionary containing the peer ID (in its
   * original byte-encoded form), the peer's IP and the peer's port.
   */
  public BEValue toBEValue() throws UnsupportedEncodingException {
    Map<String, BEValue> peer = new HashMap<String, BEValue>();
    if (this.hasPeerId()) {
      peer.put("peer id", new BEValue(this.getPeerId().array()));
    }
    peer.put("ip", new BEValue(this.getIp(), Torrent.BYTE_ENCODING));
    peer.put("port", new BEValue(this.getPort()));
    return new BEValue(peer);
  }
}
TOP

Related Classes of com.turn.ttorrent.tracker.TrackedPeer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.