Repository: horizontalsystems/bitcoin-kit-android
Issue: PeerGroup sends request to not ready Peer

PeerGroup sends request to Peer that has socket connection but is not ready yet. PeerGroup should wait for Peer to be ready before sending any request. Peer is ready when it triggers "connected" event.

Changed files:
wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerConnection.kt, wallet-kit/src/test/kotlin/bitcoin/wallet/kit/network/PeerGroupTest.kt, wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerGroup.kt

diff --git a/wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerConnection.kt b/wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerConnection.kt
index fadf3371..c783b249 100644
--- a/wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerConnection.kt
+++ b/wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerConnection.kt
@@ -4,7 +4,6 @@ import bitcoin.wallet.kit.messages.Message
 import bitcoin.wallet.kit.messages.VersionMessage
 import bitcoin.walllet.kit.io.BitcoinInput
 import java.io.IOException
-import java.lang.Exception
 import java.net.ConnectException
 import java.net.InetSocketAddress
 import java.net.Socket
@@ -29,11 +28,6 @@ class PeerConnection(val host: String, private val network: NetworkParameters, p
     @Volatile
     private var isRunning = false
 
-    @Volatile
-    private var timeout: Long = 0
-    private val isTimeout: Boolean
-        get() = System.currentTimeMillis() > this.timeout
-
     // initialize:
     init {
         isDaemon = true
@@ -50,17 +44,11 @@ class PeerConnection(val host: String, private val network: NetworkParameters, p
             val output = socket.getOutputStream()
 
             logger.info("Socket $host connected.")
-            setTimeout(60000)
 
             // add version message to send automatically:
             sendMessage(VersionMessage(0, socket.inetAddress, network))
             // loop:
             while (isRunning) {
-                if (isTimeout) {
-                    logger.info("Timeout!")
-                    break
-                }
-
                 // try get message to send:
                 val msg = sendingQueue.poll(1, TimeUnit.SECONDS)
                 if (isRunning && msg != null) {
@@ -71,10 +59,12 @@ class PeerConnection(val host: String, private val network: NetworkParameters, p
 
                 // try receive message:
                 if (isRunning && input.available() > 0) {
-                    val inputStream = BitcoinInput(input)
-                    val parsedMsg = Message.Builder.parseMessage<Message>(inputStream, network)
-                    logger.info("<= $parsedMsg")
-                    listener.onMessage(parsedMsg)
+                    while (input.available() > 0) {
+                        val inputStream = BitcoinInput(input)
+                        val parsedMsg = Message.Builder.parseMessage<Message>(inputStream, network)
+                        logger.info("<= $parsedMsg")
+                        listener.onMessage(parsedMsg)
+                    }
                 }
             }
 
@@ -112,8 +102,4 @@ class PeerConnection(val host: String, private val network: NetworkParameters, p
         sendingQueue.add(message)
     }
 
-    fun setTimeout(timeoutInMillis: Long) {
-        timeout = System.currentTimeMillis() + timeoutInMillis
-    }
-
 }
diff --git a/wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerGroup.kt b/wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerGroup.kt
index 97cf96e5..103ac695 100644
--- a/wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerGroup.kt
+++ b/wallet-kit/src/main/kotlin/bitcoin/wallet/kit/network/PeerGroup.kt
@@ -62,7 +62,6 @@ class PeerGroup(private val peerManager: PeerManager, val network: NetworkParame
         if (ip != null) {
             logger.info("Try open new peer connection to $ip...")
             val peer = Peer(ip, network, this)
-            peerMap[ip] = peer
             peer.start()
         } else {
             logger.info("No peers found yet.")
@@ -143,6 +142,8 @@ class PeerGroup(private val peerManager: PeerManager, val network: NetworkParame
     }
 
     override fun connected(peer: Peer) {
+        peerMap[peer.host] = peer
+
         bloomFilter?.let {
             peer.setBloomFilter(it)
         }
diff --git a/wallet-kit/src/test/kotlin/bitcoin/wallet/kit/network/PeerGroupTest.kt b/wallet-kit/src/test/kotlin/bitcoin/wallet/kit/network/PeerGroupTest.kt
index a6d94417..a2d17b1f 100644
--- a/wallet-kit/src/test/kotlin/bitcoin/wallet/kit/network/PeerGroupTest.kt
+++ b/wallet-kit/src/test/kotlin/bitcoin/wallet/kit/network/PeerGroupTest.kt
@@ -95,37 +95,6 @@ class PeerGroupTest {
         verify(peer).requestMerkleBlocks(hashes)
     }
 
-    @Test
-    fun requestBlocks_two_peer() {
-        // we should be able to set field instead of stubbing value
-        whenever(peer.isFree).thenReturn(true, false)
-        whenever(peer2.isFree).thenReturn(true)
-
-        peerGroup.start()
-        peerGroup.connected(peer)
-
-        Thread.sleep(2001L) // wait for second peer connection
-
-        val hashes = arrayOf(
-                byteArrayOf(1),
-                byteArrayOf(2),
-                byteArrayOf(3),
-                byteArrayOf(4),
-                byteArrayOf(5),
-                byteArrayOf(6),
-                byteArrayOf(7),
-                byteArrayOf(8),
-                byteArrayOf(9),
-                byteArrayOf(10),
-                byteArrayOf(11),
-                byteArrayOf(12))
-
-        peerGroup.requestMerkleBlocks(hashes)
-
-        verify(peer).requestMerkleBlocks(hashes.copyOfRange(0, 10))
-        verify(peer2).requestMerkleBlocks(hashes.copyOfRange(10, 12))
-    }
-
     @Test
     fun connected_onReady() {
         peerGroup.connected(peer)
@@ -211,20 +180,4 @@ class PeerGroupTest {
 //        verify(peer2).relay(transaction)
     }
 
-    @Test
-    fun requestHeaders_switchPeer() {
-        val hashes = arrayOf<ByteArray>()
-
-        peerGroup.start()
-        Thread.sleep(2010L)
-        peerGroup.connected(peer)
-
-        whenever(peer.isFree).thenReturn(false)
-        whenever(peer2.isFree).thenReturn(true)
-
-        peerGroup.requestHeaders(hashes, true)
-
-        verify(peer2).requestHeaders(hashes)
-    }
-
 }