Example #1
0
 /**
  * Send the DHT port numbers
  *
  * @since DHT
  */
 public static void sendDHT(Peer peer, int qport, int rport) {
   Map<String, Object> map = new HashMap<String, Object>();
   map.put("port", Integer.valueOf(qport));
   map.put("rport", Integer.valueOf(rport));
   byte[] payload = BEncoder.bencode(map);
   try {
     int hisMsgCode = peer.getHandshakeMap().get("m").getMap().get(TYPE_DHT).getInt();
     peer.sendExtension(hisMsgCode, payload);
   } catch (Exception e) {
     // NPE, no DHT caps
     // if (log.shouldLog(Log.INFO))
     //    log.info("DHT msg exception to " + peer, e);
   }
 }
Example #2
0
 /** REQUEST and REJECT are the same except for message type */
 private static void sendMessage(Peer peer, int type, int piece) {
   Map<String, Object> map = new HashMap<String, Object>();
   map.put("msg_type", Integer.valueOf(type));
   map.put("piece", Integer.valueOf(piece));
   byte[] payload = BEncoder.bencode(map);
   try {
     int hisMsgCode = peer.getHandshakeMap().get("m").getMap().get(TYPE_METADATA).getInt();
     peer.sendExtension(hisMsgCode, payload);
   } catch (Exception e) {
     // NPE, no metadata capability
     // if (log.shouldLog(Log.INFO))
     //    log.info("Metadata send req msg exception to " + peer, e);
   }
 }
Example #3
0
  /**
   * Called when a full chunk (i.e. a piece message) has been received by PeerConnectionIn.
   *
   * <p>This may block quite a while if it is the last chunk for a piece, as it calls the listener,
   * who stores the piece and then calls havePiece for every peer on the torrent (including us).
   */
  void pieceMessage(Request req) {
    int size = req.len;
    peer.downloaded(size);
    listener.downloaded(peer, size);

    if (_log.shouldLog(Log.DEBUG))
      _log.debug(
          "got end of Chunk(" + req.getPiece() + "," + req.off + "," + req.len + ") from " + peer);

    // Last chunk needed for this piece?
    // FIXME if priority changed to skip, we will think we're done when we aren't
    if (getFirstOutstandingRequest(req.getPiece()) == -1) {
      // warning - may block here for a while
      if (listener.gotPiece(peer, req.getPartialPiece())) {
        if (_log.shouldLog(Log.DEBUG)) _log.debug("Got " + req.getPiece() + ": " + peer);
      } else {
        if (_log.shouldLog(Log.WARN)) _log.warn("Got BAD " + req.getPiece() + " from " + peer);
      }
    }

    // ok done with this one
    synchronized (this) {
      pendingRequest = null;
    }
  }
Example #4
0
  void bitfieldMessage(byte[] bitmap) {
    synchronized (this) {
      if (_log.shouldLog(Log.DEBUG)) _log.debug(peer + " rcv bitfield");
      if (bitfield != null) {
        // XXX - Be liberal in what you accept?
        if (_log.shouldLog(Log.WARN)) _log.warn("Got unexpected bitfield message from " + peer);
        return;
      }

      // XXX - Check for weird bitfield and disconnect?
      // FIXME will have to regenerate the bitfield after we know exactly
      // how many pieces there are, as we don't know how many spare bits there are.
      if (metainfo == null) bitfield = new BitField(bitmap, bitmap.length * 8);
      else bitfield = new BitField(bitmap, metainfo.getPieces());
    }
    if (metainfo == null) return;
    boolean interest = listener.gotBitField(peer, bitfield);
    setInteresting(interest);
    if (bitfield.complete() && !interest) {
      // They are seeding and we are seeding,
      // why did they contact us? (robert)
      // Dump them quick before we send our whole bitmap
      if (_log.shouldLog(Log.WARN)) _log.warn("Disconnecting seed that connects to seeds: " + peer);
      peer.disconnect(true);
    }
  }
Example #5
0
 /**
  * Can't find a published standard for this anywhere. See the libtorrent code. Here we use the
  * "added" key as a single string of concatenated 32-byte peer hashes. added.f and dropped
  * unsupported
  *
  * @since 0.8.4
  */
 private static void handlePEX(Peer peer, PeerListener listener, byte[] bs, Log log) {
   if (log.shouldLog(Log.DEBUG)) log.debug("Got PEX msg from " + peer);
   try {
     InputStream is = new ByteArrayInputStream(bs);
     BDecoder dec = new BDecoder(is);
     BEValue bev = dec.bdecodeMap();
     Map<String, BEValue> map = bev.getMap();
     bev = map.get("added");
     if (bev == null) return;
     byte[] ids = bev.getBytes();
     if (ids.length < HASH_LENGTH) return;
     int len = Math.min(ids.length, (I2PSnarkUtil.MAX_CONNECTIONS - 1) * HASH_LENGTH);
     List<PeerID> peers = new ArrayList<PeerID>(len / HASH_LENGTH);
     for (int off = 0; off < len; off += HASH_LENGTH) {
       byte[] hash = new byte[HASH_LENGTH];
       System.arraycopy(ids, off, hash, 0, HASH_LENGTH);
       if (DataHelper.eq(hash, peer.getPeerID().getDestHash())) continue;
       PeerID pID = new PeerID(hash, listener.getUtil());
       peers.add(pID);
     }
     // could include ourselves, listener must remove
     listener.gotPeers(peer, peers);
   } catch (Exception e) {
     if (log.shouldLog(Log.INFO)) log.info("PEX msg exception from " + peer, e);
     // peer.disconnect(false);
   }
 }
Example #6
0
 private static void sendPiece(Peer peer, int piece, byte[] data) {
   Map<String, Object> map = new HashMap<String, Object>();
   map.put("msg_type", Integer.valueOf(TYPE_DATA));
   map.put("piece", Integer.valueOf(piece));
   map.put("total_size", Integer.valueOf(data.length));
   byte[] dict = BEncoder.bencode(map);
   byte[] payload = new byte[dict.length + data.length];
   System.arraycopy(dict, 0, payload, 0, dict.length);
   System.arraycopy(data, 0, payload, dict.length, data.length);
   try {
     int hisMsgCode = peer.getHandshakeMap().get("m").getMap().get(TYPE_METADATA).getInt();
     peer.sendExtension(hisMsgCode, payload);
   } catch (Exception e) {
     // NPE, no metadata caps
     // if (log.shouldLog(Log.INFO))
     //    log.info("Metadata send piece msg exception to " + peer, e);
   }
 }
Example #7
0
 /**
  * added.f and dropped unsupported
  *
  * @param pList non-null
  * @since 0.8.4
  */
 public static void sendPEX(Peer peer, List<Peer> pList) {
   if (pList.isEmpty()) return;
   Map<String, Object> map = new HashMap<String, Object>();
   byte[] peers = new byte[HASH_LENGTH * pList.size()];
   int off = 0;
   for (Peer p : pList) {
     System.arraycopy(p.getPeerID().getDestHash(), 0, peers, off, HASH_LENGTH);
     off += HASH_LENGTH;
   }
   map.put("added", peers);
   byte[] payload = BEncoder.bencode(map);
   try {
     int hisMsgCode = peer.getHandshakeMap().get("m").getMap().get(TYPE_PEX).getInt();
     peer.sendExtension(hisMsgCode, payload);
   } catch (Exception e) {
     // NPE, no PEX caps
     // if (log.shouldLog(Log.INFO))
     //    log.info("PEX msg exception to " + peer, e);
   }
 }
Example #8
0
 /**
  * Called when some bytes have left the outgoing connection. XXX - Should indicate whether it was
  * a real piece or overhead.
  */
 void uploaded(int size) {
   peer.uploaded(size);
   listener.uploaded(peer, size);
 }
Example #9
0
  private static void handleHandshake(Peer peer, PeerListener listener, byte[] bs, Log log) {
    if (log.shouldLog(Log.DEBUG)) log.debug("Got handshake msg from " + peer);
    try {
      // this throws NPE on missing keys
      InputStream is = new ByteArrayInputStream(bs);
      BDecoder dec = new BDecoder(is);
      BEValue bev = dec.bdecodeMap();
      Map<String, BEValue> map = bev.getMap();
      peer.setHandshakeMap(map);
      Map<String, BEValue> msgmap = map.get("m").getMap();

      if (log.shouldLog(Log.DEBUG))
        log.debug("Peer " + peer + " supports extensions: " + msgmap.keySet());

      // if (msgmap.get(TYPE_PEX) != null) {
      //    if (log.shouldLog(Log.DEBUG))
      //        log.debug("Peer supports PEX extension: " + peer);
      //    // peer state calls peer listener calls sendPEX()
      // }

      // if (msgmap.get(TYPE_DHT) != null) {
      //    if (log.shouldLog(Log.DEBUG))
      //        log.debug("Peer supports DHT extension: " + peer);
      //    // peer state calls peer listener calls sendDHT()
      // }

      MagnetState state = peer.getMagnetState();

      if (msgmap.get(TYPE_METADATA) == null) {
        if (log.shouldLog(Log.DEBUG))
          log.debug("Peer does not support metadata extension: " + peer);
        // drop if we need metainfo and we haven't found anybody yet
        synchronized (state) {
          if (!state.isInitialized()) {
            if (log.shouldLog(Log.DEBUG)) log.debug("Dropping peer, we need metadata! " + peer);
            peer.disconnect();
          }
        }
        return;
      }

      BEValue msize = map.get("metadata_size");
      if (msize == null) {
        if (log.shouldLog(Log.DEBUG))
          log.debug("Peer does not have the metainfo size yet: " + peer);
        // drop if we need metainfo and we haven't found anybody yet
        synchronized (state) {
          if (!state.isInitialized()) {
            if (log.shouldLog(Log.DEBUG)) log.debug("Dropping peer, we need metadata! " + peer);
            peer.disconnect();
          }
        }
        return;
      }
      int metaSize = msize.getInt();
      if (log.shouldLog(Log.DEBUG)) log.debug("Got the metainfo size: " + metaSize);

      int remaining;
      synchronized (state) {
        if (state.isComplete()) return;

        if (state.isInitialized()) {
          if (state.getSize() != metaSize) {
            if (log.shouldLog(Log.DEBUG))
              log.debug("Wrong metainfo size " + metaSize + " from: " + peer);
            peer.disconnect();
            return;
          }
        } else {
          // initialize it
          if (metaSize > MAX_METADATA_SIZE) {
            if (log.shouldLog(Log.DEBUG))
              log.debug("Huge metainfo size " + metaSize + " from: " + peer);
            peer.disconnect(false);
            return;
          }
          if (log.shouldLog(Log.INFO))
            log.info("Initialized state, metadata size = " + metaSize + " from " + peer);
          state.initialize(metaSize);
        }
        remaining = state.chunksRemaining();
      }

      // send requests for chunks
      int count = Math.min(remaining, PARALLEL_REQUESTS);
      for (int i = 0; i < count; i++) {
        int chk;
        synchronized (state) {
          chk = state.getNextRequest();
        }
        if (log.shouldLog(Log.INFO)) log.info("Request chunk " + chk + " from " + peer);
        sendRequest(peer, chk);
      }
    } catch (Exception e) {
      if (log.shouldLog(Log.WARN)) log.warn("Handshake exception from " + peer, e);
    }
  }
Example #10
0
  /**
   * REF: BEP 9
   *
   * @since 0.8.4
   */
  private static void handleMetadata(Peer peer, PeerListener listener, byte[] bs, Log log) {
    if (log.shouldLog(Log.DEBUG)) log.debug("Got metadata msg from " + peer);
    try {
      InputStream is = new ByteArrayInputStream(bs);
      BDecoder dec = new BDecoder(is);
      BEValue bev = dec.bdecodeMap();
      Map<String, BEValue> map = bev.getMap();
      int type = map.get("msg_type").getInt();
      int piece = map.get("piece").getInt();

      MagnetState state = peer.getMagnetState();
      if (type == TYPE_REQUEST) {
        if (log.shouldLog(Log.DEBUG)) log.debug("Got request for " + piece + " from: " + peer);
        byte[] pc;
        synchronized (state) {
          pc = state.getChunk(piece);
        }
        sendPiece(peer, piece, pc);
        // Do this here because PeerConnectionOut only reports for PIECE messages
        peer.uploaded(pc.length);
        listener.uploaded(peer, pc.length);
      } else if (type == TYPE_DATA) {
        int size = map.get("total_size").getInt();
        if (log.shouldLog(Log.DEBUG))
          log.debug("Got data for " + piece + " length " + size + " from: " + peer);
        boolean done;
        int chk = -1;
        synchronized (state) {
          if (state.isComplete()) return;
          int len = is.available();
          if (len != size) {
            // probably fatal
            if (log.shouldLog(Log.WARN)) log.warn("total_size " + size + " but avail data " + len);
          }
          peer.downloaded(len);
          listener.downloaded(peer, len);
          done = state.saveChunk(piece, bs, bs.length - len, len);
          if (log.shouldLog(Log.INFO)) log.info("Got chunk " + piece + " from " + peer);
          if (!done) chk = state.getNextRequest();
        }
        // out of the lock
        if (done) {
          // Done!
          // PeerState will call the listener (peer coord), who will
          // check to see if the MagnetState has it
          if (log.shouldLog(Log.WARN)) log.warn("Got last chunk from " + peer);
        } else {
          // get the next chunk
          if (log.shouldLog(Log.INFO)) log.info("Request chunk " + chk + " from " + peer);
          sendRequest(peer, chk);
        }
      } else if (type == TYPE_REJECT) {
        if (log.shouldLog(Log.WARN)) log.warn("Got reject msg from " + peer);
        peer.disconnect(false);
      } else {
        if (log.shouldLog(Log.WARN)) log.warn("Got unknown metadata msg from " + peer);
        peer.disconnect(false);
      }
    } catch (Exception e) {
      if (log.shouldLog(Log.INFO)) log.info("Metadata ext. msg. exception from " + peer, e);
      // fatal ?
      peer.disconnect(false);
    }
  }