Beispiel #1
0
    def test_whenNodeRestarts_andNodeHasLessThanTwoOutgoingConnections_andElevenSecondsElapsed_receivesIPsFromSeeder(self):
        # patch MAX_OUTGOING instances in network.py so our node doesnt make any connections

        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer.addToTried(self.nodePeer2.ipV4Addr, 0)
        
        restartEvent = event(srcNode=self.nodePeer, destNode=None, eventType=RESTART, info=None)
        self.network.eventQueue.put((0, restartEvent))

        # process RESTART event
        self.network.processNextEvent()

        # get time of REJOIN, place back in eventQueue
        rejoinTime, rejoinEvent = self.network.eventQueue.get()
        self.assertEqual(rejoinEvent.eventType, REJOIN)
        self.network.eventQueue.put((rejoinTime, rejoinEvent))

        # process REJOIN, AFTER_REJOIN_MAYBE_REQUEST_SEEDER events
        self.network.processNextEvent()
        self.network.processNextEvent()

        nextTime, nextEvent = self.network.eventQueue.get()

        # assert seeder request more than 11 seconds from rejoin event
        self.assertTrue(rejoinTime + 11 <= nextTime)

        # assert correct nodes involved in REQUEST_CONNECTION_INFO event
        self.assertEqual(nextEvent.srcNode, self.nodePeer)
        self.assertTrue(nextEvent.destNode in self.network.seederNodes)
        self.assertEqual(nextEvent.eventType, REQUEST_CONNECTION_INFO)
Beispiel #2
0
    def test_whenConnectSuccessToPeer_peerAddressInsertedIntoTried(self):
        # generate node with space for at least 1 new connection
        self.sourceIP = self.network.assignIP()
        for ip in [
                self.network.assignIP()
                for i in range(MAX_OUTGOING - random.randint(1, MAX_OUTGOING))
        ]:
            self.nodePeer.outgoingCnxs.append(ip)
            self.nodePeer.learnIP(ip, self.sourceIP)

        # communicating nodes have heard of each other before
        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer2.learnIP(self.nodePeer.ipV4Addr, self.sourceIP)

        # add CONNECT event to network.eventQueue as only existing event
        connectEvent = event(srcNode=self.nodePeer,
                             destNode=self.nodePeer2,
                             eventType=CONNECT,
                             info=None)
        self.network.eventQueue.put((self.network.globalTime, connectEvent))

        # collect data, process event, collect data
        peerIP = self.nodePeer2.ipV4Addr
        bucket = self.nodePeer.mapToTriedBucket(peerIP)

        isPeerInTriedTableBefore = (peerIP in self.nodePeer.triedTable[bucket])
        self.network.processNextEvent()
        isPeerInTriedTableAfter = (peerIP in self.nodePeer.triedTable[bucket])

        # assert data correct
        self.assertFalse(isPeerInTriedTableBefore)
        self.assertTrue(isPeerInTriedTableAfter)
Beispiel #3
0
    def test_whenConnectSuccessToPeer_peerAddressInsertedIntoTried(self):
        # generate node with space for at least 1 new connection
        self.sourceIP = self.network.assignIP()
        for ip in [self.network.assignIP() for i in range(MAX_OUTGOING - random.randint(1, MAX_OUTGOING))]:
            self.nodePeer.outgoingCnxs.append(ip)
            self.nodePeer.learnIP(ip, self.sourceIP)

        # communicating nodes have heard of each other before
        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer2.learnIP(self.nodePeer.ipV4Addr, self.sourceIP)

        # add CONNECT event to network.eventQueue as only existing event
        connectEvent = event(srcNode=self.nodePeer, destNode=self.nodePeer2, eventType=CONNECT, info=None)
        self.network.eventQueue.put((self.network.globalTime, connectEvent))

        # collect data, process event, collect data
        peerIP = self.nodePeer2.ipV4Addr
        bucket = self.nodePeer.mapToTriedBucket(peerIP)

        isPeerInTriedTableBefore = (peerIP in self.nodePeer.triedTable[bucket])
        self.network.processNextEvent()
        isPeerInTriedTableAfter = (peerIP in self.nodePeer.triedTable[bucket])
        
        # assert data correct
        self.assertFalse(isPeerInTriedTableBefore)
        self.assertTrue(isPeerInTriedTableAfter)
Beispiel #4
0
    def test_whenAddressFromDnsSeeder_onlyAddedToNewTable(self):
        ip = self.network.assignIP()
        self.nodePeer2.ipV4Addr = ip
        self.network.ipToNodes[ip] = self.nodePeer2
        self.nodePeer.nonce = 'some nonce'
        
        # fill nodePeer's outgoing connection to force ip into new table
        for i in range(MAX_OUTGOING):
            outIp = self.network.assignIP()
            self.nodePeer.outgoingCnxs.append(outIp)

        connectionInfoEvent = event(srcNode=self.seederNode, destNode=self.nodePeer, eventType=CONNECTION_INFO, info=(DNS_MSG, [ip]))
        self.network.eventQueue.put((self.network.globalTime, connectionInfoEvent))

        self.nodePeer.learnIP(ip, self.seederNode.ipV4Addr)

        # run code (CONNECTION_INFO, and CONNECT)
        self.network.processNextEvent()

        # verify ip appears in new table and not tried table
        foundInNew = False
        for bucketNum, addressDictionary in enumerate(self.nodePeer.newTable):
            if ip in addressDictionary.keys():
                foundInNew = True

        foundInTried = False
        for bucketNum, addressDictionary in enumerate(self.nodePeer.triedTable):
            if ip in addressDictionary.keys():
                foundInTried = True

        self.assertTrue(foundInNew)
        self.assertFalse(foundInTried)
Beispiel #5
0
    def test_whenNodeRestarts_andNodeHasLessThanTwoOutgoingConnections_andElevenSecondsElapsed_receivesIPsFromSeeder(
            self):
        # patch MAX_OUTGOING instances in network.py so our node doesnt make any connections

        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer.addToTried(self.nodePeer2.ipV4Addr, 0)

        restartEvent = event(srcNode=self.nodePeer,
                             destNode=None,
                             eventType=RESTART,
                             info=None)
        self.network.eventQueue.put((0, restartEvent))

        # process RESTART event
        self.network.processNextEvent()

        # get time of REJOIN, place back in eventQueue
        rejoinTime, rejoinEvent = self.network.eventQueue.get()
        self.assertEqual(rejoinEvent.eventType, REJOIN)
        self.network.eventQueue.put((rejoinTime, rejoinEvent))

        # process REJOIN, AFTER_REJOIN_MAYBE_REQUEST_SEEDER events
        self.network.processNextEvent()
        self.network.processNextEvent()

        nextTime, nextEvent = self.network.eventQueue.get()

        # assert seeder request more than 11 seconds from rejoin event
        self.assertTrue(rejoinTime + 11 <= nextTime)

        # assert correct nodes involved in REQUEST_CONNECTION_INFO event
        self.assertEqual(nextEvent.srcNode, self.nodePeer)
        self.assertTrue(nextEvent.destNode in self.network.seederNodes)
        self.assertEqual(nextEvent.eventType, REQUEST_CONNECTION_INFO)
Beispiel #6
0
    def test_whenOutgoingConnectionEstablishedWithPeer_receiveAddrMsgFromPeer(self):
        # prepare nodes for CONNECT
        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer2.learnIP(self.nodePeer.ipV4Addr, self.sourceIP)
        # populate nodePeer2's tables with some IPs (that will be sent in ADDR)
        someIPs = [self.network.assignIP() for _ in range(100)]
        for ip in someIPs[:50]:
            self.nodePeer2.learnIP(ip, self.sourceIP)
            self.nodePeer2.addToTried(ip, 0)
        for ip in someIPs[50:]:
            self.nodePeer2.learnIP(ip, self.sourceIP)
            self.nodePeer2.addToNew(ip, 0)

        # prepare eventQueue
        connectEvent = event(srcNode=self.nodePeer, destNode=self.nodePeer2, eventType=CONNECT, info=None)
        self.network.eventQueue.put((self.network.globalTime, connectEvent))

        # process CONNECT event
        self.network.processNextEvent()

        # assert generated event is ADDR between correct nodes
        nextTime, nextEvent = self.network.eventQueue.get()
        self.assertEqual(nextEvent.eventType, CONNECTION_INFO)
        self.assertEqual(nextEvent.srcNode, self.nodePeer2)
        self.assertEqual(nextEvent.destNode, self.nodePeer)
        self.assertEqual(nextEvent.info[0], ADDR_MSG)

        # assert sent IPs come from nodePeer2's tables
        flattenedIPs = []
        for bucket in self.nodePeer2.triedTable:
            flattenedIPs.extend(bucket.keys())
        for bucket in self.nodePeer2.newTable:
            flattenedIPs.extend(bucket.keys())
        [self.assertTrue(ip in flattenedIPs) for ip in nextEvent.info[1]]
Beispiel #7
0
    def test_whenNodeMakesOutgoingConnectionRequest_doesNotExceedMaxOutgoingConnections(self):
        # generate node with max outgoing connections
        for ip in [self.network.assignIP() for i in range(MAX_OUTGOING)]:
            self.nodePeer.outgoingCnxs.append(ip)
            self.nodePeer.learnIP(ip, self.sourceIP)

        # communicating nodes have heard of each other before
        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer2.learnIP(self.nodePeer.ipV4Addr, self.sourceIP)

        # add CONNECT event to network.eventQueue as only existing event
        connectEvent = event(srcNode=self.nodePeer, destNode=self.nodePeer2, eventType=CONNECT, info=None)
        self.network.eventQueue.put((self.network.globalTime, connectEvent))

        # mock eventQueue.put from here forward so we can monitor when it is called
        self.network.eventQueue.put = mock.Mock()
        # mock randomness out
        latency = 0.1
        self.network.generateLatency = mock.Mock(return_value=latency)

        # collect data, process event, collect data
        numConnectionsBefore = len(self.nodePeer.outgoingCnxs)
        self.network.processNextEvent()
        numConnectionsAfter = len(self.nodePeer.outgoingCnxs)
        
        # assert data correct and monitored method called as expected
        self.assertEqual(numConnectionsBefore, numConnectionsAfter)
        self.network.eventQueue.put.assert_called_once_with((self.network.globalTime+latency, event(srcNode=self.nodePeer2, destNode=self.nodePeer, eventType=CONNECTION_FAILURE, info=None)))
Beispiel #8
0
    def test_whenBlacklistedNodeAttemptsToConnect_ignoreIt(
            self, mock_node_selectAddrs):
        # patch node.selectAddrs() to return too many addresses such that another node will blacklist it
        tooManyIPs = [[
            self.network.assignIP() for _ in range(MAX_ADDRS_PER_MSG + 1)
        ]]
        mock_node_selectAddrs.return_value = tooManyIPs

        # take measurements before
        totalConnectionsBefore1 = sum(self.nodePeer.incomingCnxs) + sum(
            self.nodePeer.outgoingCnxs)
        totalConnectionsBefore2 = sum(self.nodePeer2.incomingCnxs) + sum(
            self.nodePeer2.outgoingCnxs)
        newTableSizeBefore = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeBefore = sum([len(b) for b in self.nodePeer.triedTable])

        # prepare nodes for CONNECT
        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer2.learnIP(self.nodePeer.ipV4Addr, self.sourceIP)

        # prepare eventQueue
        connectEvent = event(srcNode=self.nodePeer,
                             destNode=self.nodePeer2,
                             eventType=CONNECT,
                             info=None)
        self.network.eventQueue.put((self.network.globalTime, connectEvent))

        # process CONNECT, CONNECTION_INFO events
        self.network.processNextEvent()
        self.network.processNextEvent()

        # assert ip is blacklisted
        self.assertTrue(
            self.nodePeer2.ipV4Addr in self.nodePeer.blacklistedIPs)

        # assert no connections kept
        totalConnectionsAfter1 = sum(self.nodePeer.incomingCnxs) + sum(
            self.nodePeer.outgoingCnxs)
        totalConnectionsAfter2 = sum(self.nodePeer2.incomingCnxs) + sum(
            self.nodePeer2.outgoingCnxs)
        self.assertEqual(totalConnectionsBefore1, totalConnectionsAfter1)
        self.assertEqual(totalConnectionsBefore2, totalConnectionsAfter2)

        # assert nothing was added to new table
        newTableSizeAfter = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeAfter = sum([len(b) for b in self.nodePeer.triedTable])
        self.assertEqual(newTableSizeBefore, newTableSizeAfter)
        self.assertEqual(triedTableSizeBefore + 1, triedTableSizeAfter)

        # assert nodePeer's tried table only contains blacklisted ip
        flattenedIPs = []
        for bucket in self.nodePeer.triedTable:
            flattenedIPs.extend(bucket.keys())
        self.assertEqual(len(flattenedIPs), 1)
        self.assertTrue(self.nodePeer2.ipV4Addr in flattenedIPs)
Beispiel #9
0
    def test_whenNodeJoinsNetwork_andSeederFailsToReply_usesHardcodedIPs(self):
        # patch constant SEEDER_REPLY_FAIL_RATE so we automatically decide seeder will timeout

        joinEvent = event(srcNode=self.nodePeer,
                          destNode=None,
                          eventType=JOIN,
                          info=None)
        self.network.eventQueue.put((0, joinEvent))

        newTableSizeBefore = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeBefore = sum([len(b) for b in self.nodePeer.triedTable])

        # process JOIN
        self.network.processNextEvent()

        # remove RESTART event
        time1, event1 = self.network.eventQueue.get()
        time2, event2 = self.network.eventQueue.get()
        if event1.eventType == REQUEST_CONNECTION_INFO:
            self.network.eventQueue.put((time1, event1))
        else:
            self.network.eventQueue.put((time2, event2))

        # process REQUEST_CONNECTION_INFO and USE_HARDCODED_IPS events
        self.network.processNextEvent()
        self.network.processNextEvent()

        newTableSizeAfter = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeAfter = sum([len(b) for b in self.nodePeer.triedTable])

        # assert all IPs in new table from HARDCODED_IP_SOURCE and network's hardcoded ip list
        for ip in self.nodePeer.ipToAddr.keys():
            sourceIP = self.nodePeer.ipToAddr[ip].sourceIP
            self.assertEqual(sourceIP, HARDCODED_IP_SOURCE)

            self.assertTrue(ip in self.network.hardcodedIPs)
        self.assertEqual(newTableSizeBefore + len(self.network.hardcodedIPs),
                         newTableSizeAfter)

        # assert tried table remains empty
        self.assertEqual(triedTableSizeBefore, 0)
        self.assertEqual(triedTableSizeAfter, 0)

        # assert MAX_OUTGOING connect events in eventQueue, all with source nodePeer, dest ip in hardcoded_list
        self.assertEqual(self.network.eventQueue.qsize(), MAX_OUTGOING)
        for i in range(MAX_OUTGOING):
            timestamp, thisEvent = self.network.eventQueue.get()

            self.assertEqual(thisEvent.eventType, CONNECT)
            self.assertEqual(thisEvent.srcNode, self.nodePeer)
            self.assertTrue(
                thisEvent.destNode.ipV4Addr in self.network.hardcodedIPs)
Beispiel #10
0
    def test_whenNodeReceivesIncomingConnectionRequest_doesNotExceedMaxIncomingConnections_andGeneratesConnectionFailureEvent(
            self):
        # generate node with max incoming connections
        for ip in [self.network.assignIP() for i in range(MAX_INCOMING)]:
            self.nodePeer.incomingCnxs.append(ip)
            self.nodePeer.learnIP(ip, self.sourceIP)

        # communicating nodes have heard of each other before
        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer2.learnIP(self.nodePeer.ipV4Addr, self.sourceIP)

        # add CONNECT event to network.eventQueue as only existing event
        connectEvent = event(srcNode=self.nodePeer2,
                             destNode=self.nodePeer,
                             eventType=CONNECT,
                             info=None)
        self.network.eventQueue.put((self.network.globalTime, connectEvent))

        # mock eventQueue.put from here forward so we can monitor when it is called
        self.network.eventQueue.put = mock.Mock()
        # mock randomness out
        latency = 0.1
        self.network.generateLatency = mock.Mock(return_value=latency)

        # collect data, process event, collect data
        numConnectionsBefore = len(self.nodePeer.incomingCnxs)
        self.network.processNextEvent()
        numConnectionsAfter = len(self.nodePeer.incomingCnxs)

        # assert data correct and monitored method called as expected
        self.assertEqual(numConnectionsBefore, numConnectionsAfter)
        self.network.eventQueue.put.assert_called_once_with(
            (self.network.globalTime + latency,
             event(srcNode=self.nodePeer,
                   destNode=self.nodePeer2,
                   eventType=CONNECTION_FAILURE,
                   info=None)))
Beispiel #11
0
    def test_whenNodeJoinsNetwork_andSeederFailsToReply_usesHardcodedIPs(self):
        # patch constant SEEDER_REPLY_FAIL_RATE so we automatically decide seeder will timeout

        joinEvent = event(srcNode=self.nodePeer, destNode=None, eventType=JOIN, info=None)
        self.network.eventQueue.put((0, joinEvent))

        newTableSizeBefore = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeBefore = sum([len(b) for b in self.nodePeer.triedTable])

        # process JOIN
        self.network.processNextEvent()

        # remove RESTART event
        time1, event1 = self.network.eventQueue.get()
        time2, event2 = self.network.eventQueue.get()
        if event1.eventType == REQUEST_CONNECTION_INFO:
            self.network.eventQueue.put((time1, event1))
        else:
            self.network.eventQueue.put((time2, event2))

        # process REQUEST_CONNECTION_INFO and USE_HARDCODED_IPS events
        self.network.processNextEvent()
        self.network.processNextEvent()

        newTableSizeAfter = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeAfter = sum([len(b) for b in self.nodePeer.triedTable])

        # assert all IPs in new table from HARDCODED_IP_SOURCE and network's hardcoded ip list
        for ip in self.nodePeer.ipToAddr.keys():
            sourceIP = self.nodePeer.ipToAddr[ip].sourceIP
            self.assertEqual(sourceIP, HARDCODED_IP_SOURCE)

            self.assertTrue(ip in self.network.hardcodedIPs)
        self.assertEqual(newTableSizeBefore + len(self.network.hardcodedIPs), newTableSizeAfter)

        # assert tried table remains empty
        self.assertEqual(triedTableSizeBefore, 0)
        self.assertEqual(triedTableSizeAfter, 0)

        # assert MAX_OUTGOING connect events in eventQueue, all with source nodePeer, dest ip in hardcoded_list
        self.assertEqual(self.network.eventQueue.qsize(), MAX_OUTGOING)
        for i in range(MAX_OUTGOING):
            timestamp, thisEvent = self.network.eventQueue.get()
            
            self.assertEqual(thisEvent.eventType, CONNECT)
            self.assertEqual(thisEvent.srcNode, self.nodePeer)
            self.assertTrue(thisEvent.destNode.ipV4Addr in self.network.hardcodedIPs)
Beispiel #12
0
    def test_whenBlacklistedNodeAttemptsToConnect_ignoreIt(self, mock_node_selectAddrs):
        # patch node.selectAddrs() to return too many addresses such that another node will blacklist it
        tooManyIPs = [[self.network.assignIP() for _ in range(MAX_ADDRS_PER_MSG+1)]]
        mock_node_selectAddrs.return_value = tooManyIPs

        # take measurements before
        totalConnectionsBefore1 = sum(self.nodePeer.incomingCnxs) + sum(self.nodePeer.outgoingCnxs)
        totalConnectionsBefore2 = sum(self.nodePeer2.incomingCnxs) + sum(self.nodePeer2.outgoingCnxs)
        newTableSizeBefore = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeBefore = sum([len(b) for b in self.nodePeer.triedTable])

        # prepare nodes for CONNECT
        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer2.learnIP(self.nodePeer.ipV4Addr, self.sourceIP)

        # prepare eventQueue
        connectEvent = event(srcNode=self.nodePeer, destNode=self.nodePeer2, eventType=CONNECT, info=None)
        self.network.eventQueue.put((self.network.globalTime, connectEvent))

        # process CONNECT, CONNECTION_INFO events
        self.network.processNextEvent()
        self.network.processNextEvent()

        # assert ip is blacklisted
        self.assertTrue(self.nodePeer2.ipV4Addr in self.nodePeer.blacklistedIPs)

        # assert no connections kept
        totalConnectionsAfter1 = sum(self.nodePeer.incomingCnxs) + sum(self.nodePeer.outgoingCnxs)
        totalConnectionsAfter2 = sum(self.nodePeer2.incomingCnxs) + sum(self.nodePeer2.outgoingCnxs)
        self.assertEqual(totalConnectionsBefore1, totalConnectionsAfter1)
        self.assertEqual(totalConnectionsBefore2, totalConnectionsAfter2)

        # assert nothing was added to new table
        newTableSizeAfter = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeAfter = sum([len(b) for b in self.nodePeer.triedTable])
        self.assertEqual(newTableSizeBefore, newTableSizeAfter)
        self.assertEqual(triedTableSizeBefore + 1, triedTableSizeAfter)

        # assert nodePeer's tried table only contains blacklisted ip
        flattenedIPs = []
        for bucket in self.nodePeer.triedTable:
            flattenedIPs.extend(bucket.keys())
        self.assertEqual(len(flattenedIPs), 1)
        self.assertTrue(self.nodePeer2.ipV4Addr in flattenedIPs)
Beispiel #13
0
    def test_whenSelectingBucket_useSchemeFromPaper(self):
        ip = self.network.assignIP()
        self.nodePeer2.ipV4Addr = ip
        self.network.ipToNodes[ip] = self.nodePeer2
        self.nodePeer.nonce = 'some nonce'

        # fill nodePeer's outgoing connection to force ip into new table
        for i in range(MAX_OUTGOING):
            outIp = self.network.assignIP()
            self.nodePeer.outgoingCnxs.append(outIp)

        connectionInfoEvent = event(srcNode=self.seederNode,
                                    destNode=self.nodePeer,
                                    eventType=CONNECTION_INFO,
                                    info=(DNS_MSG, [ip]))
        self.network.eventQueue.put(
            (self.network.globalTime, connectionInfoEvent))

        self.nodePeer.learnIP(ip, self.seederNode.ipV4Addr)
        sourceIp = self.nodePeer.ipToAddr[ip].sourceIP

        # compute bucket manually
        ipTemp = ip.split('.')
        ipGroup = ipTemp[0] + '.' + ipTemp[1]

        sourceTemp = sourceIp.split('.')
        srcIPGroup = sourceTemp[0] + '.' + sourceTemp[1]

        nonce = str(self.nodePeer.nonce)
        i = hash(nonce + ipGroup + srcIPGroup) % 32
        expectedBucket = hash(nonce + srcIPGroup + str(i)) % 256

        # run code
        self.network.processNextEvent()

        # verify bucket
        actualBucket = []
        for bucketNum, addressDictionary in enumerate(self.nodePeer.newTable):
            if ip in addressDictionary.keys():
                actualBucket.append(bucketNum)

        self.assertEqual(len(actualBucket), 1)
        self.assertEqual(actualBucket[0], expectedBucket)
Beispiel #14
0
    def test_whenNodeJoinsNetwork_receivesIPsFromSeeder(self):
        # patch constant SEEDER_REPLY_FAIL_RATE so we automatically decide seeder does not timeout

        joinEvent = event(srcNode=self.nodePeer,
                          destNode=None,
                          eventType=JOIN,
                          info=None)
        self.network.eventQueue.put((0, joinEvent))

        newTableSizeBefore = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeBefore = sum([len(b) for b in self.nodePeer.triedTable])

        # process JOIN
        self.network.processNextEvent()

        # get a hold of seeder node, place event back in eventQueue
        eventTime, reqConInfoEvent = self.network.eventQueue.get()
        self.assertEquals(reqConInfoEvent.eventType, REQUEST_CONNECTION_INFO)
        self.seederNode = reqConInfoEvent.destNode
        self.network.eventQueue.put((eventTime, reqConInfoEvent))

        # process REQUEST_CONNECTION_INFO and CONNECTION_INFO
        self.network.processNextEvent()
        self.network.processNextEvent()

        newTableSizeAfter = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeAfter = sum([len(b) for b in self.nodePeer.triedTable])

        # assert all new table entries from seeder
        for ip in self.nodePeer.ipToAddr.keys():
            sourceIP = self.nodePeer.ipToAddr[ip].sourceIP
            self.assertEqual(sourceIP, self.seederNode.ipV4Addr)

            self.assertTrue(ip in self.seederNode.knownIPs)
        self.assertEqual(newTableSizeBefore + DNS_QUERY_SIZE,
                         newTableSizeAfter)

        # assert tried table remains empty
        self.assertEqual(triedTableSizeBefore, 0)
        self.assertEqual(triedTableSizeAfter, 0)
Beispiel #15
0
    def test_whenSelectingBucket_useSchemeFromPaper(self):
        ip = self.network.assignIP()
        self.nodePeer2.ipV4Addr = ip
        self.network.ipToNodes[ip] = self.nodePeer2
        self.nodePeer.nonce = 'some nonce'
        
        # fill nodePeer's outgoing connection to force ip into new table
        for i in range(MAX_OUTGOING):
            outIp = self.network.assignIP()
            self.nodePeer.outgoingCnxs.append(outIp)

        connectionInfoEvent = event(srcNode=self.seederNode, destNode=self.nodePeer, eventType=CONNECTION_INFO, info=(DNS_MSG, [ip]))
        self.network.eventQueue.put((self.network.globalTime, connectionInfoEvent))

        self.nodePeer.learnIP(ip, self.seederNode.ipV4Addr)
        sourceIp = self.nodePeer.ipToAddr[ip].sourceIP

        # compute bucket manually
        ipTemp = ip.split('.')
        ipGroup = ipTemp[0] + '.' + ipTemp[1]

        sourceTemp = sourceIp.split('.')
        srcIPGroup = sourceTemp[0] + '.' + sourceTemp[1] 

        nonce = str(self.nodePeer.nonce)
        i = hash(nonce + ipGroup + srcIPGroup) % 32
        expectedBucket = hash(nonce + srcIPGroup + str(i)) % 256
        
        # run code
        self.network.processNextEvent()

        # verify bucket
        actualBucket = []
        for bucketNum, addressDictionary in enumerate(self.nodePeer.newTable):
            if ip in addressDictionary.keys():
                actualBucket.append(bucketNum)

        self.assertEqual(len(actualBucket), 1)
        self.assertEqual(actualBucket[0], expectedBucket)
Beispiel #16
0
    def test_whenOutgoingConnectionEstablishedWithPeer_receiveAddrMsgFromPeer(
            self):
        # prepare nodes for CONNECT
        self.nodePeer.learnIP(self.nodePeer2.ipV4Addr, self.sourceIP)
        self.nodePeer2.learnIP(self.nodePeer.ipV4Addr, self.sourceIP)
        # populate nodePeer2's tables with some IPs (that will be sent in ADDR)
        someIPs = [self.network.assignIP() for _ in range(100)]
        for ip in someIPs[:50]:
            self.nodePeer2.learnIP(ip, self.sourceIP)
            self.nodePeer2.addToTried(ip, 0)
        for ip in someIPs[50:]:
            self.nodePeer2.learnIP(ip, self.sourceIP)
            self.nodePeer2.addToNew(ip, 0)

        # prepare eventQueue
        connectEvent = event(srcNode=self.nodePeer,
                             destNode=self.nodePeer2,
                             eventType=CONNECT,
                             info=None)
        self.network.eventQueue.put((self.network.globalTime, connectEvent))

        # process CONNECT event
        self.network.processNextEvent()

        # assert generated event is ADDR between correct nodes
        nextTime, nextEvent = self.network.eventQueue.get()
        self.assertEqual(nextEvent.eventType, CONNECTION_INFO)
        self.assertEqual(nextEvent.srcNode, self.nodePeer2)
        self.assertEqual(nextEvent.destNode, self.nodePeer)
        self.assertEqual(nextEvent.info[0], ADDR_MSG)

        # assert sent IPs come from nodePeer2's tables
        flattenedIPs = []
        for bucket in self.nodePeer2.triedTable:
            flattenedIPs.extend(bucket.keys())
        for bucket in self.nodePeer2.newTable:
            flattenedIPs.extend(bucket.keys())
        [self.assertTrue(ip in flattenedIPs) for ip in nextEvent.info[1]]
Beispiel #17
0
    def test_whenAddressFromDnsSeeder_onlyAddedToNewTable(self):
        ip = self.network.assignIP()
        self.nodePeer2.ipV4Addr = ip
        self.network.ipToNodes[ip] = self.nodePeer2
        self.nodePeer.nonce = 'some nonce'

        # fill nodePeer's outgoing connection to force ip into new table
        for i in range(MAX_OUTGOING):
            outIp = self.network.assignIP()
            self.nodePeer.outgoingCnxs.append(outIp)

        connectionInfoEvent = event(srcNode=self.seederNode,
                                    destNode=self.nodePeer,
                                    eventType=CONNECTION_INFO,
                                    info=(DNS_MSG, [ip]))
        self.network.eventQueue.put(
            (self.network.globalTime, connectionInfoEvent))

        self.nodePeer.learnIP(ip, self.seederNode.ipV4Addr)

        # run code (CONNECTION_INFO, and CONNECT)
        self.network.processNextEvent()

        # verify ip appears in new table and not tried table
        foundInNew = False
        for bucketNum, addressDictionary in enumerate(self.nodePeer.newTable):
            if ip in addressDictionary.keys():
                foundInNew = True

        foundInTried = False
        for bucketNum, addressDictionary in enumerate(
                self.nodePeer.triedTable):
            if ip in addressDictionary.keys():
                foundInTried = True

        self.assertTrue(foundInNew)
        self.assertFalse(foundInTried)
Beispiel #18
0
    def test_whenNodeJoinsNetwork_receivesIPsFromSeeder(self):
        # patch constant SEEDER_REPLY_FAIL_RATE so we automatically decide seeder does not timeout

        joinEvent = event(srcNode = self.nodePeer, destNode = None, eventType = JOIN, info = None)
        self.network.eventQueue.put((0, joinEvent))

        newTableSizeBefore = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeBefore = sum([len(b) for b in self.nodePeer.triedTable])

        # process JOIN
        self.network.processNextEvent()
        
        # get a hold of seeder node, place event back in eventQueue
        eventTime, reqConInfoEvent = self.network.eventQueue.get()
        self.assertEquals(reqConInfoEvent.eventType, REQUEST_CONNECTION_INFO)
        self.seederNode = reqConInfoEvent.destNode
        self.network.eventQueue.put((eventTime, reqConInfoEvent))

        # process REQUEST_CONNECTION_INFO and CONNECTION_INFO
        self.network.processNextEvent()
        self.network.processNextEvent()

        newTableSizeAfter = sum([len(b) for b in self.nodePeer.newTable])
        triedTableSizeAfter = sum([len(b) for b in self.nodePeer.triedTable])

        # assert all new table entries from seeder
        for ip in self.nodePeer.ipToAddr.keys():
            sourceIP = self.nodePeer.ipToAddr[ip].sourceIP
            self.assertEqual(sourceIP, self.seederNode.ipV4Addr)

            self.assertTrue(ip in self.seederNode.knownIPs)
        self.assertEqual(newTableSizeBefore + DNS_QUERY_SIZE, newTableSizeAfter)

        # assert tried table remains empty
        self.assertEqual(triedTableSizeBefore, 0)
        self.assertEqual(triedTableSizeAfter, 0)