From beaa7bc3cbf6427c5f99c567531b2b9ad969ae29 Mon Sep 17 00:00:00 2001 From: Jack Robison Date: Sun, 1 Nov 2020 15:25:51 -0500 Subject: [PATCH] fix scpd breaking if content-length is not provided -applies to at least actiontec -add actiontec and dd-wrt discover + get_external_ip replay tests --- aioupnp/protocols/scpd.py | 57 ++++++--- tests/__init__.py | 7 +- tests/replays/Actiontec GT784WN | 120 ++++++++++++++++++ tests/replays/NewMedia-NET GmbH Generic X86 | 129 ++++++++++++++++++++ tests/test_gateway.py | 74 ++++++++++- 5 files changed, 366 insertions(+), 21 deletions(-) create mode 100644 tests/replays/Actiontec GT784WN create mode 100644 tests/replays/NewMedia-NET GmbH Generic X86 diff --git a/aioupnp/protocols/scpd.py b/aioupnp/protocols/scpd.py index a1bd4dc..01147c4 100644 --- a/aioupnp/protocols/scpd.py +++ b/aioupnp/protocols/scpd.py @@ -56,6 +56,7 @@ class SCPDHTTPClientProtocol(Protocol): self._response_msg = b"" self._content_length = 0 self._got_headers = False + self._has_content_length = True self._headers: typing.Dict[bytes, bytes] = {} self._body = b"" self.transport: typing.Optional[asyncio.WriteTransport] = None @@ -67,35 +68,57 @@ class SCPDHTTPClientProtocol(Protocol): return None def data_received(self, data: bytes) -> None: + if self.finished.done(): # possible to hit during tests + return self.response_buff += data for i, line in enumerate(self.response_buff.split(b'\r\n')): if not line: # we hit the blank line between the headers and the body if i == (len(self.response_buff.split(b'\r\n')) - 1): return None # the body is still yet to be written if not self._got_headers: - self._headers, self._response_code, self._response_msg = parse_headers( - b'\r\n'.join(self.response_buff.split(b'\r\n')[:i]) - ) + try: + self._headers, self._response_code, self._response_msg = parse_headers( + b'\r\n'.join(self.response_buff.split(b'\r\n')[:i]) + ) + except ValueError as err: + self.finished.set_exception(UPnPError(str(err))) + return content_length = get_dict_val_case_insensitive( self._headers, b'Content-Length' ) - if content_length is None: - return None - self._content_length = int(content_length or 0) + if content_length is not None: + self._content_length = int(content_length) + else: + self._has_content_length = False self._got_headers = True - body = b'\r\n'.join(self.response_buff.split(b'\r\n')[i+1:]) - if self._content_length == len(body): - self.finished.set_result((self.response_buff, body, self._response_code, self._response_msg)) - elif self._content_length > len(body): - pass - else: - self.finished.set_exception( - UPnPError( - "too many bytes written to response (%i vs %i expected)" % ( - len(body), self._content_length + if self._got_headers and self._has_content_length: + body = b'\r\n'.join(self.response_buff.split(b'\r\n')[i+1:]) + if self._content_length == len(body): + self.finished.set_result((self.response_buff, body, self._response_code, self._response_msg)) + elif self._content_length > len(body): + pass + else: + self.finished.set_exception( + UPnPError( + "too many bytes written to response (%i vs %i expected)" % ( + len(body), self._content_length + ) ) ) - ) + elif any(map(self.response_buff.endswith, (b"\r\n", b"\r\n"))): + # Actiontec has a router that doesn't give a Content-Length for the gateway xml + body = b'\r\n'.join(self.response_buff.split(b'\r\n')[i+1:]) + self.finished.set_result((self.response_buff, body, self._response_code, self._response_msg)) + elif len(self.response_buff) >= 65535: + self.finished.set_exception( + UPnPError( + "too many bytes written to response (%i) with unspecified content length" % len(self.response_buff) + ) + ) + return + else: + # needed for the actiontec case + pass return None return None diff --git a/tests/__init__.py b/tests/__init__.py index 45c9d29..4cf83d1 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -18,7 +18,7 @@ except ImportError: @contextlib.contextmanager def mock_tcp_and_udp(loop, udp_expected_addr=None, udp_replies=None, udp_delay_reply=0.0, sent_udp_packets=None, tcp_replies=None, tcp_delay_reply=0.0, sent_tcp_packets=None, add_potato_datagrams=False, - raise_oserror_on_bind=False, raise_connectionerror=False): + raise_oserror_on_bind=False, raise_connectionerror=False, tcp_chunk_size=100): sent_udp_packets = sent_udp_packets if sent_udp_packets is not None else [] udp_replies = udp_replies or {} @@ -36,8 +36,8 @@ def mock_tcp_and_udp(loop, udp_expected_addr=None, udp_replies=None, udp_delay_r reply = tcp_replies[data] i = 0 while i < len(reply): - loop.call_later(tcp_delay_reply, p.data_received, reply[i:i+100]) - i += 100 + loop.call_later(tcp_delay_reply, p.data_received, reply[i:i+tcp_chunk_size]) + i += tcp_chunk_size return else: pass @@ -71,6 +71,7 @@ def mock_tcp_and_udp(loop, udp_expected_addr=None, udp_replies=None, udp_delay_r loop.call_later(udp_delay_reply, p.datagram_received, udp_replies[(data, addr)], (udp_expected_addr, 1900)) + return _sendto protocol = proto_lam() diff --git a/tests/replays/Actiontec GT784WN b/tests/replays/Actiontec GT784WN new file mode 100644 index 0000000..7eb2e79 --- /dev/null +++ b/tests/replays/Actiontec GT784WN @@ -0,0 +1,120 @@ +{ + "gateway": { + "gateway_address": "192.168.0.1", + "soap_port": 5431, + "m_search_args": { + "HOST": "239.255.255.250:1900", + "MAN": "\"ssdp:discover\"", + "MX": 1, + "ST": "upnp:rootdevice" + }, + "reply": { + "Server": "Custom/1.0 UPnP/1.0 Proc/Ver", + "Location": "http://192.168.0.1:5431/dyndev/uuid:deadbeef-dead-beef-dead-beefdeadbeef00", + "CACHE_CONTROL": "max-age=1800", + "ST": "upnp:rootdevice", + "USN": "uuid:deadbeef-dead-beef-dead-beefdeadbeef00::upnp:rootdevice" + }, + "registered_soap_commands": { + "GetDefaultConnectionService": "urn:schemas-upnp-org:service:Layer3Forwarding:1", + "SetDefaultConnectionService": "urn:schemas-upnp-org:service:Layer3Forwarding:1", + "GetCommonLinkProperties": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "GetTotalBytesSent": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "GetTotalBytesReceived": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "GetTotalPacketsReceived": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "GetTotalPacketsSent": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "SetConnectionType": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "GetConnectionTypeInfo": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "RequestConnection": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "ForceTermination": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "GetStatusInfo": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "GetNATRSIPStatus": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "GetGenericPortMappingEntry": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "GetSpecificPortMappingEntry": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "AddPortMapping": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "DeletePortMapping": "urn:schemas-upnp-org:service:WANPPPConnection:1", + "GetExternalIPAddress": "urn:schemas-upnp-org:service:WANPPPConnection:1" + }, + "unsupported_soap_commands": {}, + "gateway_xml": "HTTP/1.0 200 OK\r\nSERVER: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nCONTENT-TYPE: application/octet-stream\r\nCache-Control: max-age=1\r\nPRAGMA: no-cache\r\nConnection: Close\r\n\r\n\r\n\r\n\r\n1\r\n0\r\n\r\nhttp://192.168.0.1:5431/\r\n\r\nurn:schemas-upnp-org:device:InternetGatewayDevice:1\r\nhttp://192.168.0.1:80/\r\nActiontec GT784WN\r\nActiontec\r\nhttp://www.broadcom.com/\r\n(null)\r\nGT784WN\r\n1.0\r\nhttp://www.broadcom.com/\r\nuuid:deadbeef-dead-beef-dead-beefdeadbeef00\r\n\r\n\r\nurn:schemas-upnp-org:service:Layer3Forwarding:1\r\nurn:upnp-org:serviceId:Layer3Forwarding.1\r\n/uuid:deadbeef-dead-beef-dead-beefdeadbeef00/Layer3Forwarding:1\r\n/uuid:deadbeef-dead-beef-dead-beefdeadbeef00/Layer3Forwarding:1\r\n/dynsvc/Layer3Forwarding:1.xml\r\n\r\n\r\n\r\n\r\nurn:schemas-upnp-org:device:WANDevice:1\r\nWANDevice.1\r\nActiontec\r\nhttp://www.broadcom.com/\r\n(null)\r\nGT784WN\r\n1.0\r\nhttp://www.broadcom.com/\r\nuuid:70f196f9-33f5-f533-f996-f170f1f9f50001\r\n\r\n\r\nurn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\r\nurn:upnp-org:serviceId:WANCommonInterfaceConfig.1\r\n/uuid:70f196f9-33f5-f533-f996-f170f1f9f50001/WANCommonInterfaceConfig:1\r\n/uuid:70f196f9-33f5-f533-f996-f170f1f9f50001/WANCommonInterfaceConfig:1\r\n/dynsvc/WANCommonInterfaceConfig:1.xml\r\n\r\n\r\n\r\n\r\nurn:schemas-upnp-org:device:WANConnectionDevice:1\r\nWanConnectionDevice.2\r\nActiontec\r\nhttp://www.broadcom.com/\r\n(null)\r\nGT784WN\r\n1.0\r\nhttp://www.broadcom.com/\r\nuuid:70f196f9-33f5-f533-f996-f170f1f9f50002\r\n\r\n\r\nurn:schemas-upnp-org:service:WANPPPConnection:1\r\nurn:upnp-org:serviceId:WANPPPConnection.2\r\n/uuid:70f196f9-33f5-f533-f996-f170f1f9f50002/WANPPPConnection:1\r\n/uuid:70f196f9-33f5-f533-f996-f170f1f9f50002/WANPPPConnection:1\r\n/dynsvc/WANPPPConnection:1.xml\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "service_descriptors": { + "/dynsvc/Layer3Forwarding:1.xml": "HTTP/1.0 200 OK\r\nSERVER: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nCONTENT-TYPE: application/octet-stream\r\nCache-Control: max-age=1\r\nPRAGMA: no-cache\r\nConnection: Close\r\n\r\n\r\n\r\n \r\n 1\r\n 0\r\n \r\n\r\n\r\nGetDefaultConnectionService\r\n\r\n\r\nNewDefaultConnectionService\r\nDefaultConnectionService\r\nout\r\n\r\n\r\n\r\n\r\nSetDefaultConnectionService\r\n\r\n\r\nNewDefaultConnectionService\r\nDefaultConnectionService\r\nin\r\n\r\n\r\n\r\n\r\n\r\n\r\n DefaultConnectionService\r\n string\r\n\r\n\r\n\r\n", + "/dynsvc/WANCommonInterfaceConfig:1.xml": "HTTP/1.0 200 OK\r\nSERVER: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nCONTENT-TYPE: application/octet-stream\r\nCache-Control: max-age=1\r\nPRAGMA: no-cache\r\nConnection: Close\r\n\r\n\r\n\r\n \r\n 1\r\n 0\r\n \r\n\r\n\r\nGetCommonLinkProperties\r\n\r\n\r\nNewWANAccessType\r\nWANAccessType\r\nout\r\n\r\n\r\nNewLayer1UpstreamMaxBitRate\r\nLayer1UpstreamMaxBitRate\r\nout\r\n\r\n\r\nNewLayer1DownstreamMaxBitRate\r\nLayer1DownstreamMaxBitRate\r\nout\r\n\r\n\r\nNewPhysicalLinkStatus\r\nPhysicalLinkStatus\r\nout\r\n\r\n\r\n\r\n\r\nGetTotalBytesSent\r\n\r\n\r\nNewTotalBytesSent\r\nTotalBytesSent\r\nout\r\n\r\n\r\n\r\n\r\nGetTotalBytesReceived\r\n\r\n\r\nNewTotalBytesReceived\r\nTotalBytesReceived\r\nout\r\n\r\n\r\n\r\n\r\nGetTotalPacketsReceived\r\n\r\n\r\nNewTotalPacketsReceived\r\nTotalPacketsReceived\r\nout\r\n\r\n\r\n\r\n\r\nGetTotalPacketsSent\r\n\r\n\r\nNewTotalPacketsSent\r\nTotalPacketsSent\r\nout\r\n\r\n\r\n\r\n\r\n\r\n\r\n WANAccessType\r\n string\r\n \r\n DSL\r\n POTS\r\n Cable\r\n Ethernet\r\n Other\r\n \r\n\r\n\r\n Layer1UpstreamMaxBitRate\r\n ui4\r\n\r\n\r\n Layer1DownstreamMaxBitRate\r\n ui4\r\n\r\n\r\n PhysicalLinkStatus\r\n string\r\n \r\n Up\r\n Down\r\n Initializing\r\n Unavailable\r\n \r\n\r\n\r\n EnabledForInternet\r\n boolean\r\n\r\n\r\n TotalBytesSent\r\n ui4\r\n\r\n\r\n TotalBytesReceived\r\n ui4\r\n\r\n\r\n TotalPacketsSent\r\n ui4\r\n\r\n\r\n TotalPacketsReceived\r\n ui4\r\n\r\n\r\n\r\n", + "/dynsvc/WANPPPConnection:1.xml": "HTTP/1.0 200 OK\r\nSERVER: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nCONTENT-TYPE: application/octet-stream\r\nCache-Control: max-age=1\r\nPRAGMA: no-cache\r\nConnection: Close\r\n\r\n\r\n\r\n \r\n 1\r\n 0\r\n \r\n\r\n\r\nSetConnectionType\r\n\r\n\r\nNewConnectionType\r\nConnectionType\r\nin\r\n\r\n\r\n\r\n\r\nGetConnectionTypeInfo\r\n\r\n\r\nNewConnectionType\r\nConnectionType\r\nout\r\n\r\n\r\nNewPossibleConnectionTypes\r\nPossibleConnectionTypes\r\nout\r\n\r\n\r\n\r\n\r\nRequestConnection\r\n\r\n\r\nForceTermination\r\n\r\n\r\nGetStatusInfo\r\n\r\n\r\nNewConnectionStatus\r\nConnectionStatus\r\nout\r\n\r\n\r\nNewLastConnectionError\r\nLastConnectionError\r\nout\r\n\r\n\r\nNewUptime\r\nUptime\r\nout\r\n\r\n\r\n\r\n\r\nGetNATRSIPStatus\r\n\r\n\r\nNewRSIPAvailable\r\nRSIPAvailable\r\nout\r\n\r\n\r\nNewNATEnabled\r\nNATEnabled\r\nout\r\n\r\n\r\n\r\n\r\nGetGenericPortMappingEntry\r\n\r\n\r\nNewPortMappingIndex\r\nPortMappingNumberOfEntries\r\nin\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nout\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nout\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nout\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nout\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nout\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nout\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nout\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nout\r\n\r\n\r\n\r\n\r\nGetSpecificPortMappingEntry\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nout\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nout\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nout\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nout\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nout\r\n\r\n\r\n\r\n\r\nAddPortMapping\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nin\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nin\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nin\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nin\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nin\r\n\r\n\r\n\r\n\r\nDeletePortMapping\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\n\r\n\r\nGetExternalIPAddress\r\n\r\n\r\nNewExternalIPAddress\r\nExternalIPAddress\r\nout\r\n\r\n\r\n\r\n\r\n\r\n\r\n ConnectionType\r\n string\r\n \r\n Unconfigured\r\n IP_Routed\r\n DHCP_Spoofed\r\n PPPoE_Bridged\r\n PPTP_Relay\r\n L2TP_Relay\r\n PPPoE_Relay\r\n \r\n\r\n\r\n PossibleConnectionTypes\r\n string\r\n \r\n Unconfigured\r\n IP_Routed\r\n DHCP_Spoofed\r\n PPPoE_Bridged\r\n PPTP_Relay\r\n L2TP_Relay\r\n PPPoE_Relay\r\n \r\n\r\n\r\n ConnectionStatus\r\n string\r\n \r\n Unconfigured\r\n Connecting\r\n Authenticating\r\n Connected\r\n PendingDisconnect\r\n Disconnecting\r\n Disconnected\r\n \r\n\r\n\r\n Uptime\r\n ui4\r\n\r\n\r\n UpstreamMaxBitRate\r\n ui4\r\n\r\n\r\n DownstreamMaxBitRate\r\n ui4\r\n\r\n\r\n LastConnectionError\r\n string\r\n \r\n ERROR_NONE\r\n ERROR_UNKNOWN\r\n \r\n\r\n\r\n RSIPAvailable\r\n boolean\r\n\r\n\r\n NATEnabled\r\n boolean\r\n\r\n\r\n ExternalIPAddress\r\n string\r\n\r\n\r\n PortMappingNumberOfEntries\r\n ui2\r\n\r\n\r\n PortMappingEnabled\r\n boolean\r\n\r\n\r\n PortMappingLeaseDuration\r\n ui4\r\n\r\n\r\n RemoteHost\r\n string\r\n\r\n\r\n ExternalPort\r\n ui2\r\n\r\n\r\n InternalPort\r\n ui2\r\n\r\n\r\n PortMappingProtocol\r\n string\r\n \r\n TCP\r\n UDP\r\n \r\n\r\n\r\n InternalClient\r\n string\r\n\r\n\r\n PortMappingDescription\r\n string\r\n\r\n\r\n\r\n" + }, + "soap_requests": { + "GetDefaultConnectionService": [], + "SetDefaultConnectionService": [], + "GetCommonLinkProperties": [], + "GetTotalBytesSent": [], + "GetTotalBytesReceived": [], + "GetTotalPacketsReceived": [], + "GetTotalPacketsSent": [], + "SetConnectionType": [], + "GetConnectionTypeInfo": [], + "RequestConnection": [], + "ForceTermination": [], + "GetStatusInfo": [], + "GetNATRSIPStatus": [], + "GetGenericPortMappingEntry": [ + [ + { + "NewPortMappingIndex": 0 + }, + "HTTP/1.1 200 OK\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nConnection: Keep-Alive\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nContent-Length: 654\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nEXT:\r\n\r\n\r\n3658UDP3658192.168.0.101192.168.0.10:3658 to 3658 (UDP)0\r\n" + ], + [ + { + "NewPortMappingIndex": 1 + }, + "HTTP/1.1 500 Internal Server Error\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nConnection: Keep-Alive\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nContent-Length: 474\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nEXT:\r\n\r\n\r\n \r\n \r\n s:Client\r\n UPnPError\r\n \r\n \r\n 713\r\n SpecifiedArrayIndexInvalid\r\n \r\n \r\n \r\n \r\n\r\n" + ], + [ + { + "NewPortMappingIndex": 0 + }, + "HTTP/1.1 200 OK\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nConnection: Keep-Alive\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nContent-Length: 654\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nEXT:\r\n\r\n\r\n3658UDP3658192.168.0.101192.168.0.10:3658 to 3658 (UDP)0\r\n" + ], + [ + { + "NewPortMappingIndex": 1 + }, + "HTTP/1.1 500 Internal Server Error\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nConnection: Keep-Alive\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nContent-Length: 474\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nEXT:\r\n\r\n\r\n \r\n \r\n s:Client\r\n UPnPError\r\n \r\n \r\n 713\r\n SpecifiedArrayIndexInvalid\r\n \r\n \r\n \r\n \r\n\r\n" + ] + ], + "GetSpecificPortMappingEntry": [], + "AddPortMapping": [ + [ + { + "NewRemoteHost": "", + "NewExternalPort": 4567, + "NewProtocol": "UDP", + "NewInternalPort": 4567, + "NewInternalClient": "192.168.0.9", + "NewEnabled": true, + "NewPortMappingDescription": "aioupnp test mapping", + "NewLeaseDuration": "" + }, + "" + ] + ], + "DeletePortMapping": [ + [ + { + "NewRemoteHost": "", + "NewExternalPort": 4567, + "NewProtocol": "UDP" + }, + "" + ] + ], + "GetExternalIPAddress": [ + [ + {}, + "HTTP/1.1 200 OK\r\nDATE: Thu, 11 Oct 2018 15:42:26 GMT\r\nConnection: Keep-Alive\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nContent-Length: 360\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nEXT:\r\n\r\n\r\n11.222.33.111\r\n" + ] + ] + } + }, + "client_address": "192.168.0.9" +} \ No newline at end of file diff --git a/tests/replays/NewMedia-NET GmbH Generic X86 b/tests/replays/NewMedia-NET GmbH Generic X86 new file mode 100644 index 0000000..c34840b --- /dev/null +++ b/tests/replays/NewMedia-NET GmbH Generic X86 @@ -0,0 +1,129 @@ +{ + "gateway": { + "gateway_address": "192.168.1.1", + "soap_port": 5431, + "m_search_args": { + "HOST": "239.255.255.250:1900", + "MAN": "\"ssdp:discover\"", + "MX": 1, + "ST": "upnp:rootdevice" + }, + "reply": { + "ST": "upnp:rootdevice", + "USN": "uuid:dead-beef-deadbeef2222::upnp:rootdevice", + "Location": "http://192.168.1.1:5431/dyndev/uuid:dead-beef-deadbeef2222", + "Server": "Custom/1.0 UPnP/1.0 Proc/Ver", + "CACHE_CONTROL": "max-age=180" + }, + "registered_soap_commands": { + "GetDefaultConnectionService": "urn:schemas-upnp-org:service:Layer3Forwarding:1", + "SetDefaultConnectionService": "urn:schemas-upnp-org:service:Layer3Forwarding:1", + "GetCommonLinkProperties": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "GetTotalBytesSent": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "GetTotalBytesReceived": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "GetTotalPacketsReceived": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "GetTotalPacketsSent": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", + "SetConnectionType": "urn:schemas-upnp-org:service:WANIPConnection:1", + "GetConnectionTypeInfo": "urn:schemas-upnp-org:service:WANIPConnection:1", + "RequestConnection": "urn:schemas-upnp-org:service:WANIPConnection:1", + "ForceTermination": "urn:schemas-upnp-org:service:WANIPConnection:1", + "GetStatusInfo": "urn:schemas-upnp-org:service:WANIPConnection:1", + "GetNATRSIPStatus": "urn:schemas-upnp-org:service:WANIPConnection:1", + "GetGenericPortMappingEntry": "urn:schemas-upnp-org:service:WANIPConnection:1", + "GetSpecificPortMappingEntry": "urn:schemas-upnp-org:service:WANIPConnection:1", + "AddPortMapping": "urn:schemas-upnp-org:service:WANIPConnection:1", + "DeletePortMapping": "urn:schemas-upnp-org:service:WANIPConnection:1", + "GetExternalIPAddress": "urn:schemas-upnp-org:service:WANIPConnection:1" + }, + "unsupported_soap_commands": { + "urn:schemas-upnp-org:service:WANPPPConnection:1": [ + "SetConnectionType", + "GetConnectionTypeInfo", + "ConfigureConnection", + "RequestConnection", + "ForceTermination", + "SetIdleDisconnectTime", + "GetStatusInfo", + "GetLinkLayerMaxBitRates", + "GetUserName", + "GetPassword", + "GetIdleDisconnectTime", + "GetNATRSIPStatus", + "GetGenericPortMappingEntry", + "GetSpecificPortMappingEntry", + "AddPortMapping", + "DeletePortMapping", + "GetExternalIPAddress" + ] + }, + "gateway_xml": "HTTP/1.0 200 OK\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDate: Thu, 01 Jan 1970 00:23:13 GMT\r\nContent-Type: text/xml\r\nCache-Control: max-age=1\r\nPragma: no-cache\r\nConnection: close\r\n\r\n\r\n\r\n \r\n 1\r\n 0\r\n \r\n \r\n urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n DD-WRT Router (192.168.1.1)\r\n NewMedia-NET GmbH\r\n http://www.dd-wrt.com/\r\n Internet Gateway Device\r\n Generic X86\r\n DD-WRT v24 (05/20/08)\r\n http://www.dd-wrt.com/\r\n Not Available\r\n uuid:dead-beef-deadbeef2222\r\n \r\n \r\n urn:schemas-upnp-org:service:Layer3Forwarding:1\r\n urn:upnp-org:serviceId:L3Forwarding1\r\n /dynsvc/Layer3Forwarding:1.xml\r\n /uuid:dead-beef-deadbeef2222/Layer3Forwarding:1\r\n /uuid:dead-beef-deadbeef2222/Layer3Forwarding:1\r\n \r\n \r\n \r\n \r\n urn:schemas-upnp-org:device:WANDevice:1\r\n urn:schemas-upnp-org:device:WANDevice:1\r\n NewMedia-NET GmbH\r\n http://www.dd-wrt.com/\r\n Internet Gateway Device\r\n Generic X86\r\n DD-WRT v24 (05/20/08)\r\n http://www.dd-wrt.com/\r\n Not Available\r\n uuid:000c-29ea-247501c00098\r\n \r\n \r\n urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\r\n urn:upnp-org:serviceId:WANCommonIFC1\r\n /dynsvc/WANCommonInterfaceConfig:1.xml\r\n /uuid:000c-29ea-247501c00098/WANCommonInterfaceConfig:1\r\n /uuid:000c-29ea-247501c00098/WANCommonInterfaceConfig:1\r\n \r\n \r\n \r\n \r\n urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n NewMedia-NET GmbH\r\n http://www.dd-wrt.com/\r\n Internet Gateway Device\r\n Generic X86\r\n DD-WRT v24 (05/20/08)\r\n http://www.dd-wrt.com/\r\n Not Available\r\n uuid:dead-beef-deadbeef0000\r\n \r\n \r\n urn:schemas-upnp-org:service:WANIPConnection:1\r\n urn:upnp-org:serviceId:WANIPConn1\r\n /dynsvc/WANIPConnection:1.xml\r\n /uuid:dead-beef-deadbeef0000/WANIPConnection:1\r\n /uuid:dead-beef-deadbeef0000/WANIPConnection:1\r\n \r\n \r\n urn:schemas-upnp-org:service:WANPPPConnection:1\r\n urn:upnp-org:serviceId:WANPPPConn1\r\n /dynsvc/WANPPPConnection:1.xml\r\n /uuid:dead-beef-deadbeef0000/WANPPPConnection:1\r\n /uuid:dead-beef-deadbeef0000/WANPPPConnection:1\r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n", + "service_descriptors": { + "/dynsvc/Layer3Forwarding:1.xml": "HTTP/1.0 200 OK\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDate: Thu, 01 Jan 1970 00:23:13 GMT\r\nContent-Type: text/xml\r\nCache-Control: max-age=1\r\nPragma: no-cache\r\nConnection: close\r\n\r\n\r\n\r\n \r\n 1\r\n 0\r\n \r\n\r\n\r\nGetDefaultConnectionService\r\n\r\n\r\nNewDefaultConnectionService\r\nDefaultConnectionService\r\nout\r\n\r\n\r\n\r\n\r\nSetDefaultConnectionService\r\n\r\n\r\nNewDefaultConnectionService\r\nDefaultConnectionService\r\nin\r\n\r\n\r\n\r\n\r\n\r\n\r\n DefaultConnectionService\r\n string\r\n\r\n\r\n\r\n", + "/dynsvc/WANCommonInterfaceConfig:1.xml": "HTTP/1.0 200 OK\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDate: Thu, 01 Jan 1970 00:23:13 GMT\r\nContent-Type: text/xml\r\nCache-Control: max-age=1\r\nPragma: no-cache\r\nConnection: close\r\n\r\n\r\n\r\n \r\n 1\r\n 0\r\n \r\n\r\n\r\nGetCommonLinkProperties\r\n\r\n\r\nNewWANAccessType\r\nWANAccessType\r\nout\r\n\r\n\r\nNewLayer1UpstreamMaxBitRate\r\nLayer1UpstreamMaxBitRate\r\nout\r\n\r\n\r\nNewLayer1DownstreamMaxBitRate\r\nLayer1DownstreamMaxBitRate\r\nout\r\n\r\n\r\nNewPhysicalLinkStatus\r\nPhysicalLinkStatus\r\nout\r\n\r\n\r\n\r\n\r\nGetTotalBytesSent\r\n\r\n\r\nNewTotalBytesSent\r\nTotalBytesSent\r\nout\r\n\r\n\r\n\r\n\r\nGetTotalBytesReceived\r\n\r\n\r\nNewTotalBytesReceived\r\nTotalBytesReceived\r\nout\r\n\r\n\r\n\r\n\r\nGetTotalPacketsReceived\r\n\r\n\r\nNewTotalPacketsReceived\r\nTotalPacketsReceived\r\nout\r\n\r\n\r\n\r\n\r\nGetTotalPacketsSent\r\n\r\n\r\nNewTotalPacketsSent\r\nTotalPacketsSent\r\nout\r\n\r\n\r\n\r\n\r\n\r\n\r\n WANAccessType\r\n string\r\n \r\n DSL\r\n POTS\r\n Cable\r\n Ethernet\r\n Other\r\n \r\n\r\n\r\n Layer1UpstreamMaxBitRate\r\n ui4\r\n\r\n\r\n Layer1DownstreamMaxBitRate\r\n ui4\r\n\r\n\r\n PhysicalLinkStatus\r\n string\r\n \r\n Up\r\n Down\r\n Initializing\r\n Unavailable\r\n \r\n\r\n\r\n EnabledForInternet\r\n boolean\r\n\r\n\r\n TotalBytesSent\r\n ui4\r\n\r\n\r\n TotalBytesReceived\r\n ui4\r\n\r\n\r\n TotalPacketsSent\r\n ui4\r\n\r\n\r\n TotalPacketsReceived\r\n ui4\r\n\r\n\r\n\r\n", + "/dynsvc/WANIPConnection:1.xml": "HTTP/1.0 200 OK\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDate: Thu, 01 Jan 1970 00:23:13 GMT\r\nContent-Type: text/xml\r\nCache-Control: max-age=1\r\nPragma: no-cache\r\nConnection: close\r\n\r\n\r\n\r\n \r\n 1\r\n 0\r\n \r\n\r\n\r\nSetConnectionType\r\n\r\n\r\nNewConnectionType\r\nConnectionType\r\nin\r\n\r\n\r\n\r\n\r\nGetConnectionTypeInfo\r\n\r\n\r\nNewConnectionType\r\nConnectionType\r\nout\r\n\r\n\r\nNewPossibleConnectionTypes\r\nPossibleConnectionTypes\r\nout\r\n\r\n\r\n\r\n\r\nRequestConnection\r\n\r\n\r\nForceTermination\r\n\r\n\r\nGetStatusInfo\r\n\r\n\r\nNewConnectionStatus\r\nConnectionStatus\r\nout\r\n\r\n\r\nNewLastConnectionError\r\nLastConnectionError\r\nout\r\n\r\n\r\nNewUptime\r\nUptime\r\nout\r\n\r\n\r\n\r\n\r\nGetNATRSIPStatus\r\n\r\n\r\nNewRSIPAvailable\r\nRSIPAvailable\r\nout\r\n\r\n\r\nNewNATEnabled\r\nNATEnabled\r\nout\r\n\r\n\r\n\r\n\r\nGetGenericPortMappingEntry\r\n\r\n\r\nNewPortMappingIndex\r\nPortMappingNumberOfEntries\r\nin\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nout\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nout\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nout\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nout\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nout\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nout\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nout\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nout\r\n\r\n\r\n\r\n\r\nGetSpecificPortMappingEntry\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nout\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nout\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nout\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nout\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nout\r\n\r\n\r\n\r\n\r\nAddPortMapping\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nin\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nin\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nin\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nin\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nin\r\n\r\n\r\n\r\n\r\nDeletePortMapping\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\n\r\n\r\nGetExternalIPAddress\r\n\r\n\r\nNewExternalIPAddress\r\nExternalIPAddress\r\nout\r\n\r\n\r\n\r\n\r\n\r\n\r\n ConnectionType\r\n string\r\n\r\n\r\n PossibleConnectionTypes\r\n string\r\n \r\n Unconfigured\r\n IP_Routed\r\n IP_Bridged\r\n \r\n\r\n\r\n ConnectionStatus\r\n string\r\n \r\n Unconfigured\r\n Connecting\r\n Authenticating\r\n Connected\r\n PendingDisconnect\r\n Disconnecting\r\n Disconnected\r\n \r\n\r\n\r\n Uptime\r\n ui4\r\n\r\n\r\n LastConnectionError\r\n string\r\n \r\n ERROR_NONE\r\n ERROR_UNKNOWN\r\n \r\n\r\n\r\n RSIPAvailable\r\n boolean\r\n\r\n\r\n NATEnabled\r\n boolean\r\n\r\n\r\n ExternalIPAddress\r\n string\r\n\r\n\r\n PortMappingNumberOfEntries\r\n ui2\r\n\r\n\r\n PortMappingEnabled\r\n boolean\r\n\r\n\r\n PortMappingLeaseDuration\r\n ui4\r\n\r\n\r\n RemoteHost\r\n string\r\n\r\n\r\n ExternalPort\r\n ui2\r\n\r\n\r\n InternalPort\r\n ui2\r\n\r\n\r\n PortMappingProtocol\r\n string\r\n \r\n TCP\r\n UDP\r\n \r\n\r\n\r\n InternalClient\r\n string\r\n\r\n\r\n PortMappingDescription\r\n string\r\n\r\n\r\n\r\n", + "/dynsvc/WANPPPConnection:1.xml": "HTTP/1.0 200 OK\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nDate: Thu, 01 Jan 1970 00:23:13 GMT\r\nContent-Type: text/xml\r\nCache-Control: max-age=1\r\nPragma: no-cache\r\nConnection: close\r\n\r\n\r\n\r\n \r\n 1\r\n 0\r\n \r\n\r\n\r\nSetConnectionType\r\n\r\n\r\nNewConnectionType\r\nConnectionType\r\nin\r\n\r\n\r\n\r\n\r\nGetConnectionTypeInfo\r\n\r\n\r\nNewConnectionType\r\nConnectionType\r\nout\r\n\r\n\r\nNewPossibleConnectionTypes\r\nPossibleConnectionTypes\r\nout\r\n\r\n\r\n\r\n\r\nConfigureConnection\r\n\r\n\r\nNewUserName\r\nUserName\r\nin\r\n\r\n\r\nNewPassword\r\nPassword\r\nin\r\n\r\n\r\n\r\n\r\nRequestConnection\r\n\r\n\r\nForceTermination\r\n\r\n\r\nSetIdleDisconnectTime\r\n\r\n\r\nNewIdleDisconnectTime\r\nIdleDisconnectTime\r\nin\r\n\r\n\r\n\r\n\r\nGetStatusInfo\r\n\r\n\r\nNewConnectionStatus\r\nConnectionStatus\r\nout\r\n\r\n\r\nNewLastConnectionError\r\nLastConnectionError\r\nout\r\n\r\n\r\nNewUptime\r\nUptime\r\nout\r\n\r\n\r\n\r\n\r\nGetLinkLayerMaxBitRates\r\n\r\n\r\nNewUpstreamMaxBitRate\r\nUpstreamMaxBitRate\r\nout\r\n\r\n\r\nNewDownstreamMaxBitRate\r\nDownstreamMaxBitRate\r\nout\r\n\r\n\r\n\r\n\r\nGetUserName\r\n\r\n\r\nNewUserName\r\nUserName\r\nout\r\n\r\n\r\n\r\n\r\nGetPassword\r\n\r\n\r\nNewPassword\r\nPassword\r\nout\r\n\r\n\r\n\r\n\r\nGetIdleDisconnectTime\r\n\r\n\r\nNewIdleDisconnectTime\r\nIdleDisconnectTime\r\nout\r\n\r\n\r\n\r\n\r\nGetNATRSIPStatus\r\n\r\n\r\nNewRSIPAvailable\r\nRSIPAvailable\r\nout\r\n\r\n\r\nNewNATEnabled\r\nNATEnabled\r\nout\r\n\r\n\r\n\r\n\r\nGetGenericPortMappingEntry\r\n\r\n\r\nNewPortMappingIndex\r\nPortMappingNumberOfEntries\r\nin\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nout\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nout\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nout\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nout\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nout\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nout\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nout\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nout\r\n\r\n\r\n\r\n\r\nGetSpecificPortMappingEntry\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nout\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nout\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nout\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nout\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nout\r\n\r\n\r\n\r\n\r\nAddPortMapping\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\nNewInternalPort\r\nInternalPort\r\nin\r\n\r\n\r\nNewInternalClient\r\nInternalClient\r\nin\r\n\r\n\r\nNewEnabled\r\nPortMappingEnabled\r\nin\r\n\r\n\r\nNewPortMappingDescription\r\nPortMappingDescription\r\nin\r\n\r\n\r\nNewLeaseDuration\r\nPortMappingLeaseDuration\r\nin\r\n\r\n\r\n\r\n\r\nDeletePortMapping\r\n\r\n\r\nNewRemoteHost\r\nRemoteHost\r\nin\r\n\r\n\r\nNewExternalPort\r\nExternalPort\r\nin\r\n\r\n\r\nNewProtocol\r\nPortMappingProtocol\r\nin\r\n\r\n\r\n\r\n\r\nGetExternalIPAddress\r\n\r\n\r\nNewExternalIPAddress\r\nExternalIPAddress\r\nout\r\n\r\n\r\n\r\n\r\n\r\n\r\n ConnectionType\r\n string\r\n\r\n\r\n PossibleConnectionTypes\r\n string\r\n \r\n Unconfigured\r\n IP_Routed\r\n DHCP_Spoofed\r\n PPPoE_Bridged\r\n PPTP_Relay\r\n L2TP_Relay\r\n PPPoE_Relay\r\n \r\n\r\n\r\n ConnectionStatus\r\n string\r\n \r\n Unconfigured\r\n Connecting\r\n Authenticating\r\n Connected\r\n PendingDisconnect\r\n Disconnecting\r\n Disconnected\r\n \r\n\r\n\r\n Uptime\r\n ui4\r\n\r\n\r\n UpstreamMaxBitRate\r\n ui4\r\n\r\n\r\n DownstreamMaxBitRate\r\n ui4\r\n\r\n\r\n LastConnectionError\r\n string\r\n \r\n ERROR_NONE\r\n ERROR_UNKNOWN\r\n \r\n\r\n\r\n IdleDisconnectTime\r\n ui4\r\n\r\n\r\n RSIPAvailable\r\n boolean\r\n\r\n\r\n NATEnabled\r\n boolean\r\n\r\n\r\n UserName\r\n string\r\n\r\n\r\n Password\r\n string\r\n\r\n\r\n ExternalIPAddress\r\n string\r\n\r\n\r\n PortMappingNumberOfEntries\r\n ui2\r\n\r\n\r\n PortMappingEnabled\r\n boolean\r\n\r\n\r\n PortMappingLeaseDuration\r\n ui4\r\n\r\n\r\n RemoteHost\r\n string\r\n\r\n\r\n ExternalPort\r\n ui2\r\n\r\n\r\n InternalPort\r\n ui2\r\n\r\n\r\n PortMappingProtocol\r\n string\r\n \r\n TCP\r\n UDP\r\n \r\n\r\n\r\n InternalClient\r\n string\r\n\r\n\r\n PortMappingDescription\r\n string\r\n\r\n\r\n\r\n" + }, + "soap_requests": { + "GetDefaultConnectionService": [], + "SetDefaultConnectionService": [], + "GetCommonLinkProperties": [], + "GetTotalBytesSent": [], + "GetTotalBytesReceived": [], + "GetTotalPacketsReceived": [], + "GetTotalPacketsSent": [], + "SetConnectionType": [], + "GetConnectionTypeInfo": [], + "RequestConnection": [], + "ForceTermination": [], + "GetStatusInfo": [], + "GetNATRSIPStatus": [], + "GetGenericPortMappingEntry": [ + [ + { + "NewPortMappingIndex": 0 + }, + "HTTP/1.1 500 Internal Server Error\r\nDATE: Thu, 01 Jan 1970 00:23:13 GMT\r\nConnection: Keep-Alive\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nContent-Length: 474\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nEXT:\r\n\r\n\r\n \r\n \r\n s:Client\r\n UPnPError\r\n \r\n \r\n 713\r\n SpecifiedArrayIndexInvalid\r\n \r\n \r\n \r\n \r\n\r\n" + ], + [ + { + "NewPortMappingIndex": 0 + }, + "HTTP/1.1 500 Internal Server Error\r\nDATE: Thu, 01 Jan 1970 00:23:13 GMT\r\nConnection: Keep-Alive\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nContent-Length: 474\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nEXT:\r\n\r\n\r\n \r\n \r\n s:Client\r\n UPnPError\r\n \r\n \r\n 713\r\n SpecifiedArrayIndexInvalid\r\n \r\n \r\n \r\n \r\n\r\n" + ] + ], + "GetSpecificPortMappingEntry": [], + "AddPortMapping": [ + [ + { + "NewRemoteHost": "", + "NewExternalPort": 4567, + "NewProtocol": "UDP", + "NewInternalPort": 4567, + "NewInternalClient": "192.168.1.137", + "NewEnabled": true, + "NewPortMappingDescription": "aioupnp test mapping", + "NewLeaseDuration": "" + }, + "" + ] + ], + "DeletePortMapping": [ + [ + { + "NewRemoteHost": "", + "NewExternalPort": 4567, + "NewProtocol": "UDP" + }, + "" + ] + ], + "GetExternalIPAddress": [ + [ + {}, + "HTTP/1.1 200 OK\r\nDATE: Thu, 01 Jan 1970 00:23:13 GMT\r\nConnection: Keep-Alive\r\nServer: LINUX/2.4 UPnP/1.0 BRCM400/1.0\r\nContent-Length: 359\r\nContent-Type: text/xml; charset=\"utf-8\"\r\nEXT:\r\n\r\n\r\n11.222.33.111\r\n" + ] + ] + } + }, + "client_address": "192.168.1.137" +} \ No newline at end of file diff --git a/tests/test_gateway.py b/tests/test_gateway.py index 6b0a50b..e0965ae 100644 --- a/tests/test_gateway.py +++ b/tests/test_gateway.py @@ -1,8 +1,12 @@ +import os +import json +from collections import OrderedDict from aioupnp.fault import UPnPError from tests import AsyncioTestCase, mock_tcp_and_udp -from collections import OrderedDict from aioupnp.gateway import Gateway, get_action_list from aioupnp.serialization.ssdp import SSDPDatagram +from aioupnp.serialization.soap import serialize_soap_post +from aioupnp.upnp import UPnP def gen_get_bytes(location: str, host: str) -> bytes: @@ -296,3 +300,71 @@ class TestDiscoverNetgearNighthawkAC2350(TestDiscoverDLinkDIR890L): 'RequestConnection', 'ForceTermination', 'GetStatusInfo', 'GetNATRSIPStatus']}, 'soap_requests': []} + + +class TestActiontec(AsyncioTestCase): + name = "Actiontec GT784WN" + _location_key = 'Location' + + @property + def data_path(self): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "replays", self.name) + + def _get_location(self): + # return self.gateway_info['reply']['Location'].split(self.gateway_address)[-1] + return self.gateway_info['reply'][self._location_key].split(f"{self.gateway_address}:{self.gateway_info['soap_port']}")[-1] + + def setUp(self) -> None: + with open(self.data_path, 'r') as f: + data = json.loads(f.read()) + self.gateway_info = data['gateway'] + self.client_address = data['client_address'] + self.gateway_address = self.gateway_info['gateway_address'] + self.udp_replies = { + (SSDPDatagram('M-SEARCH', self.gateway_info['m_search_args']).encode().encode(), ("239.255.255.250", 1900)): SSDPDatagram("OK", self.gateway_info['reply']).encode().encode() + } + self.tcp_replies = { + ( + f"GET {path} HTTP/1.1\r\n" + f"Accept-Encoding: gzip\r\n" + f"Host: {self.gateway_info['gateway_address']}\r\n" + f"Connection: Close\r\n" + f"\r\n" + ).encode(): xml_bytes.encode() + for path, xml_bytes in self.gateway_info['service_descriptors'].items() + } + self.tcp_replies.update({ + ( + f"GET {self._get_location()} HTTP/1.1\r\n" + f"Accept-Encoding: gzip\r\n" + f"Host: {self.gateway_info['gateway_address']}\r\n" + f"Connection: Close\r\n" + f"\r\n" + ).encode(): self.gateway_info['gateway_xml'].encode() + }) + self.registered_soap_commands = self.gateway_info['registered_soap_commands'] + super().setUp() + + async def setup_request_replay(self, u: UPnP): + for method, reqs in self.gateway_info['soap_requests'].items(): + if not reqs: + continue + self.tcp_replies.update({ + serialize_soap_post( + method, list(args.keys()), self.registered_soap_commands[method].encode(), + self.gateway_address.encode(), u.gateway.services[self.registered_soap_commands[method]].controlURL.encode() + ): response.encode() for args, response in reqs + }) + + async def replay(self, u: UPnP): + self.assertEqual('11.222.33.111', await u.get_external_ip()) + + async def test_replay(self): + with mock_tcp_and_udp(self.loop, udp_replies=self.udp_replies, tcp_replies=self.tcp_replies, udp_expected_addr=self.gateway_address, tcp_chunk_size=1450): + u = await UPnP.discover(lan_address=self.client_address, gateway_address=self.gateway_address, loop=self.loop) + await self.setup_request_replay(u) + await self.replay(u) + + +class TestNewMediaNet(TestActiontec): + name = "NewMedia-NET GmbH Generic X86"