-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
150 lines (131 loc) · 4.84 KB
/
server.py
File metadata and controls
150 lines (131 loc) · 4.84 KB
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
import errno
import getopt
import sys
from time import sleep
import message
import utils
from message import Message, HostType, MessageType
from logger import prepare_logger
import files
import key_gen
import tracker
from utils import *
import tqdm
import os
default_port = 31235
class Server:
def __init__(self, ip, key, trackers, directories):
self.s = None
self.ip = ip
self.socket_range = 50
self.port = default_port
self.key = key
self.open_connections = 100
self.request_time = 20
self.clients = []
self.connected_clients = []
self.directories = directories
self.trackers = tracker.prepare_trackers(trackers)
def start(self):
logging.info(f"Directories to backup: {directories}")
self.s = socket.socket()
if not self.allocate_port():
logging.info("Shutting down")
self.s.close()
sys.exit()
self.s.listen(self.open_connections)
self.run()
self.close_all_sockets()
def close_all_sockets(self):
self.s.close()
for tr in self.trackers:
tr["socket"].close()
def allocate_port(self):
for i in range(1, self.socket_range):
if self.try_to_allocate_port():
return True
self.port += 1
logging.info("Socket couldn't be opened")
return False
def try_to_allocate_port(self):
try:
self.s.bind((self.ip, self.port))
logging.info(f"Opened socket on address: {self.s.getsockname()}")
except socket.error as e:
if e.errno == errno.EADDRINUSE:
logging.info(f"Port {self.port} is already in use. Trying to find empty one")
return False
return True
def retrieve_clients_from_trackers(self):
while True:
for tr in self.trackers:
logging.info(
"Trying to retrieve connected client hosts from tracker %s:%s" % (
tr["ip"], tr["port"]))
if connect_to_host(tr["socket"], tr["ip"], tr["port"]):
tracker.retrieve_hosts_from_tracker(tr["socket"], HostType.SERVER,
self.port, self.key, self.clients)
sleep(self.request_time)
def send_file(self, conn, file):
filename = file
filesize = os.stat(file).st_size
progress = tqdm.tqdm(range(filesize), f"Sending {filename}", unit="B", unit_scale=True,
unit_divisor=1024)
with open(file, "rb") as f:
for _ in progress:
bytes_read = f.read(
files.BUFFER_SIZE - Message.metadata_length - message.FileTransfer.total_metadata_length - len(filename))
if not bytes_read:
break
msg = Message.encode(MessageType.File.value, (filename, filesize, bytes_read))
conn.send(msg)
progress.update(len(bytes_read))
def send_all_files_to_client(self, conn):
for dir in self.directories:
for file in files.get_absolute_file_paths(dir):
self.send_file(conn, file)
logging.info("Sent all files")
msg = bytes(Message.id_msg_length)
conn.send(msg)
def listen_for_connections(self):
logging.info("Started thread: listening for connections")
while True:
(conn, address) = self.s.accept()
logging.info("Accepted a connection request from %s:%s" % (address[0], address[1]))
self.connected_clients.append({conn: address})
start_new_thread(self.send_all_files_to_client, (conn,), True)
def run(self):
start_new_thread(self.retrieve_clients_from_trackers, (), True)
start_new_thread(self.listen_for_connections, (), True)
while True:
try:
pass
except KeyboardInterrupt:
return
def print_help():
print('server.py -k key:\n'
'key - same key as the server which is used to get server\'s ip from a tracker')
def parse_arguments(argv):
key = ''
try:
opts, args = getopt.getopt(argv, "hk", ["key="])
except getopt.GetoptError:
print_help()
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print_help()
sys.exit()
elif opt in ("-k", "--key"):
key = arg
if key == '':
key = key_gen.gen_key()
logging.info("Key has been generated: " + key)
return key
if __name__ == '__main__':
prepare_logger(HostType.SERVER.name)
key = parse_arguments(sys.argv[1:])
trackers = [("127.0.0.1", tracker.default_tracker_port)]
directories = ["C:\\Temp", "C:\\Oracle SQL"]
server = Server("localhost", key, trackers, directories)
server.start()