Skip to content

Commit 2a2c723

Browse files
committed
event loop, node address management
1 parent 8cab929 commit 2a2c723

File tree

3 files changed

+85
-30
lines changed

3 files changed

+85
-30
lines changed

bitcoin.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,25 @@ def initialize_configuration():
6666
if options.nodes:
6767
options.irc = ""
6868
options.dns = ""
69-
options.add_nodes = []
69+
options.add_nodes = ""
70+
71+
nodes = []
72+
for node in options.nodes.split(","):
73+
if not node:
74+
continue
75+
ip, port = node.split(":")
76+
nodes.append((ip, int(port)))
77+
78+
for node in options.add_nodes.split(","):
79+
if not node:
80+
continue
81+
ip, port = node.split(":")
82+
nodes.append((ip, int(port)))
83+
84+
irc = None
85+
if options.irc:
86+
irc_ip, irc_port = options.irc.split(":")
87+
irc = (irc_ip, int(irc_port))
7088

7189
config = {
7290
"boot" : time.time(),
@@ -80,15 +98,13 @@ def initialize_configuration():
8098
"local_port" : options.port,
8199
"external_ip" : options.external_ip,
82100
"irc_timeout" : options.irc_timeout,
83-
"dns_seed" : options.dns.split(","),
101+
"dns_seed" : options.dns.split(",") if options.dns else [],
84102
"genesis_hash" : genesis_hash,
85103
"event_loop_sleep" : 0.01,
86104
"event_loop_timeout" : 10,
87-
"nodes" : options.nodes + options.add_nodes,
105+
"nodes" : nodes,
106+
"irc" : irc,
88107
}
89-
if options.irc:
90-
irc_ip, irc_port = options.irc.split(":")
91-
config["irc"] = (irc_ip, int(irc_port))
92108

93109
return config
94110

context.py

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ def __init__(self, config):
2424
self.nodes = set()
2525

2626
def get_dns_nodes(self):
27-
for host in hosts:
27+
for host in self.config["dns_seed"]:
28+
if not host:
29+
continue
2830
ips = socket.gethostbyname_ex(host)[2]
2931
for ip in ips:
3032
yield ip
@@ -38,34 +40,60 @@ def get_external_ip_using_http(self):
3840

3941
def seed_dns_nodes(self):
4042
for ip in self.get_dns_nodes():
43+
if not ip:
44+
continue
4145
self.add_node_address((ip, config["default_port"]))
4246

4347
def event_loop(self):
44-
seeder = None
45-
state = 1
46-
if self.config.get("irc", None) is not None:
47-
seeder = irc.BIRCSeeder(self)
48-
state = 0
49-
48+
bootstrap = True
49+
birc = None
50+
uptime_wait = 1
51+
if self.config.get("irc", None):
52+
birc = irc.BIRCSeeder(self)
53+
uptime_wait = 10
54+
55+
nodes = []
56+
if self.config["nodes"]:
57+
for node in self.config["nodes"]:
58+
self.add_node_address(node)
59+
60+
uptime = self.get_uptime()
61+
delta = 0
5062
while True:
5163
asyncore.loop(timeout=self.config["event_loop_timeout"],count=1)
5264
time.sleep(self.config["event_loop_sleep"])
53-
if state == 0:
54-
if seeder:
55-
if self.config.get("external_ip", None) and len(self.addresses[1]) > 0:
56-
state = 2
57-
elif self.get_uptime() > self.config["irc_timeout"]:
58-
logging.error("IRC failed to get external IP or nodes within %s seconds", self.get_uptime())
59-
state = 1
60-
elif state == 1:
61-
self.set_external_ip(self.get_external_ip_using_http())
62-
self.seed_dns_nodes()
63-
state = 2
64-
elif state == 2:
65+
delta += self.get_uptime() - uptime
66+
uptime = self.get_uptime()
67+
if bootstrap and uptime > uptime_wait and delta > 1:
68+
delta = 0
69+
eip = self.config.get("external_ip", None)
70+
naddr = len(self.addresses[1])
71+
if eip and naddr > 0:
72+
bootstrap = False
73+
continue
74+
if birc and uptime > self.config["irc_timeout"]:
75+
logging.error("IRC failed to get external IP or nodes within %s seconds, falling back", uptime)
76+
birc.close()
77+
birc = None
78+
if not birc:
79+
if self.config.get("dns_seed"):
80+
logging.debug("seeding using dns")
81+
self.seed_dns_nodes()
82+
if not eip:
83+
ip = self.get_external_ip_using_http()
84+
self.set_external_ip(ip)
85+
bootstrap = False
86+
elif not bootstrap and delta > 1:
6587
if len(self.nodes) < self.config["maxconnections"]:
66-
self.create_node_connection()
88+
if len(self.addresses[0]) > 0:
89+
self.create_node_connection()
90+
elif len(self.addresses[1]) == 0:
91+
logging.error("No addresses available")
92+
time.sleep(5)
6793

6894
def create_node_connection(self):
95+
if len(self.addresses[0]) == 0:
96+
return
6997
addr = self.addresses[0].pop()
7098
node = net.BConnection(addr, self)
7199
self.nodes.add(node)
@@ -76,8 +104,12 @@ def add_node_address(self, addr):
76104
self.addresses[1].add(addr)
77105

78106
def set_external_ip(self, ip):
107+
logging.debug("got external ip %s", ip)
79108
self.config["external_ip"] = ip
80109

110+
def get_external_address(self):
111+
return self.config["external_ip"]
112+
81113
def get_last_block(self):
82114
return len(self.blocks)
83115

net.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ def reset_incoming_data(self):
4444
def handle_connect(self):
4545
logging.debug("connected to node %s", self.addr)
4646

47+
def handle_expt(self):
48+
if not self.connected:
49+
logging.debug("connection refused to %s", self.addr)
50+
else:
51+
logging.exception()
52+
self.close()
53+
4754
def found_terminator(self):
4855
logging.debug("received packet %s", len(self.incoming_data))
4956
if callable(self.incoming_handler):
@@ -56,7 +63,7 @@ def found_terminator(self):
5663
self.close()
5764
return
5865
network, command, paylen = self.unpack_incoming_header()
59-
if network != self.content.config["network"]:
66+
if network != self.context.config["network"]:
6067
logging.error("received garbage from %s", connection.addr)
6168
self.close()
6269
return
@@ -91,7 +98,7 @@ def push_version(self):
9198
self.addr[0], self.addr[1])
9299
local = self.context.parser.pack_address(
93100
self.context.config["services"],
94-
self.context.config["external_ip"],
101+
self.context.get_external_address(),
95102
self.context.config["local_port"])
96103
data = struct.pack("<iQQ26s26sQxL",
97104
self.context.config["version"],
@@ -107,9 +114,9 @@ def pop_version(self):
107114
if self.remote:
108115
return
109116
self.incoming_handler = None
110-
(pack,), data = self.context.parser.unpack("<iQQ26s26sQxL", self.incoming_data)
117+
result, data = self.context.parser.unpack("<iQQ26s26sQxL", self.incoming_data)
111118
self.incoming_data = data
112-
version, services, timestamp, remote, local, nonce, last = pack
119+
version, services, timestamp, remote, local, nonce, last = result
113120
logging.debug("pop_version %s %s %s %s %s", version, services, timestamp, nonce, last)
114121
if nonce == self.context.config["nonce"] and nonce > 1:
115122
logging.error("Connected to self, disconnecting")

0 commit comments

Comments
 (0)