miniupnpc fallback
This commit is contained in:
parent
947d70c193
commit
f9c6ce9bd6
2 changed files with 139 additions and 3 deletions
124
txupnp/scpd.py
124
txupnp/scpd.py
|
@ -1,6 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer, threads
|
||||||
from twisted.web.client import Agent, HTTPConnectionPool
|
from twisted.web.client import Agent, HTTPConnectionPool
|
||||||
import treq
|
import treq
|
||||||
from treq.client import HTTPClient
|
from treq.client import HTTPClient
|
||||||
|
@ -318,3 +318,125 @@ class SCPDCommandRunner(object):
|
||||||
def SetDefaultConnectionService(NewDefaultConnectionService):
|
def SetDefaultConnectionService(NewDefaultConnectionService):
|
||||||
"""Returns (None)"""
|
"""Returns (None)"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
class UPnPFallback(object):
|
||||||
|
def __init__(self):
|
||||||
|
try:
|
||||||
|
import miniupnpc
|
||||||
|
self._upnp = miniupnpc.UPnP()
|
||||||
|
self.available = True
|
||||||
|
except ImportError:
|
||||||
|
self._upnp = None
|
||||||
|
self.available = False
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def discover(self):
|
||||||
|
if not self.available:
|
||||||
|
raise NotImplementedError()
|
||||||
|
devices = yield threads.deferToThread(self._upnp.discover)
|
||||||
|
if devices:
|
||||||
|
device_url = yield threads.deferToThread(self._upnp.selectigd)
|
||||||
|
else:
|
||||||
|
device_url = None
|
||||||
|
|
||||||
|
defer.returnValue(devices > 0)
|
||||||
|
|
||||||
|
@return_types(none)
|
||||||
|
def AddPortMapping(self, NewRemoteHost, NewExternalPort, NewProtocol, NewInternalPort, NewInternalClient,
|
||||||
|
NewEnabled, NewPortMappingDescription, NewLeaseDuration):
|
||||||
|
"""Returns None"""
|
||||||
|
if not self.available:
|
||||||
|
raise NotImplementedError()
|
||||||
|
return threads.deferToThread(self._upnp.addportmapping, NewExternalPort, NewProtocol, NewInternalPort,
|
||||||
|
NewInternalClient, NewPortMappingDescription, NewLeaseDuration)
|
||||||
|
|
||||||
|
def GetNATRSIPStatus(self):
|
||||||
|
"""Returns (NewRSIPAvailable, NewNATEnabled)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@return_types(none_or_str, int, str, int, str, bool, str, int)
|
||||||
|
def GetGenericPortMappingEntry(self, NewPortMappingIndex):
|
||||||
|
"""
|
||||||
|
Returns (NewRemoteHost, NewExternalPort, NewProtocol, NewInternalPort, NewInternalClient, NewEnabled,
|
||||||
|
NewPortMappingDescription, NewLeaseDuration)
|
||||||
|
"""
|
||||||
|
if not self.available:
|
||||||
|
raise NotImplementedError()
|
||||||
|
return threads.deferToThread(self._upnp.getgenericportmapping, NewPortMappingIndex)
|
||||||
|
|
||||||
|
@return_types(int, str, bool, str, int)
|
||||||
|
def GetSpecificPortMappingEntry(self, NewRemoteHost, NewExternalPort, NewProtocol):
|
||||||
|
"""Returns (NewInternalPort, NewInternalClient, NewEnabled, NewPortMappingDescription, NewLeaseDuration)"""
|
||||||
|
if not self.available:
|
||||||
|
raise NotImplementedError()
|
||||||
|
return threads.deferToThread(self._upnp.getspecificportmapping, NewExternalPort, NewProtocol)
|
||||||
|
|
||||||
|
def SetConnectionType(self, NewConnectionType):
|
||||||
|
"""Returns None"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@return_types(str)
|
||||||
|
def GetExternalIPAddress(self):
|
||||||
|
"""Returns (NewExternalIPAddress)"""
|
||||||
|
if not self.available:
|
||||||
|
raise NotImplementedError()
|
||||||
|
return threads.deferToThread(self._upnp.externalipaddress)
|
||||||
|
|
||||||
|
def GetConnectionTypeInfo(self):
|
||||||
|
"""Returns (NewConnectionType, NewPossibleConnectionTypes)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@return_types(str, str, int)
|
||||||
|
def GetStatusInfo(self):
|
||||||
|
"""Returns (NewConnectionStatus, NewLastConnectionError, NewUptime)"""
|
||||||
|
if not self.available:
|
||||||
|
raise NotImplementedError()
|
||||||
|
return threads.deferToThread(self._upnp.statusinfo)
|
||||||
|
|
||||||
|
def ForceTermination(self):
|
||||||
|
"""Returns None"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@return_types(none)
|
||||||
|
def DeletePortMapping(self, NewRemoteHost, NewExternalPort, NewProtocol):
|
||||||
|
"""Returns None"""
|
||||||
|
if not self.available:
|
||||||
|
raise NotImplementedError()
|
||||||
|
return threads.deferToThread(self._upnp.deleteportmapping, NewExternalPort, NewProtocol)
|
||||||
|
|
||||||
|
def RequestConnection(self):
|
||||||
|
"""Returns None"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def GetCommonLinkProperties(self):
|
||||||
|
"""Returns (NewWANAccessType, NewLayer1UpstreamMaxBitRate, NewLayer1DownstreamMaxBitRate, NewPhysicalLinkStatus)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def GetTotalBytesSent(self):
|
||||||
|
"""Returns (NewTotalBytesSent)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def GetTotalBytesReceived(self):
|
||||||
|
"""Returns (NewTotalBytesReceived)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def GetTotalPacketsSent(self):
|
||||||
|
"""Returns (NewTotalPacketsSent)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def GetTotalPacketsReceived(self):
|
||||||
|
"""Returns (NewTotalPacketsReceived)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def X_GetICSStatistics(self):
|
||||||
|
"""Returns (TotalBytesSent, TotalBytesReceived, TotalPacketsSent, TotalPacketsReceived, Layer1DownstreamMaxBitRate, Uptime)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def GetDefaultConnectionService(self):
|
||||||
|
"""Returns (NewDefaultConnectionService)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def SetDefaultConnectionService(self, NewDefaultConnectionService):
|
||||||
|
"""Returns (None)"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
|
@ -3,15 +3,18 @@ import json
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from txupnp.fault import UPnPError
|
from txupnp.fault import UPnPError
|
||||||
from txupnp.soap import SOAPServiceManager
|
from txupnp.soap import SOAPServiceManager
|
||||||
|
from txupnp.scpd import UPnPFallback
|
||||||
from txupnp.util import DeferredDict
|
from txupnp.util import DeferredDict
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UPnP(object):
|
class UPnP(object):
|
||||||
def __init__(self, reactor):
|
def __init__(self, reactor, miniupnpc_fallback=True):
|
||||||
self._reactor = reactor
|
self._reactor = reactor
|
||||||
|
self._miniupnpc_fallback = miniupnpc_fallback
|
||||||
self.soap_manager = SOAPServiceManager(reactor)
|
self.soap_manager = SOAPServiceManager(reactor)
|
||||||
|
self.miniupnpc_runner = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lan_address(self):
|
def lan_address(self):
|
||||||
|
@ -22,6 +25,8 @@ class UPnP(object):
|
||||||
try:
|
try:
|
||||||
return self.soap_manager.get_runner()
|
return self.soap_manager.get_runner()
|
||||||
except UPnPError as err:
|
except UPnPError as err:
|
||||||
|
if self._miniupnpc_fallback and self.miniupnpc_runner:
|
||||||
|
return self.miniupnpc_runner
|
||||||
log.warning("upnp is not available: %s", err)
|
log.warning("upnp is not available: %s", err)
|
||||||
|
|
||||||
def m_search(self, address, timeout=30, max_devices=2):
|
def m_search(self, address, timeout=30, max_devices=2):
|
||||||
|
@ -44,11 +49,20 @@ class UPnP(object):
|
||||||
yield self.soap_manager.discover_services(timeout=timeout, max_devices=max_devices)
|
yield self.soap_manager.discover_services(timeout=timeout, max_devices=max_devices)
|
||||||
found = True
|
found = True
|
||||||
except defer.TimeoutError:
|
except defer.TimeoutError:
|
||||||
log.warning("failed to find upnp gateway")
|
|
||||||
found = False
|
found = False
|
||||||
finally:
|
finally:
|
||||||
if not keep_listening:
|
if not keep_listening:
|
||||||
self.soap_manager.sspd_factory.disconnect()
|
self.soap_manager.sspd_factory.disconnect()
|
||||||
|
if not self.commands:
|
||||||
|
log.debug("trying miniupnpc fallback")
|
||||||
|
fallback = UPnPFallback()
|
||||||
|
success = yield fallback.discover()
|
||||||
|
if success:
|
||||||
|
log.info("successfully started miniupnpc fallback")
|
||||||
|
self.miniupnpc_runner = fallback
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
log.warning("failed to find upnp gateway")
|
||||||
defer.returnValue(found)
|
defer.returnValue(found)
|
||||||
|
|
||||||
def get_external_ip(self):
|
def get_external_ip(self):
|
||||||
|
|
Loading…
Reference in a new issue