Search in sources :

Example 1 with BEValue

use of org.klomp.snark.bencode.BEValue in project i2p.i2p by i2p.

the class KRPC method receivePeers.

/**
 *  rcv 32 byte Hashes, return as a List
 *  @throws NPE, IllegalArgumentException, and others too
 */
private List<Hash> receivePeers(NodeInfo nInfo, List<BEValue> peers) throws InvalidBEncodingException {
    if (_log.shouldLog(Log.INFO))
        _log.info("Rcvd peers from: " + nInfo);
    int max = Math.min(MAX_WANT * 2, peers.size());
    List<Hash> rv = new ArrayList<Hash>(max);
    for (BEValue bev : peers) {
        byte[] b = bev.getBytes();
        if (b.length != Hash.HASH_LENGTH) {
            if (_log.shouldWarn())
                _log.info("Bad peers entry from: " + nInfo);
            continue;
        }
        // Hash h = new Hash(b);
        Hash h = Hash.create(b);
        rv.add(h);
        if (rv.size() >= max)
            break;
    }
    if (_log.shouldLog(Log.INFO))
        _log.info("Rcvd " + peers.size() + " peers from: " + nInfo + ": " + DataHelper.toString(rv));
    return rv;
}
Also used : ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) BEValue(org.klomp.snark.bencode.BEValue)

Example 2 with BEValue

use of org.klomp.snark.bencode.BEValue in project i2p.i2p by i2p.

the class KRPC method receiveQuery.

// Queries.....
/**
 *  Adds sender to our DHT.
 *  @param dest may be null for announce_peer method only
 *  @throws NPE too
 */
private void receiveQuery(MsgID msgID, Destination dest, int fromPort, String method, Map<String, BEValue> args) throws InvalidBEncodingException {
    if (dest == null && !method.equals("announce_peer")) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Received non-announce_peer query method on reply port: " + method);
        return;
    }
    byte[] nid = args.get("id").getBytes();
    NodeInfo nInfo;
    if (dest != null) {
        nInfo = new NodeInfo(new NID(nid), dest, fromPort);
        nInfo = heardFrom(nInfo);
        nInfo.setDestination(dest);
    // ninfo.checkport ?
    } else {
        nInfo = null;
    }
    if (method.equals("ping")) {
        receivePing(msgID, nInfo);
    } else if (method.equals("find_node")) {
        byte[] tid = args.get("target").getBytes();
        NID tID = new NID(tid);
        receiveFindNode(msgID, nInfo, tID);
    } else if (method.equals("get_peers")) {
        byte[] hash = args.get("info_hash").getBytes();
        InfoHash ih = new InfoHash(hash);
        boolean noSeeds = false;
        BEValue nos = args.get("noseed");
        if (nos != null)
            noSeeds = nos.getInt() == 1;
        receiveGetPeers(msgID, nInfo, ih, noSeeds);
    } else if (method.equals("announce_peer")) {
        byte[] hash = args.get("info_hash").getBytes();
        InfoHash ih = new InfoHash(hash);
        // this is the "TCP" port, we don't care
        // int port = args.get("port").getInt();
        byte[] token = args.get("token").getBytes();
        boolean isSeed = false;
        BEValue iss = args.get("seed");
        if (iss != null)
            isSeed = iss.getInt() == 1;
        receiveAnnouncePeer(msgID, ih, token, isSeed);
    } else {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Unknown query method rcvd: " + method);
    }
}
Also used : BEValue(org.klomp.snark.bencode.BEValue)

Example 3 with BEValue

use of org.klomp.snark.bencode.BEValue in project i2p.i2p by i2p.

the class KRPC method receiveMessage.

// /// Reception.....
/**
 *  @param from dest or null if it didn't come in on signed port
 */
private void receiveMessage(Destination from, int fromPort, byte[] payload) {
    try {
        InputStream is = new ByteArrayInputStream(payload);
        BDecoder dec = new BDecoder(is);
        BEValue bev = dec.bdecodeMap();
        Map<String, BEValue> map = bev.getMap();
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Got KRPC message " + bev.toString());
        // Lazy here, just let missing Map entries throw NPEs, caught below
        byte[] msgIDBytes = map.get("t").getBytes();
        MsgID mID = new MsgID(msgIDBytes);
        String type = map.get("y").getString();
        if (type.equals("q")) {
            // queries must be repliable
            String method = map.get("q").getString();
            Map<String, BEValue> args = map.get("a").getMap();
            receiveQuery(mID, from, fromPort, method, args);
        } else if (type.equals("r") || type.equals("e")) {
            // get dest from id->dest map
            ReplyWaiter waiter = _sentQueries.remove(mID);
            if (waiter != null) {
                // TODO verify waiter NID and port?
                if (type.equals("r")) {
                    Map<String, BEValue> response = map.get("r").getMap();
                    receiveResponse(waiter, response);
                } else {
                    List<BEValue> error = map.get("e").getList();
                    receiveError(waiter, error);
                }
            } else {
                if (_log.shouldLog(Log.WARN))
                    _log.warn("Rcvd msg with no one waiting: " + bev.toString());
            }
        } else {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Unknown msg type rcvd: " + bev.toString());
            throw new InvalidBEncodingException("Unknown type: " + type);
        }
    // success
    /**
     *        } catch (InvalidBEncodingException e) {
     *        } catch (IOException e) {
     *        } catch (ArrayIndexOutOfBoundsException e) {
     *        } catch (IllegalArgumentException e) {
     *        } catch (ClassCastException e) {
     *        } catch (NullPointerException e) {
     **
     */
    } catch (Exception e) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Receive error for message", e);
    }
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) BEValue(org.klomp.snark.bencode.BEValue) I2PInvalidDatagramException(net.i2p.client.datagram.I2PInvalidDatagramException) NoSuchElementException(java.util.NoSuchElementException) DataFormatException(net.i2p.data.DataFormatException) IOException(java.io.IOException) I2PSessionException(net.i2p.client.I2PSessionException) InvalidBEncodingException(org.klomp.snark.bencode.InvalidBEncodingException) InvalidBEncodingException(org.klomp.snark.bencode.InvalidBEncodingException) ByteArrayInputStream(java.io.ByteArrayInputStream) BDecoder(org.klomp.snark.bencode.BDecoder) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 4 with BEValue

use of org.klomp.snark.bencode.BEValue in project i2p.i2p by i2p.

the class ExtensionHandler method handleMetadata.

/**
 * 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;
            int totalSize;
            synchronized (state) {
                pc = state.getChunk(piece);
                totalSize = state.getSize();
            }
            sendPiece(peer, piece, pc, totalSize);
            // Do this here because PeerConnectionOut only reports for PIECE messages
            peer.uploaded(pc.length);
            listener.uploaded(peer, pc.length);
        } else if (type == TYPE_DATA) {
            // On close reading of BEP 9, this is the total metadata size.
            // Prior to 0.9.21, we sent the piece size, so we can't count on it.
            // just ignore it. The actual length will be verified in saveChunk()
            // 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();
                peer.downloaded(len);
                listener.downloaded(peer, len);
                // this checks the size
                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) {
                // 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);
    }
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) BDecoder(org.klomp.snark.bencode.BDecoder) BEValue(org.klomp.snark.bencode.BEValue)

Example 5 with BEValue

use of org.klomp.snark.bencode.BEValue in project i2p.i2p by i2p.

the class ExtensionHandler method handlePEX.

/**
 * 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);
    }
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) BDecoder(org.klomp.snark.bencode.BDecoder) ArrayList(java.util.ArrayList) BEValue(org.klomp.snark.bencode.BEValue)

Aggregations

BEValue (org.klomp.snark.bencode.BEValue)18 BDecoder (org.klomp.snark.bencode.BDecoder)8 ByteArrayInputStream (java.io.ByteArrayInputStream)7 InputStream (java.io.InputStream)7 InvalidBEncodingException (org.klomp.snark.bencode.InvalidBEncodingException)7 ArrayList (java.util.ArrayList)6 HashMap (java.util.HashMap)6 IOException (java.io.IOException)3 List (java.util.List)3 Map (java.util.Map)3 MessageDigest (java.security.MessageDigest)1 HashSet (java.util.HashSet)1 NoSuchElementException (java.util.NoSuchElementException)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 I2PSessionException (net.i2p.client.I2PSessionException)1 I2PInvalidDatagramException (net.i2p.client.datagram.I2PInvalidDatagramException)1 DataFormatException (net.i2p.data.DataFormatException)1 Hash (net.i2p.data.Hash)1 Comment (org.klomp.snark.comments.Comment)1 CommentSet (org.klomp.snark.comments.CommentSet)1