/** * 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); } }
/** * 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); } }