-
Notifications
You must be signed in to change notification settings - Fork 1
/
bootstrap.py
141 lines (111 loc) · 4 KB
/
bootstrap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
"""
Bootstrapping process is as follows
1. Listen on multicast address
2. Multicast your IP address, listen for responses (IP addresses of other nodes)
3. Store responses
**4. If no responses, contact main server for list of nodes
**5. Receive list of nodes from main server
**6. If no other nodes, try again later
** Currently Disabled
"""
import json
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.application.internet import MulticastServer
import time, datetime, signal, socket
from urllib2 import urlopen
#from threading import Thread
import threading
signal.signal(signal.SIGINT,signal.SIG_DFL)
##########
# SERVER #
##########
class MulticastServerUDP(DatagramProtocol):
def __init__(self, pkey):
self.pkey = pkey
def startProtocol(self):
print 'Multicast Server Started Listening....'
# Join a specific multicast group, which is the IP we will respond to
self.transport.joinGroup('224.0.1.123')
def datagramReceived(self, datagram, address):
ip, pkey = datagram.split(None, 1)
if ip != Bootstrapper.myip:
Bootstrapper.hosts[ip] = pkey
print "Bootstrap Server Hosts:....", Bootstrapper.hosts
print "Heard Multicast Datagram:", repr(ip)
self.transport.write("%s %s" % (Bootstrapper.myip, self.pkey), address)
class MulticastServerThread(threading.Thread):
def __init__(self, pkey):
threading.Thread.__init__(self)
self.pkey = pkey
def run(self):
reactor.listenMulticast(8005, MulticastServerUDP(self.pkey))
#reactor.run(installSignalHandlers=0)
##########
# CLIENT #
##########
class MulticastClientUDP(DatagramProtocol):
def datagramReceived(self, datagram, address):
ip, pkey = datagram.split()
if ip != Bootstrapper.myip:
Bootstrapper.hosts[ip] = pkey
class MulticastClientThread(threading.Thread):
def __init__(self, pkey):
threading.Thread.__init__(self)
self.pkey = pkey
def run(self):
print "sending multicast hello"
# Send multicast on 224.0.1.123:8005, on our dynamically allocated port
reactor.listenUDP(0, MulticastClientUDP()).write("%s %s" % (Bootstrapper.myip, self.pkey), ('224.0.1.123', 8005))
##########
# BACKUP #
##########
HOST = '172.23.124.59'
PORT = 8007
class BackupClientThread(threading.Thread):
def __init__(self, pkey):
threading.Thread.__init__(self)
self.pkey = pkey
def run(self):
print "No clients located, attempting to contact backup server...."
while True:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#try:
s.connect((HOST, PORT))
s.send("GIMMEHOSTS %s" % self.pkey)
data = ''
while True:
x = s.recv(2048)
if x[-1] == '}':
data += x
break
data += x
data = json.loads(data)
for datum in data:
if datum != Bootstrapper.myip:
Bootstrapper.hosts[datum] = data[datum]
#except Exception as e:
# print "Home server is not available at this time: ", e, HOST, PORT
# break
#print "Hosts received from backup server:", Bootstrapper.hosts
time.sleep(2)
######################
### INITIALIZATION ###
######################
class Bootstrapper:
hosts = {}
#myip = urlopen('http://whatismyip.org/').read()
myip = socket.gethostbyname(socket.gethostname())
def __init__(self, pkey):
self.pkey = pkey
print "BOOTSTRAP IP", Bootstrapper.myip
def bootstrap(self):
MulticastServerThread(self.pkey).start()
MulticastClientThread(self.pkey).start()
#Give multicast a chance to find some friends
time.sleep(5)
if len(self.hosts)==0:
BackupClientThread(self.pkey).start()
if __name__ == "__main__":
b = Bootstrapper(1337)
b.bootstrap()