Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Commit 03ad34a

Browse files
authored
Update main.py
1 parent 87c9204 commit 03ad34a

File tree

1 file changed

+193
-130
lines changed

1 file changed

+193
-130
lines changed

server/main.py

Lines changed: 193 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,166 +1,229 @@
1-
import rsa
1+
from threading import Thread
22
import socket
3+
import rsa
34
import zlib
5+
import sys
46
import time
57
import json
6-
import _thread as thd
78

89
from rich import print
910

10-
#start
11+
# Read config file
1112
config_file = "config.json"
1213
with open(config_file, "r") as f:
1314
config_json = json.load(f)
1415

15-
#vars
16+
# Vars
1617
clients = []
17-
username = {}
18+
nicknames = []
19+
20+
# Config
1821

19-
#config
20-
ip = config_json["ip"]
21-
port = config_json["port"]
22-
buffer = config_json["buffer"]
23-
welcome_message = config_json["welcome_message"]
22+
"""
23+
ip : The IP address where the server will start listening for connections
24+
port : The connection port, it is recommended to keep it default (8889)
25+
buffer : The maximum network buffer
26+
welcome_message : Welcome message to new users
27+
"""
2428

25-
#create socket
29+
ip: str = config_json["ip"]
30+
port: int = config_json["port"]
31+
buffer: int = config_json["buffer"]
32+
welcome_message: str = config_json["welcome_message"]
33+
34+
# Create socket
2635
server = socket.socket()
2736

28-
#start listing
29-
server.bind((ip,port))
37+
# Start listing
38+
server.bind((ip, port))
3039
server.listen(32)
3140

32-
#creating RSA key
33-
def create_keys(buffer: int):
34-
public_key, private_key = rsa.newkeys(buffer)
35-
return public_key, private_key
41+
42+
class API:
43+
44+
"""
45+
def create_keys (buffer: int):
46+
Generate an RSA key
47+
48+
def send_buffer (socket, buffer: int):
49+
Send the buffer to the client
50+
51+
class Chat:
52+
arg: private_key, public_key
53+
54+
def send (socket, message: str):
55+
Send encrypted message
56+
57+
def recv (socketm, message: str):
58+
Receives a message and decrypt it
59+
60+
class RSA:
61+
arg: public_key, private_key
62+
63+
def encryption (message: str):
64+
Encrypt message
65+
66+
def decrypt (message: bytes):
67+
Decrypt message
68+
"""
69+
70+
def create_keys(buffer: int):
71+
public_key, private_key = rsa.newkeys(buffer)
72+
return public_key, private_key
73+
74+
def send_buffer(s, buffer: int):
75+
s.send(str(buffer).encode())
76+
77+
class Chat:
78+
def __init__(self, priv_key, pub_key) -> None:
79+
self.priv_key = priv_key
80+
self.pub_key = pub_key
81+
82+
def send(self, s, msg: str):
83+
s.send(rsa.encrypt(msg.encode(), self.pub_key))
84+
85+
def recv(self, s, buffer: int):
86+
msg = s.recv(buffer)
87+
return rsa.decrypt(msg, self.priv_key)
88+
89+
class Send_keys:
90+
def __init__(self, pub_key, priv_key, client) -> None:
91+
self.client = client
92+
self.pub_key = pub_key
93+
self.priv_key = priv_key
94+
95+
def private(self):
96+
private_key_exported = rsa.PrivateKey.save_pkcs1(self.priv_key)
97+
# compressing
98+
private_key_exported = zlib.compress(private_key_exported, 4)
99+
self.client.send(private_key_exported)
100+
101+
def public(self):
102+
public_key_exported = rsa.PublicKey.save_pkcs1(self.pub_key)
103+
# compressing
104+
public_key_exported = zlib.compress(public_key_exported, 4)
105+
self.client.send(public_key_exported)
106+
107+
class RSA:
108+
def __init__(self, pub_key, priv_key) -> None:
109+
self.pub_key = pub_key
110+
self.priv_key = priv_key
111+
112+
def encrypt(self, msg: str):
113+
return rsa.encrypt(msg.encode(), self.pub_key)
114+
115+
def decrypt(self, msg: bytes):
116+
return rsa.decrypt(msg, self.priv_key)
117+
36118

37119
class Chat:
38-
def __init__(self, priv_key, pub_key) -> None:
39-
self.priv_key = priv_key
40-
self.pub_key = pub_key
41-
def send(self, s, msg:str):
42-
s.send(rsa.encrypt(msg.encode(), self.pub_key))
43-
def recv(self, s, buffer: int):
44-
msg = s.recv(buffer)
45-
return rsa.decrypt(msg, self.priv_key)
46-
47-
class Send_keys:
48-
def __init__(self,pub_key, priv_key, client) -> None:
120+
"""
121+
Args: client (socket), private_key, public_key
122+
123+
def joined (nickname: str):
124+
It will send a message when a client disconnect
125+
126+
def welcome_message (bytes: bytes):
127+
It will send the clients the encrypted welcome message
128+
129+
def send_to_clients (message: bytes):
130+
It sends clients a message, but it won't be able to send it to itself
131+
132+
def remove_client (client):
133+
removes clients from the client list
134+
135+
def middle:
136+
When a customer enters the chat, perform this function.
137+
Send clients a message announcing that a client has logged in,
138+
then wait for a message from the client and then send it to all
139+
140+
def run:
141+
It's where this class will launch
142+
"""
143+
144+
def __init__(self, client, private_key, public_key) -> None:
49145
self.client = client
50-
self.pub_key = pub_key
51-
self.priv_key = priv_key
146+
self.private_key = private_key
147+
self.public_key = public_key
52148

53-
def private(self):
54-
private_key_exported = rsa.PrivateKey.save_pkcs1(self.priv_key)
55-
#compressing
56-
private_key_exported = zlib.compress(private_key_exported, 4)
57-
self.client.send(private_key_exported)
149+
def joined(self, nickname: str):
150+
self.send_to_clients(self.rsa_api.encrypt(
151+
f"[green]{nickname}[/green] has joined."))
58152

59-
def public(self):
60-
public_key_exported = rsa.PublicKey.save_pkcs1(self.pub_key)
61-
#compressing
62-
public_key_exported = zlib.compress(public_key_exported, 4)
63-
self.client.send(public_key_exported)
153+
def welcome_message(self, welcome_message: bytes):
154+
self.client.send(welcome_message)
64155

65-
class Main:
66-
def __init__(self) -> None:
67-
pass
68-
69-
def chat(client, public_key, private_key):
70-
def send_buffer():
71-
client.send(str(buffer).encode())
72-
73-
def remove_connection(client_socket):
74-
if client_socket in clients:
75-
#remove client socket
76-
clients.remove(client_socket)
77-
#remove username
78-
username.pop(client_socket)
79-
print("[[yellow]?[/yellow]] Client disconnected")
80-
81-
def send_to_clients(msg):
82-
for client_socket in clients:
83-
if client != client_socket:
84-
try:
85-
client_socket.send(msg)
86-
except:
87-
client_socket.close()
88-
remove_connection(client_socket)
89-
90-
def check_username():
91-
exist = False
92-
93-
username_unchecked = client.recv(buffer).decode()
94-
for user in username:
95-
if not exist:
96-
if username[user] == username_unchecked:
97-
exist = True
98-
#send code status and close connection
99-
if exist:
100-
client.send("False".encode())
101-
remove_connection(client)
102-
#send code status and add username
103-
else:
104-
client.send("True".encode())
105-
username[client] = username_unchecked
106-
def middle():
107-
while True:
156+
def send_to_clients(self, msg: bytes):
157+
for client in clients:
158+
if client != self.client:
108159
try:
109-
msg = client.recv(buffer)
110-
if msg.decode() == "/users":
111-
users = ""
112-
for user in username:
113-
users += username[user]+","
114-
client.send(users.encode())
115-
else:
116-
if msg:
117-
send_to_clients(msg)
118-
else:
119-
remove_connection(client)
120-
except:
121-
continue
122-
123-
send_buffer()
124-
125-
#init class for send RSA keys
126-
client_key = Send_keys(public_key, private_key, client)
127-
128-
#send keys
129-
client_key.private(); time.sleep(0.5)
130-
client_key.public()
131-
132-
#API
133-
chat_sock = Chat(private_key, public_key)
160+
client.send(msg)
161+
except BaseException:
162+
self.remove_client(client)
163+
164+
def remove_client(self, client):
165+
print("[[yellow]?[/yellow]] Client disconnected")
166+
index = clients.index(client)
167+
clients.remove(client)
168+
nickname = nicknames[index]
169+
self.send_to_clients(self.rsa_api.encrypt(
170+
f"[green]{nickname}[/green] has left."))
171+
nicknames.remove(nickname)
172+
173+
def middle(self):
174+
index = clients.index(self.client)
175+
nickname = nicknames[index]
176+
self.joined(nickname)
177+
while True:
178+
try:
179+
msg = self.client.recv(buffer)
180+
self.send_to_clients(msg)
181+
except BaseException:
182+
self.remove_client(self.client)
183+
break
134184

135-
time.sleep(0.5)
185+
def run(self):
186+
API.send_buffer(self.client, buffer)
187+
send_keys = API.Send_keys(
188+
self.public_key,
189+
self.private_key,
190+
self.client)
136191

137-
#check username
138-
check_username()
139-
192+
self.rsa_api = API.RSA(self.public_key, self.private_key)
193+
self.chat_api = API.Chat(self.private_key, self.public_key)
194+
195+
send_keys.public()
140196
time.sleep(0.5)
197+
send_keys.private()
198+
# Encrypt welcome_message and send to client
199+
self.welcome_message(self.rsa_api.encrypt(welcome_message))
200+
self.middle()
141201

142-
#welcome message
143-
chat_sock.send(client, welcome_message)
144202

145-
middle()
146-
def run(self):
147-
stopped = False
148-
149-
print(f"[[cyan]+[/cyan]] Buffer: {buffer}")
150-
151-
print("[[cyan]+[/cyan]] Creating RSA keys...")
152-
self.public_key, self.private_key = create_keys(buffer)
153-
print("[[cyan]+[/cyan]] RSA keys created")
154-
155-
while (not stopped):
203+
class Main:
204+
"""
205+
def run:
206+
It will generate keys and wait for connections
207+
"""
208+
def run():
209+
print(f"[[magenta]*[/magenta]] Buffer: {buffer}")
210+
print("[[cyan]+[/cyan]] RSA key generation...")
211+
public_key, private_key = API.create_keys(buffer)
212+
print("[[cyan]+[/cyan]] RSA key generated")
213+
while True:
156214
client, addr = server.accept()
157215
print("[[yellow]?[/yellow]] Client connected")
158-
#add
216+
217+
nickname = client.recv(buffer).decode()
218+
nicknames.append(nickname)
219+
159220
clients.append(client)
160221

161-
#start in idle
162-
thd.start_new_thread(Main.chat, (client, self.public_key, self.private_key))
222+
chat = Chat(client, private_key, public_key)
223+
224+
multi_conn = Thread(target=chat.run)
225+
multi_conn.start()
226+
163227

164228
if __name__ == "__main__":
165-
main_start = Main()
166-
main_start.run()
229+
Main.run()

0 commit comments

Comments
 (0)