diff --git a/src/api.py b/src/api.py index ded65b3fc..398e82ceb 100644 --- a/src/api.py +++ b/src/api.py @@ -1551,8 +1551,8 @@ def HandleListConnections(self): Returns bitmessage connection information as dict with keys *inbound*, *outbound*. """ - if connectionpool is None: - raise APIError(21, 'Could not import BMConnectionPool.') + if connectionpool is None or connectionpool.pool is None: + raise APIError(21, 'Network is not started.') inboundConnections = [] outboundConnections = [] for i in connectionpool.pool.inboundConnections.values(): diff --git a/src/network/__init__.py b/src/network/__init__.py index c87ad64d6..f7ba31f32 100644 --- a/src/network/__init__.py +++ b/src/network/__init__.py @@ -20,7 +20,8 @@ def start(config, state): """Start network threads""" from .announcethread import AnnounceThread - import connectionpool # pylint: disable=relative-import + from . import connectionpool + from .connectionpool import BMConnectionPool from .addrthread import AddrThread from .downloadthread import DownloadThread from .invthread import InvThread @@ -29,6 +30,9 @@ def start(config, state): from .receivequeuethread import ReceiveQueueThread from .uploadthread import UploadThread + # create the connection pool + connectionpool.pool = BMConnectionPool() + # check and set dandelion enabled value at network startup dandelion_ins.init_dandelion_enabled(config) # pass pool instance into dandelion class instance diff --git a/src/network/addrthread.py b/src/network/addrthread.py index 81e445060..e85bb2a12 100644 --- a/src/network/addrthread.py +++ b/src/network/addrthread.py @@ -4,12 +4,11 @@ import random from six.moves import queue -# magic imports! -import connectionpool +from . import connectionpool from protocol import assembleAddrMessage from network import addrQueue # FIXME: init with queue -from threads import StoppableThread +from .threads import StoppableThread class AddrThread(StoppableThread): diff --git a/src/network/advanceddispatcher.py b/src/network/advanceddispatcher.py index 49f0d19d7..33c0c12ed 100644 --- a/src/network/advanceddispatcher.py +++ b/src/network/advanceddispatcher.py @@ -7,7 +7,7 @@ import network.asyncore_pollchoose as asyncore import state -from threads import BusyError, nonBlocking +from .threads import BusyError, nonBlocking class ProcessingError(Exception): diff --git a/src/network/announcethread.py b/src/network/announcethread.py index 7cb35e779..3d27bcb3f 100644 --- a/src/network/announcethread.py +++ b/src/network/announcethread.py @@ -3,13 +3,12 @@ """ import time -# magic imports! -import connectionpool +from . import connectionpool from bmconfigparser import config from protocol import assembleAddrMessage -from node import Peer -from threads import StoppableThread +from .node import Peer +from .threads import StoppableThread class AnnounceThread(StoppableThread): diff --git a/src/network/bmobject.py b/src/network/bmobject.py index 1a54fc7b7..61b930461 100644 --- a/src/network/bmobject.py +++ b/src/network/bmobject.py @@ -6,7 +6,7 @@ import protocol import state -import connectionpool +from . import connectionpool from network import dandelion_ins from highlevelcrypto import calculateInventoryHash diff --git a/src/network/bmproto.py b/src/network/bmproto.py index fbb5a06e4..e49ccc20b 100644 --- a/src/network/bmproto.py +++ b/src/network/bmproto.py @@ -12,10 +12,10 @@ # magic imports! import addresses -import knownnodes import protocol import state -import connectionpool +from . import connectionpool +from . import knownnodes from bmconfigparser import config from queues import objectProcessorQueue from randomtrackingdict import RandomTrackingDict @@ -27,8 +27,8 @@ ) from network.proxy import ProxyError from network import dandelion_ins, invQueue, portCheckerQueue -from node import Node, Peer -from objectracker import ObjectTracker, missingObjects +from .node import Node, Peer +from .objectracker import ObjectTracker, missingObjects logger = logging.getLogger('default') diff --git a/src/network/connectionchooser.py b/src/network/connectionchooser.py index e2981d51c..217a883da 100644 --- a/src/network/connectionchooser.py +++ b/src/network/connectionchooser.py @@ -7,7 +7,7 @@ from six.moves import queue -import knownnodes +from . import knownnodes import protocol import state diff --git a/src/network/connectionpool.py b/src/network/connectionpool.py index 93e54af8e..5bcd94ad7 100644 --- a/src/network/connectionpool.py +++ b/src/network/connectionpool.py @@ -9,18 +9,14 @@ import time import random -import asyncore_pollchoose as asyncore -import knownnodes +from . import asyncore_pollchoose as asyncore +from . import knownnodes import protocol import state from bmconfigparser import config -from connectionchooser import chooseConnection -from node import Peer -from proxy import Proxy -from tcp import ( - bootstrap, Socks4aBMConnection, Socks5BMConnection, - TCPConnection, TCPServer) -from udp import UDPSocket +from .connectionchooser import chooseConnection +from .node import Peer +from .proxy import Proxy logger = logging.getLogger('default') @@ -123,6 +119,7 @@ def isAlreadyConnected(self, nodeid): def addConnection(self, connection): """Add a connection object to our internal dict""" + from .udp import UDPSocket if isinstance(connection, UDPSocket): return if connection.isOutbound: @@ -136,6 +133,8 @@ def addConnection(self, connection): def removeConnection(self, connection): """Remove a connection from our internal dict""" + from .tcp import TCPServer + from .udp import UDPSocket if isinstance(connection, UDPSocket): del self.udpSockets[connection.listening.host] elif isinstance(connection, TCPServer): @@ -177,6 +176,7 @@ def getListeningIP(): def startListening(self, bind=None): """Open a listening socket and start accepting connections on it""" + from .tcp import TCPServer if bind is None: bind = self.getListeningIP() port = config.safeGetInt("bitmessagesettings", "port") @@ -189,6 +189,7 @@ def startUDPSocket(self, bind=None): Open an UDP socket. Depending on settings, it can either only accept incoming UDP packets, or also be able to send them. """ + from .udp import UDPSocket if bind is None: host = self.getListeningIP() udpSocket = UDPSocket(host=host, announcing=True) @@ -201,6 +202,9 @@ def startUDPSocket(self, bind=None): def startBootstrappers(self): """Run the process of resolving bootstrap hostnames""" + from .tcp import ( + bootstrap, Socks4aBMConnection, Socks5BMConnection, + TCPConnection) proxy_type = config.safeGet( 'bitmessagesettings', 'socksproxytype') # A plugins may be added here @@ -252,6 +256,9 @@ def loop(self): # pylint: disable=too-many-branches,too-many-statements ): acceptConnections = False + from .tcp import ( + Socks4aBMConnection, Socks5BMConnection, TCPConnection) + # pylint: disable=too-many-nested-blocks if spawnConnections: if not knownnodes.knownNodesActual: @@ -401,4 +408,4 @@ def loop(self): # pylint: disable=too-many-branches,too-many-statements self.removeConnection(i) -pool = BMConnectionPool() +pool = None diff --git a/src/network/downloadthread.py b/src/network/downloadthread.py index 7c8bccb69..f8ca4e53c 100644 --- a/src/network/downloadthread.py +++ b/src/network/downloadthread.py @@ -6,10 +6,10 @@ import state import addresses import protocol -import connectionpool +from . import connectionpool from network import dandelion_ins -from objectracker import missingObjects -from threads import StoppableThread +from .objectracker import missingObjects +from .threads import StoppableThread class DownloadThread(StoppableThread): diff --git a/src/network/http.py b/src/network/http.py index d7a938fab..8a49e760c 100644 --- a/src/network/http.py +++ b/src/network/http.py @@ -1,10 +1,10 @@ import socket -from advanceddispatcher import AdvancedDispatcher -import asyncore_pollchoose as asyncore -from proxy import ProxyError -from socks5 import Socks5Connection, Socks5Resolver -from socks4a import Socks4aConnection, Socks4aResolver +from .advanceddispatcher import AdvancedDispatcher +from . import asyncore_pollchoose as asyncore +from .proxy import ProxyError +from .socks5 import Socks5Connection, Socks5Resolver +from .socks4a import Socks4aConnection, Socks4aResolver class HttpError(ProxyError): diff --git a/src/network/httpd.py b/src/network/httpd.py index b69ffa990..654566c28 100644 --- a/src/network/httpd.py +++ b/src/network/httpd.py @@ -5,7 +5,7 @@ import asyncore import socket -from tls import TLSHandshake +from .tls import TLSHandshake class HTTPRequestHandler(asyncore.dispatcher): diff --git a/src/network/https.py b/src/network/https.py index a7b8b57ce..93068bf67 100644 --- a/src/network/https.py +++ b/src/network/https.py @@ -1,7 +1,7 @@ import asyncore -from http import HTTPClient -from tls import TLSHandshake +from .http import HTTPClient +from .tls import TLSHandshake """ self.sslSock = ssl.wrap_socket( diff --git a/src/network/invthread.py b/src/network/invthread.py index 503eefa16..14508422d 100644 --- a/src/network/invthread.py +++ b/src/network/invthread.py @@ -1,16 +1,17 @@ """ Thread to send inv annoucements """ -import Queue import random from time import time +from six.moves import queue + import addresses import protocol import state -import connectionpool +from . import connectionpool from network import dandelion_ins, invQueue -from threads import StoppableThread +from .threads import StoppableThread def handleExpiredDandelion(expired): @@ -58,7 +59,7 @@ def run(self): # pylint: disable=too-many-branches # locally generated if len(data) == 2 or data[2] is None: self.handleLocallyGenerated(data[0], data[1]) - except Queue.Empty: + except queue.Empty: break if chunk: diff --git a/src/network/networkthread.py b/src/network/networkthread.py index 640d47a1f..510cd7fa6 100644 --- a/src/network/networkthread.py +++ b/src/network/networkthread.py @@ -2,9 +2,9 @@ A thread to handle network concerns """ import network.asyncore_pollchoose as asyncore -import connectionpool +from . import connectionpool from queues import excQueue -from threads import StoppableThread +from .threads import StoppableThread class BMNetworkThread(StoppableThread): diff --git a/src/network/objectracker.py b/src/network/objectracker.py index 91bb0552a..d40ebd309 100644 --- a/src/network/objectracker.py +++ b/src/network/objectracker.py @@ -4,7 +4,7 @@ import time from threading import RLock -import connectionpool +from . import connectionpool from network import dandelion_ins from randomtrackingdict import RandomTrackingDict diff --git a/src/network/proxy.py b/src/network/proxy.py index ed1af127b..92734ee1e 100644 --- a/src/network/proxy.py +++ b/src/network/proxy.py @@ -6,10 +6,10 @@ import socket import time -import asyncore_pollchoose as asyncore -from advanceddispatcher import AdvancedDispatcher +from . import asyncore_pollchoose as asyncore +from .advanceddispatcher import AdvancedDispatcher from bmconfigparser import config -from node import Peer +from .node import Peer logger = logging.getLogger('default') diff --git a/src/network/receivequeuethread.py b/src/network/receivequeuethread.py index 88d3b740c..bd642d9fb 100644 --- a/src/network/receivequeuethread.py +++ b/src/network/receivequeuethread.py @@ -2,13 +2,14 @@ Process data incoming from network """ import errno -import Queue import socket -import connectionpool +from six.moves import queue + +from . import connectionpool from network.advanceddispatcher import UnknownStateError from network import receiveDataQueue -from threads import StoppableThread +from .threads import StoppableThread class ReceiveQueueThread(StoppableThread): @@ -21,7 +22,7 @@ def run(self): while not self._stopped: try: dest = receiveDataQueue.get(block=True, timeout=1) - except Queue.Empty: + except queue.Empty: continue if self._stopped: diff --git a/src/network/socks4a.py b/src/network/socks4a.py index e97861684..2758838a2 100644 --- a/src/network/socks4a.py +++ b/src/network/socks4a.py @@ -6,7 +6,7 @@ import socket import struct -from proxy import GeneralProxyError, Proxy, ProxyError +from .proxy import GeneralProxyError, Proxy, ProxyError logger = logging.getLogger('default') diff --git a/src/network/socks5.py b/src/network/socks5.py index d1daae422..1838a737f 100644 --- a/src/network/socks5.py +++ b/src/network/socks5.py @@ -7,8 +7,8 @@ import socket import struct -from node import Peer -from proxy import GeneralProxyError, Proxy, ProxyError +from .node import Peer +from .proxy import GeneralProxyError, Proxy, ProxyError logger = logging.getLogger('default') diff --git a/src/network/stats.py b/src/network/stats.py index 0ab1ae0fd..398644a3b 100644 --- a/src/network/stats.py +++ b/src/network/stats.py @@ -3,9 +3,9 @@ """ import time -import asyncore_pollchoose as asyncore -import connectionpool -from objectracker import missingObjects +from . import asyncore_pollchoose as asyncore +from . import connectionpool +from .objectracker import missingObjects lastReceivedTimestamp = time.time() @@ -18,6 +18,8 @@ def connectedHostsList(): """List of all the connected hosts""" + if connectionpool.pool is None: + return [] return connectionpool.pool.establishedConnections() diff --git a/src/network/tcp.py b/src/network/tcp.py index e8df5b728..db9c91126 100644 --- a/src/network/tcp.py +++ b/src/network/tcp.py @@ -14,22 +14,22 @@ import l10n import protocol import state -import connectionpool +from . import connectionpool from bmconfigparser import config from highlevelcrypto import randomBytes from network import dandelion_ins, invQueue, receiveDataQueue from queues import UISignalQueue from tr import _translate -import asyncore_pollchoose as asyncore -import knownnodes +from . import asyncore_pollchoose as asyncore +from . import knownnodes from network.advanceddispatcher import AdvancedDispatcher from network.bmproto import BMProto from network.objectracker import ObjectTracker from network.socks4a import Socks4aConnection from network.socks5 import Socks5Connection from network.tls import TLSDispatcher -from node import Peer +from .node import Peer logger = logging.getLogger('default') diff --git a/src/network/udp.py b/src/network/udp.py index 30643d40c..4a5df79b6 100644 --- a/src/network/udp.py +++ b/src/network/udp.py @@ -8,12 +8,12 @@ # magic imports! import protocol import state -import connectionpool +from . import connectionpool from network import receiveDataQueue -from bmproto import BMProto -from node import Peer -from objectracker import ObjectTracker +from .bmproto import BMProto +from .node import Peer +from .objectracker import ObjectTracker logger = logging.getLogger('default') diff --git a/src/network/uploadthread.py b/src/network/uploadthread.py index 602098328..6d23dcec8 100644 --- a/src/network/uploadthread.py +++ b/src/network/uploadthread.py @@ -6,10 +6,10 @@ import random import protocol import state -import connectionpool +from . import connectionpool from randomtrackingdict import RandomTrackingDict from network import dandelion_ins -from threads import StoppableThread +from .threads import StoppableThread class UploadThread(StoppableThread): diff --git a/src/tests/test_network.py b/src/tests/test_network.py index 206117e03..0c9b2ee2d 100644 --- a/src/tests/test_network.py +++ b/src/tests/test_network.py @@ -27,11 +27,13 @@ def setUpClass(cls): # beware of singleton connectionpool.config = cls.config - cls.pool = connectionpool.pool cls.stats = stats network.start(cls.config, cls.state) + # pool is created inside network.start(), read it after + cls.pool = connectionpool.pool + def test_threads(self): """Ensure all the network threads started""" threads = {