Merge pull request #703 from croneter/fix-websocket
Allow websocket redirects. Never allow insecure HTTPs connections for Kodi Leia
This commit is contained in:
commit
d8770603ba
2 changed files with 51 additions and 16 deletions
|
@ -105,6 +105,19 @@ class WebSocketTimeoutException(WebSocketException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class WebsocketRedirect(WebSocketException):
|
||||||
|
"""
|
||||||
|
WebsocketRedirect will be raised if a status code 301 is returned
|
||||||
|
The Exception will be instantiated with a dict containing all response
|
||||||
|
headers; which should contain the redirect address under the key 'location'
|
||||||
|
|
||||||
|
Access the headers via the attribute headers
|
||||||
|
"""
|
||||||
|
def __init__(self, headers):
|
||||||
|
self.headers = headers
|
||||||
|
super(WebsocketRedirect, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_TIMEOUT = None
|
DEFAULT_TIMEOUT = None
|
||||||
TRACE_ENABLED = False
|
TRACE_ENABLED = False
|
||||||
|
|
||||||
|
@ -162,10 +175,10 @@ def _parse_url(url):
|
||||||
port = parsed.port
|
port = parsed.port
|
||||||
|
|
||||||
is_secure = False
|
is_secure = False
|
||||||
if scheme == "ws":
|
if scheme == "ws" or scheme == 'http':
|
||||||
if not port:
|
if not port:
|
||||||
port = 80
|
port = 80
|
||||||
elif scheme == "wss":
|
elif scheme == "wss" or scheme == 'https':
|
||||||
is_secure = True
|
is_secure = True
|
||||||
if not port:
|
if not port:
|
||||||
port = 443
|
port = 443
|
||||||
|
@ -500,6 +513,9 @@ class WebSocket(object):
|
||||||
LOG.debug("-----------------------")
|
LOG.debug("-----------------------")
|
||||||
|
|
||||||
status, resp_headers = self._read_headers()
|
status, resp_headers = self._read_headers()
|
||||||
|
if status == 301:
|
||||||
|
# Redirect
|
||||||
|
raise WebsocketRedirect(resp_headers)
|
||||||
if status != 101:
|
if status != 101:
|
||||||
self.close()
|
self.close()
|
||||||
raise WebSocketException("Handshake Status %d" % status)
|
raise WebSocketException("Handshake Status %d" % status)
|
||||||
|
|
|
@ -18,6 +18,7 @@ class WebSocket(backgroundthread.KillableThread):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.ws = None
|
self.ws = None
|
||||||
|
self.redirect_uri = None
|
||||||
super(WebSocket, self).__init__()
|
super(WebSocket, self).__init__()
|
||||||
|
|
||||||
def process(self, opcode, message):
|
def process(self, opcode, message):
|
||||||
|
@ -91,6 +92,16 @@ class WebSocket(backgroundthread.KillableThread):
|
||||||
self.__class__.__name__)
|
self.__class__.__name__)
|
||||||
self.ws = None
|
self.ws = None
|
||||||
app.APP.monitor.waitForAbort(1)
|
app.APP.monitor.waitForAbort(1)
|
||||||
|
except websocket.WebsocketRedirect as e:
|
||||||
|
LOG.info('301 redirect detected')
|
||||||
|
self.redirect_uri = e.headers.get('location', e.headers.get('Location'))
|
||||||
|
if self.redirect_uri:
|
||||||
|
self.redirect_uri.decode('utf-8')
|
||||||
|
counter += 1
|
||||||
|
if counter >= 10:
|
||||||
|
LOG.info('%s: Repeated WebsocketRedirect detected. Stopping now',
|
||||||
|
self.__class__.__name__)
|
||||||
|
break
|
||||||
except websocket.WebSocketException as e:
|
except websocket.WebSocketException as e:
|
||||||
LOG.info('%s: WebSocketException: %s',
|
LOG.info('%s: WebSocketException: %s',
|
||||||
self.__class__.__name__, e)
|
self.__class__.__name__, e)
|
||||||
|
@ -141,18 +152,22 @@ class PMS_Websocket(WebSocket):
|
||||||
app.SYNC.background_sync_disabled)
|
app.SYNC.background_sync_disabled)
|
||||||
|
|
||||||
def getUri(self):
|
def getUri(self):
|
||||||
server = app.CONN.server
|
if self.redirect_uri:
|
||||||
# Get the appropriate prefix for the websocket
|
uri = self.redirect_uri
|
||||||
if server.startswith('https'):
|
self.redirect_uri = None
|
||||||
server = "wss%s" % server[5:]
|
|
||||||
else:
|
else:
|
||||||
server = "ws%s" % server[4:]
|
server = app.CONN.server
|
||||||
uri = "%s/:/websockets/notifications" % server
|
# Get the appropriate prefix for the websocket
|
||||||
# Need to use plex.tv token, if any. NOT user token
|
if server.startswith('https'):
|
||||||
if app.ACCOUNT.plex_token:
|
server = "wss%s" % server[5:]
|
||||||
uri += '?X-Plex-Token=%s' % app.ACCOUNT.plex_token
|
else:
|
||||||
|
server = "ws%s" % server[4:]
|
||||||
|
uri = "%s/:/websockets/notifications" % server
|
||||||
|
# Need to use plex.tv token, if any. NOT user token
|
||||||
|
if app.ACCOUNT.plex_token:
|
||||||
|
uri += '?X-Plex-Token=%s' % app.ACCOUNT.plex_token
|
||||||
sslopt = {}
|
sslopt = {}
|
||||||
if utils.settings('sslverify') == "false":
|
if v.KODIVERSION == 17 and utils.settings('sslverify') == "false":
|
||||||
sslopt["cert_reqs"] = CERT_NONE
|
sslopt["cert_reqs"] = CERT_NONE
|
||||||
LOG.debug("%s: Uri: %s, sslopt: %s",
|
LOG.debug("%s: Uri: %s, sslopt: %s",
|
||||||
self.__class__.__name__, uri, sslopt)
|
self.__class__.__name__, uri, sslopt)
|
||||||
|
@ -209,10 +224,14 @@ class Alexa_Websocket(WebSocket):
|
||||||
app.ACCOUNT.restricted_user)
|
app.ACCOUNT.restricted_user)
|
||||||
|
|
||||||
def getUri(self):
|
def getUri(self):
|
||||||
uri = ('wss://pubsub.plex.tv/sub/websockets/%s/%s?X-Plex-Token=%s'
|
if self.redirect_uri:
|
||||||
% (app.ACCOUNT.plex_user_id,
|
uri = self.redirect_uri
|
||||||
v.PKC_MACHINE_IDENTIFIER,
|
self.redirect_uri = None
|
||||||
app.ACCOUNT.plex_token))
|
else:
|
||||||
|
uri = ('wss://pubsub.plex.tv/sub/websockets/%s/%s?X-Plex-Token=%s'
|
||||||
|
% (app.ACCOUNT.plex_user_id,
|
||||||
|
v.PKC_MACHINE_IDENTIFIER,
|
||||||
|
app.ACCOUNT.plex_token))
|
||||||
sslopt = {}
|
sslopt = {}
|
||||||
LOG.debug("%s: Uri: %s, sslopt: %s",
|
LOG.debug("%s: Uri: %s, sslopt: %s",
|
||||||
self.__class__.__name__, uri, sslopt)
|
self.__class__.__name__, uri, sslopt)
|
||||||
|
|
Loading…
Reference in a new issue