Files
deb-python-eventlet/eventlet/websocket.py

89 lines
2.9 KiB
Python

import collections
import errno
from eventlet import wsgi
from eventlet import pools
import eventlet
from eventlet.common import get_errno
from eventlet.green import socket
#from pprint import pformat
class WebSocket(object):
"""Handles access to the actual socket"""
def __init__(self, sock, environ):
"""
:param socket: The eventlet socket
:type socket: :class:`eventlet.greenio.GreenSocket`
:param environ: The wsgi environment
"""
self.socket = sock
self.origin = environ.get('HTTP_ORIGIN')
self.protocol = environ.get('HTTP_WEBSOCKET_PROTOCOL')
self.path = environ.get('PATH_INFO')
self.environ = environ
self._buf = ""
self._msgs = collections.deque()
self._sendlock = pools.TokenPool(1)
@staticmethod
def pack_message(message):
"""Pack the message inside ``00`` and ``FF``
As per the dataframing section (5.3) for the websocket spec
"""
if isinstance(message, unicode):
message = message.encode('utf-8')
elif not isinstance(message, str):
message = str(message)
packed = "\x00%s\xFF" % message
return packed
def parse_messages(self):
""" Parses for messages in the buffer *buf*. It is assumed that
the buffer contains the start character for a message, but that it
may contain only part of the rest of the message. NOTE: only understands
lengthless messages for now.
Returns an array of messages, and the buffer remainder that didn't contain
any full messages."""
msgs = []
end_idx = 0
buf = self._buf
while buf:
assert ord(buf[0]) == 0, "Don't understand how to parse this type of message: %r" % buf
end_idx = buf.find("\xFF")
if end_idx == -1: #pragma NO COVER
break
msgs.append(buf[1:end_idx].decode('utf-8', 'replace'))
buf = buf[end_idx+1:]
self._buf = buf
return msgs
def send(self, message):
"""Send a message to the client"""
packed = self.pack_message(message)
# if two greenthreads are trying to send at the same time
# on the same socket, sendlock prevents interleaving and corruption
t = self._sendlock.get()
try:
self.socket.sendall(packed)
finally:
self._sendlock.put(t)
def wait(self):
"""Waits for an deserializes messages"""
while not self._msgs:
# no parsed messages, must mean buf needs more data
delta = self.socket.recv(1024)
if delta == '':
return None
self._buf += delta
msgs = self.parse_messages()
self._msgs.extend(msgs)
return self._msgs.popleft()
def close(self):
self.socket.shutdown(True)