-
Notifications
You must be signed in to change notification settings - Fork 3
/
tracker.py
118 lines (100 loc) · 3.92 KB
/
tracker.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
import json
import pprint
import threading
from collections import defaultdict
from crypto.cryptography_unit import crypto_unit
from datagram import UDPDatagram
from messages import modes
from messages.message import Message
from messages.tracker_to_node import TrackerToNode
from utils import *
class Tracker:
def __init__(self):
self.tracker_s = create_socket(TRACKER_ADDR[1])
self.uploader_list = defaultdict(list)
self.upload_freq_list = defaultdict(int)
def send_datagram(self, message: bytes, addr: Tuple[str, int]):
dg = UDPDatagram(port_number(self.tracker_s), addr[1], message)
enc = crypto_unit.encrypt(dg)
self.tracker_s.sendto(enc, addr)
def handle_node(self, data, addr):
dg = crypto_unit.decrypt(data)
message = Message.decode(dg.data)
message_mode = message['mode']
if message_mode == modes.HAVE:
self.add_uploader(message, addr)
elif message_mode == modes.NEED:
self.search_file(message, addr)
elif message_mode == modes.EXIT:
self.exit_uploader(message, addr)
def listen(self):
while True:
data, addr = self.tracker_s.recvfrom(BUFFER_SIZE)
t = threading.Thread(target=self.handle_node, args=(data, addr))
t.start()
def start(self):
t = threading.Thread(target=self.listen())
t.daemon = True
t.start()
t.join()
def add_uploader(self, message, addr):
node_name = message['name']
filename = message['filename']
item = {
'name': node_name,
'ip': addr[0],
'port': addr[1]
}
self.upload_freq_list[node_name] = self.upload_freq_list[node_name] + 1
self.uploader_list[filename].append(json.dumps(item))
self.uploader_list[filename] = list(set(self.uploader_list[filename]))
self.print_db()
def search_file(self, message, addr):
node_name = message['name']
filename = message['filename']
self.print_search_log(node_name, filename)
search_result = []
for item_json in self.uploader_list[filename]:
item = json.loads(item_json)
upload_freq = self.upload_freq_list[item['name']]
search_result.append(
(item['name'], (item['ip'], item['port']), upload_freq))
response = TrackerToNode(node_name, search_result, filename).encode()
self.send_datagram(response, addr)
def exit_uploader(self, message, addr):
node_name = message['name']
item = {
'name': node_name,
'ip': addr[0],
'port': addr[1]
}
item_json = json.dumps(item)
self.upload_freq_list[node_name] = 0
files = self.uploader_list.copy()
for file in files:
if item_json in self.uploader_list[file]:
self.uploader_list[file].remove(item_json)
if len(self.uploader_list[file]) == 0:
self.uploader_list.pop(file)
print(f"Node {message['name']} exited the network.")
self.print_db()
def print_db(self):
print(
'\n************************* Current Database *************************')
print('* Upload frequency list:')
pprint.pprint(self.upload_freq_list, width=1)
print("\n* Files' uploader list:")
pprint.pprint(self.uploader_list)
print(
'********************************************************************')
def print_search_log(self, node_name, filename):
print(
'\n************************* Search Log *************************')
print(f'{node_name} is searching for {filename}...')
print(
'****************************************************************')
def main():
t = Tracker()
t.start()
if __name__ == '__main__':
main()