Re-wired connection manager

This commit is contained in:
tomkat83 2016-05-24 19:00:39 +02:00
parent 67755d6a23
commit ae34b63de9
3 changed files with 151 additions and 114 deletions

View file

@ -508,24 +508,33 @@ class PlexAPI():
self.g_PMS dict set self.g_PMS dict set
""" """
self.g_PMS = {} self.g_PMS = {}
# "Searching for Plex Server"
xbmcgui.Dialog().notification( xbmcgui.Dialog().notification(
heading=self.addonName, heading=self.addonName,
message=self.__language__(39055), message=self.__language__(39055),
icon="special://home/addons/plugin.video.plexkodiconnect/icon.png", icon="special://home/addons/plugin.video.plexkodiconnect/icon.png",
time=3000, time=4000,
sound=False) sound=False)
# Look first for local PMS in the LAN # Look first for local PMS in the LAN
pmsList = self.PlexGDM() pmsList = self.PlexGDM()
self.logMsg('pmslist: %s' % pmsList, 1) self.logMsg('PMS found in the local LAN via GDM: %s' % pmsList, 2)
# Get PMS from plex.tv
if plexToken:
self.logMsg('Checking with plex.tv for more PMS to connect to', 1)
self.getPMSListFromMyPlex(plexToken)
else:
self.logMsg('No plex token supplied, only checked LAN for PMS', 1)
for uuid in pmsList: for uuid in pmsList:
PMS = pmsList[uuid] PMS = pmsList[uuid]
if PMS['uuid'] in self.g_PMS:
continue
self.declarePMS(PMS['uuid'], PMS['serverName'], 'http', self.declarePMS(PMS['uuid'], PMS['serverName'], 'http',
PMS['ip'], PMS['port']) PMS['ip'], PMS['port'])
self.updatePMSProperty(PMS['uuid'], 'owned', '-')
# Ping to check whether we need HTTPs or HTTP # Ping to check whether we need HTTPs or HTTP
url = '%s:%s' % (PMS['ip'], PMS['port']) https = PMSHttpsEnabled('%s:%s' % (PMS['ip'], PMS['port']))
https = PMSHttpsEnabled(url)
if https is None: if https is None:
# Error contacting url. Skip for now # Error contacting url. Skip for now
continue continue
@ -539,10 +548,6 @@ class PlexAPI():
# Already declared with http # Already declared with http
pass pass
if not plexToken:
self.logMsg('No plex.tv token supplied, checked LAN for PMS', 0)
return
# install plex.tv "virtual" PMS - for myPlex, PlexHome # install plex.tv "virtual" PMS - for myPlex, PlexHome
# self.declarePMS('plex.tv', 'plex.tv', 'https', 'plex.tv', '443') # self.declarePMS('plex.tv', 'plex.tv', 'https', 'plex.tv', '443')
# self.updatePMSProperty('plex.tv', 'local', '-') # self.updatePMSProperty('plex.tv', 'local', '-')
@ -551,9 +556,6 @@ class PlexAPI():
# 'plex.tv', 'accesstoken', plexToken) # 'plex.tv', 'accesstoken', plexToken)
# (remote and local) servers from plex.tv # (remote and local) servers from plex.tv
# Get PMS from plex.tv. This will overwrite any PMS we already found
self.getPMSListFromMyPlex(plexToken)
def getPMSListFromMyPlex(self, token): def getPMSListFromMyPlex(self, token):
""" """
getPMSListFromMyPlex getPMSListFromMyPlex
@ -566,7 +568,7 @@ class PlexAPI():
headerOptions={'X-Plex-Token': token}) headerOptions={'X-Plex-Token': token})
try: try:
xml.attrib xml.attrib
except: except AttributeError:
self.logMsg('Could not get list of PMS from plex.tv', -1) self.logMsg('Could not get list of PMS from plex.tv', -1)
return return
@ -574,105 +576,110 @@ class PlexAPI():
queue = Queue.Queue() queue = Queue.Queue()
threads = [] threads = []
maxAgeSeconds = 2*60*60*24
for Dir in xml.findall('Device'): for Dir in xml.findall('Device'):
if "server" in Dir.get('provides'): if 'server' not in Dir.get('provides'):
if Dir.find('Connection') is None: # No PMS - skip
# no valid connection - skip continue
continue if Dir.find('Connection') is None:
# no valid connection - skip
continue
# check MyPlex data age - skip if >2 days # check MyPlex data age - skip if >2 days
PMS = {} PMS = {}
PMS['name'] = Dir.get('name') PMS['name'] = Dir.get('name')
infoAge = time.time() - int(Dir.get('lastSeenAt')) infoAge = time.time() - int(Dir.get('lastSeenAt'))
oneDayInSec = 60 * 60 * 24 if infoAge > maxAgeSeconds:
if infoAge > 2 * oneDayInSec: self.logMsg("Server %s not seen for 2 days - skipping."
self.logMsg("Server %s not seen for 2 days - " % PMS['name'], 1)
"skipping." % PMS['name'], 0) continue
continue
PMS['uuid'] = Dir.get('clientIdentifier') PMS['uuid'] = Dir.get('clientIdentifier')
PMS['token'] = Dir.get('accessToken', token) PMS['token'] = Dir.get('accessToken', token)
PMS['owned'] = Dir.get('owned', '0') PMS['owned'] = Dir.get('owned', '1')
PMS['local'] = Dir.get('publicAddressMatches') PMS['local'] = Dir.get('publicAddressMatches')
PMS['ownername'] = Dir.get('sourceTitle', '') PMS['ownername'] = Dir.get('sourceTitle', '')
PMS['path'] = '/' PMS['path'] = '/'
PMS['options'] = None PMS['options'] = None
# If PMS seems (!!) local, try a local connection first # Try a local connection first
# Backup to remote connection, if that failes # Backup to remote connection, if that failes
PMS['baseURL'] = '' PMS['connections'] = []
for Con in Dir.findall('Connection'): for Con in Dir.findall('Connection'):
localConn = Con.get('local') if Con.get('local') == '1':
if ((PMS['local'] == '1' and localConn == '1') or PMS['connections'].append(Con)
(PMS['local'] == '0' and localConn == '0')): # Append non-local
# Either both local or both remote for Con in Dir.findall('Connection'):
PMS['protocol'] = Con.get('protocol') if Con.get('local') != '1':
PMS['ip'] = Con.get('address') PMS['connections'].append(Con)
PMS['port'] = Con.get('port')
PMS['baseURL'] = Con.get('uri')
elif PMS['local'] == '1' and localConn == '0':
# Backup connection if local one did not work
PMS['backup'] = {}
PMS['backup']['protocol'] = Con.get('protocol')
PMS['backup']['ip'] = Con.get('address')
PMS['backup']['port'] = Con.get('port')
PMS['backup']['baseURL'] = Con.get('uri')
# poke PMS, own thread for each poke # poke PMS, own thread for each poke
t = Thread(target=self.pokePMS, t = Thread(target=self.pokePMS,
args=(PMS, queue)) args=(PMS, queue))
t.start() t.start()
threads.append(t) threads.append(t)
# wait for requests being answered # wait for requests being answered
for t in threads: for t in threads:
t.join() t.join()
# declare new PMSs # declare new PMSs
while not queue.empty(): while not queue.empty():
PMS = queue.get() PMS = queue.get()
self.declarePMS(PMS['uuid'], PMS['name'], self.declarePMS(PMS['uuid'], PMS['name'],
PMS['protocol'], PMS['ip'], PMS['port']) PMS['protocol'], PMS['ip'], PMS['port'])
# dflt: token='', local, owned - updated later # dflt: token='', local, owned - updated later
self.updatePMSProperty( self.updatePMSProperty(
PMS['uuid'], 'accesstoken', PMS['token']) PMS['uuid'], 'accesstoken', PMS['token'])
self.updatePMSProperty( self.updatePMSProperty(
PMS['uuid'], 'owned', PMS['owned']) PMS['uuid'], 'owned', PMS['owned'])
self.updatePMSProperty( self.updatePMSProperty(
PMS['uuid'], 'local', PMS['local']) PMS['uuid'], 'local', PMS['local'])
# set in declarePMS, overwrite for https encryption # set in declarePMS, overwrite for https encryption
self.updatePMSProperty( self.updatePMSProperty(
PMS['uuid'], 'baseURL', PMS['baseURL']) PMS['uuid'], 'baseURL', PMS['baseURL'])
self.updatePMSProperty( self.updatePMSProperty(
PMS['uuid'], 'ownername', PMS['ownername']) PMS['uuid'], 'ownername', PMS['ownername'])
queue.task_done() queue.task_done()
def pokePMS(self, PMS, queue): def pokePMS(self, PMS, queue):
# Ignore SSL certificates for now if PMS['connections'][0].get('local') == '1':
xml = self.doUtils(PMS['baseURL'], protocol = PMS['connections'][0].get('protocol')
address = PMS['connections'][0].get('address')
port = PMS['connections'][0].get('port')
url = '%s://%s:%s' % (protocol, address, port)
else:
url = PMS['connections'][0].get('uri')
protocol, address, port = url.split(':')
address = address.replace('/', '')
xml = self.doUtils('%s/identity' % url,
authenticate=False, authenticate=False,
headerOptions={'X-Plex-Token': PMS['token']}, headerOptions={'X-Plex-Token': PMS['token']},
verifySSL=False) verifySSL=False,
timeout=3)
try: try:
xml.attrib xml.attrib
except: except AttributeError:
# Connection failed # No connection, delete the one we just tested
# retry with remote connection if we just tested local one. del PMS['connections'][0]
if PMS['local'] == '1' and PMS.get('backup'): if len(PMS['connections']) > 0:
self.logMsg('Couldnt talk to local PMS locally.' # Still got connections left, try them
'Trying again remotely.', 0) return self.pokePMS(PMS, queue)
PMS['protocol'] = PMS['backup']['protocol'] return
PMS['ip'] = PMS['backup']['ip']
PMS['port'] = PMS['backup']['port']
PMS['baseURL'] = PMS['backup']['baseURL']
PMS['local'] = '0'
# Try again
self.pokePMS(PMS, queue)
else:
return
else: else:
# Connection successful, process later # Connection successful - correct PMS?
queue.put(PMS) if xml.get('machineIdentifier') == PMS['uuid']:
# process later
PMS['baseURL'] = url
PMS['protocol'] = protocol
PMS['ip'] = address
PMS['port'] = port
queue.put(PMS)
return
self.logMsg('Found a PMS at %s, but the expected machineIdentifier of '
'%s did not match the one we found: %s'
% (url, PMS['uuid'], xml.get('machineIdentifier')), -1)
def MyPlexSignIn(self, username, password, options): def MyPlexSignIn(self, username, password, options):
""" """

View file

@ -424,14 +424,14 @@ def PMSHttpsEnabled(url):
verifySSL=False) verifySSL=False)
try: try:
res.attrib res.attrib
except: except AttributeError:
# Might have SSL deactivated. Try with http # Might have SSL deactivated. Try with http
res = doUtils('http://%s/identity' % url, res = doUtils('http://%s/identity' % url,
authenticate=False, authenticate=False,
verifySSL=False) verifySSL=False)
try: try:
res.attrib res.attrib
except: except AttributeError:
logMsg(title, "Could not contact PMS %s" % url, -1) logMsg(title, "Could not contact PMS %s" % url, -1)
return None return None
else: else:
@ -448,15 +448,16 @@ def GetMachineIdentifier(url):
Returns None if something went wrong Returns None if something went wrong
""" """
xml = downloadutils.DownloadUtils().downloadUrl(url + '/identity') xml = downloadutils.DownloadUtils().downloadUrl('%s/identity' % url,
authenticate=False,
verifySSL=False)
try: try:
xml.attrib machineIdentifier = xml.attrib['machineIdentifier']
except: except (AttributeError, KeyError):
logMsg(title, 'Could not get the PMS machineIdentifier for %s' logMsg(title, 'Could not get the PMS machineIdentifier for %s'
% url, -1) % url, -1)
return None return None
machineIdentifier = xml.attrib.get('machineIdentifier') logMsg(title, 'Found machineIdentifier %s for the PMS %s'
logMsg(title, 'Found machineIdentifier %s for %s'
% (machineIdentifier, url), 1) % (machineIdentifier, url), 1)
return machineIdentifier return machineIdentifier

View file

@ -12,6 +12,7 @@ import downloadutils
import userclient import userclient
import PlexAPI import PlexAPI
from PlexFunctions import GetMachineIdentifier
############################################################################### ###############################################################################
@ -26,6 +27,11 @@ class InitialSetup():
self.userClient = userclient.UserClient() self.userClient = userclient.UserClient()
self.plx = PlexAPI.PlexAPI() self.plx = PlexAPI.PlexAPI()
def PlexTvSignIn(self):
"""
Checks existing connection to plex.tv. If not, triggers sign in
"""
def setup(self, forcePlexTV=False, chooseServer=False): def setup(self, forcePlexTV=False, chooseServer=False):
""" """
Initial setup. Run once upon startup. Initial setup. Run once upon startup.
@ -44,7 +50,7 @@ class InitialSetup():
plexToken = plexdict['plexToken'] plexToken = plexdict['plexToken']
plexid = plexdict['plexid'] plexid = plexdict['plexid']
if plexToken: if plexToken:
self.logMsg('Found plex.tv token in settings', 0) self.logMsg('Found a plex.tv token in the settings', 0)
dialog = xbmcgui.Dialog() dialog = xbmcgui.Dialog()
@ -79,11 +85,10 @@ class InitialSetup():
authenticate=False, authenticate=False,
headerOptions={'X-Plex-Token': plexToken}) headerOptions={'X-Plex-Token': plexToken})
try: try:
xml.attrib plexLogin = xml.attrib['title']
except: except (AttributeError, KeyError):
self.logMsg('Failed to update Plex info from plex.tv', -1) self.logMsg('Failed to update Plex info from plex.tv', -1)
else: else:
plexLogin = xml.attrib.get('title')
utils.settings('plexLogin', value=plexLogin) utils.settings('plexLogin', value=plexLogin)
home = 'true' if xml.attrib.get('home') == '1' else 'false' home = 'true' if xml.attrib.get('home') == '1' else 'false'
utils.settings('plexhome', value=home) utils.settings('plexhome', value=home)
@ -92,12 +97,36 @@ class InitialSetup():
'plexHomeSize', value=xml.attrib.get('homeSize', '1')) 'plexHomeSize', value=xml.attrib.get('homeSize', '1'))
self.logMsg('Updated Plex info from plex.tv', 0) self.logMsg('Updated Plex info from plex.tv', 0)
# If a Plex server IP has already been set, return. # If a Plex server IP has already been set
# return only if the right machine identifier is found
getNewPMS = False
if server and forcePlexTV is False and chooseServer is False: if server and forcePlexTV is False and chooseServer is False:
self.logMsg("Server is already set.", 0) self.logMsg("PMS is already set: %s. Checking now..." % server, 0)
self.logMsg("url: %s, Plex machineIdentifier: %s" chk = self.plx.CheckConnection(server, verifySSL=False)
% (server, serverid), 0) if chk is False:
return self.logMsg('Could not reach PMS %s' % server, -1)
getNewPMS = True
if getNewPMS is False and not serverid:
self.logMsg('No PMS machineIdentifier found for %s. Trying to '
'get the PMS unique ID' % server, 1)
serverid = GetMachineIdentifier(server)
if serverid is None:
self.logMsg('Could not retrieve machineIdentifier', -1)
getNewPMS = True
else:
utils.settings('plex_machineIdentifier', value=serverid)
elif getNewPMS is False:
tempServerid = GetMachineIdentifier(server)
if tempServerid != serverid:
self.logMsg('The current PMS %s was expected to have a '
'unique machineIdentifier of %s. But we got '
'%s. Pick a new server to be sure'
% (server, serverid, tempServerid), 1)
getNewPMS = True
if getNewPMS is False:
self.logMsg("Using PMS %s with machineIdentifier %s"
% (server, serverid), 0)
return
# If not already retrieved myplex info, optionally let user sign in # If not already retrieved myplex info, optionally let user sign in
# to plex.tv. This DOES get called on very first install run # to plex.tv. This DOES get called on very first install run