Hi Fujita-San, Kobayashi-San, This page might be helpful. https://launchpad.net/ubuntu/+source/python-eventlet
According to this page, python-eventlet version is still 0.13 in Ubuntu 14.04 now. Ubuntu 15.04 will update python-eventlet to version 0.16, though... Thanks, Iwase On 2015年04月17日 10:34, Satoshi KOBAYASHI wrote: > 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] > <mailto:[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] > <mailto:[email protected]>> wrote: > > > Signed-off-by: Satoshi Kobayashi <[email protected] > <mailto:[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] <mailto:[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 > ------------------------------------------------------------------------------ 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
