-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathserver.py
More file actions
78 lines (60 loc) · 2.65 KB
/
server.py
File metadata and controls
78 lines (60 loc) · 2.65 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
import SocketServer
import hashlib
import base64
WS_MAGIC_STRING = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
headers = self.data.split("\r\n")
# is it a websocket request?
if "Connection: Upgrade" in self.data and "Upgrade: websocket" in self.data:
# getting the websocket key out
for h in headers:
if "Sec-WebSocket-Key" in h:
key = h.split(" ")[1]
# let's shake hands shall we?
self.shake_hand(key)
while True:
payload = self.decode_frame(bytearray(self.request.recv(1024).strip()))
decoded_payload = payload.decode('utf-8')
self.send_frame(payload)
if "bye" == decoded_payload.lower():
"Bidding goodbye to our client..."
return
else:
self.request.sendall("HTTP/1.1 400 Bad Request\r\n" + \
"Content-Type: text/plain\r\n" + \
"Connection: close\r\n" + \
"\r\n" + \
"Incorrect request")
def shake_hand(self,key):
# calculating response as per protocol RFC
key = key + WS_MAGIC_STRING
resp_key = base64.standard_b64encode(hashlib.sha1(key).digest())
resp="HTTP/1.1 101 Switching Protocols\r\n" + \
"Upgrade: websocket\r\n" + \
"Connection: Upgrade\r\n" + \
"Sec-WebSocket-Accept: %s\r\n\r\n"%(resp_key)
self.request.sendall(resp)
def decode_frame(self,frame):
opcode_and_fin = frame[0]
# assuming it's masked, hence removing the mask bit(MSB) to get len. also assuming len is <125
payload_len = frame[1] - 128
mask = frame [2:6]
encrypted_payload = frame [6: 6+payload_len]
payload = bytearray([ encrypted_payload[i] ^ mask[i%4] for i in range(payload_len)])
return payload
def send_frame(self, payload):
# setting fin to 1 and opcpde to 0x1
frame = [129]
# adding len. no masking hence not doing +128
frame += [len(payload)]
# adding payload
frame_to_send = bytearray(frame) + payload
self.request.sendall(frame_to_send)
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()