public void handle(PeerMessage event) { PeerAddress oldFriend; PeerAddress sender = event.getMSPeerSource(); PeerAddress newFriend = event.getNewFriend(); // add the sender address to the list of friends if (!friends.contains(sender)) { if (friends.size() == viewSize) { oldFriend = friends.get(rand.nextInt(viewSize)); friends.remove(oldFriend); fdUnregister(oldFriend); Snapshot.removeFriend(serverPeerAddress, oldFriend); } friends.addElement(sender); fdRegister(sender); Snapshot.addFriend(serverPeerAddress, sender); } // add the received new friend from the sender to the list of friends if (!friends.contains(newFriend) && !serverPeerAddress.equals(newFriend)) { if (friends.size() == viewSize) { oldFriend = friends.get(rand.nextInt(viewSize)); friends.remove(oldFriend); fdUnregister(oldFriend); Snapshot.removeFriend(serverPeerAddress, oldFriend); } friends.addElement(newFriend); fdRegister(newFriend); Snapshot.addFriend(serverPeerAddress, newFriend); } }
/** * Remove a peer from the list. In order to not reappear, the node is put for a certain time in a * cache list to keep the node removed. This method is thread-safe. * * @param remotePeer The node that should be removed * @param force A flag that removes a peer immediately. * @return True if the neighbor was removed and added to a cache list. False if peer has not been * removed or is already in the peer removed temporarly list. */ public boolean peerOffline(final PeerAddress remotePeer, final boolean force) { if (logger.isDebugEnabled()) { logger.debug("peer " + remotePeer + " is offline"); } if (remotePeer.getID().isZero() || self().equals(remotePeer.getID())) { return false; } notifyPeerFail(remotePeer, force); Log log; synchronized (peerOfflineLogs) { log = peerOfflineLogs.get(remotePeer); if (log == null) { log = new Log(); peerOfflineLogs.put(remotePeer, log); } } synchronized (log) { if (!force) { if (shouldPeerBeRemoved(log)) { remove(remotePeer, Reason.NOT_REACHABLE); return true; } log.inc(); if (!shouldPeerBeRemoved(log)) { peerMapStat.removeStat(remotePeer); addToMaintenanceQueue(remotePeer); return false; } } else { log.set(maxFail); } } remove(remotePeer, Reason.NOT_REACHABLE); return true; }
public boolean contains(PeerAddress peerAddress) { final int classMember = classMember(peerAddress.getID()); if (classMember == -1) { // -1 means we searched for ourself and we never are our neighbor return false; } Map<Number160, PeerAddress> tmp = peerMap.get(classMember); return tmp.containsKey(peerAddress.getID()); }
public static ChannelFuture connect(PeerAddress peerAddress, byte[] hashinfo) throws InterruptedException { if (bootstrap == null) { init(); } bootstrap.handler(HandlerFactory.client(hashinfo)); ChannelFuture channelFuture = bootstrap.connect(peerAddress.getAddress(), peerAddress.getPort()).sync(); register(peerAddress, channelFuture.channel()); return channelFuture; }
/** * Checks if a peer already existis in this map and if it does, it will update the entry becaues * the peer address (e.g. port) may have changed. * * @param peerAddress The address of the peer that may have been changed. * @return True if we have updated the peer, false otherwise */ public boolean updateExistingPeerAddress(PeerAddress peerAddress) { final int classMember = classMember(peerAddress.getID()); Map<Number160, PeerAddress> tmp = peerMap.get(classMember); synchronized (tmp) { if (tmp.containsKey(peerAddress.getID())) { tmp.put(peerAddress.getID(), peerAddress); return true; } } return false; }
/** * Removes the peer from the neighbor list if present in the list. Notifies listeners that a peer * is offline. * * @param remotePeer The peer that has gone offline. * @param reason The reason for going offline * @return True if the peer was in our map and was removed. */ private boolean remove(final PeerAddress remotePeer, final Reason reason) { final int classMember = classMember(remotePeer.getID()); final Map<Number160, PeerAddress> map = peerMap.get(classMember); final boolean retVal = map.remove(remotePeer.getID()) != null; if (retVal) { removeFromMaintenance(remotePeer); peerCount.decrementAndGet(); notifyRemove(remotePeer); } notifyOffline(remotePeer, reason); return retVal; }
/** Catch any exceptions, logging them and then closing the channel. */ private void exceptionCaught(Exception e) { PeerAddress addr = getAddress(); String s = addr == null ? "?" : addr.toString(); if (e instanceof ConnectException || e instanceof IOException) { // Short message for network errors log.info(s + " - " + e.getMessage()); } else { log.warn(s + " - ", e); Thread.UncaughtExceptionHandler handler = Threading.uncaughtExceptionHandler; if (handler != null) handler.uncaughtException(Thread.currentThread(), e); } close(); }
private static void writeConfidence( Protos.Transaction.Builder txBuilder, TransactionConfidence confidence, Protos.TransactionConfidence.Builder confidenceBuilder) { synchronized (confidence) { confidenceBuilder.setType( Protos.TransactionConfidence.Type.valueOf(confidence.getConfidenceType().getValue())); if (confidence.getConfidenceType() == ConfidenceType.BUILDING) { confidenceBuilder.setAppearedAtHeight(confidence.getAppearedAtChainHeight()); confidenceBuilder.setDepth(confidence.getDepthInBlocks()); if (confidence.getWorkDone() != null) { confidenceBuilder.setWorkDone(confidence.getWorkDone().longValue()); } } if (confidence.getConfidenceType() == ConfidenceType.DEAD) { // Copy in the overriding transaction, if available. // (A dead coinbase transaction has no overriding transaction). if (confidence.getOverridingTransaction() != null) { Sha256Hash overridingHash = confidence.getOverridingTransaction().getHash(); confidenceBuilder.setOverridingTransaction(hashToByteString(overridingHash)); } } TransactionConfidence.Source source = confidence.getSource(); switch (source) { case SELF: confidenceBuilder.setSource(Protos.TransactionConfidence.Source.SOURCE_SELF); break; case NETWORK: confidenceBuilder.setSource(Protos.TransactionConfidence.Source.SOURCE_NETWORK); break; case UNKNOWN: // Fall through. default: confidenceBuilder.setSource(Protos.TransactionConfidence.Source.SOURCE_UNKNOWN); break; } } for (ListIterator<PeerAddress> it = confidence.getBroadcastBy(); it.hasNext(); ) { PeerAddress address = it.next(); Protos.PeerAddress proto = Protos.PeerAddress.newBuilder() .setIpAddress(ByteString.copyFrom(address.getAddr().getAddress())) .setPort(address.getPort()) .setServices(address.getServices().longValue()) .build(); confidenceBuilder.addBroadcastBy(proto); } txBuilder.setConfidence(confidenceBuilder); }
/** * Adds a peer to the set. If a peer reaches the bag size, the class is reported to the * oversizebag. Furthermore, it notifies listeners about an insert. * * @param map The set to add the peer * @param remotePeer The remote peer to add * @param classMember The class member, which is used to report oversize. * @return True if the peer could be added. If the peer is already in, it returns false */ private boolean insertOrUpdate( final Map<Number160, PeerAddress> map, final PeerAddress remotePeer, final int classMember) { boolean retVal; synchronized (map) { retVal = !map.containsKey(remotePeer.getID()); map.put(remotePeer.getID(), remotePeer); } if (retVal) { peerCount.incrementAndGet(); notifyInsert(remotePeer); } else { notifyUpdate(remotePeer); } return retVal; }
// ------------------------------------------------------------------- // This method shows how to register the failure detector for a node. // ------------------------------------------------------------------- private void fdRegister(PeerAddress peer) { Address peerAddress = peer.getPeerAddress(); StartProbingPeer spp = new StartProbingPeer(peerAddress, peer); fdRequests.put(peerAddress, spp.getRequestId()); trigger(spp, fd.getPositive(FailureDetector.class)); fdPeers.put(peerAddress, peer); }
// ------------------------------------------------------------------- // This method shows how to unregister the failure detector for a node. // ------------------------------------------------------------------- private void fdUnregister(PeerAddress peer) { if (peer == null) return; Address peerAddress = peer.getPeerAddress(); trigger( new StopProbingPeer(peerAddress, fdRequests.get(peerAddress)), fd.getPositive(FailureDetector.class)); fdRequests.remove(peerAddress); fdPeers.remove(peerAddress); }
/** * Adds a neighbor to the neighbor list. If the bag is full, the id zero or the same as our id, * the neighbor is not added. This method is tread-safe * * @param remotePeer The node that should be added * @param referrer If we had direct contact and we know for sure that this node is online, we set * firsthand to true. Information from 3rd party peers are always second hand and treated as * such * @return True if the neighbor could be added or updated, otherwise false. */ public boolean peerFound(final PeerAddress remotePeer, final PeerAddress referrer) { boolean firstHand = referrer == null; // always trust first hand information if (firstHand) { notifyPeerOnline(remotePeer); synchronized (peerOfflineLogs) { peerOfflineLogs.remove(remotePeer); } } // don't add nodes with zero node id, do not add myself and do not add // nodes marked as bad if (remotePeer.getID().isZero() || self().equals(remotePeer.getID()) || isPeerRemovedTemporarly(remotePeer) || filteredAddresses.contains(remotePeer.getInetAddress())) { return false; } // the peer might have a new port if (updateExistingPeerAddress(remotePeer)) { // we update the peer, so we can exit here and report that we have // updated it. return true; } // check if we have should accept this peer in our peer map. if (!mapHandler.acceptPeer(firstHand, remotePeer)) { return false; } final int classMember = classMember(remotePeer.getID()); final Map<Number160, PeerAddress> map = peerMap.get(classMember); if (size() < maxPeers) { // this updates stats and schedules peer for maintenance prepareInsertOrUpdate(remotePeer, firstHand); // fill it in, regardless of the bag size, also update if we // already have this peer, we update the last seen time with // this return insertOrUpdate(map, remotePeer, classMember); } else { // the class is not full, remove other nodes! PeerAddress toRemove = removeLatestEntryExceedingBagSize(); if (classMember(toRemove.getID()) > classMember(remotePeer.getID())) { if (remove(toRemove, Reason.REMOVED_FROM_MAP)) { // this updates stats and schedules peer for maintenance prepareInsertOrUpdate(remotePeer, firstHand); return insertOrUpdate(map, remotePeer, classMember); } } } return false; }
public void handle(PeerInit init) { System.out.println(" Server is initiated."); serverPeerAddress = init.getMSPeerSelf(); serverAddress = serverPeerAddress.getPeerAddress(); // serverAddress ?? friends = new Vector<PeerAddress>(); msgPeriod = init.getMSConfiguration().getSnapshotPeriod(); viewSize = init.getMSConfiguration().getViewSize(); trigger( new BootstrapClientInit(serverAddress, init.getBootstrapConfiguration()), bootstrap.getControl()); trigger( new PingFailureDetectorInit(serverAddress, init.getFdConfiguration()), fd.getControl()); }
private void readConfidence( Transaction tx, Protos.TransactionConfidence confidenceProto, TransactionConfidence confidence) throws UnreadableWalletException { // We are lenient here because tx confidence is not an essential part of the wallet. // If the tx has an unknown type of confidence, ignore. if (!confidenceProto.hasType()) { log.warn("Unknown confidence type for tx {}", tx.getHashAsString()); return; } ConfidenceType confidenceType; switch (confidenceProto.getType()) { case BUILDING: confidenceType = ConfidenceType.BUILDING; break; case DEAD: confidenceType = ConfidenceType.DEAD; break; // These two are equivalent (must be able to read old wallets). case NOT_IN_BEST_CHAIN: confidenceType = ConfidenceType.PENDING; break; case PENDING: confidenceType = ConfidenceType.PENDING; break; case UNKNOWN: // Fall through. default: confidenceType = ConfidenceType.UNKNOWN; break; } confidence.setConfidenceType(confidenceType); if (confidenceProto.hasAppearedAtHeight()) { if (confidence.getConfidenceType() != ConfidenceType.BUILDING) { log.warn("Have appearedAtHeight but not BUILDING for tx {}", tx.getHashAsString()); return; } confidence.setAppearedAtChainHeight(confidenceProto.getAppearedAtHeight()); } if (confidenceProto.hasDepth()) { if (confidence.getConfidenceType() != ConfidenceType.BUILDING) { log.warn("Have depth but not BUILDING for tx {}", tx.getHashAsString()); return; } confidence.setDepthInBlocks(confidenceProto.getDepth()); } if (confidenceProto.hasOverridingTransaction()) { if (confidence.getConfidenceType() != ConfidenceType.DEAD) { log.warn("Have overridingTransaction but not OVERRIDDEN for tx {}", tx.getHashAsString()); return; } Transaction overridingTransaction = txMap.get(confidenceProto.getOverridingTransaction()); if (overridingTransaction == null) { log.warn( "Have overridingTransaction that is not in wallet for tx {}", tx.getHashAsString()); return; } confidence.setOverridingTransaction(overridingTransaction); } for (Protos.PeerAddress proto : confidenceProto.getBroadcastByList()) { InetAddress ip; try { ip = InetAddress.getByAddress(proto.getIpAddress().toByteArray()); } catch (UnknownHostException e) { throw new UnreadableWalletException("Peer IP address does not have the right length", e); } int port = proto.getPort(); int protocolVersion = tx.getParams().getProtocolVersion(); PeerAddress address = new PeerAddress(ip, port, protocolVersion); address.setServices(BigInteger.valueOf(proto.getServices())); confidence.markBroadcastBy(address); } switch (confidenceProto.getSource()) { case SOURCE_SELF: confidence.setSource(TransactionConfidence.Source.SELF); break; case SOURCE_NETWORK: confidence.setSource(TransactionConfidence.Source.NETWORK); break; case SOURCE_UNKNOWN: // Fall through. default: confidence.setSource(TransactionConfidence.Source.UNKNOWN); break; } }
/** * Returns -1 if the first remote node is closer to the key, if the secondBITS is closer, then 1 * is returned. If both are equal, 0 is returned * * @param id The id as a distance reference * @param rn The peer to test if closer to the id * @param rn2 The other peer to test if closer to the id * @return -1 if first peer is closer, 1 otherwise, 0 if both are equal */ public static int isKadCloser(Number160 id, PeerAddress rn, PeerAddress rn2) { return distance(id, rn.getID()).compareTo(distance(id, rn2.getID())); }