This commit is contained in:
Jack Robison 2018-07-29 18:20:42 -04:00
parent 8e004a8744
commit 897276897d
No known key found for this signature in database
GPG key ID: DF25C68FE0239BB2

View file

@ -1,3 +1,4 @@
import json
import logging import logging
from collections import OrderedDict from collections import OrderedDict
from twisted.internet import defer from twisted.internet import defer
@ -129,19 +130,22 @@ class SCPDResponse(object):
class SCPDCommandRunner(object): class SCPDCommandRunner(object):
def __init__(self, gateway): def __init__(self, gateway):
self._gateway = gateway self._gateway = gateway
self._unsupported_actions = [] self._unsupported_actions = {}
self._scpd_responses = [] self._registered_commands = {}
@defer.inlineCallbacks @defer.inlineCallbacks
def _discover_commands(self, service): def _discover_commands(self, service):
scpd_url = self._gateway.base_address + service.scpd_path.encode() scpd_url = self._gateway.base_address + service.scpd_path.encode()
response = yield treq.get(scpd_url) response = yield treq.get(scpd_url)
content = yield response.content() content = yield response.content()
scpd_response = SCPDResponse(scpd_url, try:
response.headers, content) scpd_response = SCPDResponse(scpd_url,
self._scpd_responses.append(scpd_response) response.headers, content)
for action_dict in scpd_response.get_action_list(): for action_dict in scpd_response.get_action_list():
self._register_command(action_dict, service.service_type) self._register_command(action_dict, service.service_type)
except Exception as err:
log.exception("failed to parse scpd response (%s) from %s\nheaders:\n%s\ncontent\n%s",
err, scpd_url, response.headers, content)
defer.returnValue(None) defer.returnValue(None)
@defer.inlineCallbacks @defer.inlineCallbacks
@ -151,6 +155,7 @@ class SCPDCommandRunner(object):
if not service: if not service:
continue continue
yield self._discover_commands(service) yield self._discover_commands(service)
log.debug(self.debug_commands())
@staticmethod @staticmethod
def _soap_function_info(action_dict): def _soap_function_info(action_dict):
@ -171,28 +176,34 @@ class SCPDCommandRunner(object):
) )
def __register_command(self, action_info, service_type): def __register_command(self, action_info, service_type):
func_info = self._soap_function_info(action_info) func_info = self._soap_function_info(action_info)
command = _SCPDCommand(self._gateway.base_address, self._gateway.port, command = _SCPDCommand(self._gateway.base_address, self._gateway.port,
self._gateway.base_address + self._gateway.get_service(service_type).control_path.encode(), self._gateway.base_address + self._gateway.get_service(service_type).control_path.encode(),
self._gateway.get_service(service_type).service_id.encode(), *func_info) self._gateway.get_service(service_type).service_id.encode(), *func_info)
if not hasattr(self, command.method):
self._unsupported_actions.append(action_info)
print(("# send this to jack!\n\n@staticmethod\ndef %s(" % func_info[0]) + ("" if not func_info[1] else ", ".join(func_info[1])) + ("):\n \"\"\"Returns (%s)\"\"\"\n raise NotImplementedError()\n\n" % ("None" if not func_info[2] else ", ".join(func_info[2]))))
return
current = getattr(self, command.method) current = getattr(self, command.method)
if hasattr(current, "_return_types"): if hasattr(current, "_return_types"):
command._process_result = _return_types(*current._return_types)(command._process_result) command._process_result = _return_types(*current._return_types)(command._process_result)
setattr(command, "__doc__", current.__doc__) setattr(command, "__doc__", current.__doc__)
setattr(self, command.method, command) setattr(self, command.method, command)
self._registered_commands[command.method] = service_type
log.debug("registered %s %s", service_type, action_info['name']) log.debug("registered %s %s", service_type, action_info['name'])
return True
def _register_command(self, action_info, service_type): def _register_command(self, action_info, service_type):
try: try:
return self.__register_command(action_info, service_type) return self.__register_command(action_info, service_type)
except Exception as err: except Exception as err:
s = self._unsupported_actions.get(service_type, [])
s.append((action_info, err))
self._unsupported_actions[service_type] = s
log.error("failed to setup command for %s\n%s", service_type, action_info) log.error("failed to setup command for %s\n%s", service_type, action_info)
def debug_commands(self):
return json.dumps({
'available': self._registered_commands,
'failed': self._unsupported_actions
}, indent=2)
@staticmethod @staticmethod
@return_types(none) @return_types(none)
def AddPortMapping(NewRemoteHost, NewExternalPort, NewProtocol, NewInternalPort, NewInternalClient, def AddPortMapping(NewRemoteHost, NewExternalPort, NewProtocol, NewInternalPort, NewInternalClient,