From 2a3a480b43c993de806e1fc5123cd8bf3aaebb8b Mon Sep 17 00:00:00 2001 From: per Date: Sun, 27 Oct 2013 09:12:01 +0100 Subject: [PATCH 1/3] Move build fix in ChangeLog to correct location --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 49f5b2c99..3fc26c825 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,5 @@ 2013-xx-xx: Version 3.1.1 * General: - * Change: Simplify build process by getting rid of bison/flex dependencies (commit:d13bc0de7dd0588351af24dc45d55110d0eed6e8) * Change: Filter out bad maps (commit:acfe83cdf6f44660276ba73931e2cebdc8a250ac) * Change: Also show in the bottom menu, if allies are researching the same as us (commit:b6b6265e4e430486ea44a200bce870b115dfc37f) * Change: Keep showing allied research even while facilities are upgraded (commit:423e358b6715c12dda70ff5f6f2bd0348c09f699) @@ -26,6 +25,7 @@ * Maps: * Fix: Remove lop-sided oil barrels from 4c-pyramidal (commit:6092fe1194529f0c7fe023d9c98973e44f9f9f24) * Build system: + * Change: Simplify build process by getting rid of bison/flex dependencies (commit:d13bc0de7dd0588351af24dc45d55110d0eed6e8) * Fix: Building on OpenBSD (commit:9b9383500fb4c1dd5270a68e3490dc358e2da55f, ticket:3917, commit:47a6d6d4684b993d15e378f6d0877fa043b26ca0, ticket:3845) 2012-12-09: Version 3.1.0 From 8f4adda206597754163f7400f9542512ae862d39 Mon Sep 17 00:00:00 2001 From: vexed Date: Sun, 27 Oct 2013 20:57:38 -0400 Subject: [PATCH 2/3] Upgrade miniupnp to miniupnpc-1.8.20131007 *NOTE* mimiupnp source has been modified so we can compile it without errors! Fix UPnP so it actually works on windows & linux & most likely mac. Add more information about UPnP progress in console. closes ticket:4095 --- 3rdparty/miniupnpc/Changelog.txt | 207 ++++++++- 3rdparty/miniupnpc/LICENSE | 3 +- 3rdparty/miniupnpc/Makefile.am | 5 + 3rdparty/miniupnpc/README | 18 +- 3rdparty/miniupnpc/bsdqueue.h | 12 +- 3rdparty/miniupnpc/codelength.h | 17 +- 3rdparty/miniupnpc/connecthostport.c | 51 ++- 3rdparty/miniupnpc/connecthostport.h | 11 +- 3rdparty/miniupnpc/declspec.h | 6 +- 3rdparty/miniupnpc/igd_desc_parse.c | 13 +- 3rdparty/miniupnpc/igd_desc_parse.h | 9 +- 3rdparty/miniupnpc/minisoap.c | 13 +- 3rdparty/miniupnpc/minisoap.h | 6 +- 3rdparty/miniupnpc/minissdpc.c | 16 +- 3rdparty/miniupnpc/minissdpc.h | 6 +- 3rdparty/miniupnpc/miniupnpc.c | 632 ++++++++++++++------------ 3rdparty/miniupnpc/miniupnpc.h | 48 +- 3rdparty/miniupnpc/miniupnpcstrings.h | 25 +- 3rdparty/miniupnpc/miniupnpctypes.h | 19 + 3rdparty/miniupnpc/miniwget.c | 373 +++++++++------ 3rdparty/miniupnpc/miniwget.h | 14 +- 3rdparty/miniupnpc/minixml.c | 45 +- 3rdparty/miniupnpc/minixml.h | 6 +- 3rdparty/miniupnpc/portlistingparse.c | 159 +++++++ 3rdparty/miniupnpc/portlistingparse.h | 71 +++ 3rdparty/miniupnpc/receivedata.c | 109 +++++ 3rdparty/miniupnpc/receivedata.h | 19 + 3rdparty/miniupnpc/upnpcommands.c | 604 +++++++++++++++++++++--- 3rdparty/miniupnpc/upnpcommands.h | 121 ++++- 3rdparty/miniupnpc/upnperrors.c | 42 +- 3rdparty/miniupnpc/upnperrors.h | 8 +- 3rdparty/miniupnpc/upnpreplyparse.c | 88 +++- 3rdparty/miniupnpc/upnpreplyparse.h | 19 +- lib/netplay/netplay.cpp | 85 ++-- lib/netplay/netplay.vcxproj | 5 + lib/netplay/netplay.vcxproj.filters | 15 + src/frontend.cpp | 2 +- src/multiint.cpp | 15 +- 38 files changed, 2243 insertions(+), 674 deletions(-) create mode 100644 3rdparty/miniupnpc/miniupnpctypes.h create mode 100644 3rdparty/miniupnpc/portlistingparse.c create mode 100644 3rdparty/miniupnpc/portlistingparse.h create mode 100644 3rdparty/miniupnpc/receivedata.c create mode 100644 3rdparty/miniupnpc/receivedata.h diff --git a/3rdparty/miniupnpc/Changelog.txt b/3rdparty/miniupnpc/Changelog.txt index 88498314f..4fa6cee31 100644 --- a/3rdparty/miniupnpc/Changelog.txt +++ b/3rdparty/miniupnpc/Changelog.txt @@ -1,6 +1,205 @@ -$Id: Changelog.txt,v 1.125 2010/12/21 16:13:13 nanard Exp $ +$Id: Changelog.txt,v 1.189 2013/10/07 10:04:55 nanard Exp $ miniUPnP client Changelog. +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 @@ -155,7 +354,7 @@ VERSION 1.2 : small modif to make Clang happy :) 2008/07/17: - #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... + #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... 2008/07/14: include declspec.h in installation (to /usr/include/miniupnpc) @@ -177,7 +376,7 @@ VERSION 1.1 : improved python module error/exception reporting. 2008/04/23: - Completely rewrite igd_desc_parse.c in order to be compatible with + Completely rewrite igd_desc_parse.c in order to be compatible with Linksys WAG200G Added testigddescparse updated python module @@ -200,7 +399,7 @@ VERSION 1.0 : improved make install :) 2007/12/22: - Adding upnperrors.c/h to provide a strupnperror() function + Adding upnperrors.c/h to provide a strupnperror() function used to translate UPnP error codes to string. 2007/12/19: diff --git a/3rdparty/miniupnpc/LICENSE b/3rdparty/miniupnpc/LICENSE index 2b561fb4f..ac89a7516 100644 --- a/3rdparty/miniupnpc/LICENSE +++ b/3rdparty/miniupnpc/LICENSE @@ -1,4 +1,5 @@ -Copyright (c) 2005-2009, Thomas BERNARD +MiniUPnPc +Copyright (c) 2005-2011, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/3rdparty/miniupnpc/Makefile.am b/3rdparty/miniupnpc/Makefile.am index 84a8010c6..1d4826561 100644 --- a/3rdparty/miniupnpc/Makefile.am +++ b/3rdparty/miniupnpc/Makefile.am @@ -18,8 +18,11 @@ noinst_HEADERS = \ minissdpc.h \ miniupnpc.h \ miniupnpcstrings.h \ + miniupnpctypes.h \ miniwget.h \ minixml.h \ + portlistingparse.h \ + receivedata.h \ upnpcommands.h \ upnperrors.h \ upnpreplyparse.h @@ -32,6 +35,8 @@ libminiupnpc_a_SOURCES = \ miniupnpc.c \ miniwget.c \ minixml.c \ + portlistingparse.c \ + receivedata.c \ upnpcommands.c \ upnperrors.c \ upnpreplyparse.c diff --git a/3rdparty/miniupnpc/README b/3rdparty/miniupnpc/README index 429507062..b23478de9 100644 --- a/3rdparty/miniupnpc/README +++ b/3rdparty/miniupnpc/README @@ -1,28 +1,35 @@ 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-2009 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 * + +* 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 in a specific location, use : +alternatively, to install into a specific location, use : > INSTALLPREFIX=/usr/local make install upnpc.c is a sample client using the libminiupnpc. @@ -40,9 +47,10 @@ 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' +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. @@ -53,4 +61,6 @@ 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/3rdparty/miniupnpc/bsdqueue.h b/3rdparty/miniupnpc/bsdqueue.h index 1fe0599f5..c6afe1f7c 100644 --- a/3rdparty/miniupnpc/bsdqueue.h +++ b/3rdparty/miniupnpc/bsdqueue.h @@ -36,7 +36,7 @@ #define _SYS_QUEUE_H_ /* - * This file defines five types of data structures: singly-linked lists, + * This file defines five types of data structures: singly-linked lists, * lists, simple queues, tail queues, and circular queues. * * @@ -95,7 +95,7 @@ struct name { \ struct type *slh_first; /* first element */ \ } - + #define SLIST_HEAD_INITIALIZER(head) \ { NULL } @@ -107,7 +107,7 @@ struct name { \ struct { \ struct type *sle_next; /* next element */ \ } - + /* * Singly-linked List access methods. */ @@ -322,8 +322,8 @@ struct { \ struct type **tqe_prev; /* address of previous next element */ \ } -/* - * tail queue access methods +/* + * tail queue access methods */ #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_END(head) NULL @@ -430,7 +430,7 @@ struct { \ } /* - * Circular queue access methods + * Circular queue access methods */ #define CIRCLEQ_FIRST(head) ((head)->cqh_first) #define CIRCLEQ_LAST(head) ((head)->cqh_last) diff --git a/3rdparty/miniupnpc/codelength.h b/3rdparty/miniupnpc/codelength.h index f11e5e936..d342bd141 100644 --- a/3rdparty/miniupnpc/codelength.h +++ b/3rdparty/miniupnpc/codelength.h @@ -1,18 +1,25 @@ -/* $Id: codelength.h,v 1.1 2008/10/06 22:04:06 nanard Exp $ */ +/* $Id: codelength.h,v 1.4 2012/09/27 15:40:29 nanard Exp $ */ /* Project : miniupnp * Author : Thomas BERNARD - * copyright (c) 2005-2008 Thomas Bernard + * copyright (c) 2005-2011 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ -#ifndef __CODELENGTH_H__ -#define __CODELENGTH_H__ +#ifndef CODELENGTH_H_INCLUDED +#define CODELENGTH_H_INCLUDED /* Encode length by using 7bit per Byte : * Most significant bit of each byte specifies that the * following byte is part of the code */ #define DECODELENGTH(n, p) n = 0; \ do { n = (n << 7) | (*p & 0x7f); } \ - while(*(p++)&0x80); + while((*(p++)&0x80) && (n<(1<<25))); + +#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ + n = 0; \ + do { \ + if((p) >= (p_limit)) break; \ + n = (n << 7) | (*(p) & 0x7f); \ + } while((*((p)++)&0x80) && (n<(1<<25))); #define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ diff --git a/3rdparty/miniupnpc/connecthostport.c b/3rdparty/miniupnpc/connecthostport.c index 5e5da3af7..aabc7a6eb 100644 --- a/3rdparty/miniupnpc/connecthostport.c +++ b/3rdparty/miniupnpc/connecthostport.c @@ -1,7 +1,7 @@ -/* $Id: connecthostport.c,v 1.3 2010/12/21 16:13:14 nanard Exp $ */ +/* $Id: connecthostport.c,v 1.11 2013/08/01 21:21:25 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2010 Thomas Bernard + * Copyright (c) 2010-2013 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -13,18 +13,22 @@ #include #include -#ifdef WIN32 +#ifdef _WIN32 #include #include #include +#define MAXHOSTNAMELEN 64 #define snprintf _snprintf #define herror #define socklen_t int -#else /* #ifdef WIN32 */ +#else /* #ifdef _WIN32 */ #include +#include +#include #include #define closesocket close #include +#include /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions * during the connect() call */ #define MINIUPNPC_IGNORE_EINTR @@ -32,10 +36,10 @@ #include #include #endif /* #ifndef USE_GETHOSTBYNAME */ -#endif /* #else WIN32 */ +#endif /* #else _WIN32 */ /* definition of PRINT_SOCKET_ERROR */ -#ifdef WIN32 +#ifdef _WIN32 #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #else #define PRINT_SOCKET_ERROR(x) perror(x) @@ -47,16 +51,22 @@ #include "connecthostport.h" +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + /* connecthostport() * return a socket connected (TCP) to the host and port * or -1 in case of error */ -int connecthostport(const char * host, unsigned short port) +int connecthostport(const char * host, unsigned short port, + unsigned int scope_id) { int s, n; #ifdef USE_GETHOSTBYNAME struct sockaddr_in dest; struct hostent *hp; #else /* #ifdef USE_GETHOSTBYNAME */ + char tmp_host[MAXHOSTNAMELEN+1]; char port_str[8]; struct addrinfo *ai, *p; struct addrinfo hints; @@ -64,7 +74,7 @@ int connecthostport(const char * host, unsigned short port) #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT struct timeval timeout; #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - + #ifdef USE_GETHOSTBYNAME hp = gethostbyname(host); if(hp == NULL) @@ -139,10 +149,27 @@ int connecthostport(const char * host, unsigned short port) hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ /* hints.ai_protocol = IPPROTO_TCP; */ snprintf(port_str, sizeof(port_str), "%hu", port); - n = getaddrinfo(host, port_str, &hints, &ai); + if(host[0] == '[') + { + /* literal ip v6 address */ + int i, j; + for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++) + { + tmp_host[i] = host[j]; + if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */ + j+=2; /* skip "25" */ + } + tmp_host[i] = '\0'; + } + else + { + strncpy(tmp_host, host, MAXHOSTNAMELEN); + } + tmp_host[MAXHOSTNAMELEN] = '\0'; + n = getaddrinfo(tmp_host, port_str, &hints, &ai); if(n != 0) { -#ifdef WIN32 +#ifdef _WIN32 fprintf(stderr, "getaddrinfo() error : %d\n", n); #else fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); @@ -155,6 +182,10 @@ int connecthostport(const char * host, unsigned short port) s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if(s < 0) continue; + if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) { + struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr; + addr6->sin6_scope_id = scope_id; + } #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT /* setting a 3 seconds timeout for the connect() call */ timeout.tv_sec = 3; diff --git a/3rdparty/miniupnpc/connecthostport.h b/3rdparty/miniupnpc/connecthostport.h index 57e24eb27..56941d6fa 100644 --- a/3rdparty/miniupnpc/connecthostport.h +++ b/3rdparty/miniupnpc/connecthostport.h @@ -1,17 +1,18 @@ -/* $Id: connecthostport.h,v 1.1 2010/04/04 23:21:03 nanard Exp $ */ +/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard - * Copyright (c) 2010 Thomas Bernard + * Copyright (c) 2010-2012 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ -#ifndef __CONNECTHOSTPORT_H__ -#define __CONNECTHOSTPORT_H__ +#ifndef CONNECTHOSTPORT_H_INCLUDED +#define CONNECTHOSTPORT_H_INCLUDED /* connecthostport() * return a socket connected (TCP) to the host and port * or -1 in case of error */ -int connecthostport(const char * host, unsigned short port); +int connecthostport(const char * host, unsigned short port, + unsigned int scope_id); #endif diff --git a/3rdparty/miniupnpc/declspec.h b/3rdparty/miniupnpc/declspec.h index b804247d2..f66b6d7cb 100644 --- a/3rdparty/miniupnpc/declspec.h +++ b/3rdparty/miniupnpc/declspec.h @@ -1,7 +1,7 @@ -#ifndef __DECLSPEC_H__ -#define __DECLSPEC_H__ +#ifndef DECLSPEC_H_INCLUDED +#define DECLSPEC_H_INCLUDED -#if defined(WIN32) && !defined(STATICLIB) +#if defined(_WIN32) && !defined(STATICLIB) #ifdef MINIUPNP_EXPORTS #define LIBSPEC __declspec(dllexport) #else diff --git a/3rdparty/miniupnpc/igd_desc_parse.c b/3rdparty/miniupnpc/igd_desc_parse.c index 8df6950e1..6c3e65677 100644 --- a/3rdparty/miniupnpc/igd_desc_parse.c +++ b/3rdparty/miniupnpc/igd_desc_parse.c @@ -1,4 +1,4 @@ -/* $Id: igd_desc_parse.c,v 1.11 2010/12/11 17:56:51 nanard Exp $ */ +/* $Id: igd_desc_parse.c,v 1.14 2011/04/11 09:19:24 nanard Exp $ */ /* Project : miniupnp * http://miniupnp.free.fr/ * Author : Thomas Bernard @@ -46,6 +46,9 @@ void IGDendelt(void * d, const char * name, int l) if(0==strcmp(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) { memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); + } else if(0==strcmp(datas->tmp.servicetype, + "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1")) { + memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); } else if(0==strcmp(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANIPConnection:1") || 0==strcmp(datas->tmp.servicetype, @@ -69,6 +72,8 @@ void IGDdata(void * d, const char * data, int l) datas->level, datas->cureltname, l, data); */ if( !strcmp(datas->cureltname, "URLBase") ) dstmember = datas->urlbase; + else if( !strcmp(datas->cureltname, "presentationURL") ) + dstmember = datas->presentationurl; else if( !strcmp(datas->cureltname, "serviceType") ) dstmember = datas->tmp.servicetype; else if( !strcmp(datas->cureltname, "controlURL") ) @@ -109,6 +114,12 @@ void printIGD(struct IGDdatas * d) printf(" controlURL = '%s'\n", d->second.controlurl); printf(" eventSubURL = '%s'\n", d->second.eventsuburl); printf(" SCPDURL = '%s'\n", d->second.scpdurl); + printf("WAN IPv6 Firewall Control :\n"); + /*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/ + printf(" servicetype = '%s'\n", d->IPv6FC.servicetype); + printf(" controlURL = '%s'\n", d->IPv6FC.controlurl); + printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); + printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); } diff --git a/3rdparty/miniupnpc/igd_desc_parse.h b/3rdparty/miniupnpc/igd_desc_parse.h index 40cca60b2..0a49b019d 100644 --- a/3rdparty/miniupnpc/igd_desc_parse.h +++ b/3rdparty/miniupnpc/igd_desc_parse.h @@ -1,4 +1,4 @@ -/* $Id: igd_desc_parse.h,v 1.7 2010/04/05 20:36:59 nanard Exp $ */ +/* $Id: igd_desc_parse.h,v 1.11 2012/10/16 16:49:02 nanard Exp $ */ /* Project : miniupnp * http://miniupnp.free.fr/ * Author : Thomas Bernard @@ -6,8 +6,8 @@ * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ -#ifndef __IGD_DESC_PARSE_H__ -#define __IGD_DESC_PARSE_H__ +#ifndef IGD_DESC_PARSE_H_INCLUDED +#define IGD_DESC_PARSE_H_INCLUDED /* Structure to store the result of the parsing of UPnP * descriptions of Internet Gateway Devices */ @@ -23,6 +23,7 @@ struct IGDdatas_service { struct IGDdatas { char cureltname[MINIUPNPC_URL_MAXSIZE]; char urlbase[MINIUPNPC_URL_MAXSIZE]; + char presentationurl[MINIUPNPC_URL_MAXSIZE]; int level; /*int state;*/ /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ @@ -32,6 +33,8 @@ struct IGDdatas { struct IGDdatas_service first; /* if both WANIPConnection and WANPPPConnection are present */ struct IGDdatas_service second; + /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ + struct IGDdatas_service IPv6FC; /* tmp */ struct IGDdatas_service tmp; }; diff --git a/3rdparty/miniupnpc/minisoap.c b/3rdparty/miniupnpc/minisoap.c index a834c5e2a..e45a481ac 100644 --- a/3rdparty/miniupnpc/minisoap.c +++ b/3rdparty/miniupnpc/minisoap.c @@ -1,7 +1,7 @@ -/* $Id: minisoap.c,v 1.20 2010/12/11 17:56:51 nanard Exp $ */ +/* $Id: minisoap.c,v 1.22 2012/01/21 13:30:31 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2009 Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * @@ -9,7 +9,7 @@ */ #include #include -#ifdef WIN32 +#ifdef _WIN32 #include #include #define snprintf _snprintf @@ -24,7 +24,7 @@ /* only for malloc */ #include -#ifdef WIN32 +#ifdef _WIN32 #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #else #define PRINT_SOCKET_ERROR(x) perror(x) @@ -57,7 +57,7 @@ httpWrite(int fd, const char * body, int bodysize, /* disable send on the socket */ /* draytek routers dont seems to like that... */ #if 0 -#ifdef WIN32 +#ifdef _WIN32 if(shutdown(fd, SD_SEND)<0) { #else if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/ @@ -112,7 +112,8 @@ int soapPostSubmit(int fd, printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n", url, httpversion, host, portstr); printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize); - /*printf("%s", headerbuf);*/ + printf("Headers :\n%s", headerbuf); + printf("Body :\n%s\n", body); #endif return httpWrite(fd, body, bodysize, headerbuf, headerssize); } diff --git a/3rdparty/miniupnpc/minisoap.h b/3rdparty/miniupnpc/minisoap.h index 696725f62..14c859d1e 100644 --- a/3rdparty/miniupnpc/minisoap.h +++ b/3rdparty/miniupnpc/minisoap.h @@ -1,11 +1,11 @@ -/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */ +/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ -#ifndef __MINISOAP_H__ -#define __MINISOAP_H__ +#ifndef MINISOAP_H_INCLUDED +#define MINISOAP_H_INCLUDED /*int httpWrite(int, const char *, int, const char *);*/ int soapPostSubmit(int, const char *, const char *, unsigned short, diff --git a/3rdparty/miniupnpc/minissdpc.c b/3rdparty/miniupnpc/minissdpc.c index e4d6d467c..e0a8efc03 100644 --- a/3rdparty/miniupnpc/minissdpc.c +++ b/3rdparty/miniupnpc/minissdpc.c @@ -1,18 +1,18 @@ -/* $Id: minissdpc.c,v 1.14 2010/11/25 09:57:25 nanard Exp $ */ +/* $Id: minissdpc.c,v 1.16 2012/03/05 19:42:46 nanard Exp $ */ /* Project : miniupnp + * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD - * copyright (c) 2005-2009 Thomas Bernard + * copyright (c) 2005-2012 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ /*#include */ -#include #include #include #include #include #include -#if defined(WIN32) || defined(__amigaos__) || defined(__amigaos4__) -#ifdef WIN32 +#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) +#ifdef _WIN32 #include #include #include @@ -41,6 +41,10 @@ struct sockaddr_un { #include "codelength.h" +#if defined(_MSC_VER) +typedef SSIZE_T ssize_t; +#endif + struct UPNPDev * getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath) { @@ -120,7 +124,7 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath) p += stsize; tmp->buffer[urlsize+1+stsize] = '\0'; devlist = tmp; - /* added for compatibility with recent versions of MiniSSDPd + /* added for compatibility with recent versions of MiniSSDPd * >= 2007/12/19 */ DECODELENGTH(usnsize, p); p += usnsize; diff --git a/3rdparty/miniupnpc/minissdpc.h b/3rdparty/miniupnpc/minissdpc.h index 25e91ce31..915b0026f 100644 --- a/3rdparty/miniupnpc/minissdpc.h +++ b/3rdparty/miniupnpc/minissdpc.h @@ -1,12 +1,12 @@ -/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */ +/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author: Thomas Bernard * Copyright (c) 2005-2007 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ -#ifndef __MINISSDPC_H__ -#define __MINISSDPC_H__ +#ifndef MINISSDPC_H_INCLUDED +#define MINISSDPC_H_INCLUDED struct UPNPDev * getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath); diff --git a/3rdparty/miniupnpc/miniupnpc.c b/3rdparty/miniupnpc/miniupnpc.c index d91591c2c..7444e1d11 100644 --- a/3rdparty/miniupnpc/miniupnpc.c +++ b/3rdparty/miniupnpc/miniupnpc.c @@ -1,7 +1,8 @@ -/* $Id: miniupnpc.c,v 1.85 2010/12/21 16:13:14 nanard Exp $ */ +/* $Id: miniupnpc.c,v 1.113 2013/10/07 10:04:56 nanard Exp $ */ /* Project : miniupnp + * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD - * copyright (c) 2005-2010 Thomas Bernard + * copyright (c) 2005-2013 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #define __EXTENSIONS__ 1 @@ -16,23 +17,31 @@ #endif #endif +#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(MACOSX) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) +// NOTE: This breaks our builds. (linux). All other builds don't use this. +//#define HAS_IP_MREQN +#endif + #include #include #include -#ifdef WIN32 +#ifdef _WIN32 /* Win32 Specific includes and defines */ #include #include #include #include #define snprintf _snprintf +#define strdup _strdup +#ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define strncasecmp _memicmp #else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #define strncasecmp memicmp #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ +#endif /* #ifndef strncasecmp */ #define MAXHOSTNAMELEN 64 -#else /* #ifdef WIN32 */ +#else /* #ifdef _WIN32 */ /* Standard POSIX includes */ #include #if defined(__amigaos__) && !defined(__amigaos4__) @@ -47,14 +56,14 @@ #include #include #include +#include #if !defined(__amigaos__) && !defined(__amigaos4__) #include #endif #include #include #define closesocket close -#define MINIUPNPC_IGNORE_EINTR -#endif /* #else WIN32 */ +#endif /* #else _WIN32 */ #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT #include #endif @@ -70,13 +79,18 @@ #include "minixml.h" #include "upnpcommands.h" #include "connecthostport.h" +#include "receivedata.h" -#ifdef WIN32 +#ifdef _WIN32 #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); #else #define PRINT_SOCKET_ERROR(x) perror(x) #endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + #define SOAPPREFIX "s" #define SERVICEPREFIX "u" #define SERVICEPREFIX2 'u' @@ -99,85 +113,14 @@ LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * d #endif } -#if 0 -/* getcontentlenfromline() : parse the Content-Length HTTP header line. - * Content-length: nnn */ -static int getcontentlenfromline(const char * p, int n) -{ - static const char contlenstr[] = "content-length"; - const char * p2 = contlenstr; - int a = 0; - while(*p2) - { - if(n==0) - return -1; - if(*p2 != *p && *p2 != (*p + 32)) - return -1; - p++; p2++; n--; - } - if(n==0) - return -1; - if(*p != ':') - return -1; - p++; n--; - while(*p == ' ') - { - if(n==0) - return -1; - p++; n--; - } - while(*p >= '0' && *p <= '9') - { - if(n==0) - return -1; - a = (a * 10) + (*p - '0'); - p++; n--; - } - return a; -} - -/* getContentLengthAndHeaderLength() - * retrieve header length and content length from an HTTP response - * TODO : retrieve Transfer-Encoding: header value, in order to support - * HTTP/1.1, chunked transfer encoding must be supported. */ -static void -getContentLengthAndHeaderLength(char * p, int n, - int * contentlen, int * headerlen) -{ - char * line; - int linelen; - int r; - line = p; - while(line < p + n) - { - linelen = 0; - while(line[linelen] != '\r' && line[linelen] != '\r') - { - if(line+linelen >= p+n) - return; - linelen++; - } - r = getcontentlenfromline(line, linelen); - if(r>0) - *contentlen = r; - line = line + linelen + 2; - if(line[0] == '\r' && line[1] == '\n') - { - *headerlen = (line - p) + 2; - return; - } - } -} -#endif - /* simpleUPnPcommand2 : * not so simple ! * return values : - * 0 - OK - * -1 - error */ -static int simpleUPnPcommand2(int s, const char * url, const char * service, + * pointer - OK + * NULL - error */ +char * simpleUPnPcommand2(int s, const char * url, const char * service, const char * action, struct UPNParg * args, - char * buffer, int * bufsize, const char * httpversion) + int * bufsize, const char * httpversion) { char hostname[MAXHOSTNAMELEN+1]; unsigned short port = 0; @@ -185,10 +128,9 @@ static int simpleUPnPcommand2(int s, const char * url, const char * service, char soapact[128]; char soapbody[2048]; char * buf; - /*int buffree;*/ int n; - /*int contentlen, headerlen;*/ /* for the response */ + *bufsize = 0; snprintf(soapact, sizeof(soapact), "%s#%s", service, action); if(args==NULL) { @@ -223,8 +165,7 @@ static int simpleUPnPcommand2(int s, const char * url, const char * service, if(soapbody + sizeof(soapbody) <= p + 100) { /* we keep a margin of at least 100 bytes */ - *bufsize = 0; - return -1; + return NULL; } *(p++) = '<'; pe = args->elt; @@ -254,14 +195,12 @@ static int simpleUPnPcommand2(int s, const char * url, const char * service, strncpy(p, ">\r\n", soapbody + sizeof(soapbody) - p); } - if(!parseURL(url, hostname, &port, &path)) return -1; - if(s<0) - { - s = connecthostport(hostname, port); - if(s < 0) - { - *bufsize = 0; - return -1; + if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; + if(s < 0) { + s = connecthostport(hostname, port, 0); + if(s < 0) { + /* failed to connect */ + return NULL; } } @@ -271,77 +210,44 @@ static int simpleUPnPcommand2(int s, const char * url, const char * service, printf("Error sending SOAP request\n"); #endif closesocket(s); - return -1; + return NULL; } -#if 0 - contentlen = -1; - headerlen = -1; - buf = buffer; - buffree = *bufsize; - *bufsize = 0; - while ((n = ReceiveData(s, buf, buffree, 5000)) > 0) { - buffree -= n; - buf += n; - *bufsize += n; - getContentLengthAndHeaderLength(buffer, *bufsize, - &contentlen, &headerlen); + buf = getHTTPResponse(s, bufsize); #ifdef DEBUG - printf("received n=%dbytes bufsize=%d ContLen=%d HeadLen=%d\n", - n, *bufsize, contentlen, headerlen); -#endif - /* break if we received everything */ - if(contentlen > 0 && headerlen > 0 && *bufsize >= contentlen+headerlen) - break; - } -#endif - buf = getHTTPResponse(s, &n); - if(n > 0 && buf) + if(*bufsize > 0 && buf) { -#ifdef DEBUG - printf("SOAP Response :\n%.*s\n", n, buf); -#endif - if(*bufsize > n) - { - memcpy(buffer, buf, n); - *bufsize = n; - } - else - { - memcpy(buffer, buf, *bufsize); - } - free(buf); - buf = 0; + printf("SOAP Response :\n%.*s\n", *bufsize, buf); } +#endif closesocket(s); - return 0; + return buf; } /* simpleUPnPcommand : * not so simple ! * return values : - * 0 - OK - * -1 - error */ -int simpleUPnPcommand(int s, const char * url, const char * service, + * pointer - OK + * NULL - error */ +char * simpleUPnPcommand(int s, const char * url, const char * service, const char * action, struct UPNParg * args, - char * buffer, int * bufsize) + int * bufsize) { - int result; - /*int origbufsize = *bufsize;*/ + char * buf; - result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.1"); -/* - result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.0"); - if (result < 0 || *bufsize == 0) +#if 1 + buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); +#else + buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.0"); + if (!buf || *bufsize == 0) { #if DEBUG printf("Error or no result from SOAP request; retrying with HTTP/1.1\n"); #endif - *bufsize = origbufsize; - result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.1"); + buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); } -*/ - return result; +#endif + return buf; } /* parseMSEARCHReply() @@ -357,7 +263,7 @@ parseMSEARCHReply(const char * reply, int size, int a, b, i; i = 0; a = i; /* start of the line */ - b = 0; + b = 0; /* end of the "header" (position of the colon) */ while(isin6_family = AF_INET6; if(sameport) p->sin6_port = htons(PORT); - p->sin6_addr = in6addr_any;//IN6ADDR_ANY_INIT;/*INADDR_ANY;*/ + p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */ } else { struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; p->sin_family = AF_INET; @@ -491,12 +417,13 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, p->sin_port = htons(PORT); p->sin_addr.s_addr = INADDR_ANY; } -#ifdef WIN32 -/* This code could help us to use the right Network interface for +#ifdef _WIN32 +/* This code could help us to use the right Network interface for * SSDP multicast traffic */ /* Get IP associated with the index given in the ip_forward struct * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ - if(GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR) { + if(!ipv6 + && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) { DWORD dwRetVal = 0; PMIB_IPADDRTABLE pIPAddrTable; DWORD dwSize = 0; @@ -550,102 +477,182 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, } #endif -#ifdef WIN32 +#ifdef _WIN32 if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) #else if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) #endif { + if(error) + *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("setsockopt"); return NULL; } if(multicastif) { - struct in_addr mc_if; - mc_if.s_addr = inet_addr(multicastif); - if(0/*ipv6*/) { + if(ipv6) { +#if !defined(_WIN32) + /* according to MSDN, if_nametoindex() is supported since + * MS Windows Vista and MS Windows Server 2008. + * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ + unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ + if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(&ifindex)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#else +#ifdef DEBUG + printf("Setting of multicast interface not supported in IPv6 under Windows.\n"); +#endif +#endif } else { - ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; - } - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); + struct in_addr mc_if; + mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ + if(mc_if.s_addr != INADDR_NONE) + { + ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } + } else { +#ifdef HAS_IP_MREQN + /* was not an ip address, try with an interface name */ + struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */ + memset(&reqn, 0, sizeof(struct ip_mreqn)); + reqn.imr_ifindex = if_nametoindex(multicastif); + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#else +#ifdef DEBUG + printf("Setting of multicast interface not supported with interface name.\n"); +#endif +#endif + } } } /* Avant d'envoyer le paquet on bind pour recevoir la reponse */ - if (bind(sudp, &sockudp_r, 0/*ipv6*/?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)) != 0) + if (bind(sudp, (const struct sockaddr *)&sockudp_r, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) { + if(error) + *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("bind"); closesocket(sudp); return NULL; } + if(error) + *error = UPNPDISCOVER_SUCCESS; /* Calculating maximum response time in seconds */ mx = ((unsigned int)delay) / 1000u; /* receiving SSDP response packet */ - for(n = 0;;) + for(n = 0; deviceList[deviceIndex]; deviceIndex++) { if(n == 0) { /* sending the SSDP M-SEARCH packet */ n = snprintf(bufr, sizeof(bufr), - MSearchMsgFmt, deviceList[deviceIndex++], mx); - /*printf("Sending %s", bufr);*/ + MSearchMsgFmt, + ipv6 ? + (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") + : UPNP_MCAST_ADDR, + deviceList[deviceIndex], mx); +#ifdef DEBUG + printf("Sending %s", bufr); +#endif #ifdef NO_GETADDRINFO /* the following code is not using getaddrinfo */ /* emission */ - memset(&sockudp_w, 0, sizeof(struct sockaddr_in)); - sockudp_w.sin_family = AF_INET; - sockudp_w.sin_port = htons(PORT); - sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); + memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); + if(ipv6) { + struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; + p->sin6_family = AF_INET6; + p->sin6_port = htons(PORT); + inet_pton(AF_INET6, + linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR, + &(p->sin6_addr)); + } else { + struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; + p->sin_family = AF_INET; + p->sin_port = htons(PORT); + p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); + } n = sendto(sudp, bufr, n, 0, - (struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in)); + &sockudp_w, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); if (n < 0) { + if(error) + *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("sendto"); - closesocket(sudp); - return devlist; + break; } #else /* #ifdef NO_GETADDRINFO */ memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; // AF_INET6 or AF_INET + hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */ hints.ai_socktype = SOCK_DGRAM; /*hints.ai_flags = */ - if ((rv = getaddrinfo(UPNP_MCAST_ADDR, XSTR(PORT), &hints, &servinfo)) != 0) { -#ifdef WIN32 + if ((rv = getaddrinfo(ipv6 + ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR) + : UPNP_MCAST_ADDR, + XSTR(PORT), &hints, &servinfo)) != 0) { + if(error) + *error = UPNPDISCOVER_SOCKET_ERROR; +#ifdef _WIN32 fprintf(stderr, "getaddrinfo() failed: %d\n", rv); #else fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); #endif - return devlist; + break; } for(p = servinfo; p; p = p->ai_next) { n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); if (n < 0) { +#ifdef DEBUG + char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; + if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf, + sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { + fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf); + } +#endif PRINT_SOCKET_ERROR("sendto"); continue; } } freeaddrinfo(servinfo); if(n < 0) { - closesocket(sudp); - return devlist; + if(error) + *error = UPNPDISCOVER_SOCKET_ERROR; + break; } #endif /* #ifdef NO_GETADDRINFO */ } /* Waiting for SSDP REPLY packet to M-SEARCH */ - n = ReceiveData(sudp, bufr, sizeof(bufr), delay); + n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); if (n < 0) { /* error */ - closesocket(sudp); - return devlist; + if(error) + *error = UPNPDISCOVER_SOCKET_ERROR; + break; } else if (n == 0) { /* no data or Time Out */ - if (devlist || (deviceList[deviceIndex] == 0)) { + if (devlist) { /* no more device type to look for... */ - closesocket(sudp); - return devlist; + if(error) + *error = UPNPDISCOVER_SUCCESS; + break; + } + if(ipv6) { + if(linklocal) { + linklocal = 0; + --deviceIndex; + } else { + linklocal = 1; + } } } else { const char * descURL=NULL; @@ -672,6 +679,12 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, if(tmp) continue; tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); + if(!tmp) { + /* memory allocation error */ + if(error) + *error = UPNPDISCOVER_MEMORY_ERROR; + break; + } tmp->pNext = devlist; tmp->descURL = tmp->buffer; tmp->st = tmp->buffer + 1 + urlsize; @@ -679,10 +692,13 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, tmp->buffer[urlsize] = '\0'; memcpy(tmp->buffer + urlsize + 1, st, stsize); tmp->buffer[urlsize+1+stsize] = '\0'; + tmp->scope_id = scope_id; devlist = tmp; } } } + closesocket(sudp); + return devlist; } /* freeUPNPDevlist() should be used to @@ -723,39 +739,84 @@ url_cpy_or_cat(char * dst, const char * src, int n) /* Prepare the Urls for usage... */ -LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, - const char * descURL) +LIBSPEC void +GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, + const char * descURL, unsigned int scope_id) { char * p; - int n1, n2, n3; + int n1, n2, n3, n4; +#ifdef IF_NAMESIZE + char ifname[IF_NAMESIZE]; +#else + char scope_str[8]; +#endif + n1 = strlen(data->urlbase); if(n1==0) n1 = strlen(descURL); + if(scope_id != 0) { +#ifdef IF_NAMESIZE + if(if_indextoname(scope_id, ifname)) { + n1 += 3 + strlen(ifname); /* 3 == strlen(%25) */ + } +#else + /* under windows, scope is numerical */ + snprintf(scope_str, sizeof(scope_str), "%u", scope_id); +#endif + } n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ - n2 = n1; n3 = n1; + n2 = n1; n3 = n1; n4 = n1; n1 += strlen(data->first.scpdurl); n2 += strlen(data->first.controlurl); n3 += strlen(data->CIF.controlurl); + n4 += strlen(data->IPv6FC.controlurl); + /* allocate memory to store URLs */ urls->ipcondescURL = (char *)malloc(n1); urls->controlURL = (char *)malloc(n2); urls->controlURL_CIF = (char *)malloc(n3); - /* maintenant on chope la desc du WANIPConnection */ + urls->controlURL_6FC = (char *)malloc(n4); + + /* strdup descURL */ + urls->rootdescURL = strdup(descURL); + + /* get description of WANIPConnection */ if(data->urlbase[0] != '\0') strncpy(urls->ipcondescURL, data->urlbase, n1); else strncpy(urls->ipcondescURL, descURL, n1); p = strchr(urls->ipcondescURL+7, '/'); if(p) p[0] = '\0'; + if(scope_id != 0) { + if(0 == memcmp(urls->ipcondescURL, "http://[fe80:", 13)) { + /* this is a linklocal IPv6 address */ + p = strchr(urls->ipcondescURL, ']'); + if(p) { + /* insert %25 into URL */ +#ifdef IF_NAMESIZE + memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); + memcpy(p, "%25", 3); + memcpy(p + 3, ifname, strlen(ifname)); +#else + memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); + memcpy(p, "%25", 3); + memcpy(p + 3, scope_str, strlen(scope_str)); +#endif + } + } + } strncpy(urls->controlURL, urls->ipcondescURL, n2); strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); - + strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4); + url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1); url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3); + url_cpy_or_cat(urls->controlURL_6FC, data->IPv6FC.controlurl, n4); + #ifdef DEBUG printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL, (unsigned)strlen(urls->ipcondescURL), n1); @@ -763,6 +824,8 @@ LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, (unsigned)strlen(urls->controlURL), n2); printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF, (unsigned)strlen(urls->controlURL_CIF), n3); + printf("urls->controlURL_6FC='%s' %u n4=%d\n", urls->controlURL_6FC, + (unsigned)strlen(urls->controlURL_6FC), n4); #endif } @@ -777,56 +840,10 @@ FreeUPNPUrls(struct UPNPUrls * urls) urls->ipcondescURL = 0; free(urls->controlURL_CIF); urls->controlURL_CIF = 0; -} - - -int ReceiveData(int socket, char * data, int length, int timeout) -{ - int n; -#if !defined(WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) - struct pollfd fds[1]; /* for the poll */ -#ifdef MINIUPNPC_IGNORE_EINTR - do { -#endif - fds[0].fd = socket; - fds[0].events = POLLIN; - n = poll(fds, 1, timeout); -#ifdef MINIUPNPC_IGNORE_EINTR - } while(n < 0 && errno == EINTR); -#endif - if(n < 0) - { - PRINT_SOCKET_ERROR("poll"); - return -1; - } - else if(n == 0) - { - return 0; - } -#else - fd_set socketSet; - TIMEVAL timeval; - FD_ZERO(&socketSet); - FD_SET(socket, &socketSet); - timeval.tv_sec = timeout / 1000; - timeval.tv_usec = (timeout % 1000) * 1000; - n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); - if(n < 0) - { - PRINT_SOCKET_ERROR("select"); - return -1; - } - else if(n == 0) - { - return 0; - } -#endif - n = recv(socket, data, length, 0); - if(n<0) - { - PRINT_SOCKET_ERROR("recv"); - } - return n; + free(urls->controlURL_6FC); + urls->controlURL_6FC = 0; + free(urls->rootdescURL); + urls->rootdescURL = 0; } int @@ -848,13 +865,14 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) /* UPNP_GetValidIGD() : * return values : + * -1 = Internal error * 0 = NO IGD found * 1 = A valid connected IGD has been found * 2 = A valid IGD has been found but it reported as * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * - * In any non zero return case, the urls and data structures + * In any positive non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. */ @@ -864,11 +882,17 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, struct IGDdatas * data, char * lanaddr, int lanaddrlen) { - char * descXML; - int descXMLsize = 0; + struct xml_desc { + char * xml; + int size; + int is_igd; + } * desc = NULL; struct UPNPDev * dev; int ndev = 0; - int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ + int i; + int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ + int n_igd = 0; + char extIpAddr[16]; if(!devlist) { #ifdef DEBUG @@ -876,35 +900,68 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, #endif return 0; } + /* counting total number of devices in the list */ + for(dev = devlist; dev; dev = dev->pNext) + ndev++; + if(ndev > 0) + { + desc = calloc(ndev, sizeof(struct xml_desc)); + if(!desc) + return -1; /* memory allocation error */ + } + /* Step 1 : downloading descriptions and testing type */ + for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) + { + /* we should choose an internet gateway device. + * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ + desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), + lanaddr, lanaddrlen, + dev->scope_id); +#ifdef DEBUG + if(!desc[i].xml) + { + printf("error getting XML description %s\n", dev->descURL); + } +#endif + if(desc[i].xml) + { + memset(data, 0, sizeof(struct IGDdatas)); + memset(urls, 0, sizeof(struct UPNPUrls)); + parserootdesc(desc[i].xml, desc[i].size, data); + if(0==strcmp(data->CIF.servicetype, + "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) + { + desc[i].is_igd = 1; + n_igd++; + } + } + } + /* iterate the list to find a device depending on state */ for(state = 1; state <= 3; state++) { - for(dev = devlist; dev; dev = dev->pNext) + for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { - /* we should choose an internet gateway device. - * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ - descXML = miniwget_getaddr(dev->descURL, &descXMLsize, - lanaddr, lanaddrlen); - if(descXML) + if(desc[i].xml) { - ndev++; memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); - parserootdesc(descXML, descXMLsize, data); - free(descXML); - descXML = NULL; - if(0==strcmp(data->CIF.servicetype, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") - || state >= 3 ) + parserootdesc(desc[i].xml, desc[i].size, data); + if(desc[i].is_igd || state >= 3 ) { - GetUPNPUrls(urls, data, dev->descURL); + GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); + /* in state 2 and 3 we dont test if device is connected ! */ + if(state >= 2) + goto free_and_return; #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif - if((state >= 2) || UPNPIGD_IsConnected(urls, data)) - return state; + /* checks that status is connected AND there is a external IP address assigned */ + if(UPNPIGD_IsConnected(urls, data) + && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) + goto free_and_return; FreeUPNPUrls(urls); if(data->second.servicetype[0] != '\0') { #ifdef DEBUG @@ -915,28 +972,33 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); - GetUPNPUrls(urls, data, dev->descURL); + GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif - if((state >= 2) || UPNPIGD_IsConnected(urls, data)) - return state; + if(UPNPIGD_IsConnected(urls, data) + && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) + goto free_and_return; FreeUPNPUrls(urls); } } memset(data, 0, sizeof(struct IGDdatas)); } -#ifdef DEBUG - else - { - printf("error getting XML description %s\n", dev->descURL); - } -#endif } } - return 0; + state = 0; +free_and_return: + if(desc) { + for(i = 0; i < ndev; i++) { + if(desc[i].xml) { + free(desc[i].xml); + } + } + free(desc); + } + return state; } /* UPNP_GetIGDFromUrl() @@ -953,14 +1015,14 @@ UPNP_GetIGDFromUrl(const char * rootdescurl, char * descXML; int descXMLsize = 0; descXML = miniwget_getaddr(rootdescurl, &descXMLsize, - lanaddr, lanaddrlen); + lanaddr, lanaddrlen, 0); if(descXML) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(descXML, descXMLsize, data); free(descXML); descXML = NULL; - GetUPNPUrls(urls, data, rootdescurl); + GetUPNPUrls(urls, data, rootdescurl, 0); return 1; } else { return 0; diff --git a/3rdparty/miniupnpc/miniupnpc.h b/3rdparty/miniupnpc/miniupnpc.h index 2379ba14c..b3d727dca 100644 --- a/3rdparty/miniupnpc/miniupnpc.h +++ b/3rdparty/miniupnpc/miniupnpc.h @@ -1,16 +1,26 @@ -/* $Id: miniupnpc.h,v 1.19 2009/10/10 19:15:35 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.32 2013/02/06 14:44:42 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard - * Copyright (c) 2005-2006 Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ -#ifndef __MINIUPNPC_H__ -#define __MINIUPNPC_H__ +#ifndef MINIUPNPC_H_INCLUDED +#define MINIUPNPC_H_INCLUDED #include "declspec.h" #include "igd_desc_parse.h" +/* error codes : */ +#define UPNPDISCOVER_SUCCESS (0) +#define UPNPDISCOVER_UNKNOWN_ERROR (-1) +#define UPNPDISCOVER_SOCKET_ERROR (-101) +#define UPNPDISCOVER_MEMORY_ERROR (-102) + +/* versions : */ +#define MINIUPNPC_VERSION "1.8.20131007" +#define MINIUPNPC_API_VERSION 9 + #ifdef __cplusplus extern "C" { #endif @@ -18,14 +28,16 @@ extern "C" { /* Structures definitions : */ struct UPNParg { const char * elt; const char * val; }; -int simpleUPnPcommand(int, const char *, const char *, - const char *, struct UPNParg *, - char *, int *); +char * +simpleUPnPcommand(int, const char *, const char *, + const char *, struct UPNParg *, + int *); struct UPNPDev { struct UPNPDev * pNext; char * descURL; char * st; + unsigned int scope_id; char buffer[2]; }; @@ -42,8 +54,11 @@ struct UPNPDev { * multicast interface for sending SSDP discover packets. * If sameport is not null, SSDP packets will be sent from the source port * 1900 (same as destination port) otherwise system assign a source port. */ -LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport); +LIBSPEC struct UPNPDev * +upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int sameport, + int ipv6, + int * error); /* freeUPNPDevlist() * free list returned by upnpDiscover() */ LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); @@ -57,11 +72,14 @@ LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); * controlURL: controlURL of the WANIPConnection * ipcondescURL: url of the description of the WANIPConnection * controlURL_CIF: controlURL of the WANCommonInterfaceConfig + * controlURL_6FC: controlURL of the WANIPv6FirewallControl */ struct UPNPUrls { char * controlURL; char * ipcondescURL; char * controlURL_CIF; + char * controlURL_6FC; + char * rootdescURL; }; /* UPNP_GetValidIGD() : @@ -93,14 +111,12 @@ UPNP_GetIGDFromUrl(const char * rootdescurl, struct IGDdatas * data, char * lanaddr, int lanaddrlen); -LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *); +LIBSPEC void +GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, + const char *, unsigned int); -LIBSPEC void FreeUPNPUrls(struct UPNPUrls *); - -/* Reads data from the specified socket. - * Returns the number of bytes read if successful, zero if no bytes were - * read or if we timed out. Returns negative if there was an error. */ -int ReceiveData(int socket, char * data, int length, int timeout); +LIBSPEC void +FreeUPNPUrls(struct UPNPUrls *); /* return 0 or 1 */ LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); diff --git a/3rdparty/miniupnpc/miniupnpcstrings.h b/3rdparty/miniupnpc/miniupnpcstrings.h index 4376ade04..40cab7803 100644 --- a/3rdparty/miniupnpc/miniupnpcstrings.h +++ b/3rdparty/miniupnpc/miniupnpcstrings.h @@ -1,26 +1,7 @@ -/* $Id: miniupnpcstrings.h.in,v 1.2 2009/10/30 09:18:18 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2009 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef __MINIUPNPCSTRINGS_H__ -#define __MINIUPNPCSTRINGS_H__ +#ifndef MINIUPNPCSTRINGS_H_INCLUDED +#define MINIUPNPCSTRINGS_H_INCLUDED -#include "lib/framework/wzglobal.h" - -#if defined(WZ_OS_WIN32) #define OS_STRING "Windows" -#elif defined (WZ_OS_MAC) -#define OS_STRING "Mac OS" -#elif defined(WZ_OS_LINUX) -#define OS_STRING "Linux" -#else -#define OS_STRING "Other/unknown" -#endif - -#define MINIUPNPC_VERSION_STRING "1.5" +#define MINIUPNPC_VERSION_STRING "1.7" #endif - diff --git a/3rdparty/miniupnpc/miniupnpctypes.h b/3rdparty/miniupnpc/miniupnpctypes.h new file mode 100644 index 000000000..591c32fb6 --- /dev/null +++ b/3rdparty/miniupnpc/miniupnpctypes.h @@ -0,0 +1,19 @@ +/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ +/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org + * Author : Thomas Bernard + * Copyright (c) 2011 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided within this distribution */ +#ifndef MINIUPNPCTYPES_H_INCLUDED +#define MINIUPNPCTYPES_H_INCLUDED + +#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) +#define UNSIGNED_INTEGER unsigned long long +#define STRTOUI strtoull +#else +#define UNSIGNED_INTEGER unsigned int +#define STRTOUI strtoul +#endif + +#endif + diff --git a/3rdparty/miniupnpc/miniwget.c b/3rdparty/miniupnpc/miniwget.c index 684c8c94d..a75f55b16 100644 --- a/3rdparty/miniupnpc/miniwget.c +++ b/3rdparty/miniupnpc/miniwget.c @@ -1,16 +1,16 @@ -/* $Id: miniwget.c,v 1.41 2010/12/12 23:52:02 nanard Exp $ */ +/* $Id: miniwget.c,v 1.60 2013/10/07 10:03:16 nanard Exp $ */ /* Project : miniupnp + * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2010 Thomas Bernard + * Copyright (c) 2005-2013 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ - + #include #include #include #include -#include "miniupnpc.h" -#ifdef WIN32 +#ifdef _WIN32 #include #include #include @@ -18,12 +18,14 @@ #define MIN(x,y) (((x)<(y))?(x):(y)) #define snprintf _snprintf #define socklen_t int +#ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define strncasecmp _memicmp #else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #define strncasecmp memicmp #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#else /* #ifdef WIN32 */ +#endif /* #ifndef strncasecmp */ +#else /* #ifdef _WIN32 */ #include #include #if defined(__amigaos__) && !defined(__amigaos4__) @@ -32,13 +34,15 @@ #include #endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ #include +#include #include +#include #include #define closesocket close /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions * during the connect() call */ #define MINIUPNPC_IGNORE_EINTR -#endif /* #else WIN32 */ +#endif /* #else _WIN32 */ #if defined(__sun) || defined(sun) #define MIN(x,y) (((x)<(y))?(x):(y)) #endif @@ -46,35 +50,46 @@ #include "miniupnpcstrings.h" #include "miniwget.h" #include "connecthostport.h" +#include "receivedata.h" + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif /* * Read a HTTP response from a socket. * Process Content-Length and Transfer-encoding headers. + * return a pointer to the content buffer, which length is saved + * to the length parameter. */ void * getHTTPResponse(int s, int * size) { char buf[2048]; int n; - int headers = 1; + int endofheaders = 0; int chunked = 0; int content_length = -1; unsigned int chunksize = 0; unsigned int bytestocopy = 0; /* buffers : */ char * header_buf; - int header_buf_len = 2048; - int header_buf_used = 0; + unsigned int header_buf_len = 2048; + unsigned int header_buf_used = 0; char * content_buf; - int content_buf_len = 2048; - int content_buf_used = 0; + unsigned int content_buf_len = 2048; + unsigned int content_buf_used = 0; + char chunksize_buf[32]; + unsigned int chunksize_buf_index; header_buf = malloc(header_buf_len); content_buf = malloc(content_buf_len); + chunksize_buf[0] = '\0'; + chunksize_buf_index = 0; - while((n = ReceiveData(s, buf, 2048, 5000)) > 0) + while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0) { - if(headers) + if(endofheaders == 0) { int i; int linestart=0; @@ -86,17 +101,43 @@ getHTTPResponse(int s, int * size) } memcpy(header_buf + header_buf_used, buf, n); header_buf_used += n; - for(i = 0; i < (header_buf_used-3); i++) { + /* search for CR LF CR LF (end of headers) + * recognize also LF LF */ + i = 0; + while(i < ((int)header_buf_used-1) && (endofheaders == 0)) { + if(header_buf[i] == '\r') { + i++; + if(header_buf[i] == '\n') { + i++; + if(i < (int)header_buf_used && header_buf[i] == '\r') { + i++; + if(i < (int)header_buf_used && header_buf[i] == '\n') { + endofheaders = i+1; + } + } + } + } else if(header_buf[i] == '\n') { + i++; + if(header_buf[i] == '\n') { + endofheaders = i+1; + } + } + i++; + } + if(endofheaders == 0) + continue; + /* parse header lines */ + for(i = 0; i < endofheaders - 1; i++) { if(colon <= linestart && header_buf[i]==':') { colon = i; - while(i < (n-3) + while(i < (endofheaders-1) && (header_buf[i+1] == ' ' || header_buf[i+1] == '\t')) i++; valuestart = i + 1; } /* detecting end of line */ - else if(header_buf[i]=='\r' && header_buf[i+1]=='\n') + else if(header_buf[i]=='\r' || header_buf[i]=='\n') { if(colon > linestart && valuestart > colon) { @@ -113,7 +154,7 @@ getHTTPResponse(int s, int * size) #endif } else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart) - && 0==strncasecmp(buf+valuestart, "chunked", 7)) + && 0==strncasecmp(header_buf+valuestart, "chunked", 7)) { #ifdef DEBUG printf("chunked transfer-encoding!\n"); @@ -121,76 +162,19 @@ getHTTPResponse(int s, int * size) chunked = 1; } } - linestart = i+2; + while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n')) + i++; + linestart = i; colon = linestart; valuestart = 0; - } - /* searching for the end of the HTTP headers */ - if(header_buf[i]=='\r' && header_buf[i+1]=='\n' - && header_buf[i+2]=='\r' && header_buf[i+3]=='\n') - { - headers = 0; /* end */ - i += 4; - if(i < header_buf_used) - { - if(chunked) - { - while(i= '0' && header_buf[i] <= '9') - chunksize = (chunksize << 4) + (header_buf[i] - '0'); - else - chunksize = (chunksize << 4) + ((header_buf[i] | 32) - 'a' + 10); - i++; - } - /* discarding chunk-extension */ - while(i < header_buf_used && header_buf[i] != '\r') i++; - if(i < header_buf_used && header_buf[i] == '\r') i++; - if(i < header_buf_used && header_buf[i] == '\n') i++; -#ifdef DEBUG - printf("chunksize = %u (%x)\n", chunksize, chunksize); -#endif - if(chunksize == 0) - { -#ifdef DEBUG - printf("end of HTTP content !\n"); -#endif - goto end_of_stream; - } - bytestocopy = ((int)chunksize < header_buf_used - i)?chunksize:(header_buf_used - i); -#ifdef DEBUG - printf("chunksize=%u bytestocopy=%u (i=%d header_buf_used=%d)\n", - chunksize, bytestocopy, i, header_buf_used); -#endif - if(content_buf_len < (int)(content_buf_used + bytestocopy)) - { - content_buf = realloc(content_buf, content_buf_used + bytestocopy); - content_buf_len = content_buf_used + bytestocopy; - } - memcpy(content_buf + content_buf_used, header_buf + i, bytestocopy); - content_buf_used += bytestocopy; - chunksize -= bytestocopy; - i += bytestocopy; - } - } - else - { - if(content_buf_len < header_buf_used - i) - { - content_buf = realloc(content_buf, header_buf_used - i); - content_buf_len = header_buf_used - i; - } - memcpy(content_buf, header_buf + i, header_buf_used - i); - content_buf_used = header_buf_used - i; - i = header_buf_used; - } - } } } + /* copy the remaining of the received data back to buf */ + n = header_buf_used - endofheaders; + memcpy(buf, header_buf + endofheaders, n); + /* if(headers) */ } - else + if(endofheaders) { /* content */ if(chunked) @@ -201,19 +185,37 @@ getHTTPResponse(int s, int * size) if(chunksize == 0) { /* reading chunk size */ - if(i= '0' && buf[i] <= '9') - chunksize = (chunksize << 4) + (buf[i] - '0'); - else - chunksize = (chunksize << 4) + ((buf[i] | 32) - 'a' + 10); + chunksize_buf[chunksize_buf_index++] = buf[i]; + chunksize_buf[chunksize_buf_index] = '\0'; i++; } - while(i= '0' + && chunksize_buf[j] <= '9') + chunksize = (chunksize << 4) + (chunksize_buf[j] - '0'); + else + chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10); + } + chunksize_buf[0] = '\0'; + chunksize_buf_index = 0; + i++; + } else { + /* not finished to get chunksize */ + continue; + } #ifdef DEBUG printf("chunksize = %u (%x)\n", chunksize, chunksize); #endif @@ -226,12 +228,16 @@ getHTTPResponse(int s, int * size) goto end_of_stream; } } - bytestocopy = ((int)chunksize < n - i)?chunksize:(n - i); - if((int)(content_buf_used + bytestocopy) > content_buf_len) + bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i); + if((content_buf_used + bytestocopy) > content_buf_len) { - content_buf = (char *)realloc((void *)content_buf, - content_buf_used + bytestocopy); - content_buf_len = content_buf_used + bytestocopy; + if(content_length >= (int)(content_buf_used + bytestocopy)) { + content_buf_len = content_length; + } else { + content_buf_len = content_buf_used + bytestocopy; + } + content_buf = (char *)realloc((void *)content_buf, + content_buf_len); } memcpy(content_buf + content_buf_used, buf + i, bytestocopy); content_buf_used += bytestocopy; @@ -241,17 +247,28 @@ getHTTPResponse(int s, int * size) } else { + /* not chunked */ + if(content_length > 0 + && (int)(content_buf_used + n) > content_length) { + /* skipping additional bytes */ + n = content_length - content_buf_used; + } if(content_buf_used + n > content_buf_len) { - content_buf = (char *)realloc((void *)content_buf, - content_buf_used + n); - content_buf_len = content_buf_used + n; + if(content_length >= (int)(content_buf_used + n)) { + content_buf_len = content_length; + } else { + content_buf_len = content_buf_used + n; + } + content_buf = (char *)realloc((void *)content_buf, + content_buf_len); } memcpy(content_buf + content_buf_used, buf, n); content_buf_used += n; } } - if(content_length > 0 && content_buf_used >= content_length) + /* use the Content-Length header value if available */ + if(content_length > 0 && (int)content_buf_used >= content_length) { #ifdef DEBUG printf("End of HTTP content\n"); @@ -274,29 +291,31 @@ end_of_stream: * do all the work. * Return NULL if something failed. */ static void * -miniwget3(const char * url, const char * host, - unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len, const char * httpversion) +miniwget3(const char * host, + unsigned short port, const char * path, + int * size, char * addr_str, int addr_str_len, + const char * httpversion, unsigned int scope_id) { char buf[2048]; int s; int n; int len; int sent; + void * content; *size = 0; - s = connecthostport(host, port); + s = connecthostport(host, port, scope_id); if(s < 0) return NULL; /* get address for caller ! */ if(addr_str) { - struct sockaddr saddr; + struct sockaddr_storage saddr; socklen_t saddrlen; saddrlen = sizeof(saddr); - if(getsockname(s, &saddr, &saddrlen) < 0) + if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0) { perror("getsockname"); } @@ -310,15 +329,28 @@ miniwget3(const char * url, const char * host, { printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError()); }*/ + /* the following code is only compatible with ip v4 addresses */ strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len); #else - /*inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);*/ - n = getnameinfo(&saddr, saddrlen, +#if 0 + if(saddr.sa_family == AF_INET6) { + inet_ntop(AF_INET6, + &(((struct sockaddr_in6 *)&saddr)->sin6_addr), + addr_str, addr_str_len); + } else { + inet_ntop(AF_INET, + &(((struct sockaddr_in *)&saddr)->sin_addr), + addr_str, addr_str_len); + } +#endif + /* getnameinfo return ip v6 address with the scope identifier + * such as : 2a01:e35:8b2b:7330::%4281128194 */ + n = getnameinfo((const struct sockaddr *)&saddr, saddrlen, addr_str, addr_str_len, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); if(n != 0) { -#ifdef WIN32 +#ifdef _WIN32 fprintf(stderr, "getnameinfo() failed : %d\n", n); #else fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n)); @@ -355,30 +387,37 @@ miniwget3(const char * url, const char * host, sent += n; } } - return getHTTPResponse(s, size); + content = getHTTPResponse(s, size); + closesocket(s); + return content; } /* miniwget2() : * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */ static void * -miniwget2(const char * url, const char * host, +miniwget2(const char * host, unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len) + int * size, char * addr_str, int addr_str_len, + unsigned int scope_id) { char * respbuffer; - respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.1"); -/* - respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.0"); +#if 1 + respbuffer = miniwget3(host, port, path, size, + addr_str, addr_str_len, "1.1", scope_id); +#else + respbuffer = miniwget3(host, port, path, size, + addr_str, addr_str_len, "1.0", scope_id); if (*size == 0) { #ifdef DEBUG printf("Retrying with HTTP/1.1\n"); #endif free(respbuffer); - respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.1"); + respbuffer = miniwget3(host, port, path, size, + addr_str, addr_str_len, "1.1", scope_id); } -*/ +#endif return respbuffer; } @@ -390,12 +429,15 @@ miniwget2(const char * url, const char * host, * url : source string not modified * hostname : hostname destination string (size of MAXHOSTNAMELEN+1) * port : port (destination) - * path : pointer to the path part of the URL + * path : pointer to the path part of the URL * * Return values : * 0 - Failure * 1 - Success */ -int parseURL(const char * url, char * hostname, unsigned short * port, char * * path) +int +parseURL(const char * url, + char * hostname, unsigned short * port, + char * * path, unsigned int * scope_id) { char * p1, *p2, *p3; if(!url) @@ -407,11 +449,75 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * * if( (url[0]!='h') || (url[1]!='t') ||(url[2]!='t') || (url[3]!='p')) return 0; + memset(hostname, 0, MAXHOSTNAMELEN + 1); + if(*p1 == '[') + { + /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ + char * scope; + scope = strchr(p1, '%'); + p2 = strchr(p1, ']'); + if(p2 && scope && scope < p2 && scope_id) { + /* parse scope */ +#ifdef IF_NAMESIZE + char tmp[IF_NAMESIZE]; + int l; + scope++; + /* "%25" is just '%' in URL encoding */ + if(scope[0] == '2' && scope[1] == '5') + scope += 2; /* skip "25" */ + l = p2 - scope; + if(l >= IF_NAMESIZE) + l = IF_NAMESIZE - 1; + memcpy(tmp, scope, l); + tmp[l] = '\0'; + *scope_id = if_nametoindex(tmp); + if(*scope_id == 0) { + *scope_id = (unsigned int)strtoul(tmp, NULL, 10); + } +#else + /* under windows, scope is numerical */ + char tmp[8]; + int l; + scope++; + /* "%25" is just '%' in URL encoding */ + if(scope[0] == '2' && scope[1] == '5') + scope += 2; /* skip "25" */ + l = p2 - scope; + if(l >= sizeof(tmp)) + l = sizeof(tmp) - 1; + memcpy(tmp, scope, l); + tmp[l] = '\0'; + *scope_id = (unsigned int)strtoul(tmp, NULL, 10); +#endif + } + p3 = strchr(p1, '/'); + if(p2 && p3) + { + p2++; + strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); + if(*p2 == ':') + { + *port = 0; + p2++; + while( (*p2 >= '0') && (*p2 <= '9')) + { + *port *= 10; + *port += (unsigned short)(*p2 - '0'); + p2++; + } + } + else + { + *port = 80; + } + *path = p3; + return 1; + } + } p2 = strchr(p1, ':'); p3 = strchr(p1, '/'); if(!p3) return 0; - memset(hostname, 0, MAXHOSTNAMELEN + 1); if(!p2 || (p2>p3)) { strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1))); @@ -433,29 +539,40 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * * return 1; } -void * miniwget(const char * url, int * size) +void * +miniwget(const char * url, int * size, unsigned int scope_id) { unsigned short port; char * path; /* protocol://host:port/chemin */ char hostname[MAXHOSTNAMELEN+1]; *size = 0; - if(!parseURL(url, hostname, &port, &path)) + if(!parseURL(url, hostname, &port, &path, &scope_id)) return NULL; - return miniwget2(url, hostname, port, path, size, 0, 0); +#ifdef DEBUG + printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", + hostname, port, path, scope_id); +#endif + return miniwget2(hostname, port, path, size, 0, 0, scope_id); } -void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen) +void * +miniwget_getaddr(const char * url, int * size, + char * addr, int addrlen, unsigned int scope_id) { unsigned short port; char * path; - /* protocol://host:port/chemin */ + /* protocol://host:port/path */ char hostname[MAXHOSTNAMELEN+1]; *size = 0; if(addr) addr[0] = '\0'; - if(!parseURL(url, hostname, &port, &path)) + if(!parseURL(url, hostname, &port, &path, &scope_id)) return NULL; - return miniwget2(url, hostname, port, path, size, addr, addrlen); +#ifdef DEBUG + printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", + hostname, port, path, scope_id); +#endif + return miniwget2(hostname, port, path, size, addr, addrlen, scope_id); } diff --git a/3rdparty/miniupnpc/miniwget.h b/3rdparty/miniupnpc/miniwget.h index 8314b4000..31bcea322 100644 --- a/3rdparty/miniupnpc/miniwget.h +++ b/3rdparty/miniupnpc/miniwget.h @@ -1,12 +1,12 @@ -/* $Id: miniwget.h,v 1.6 2010/12/09 16:11:33 nanard Exp $ */ +/* $Id: miniwget.h,v 1.8 2012/09/27 15:42:10 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ -#ifndef __MINIWGET_H__ -#define __MINIWGET_H__ +#ifndef MINIWGET_H_INCLUDED +#define MINIWGET_H_INCLUDED #include "declspec.h" @@ -16,11 +16,11 @@ extern "C" { LIBSPEC void * getHTTPResponse(int s, int * size); -LIBSPEC void * miniwget(const char *, int *); +LIBSPEC void * miniwget(const char *, int *, unsigned int); -LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int); +LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int); -int parseURL(const char *, char *, unsigned short *, char * *); +int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); #ifdef __cplusplus } diff --git a/3rdparty/miniupnpc/minixml.c b/3rdparty/miniupnpc/minixml.c index 83c6acd97..eb4d7d985 100644 --- a/3rdparty/miniupnpc/minixml.c +++ b/3rdparty/miniupnpc/minixml.c @@ -1,10 +1,10 @@ -/* $Id: minixml.c,v 1.7 2009/10/10 19:15:35 nanard Exp $ */ +/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */ /* minixml.c : the minimum size a xml parser can be ! */ /* Project : miniupnp * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard -Copyright (c) 2005-2009, Thomas BERNARD +Copyright (c) 2005-2011, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,6 +30,7 @@ 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. */ +#include #include "minixml.h" /* parseatt : used to parse the argument list @@ -142,19 +143,43 @@ static void parseelt(struct xmlparser * p) if (p->xml >= p->xmlend) return; while( IS_WHITE_SPACE(*p->xml) ) - { - p->xml++; - if (p->xml >= p->xmlend) - return; - } - while(*p->xml!='<') { i++; p->xml++; if (p->xml >= p->xmlend) return; } - if(i>0 && p->datafunc) - p->datafunc(p->data, data, i); + if(memcmp(p->xml, "xml += 9; + data = p->xml; + i = 0; + while(memcmp(p->xml, "]]>", 3) != 0) + { + i++; p->xml++; + if ((p->xml + 3) >= p->xmlend) + return; + } + if(i>0 && p->datafunc) + p->datafunc(p->data, data, i); + while(*p->xml!='<') + { + p->xml++; + if (p->xml >= p->xmlend) + return; + } + } + else + { + while(*p->xml!='<') + { + i++; p->xml++; + if ((p->xml + 1) >= p->xmlend) + return; + } + if(i>0 && p->datafunc && *(p->xml + 1) == '/') + p->datafunc(p->data, data, i); + } } } else if(*p->xml == '/') diff --git a/3rdparty/miniupnpc/minixml.h b/3rdparty/miniupnpc/minixml.h index 857c70ee9..9f43aa48c 100644 --- a/3rdparty/miniupnpc/minixml.h +++ b/3rdparty/miniupnpc/minixml.h @@ -1,4 +1,4 @@ -/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */ +/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ /* minimal xml parser * * Project : miniupnp @@ -8,8 +8,8 @@ * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ -#ifndef __MINIXML_H__ -#define __MINIXML_H__ +#ifndef MINIXML_H_INCLUDED +#define MINIXML_H_INCLUDED #define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) /* if a callback function pointer is set to NULL, diff --git a/3rdparty/miniupnpc/portlistingparse.c b/3rdparty/miniupnpc/portlistingparse.c new file mode 100644 index 000000000..19e3054eb --- /dev/null +++ b/3rdparty/miniupnpc/portlistingparse.c @@ -0,0 +1,159 @@ +/* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2011 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ +#include +#include +#include "portlistingparse.h" +#include "minixml.h" + +/* list of the elements */ +static const struct { + const portMappingElt code; + const char * const str; +} elements[] = { + { PortMappingEntry, "PortMappingEntry"}, + { NewRemoteHost, "NewRemoteHost"}, + { NewExternalPort, "NewExternalPort"}, + { NewProtocol, "NewProtocol"}, + { NewInternalPort, "NewInternalPort"}, + { NewInternalClient, "NewInternalClient"}, + { NewEnabled, "NewEnabled"}, + { NewDescription, "NewDescription"}, + { NewLeaseTime, "NewLeaseTime"}, + { PortMappingEltNone, NULL} +}; + +/* Helper function */ +static UNSIGNED_INTEGER +atoui(const char * p, int l) +{ + UNSIGNED_INTEGER r = 0; + while(l > 0 && *p) + { + if(*p >= '0' && *p <= '9') + r = r*10 + (*p - '0'); + else + break; + p++; + l--; + } + return r; +} + +/* Start element handler */ +static void +startelt(void * d, const char * name, int l) +{ + int i; + struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; + pdata->curelt = PortMappingEltNone; + for(i = 0; elements[i].str; i++) + { + if(memcmp(name, elements[i].str, l) == 0) + { + pdata->curelt = elements[i].code; + break; + } + } + if(pdata->curelt == PortMappingEntry) + { + struct PortMapping * pm; + pm = calloc(1, sizeof(struct PortMapping)); + LIST_INSERT_HEAD( &(pdata->head), pm, entries); + } +} + +/* End element handler */ +static void +endelt(void * d, const char * name, int l) +{ + struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; + (void)name; + (void)l; + pdata->curelt = PortMappingEltNone; +} + +/* Data handler */ +static void +data(void * d, const char * data, int l) +{ + struct PortMapping * pm; + struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; + pm = pdata->head.lh_first; + if(!pm) + return; + if(l > 63) + l = 63; + switch(pdata->curelt) + { + case NewRemoteHost: + memcpy(pm->remoteHost, data, l); + pm->remoteHost[l] = '\0'; + break; + case NewExternalPort: + pm->externalPort = (unsigned short)atoui(data, l); + break; + case NewProtocol: + if(l > 3) + l = 3; + memcpy(pm->protocol, data, l); + pm->protocol[l] = '\0'; + break; + case NewInternalPort: + pm->internalPort = (unsigned short)atoui(data, l); + break; + case NewInternalClient: + memcpy(pm->internalClient, data, l); + pm->internalClient[l] = '\0'; + break; + case NewEnabled: + pm->enabled = (unsigned char)atoui(data, l); + break; + case NewDescription: + memcpy(pm->description, data, l); + pm->description[l] = '\0'; + break; + case NewLeaseTime: + pm->leaseTime = atoui(data, l); + break; + default: + break; + } +} + + +/* Parse the PortMappingList XML document for IGD version 2 + */ +void +ParsePortListing(const char * buffer, int bufsize, + struct PortMappingParserData * pdata) +{ + struct xmlparser parser; + + memset(pdata, 0, sizeof(struct PortMappingParserData)); + LIST_INIT(&(pdata->head)); + /* init xmlparser */ + parser.xmlstart = buffer; + parser.xmlsize = bufsize; + parser.data = pdata; + parser.starteltfunc = startelt; + parser.endeltfunc = endelt; + parser.datafunc = data; + parser.attfunc = 0; + parsexml(&parser); +} + +void +FreePortListing(struct PortMappingParserData * pdata) +{ + struct PortMapping * pm; + while((pm = pdata->head.lh_first) != NULL) + { + LIST_REMOVE(pm, entries); + free(pm); + } +} + diff --git a/3rdparty/miniupnpc/portlistingparse.h b/3rdparty/miniupnpc/portlistingparse.h new file mode 100644 index 000000000..bafa2a47c --- /dev/null +++ b/3rdparty/miniupnpc/portlistingparse.h @@ -0,0 +1,71 @@ +/* $Id: portlistingparse.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2011-2012 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ +#ifndef PORTLISTINGPARSE_H_INCLUDED +#define PORTLISTINGPARSE_H_INCLUDED + +#include "declspec.h" +/* for the definition of UNSIGNED_INTEGER */ +#include "miniupnpctypes.h" + +#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__) +#include "bsdqueue.h" +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* sample of PortMappingEntry : + + 202.233.2.1 + 2345 + TCP + 2345 + 192.168.1.137 + 1 + dooom + 345 + + */ +typedef enum { PortMappingEltNone, + PortMappingEntry, NewRemoteHost, + NewExternalPort, NewProtocol, + NewInternalPort, NewInternalClient, + NewEnabled, NewDescription, + NewLeaseTime } portMappingElt; + +struct PortMapping { + LIST_ENTRY(PortMapping) entries; + UNSIGNED_INTEGER leaseTime; + unsigned short externalPort; + unsigned short internalPort; + char remoteHost[64]; + char internalClient[64]; + char description[64]; + char protocol[4]; + unsigned char enabled; +}; + +struct PortMappingParserData { + LIST_HEAD(portmappinglisthead, PortMapping) head; + portMappingElt curelt; +}; + +LIBSPEC void +ParsePortListing(const char * buffer, int bufsize, + struct PortMappingParserData * pdata); + +LIBSPEC void +FreePortListing(struct PortMappingParserData * pdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/3rdparty/miniupnpc/receivedata.c b/3rdparty/miniupnpc/receivedata.c new file mode 100644 index 000000000..ffbfbead6 --- /dev/null +++ b/3rdparty/miniupnpc/receivedata.c @@ -0,0 +1,109 @@ +/* $Id: receivedata.c,v 1.5 2013/10/07 09:48:36 nanard Exp $ */ +/* Project : miniupnp + * Website : http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2011-2012 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +#include +#ifdef _WIN32 +#include +#include +#else +#include +#if defined(__amigaos__) && !defined(__amigaos4__) +#define socklen_t int +#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ +#include +#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ +#include +#include +#if !defined(__amigaos__) && !defined(__amigaos4__) +#include +#endif +#include +#define MINIUPNPC_IGNORE_EINTR +#endif + +#ifdef _WIN32 +#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); +#else +#define PRINT_SOCKET_ERROR(x) perror(x) +#endif + +#include "receivedata.h" + +int +receivedata(int socket, + char * data, int length, + int timeout, unsigned int * scope_id) +{ +#if MINIUPNPC_GET_SRC_ADDR +#ifdef DEBUG + /* to shut up valgrind about uninit value */ + struct sockaddr_storage src_addr = {0}; +#else + struct sockaddr_storage src_addr; +#endif + socklen_t src_addr_len = sizeof(src_addr); +#endif + int n; +#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) + /* using poll */ + struct pollfd fds[1]; /* for the poll */ +#ifdef MINIUPNPC_IGNORE_EINTR + do { +#endif + fds[0].fd = socket; + fds[0].events = POLLIN; + n = poll(fds, 1, timeout); +#ifdef MINIUPNPC_IGNORE_EINTR + } while(n < 0 && errno == EINTR); +#endif + if(n < 0) { + PRINT_SOCKET_ERROR("poll"); + return -1; + } else if(n == 0) { + /* timeout */ + return 0; + } +#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ + /* using select under _WIN32 and amigaos */ + fd_set socketSet; + TIMEVAL timeval; + FD_ZERO(&socketSet); + FD_SET(socket, &socketSet); + timeval.tv_sec = timeout / 1000; + timeval.tv_usec = (timeout % 1000) * 1000; + n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); + if(n < 0) { + PRINT_SOCKET_ERROR("select"); + return -1; + } else if(n == 0) { + return 0; + } +#endif +#if MINIUPNPC_GET_SRC_ADDR + n = recvfrom(socket, data, length, 0, + (struct sockaddr *)&src_addr, &src_addr_len); +#else + n = recv(socket, data, length, 0); +#endif + if(n<0) { + PRINT_SOCKET_ERROR("recv"); + } +#if MINIUPNPC_GET_SRC_ADDR + if (src_addr.ss_family == AF_INET6) { + const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; +#ifdef DEBUG + printf("scope_id=%u\n", src_addr6->sin6_scope_id); +#endif + if(scope_id) + *scope_id = src_addr6->sin6_scope_id; + } +#endif + return n; +} + + diff --git a/3rdparty/miniupnpc/receivedata.h b/3rdparty/miniupnpc/receivedata.h new file mode 100644 index 000000000..0520a11d3 --- /dev/null +++ b/3rdparty/miniupnpc/receivedata.h @@ -0,0 +1,19 @@ +/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2011-2012 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef RECEIVEDATA_H_INCLUDED +#define RECEIVEDATA_H_INCLUDED + +/* Reads data from the specified socket. + * Returns the number of bytes read if successful, zero if no bytes were + * read or if we timed out. Returns negative if there was an error. */ +int receivedata(int socket, + char * data, int length, + int timeout, unsigned int * scope_id); + +#endif + diff --git a/3rdparty/miniupnpc/upnpcommands.c b/3rdparty/miniupnpc/upnpcommands.c index 20e48d819..662c10bc6 100644 --- a/3rdparty/miniupnpc/upnpcommands.c +++ b/3rdparty/miniupnpc/upnpcommands.c @@ -1,7 +1,7 @@ -/* $Id: upnpcommands.c,v 1.26 2010/06/09 10:59:09 nanard Exp $ */ +/* $Id: upnpcommands.c,v 1.40 2012/06/23 22:36:35 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2010 Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ @@ -10,6 +10,7 @@ #include #include "upnpcommands.h" #include "miniupnpc.h" +#include "portlistingparse.h" static UNSIGNED_INTEGER my_atoui(const char * s) @@ -24,15 +25,17 @@ UPNP_GetTotalBytesSent(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; unsigned int r = 0; char * p; - if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetTotalBytesSent", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent"); r = my_atoui(p); ClearNameValueList(&pdata); @@ -46,15 +49,17 @@ UPNP_GetTotalBytesReceived(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; unsigned int r = 0; char * p; - if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetTotalBytesReceived", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived"); r = my_atoui(p); ClearNameValueList(&pdata); @@ -68,15 +73,17 @@ UPNP_GetTotalPacketsSent(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; unsigned int r = 0; char * p; - if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetTotalPacketsSent", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent"); r = my_atoui(p); ClearNameValueList(&pdata); @@ -90,15 +97,17 @@ UPNP_GetTotalPacketsReceived(const char * controlURL, const char * servicetype) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; unsigned int r = 0; char * p; - if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetTotalPacketsReceived", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived"); r = my_atoui(p); ClearNameValueList(&pdata); @@ -110,13 +119,13 @@ UPNP_GetTotalPacketsReceived(const char * controlURL, LIBSPEC int UPNP_GetStatusInfo(const char * controlURL, const char * servicetype, - char * status, + char * status, unsigned int * uptime, char * lastconnerror) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; char * p; char * up; char * err; @@ -125,11 +134,13 @@ UPNP_GetStatusInfo(const char * controlURL, if(!status && !uptime) return UPNPCOMMAND_INVALID_ARGS; - if(simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetStatusInfo", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); /*DisplayNameValueList(buffer, bufsize);*/ + free(buffer); buffer = NULL; up = GetValueFromNameValueList(&pdata, "NewUptime"); p = GetValueFromNameValueList(&pdata, "NewConnectionStatus"); err = GetValueFromNameValueList(&pdata, "NewLastConnectionError"); @@ -176,19 +187,20 @@ UPNP_GetConnectionTypeInfo(const char * controlURL, char * connectionType) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!connectionType) return UPNPCOMMAND_INVALID_ARGS; - if(simpleUPnPcommand(-1, controlURL, servicetype, - "GetConnectionTypeInfo", 0, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetConnectionTypeInfo", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewConnectionType"); /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/ /* PossibleConnectionTypes will have several values.... */ @@ -209,18 +221,18 @@ UPNP_GetConnectionTypeInfo(const char * controlURL, /* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method. * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth. - * One of the values can be null - * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only + * One of the values can be null + * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */ LIBSPEC int UPNP_GetLinkLayerMaxBitRates(const char * controlURL, const char * servicetype, unsigned int * bitrateDown, - unsigned int* bitrateUp) + unsigned int * bitrateUp) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; int ret = UPNPCOMMAND_UNKNOWN_ERROR; char * down; char * up; @@ -230,19 +242,20 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL, return UPNPCOMMAND_INVALID_ARGS; /* shouldn't we use GetCommonLinkProperties ? */ - if(simpleUPnPcommand(-1, controlURL, servicetype, - "GetCommonLinkProperties", 0, buffer, &bufsize) < 0) { - /*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize);*/ + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetCommonLinkProperties", 0, &bufsize))) { + /*"GetLinkLayerMaxBitRates", 0, &bufsize);*/ return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/ /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/ down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate"); up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate"); /*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/ - /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus");*/ + /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/ if(down && up) ret = UPNPCOMMAND_SUCCESS; @@ -272,7 +285,7 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL, /* UPNP_GetExternalIPAddress() call the corresponding UPNP method. * if the third arg is not null the value is copied to it. * at least 16 bytes must be available - * + * * Return values : * 0 : SUCCESS * NON ZERO : ERROR Either an UPnP error code or an unknown error. @@ -286,19 +299,21 @@ UPNP_GetExternalIPAddress(const char * controlURL, char * extIpAdd) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; if(!extIpAdd || !controlURL || !servicetype) return UPNPCOMMAND_INVALID_ARGS; - if(simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetExternalIPAddress", 0, &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/ p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress"); if(p) { @@ -325,11 +340,12 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * inClient, const char * desc, const char * proto, - const char * remoteHost) + const char * remoteHost, + const char * leaseDuration) { struct UPNParg * AddPortMappingArgs; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; @@ -353,8 +369,10 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, AddPortMappingArgs[6].elt = "NewPortMappingDescription"; AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; AddPortMappingArgs[7].elt = "NewLeaseDuration"; - AddPortMappingArgs[7].val = "0"; - if(simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize) < 0) { + AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddPortMapping", AddPortMappingArgs, + &bufsize))) { free(AddPortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } @@ -362,6 +380,7 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, /*buffer[bufsize] = '\0';*/ /*puts(buffer);*/ ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ @@ -382,8 +401,8 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, { /*struct NameValueParserData pdata;*/ struct UPNParg * DeletePortMappingArgs; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; struct NameValueParserData pdata; const char * resVal; int ret; @@ -398,14 +417,15 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, DeletePortMappingArgs[1].val = extPort; DeletePortMappingArgs[2].elt = "NewProtocol"; DeletePortMappingArgs[2].val = proto; - if(simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePortMapping", - DeletePortMappingArgs, buffer, &bufsize) < 0 ) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "DeletePortMapping", + DeletePortMappingArgs, &bufsize))) { free(DeletePortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; resVal = GetValueFromNameValueList(&pdata, "errorCode"); if(resVal) { ret = UPNPCOMMAND_UNKNOWN_ERROR; @@ -433,8 +453,8 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, { struct NameValueParserData pdata; struct UPNParg * GetPortMappingArgs; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; char * p; int r = UPNPCOMMAND_UNKNOWN_ERROR; if(!index) @@ -444,13 +464,15 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); GetPortMappingArgs[0].elt = "NewPortMappingIndex"; GetPortMappingArgs[0].val = index; - if(simpleUPnPcommand(-1, controlURL, servicetype, - "GetGenericPortMappingEntry", - GetPortMappingArgs, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetGenericPortMappingEntry", + GetPortMappingArgs, &bufsize))) { free(GetPortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + p = GetValueFromNameValueList(&pdata, "NewRemoteHost"); if(p && rHost) { @@ -517,17 +539,20 @@ UPNP_GetPortMappingNumberOfEntries(const char * controlURL, unsigned int * numEntries) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; char* p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; - if(simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetPortMappingNumberOfEntries", 0, + &bufsize))) { return UPNPCOMMAND_HTTP_ERROR; } #ifdef DEBUG DisplayNameValueList(buffer, bufsize); #endif ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries"); if(numEntries && p) { @@ -555,12 +580,15 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * extPort, const char * proto, char * intClient, - char * intPort) + char * intPort, + char * desc, + char * enabled, + char * leaseDuration) { struct NameValueParserData pdata; struct UPNParg * GetPortMappingArgs; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; char * p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; @@ -569,18 +597,20 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); GetPortMappingArgs[0].elt = "NewRemoteHost"; + /* TODO : add remote host ? */ GetPortMappingArgs[1].elt = "NewExternalPort"; GetPortMappingArgs[1].val = extPort; GetPortMappingArgs[2].elt = "NewProtocol"; GetPortMappingArgs[2].val = proto; - if(simpleUPnPcommand(-1, controlURL, servicetype, - "GetSpecificPortMappingEntry", - GetPortMappingArgs, buffer, &bufsize) < 0) { + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetSpecificPortMappingEntry", + GetPortMappingArgs, &bufsize))) { free(GetPortMappingArgs); return UPNPCOMMAND_HTTP_ERROR; } /*DisplayNameValueList(buffer, bufsize);*/ ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; p = GetValueFromNameValueList(&pdata, "NewInternalClient"); if(p) { @@ -597,6 +627,25 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, } else intPort[0] = '\0'; + p = GetValueFromNameValueList(&pdata, "NewEnabled"); + if(p && enabled) { + strncpy(enabled, p, 4); + enabled[3] = '\0'; + } + + p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); + if(p && desc) { + strncpy(desc, p, 80); + desc[79] = '\0'; + } + + p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); + if(p && leaseDuration) + { + strncpy(leaseDuration, p, 16); + leaseDuration[15] = '\0'; + } + p = GetValueFromNameValueList(&pdata, "errorCode"); if(p) { ret = UPNPCOMMAND_UNKNOWN_ERROR; @@ -608,4 +657,441 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, return ret; } +/* UPNP_GetListOfPortMappings() + * + * Possible UPNP Error codes : + * 606 Action not Authorized + * 730 PortMappingNotFound - no port mapping is found in the specified range. + * 733 InconsistantParameters - NewStartPort and NewEndPort values are not + * consistent. + */ +LIBSPEC int +UPNP_GetListOfPortMappings(const char * controlURL, + const char * servicetype, + const char * startPort, + const char * endPort, + const char * protocol, + const char * numberOfPorts, + struct PortMappingParserData * data) +{ + struct NameValueParserData pdata; + struct UPNParg * GetListOfPortMappingsArgs; + const char * p; + char * buffer; + int bufsize; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!startPort || !endPort || !protocol) + return UPNPCOMMAND_INVALID_ARGS; + + GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg)); + GetListOfPortMappingsArgs[0].elt = "NewStartPort"; + GetListOfPortMappingsArgs[0].val = startPort; + GetListOfPortMappingsArgs[1].elt = "NewEndPort"; + GetListOfPortMappingsArgs[1].val = endPort; + GetListOfPortMappingsArgs[2].elt = "NewProtocol"; + GetListOfPortMappingsArgs[2].val = protocol; + GetListOfPortMappingsArgs[3].elt = "NewManage"; + GetListOfPortMappingsArgs[3].val = "1"; + GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts"; + GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000"; + + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetListOfPortMappings", + GetListOfPortMappingsArgs, &bufsize))) { + free(GetListOfPortMappingsArgs); + return UPNPCOMMAND_HTTP_ERROR; + } + free(GetListOfPortMappingsArgs); + + /*DisplayNameValueList(buffer, bufsize);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + /*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/ + /*if(p) { + printf("NewPortListing : %s\n", p); + }*/ + /*printf("NewPortListing(%d chars) : %s\n", + pdata.portListingLength, pdata.portListing);*/ + if(pdata.portListing) + { + /*struct PortMapping * pm; + int i = 0;*/ + ParsePortListing(pdata.portListing, pdata.portListingLength, + data); + ret = UPNPCOMMAND_SUCCESS; + /* + for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next) + { + printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n", + i, pm->protocol, pm->externalPort, pm->internalClient, + pm->internalPort, + pm->description, pm->remoteHost); + i++; + } + */ + /*FreePortListing(&data);*/ + } + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + ClearNameValueList(&pdata); + + /*printf("%.*s", bufsize, buffer);*/ + + return ret; +} + +/* IGD:2, functions for service WANIPv6FirewallControl:1 */ +LIBSPEC int +UPNP_GetFirewallStatus(const char * controlURL, + const char * servicetype, + int * firewallEnabled, + int * inboundPinholeAllowed) +{ + struct NameValueParserData pdata; + char * buffer; + int bufsize; + char * fe, *ipa, *p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!firewallEnabled && !inboundPinholeAllowed) + return UPNPCOMMAND_INVALID_ARGS; + + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetFirewallStatus", 0, &bufsize); + if(!buffer) { + return UPNPCOMMAND_HTTP_ERROR; + } + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + fe = GetValueFromNameValueList(&pdata, "FirewallEnabled"); + ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed"); + if(ipa && fe) + ret = UPNPCOMMAND_SUCCESS; + if(fe) + *firewallEnabled = my_atoui(fe); + /*else + *firewallEnabled = 0;*/ + if(ipa) + *inboundPinholeAllowed = my_atoui(ipa); + /*else + *inboundPinholeAllowed = 0;*/ + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + ClearNameValueList(&pdata); + return ret; +} + +LIBSPEC int +UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, + const char * remoteHost, + const char * remotePort, + const char * intClient, + const char * intPort, + const char * proto, + int * opTimeout) +{ + struct UPNParg * GetOutboundPinholeTimeoutArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + char * p; + int ret; + + if(!intPort || !intClient || !proto || !remotePort || !remoteHost) + return UPNPCOMMAND_INVALID_ARGS; + + GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg)); + GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost"; + GetOutboundPinholeTimeoutArgs[0].val = remoteHost; + GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort"; + GetOutboundPinholeTimeoutArgs[1].val = remotePort; + GetOutboundPinholeTimeoutArgs[2].elt = "Protocol"; + GetOutboundPinholeTimeoutArgs[2].val = proto; + GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort"; + GetOutboundPinholeTimeoutArgs[3].val = intPort; + GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient"; + GetOutboundPinholeTimeoutArgs[4].val = intClient; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } + else + { + ret = UPNPCOMMAND_SUCCESS; + p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout"); + if(p) + *opTimeout = my_atoui(p); + } + ClearNameValueList(&pdata); + free(GetOutboundPinholeTimeoutArgs); + return ret; +} + +LIBSPEC int +UPNP_AddPinhole(const char * controlURL, const char * servicetype, + const char * remoteHost, + const char * remotePort, + const char * intClient, + const char * intPort, + const char * proto, + const char * leaseTime, + char * uniqueID) +{ + struct UPNParg * AddPinholeArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + char * p; + int ret; + + if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime) + return UPNPCOMMAND_INVALID_ARGS; + + AddPinholeArgs = calloc(7, sizeof(struct UPNParg)); + /* RemoteHost can be wilcarded */ + if(strncmp(remoteHost, "empty", 5)==0) + { + AddPinholeArgs[0].elt = "RemoteHost"; + AddPinholeArgs[0].val = ""; + } + else + { + AddPinholeArgs[0].elt = "RemoteHost"; + AddPinholeArgs[0].val = remoteHost; + } + AddPinholeArgs[1].elt = "RemotePort"; + AddPinholeArgs[1].val = remotePort; + AddPinholeArgs[2].elt = "Protocol"; + AddPinholeArgs[2].val = proto; + AddPinholeArgs[3].elt = "InternalPort"; + AddPinholeArgs[3].val = intPort; + if(strncmp(intClient, "empty", 5)==0) + { + AddPinholeArgs[4].elt = "InternalClient"; + AddPinholeArgs[4].val = ""; + } + else + { + AddPinholeArgs[4].elt = "InternalClient"; + AddPinholeArgs[4].val = intClient; + } + AddPinholeArgs[5].elt = "LeaseTime"; + AddPinholeArgs[5].val = leaseTime; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddPinhole", AddPinholeArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + p = GetValueFromNameValueList(&pdata, "UniqueID"); + if(p) + { + strncpy(uniqueID, p, 8); + uniqueID[7] = '\0'; + } + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) + { + /*printf("AddPortMapping errorCode = '%s'\n", resVal);*/ + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } + else + { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(AddPinholeArgs); + return ret; +} + +LIBSPEC int +UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, + const char * uniqueID, + const char * leaseTime) +{ + struct UPNParg * UpdatePinholeArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!uniqueID || !leaseTime) + return UPNPCOMMAND_INVALID_ARGS; + + UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg)); + UpdatePinholeArgs[0].elt = "UniqueID"; + UpdatePinholeArgs[0].val = uniqueID; + UpdatePinholeArgs[1].elt = "NewLeaseTime"; + UpdatePinholeArgs[1].val = leaseTime; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "UpdatePinhole", UpdatePinholeArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) + { + /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } + else + { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(UpdatePinholeArgs); + return ret; +} + +LIBSPEC int +UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID) +{ + /*struct NameValueParserData pdata;*/ + struct UPNParg * DeletePinholeArgs; + char * buffer; + int bufsize; + struct NameValueParserData pdata; + const char * resVal; + int ret; + + if(!uniqueID) + return UPNPCOMMAND_INVALID_ARGS; + + DeletePinholeArgs = calloc(2, sizeof(struct UPNParg)); + DeletePinholeArgs[0].elt = "UniqueID"; + DeletePinholeArgs[0].val = uniqueID; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "DeletePinhole", DeletePinholeArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + /*DisplayNameValueList(buffer, bufsize);*/ + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + resVal = GetValueFromNameValueList(&pdata, "errorCode"); + if(resVal) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(resVal, "%d", &ret); + } + else + { + ret = UPNPCOMMAND_SUCCESS; + } + ClearNameValueList(&pdata); + free(DeletePinholeArgs); + return ret; +} + +LIBSPEC int +UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, + const char * uniqueID, int * isWorking) +{ + struct NameValueParserData pdata; + struct UPNParg * CheckPinholeWorkingArgs; + char * buffer; + int bufsize; + char * p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!uniqueID) + return UPNPCOMMAND_INVALID_ARGS; + + CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg)); + CheckPinholeWorkingArgs[0].elt = "UniqueID"; + CheckPinholeWorkingArgs[0].val = uniqueID; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + p = GetValueFromNameValueList(&pdata, "IsWorking"); + if(p) + { + *isWorking=my_atoui(p); + ret = UPNPCOMMAND_SUCCESS; + } + else + *isWorking = 0; + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + + ClearNameValueList(&pdata); + free(CheckPinholeWorkingArgs); + return ret; +} + +LIBSPEC int +UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, + const char * uniqueID, int * packets) +{ + struct NameValueParserData pdata; + struct UPNParg * GetPinholePacketsArgs; + char * buffer; + int bufsize; + char * p; + int ret = UPNPCOMMAND_UNKNOWN_ERROR; + + if(!uniqueID) + return UPNPCOMMAND_INVALID_ARGS; + + GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg)); + GetPinholePacketsArgs[0].elt = "UniqueID"; + GetPinholePacketsArgs[0].val = uniqueID; + buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "GetPinholePackets", GetPinholePacketsArgs, &bufsize); + if(!buffer) + return UPNPCOMMAND_HTTP_ERROR; + ParseNameValue(buffer, bufsize, &pdata); + free(buffer); buffer = NULL; + + p = GetValueFromNameValueList(&pdata, "PinholePackets"); + if(p) + { + *packets=my_atoui(p); + ret = UPNPCOMMAND_SUCCESS; + } + + p = GetValueFromNameValueList(&pdata, "errorCode"); + if(p) + { + ret = UPNPCOMMAND_UNKNOWN_ERROR; + sscanf(p, "%d", &ret); + } + + ClearNameValueList(&pdata); + free(GetPinholePacketsArgs); + return ret; +} + diff --git a/3rdparty/miniupnpc/upnpcommands.h b/3rdparty/miniupnpc/upnpcommands.h index 5561beaae..ee3ce89df 100644 --- a/3rdparty/miniupnpc/upnpcommands.h +++ b/3rdparty/miniupnpc/upnpcommands.h @@ -1,14 +1,16 @@ -/* $Id: upnpcommands.h,v 1.18 2010/06/09 10:59:09 nanard Exp $ */ +/* $Id: upnpcommands.h,v 1.25 2012/09/27 15:42:10 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2010 Thomas Bernard + * Copyright (c) 2005-2011 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ -#ifndef __UPNPCOMMANDS_H__ -#define __UPNPCOMMANDS_H__ +#ifndef UPNPCOMMANDS_H_INCLUDED +#define UPNPCOMMANDS_H_INCLUDED #include "upnpreplyparse.h" +#include "portlistingparse.h" #include "declspec.h" +#include "miniupnpctypes.h" /* MiniUPnPc return codes : */ #define UPNPCOMMAND_SUCCESS (0) @@ -20,14 +22,6 @@ extern "C" { #endif -#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) -#define UNSIGNED_INTEGER unsigned long long -#define STRTOUI strtoull -#else -#define UNSIGNED_INTEGER unsigned int -#define STRTOUI strtoul -#endif - LIBSPEC UNSIGNED_INTEGER UPNP_GetTotalBytesSent(const char * controlURL, const char * servicetype); @@ -68,12 +62,12 @@ UPNP_GetConnectionTypeInfo(const char * controlURL, /* UPNP_GetExternalIPAddress() call the corresponding UPNP method. * if the third arg is not null the value is copied to it. - * at least 16 bytes must be available + * at least 16 bytes must be available * * Return values : * 0 : SUCCESS * NON ZERO : ERROR Either an UPnP error code or an unknown error. - * + * * possible UPnP Errors : * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. */ @@ -101,7 +95,7 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL, * Return values : * 0 : SUCCESS * NON ZERO : ERROR. Either an UPnP error code or an unknown error. - * + * * List of possible UPnP errors for AddPortMapping : * errorCode errorDescription (short) - Description (long) * 402 Invalid Args - See UPnP Device Architecture section on Control. @@ -112,7 +106,7 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL, * 718 ConflictInMappingEntry - The port mapping entry specified conflicts * with a mapping assigned previously to another client * 724 SamePortValuesRequired - Internal and External port values - * must be the same + * must be the same * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports * permanent lease times on port mappings * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard @@ -126,7 +120,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * inClient, const char * desc, const char * proto, - const char * remoteHost); + const char * remoteHost, + const char * leaseDuration); /* UPNP_DeletePortMapping() * Use same argument values as what was used for AddPortMapping(). @@ -146,11 +141,20 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, /* UPNP_GetPortMappingNumberOfEntries() * not supported by all routers */ LIBSPEC int -UPNP_GetPortMappingNumberOfEntries(const char* controlURL, const char* servicetype, unsigned int * num); +UPNP_GetPortMappingNumberOfEntries(const char* controlURL, + const char* servicetype, + unsigned int * num); -/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping - * the result is returned in the intClient and intPort strings - * please provide 16 and 6 bytes of data +/* UPNP_GetSpecificPortMappingEntry() + * retrieves an existing port mapping + * params : + * in extPort + * in proto + * out intClient (16 bytes) + * out intPort (6 bytes) + * out desc (80 bytes) + * out enabled (4 bytes) + * out leaseDuration (16 bytes) * * return value : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR @@ -161,9 +165,22 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * extPort, const char * proto, char * intClient, - char * intPort); + char * intPort, + char * desc, + char * enabled, + char * leaseDuration); /* UPNP_GetGenericPortMappingEntry() + * params : + * in index + * out extPort (6 bytes) + * out intClient (16 bytes) + * out intPort (6 bytes) + * out protocol (4 bytes) + * out desc (80 bytes) + * out enabled (4 bytes) + * out rHost (64 bytes) + * out duration (16 bytes) * * return value : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR @@ -186,6 +203,66 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, char * rHost, char * duration); +/* UPNP_GetListOfPortMappings() Available in IGD v2 + * + * + * Possible UPNP Error codes : + * 606 Action not Authorized + * 730 PortMappingNotFound - no port mapping is found in the specified range. + * 733 InconsistantParameters - NewStartPort and NewEndPort values are not + * consistent. + */ +LIBSPEC int +UPNP_GetListOfPortMappings(const char * controlURL, + const char * servicetype, + const char * startPort, + const char * endPort, + const char * protocol, + const char * numberOfPorts, + struct PortMappingParserData * data); + +/* IGD:2, functions for service WANIPv6FirewallControl:1 */ +LIBSPEC int +UPNP_GetFirewallStatus(const char * controlURL, + const char * servicetype, + int * firewallEnabled, + int * inboundPinholeAllowed); + +LIBSPEC int +UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, + const char * remoteHost, + const char * remotePort, + const char * intClient, + const char * intPort, + const char * proto, + int * opTimeout); + +LIBSPEC int +UPNP_AddPinhole(const char * controlURL, const char * servicetype, + const char * remoteHost, + const char * remotePort, + const char * intClient, + const char * intPort, + const char * proto, + const char * leaseTime, + char * uniqueID); + +LIBSPEC int +UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, + const char * uniqueID, + const char * leaseTime); + +LIBSPEC int +UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); + +LIBSPEC int +UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, + const char * uniqueID, int * isWorking); + +LIBSPEC int +UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, + const char * uniqueID, int * packets); + #ifdef __cplusplus } #endif diff --git a/3rdparty/miniupnpc/upnperrors.c b/3rdparty/miniupnpc/upnperrors.c index 8a05349b1..644098f0d 100644 --- a/3rdparty/miniupnpc/upnperrors.c +++ b/3rdparty/miniupnpc/upnperrors.c @@ -1,4 +1,4 @@ -/* $Id: upnperrors.c,v 1.3 2008/04/27 17:21:51 nanard Exp $ */ +/* $Id: upnperrors.c,v 1.6 2012/03/15 01:02:03 nanard Exp $ */ /* Project : miniupnp * Author : Thomas BERNARD * copyright (c) 2007 Thomas Bernard @@ -9,6 +9,7 @@ #include #include "upnperrors.h" #include "upnpcommands.h" +#include "miniupnpc.h" const char * strupnperror(int err) { @@ -23,6 +24,12 @@ const char * strupnperror(int err) case UPNPCOMMAND_INVALID_ARGS: s = "Miniupnpc Invalid Arguments"; break; + case UPNPDISCOVER_SOCKET_ERROR: + s = "Miniupnpc Socket error"; + break; + case UPNPDISCOVER_MEMORY_ERROR: + s = "Miniupnpc Memory allocation error"; + break; case 401: s = "Invalid Action"; break; @@ -32,6 +39,36 @@ const char * strupnperror(int err) case 501: s = "Action Failed"; break; + case 606: + s = "Action not authorized"; + break; + case 701: + s = "PinholeSpaceExhausted"; + break; + case 702: + s = "FirewallDisabled"; + break; + case 703: + s = "InboundPinholeNotAllowed"; + break; + case 704: + s = "NoSuchEntry"; + break; + case 705: + s = "ProtocolNotSupported"; + break; + case 706: + s = "InternalPortWildcardingNotAllowed"; + break; + case 707: + s = "ProtocolWildcardingNotAllowed"; + break; + case 708: + s = "WildcardNotPermittedInSrcIP"; + break; + case 709: + s = "NoPacketSent"; + break; case 713: s = "SpecifiedArrayIndexInvalid"; break; @@ -60,7 +97,8 @@ const char * strupnperror(int err) s = "ExternalPortOnlySupportsWildcard"; break; default: - s = NULL; + s = "UnknownError"; + break; } return s; } diff --git a/3rdparty/miniupnpc/upnperrors.h b/3rdparty/miniupnpc/upnperrors.h index 2c544c97c..077d6938b 100644 --- a/3rdparty/miniupnpc/upnperrors.h +++ b/3rdparty/miniupnpc/upnperrors.h @@ -1,12 +1,12 @@ -/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */ +/* $Id: upnperrors.h,v 1.4 2012/09/27 15:42:11 nanard Exp $ */ /* (c) 2007 Thomas Bernard * All rights reserved. * MiniUPnP Project. * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * This software is subjet to the conditions detailed in the * provided LICENCE file. */ -#ifndef __UPNPERRORS_H__ -#define __UPNPERRORS_H__ +#ifndef UPNPERRORS_H_INCLUDED +#define UPNPERRORS_H_INCLUDED #include "declspec.h" @@ -15,7 +15,7 @@ extern "C" { #endif /* strupnperror() - * Return a string description of the UPnP error code + * Return a string description of the UPnP error code * or NULL for undefinded errors */ LIBSPEC const char * strupnperror(int err); diff --git a/3rdparty/miniupnpc/upnpreplyparse.c b/3rdparty/miniupnpc/upnpreplyparse.c index c72b4c825..dafa26313 100644 --- a/3rdparty/miniupnpc/upnpreplyparse.c +++ b/3rdparty/miniupnpc/upnpreplyparse.c @@ -1,7 +1,7 @@ -/* $Id: upnpreplyparse.c,v 1.10 2008/02/21 13:05:27 nanard Exp $ */ +/* $Id: upnpreplyparse.c,v 1.15 2013/06/06 21:36:40 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -15,40 +15,90 @@ static void NameValueParserStartElt(void * d, const char * name, int l) { - struct NameValueParserData * data = (struct NameValueParserData *)d; + struct NameValueParserData * data = (struct NameValueParserData *)d; + data->topelt = 1; if(l>63) l = 63; memcpy(data->curelt, name, l); data->curelt[l] = '\0'; + data->cdata = NULL; + data->cdatalen = 0; +} + +static void +NameValueParserEndElt(void * d, const char * name, int l) +{ + struct NameValueParserData * data = (struct NameValueParserData *)d; + struct NameValue * nv; + (void)name; + (void)l; + if(!data->topelt) + return; + if(strcmp(data->curelt, "NewPortListing") != 0) + { + int l; + /* standard case. Limited to n chars strings */ + l = data->cdatalen; + nv = malloc(sizeof(struct NameValue)); + if(l>=(int)sizeof(nv->value)) + l = sizeof(nv->value) - 1; + strncpy(nv->name, data->curelt, 64); + nv->name[63] = '\0'; + if(data->cdata != NULL) + { + memcpy(nv->value, data->cdata, l); + nv->value[l] = '\0'; + } + else + { + nv->value[0] = '\0'; + } + LIST_INSERT_HEAD( &(data->head), nv, entries); + } + data->cdata = NULL; + data->cdatalen = 0; + data->topelt = 0; } static void NameValueParserGetData(void * d, const char * datas, int l) { struct NameValueParserData * data = (struct NameValueParserData *)d; - struct NameValue * nv; - nv = malloc(sizeof(struct NameValue)); - if(l>63) - l = 63; - strncpy(nv->name, data->curelt, 64); - nv->name[63] = '\0'; - memcpy(nv->value, datas, l); - nv->value[l] = '\0'; - LIST_INSERT_HEAD( &(data->head), nv, entries); + if(strcmp(data->curelt, "NewPortListing") == 0) + { + /* specific case for NewPortListing which is a XML Document */ + data->portListing = malloc(l + 1); + if(!data->portListing) + { + /* malloc error */ + return; + } + memcpy(data->portListing, datas, l); + data->portListing[l] = '\0'; + data->portListingLength = l; + } + else + { + /* standard case. */ + data->cdata = datas; + data->cdatalen = l; + } } void ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data) + struct NameValueParserData * data) { struct xmlparser parser; LIST_INIT(&(data->head)); + data->portListing = NULL; + data->portListingLength = 0; /* init xmlparser object */ parser.xmlstart = buffer; parser.xmlsize = bufsize; parser.data = data; parser.starteltfunc = NameValueParserStartElt; - parser.endeltfunc = 0; + parser.endeltfunc = NameValueParserEndElt; parser.datafunc = NameValueParserGetData; parser.attfunc = 0; parsexml(&parser); @@ -58,6 +108,12 @@ void ClearNameValueList(struct NameValueParserData * pdata) { struct NameValue * nv; + if(pdata->portListing) + { + free(pdata->portListing); + pdata->portListing = NULL; + pdata->portListingLength = 0; + } while((nv = pdata->head.lh_first) != NULL) { LIST_REMOVE(nv, entries); @@ -65,7 +121,7 @@ ClearNameValueList(struct NameValueParserData * pdata) } } -char * +char * GetValueFromNameValueList(struct NameValueParserData * pdata, const char * Name) { @@ -106,7 +162,7 @@ GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, } #endif -/* debug all-in-one function +/* debug all-in-one function * do parsing then display to stdout */ #ifdef DEBUG void diff --git a/3rdparty/miniupnpc/upnpreplyparse.h b/3rdparty/miniupnpc/upnpreplyparse.h index fb7d4535c..d4e37576a 100644 --- a/3rdparty/miniupnpc/upnpreplyparse.h +++ b/3rdparty/miniupnpc/upnpreplyparse.h @@ -1,14 +1,14 @@ -/* $Id: upnpreplyparse.h,v 1.10 2009/07/09 16:01:50 nanard Exp $ */ +/* $Id: upnpreplyparse.h,v 1.17 2013/06/06 21:36:40 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2009 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ -#ifndef __UPNPREPLYPARSE_H__ -#define __UPNPREPLYPARSE_H__ +#ifndef UPNPREPLYPARSE_H_INCLUDED +#define UPNPREPLYPARSE_H_INCLUDED -#if defined(NO_SYS_QUEUE_H) || defined(WIN32) || defined(__HAIKU__) +#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__) #include "bsdqueue.h" #else #include @@ -21,12 +21,17 @@ extern "C" { struct NameValue { LIST_ENTRY(NameValue) entries; char name[64]; - char value[64]; + char value[128]; }; struct NameValueParserData { LIST_HEAD(listhead, NameValue) head; char curelt[64]; + char * portListing; + int portListingLength; + int topelt; + const char * cdata; + int cdatalen; }; /* ParseNameValue() */ @@ -43,10 +48,12 @@ char * GetValueFromNameValueList(struct NameValueParserData * pdata, const char * Name); +#if 0 /* GetValueFromNameValueListIgnoreNS() */ char * GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, const char * Name); +#endif /* DisplayNameValueList() */ #ifdef DEBUG diff --git a/lib/netplay/netplay.cpp b/lib/netplay/netplay.cpp index fd2496120..eb5316c7c 100644 --- a/lib/netplay/netplay.cpp +++ b/lib/netplay/netplay.cpp @@ -142,14 +142,15 @@ static SocketSet* socket_set = NULL; // UPnP static int upnp = false; -static bool upnp_done = false; + WZ_THREAD *upnpdiscover; static struct UPNPUrls urls; static struct IGDdatas data; // local ip address -static char lanaddr[16]; +static char lanaddr[40]; +static char externalIPAddress[40]; /** * Used for connections with clients. */ @@ -934,7 +935,6 @@ static bool NETrecvGAMESTRUCT(GAMESTRUCT* ourgamestruct) } - static int upnp_init(void *asdf) { struct UPNPDev *devlist; @@ -942,14 +942,14 @@ static int upnp_init(void *asdf) char *descXML; int descXMLsize = 0; char buf[255]; - + int result; memset(&urls, 0, sizeof(struct UPNPUrls)); memset(&data, 0, sizeof(struct IGDdatas)); if (NetPlay.isUPNP) { debug(LOG_NET, "Searching for UPnP devices for automatic port forwarding..."); - devlist = upnpDiscover(2000, NULL, NULL, 0); + devlist = upnpDiscover(3000, NULL, NULL, 0, 0, &result); debug(LOG_NET, "UPnP device search finished."); if (devlist) { @@ -967,13 +967,13 @@ static int upnp_init(void *asdf) debug(LOG_NET, "UPnP device found: %s %s\n", dev->descURL, dev->st); - descXML = (char *)miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, sizeof(lanaddr)); + descXML = (char *)miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, sizeof(lanaddr), dev->scope_id); debug(LOG_NET, "LAN address: %s", lanaddr); if (descXML) { parserootdesc (descXML, descXMLsize, &data); free (descXML); descXML = 0; - GetUPNPUrls (&urls, &data, dev->descURL); + GetUPNPUrls (&urls, &data, dev->descURL, dev->scope_id); } ssprintf(buf, "UPnP device found: %s %s LAN address %s", dev->descURL, dev->st, lanaddr); addDumpInfo(buf); @@ -983,13 +983,20 @@ static int upnp_init(void *asdf) { ssprintf(buf, "controlURL not available, UPnP disabled"); addDumpInfo(buf); + ssprintf(buf, _("Your router doesn't support UPnP, you must manually configure your router & firewall to open port 2100 before you can host a game.")); + addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); return false; } + + NETaddRedirects(); + upnp = true; return true; } ssprintf(buf, "UPnP device not found."); addDumpInfo(buf); debug(LOG_NET, "No UPnP devices found."); + ssprintf(buf, _("No UPnP device was found. You must manually configure your router & firewall to open port 2100 before you can host a game.")); + addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); return false; } else @@ -999,55 +1006,74 @@ static int upnp_init(void *asdf) debug(LOG_NET, "UPnP detection routine disabled by user."); return false; } + } static bool upnp_add_redirect(int port) { - char externalIP[16]; char port_str[16]; + char buf[512]={'\0'}; int r; - debug(LOG_NET, "upnp_add_redir(%d)\n", port); - UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIP); + debug(LOG_NET, "upnp_add_redir(%d)", port); sprintf(port_str, "%d", port); r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port_str, port_str, lanaddr, "Warzone 2100", "TCP", 0); + port_str, port_str, lanaddr, "Warzone 2100", "TCP", 0, "0"); // "0" = lease time unlimited if (r != UPNPCOMMAND_SUCCESS) { - debug(LOG_NET, "AddPortMapping(%s, %s, %s) failed\n", port_str, port_str, lanaddr); + ssprintf(buf, _("Could not open require port (%s) on (%s)"), port_str, lanaddr); + debug(LOG_NET, "%s", buf); + addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); + ssprintf(buf, _("You must manually configure your router & firewall to open port 2100 before you can host a game.")); + addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); return false; } - return true; + r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); + if(r != UPNPCOMMAND_SUCCESS) + { + ssprintf(externalIPAddress, "???"); + } + ssprintf(buf, _("Game configured port (%s) correctly on (%s). Your external IP is %s"), port_str, lanaddr, externalIPAddress); + addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); + + return true; } -static void upnp_rem_redirect(int port) +static int upnp_rem_redirect(int port) { char port_str[16]; debug(LOG_NET, "upnp_rem_redir(%d)", port); sprintf(port_str, "%d", port); - UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port_str, "TCP", 0); + return UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port_str, "TCP", NULL); } void NETaddRedirects(void) { - debug(LOG_NET, "%s\n", __FUNCTION__); - if (!upnp_done) + if (upnp_add_redirect(gameserver_port)) { - upnp = wzThreadJoin(upnpdiscover); - upnp_done = true; + debug(LOG_NET, "successful!"); } - if (upnp) { - upnp_add_redirect(gameserver_port); + else + { + debug(LOG_NET, "failed!"); } } void NETremRedirects(void) { - debug(LOG_NET, "%s\n", __FUNCTION__); + debug(LOG_NET, "upnp is %d", upnp); if (upnp) { - upnp_rem_redirect(gameserver_port); + int result = upnp_rem_redirect(gameserver_port); + if (!result) + { + debug(LOG_NET, "removed UPnP entry."); + } + else + { + debug(LOG_ERROR, "Failed to remove UPnP entry for the game. You must manually remove it from your router. (%d)", result); + } } } @@ -1096,6 +1122,10 @@ int NETshutdown(void) { debug( LOG_NET, "NETshutdown" ); NETlogEntry("NETshutdown", SYNC_FLAG, selectedPlayer); + if (NetPlay.bComms && NetPlay.isUPNP) + { + NETremRedirects(); + } NETstopLogging(); if (IPlist) free(IPlist); @@ -1108,11 +1138,6 @@ int NETshutdown(void) NETdeleteQueue(); SOCKETshutdown(); - if (NetPlay.bComms && NetPlay.isUPNP) - { - NETremRedirects(); - } - // Reset net usage statistics. nStats = nZeroStats; nStatsLastSec = nZeroStats; @@ -2587,10 +2612,6 @@ bool NEThostGame(const char* SessionName, const char* PlayerName, mapDownloadProgress = 100; netPlayersUpdated = true; - if (NetPlay.bComms && NetPlay.isUPNP) - { - NETaddRedirects(); - } NET_InitPlayers(); for (unsigned n = 0; n < MAX_PLAYERS_IN_GUI; ++n) { diff --git a/lib/netplay/netplay.vcxproj b/lib/netplay/netplay.vcxproj index e49168140..fa105d12d 100644 --- a/lib/netplay/netplay.vcxproj +++ b/lib/netplay/netplay.vcxproj @@ -207,6 +207,8 @@ + + @@ -246,8 +248,11 @@ + + + diff --git a/lib/netplay/netplay.vcxproj.filters b/lib/netplay/netplay.vcxproj.filters index a0db0845b..829b2e6be 100644 --- a/lib/netplay/netplay.vcxproj.filters +++ b/lib/netplay/netplay.vcxproj.filters @@ -68,6 +68,12 @@ Source Files + + Source Files\miniUPnP\src files + + + Source Files\miniUPnP\src files + @@ -127,5 +133,14 @@ Header Files + + Source Files\miniUPnP\header files + + + Source Files\miniUPnP\header files + + + Source Files\miniUPnP\header files + \ No newline at end of file diff --git a/src/frontend.cpp b/src/frontend.cpp index 3d1f0e066..97e2e10c4 100644 --- a/src/frontend.cpp +++ b/src/frontend.cpp @@ -412,11 +412,11 @@ bool runMultiPlayerMenu(void) case FRONTEND_HOST: // don't pretend we are running a network game. Really do it! NetPlay.bComms = true; // use network = true - NETdiscoverUPnPDevices(); ingame.bHostSetup = true; bMultiPlayer = true; bMultiMessages = true; NETinit(true); + NETdiscoverUPnPDevices(); game.type = SKIRMISH; // needed? lastTitleMode = MULTI; changeTitleMode(MULTIOPTION); diff --git a/src/multiint.cpp b/src/multiint.cpp index c7767c998..2c5bed2ae 100644 --- a/src/multiint.cpp +++ b/src/multiint.cpp @@ -3870,9 +3870,22 @@ bool startMultiOptions(bool bReenter) addPlayerBox(false); // Players addGameOptions(); - addChatBox(); + char buf[512]={'\0'}; + if (NetPlay.isUPNP) + { + ssprintf(buf, _("UPnP detection is in progress...")); + addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); + } + else + { + ssprintf(buf, _("UPnP detection disabled by user. Autoconfig of port 2100 will not happen.")); + addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); + } + ssprintf(buf, _("Press the start hosting button to begin hosting a game.")); + addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); + // going back to multiop after setting limits up.. if(bReenter && bHosted) { From f6dea54529eebb74b2617cc8165466dab645cdf0 Mon Sep 17 00:00:00 2001 From: vexed Date: Sun, 27 Oct 2013 21:03:36 -0400 Subject: [PATCH 3/3] Update ChangeLog --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3fc26c825..c831feb63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,7 @@ * Change: Filter out bad maps (commit:acfe83cdf6f44660276ba73931e2cebdc8a250ac) * Change: Also show in the bottom menu, if allies are researching the same as us (commit:b6b6265e4e430486ea44a200bce870b115dfc37f) * Change: Keep showing allied research even while facilities are upgraded (commit:423e358b6715c12dda70ff5f6f2bd0348c09f699) - * Change: Retreat buttons now should health bar colours (commit:4e2f4bbf3cd5e03e58b9b67fcf370bff088e6d91) + * Change: Retreat buttons now show health bar colours (commit:4e2f4bbf3cd5e03e58b9b67fcf370bff088e6d91) * Fix: Bug that made droids produced by scripts get human player's upgrades (commit:8149dc94c0b61117982281cdaf2aac1bec2525e9) * Fix: Backwards terrain shadows (commit:85ecd9a3937e7843d9eb4798572651f950bd7555) * Fix: Mod loading bug (commit:87cade1a684f3da0572f13e92539100f35b4f6fe, ticket:3567) @@ -24,6 +24,7 @@ * Fix: Add parameter checking for buildings that do not exist (commit:e38de7b64242a547acd77c7775dbfae10c74ca3d) * Maps: * Fix: Remove lop-sided oil barrels from 4c-pyramidal (commit:6092fe1194529f0c7fe023d9c98973e44f9f9f24) + * Add: Gamma (3p) and Melting (6p) by NoQ (commit:b8bdf44737e1d9423c2581b1377cf1be9c4a3666) * Build system: * Change: Simplify build process by getting rid of bison/flex dependencies (commit:d13bc0de7dd0588351af24dc45d55110d0eed6e8) * Fix: Building on OpenBSD (commit:9b9383500fb4c1dd5270a68e3490dc358e2da55f, ticket:3917, commit:47a6d6d4684b993d15e378f6d0877fa043b26ca0, ticket:3845)