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;
}
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);
}
}
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);
}
}
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);
}
}
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);
}
}
Aggregations