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
|
||||
from collections import OrderedDict
|
||||
from twisted.internet import defer
|
||||
from twisted.internet import defer, threads
|
||||
from twisted.web.client import Agent, HTTPConnectionPool
|
||||
import treq
|
||||
from treq.client import HTTPClient
|
||||
|
@ -318,3 +318,125 @@ class SCPDCommandRunner(object):
|
|||
def SetDefaultConnectionService(NewDefaultConnectionService):
|
||||
"""Returns (None)"""
|
||||
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 txupnp.fault import UPnPError
|
||||
from txupnp.soap import SOAPServiceManager
|
||||
from txupnp.scpd import UPnPFallback
|
||||
from txupnp.util import DeferredDict
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UPnP(object):
|
||||
def __init__(self, reactor):
|
||||
def __init__(self, reactor, miniupnpc_fallback=True):
|
||||
self._reactor = reactor
|
||||
self._miniupnpc_fallback = miniupnpc_fallback
|
||||
self.soap_manager = SOAPServiceManager(reactor)
|
||||
self.miniupnpc_runner = None
|
||||
|
||||
@property
|
||||
def lan_address(self):
|
||||
|
@ -22,6 +25,8 @@ class UPnP(object):
|
|||
try:
|
||||
return self.soap_manager.get_runner()
|
||||
except UPnPError as err:
|
||||
if self._miniupnpc_fallback and self.miniupnpc_runner:
|
||||
return self.miniupnpc_runner
|
||||
log.warning("upnp is not available: %s", err)
|
||||
|
||||
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)
|
||||
found = True
|
||||
except defer.TimeoutError:
|
||||
log.warning("failed to find upnp gateway")
|
||||
found = False
|
||||
finally:
|
||||
if not keep_listening:
|
||||
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)
|
||||
|
||||
def get_external_ip(self):
|
||||
|
|
Loading…
Reference in a new issue