/** * Sleep every interval period, and send the keep alive if no other packets are sent. The * interrupt call is made on this thread when any other message is sent. */ public void run() { while (this.isRunning) { try { Thread.sleep(interval); } catch (InterruptedException e) { continue; } try { peer.sendMessage(Message.KEEP_ALIVE_MSG); } catch (IOException e) { System.out.println("Couldn't send keep alive message"); } } }
public void run() { // We now have enough connected peers to send the transaction. // This can be called immediately if we already have enough. Otherwise it'll be called from a // peer // thread. // We will send the tx simultaneously to half the connected peers and wait to hear back from // at least half // of the other half, i.e., with 4 peers connected we will send the tx to 2 randomly chosen // peers, and then // wait for it to show up on one of the other two. This will be taken as sign of network // acceptance. As can // be seen, 4 peers is probably too little - it doesn't taken many broken peers for tx // propagation to have // a big effect. List<Peer> peers = peerGroup.getConnectedPeers(); // snapshots // We intern the tx here so we are using a canonical version of the object (as it's // unfortunately mutable). pinnedTx = peerGroup.getMemoryPool().intern(tx); // Prepare to send the transaction by adding a listener that'll be called when confidence // changes. // Only bother with this if we might actually hear back: if (minConnections > 1) pinnedTx.getConfidence().addEventListener(new ConfidenceChange()); // Satoshis code sends an inv in this case and then lets the peer request the tx data. We just // blast out the TX here for a couple of reasons. Firstly it's simpler: in the case where we // have // just a single connection we don't have to wait for getdata to be received and handled // before // completing the future in the code immediately below. Secondly, it's faster. The reason the // Satoshi client sends an inv is privacy - it means you can't tell if the peer originated the // transaction or not. However, we are not a fully validating node and this is advertised in // our version message, as SPV nodes cannot relay it doesn't give away any additional // information // to skip the inv here - we wouldn't send invs anyway. int numConnected = peers.size(); numToBroadcastTo = (int) Math.max(1, Math.round(Math.ceil(peers.size() / 2.0))); numWaitingFor = (int) Math.ceil((peers.size() - numToBroadcastTo) / 2.0); Collections.shuffle(peers, random); peers = peers.subList(0, numToBroadcastTo); log.info( "broadcastTransaction: We have {} peers, adding {} to the memory pool and sending to {} peers, will wait for {}: {}", numConnected, tx.getHashAsString(), numToBroadcastTo, numWaitingFor, Joiner.on(",").join(peers)); for (Peer peer : peers) { try { peer.sendMessage(pinnedTx); // We don't record the peer as having seen the tx in the memory pool because we want to // track only // how many peers announced to us. } catch (Exception e) { log.error("Caught exception sending to {}", peer, e); } } // If we've been limited to talk to only one peer, we can't wait to hear back because the // remote peer won't tell us about transactions we just announced to it for obvious reasons. // So we just have to assume we're done, at that point. This happens when we're not given // any peer discovery source and the user just calls connectTo() once. if (minConnections == 1) { future.set(pinnedTx); } }