-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.py
126 lines (113 loc) · 4.21 KB
/
server.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
import socket
import threading
import os
import time
import json
from connectionManager import connectionManager
from fileManager import fileManager, getChecksum
# Globals
controlHost = "0.0.0.0"
PORT = 3000
# This bit of code determines the local ip address of the server
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = (s.getsockname()[0])
s.close()
print(f"Server IP : {ip}")
print()
print("Waiting for clients...")
def process(header: bytes, man: connectionManager): # Receives a header message and processes it to do the specified command
comm = header.split("#")
if comm[0] == "GET":
try:
size = os.path.getsize("Files/" + comm[1])
except FileNotFoundError:
man.send("-1")
return ""
checksum = getChecksum("Files/" + comm[1])
man.send(str(size) + "#" + checksum)
fm = fileManager("Files/" + comm[1])
while fm.chunk == fm.chunkSize:
if man.sendBytes(fm.getChunk()) == 0:
break
print("Successfully sent file " + comm[1])
elif comm[0] == "LIST":
files = os.listdir(os.getcwd()+"/Files")
out = ""
for item in files:
out += item + "#"
man.send(out)
elif comm[0] == "POST":
print("Preparing for upload")
filename = comm[1]
size = int(comm[2])
if size == -1:
print("404 - File not found")
return ""
print(f"Size is {size}")
received = 0
with open("Files/" + filename, "wb") as f:
prev = 0
while received < size:
chunk = man.receiveBytes()
f.write(chunk)
received += len(chunk)
percent = round((received/size)*100, 1)
if percent - prev > 1:
print(f"{percent}%")
prev = percent
checksum = getChecksum("Files/" + comm[1])
if comm[3] == checksum:
print("Checksum Match - File was not altered in transit")
man.send("Success! - Checksum match")
else:
print("ERROR CHECKSUM MISMATCH - File was altered in Transit")
print("Removing Altered/Corrupted File")
os.remove("Files/" + filename)
elif comm[0] == "DELETE":
if comm[1] == '':
return
print("Deleting file " + comm[1])
try:
os.remove("Files/" + comm[1])
except FileNotFoundError:
print("ERROR 404 - File not found")
else:
print("Invalid header")
man.send("ERROR - INVALID HEADER")
def clientThread(conn: socket.socket): # The target method when the server receieves a connection the server creates a new thread
with conn:
# create a new connection manager and set to not sending
man = connectionManager(False, conn)
while True:
out = man.receive()
print(out)
if out == 0: # If it could not send the data, terminate the current thread
break # Escape the loop if message failed
if not out:
break
process(out, man)
# Begining of the server
def main(): # The main part of the server, waits for a connection on the correct port and then when a client connects it creates a new thread.
global threads, controlHost
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as clientSocket:
clientSocket.bind((controlHost, PORT))
clientSocket.listen()
while True:
try:
conn, addr = clientSocket.accept()
print(f"Connected by {addr} on {PORT}")
# When connection is created fork the thread and then repeat
client = threading.Thread(target=clientThread, args=(conn,))
client.daemon = True
client.start()
# Naming of threads for debugging reasons
threads = threading.active_count()-1
client.name = f"Client{threads}"
print(f"Active Clients {threads}")
except KeyboardInterrupt:
print("Done")
clientSocket.close()
print()
if __name__ == "__main__":
main()