-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhwx_server.py
More file actions
180 lines (157 loc) · 6.52 KB
/
hwx_server.py
File metadata and controls
180 lines (157 loc) · 6.52 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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import select
import socket
class Server:
SERVER_ADDR = ("localhost", 7596)
MAX_DESC = 3
socket = None
inStream = list()
outStream = list()
clientsInfo = {}
def __init__(self):
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setblocking(False)
self.socket.bind(self.SERVER_ADDR)
self.socket.listen(self.MAX_DESC)
except Exception:
print("[ERROR] Cannot to start. Probably you need to be root-user for launch the app!")
def run(self):
self.inStream.append(self.socket)
print("[INFO] Server is running, use Ctrl+C to stop")
try:
while True:
readables, writables, exceptional = select.select(self.inStream, self.outStream, self.inStream)
self.on_event(readables)
except KeyboardInterrupt:
self.free_res(self.socket)
print("[INFO] Server was stopped!")
def accept_new_client(self, resource):
connection, client_address = resource.accept()
connection.setblocking(0)
self.inStream.append(connection)
print("New client {address}".format(address=client_address))
def receive_data(self, resource):
data = ""
try:
data = resource.recv(1024)
except ConnectionResetError:
print("[WARNING] Connection was closed!")
self.send_join_left_message(resource, isJoin=False)
if data:
data = str(data, encoding="UTF-8")
print("[TEXT-LOG]: {}".format(data))
if resource not in self.outStream:
self.outStream.append(resource)
if data.find("#[SERVICE]#") != -1:
self.service_action(resource, data)
else:
self.send_broadcast(data, resource)
else:
self.free_res(resource)
def on_event(self, readables):
for resource in readables:
if resource is self.socket:
self.accept_new_client(resource)
else:
self.receive_data(resource)
def get_resource_id(self, resource):
if self.outStream.count(resource) > 0:
return self.outStream.index(resource)
return -1
def service_action(self, resource, data):
data = data[11:]
raw = data.split(":")
if raw[0] == "cmd":
if raw[1] == "userlist":
self.show_user_list(resource)
if raw[1] == "whoami":
self.show_whoami(resource)
if raw[1] == "help":
self.show_help(resource)
if raw[1] == "p":
self.send_private_message(raw, resource)
if raw[1] == "cname":
self.change_user_name(raw, resource)
else:
self.add_user_info(raw, resource)
def add_user_info(self, raw, resource):
unum = self.get_resource_id(resource)
isGreeting = 0
if unum not in self.clientsInfo.keys():
isGreeting = -1
info = {raw[0]: raw[1]}
if unum != -1:
self.clientsInfo[unum] = info
if isGreeting == -1:
self.send_join_left_message(resource, isJoin=True)
def send_join_left_message(self, resource, isJoin=True):
nickname = self.clientsInfo[self.get_resource_id(resource)]["NICK"]
words = " join in" if isJoin else " left from"
message = "User " + nickname + words + " our chat!"
self.send_broadcast(message)
def send_broadcast(self, message, innerres=None):
for resource in self.outStream:
try:
if innerres is not None:
if innerres != resource:
id = self.outStream.index(innerres)
info = self.clientsInfo[id]
resource.send(bytes(info["NICK"] + ": " + message, encoding='UTF-8'))
else:
resource.send(bytes(message, encoding='UTF-8'))
except OSError:
self.free_res(resource)
def send_answer_to(self, toclient, message, fromclient=None):
fromId = self.get_resource_id(fromclient)
try:
if fromclient is not None:
infoFromClient = self.clientsInfo[fromId]
message = infoFromClient["NICK"] + ": " + message
if toclient in self.clientsInfo.keys():
self.outStream[toclient].send(bytes(message, encoding='UTF-8'))
else:
self.send_answer_to(fromId, "[SERVER] Your message was not delivered")
except OSError:
self.free_res(self.outStream[toclient])
def show_user_list(self, resource):
unum = self.get_resource_id(resource)
if unum != -1:
result = "\nWho is online: \n"
for k, v in self.clientsInfo.items():
result += "#{} -> {}\n".format(k, v["NICK"])
self.send_answer_to(unum, result)
def show_help(self, resource):
unum = self.get_resource_id(resource)
if unum != -1:
result = "=====================================\n" \
"/userlist - Show all users online\n" \
"/help - Get the command list\n" \
"/quit - Leave from the hell\n" \
"/whoami - Returns your nickname and ID\n" \
"/p:ID - Send a private message\n" \
"/cname:NEWNAME to change your nickname\n" \
"====================================="
self.send_answer_to(unum, result)
def show_whoami(self, resource):
unum = self.get_resource_id(resource)
try:
name = self.clientsInfo[unum]["NICK"]
self.outStream[unum].send(bytes("You are #{} -> {}".format(unum, name), encoding='UTF-8'))
except OSError:
self.free_res(self.outStream[unum])
def send_private_message(self, raw, resource):
if raw[2] != "" and raw[3] != "":
self.send_answer_to(int(raw[2]), "(private) " + raw[3], resource)
def free_res(self, resource):
if resource in self.outStream:
self.outStream.remove(resource)
if resource in self.inStream:
self.inStream.remove(resource)
resource.close()
print('[INFO] Closing connection ' + str(resource))
def change_user_name(self, raw, resource):
if raw[2] != "":
self.add_user_info(["NICK", raw[2]], resource)
if __name__ == '__main__':
server = Server()
server.run()