Skip to content

Commit dc9d913

Browse files
committed
Check the opcode of the frame
We implement a system of opcode checking so we can differentiate the types of frame we are receiving. In case the opcode is unknown, we close the connection according to RFC 6455: "If an unknown opcode is received, the receiving endpoint MUST _Fail the WebSocket Connection_." However, if the opcode is know but we do not support it, we just display a warning and ignore the frame. For now on, nothing happens if we receive a PING or PONG frame. fixed Pithikos#6 Signed-off-by: Olivier Gayot <[email protected]>
1 parent 4dae1c1 commit dc9d913

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

websocket_server/websocket_server.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@
3737
PAYLOAD_LEN_EXT16 = 0x7e
3838
PAYLOAD_LEN_EXT64 = 0x7f
3939

40-
OPCODE_TEXT = 0x01
41-
CLOSE_CONN = 0x8
42-
40+
OPCODE_CONTINUATION = 0x0
41+
OPCODE_TEXT = 0x1
42+
OPCODE_BINARY = 0x2
43+
OPCODE_CLOSE_CONN = 0x8
44+
OPCODE_PING = 0x9
45+
OPCODE_PONG = 0xA
4346

4447

4548
# -------------------------------- API ---------------------------------
@@ -99,6 +102,12 @@ def __init__(self, port, host='127.0.0.1'):
99102
def _message_received_(self, handler, msg):
100103
self.message_received(self.handler_to_client(handler), self, msg)
101104

105+
def _ping_received_(self, handler, msg):
106+
pass
107+
108+
def _pong_received_(self, handler, msg):
109+
pass
110+
102111
def _new_client_(self, handler):
103112
self.id_counter += 1
104113
client={
@@ -164,19 +173,36 @@ def read_next_message(self):
164173
opcode = b1 & OPCODE
165174
masked = b2 & MASKED
166175
payload_length = b2 & PAYLOAD_LEN
176+
opcode_handler = None
167177

168178
if not b1:
169179
print("Client closed connection.")
170180
self.keep_alive = 0
171181
return
172-
if opcode == CLOSE_CONN:
182+
if opcode == OPCODE_CLOSE_CONN:
173183
print("Client asked to close connection.")
174184
self.keep_alive = 0
175185
return
176186
if not masked:
177187
print("Client must always be masked.")
178188
self.keep_alive = 0
179189
return
190+
if opcode == OPCODE_CONTINUATION:
191+
print("Continuation frames not handled.")
192+
return
193+
elif opcode == OPCODE_BINARY:
194+
print("Binary frames not handled.")
195+
return
196+
elif opcode == OPCODE_TEXT:
197+
opcode_handler = self.server._message_received_
198+
elif opcode == OPCODE_PING:
199+
opcode_handler = self.server._ping_received_
200+
elif opcode == OPCODE_PONG:
201+
opcode_handler = self.server._pong_received_
202+
else:
203+
print("Unknown opcode %#x." + opcode)
204+
self.keep_alive = 0
205+
return
180206

181207
if payload_length == 126:
182208
payload_length = struct.unpack(">H", self.rfile.read(2))[0]
@@ -188,7 +214,7 @@ def read_next_message(self):
188214
for char in self.read_bytes(payload_length):
189215
char ^= masks[len(decoded) % 4]
190216
decoded += chr(char)
191-
self.server._message_received_(self, decoded)
217+
opcode_handler(self, decoded)
192218

193219
def send_message(self, message):
194220
self.send_text(message)

0 commit comments

Comments
 (0)