/
gateway.py
158 lines (137 loc) · 5.48 KB
/
gateway.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
''' PBJ
Camden Clements
Adam Hodges
Zach Welch
gateway.py contains code for the PBJ gateway, which controls how nodes are
added to the network
'''
# activate virtualenv
import os
activate_this = os.path.expanduser("env/bin/activate_this.py")
execfile(activate_this, dict(__file__=activate_this))
import pickle
import sys
import math
import threading
import time
import argparse
from flask import Flask
from flask import request
from httpcli import send_ping, send_tellsearch
app = Flask(__name__)
PEERS_PER_UPEER = 0
class Node:
'''gateway representation of a network node'''
def __init__(self, address, port, ultraId):
'''constructor
name - IP address of node
port - port of node
ultraId - ultra peer ID number (-1 if not an ultra peer)
'''
self.name = address+":"+port
if ultraId == -1:
self.isUltra = False
self.upeer = None
else:
self.isUltra = True
self.upeerid = ultraId
self.peers = {}
self.upeers = {}
class Network:
'''gateway representation of entire network'''
def __init__(self):
'''constructor, sets up empty network'''
self.upeerCount = -1
self.upeers = {}
self.outOfOrder = 0
def findUPeer(self):
'''returns the ultra peer with an empty sub network slot or None if all ultra peers are full'''
for peer in self.upeers.values():
if(len(peer.peers.keys()) < self.ppup):
if self.outOfOrder == 0:
return peer
def linkUPeer(self, up):
'''links a ultra peer to all other ultra peers it should be linked with'''
for ids,curup in self.upeers.items():
if(up.upeerid - curup.upeerid != 0):
if(math.log(math.fabs((up.upeerid - curup.upeerid)), 2) % 2 == 0):
print "Linking ultrapeers %d and %d." % (curup.upeerid, up.upeerid)
up.upeers[curup.name] = curup
curup.upeers[up.name] = up
def addPeer(self, name, port):
'''process for adding a peer to the network. Checks network for lost nodes
before adding new ones
name - ip address of new node to be added
port - port of new node to be added
'''
result = {}
# ping ultrapeers to verify network
for id,up in self.upeers.items():
if send_ping(up.name) == False:
print "Lost Ultrapeer ", id
del self.upeers[id]
self.outOfOrder += 1
self.upeerCount -= 1
upeer = self.findUPeer()
if upeer is None:
# new peer is ultra peer
result['isUltra'] = True
self.upeerCount += 1
if(self.upeerCount>1):
print "Telling " + self.upeers[0].name + " to search"
send_tellsearch("", self.upeers[0].name)
# adjust ultrapeers
if self.outOfOrder != 0:
self.outOfOrder -= 1
for i in range(self.upeerCount):
if self.upeers.has_key(i) == False:
newNode = Node(name, port, i)
self.upeers[i]= newNode
self.linkUPeer(newNode)
result['uPeers'] = newNode.upeers.keys()
result['upId'] = newNode.upeerid
print "Node %s added to network as Ultrapeer %d." % (name, newNode.upeerid)
return result
# put new upeer at end of upeers
newNode = Node(name, port, self.upeerCount)
self.upeers[self.upeerCount]= newNode
self.linkUPeer(newNode)
result['uPeers'] = newNode.upeers.keys()
result['upId'] = newNode.upeerid
print "Node %s added to network as Ultrapeer %d." % (name, newNode.upeerid)
return result
else:
# new peer is not an ultra peer
newNode = Node(name, port, -1)
newNode.upeer = upeer
upeer.peers[name] = newNode
result['isUltra'] = False
result['uPeer'] = upeer.name
print "Node %s added to network under Ultrapeer %s" % (name, upeer.upeerid)
return result
def UPeerRemovePeer(self, upeer, peer):
'''method for removing peer from a upeers sub network'''
for ids,up in self.upeers.items():
if(up.name==upeer):
del up.peers[peer]
#set upeer's count to count
pbj = Network()
@app.route("/register", methods=['GET'])
def register():
'''flask method that new nodes use to register with the network'''
data=pbj.addPeer(request.remote_addr, request.args.get('port'))
return pickle.dumps(data)
@app.route("/upeer_remove_peer", methods=['POST'])
def updatePeerCount():
'''flask method that ultranodes use to tell gateway they have lost a node'''
peer=request.form['peer']
port=request.form['peerport']
upeer=request.remote_addr
pbj.UPeerRemovePeer(upeer, peer, port)
return "OK"
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Run the gateway server')
parser.add_argument('-l', action="store", dest="ppup", default=PEERS_PER_UPEER, help='Set number of peers per ultra peer', type=int)
arg_results = parser.parse_args()
pbj.ppup = arg_results.ppup
app.run(host='0.0.0.0', debug=True)