def sendaddr(self):
        addrsInMyStream = {}
        addrsInChildStreamLeft = {}
        addrsInChildStreamRight = {}
        # print 'knownNodes', shared.knownNodes

        # We are going to share a maximum number of 1000 addrs with our peer.
        # 500 from this stream, 250 from the left child stream, and 250 from
        # the right child stream.
        shared.knownNodesLock.acquire()
        if len(shared.knownNodes[self.streamNumber]) > 0:
            for i in range(500):
                peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
                if helper_generic.isHostInPrivateIPRange(peer.host):
                    continue
                addrsInMyStream[peer] = shared.knownNodes[
                    self.streamNumber][peer]
        if len(shared.knownNodes[self.streamNumber * 2]) > 0:
            for i in range(250):
                peer, = random.sample(shared.knownNodes[
                                      self.streamNumber * 2], 1)
                if helper_generic.isHostInPrivateIPRange(peer.host):
                    continue
                addrsInChildStreamLeft[peer] = shared.knownNodes[
                    self.streamNumber * 2][peer]
        if len(shared.knownNodes[(self.streamNumber * 2) + 1]) > 0:
            for i in range(250):
                peer, = random.sample(shared.knownNodes[
                                      (self.streamNumber * 2) + 1], 1)
                if helper_generic.isHostInPrivateIPRange(peer.host):
                    continue
                addrsInChildStreamRight[peer] = shared.knownNodes[
                    (self.streamNumber * 2) + 1][peer]
        shared.knownNodesLock.release()
        numberOfAddressesInAddrMessage = 0
        payload = ''
        # print 'addrsInMyStream.items()', addrsInMyStream.items()
        for (HOST, PORT), value in addrsInMyStream.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', self.streamNumber)
                payload += pack(
                    '>q', 1)  # service bit flags offered by this node
                payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \
                    socket.inet_aton(HOST)
                payload += pack('>H', PORT)  # remote port
        for (HOST, PORT), value in addrsInChildStreamLeft.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', self.streamNumber * 2)
                payload += pack(
                    '>q', 1)  # service bit flags offered by this node
                payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \
                    socket.inet_aton(HOST)
                payload += pack('>H', PORT)  # remote port
        for (HOST, PORT), value in addrsInChildStreamRight.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', (self.streamNumber * 2) + 1)
                payload += pack(
                    '>q', 1)  # service bit flags offered by this node
                payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \
                    socket.inet_aton(HOST)
                payload += pack('>H', PORT)  # remote port

        payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
        datatosend = '\xE9\xBE\xB4\xD9addr\x00\x00\x00\x00\x00\x00\x00\x00'
        datatosend = datatosend + pack('>L', len(payload))  # payload length
        datatosend = datatosend + hashlib.sha512(payload).digest()[0:4]
        datatosend = datatosend + payload
        self.sendDataThreadQueue.put((0, 'sendRawData', datatosend))
    def sendaddr(self):
        addrsInMyStream = {}
        addrsInChildStreamLeft = {}
        addrsInChildStreamRight = {}
        # print 'knownNodes', shared.knownNodes

        # We are going to share a maximum number of 1000 addrs with our peer.
        # 500 from this stream, 250 from the left child stream, and 250 from
        # the right child stream.
        shared.knownNodesLock.acquire()
        if len(shared.knownNodes[self.streamNumber]) > 0:
            for i in range(500):
                peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
                if isHostInPrivateIPRange(peer.host):
                    continue
                addrsInMyStream[peer] = shared.knownNodes[self.streamNumber][peer]
        if len(shared.knownNodes[self.streamNumber * 2]) > 0:
            for i in range(250):
                peer, = random.sample(shared.knownNodes[self.streamNumber * 2], 1)
                if isHostInPrivateIPRange(peer.host):
                    continue
                addrsInChildStreamLeft[peer] = shared.knownNodes[self.streamNumber * 2][peer]
        if len(shared.knownNodes[(self.streamNumber * 2) + 1]) > 0:
            for i in range(250):
                peer, = random.sample(shared.knownNodes[(self.streamNumber * 2) + 1], 1)
                if isHostInPrivateIPRange(peer.host):
                    continue
                addrsInChildStreamRight[peer] = shared.knownNodes[(self.streamNumber * 2) + 1][peer]
        shared.knownNodesLock.release()
        numberOfAddressesInAddrMessage = 0
        payload = ""
        # print 'addrsInMyStream.items()', addrsInMyStream.items()
        for (HOST, PORT), value in addrsInMyStream.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (
                int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers
            ):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(">Q", timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack(">I", self.streamNumber)
                payload += pack(">q", 1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack(">H", PORT)  # remote port
        for (HOST, PORT), value in addrsInChildStreamLeft.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (
                int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers
            ):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(">Q", timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack(">I", self.streamNumber * 2)
                payload += pack(">q", 1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack(">H", PORT)  # remote port
        for (HOST, PORT), value in addrsInChildStreamRight.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (
                int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers
            ):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(">Q", timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack(">I", (self.streamNumber * 2) + 1)
                payload += pack(">q", 1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack(">H", PORT)  # remote port

        payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
        self.sendDataThreadQueue.put((0, "sendRawData", shared.CreatePacket("addr", payload)))
    def recversion(self, data):
        if len(data) < 83:
            # This version message is unreasonably short. Forget it.
            return
        if self.verackSent:
            """
            We must have already processed the remote node's version message.
            There might be a time in the future when we Do want to process
            a new version message, like if the remote node wants to update
            the streams in which they are interested. But for now we'll
            ignore this version message
            """ 
            return
        self.remoteProtocolVersion, = unpack('>L', data[:4])
        self.services, = unpack('>q', data[4:12])
        if self.remoteProtocolVersion < 3:
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            logger.debug ('Closing connection to old protocol version ' + str(self.remoteProtocolVersion) + ' node: ' + str(self.peer))
            return
        timestamp, = unpack('>Q', data[12:20])
        timeOffset = timestamp - int(time.time())
        if timeOffset > 3600:
            self.sendDataThreadQueue.put((0, 'sendRawData', shared.assembleErrorMessage(fatal=2, errorText="Your time is too far in the future compared to mine. Closing connection.")))
            logger.info("%s's time is too far in the future (%s seconds). Closing connection to it." % (self.peer, timeOffset))
            time.sleep(2)
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            return
        if timeOffset < -3600:
            self.sendDataThreadQueue.put((0, 'sendRawData', shared.assembleErrorMessage(fatal=2, errorText="Your time is too far in the past compared to mine. Closing connection.")))
            logger.info("%s's time is too far in the past (timeOffset %s seconds). Closing connection to it." % (self.peer, timeOffset))
            time.sleep(2)
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            return 
        self.myExternalIP = socket.inet_ntoa(data[40:44])
        # print 'myExternalIP', self.myExternalIP
        self.remoteNodeIncomingPort, = unpack('>H', data[70:72])
        # print 'remoteNodeIncomingPort', self.remoteNodeIncomingPort
        useragentLength, lengthOfUseragentVarint = decodeVarint(
            data[80:84])
        readPosition = 80 + lengthOfUseragentVarint
        useragent = data[readPosition:readPosition + useragentLength]
        
        # version check
        try:
            userAgentName, userAgentVersion = useragent[1:-1].split(":", 2)
        except:
            userAgentName = useragent
            userAgentVersion = "0.0.0"
        if userAgentName == "PyBitmessage":
            myVersion = [int(n) for n in shared.softwareVersion.split(".")]
            try:
                remoteVersion = [int(n) for n in userAgentVersion.split(".")]
            except:
                remoteVersion = 0
            # remote is newer, but do not cross between stable and unstable
            try:
                if cmp(remoteVersion, myVersion) > 0 and \
                    (myVersion[1] % 2 == remoteVersion[1] % 2):
                    shared.UISignalQueue.put(('newVersionAvailable', remoteVersion))
            except:
                pass
                
        readPosition += useragentLength
        numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(
            data[readPosition:])
        readPosition += lengthOfNumberOfStreamsInVersionMessage
        self.streamNumber, lengthOfRemoteStreamNumber = decodeVarint(
            data[readPosition:])
        logger.debug('Remote node useragent: ' + useragent + '  stream number:' + str(self.streamNumber) + '  time offset: ' + str(timeOffset) + ' seconds.')

        if self.streamNumber != 1:
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            logger.debug ('Closed connection to ' + str(self.peer) + ' because they are interested in stream ' + str(self.streamNumber) + '.')
            return
        shared.connectedHostsList[
            self.peer.host] = 1  # We use this data structure to not only keep track of what hosts we are connected to so that we don't try to connect to them again, but also to list the connections count on the Network Status tab.
        # If this was an incoming connection, then the sendDataThread
        # doesn't know the stream. We have to set it.
        if not self.initiatedConnection:
            self.sendDataThreadQueue.put((0, 'setStreamNumber', self.streamNumber))
        if data[72:80] == shared.eightBytesOfRandomDataUsedToDetectConnectionsToSelf:
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            logger.debug('Closing connection to myself: ' + str(self.peer))
            return
        
        # The other peer's protocol version is of interest to the sendDataThread but we learn of it
        # in this version message. Let us inform the sendDataThread.
        self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))

        if not isHostInPrivateIPRange(self.peer.host):
            with shared.knownNodesLock:
                shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
                shared.needToWriteKnownNodesToDisk = True

        self.sendverack()
        if self.initiatedConnection == False:
            self.sendversion()
    def sendaddr(self):
        addrsInMyStream = {}
        addrsInChildStreamLeft = {}
        addrsInChildStreamRight = {}
        # print 'knownNodes', shared.knownNodes

        # We are going to share a maximum number of 1000 addrs with our peer.
        # 500 from this stream, 250 from the left child stream, and 250 from
        # the right child stream.
        with shared.knownNodesLock:
            if len(shared.knownNodes[self.streamNumber]) > 0:
                for i in range(500):
                    peer, = random.sample(shared.knownNodes[self.streamNumber],
                                          1)
                    if isHostInPrivateIPRange(peer.host):
                        continue
                    addrsInMyStream[peer] = shared.knownNodes[
                        self.streamNumber][peer]
            if len(shared.knownNodes[self.streamNumber * 2]) > 0:
                for i in range(250):
                    peer, = random.sample(
                        shared.knownNodes[self.streamNumber * 2], 1)
                    if isHostInPrivateIPRange(peer.host):
                        continue
                    addrsInChildStreamLeft[peer] = shared.knownNodes[
                        self.streamNumber * 2][peer]
            if len(shared.knownNodes[(self.streamNumber * 2) + 1]) > 0:
                for i in range(250):
                    peer, = random.sample(
                        shared.knownNodes[(self.streamNumber * 2) + 1], 1)
                    if isHostInPrivateIPRange(peer.host):
                        continue
                    addrsInChildStreamRight[peer] = shared.knownNodes[
                        (self.streamNumber * 2) + 1][peer]
        numberOfAddressesInAddrMessage = 0
        payload = ''
        # print 'addrsInMyStream.items()', addrsInMyStream.items()
        for (HOST, PORT), value in addrsInMyStream.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (
                    int(time.time()) -
                    shared.maximumAgeOfNodesThatIAdvertiseToOthers
            ):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', self.streamNumber)
                payload += pack('>q',
                                1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack('>H', PORT)  # remote port
        for (HOST, PORT), value in addrsInChildStreamLeft.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (
                    int(time.time()) -
                    shared.maximumAgeOfNodesThatIAdvertiseToOthers
            ):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', self.streamNumber * 2)
                payload += pack('>q',
                                1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack('>H', PORT)  # remote port
        for (HOST, PORT), value in addrsInChildStreamRight.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (
                    int(time.time()) -
                    shared.maximumAgeOfNodesThatIAdvertiseToOthers
            ):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', (self.streamNumber * 2) + 1)
                payload += pack('>q',
                                1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack('>H', PORT)  # remote port

        payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
        self.sendDataThreadQueue.put(
            (0, 'sendRawData', shared.CreatePacket('addr', payload)))
Example #5
0
    def recversion(self, data):
        if len(data) < 83:
            # This version message is unreasonably short. Forget it.
            return
        if self.verackSent:
            """
            We must have already processed the remote node's version message.
            There might be a time in the future when we Do want to process
            a new version message, like if the remote node wants to update
            the streams in which they are interested. But for now we'll
            ignore this version message
            """ 
            return

        self.remoteProtocolVersion, = unpack('>L', data[:4])
        self.services, = unpack('>q', data[4:12])

        timestamp, = unpack('>Q', data[12:20])
        self.timeOffset = timestamp - int(time.time())

        self.myExternalIP = socket.inet_ntoa(data[40:44])
        # print 'myExternalIP', self.myExternalIP
        self.remoteNodeIncomingPort, = unpack('>H', data[70:72])
        # print 'remoteNodeIncomingPort', self.remoteNodeIncomingPort
        useragentLength, lengthOfUseragentVarint = decodeVarint(
            data[80:84])
        readPosition = 80 + lengthOfUseragentVarint
        self.userAgent = data[readPosition:readPosition + useragentLength]

        readPosition += useragentLength
        numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(
            data[readPosition:])
        readPosition += lengthOfNumberOfStreamsInVersionMessage
        self.remoteStreams = []
        for i in xrange(numberOfStreamsInVersionMessage):
            newStreamNumber, lengthOfRemoteStreamNumber = decodeVarint(data[readPosition:])
            readPosition += lengthOfRemoteStreamNumber
            self.remoteStreams.append(newStreamNumber)
        logger.debug('Remote node useragent: %s, streams: (%s), time offset: %is.',
            self.userAgent, ', '.join(str(x) for x in self.remoteStreams), self.timeOffset)

        # find shared streams
        self.streamNumber = sorted(set(state.streamsInWhichIAmParticipating).intersection(self.remoteStreams))

        self.remoteNodeId, = unpack('>Q', data[72:80])

        if not self.validatePeer():
            time.sleep(2)
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            self.checkTimeOffsetNotification()
            return

        shared.connectedHostsList[
            self.hostIdent] = 1  # We use this data structure to not only keep track of what hosts we are connected to so that we don't try to connect to them again, but also to list the connections count on the Network Status tab.

        self.sendDataThreadQueue.put((0, 'setStreamNumber', self.remoteStreams))

        # The other peer's protocol version is of interest to the sendDataThread but we learn of it
        # in this version message. Let us inform the sendDataThread.
        self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))

        if not isHostInPrivateIPRange(self.peer.host):
            with knownnodes.knownNodesLock:
                for stream in self.remoteStreams:
                    knownnodes.knownNodes[stream][state.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
                    if not self.initiatedConnection:
                        # bootstrap provider?
                        if BMConfigParser().safeGetInt('bitmessagesettings', 'maxoutboundconnections') >= \
                            BMConfigParser().safeGetInt('bitmessagesettings', 'maxtotalconnections', 200):
                            knownnodes.knownNodes[stream][state.Peer(self.peer.host, self.remoteNodeIncomingPort)] -= 10800 # penalise inbound, 3 hours
                        else:
                            knownnodes.knownNodes[stream][state.Peer(self.peer.host, self.remoteNodeIncomingPort)] -= 7200 # penalise inbound, 2 hours
                    shared.needToWriteKnownNodesToDisk = True

        self.sendverack()
        if self.initiatedConnection == False:
            self.sendversion()
    def recversion(self, data):
        if len(data) < 83:
            # This version message is unreasonably short. Forget it.
            return
        if self.verackSent:
            """
            We must have already processed the remote node's version message.
            There might be a time in the future when we Do want to process
            a new version message, like if the remote node wants to update
            the streams in which they are interested. But for now we'll
            ignore this version message
            """ 
            return
        self.remoteProtocolVersion, = unpack('>L', data[:4])
        self.services, = unpack('>q', data[4:12])
        if self.remoteProtocolVersion < 3:
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            logger.debug ('Closing connection to old protocol version ' + str(self.remoteProtocolVersion) + ' node: ' + str(self.peer))
            return
        timestamp, = unpack('>Q', data[12:20])
        timeOffset = timestamp - int(time.time())
        if timeOffset > 3600:
            self.sendDataThreadQueue.put((0, 'sendRawData', shared.assembleErrorMessage(fatal=2, errorText="Your time is too far in the future compared to mine. Closing connection.")))
            logger.info("%s's time is too far in the future (%s seconds). Closing connection to it." % (self.peer, timeOffset))
            time.sleep(2)
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            return
        if timeOffset < -3600:
            self.sendDataThreadQueue.put((0, 'sendRawData', shared.assembleErrorMessage(fatal=2, errorText="Your time is too far in the past compared to mine. Closing connection.")))
            logger.info("%s's time is too far in the past (timeOffset %s seconds). Closing connection to it." % (self.peer, timeOffset))
            time.sleep(2)
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            return 
        self.myExternalIP = socket.inet_ntoa(data[40:44])
        # print 'myExternalIP', self.myExternalIP
        self.remoteNodeIncomingPort, = unpack('>H', data[70:72])
        # print 'remoteNodeIncomingPort', self.remoteNodeIncomingPort
        useragentLength, lengthOfUseragentVarint = decodeVarint(
            data[80:84])
        readPosition = 80 + lengthOfUseragentVarint
        useragent = data[readPosition:readPosition + useragentLength]
        
        # version check
        try:
            userAgentName, userAgentVersion = useragent[1:-1].split(":", 2)
        except:
            userAgentName = useragent
            userAgentVersion = "0.0.0"
        if userAgentName == "PyBitmessage":
            myVersion = [int(n) for n in shared.softwareVersion.split(".")]
            try:
                remoteVersion = [int(n) for n in userAgentVersion.split(".")]
            except:
                remoteVersion = 0
            # remote is newer, but do not cross between stable and unstable
            try:
                if cmp(remoteVersion, myVersion) > 0 and \
                    (myVersion[1] % 2 == remoteVersion[1] % 2):
                    shared.UISignalQueue.put(('newVersionAvailable', remoteVersion))
            except:
                pass
                
        readPosition += useragentLength
        numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(
            data[readPosition:])
        readPosition += lengthOfNumberOfStreamsInVersionMessage
        self.streamNumber, lengthOfRemoteStreamNumber = decodeVarint(
            data[readPosition:])
        logger.debug('Remote node useragent: ' + useragent + '  stream number:' + str(self.streamNumber) + '  time offset: ' + str(timeOffset) + ' seconds.')

        if self.streamNumber != 1:
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            logger.debug ('Closed connection to ' + str(self.peer) + ' because they are interested in stream ' + str(self.streamNumber) + '.')
            return
        shared.connectedHostsList[
            self.peer.host] = 1  # We use this data structure to not only keep track of what hosts we are connected to so that we don't try to connect to them again, but also to list the connections count on the Network Status tab.
        # If this was an incoming connection, then the sendDataThread
        # doesn't know the stream. We have to set it.
        if not self.initiatedConnection:
            self.sendDataThreadQueue.put((0, 'setStreamNumber', self.streamNumber))
        if data[72:80] == shared.eightBytesOfRandomDataUsedToDetectConnectionsToSelf:
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            logger.debug('Closing connection to myself: ' + str(self.peer))
            return
        
        # The other peer's protocol version is of interest to the sendDataThread but we learn of it
        # in this version message. Let us inform the sendDataThread.
        self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))

        if not isHostInPrivateIPRange(self.peer.host):
            with shared.knownNodesLock:
                shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
                if not self.initiatedConnection:
                    shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] -= 162000 # penalise inbound, 2 days minus 3 hours
                shared.needToWriteKnownNodesToDisk = True

        self.sendverack()
        if self.initiatedConnection == False:
            self.sendversion()
    def sendaddr(self):
        addrsInMyStream = {}
        addrsInChildStreamLeft = {}
        addrsInChildStreamRight = {}
        # print 'knownNodes', shared.knownNodes

        # We are going to share a maximum number of 1000 addrs with our peer.
        # 500 from this stream, 250 from the left child stream, and 250 from
        # the right child stream.
        with shared.knownNodesLock:
            if len(shared.knownNodes[self.streamNumber]) > 0:
                ownPosition = random.randint(0, 499)
                sentOwn = False
                for i in range(500):
                    # if current connection is over a proxy, sent our own onion address at a random position
                    if ownPosition == i and ".onion" in shared.config.get("bitmessagesettings", "onionhostname") and \
                        hasattr(self.sock, "getproxytype") and self.sock.getproxytype() != "none" and not sentOwn:
                        peer = shared.Peer(shared.config.get("bitmessagesettings", "onionhostname"), shared.config.getint("bitmessagesettings", "onionport"))
                    else:
                    # still may contain own onion address, but we don't change it
                        peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
                    if isHostInPrivateIPRange(peer.host):
                        continue
                    if peer.host == shared.config.get("bitmessagesettings", "onionhostname") and peer.port == shared.config.getint("bitmessagesettings", "onionport") :
                        sentOwn = True
                    addrsInMyStream[peer] = shared.knownNodes[
                        self.streamNumber][peer]
            if len(shared.knownNodes[self.streamNumber * 2]) > 0:
                for i in range(250):
                    peer, = random.sample(shared.knownNodes[
                                          self.streamNumber * 2], 1)
                    if isHostInPrivateIPRange(peer.host):
                        continue
                    addrsInChildStreamLeft[peer] = shared.knownNodes[
                        self.streamNumber * 2][peer]
            if len(shared.knownNodes[(self.streamNumber * 2) + 1]) > 0:
                for i in range(250):
                    peer, = random.sample(shared.knownNodes[
                                          (self.streamNumber * 2) + 1], 1)
                    if isHostInPrivateIPRange(peer.host):
                        continue
                    addrsInChildStreamRight[peer] = shared.knownNodes[
                        (self.streamNumber * 2) + 1][peer]
        numberOfAddressesInAddrMessage = 0
        payload = ''
        # print 'addrsInMyStream.items()', addrsInMyStream.items()
        for (HOST, PORT), value in addrsInMyStream.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', self.streamNumber)
                payload += pack(
                    '>q', 1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack('>H', PORT)  # remote port
        for (HOST, PORT), value in addrsInChildStreamLeft.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', self.streamNumber * 2)
                payload += pack(
                    '>q', 1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack('>H', PORT)  # remote port
        for (HOST, PORT), value in addrsInChildStreamRight.items():
            timeLastReceivedMessageFromThisNode = value
            if timeLastReceivedMessageFromThisNode > (int(time.time()) - shared.maximumAgeOfNodesThatIAdvertiseToOthers):  # If it is younger than 3 hours old..
                numberOfAddressesInAddrMessage += 1
                payload += pack(
                    '>Q', timeLastReceivedMessageFromThisNode)  # 64-bit time
                payload += pack('>I', (self.streamNumber * 2) + 1)
                payload += pack(
                    '>q', 1)  # service bit flags offered by this node
                payload += shared.encodeHost(HOST)
                payload += pack('>H', PORT)  # remote port

        payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
        self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('addr', payload)))
Example #8
0
    def recversion(self, data):
        if len(data) < 83:
            # This version message is unreasonably short. Forget it.
            return
        if self.verackSent:
            """
            We must have already processed the remote node's version message.
            There might be a time in the future when we Do want to process
            a new version message, like if the remote node wants to update
            the streams in which they are interested. But for now we'll
            ignore this version message
            """
            return

        self.remoteProtocolVersion, = unpack('>L', data[:4])
        self.services, = unpack('>q', data[4:12])

        timestamp, = unpack('>Q', data[12:20])
        self.timeOffset = timestamp - int(time.time())

        self.myExternalIP = socket.inet_ntoa(data[40:44])
        # print 'myExternalIP', self.myExternalIP
        self.remoteNodeIncomingPort, = unpack('>H', data[70:72])
        # print 'remoteNodeIncomingPort', self.remoteNodeIncomingPort
        useragentLength, lengthOfUseragentVarint = decodeVarint(data[80:84])
        readPosition = 80 + lengthOfUseragentVarint
        self.userAgent = data[readPosition:readPosition + useragentLength]

        # version check
        try:
            userAgentName, userAgentVersion = self.userAgent[1:-1].split(
                ":", 2)
        except:
            userAgentName = self.userAgent
            userAgentVersion = "0.0.0"
        if userAgentName == "PyBitmessage":
            myVersion = [int(n) for n in softwareVersion.split(".")]
            try:
                remoteVersion = [int(n) for n in userAgentVersion.split(".")]
            except:
                remoteVersion = 0
            # remote is newer, but do not cross between stable and unstable
            try:
                if cmp(remoteVersion, myVersion) > 0 and \
                    (myVersion[1] % 2 == remoteVersion[1] % 2):
                    queues.UISignalQueue.put(
                        ('newVersionAvailable', remoteVersion))
            except:
                pass

        readPosition += useragentLength
        numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(
            data[readPosition:])
        readPosition += lengthOfNumberOfStreamsInVersionMessage
        self.remoteStreams = []
        for i in range(numberOfStreamsInVersionMessage):
            newStreamNumber, lengthOfRemoteStreamNumber = decodeVarint(
                data[readPosition:])
            readPosition += lengthOfRemoteStreamNumber
            self.remoteStreams.append(newStreamNumber)
        logger.debug(
            'Remote node useragent: %s, streams: (%s), time offset: %is.',
            self.userAgent, ', '.join(str(x) for x in self.remoteStreams),
            self.timeOffset)

        # find shared streams
        self.streamNumber = sorted(
            set(state.streamsInWhichIAmParticipating).intersection(
                self.remoteStreams))

        shared.connectedHostsList[
            self.
            hostIdent] = 1  # We use this data structure to not only keep track of what hosts we are connected to so that we don't try to connect to them again, but also to list the connections count on the Network Status tab.
        self.sendDataThreadQueue.put(
            (0, 'setStreamNumber', self.remoteStreams))
        if data[72:
                80] == protocol.eightBytesOfRandomDataUsedToDetectConnectionsToSelf:
            self.sendDataThreadQueue.put((0, 'shutdown', 'no data'))
            logger.debug('Closing connection to myself: ' + str(self.peer))
            return

        # The other peer's protocol version is of interest to the sendDataThread but we learn of it
        # in this version message. Let us inform the sendDataThread.
        self.sendDataThreadQueue.put(
            (0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))

        if not isHostInPrivateIPRange(self.peer.host):
            with knownnodes.knownNodesLock:
                for stream in self.remoteStreams:
                    knownnodes.knownNodes[stream][state.Peer(
                        self.peer.host,
                        self.remoteNodeIncomingPort)] = int(time.time())
                    if not self.initiatedConnection:
                        # bootstrap provider?
                        if BMConfigParser().safeGetInt('bitmessagesettings', 'maxoutboundconnections') >= \
                            BMConfigParser().safeGetInt('bitmessagesettings', 'maxtotalconnections', 200):
                            knownnodes.knownNodes[stream][state.Peer(
                                self.peer.host, self.remoteNodeIncomingPort
                            )] -= 10800  # penalise inbound, 3 hours
                        else:
                            knownnodes.knownNodes[stream][state.Peer(
                                self.peer.host, self.remoteNodeIncomingPort
                            )] -= 7200  # penalise inbound, 2 hours
                    shared.needToWriteKnownNodesToDisk = True

        self.sendverack()
        if self.initiatedConnection == False:
            self.sendversion()
    def recversion(self, data):
        if len(data) < 83:
            # This version message is unreasonably short. Forget it.
            return
        if self.verackSent:
            """
            We must have already processed the remote node's version message.
            There might be a time in the future when we Do want to process
            a new version message, like if the remote node wants to update
            the streams in which they are interested. But for now we'll
            ignore this version message
            """ 
            return

        self.remoteProtocolVersion, = unpack('>L', data[:4])
        self.services, = unpack('>q', data[4:12])

        timestamp, = unpack('>Q', data[12:20])
        self.timeOffset = timestamp - int(time.time())

        self.myExternalIP = socket.inet_ntoa(data[40:44])
        # print 'myExternalIP', self.myExternalIP
        self.remoteNodeIncomingPort, = unpack('>H', data[70:72])
        # print 'remoteNodeIncomingPort', self.remoteNodeIncomingPort
        useragentLength, lengthOfUseragentVarint = decodeVarint(
            data[80:84])
        readPosition = 80 + lengthOfUseragentVarint
        self.userAgent = data[readPosition:readPosition + useragentLength]
        
        # version check
        try:
            userAgentName, userAgentVersion = self.userAgent[1:-1].split(":", 2)
        except:
            userAgentName = self.userAgent
            userAgentVersion = "0.0.0"
        if userAgentName == "PyBitmessage":
            myVersion = [int(n) for n in softwareVersion.split(".")]
            try:
                remoteVersion = [int(n) for n in userAgentVersion.split(".")]
            except:
                remoteVersion = 0
            # remote is newer, but do not cross between stable and unstable
            try:
                if cmp(remoteVersion, myVersion) > 0 and \
                    (myVersion[1] % 2 == remoteVersion[1] % 2):
                    queues.UISignalQueue.put(('newVersionAvailable', remoteVersion))
            except:
                pass
                
        readPosition += useragentLength
        numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(
            data[readPosition:])
        readPosition += lengthOfNumberOfStreamsInVersionMessage
        self.remoteStreams = []
        for i in range(numberOfStreamsInVersionMessage):
            newStreamNumber, lengthOfRemoteStreamNumber = decodeVarint(data[readPosition:])
            readPosition += lengthOfRemoteStreamNumber
            self.remoteStreams.append(newStreamNumber)
        logger.debug('Remote node useragent: %s, streams: (%s), time offset: %is.',
            self.userAgent, ', '.join(str(x) for x in self.remoteStreams), self.timeOffset)

        # find shared streams
        self.streamNumber = sorted(set(state.streamsInWhichIAmParticipating).intersection(self.remoteStreams))

        shared.connectedHostsList[
            self.hostIdent] = 1  # We use this data structure to not only keep track of what hosts we are connected to so that we don't try to connect to them again, but also to list the connections count on the Network Status tab.
        self.sendDataThreadQueue.put((0, 'setStreamNumber', self.remoteStreams))
        if data[72:80] == protocol.eightBytesOfRandomDataUsedToDetectConnectionsToSelf:
            self.sendDataThreadQueue.put((0, 'shutdown','no data'))
            logger.debug('Closing connection to myself: ' + str(self.peer))
            return
        
        # The other peer's protocol version is of interest to the sendDataThread but we learn of it
        # in this version message. Let us inform the sendDataThread.
        self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))

        if not isHostInPrivateIPRange(self.peer.host):
            with knownnodes.knownNodesLock:
                for stream in self.remoteStreams:
                    knownnodes.knownNodes[stream][state.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
                    if not self.initiatedConnection:
                        # bootstrap provider?
                        if BMConfigParser().safeGetInt('bitmessagesettings', 'maxoutboundconnections') >= \
                            BMConfigParser().safeGetInt('bitmessagesettings', 'maxtotalconnections', 200):
                            knownnodes.knownNodes[stream][state.Peer(self.peer.host, self.remoteNodeIncomingPort)] -= 10800 # penalise inbound, 3 hours
                        else:
                            knownnodes.knownNodes[stream][state.Peer(self.peer.host, self.remoteNodeIncomingPort)] -= 7200 # penalise inbound, 2 hours
                    shared.needToWriteKnownNodesToDisk = True

        self.sendverack()
        if self.initiatedConnection == False:
            self.sendversion()