Unfortunately, No... I tried to check Ubuntu 14.04 now.
vagrant@ubuntu1404:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.1 LTS"
vagrant@ubuntu1404:~$ apt-cache show python-eventlet | grep -i ^version
Version: 0.13.0-1ubuntu2
2015-04-17 7:51 GMT+09:00 FUJITA Tomonori <[email protected]>:
> Thanks! I've applied #2-8. 0.15 or the newer is already shipped with
> major distributions like Ubuntu? If not, I tend to postpone this.
>
> On Tue, 14 Apr 2015 13:18:17 +0900
> Satoshi Kobayashi <[email protected]> wrote:
>
> > Signed-off-by: Satoshi Kobayashi <[email protected]>
> > ---
> > ryu/app/wsgi.py | 12 +-
> > ryu/contrib/_eventlet/__init__.py | 0
> > ryu/contrib/_eventlet/websocket.py | 656
> -------------------------------------
> > ryu/lib/hub.py | 2 +-
> > tools/pip-requires | 2 +-
> > 5 files changed, 8 insertions(+), 664 deletions(-)
> > delete mode 100644 ryu/contrib/_eventlet/__init__.py
> > delete mode 100644 ryu/contrib/_eventlet/websocket.py
> >
> > diff --git a/ryu/app/wsgi.py b/ryu/app/wsgi.py
> > index 94e67f6..85ab7c3 100644
> > --- a/ryu/app/wsgi.py
> > +++ b/ryu/app/wsgi.py
> > @@ -23,12 +23,12 @@ from ryu import cfg
> > from ryu.lib import hub
> > from routes import Mapper
> > from routes.util import URLGenerator
> > -from tinyrpc.server import RPCServer
> > -from tinyrpc.dispatch import RPCDispatcher
> > -from tinyrpc.dispatch import public as rpc_public
> > -from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
> > -from tinyrpc.transports import ServerTransport, ClientTransport
> > -from tinyrpc.client import RPCClient
> > +from ryu.contrib.tinyrpc.server import RPCServer
> > +from ryu.contrib.tinyrpc.dispatch import RPCDispatcher
> > +from ryu.contrib.tinyrpc.dispatch import public as rpc_public
> > +from ryu.contrib.tinyrpc.protocols.jsonrpc import JSONRPCProtocol
> > +from ryu.contrib.tinyrpc.transports import ServerTransport,
> ClientTransport
> > +from ryu.contrib.tinyrpc.client import RPCClient
> >
> > CONF = cfg.CONF
> > CONF.register_cli_opts([
> > diff --git a/ryu/contrib/_eventlet/__init__.py
> b/ryu/contrib/_eventlet/__init__.py
> > deleted file mode 100644
> > index e69de29..0000000
> > diff --git a/ryu/contrib/_eventlet/websocket.py
> b/ryu/contrib/_eventlet/websocket.py
> > deleted file mode 100644
> > index 4a07c8d..0000000
> > --- a/ryu/contrib/_eventlet/websocket.py
> > +++ /dev/null
> > @@ -1,656 +0,0 @@
> > -import base64
> > -import codecs
> > -import collections
> > -import errno
> > -from random import Random
> > -import string
> > -import struct
> > -import sys
> > -import time
> > -from socket import error as SocketError
> > -
> > -try:
> > - from hashlib import md5, sha1
> > -except ImportError: #pragma NO COVER
> > - from md5 import md5
> > - from sha import sha as sha1
> > -
> > -import eventlet
> > -from eventlet import semaphore
> > -from eventlet import wsgi
> > -from eventlet.green import socket
> > -from eventlet.support import get_errno
> > -
> > -# Python 2's utf8 decoding is more lenient than we'd like
> > -# In order to pass autobahn's testsuite we need stricter validation
> > -# if available...
> > -for _mod in ('wsaccel.utf8validator', 'autobahn.utf8validator'):
> > - # autobahn has it's own python-based validator. in newest versions
> > - # this prefers to use wsaccel, a cython based implementation, if
> available.
> > - # wsaccel may also be installed w/out autobahn, or with a earlier
> version.
> > - try:
> > - utf8validator = __import__(_mod, {}, {}, [''])
> > - except ImportError:
> > - utf8validator = None
> > - else:
> > - break
> > -
> > -ACCEPTABLE_CLIENT_ERRORS = set((errno.ECONNRESET, errno.EPIPE))
> > -
> > -__all__ = ["WebSocketWSGI", "WebSocket"]
> > -PROTOCOL_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
> > -VALID_CLOSE_STATUS = (range(1000, 1004)
> > - + range(1007, 1012)
> > - # 3000-3999: reserved for use by libraries,
> frameworks,
> > - # and applications
> > - + range(3000, 4000)
> > - # 4000-4999: reserved for private use and thus
> can't
> > - # be registered
> > - + range(4000, 5000))
> > -
> > -
> > -class BadRequest(Exception):
> > - def __init__(self, status='400 Bad Request', body=None,
> headers=None):
> > - super(Exception, self).__init__()
> > - self.status = status
> > - self.body = body
> > - self.headers = headers
> > -
> > -
> > -class WebSocketWSGI(object):
> > - """Wraps a websocket handler function in a WSGI application.
> > -
> > - Use it like this::
> > -
> > - @websocket.WebSocketWSGI
> > - def my_handler(ws):
> > - from_browser = ws.wait()
> > - ws.send("from server")
> > -
> > - The single argument to the function will be an instance of
> > - :class:`WebSocket`. To close the socket, simply return from the
> > - function. Note that the server will log the websocket request at
> > - the time of closure.
> > - """
> > - def __init__(self, handler):
> > - self.handler = handler
> > - self.protocol_version = None
> > - self.support_legacy_versions = True
> > - self.supported_protocols = []
> > - self.origin_checker = None
> > -
> > - @classmethod
> > - def configured(cls,
> > - handler=None,
> > - supported_protocols=None,
> > - origin_checker=None,
> > - support_legacy_versions=False):
> > - def decorator(handler):
> > - inst = cls(handler)
> > - inst.support_legacy_versions = support_legacy_versions
> > - inst.origin_checker = origin_checker
> > - if supported_protocols:
> > - inst.supported_protocols = supported_protocols
> > - return inst
> > - if handler is None:
> > - return decorator
> > - return decorator(handler)
> > -
> > - def __call__(self, environ, start_response):
> > - http_connection_parts = [
> > - part.strip()
> > - for part in environ.get('HTTP_CONNECTION',
> '').lower().split(',')]
> > - if not ('upgrade' in http_connection_parts and
> > - environ.get('HTTP_UPGRADE', '').lower() == 'websocket'):
> > - # need to check a few more things here for true compliance
> > - start_response('400 Bad Request', [('Connection', 'close')])
> > - return []
> > -
> > - try:
> > - if 'HTTP_SEC_WEBSOCKET_VERSION' in environ:
> > - ws = self._handle_hybi_request(environ)
> > - elif self.support_legacy_versions:
> > - ws = self._handle_legacy_request(environ)
> > - else:
> > - raise BadRequest()
> > - except BadRequest as e:
> > - status = e.status
> > - body = e.body or ''
> > - headers = e.headers or []
> > - start_response(status,
> > - [('Connection', 'close'), ] + headers)
> > - return [body]
> > -
> > - try:
> > - self.handler(ws)
> > - except socket.error as e:
> > - if get_errno(e) not in ACCEPTABLE_CLIENT_ERRORS:
> > - raise
> > - # Make sure we send the closing frame
> > - ws._send_closing_frame(True)
> > - # use this undocumented feature of eventlet.wsgi to ensure that
> it
> > - # doesn't barf on the fact that we didn't call start_response
> > - return wsgi.ALREADY_HANDLED
> > -
> > - def _handle_legacy_request(self, environ):
> > - sock = environ['eventlet.input'].get_socket()
> > -
> > - if 'HTTP_SEC_WEBSOCKET_KEY1' in environ:
> > - self.protocol_version = 76
> > - if 'HTTP_SEC_WEBSOCKET_KEY2' not in environ:
> > - raise BadRequest()
> > - else:
> > - self.protocol_version = 75
> > -
> > - if self.protocol_version == 76:
> > - key1 =
> self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY1'])
> > - key2 =
> self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY2'])
> > - # There's no content-length header in the request, but it
> has 8
> > - # bytes of data.
> > - environ['wsgi.input'].content_length = 8
> > - key3 = environ['wsgi.input'].read(8)
> > - key = struct.pack(">II", key1, key2) + key3
> > - response = md5(key).digest()
> > -
> > - # Start building the response
> > - scheme = 'ws'
> > - if environ.get('wsgi.url_scheme') == 'https':
> > - scheme = 'wss'
> > - location = '%s://%s%s%s' % (
> > - scheme,
> > - environ.get('HTTP_HOST'),
> > - environ.get('SCRIPT_NAME'),
> > - environ.get('PATH_INFO')
> > - )
> > - qs = environ.get('QUERY_STRING')
> > - if qs is not None:
> > - location += '?' + qs
> > - if self.protocol_version == 75:
> > - handshake_reply = ("HTTP/1.1 101 Web Socket Protocol
> Handshake\r\n"
> > - "Upgrade: WebSocket\r\n"
> > - "Connection: Upgrade\r\n"
> > - "WebSocket-Origin: %s\r\n"
> > - "WebSocket-Location: %s\r\n\r\n" % (
> > - environ.get('HTTP_ORIGIN'),
> > - location))
> > - elif self.protocol_version == 76:
> > - handshake_reply = ("HTTP/1.1 101 WebSocket Protocol
> Handshake\r\n"
> > - "Upgrade: WebSocket\r\n"
> > - "Connection: Upgrade\r\n"
> > - "Sec-WebSocket-Origin: %s\r\n"
> > - "Sec-WebSocket-Protocol: %s\r\n"
> > - "Sec-WebSocket-Location: %s\r\n"
> > - "\r\n%s" % (
> > - environ.get('HTTP_ORIGIN'),
> > - environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL',
> 'default'),
> > - location,
> > - response))
> > - else: #pragma NO COVER
> > - raise ValueError("Unknown WebSocket protocol version.")
> > - sock.sendall(handshake_reply)
> > - return WebSocket(sock, environ, self.protocol_version)
> > -
> > - def _handle_hybi_request(self, environ):
> > - sock = environ['eventlet.input'].get_socket()
> > - hybi_version = environ['HTTP_SEC_WEBSOCKET_VERSION']
> > - if hybi_version not in ('8', '13', ):
> > - raise BadRequest(status='426 Upgrade Required',
> > - headers=[('Sec-WebSocket-Version', '8,
> 13')])
> > - self.protocol_version = int(hybi_version)
> > - if 'HTTP_SEC_WEBSOCKET_KEY' not in environ:
> > - # That's bad.
> > - raise BadRequest()
> > - origin = environ.get(
> > - 'HTTP_ORIGIN',
> > - (environ.get('HTTP_SEC_WEBSOCKET_ORIGIN', '')
> > - if self.protocol_version <= 8 else ''))
> > - if self.origin_checker is not None:
> > - if not self.origin_checker(environ.get('HTTP_HOST'),
> origin):
> > - raise BadRequest(status='403 Forbidden')
> > - protocols = environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', None)
> > - negotiated_protocol = None
> > - if protocols:
> > - for p in (i.strip() for i in protocols.split(',')):
> > - if p in self.supported_protocols:
> > - negotiated_protocol = p
> > - break
> > - #extensions = environ.get('HTTP_SEC_WEBSOCKET_EXTENSIONS', None)
> > - #if extensions:
> > - # extensions = [i.strip() for i in extensions.split(',')]
> > -
> > - key = environ['HTTP_SEC_WEBSOCKET_KEY']
> > - response = base64.b64encode(sha1(key + PROTOCOL_GUID).digest())
> > - handshake_reply = ["HTTP/1.1 101 Switching Protocols",
> > - "Upgrade: websocket",
> > - "Connection: Upgrade",
> > - "Sec-WebSocket-Accept: %s" % (response, )]
> > - if negotiated_protocol:
> > - handshake_reply.append("Sec-WebSocket-Protocol: %s"
> > - % (negotiated_protocol, ))
> > - sock.sendall('\r\n'.join(handshake_reply) + '\r\n\r\n')
> > - return RFC6455WebSocket(sock, environ, self.protocol_version,
> > - protocol=negotiated_protocol)
> > -
> > - def _extract_number(self, value):
> > - """
> > - Utility function which, given a string like 'g98sd 5[]221@1',
> will
> > - return 9852211. Used to parse the Sec-WebSocket-Key headers.
> > - """
> > - out = ""
> > - spaces = 0
> > - for char in value:
> > - if char in string.digits:
> > - out += char
> > - elif char == " ":
> > - spaces += 1
> > - return int(out) / spaces
> > -
> > -class WebSocket(object):
> > - """A websocket object that handles the details of
> > - serialization/deserialization to the socket.
> > -
> > - The primary way to interact with a :class:`WebSocket` object is to
> > - call :meth:`send` and :meth:`wait` in order to pass messages back
> > - and forth with the browser. Also available are the following
> > - properties:
> > -
> > - path
> > - The path value of the request. This is the same as the WSGI
> PATH_INFO variable, but more convenient.
> > - protocol
> > - The value of the Websocket-Protocol header.
> > - origin
> > - The value of the 'Origin' header.
> > - environ
> > - The full WSGI environment for this request.
> > -
> > - """
> > - def __init__(self, sock, environ, version=76):
> > - """
> > - :param socket: The eventlet socket
> > - :type socket: :class:`eventlet.greenio.GreenSocket`
> > - :param environ: The wsgi environment
> > - :param version: The WebSocket spec version to follow (default
> is 76)
> > - """
> > - 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.version = version
> > - self.websocket_closed = False
> > - self._buf = ""
> > - self._msgs = collections.deque()
> > - self._sendlock = semaphore.Semaphore()
> > -
> > - @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.
> > -
> > - 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:
> > - frame_type = ord(buf[0])
> > - if frame_type == 0:
> > - # Normal message.
> > - 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:]
> > - elif frame_type == 255:
> > - # Closing handshake.
> > - assert ord(buf[1]) == 0, "Unexpected closing handshake:
> %r" % buf
> > - self.websocket_closed = True
> > - break
> > - else:
> > - raise ValueError("Don't understand how to parse this
> type of message: %r" % buf)
> > - self._buf = buf
> > - return msgs
> > -
> > - def send(self, message):
> > - """Send a message to the browser.
> > -
> > - *message* should be convertable to a string; unicode objects
> should be
> > - encodable as utf-8. Raises socket.error with errno of 32
> > - (broken pipe) if the socket has already been closed by 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
> > - self._sendlock.acquire()
> > - try:
> > - self.socket.sendall(packed)
> > - finally:
> > - self._sendlock.release()
> > -
> > - def wait(self):
> > - """Waits for and deserializes messages.
> > -
> > - Returns a single message; the oldest not yet processed. If the
> client
> > - has already closed the connection, returns None. This is
> different
> > - from normal socket behavior because the empty string is a valid
> > - websocket message."""
> > - while not self._msgs:
> > - # Websocket might be closed already.
> > - if self.websocket_closed:
> > - return None
> > - # no parsed messages, must mean buf needs more data
> > - delta = self.socket.recv(8096)
> > - if delta == '':
> > - return None
> > - self._buf += delta
> > - msgs = self._parse_messages()
> > - self._msgs.extend(msgs)
> > - return self._msgs.popleft()
> > -
> > - def _send_closing_frame(self, ignore_send_errors=False):
> > - """Sends the closing frame to the client, if required."""
> > - if self.version == 76 and not self.websocket_closed:
> > - try:
> > - self.socket.sendall("\xff\x00")
> > - except SocketError:
> > - # Sometimes, like when the remote side cuts off the
> connection,
> > - # we don't care about this.
> > - if not ignore_send_errors: #pragma NO COVER
> > - raise
> > - self.websocket_closed = True
> > -
> > - def close(self):
> > - """Forcibly close the websocket; generally it is preferable to
> > - return from the handler method."""
> > - self._send_closing_frame()
> > - self.socket.shutdown(True)
> > - self.socket.close()
> > -
> > -
> > -class ConnectionClosedError(Exception):
> > - pass
> > -
> > -
> > -class FailedConnectionError(Exception):
> > - def __init__(self, status, message):
> > - super(FailedConnectionError, self).__init__(status, message)
> > - self.message = message
> > - self.status = status
> > -
> > -
> > -class ProtocolError(ValueError):
> > - pass
> > -
> > -
> > -class RFC6455WebSocket(WebSocket):
> > - def __init__(self, sock, environ, version=13, protocol=None,
> client=False):
> > - super(RFC6455WebSocket, self).__init__(sock, environ, version)
> > - self.iterator = self._iter_frames()
> > - self.client = client
> > - self.protocol = protocol
> > -
> > - class UTF8Decoder(object):
> > - def __init__(self):
> > - if utf8validator:
> > - self.validator = utf8validator.Utf8Validator()
> > - else:
> > - self.validator = None
> > - decoderclass = codecs.getincrementaldecoder('utf8')
> > - self.decoder = decoderclass()
> > -
> > - def reset(self):
> > - if self.validator:
> > - self.validator.reset()
> > - self.decoder.reset()
> > -
> > - def decode(self, data, final=False):
> > - if self.validator:
> > - valid, eocp, c_i, t_i = self.validator.validate(data)
> > - if not valid:
> > - raise ValueError('Data is not valid unicode')
> > - return self.decoder.decode(data, final)
> > -
> > - def _get_bytes(self, numbytes):
> > - data = ''
> > - while len(data) < numbytes:
> > - d = self.socket.recv(numbytes - len(data))
> > - if not d:
> > - raise ConnectionClosedError()
> > - data = data + d
> > - return data
> > -
> > - class Message(object):
> > - def __init__(self, opcode, decoder=None):
> > - self.decoder = decoder
> > - self.data = []
> > - self.finished = False
> > - self.opcode = opcode
> > -
> > - def push(self, data, final=False):
> > - if self.decoder:
> > - data = self.decoder.decode(data, final=final)
> > - self.finished = final
> > - self.data.append(data)
> > -
> > - def getvalue(self):
> > - return ''.join(self.data)
> > -
> > - @staticmethod
> > - def _apply_mask(data, mask, length=None, offset=0):
> > - if length is None:
> > - length = len(data)
> > - cnt = range(length)
> > - return ''.join(chr(ord(data[i]) ^ mask[(offset + i) % 4]) for i
> in cnt)
> > -
> > - def _handle_control_frame(self, opcode, data):
> > - if opcode == 8: # connection close
> > - if not data:
> > - status = 1000
> > - elif len(data) > 1:
> > - status = struct.unpack_from('!H', data)[0]
> > - if not status or status not in VALID_CLOSE_STATUS:
> > - raise FailedConnectionError(
> > - 1002,
> > - "Unexpected close status code.")
> > - try:
> > - data = self.UTF8Decoder().decode(data[2:], True)
> > - except (UnicodeDecodeError, ValueError):
> > - raise FailedConnectionError(
> > - 1002,
> > - "Close message data should be valid UTF-8.")
> > - else:
> > - status = 1002
> > - self.close(close_data=(status, ''))
> > - raise ConnectionClosedError()
> > - elif opcode == 9: # ping
> > - self.send(data, control_code=0xA)
> > - elif opcode == 0xA: # pong
> > - pass
> > - else:
> > - raise FailedConnectionError(
> > - 1002, "Unknown control frame received.")
> > -
> > - def _iter_frames(self):
> > - fragmented_message = None
> > - try:
> > - while True:
> > - message = self._recv_frame(message=fragmented_message)
> > - if message.opcode & 8:
> > - self._handle_control_frame(
> > - message.opcode, message.getvalue())
> > - continue
> > - if fragmented_message and message is not
> fragmented_message:
> > - raise RuntimeError('Unexpected message change.')
> > - fragmented_message = message
> > - if message.finished:
> > - data = fragmented_message.getvalue()
> > - fragmented_message = None
> > - yield data
> > - except FailedConnectionError:
> > - exc_typ, exc_val, exc_tb = sys.exc_info()
> > - self.close(close_data=(exc_val.status, exc_val.message))
> > - except ConnectionClosedError:
> > - return
> > - except Exception:
> > - self.close(close_data=(1011, 'Internal Server Error'))
> > - raise
> > -
> > - def _recv_frame(self, message=None):
> > - recv = self._get_bytes
> > - header = recv(2)
> > - a, b = struct.unpack('!BB', header)
> > - finished = a >> 7 == 1
> > - rsv123 = a >> 4 & 7
> > - if rsv123:
> > - # must be zero
> > - raise FailedConnectionError(
> > - 1002,
> > - "RSV1, RSV2, RSV3: MUST be 0 unless an extension is"
> > - " negotiated that defines meanings for non-zero
> values.")
> > - opcode = a & 15
> > - if opcode not in (0, 1, 2, 8, 9, 0xA):
> > - raise FailedConnectionError(1002, "Unknown opcode
> received.")
> > - masked = b & 128 == 128
> > - if not masked and not self.client:
> > - raise FailedConnectionError(1002, "A client MUST mask all
> frames"
> > - " that it sends to the server")
> > - length = b & 127
> > - if opcode & 8:
> > - if not finished:
> > - raise FailedConnectionError(1002, "Control frames must
> not"
> > - " be fragmented.")
> > - if length > 125:
> > - raise FailedConnectionError(
> > - 1002,
> > - "All control frames MUST have a payload length of
> 125"
> > - " bytes or less")
> > - elif opcode and message:
> > - raise FailedConnectionError(
> > - 1002,
> > - "Received a non-continuation opcode within"
> > - " fragmented message.")
> > - elif not opcode and not message:
> > - raise FailedConnectionError(
> > - 1002,
> > - "Received continuation opcode with no previous"
> > - " fragments received.")
> > - if length == 126:
> > - length = struct.unpack('!H', recv(2))[0]
> > - elif length == 127:
> > - length = struct.unpack('!Q', recv(8))[0]
> > - if masked:
> > - mask = struct.unpack('!BBBB', recv(4))
> > - received = 0
> > - if not message or opcode & 8:
> > - decoder = self.UTF8Decoder() if opcode == 1 else None
> > - message = self.Message(opcode, decoder=decoder)
> > - if not length:
> > - message.push('', final=finished)
> > - else:
> > - while received < length:
> > - d = self.socket.recv(length - received)
> > - if not d:
> > - raise ConnectionClosedError()
> > - dlen = len(d)
> > - if masked:
> > - d = self._apply_mask(d, mask, length=dlen,
> offset=received)
> > - received = received + dlen
> > - try:
> > - message.push(d, final=finished)
> > - except (UnicodeDecodeError, ValueError):
> > - raise FailedConnectionError(
> > - 1007, "Text data must be valid utf-8")
> > - return message
> > -
> > - @staticmethod
> > - def _pack_message(message, masked=False,
> > - continuation=False, final=True,
> control_code=None):
> > - is_text = False
> > - if isinstance(message, unicode):
> > - message = message.encode('utf-8')
> > - is_text = True
> > - length = len(message)
> > - if not length:
> > - # no point masking empty data
> > - masked = False
> > - if control_code:
> > - if control_code not in (8, 9, 0xA):
> > - raise ProtocolError('Unknown control opcode.')
> > - if continuation or not final:
> > - raise ProtocolError('Control frame cannot be a
> fragment.')
> > - if length > 125:
> > - raise ProtocolError('Control frame data too large
> (>125).')
> > - header = struct.pack('!B', control_code | 1 << 7)
> > - else:
> > - opcode = 0 if continuation else (1 if is_text else 2)
> > - header = struct.pack('!B', opcode | (1 << 7 if final else
> 0))
> > - lengthdata = 1 << 7 if masked else 0
> > - if length > 65535:
> > - lengthdata = struct.pack('!BQ', lengthdata | 127, length)
> > - elif length > 125:
> > - lengthdata = struct.pack('!BH', lengthdata | 126, length)
> > - else:
> > - lengthdata = struct.pack('!B', lengthdata | length)
> > - if masked:
> > - # NOTE: RFC6455 states:
> > - # A server MUST NOT mask any frames that it sends to the
> client
> > - rand = Random(time.time())
> > - mask = map(rand.getrandbits, (8, ) * 4)
> > - message = RFC6455WebSocket._apply_mask(message, mask,
> length)
> > - maskdata = struct.pack('!BBBB', *mask)
> > - else:
> > - maskdata = ''
> > - return ''.join((header, lengthdata, maskdata, message))
> > -
> > - def wait(self):
> > - for i in self.iterator:
> > - return i
> > -
> > - def _send(self, frame):
> > - self._sendlock.acquire()
> > - try:
> > - self.socket.sendall(frame)
> > - finally:
> > - self._sendlock.release()
> > -
> > - def send(self, message, **kw):
> > - kw['masked'] = self.client
> > - payload = self._pack_message(message, **kw)
> > - self._send(payload)
> > -
> > - def _send_closing_frame(self, ignore_send_errors=False,
> close_data=None):
> > - if self.version in (8, 13) and not self.websocket_closed:
> > - if close_data is not None:
> > - status, msg = close_data
> > - if isinstance(msg, unicode):
> > - msg = msg.encode('utf-8')
> > - data = struct.pack('!H', status) + msg
> > - else:
> > - data = ''
> > - try:
> > - self.send(data, control_code=8)
> > - except SocketError:
> > - # Sometimes, like when the remote side cuts off the
> connection,
> > - # we don't care about this.
> > - if not ignore_send_errors: # pragma NO COVER
> > - raise
> > - self.websocket_closed = True
> > -
> > - def close(self, close_data=None):
> > - """Forcibly close the websocket; generally it is preferable to
> > - return from the handler method."""
> > - self._send_closing_frame(close_data=close_data)
> > - self.socket.shutdown(socket.SHUT_WR)
> > - self.socket.close()
> > diff --git a/ryu/lib/hub.py b/ryu/lib/hub.py
> > index 836b924..5621147 100644
> > --- a/ryu/lib/hub.py
> > +++ b/ryu/lib/hub.py
> > @@ -32,7 +32,7 @@ if HUB_TYPE == 'eventlet':
> > import eventlet.semaphore
> > import eventlet.timeout
> > import eventlet.wsgi
> > - from ryu.contrib._eventlet import websocket
> > + from eventlet import websocket
> > import greenlet
> > import ssl
> > import socket
> > diff --git a/tools/pip-requires b/tools/pip-requires
> > index 5753ce5..9e2bf28 100644
> > --- a/tools/pip-requires
> > +++ b/tools/pip-requires
> > @@ -1,4 +1,4 @@
> > -eventlet
> > +eventlet>=0.15
> > msgpack-python>=0.3.0 # RPC library, BGP speaker(net_cntl)
> > netaddr
> > oslo.config>=1.2.0
> > --
> > 2.3.2 (Apple Git-55)
> >
> >
> >
> ------------------------------------------------------------------------------
> > BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
> > Develop your own process in accordance with the BPMN 2 standard
> > Learn Process modeling best practices with Bonita BPM through live
> exercises
> > http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
> event?utm_
> > source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
> > _______________________________________________
> > Ryu-devel mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/ryu-devel
>
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel