This commit is contained in:
Nick 2016-12-06 23:55:05 +00:00 committed by GitHub
commit 1375821a0d
1 changed files with 25 additions and 11 deletions

View File

@ -156,13 +156,16 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
@staticmethod @staticmethod
def encode_hybi(buf, opcode, base64=False): def encode_hybi(buf, opcode, base64=False):
""" Encode a HyBi style WebSocket frame. """ Encode a HyBi style WebSocket frame.
Optional opcode: Opcode, defined by the HyBi spec:
0x0 - continuation 0x0 - continuation
0x1 - text frame (base64 encode buf) 0x1 - text frame
0x2 - binary frame (use raw buf) 0x2 - binary frame
0x8 - connection close 0x8 - connection close
0x9 - ping 0x9 - ping
0xA - pong 0xA - pong
If base64 is set, the buffer will be base64 encoded before being sent.
This is probably only useful in conjunction with opcode=0x1.
""" """
if base64: if base64:
buf = b64encode(buf) buf = b64encode(buf)
@ -310,10 +313,12 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
if bufs: if bufs:
for buf in bufs: for buf in bufs:
if self.base64: if self.mode == 'base64':
encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=1, base64=True) encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=1, base64=True)
else: elif self.mode == 'binary':
encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=2, base64=False) encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=2, base64=False)
elif self.mode == 'text':
encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=1, base64=False)
if self.rec: if self.rec:
self.rec.write("%s,\n" % self.rec.write("%s,\n" %
@ -448,12 +453,13 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
# Choose binary if client supports it # Choose binary if client supports it
if 'binary' in protocols: if 'binary' in protocols:
self.base64 = False self.mode = 'binary'
elif 'base64' in protocols: elif 'base64' in protocols:
self.base64 = True self.mode = 'base64'
elif 'text' in protocols:
self.mode = 'text'
else: else:
self.send_error(400, "Client must support 'binary' or 'base64' protocol") self.mode = 'text'
return False
# Generate the hash value for the accept header # Generate the hash value for the accept header
accept = b64encode(sha1(s2b(key + self.GUID)).digest()) accept = b64encode(sha1(s2b(key + self.GUID)).digest())
@ -464,15 +470,23 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.send_header("Sec-WebSocket-Accept", b2s(accept)) self.send_header("Sec-WebSocket-Accept", b2s(accept))
if self.base64: if self.base64:
self.send_header("Sec-WebSocket-Protocol", "base64") self.send_header("Sec-WebSocket-Protocol", "base64")
else: elif self.binary:
self.send_header("Sec-WebSocket-Protocol", "binary") self.send_header("Sec-WebSocket-Protocol", "binary")
# no header for "text" mode; it is the default websocket mode.
self.end_headers() self.end_headers()
return True return True
else: else:
self.send_error(400, "Missing Sec-WebSocket-Version header. Hixie protocols not supported.") self.send_error(400, "Missing Sec-WebSocket-Version header. Hixie protocols not supported.")
return False return False
@property
def base64(self): return self.mode == 'base64'
@property
def binary(self): return self.mode == 'binary'
def handle_websocket(self): def handle_websocket(self):
"""Upgrade a connection to Websocket, if requested. If this succeeds, """Upgrade a connection to Websocket, if requested. If this succeeds,
new_websocket_client() will be called. Otherwise, False is returned. new_websocket_client() will be called. Otherwise, False is returned.