commit
0cf35b7b87
22 changed files with 749 additions and 337 deletions
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.12.24" provider-name="croneter">
|
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.12.25" provider-name="croneter">
|
||||||
<requires>
|
<requires>
|
||||||
<import addon="xbmc.python" version="2.1.0"/>
|
<import addon="xbmc.python" version="2.1.0"/>
|
||||||
<import addon="script.module.requests" version="2.9.1" />
|
<import addon="script.module.requests" version="2.9.1" />
|
||||||
|
@ -88,7 +88,10 @@
|
||||||
<summary lang="ko_KR">Plex를 Kodi에 기본 통합</summary>
|
<summary lang="ko_KR">Plex를 Kodi에 기본 통합</summary>
|
||||||
<description lang="ko_KR">Kodi를 Plex Media Server에 연결합니다. 이 플러그인은 Plex로 모든 비디오를 관리하고 Kodi로는 관리하지 않는다고 가정합니다. Kodi 비디오 및 음악 데이터베이스에 이미 저장된 데이터가 손실 될 수 있습니다 (이 플러그인이 직접 변경하므로). 자신의 책임하에 사용하십시오!</description>
|
<description lang="ko_KR">Kodi를 Plex Media Server에 연결합니다. 이 플러그인은 Plex로 모든 비디오를 관리하고 Kodi로는 관리하지 않는다고 가정합니다. Kodi 비디오 및 음악 데이터베이스에 이미 저장된 데이터가 손실 될 수 있습니다 (이 플러그인이 직접 변경하므로). 자신의 책임하에 사용하십시오!</description>
|
||||||
<disclaimer lang="ko_KR">자신의 책임하에 사용</disclaimer>
|
<disclaimer lang="ko_KR">자신의 책임하에 사용</disclaimer>
|
||||||
<news>version 2.12.24:
|
<news>version 2.12.25:
|
||||||
|
- Update websocket client to 0.59.0. Fix threading issues and AttributeErrors
|
||||||
|
|
||||||
|
version 2.12.24:
|
||||||
- version 2.12.23 for everyone
|
- version 2.12.23 for everyone
|
||||||
|
|
||||||
version 2.12.23 (beta only):
|
version 2.12.23 (beta only):
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
version 2.12.25:
|
||||||
|
- Update websocket client to 0.59.0. Fix threading issues and AttributeErrors
|
||||||
|
|
||||||
version 2.12.24:
|
version 2.12.24:
|
||||||
- version 2.12.23 for everyone
|
- version 2.12.23 for everyone
|
||||||
|
|
||||||
|
|
|
@ -25,4 +25,4 @@ from ._exceptions import *
|
||||||
from ._logging import *
|
from ._logging import *
|
||||||
from ._socket import *
|
from ._socket import *
|
||||||
|
|
||||||
__version__ = "0.58.0"
|
__version__ = "0.59.0"
|
||||||
|
|
|
@ -228,9 +228,9 @@ class ABNF(object):
|
||||||
if length >= ABNF.LENGTH_63:
|
if length >= ABNF.LENGTH_63:
|
||||||
raise ValueError("data is too long")
|
raise ValueError("data is too long")
|
||||||
|
|
||||||
frame_header = chr(self.fin << 7
|
frame_header = chr(self.fin << 7 |
|
||||||
| self.rsv1 << 6 | self.rsv2 << 5 | self.rsv3 << 4
|
self.rsv1 << 6 | self.rsv2 << 5 | self.rsv3 << 4 |
|
||||||
| self.opcode)
|
self.opcode)
|
||||||
if length < ABNF.LENGTH_7:
|
if length < ABNF.LENGTH_7:
|
||||||
frame_header += chr(self.mask << 7 | length)
|
frame_header += chr(self.mask << 7 | length)
|
||||||
frame_header = six.b(frame_header)
|
frame_header = six.b(frame_header)
|
||||||
|
|
|
@ -39,6 +39,7 @@ from . import _logging
|
||||||
|
|
||||||
__all__ = ["WebSocketApp"]
|
__all__ = ["WebSocketApp"]
|
||||||
|
|
||||||
|
|
||||||
class Dispatcher:
|
class Dispatcher:
|
||||||
"""
|
"""
|
||||||
Dispatcher
|
Dispatcher
|
||||||
|
@ -56,6 +57,7 @@ class Dispatcher:
|
||||||
break
|
break
|
||||||
check_callback()
|
check_callback()
|
||||||
|
|
||||||
|
|
||||||
class SSLDispatcher:
|
class SSLDispatcher:
|
||||||
"""
|
"""
|
||||||
SSLDispatcher
|
SSLDispatcher
|
||||||
|
@ -190,23 +192,25 @@ class WebSocketApp(object):
|
||||||
self.sock.close(**kwargs)
|
self.sock.close(**kwargs)
|
||||||
self.sock = None
|
self.sock = None
|
||||||
|
|
||||||
def _send_ping(self, interval, event):
|
def _send_ping(self, interval, event, payload):
|
||||||
while not event.wait(interval):
|
while not event.wait(interval):
|
||||||
self.last_ping_tm = time.time()
|
self.last_ping_tm = time.time()
|
||||||
if self.sock:
|
if self.sock:
|
||||||
try:
|
try:
|
||||||
self.sock.ping()
|
self.sock.ping(payload)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_logging.warning("send_ping routine terminated: {}".format(ex))
|
_logging.warning("send_ping routine terminated: {}".format(ex))
|
||||||
break
|
break
|
||||||
|
|
||||||
def run_forever(self, sockopt=None, sslopt=None,
|
def run_forever(self, sockopt=None, sslopt=None,
|
||||||
ping_interval=0, ping_timeout=None,
|
ping_interval=0, ping_timeout=None,
|
||||||
|
ping_payload="",
|
||||||
http_proxy_host=None, http_proxy_port=None,
|
http_proxy_host=None, http_proxy_port=None,
|
||||||
http_no_proxy=None, http_proxy_auth=None,
|
http_no_proxy=None, http_proxy_auth=None,
|
||||||
skip_utf8_validation=False,
|
skip_utf8_validation=False,
|
||||||
host=None, origin=None, dispatcher=None,
|
host=None, origin=None, dispatcher=None,
|
||||||
suppress_origin=False, proxy_type=None):
|
suppress_origin=False, proxy_type=None,
|
||||||
|
enable_multithread=True):
|
||||||
"""
|
"""
|
||||||
Run event loop for WebSocket framework.
|
Run event loop for WebSocket framework.
|
||||||
|
|
||||||
|
@ -226,6 +230,8 @@ class WebSocketApp(object):
|
||||||
if set to 0, not send automatically.
|
if set to 0, not send automatically.
|
||||||
ping_timeout: int or float
|
ping_timeout: int or float
|
||||||
timeout (in seconds) if the pong message is not received.
|
timeout (in seconds) if the pong message is not received.
|
||||||
|
ping_payload: str
|
||||||
|
payload message to send with each ping.
|
||||||
http_proxy_host: <type>
|
http_proxy_host: <type>
|
||||||
http proxy host name.
|
http proxy host name.
|
||||||
http_proxy_port: <type>
|
http_proxy_port: <type>
|
||||||
|
@ -287,7 +293,7 @@ class WebSocketApp(object):
|
||||||
self.get_mask_key, sockopt=sockopt, sslopt=sslopt,
|
self.get_mask_key, sockopt=sockopt, sslopt=sslopt,
|
||||||
fire_cont_frame=self.on_cont_message is not None,
|
fire_cont_frame=self.on_cont_message is not None,
|
||||||
skip_utf8_validation=skip_utf8_validation,
|
skip_utf8_validation=skip_utf8_validation,
|
||||||
enable_multithread=True if ping_interval else False)
|
enable_multithread=enable_multithread)
|
||||||
self.sock.settimeout(getdefaulttimeout())
|
self.sock.settimeout(getdefaulttimeout())
|
||||||
self.sock.connect(
|
self.sock.connect(
|
||||||
self.url, header=self.header, cookie=self.cookie,
|
self.url, header=self.header, cookie=self.cookie,
|
||||||
|
@ -304,8 +310,8 @@ class WebSocketApp(object):
|
||||||
if ping_interval:
|
if ping_interval:
|
||||||
event = threading.Event()
|
event = threading.Event()
|
||||||
thread = threading.Thread(
|
thread = threading.Thread(
|
||||||
target=self._send_ping, args=(ping_interval, event))
|
target=self._send_ping, args=(ping_interval, event, ping_payload))
|
||||||
thread.setDaemon(True)
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def read():
|
def read():
|
||||||
|
@ -340,9 +346,9 @@ class WebSocketApp(object):
|
||||||
has_pong_not_arrived_after_last_ping = self.last_pong_tm - self.last_ping_tm < 0
|
has_pong_not_arrived_after_last_ping = self.last_pong_tm - self.last_ping_tm < 0
|
||||||
has_pong_arrived_too_late = self.last_pong_tm - self.last_ping_tm > ping_timeout
|
has_pong_arrived_too_late = self.last_pong_tm - self.last_ping_tm > ping_timeout
|
||||||
|
|
||||||
if (self.last_ping_tm
|
if (self.last_ping_tm and
|
||||||
and has_timeout_expired
|
has_timeout_expired and
|
||||||
and (has_pong_not_arrived_after_last_ping or has_pong_arrived_too_late)):
|
(has_pong_not_arrived_after_last_ping or has_pong_arrived_too_late)):
|
||||||
raise WebSocketTimeoutException("ping/pong timed out")
|
raise WebSocketTimeoutException("ping/pong timed out")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -72,5 +72,7 @@ class SimpleCookieJar(object):
|
||||||
if host.endswith(domain) or host == domain[1:]:
|
if host.endswith(domain) or host == domain[1:]:
|
||||||
cookies.append(self.jar.get(domain))
|
cookies.append(self.jar.get(domain))
|
||||||
|
|
||||||
return "; ".join(filter(None, ["%s=%s" % (k, v.value) for cookie in filter(None, sorted(cookies)) for k, v in
|
return "; ".join(filter(
|
||||||
sorted(cookie.items())]))
|
None, sorted(
|
||||||
|
["%s=%s" % (k, v.value) for cookie in filter(None, cookies) for k, v in cookie.items()]
|
||||||
|
)))
|
||||||
|
|
|
@ -44,6 +44,7 @@ from ._utils import *
|
||||||
|
|
||||||
__all__ = ['WebSocket', 'create_connection']
|
__all__ = ['WebSocket', 'create_connection']
|
||||||
|
|
||||||
|
|
||||||
class WebSocket(object):
|
class WebSocket(object):
|
||||||
"""
|
"""
|
||||||
Low level WebSocket interface.
|
Low level WebSocket interface.
|
||||||
|
@ -466,8 +467,7 @@ class WebSocket(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.connected = False
|
self.connected = False
|
||||||
self.send(struct.pack('!H', status) +
|
self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE)
|
||||||
reason, ABNF.OPCODE_CLOSE)
|
|
||||||
sock_timeout = self.sock.gettimeout()
|
sock_timeout = self.sock.gettimeout()
|
||||||
self.sock.settimeout(timeout)
|
self.sock.settimeout(timeout)
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
|
@ -23,6 +23,7 @@ Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class WebSocketException(Exception):
|
class WebSocketException(Exception):
|
||||||
"""
|
"""
|
||||||
WebSocket exception class.
|
WebSocket exception class.
|
||||||
|
|
|
@ -93,6 +93,7 @@ def _pack_hostname(hostname):
|
||||||
|
|
||||||
return hostname
|
return hostname
|
||||||
|
|
||||||
|
|
||||||
def _get_handshake_headers(resource, host, port, options):
|
def _get_handshake_headers(resource, host, port, options):
|
||||||
headers = [
|
headers = [
|
||||||
"GET %s HTTP/1.1" % resource,
|
"GET %s HTTP/1.1" % resource,
|
||||||
|
@ -116,16 +117,16 @@ def _get_handshake_headers(resource, host, port, options):
|
||||||
key = _create_sec_websocket_key()
|
key = _create_sec_websocket_key()
|
||||||
|
|
||||||
# Append Sec-WebSocket-Key & Sec-WebSocket-Version if not manually specified
|
# Append Sec-WebSocket-Key & Sec-WebSocket-Version if not manually specified
|
||||||
if not 'header' in options or 'Sec-WebSocket-Key' not in options['header']:
|
if 'header' not in options or 'Sec-WebSocket-Key' not in options['header']:
|
||||||
key = _create_sec_websocket_key()
|
key = _create_sec_websocket_key()
|
||||||
headers.append("Sec-WebSocket-Key: %s" % key)
|
headers.append("Sec-WebSocket-Key: %s" % key)
|
||||||
else:
|
else:
|
||||||
key = options['header']['Sec-WebSocket-Key']
|
key = options['header']['Sec-WebSocket-Key']
|
||||||
|
|
||||||
if not 'header' in options or 'Sec-WebSocket-Version' not in options['header']:
|
if 'header' not in options or 'Sec-WebSocket-Version' not in options['header']:
|
||||||
headers.append("Sec-WebSocket-Version: %s" % VERSION)
|
headers.append("Sec-WebSocket-Version: %s" % VERSION)
|
||||||
|
|
||||||
if not 'connection' in options or options['connection'] is None:
|
if 'connection' not in options or options['connection'] is None:
|
||||||
headers.append('Connection: Upgrade')
|
headers.append('Connection: Upgrade')
|
||||||
else:
|
else:
|
||||||
headers.append(options['connection'])
|
headers.append(options['connection'])
|
||||||
|
@ -177,8 +178,8 @@ def _validate(headers, key, subprotocols):
|
||||||
r = headers.get(k, None)
|
r = headers.get(k, None)
|
||||||
if not r:
|
if not r:
|
||||||
return False, None
|
return False, None
|
||||||
r = r.lower()
|
r = [x.strip().lower() for x in r.split(',')]
|
||||||
if v != r:
|
if v not in r:
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
if subprotocols:
|
if subprotocols:
|
||||||
|
|
|
@ -47,6 +47,7 @@ except:
|
||||||
pass
|
pass
|
||||||
HAS_PYSOCKS = False
|
HAS_PYSOCKS = False
|
||||||
|
|
||||||
|
|
||||||
class proxy_info(object):
|
class proxy_info(object):
|
||||||
|
|
||||||
def __init__(self, **options):
|
def __init__(self, **options):
|
||||||
|
@ -273,7 +274,9 @@ def _ssl_socket(sock, user_sslopt, hostname):
|
||||||
|
|
||||||
def _tunnel(sock, host, port, auth):
|
def _tunnel(sock, host, port, auth):
|
||||||
debug("Connecting proxy...")
|
debug("Connecting proxy...")
|
||||||
connect_header = "CONNECT %s:%d HTTP/1.0\r\n" % (host, port)
|
connect_header = "CONNECT %s:%d HTTP/1.1\r\n" % (host, port)
|
||||||
|
connect_header += "Host: %s:%d\r\n" % (host, port)
|
||||||
|
|
||||||
# TODO: support digest auth.
|
# TODO: support digest auth.
|
||||||
if auth and auth[0]:
|
if auth and auth[0]:
|
||||||
auth_str = auth[0]
|
auth_str = auth[0]
|
||||||
|
@ -320,6 +323,9 @@ def read_headers(sock):
|
||||||
kv = line.split(":", 1)
|
kv = line.split(":", 1)
|
||||||
if len(kv) == 2:
|
if len(kv) == 2:
|
||||||
key, value = kv
|
key, value = kv
|
||||||
|
if key.lower() == "set-cookie" and headers.get("set-cookie"):
|
||||||
|
headers["set-cookie"] = headers.get("set-cookie") + "; " + value.strip()
|
||||||
|
else:
|
||||||
headers[key.lower()] = value.strip()
|
headers[key.lower()] = value.strip()
|
||||||
else:
|
else:
|
||||||
raise WebSocketException("Invalid header")
|
raise WebSocketException("Invalid header")
|
||||||
|
|
|
@ -55,6 +55,7 @@ def enableTrace(traceable, handler = logging.StreamHandler()):
|
||||||
_logger.addHandler(handler)
|
_logger.addHandler(handler)
|
||||||
_logger.setLevel(logging.DEBUG)
|
_logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
def dump(title, message):
|
def dump(title, message):
|
||||||
if _traceEnabled:
|
if _traceEnabled:
|
||||||
_logger.debug("--- " + title + " ---")
|
_logger.debug("--- " + title + " ---")
|
||||||
|
@ -86,5 +87,6 @@ def isEnabledForError():
|
||||||
def isEnabledForDebug():
|
def isEnabledForDebug():
|
||||||
return _logger.isEnabledFor(logging.DEBUG)
|
return _logger.isEnabledFor(logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
def isEnabledForTrace():
|
def isEnabledForTrace():
|
||||||
return _traceEnabled
|
return _traceEnabled
|
||||||
|
|
|
@ -27,7 +27,6 @@ import select
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
import six
|
import six
|
||||||
import sys
|
|
||||||
|
|
||||||
from ._exceptions import *
|
from ._exceptions import *
|
||||||
from ._ssl_compat import *
|
from ._ssl_compat import *
|
||||||
|
|
|
@ -48,6 +48,6 @@ except ImportError:
|
||||||
class SSLWantWriteError(Exception):
|
class SSLWantWriteError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
ssl = lambda: None
|
ssl = None
|
||||||
|
|
||||||
HAVE_SSL = False
|
HAVE_SSL = False
|
||||||
|
|
|
@ -47,7 +47,7 @@ def parse_url(url):
|
||||||
|
|
||||||
scheme, url = url.split(":", 1)
|
scheme, url = url.split(":", 1)
|
||||||
|
|
||||||
parsed = urlparse(url, scheme="ws")
|
parsed = urlparse(url, scheme="http")
|
||||||
if parsed.hostname:
|
if parsed.hostname:
|
||||||
hostname = parsed.hostname
|
hostname = parsed.hostname
|
||||||
else:
|
else:
|
||||||
|
@ -99,10 +99,12 @@ def _is_subnet_address(hostname):
|
||||||
|
|
||||||
|
|
||||||
def _is_address_in_network(ip, net):
|
def _is_address_in_network(ip, net):
|
||||||
ipaddr = struct.unpack('I', socket.inet_aton(ip))[0]
|
ipaddr = struct.unpack('!I', socket.inet_aton(ip))[0]
|
||||||
netaddr, bits = net.split('/')
|
netaddr, netmask = net.split('/')
|
||||||
netmask = struct.unpack('I', socket.inet_aton(netaddr))[0] & ((2 << int(bits) - 1) - 1)
|
netaddr = struct.unpack('!I', socket.inet_aton(netaddr))[0]
|
||||||
return ipaddr & netmask == netmask
|
|
||||||
|
netmask = (0xFFFFFFFF << (32 - int(netmask))) & 0xFFFFFFFF
|
||||||
|
return ipaddr & netmask == netaddr
|
||||||
|
|
||||||
|
|
||||||
def _is_no_proxy_host(hostname, no_proxy):
|
def _is_no_proxy_host(hostname, no_proxy):
|
||||||
|
@ -113,11 +115,15 @@ def _is_no_proxy_host(hostname, no_proxy):
|
||||||
if not no_proxy:
|
if not no_proxy:
|
||||||
no_proxy = DEFAULT_NO_PROXY_HOST
|
no_proxy = DEFAULT_NO_PROXY_HOST
|
||||||
|
|
||||||
|
if '*' in no_proxy:
|
||||||
|
return True
|
||||||
if hostname in no_proxy:
|
if hostname in no_proxy:
|
||||||
return True
|
return True
|
||||||
elif _is_ip_address(hostname):
|
if _is_ip_address(hostname):
|
||||||
return any([_is_address_in_network(hostname, subnet) for subnet in no_proxy if _is_subnet_address(subnet)])
|
return any([_is_address_in_network(hostname, subnet) for subnet in no_proxy if _is_subnet_address(subnet)])
|
||||||
|
for domain in [domain for domain in no_proxy if domain.startswith('.')]:
|
||||||
|
if hostname.endswith(domain):
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
6
resources/lib/websocket/tests/data/header03.txt
Normal file
6
resources/lib/websocket/tests/data/header03.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
HTTP/1.1 101 WebSocket Protocol Handshake
|
||||||
|
Connection: Upgrade, Keep-Alive
|
||||||
|
Upgrade: WebSocket
|
||||||
|
Sec-WebSocket-Accept: Kxep+hNu9n51529fGidYu7a3wO0=
|
||||||
|
some_header: something
|
||||||
|
|
77
resources/lib/websocket/tests/test_abnf.py
Normal file
77
resources/lib/websocket/tests/test_abnf.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
websocket - WebSocket client library for Python
|
||||||
|
|
||||||
|
Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import websocket as ws
|
||||||
|
from websocket._abnf import *
|
||||||
|
import sys
|
||||||
|
sys.path[0:0] = [""]
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||||
|
import unittest2 as unittest
|
||||||
|
else:
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class ABNFTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def testInit(self):
|
||||||
|
a = ABNF(0,0,0,0, opcode=ABNF.OPCODE_PING)
|
||||||
|
self.assertEqual(a.fin, 0)
|
||||||
|
self.assertEqual(a.rsv1, 0)
|
||||||
|
self.assertEqual(a.rsv2, 0)
|
||||||
|
self.assertEqual(a.rsv3, 0)
|
||||||
|
self.assertEqual(a.opcode, 9)
|
||||||
|
self.assertEqual(a.data, '')
|
||||||
|
a_bad = ABNF(0,1,0,0, opcode=77)
|
||||||
|
self.assertEqual(a_bad.rsv1, 1)
|
||||||
|
self.assertEqual(a_bad.opcode, 77)
|
||||||
|
|
||||||
|
def testValidate(self):
|
||||||
|
a = ABNF(0,0,0,0, opcode=ABNF.OPCODE_PING)
|
||||||
|
self.assertRaises(ws.WebSocketProtocolException, a.validate)
|
||||||
|
a_bad = ABNF(0,1,0,0, opcode=77)
|
||||||
|
self.assertRaises(ws.WebSocketProtocolException, a_bad.validate)
|
||||||
|
a_close = ABNF(0,1,0,0, opcode=ABNF.OPCODE_CLOSE, data="abcdefgh1234567890abcdefgh1234567890abcdefgh1234567890abcdefgh1234567890")
|
||||||
|
self.assertRaises(ws.WebSocketProtocolException, a_close.validate)
|
||||||
|
|
||||||
|
# This caused an error in the Python 2.7 Github Actions build
|
||||||
|
# Uncomment test case when Python 2 support no longer wanted
|
||||||
|
# def testMask(self):
|
||||||
|
# ab = ABNF(0,0,0,0, opcode=ABNF.OPCODE_PING)
|
||||||
|
# bytes_val = bytes("aaaa", 'utf-8')
|
||||||
|
# self.assertEqual(ab._get_masked(bytes_val), bytes_val)
|
||||||
|
|
||||||
|
def testFrameBuffer(self):
|
||||||
|
fb = frame_buffer(0, True)
|
||||||
|
self.assertEqual(fb.recv, 0)
|
||||||
|
self.assertEqual(fb.skip_utf8_validation, True)
|
||||||
|
fb.clear
|
||||||
|
self.assertEqual(fb.header, None)
|
||||||
|
self.assertEqual(fb.length, None)
|
||||||
|
self.assertEqual(fb.mask, None)
|
||||||
|
self.assertEqual(fb.has_mask(), False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
137
resources/lib/websocket/tests/test_app.py
Normal file
137
resources/lib/websocket/tests/test_app.py
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
websocket - WebSocket client library for Python
|
||||||
|
|
||||||
|
Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import websocket as ws
|
||||||
|
import sys
|
||||||
|
sys.path[0:0] = [""]
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ssl
|
||||||
|
except ImportError:
|
||||||
|
HAVE_SSL = False
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||||
|
import unittest2 as unittest
|
||||||
|
else:
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# Skip test to access the internet.
|
||||||
|
TEST_WITH_INTERNET = os.environ.get('TEST_WITH_INTERNET', '0') == '1'
|
||||||
|
TRACEABLE = True
|
||||||
|
|
||||||
|
|
||||||
|
class WebSocketAppTest(unittest.TestCase):
|
||||||
|
|
||||||
|
class NotSetYet(object):
|
||||||
|
""" A marker class for signalling that a value hasn't been set yet.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
ws.enableTrace(TRACEABLE)
|
||||||
|
|
||||||
|
WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet()
|
||||||
|
WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet()
|
||||||
|
WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet()
|
||||||
|
WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet()
|
||||||
|
WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet()
|
||||||
|
|
||||||
|
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||||
|
def testKeepRunning(self):
|
||||||
|
""" A WebSocketApp should keep running as long as its self.keep_running
|
||||||
|
is not False (in the boolean context).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_open(self, *args, **kwargs):
|
||||||
|
""" Set the keep_running flag for later inspection and immediately
|
||||||
|
close the connection.
|
||||||
|
"""
|
||||||
|
WebSocketAppTest.keep_running_open = self.keep_running
|
||||||
|
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def on_close(self, *args, **kwargs):
|
||||||
|
""" Set the keep_running flag for the test to use.
|
||||||
|
"""
|
||||||
|
WebSocketAppTest.keep_running_close = self.keep_running
|
||||||
|
|
||||||
|
app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, on_close=on_close)
|
||||||
|
app.run_forever()
|
||||||
|
|
||||||
|
# if numpy is installed, this assertion fail
|
||||||
|
# self.assertFalse(isinstance(WebSocketAppTest.keep_running_open,
|
||||||
|
# WebSocketAppTest.NotSetYet))
|
||||||
|
|
||||||
|
# self.assertFalse(isinstance(WebSocketAppTest.keep_running_close,
|
||||||
|
# WebSocketAppTest.NotSetYet))
|
||||||
|
|
||||||
|
# self.assertEqual(True, WebSocketAppTest.keep_running_open)
|
||||||
|
# self.assertEqual(False, WebSocketAppTest.keep_running_close)
|
||||||
|
|
||||||
|
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||||
|
def testSockMaskKey(self):
|
||||||
|
""" A WebSocketApp should forward the received mask_key function down
|
||||||
|
to the actual socket.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def my_mask_key_func():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_open(self, *args, **kwargs):
|
||||||
|
""" Set the value so the test can use it later on and immediately
|
||||||
|
close the connection.
|
||||||
|
"""
|
||||||
|
WebSocketAppTest.get_mask_key_id = id(self.get_mask_key)
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, get_mask_key=my_mask_key_func)
|
||||||
|
app.run_forever()
|
||||||
|
|
||||||
|
# if numpy is installed, this assertion fail
|
||||||
|
# Note: We can't use 'is' for comparing the functions directly, need to use 'id'.
|
||||||
|
# self.assertEqual(WebSocketAppTest.get_mask_key_id, id(my_mask_key_func))
|
||||||
|
|
||||||
|
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||||
|
def testPingInterval(self):
|
||||||
|
""" A WebSocketApp should ping regularly
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_ping(app, msg):
|
||||||
|
print("Got a ping!")
|
||||||
|
app.close()
|
||||||
|
|
||||||
|
def on_pong(app, msg):
|
||||||
|
print("Got a pong! No need to respond")
|
||||||
|
app.close()
|
||||||
|
|
||||||
|
app = ws.WebSocketApp('wss://api-pub.bitfinex.com/ws/1', on_ping=on_ping, on_pong=on_pong)
|
||||||
|
app.run_forever(ping_interval=2, ping_timeout=1) # , sslopt={"cert_reqs": ssl.CERT_NONE}
|
||||||
|
self.assertRaises(ws.WebSocketException, app.run_forever, ping_interval=2, ping_timeout=3, sslopt={"cert_reqs": ssl.CERT_NONE})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
|
@ -26,11 +26,6 @@ import unittest
|
||||||
|
|
||||||
from websocket._cookiejar import SimpleCookieJar
|
from websocket._cookiejar import SimpleCookieJar
|
||||||
|
|
||||||
try:
|
|
||||||
import Cookie
|
|
||||||
except:
|
|
||||||
import http.cookies as Cookie
|
|
||||||
|
|
||||||
|
|
||||||
class CookieJarTest(unittest.TestCase):
|
class CookieJarTest(unittest.TestCase):
|
||||||
def testAdd(self):
|
def testAdd(self):
|
||||||
|
|
109
resources/lib/websocket/tests/test_http.py
Normal file
109
resources/lib/websocket/tests/test_http.py
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
websocket - WebSocket client library for Python
|
||||||
|
|
||||||
|
Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import websocket as ws
|
||||||
|
from websocket._http import proxy_info, read_headers, _open_proxied_socket, _tunnel
|
||||||
|
import sys
|
||||||
|
sys.path[0:0] = [""]
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||||
|
import unittest2 as unittest
|
||||||
|
else:
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class SockMock(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.data = []
|
||||||
|
self.sent = []
|
||||||
|
|
||||||
|
def add_packet(self, data):
|
||||||
|
self.data.append(data)
|
||||||
|
|
||||||
|
def gettimeout(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def recv(self, bufsize):
|
||||||
|
if self.data:
|
||||||
|
e = self.data.pop(0)
|
||||||
|
if isinstance(e, Exception):
|
||||||
|
raise e
|
||||||
|
if len(e) > bufsize:
|
||||||
|
self.data.insert(0, e[bufsize:])
|
||||||
|
return e[:bufsize]
|
||||||
|
|
||||||
|
def send(self, data):
|
||||||
|
self.sent.append(data)
|
||||||
|
return len(data)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderSockMock(SockMock):
|
||||||
|
|
||||||
|
def __init__(self, fname):
|
||||||
|
SockMock.__init__(self)
|
||||||
|
path = os.path.join(os.path.dirname(__file__), fname)
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
self.add_packet(f.read())
|
||||||
|
|
||||||
|
|
||||||
|
class OptsList():
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.timeout = 0
|
||||||
|
self.sockopt = []
|
||||||
|
|
||||||
|
|
||||||
|
class HttpTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def testReadHeader(self):
|
||||||
|
status, header, status_message = read_headers(HeaderSockMock("data/header01.txt"))
|
||||||
|
self.assertEqual(status, 101)
|
||||||
|
self.assertEqual(header["connection"], "Upgrade")
|
||||||
|
# header02.txt is intentionally malformed
|
||||||
|
self.assertRaises(ws.WebSocketException, read_headers, HeaderSockMock("data/header02.txt"))
|
||||||
|
|
||||||
|
def testTunnel(self):
|
||||||
|
self.assertRaises(ws.WebSocketProxyException, _tunnel, HeaderSockMock("data/header01.txt"), "example.com", 80, ("username", "password"))
|
||||||
|
self.assertRaises(ws.WebSocketProxyException, _tunnel, HeaderSockMock("data/header02.txt"), "example.com", 80, ("username", "password"))
|
||||||
|
|
||||||
|
def testConnect(self):
|
||||||
|
# Not currently testing an actual proxy connection, so just check whether TypeError is raised
|
||||||
|
self.assertRaises(TypeError, _open_proxied_socket, "wss://example.com", OptsList(), proxy_info(http_proxy_host="example.com", http_proxy_port="8080", proxy_type="http"))
|
||||||
|
self.assertRaises(TypeError, _open_proxied_socket, "wss://example.com", OptsList(), proxy_info(http_proxy_host="example.com", http_proxy_port="8080", proxy_type="socks4"))
|
||||||
|
self.assertRaises(TypeError, _open_proxied_socket, "wss://example.com", OptsList(), proxy_info(http_proxy_host="example.com", http_proxy_port="8080", proxy_type="socks5h"))
|
||||||
|
|
||||||
|
def testProxyInfo(self):
|
||||||
|
self.assertEqual(proxy_info(http_proxy_host="127.0.0.1", http_proxy_port="8080", proxy_type="http").type, "http")
|
||||||
|
self.assertRaises(ValueError, proxy_info, http_proxy_host="127.0.0.1", http_proxy_port="8080", proxy_type="badval")
|
||||||
|
self.assertEqual(proxy_info(http_proxy_host="example.com", http_proxy_port="8080", proxy_type="http").host, "example.com")
|
||||||
|
self.assertEqual(proxy_info(http_proxy_host="127.0.0.1", http_proxy_port="8080", proxy_type="http").port, "8080")
|
||||||
|
self.assertEqual(proxy_info(http_proxy_host="127.0.0.1", http_proxy_port="8080", proxy_type="http").auth, None)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
309
resources/lib/websocket/tests/test_url.py
Normal file
309
resources/lib/websocket/tests/test_url.py
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
websocket - WebSocket client library for Python
|
||||||
|
|
||||||
|
Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
from websocket._url import get_proxy_info, parse_url, _is_address_in_network, _is_no_proxy_host
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||||
|
import unittest2 as unittest
|
||||||
|
else:
|
||||||
|
import unittest
|
||||||
|
sys.path[0:0] = [""]
|
||||||
|
|
||||||
|
|
||||||
|
class UrlTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_address_in_network(self):
|
||||||
|
self.assertTrue(_is_address_in_network('127.0.0.1', '127.0.0.0/8'))
|
||||||
|
self.assertTrue(_is_address_in_network('127.1.0.1', '127.0.0.0/8'))
|
||||||
|
self.assertFalse(_is_address_in_network('127.1.0.1', '127.0.0.0/24'))
|
||||||
|
|
||||||
|
def testParseUrl(self):
|
||||||
|
p = parse_url("ws://www.example.com/r")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 80)
|
||||||
|
self.assertEqual(p[2], "/r")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("ws://www.example.com/r/")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 80)
|
||||||
|
self.assertEqual(p[2], "/r/")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("ws://www.example.com/")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 80)
|
||||||
|
self.assertEqual(p[2], "/")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("ws://www.example.com")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 80)
|
||||||
|
self.assertEqual(p[2], "/")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("ws://www.example.com:8080/r")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 8080)
|
||||||
|
self.assertEqual(p[2], "/r")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("ws://www.example.com:8080/")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 8080)
|
||||||
|
self.assertEqual(p[2], "/")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("ws://www.example.com:8080")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 8080)
|
||||||
|
self.assertEqual(p[2], "/")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("wss://www.example.com:8080/r")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 8080)
|
||||||
|
self.assertEqual(p[2], "/r")
|
||||||
|
self.assertEqual(p[3], True)
|
||||||
|
|
||||||
|
p = parse_url("wss://www.example.com:8080/r?key=value")
|
||||||
|
self.assertEqual(p[0], "www.example.com")
|
||||||
|
self.assertEqual(p[1], 8080)
|
||||||
|
self.assertEqual(p[2], "/r?key=value")
|
||||||
|
self.assertEqual(p[3], True)
|
||||||
|
|
||||||
|
self.assertRaises(ValueError, parse_url, "http://www.example.com/r")
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
||||||
|
return
|
||||||
|
|
||||||
|
p = parse_url("ws://[2a03:4000:123:83::3]/r")
|
||||||
|
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||||
|
self.assertEqual(p[1], 80)
|
||||||
|
self.assertEqual(p[2], "/r")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("ws://[2a03:4000:123:83::3]:8080/r")
|
||||||
|
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||||
|
self.assertEqual(p[1], 8080)
|
||||||
|
self.assertEqual(p[2], "/r")
|
||||||
|
self.assertEqual(p[3], False)
|
||||||
|
|
||||||
|
p = parse_url("wss://[2a03:4000:123:83::3]/r")
|
||||||
|
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||||
|
self.assertEqual(p[1], 443)
|
||||||
|
self.assertEqual(p[2], "/r")
|
||||||
|
self.assertEqual(p[3], True)
|
||||||
|
|
||||||
|
p = parse_url("wss://[2a03:4000:123:83::3]:8080/r")
|
||||||
|
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
||||||
|
self.assertEqual(p[1], 8080)
|
||||||
|
self.assertEqual(p[2], "/r")
|
||||||
|
self.assertEqual(p[3], True)
|
||||||
|
|
||||||
|
|
||||||
|
class IsNoProxyHostTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.no_proxy = os.environ.get("no_proxy", None)
|
||||||
|
if "no_proxy" in os.environ:
|
||||||
|
del os.environ["no_proxy"]
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
if self.no_proxy:
|
||||||
|
os.environ["no_proxy"] = self.no_proxy
|
||||||
|
elif "no_proxy" in os.environ:
|
||||||
|
del os.environ["no_proxy"]
|
||||||
|
|
||||||
|
def testMatchAll(self):
|
||||||
|
self.assertTrue(_is_no_proxy_host("any.websocket.org", ['*']))
|
||||||
|
self.assertTrue(_is_no_proxy_host("192.168.0.1", ['*']))
|
||||||
|
self.assertTrue(_is_no_proxy_host("any.websocket.org", ['other.websocket.org', '*']))
|
||||||
|
os.environ['no_proxy'] = '*'
|
||||||
|
self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
|
||||||
|
self.assertTrue(_is_no_proxy_host("192.168.0.1", None))
|
||||||
|
os.environ['no_proxy'] = 'other.websocket.org, *'
|
||||||
|
self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
|
||||||
|
|
||||||
|
def testIpAddress(self):
|
||||||
|
self.assertTrue(_is_no_proxy_host("127.0.0.1", ['127.0.0.1']))
|
||||||
|
self.assertFalse(_is_no_proxy_host("127.0.0.2", ['127.0.0.1']))
|
||||||
|
self.assertTrue(_is_no_proxy_host("127.0.0.1", ['other.websocket.org', '127.0.0.1']))
|
||||||
|
self.assertFalse(_is_no_proxy_host("127.0.0.2", ['other.websocket.org', '127.0.0.1']))
|
||||||
|
os.environ['no_proxy'] = '127.0.0.1'
|
||||||
|
self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
|
||||||
|
self.assertFalse(_is_no_proxy_host("127.0.0.2", None))
|
||||||
|
os.environ['no_proxy'] = 'other.websocket.org, 127.0.0.1'
|
||||||
|
self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
|
||||||
|
self.assertFalse(_is_no_proxy_host("127.0.0.2", None))
|
||||||
|
|
||||||
|
def testIpAddressInRange(self):
|
||||||
|
self.assertTrue(_is_no_proxy_host("127.0.0.1", ['127.0.0.0/8']))
|
||||||
|
self.assertTrue(_is_no_proxy_host("127.0.0.2", ['127.0.0.0/8']))
|
||||||
|
self.assertFalse(_is_no_proxy_host("127.1.0.1", ['127.0.0.0/24']))
|
||||||
|
os.environ['no_proxy'] = '127.0.0.0/8'
|
||||||
|
self.assertTrue(_is_no_proxy_host("127.0.0.1", None))
|
||||||
|
self.assertTrue(_is_no_proxy_host("127.0.0.2", None))
|
||||||
|
os.environ['no_proxy'] = '127.0.0.0/24'
|
||||||
|
self.assertFalse(_is_no_proxy_host("127.1.0.1", None))
|
||||||
|
|
||||||
|
def testHostnameMatch(self):
|
||||||
|
self.assertTrue(_is_no_proxy_host("my.websocket.org", ['my.websocket.org']))
|
||||||
|
self.assertTrue(_is_no_proxy_host("my.websocket.org", ['other.websocket.org', 'my.websocket.org']))
|
||||||
|
self.assertFalse(_is_no_proxy_host("my.websocket.org", ['other.websocket.org']))
|
||||||
|
os.environ['no_proxy'] = 'my.websocket.org'
|
||||||
|
self.assertTrue(_is_no_proxy_host("my.websocket.org", None))
|
||||||
|
self.assertFalse(_is_no_proxy_host("other.websocket.org", None))
|
||||||
|
os.environ['no_proxy'] = 'other.websocket.org, my.websocket.org'
|
||||||
|
self.assertTrue(_is_no_proxy_host("my.websocket.org", None))
|
||||||
|
|
||||||
|
def testHostnameMatchDomain(self):
|
||||||
|
self.assertTrue(_is_no_proxy_host("any.websocket.org", ['.websocket.org']))
|
||||||
|
self.assertTrue(_is_no_proxy_host("my.other.websocket.org", ['.websocket.org']))
|
||||||
|
self.assertTrue(_is_no_proxy_host("any.websocket.org", ['my.websocket.org', '.websocket.org']))
|
||||||
|
self.assertFalse(_is_no_proxy_host("any.websocket.com", ['.websocket.org']))
|
||||||
|
os.environ['no_proxy'] = '.websocket.org'
|
||||||
|
self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
|
||||||
|
self.assertTrue(_is_no_proxy_host("my.other.websocket.org", None))
|
||||||
|
self.assertFalse(_is_no_proxy_host("any.websocket.com", None))
|
||||||
|
os.environ['no_proxy'] = 'my.websocket.org, .websocket.org'
|
||||||
|
self.assertTrue(_is_no_proxy_host("any.websocket.org", None))
|
||||||
|
|
||||||
|
|
||||||
|
class ProxyInfoTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.http_proxy = os.environ.get("http_proxy", None)
|
||||||
|
self.https_proxy = os.environ.get("https_proxy", None)
|
||||||
|
self.no_proxy = os.environ.get("no_proxy", None)
|
||||||
|
if "http_proxy" in os.environ:
|
||||||
|
del os.environ["http_proxy"]
|
||||||
|
if "https_proxy" in os.environ:
|
||||||
|
del os.environ["https_proxy"]
|
||||||
|
if "no_proxy" in os.environ:
|
||||||
|
del os.environ["no_proxy"]
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
if self.http_proxy:
|
||||||
|
os.environ["http_proxy"] = self.http_proxy
|
||||||
|
elif "http_proxy" in os.environ:
|
||||||
|
del os.environ["http_proxy"]
|
||||||
|
|
||||||
|
if self.https_proxy:
|
||||||
|
os.environ["https_proxy"] = self.https_proxy
|
||||||
|
elif "https_proxy" in os.environ:
|
||||||
|
del os.environ["https_proxy"]
|
||||||
|
|
||||||
|
if self.no_proxy:
|
||||||
|
os.environ["no_proxy"] = self.no_proxy
|
||||||
|
elif "no_proxy" in os.environ:
|
||||||
|
del os.environ["no_proxy"]
|
||||||
|
|
||||||
|
def testProxyFromArgs(self):
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost"), ("localhost", 0, None))
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128),
|
||||||
|
("localhost", 3128, None))
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost"), ("localhost", 0, None))
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128),
|
||||||
|
("localhost", 3128, None))
|
||||||
|
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_auth=("a", "b")),
|
||||||
|
("localhost", 0, ("a", "b")))
|
||||||
|
self.assertEqual(
|
||||||
|
get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128, proxy_auth=("a", "b")),
|
||||||
|
("localhost", 3128, ("a", "b")))
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_auth=("a", "b")),
|
||||||
|
("localhost", 0, ("a", "b")))
|
||||||
|
self.assertEqual(
|
||||||
|
get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, proxy_auth=("a", "b")),
|
||||||
|
("localhost", 3128, ("a", "b")))
|
||||||
|
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128,
|
||||||
|
no_proxy=["example.com"], proxy_auth=("a", "b")),
|
||||||
|
("localhost", 3128, ("a", "b")))
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128,
|
||||||
|
no_proxy=["echo.websocket.org"], proxy_auth=("a", "b")),
|
||||||
|
(None, 0, None))
|
||||||
|
|
||||||
|
def testProxyFromEnv(self):
|
||||||
|
os.environ["http_proxy"] = "http://localhost/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, None))
|
||||||
|
os.environ["http_proxy"] = "http://localhost:3128/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", 3128, None))
|
||||||
|
|
||||||
|
os.environ["http_proxy"] = "http://localhost/"
|
||||||
|
os.environ["https_proxy"] = "http://localhost2/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, None))
|
||||||
|
os.environ["http_proxy"] = "http://localhost:3128/"
|
||||||
|
os.environ["https_proxy"] = "http://localhost2:3128/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", 3128, None))
|
||||||
|
|
||||||
|
os.environ["http_proxy"] = "http://localhost/"
|
||||||
|
os.environ["https_proxy"] = "http://localhost2/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True), ("localhost2", None, None))
|
||||||
|
os.environ["http_proxy"] = "http://localhost:3128/"
|
||||||
|
os.environ["https_proxy"] = "http://localhost2:3128/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True), ("localhost2", 3128, None))
|
||||||
|
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, ("a", "b")))
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", 3128, ("a", "b")))
|
||||||
|
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost/"
|
||||||
|
os.environ["https_proxy"] = "http://a:b@localhost2/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, ("a", "b")))
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
||||||
|
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", 3128, ("a", "b")))
|
||||||
|
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost/"
|
||||||
|
os.environ["https_proxy"] = "http://a:b@localhost2/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True), ("localhost2", None, ("a", "b")))
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
||||||
|
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True), ("localhost2", 3128, ("a", "b")))
|
||||||
|
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost/"
|
||||||
|
os.environ["https_proxy"] = "http://a:b@localhost2/"
|
||||||
|
os.environ["no_proxy"] = "example1.com,example2.com"
|
||||||
|
self.assertEqual(get_proxy_info("example.1.com", True), ("localhost2", None, ("a", "b")))
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
||||||
|
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
||||||
|
os.environ["no_proxy"] = "example1.com,example2.com, echo.websocket.org"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True), (None, 0, None))
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
||||||
|
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
||||||
|
os.environ["no_proxy"] = "example1.com,example2.com, .websocket.org"
|
||||||
|
self.assertEqual(get_proxy_info("echo.websocket.org", True), (None, 0, None))
|
||||||
|
|
||||||
|
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
||||||
|
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
||||||
|
os.environ["no_proxy"] = "127.0.0.0/8, 192.168.0.0/16"
|
||||||
|
self.assertEqual(get_proxy_info("127.0.0.1", False), (None, 0, None))
|
||||||
|
self.assertEqual(get_proxy_info("192.168.1.1", False), (None, 0, None))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
|
@ -39,7 +39,6 @@ import websocket as ws
|
||||||
from websocket._handshake import _create_sec_websocket_key, \
|
from websocket._handshake import _create_sec_websocket_key, \
|
||||||
_validate as _validate_header
|
_validate as _validate_header
|
||||||
from websocket._http import read_headers
|
from websocket._http import read_headers
|
||||||
from websocket._url import get_proxy_info, parse_url
|
|
||||||
from websocket._utils import validate_utf8
|
from websocket._utils import validate_utf8
|
||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
|
@ -61,9 +60,6 @@ except ImportError:
|
||||||
|
|
||||||
# Skip test to access the internet.
|
# Skip test to access the internet.
|
||||||
TEST_WITH_INTERNET = os.environ.get('TEST_WITH_INTERNET', '0') == '1'
|
TEST_WITH_INTERNET = os.environ.get('TEST_WITH_INTERNET', '0') == '1'
|
||||||
|
|
||||||
# Skip Secure WebSocket test.
|
|
||||||
TEST_SECURE_WS = True
|
|
||||||
TRACEABLE = True
|
TRACEABLE = True
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,102 +117,24 @@ class WebSocketTest(unittest.TestCase):
|
||||||
self.assertEqual(ws.getdefaulttimeout(), 10)
|
self.assertEqual(ws.getdefaulttimeout(), 10)
|
||||||
ws.setdefaulttimeout(None)
|
ws.setdefaulttimeout(None)
|
||||||
|
|
||||||
def testParseUrl(self):
|
|
||||||
p = parse_url("ws://www.example.com/r")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 80)
|
|
||||||
self.assertEqual(p[2], "/r")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("ws://www.example.com/r/")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 80)
|
|
||||||
self.assertEqual(p[2], "/r/")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("ws://www.example.com/")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 80)
|
|
||||||
self.assertEqual(p[2], "/")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("ws://www.example.com")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 80)
|
|
||||||
self.assertEqual(p[2], "/")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("ws://www.example.com:8080/r")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 8080)
|
|
||||||
self.assertEqual(p[2], "/r")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("ws://www.example.com:8080/")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 8080)
|
|
||||||
self.assertEqual(p[2], "/")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("ws://www.example.com:8080")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 8080)
|
|
||||||
self.assertEqual(p[2], "/")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("wss://www.example.com:8080/r")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 8080)
|
|
||||||
self.assertEqual(p[2], "/r")
|
|
||||||
self.assertEqual(p[3], True)
|
|
||||||
|
|
||||||
p = parse_url("wss://www.example.com:8080/r?key=value")
|
|
||||||
self.assertEqual(p[0], "www.example.com")
|
|
||||||
self.assertEqual(p[1], 8080)
|
|
||||||
self.assertEqual(p[2], "/r?key=value")
|
|
||||||
self.assertEqual(p[3], True)
|
|
||||||
|
|
||||||
self.assertRaises(ValueError, parse_url, "http://www.example.com/r")
|
|
||||||
|
|
||||||
if sys.version_info[0] == 2 and sys.version_info[1] < 7:
|
|
||||||
return
|
|
||||||
|
|
||||||
p = parse_url("ws://[2a03:4000:123:83::3]/r")
|
|
||||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
|
||||||
self.assertEqual(p[1], 80)
|
|
||||||
self.assertEqual(p[2], "/r")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("ws://[2a03:4000:123:83::3]:8080/r")
|
|
||||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
|
||||||
self.assertEqual(p[1], 8080)
|
|
||||||
self.assertEqual(p[2], "/r")
|
|
||||||
self.assertEqual(p[3], False)
|
|
||||||
|
|
||||||
p = parse_url("wss://[2a03:4000:123:83::3]/r")
|
|
||||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
|
||||||
self.assertEqual(p[1], 443)
|
|
||||||
self.assertEqual(p[2], "/r")
|
|
||||||
self.assertEqual(p[3], True)
|
|
||||||
|
|
||||||
p = parse_url("wss://[2a03:4000:123:83::3]:8080/r")
|
|
||||||
self.assertEqual(p[0], "2a03:4000:123:83::3")
|
|
||||||
self.assertEqual(p[1], 8080)
|
|
||||||
self.assertEqual(p[2], "/r")
|
|
||||||
self.assertEqual(p[3], True)
|
|
||||||
|
|
||||||
def testWSKey(self):
|
def testWSKey(self):
|
||||||
key = _create_sec_websocket_key()
|
key = _create_sec_websocket_key()
|
||||||
self.assertTrue(key != 24)
|
self.assertTrue(key != 24)
|
||||||
self.assertTrue(six.u("¥n") not in key)
|
self.assertTrue(six.u("¥n") not in key)
|
||||||
|
|
||||||
|
def testNonce(self):
|
||||||
|
""" WebSocket key should be a random 16-byte nonce.
|
||||||
|
"""
|
||||||
|
key = _create_sec_websocket_key()
|
||||||
|
nonce = base64decode(key.encode("utf-8"))
|
||||||
|
self.assertEqual(16, len(nonce))
|
||||||
|
|
||||||
def testWsUtils(self):
|
def testWsUtils(self):
|
||||||
key = "c6b8hTg4EeGb2gQMztV1/g=="
|
key = "c6b8hTg4EeGb2gQMztV1/g=="
|
||||||
required_header = {
|
required_header = {
|
||||||
"upgrade": "websocket",
|
"upgrade": "websocket",
|
||||||
"connection": "upgrade",
|
"connection": "upgrade",
|
||||||
"sec-websocket-accept": "Kxep+hNu9n51529fGidYu7a3wO0=",
|
"sec-websocket-accept": "Kxep+hNu9n51529fGidYu7a3wO0="}
|
||||||
}
|
|
||||||
self.assertEqual(_validate_header(required_header, key, None), (True, None))
|
self.assertEqual(_validate_header(required_header, key, None), (True, None))
|
||||||
|
|
||||||
header = required_header.copy()
|
header = required_header.copy()
|
||||||
|
@ -254,6 +172,10 @@ class WebSocketTest(unittest.TestCase):
|
||||||
self.assertEqual(status, 101)
|
self.assertEqual(status, 101)
|
||||||
self.assertEqual(header["connection"], "Upgrade")
|
self.assertEqual(header["connection"], "Upgrade")
|
||||||
|
|
||||||
|
status, header, status_message = read_headers(HeaderSockMock("data/header03.txt"))
|
||||||
|
self.assertEqual(status, 101)
|
||||||
|
self.assertEqual(header["connection"], "Upgrade, Keep-Alive")
|
||||||
|
|
||||||
HeaderSockMock("data/header02.txt")
|
HeaderSockMock("data/header02.txt")
|
||||||
self.assertRaises(ws.WebSocketException, read_headers, HeaderSockMock("data/header02.txt"))
|
self.assertRaises(ws.WebSocketException, read_headers, HeaderSockMock("data/header02.txt"))
|
||||||
|
|
||||||
|
@ -271,7 +193,10 @@ class WebSocketTest(unittest.TestCase):
|
||||||
sock.send(u"こんにちは")
|
sock.send(u"こんにちは")
|
||||||
self.assertEqual(s.sent[1], six.b("\x81\x8fabcd\x82\xe3\xf0\x87\xe3\xf1\x80\xe5\xca\x81\xe2\xc5\x82\xe3\xcc"))
|
self.assertEqual(s.sent[1], six.b("\x81\x8fabcd\x82\xe3\xf0\x87\xe3\xf1\x80\xe5\xca\x81\xe2\xc5\x82\xe3\xcc"))
|
||||||
|
|
||||||
sock.send("x" * 127)
|
# sock.send("x" * 5000)
|
||||||
|
# self.assertEqual(s.sent[1], six.b("\x81\x8fabcd\x82\xe3\xf0\x87\xe3\xf1\x80\xe5\xca\x81\xe2\xc5\x82\xe3\xcc"))
|
||||||
|
|
||||||
|
self.assertEqual(sock.send_binary(b'1111111111101'), 19)
|
||||||
|
|
||||||
def testRecv(self):
|
def testRecv(self):
|
||||||
# TODO: add longer frame data
|
# TODO: add longer frame data
|
||||||
|
@ -444,6 +369,7 @@ class WebSocketTest(unittest.TestCase):
|
||||||
s.send(u"こにゃにゃちは、世界")
|
s.send(u"こにゃにゃちは、世界")
|
||||||
result = s.recv()
|
result = s.recv()
|
||||||
self.assertEqual(result, "こにゃにゃちは、世界")
|
self.assertEqual(result, "こにゃにゃちは、世界")
|
||||||
|
self.assertRaises(ValueError, s.send_close, -1, "")
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||||
|
@ -455,22 +381,14 @@ class WebSocketTest(unittest.TestCase):
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||||
@unittest.skipUnless(TEST_SECURE_WS, "wss://echo.websocket.org doesn't work well.")
|
|
||||||
def testSecureWebSocket(self):
|
def testSecureWebSocket(self):
|
||||||
if 1:
|
|
||||||
import ssl
|
import ssl
|
||||||
s = ws.create_connection("wss://echo.websocket.org/")
|
s = ws.create_connection("wss://api.bitfinex.com/ws/2")
|
||||||
self.assertNotEqual(s, None)
|
self.assertNotEqual(s, None)
|
||||||
self.assertTrue(isinstance(s.sock, ssl.SSLSocket))
|
self.assertTrue(isinstance(s.sock, ssl.SSLSocket))
|
||||||
s.send("Hello, World")
|
self.assertEqual(s.getstatus(), 101)
|
||||||
result = s.recv()
|
self.assertNotEqual(s.getheaders(), None)
|
||||||
self.assertEqual(result, "Hello, World")
|
|
||||||
s.send(u"こにゃにゃちは、世界")
|
|
||||||
result = s.recv()
|
|
||||||
self.assertEqual(result, "こにゃにゃちは、世界")
|
|
||||||
s.close()
|
s.close()
|
||||||
#except:
|
|
||||||
# pass
|
|
||||||
|
|
||||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||||
def testWebSocketWithCustomHeader(self):
|
def testWebSocketWithCustomHeader(self):
|
||||||
|
@ -480,6 +398,7 @@ class WebSocketTest(unittest.TestCase):
|
||||||
s.send("Hello, World")
|
s.send("Hello, World")
|
||||||
result = s.recv()
|
result = s.recv()
|
||||||
self.assertEqual(result, "Hello, World")
|
self.assertEqual(result, "Hello, World")
|
||||||
|
self.assertRaises(ValueError, s.close, -1, "")
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||||
|
@ -490,87 +409,6 @@ class WebSocketTest(unittest.TestCase):
|
||||||
self.assertRaises(ws.WebSocketConnectionClosedException, s.send, "Hello")
|
self.assertRaises(ws.WebSocketConnectionClosedException, s.send, "Hello")
|
||||||
self.assertRaises(ws.WebSocketConnectionClosedException, s.recv)
|
self.assertRaises(ws.WebSocketConnectionClosedException, s.recv)
|
||||||
|
|
||||||
def testNonce(self):
|
|
||||||
""" WebSocket key should be a random 16-byte nonce.
|
|
||||||
"""
|
|
||||||
key = _create_sec_websocket_key()
|
|
||||||
nonce = base64decode(key.encode("utf-8"))
|
|
||||||
self.assertEqual(16, len(nonce))
|
|
||||||
|
|
||||||
|
|
||||||
class WebSocketAppTest(unittest.TestCase):
|
|
||||||
|
|
||||||
class NotSetYet(object):
|
|
||||||
""" A marker class for signalling that a value hasn't been set yet.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
ws.enableTrace(TRACEABLE)
|
|
||||||
|
|
||||||
WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet()
|
|
||||||
WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet()
|
|
||||||
WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet()
|
|
||||||
WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet()
|
|
||||||
WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet()
|
|
||||||
|
|
||||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
|
||||||
def testKeepRunning(self):
|
|
||||||
""" A WebSocketApp should keep running as long as its self.keep_running
|
|
||||||
is not False (in the boolean context).
|
|
||||||
"""
|
|
||||||
|
|
||||||
def on_open(self, *args, **kwargs):
|
|
||||||
""" Set the keep_running flag for later inspection and immediately
|
|
||||||
close the connection.
|
|
||||||
"""
|
|
||||||
WebSocketAppTest.keep_running_open = self.keep_running
|
|
||||||
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def on_close(self, *args, **kwargs):
|
|
||||||
""" Set the keep_running flag for the test to use.
|
|
||||||
"""
|
|
||||||
WebSocketAppTest.keep_running_close = self.keep_running
|
|
||||||
|
|
||||||
app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, on_close=on_close)
|
|
||||||
app.run_forever()
|
|
||||||
|
|
||||||
# if numpy is installed, this assertion fail
|
|
||||||
# self.assertFalse(isinstance(WebSocketAppTest.keep_running_open,
|
|
||||||
# WebSocketAppTest.NotSetYet))
|
|
||||||
|
|
||||||
# self.assertFalse(isinstance(WebSocketAppTest.keep_running_close,
|
|
||||||
# WebSocketAppTest.NotSetYet))
|
|
||||||
|
|
||||||
# self.assertEqual(True, WebSocketAppTest.keep_running_open)
|
|
||||||
# self.assertEqual(False, WebSocketAppTest.keep_running_close)
|
|
||||||
|
|
||||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
|
||||||
def testSockMaskKey(self):
|
|
||||||
""" A WebSocketApp should forward the received mask_key function down
|
|
||||||
to the actual socket.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def my_mask_key_func():
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_open(self, *args, **kwargs):
|
|
||||||
""" Set the value so the test can use it later on and immediately
|
|
||||||
close the connection.
|
|
||||||
"""
|
|
||||||
WebSocketAppTest.get_mask_key_id = id(self.get_mask_key)
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, get_mask_key=my_mask_key_func)
|
|
||||||
app.run_forever()
|
|
||||||
|
|
||||||
# if numpu is installed, this assertion fail
|
|
||||||
# Note: We can't use 'is' for comparing the functions directly, need to use 'id'.
|
|
||||||
# self.assertEqual(WebSocketAppTest.get_mask_key_id, id(my_mask_key_func))
|
|
||||||
|
|
||||||
|
|
||||||
class SockOptTest(unittest.TestCase):
|
class SockOptTest(unittest.TestCase):
|
||||||
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
|
||||||
|
@ -591,101 +429,5 @@ class UtilsTest(unittest.TestCase):
|
||||||
self.assertEqual(state, True)
|
self.assertEqual(state, True)
|
||||||
|
|
||||||
|
|
||||||
class ProxyInfoTest(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.http_proxy = os.environ.get("http_proxy", None)
|
|
||||||
self.https_proxy = os.environ.get("https_proxy", None)
|
|
||||||
if "http_proxy" in os.environ:
|
|
||||||
del os.environ["http_proxy"]
|
|
||||||
if "https_proxy" in os.environ:
|
|
||||||
del os.environ["https_proxy"]
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
if self.http_proxy:
|
|
||||||
os.environ["http_proxy"] = self.http_proxy
|
|
||||||
elif "http_proxy" in os.environ:
|
|
||||||
del os.environ["http_proxy"]
|
|
||||||
|
|
||||||
if self.https_proxy:
|
|
||||||
os.environ["https_proxy"] = self.https_proxy
|
|
||||||
elif "https_proxy" in os.environ:
|
|
||||||
del os.environ["https_proxy"]
|
|
||||||
|
|
||||||
def testProxyFromArgs(self):
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost"), ("localhost", 0, None))
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128), ("localhost", 3128, None))
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost"), ("localhost", 0, None))
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128), ("localhost", 3128, None))
|
|
||||||
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_auth=("a", "b")),
|
|
||||||
("localhost", 0, ("a", "b")))
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128, proxy_auth=("a", "b")),
|
|
||||||
("localhost", 3128, ("a", "b")))
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_auth=("a", "b")),
|
|
||||||
("localhost", 0, ("a", "b")))
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, proxy_auth=("a", "b")),
|
|
||||||
("localhost", 3128, ("a", "b")))
|
|
||||||
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, no_proxy=["example.com"], proxy_auth=("a", "b")),
|
|
||||||
("localhost", 3128, ("a", "b")))
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, no_proxy=["echo.websocket.org"], proxy_auth=("a", "b")),
|
|
||||||
(None, 0, None))
|
|
||||||
|
|
||||||
def testProxyFromEnv(self):
|
|
||||||
os.environ["http_proxy"] = "http://localhost/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, None))
|
|
||||||
os.environ["http_proxy"] = "http://localhost:3128/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", 3128, None))
|
|
||||||
|
|
||||||
os.environ["http_proxy"] = "http://localhost/"
|
|
||||||
os.environ["https_proxy"] = "http://localhost2/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, None))
|
|
||||||
os.environ["http_proxy"] = "http://localhost:3128/"
|
|
||||||
os.environ["https_proxy"] = "http://localhost2:3128/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", 3128, None))
|
|
||||||
|
|
||||||
os.environ["http_proxy"] = "http://localhost/"
|
|
||||||
os.environ["https_proxy"] = "http://localhost2/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True), ("localhost2", None, None))
|
|
||||||
os.environ["http_proxy"] = "http://localhost:3128/"
|
|
||||||
os.environ["https_proxy"] = "http://localhost2:3128/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True), ("localhost2", 3128, None))
|
|
||||||
|
|
||||||
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, ("a", "b")))
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", 3128, ("a", "b")))
|
|
||||||
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost/"
|
|
||||||
os.environ["https_proxy"] = "http://a:b@localhost2/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, ("a", "b")))
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
|
||||||
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", 3128, ("a", "b")))
|
|
||||||
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost/"
|
|
||||||
os.environ["https_proxy"] = "http://a:b@localhost2/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True), ("localhost2", None, ("a", "b")))
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
|
||||||
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True), ("localhost2", 3128, ("a", "b")))
|
|
||||||
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost/"
|
|
||||||
os.environ["https_proxy"] = "http://a:b@localhost2/"
|
|
||||||
os.environ["no_proxy"] = "example1.com,example2.com"
|
|
||||||
self.assertEqual(get_proxy_info("example.1.com", True), ("localhost2", None, ("a", "b")))
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
|
||||||
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
|
||||||
os.environ["no_proxy"] = "example1.com,example2.com, echo.websocket.org"
|
|
||||||
self.assertEqual(get_proxy_info("echo.websocket.org", True), (None, 0, None))
|
|
||||||
|
|
||||||
os.environ["http_proxy"] = "http://a:b@localhost:3128/"
|
|
||||||
os.environ["https_proxy"] = "http://a:b@localhost2:3128/"
|
|
||||||
os.environ["no_proxy"] = "127.0.0.0/8, 192.168.0.0/16"
|
|
||||||
self.assertEqual(get_proxy_info("127.0.0.1", False), (None, 0, None))
|
|
||||||
self.assertEqual(get_proxy_info("192.168.1.1", False), (None, 0, None))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -164,6 +164,14 @@ class PlexWebSocketApp(websocket.WebSocketApp,
|
||||||
if self.sleeptime < 6:
|
if self.sleeptime < 6:
|
||||||
self.sleeptime += 1
|
self.sleeptime += 1
|
||||||
|
|
||||||
|
def close(self, **kwargs):
|
||||||
|
"""websocket.WebSocketApp is not yet thread-safe. close() might
|
||||||
|
encounter websockets that have already been closed"""
|
||||||
|
try:
|
||||||
|
websocket.WebSocketApp.close(self, **kwargs)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def suspend(self, block=False, timeout=None):
|
def suspend(self, block=False, timeout=None):
|
||||||
"""
|
"""
|
||||||
Call this method from another thread to suspend this websocket thread
|
Call this method from another thread to suspend this websocket thread
|
||||||
|
|
Loading…
Reference in a new issue