From d1877085ac2387e9d8181391ba2a53c03edcd891 Mon Sep 17 00:00:00 2001 From: sirMackk Date: Sun, 15 Feb 2015 18:41:41 -0500 Subject: [PATCH 1/2] Adds upnp port forwarder skeleton --- src/util/UpnpPunch.py | 151 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/util/UpnpPunch.py diff --git a/src/util/UpnpPunch.py b/src/util/UpnpPunch.py new file mode 100644 index 00000000..df8fe026 --- /dev/null +++ b/src/util/UpnpPunch.py @@ -0,0 +1,151 @@ +import socket +import re +import urllib2 +import httplib +from urlparse import urlparse +from xml.dom.minidom import parseString + +# Relevant UPnP spec: http://www.upnp.org/specs/gw/UPnP-gw-WANIPConnection-v1-Service.pdf + +# General TODOs: +# Handle 0 or >1 IGDs +# Format the SOAP AddPortEntry message correctly (remove spaces/whitespace) +# Find robust way to find own ip + + +def _m_search_ssdp(): + """ + Broadcast a UDP SSDP M-SEARCH packet and return response. + """ + search_target = "urn:schemas-upnp-org:device:InternetGatewayDevice:1" + + ssdp_request = ''.join( + ['M-SEARCH * HTTP/1.1\r\n', + 'HOST: 239.255.255.250:1900\r\n', + 'MAN: "ssdp:discover"\r\n', + 'MX: 2\r\n', + 'ST: {0}\r\n'.format(search_target), + '\r\n'] + ) + + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.sendto(ssdp_request, ('239.255.255.250', 1900)) + + # TODO: add timeout + return sock.recv(1024) + + +def _retrieve_location_from_ssdp(response): + """ + Parse raw HTTP response to retrieve the UPnP location header + and return a ParseResult object. + """ + parsed = re.findall(r'(?P.*?): (?P.*?)\r\n', response) + location_header = filter(lambda x: x[0].lower() == 'location', parsed) + + if not len(location_header): + # no location header returned :( + return False + + return urlparse(location_header[0][1]) + + +def _retrieve_igd_profile(url): + """ + Retrieve the device's UPnP profile. + """ + # TODO: add exception handling + return urllib2.urlopen(url.geturl()).read() + + +def __get_node_value(node): + """ + Get the text value of the first child text node of a node. + """ + return node.childeNodes[0].data + + +def _parse_igd_profile(profile_xml): + """ + Traverse the profile xml DOM looking for either + WANIPConnection or WANPPPConnection and return + the value found as well as the 'controlURL'. + """ + # TODO: return upnp schema as well + dom = parseString(profile_xml) + + service_types = dom.getElementsByTagName('serviceType') + for service in service_types: + if __get_node_value(service).find('WANIPConnection') > 0 or \ + __get_node_value(service).find('WANPPPConnection') > 0: + control_url = service.parentNode.getElementsByTagName( + 'controlURL' + )[0].childNodes[0].data + + return control_url, upnp_schema + + +def _create_soap_message(port, description="UPnPPunch", protocol="TCP", + upnp_schema='WANIPConnection'): + """ + Build a SOAP AddPortMapping message. + """ + # TODO: get current ip + current_ip = '192.168.0.2' + + soap_message = """ + + + + + {port} + {protocol} + {port} + {host_ip} + 1 + {description} + 0 + + +""".format(port=port, + protocol=protocol, + host_ip=current_ip, + description=description, + upnp_schema=upnp_schema) + + return soap_message + + +def _send_soap_request(location, upnp_schema, control_url, soap_message): + """ + Send out SOAP request to UPnP device and return a response. + """ + headers = { + 'SOAPAction': ( + '"urn:schemas-upnp-org:service:{schema}:' + '1#AddPortMapping"'.format(schema=upnp_schema) + ), + 'Content-Type': 'text/xml' + } + conn = httplib.HTTPConnection(location.hostname, location.port) + conn.request('POST', control_url, soap_message, headers) + + response_body = conn.getresponse().read() + + return response_body + + +def open_port(port=15441): + """ + Attempt to forward a port using UPnP. + """ + location = _retrieve_location_from_ssdp(_m_search_ssdp()) + control_url, upnp_schema = _parse_igd_profile( + _retrieve_igd_profile(location) + ) + + for protocol in ["TCP", "UDP"]: + message = _create_soap_message(port, protocol, upnp_schema) + # TODO: gevent this + _send_soap_request(location, upnp_schema, control_url, message) + # TODO: handle error code in response From 218ceb4bddefe06cdfe9c938831aa75ff11103ac Mon Sep 17 00:00:00 2001 From: sirMackk Date: Tue, 24 Feb 2015 08:02:05 -0500 Subject: [PATCH 2/2] Merging in upnp_punch_squashed --- src/Config.py | 3 - src/File/FileServer.py | 27 +- src/util/UpnpPunch.py | 267 +++++++++------- tools/upnpc/Changelog.txt | 585 ----------------------------------- tools/upnpc/LICENSE | 27 -- tools/upnpc/README | 66 ---- tools/upnpc/libminiupnpc.a | Bin 41310 -> 0 bytes tools/upnpc/miniupnpc.def | 43 --- tools/upnpc/miniupnpc.dll | Bin 91712 -> 0 bytes tools/upnpc/miniupnpc.lib | Bin 26584 -> 0 bytes tools/upnpc/upnpc-shared.exe | Bin 8704 -> 0 bytes 11 files changed, 169 insertions(+), 849 deletions(-) delete mode 100644 tools/upnpc/Changelog.txt delete mode 100644 tools/upnpc/LICENSE delete mode 100644 tools/upnpc/README delete mode 100644 tools/upnpc/libminiupnpc.a delete mode 100644 tools/upnpc/miniupnpc.def delete mode 100644 tools/upnpc/miniupnpc.dll delete mode 100644 tools/upnpc/miniupnpc.lib delete mode 100644 tools/upnpc/upnpc-shared.exe diff --git a/src/Config.py b/src/Config.py index af277082..e495b12e 100644 --- a/src/Config.py +++ b/src/Config.py @@ -19,10 +19,8 @@ class Config(object): def createArguments(self): # Platform specific if sys.platform.startswith("win"): - upnpc = "tools\\upnpc\\upnpc-shared.exe" coffeescript = "type %s | tools\\coffee\\coffee.cmd" else: - upnpc = None coffeescript = None # Create parser @@ -81,7 +79,6 @@ class Config(object): parser.add_argument('--fileserver_port',help='FileServer bind port', default=15441, type=int, metavar='port') parser.add_argument('--ip_external', help='External ip (tested on start if None)', metavar='ip') - parser.add_argument('--upnpc', help='MiniUPnP binary for open port on router', default=upnpc, metavar='executable_path') parser.add_argument('--coffeescript_compiler', help='Coffeescript compiler for developing', default=coffeescript, metavar='executable_path') diff --git a/src/File/FileServer.py b/src/File/FileServer.py index d5f2d763..58bf7bb7 100644 --- a/src/File/FileServer.py +++ b/src/File/FileServer.py @@ -6,6 +6,7 @@ from FileRequest import FileRequest from Site import SiteManager from Debug import Debug from Connection import ConnectionServer +from util import UpnpPunch class FileServer(ConnectionServer): @@ -44,24 +45,16 @@ class FileServer(ConnectionServer): if self.testOpenport(port)["result"] == True: return True # Port already opened - if config.upnpc: # If we have upnpc util, try to use it to puch port on our router - self.log.info("Try to open port using upnpc...") - try: - exit = os.system("%s -e ZeroNet -r %s tcp" % (config.upnpc, self.port)) - if exit == 0: # Success - upnpc_success = True - else: # Failed - exit = os.system("%s -r %s tcp" % (config.upnpc, self.port)) # Try without -e option - if exit == 0: - upnpc_success = True - else: - upnpc_success = False - except Exception, err: - self.log.error("Upnpc run error: %s" % Debug.formatException(err)) - upnpc_success = False + self.log.info("Trying to open port using UpnpPunch...") + try: + upnp_punch = UpnpPunch.open_port(self.port, 'ZeroNet') + upnp_punch = True + except Exception, err: + self.log.error("UpnpPunch run error: %s" % Debug.formatException(err)) + upnp_punch = False - if upnpc_success and self.testOpenport(port)["result"] == True: - return True + if upnp_punch and self.testOpenport(port)["result"] == True: + return True self.log.info("Upnp mapping failed :( Please forward port %s on your router to your ipaddress" % port) return False diff --git a/src/util/UpnpPunch.py b/src/util/UpnpPunch.py index df8fe026..9ed4a7ab 100644 --- a/src/util/UpnpPunch.py +++ b/src/util/UpnpPunch.py @@ -1,7 +1,10 @@ -import socket -import re -import urllib2 -import httplib +import gevent +from gevent import socket +from gevent import monkey + +monkey.patch_socket() + +import re, urllib2, httplib from urlparse import urlparse from xml.dom.minidom import parseString @@ -9,143 +12,191 @@ from xml.dom.minidom import parseString # General TODOs: # Handle 0 or >1 IGDs -# Format the SOAP AddPortEntry message correctly (remove spaces/whitespace) -# Find robust way to find own ip + +remove_whitespace = re.compile(r'>\s*<') def _m_search_ssdp(): - """ - Broadcast a UDP SSDP M-SEARCH packet and return response. - """ - search_target = "urn:schemas-upnp-org:device:InternetGatewayDevice:1" + """ + Broadcast a UDP SSDP M-SEARCH packet and return response. + """ + search_target = "urn:schemas-upnp-org:device:InternetGatewayDevice:1" - ssdp_request = ''.join( - ['M-SEARCH * HTTP/1.1\r\n', - 'HOST: 239.255.255.250:1900\r\n', - 'MAN: "ssdp:discover"\r\n', - 'MX: 2\r\n', - 'ST: {0}\r\n'.format(search_target), - '\r\n'] - ) + ssdp_request = ''.join( + ['M-SEARCH * HTTP/1.1\r\n', + 'HOST: 239.255.255.250:1900\r\n', + 'MAN: "ssdp:discover"\r\n', + 'MX: 2\r\n', + 'ST: {0}\r\n'.format(search_target), + '\r\n'] + ) - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.sendto(ssdp_request, ('239.255.255.250', 1900)) + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.sendto(ssdp_request, ('239.255.255.250', 1900)) + sock.settimeout(5) - # TODO: add timeout - return sock.recv(1024) + try: + data = sock.recv(2048) + except SocketError: + # socket has stopped reading on windows + pass + + return data def _retrieve_location_from_ssdp(response): - """ - Parse raw HTTP response to retrieve the UPnP location header - and return a ParseResult object. - """ - parsed = re.findall(r'(?P.*?): (?P.*?)\r\n', response) - location_header = filter(lambda x: x[0].lower() == 'location', parsed) + """ + Parse raw HTTP response to retrieve the UPnP location header + and return a ParseResult object. + """ + parsed = re.findall(r'(?P.*?): (?P.*?)\r\n', response) + location_header = filter(lambda x: x[0].lower() == 'location', parsed) - if not len(location_header): - # no location header returned :( - return False + if not len(location_header): + # no location header returned :( + return False - return urlparse(location_header[0][1]) + return urlparse(location_header[0][1]) def _retrieve_igd_profile(url): - """ - Retrieve the device's UPnP profile. - """ - # TODO: add exception handling - return urllib2.urlopen(url.geturl()).read() + """ + Retrieve the device's UPnP profile. + """ + return urllib2.urlopen(url.geturl()).read() -def __get_node_value(node): - """ - Get the text value of the first child text node of a node. - """ - return node.childeNodes[0].data +def _node_val(node): + """ + Get the text value of the first child text node of a node. + """ + return node.childNodes[0].data def _parse_igd_profile(profile_xml): - """ - Traverse the profile xml DOM looking for either - WANIPConnection or WANPPPConnection and return - the value found as well as the 'controlURL'. - """ - # TODO: return upnp schema as well - dom = parseString(profile_xml) + """ + Traverse the profile xml DOM looking for either + WANIPConnection or WANPPPConnection and return + the value found as well as the 'controlURL'. + """ + dom = parseString(profile_xml) - service_types = dom.getElementsByTagName('serviceType') - for service in service_types: - if __get_node_value(service).find('WANIPConnection') > 0 or \ - __get_node_value(service).find('WANPPPConnection') > 0: - control_url = service.parentNode.getElementsByTagName( - 'controlURL' - )[0].childNodes[0].data + service_types = dom.getElementsByTagName('serviceType') + for service in service_types: + if _node_val(service).find('WANIPConnection') > 0 or \ + _node_val(service).find('WANPPPConnection') > 0: + control_url = service.parentNode.getElementsByTagName( + 'controlURL' + )[0].childNodes[0].data + upnp_schema = _node_val(service).split(':')[-2] + return control_url, upnp_schema - return control_url, upnp_schema + return False + + +def _get_local_ip(): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + # not using because gevents getaddrinfo doesn't like that + # using port 1 as per hobbldygoop's comment about port 0 not working on osx: + # https://github.com/sirMackk/ZeroNet/commit/fdcd15cf8df0008a2070647d4d28ffedb503fba2#commitcomment-9863928 + s.connect(('239.255.255.250', 1)) + return s.getsockname()[0] def _create_soap_message(port, description="UPnPPunch", protocol="TCP", - upnp_schema='WANIPConnection'): - """ - Build a SOAP AddPortMapping message. - """ - # TODO: get current ip - current_ip = '192.168.0.2' + upnp_schema='WANIPConnection'): + """ + Build a SOAP AddPortMapping message. + """ + current_ip = _get_local_ip() - soap_message = """ + soap_message = """ - - - - {port} - {protocol} - {port} - {host_ip} - 1 - {description} - 0 - - + + + + {port} + {protocol} + {port} + {host_ip} + 1 + {description} + 0 + + """.format(port=port, - protocol=protocol, - host_ip=current_ip, - description=description, - upnp_schema=upnp_schema) + protocol=protocol, + host_ip=current_ip, + description=description, + upnp_schema=upnp_schema) + return remove_whitespace.sub('><', soap_message) - return soap_message + +def _parse_for_errors(soap_response): + if soap_response.status == 500: + err_dom = parseString(soap_response.read()) + err_code = _node_val(err_dom.getElementsByTagName('errorCode')[0]) + err_msg = _node_val( + err_dom.getElementsByTagName('errorDescription')[0] + ) + raise Exception( + 'SOAP request error: {0} - {1}'.format(err_code, err_msg) + ) + return False + else: + return True def _send_soap_request(location, upnp_schema, control_url, soap_message): - """ - Send out SOAP request to UPnP device and return a response. - """ - headers = { - 'SOAPAction': ( - '"urn:schemas-upnp-org:service:{schema}:' - '1#AddPortMapping"'.format(schema=upnp_schema) - ), - 'Content-Type': 'text/xml' - } - conn = httplib.HTTPConnection(location.hostname, location.port) - conn.request('POST', control_url, soap_message, headers) + """ + Send out SOAP request to UPnP device and return a response. + """ + headers = { + 'SOAPAction': ( + '"urn:schemas-upnp-org:service:{schema}:' + '1#AddPortMapping"'.format(schema=upnp_schema) + ), + 'Content-Type': 'text/xml' + } + conn = httplib.HTTPConnection(location.hostname, location.port) + conn.request('POST', control_url, soap_message, headers) - response_body = conn.getresponse().read() + response = conn.getresponse() + conn.close() - return response_body + return _parse_for_errors(response) -def open_port(port=15441): - """ - Attempt to forward a port using UPnP. - """ - location = _retrieve_location_from_ssdp(_m_search_ssdp()) - control_url, upnp_schema = _parse_igd_profile( - _retrieve_igd_profile(location) - ) +def open_port(port=15441, desc="UpnpPunch"): + """ + Attempt to forward a port using UPnP. + """ - for protocol in ["TCP", "UDP"]: - message = _create_soap_message(port, protocol, upnp_schema) - # TODO: gevent this - _send_soap_request(location, upnp_schema, control_url, message) - # TODO: handle error code in response + location = _retrieve_location_from_ssdp(_m_search_ssdp()) + + if not location: + return False + + parsed = _parse_igd_profile( + _retrieve_igd_profile(location) + ) + + if not parsed: + return False + + control_url, upnp_schema = parsed + + soap_messages = [_create_soap_message(port, desc, proto, upnp_schema) + for proto in ['TCP', 'UDP']] + + requests = [gevent.spawn( + _send_soap_request, location, upnp_schema, control_url, message + ) for message in soap_messages] + + gevent.joinall(requests, timeout=3) + + if all(requests): + return True + else: + return False diff --git a/tools/upnpc/Changelog.txt b/tools/upnpc/Changelog.txt deleted file mode 100644 index f09215cd..00000000 --- a/tools/upnpc/Changelog.txt +++ /dev/null @@ -1,585 +0,0 @@ -$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $ -miniUPnP client Changelog. - -2014/02/05: - handle EINPROGRESS after connect() - -2014/02/03: - minixml now handle XML comments - -VERSION 1.9 : released 2014/01/31 - -2014/01/31: - added argument remoteHost to UPNP_GetSpecificPortMappingEntry() - increment API_VERSION to 10 - -2013/12/09: - --help and -h arguments in upnpc.c - -2013/10/07: - fixed potential buffer overrun in miniwget.c - Modified UPNP_GetValidIGD() to check for ExternalIpAddress - -2013/08/01: - define MAXHOSTNAMELEN if not already done - -2013/06/06: - update upnpreplyparse to allow larger values (128 chars instead of 64) - -2013/05/14: - Update upnpreplyparse to take into account "empty" elements - validate upnpreplyparse.c code with "make check" - -2013/05/03: - Fix Solaris build thanks to Maciej Małecki - -2013/04/27: - Fix testminiwget.sh for BSD - -2013/03/23: - Fixed Makefile for *BSD - -2013/03/11: - Update Makefile to use JNAerator version 0.11 - -2013/02/11: - Fix testminiwget.sh for use with dash - Use $(DESTDIR) in Makefile - -VERSION 1.8 : released 2013/02/06 - -2012/10/16: - fix testminiwget with no IPv6 support - -2012/09/27: - Rename all include guards to not clash with C99 - (7.1.3 Reserved identifiers). - -2012/08/30: - Added -e option to upnpc program (set description for port mappings) - -2012/08/29: - Python 3 support (thanks to Christopher Foo) - -2012/08/11: - Fix a memory link in UPNP_GetValidIGD() - Try to handle scope id in link local IPv6 URL under MS Windows - -2012/07/20: - Disable HAS_IP_MREQN on DragonFly BSD - -2012/06/28: - GetUPNPUrls() now inserts scope into link-local IPv6 addresses - -2012/06/23: - More error return checks in upnpc.c - #define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id - parseURL() now parses IPv6 addresses scope - new parameter for miniwget() : IPv6 address scope - increment API_VERSION to 9 - -2012/06/20: - fixed CMakeLists.txt - -2012/05/29 - Improvements in testminiwget.sh - -VERSION 1.7 : released 2012/05/24 - -2012/05/01: - Cleanup settings of CFLAGS in Makefile - Fix signed/unsigned integer comparaisons - -2012/04/20: - Allow to specify protocol with TCP or UDP for -A option - -2012/04/09: - Only try to fetch XML description once in UPNP_GetValidIGD() - Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments. - -2012/04/05: - minor improvements to minihttptestserver.c - -2012/03/15: - upnperrors.c returns valid error string for unrecognized error codes - -2012/03/08: - make minihttptestserver listen on loopback interface instead of 0.0.0.0 - -2012/01/25: - Maven installation thanks to Alexey Kuznetsov - -2012/01/21: - Replace WIN32 macro by _WIN32 - -2012/01/19: - Fixes in java wrappers thanks to Alexey Kuznetsov : - https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc - Make and install .deb packages (python) thanks to Alexey Kuznetsov : - https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc - -2012/01/07: - The multicast interface can now be specified by name with IPv4. - -2012/01/02: - Install man page - -2011/11/25: - added header to Port Mappings list in upnpc.c - -2011/10/09: - Makefile : make clean now removes jnaerator generated files. - MINIUPNPC_VERSION in miniupnpc.h (updated by make) - -2011/09/12: - added rootdescURL to UPNPUrls structure. - -VERSION 1.6 : released 2011/07/25 - -2011/07/25: - Update doc for version 1.6 release - -2011/06/18: - Fix for windows in miniwget.c - -2011/06/04: - display remote host in port mapping listing - -2011/06/03: - Fix in make install : there were missing headers - -2011/05/26: - Fix the socket leak in miniwget thanks to Richard Marsh. - Permit to add leaseduration in -a command. Display lease duration. - -2011/05/15: - Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6 - -2011/05/09: - add a test in testminiwget.sh. - more error checking in miniwget.c - -2011/05/06: - Adding some tool to test and validate miniwget.c - simplified and debugged miniwget.c - -2011/04/11: - moving ReceiveData() to a receivedata.c file. - parsing presentation url - adding IGD v2 WANIPv6FirewallControl commands - -2011/04/10: - update of miniupnpcmodule.c - comments in miniwget.c, update in testminiwget - Adding errors codes from IGD v2 - new functions in upnpc.c for IGD v2 - -2011/04/09: - Support for litteral ip v6 address in miniwget - -2011/04/08: - Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 - Updating APIVERSION - Supporting IPV6 in upnpDiscover() - Adding a -6 option to upnpc command line tool - -2011/03/18: - miniwget/parseURL() : return an error when url param is null. - fixing GetListOfPortMappings() - -2011/03/14: - upnpDiscover() now reporting an error code. - improvements in comments. - -2011/03/11: - adding miniupnpcstrings.h.cmake and CMakeLists.txt files. - -2011/02/15: - Implementation of GetListOfPortMappings() - -2011/02/07: - updates to minixml to support character data starting with spaces - minixml now support CDATA - upnpreplyparse treats specificaly - change in simpleUPnPcommand to return the buffer (simplification) - -2011/02/06: - Added leaseDuration argument to AddPortMapping() - Starting to implement GetListOfPortMappings() - -2011/01/11: - updating wingenminiupnpcstrings.c - -2011/01/04: - improving updateminiupnpcstrings.sh - -VERSION 1.5 : released 2011/01/01 - -2010/12/21: - use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo - -2010/12/11: - Improvements on getHTTPResponse() code. - -2010/12/09: - new code for miniwget that handle Chunked transfer encoding - using getHTTPResponse() in SOAP call code - Adding MANIFEST.in for 'python setup.py bdist_rpm' - -2010/11/25: - changes to minissdpc.c to compile under Win32. - see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729 - -2010/09/17: - Various improvement to Makefile from Michał Górny - -2010/08/05: - Adding the script "external-ip.sh" from Reuben Hawkins - -2010/06/09: - update to python module to match modification made on 2010/04/05 - update to Java test code to match modification made on 2010/04/05 - all UPNP_* function now return an error if the SOAP request failed - at HTTP level. - -2010/04/17: - Using GetBestRoute() under win32 in order to find the - right interface to use. - -2010/04/12: - Retrying with HTTP/1.1 if HTTP/1.0 failed. see - http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703 - -2010/04/07: - avoid returning duplicates in upnpDiscover() - -2010/04/05: - Create a connecthostport.h/.c with connecthostport() function - and use it in miniwget and miniupnpc. - Use getnameinfo() instead of inet_ntop or inet_ntoa - Work to make miniupnpc IPV6 compatible... - Add java test code. - Big changes in order to support device having both WANIPConnection - and WANPPPConnection. - -2010/04/04: - Use getaddrinfo() instead of gethostbyname() in miniwget. - -2010/01/06: - #define _DARWIN_C_SOURCE for Mac OS X - -2009/12/19: - Improve MinGW32 build - -2009/12/11: - adding a MSVC9 project to build the static library and executable - -2009/12/10: - Fixing some compilation stuff for Windows/MinGW - -2009/12/07: - adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS - some fixes for Windows when using virtual ethernet adapters (it is the - case with VMWare installed). - -2009/12/04: - some fixes for AmigaOS compilation - Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked - transfer encoding) - -2009/12/03: - updating printIDG and testigddescparse.c for debug. - modifications to compile under AmigaOS - adding a testminiwget program - Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked - transfer encoding - -2009/11/26: - fixing updateminiupnpcstrings.sh to take into account - which command that does not return an error code. - -VERSION 1.4 : released 2009/10/30 - -2009/10/16: - using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module. - -2009/10/10: - Some fixes for compilation under Solaris - compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464 - -2009/09/21: - fixing the code to ignore EINTR during connect() calls. - -2009/08/07: - Set socket timeout for connect() - Some cleanup in miniwget.c - -2009/08/04: - remove multiple redirections with -d in upnpc.c - Print textual error code in upnpc.c - Ignore EINTR during the connect() and poll() calls. - -2009/07/29: - fix in updateminiupnpcstrings.sh if OS name contains "/" - Sending a correct value for MX: field in SSDP request - -2009/07/20: - Change the Makefile to compile under Mac OS X - Fixed a stackoverflow in getDevicesFromMiniSSDPD() - -2009/07/09: - Compile under Haiku - generate miniupnpcstrings.h.in from miniupnpcstrings.h - -2009/06/04: - patching to compile under CygWin and cross compile for minGW - -VERSION 1.3 : - -2009/04/17: - updating python module - Use strtoull() when using C99 - -2009/02/28: - Fixed miniwget.c for compiling under sun - -2008/12/18: - cleanup in Makefile (thanks to Paul de Weerd) - minissdpc.c : win32 compatibility - miniupnpc.c : changed xmlns prefix from 'm' to 'u' - Removed NDEBUG (using DEBUG) - -2008/10/14: - Added the ExternalHost argument to DeletePortMapping() - -2008/10/11: - Added the ExternalHost argument to AddPortMapping() - Put a correct User-Agent: header in HTTP requests. - -VERSION 1.2 : - -2008/10/07: - Update docs - -2008/09/25: - Integrated sameport patch from Dario Meloni : Added a "sameport" - argument to upnpDiscover(). - -2008/07/18: - small modif to make Clang happy :) - -2008/07/17: - #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... - -2008/07/14: - include declspec.h in installation (to /usr/include/miniupnpc) - -VERSION 1.1 : - -2008/07/04: - standard options for install/ln instead of gnu-specific stuff. - -2008/07/03: - now builds a .dll and .lib with win32. (mingw32) - -2008/04/28: - make install now install the binary of the upnpc tool - -2008/04/27: - added testupnpigd.py - added error strings for miniupnpc "internal" errors - improved python module error/exception reporting. - -2008/04/23: - Completely rewrite igd_desc_parse.c in order to be compatible with - Linksys WAG200G - Added testigddescparse - updated python module - -VERSION 1.0 : - -2008/02/21: - put some #ifdef DEBUG around DisplayNameValueList() - -2008/02/18: - Improved error reporting in upnpcommands.c - UPNP_GetStatusInfo() returns LastConnectionError - -2008/02/16: - better error handling in minisoap.c - improving display of "valid IGD found" in upnpc.c - -2008/02/03: - Fixing UPNP_GetValidIGD() - improved make install :) - -2007/12/22: - Adding upnperrors.c/h to provide a strupnperror() function - used to translate UPnP error codes to string. - -2007/12/19: - Fixing getDevicesFromMiniSSDPD() - improved error reporting of UPnP functions - -2007/12/18: - It is now possible to specify a different location for MiniSSDPd socket. - working with MiniSSDPd is now more efficient. - python module improved. - -2007/12/16: - improving error reporting - -2007/12/13: - Try to improve compatibility by using HTTP/1.0 instead of 1.1 and - XML a bit different for SOAP. - -2007/11/25: - fixed select() call for linux - -2007/11/15: - Added -fPIC to CFLAG for better shared library code. - -2007/11/02: - Fixed a potential socket leak in miniwget2() - -2007/10/16: - added a parameter to upnpDiscover() in order to allow the use of another - interface than the default multicast interface. - -2007/10/12: - Fixed the creation of symbolic link in Makefile - -2007/10/08: - Added man page - -2007/10/02: - fixed memory bug in GetUPNPUrls() - -2007/10/01: - fixes in the Makefile - Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly. - Added SONAME in the shared library to please debian :) - fixed MS Windows compilation (minissdpd is not available under MS Windows). - -2007/09/25: - small change to Makefile to be able to install in a different location - (default is /usr) - -2007/09/24: - now compiling both shared and static library - -2007/09/19: - Cosmetic changes on upnpc.c - -2007/09/02: - adapting to new miniSSDPd (release version ?) - -2007/08/31: - Usage of miniSSDPd to skip discovery process. - -2007/08/27: - fixed python module to allow compilation with Python older than Python 2.4 - -2007/06/12: - Added a python module. - -2007/05/19: - Fixed compilation under MinGW - -2007/05/15: - fixed a memory leak in AddPortMapping() - Added testupnpreplyparse executable to check the parsing of - upnp soap messages - minixml now ignore namespace prefixes. - -2007/04/26: - upnpc now displays external ip address with -s or -l - -2007/04/11: - changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210" - -2007/03/19: - cleanup in miniwget.c - -2007/03/01: - Small typo fix... - -2007/01/30: - Now parsing the HTTP header from SOAP responses in order to - get content-length value. - -2007/01/29: - Fixed the Soap Query to speedup the HTTP request. - added some Win32 DLL stuff... - -2007/01/27: - Fixed some WIN32 compatibility issues - -2006/12/14: - Added UPNPIGD_IsConnected() function in miniupnp.c/.h - Added UPNP_GetValidIGD() in miniupnp.c/.h - cleaned upnpc.c main(). now using UPNP_GetValidIGD() - -2006/12/07: - Version 1.0-RC1 released - -2006/12/03: - Minor changes to compile under SunOS/Solaris - -2006/11/30: - made a minixml parser validator program - updated minixml to handle attributes correctly - -2006/11/22: - Added a -r option to the upnpc sample thanks to Alexander Hubmann. - -2006/11/19: - Cleanup code to make it more ANSI C compliant - -2006/11/10: - detect and display local lan address. - -2006/11/04: - Packets and Bytes Sent/Received are now unsigned int. - -2006/11/01: - Bug fix thanks to Giuseppe D'Angelo - -2006/10/31: - C++ compatibility for .h files. - Added a way to get ip Address on the LAN used to reach the IGD. - -2006/10/25: - Added M-SEARCH to the services in the discovery process. - -2006/10/22: - updated the Makefile to use makedepend, added a "make install" - update Makefile - -2006/10/20: - fixing the description url parsing thanks to patch sent by - Wayne Dawe. - Fixed/translated some comments. - Implemented a better discover process, first looking - for IGD then for root devices (as some devices only reply to - M-SEARCH for root devices). - -2006/09/02: - added freeUPNPDevlist() function. - -2006/08/04: - More command line arguments checking - -2006/08/01: - Added the .bat file to compile under Win32 with minGW32 - -2006/07/31: - Fixed the rootdesc parser (igd_desc_parse.c) - -2006/07/20: - parseMSEARCHReply() is now returning the ST: line as well - starting changes to detect several UPnP devices on the network - -2006/07/19: - using GetCommonLinkProperties to get down/upload bitrate - diff --git a/tools/upnpc/LICENSE b/tools/upnpc/LICENSE deleted file mode 100644 index 240857fc..00000000 --- a/tools/upnpc/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -MiniUPnPc -Copyright (c) 2005-2011, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/tools/upnpc/README b/tools/upnpc/README deleted file mode 100644 index 74306055..00000000 --- a/tools/upnpc/README +++ /dev/null @@ -1,66 +0,0 @@ -Project: miniupnp -Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -github: https://github.com/miniupnp/miniupnp -freecode: http://freecode.com/projects/miniupnp -Author: Thomas Bernard -Copyright (c) 2005-2012 Thomas Bernard -This software is subject to the conditions detailed in the -LICENSE file provided within this distribution. - - -For the comfort of Win32 users, bsdqueue.h is included in the distribution. -Its licence is included in the header of the file. -bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system. - - -* miniUPnP Client - miniUPnPc * - -To compile, simply run 'gmake' (could be 'make' on your system). -Under win32, to compile with MinGW, type "mingw32make.bat". -MS Visual C solution and project files are supplied in the msvc/ subdirectory. - -The compilation is known to work under linux, FreeBSD, -OpenBSD, MacOS X, AmigaOS and cygwin. -The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3. -upx (http://upx.sourceforge.net) is used to compress the win32 .exe files. - -To install the library and headers on the system use : -> su -> make install -> exit - -alternatively, to install into a specific location, use : -> INSTALLPREFIX=/usr/local make install - -upnpc.c is a sample client using the libminiupnpc. -To use the libminiupnpc in your application, link it with -libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h, -upnpcommands.h and miniwget.h : -- upnpDiscover() -- miniwget() -- parserootdesc() -- GetUPNPUrls() -- UPNP_* (calling UPNP methods) - -Note : use #include etc... for the includes -and -lminiupnpc for the link - -Discovery process is speeded up when MiniSSDPd is running on the machine. - - -* Python module * - -you can build a python module with 'make pythonmodule' -and install it with 'make installpythonmodule'. -setup.py (and setupmingw32.py) are included in the distribution. - - -Feel free to contact me if you have any problem : -e-mail : miniupnp@free.fr - -If you are using libminiupnpc in your application, please -send me an email ! - -For any question, you can use the web forum : -http://miniupnp.tuxfamily.org/forum/ - diff --git a/tools/upnpc/libminiupnpc.a b/tools/upnpc/libminiupnpc.a deleted file mode 100644 index 63c1f171279c4655332bab51ae2204f426a629c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41310 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 diff --git a/tools/upnpc/miniupnpc.def b/tools/upnpc/miniupnpc.def deleted file mode 100644 index 5a9f9e20..00000000 --- a/tools/upnpc/miniupnpc.def +++ /dev/null @@ -1,43 +0,0 @@ -LIBRARY -; miniupnpc library - miniupnpc - -EXPORTS -; miniupnpc - upnpDiscover - freeUPNPDevlist - parserootdesc - UPNP_GetValidIGD - UPNP_GetIGDFromUrl - GetUPNPUrls - FreeUPNPUrls -; miniwget - miniwget - miniwget_getaddr -; upnpcommands - UPNP_GetTotalBytesSent - UPNP_GetTotalBytesReceived - UPNP_GetTotalPacketsSent - UPNP_GetTotalPacketsReceived - UPNP_GetStatusInfo - UPNP_GetConnectionTypeInfo - UPNP_GetExternalIPAddress - UPNP_GetLinkLayerMaxBitRates - UPNP_AddPortMapping - UPNP_DeletePortMapping - UPNP_GetPortMappingNumberOfEntries - UPNP_GetSpecificPortMappingEntry - UPNP_GetGenericPortMappingEntry - UPNP_GetListOfPortMappings - UPNP_AddPinhole - UPNP_CheckPinholeWorking - UPNP_UpdatePinhole - UPNP_GetPinholePackets - UPNP_DeletePinhole - UPNP_GetFirewallStatus - UPNP_GetOutboundPinholeTimeout -; upnperrors - strupnperror -; portlistingparse - ParsePortListing - FreePortListing diff --git a/tools/upnpc/miniupnpc.dll b/tools/upnpc/miniupnpc.dll deleted file mode 100644 index a5ae06671761af68e4dd270b992fb50fce3bd155..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91712 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 C6$r8b diff --git a/tools/upnpc/upnpc-shared.exe b/tools/upnpc/upnpc-shared.exe deleted file mode 100644 index b3cfc2d3a233f55be2267c6221a224dc03bc53fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8704 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