-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrouter.py
94 lines (70 loc) · 2.7 KB
/
router.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
import time
import sys
import _thread
import queue
class Router:
"""Router superclass that handles the details of
packet send/receive and link changes.
Subclass this class and override the "handle..." methods
to implement routing algorithm functionality"""
def __init__(self, addr, heartbeatTime=None):
"""Initialize Router address and threadsafe queue for link changes"""
self.addr = addr # address of router
self.links = {} # links indexed by port
self.linkChanges = queue.Queue()
self.keepRunning = True
def changeLink(self, change):
"""Add, remove, or change the cost of a link.
The change argument is a tuple with first element
'add', or 'remove' """
self.linkChanges.put(change)
def addLink(self, port, endpointAddr, link, cost):
"""Add new link to router"""
if port in self.links:
self.removeLink(port)
self.links[port] = link
self.handleNewLink(port, endpointAddr, cost)
def removeLink(self, port):
"""Remove link from router"""
self.links = {p:link for p,link in self.links.items() if p != port}
self.handleRemoveLink(port)
def runRouter(self):
"""Main loop of router"""
while self.keepRunning:
time.sleep(0.1)
timeMillisecs = int(round(time.time() * 1000))
try:
change = self.linkChanges.get_nowait()
if change[0] == "add":
self.addLink(*change[1:])
elif change[0] == "remove":
self.removeLink(*change[1:])
except queue.Empty:
pass
for port in list(self.links.keys()):
packet = self.links[port].recv(self.addr)
if packet:
self.handlePacket(port, packet)
self.handleTime(timeMillisecs)
def send(self, port, packet):
"""Send a packet out given port"""
try:
self.links[port].send(packet, self.addr)
except KeyError:
pass
def handlePacket(self, port, packet):
"""process incoming packet"""
# default implementation sends packet back out the port it arrived
self.send(port, packet)
def handleNewLink(self, port, endpoint, cost):
"""handle new link"""
pass
def handleRemoveLink(self, port):
"""handle removed link"""
pass
def handleTime(self, timeMillisecs):
"""handle current time"""
pass
def debugString(self):
"""generate a string for debugging in network visualizer"""
return "Mirror router: address {}".format(self.addr)