Skip to content

Commit ef19ed4

Browse files
committed
Frame is not sent fragmented anymore
1 parent bc5e953 commit ef19ed4

File tree

1 file changed

+47
-52
lines changed

1 file changed

+47
-52
lines changed

websocket.py

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616

1717
class API():
18-
1918
def run_forever(self):
2019
try:
2120
print("Listening on port %d for clients.." % self.port)
@@ -26,28 +25,20 @@ def run_forever(self):
2625
except Exception as e:
2726
print("ERROR: WebSocketsServer: "+str(e))
2827
exit(1)
29-
3028
def new_client(self, client, server):
3129
pass
32-
3330
def client_left(self, client, server):
3431
pass
35-
3632
def message_received(self, client, server, message):
3733
pass
38-
3934
def set_fn_new_client(self, fn):
4035
self.new_client=fn
41-
4236
def set_fn_client_left(self, fn):
4337
self.client_left=fn
44-
4538
def set_fn_message_received(self, fn):
4639
self.message_received=fn
47-
4840
def send_message(self, client, msg):
4941
self._unicast_(client, msg)
50-
5142
def send_message_to_all(self, msg):
5243
self._multicast_(msg)
5344

@@ -83,13 +74,13 @@ def _new_client_(self, handler):
8374
}
8475
self.clients.append(client)
8576
self.new_client(client, self)
86-
77+
8778
def _client_left_(self, handler):
8879
client=self.handler_to_client(handler)
8980
self.client_left(client, self)
9081
if client in self.clients:
9182
self.clients.remove(client)
92-
83+
9384
def _unicast_(self, to_client, msg):
9485
to_client['handler'].send_message(msg)
9586

@@ -123,6 +114,7 @@ def handle(self):
123114
elif self.valid_client:
124115
self.read_next_message()
125116

117+
126118
def read_next_message(self):
127119

128120
b1 = self.rfile.read(1)
@@ -165,9 +157,11 @@ def read_next_message(self):
165157
decoded += chr(char)
166158
self.server._message_received_(self, decoded)
167159

160+
168161
def send_message(self, message):
169162
self.send_text(message)
170163

164+
171165
def send_text(self, message):
172166
'''
173167
+-+-+-+-+-------+-+-------------+-------------------------------+
@@ -181,60 +175,58 @@ def send_text(self, message):
181175
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
182176
| Extended payload length continued, if payload len == 127 |
183177
+ - - - - - - - - - - - - - - - +-------------------------------+
184-
| | Masking-key, if MASK set to 1 |
185-
+-------------------------------+-------------------------------+
186-
| Masking-key (continued) | Payload Data |
187-
+-------------------------------- - - - - - - - - - - - - - - - +
188-
: Payload Data continued ... :
189-
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
190178
| Payload Data continued ... |
191179
+---------------------------------------------------------------+
192-
180+
193181
NOTES
194182
Fragmented(=continuation) messages are not being used since their usage
195183
is needed in very limited cases - when we don't know the payload length.
196184
'''
197185

198-
# 0 = '0x00' = 0b00000000
199-
# 125 = '0x7d' = 0b01111101
200-
# 126 = '0x7e' = 0b01111110
201-
# 127 = '0x7f' = 0b01111111
202-
# 128 = '0x80' = 0b10000000
203-
# 129 = '0x81' = 0b10000001
204-
205-
# assure message is of acceptable format and encode to UTF-8 if needed
206-
encoded_message = None
186+
FIN = 0x80
187+
OPCODE_TEXT = 0x01
188+
EXT_PAYLOAD_16BITS = 0x7e
189+
EXT_PAYLOAD_64BITS = 0x7f
190+
191+
# Validate message
207192
if isinstance(message, bytes):
208193
message = try_decode_UTF8(message) # this is slower but assures we have UTF-8
209194
if not message:
210-
raise Exception("Can\'t send message, message is not valid UTF-8")
195+
print("Can\'t send message, message is not valid UTF-8")
211196
return False
212-
elif not (isinstance(message, str) or isinstance(message, unicode)):
213-
raise Exception('Can\'t send message, message has to be a string or bytes. Given type is %s' % type(message))
197+
elif isinstance(message, str):
198+
pass
199+
else:
200+
print('Can\'t send message, message has to be a string or bytes. Given type is %s' % type(message))
214201
return False
215-
encoded_message = encode_to_UTF8(message)
216-
length = len(encoded_message)
217-
218-
# normal payload
219-
if length <= 125:
220-
#print("sending single frame of size %s", length)
221-
self.request.send(b'\x81')
222-
self.request.send(chr(length).encode())
223-
self.request.send(encoded_message)
202+
203+
header = bytearray()
204+
payload = encode_to_UTF8(message)
205+
payload_length = len(payload)
206+
207+
# Normal payload
208+
if payload_length <= 125:
209+
header.append(FIN | OPCODE_TEXT)
210+
header.append(payload_length)
211+
212+
# Extended payload
213+
elif payload_length >= 126 and payload_length <= 65535:
214+
header.append(FIN | OPCODE_TEXT)
215+
header.append(EXT_PAYLOAD_16BITS)
216+
header.extend(struct.pack(">H", payload_length))
217+
218+
# Huge extended payload
219+
elif payload_length < 18446744073709551616:
220+
header.append(FIN | OPCODE_TEXT)
221+
header.append(EXT_PAYLOAD_64BITS)
222+
header.extend(struct.pack(">Q", payload_length))
224223

225-
# extended payload
226-
elif length >= 126 and length <= 65535:
227-
#print("sending extended frame of size %s", length)
228-
self.request.send(b'\x81\x7e')
229-
self.request.send(struct.pack(">H", length)) # MUST be 16bits
230-
self.request.send(encoded_message)
231-
232-
# huge extended payload
233-
elif length < 18446744073709551616:
234-
#print("sending extended frame of size %s", length)
235-
self.request.send(b'\x81\x7f')
236-
self.request.send(struct.pack(">Q", length)) # MUST be 64bits
237-
self.request.send(encoded_message)
224+
else:
225+
raise Exception("Message is too big. Consider breaking it into chunks.")
226+
return
227+
228+
self.request.send(header + payload)
229+
238230

239231
def handshake(self):
240232
message = self.request.recv(1024).decode().strip()
@@ -254,6 +246,7 @@ def handshake(self):
254246
self.valid_client = True
255247
self.server._new_client_(self)
256248

249+
257250
def make_handshake_response(self, key):
258251
return \
259252
'HTTP/1.1 101 Switching Protocols\r\n'\
@@ -262,12 +255,14 @@ def make_handshake_response(self, key):
262255
'Sec-WebSocket-Accept: %s\r\n' \
263256
'\r\n' % self.calculate_response_key(key)
264257

258+
265259
def calculate_response_key(self, key):
266260
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
267261
hash = sha1(key.encode() + GUID.encode())
268262
response_key = b64encode(hash.digest()).strip()
269263
return response_key.decode('ASCII')
270264

265+
271266
def finish(self):
272267
self.server._client_left_(self)
273268

0 commit comments

Comments
 (0)