diff --git a/source/shared_lib/include/platform/miniupnpc/connecthostport.h b/source/shared_lib/include/platform/miniupnpc/connecthostport.h new file mode 100644 index 000000000..57e24eb27 --- /dev/null +++ b/source/shared_lib/include/platform/miniupnpc/connecthostport.h @@ -0,0 +1,17 @@ +/* $Id: connecthostport.h,v 1.1 2010/04/04 23:21:03 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ + * Author: Thomas Bernard + * Copyright (c) 2010 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef __CONNECTHOSTPORT_H__ +#define __CONNECTHOSTPORT_H__ + +/* 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); + +#endif + diff --git a/source/shared_lib/include/platform/miniupnpc/declspec.h b/source/shared_lib/include/platform/miniupnpc/declspec.h index 5ab69a19b..b804247d2 100644 --- a/source/shared_lib/include/platform/miniupnpc/declspec.h +++ b/source/shared_lib/include/platform/miniupnpc/declspec.h @@ -5,9 +5,7 @@ #ifdef MINIUPNP_EXPORTS #define LIBSPEC __declspec(dllexport) #else -// NOTE: with the cross compiler, even if we have -DSTATICLIB, for some odd reason it still does this -// #define LIBSPEC __declspec(dllimport) which is not what we want. So we hack the line like so. - #define LIBSPEC + #define LIBSPEC __declspec(dllimport) #endif #else #define LIBSPEC diff --git a/source/shared_lib/include/platform/miniupnpc/igd_desc_parse.h b/source/shared_lib/include/platform/miniupnpc/igd_desc_parse.h index aabcb087d..bab1fd56f 100644 --- a/source/shared_lib/include/platform/miniupnpc/igd_desc_parse.h +++ b/source/shared_lib/include/platform/miniupnpc/igd_desc_parse.h @@ -1,8 +1,8 @@ -/* $Id: igd_desc_parse.h,v 1.6 2008/04/23 11:51:07 nanard Exp $ */ +/* $Id: igd_desc_parse.h,v 1.10 2011/04/11 09:19:24 nanard Exp $ */ /* Project : miniupnp * http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2008 Thomas Bernard + * Copyright (c) 2005-2010 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ @@ -12,30 +12,31 @@ /* Structure to store the result of the parsing of UPnP * descriptions of Internet Gateway Devices */ #define MINIUPNPC_URL_MAXSIZE (128) -struct IGDdatas { - char cureltname[MINIUPNPC_URL_MAXSIZE]; - char urlbase[MINIUPNPC_URL_MAXSIZE]; - int level; - /*int state;*/ - /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ - char controlurl_CIF[MINIUPNPC_URL_MAXSIZE]; - char eventsuburl_CIF[MINIUPNPC_URL_MAXSIZE]; - char scpdurl_CIF[MINIUPNPC_URL_MAXSIZE]; - char servicetype_CIF[MINIUPNPC_URL_MAXSIZE]; - /*char devicetype_CIF[MINIUPNPC_URL_MAXSIZE];*/ - /* "urn:schemas-upnp-org:service:WANIPConnection:1" - * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ +struct IGDdatas_service { char controlurl[MINIUPNPC_URL_MAXSIZE]; char eventsuburl[MINIUPNPC_URL_MAXSIZE]; char scpdurl[MINIUPNPC_URL_MAXSIZE]; char servicetype[MINIUPNPC_URL_MAXSIZE]; /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ +}; + +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" */ + struct IGDdatas_service CIF; + /* "urn:schemas-upnp-org:service:WANIPConnection:1" + * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ + 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 */ - char controlurl_tmp[MINIUPNPC_URL_MAXSIZE]; - char eventsuburl_tmp[MINIUPNPC_URL_MAXSIZE]; - char scpdurl_tmp[MINIUPNPC_URL_MAXSIZE]; - char servicetype_tmp[MINIUPNPC_URL_MAXSIZE]; - /*char devicetype_tmp[MINIUPNPC_URL_MAXSIZE];*/ + struct IGDdatas_service tmp; }; void IGDstartelt(void *, const char *, int); diff --git a/source/shared_lib/include/platform/miniupnpc/minisoap.h b/source/shared_lib/include/platform/miniupnpc/minisoap.h index 9fa297fd3..696725f62 100644 --- a/source/shared_lib/include/platform/miniupnpc/minisoap.h +++ b/source/shared_lib/include/platform/miniupnpc/minisoap.h @@ -1,4 +1,4 @@ -/* $Id: minisoap.h,v 1.3 2006/11/19 22:32:34 nanard Exp $ */ +/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005 Thomas Bernard @@ -9,7 +9,7 @@ /*int httpWrite(int, const char *, int, const char *);*/ int soapPostSubmit(int, const char *, const char *, unsigned short, - const char *, const char *); + const char *, const char *, const char *); #endif diff --git a/source/shared_lib/include/platform/miniupnpc/miniupnpc.h b/source/shared_lib/include/platform/miniupnpc/miniupnpc.h index 9a619e6b9..50df01777 100644 --- a/source/shared_lib/include/platform/miniupnpc/miniupnpc.h +++ b/source/shared_lib/include/platform/miniupnpc/miniupnpc.h @@ -1,19 +1,21 @@ -/* $Id: miniupnpc.h,v 1.19 2009/10/10 19:15:35 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.23 2011/04/11 08:21:46 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard - * Copyright (c) 2005-2006 Thomas Bernard + * Copyright (c) 2005-2011 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef __MINIUPNPC_H__ #define __MINIUPNPC_H__ -#define MEGAGLEST_EMBEDDED_MINIUPNPC - #include "declspec.h" #include "igd_desc_parse.h" -#undef DEBUG +/* error codes : */ +#define UPNPDISCOVER_SUCCESS (0) +#define UPNPDISCOVER_UNKNOWN_ERROR (-1) +#define UPNPDISCOVER_SOCKET_ERROR (-101) +#define UPNPDISCOVER_MEMORY_ERROR (-102) #ifdef __cplusplus extern "C" { @@ -22,9 +24,10 @@ 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; @@ -46,8 +49,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); @@ -61,11 +67,13 @@ 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; }; /* UPNP_GetValidIGD() : @@ -101,11 +109,6 @@ LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *); 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); - /* return 0 or 1 */ LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); diff --git a/source/shared_lib/include/platform/miniupnpc/miniupnpctypes.h b/source/shared_lib/include/platform/miniupnpc/miniupnpctypes.h new file mode 100644 index 000000000..86081c3cc --- /dev/null +++ b/source/shared_lib/include/platform/miniupnpc/miniupnpctypes.h @@ -0,0 +1,19 @@ +/* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 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__ +#define __MINIUPNPCTYPES_H__ + +#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/source/shared_lib/include/platform/miniupnpc/miniwget.h b/source/shared_lib/include/platform/miniupnpc/miniwget.h index 12c062c6d..8314b4000 100644 --- a/source/shared_lib/include/platform/miniupnpc/miniwget.h +++ b/source/shared_lib/include/platform/miniupnpc/miniwget.h @@ -1,4 +1,4 @@ -/* $Id: miniwget.h,v 1.5 2007/01/29 20:27:23 nanard Exp $ */ +/* $Id: miniwget.h,v 1.6 2010/12/09 16:11:33 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005 Thomas Bernard @@ -14,6 +14,8 @@ extern "C" { #endif +LIBSPEC void * getHTTPResponse(int s, int * size); + LIBSPEC void * miniwget(const char *, int *); LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int); diff --git a/source/shared_lib/include/platform/miniupnpc/portlistingparse.h b/source/shared_lib/include/platform/miniupnpc/portlistingparse.h new file mode 100644 index 000000000..18524786c --- /dev/null +++ b/source/shared_lib/include/platform/miniupnpc/portlistingparse.h @@ -0,0 +1,71 @@ +/* $Id: portlistingparse.h,v 1.4 2011/02/15 23:03:56 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 */ +#ifndef __PORTLISTINGPARSE_H__ +#define __PORTLISTINGPARSE_H__ + +#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/source/shared_lib/include/platform/miniupnpc/receivedata.h b/source/shared_lib/include/platform/miniupnpc/receivedata.h new file mode 100644 index 000000000..7a551b9ac --- /dev/null +++ b/source/shared_lib/include/platform/miniupnpc/receivedata.h @@ -0,0 +1,17 @@ +/* $Id: receivedata.h,v 1.1 2011/04/11 08:21:47 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2011 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef __RECEIVEDATA_H__ +#define __RECEIVEDATA_H__ + +/* 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); + +#endif + diff --git a/source/shared_lib/include/platform/miniupnpc/upnpcommands.h b/source/shared_lib/include/platform/miniupnpc/upnpcommands.h index 217c472be..66d95e0ca 100644 --- a/source/shared_lib/include/platform/miniupnpc/upnpcommands.h +++ b/source/shared_lib/include/platform/miniupnpc/upnpcommands.h @@ -1,32 +1,27 @@ -/* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */ +/* $Id: upnpcommands.h,v 1.23 2011/04/11 09:14:00 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2008 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__ #include "upnpreplyparse.h" +#include "portlistingparse.h" #include "declspec.h" +#include "miniupnpctypes.h" /* MiniUPnPc return codes : */ #define UPNPCOMMAND_SUCCESS (0) #define UPNPCOMMAND_UNKNOWN_ERROR (-1) #define UPNPCOMMAND_INVALID_ARGS (-2) +#define UPNPCOMMAND_HTTP_ERROR (-3) #ifdef __cplusplus 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); @@ -125,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(). @@ -145,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 @@ -160,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 @@ -185,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/source/shared_lib/include/platform/miniupnpc/upnpreplyparse.h b/source/shared_lib/include/platform/miniupnpc/upnpreplyparse.h index fb7d4535c..267ea8783 100644 --- a/source/shared_lib/include/platform/miniupnpc/upnpreplyparse.h +++ b/source/shared_lib/include/platform/miniupnpc/upnpreplyparse.h @@ -1,7 +1,7 @@ -/* $Id: upnpreplyparse.h,v 1.10 2009/07/09 16:01:50 nanard Exp $ */ +/* $Id: upnpreplyparse.h,v 1.11 2011/02/07 16:17:06 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2009 Thomas Bernard + * (c) 2006-2011 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -27,6 +27,8 @@ struct NameValue { struct NameValueParserData { LIST_HEAD(listhead, NameValue) head; char curelt[64]; + char * portListing; + int portListingLength; }; /* ParseNameValue() */ diff --git a/source/shared_lib/sources/platform/miniupnpc/Changelog.txt b/source/shared_lib/sources/platform/miniupnpc/Changelog.txt new file mode 100644 index 000000000..70b656498 --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/Changelog.txt @@ -0,0 +1,452 @@ +$Id: Changelog.txt,v 1.152 2011/07/25 18:02:11 nanard Exp $ +miniUPnP client Changelog. + +VERSION 1.6 : released 2011/07/25 + +2011/07/25: + Update doc for version 1.6 release + +2011/06/18: + Fix for windows in miniwget.c + +2011/06/04: + display remote host in port mapping listing + +2011/06/03: + Fix in make install : there were missing headers + +2011/05/26: + Fix the socket leak in miniwget thanks to Richard Marsh. + Permit to add leaseduration in -a command. Display lease duration. + +2011/05/15: + Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6 + +2011/05/09: + add a test in testminiwget.sh. + more error checking in miniwget.c + +2011/05/06: + Adding some tool to test and validate miniwget.c + simplified and debugged miniwget.c + +2011/04/11: + moving ReceiveData() to a receivedata.c file. + parsing presentation url + adding IGD v2 WANIPv6FirewallControl commands + +2011/04/10: + update of miniupnpcmodule.c + comments in miniwget.c, update in testminiwget + Adding errors codes from IGD v2 + new functions in upnpc.c for IGD v2 + +2011/04/09: + Support for litteral ip v6 address in miniwget + +2011/04/08: + Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 + Updating APIVERSION + Supporting IPV6 in upnpDiscover() + Adding a -6 option to upnpc command line tool + +2011/03/18: + miniwget/parseURL() : return an error when url param is null. + fixing GetListOfPortMappings() + +2011/03/14: + upnpDiscover() now reporting an error code. + improvements in comments. + +2011/03/11: + adding miniupnpcstrings.h.cmake and CMakeLists.txt files. + +2011/02/15: + Implementation of GetListOfPortMappings() + +2011/02/07: + updates to minixml to support character data starting with spaces + minixml now support CDATA + upnpreplyparse treats specificaly + change in simpleUPnPcommand to return the buffer (simplification) + +2011/02/06: + Added leaseDuration argument to AddPortMapping() + Starting to implement GetListOfPortMappings() + +2011/01/11: + updating wingenminiupnpcstrings.c + +2011/01/04: + improving updateminiupnpcstrings.sh + +VERSION 1.5 : released 2011/01/01 + +2010/12/21: + use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo + +2010/12/11: + Improvements on getHTTPResponse() code. + +2010/12/09: + new code for miniwget that handle Chunked transfer encoding + using getHTTPResponse() in SOAP call code + Adding MANIFEST.in for 'python setup.py bdist_rpm' + +2010/11/25: + changes to minissdpc.c to compile under Win32. + see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729 + +2010/09/17: + Various improvement to Makefile from MichaÅ‚ Górny + +2010/08/05: + Adding the script "external-ip.sh" from Reuben Hawkins + +2010/06/09: + update to python module to match modification made on 2010/04/05 + update to Java test code to match modification made on 2010/04/05 + all UPNP_* function now return an error if the SOAP request failed + at HTTP level. + +2010/04/17: + Using GetBestRoute() under win32 in order to find the + right interface to use. + +2010/04/12: + Retrying with HTTP/1.1 if HTTP/1.0 failed. see + http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703 + +2010/04/07: + avoid returning duplicates in upnpDiscover() + +2010/04/05: + Create a connecthostport.h/.c with connecthostport() function + and use it in miniwget and miniupnpc. + Use getnameinfo() instead of inet_ntop or inet_ntoa + Work to make miniupnpc IPV6 compatible... + Add java test code. + Big changes in order to support device having both WANIPConnection + and WANPPPConnection. + +2010/04/04: + Use getaddrinfo() instead of gethostbyname() in miniwget. + +2010/01/06: + #define _DARWIN_C_SOURCE for Mac OS X + +2009/12/19: + Improve MinGW32 build + +2009/12/11: + adding a MSVC9 project to build the static library and executable + +2009/12/10: + Fixing some compilation stuff for Windows/MinGW + +2009/12/07: + adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS + some fixes for Windows when using virtual ethernet adapters (it is the + case with VMWare installed). + +2009/12/04: + some fixes for AmigaOS compilation + Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked + transfer encoding) + +2009/12/03: + updating printIDG and testigddescparse.c for debug. + modifications to compile under AmigaOS + adding a testminiwget program + Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked + transfer encoding + +2009/11/26: + fixing updateminiupnpcstrings.sh to take into account + which command that does not return an error code. + +VERSION 1.4 : released 2009/10/30 + +2009/10/16: + using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module. + +2009/10/10: + Some fixes for compilation under Solaris + compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464 + +2009/09/21: + fixing the code to ignore EINTR during connect() calls. + +2009/08/07: + Set socket timeout for connect() + Some cleanup in miniwget.c + +2009/08/04: + remove multiple redirections with -d in upnpc.c + Print textual error code in upnpc.c + Ignore EINTR during the connect() and poll() calls. + +2009/07/29: + fix in updateminiupnpcstrings.sh if OS name contains "/" + Sending a correct value for MX: field in SSDP request + +2009/07/20: + Change the Makefile to compile under Mac OS X + Fixed a stackoverflow in getDevicesFromMiniSSDPD() + +2009/07/09: + Compile under Haiku + generate miniupnpcstrings.h.in from miniupnpcstrings.h + +2009/06/04: + patching to compile under CygWin and cross compile for minGW + +VERSION 1.3 : + +2009/04/17: + updating python module + Use strtoull() when using C99 + +2009/02/28: + Fixed miniwget.c for compiling under sun + +2008/12/18: + cleanup in Makefile (thanks to Paul de Weerd) + minissdpc.c : win32 compatibility + miniupnpc.c : changed xmlns prefix from 'm' to 'u' + Removed NDEBUG (using DEBUG) + +2008/10/14: + Added the ExternalHost argument to DeletePortMapping() + +2008/10/11: + Added the ExternalHost argument to AddPortMapping() + Put a correct User-Agent: header in HTTP requests. + +VERSION 1.2 : + +2008/10/07: + Update docs + +2008/09/25: + Integrated sameport patch from Dario Meloni : Added a "sameport" + argument to upnpDiscover(). + +2008/07/18: + small modif to make Clang happy :) + +2008/07/17: + #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... + +2008/07/14: + include declspec.h in installation (to /usr/include/miniupnpc) + +VERSION 1.1 : + +2008/07/04: + standard options for install/ln instead of gnu-specific stuff. + +2008/07/03: + now builds a .dll and .lib with win32. (mingw32) + +2008/04/28: + make install now install the binary of the upnpc tool + +2008/04/27: + added testupnpigd.py + added error strings for miniupnpc "internal" errors + improved python module error/exception reporting. + +2008/04/23: + Completely rewrite igd_desc_parse.c in order to be compatible with + Linksys WAG200G + Added testigddescparse + updated python module + +VERSION 1.0 : + +2008/02/21: + put some #ifdef DEBUG around DisplayNameValueList() + +2008/02/18: + Improved error reporting in upnpcommands.c + UPNP_GetStatusInfo() returns LastConnectionError + +2008/02/16: + better error handling in minisoap.c + improving display of "valid IGD found" in upnpc.c + +2008/02/03: + Fixing UPNP_GetValidIGD() + improved make install :) + +2007/12/22: + Adding upnperrors.c/h to provide a strupnperror() function + used to translate UPnP error codes to string. + +2007/12/19: + Fixing getDevicesFromMiniSSDPD() + improved error reporting of UPnP functions + +2007/12/18: + It is now possible to specify a different location for MiniSSDPd socket. + working with MiniSSDPd is now more efficient. + python module improved. + +2007/12/16: + improving error reporting + +2007/12/13: + Try to improve compatibility by using HTTP/1.0 instead of 1.1 and + XML a bit different for SOAP. + +2007/11/25: + fixed select() call for linux + +2007/11/15: + Added -fPIC to CFLAG for better shared library code. + +2007/11/02: + Fixed a potential socket leak in miniwget2() + +2007/10/16: + added a parameter to upnpDiscover() in order to allow the use of another + interface than the default multicast interface. + +2007/10/12: + Fixed the creation of symbolic link in Makefile + +2007/10/08: + Added man page + +2007/10/02: + fixed memory bug in GetUPNPUrls() + +2007/10/01: + fixes in the Makefile + Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly. + Added SONAME in the shared library to please debian :) + fixed MS Windows compilation (minissdpd is not available under MS Windows). + +2007/09/25: + small change to Makefile to be able to install in a different location + (default is /usr) + +2007/09/24: + now compiling both shared and static library + +2007/09/19: + Cosmetic changes on upnpc.c + +2007/09/02: + adapting to new miniSSDPd (release version ?) + +2007/08/31: + Usage of miniSSDPd to skip discovery process. + +2007/08/27: + fixed python module to allow compilation with Python older than Python 2.4 + +2007/06/12: + Added a python module. + +2007/05/19: + Fixed compilation under MinGW + +2007/05/15: + fixed a memory leak in AddPortMapping() + Added testupnpreplyparse executable to check the parsing of + upnp soap messages + minixml now ignore namespace prefixes. + +2007/04/26: + upnpc now displays external ip address with -s or -l + +2007/04/11: + changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210" + +2007/03/19: + cleanup in miniwget.c + +2007/03/01: + Small typo fix... + +2007/01/30: + Now parsing the HTTP header from SOAP responses in order to + get content-length value. + +2007/01/29: + Fixed the Soap Query to speedup the HTTP request. + added some Win32 DLL stuff... + +2007/01/27: + Fixed some WIN32 compatibility issues + +2006/12/14: + Added UPNPIGD_IsConnected() function in miniupnp.c/.h + Added UPNP_GetValidIGD() in miniupnp.c/.h + cleaned upnpc.c main(). now using UPNP_GetValidIGD() + +2006/12/07: + Version 1.0-RC1 released + +2006/12/03: + Minor changes to compile under SunOS/Solaris + +2006/11/30: + made a minixml parser validator program + updated minixml to handle attributes correctly + +2006/11/22: + Added a -r option to the upnpc sample thanks to Alexander Hubmann. + +2006/11/19: + Cleanup code to make it more ANSI C compliant + +2006/11/10: + detect and display local lan address. + +2006/11/04: + Packets and Bytes Sent/Received are now unsigned int. + +2006/11/01: + Bug fix thanks to Giuseppe D'Angelo + +2006/10/31: + C++ compatibility for .h files. + Added a way to get ip Address on the LAN used to reach the IGD. + +2006/10/25: + Added M-SEARCH to the services in the discovery process. + +2006/10/22: + updated the Makefile to use makedepend, added a "make install" + update Makefile + +2006/10/20: + fixing the description url parsing thanks to patch sent by + Wayne Dawe. + Fixed/translated some comments. + Implemented a better discover process, first looking + for IGD then for root devices (as some devices only reply to + M-SEARCH for root devices). + +2006/09/02: + added freeUPNPDevlist() function. + +2006/08/04: + More command line arguments checking + +2006/08/01: + Added the .bat file to compile under Win32 with minGW32 + +2006/07/31: + Fixed the rootdesc parser (igd_desc_parse.c) + +2006/07/20: + parseMSEARCHReply() is now returning the ST: line as well + starting changes to detect several UPnP devices on the network + +2006/07/19: + using GetCommonLinkProperties to get down/upload bitrate + diff --git a/source/shared_lib/sources/platform/miniupnpc/LICENSE b/source/shared_lib/sources/platform/miniupnpc/LICENSE new file mode 100644 index 000000000..2434c86e4 --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/LICENSE @@ -0,0 +1,27 @@ +MiniUPnPc +Copyright (c) 2005-2011, Thomas BERNARD +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/source/shared_lib/sources/platform/miniupnpc/Makefile b/source/shared_lib/sources/platform/miniupnpc/Makefile index 046bf6296..2f46e6d19 100644 --- a/source/shared_lib/sources/platform/miniupnpc/Makefile +++ b/source/shared_lib/sources/platform/miniupnpc/Makefile @@ -1,553 +1,214 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. -# lib/netplay/miniupnpc/Makefile. Generated from Makefile.in by configure. +# $Id: Makefile,v 1.81 2011/06/21 15:24:14 nanard Exp $ +# MiniUPnP Project +# http://miniupnp.free.fr/ +# (c) 2005-2011 Thomas Bernard +# to install use : +# $ PREFIX=/tmp/dummylocation make install +# or +# $ INSTALLPREFIX=/usr/local make install +# or +# make install (will go to /usr/bin, /usr/lib, etc...) +OS = $(shell uname -s) +CC ?= gcc +#AR = gar +#CFLAGS = -O -Wall -g -DDEBUG +CFLAGS ?= -O -Wall -DNDEBUG -DMINIUPNPC_SET_SOCKET_TIMEOUT -Wstrict-prototypes +# -DNO_GETADDRINFO +INSTALL = install +SH = /bin/sh +JAVA = java +# see http://code.google.com/p/jnaerator/ +JNAERATOR = jnaerator-0.9.3.jar +#following libs are needed on Solaris +#LDLIBS=-lsocket -lnsl -lresolv -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. +# APIVERSION is used to build SONAME +APIVERSION = 8 -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. +SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \ + upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \ + minixmlvalid.c testupnpreplyparse.c minissdpc.c \ + upnperrors.c testigddescparse.c testminiwget.c \ + connecthostport.c portlistringparse.c receivedata.c + +LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \ + miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ + connecthostport.o portlistingparse.o receivedata.o + +ifneq ($(OS), AmigaOS) +CFLAGS := -fPIC $(CFLAGS) +LIBOBJS := $(LIBOBJS) minissdpc.o +endif + +OBJS = $(patsubst %.c,%.o,$(SRCS)) + +# HEADERS to install +HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \ + upnpreplyparse.h upnperrors.h miniupnpctypes.h \ + portlistingparse.h \ + declspec.h + +# library names +LIBRARY = libminiupnpc.a +ifeq ($(OS), Darwin) + SHAREDLIBRARY = libminiupnpc.dylib + SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib + CFLAGS := -DMACOSX -D_DARWIN_C_SOURCE $(CFLAGS) +else + SHAREDLIBRARY = libminiupnpc.so + SONAME = $(SHAREDLIBRARY).$(APIVERSION) +endif + +EXECUTABLES = upnpc-static +EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \ + testigddescparse testminiwget + +TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o + +TESTMINIWGETOBJS = miniwget.o testminiwget.o connecthostport.o receivedata.o + +TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o + +TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.o \ + miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \ + minisoap.o connecthostport.o receivedata.o \ + portlistingparse.o + +ifneq ($(OS), AmigaOS) +EXECUTABLES := $(EXECUTABLES) upnpc-shared +TESTMINIWGETOBJS := $(TESTMINIWGETOBJS) minissdpc.o +TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o +endif + +# install directories +INSTALLPREFIX ?= $(PREFIX)/usr +INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc +INSTALLDIRLIB = $(INSTALLPREFIX)/lib +INSTALLDIRBIN = $(INSTALLPREFIX)/bin + +FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES) +ifneq ($(OS), AmigaOS) +FILESTOINSTALL := $(FILESTOINSTALL) $(SHAREDLIBRARY) +endif +.PHONY: install clean depend all check everything \ + installpythonmodule +# validateminixml validateminiwget +all: $(LIBRARY) $(EXECUTABLES) +check: validateminixml validateminiwget -pkgdatadir = $(datadir)/warzone2100 -pkgincludedir = $(includedir)/warzone2100 -pkglibdir = $(libdir)/warzone2100 -pkglibexecdir = $(libexecdir)/warzone2100 -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = i686-pc-linux-gnu -host_triplet = i686-pc-linux-gnu -subdir = lib/netplay/miniupnpc -DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c_check_flag.m4 \ - $(top_srcdir)/m4/ax_compare_version.m4 \ - $(top_srcdir)/m4/ax_ext_check_header.m4 \ - $(top_srcdir)/m4/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4/ax_with_prog.m4 $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ - $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/progversion.m4 \ - $(top_srcdir)/m4/stack-protector.m4 \ - $(top_srcdir)/m4/strlfuncs.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LIBRARIES = $(noinst_LIBRARIES) -AR = ar -ARFLAGS = cru -libminiupnpc_a_AR = $(AR) $(ARFLAGS) -libminiupnpc_a_LIBADD = -am_libminiupnpc_a_OBJECTS = miniwget.$(OBJEXT) minixml.$(OBJEXT) \ - igd_desc_parse.$(OBJEXT) minisoap.$(OBJEXT) \ - miniupnpc.$(OBJEXT) upnpreplyparse.$(OBJEXT) \ - upnpcommands.$(OBJEXT) minissdpc.$(OBJEXT) \ - upnperrors.$(OBJEXT) -libminiupnpc_a_OBJECTS = $(am_libminiupnpc_a_OBJECTS) -DEFAULT_INCLUDES = -I. -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(libminiupnpc_a_SOURCES) -DIST_SOURCES = $(libminiupnpc_a_SOURCES) -HEADERS = $(noinst_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = ${SHELL} /home/softcoder/Code/warzone2100/trunk/missing --run aclocal-1.11 -AMTAR = ${SHELL} /home/softcoder/Code/warzone2100/trunk/missing --run tar -AUTOCONF = ${SHELL} /home/softcoder/Code/warzone2100/trunk/missing --run autoconf -AUTOHEADER = ${SHELL} /home/softcoder/Code/warzone2100/trunk/missing --run autoheader -AUTOMAKE = ${SHELL} /home/softcoder/Code/warzone2100/trunk/missing --run automake-1.11 -AWK = gawk -BFD_LIBS = -CC = gcc -std=gnu99 -CCDEPMODE = depmode=gcc3 -CC_FOR_BUILD = gcc -std=gnu99 -CFLAGS = -fstack-protector -CFLAGS_FOR_BUILD = -fstack-protector -CPP = gcc -std=gnu99 -E -CPPFLAGS = -CPPFLAGS_FOR_BUILD = -CXX = g++ -CXXDEPMODE = depmode=gcc3 -CXXFLAGS = -g -O2 -fstack-protector -CXXFLAGS_FOR_BUILD = -g -O2 -fstack-protector -CXX_FOR_BUILD = g++ -CYGPATH_W = echo -DEFS = -DHAVE_CONFIG_H -DEPDIR = .deps -ECHO_C = -ECHO_N = -n -ECHO_T = -EGREP = /bin/grep -E -EXEEXT = -FONTCONFIG_CFLAGS = -FONTCONFIG_LIBS = -FREETYPE_CFLAGS = -FREETYPE_LIBS = -GETTEXT_MACRO_VERSION = 0.17 -GLee_CFLAGS = -I$(top_srcdir)/lib/ivis_opengl -GLee_LIBS = -GMSGFMT = /usr/bin/msgfmt -GMSGFMT_015 = /usr/bin/msgfmt -GREP = /bin/grep -IBERTY_LIBS = -INSTALL = /usr/bin/install -c -INSTALLER_COMPRESSION = lzma -INSTALLER_EXTDIR = -INSTALLER_VERSION = -INSTALL_DATA = ${INSTALL} -m 644 -INSTALL_PROGRAM = ${INSTALL} -INSTALL_SCRIPT = ${INSTALL} -INSTALL_STRIP_PROGRAM = $(install_sh) -c -s -INTLLIBS = -INTL_MACOSX_LIBS = -LDFLAGS = -rdynamic -LEX = flex -LEXLIB = -lfl -LEX_OUTPUT_ROOT = lex.yy -LIBICONV = -liconv -LIBINTL = -LIBOBJS = -LIBS = -LTLIBICONV = -liconv -LTLIBINTL = -LTLIBOBJS = -MAKEINFO = ${SHELL} /home/softcoder/Code/warzone2100/trunk/missing --run makeinfo -MAKENSIS = -MKDIR_P = /bin/mkdir -p -MSGFMT = /usr/bin/msgfmt -MSGFMT_015 = /usr/bin/msgfmt -MSGMERGE = /usr/bin/msgmerge -OBJEXT = o -OGGVORBIS_CFLAGS = -OGGVORBIS_LIBS = -lvorbisfile -lvorbis -lm -logg -OPENAL_CFLAGS = -I/usr/local/include -OPENAL_LIBS = -L/usr/local/lib -lopenal -OPENGLC_LIBS = -lGLC -OPENGL_LIBS = -lGL -lGLU -PACKAGE = warzone2100 -PACKAGE_BUGREPORT = http://wz2100.net/ -PACKAGE_NAME = Warzone 2100 -PACKAGE_STRING = Warzone 2100 TRUNK -PACKAGE_TARNAME = warzone2100 -PACKAGE_URL = -PACKAGE_VERSION = TRUNK -PATH_SEPARATOR = : -PERL = /usr/bin/perl -PERL_VERSION = 5.10.0 -PHYSFS_LIBS = -lphysfs -PKGCONFIG_DEFAULT_PREFIX = -PKGCONFIG_PREFIX = -PKG_CONFIG = /usr/bin/pkg-config -PNG_CFLAGS = -I/usr/local/include/libpng12 -PNG_LIBS = -L/usr/local/lib -lpng12 -POSUB = po -RANLIB = ranlib -SDL_CFLAGS = -D_GNU_SOURCE=1 -D_REENTRANT -I/usr/include/SDL -SDL_LIBS = -lSDL -SED = /bin/sed -SET_MAKE = -SHELL = /bin/sh -STRIP = -THEORA_CFLAGS = -THEORA_LIBS = -ltheora -logg -UNZIP = unzip -USE_NLS = yes -VERSION = TRUNK -WIN32_LIBS = -WINDRES = -WZ_C99FLAGS = -Wno-declaration-after-statement -WZ_CFLAGS = -O0 -g -Wno-pointer-to-int-cast -Wstrict-prototypes -Wdeclaration-after-statement -Wall -Werror -Wno-unused-label -Wmissing-field-initializers -Wcast-align -Wwrite-strings -Wmissing-declarations -Wpointer-arith -Wno-format-security -Wno-switch -WZ_CPPFLAGS = -DDEBUG -DWZ_DATADIR="\"${datadir}/${PACKAGE}\"" -DLOCALEDIR="\"${localedir}\"" -I$(top_srcdir) -WZ_CXXFLAGS = -O0 -g -Wextra -Wall -Werror -Wno-unused-label -Wmissing-field-initializers -Wcast-align -Wwrite-strings -Wmissing-declarations -Wpointer-arith -Wno-format-security -X11_LIBS = -lX11 -XGETTEXT = /usr/bin/xgettext -XGETTEXT_015 = /usr/bin/xgettext -XGETTEXT_EXTRA_OPTIONS = -YACC = bison -y -YFLAGS = -ZIP = zip -abs_builddir = /home/softcoder/Code/warzone2100/trunk/lib/netplay/miniupnpc -abs_srcdir = /home/softcoder/Code/warzone2100/trunk/lib/netplay/miniupnpc -abs_top_builddir = /home/softcoder/Code/warzone2100/trunk -abs_top_srcdir = /home/softcoder/Code/warzone2100/trunk -ac_ct_CC = gcc -ac_ct_CXX = g++ -am__include = include -am__leading_dot = . -am__quote = -am__tar = tar --format=ustar -chf - "$$tardir" -am__untar = tar -xf - -applicationdir = ${datarootdir}/applications -bindir = ${exec_prefix}/bin -build = i686-pc-linux-gnu -build_alias = -build_cpu = i686 -build_os = linux-gnu -build_vendor = pc -builddir = . -datadir = ${datarootdir} -datarootdir = ${prefix}/share -docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} -dvidir = ${docdir} -exec_prefix = ${prefix} -host = i686-pc-linux-gnu -host_alias = -host_cpu = i686 -host_os = linux-gnu -host_vendor = pc -htmldir = ${docdir} -icondir = ${datarootdir}/icons -includedir = ${prefix}/include -infodir = ${datarootdir}/info -install_sh = ${SHELL} /home/softcoder/Code/warzone2100/trunk/install-sh -libdir = ${exec_prefix}/lib -libexecdir = ${exec_prefix}/libexec -localedir = ${datarootdir}/locale -localstatedir = ${prefix}/var -mandir = ${datarootdir}/man -mkdir_p = /bin/mkdir -p -oldincludedir = /usr/include -pdfdir = ${docdir} -prefix = /usr/local -program_transform_name = s,x,x, -psdir = ${docdir} -sbindir = ${exec_prefix}/sbin -sharedstatedir = ${prefix}/com -srcdir = . -sysconfdir = ${prefix}/etc -target_alias = -top_build_prefix = ../../../ -top_builddir = ../../.. -top_srcdir = ../../.. -AM_CPPFLAGS = -DSTATICLIB $(SDL_CFLAGS) $(WZ_CPPFLAGS) -AM_CFLAGS = -DSTATICLIB $(WZ_CFLAGS) -noinst_LIBRARIES = libminiupnpc.a -noinst_HEADERS = \ - miniupnpc.h \ - miniupnpcstrings.h \ - miniwget.h \ - minixml.h \ - minisoap.h \ - minissdpc.h \ - codelength.h \ - upnpcommands.h \ - igd_desc_parse.h \ - upnpreplyparse.h \ - upnperrors.h \ - declspec.h \ - bsdqueue.h +everything: all $(EXECUTABLES_ADDTESTS) -libminiupnpc_a_SOURCES = \ - miniwget.c \ - minixml.c \ - igd_desc_parse.c \ - minisoap.c \ - miniupnpc.c \ - upnpreplyparse.c \ - upnpcommands.c \ - minissdpc.c \ - upnperrors.c +pythonmodule: $(LIBRARY) miniupnpcmodule.c setup.py + python setup.py build + touch $@ -EXTRA_DIST = LICENCE README -all: all-am +installpythonmodule: pythonmodule + python setup.py install -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/netplay/miniupnpc/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign lib/netplay/miniupnpc/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; +validateminixml: minixmlvalid + @echo "minixml validation test" + ./minixmlvalid + touch $@ -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +validateminiwget: testminiwget minihttptestserver testminiwget.sh + @echo "miniwget validation test" + ./testminiwget.sh + touch $@ -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): +clean: + $(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h + # clean python stuff + $(RM) pythonmodule validateminixml + $(RM) -r build/ dist/ + #python setup.py clean -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) -libminiupnpc.a: $(libminiupnpc_a_OBJECTS) $(libminiupnpc_a_DEPENDENCIES) - -rm -f libminiupnpc.a - $(libminiupnpc_a_AR) libminiupnpc.a $(libminiupnpc_a_OBJECTS) $(libminiupnpc_a_LIBADD) - $(RANLIB) libminiupnpc.a +install: $(FILESTOINSTALL) + $(INSTALL) -d $(INSTALLDIRINC) + $(INSTALL) -m 644 $(HEADERS) $(INSTALLDIRINC) + $(INSTALL) -d $(INSTALLDIRLIB) + $(INSTALL) -m 644 $(LIBRARY) $(INSTALLDIRLIB) +ifneq ($(OS), AmigaOS) + $(INSTALL) -m 644 $(SHAREDLIBRARY) $(INSTALLDIRLIB)/$(SONAME) + ln -fs $(SONAME) $(INSTALLDIRLIB)/$(SHAREDLIBRARY) +endif + $(INSTALL) -d $(INSTALLDIRBIN) +ifeq ($(OS), AmigaOS) + $(INSTALL) -m 755 upnpc-static $(INSTALLDIRBIN)/upnpc +else + $(INSTALL) -m 755 upnpc-shared $(INSTALLDIRBIN)/upnpc +endif + $(INSTALL) -m 755 external-ip.sh $(INSTALLDIRBIN)/external-ip -mostlyclean-compile: - -rm -f *.$(OBJEXT) +cleaninstall: + $(RM) -r $(INSTALLDIRINC) + $(RM) $(INSTALLDIRLIB)/$(LIBRARY) + $(RM) $(INSTALLDIRLIB)/$(SHAREDLIBRARY) -distclean-compile: - -rm -f *.tab.c +depend: + makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null -include ./$(DEPDIR)/igd_desc_parse.Po -include ./$(DEPDIR)/minisoap.Po -include ./$(DEPDIR)/minissdpc.Po -include ./$(DEPDIR)/miniupnpc.Po -include ./$(DEPDIR)/miniwget.Po -include ./$(DEPDIR)/minixml.Po -include ./$(DEPDIR)/upnpcommands.Po -include ./$(DEPDIR)/upnperrors.Po -include ./$(DEPDIR)/upnpreplyparse.Po +$(LIBRARY): $(LIBOBJS) + $(AR) crs $@ $? -.c.o: - $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< - $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -# source='$<' object='$@' libtool=no \ -# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ -# $(COMPILE) -c $< +$(SHAREDLIBRARY): $(LIBOBJS) +ifeq ($(OS), Darwin) + $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^ +else + $(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^ +endif -.c.obj: - $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` - $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -# source='$<' object='$@' libtool=no \ -# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ -# $(COMPILE) -c `$(CYGPATH_W) '$<'` +upnpc-static: upnpc.o $(LIBRARY) $(LDLIBS) + $(CC) $(LDFLAGS) -o $@ $^ -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS +upnpc-shared: upnpc.o $(SHAREDLIBRARY) $(LDLIBS) + $(CC) $(LDFLAGS) -o $@ $^ -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique +testminixml: $(TESTMINIXMLOBJS) -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" +testminiwget: $(TESTMINIWGETOBJS) -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +minixmlvalid: minixml.o minixmlvalid.o -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LIBRARIES) $(HEADERS) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am +testupnpreplyparse: $(TESTUPNPREPLYPARSE) -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +testigddescparse: $(TESTIGDDESCPARSE) -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: +miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh + $(SH) updateminiupnpcstrings.sh -clean-generic: +jar: $(SHAREDLIBRARY) + $(JAVA) -jar $(JNAERATOR) -library miniupnpc miniupnpc.h declspec.h upnpcommands.h upnpreplyparse.h igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) -package fr.free.miniupnp -o . -jar java/miniupnpc_$(OS).jar -v -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) +minihttptestserver: minihttptestserver.o -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am +# DO NOT DELETE THIS LINE -- make depend depends on it. -clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES ctags distclean distclean-compile \ - distclean-generic distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ - uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: +igd_desc_parse.o: igd_desc_parse.h +miniupnpc.o: miniupnpc.h declspec.h igd_desc_parse.h minissdpc.h miniwget.h +miniupnpc.o: minisoap.h minixml.h upnpcommands.h upnpreplyparse.h +miniupnpc.o: portlistingparse.h miniupnpctypes.h connecthostport.h +miniupnpc.o: receivedata.h +minixml.o: minixml.h +minisoap.o: minisoap.h miniupnpcstrings.h +miniwget.o: miniupnpcstrings.h miniwget.h declspec.h connecthostport.h +miniwget.o: receivedata.h +upnpc.o: miniwget.h declspec.h miniupnpc.h igd_desc_parse.h upnpcommands.h +upnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h upnperrors.h +upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h declspec.h +upnpcommands.o: miniupnpctypes.h miniupnpc.h igd_desc_parse.h +upnpreplyparse.o: upnpreplyparse.h minixml.h +testminixml.o: minixml.h igd_desc_parse.h +minixmlvalid.o: minixml.h +testupnpreplyparse.o: upnpreplyparse.h +minissdpc.o: minissdpc.h miniupnpc.h declspec.h igd_desc_parse.h codelength.h +upnperrors.o: upnperrors.h declspec.h upnpcommands.h upnpreplyparse.h +upnperrors.o: portlistingparse.h miniupnpctypes.h miniupnpc.h +upnperrors.o: igd_desc_parse.h +testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h declspec.h +testminiwget.o: miniwget.h declspec.h +connecthostport.o: connecthostport.h +receivedata.o: receivedata.h diff --git a/source/shared_lib/sources/platform/miniupnpc/Makefile.mingw b/source/shared_lib/sources/platform/miniupnpc/Makefile.mingw index 2ca15dbc8..b9e1b3200 100644 --- a/source/shared_lib/sources/platform/miniupnpc/Makefile.mingw +++ b/source/shared_lib/sources/platform/miniupnpc/Makefile.mingw @@ -1,26 +1,33 @@ -# $Id: Makefile.mingw,v 1.9 2008/07/02 23:31:15 nanard Exp $ +# $Id: Makefile.mingw,v 1.16 2011/04/18 17:39:31 nanard Exp $ # Miniupnp project. # http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -# (c) 2005-2008 Thomas Bernard +# (c) 2005-2011 Thomas Bernard +# This Makefile is made for MinGW +# CC = gcc -#CFLAGS = -Wall -g -DDEBUG -CFLAGS = -Wall -Os -DNDEBUG -LDLIBS = -lws2_32 +#CFLAGS = -Wall -g -DDEBUG -D_WIN32_WINNT=0X501 +CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501 +LDLIBS = -lws2_32 -liphlpapi # -lwsock32 +# -liphlpapi is used for GetBestRoute() PYTHON=\utils\python25\python OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \ - miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o + miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ + connecthostport.o portlistingparse.o receivedata.o OBJSDLL=$(addprefix dll/, $(OBJS)) all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll init: mkdir dll - echo "" > init + echo init > init clean: del upnpc testminixml *.o - del dll/*.o + del dll\*.o + del *.exe + del miniupnpc.dll + del libminiupnpc.a libminiupnpc.a: $(OBJS) $(AR) cr $@ $? @@ -30,8 +37,10 @@ pythonmodule: libminiupnpc.a $(PYTHON) setupmingw32.py install --skip-build miniupnpc.dll: libminiupnpc.a $(OBJSDLL) - dllwrap -k --driver-name gcc --def miniupnpc.def \ - --output-def miniupnpc.dll.def --implib miniupnpc.lib -o $@ \ + dllwrap -k --driver-name gcc \ + --def miniupnpc.def \ + --output-def miniupnpc.dll.def \ + --implib miniupnpc.lib -o $@ \ $(OBJSDLL) $(LDLIBS) miniupnpc.lib: miniupnpc.dll @@ -49,18 +58,25 @@ upnpc.o: $(CC) $(CFLAGS) -c -o dll/$@ $< upnpc-static: upnpc.o libminiupnpc.a - $(CC) -o $@ $^ $(LDLIBS) + $(CC) -enable-stdcall-fixup -o $@ $^ $(LDLIBS) upnpc-shared: dll/upnpc.o miniupnpc.lib - $(CC) -o $@ $^ $(LDLIBS) + $(CC) -enable-stdcall-fixup -o $@ $^ $(LDLIBS) -minixml.o: minixml.c minixml.h +wingenminiupnpcstrings: wingenminiupnpcstrings.o -upnpc.o: upnpc.c miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h upnpreplyparse.h upnpcommands.h +wingenminiupnpcstrings.o: wingenminiupnpcstrings.c -miniwget.o: miniwget.c miniwget.h +miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings + wingenminiupnpcstrings $< $@ -minisoap.o: minisoap.c minisoap.h +minixml.o: minixml.c minixml.h miniupnpcstrings.h + +upnpc.o: upnpc.c miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h upnpreplyparse.h upnpcommands.h upnperrors.h + +miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h + +minisoap.o: minisoap.c minisoap.h miniupnpcstrings.h miniupnpc.o: miniupnpc.c miniupnpc.h minisoap.h miniwget.h minixml.h @@ -70,5 +86,5 @@ testminixml: minixml.o igd_desc_parse.o testminixml.c upnpreplyparse.o: upnpreplyparse.c upnpreplyparse.h minixml.h -upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h +upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h diff --git a/source/shared_lib/sources/platform/miniupnpc/README b/source/shared_lib/sources/platform/miniupnpc/README index 3aa2a361b..12c7fed35 100644 --- a/source/shared_lib/sources/platform/miniupnpc/README +++ b/source/shared_lib/sources/platform/miniupnpc/README @@ -1,9 +1,9 @@ Project: miniupnp Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ Author: Thomas Bernard -Copyright (c) 2005-2008 Thomas Bernard +Copyright (c) 2005-2011 Thomas Bernard This software is subject to the conditions detailed in the -LICENCE file provided within this distribution. +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. @@ -11,10 +11,13 @@ bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system. * miniupnp Client * -To compile, simply run 'gmake' (could be 'make'). +To compile, simply run 'gmake' (could be 'make' on your system). Under win32, to compile with MinGW, type "mingw32make.bat". The compilation is known to work under linux, FreeBSD, -OpenBSD, MacOS X and cygwin. +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 @@ -25,7 +28,7 @@ alternatively, to install in a specific location, use : upnpc.c is a sample client using the libminiupnpc. To use the libminiupnpc in your application, link it with -libminiupnpc.a and use the following functions found in miniupnpc.h, +libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h, upnpcommands.h and miniwget.h : - upnpDiscover() - miniwget() @@ -51,4 +54,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/source/shared_lib/sources/platform/miniupnpc/VERSION b/source/shared_lib/sources/platform/miniupnpc/VERSION new file mode 100644 index 000000000..810ee4e91 --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/VERSION @@ -0,0 +1 @@ +1.6 diff --git a/source/shared_lib/sources/platform/miniupnpc/connecthostport.c b/source/shared_lib/sources/platform/miniupnpc/connecthostport.c new file mode 100644 index 000000000..76e8e374b --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/connecthostport.c @@ -0,0 +1,241 @@ +/* $Id: connecthostport.c,v 1.5 2011/04/09 08:49:50 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2010-2011 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +/* use getaddrinfo() or gethostbyname() + * uncomment the following line in order to use gethostbyname() */ +#ifdef NO_GETADDRINFO +#define USE_GETHOSTBYNAME +#endif + +#include +#include +#ifdef WIN32 +#include +#include +#include +#define MAXHOSTNAMELEN 64 +#define snprintf _snprintf +#define herror +#define socklen_t int +#else /* #ifdef WIN32 */ +#include +#include +#include +#define closesocket close +#include +/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions + * during the connect() call */ +#define MINIUPNPC_IGNORE_EINTR +#ifndef USE_GETHOSTBYNAME +#include +#include +#endif /* #ifndef USE_GETHOSTBYNAME */ +#endif /* #else WIN32 */ + +/* definition of PRINT_SOCKET_ERROR */ +#ifdef WIN32 +#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); +#else +#define PRINT_SOCKET_ERROR(x) perror(x) +#endif + +#if defined(__amigaos__) || defined(__amigaos4__) +#define herror(A) printf("%s\n", A) +#endif + +#include "connecthostport.h" + +/* 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 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; +#endif /* #ifdef USE_GETHOSTBYNAME */ +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + struct timeval timeout; +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + +#ifdef USE_GETHOSTBYNAME + hp = gethostbyname(host); + if(hp == NULL) + { + herror(host); + return -1; + } + memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr)); + memset(dest.sin_zero, 0, sizeof(dest.sin_zero)); + s = socket(PF_INET, SOCK_STREAM, 0); + if(s < 0) + { + PRINT_SOCKET_ERROR("socket"); + return -1; + } +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + /* setting a 3 seconds timeout for the connect() call */ + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + dest.sin_family = AF_INET; + dest.sin_port = htons(port); + n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); +#ifdef MINIUPNPC_IGNORE_EINTR + while(n < 0 && errno == EINTR) + { + socklen_t len; + fd_set wset; + int err; + FD_ZERO(&wset); + FD_SET(s, &wset); + if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) + continue; + /*len = 0;*/ + /*n = getpeername(s, NULL, &len);*/ + len = sizeof(err); + if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { + PRINT_SOCKET_ERROR("getsockopt"); + closesocket(s); + return -1; + } + if(err != 0) { + errno = err; + n = -1; + } + } +#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ + if(n<0) + { + PRINT_SOCKET_ERROR("connect"); + closesocket(s); + return -1; + } +#else /* #ifdef USE_GETHOSTBYNAME */ + /* use getaddrinfo() instead of gethostbyname() */ + memset(&hints, 0, sizeof(hints)); + /* hints.ai_flags = AI_ADDRCONFIG; */ +#ifdef AI_NUMERICSERV + hints.ai_flags = AI_NUMERICSERV; +#endif + hints.ai_socktype = SOCK_STREAM; + 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); + if(host[0] == '[') + { + /* literal ip v6 address */ + int i; + for(i = 0; host[i+1] && (host[i+1] != ']') && i < MAXHOSTNAMELEN; i++) + { + tmp_host[i] = host[i+1]; + } + 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 + fprintf(stderr, "getaddrinfo() error : %d\n", n); +#else + fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); +#endif + return -1; + } + s = -1; + for(p = ai; p; p = p->ai_next) + { + s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if(s < 0) + continue; +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + /* setting a 3 seconds timeout for the connect() call */ + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + n = connect(s, p->ai_addr, p->ai_addrlen); +#ifdef MINIUPNPC_IGNORE_EINTR + while(n < 0 && errno == EINTR) + { + socklen_t len; + fd_set wset; + int err; + FD_ZERO(&wset); + FD_SET(s, &wset); + if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) + continue; + /*len = 0;*/ + /*n = getpeername(s, NULL, &len);*/ + len = sizeof(err); + if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { + PRINT_SOCKET_ERROR("getsockopt"); + closesocket(s); + freeaddrinfo(ai); + return -1; + } + if(err != 0) { + errno = err; + n = -1; + } + } +#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ + if(n < 0) + { + closesocket(s); + continue; + } + else + { + break; + } + } + freeaddrinfo(ai); + if(s < 0) + { + PRINT_SOCKET_ERROR("socket"); + return -1; + } + if(n < 0) + { + PRINT_SOCKET_ERROR("connect"); + return -1; + } +#endif /* #ifdef USE_GETHOSTBYNAME */ + return s; +} + diff --git a/source/shared_lib/sources/platform/miniupnpc/external-ip.sh b/source/shared_lib/sources/platform/miniupnpc/external-ip.sh new file mode 100644 index 000000000..965d86b2a --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/external-ip.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $ +# (c) 2010 Reuben Hawkins +upnpc -s | grep ExternalIPAddress | sed 's/[^0-9\.]//g' diff --git a/source/shared_lib/sources/platform/miniupnpc/igd_desc_parse.c b/source/shared_lib/sources/platform/miniupnpc/igd_desc_parse.c index e839ff4c1..6c3e65677 100644 --- a/source/shared_lib/sources/platform/miniupnpc/igd_desc_parse.c +++ b/source/shared_lib/sources/platform/miniupnpc/igd_desc_parse.c @@ -1,18 +1,15 @@ -/* $Id: igd_desc_parse.c,v 1.8 2008/04/23 11:51:06 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 - * Copyright (c) 2005-2008 Thomas Bernard + * Copyright (c) 2005-2010 Thomas Bernard * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ + * LICENCE file provided in this distribution. */ + #include "igd_desc_parse.h" #include #include -/* TODO : rewrite this code so it correctly handle descriptions with - * both WANIPConnection and/or WANPPPConnection */ - /* Start element handler : * update nesting level counter and copy element name */ void IGDstartelt(void * d, const char * name, int l) @@ -22,10 +19,10 @@ void IGDstartelt(void * d, const char * name, int l) datas->cureltname[l] = '\0'; datas->level++; if( (l==7) && !memcmp(name, "service", l) ) { - datas->controlurl_tmp[0] = '\0'; - datas->eventsuburl_tmp[0] = '\0'; - datas->scpdurl_tmp[0] = '\0'; - datas->servicetype_tmp[0] = '\0'; + datas->tmp.controlurl[0] = '\0'; + datas->tmp.eventsuburl[0] = '\0'; + datas->tmp.scpdurl[0] = '\0'; + datas->tmp.servicetype[0] = '\0'; } } @@ -46,20 +43,21 @@ void IGDendelt(void * d, const char * name, int l) "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) datas->state ++; */ - if(0==strcmp(datas->servicetype_tmp, + if(0==strcmp(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) { - memcpy(datas->controlurl_CIF, datas->controlurl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->eventsuburl_CIF, datas->eventsuburl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->scpdurl_CIF, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->servicetype_CIF, datas->servicetype_tmp, MINIUPNPC_URL_MAXSIZE); - } else if(0==strcmp(datas->servicetype_tmp, + 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->servicetype_tmp, + || 0==strcmp(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANPPPConnection:1") ) { - memcpy(datas->controlurl, datas->controlurl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->eventsuburl, datas->eventsuburl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->scpdurl, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->servicetype, datas->servicetype_tmp, MINIUPNPC_URL_MAXSIZE); + if(datas->first.servicetype[0] == '\0') { + memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); + } else { + memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); + } } } } @@ -74,14 +72,16 @@ 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->servicetype_tmp; + dstmember = datas->tmp.servicetype; else if( !strcmp(datas->cureltname, "controlURL") ) - dstmember = datas->controlurl_tmp; + dstmember = datas->tmp.controlurl; else if( !strcmp(datas->cureltname, "eventSubURL") ) - dstmember = datas->eventsuburl_tmp; + dstmember = datas->tmp.eventsuburl; else if( !strcmp(datas->cureltname, "SCPDURL") ) - dstmember = datas->scpdurl_tmp; + dstmember = datas->tmp.scpdurl; /* else if( !strcmp(datas->cureltname, "deviceType") ) dstmember = datas->devicetype_tmp;*/ if(dstmember) @@ -95,19 +95,31 @@ void IGDdata(void * d, const char * data, int l) void printIGD(struct IGDdatas * d) { - printf("urlbase = %s\n", d->urlbase); + printf("urlbase = '%s'\n", d->urlbase); printf("WAN Device (Common interface config) :\n"); - /*printf(" deviceType = %s\n", d->devicetype_CIF);*/ - printf(" serviceType = %s\n", d->servicetype_CIF); - printf(" controlURL = %s\n", d->controlurl_CIF); - printf(" eventSubURL = %s\n", d->eventsuburl_CIF); - printf(" SCPDURL = %s\n", d->scpdurl_CIF); - printf("WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = %s\n", d->devicetype);*/ - printf(" servicetype = %s\n", d->servicetype); - printf(" controlURL = %s\n", d->controlurl); - printf(" eventSubURL = %s\n", d->eventsuburl); - printf(" SCPDURL = %s\n", d->scpdurl); + /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ + printf(" serviceType = '%s'\n", d->CIF.servicetype); + printf(" controlURL = '%s'\n", d->CIF.controlurl); + printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); + printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); + printf("primary WAN Connection Device (IP or PPP Connection):\n"); + /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ + printf(" servicetype = '%s'\n", d->first.servicetype); + printf(" controlURL = '%s'\n", d->first.controlurl); + printf(" eventSubURL = '%s'\n", d->first.eventsuburl); + printf(" SCPDURL = '%s'\n", d->first.scpdurl); + printf("secondary WAN Connection Device (IP or PPP Connection):\n"); + /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ + printf(" servicetype = '%s'\n", d->second.servicetype); + 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/source/shared_lib/sources/platform/miniupnpc/mingw32make.bat b/source/shared_lib/sources/platform/miniupnpc/mingw32make.bat index 3e59be59b..c5d3cc4ff 100644 --- a/source/shared_lib/sources/platform/miniupnpc/mingw32make.bat +++ b/source/shared_lib/sources/platform/miniupnpc/mingw32make.bat @@ -1,5 +1,6 @@ @mingw32-make -f Makefile.mingw %1 @if errorlevel 1 goto end +@if not exist upnpc-static.exe goto end @strip upnpc-static.exe @upx --best upnpc-static.exe @strip upnpc-shared.exe diff --git a/source/shared_lib/sources/platform/miniupnpc/minihttptestserver.c b/source/shared_lib/sources/platform/miniupnpc/minihttptestserver.c new file mode 100644 index 000000000..a1dddf0ea --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/minihttptestserver.c @@ -0,0 +1,461 @@ +/* $Id: minihttptestserver.c,v 1.6 2011/05/09 08:53:15 nanard Exp $ */ +/* Project : miniUPnP + * Author : Thomas Bernard + * Copyright (c) 2011 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CRAP_LENGTH (2048) + +volatile int quit = 0; +volatile int child_to_wait_for = 0; + +/** + * signal handler for SIGCHLD (child status has changed) + */ +void handle_signal_chld(int sig) +{ + printf("handle_signal_chld(%d)\n", sig); + ++child_to_wait_for; +} + +/** + * signal handler for SIGINT (CRTL C) + */ +#if 0 +void handle_signal_int(int sig) +{ + printf("handle_signal_int(%d)\n", sig); + quit = 1; +} +#endif + +/** + * build a text/plain content of the specified length + */ +void build_content(char * p, int n) +{ + char line_buffer[80]; + int k; + int i = 0; + + while(n > 0) { + k = snprintf(line_buffer, sizeof(line_buffer), + "%04d_ABCDEFGHIJKL_This_line_is_64_bytes_long_ABCDEFGHIJKL_%04d\r\n", + i, i); + if(k != 64) { + fprintf(stderr, "snprintf() returned %d in build_content()\n", k); + } + ++i; + if(n >= 64) { + memcpy(p, line_buffer, 64); + p += 64; + n -= 64; + } else { + memcpy(p, line_buffer, n); + p += n; + n = 0; + } + } +} + +/** + * build crappy content + */ +void build_crap(char * p, int n) +{ + static const char crap[] = "_CRAP_\r\n"; + int i; + + while(n > 0) { + i = sizeof(crap) - 1; + if(i > n) + i = n; + memcpy(p, crap, i); + p += i; + n -= i; + } +} + +/** + * build chunked response. + * return a malloc'ed buffer + */ +char * build_chunked_response(int content_length, int * response_len) { + char * response_buffer; + char * content_buffer; + int buffer_length; + int i, n; + + /* allocate to have some margin */ + buffer_length = 256 + content_length + (content_length >> 4); + response_buffer = malloc(buffer_length); + *response_len = snprintf(response_buffer, buffer_length, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n"); + + /* build the content */ + content_buffer = malloc(content_length); + build_content(content_buffer, content_length); + + /* chunk it */ + i = 0; + while(i < content_length) { + n = (rand() % 199) + 1; + if(i + n > content_length) { + n = content_length - i; + } + /* TODO : check buffer size ! */ + *response_len += snprintf(response_buffer + *response_len, + buffer_length - *response_len, + "%x\r\n", n); + memcpy(response_buffer + *response_len, content_buffer + i, n); + *response_len += n; + i += n; + response_buffer[(*response_len)++] = '\r'; + response_buffer[(*response_len)++] = '\n'; + } + memcpy(response_buffer + *response_len, "0\r\n", 3); + *response_len += 3; + free(content_buffer); + + printf("resp_length=%d buffer_length=%d content_length=%d\n", + *response_len, buffer_length, content_length); + return response_buffer; +} + +enum modes { MODE_INVALID, MODE_CHUNKED, MODE_ADDCRAP, MODE_NORMAL }; +const struct { + const enum modes mode; + const char * text; +} modes_array[] = { + {MODE_CHUNKED, "chunked"}, + {MODE_ADDCRAP, "addcrap"}, + {MODE_NORMAL, "normal"}, + {MODE_INVALID, NULL} +}; + +/** + * write the response with random behaviour ! + */ +void send_response(int c, const char * buffer, int len) +{ + int n; + while(len > 0) { + n = (rand() % 99) + 1; + if(n > len) + n = len; + n = write(c, buffer, n); + if(n < 0) { + perror("write"); + return; + } else { + len -= n; + buffer += n; + } + usleep(10000); /* 10ms */ + } +} + +/** + * handle the HTTP connection + */ +void handle_http_connection(int c) +{ + char request_buffer[2048]; + int request_len = 0; + int headers_found = 0; + int n, i; + char request_method[16]; + char request_uri[256]; + char http_version[16]; + char * p; + char * response_buffer; + int response_len; + enum modes mode; + int content_length = 16*1024; + + /* read the request */ + while(request_len < sizeof(request_buffer) && !headers_found) { + n = read(c, + request_buffer + request_len, + sizeof(request_buffer) - request_len); + if(n < 0) { + perror("read"); + return; + } else if(n==0) { + /* remote host closed the connection */ + break; + } else { + request_len += n; + for(i = 0; i < request_len - 3; i++) { + if(0 == memcmp(request_buffer + i, "\r\n\r\n", 4)) { + /* found the end of headers */ + headers_found = 1; + break; + } + } + } + } + if(!headers_found) { + /* error */ + return; + } + printf("headers :\n%.*s", request_len, request_buffer); + /* the request have been received, now parse the request line */ + p = request_buffer; + for(i = 0; i < sizeof(request_method) - 1; i++) { + if(*p == ' ' || *p == '\r') + break; + request_method[i] = *p; + ++p; + } + request_method[i] = '\0'; + while(*p == ' ') + p++; + for(i = 0; i < sizeof(request_uri) - 1; i++) { + if(*p == ' ' || *p == '\r') + break; + request_uri[i] = *p; + ++p; + } + request_uri[i] = '\0'; + while(*p == ' ') + p++; + for(i = 0; i < sizeof(http_version) - 1; i++) { + if(*p == ' ' || *p == '\r') + break; + http_version[i] = *p; + ++p; + } + http_version[i] = '\0'; + printf("Method = %s, URI = %s, %s\n", + request_method, request_uri, http_version); + /* check if the request method is allowed */ + if(0 != strcmp(request_method, "GET")) { + const char response405[] = "HTTP/1.1 405 Method Not Allowed\r\n" + "Allow: GET\r\n\r\n"; + /* 405 Method Not Allowed */ + /* The response MUST include an Allow header containing a list + * of valid methods for the requested resource. */ + write(c, response405, sizeof(response405) - 1); + return; + } + + mode = MODE_INVALID; + /* use the request URI to know what to do */ + for(i = 0; modes_array[i].mode != MODE_INVALID; i++) { + if(strstr(request_uri, modes_array[i].text)) { + mode = modes_array[i].mode; /* found */ + break; + } + } + + switch(mode) { + case MODE_CHUNKED: + response_buffer = build_chunked_response(content_length, &response_len); + break; + case MODE_ADDCRAP: + response_len = content_length+256; + response_buffer = malloc(response_len); + n = snprintf(response_buffer, response_len, + "HTTP/1.1 200 OK\r\n" + "Server: minihttptestserver\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: %d\r\n" + "\r\n", content_length); + response_len = content_length+n+CRAP_LENGTH; + response_buffer = realloc(response_buffer, response_len); + build_content(response_buffer + n, content_length); + build_crap(response_buffer + n + content_length, CRAP_LENGTH); + break; + default: + response_len = content_length+256; + response_buffer = malloc(response_len); + n = snprintf(response_buffer, response_len, + "HTTP/1.1 200 OK\r\n" + "Server: minihttptestserver\r\n" + "Content-Type: text/plain\r\n" + "\r\n"); + response_len = content_length+n; + response_buffer = realloc(response_buffer, response_len); + build_content(response_buffer + n, response_len - n); + } + + if(response_buffer) { + send_response(c, response_buffer, response_len); + free(response_buffer); + } else { + /* Error 500 */ + } +} + +/** + */ +int main(int argc, char * * argv) { + int ipv6 = 0; + int s, c, i; + unsigned short port = 0; + struct sockaddr_storage server_addr; + socklen_t server_addrlen; + struct sockaddr_storage client_addr; + socklen_t client_addrlen; + pid_t pid; + int child = 0; + int status; + const char * expected_file_name = NULL; + + for(i = 1; i < argc; i++) { + if(argv[i][0] == '-') { + switch(argv[i][1]) { + case '6': + ipv6 = 1; + break; + case 'e': + /* write expected file ! */ + expected_file_name = argv[++i]; + break; + case 'p': + /* port */ + if(++i < argc) { + port = (unsigned short)atoi(argv[i]); + } + break; + default: + fprintf(stderr, "unknown command line switch '%s'\n", argv[i]); + } + } else { + fprintf(stderr, "unkown command line argument '%s'\n", argv[i]); + } + } + + srand(time(NULL)); + signal(SIGCHLD, handle_signal_chld); +#if 0 + signal(SIGINT, handle_signal_int); +#endif + + s = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0); + if(s < 0) { + perror("socket"); + return 1; + } + memset(&server_addr, 0, sizeof(struct sockaddr_storage)); + memset(&client_addr, 0, sizeof(struct sockaddr_storage)); + if(ipv6) { + struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr; + addr->sin6_family = AF_INET6; + addr->sin6_port = htons(port); + addr->sin6_addr = in6addr_any; + } else { + struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr; + addr->sin_family = AF_INET; + addr->sin_port = htons(port); + addr->sin_addr.s_addr = htonl(INADDR_ANY); + } + if(bind(s, (struct sockaddr *)&server_addr, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + return 1; + } + if(listen(s, 5) < 0) { + perror("listen"); + } + if(port == 0) { + server_addrlen = sizeof(struct sockaddr_storage); + if(getsockname(s, (struct sockaddr *)&server_addr, &server_addrlen) < 0) { + perror("getsockname"); + return 1; + } + if(ipv6) { + struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr; + port = ntohs(addr->sin6_port); + } else { + struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr; + port = ntohs(addr->sin_port); + } + printf("Listening on port %hu\n", port); + fflush(stdout); + } + + /* write expected file */ + if(expected_file_name) { + FILE * f; + f = fopen(expected_file_name, "wb"); + if(f) { + char * buffer; + buffer = malloc(16*1024); + build_content(buffer, 16*1024); + fwrite(buffer, 1, 16*1024, f); + free(buffer); + fclose(f); + } + } + + /* fork() loop */ + while(!child && !quit) { + while(child_to_wait_for > 0) { + pid = wait(&status); + if(pid < 0) { + perror("wait"); + } else { + printf("child(%d) terminated with status %d\n", pid, status); + } + --child_to_wait_for; + } + /* TODO : add a select() call in order to handle the case + * when a signal is caught */ + client_addrlen = sizeof(struct sockaddr_storage); + c = accept(s, (struct sockaddr *)&client_addr, + &client_addrlen); + if(c < 0) { + perror("accept"); + return 1; + } + printf("accept...\n"); + pid = fork(); + if(pid < 0) { + perror("fork"); + return 1; + } else if(pid == 0) { + /* child */ + child = 1; + close(s); + s = -1; + handle_http_connection(c); + } + close(c); + } + if(s >= 0) { + close(s); + s = -1; + } + if(!child) { + while(child_to_wait_for > 0) { + pid = wait(&status); + if(pid < 0) { + perror("wait"); + } else { + printf("child(%d) terminated with status %d\n", pid, status); + } + --child_to_wait_for; + } + printf("Bye...\n"); + } + return 0; +} + diff --git a/source/shared_lib/sources/platform/miniupnpc/minisoap.c b/source/shared_lib/sources/platform/miniupnpc/minisoap.c index 2e8ad6205..8889bf040 100644 --- a/source/shared_lib/sources/platform/miniupnpc/minisoap.c +++ b/source/shared_lib/sources/platform/miniupnpc/minisoap.c @@ -1,7 +1,7 @@ -/* $Id: minisoap.c,v 1.16 2008/10/11 16:39:29 nanard Exp $ */ +/* $Id: minisoap.c,v 1.21 2011/03/22 19:15:35 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard + * Copyright (c) 2005-2009 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * @@ -21,8 +21,6 @@ #include "minisoap.h" #include "miniupnpcstrings.h" -#undef DEBUG - /* only for malloc */ #include @@ -77,7 +75,8 @@ int soapPostSubmit(int fd, const char * host, unsigned short port, const char * action, - const char * body) + const char * body, + const char * httpversion) { int bodysize; char headerbuf[512]; @@ -86,14 +85,16 @@ int soapPostSubmit(int fd, bodysize = (int)strlen(body); /* We are not using keep-alive HTTP connections. * HTTP/1.1 needs the header Connection: close to do that. - * This is the default with HTTP/1.0 */ + * This is the default with HTTP/1.0 + * Using HTTP/1.1 means we need to support chunked transfer-encoding : + * When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked + * transfer encoding. */ /* Connection: Close is normally there only in HTTP/1.1 but who knows */ portstr[0] = '\0'; if(port != 80) snprintf(portstr, sizeof(portstr), ":%hu", port); headerssize = snprintf(headerbuf, sizeof(headerbuf), - "POST %s HTTP/1.1\r\n" -/* "POST %s HTTP/1.0\r\n"*/ + "POST %s HTTP/%s\r\n" "Host: %s%s\r\n" "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "Content-Length: %d\r\n" @@ -103,11 +104,16 @@ int soapPostSubmit(int fd, "Cache-Control: no-cache\r\n" /* ??? */ "Pragma: no-cache\r\n" "\r\n", - url, host, portstr, bodysize, action); + url, httpversion, host, portstr, bodysize, action); #ifdef DEBUG - printf("SOAP request : headersize=%d bodysize=%d\n", + /*printf("SOAP request : headersize=%d bodysize=%d\n", headerssize, bodysize); - /*printf("%s", headerbuf);*/ + */ + 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("Headers :\n%s", headerbuf); + printf("Body :\n%s\n", body); #endif return httpWrite(fd, body, bodysize, headerbuf, headerssize); } diff --git a/source/shared_lib/sources/platform/miniupnpc/minissdpc.c b/source/shared_lib/sources/platform/miniupnpc/minissdpc.c index 15bd97458..e5e852855 100644 --- a/source/shared_lib/sources/platform/miniupnpc/minissdpc.c +++ b/source/shared_lib/sources/platform/miniupnpc/minissdpc.c @@ -1,4 +1,4 @@ -/* $Id: minissdpc.c,v 1.10 2009/09/21 12:57:42 nanard Exp $ */ +/* $Id: minissdpc.c,v 1.14 2010/11/25 09:57:25 nanard Exp $ */ /* Project : miniupnp * Author : Thomas BERNARD * copyright (c) 2005-2009 Thomas Bernard @@ -8,17 +8,22 @@ #include #include #include +#include #include +#if defined(WIN32) || defined(__amigaos__) || defined(__amigaos4__) #ifdef WIN32 #include #include #include - -typedef short int int16_t; -typedef unsigned short int uint16_t; - -typedef SSIZE_T ssize_t; -// end WZ +#include +#include +#endif +#if defined(__amigaos__) || defined(__amigaos4__) +#include +#endif +#if defined(__amigaos__) +#define uint16_t unsigned short +#endif /* Hack */ #define UNIX_PATH_LEN 108 struct sockaddr_un { @@ -28,7 +33,6 @@ struct sockaddr_un { #else #include #include -#include #endif #include "minissdpc.h" diff --git a/source/shared_lib/sources/platform/miniupnpc/miniupnpc.c b/source/shared_lib/sources/platform/miniupnpc/miniupnpc.c index ba7442865..bd46a2421 100644 --- a/source/shared_lib/sources/platform/miniupnpc/miniupnpc.c +++ b/source/shared_lib/sources/platform/miniupnpc/miniupnpc.c @@ -1,9 +1,9 @@ -/* $Id: miniupnpc.c,v 1.66 2009/10/10 19:15:34 nanard Exp $ */ +/* $Id: miniupnpc.c,v 1.95 2011/05/15 21:42:26 nanard Exp $ */ /* Project : miniupnp * Author : Thomas BERNARD - * copyright (c) 2005-2009 Thomas Bernard + * copyright (c) 2005-2011 Thomas Bernard * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ + * provided LICENSE file. */ #define __EXTENSIONS__ 1 #if !defined(MACOSX) && !defined(__sun) #if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__) && !defined(__NetBSD__) @@ -16,8 +16,6 @@ #endif #endif -//#include "lib/framework/wzglobal.h" - #include #include #include @@ -26,43 +24,55 @@ #include #include #include +#include #define snprintf _snprintf +#ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define strncasecmp _memicmp -#else +#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #define strncasecmp memicmp -#endif +#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ +#endif /* #ifndef strncasecmp */ #define MAXHOSTNAMELEN 64 -#else +#else /* #ifdef WIN32 */ /* Standard POSIX includes */ #include +#if defined(__amigaos__) && !defined(__amigaos4__) +/* Amiga OS 3 specific stuff */ +#define socklen_t int +#else #include +#endif #include #include #include -#ifdef WZ_OS_MAC -# undef _POSIX_C_SOURCE -# include -#else -# include -#endif +#include #include -#include #include +#include +#if !defined(__amigaos__) && !defined(__amigaos4__) +#include +#endif #include #include #define closesocket close -#define MINIUPNPC_IGNORE_EINTR -#endif +#endif /* #else WIN32 */ #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT #include #endif +#if defined(__amigaos__) || defined(__amigaos4__) +/* Amiga OS specific stuff */ +#define TIMEVAL struct timeval +#endif + #include "miniupnpc.h" #include "minissdpc.h" #include "miniwget.h" #include "minisoap.h" #include "minixml.h" #include "upnpcommands.h" +#include "connecthostport.h" +#include "receivedata.h" #ifdef WIN32 #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); @@ -78,8 +88,6 @@ LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data) { struct xmlparser parser; - memset(&parser,0,sizeof(parser)); - /* xmlparser object */ parser.xmlstart = buffer; parser.xmlsize = bufsize; @@ -94,92 +102,24 @@ LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * d #endif } -/* 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; -} - -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; - } - } -} - -/* simpleUPnPcommand : +/* simpleUPnPcommand2 : * not so simple ! * return values : - * 0 - OK - * -1 - error */ -int simpleUPnPcommand(int s, const char * url, const char * service, - const char * action, struct UPNParg * args, - char * buffer, int * bufsize) + * pointer - OK + * NULL - error */ +char * simpleUPnPcommand2(int s, const char * url, const char * service, + const char * action, struct UPNParg * args, + int * bufsize, const char * httpversion) { - struct sockaddr_in dest; char hostname[MAXHOSTNAMELEN+1]; unsigned short port = 0; char * path; char soapact[128]; char soapbody[2048]; char * buf; - int buffree; int n; - int contentlen, headerlen; /* for the response */ -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - struct timeval timeout; -#endif + + *bufsize = 0; snprintf(soapact, sizeof(soapact), "%s#%s", service, action); if(args==NULL) { @@ -214,8 +154,7 @@ int simpleUPnPcommand(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; @@ -245,101 +184,59 @@ int simpleUPnPcommand(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(!parseURL(url, hostname, &port, &path)) return NULL; if(s<0) { - s = socket(PF_INET, SOCK_STREAM, 0); - if(s<0) + s = connecthostport(hostname, port); + if(s < 0) { - PRINT_SOCKET_ERROR("socket"); - *bufsize = 0; - return -1; - } -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - /* setting a 3 seconds timeout for the connect() call */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } -#endif - dest.sin_family = AF_INET; - dest.sin_port = htons(port); - dest.sin_addr.s_addr = inet_addr(hostname); - n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr)); -#ifdef MINIUPNPC_IGNORE_EINTR - while(n < 0 && errno == EINTR) - { - socklen_t len; - fd_set wset; - int err; - FD_ZERO(&wset); - FD_SET(s, &wset); - if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) - continue; - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ - len = sizeof(err); - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - PRINT_SOCKET_ERROR("getsockopt"); - closesocket(s); - return -1; - } - if(err != 0) { - errno = err; - n = -1; - } else { - n = 0; - } - } -#endif - if(n < 0) - { - PRINT_SOCKET_ERROR("connect"); - closesocket(s); - *bufsize = 0; - return -1; + return NULL; } } - n = soapPostSubmit(s, path, hostname, port, soapact, soapbody); + n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion); if(n<=0) { #ifdef DEBUG printf("Error sending SOAP request\n"); #endif closesocket(s); - return -1; + return NULL; } - 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; + if(*bufsize > 0 && buf) + { + printf("SOAP Response :\n%.*s\n", *bufsize, buf); } - +#endif closesocket(s); - return 0; + return buf; +} + +/* simpleUPnPcommand : + * not so simple ! + * return values : + * pointer - OK + * NULL - error */ +char * simpleUPnPcommand(int s, const char * url, const char * service, + const char * action, struct UPNParg * args, + int * bufsize) +{ + char * buf; + + buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); +/* + 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 + buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); + } +*/ + return buf; } /* parseMSEARCHReply() @@ -355,7 +252,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 is not available with MinGW32 3.4.2 */ + } else { + struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; + p->sin_family = AF_INET; + if(sameport) + 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 + * 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(!ipv6 + && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) { + DWORD dwRetVal = 0; + PMIB_IPADDRTABLE pIPAddrTable; + DWORD dwSize = 0; +#ifdef DEBUG + IN_ADDR IPAddr; +#endif + int i; +#ifdef DEBUG + printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop); +#endif + pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE)); + if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { + free(pIPAddrTable); + pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize); + } + if(pIPAddrTable) { + dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 ); +#ifdef DEBUG + printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); +#endif + for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { +#ifdef DEBUG + printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); + IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; + printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); + IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; + printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); + IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; + printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); + printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); + printf("\tType and State[%d]:", i); + printf("\n"); +#endif + if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) { + /* Set the address of this interface to be used */ + struct in_addr mc_if; + memset(&mc_if, 0, sizeof(mc_if)); + mc_if.s_addr = pIPAddrTable->table[i].dwAddr; + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { + PRINT_SOCKET_ERROR("setsockopt"); + } + ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr; +#ifndef DEBUG + break; +#endif + } + } + free(pIPAddrTable); + pIPAddrTable = NULL; + } + } +#endif #ifdef WIN32 if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) @@ -483,60 +471,151 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, 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); - 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"); + 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 in_addr mc_if; + mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ + ((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"); + } } } /* Avant d'envoyer le paquet on bind pour recevoir la reponse */ - if (bind(sudp, (struct sockaddr *)&sockudp_r, 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);*/ - n = sendto(sudp, bufr, n, 0, - (struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in)); - if (n < 0) { - PRINT_SOCKET_ERROR("sendto"); - closesocket(sudp); - return devlist; + 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_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, + &sockudp_w, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); + if (n < 0) { + if(error) + *error = UPNPDISCOVER_SOCKET_ERROR; + PRINT_SOCKET_ERROR("sendto"); + break; + } +#else /* #ifdef NO_GETADDRINFO */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // AF_INET6 or AF_INET + hints.ai_socktype = SOCK_DGRAM; + /*hints.ai_flags = */ + 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 + break; + } + for(p = servinfo; p; p = p->ai_next) { + n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); + if (n < 0) { + PRINT_SOCKET_ERROR("sendto"); + continue; + } + } + freeaddrinfo(servinfo); + if(n < 0) { + 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); 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; @@ -547,9 +626,28 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize); if(st&&descURL) { - /*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", - stsize, st, urlsize, descURL); */ +#ifdef DEBUG + printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", + stsize, st, urlsize, descURL); +#endif + for(tmp=devlist; tmp; tmp = tmp->pNext) { + if(memcmp(tmp->descURL, descURL, urlsize) == 0 && + tmp->descURL[urlsize] == '\0' && + memcmp(tmp->st, st, stsize) == 0 && + tmp->st[stsize] == '\0') + break; + } + /* at the exit of the loop above, tmp is null if + * no duplicate device was found */ + 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; @@ -561,6 +659,8 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, } } } + closesocket(sudp); + return devlist; } /* freeUPNPDevlist() should be used to @@ -605,19 +705,21 @@ LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, const char * descURL) { char * p; - int n1, n2, n3; + int n1, n2, n3, n4; n1 = strlen(data->urlbase); if(n1==0) n1 = strlen(descURL); n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ - n2 = n1; n3 = n1; - n1 += strlen(data->scpdurl); - n2 += strlen(data->controlurl); - n3 += strlen(data->controlurl_CIF); + 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); urls->ipcondescURL = (char *)malloc(n1); urls->controlURL = (char *)malloc(n2); urls->controlURL_CIF = (char *)malloc(n3); + urls->controlURL_6FC = (char *)malloc(n4); /* maintenant on chope la desc du WANIPConnection */ if(data->urlbase[0] != '\0') strncpy(urls->ipcondescURL, data->urlbase, n1); @@ -627,20 +729,25 @@ LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, if(p) p[0] = '\0'; 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->ipcondescURL, data->scpdurl, n1); + url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); - url_cpy_or_cat(urls->controlURL, data->controlurl, n2); + url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3); - url_cpy_or_cat(urls->controlURL_CIF, data->controlurl_CIF, n3); + url_cpy_or_cat(urls->controlURL_6FC, data->IPv6FC.controlurl, n4); #ifdef DEBUG - printf("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL, - strlen(urls->ipcondescURL), n1); - printf("urls->controlURL='%s' %d n2=%d\n", urls->controlURL, - strlen(urls->controlURL), n2); - printf("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF, - strlen(urls->controlURL_CIF), n3); + printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL, + (unsigned)strlen(urls->ipcondescURL), n1); + printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL, + (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 } @@ -655,56 +762,8 @@ 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; -#ifndef WIN32 - 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; } int @@ -713,7 +772,7 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) char status[64]; unsigned int uptime; status[0] = '\0'; - UPNP_GetStatusInfo(urls->controlURL, data->servicetype, + UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, status, &uptime, NULL); if(0 == strcmp("Connected", status)) { @@ -770,7 +829,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, parserootdesc(descXML, descXMLsize, data); free(descXML); descXML = NULL; - if(0==strcmp(data->servicetype_CIF, + if(0==strcmp(data->CIF.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") || state >= 3 ) { @@ -784,6 +843,25 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, if((state >= 2) || UPNPIGD_IsConnected(urls, data)) return state; FreeUPNPUrls(urls); + if(data->second.servicetype[0] != '\0') { +#ifdef DEBUG + printf("We tried %s, now we try %s !\n", + data->first.servicetype, data->second.servicetype); +#endif + /* swaping WANPPPConnection and WANIPConnection ! */ + 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); +#ifdef DEBUG + printf("UPNPIGD_IsConnected(%s) = %d\n", + urls->controlURL, + UPNPIGD_IsConnected(urls, data)); +#endif + if((state >= 2) || UPNPIGD_IsConnected(urls, data)) + return state; + FreeUPNPUrls(urls); + } } memset(data, 0, sizeof(struct IGDdatas)); } diff --git a/source/shared_lib/sources/platform/miniupnpc/miniupnpc.def b/source/shared_lib/sources/platform/miniupnpc/miniupnpc.def index 21e66a4c3..10b9f5800 100644 --- a/source/shared_lib/sources/platform/miniupnpc/miniupnpc.def +++ b/source/shared_lib/sources/platform/miniupnpc/miniupnpc.def @@ -26,6 +26,17 @@ EXPORTS UPNP_DeletePortMapping UPNP_GetPortMappingNumberOfEntries UPNP_GetSpecificPortMappingEntry - UPNP_GetGenericPortMappingEntry + UPNP_GetGenericPortMappingEntry + UPNP_GetListOfPortMappings + UPNP_AddPinhole + UPNP_CheckPinholeWorking + UPNP_UpdatePinhole + UPNP_GetPinholePackets + UPNP_DeletePinhole + UPNP_GetFirewallStatus + UPNP_GetOutboundPinholeTimeout ; upnperrors - strupnperror \ No newline at end of file + strupnperror +; portlistingparse + ParsePortListing + FreePortListing diff --git a/source/shared_lib/sources/platform/miniupnpc/miniupnpcstrings.h.in b/source/shared_lib/sources/platform/miniupnpc/miniupnpcstrings.h.in index 8ab3f29f7..201c9a862 100644 --- a/source/shared_lib/sources/platform/miniupnpc/miniupnpcstrings.h.in +++ b/source/shared_lib/sources/platform/miniupnpc/miniupnpcstrings.h.in @@ -1,15 +1,15 @@ -/* $Id: miniupnpcstrings.h.in,v 1.2 2009/10/30 09:18:18 nanard Exp $ */ +/* $Id: miniupnpcstrings.h.in,v 1.4 2011/01/04 11:41:53 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author: Thomas Bernard - * Copyright (c) 2005-2009 Thomas Bernard + * Copyright (c) 2005-2011 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef __MINIUPNPCSTRINGS_H__ #define __MINIUPNPCSTRINGS_H__ #define OS_STRING "OS/version" -#define MINIUPNPC_VERSION_STRING "1.4" +#define MINIUPNPC_VERSION_STRING "version" #endif diff --git a/source/shared_lib/sources/platform/miniupnpc/miniwget.c b/source/shared_lib/sources/platform/miniupnpc/miniwget.c index cc053abb1..87f61556b 100644 --- a/source/shared_lib/sources/platform/miniupnpc/miniwget.c +++ b/source/shared_lib/sources/platform/miniupnpc/miniwget.c @@ -1,128 +1,310 @@ -/* $Id: miniwget.c,v 1.28 2009/10/10 19:15:35 nanard Exp $ */ +/* $Id: miniwget.c,v 1.52 2011/06/17 22:59:42 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2009 Thomas Bernard + * Copyright (c) 2005-2011 Thomas Bernard * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ + * LICENCE file provided in this distribution. */ + #include #include #include -#include "miniupnpc.h" +#include #ifdef WIN32 #include +#include #include #define MAXHOSTNAMELEN 64 #define MIN(x,y) (((x)<(y))?(x):(y)) #define snprintf _snprintf -#define herror #define socklen_t int -#else +#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 */ +#else /* #ifdef WIN32 */ #include #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 -#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 +#endif /* #else WIN32 */ #if defined(__sun) || defined(sun) #define MIN(x,y) (((x)<(y))?(x):(y)) #endif #include "miniupnpcstrings.h" #include "miniwget.h" +#include "connecthostport.h" +#include "receivedata.h" -/* miniwget2() : - * */ +/* + * 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 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; + char * content_buf; + int content_buf_len = 2048; + int content_buf_used = 0; + char chunksize_buf[32]; + 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) + { + if(endofheaders == 0) + { + int i; + int linestart=0; + int colon=0; + int valuestart=0; + if(header_buf_used + n > header_buf_len) { + header_buf = realloc(header_buf, header_buf_used + n); + header_buf_len = header_buf_used + n; + } + memcpy(header_buf + header_buf_used, buf, n); + header_buf_used += n; + /* search for CR LF CR LF (end of headers) + * recognize also LF LF */ + i = 0; + while(i < (header_buf_used-1) && (endofheaders == 0)) { + if(header_buf[i] == '\r') { + i++; + if(header_buf[i] == '\n') { + i++; + if(i < header_buf_used && header_buf[i] == '\r') { + i++; + if(i < 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 < (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]=='\n') + { + if(colon > linestart && valuestart > colon) + { +#ifdef DEBUG + printf("header='%.*s', value='%.*s'\n", + colon-linestart, header_buf+linestart, + i-valuestart, header_buf+valuestart); +#endif + if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart)) + { + content_length = atoi(header_buf+valuestart); +#ifdef DEBUG + printf("Content-Length: %d\n", content_length); +#endif + } + else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart) + && 0==strncasecmp(header_buf+valuestart, "chunked", 7)) + { +#ifdef DEBUG + printf("chunked transfer-encoding!\n"); +#endif + chunked = 1; + } + } + while(header_buf[i]=='\r' || header_buf[i] == '\n') + i++; + linestart = i; + colon = linestart; + valuestart = 0; + } + } + /* copy the remaining of the received data back to buf */ + n = header_buf_used - endofheaders; + memcpy(buf, header_buf + endofheaders, n); + /* if(headers) */ + } + if(endofheaders) + { + /* content */ + if(chunked) + { + int i = 0; + while(i < n) + { + if(chunksize == 0) + { + /* reading chunk size */ + if(chunksize_buf_index == 0) { + /* skipping any leading CR LF */ + if(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 + if(chunksize == 0) + { +#ifdef DEBUG + printf("end of HTTP content - %d %d\n", i, n); + /*printf("'%.*s'\n", n-i, buf+i);*/ +#endif + goto end_of_stream; + } + } + bytestocopy = ((int)chunksize < n - i)?chunksize:(n - i); + if((int)(content_buf_used + bytestocopy) > content_buf_len) + { + if(content_length >= content_buf_used + (int)bytestocopy) { + content_buf_len = content_length; + } else { + content_buf_len = content_buf_used + (int)bytestocopy; + } + content_buf = (char *)realloc((void *)content_buf, + content_buf_len); + } + memcpy(content_buf + content_buf_used, buf + i, bytestocopy); + content_buf_used += bytestocopy; + i += bytestocopy; + chunksize -= bytestocopy; + } + } + else + { + /* not chunked */ + if(content_length > 0 + && (content_buf_used + n) > content_length) { + /* skipping additional bytes */ + n = content_length - content_buf_used; + } + if(content_buf_used + n > content_buf_len) + { + if(content_length >= 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; + } + } + /* use the Content-Length header value if available */ + if(content_length > 0 && content_buf_used >= content_length) + { +#ifdef DEBUG + printf("End of HTTP content\n"); +#endif + break; + } + } +end_of_stream: + free(header_buf); header_buf = NULL; + *size = content_buf_used; + if(content_buf_used == 0) + { + free(content_buf); + content_buf = NULL; + } + return content_buf; +} + +/* miniwget3() : + * do all the work. + * Return NULL if something failed. */ static void * -miniwget2(const char * url, const char * host, - unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len) +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) { char buf[2048]; int s; - struct sockaddr_in dest; - struct hostent *hp; int n; int len; int sent; -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - struct timeval timeout; -#endif + void * content; + *size = 0; - hp = gethostbyname(host); - if(hp==NULL) - { - herror(host); - return NULL; - } - /* memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length); */ - memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr)); - memset(dest.sin_zero, 0, sizeof(dest.sin_zero)); - s = socket(PF_INET, SOCK_STREAM, 0); + s = connecthostport(host, port); if(s < 0) - { - perror("socket"); return NULL; - } -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - /* setting a 3 seconds timeout for the connect() call */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - perror("setsockopt"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - perror("setsockopt"); - } -#endif - dest.sin_family = AF_INET; - dest.sin_port = htons(port); - n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); -#ifdef MINIUPNPC_IGNORE_EINTR - while(n < 0 && errno == EINTR) - { - socklen_t len; - fd_set wset; - int err; - FD_ZERO(&wset); - FD_SET(s, &wset); - if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) - continue; - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ - len = sizeof(err); - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - perror("getsockopt"); - closesocket(s); - return NULL; - } - if(err != 0) { - errno = err; - n = -1; - } - } -#endif - if(n<0) - { - perror("connect"); - closesocket(s); - return NULL; - } /* get address for caller ! */ if(addr_str) { - struct sockaddr_in saddr; + struct sockaddr_storage saddr; socklen_t saddrlen; saddrlen = sizeof(saddr); @@ -132,9 +314,7 @@ miniwget2(const char * url, const char * host, } else { -#ifndef WIN32 - inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len); -#else +#if defined(__amigaos__) && !defined(__amigaos4__) /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); * But his function make a string with the port : nn.nn.nn.nn:port */ /* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr), @@ -142,7 +322,33 @@ miniwget2(const char * url, const char * host, { printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError()); }*/ - strncpy(addr_str, inet_ntoa(saddr.sin_addr), addr_str_len); + /* 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 +#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 + fprintf(stderr, "getnameinfo() failed : %d\n", n); +#else + fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n)); +#endif + } #endif } #ifdef DEBUG @@ -151,13 +357,13 @@ miniwget2(const char * url, const char * host, } len = snprintf(buf, sizeof(buf), - "GET %s HTTP/1.1\r\n" + "GET %s HTTP/%s\r\n" "Host: %s:%d\r\n" "Connection: Close\r\n" "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "\r\n", - path, host, port); + path, httpversion, host, port); sent = 0; /* sending the HTTP request */ while(sent < len) @@ -174,53 +380,38 @@ miniwget2(const char * url, const char * host, sent += n; } } - { - int headers=1; - char * respbuffer = NULL; - int allreadyread = 0; - /*while((n = recv(s, buf, 2048, 0)) > 0)*/ - while((n = ReceiveData(s, buf, 2048, 5000)) > 0) - { - if(headers) - { - int i=0; - while(i= '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))); @@ -279,6 +497,9 @@ void * miniwget(const char * url, int * size) *size = 0; if(!parseURL(url, hostname, &port, &path)) return NULL; +#ifdef DEBUG + printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path); +#endif return miniwget2(url, hostname, port, path, size, 0, 0); } @@ -293,6 +514,9 @@ void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen) addr[0] = '\0'; if(!parseURL(url, hostname, &port, &path)) return NULL; +#ifdef DEBUG + printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path); +#endif return miniwget2(url, hostname, port, path, size, addr, addrlen); } diff --git a/source/shared_lib/sources/platform/miniupnpc/minixml.c b/source/shared_lib/sources/platform/miniupnpc/minixml.c index aee2f134f..8b5594c88 100644 --- a/source/shared_lib/sources/platform/miniupnpc/minixml.c +++ b/source/shared_lib/sources/platform/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.9 2011/02/07 13:44:57 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 @@ -37,18 +38,17 @@ POSSIBILITY OF SUCH DAMAGE. * of the xmlbuffer is reached. */ static int parseatt(struct xmlparser * p) { - const char * attname = 0; - int attnamelen = 0; - const char * attvalue = 0; - int attvaluelen = 0; - char sep = 0; + const char * attname; + int attnamelen; + const char * attvalue; + int attvaluelen; while(p->xml < p->xmlend) { if(*p->xml=='/' || *p->xml=='>') return 0; if( !IS_WHITE_SPACE(*p->xml) ) { - sep = 0; + char sep; attname = p->xml; attnamelen = 0; while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) @@ -109,8 +109,8 @@ static int parseatt(struct xmlparser * p) * call the callback functions when needed... */ static void parseelt(struct xmlparser * p) { - int i = 0; - const char * elementname = 0; + int i; + const char * elementname; while(p->xml < (p->xmlend - 1)) { if((p->xml)[0]=='<' && (p->xml)[1]!='?') @@ -143,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/source/shared_lib/sources/platform/miniupnpc/minixmlvalid.c b/source/shared_lib/sources/platform/miniupnpc/minixmlvalid.c new file mode 100644 index 000000000..766211bcf --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/minixmlvalid.c @@ -0,0 +1,156 @@ +/* $Id: minixmlvalid.c,v 1.4 2011/02/07 13:44:57 nanard Exp $ */ +/* MiniUPnP Project + * http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ + * minixmlvalid.c : + * validation program for the minixml parser + * + * (c) 2006-2011 Thomas Bernard */ + +#include +#include +#include +#include "minixml.h" + +/* xml event structure */ +struct event { + enum { ELTSTART, ELTEND, ATT, CHARDATA } type; + const char * data; + int len; +}; + +struct eventlist { + int n; + struct event * events; +}; + +/* compare 2 xml event lists + * return 0 if the two lists are equals */ +int evtlistcmp(struct eventlist * a, struct eventlist * b) +{ + int i; + struct event * ae, * be; + if(a->n != b->n) + { + printf("event number not matching : %d != %d\n", a->n, b->n); + //return 1; + } + for(i=0; in; i++) + { + ae = a->events + i; + be = b->events + i; + if( (ae->type != be->type) + ||(ae->len != be->len) + ||memcmp(ae->data, be->data, ae->len)) + { + printf("Found a difference : %d '%.*s' != %d '%.*s'\n", + ae->type, ae->len, ae->data, + be->type, be->len, be->data); + return 1; + } + } + return 0; +} + +/* Test data */ +static const char xmldata[] = +"\n" +" " +"character data" +" \n \t" +"" +"\nstuff !\n ]]> \n\n" +" \tchardata1 chardata2 " +""; + +static const struct event evtref[] = +{ + {ELTSTART, "xmlroot", 7}, + {ELTSTART, "elt1", 4}, + /* attributes */ + {CHARDATA, "character data", 14}, + {ELTEND, "elt1", 4}, + {ELTSTART, "elt1b", 5}, + {ELTSTART, "elt1", 4}, + {CHARDATA, " stuff !\n ", 16}, + {ELTEND, "elt1", 4}, + {ELTSTART, "elt2a", 5}, + {ELTSTART, "elt2b", 5}, + {CHARDATA, "chardata1", 9}, + {ELTEND, "elt2b", 5}, + {ELTSTART, "elt2b", 5}, + {CHARDATA, " chardata2 ", 11}, + {ELTEND, "elt2b", 5}, + {ELTEND, "elt2a", 5}, + {ELTEND, "xmlroot", 7} +}; + +void startelt(void * data, const char * p, int l) +{ + struct eventlist * evtlist = data; + struct event * evt; + evt = evtlist->events + evtlist->n; + /*printf("startelt : %.*s\n", l, p);*/ + evt->type = ELTSTART; + evt->data = p; + evt->len = l; + evtlist->n++; +} + +void endelt(void * data, const char * p, int l) +{ + struct eventlist * evtlist = data; + struct event * evt; + evt = evtlist->events + evtlist->n; + /*printf("endelt : %.*s\n", l, p);*/ + evt->type = ELTEND; + evt->data = p; + evt->len = l; + evtlist->n++; +} + +void chardata(void * data, const char * p, int l) +{ + struct eventlist * evtlist = data; + struct event * evt; + evt = evtlist->events + evtlist->n; + /*printf("chardata : '%.*s'\n", l, p);*/ + evt->type = CHARDATA; + evt->data = p; + evt->len = l; + evtlist->n++; +} + +int testxmlparser(const char * xml, int size) +{ + int r; + struct eventlist evtlist; + struct eventlist evtlistref; + struct xmlparser parser; + evtlist.n = 0; + evtlist.events = malloc(sizeof(struct event)*100); + memset(&parser, 0, sizeof(parser)); + parser.xmlstart = xml; + parser.xmlsize = size; + parser.data = &evtlist; + parser.starteltfunc = startelt; + parser.endeltfunc = endelt; + parser.datafunc = chardata; + parsexml(&parser); + printf("%d events\n", evtlist.n); + /* compare */ + evtlistref.n = sizeof(evtref)/sizeof(struct event); + evtlistref.events = (struct event *)evtref; + r = evtlistcmp(&evtlistref, &evtlist); + free(evtlist.events); + return r; +} + +int main(int argc, char * * argv) +{ + int r; + r = testxmlparser(xmldata, sizeof(xmldata)-1); + if(r) + printf("minixml validation test failed\n"); + return r; +} + diff --git a/source/shared_lib/sources/platform/miniupnpc/msvc/miniupnpc.sln b/source/shared_lib/sources/platform/miniupnpc/msvc/miniupnpc.sln new file mode 100644 index 000000000..b3da1919e --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/msvc/miniupnpc.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc.vcproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static.vcproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}" + ProjectSection(ProjectDependencies) = postProject + {D28CE435-CB33-4BAE-8A52-C6EF915956F5} = {D28CE435-CB33-4BAE-8A52-C6EF915956F5} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32 + {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32 + {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/source/shared_lib/sources/platform/miniupnpc/msvc/miniupnpc.vcproj b/source/shared_lib/sources/platform/miniupnpc/msvc/miniupnpc.vcproj new file mode 100644 index 000000000..12a55aaff --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/msvc/miniupnpc.vcproj @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/shared_lib/sources/platform/miniupnpc/msvc/upnpc-static.vcproj b/source/shared_lib/sources/platform/miniupnpc/msvc/upnpc-static.vcproj new file mode 100644 index 000000000..294613877 --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/msvc/upnpc-static.vcproj @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/shared_lib/sources/platform/miniupnpc/portlistingparse.c b/source/shared_lib/sources/platform/miniupnpc/portlistingparse.c new file mode 100644 index 000000000..e09e80f39 --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/portlistingparse.c @@ -0,0 +1,157 @@ +/* $Id: portlistingparse.c,v 1.4 2011/03/18 11:02:17 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; + 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/source/shared_lib/sources/platform/miniupnpc/receivedata.c b/source/shared_lib/sources/platform/miniupnpc/receivedata.c new file mode 100644 index 000000000..a1eadfc46 --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/receivedata.c @@ -0,0 +1,81 @@ +/* $Id: receivedata.c,v 1.1 2011/04/11 08:21:47 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2011 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 +#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) +{ + 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 + n = recv(socket, data, length, 0); + if(n<0) { + PRINT_SOCKET_ERROR("recv"); + } + return n; +} + + diff --git a/source/shared_lib/sources/platform/miniupnpc/setup.py b/source/shared_lib/sources/platform/miniupnpc/setup.py new file mode 100644 index 000000000..ca31f9615 --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/setup.py @@ -0,0 +1,15 @@ +#! /usr/bin/python +# $Id: setup.py,v 1.6 2011/01/04 09:46:08 nanard Exp $ +# the MiniUPnP Project (c) 2007-2011 Thomas Bernard +# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ +# +# python script to build the miniupnpc module under unix +# +# replace libminiupnpc.a by libminiupnpc.so for shared library usage +from distutils.core import setup, Extension +setup(name="miniupnpc", version="1.5", + ext_modules=[ + Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], + extra_objects=["libminiupnpc.a"]) + ]) + diff --git a/source/shared_lib/sources/platform/miniupnpc/setupmingw32.py b/source/shared_lib/sources/platform/miniupnpc/setupmingw32.py index 6e612453d..d0539e450 100644 --- a/source/shared_lib/sources/platform/miniupnpc/setupmingw32.py +++ b/source/shared_lib/sources/platform/miniupnpc/setupmingw32.py @@ -1,15 +1,15 @@ #! /usr/bin/python -# $Id: setupmingw32.py,v 1.3 2009/10/30 09:18:18 nanard Exp $ -# the MiniUPnP Project (c) 2007-2009 Thomas Bernard +# $Id: setupmingw32.py,v 1.5 2011/05/15 21:18:43 nanard Exp $ +# the MiniUPnP Project (c) 2007-2011 Thomas Bernard # http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ # -# python script to build the miniupnpc module under unix +# python script to build the miniupnpc module under windows (using mingw32) # from distutils.core import setup, Extension -setup(name="miniupnpc", version="1.4", +setup(name="miniupnpc", version="1.5", ext_modules=[ Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], - libraries=["ws2_32"], + libraries=["ws2_32", "iphlpapi"], extra_objects=["libminiupnpc.a"]) ]) diff --git a/source/shared_lib/sources/platform/miniupnpc/testminiwget.sh b/source/shared_lib/sources/platform/miniupnpc/testminiwget.sh new file mode 100644 index 000000000..c048e5bd1 --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/testminiwget.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# $Id: testminiwget.sh,v 1.4 2011/05/09 08:53:15 nanard Exp $ +# project miniupnp : http://miniupnp.free.fr/ +# (c) 2011 Thomas Bernard +# +# test program for miniwget.c +# is usually invoked by "make check" +# +# This test program : +# 1 - launches a local HTTP server (minihttptestserver) +# 2 - uses testminiwget to retreive data from this server +# 3 - compares served and received data +# 4 - kills the local HTTP server and exits +# + +HTTPSERVEROUT=/tmp/httpserverout +EXPECTEDFILE=/tmp/expectedfile +DOWNLOADEDFILE=/tmp/downloadedfile +#ADDR=localhost +ADDR="[::1]" +PORT= +RET=0 + +#make minihttptestserver +#make testminiwget + +# launching the test HTTP server +./minihttptestserver -6 -e $EXPECTEDFILE > $HTTPSERVEROUT & +while [ "$PORT" == "" ]; do + PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' ` +done +echo "Test HTTP server is listening on $PORT" + +URL1="http://$ADDR:$PORT/index.html" +URL2="http://$ADDR:$PORT/chunked" +URL3="http://$ADDR:$PORT/addcrap" + +echo "standard test ..." +./testminiwget $URL1 "${DOWNLOADEDFILE}.1" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.1" ; then + echo "ok" +else + echo "standard test FAILED" + RET=1 +fi + +echo "chunked transfert encoding test ..." +./testminiwget $URL2 "${DOWNLOADEDFILE}.2" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.2" ; then + echo "ok" +else + echo "chunked transfert encoding test FAILED" + RET=1 +fi + +echo "response too long test ..." +./testminiwget $URL3 "${DOWNLOADEDFILE}.3" +if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.3" ; then + echo "ok" +else + echo "response too long test FAILED" + RET=1 +fi + +# kill the test HTTP server +kill %1 +wait %1 + +# remove temporary files (for success cases) +if [ $RET -eq 0 ]; then + rm -f "${DOWNLOADEDFILE}.1" + rm -f "${DOWNLOADEDFILE}.2" + rm -f "${DOWNLOADEDFILE}.3" + rm -f $EXPECTEDFILE $HTTPSERVEROUT +else + echo "at least one of the test FAILED" +fi +exit $RET + diff --git a/source/shared_lib/sources/platform/miniupnpc/testupnpigd.py b/source/shared_lib/sources/platform/miniupnpc/testupnpigd.py new file mode 100755 index 000000000..6d167a4ce --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/testupnpigd.py @@ -0,0 +1,84 @@ +#! /usr/bin/python +# $Id: testupnpigd.py,v 1.4 2008/10/11 10:27:20 nanard Exp $ +# MiniUPnP project +# Author : Thomas Bernard +# This Sample code is public domain. +# website : http://miniupnp.tuxfamily.org/ + +# import the python miniupnpc module +import miniupnpc +import socket +import BaseHTTPServer + +# function definition +def list_redirections(): + i = 0 + while True: + p = u.getgenericportmapping(i) + if p==None: + break + print i, p + i = i + 1 + +#define the handler class for HTTP connections +class handler_class(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(self): + self.send_response(200) + self.end_headers() + self.wfile.write("OK MON GARS") + +# create the object +u = miniupnpc.UPnP() +#print 'inital(default) values :' +#print ' discoverdelay', u.discoverdelay +#print ' lanaddr', u.lanaddr +#print ' multicastif', u.multicastif +#print ' minissdpdsocket', u.minissdpdsocket +u.discoverdelay = 200; + +try: + print 'Discovering... delay=%ums' % u.discoverdelay + ndevices = u.discover() + print ndevices, 'device(s) detected' + + # select an igd + u.selectigd() + # display information about the IGD and the internet connection + print 'local ip address :', u.lanaddr + externalipaddress = u.externalipaddress() + print 'external ip address :', externalipaddress + print u.statusinfo(), u.connectiontype() + + #instanciate a HTTPd object. The port is assigned by the system. + httpd = BaseHTTPServer.HTTPServer((u.lanaddr, 0), handler_class) + eport = httpd.server_port + + # find a free port for the redirection + r = u.getspecificportmapping(eport, 'TCP') + while r != None and eport < 65536: + eport = eport + 1 + r = u.getspecificportmapping(eport, 'TCP') + + print 'trying to redirect %s port %u TCP => %s port %u TCP' % (externalipaddress, eport, u.lanaddr, httpd.server_port) + + b = u.addportmapping(eport, 'TCP', u.lanaddr, httpd.server_port, + 'UPnP IGD Tester port %u' % eport, '') + if b: + print 'Success. Now waiting for some HTTP request on http://%s:%u' % (externalipaddress ,eport) + try: + httpd.handle_request() + httpd.server_close() + except KeyboardInterrupt, details: + print "CTRL-C exception!", details + b = u.deleteportmapping(eport, 'TCP') + if b: + print 'Successfully deleted port mapping' + else: + print 'Failed to remove port mapping' + else: + print 'Failed' + + httpd.server_close() + +except Exception, e: + print 'Exception :', e diff --git a/source/shared_lib/sources/platform/miniupnpc/updateminiupnpcstrings.sh b/source/shared_lib/sources/platform/miniupnpc/updateminiupnpcstrings.sh index daf71a92f..dde4354a8 100755 --- a/source/shared_lib/sources/platform/miniupnpc/updateminiupnpcstrings.sh +++ b/source/shared_lib/sources/platform/miniupnpc/updateminiupnpcstrings.sh @@ -1,7 +1,10 @@ #! /bin/sh -# $Id: updateminiupnpcstrings.sh,v 1.4 2009/07/29 08:34:01 nanard Exp $ +# $Id: updateminiupnpcstrings.sh,v 1.7 2011/01/04 11:41:53 nanard Exp $ +# project miniupnp : http://miniupnp.free.fr/ +# (c) 2009 Thomas Bernard FILE=miniupnpcstrings.h +TMPFILE=miniupnpcstrings.h.tmp TEMPLATE_FILE=${FILE}.in # detecting the OS name and version @@ -13,7 +16,7 @@ if [ -f /etc/debian_version ]; then fi # use lsb_release (Linux Standard Base) when available LSB_RELEASE=`which lsb_release` -if [ 0 -eq $? ]; then +if [ 0 -eq $? -a -x "${LSB_RELEASE}" ]; then OS_NAME=`${LSB_RELEASE} -i -s` OS_VERSION=`${LSB_RELEASE} -r -s` case $OS_NAME in @@ -26,13 +29,25 @@ if [ 0 -eq $? ]; then esac fi +# on AmigaOS 3, uname -r returns "unknown", so we use uname -v +if [ "$OS_NAME" = "AmigaOS" ]; then + if [ "$OS_VERSION" = "unknown" ]; then + OS_VERSION=`uname -v` + fi +fi + echo "Detected OS [$OS_NAME] version [$OS_VERSION]" +MINIUPNPC_VERSION=`cat VERSION` +echo "MiniUPnPc version [${MINIUPNPC_VERSION}]" EXPR="s|OS_STRING \".*\"|OS_STRING \"${OS_NAME}/${OS_VERSION}\"|" #echo $EXPR -#echo "Backuping $FILE to $FILE.bak." -#cp $FILE $FILE.bak test -f ${FILE}.in echo "setting OS_STRING macro value to ${OS_NAME}/${OS_VERSION} in $FILE." -sed -e "$EXPR" < $TEMPLATE_FILE > $FILE +sed -e "$EXPR" < $TEMPLATE_FILE > $TMPFILE + +EXPR="s|MINIUPNPC_VERSION_STRING \".*\"|MINIUPNPC_VERSION_STRING \"${MINIUPNPC_VERSION}\"|" +echo "setting MINIUPNPC_VERSION_STRING macro value to ${MINIUPNPC_VERSION} in $FILE." +sed -e "$EXPR" < $TMPFILE > $FILE +rm $TMPFILE diff --git a/source/shared_lib/sources/platform/miniupnpc/upnpc.c b/source/shared_lib/sources/platform/miniupnpc/upnpc.c new file mode 100644 index 000000000..b136d9d1f --- /dev/null +++ b/source/shared_lib/sources/platform/miniupnpc/upnpc.c @@ -0,0 +1,683 @@ +/* $Id: upnpc.c,v 1.88 2011/06/17 23:31:01 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005-2011 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +#include +#include +#include +#include +#ifdef WIN32 +#include +#define snprintf _snprintf +#endif +#include "miniwget.h" +#include "miniupnpc.h" +#include "upnpcommands.h" +#include "upnperrors.h" + +/* protofix() checks if protocol is "UDP" or "TCP" + * returns NULL if not */ +const char * protofix(const char * proto) +{ + static const char proto_tcp[4] = { 'T', 'C', 'P', 0}; + static const char proto_udp[4] = { 'U', 'D', 'P', 0}; + int i, b; + for(i=0, b=1; i<4; i++) + b = b && ( (proto[i] == proto_tcp[i]) + || (proto[i] == (proto_tcp[i] | 32)) ); + if(b) + return proto_tcp; + for(i=0, b=1; i<4; i++) + b = b && ( (proto[i] == proto_udp[i]) + || (proto[i] == (proto_udp[i] | 32)) ); + if(b) + return proto_udp; + return 0; +} + +static void DisplayInfos(struct UPNPUrls * urls, + struct IGDdatas * data) +{ + char externalIPAddress[40]; + char connectionType[64]; + char status[64]; + char lastconnerr[64]; + unsigned int uptime; + unsigned int brUp, brDown; + time_t timenow, timestarted; + int r; + UPNP_GetConnectionTypeInfo(urls->controlURL, + data->first.servicetype, + connectionType); + if(connectionType[0]) + printf("Connection Type : %s\n", connectionType); + else + printf("GetConnectionTypeInfo failed.\n"); + UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, + status, &uptime, lastconnerr); + printf("Status : %s, uptime=%us, LastConnectionError : %s\n", + status, uptime, lastconnerr); + timenow = time(NULL); + timestarted = timenow - uptime; + printf(" Time started : %s", ctime(×tarted)); + UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype, + &brDown, &brUp); + printf("MaxBitRateDown : %u bps", brDown); + if(brDown >= 1000000) { + printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10); + } else if(brDown >= 1000) { + printf(" (%u Kbps)", brDown / 1000); + } + printf(" MaxBitRateUp %u bps", brUp); + if(brUp >= 1000000) { + printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10); + } else if(brUp >= 1000) { + printf(" (%u Kbps)", brUp / 1000); + } + printf("\n"); + r = UPNP_GetExternalIPAddress(urls->controlURL, + data->first.servicetype, + externalIPAddress); + if(r != UPNPCOMMAND_SUCCESS) + printf("GetExternalIPAddress() returned %d\n", r); + if(externalIPAddress[0]) + printf("ExternalIPAddress = %s\n", externalIPAddress); + else + printf("GetExternalIPAddress failed.\n"); +} + +static void GetConnectionStatus(struct UPNPUrls * urls, + struct IGDdatas * data) +{ + unsigned int bytessent, bytesreceived, packetsreceived, packetssent; + DisplayInfos(urls, data); + bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); + bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); + packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); + packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); + printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); + printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); +} + +static void ListRedirections(struct UPNPUrls * urls, + struct IGDdatas * data) +{ + int r; + int i = 0; + char index[6]; + char intClient[40]; + char intPort[6]; + char extPort[6]; + char protocol[4]; + char desc[80]; + char enabled[6]; + char rHost[64]; + char duration[16]; + /*unsigned int num=0; + UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num); + printf("PortMappingNumberOfEntries : %u\n", num);*/ + do { + snprintf(index, 6, "%d", i); + rHost[0] = '\0'; enabled[0] = '\0'; + duration[0] = '\0'; desc[0] = '\0'; + extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; + r = UPNP_GetGenericPortMappingEntry(urls->controlURL, + data->first.servicetype, + index, + extPort, intClient, intPort, + protocol, desc, enabled, + rHost, duration); + if(r==0) + /* + printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n" + " desc='%s' rHost='%s'\n", + i, protocol, extPort, intClient, intPort, + enabled, duration, + desc, rHost); + */ + printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n", + i, protocol, extPort, intClient, intPort, + desc, rHost, duration); + else + printf("GetGenericPortMappingEntry() returned %d (%s)\n", + r, strupnperror(r)); + i++; + } while(r==0); +} + +static void NewListRedirections(struct UPNPUrls * urls, + struct IGDdatas * data) +{ + int r; + int i = 0; + struct PortMappingParserData pdata; + struct PortMapping * pm; + + memset(&pdata, 0, sizeof(struct PortMappingParserData)); + r = UPNP_GetListOfPortMappings(urls->controlURL, + data->first.servicetype, + "0", + "65535", + "TCP", + "1000", + &pdata); + if(r == UPNPCOMMAND_SUCCESS) + { + for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next) + { + printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", + i, pm->protocol, pm->externalPort, pm->internalClient, + pm->internalPort, + pm->description, pm->remoteHost, + (unsigned)pm->leaseTime); + i++; + } + FreePortListing(&pdata); + } + else + { + printf("GetListOfPortMappings() returned %d (%s)\n", + r, strupnperror(r)); + } + r = UPNP_GetListOfPortMappings(urls->controlURL, + data->first.servicetype, + "0", + "65535", + "UDP", + "1000", + &pdata); + if(r == UPNPCOMMAND_SUCCESS) + { + for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next) + { + printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", + i, pm->protocol, pm->externalPort, pm->internalClient, + pm->internalPort, + pm->description, pm->remoteHost, + (unsigned)pm->leaseTime); + i++; + } + FreePortListing(&pdata); + } + else + { + printf("GetListOfPortMappings() returned %d (%s)\n", + r, strupnperror(r)); + } +} + +/* Test function + * 1 - get connection type + * 2 - get extenal ip address + * 3 - Add port mapping + * 4 - get this port mapping from the IGD */ +static void SetRedirectAndTest(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * iaddr, + const char * iport, + const char * eport, + const char * proto, + const char * leaseDuration) +{ + char externalIPAddress[40]; + char intClient[40]; + char intPort[6]; + char duration[16]; + int r; + + if(!iaddr || !iport || !eport || !proto) + { + fprintf(stderr, "Wrong arguments\n"); + return; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "invalid protocol\n"); + return; + } + + UPNP_GetExternalIPAddress(urls->controlURL, + data->first.servicetype, + externalIPAddress); + if(externalIPAddress[0]) + printf("ExternalIPAddress = %s\n", externalIPAddress); + else + printf("GetExternalIPAddress failed.\n"); + + r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, + eport, iport, iaddr, 0, proto, 0, leaseDuration); + if(r!=UPNPCOMMAND_SUCCESS) + printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", + eport, iport, iaddr, r, strupnperror(r)); + + r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, + data->first.servicetype, + eport, proto, + intClient, intPort, NULL/*desc*/, + NULL/*enabled*/, duration); + if(r!=UPNPCOMMAND_SUCCESS) + printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", + r, strupnperror(r)); + + if(intClient[0]) { + printf("InternalIP:Port = %s:%s\n", intClient, intPort); + printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", + externalIPAddress, eport, proto, intClient, intPort, duration); + } +} + +static void +RemoveRedirect(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * eport, + const char * proto) +{ + int r; + if(!proto || !eport) + { + fprintf(stderr, "invalid arguments\n"); + return; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "protocol invalid\n"); + return; + } + r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, 0); + printf("UPNP_DeletePortMapping() returned : %d\n", r); +} + +/* IGD:2, functions for service WANIPv6FirewallControl:1 */ +static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data) +{ + unsigned int bytessent, bytesreceived, packetsreceived, packetssent; + int firewallEnabled = 0, inboundPinholeAllowed = 0; + + UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed); + printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed); + printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No"); + + bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); + bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); + packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); + packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); + printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); + printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); +} + +/* Test function + * 1 - Add pinhole + * 2 - Check if pinhole is working from the IGD side */ +static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data, + const char * remoteaddr, const char * eport, + const char * intaddr, const char * iport, + const char * proto, const char * lease_time) +{ + char uniqueID[8]; + //int isWorking = 0; + int r; + + if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time) + { + fprintf(stderr, "Wrong arguments\n"); + return; + } + /*proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "invalid protocol\n"); + return; + }*/ + r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID); + if(r!=UPNPCOMMAND_SUCCESS) + printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", + intaddr, iport, remoteaddr, eport, r, strupnperror(r)); + else + { + printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n", intaddr, iport, remoteaddr, eport, uniqueID); + /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking); + if(r!=UPNPCOMMAND_SUCCESS) + printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); + printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/ + } +} + +/* Test function + * 1 - Check if pinhole is working from the IGD side + * 2 - Update pinhole */ +static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data, + const char * uniqueID, const char * lease_time) +{ + int isWorking = 0; + int r; + + if(!uniqueID || !lease_time) + { + fprintf(stderr, "Wrong arguments\n"); + return; + } + r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); + printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); + if(r!=UPNPCOMMAND_SUCCESS) + printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); + if(isWorking || r==709) + { + r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time); + printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time); + if(r!=UPNPCOMMAND_SUCCESS) + printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r)); + } +} + +/* Test function + * Get pinhole timeout + */ +static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data, + const char * remoteaddr, const char * eport, + const char * intaddr, const char * iport, + const char * proto) +{ + int timeout = 0; + int r; + + if(!intaddr || !remoteaddr || !iport || !eport || !proto) + { + fprintf(stderr, "Wrong arguments\n"); + return; + } + + r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout); + if(r!=UPNPCOMMAND_SUCCESS) + printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", + intaddr, iport, remoteaddr, eport, r, strupnperror(r)); + else + printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout); +} + +static void +GetPinholePackets(struct UPNPUrls * urls, + struct IGDdatas * data, const char * uniqueID) +{ + int r, pinholePackets = 0; + if(!uniqueID) + { + fprintf(stderr, "invalid arguments\n"); + return; + } + r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets); + if(r!=UPNPCOMMAND_SUCCESS) + printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r)); + else + printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets); +} + +static void +CheckPinhole(struct UPNPUrls * urls, + struct IGDdatas * data, const char * uniqueID) +{ + int r, isWorking = 0; + if(!uniqueID) + { + fprintf(stderr, "invalid arguments\n"); + return; + } + r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); + if(r!=UPNPCOMMAND_SUCCESS) + printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); + else + printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); +} + +static void +RemovePinhole(struct UPNPUrls * urls, + struct IGDdatas * data, const char * uniqueID) +{ + int r; + if(!uniqueID) + { + fprintf(stderr, "invalid arguments\n"); + return; + } + r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID); + printf("UPNP_DeletePinhole() returned : %d\n", r); +} + + +/* sample upnp client program */ +int main(int argc, char ** argv) +{ + char command = 0; + char ** commandargv = 0; + int commandargc = 0; + struct UPNPDev * devlist = 0; + char lanaddr[64]; /* my ip address on the LAN */ + int i; + const char * rootdescurl = 0; + const char * multicastif = 0; + const char * minissdpdpath = 0; + int retcode = 0; + int error = 0; + int ipv6 = 0; + +#ifdef WIN32 + WSADATA wsaData; + int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); + if(nResult != NO_ERROR) + { + fprintf(stderr, "WSAStartup() failed.\n"); + return -1; + } +#endif + printf("upnpc : miniupnpc library test client. (c) 2006-2011 Thomas Bernard\n"); + printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" + "for more information.\n"); + /* command line processing */ + for(i=1; ipNext) + { + printf(" desc: %s\n st: %s\n\n", + device->descURL, device->st); + } + } + else + { + printf("upnpDiscover() error code=%d\n", error); + } + i = 1; + if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr))) + || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) + { + switch(i) { + case 1: + printf("Found valid IGD : %s\n", urls.controlURL); + break; + case 2: + printf("Found a (not connected?) IGD : %s\n", urls.controlURL); + printf("Trying to continue anyway\n"); + break; + case 3: + printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); + printf("Trying to continue anyway\n"); + break; + default: + printf("Found device (igd ?) : %s\n", urls.controlURL); + printf("Trying to continue anyway\n"); + } + printf("Local LAN ip address : %s\n", lanaddr); + #if 0 + printf("getting \"%s\"\n", urls.ipcondescURL); + descXML = miniwget(urls.ipcondescURL, &descXMLsize); + if(descXML) + { + /*fwrite(descXML, 1, descXMLsize, stdout);*/ + free(descXML); descXML = NULL; + } + #endif + + switch(command) + { + case 'l': + DisplayInfos(&urls, &data); + ListRedirections(&urls, &data); + break; + case 'L': + NewListRedirections(&urls, &data); + break; + case 'a': + SetRedirectAndTest(&urls, &data, + commandargv[0], commandargv[1], + commandargv[2], commandargv[3], + (commandargc > 4)?commandargv[4]:"0"); + break; + case 'd': + for(i=0; i #include "upnpcommands.h" #include "miniupnpc.h" +#include "portlistingparse.h" static UNSIGNED_INTEGER my_atoui(const char * s) @@ -24,13 +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; - simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, buffer, &bufsize); + 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); @@ -44,13 +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; - simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, buffer, &bufsize); + 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); @@ -64,13 +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; - simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, buffer, &bufsize); + 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); @@ -84,13 +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; - simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, buffer, &bufsize); + 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); @@ -107,8 +124,8 @@ UPNP_GetStatusInfo(const char * controlURL, char * lastconnerror) { struct NameValueParserData pdata; - char buffer[4096]; - int bufsize = 4096; + char * buffer; + int bufsize; char * p; char * up; char * err; @@ -117,9 +134,13 @@ UPNP_GetStatusInfo(const char * controlURL, if(!status && !uptime) return UPNPCOMMAND_INVALID_ARGS; - simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize); + 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"); @@ -166,17 +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; - simpleUPnPcommand(-1, controlURL, servicetype, - "GetConnectionTypeInfo", 0, buffer, &bufsize); + 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.... */ @@ -204,11 +228,11 @@ 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; @@ -218,17 +242,20 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL, return UPNPCOMMAND_INVALID_ARGS; /* shouldn't we use GetCommonLinkProperties ? */ - simpleUPnPcommand(-1, controlURL, servicetype, - "GetCommonLinkProperties", 0, buffer, &bufsize); - /*"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,17 +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; - simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize); + 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) { @@ -309,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; @@ -337,12 +369,18 @@ 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"; - simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize); + AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; + if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, + "AddPortMapping", AddPortMappingArgs, + &bufsize))) { + free(AddPortMappingArgs); + return UPNPCOMMAND_HTTP_ERROR; + } /*DisplayNameValueList(buffer, bufsize);*/ /*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); */ @@ -363,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; @@ -379,11 +417,15 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, DeletePortMappingArgs[1].val = extPort; DeletePortMappingArgs[2].elt = "NewProtocol"; DeletePortMappingArgs[2].val = proto; - simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePortMapping", - DeletePortMappingArgs, buffer, &bufsize); + 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; @@ -411,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) @@ -422,10 +464,15 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL, GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); GetPortMappingArgs[0].elt = "NewPortMappingIndex"; GetPortMappingArgs[0].val = index; - simpleUPnPcommand(-1, controlURL, servicetype, - "GetGenericPortMappingEntry", - GetPortMappingArgs, buffer, &bufsize); + 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) { @@ -492,15 +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; - simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize); + 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) { @@ -528,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; @@ -542,16 +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; - simpleUPnPcommand(-1, controlURL, servicetype, - "GetSpecificPortMappingEntry", - GetPortMappingArgs, buffer, &bufsize); - /*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */ + 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) { @@ -568,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; @@ -579,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/source/shared_lib/sources/platform/miniupnpc/upnperrors.c b/source/shared_lib/sources/platform/miniupnpc/upnperrors.c index 8a05349b1..a48ae10d3 100644 --- a/source/shared_lib/sources/platform/miniupnpc/upnperrors.c +++ b/source/shared_lib/sources/platform/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.5 2011/04/10 11:19:36 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; diff --git a/source/shared_lib/sources/platform/miniupnpc/upnpreplyparse.c b/source/shared_lib/sources/platform/miniupnpc/upnpreplyparse.c index 0d915091c..482030b35 100644 --- a/source/shared_lib/sources/platform/miniupnpc/upnpreplyparse.c +++ b/source/shared_lib/sources/platform/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.11 2011/02/07 16:17:06 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard + * (c) 2006-2011 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -27,23 +27,41 @@ 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. Limited to 63 chars strings */ + 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); + } } void ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data) + struct NameValueParserData * data) { struct xmlparser parser; - memset(&parser,0,sizeof(parser)); LIST_INIT(&(data->head)); + data->portListing = NULL; + data->portListingLength = 0; /* init xmlparser object */ parser.xmlstart = buffer; parser.xmlsize = bufsize; @@ -59,6 +77,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); diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index f18b145d2..d383cebff 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -2146,7 +2146,9 @@ int UPNP_Tools::upnp_init(void *param) { if(UPNP_Tools::isUPNP) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Searching for UPnP devices for automatic port forwarding...\n"); - devlist = upnpDiscover(2000, NULL, NULL, 0); + + int ipv6 = 0; + devlist = upnpDiscover(2000, NULL, NULL, 0, ipv6, NULL); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"UPnP device search finished.\n"); if (devlist) { @@ -2240,9 +2242,9 @@ bool UPNP_Tools::upnp_add_redirect(int ports[2]) { sprintf(int_port_str, "%d", ports[1]); #ifndef MEGAGLEST_EMBEDDED_MINIUPNPC - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,ext_port_str, int_port_str, lanaddr, "MegaGlest - www.megaglest.org", "TCP", 0); + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,ext_port_str, int_port_str, lanaddr, "MegaGlest - www.megaglest.org", "TCP", 0, NULL); #else - r = UPNP_AddPortMapping(urls.controlURL, data.servicetype,ext_port_str, int_port_str, lanaddr, "MegaGlest - www.megaglest.org", "TCP", 0); + r = UPNP_AddPortMapping(urls.controlURL, data.servicetype,ext_port_str, int_port_str, lanaddr, "MegaGlest - www.megaglest.org", "TCP", 0, NULL); #endif if (r != UPNPCOMMAND_SUCCESS) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] AddPortMapping(%s, %s, %s) failed\n",__FILE__,__FUNCTION__,__LINE__,ext_port_str, int_port_str, lanaddr);