Merge branch 'bugfixes'

Conflicts:
	src/multiint.cpp
master
vexed 2013-10-27 21:15:49 -04:00
commit 2f217ab602
39 changed files with 2245 additions and 675 deletions

View File

@ -1,6 +1,205 @@
$Id: Changelog.txt,v 1.125 2010/12/21 16:13:13 nanard Exp $
$Id: Changelog.txt,v 1.189 2013/10/07 10:04:55 nanard Exp $
miniUPnP client Changelog.
2013/10/07:
fixed potential buffer overrun in miniwget.c
Modified UPNP_GetValidIGD() to check for ExternalIpAddress
2013/08/01:
define MAXHOSTNAMELEN if not already done
2013/06/06:
update upnpreplyparse to allow larger values (128 chars instead of 64)
2013/05/14:
Update upnpreplyparse to take into account "empty" elements
validate upnpreplyparse.c code with "make check"
2013/05/03:
Fix Solaris build thanks to Maciej Małecki
2013/04/27:
Fix testminiwget.sh for BSD
2013/03/23:
Fixed Makefile for *BSD
2013/03/11:
Update Makefile to use JNAerator version 0.11
2013/02/11:
Fix testminiwget.sh for use with dash
Use $(DESTDIR) in Makefile
VERSION 1.8 : released 2013/02/06
2012/10/16:
fix testminiwget with no IPv6 support
2012/09/27:
Rename all include guards to not clash with C99
(7.1.3 Reserved identifiers).
2012/08/30:
Added -e option to upnpc program (set description for port mappings)
2012/08/29:
Python 3 support (thanks to Christopher Foo)
2012/08/11:
Fix a memory link in UPNP_GetValidIGD()
Try to handle scope id in link local IPv6 URL under MS Windows
2012/07/20:
Disable HAS_IP_MREQN on DragonFly BSD
2012/06/28:
GetUPNPUrls() now inserts scope into link-local IPv6 addresses
2012/06/23:
More error return checks in upnpc.c
#define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id
parseURL() now parses IPv6 addresses scope
new parameter for miniwget() : IPv6 address scope
increment API_VERSION to 9
2012/06/20:
fixed CMakeLists.txt
2012/05/29
Improvements in testminiwget.sh
VERSION 1.7 : released 2012/05/24
2012/05/01:
Cleanup settings of CFLAGS in Makefile
Fix signed/unsigned integer comparaisons
2012/04/20:
Allow to specify protocol with TCP or UDP for -A option
2012/04/09:
Only try to fetch XML description once in UPNP_GetValidIGD()
Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments.
2012/04/05:
minor improvements to minihttptestserver.c
2012/03/15:
upnperrors.c returns valid error string for unrecognized error codes
2012/03/08:
make minihttptestserver listen on loopback interface instead of 0.0.0.0
2012/01/25:
Maven installation thanks to Alexey Kuznetsov
2012/01/21:
Replace WIN32 macro by _WIN32
2012/01/19:
Fixes in java wrappers thanks to Alexey Kuznetsov :
https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc
Make and install .deb packages (python) thanks to Alexey Kuznetsov :
https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc
2012/01/07:
The multicast interface can now be specified by name with IPv4.
2012/01/02:
Install man page
2011/11/25:
added header to Port Mappings list in upnpc.c
2011/10/09:
Makefile : make clean now removes jnaerator generated files.
MINIUPNPC_VERSION in miniupnpc.h (updated by make)
2011/09/12:
added rootdescURL to UPNPUrls structure.
VERSION 1.6 : released 2011/07/25
2011/07/25:
Update doc for version 1.6 release
2011/06/18:
Fix for windows in miniwget.c
2011/06/04:
display remote host in port mapping listing
2011/06/03:
Fix in make install : there were missing headers
2011/05/26:
Fix the socket leak in miniwget thanks to Richard Marsh.
Permit to add leaseduration in -a command. Display lease duration.
2011/05/15:
Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6
2011/05/09:
add a test in testminiwget.sh.
more error checking in miniwget.c
2011/05/06:
Adding some tool to test and validate miniwget.c
simplified and debugged miniwget.c
2011/04/11:
moving ReceiveData() to a receivedata.c file.
parsing presentation url
adding IGD v2 WANIPv6FirewallControl commands
2011/04/10:
update of miniupnpcmodule.c
comments in miniwget.c, update in testminiwget
Adding errors codes from IGD v2
new functions in upnpc.c for IGD v2
2011/04/09:
Support for litteral ip v6 address in miniwget
2011/04/08:
Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
Updating APIVERSION
Supporting IPV6 in upnpDiscover()
Adding a -6 option to upnpc command line tool
2011/03/18:
miniwget/parseURL() : return an error when url param is null.
fixing GetListOfPortMappings()
2011/03/14:
upnpDiscover() now reporting an error code.
improvements in comments.
2011/03/11:
adding miniupnpcstrings.h.cmake and CMakeLists.txt files.
2011/02/15:
Implementation of GetListOfPortMappings()
2011/02/07:
updates to minixml to support character data starting with spaces
minixml now support CDATA
upnpreplyparse treats <NewPortListing> specificaly
change in simpleUPnPcommand to return the buffer (simplification)
2011/02/06:
Added leaseDuration argument to AddPortMapping()
Starting to implement GetListOfPortMappings()
2011/01/11:
updating wingenminiupnpcstrings.c
2011/01/04:
improving updateminiupnpcstrings.sh
VERSION 1.5 : released 2011/01/01
2010/12/21:
use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo
@ -155,7 +354,7 @@ VERSION 1.2 :
small modif to make Clang happy :)
2008/07/17:
#define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV...
#define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV...
2008/07/14:
include declspec.h in installation (to /usr/include/miniupnpc)
@ -177,7 +376,7 @@ VERSION 1.1 :
improved python module error/exception reporting.
2008/04/23:
Completely rewrite igd_desc_parse.c in order to be compatible with
Completely rewrite igd_desc_parse.c in order to be compatible with
Linksys WAG200G
Added testigddescparse
updated python module
@ -200,7 +399,7 @@ VERSION 1.0 :
improved make install :)
2007/12/22:
Adding upnperrors.c/h to provide a strupnperror() function
Adding upnperrors.c/h to provide a strupnperror() function
used to translate UPnP error codes to string.
2007/12/19:

View File

@ -1,4 +1,5 @@
Copyright (c) 2005-2009, Thomas BERNARD
MiniUPnPc
Copyright (c) 2005-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -18,8 +18,11 @@ noinst_HEADERS = \
minissdpc.h \
miniupnpc.h \
miniupnpcstrings.h \
miniupnpctypes.h \
miniwget.h \
minixml.h \
portlistingparse.h \
receivedata.h \
upnpcommands.h \
upnperrors.h \
upnpreplyparse.h
@ -32,6 +35,8 @@ libminiupnpc_a_SOURCES = \
miniupnpc.c \
miniwget.c \
minixml.c \
portlistingparse.c \
receivedata.c \
upnpcommands.c \
upnperrors.c \
upnpreplyparse.c

View File

@ -1,28 +1,35 @@
Project: miniupnp
Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
github: https://github.com/miniupnp/miniupnp
freecode: http://freecode.com/projects/miniupnp
Author: Thomas Bernard
Copyright (c) 2005-2009 Thomas Bernard
Copyright (c) 2005-2012 Thomas Bernard
This software is subject to the conditions detailed in the
LICENSE file provided within this distribution.
For the comfort of Win32 users, bsdqueue.h is included in the distribution.
Its licence is included in the header of the file.
bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system.
* miniupnp Client *
* miniUPnP Client - miniUPnPc *
To compile, simply run 'gmake' (could be 'make' on your system).
Under win32, to compile with MinGW, type "mingw32make.bat".
MS Visual C solution and project files are supplied in the msvc/ subdirectory.
The compilation is known to work under linux, FreeBSD,
OpenBSD, MacOS X, AmigaOS and cygwin.
The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3.
upx (http://upx.sourceforge.net) is used to compress the win32 .exe files.
To install the library and headers on the system use :
> su
> make install
> exit
alternatively, to install in a specific location, use :
alternatively, to install into a specific location, use :
> INSTALLPREFIX=/usr/local make install
upnpc.c is a sample client using the libminiupnpc.
@ -40,9 +47,10 @@ and -lminiupnpc for the link
Discovery process is speeded up when MiniSSDPd is running on the machine.
* Python module *
you can build a python module with 'make pythonmodule'
you can build a python module with 'make pythonmodule'
and install it with 'make installpythonmodule'.
setup.py (and setupmingw32.py) are included in the distribution.
@ -53,4 +61,6 @@ e-mail : miniupnp@free.fr
If you are using libminiupnpc in your application, please
send me an email !
For any question, you can use the web forum :
http://miniupnp.tuxfamily.org/forum/

View File

@ -36,7 +36,7 @@
#define _SYS_QUEUE_H_
/*
* This file defines five types of data structures: singly-linked lists,
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues, and circular queues.
*
*
@ -95,7 +95,7 @@
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
@ -107,7 +107,7 @@ struct name { \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List access methods.
*/
@ -322,8 +322,8 @@ struct { \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* tail queue access methods
/*
* tail queue access methods
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
@ -430,7 +430,7 @@ struct { \
}
/*
* Circular queue access methods
* Circular queue access methods
*/
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)

View File

@ -1,18 +1,25 @@
/* $Id: codelength.h,v 1.1 2008/10/06 22:04:06 nanard Exp $ */
/* $Id: codelength.h,v 1.4 2012/09/27 15:40:29 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2008 Thomas Bernard
* copyright (c) 2005-2011 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#ifndef __CODELENGTH_H__
#define __CODELENGTH_H__
#ifndef CODELENGTH_H_INCLUDED
#define CODELENGTH_H_INCLUDED
/* Encode length by using 7bit per Byte :
* Most significant bit of each byte specifies that the
* following byte is part of the code */
#define DECODELENGTH(n, p) n = 0; \
do { n = (n << 7) | (*p & 0x7f); } \
while(*(p++)&0x80);
while((*(p++)&0x80) && (n<(1<<25)));
#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \
n = 0; \
do { \
if((p) >= (p_limit)) break; \
n = (n << 7) | (*(p) & 0x7f); \
} while((*((p)++)&0x80) && (n<(1<<25)));
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \

View File

@ -1,7 +1,7 @@
/* $Id: connecthostport.c,v 1.3 2010/12/21 16:13:14 nanard Exp $ */
/* $Id: connecthostport.c,v 1.11 2013/08/01 21:21:25 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2010 Thomas Bernard
* Copyright (c) 2010-2013 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@ -13,18 +13,22 @@
#include <string.h>
#include <stdio.h>
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#define MAXHOSTNAMELEN 64
#define snprintf _snprintf
#define herror
#define socklen_t int
#else /* #ifdef WIN32 */
#else /* #ifdef _WIN32 */
#include <unistd.h>
#include <sys/param.h>
#include <sys/select.h>
#include <errno.h>
#define closesocket close
#include <netdb.h>
#include <netinet/in.h>
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
@ -32,10 +36,10 @@
#include <sys/types.h>
#include <sys/socket.h>
#endif /* #ifndef USE_GETHOSTBYNAME */
#endif /* #else WIN32 */
#endif /* #else _WIN32 */
/* definition of PRINT_SOCKET_ERROR */
#ifdef WIN32
#ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
@ -47,16 +51,22 @@
#include "connecthostport.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port)
int connecthostport(const char * host, unsigned short port,
unsigned int scope_id)
{
int s, n;
#ifdef USE_GETHOSTBYNAME
struct sockaddr_in dest;
struct hostent *hp;
#else /* #ifdef USE_GETHOSTBYNAME */
char tmp_host[MAXHOSTNAMELEN+1];
char port_str[8];
struct addrinfo *ai, *p;
struct addrinfo hints;
@ -64,7 +74,7 @@ int connecthostport(const char * host, unsigned short port)
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
struct timeval timeout;
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
#ifdef USE_GETHOSTBYNAME
hp = gethostbyname(host);
if(hp == NULL)
@ -139,10 +149,27 @@ int connecthostport(const char * host, unsigned short port)
hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */
/* hints.ai_protocol = IPPROTO_TCP; */
snprintf(port_str, sizeof(port_str), "%hu", port);
n = getaddrinfo(host, port_str, &hints, &ai);
if(host[0] == '[')
{
/* literal ip v6 address */
int i, j;
for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
{
tmp_host[i] = host[j];
if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
j+=2; /* skip "25" */
}
tmp_host[i] = '\0';
}
else
{
strncpy(tmp_host, host, MAXHOSTNAMELEN);
}
tmp_host[MAXHOSTNAMELEN] = '\0';
n = getaddrinfo(tmp_host, port_str, &hints, &ai);
if(n != 0)
{
#ifdef WIN32
#ifdef _WIN32
fprintf(stderr, "getaddrinfo() error : %d\n", n);
#else
fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n));
@ -155,6 +182,10 @@ int connecthostport(const char * host, unsigned short port)
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(s < 0)
continue;
if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) {
struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr;
addr6->sin6_scope_id = scope_id;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
timeout.tv_sec = 3;

View File

@ -1,17 +1,18 @@
/* $Id: connecthostport.h,v 1.1 2010/04/04 23:21:03 nanard Exp $ */
/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
* Copyright (c) 2010 Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __CONNECTHOSTPORT_H__
#define __CONNECTHOSTPORT_H__
#ifndef CONNECTHOSTPORT_H_INCLUDED
#define CONNECTHOSTPORT_H_INCLUDED
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port);
int connecthostport(const char * host, unsigned short port,
unsigned int scope_id);
#endif

View File

@ -1,7 +1,7 @@
#ifndef __DECLSPEC_H__
#define __DECLSPEC_H__
#ifndef DECLSPEC_H_INCLUDED
#define DECLSPEC_H_INCLUDED
#if defined(WIN32) && !defined(STATICLIB)
#if defined(_WIN32) && !defined(STATICLIB)
#ifdef MINIUPNP_EXPORTS
#define LIBSPEC __declspec(dllexport)
#else

View File

@ -1,4 +1,4 @@
/* $Id: igd_desc_parse.c,v 1.11 2010/12/11 17:56:51 nanard Exp $ */
/* $Id: igd_desc_parse.c,v 1.14 2011/04/11 09:19:24 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
@ -46,6 +46,9 @@ void IGDendelt(void * d, const char * name, int l)
if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) {
memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1")) {
memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPConnection:1")
|| 0==strcmp(datas->tmp.servicetype,
@ -69,6 +72,8 @@ void IGDdata(void * d, const char * data, int l)
datas->level, datas->cureltname, l, data); */
if( !strcmp(datas->cureltname, "URLBase") )
dstmember = datas->urlbase;
else if( !strcmp(datas->cureltname, "presentationURL") )
dstmember = datas->presentationurl;
else if( !strcmp(datas->cureltname, "serviceType") )
dstmember = datas->tmp.servicetype;
else if( !strcmp(datas->cureltname, "controlURL") )
@ -109,6 +114,12 @@ void printIGD(struct IGDdatas * d)
printf(" controlURL = '%s'\n", d->second.controlurl);
printf(" eventSubURL = '%s'\n", d->second.eventsuburl);
printf(" SCPDURL = '%s'\n", d->second.scpdurl);
printf("WAN IPv6 Firewall Control :\n");
/*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/
printf(" servicetype = '%s'\n", d->IPv6FC.servicetype);
printf(" controlURL = '%s'\n", d->IPv6FC.controlurl);
printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl);
printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl);
}

View File

@ -1,4 +1,4 @@
/* $Id: igd_desc_parse.h,v 1.7 2010/04/05 20:36:59 nanard Exp $ */
/* $Id: igd_desc_parse.h,v 1.11 2012/10/16 16:49:02 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
@ -6,8 +6,8 @@
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef __IGD_DESC_PARSE_H__
#define __IGD_DESC_PARSE_H__
#ifndef IGD_DESC_PARSE_H_INCLUDED
#define IGD_DESC_PARSE_H_INCLUDED
/* Structure to store the result of the parsing of UPnP
* descriptions of Internet Gateway Devices */
@ -23,6 +23,7 @@ struct IGDdatas_service {
struct IGDdatas {
char cureltname[MINIUPNPC_URL_MAXSIZE];
char urlbase[MINIUPNPC_URL_MAXSIZE];
char presentationurl[MINIUPNPC_URL_MAXSIZE];
int level;
/*int state;*/
/* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
@ -32,6 +33,8 @@ struct IGDdatas {
struct IGDdatas_service first;
/* if both WANIPConnection and WANPPPConnection are present */
struct IGDdatas_service second;
/* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */
struct IGDdatas_service IPv6FC;
/* tmp */
struct IGDdatas_service tmp;
};

View File

@ -1,7 +1,7 @@
/* $Id: minisoap.c,v 1.20 2010/12/11 17:56:51 nanard Exp $ */
/* $Id: minisoap.c,v 1.22 2012/01/21 13:30:31 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2009 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
*
@ -9,7 +9,7 @@
*/
#include <stdio.h>
#include <string.h>
#ifdef WIN32
#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
#define snprintf _snprintf
@ -24,7 +24,7 @@
/* only for malloc */
#include <stdlib.h>
#ifdef WIN32
#ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
@ -57,7 +57,7 @@ httpWrite(int fd, const char * body, int bodysize,
/* disable send on the socket */
/* draytek routers dont seems to like that... */
#if 0
#ifdef WIN32
#ifdef _WIN32
if(shutdown(fd, SD_SEND)<0) {
#else
if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/
@ -112,7 +112,8 @@ int soapPostSubmit(int fd,
printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n",
url, httpversion, host, portstr);
printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize);
/*printf("%s", headerbuf);*/
printf("Headers :\n%s", headerbuf);
printf("Body :\n%s\n", body);
#endif
return httpWrite(fd, body, bodysize, headerbuf, headerssize);
}

View File

@ -1,11 +1,11 @@
/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */
/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#ifndef __MINISOAP_H__
#define __MINISOAP_H__
#ifndef MINISOAP_H_INCLUDED
#define MINISOAP_H_INCLUDED
/*int httpWrite(int, const char *, int, const char *);*/
int soapPostSubmit(int, const char *, const char *, unsigned short,

View File

@ -1,18 +1,18 @@
/* $Id: minissdpc.c,v 1.14 2010/11/25 09:57:25 nanard Exp $ */
/* $Id: minissdpc.c,v 1.16 2012/03/05 19:42:46 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
* copyright (c) 2005-2009 Thomas Bernard
* copyright (c) 2005-2012 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
/*#include <syslog.h>*/
#include <lib/framework/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#if defined(WIN32) || defined(__amigaos__) || defined(__amigaos4__)
#ifdef WIN32
#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
@ -41,6 +41,10 @@ struct sockaddr_un {
#include "codelength.h"
#if defined(_MSC_VER)
typedef SSIZE_T ssize_t;
#endif
struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
{
@ -120,7 +124,7 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
p += stsize;
tmp->buffer[urlsize+1+stsize] = '\0';
devlist = tmp;
/* added for compatibility with recent versions of MiniSSDPd
/* added for compatibility with recent versions of MiniSSDPd
* >= 2007/12/19 */
DECODELENGTH(usnsize, p);
p += usnsize;

View File

@ -1,12 +1,12 @@
/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */
/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2005-2007 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __MINISSDPC_H__
#define __MINISSDPC_H__
#ifndef MINISSDPC_H_INCLUDED
#define MINISSDPC_H_INCLUDED
struct UPNPDev *
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath);

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,26 @@
/* $Id: miniupnpc.h,v 1.19 2009/10/10 19:15:35 nanard Exp $ */
/* $Id: miniupnpc.h,v 1.32 2013/02/06 14:44:42 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
* Copyright (c) 2005-2006 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __MINIUPNPC_H__
#define __MINIUPNPC_H__
#ifndef MINIUPNPC_H_INCLUDED
#define MINIUPNPC_H_INCLUDED
#include "declspec.h"
#include "igd_desc_parse.h"
/* error codes : */
#define UPNPDISCOVER_SUCCESS (0)
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
#define MINIUPNPC_VERSION "1.8.20131007"
#define MINIUPNPC_API_VERSION 9
#ifdef __cplusplus
extern "C" {
#endif
@ -18,14 +28,16 @@ extern "C" {
/* Structures definitions : */
struct UPNParg { const char * elt; const char * val; };
int simpleUPnPcommand(int, const char *, const char *,
const char *, struct UPNParg *,
char *, int *);
char *
simpleUPnPcommand(int, const char *, const char *,
const char *, struct UPNParg *,
int *);
struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
unsigned int scope_id;
char buffer[2];
};
@ -42,8 +54,11 @@ struct UPNPDev {
* multicast interface for sending SSDP discover packets.
* If sameport is not null, SSDP packets will be sent from the source port
* 1900 (same as destination port) otherwise system assign a source port. */
LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport);
LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport,
int ipv6,
int * error);
/* freeUPNPDevlist()
* free list returned by upnpDiscover() */
LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
@ -57,11 +72,14 @@ LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
* controlURL: controlURL of the WANIPConnection
* ipcondescURL: url of the description of the WANIPConnection
* controlURL_CIF: controlURL of the WANCommonInterfaceConfig
* controlURL_6FC: controlURL of the WANIPv6FirewallControl
*/
struct UPNPUrls {
char * controlURL;
char * ipcondescURL;
char * controlURL_CIF;
char * controlURL_6FC;
char * rootdescURL;
};
/* UPNP_GetValidIGD() :
@ -93,14 +111,12 @@ UPNP_GetIGDFromUrl(const char * rootdescurl,
struct IGDdatas * data,
char * lanaddr, int lanaddrlen);
LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);
LIBSPEC void
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
const char *, unsigned int);
LIBSPEC void FreeUPNPUrls(struct UPNPUrls *);
/* Reads data from the specified socket.
* Returns the number of bytes read if successful, zero if no bytes were
* read or if we timed out. Returns negative if there was an error. */
int ReceiveData(int socket, char * data, int length, int timeout);
LIBSPEC void
FreeUPNPUrls(struct UPNPUrls *);
/* return 0 or 1 */
LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);

View File

@ -1,26 +1,7 @@
/* $Id: miniupnpcstrings.h.in,v 1.2 2009/10/30 09:18:18 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2005-2009 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __MINIUPNPCSTRINGS_H__
#define __MINIUPNPCSTRINGS_H__
#ifndef MINIUPNPCSTRINGS_H_INCLUDED
#define MINIUPNPCSTRINGS_H_INCLUDED
#include "lib/framework/wzglobal.h"
#if defined(WZ_OS_WIN32)
#define OS_STRING "Windows"
#elif defined (WZ_OS_MAC)
#define OS_STRING "Mac OS"
#elif defined(WZ_OS_LINUX)
#define OS_STRING "Linux"
#else
#define OS_STRING "Other/unknown"
#endif
#define MINIUPNPC_VERSION_STRING "1.5"
#define MINIUPNPC_VERSION_STRING "1.7"
#endif

19
3rdparty/miniupnpc/miniupnpctypes.h vendored Normal file
View File

@ -0,0 +1,19 @@
/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org
* Author : Thomas Bernard
* Copyright (c) 2011 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef MINIUPNPCTYPES_H_INCLUDED
#define MINIUPNPCTYPES_H_INCLUDED
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
#define UNSIGNED_INTEGER unsigned long long
#define STRTOUI strtoull
#else
#define UNSIGNED_INTEGER unsigned int
#define STRTOUI strtoul
#endif
#endif

View File

@ -1,16 +1,16 @@
/* $Id: miniwget.c,v 1.41 2010/12/12 23:52:02 nanard Exp $ */
/* $Id: miniwget.c,v 1.60 2013/10/07 10:03:16 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* Copyright (c) 2005-2013 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "miniupnpc.h"
#ifdef WIN32
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
@ -18,12 +18,14 @@
#define MIN(x,y) (((x)<(y))?(x):(y))
#define snprintf _snprintf
#define socklen_t int
#ifndef strncasecmp
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define strncasecmp _memicmp
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#define strncasecmp memicmp
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#else /* #ifdef WIN32 */
#endif /* #ifndef strncasecmp */
#else /* #ifdef _WIN32 */
#include <unistd.h>
#include <sys/param.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
@ -32,13 +34,15 @@
#include <sys/select.h>
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#define closesocket close
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
#endif /* #else WIN32 */
#endif /* #else _WIN32 */
#if defined(__sun) || defined(sun)
#define MIN(x,y) (((x)<(y))?(x):(y))
#endif
@ -46,35 +50,46 @@
#include "miniupnpcstrings.h"
#include "miniwget.h"
#include "connecthostport.h"
#include "receivedata.h"
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/*
* Read a HTTP response from a socket.
* Process Content-Length and Transfer-encoding headers.
* return a pointer to the content buffer, which length is saved
* to the length parameter.
*/
void *
getHTTPResponse(int s, int * size)
{
char buf[2048];
int n;
int headers = 1;
int endofheaders = 0;
int chunked = 0;
int content_length = -1;
unsigned int chunksize = 0;
unsigned int bytestocopy = 0;
/* buffers : */
char * header_buf;
int header_buf_len = 2048;
int header_buf_used = 0;
unsigned int header_buf_len = 2048;
unsigned int header_buf_used = 0;
char * content_buf;
int content_buf_len = 2048;
int content_buf_used = 0;
unsigned int content_buf_len = 2048;
unsigned int content_buf_used = 0;
char chunksize_buf[32];
unsigned int chunksize_buf_index;
header_buf = malloc(header_buf_len);
content_buf = malloc(content_buf_len);
chunksize_buf[0] = '\0';
chunksize_buf_index = 0;
while((n = ReceiveData(s, buf, 2048, 5000)) > 0)
while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0)
{
if(headers)
if(endofheaders == 0)
{
int i;
int linestart=0;
@ -86,17 +101,43 @@ getHTTPResponse(int s, int * size)
}
memcpy(header_buf + header_buf_used, buf, n);
header_buf_used += n;
for(i = 0; i < (header_buf_used-3); i++) {
/* search for CR LF CR LF (end of headers)
* recognize also LF LF */
i = 0;
while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
if(header_buf[i] == '\r') {
i++;
if(header_buf[i] == '\n') {
i++;
if(i < (int)header_buf_used && header_buf[i] == '\r') {
i++;
if(i < (int)header_buf_used && header_buf[i] == '\n') {
endofheaders = i+1;
}
}
}
} else if(header_buf[i] == '\n') {
i++;
if(header_buf[i] == '\n') {
endofheaders = i+1;
}
}
i++;
}
if(endofheaders == 0)
continue;
/* parse header lines */
for(i = 0; i < endofheaders - 1; i++) {
if(colon <= linestart && header_buf[i]==':')
{
colon = i;
while(i < (n-3)
while(i < (endofheaders-1)
&& (header_buf[i+1] == ' ' || header_buf[i+1] == '\t'))
i++;
valuestart = i + 1;
}
/* detecting end of line */
else if(header_buf[i]=='\r' && header_buf[i+1]=='\n')
else if(header_buf[i]=='\r' || header_buf[i]=='\n')
{
if(colon > linestart && valuestart > colon)
{
@ -113,7 +154,7 @@ getHTTPResponse(int s, int * size)
#endif
}
else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
&& 0==strncasecmp(buf+valuestart, "chunked", 7))
&& 0==strncasecmp(header_buf+valuestart, "chunked", 7))
{
#ifdef DEBUG
printf("chunked transfer-encoding!\n");
@ -121,76 +162,19 @@ getHTTPResponse(int s, int * size)
chunked = 1;
}
}
linestart = i+2;
while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
i++;
linestart = i;
colon = linestart;
valuestart = 0;
}
/* searching for the end of the HTTP headers */
if(header_buf[i]=='\r' && header_buf[i+1]=='\n'
&& header_buf[i+2]=='\r' && header_buf[i+3]=='\n')
{
headers = 0; /* end */
i += 4;
if(i < header_buf_used)
{
if(chunked)
{
while(i<header_buf_used)
{
while(i<header_buf_used && isxdigit(header_buf[i]))
{
if(header_buf[i] >= '0' && header_buf[i] <= '9')
chunksize = (chunksize << 4) + (header_buf[i] - '0');
else
chunksize = (chunksize << 4) + ((header_buf[i] | 32) - 'a' + 10);
i++;
}
/* discarding chunk-extension */
while(i < header_buf_used && header_buf[i] != '\r') i++;
if(i < header_buf_used && header_buf[i] == '\r') i++;
if(i < header_buf_used && header_buf[i] == '\n') i++;
#ifdef DEBUG
printf("chunksize = %u (%x)\n", chunksize, chunksize);
#endif
if(chunksize == 0)
{
#ifdef DEBUG
printf("end of HTTP content !\n");
#endif
goto end_of_stream;
}
bytestocopy = ((int)chunksize < header_buf_used - i)?chunksize:(header_buf_used - i);
#ifdef DEBUG
printf("chunksize=%u bytestocopy=%u (i=%d header_buf_used=%d)\n",
chunksize, bytestocopy, i, header_buf_used);
#endif
if(content_buf_len < (int)(content_buf_used + bytestocopy))
{
content_buf = realloc(content_buf, content_buf_used + bytestocopy);
content_buf_len = content_buf_used + bytestocopy;
}
memcpy(content_buf + content_buf_used, header_buf + i, bytestocopy);
content_buf_used += bytestocopy;
chunksize -= bytestocopy;
i += bytestocopy;
}
}
else
{
if(content_buf_len < header_buf_used - i)
{
content_buf = realloc(content_buf, header_buf_used - i);
content_buf_len = header_buf_used - i;
}
memcpy(content_buf, header_buf + i, header_buf_used - i);
content_buf_used = header_buf_used - i;
i = header_buf_used;
}
}
}
}
/* copy the remaining of the received data back to buf */
n = header_buf_used - endofheaders;
memcpy(buf, header_buf + endofheaders, n);
/* if(headers) */
}
else
if(endofheaders)
{
/* content */
if(chunked)
@ -201,19 +185,37 @@ getHTTPResponse(int s, int * size)
if(chunksize == 0)
{
/* reading chunk size */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') i++;
while(i<n && isxdigit(buf[i]))
if(chunksize_buf_index == 0) {
/* skipping any leading CR LF */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') i++;
}
while(i<n && isxdigit(buf[i])
&& chunksize_buf_index < (sizeof(chunksize_buf)-1))
{
if(buf[i] >= '0' && buf[i] <= '9')
chunksize = (chunksize << 4) + (buf[i] - '0');
else
chunksize = (chunksize << 4) + ((buf[i] | 32) - 'a' + 10);
chunksize_buf[chunksize_buf_index++] = buf[i];
chunksize_buf[chunksize_buf_index] = '\0';
i++;
}
while(i<n && buf[i] != '\r') i++; /* discarding chunk-extension */
while(i<n && buf[i] != '\r' && buf[i] != '\n')
i++; /* discarding chunk-extension */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') i++;
if(i<n && buf[i] == '\n') {
unsigned int j;
for(j = 0; j < chunksize_buf_index; j++) {
if(chunksize_buf[j] >= '0'
&& chunksize_buf[j] <= '9')
chunksize = (chunksize << 4) + (chunksize_buf[j] - '0');
else
chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10);
}
chunksize_buf[0] = '\0';
chunksize_buf_index = 0;
i++;
} else {
/* not finished to get chunksize */
continue;
}
#ifdef DEBUG
printf("chunksize = %u (%x)\n", chunksize, chunksize);
#endif
@ -226,12 +228,16 @@ getHTTPResponse(int s, int * size)
goto end_of_stream;
}
}
bytestocopy = ((int)chunksize < n - i)?chunksize:(n - i);
if((int)(content_buf_used + bytestocopy) > content_buf_len)
bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
if((content_buf_used + bytestocopy) > content_buf_len)
{
content_buf = (char *)realloc((void *)content_buf,
content_buf_used + bytestocopy);
content_buf_len = content_buf_used + bytestocopy;
if(content_length >= (int)(content_buf_used + bytestocopy)) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + bytestocopy;
}
content_buf = (char *)realloc((void *)content_buf,
content_buf_len);
}
memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
content_buf_used += bytestocopy;
@ -241,17 +247,28 @@ getHTTPResponse(int s, int * size)
}
else
{
/* not chunked */
if(content_length > 0
&& (int)(content_buf_used + n) > content_length) {
/* skipping additional bytes */
n = content_length - content_buf_used;
}
if(content_buf_used + n > content_buf_len)
{
content_buf = (char *)realloc((void *)content_buf,
content_buf_used + n);
content_buf_len = content_buf_used + n;
if(content_length >= (int)(content_buf_used + n)) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + n;
}
content_buf = (char *)realloc((void *)content_buf,
content_buf_len);
}
memcpy(content_buf + content_buf_used, buf, n);
content_buf_used += n;
}
}
if(content_length > 0 && content_buf_used >= content_length)
/* use the Content-Length header value if available */
if(content_length > 0 && (int)content_buf_used >= content_length)
{
#ifdef DEBUG
printf("End of HTTP content\n");
@ -274,29 +291,31 @@ end_of_stream:
* do all the work.
* Return NULL if something failed. */
static void *
miniwget3(const char * url, const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len, const char * httpversion)
miniwget3(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
const char * httpversion, unsigned int scope_id)
{
char buf[2048];
int s;
int n;
int len;
int sent;
void * content;
*size = 0;
s = connecthostport(host, port);
s = connecthostport(host, port, scope_id);
if(s < 0)
return NULL;
/* get address for caller ! */
if(addr_str)
{
struct sockaddr saddr;
struct sockaddr_storage saddr;
socklen_t saddrlen;
saddrlen = sizeof(saddr);
if(getsockname(s, &saddr, &saddrlen) < 0)
if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
{
perror("getsockname");
}
@ -310,15 +329,28 @@ miniwget3(const char * url, const char * host,
{
printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
}*/
/* the following code is only compatible with ip v4 addresses */
strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len);
#else
/*inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);*/
n = getnameinfo(&saddr, saddrlen,
#if 0
if(saddr.sa_family == AF_INET6) {
inet_ntop(AF_INET6,
&(((struct sockaddr_in6 *)&saddr)->sin6_addr),
addr_str, addr_str_len);
} else {
inet_ntop(AF_INET,
&(((struct sockaddr_in *)&saddr)->sin_addr),
addr_str, addr_str_len);
}
#endif
/* getnameinfo return ip v6 address with the scope identifier
* such as : 2a01:e35:8b2b:7330::%4281128194 */
n = getnameinfo((const struct sockaddr *)&saddr, saddrlen,
addr_str, addr_str_len,
NULL, 0,
NI_NUMERICHOST | NI_NUMERICSERV);
if(n != 0) {
#ifdef WIN32
#ifdef _WIN32
fprintf(stderr, "getnameinfo() failed : %d\n", n);
#else
fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
@ -355,30 +387,37 @@ miniwget3(const char * url, const char * host,
sent += n;
}
}
return getHTTPResponse(s, size);
content = getHTTPResponse(s, size);
closesocket(s);
return content;
}
/* miniwget2() :
* Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
static void *
miniwget2(const char * url, const char * host,
miniwget2(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len)
int * size, char * addr_str, int addr_str_len,
unsigned int scope_id)
{
char * respbuffer;
respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.1");
/*
respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.0");
#if 1
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1", scope_id);
#else
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.0", scope_id);
if (*size == 0)
{
#ifdef DEBUG
printf("Retrying with HTTP/1.1\n");
#endif
free(respbuffer);
respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.1");
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1", scope_id);
}
*/
#endif
return respbuffer;
}
@ -390,12 +429,15 @@ miniwget2(const char * url, const char * host,
* url : source string not modified
* hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
* port : port (destination)
* path : pointer to the path part of the URL
* path : pointer to the path part of the URL
*
* Return values :
* 0 - Failure
* 1 - Success */
int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
int
parseURL(const char * url,
char * hostname, unsigned short * port,
char * * path, unsigned int * scope_id)
{
char * p1, *p2, *p3;
if(!url)
@ -407,11 +449,75 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
if( (url[0]!='h') || (url[1]!='t')
||(url[2]!='t') || (url[3]!='p'))
return 0;
memset(hostname, 0, MAXHOSTNAMELEN + 1);
if(*p1 == '[')
{
/* IP v6 : http://[2a00:1450:8002::6a]/path/abc */
char * scope;
scope = strchr(p1, '%');
p2 = strchr(p1, ']');
if(p2 && scope && scope < p2 && scope_id) {
/* parse scope */
#ifdef IF_NAMESIZE
char tmp[IF_NAMESIZE];
int l;
scope++;
/* "%25" is just '%' in URL encoding */
if(scope[0] == '2' && scope[1] == '5')
scope += 2; /* skip "25" */
l = p2 - scope;
if(l >= IF_NAMESIZE)
l = IF_NAMESIZE - 1;
memcpy(tmp, scope, l);
tmp[l] = '\0';
*scope_id = if_nametoindex(tmp);
if(*scope_id == 0) {
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
}
#else
/* under windows, scope is numerical */
char tmp[8];
int l;
scope++;
/* "%25" is just '%' in URL encoding */
if(scope[0] == '2' && scope[1] == '5')
scope += 2; /* skip "25" */
l = p2 - scope;
if(l >= sizeof(tmp))
l = sizeof(tmp) - 1;
memcpy(tmp, scope, l);
tmp[l] = '\0';
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
#endif
}
p3 = strchr(p1, '/');
if(p2 && p3)
{
p2++;
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
if(*p2 == ':')
{
*port = 0;
p2++;
while( (*p2 >= '0') && (*p2 <= '9'))
{
*port *= 10;
*port += (unsigned short)(*p2 - '0');
p2++;
}
}
else
{
*port = 80;
}
*path = p3;
return 1;
}
}
p2 = strchr(p1, ':');
p3 = strchr(p1, '/');
if(!p3)
return 0;
memset(hostname, 0, MAXHOSTNAMELEN + 1);
if(!p2 || (p2>p3))
{
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
@ -433,29 +539,40 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
return 1;
}
void * miniwget(const char * url, int * size)
void *
miniwget(const char * url, int * size, unsigned int scope_id)
{
unsigned short port;
char * path;
/* protocol://host:port/chemin */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(!parseURL(url, hostname, &port, &path))
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
return miniwget2(url, hostname, port, path, size, 0, 0);
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(hostname, port, path, size, 0, 0, scope_id);
}
void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
void *
miniwget_getaddr(const char * url, int * size,
char * addr, int addrlen, unsigned int scope_id)
{
unsigned short port;
char * path;
/* protocol://host:port/chemin */
/* protocol://host:port/path */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(addr)
addr[0] = '\0';
if(!parseURL(url, hostname, &port, &path))
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
return miniwget2(url, hostname, port, path, size, addr, addrlen);
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
}

View File

@ -1,12 +1,12 @@
/* $Id: miniwget.h,v 1.6 2010/12/09 16:11:33 nanard Exp $ */
/* $Id: miniwget.h,v 1.8 2012/09/27 15:42:10 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef __MINIWGET_H__
#define __MINIWGET_H__
#ifndef MINIWGET_H_INCLUDED
#define MINIWGET_H_INCLUDED
#include "declspec.h"
@ -16,11 +16,11 @@ extern "C" {
LIBSPEC void * getHTTPResponse(int s, int * size);
LIBSPEC void * miniwget(const char *, int *);
LIBSPEC void * miniwget(const char *, int *, unsigned int);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int);
int parseURL(const char *, char *, unsigned short *, char * *);
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);
#ifdef __cplusplus
}

View File

@ -1,10 +1,10 @@
/* $Id: minixml.c,v 1.7 2009/10/10 19:15:35 nanard Exp $ */
/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */
/* minixml.c : the minimum size a xml parser can be ! */
/* Project : miniupnp
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
Copyright (c) 2005-2009, Thomas BERNARD
Copyright (c) 2005-2011, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -30,6 +30,7 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "minixml.h"
/* parseatt : used to parse the argument list
@ -142,19 +143,43 @@ static void parseelt(struct xmlparser * p)
if (p->xml >= p->xmlend)
return;
while( IS_WHITE_SPACE(*p->xml) )
{
p->xml++;
if (p->xml >= p->xmlend)
return;
}
while(*p->xml!='<')
{
i++; p->xml++;
if (p->xml >= p->xmlend)
return;
}
if(i>0 && p->datafunc)
p->datafunc(p->data, data, i);
if(memcmp(p->xml, "<![CDATA[", 9) == 0)
{
/* CDATA handling */
p->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 == '/')

View File

@ -1,4 +1,4 @@
/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */
/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */
/* minimal xml parser
*
* Project : miniupnp
@ -8,8 +8,8 @@
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
#ifndef __MINIXML_H__
#define __MINIXML_H__
#ifndef MINIXML_H_INCLUDED
#define MINIXML_H_INCLUDED
#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
/* if a callback function pointer is set to NULL,

159
3rdparty/miniupnpc/portlistingparse.c vendored Normal file
View File

@ -0,0 +1,159 @@
/* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <string.h>
#include <stdlib.h>
#include "portlistingparse.h"
#include "minixml.h"
/* list of the elements */
static const struct {
const portMappingElt code;
const char * const str;
} elements[] = {
{ PortMappingEntry, "PortMappingEntry"},
{ NewRemoteHost, "NewRemoteHost"},
{ NewExternalPort, "NewExternalPort"},
{ NewProtocol, "NewProtocol"},
{ NewInternalPort, "NewInternalPort"},
{ NewInternalClient, "NewInternalClient"},
{ NewEnabled, "NewEnabled"},
{ NewDescription, "NewDescription"},
{ NewLeaseTime, "NewLeaseTime"},
{ PortMappingEltNone, NULL}
};
/* Helper function */
static UNSIGNED_INTEGER
atoui(const char * p, int l)
{
UNSIGNED_INTEGER r = 0;
while(l > 0 && *p)
{
if(*p >= '0' && *p <= '9')
r = r*10 + (*p - '0');
else
break;
p++;
l--;
}
return r;
}
/* Start element handler */
static void
startelt(void * d, const char * name, int l)
{
int i;
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
pdata->curelt = PortMappingEltNone;
for(i = 0; elements[i].str; i++)
{
if(memcmp(name, elements[i].str, l) == 0)
{
pdata->curelt = elements[i].code;
break;
}
}
if(pdata->curelt == PortMappingEntry)
{
struct PortMapping * pm;
pm = calloc(1, sizeof(struct PortMapping));
LIST_INSERT_HEAD( &(pdata->head), pm, entries);
}
}
/* End element handler */
static void
endelt(void * d, const char * name, int l)
{
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
(void)name;
(void)l;
pdata->curelt = PortMappingEltNone;
}
/* Data handler */
static void
data(void * d, const char * data, int l)
{
struct PortMapping * pm;
struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
pm = pdata->head.lh_first;
if(!pm)
return;
if(l > 63)
l = 63;
switch(pdata->curelt)
{
case NewRemoteHost:
memcpy(pm->remoteHost, data, l);
pm->remoteHost[l] = '\0';
break;
case NewExternalPort:
pm->externalPort = (unsigned short)atoui(data, l);
break;
case NewProtocol:
if(l > 3)
l = 3;
memcpy(pm->protocol, data, l);
pm->protocol[l] = '\0';
break;
case NewInternalPort:
pm->internalPort = (unsigned short)atoui(data, l);
break;
case NewInternalClient:
memcpy(pm->internalClient, data, l);
pm->internalClient[l] = '\0';
break;
case NewEnabled:
pm->enabled = (unsigned char)atoui(data, l);
break;
case NewDescription:
memcpy(pm->description, data, l);
pm->description[l] = '\0';
break;
case NewLeaseTime:
pm->leaseTime = atoui(data, l);
break;
default:
break;
}
}
/* Parse the PortMappingList XML document for IGD version 2
*/
void
ParsePortListing(const char * buffer, int bufsize,
struct PortMappingParserData * pdata)
{
struct xmlparser parser;
memset(pdata, 0, sizeof(struct PortMappingParserData));
LIST_INIT(&(pdata->head));
/* init xmlparser */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
parser.data = pdata;
parser.starteltfunc = startelt;
parser.endeltfunc = endelt;
parser.datafunc = data;
parser.attfunc = 0;
parsexml(&parser);
}
void
FreePortListing(struct PortMappingParserData * pdata)
{
struct PortMapping * pm;
while((pm = pdata->head.lh_first) != NULL)
{
LIST_REMOVE(pm, entries);
free(pm);
}
}

71
3rdparty/miniupnpc/portlistingparse.h vendored Normal file
View File

@ -0,0 +1,71 @@
/* $Id: portlistingparse.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2011-2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef PORTLISTINGPARSE_H_INCLUDED
#define PORTLISTINGPARSE_H_INCLUDED
#include "declspec.h"
/* for the definition of UNSIGNED_INTEGER */
#include "miniupnpctypes.h"
#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* sample of PortMappingEntry :
<p:PortMappingEntry>
<p:NewRemoteHost>202.233.2.1</p:NewRemoteHost>
<p:NewExternalPort>2345</p:NewExternalPort>
<p:NewProtocol>TCP</p:NewProtocol>
<p:NewInternalPort>2345</p:NewInternalPort>
<p:NewInternalClient>192.168.1.137</p:NewInternalClient>
<p:NewEnabled>1</p:NewEnabled>
<p:NewDescription>dooom</p:NewDescription>
<p:NewLeaseTime>345</p:NewLeaseTime>
</p:PortMappingEntry>
*/
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

109
3rdparty/miniupnpc/receivedata.c vendored Normal file
View File

@ -0,0 +1,109 @@
/* $Id: receivedata.c,v 1.5 2013/10/07 09:48:36 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2011-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <unistd.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
#define socklen_t int
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/select.h>
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
#include <sys/socket.h>
#include <netinet/in.h>
#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
#endif
#include <errno.h>
#define MINIUPNPC_IGNORE_EINTR
#endif
#ifdef _WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
#include "receivedata.h"
int
receivedata(int socket,
char * data, int length,
int timeout, unsigned int * scope_id)
{
#if MINIUPNPC_GET_SRC_ADDR
#ifdef DEBUG
/* to shut up valgrind about uninit value */
struct sockaddr_storage src_addr = {0};
#else
struct sockaddr_storage src_addr;
#endif
socklen_t src_addr_len = sizeof(src_addr);
#endif
int n;
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* using poll */
struct pollfd fds[1]; /* for the poll */
#ifdef MINIUPNPC_IGNORE_EINTR
do {
#endif
fds[0].fd = socket;
fds[0].events = POLLIN;
n = poll(fds, 1, timeout);
#ifdef MINIUPNPC_IGNORE_EINTR
} while(n < 0 && errno == EINTR);
#endif
if(n < 0) {
PRINT_SOCKET_ERROR("poll");
return -1;
} else if(n == 0) {
/* timeout */
return 0;
}
#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
/* using select under _WIN32 and amigaos */
fd_set socketSet;
TIMEVAL timeval;
FD_ZERO(&socketSet);
FD_SET(socket, &socketSet);
timeval.tv_sec = timeout / 1000;
timeval.tv_usec = (timeout % 1000) * 1000;
n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
if(n < 0) {
PRINT_SOCKET_ERROR("select");
return -1;
} else if(n == 0) {
return 0;
}
#endif
#if MINIUPNPC_GET_SRC_ADDR
n = recvfrom(socket, data, length, 0,
(struct sockaddr *)&src_addr, &src_addr_len);
#else
n = recv(socket, data, length, 0);
#endif
if(n<0) {
PRINT_SOCKET_ERROR("recv");
}
#if MINIUPNPC_GET_SRC_ADDR
if (src_addr.ss_family == AF_INET6) {
const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr;
#ifdef DEBUG
printf("scope_id=%u\n", src_addr6->sin6_scope_id);
#endif
if(scope_id)
*scope_id = src_addr6->sin6_scope_id;
}
#endif
return n;
}

19
3rdparty/miniupnpc/receivedata.h vendored Normal file
View File

@ -0,0 +1,19 @@
/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
* Copyright (c) 2011-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef RECEIVEDATA_H_INCLUDED
#define RECEIVEDATA_H_INCLUDED
/* Reads data from the specified socket.
* Returns the number of bytes read if successful, zero if no bytes were
* read or if we timed out. Returns negative if there was an error. */
int receivedata(int socket,
char * data, int length,
int timeout, unsigned int * scope_id);
#endif

View File

@ -1,7 +1,7 @@
/* $Id: upnpcommands.c,v 1.26 2010/06/09 10:59:09 nanard Exp $ */
/* $Id: upnpcommands.c,v 1.40 2012/06/23 22:36:35 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -10,6 +10,7 @@
#include <string.h>
#include "upnpcommands.h"
#include "miniupnpc.h"
#include "portlistingparse.h"
static UNSIGNED_INTEGER
my_atoui(const char * s)
@ -24,15 +25,17 @@ UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
unsigned int r = 0;
char * p;
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalBytesSent", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");
r = my_atoui(p);
ClearNameValueList(&pdata);
@ -46,15 +49,17 @@ UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
unsigned int r = 0;
char * p;
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalBytesReceived", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");
r = my_atoui(p);
ClearNameValueList(&pdata);
@ -68,15 +73,17 @@ UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
unsigned int r = 0;
char * p;
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalPacketsSent", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");
r = my_atoui(p);
ClearNameValueList(&pdata);
@ -90,15 +97,17 @@ UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
unsigned int r = 0;
char * p;
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetTotalPacketsReceived", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");
r = my_atoui(p);
ClearNameValueList(&pdata);
@ -110,13 +119,13 @@ UPNP_GetTotalPacketsReceived(const char * controlURL,
LIBSPEC int
UPNP_GetStatusInfo(const char * controlURL,
const char * servicetype,
char * status,
char * status,
unsigned int * uptime,
char * lastconnerror)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
char * p;
char * up;
char * err;
@ -125,11 +134,13 @@ UPNP_GetStatusInfo(const char * controlURL,
if(!status && !uptime)
return UPNPCOMMAND_INVALID_ARGS;
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetStatusInfo", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
free(buffer); buffer = NULL;
up = GetValueFromNameValueList(&pdata, "NewUptime");
p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");
err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");
@ -176,19 +187,20 @@ UPNP_GetConnectionTypeInfo(const char * controlURL,
char * connectionType)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!connectionType)
return UPNPCOMMAND_INVALID_ARGS;
if(simpleUPnPcommand(-1, controlURL, servicetype,
"GetConnectionTypeInfo", 0, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetConnectionTypeInfo", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewConnectionType");
/*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
/* PossibleConnectionTypes will have several values.... */
@ -209,18 +221,18 @@ UPNP_GetConnectionTypeInfo(const char * controlURL,
/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
* Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
* One of the values can be null
* Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
* One of the values can be null
* Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
* We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
LIBSPEC int
UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
const char * servicetype,
unsigned int * bitrateDown,
unsigned int* bitrateUp)
unsigned int * bitrateUp)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
char * down;
char * up;
@ -230,19 +242,20 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
return UPNPCOMMAND_INVALID_ARGS;
/* shouldn't we use GetCommonLinkProperties ? */
if(simpleUPnPcommand(-1, controlURL, servicetype,
"GetCommonLinkProperties", 0, buffer, &bufsize) < 0) {
/*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize);*/
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetCommonLinkProperties", 0, &bufsize))) {
/*"GetLinkLayerMaxBitRates", 0, &bufsize);*/
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
/*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
/*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/
down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");
up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate");
/*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/
/*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus");*/
/*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/
if(down && up)
ret = UPNPCOMMAND_SUCCESS;
@ -272,7 +285,7 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
* if the third arg is not null the value is copied to it.
* at least 16 bytes must be available
*
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR Either an UPnP error code or an unknown error.
@ -286,19 +299,21 @@ UPNP_GetExternalIPAddress(const char * controlURL,
char * extIpAdd)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!extIpAdd || !controlURL || !servicetype)
return UPNPCOMMAND_INVALID_ARGS;
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetExternalIPAddress", 0, &bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
/*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");
if(p) {
@ -325,11 +340,12 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost)
const char * remoteHost,
const char * leaseDuration)
{
struct UPNParg * AddPortMappingArgs;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
@ -353,8 +369,10 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
AddPortMappingArgs[6].elt = "NewPortMappingDescription";
AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
AddPortMappingArgs[7].elt = "NewLeaseDuration";
AddPortMappingArgs[7].val = "0";
if(simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize) < 0) {
AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0";
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddPortMapping", AddPortMappingArgs,
&bufsize))) {
free(AddPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
@ -362,6 +380,7 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
/*buffer[bufsize] = '\0';*/
/*puts(buffer);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
@ -382,8 +401,8 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
{
/*struct NameValueParserData pdata;*/
struct UPNParg * DeletePortMappingArgs;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
@ -398,14 +417,15 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
DeletePortMappingArgs[1].val = extPort;
DeletePortMappingArgs[2].elt = "NewProtocol";
DeletePortMappingArgs[2].val = proto;
if(simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMapping",
DeletePortMappingArgs, buffer, &bufsize) < 0 ) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMapping",
DeletePortMappingArgs, &bufsize))) {
free(DeletePortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
@ -433,8 +453,8 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
{
struct NameValueParserData pdata;
struct UPNParg * GetPortMappingArgs;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
char * p;
int r = UPNPCOMMAND_UNKNOWN_ERROR;
if(!index)
@ -444,13 +464,15 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
GetPortMappingArgs[0].elt = "NewPortMappingIndex";
GetPortMappingArgs[0].val = index;
if(simpleUPnPcommand(-1, controlURL, servicetype,
"GetGenericPortMappingEntry",
GetPortMappingArgs, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetGenericPortMappingEntry",
GetPortMappingArgs, &bufsize))) {
free(GetPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
if(p && rHost)
{
@ -517,17 +539,20 @@ UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
unsigned int * numEntries)
{
struct NameValueParserData pdata;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
char* p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetPortMappingNumberOfEntries", 0,
&bufsize))) {
return UPNPCOMMAND_HTTP_ERROR;
}
#ifdef DEBUG
DisplayNameValueList(buffer, bufsize);
#endif
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");
if(numEntries && p) {
@ -555,12 +580,15 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * extPort,
const char * proto,
char * intClient,
char * intPort)
char * intPort,
char * desc,
char * enabled,
char * leaseDuration)
{
struct NameValueParserData pdata;
struct UPNParg * GetPortMappingArgs;
char buffer[4096];
int bufsize = 4096;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
@ -569,18 +597,20 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
GetPortMappingArgs[0].elt = "NewRemoteHost";
/* TODO : add remote host ? */
GetPortMappingArgs[1].elt = "NewExternalPort";
GetPortMappingArgs[1].val = extPort;
GetPortMappingArgs[2].elt = "NewProtocol";
GetPortMappingArgs[2].val = proto;
if(simpleUPnPcommand(-1, controlURL, servicetype,
"GetSpecificPortMappingEntry",
GetPortMappingArgs, buffer, &bufsize) < 0) {
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetSpecificPortMappingEntry",
GetPortMappingArgs, &bufsize))) {
free(GetPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "NewInternalClient");
if(p) {
@ -597,6 +627,25 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
} else
intPort[0] = '\0';
p = GetValueFromNameValueList(&pdata, "NewEnabled");
if(p && enabled) {
strncpy(enabled, p, 4);
enabled[3] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
if(p && desc) {
strncpy(desc, p, 80);
desc[79] = '\0';
}
p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
if(p && leaseDuration)
{
strncpy(leaseDuration, p, 16);
leaseDuration[15] = '\0';
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
@ -608,4 +657,441 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
return ret;
}
/* UPNP_GetListOfPortMappings()
*
* Possible UPNP Error codes :
* 606 Action not Authorized
* 730 PortMappingNotFound - no port mapping is found in the specified range.
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent.
*/
LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype,
const char * startPort,
const char * endPort,
const char * protocol,
const char * numberOfPorts,
struct PortMappingParserData * data)
{
struct NameValueParserData pdata;
struct UPNParg * GetListOfPortMappingsArgs;
const char * p;
char * buffer;
int bufsize;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!startPort || !endPort || !protocol)
return UPNPCOMMAND_INVALID_ARGS;
GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg));
GetListOfPortMappingsArgs[0].elt = "NewStartPort";
GetListOfPortMappingsArgs[0].val = startPort;
GetListOfPortMappingsArgs[1].elt = "NewEndPort";
GetListOfPortMappingsArgs[1].val = endPort;
GetListOfPortMappingsArgs[2].elt = "NewProtocol";
GetListOfPortMappingsArgs[2].val = protocol;
GetListOfPortMappingsArgs[3].elt = "NewManage";
GetListOfPortMappingsArgs[3].val = "1";
GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts";
GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000";
if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetListOfPortMappings",
GetListOfPortMappingsArgs, &bufsize))) {
free(GetListOfPortMappingsArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
free(GetListOfPortMappingsArgs);
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
/*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/
/*if(p) {
printf("NewPortListing : %s\n", p);
}*/
/*printf("NewPortListing(%d chars) : %s\n",
pdata.portListingLength, pdata.portListing);*/
if(pdata.portListing)
{
/*struct PortMapping * pm;
int i = 0;*/
ParsePortListing(pdata.portListing, pdata.portListingLength,
data);
ret = UPNPCOMMAND_SUCCESS;
/*
for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next)
{
printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n",
i, pm->protocol, pm->externalPort, pm->internalClient,
pm->internalPort,
pm->description, pm->remoteHost);
i++;
}
*/
/*FreePortListing(&data);*/
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p) {
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
/*printf("%.*s", bufsize, buffer);*/
return ret;
}
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype,
int * firewallEnabled,
int * inboundPinholeAllowed)
{
struct NameValueParserData pdata;
char * buffer;
int bufsize;
char * fe, *ipa, *p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!firewallEnabled && !inboundPinholeAllowed)
return UPNPCOMMAND_INVALID_ARGS;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetFirewallStatus", 0, &bufsize);
if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
fe = GetValueFromNameValueList(&pdata, "FirewallEnabled");
ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed");
if(ipa && fe)
ret = UPNPCOMMAND_SUCCESS;
if(fe)
*firewallEnabled = my_atoui(fe);
/*else
*firewallEnabled = 0;*/
if(ipa)
*inboundPinholeAllowed = my_atoui(ipa);
/*else
*inboundPinholeAllowed = 0;*/
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
return ret;
}
LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
int * opTimeout)
{
struct UPNParg * GetOutboundPinholeTimeoutArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
char * p;
int ret;
if(!intPort || !intClient || !proto || !remotePort || !remoteHost)
return UPNPCOMMAND_INVALID_ARGS;
GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg));
GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost";
GetOutboundPinholeTimeoutArgs[0].val = remoteHost;
GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort";
GetOutboundPinholeTimeoutArgs[1].val = remotePort;
GetOutboundPinholeTimeoutArgs[2].elt = "Protocol";
GetOutboundPinholeTimeoutArgs[2].val = proto;
GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort";
GetOutboundPinholeTimeoutArgs[3].val = intPort;
GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient";
GetOutboundPinholeTimeoutArgs[4].val = intClient;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
else
{
ret = UPNPCOMMAND_SUCCESS;
p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout");
if(p)
*opTimeout = my_atoui(p);
}
ClearNameValueList(&pdata);
free(GetOutboundPinholeTimeoutArgs);
return ret;
}
LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
const char * leaseTime,
char * uniqueID)
{
struct UPNParg * AddPinholeArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
char * p;
int ret;
if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime)
return UPNPCOMMAND_INVALID_ARGS;
AddPinholeArgs = calloc(7, sizeof(struct UPNParg));
/* RemoteHost can be wilcarded */
if(strncmp(remoteHost, "empty", 5)==0)
{
AddPinholeArgs[0].elt = "RemoteHost";
AddPinholeArgs[0].val = "";
}
else
{
AddPinholeArgs[0].elt = "RemoteHost";
AddPinholeArgs[0].val = remoteHost;
}
AddPinholeArgs[1].elt = "RemotePort";
AddPinholeArgs[1].val = remotePort;
AddPinholeArgs[2].elt = "Protocol";
AddPinholeArgs[2].val = proto;
AddPinholeArgs[3].elt = "InternalPort";
AddPinholeArgs[3].val = intPort;
if(strncmp(intClient, "empty", 5)==0)
{
AddPinholeArgs[4].elt = "InternalClient";
AddPinholeArgs[4].val = "";
}
else
{
AddPinholeArgs[4].elt = "InternalClient";
AddPinholeArgs[4].val = intClient;
}
AddPinholeArgs[5].elt = "LeaseTime";
AddPinholeArgs[5].val = leaseTime;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddPinhole", AddPinholeArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "UniqueID");
if(p)
{
strncpy(uniqueID, p, 8);
uniqueID[7] = '\0';
}
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
/*printf("AddPortMapping errorCode = '%s'\n", resVal);*/
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
else
{
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(AddPinholeArgs);
return ret;
}
LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID,
const char * leaseTime)
{
struct UPNParg * UpdatePinholeArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!uniqueID || !leaseTime)
return UPNPCOMMAND_INVALID_ARGS;
UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg));
UpdatePinholeArgs[0].elt = "UniqueID";
UpdatePinholeArgs[0].val = uniqueID;
UpdatePinholeArgs[1].elt = "NewLeaseTime";
UpdatePinholeArgs[1].val = leaseTime;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"UpdatePinhole", UpdatePinholeArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
else
{
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(UpdatePinholeArgs);
return ret;
}
LIBSPEC int
UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID)
{
/*struct NameValueParserData pdata;*/
struct UPNParg * DeletePinholeArgs;
char * buffer;
int bufsize;
struct NameValueParserData pdata;
const char * resVal;
int ret;
if(!uniqueID)
return UPNPCOMMAND_INVALID_ARGS;
DeletePinholeArgs = calloc(2, sizeof(struct UPNParg));
DeletePinholeArgs[0].elt = "UniqueID";
DeletePinholeArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePinhole", DeletePinholeArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
resVal = GetValueFromNameValueList(&pdata, "errorCode");
if(resVal)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(resVal, "%d", &ret);
}
else
{
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
free(DeletePinholeArgs);
return ret;
}
LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking)
{
struct NameValueParserData pdata;
struct UPNParg * CheckPinholeWorkingArgs;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!uniqueID)
return UPNPCOMMAND_INVALID_ARGS;
CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg));
CheckPinholeWorkingArgs[0].elt = "UniqueID";
CheckPinholeWorkingArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "IsWorking");
if(p)
{
*isWorking=my_atoui(p);
ret = UPNPCOMMAND_SUCCESS;
}
else
*isWorking = 0;
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
free(CheckPinholeWorkingArgs);
return ret;
}
LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets)
{
struct NameValueParserData pdata;
struct UPNParg * GetPinholePacketsArgs;
char * buffer;
int bufsize;
char * p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
if(!uniqueID)
return UPNPCOMMAND_INVALID_ARGS;
GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg));
GetPinholePacketsArgs[0].elt = "UniqueID";
GetPinholePacketsArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetPinholePackets", GetPinholePacketsArgs, &bufsize);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
p = GetValueFromNameValueList(&pdata, "PinholePackets");
if(p)
{
*packets=my_atoui(p);
ret = UPNPCOMMAND_SUCCESS;
}
p = GetValueFromNameValueList(&pdata, "errorCode");
if(p)
{
ret = UPNPCOMMAND_UNKNOWN_ERROR;
sscanf(p, "%d", &ret);
}
ClearNameValueList(&pdata);
free(GetPinholePacketsArgs);
return ret;
}

View File

@ -1,14 +1,16 @@
/* $Id: upnpcommands.h,v 1.18 2010/06/09 10:59:09 nanard Exp $ */
/* $Id: upnpcommands.h,v 1.25 2012/09/27 15:42:10 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef __UPNPCOMMANDS_H__
#define __UPNPCOMMANDS_H__
#ifndef UPNPCOMMANDS_H_INCLUDED
#define UPNPCOMMANDS_H_INCLUDED
#include "upnpreplyparse.h"
#include "portlistingparse.h"
#include "declspec.h"
#include "miniupnpctypes.h"
/* MiniUPnPc return codes : */
#define UPNPCOMMAND_SUCCESS (0)
@ -20,14 +22,6 @@
extern "C" {
#endif
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
#define UNSIGNED_INTEGER unsigned long long
#define STRTOUI strtoull
#else
#define UNSIGNED_INTEGER unsigned int
#define STRTOUI strtoul
#endif
LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype);
@ -68,12 +62,12 @@ UPNP_GetConnectionTypeInfo(const char * controlURL,
/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
* if the third arg is not null the value is copied to it.
* at least 16 bytes must be available
* at least 16 bytes must be available
*
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR Either an UPnP error code or an unknown error.
*
*
* possible UPnP Errors :
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control. */
@ -101,7 +95,7 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* Return values :
* 0 : SUCCESS
* NON ZERO : ERROR. Either an UPnP error code or an unknown error.
*
*
* List of possible UPnP errors for AddPortMapping :
* errorCode errorDescription (short) - Description (long)
* 402 Invalid Args - See UPnP Device Architecture section on Control.
@ -112,7 +106,7 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
* 718 ConflictInMappingEntry - The port mapping entry specified conflicts
* with a mapping assigned previously to another client
* 724 SamePortValuesRequired - Internal and External port values
* must be the same
* must be the same
* 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
* permanent lease times on port mappings
* 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
@ -126,7 +120,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost);
const char * remoteHost,
const char * leaseDuration);
/* UPNP_DeletePortMapping()
* Use same argument values as what was used for AddPortMapping().
@ -146,11 +141,20 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
/* UPNP_GetPortMappingNumberOfEntries()
* not supported by all routers */
LIBSPEC int
UPNP_GetPortMappingNumberOfEntries(const char* controlURL, const char* servicetype, unsigned int * num);
UPNP_GetPortMappingNumberOfEntries(const char* controlURL,
const char* servicetype,
unsigned int * num);
/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
* the result is returned in the intClient and intPort strings
* please provide 16 and 6 bytes of data
/* UPNP_GetSpecificPortMappingEntry()
* retrieves an existing port mapping
* params :
* in extPort
* in proto
* out intClient (16 bytes)
* out intPort (6 bytes)
* out desc (80 bytes)
* out enabled (4 bytes)
* out leaseDuration (16 bytes)
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
@ -161,9 +165,22 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * extPort,
const char * proto,
char * intClient,
char * intPort);
char * intPort,
char * desc,
char * enabled,
char * leaseDuration);
/* UPNP_GetGenericPortMappingEntry()
* params :
* in index
* out extPort (6 bytes)
* out intClient (16 bytes)
* out intPort (6 bytes)
* out protocol (4 bytes)
* out desc (80 bytes)
* out enabled (4 bytes)
* out rHost (64 bytes)
* out duration (16 bytes)
*
* return value :
* UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
@ -186,6 +203,66 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
char * rHost,
char * duration);
/* UPNP_GetListOfPortMappings() Available in IGD v2
*
*
* Possible UPNP Error codes :
* 606 Action not Authorized
* 730 PortMappingNotFound - no port mapping is found in the specified range.
* 733 InconsistantParameters - NewStartPort and NewEndPort values are not
* consistent.
*/
LIBSPEC int
UPNP_GetListOfPortMappings(const char * controlURL,
const char * servicetype,
const char * startPort,
const char * endPort,
const char * protocol,
const char * numberOfPorts,
struct PortMappingParserData * data);
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
LIBSPEC int
UPNP_GetFirewallStatus(const char * controlURL,
const char * servicetype,
int * firewallEnabled,
int * inboundPinholeAllowed);
LIBSPEC int
UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
int * opTimeout);
LIBSPEC int
UPNP_AddPinhole(const char * controlURL, const char * servicetype,
const char * remoteHost,
const char * remotePort,
const char * intClient,
const char * intPort,
const char * proto,
const char * leaseTime,
char * uniqueID);
LIBSPEC int
UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
const char * uniqueID,
const char * leaseTime);
LIBSPEC int
UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID);
LIBSPEC int
UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
const char * uniqueID, int * isWorking);
LIBSPEC int
UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
const char * uniqueID, int * packets);
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,4 @@
/* $Id: upnperrors.c,v 1.3 2008/04/27 17:21:51 nanard Exp $ */
/* $Id: upnperrors.c,v 1.6 2012/03/15 01:02:03 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2007 Thomas Bernard
@ -9,6 +9,7 @@
#include <string.h>
#include "upnperrors.h"
#include "upnpcommands.h"
#include "miniupnpc.h"
const char * strupnperror(int err)
{
@ -23,6 +24,12 @@ const char * strupnperror(int err)
case UPNPCOMMAND_INVALID_ARGS:
s = "Miniupnpc Invalid Arguments";
break;
case UPNPDISCOVER_SOCKET_ERROR:
s = "Miniupnpc Socket error";
break;
case UPNPDISCOVER_MEMORY_ERROR:
s = "Miniupnpc Memory allocation error";
break;
case 401:
s = "Invalid Action";
break;
@ -32,6 +39,36 @@ const char * strupnperror(int err)
case 501:
s = "Action Failed";
break;
case 606:
s = "Action not authorized";
break;
case 701:
s = "PinholeSpaceExhausted";
break;
case 702:
s = "FirewallDisabled";
break;
case 703:
s = "InboundPinholeNotAllowed";
break;
case 704:
s = "NoSuchEntry";
break;
case 705:
s = "ProtocolNotSupported";
break;
case 706:
s = "InternalPortWildcardingNotAllowed";
break;
case 707:
s = "ProtocolWildcardingNotAllowed";
break;
case 708:
s = "WildcardNotPermittedInSrcIP";
break;
case 709:
s = "NoPacketSent";
break;
case 713:
s = "SpecifiedArrayIndexInvalid";
break;
@ -60,7 +97,8 @@ const char * strupnperror(int err)
s = "ExternalPortOnlySupportsWildcard";
break;
default:
s = NULL;
s = "UnknownError";
break;
}
return s;
}

View File

@ -1,12 +1,12 @@
/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */
/* $Id: upnperrors.h,v 1.4 2012/09/27 15:42:11 nanard Exp $ */
/* (c) 2007 Thomas Bernard
* All rights reserved.
* MiniUPnP Project.
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#ifndef __UPNPERRORS_H__
#define __UPNPERRORS_H__
#ifndef UPNPERRORS_H_INCLUDED
#define UPNPERRORS_H_INCLUDED
#include "declspec.h"
@ -15,7 +15,7 @@ extern "C" {
#endif
/* strupnperror()
* Return a string description of the UPnP error code
* Return a string description of the UPnP error code
* or NULL for undefinded errors */
LIBSPEC const char * strupnperror(int err);

View File

@ -1,7 +1,7 @@
/* $Id: upnpreplyparse.c,v 1.10 2008/02/21 13:05:27 nanard Exp $ */
/* $Id: upnpreplyparse.c,v 1.15 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -15,40 +15,90 @@
static void
NameValueParserStartElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValueParserData * data = (struct NameValueParserData *)d;
data->topelt = 1;
if(l>63)
l = 63;
memcpy(data->curelt, name, l);
data->curelt[l] = '\0';
data->cdata = NULL;
data->cdatalen = 0;
}
static void
NameValueParserEndElt(void * d, const char * name, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
(void)name;
(void)l;
if(!data->topelt)
return;
if(strcmp(data->curelt, "NewPortListing") != 0)
{
int l;
/* standard case. Limited to n chars strings */
l = data->cdatalen;
nv = malloc(sizeof(struct NameValue));
if(l>=(int)sizeof(nv->value))
l = sizeof(nv->value) - 1;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
if(data->cdata != NULL)
{
memcpy(nv->value, data->cdata, l);
nv->value[l] = '\0';
}
else
{
nv->value[0] = '\0';
}
LIST_INSERT_HEAD( &(data->head), nv, entries);
}
data->cdata = NULL;
data->cdatalen = 0;
data->topelt = 0;
}
static void
NameValueParserGetData(void * d, const char * datas, int l)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
nv = malloc(sizeof(struct NameValue));
if(l>63)
l = 63;
strncpy(nv->name, data->curelt, 64);
nv->name[63] = '\0';
memcpy(nv->value, datas, l);
nv->value[l] = '\0';
LIST_INSERT_HEAD( &(data->head), nv, entries);
if(strcmp(data->curelt, "NewPortListing") == 0)
{
/* specific case for NewPortListing which is a XML Document */
data->portListing = malloc(l + 1);
if(!data->portListing)
{
/* malloc error */
return;
}
memcpy(data->portListing, datas, l);
data->portListing[l] = '\0';
data->portListingLength = l;
}
else
{
/* standard case. */
data->cdata = datas;
data->cdatalen = l;
}
}
void
ParseNameValue(const char * buffer, int bufsize,
struct NameValueParserData * data)
struct NameValueParserData * data)
{
struct xmlparser parser;
LIST_INIT(&(data->head));
data->portListing = NULL;
data->portListingLength = 0;
/* init xmlparser object */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
parser.data = data;
parser.starteltfunc = NameValueParserStartElt;
parser.endeltfunc = 0;
parser.endeltfunc = NameValueParserEndElt;
parser.datafunc = NameValueParserGetData;
parser.attfunc = 0;
parsexml(&parser);
@ -58,6 +108,12 @@ void
ClearNameValueList(struct NameValueParserData * pdata)
{
struct NameValue * nv;
if(pdata->portListing)
{
free(pdata->portListing);
pdata->portListing = NULL;
pdata->portListingLength = 0;
}
while((nv = pdata->head.lh_first) != NULL)
{
LIST_REMOVE(nv, entries);
@ -65,7 +121,7 @@ ClearNameValueList(struct NameValueParserData * pdata)
}
}
char *
char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name)
{
@ -106,7 +162,7 @@ GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
}
#endif
/* debug all-in-one function
/* debug all-in-one function
* do parsing then display to stdout */
#ifdef DEBUG
void

View File

@ -1,14 +1,14 @@
/* $Id: upnpreplyparse.h,v 1.10 2009/07/09 16:01:50 nanard Exp $ */
/* $Id: upnpreplyparse.h,v 1.17 2013/06/06 21:36:40 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2009 Thomas Bernard
* (c) 2006-2013 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef __UPNPREPLYPARSE_H__
#define __UPNPREPLYPARSE_H__
#ifndef UPNPREPLYPARSE_H_INCLUDED
#define UPNPREPLYPARSE_H_INCLUDED
#if defined(NO_SYS_QUEUE_H) || defined(WIN32) || defined(__HAIKU__)
#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>
@ -21,12 +21,17 @@ extern "C" {
struct NameValue {
LIST_ENTRY(NameValue) entries;
char name[64];
char value[64];
char value[128];
};
struct NameValueParserData {
LIST_HEAD(listhead, NameValue) head;
char curelt[64];
char * portListing;
int portListingLength;
int topelt;
const char * cdata;
int cdatalen;
};
/* ParseNameValue() */
@ -43,10 +48,12 @@ char *
GetValueFromNameValueList(struct NameValueParserData * pdata,
const char * Name);
#if 0
/* GetValueFromNameValueListIgnoreNS() */
char *
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
const char * Name);
#endif
/* DisplayNameValueList() */
#ifdef DEBUG

View File

@ -1,10 +1,9 @@
2013-xx-xx: Version 3.1.1
* General:
* Change: Simplify build process by getting rid of bison/flex dependencies (commit:d13bc0de7dd0588351af24dc45d55110d0eed6e8)
* Change: Filter out bad maps (commit:acfe83cdf6f44660276ba73931e2cebdc8a250ac)
* Change: Also show in the bottom menu, if allies are researching the same as us (commit:b6b6265e4e430486ea44a200bce870b115dfc37f)
* Change: Keep showing allied research even while facilities are upgraded (commit:423e358b6715c12dda70ff5f6f2bd0348c09f699)
* Change: Retreat buttons now should health bar colours (commit:4e2f4bbf3cd5e03e58b9b67fcf370bff088e6d91)
* Change: Retreat buttons now show health bar colours (commit:4e2f4bbf3cd5e03e58b9b67fcf370bff088e6d91)
* Fix: Bug that made droids produced by scripts get human player's upgrades (commit:8149dc94c0b61117982281cdaf2aac1bec2525e9)
* Fix: Backwards terrain shadows (commit:85ecd9a3937e7843d9eb4798572651f950bd7555)
* Fix: Mod loading bug (commit:87cade1a684f3da0572f13e92539100f35b4f6fe, ticket:3567)
@ -25,7 +24,9 @@
* Fix: Add parameter checking for buildings that do not exist (commit:e38de7b64242a547acd77c7775dbfae10c74ca3d)
* Maps:
* Fix: Remove lop-sided oil barrels from 4c-pyramidal (commit:6092fe1194529f0c7fe023d9c98973e44f9f9f24)
* Add: Gamma (3p) and Melting (6p) by NoQ (commit:b8bdf44737e1d9423c2581b1377cf1be9c4a3666)
* Build system:
* Change: Simplify build process by getting rid of bison/flex dependencies (commit:d13bc0de7dd0588351af24dc45d55110d0eed6e8)
* Fix: Building on OpenBSD (commit:9b9383500fb4c1dd5270a68e3490dc358e2da55f, ticket:3917, commit:47a6d6d4684b993d15e378f6d0877fa043b26ca0, ticket:3845)
2012-12-09: Version 3.1.0

View File

@ -142,14 +142,15 @@ static SocketSet* socket_set = NULL;
// UPnP
static int upnp = false;
static bool upnp_done = false;
WZ_THREAD *upnpdiscover;
static struct UPNPUrls urls;
static struct IGDdatas data;
// local ip address
static char lanaddr[16];
static char lanaddr[40];
static char externalIPAddress[40];
/**
* Used for connections with clients.
*/
@ -934,7 +935,6 @@ static bool NETrecvGAMESTRUCT(GAMESTRUCT* ourgamestruct)
}
static int upnp_init(void *asdf)
{
struct UPNPDev *devlist;
@ -942,14 +942,14 @@ static int upnp_init(void *asdf)
char *descXML;
int descXMLsize = 0;
char buf[255];
int result;
memset(&urls, 0, sizeof(struct UPNPUrls));
memset(&data, 0, sizeof(struct IGDdatas));
if (NetPlay.isUPNP)
{
debug(LOG_NET, "Searching for UPnP devices for automatic port forwarding...");
devlist = upnpDiscover(2000, NULL, NULL, 0);
devlist = upnpDiscover(3000, NULL, NULL, 0, 0, &result);
debug(LOG_NET, "UPnP device search finished.");
if (devlist)
{
@ -967,13 +967,13 @@ static int upnp_init(void *asdf)
debug(LOG_NET, "UPnP device found: %s %s\n", dev->descURL, dev->st);
descXML = (char *)miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, sizeof(lanaddr));
descXML = (char *)miniwget_getaddr(dev->descURL, &descXMLsize, lanaddr, sizeof(lanaddr), dev->scope_id);
debug(LOG_NET, "LAN address: %s", lanaddr);
if (descXML)
{
parserootdesc (descXML, descXMLsize, &data);
free (descXML); descXML = 0;
GetUPNPUrls (&urls, &data, dev->descURL);
GetUPNPUrls (&urls, &data, dev->descURL, dev->scope_id);
}
ssprintf(buf, "UPnP device found: %s %s LAN address %s", dev->descURL, dev->st, lanaddr);
addDumpInfo(buf);
@ -983,13 +983,20 @@ static int upnp_init(void *asdf)
{
ssprintf(buf, "controlURL not available, UPnP disabled");
addDumpInfo(buf);
ssprintf(buf, _("Your router doesn't support UPnP, you must manually configure your router & firewall to open port 2100 before you can host a game."));
addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE);
return false;
}
NETaddRedirects();
upnp = true;
return true;
}
ssprintf(buf, "UPnP device not found.");
addDumpInfo(buf);
debug(LOG_NET, "No UPnP devices found.");
ssprintf(buf, _("No UPnP device was found. You must manually configure your router & firewall to open port 2100 before you can host a game."));
addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE);
return false;
}
else
@ -999,55 +1006,74 @@ static int upnp_init(void *asdf)
debug(LOG_NET, "UPnP detection routine disabled by user.");
return false;
}
}
static bool upnp_add_redirect(int port)
{
char externalIP[16];
char port_str[16];
char buf[512]={'\0'};
int r;
debug(LOG_NET, "upnp_add_redir(%d)\n", port);
UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIP);
debug(LOG_NET, "upnp_add_redir(%d)", port);
sprintf(port_str, "%d", port);
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port_str, port_str, lanaddr, "Warzone 2100", "TCP", 0);
port_str, port_str, lanaddr, "Warzone 2100", "TCP", 0, "0"); // "0" = lease time unlimited
if (r != UPNPCOMMAND_SUCCESS)
{
debug(LOG_NET, "AddPortMapping(%s, %s, %s) failed\n", port_str, port_str, lanaddr);
ssprintf(buf, _("Could not open require port (%s) on (%s)"), port_str, lanaddr);
debug(LOG_NET, "%s", buf);
addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE);
ssprintf(buf, _("You must manually configure your router & firewall to open port 2100 before you can host a game."));
addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE);
return false;
}
return true;
r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS)
{
ssprintf(externalIPAddress, "???");
}
ssprintf(buf, _("Game configured port (%s) correctly on (%s). Your external IP is %s"), port_str, lanaddr, externalIPAddress);
addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE);
return true;
}
static void upnp_rem_redirect(int port)
static int upnp_rem_redirect(int port)
{
char port_str[16];
debug(LOG_NET, "upnp_rem_redir(%d)", port);
sprintf(port_str, "%d", port);
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port_str, "TCP", 0);
return UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port_str, "TCP", NULL);
}
void NETaddRedirects(void)
{
debug(LOG_NET, "%s\n", __FUNCTION__);
if (!upnp_done)
if (upnp_add_redirect(gameserver_port))
{
upnp = wzThreadJoin(upnpdiscover);
upnp_done = true;
debug(LOG_NET, "successful!");
}
if (upnp) {
upnp_add_redirect(gameserver_port);
else
{
debug(LOG_NET, "failed!");
}
}
void NETremRedirects(void)
{
debug(LOG_NET, "%s\n", __FUNCTION__);
debug(LOG_NET, "upnp is %d", upnp);
if (upnp)
{
upnp_rem_redirect(gameserver_port);
int result = upnp_rem_redirect(gameserver_port);
if (!result)
{
debug(LOG_NET, "removed UPnP entry.");
}
else
{
debug(LOG_ERROR, "Failed to remove UPnP entry for the game. You must manually remove it from your router. (%d)", result);
}
}
}
@ -1096,6 +1122,10 @@ int NETshutdown(void)
{
debug( LOG_NET, "NETshutdown" );
NETlogEntry("NETshutdown", SYNC_FLAG, selectedPlayer);
if (NetPlay.bComms && NetPlay.isUPNP)
{
NETremRedirects();
}
NETstopLogging();
if (IPlist)
free(IPlist);
@ -1108,11 +1138,6 @@ int NETshutdown(void)
NETdeleteQueue();
SOCKETshutdown();
if (NetPlay.bComms && NetPlay.isUPNP)
{
NETremRedirects();
}
// Reset net usage statistics.
nStats = nZeroStats;
nStatsLastSec = nZeroStats;
@ -2587,10 +2612,6 @@ bool NEThostGame(const char* SessionName, const char* PlayerName,
mapDownloadProgress = 100;
netPlayersUpdated = true;
if (NetPlay.bComms && NetPlay.isUPNP)
{
NETaddRedirects();
}
NET_InitPlayers();
for (unsigned n = 0; n < MAX_PLAYERS_IN_GUI; ++n)
{

View File

@ -207,6 +207,8 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\3rdparty\miniupnpc\connecthostport.c" />
<ClCompile Include="..\..\3rdparty\miniupnpc\portlistingparse.c" />
<ClCompile Include="..\..\3rdparty\miniupnpc\receivedata.c" />
<ClCompile Include="netjoin_stub.cpp" />
<ClCompile Include="netlog.cpp" />
<ClCompile Include="netplay.cpp" />
@ -246,8 +248,11 @@
<ClInclude Include="..\..\3rdparty\miniupnpc\minissdpc.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\miniupnpc.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\miniupnpcstrings.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\miniupnpctypes.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\miniwget.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\minixml.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\portlistingparse.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\receivedata.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\upnpcommands.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\upnperrors.h" />
<ClInclude Include="..\..\3rdparty\miniupnpc\upnpreplyparse.h" />

View File

@ -68,6 +68,12 @@
<ClCompile Include="netjoin_stub.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\3rdparty\miniupnpc\portlistingparse.c">
<Filter>Source Files\miniUPnP\src files</Filter>
</ClCompile>
<ClCompile Include="..\..\3rdparty\miniupnpc\receivedata.c">
<Filter>Source Files\miniUPnP\src files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\3rdparty\miniupnpc\bsdqueue.h">
@ -127,5 +133,14 @@
<ClInclude Include="nettypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\3rdparty\miniupnpc\miniupnpctypes.h">
<Filter>Source Files\miniUPnP\header files</Filter>
</ClInclude>
<ClInclude Include="..\..\3rdparty\miniupnpc\portlistingparse.h">
<Filter>Source Files\miniUPnP\header files</Filter>
</ClInclude>
<ClInclude Include="..\..\3rdparty\miniupnpc\receivedata.h">
<Filter>Source Files\miniUPnP\header files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -537,11 +537,11 @@ bool runMultiPlayerMenu(void)
case FRONTEND_HOST:
// don't pretend we are running a network game. Really do it!
NetPlay.bComms = true; // use network = true
NETdiscoverUPnPDevices();
ingame.bHostSetup = true;
bMultiPlayer = true;
bMultiMessages = true;
NETinit(true);
NETdiscoverUPnPDevices();
game.type = SKIRMISH; // needed?
lastTitleMode = MULTI;
changeTitleMode(MULTIOPTION);

View File

@ -3780,9 +3780,22 @@ bool startMultiOptions(bool bReenter)
}
else
{
char buf[512] = {'\0'};
addPlayerBox(false); // Players
addGameOptions();
addChatBox();
if (NetPlay.isUPNP)
{
ssprintf(buf, _("UPnP detection is in progress..."));
addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE);
}
else
{
ssprintf(buf, _("UPnP detection disabled by user. Autoconfig of port 2100 will not happen."));
addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE);
}
ssprintf(buf, _("Press the start hosting button to begin hosting a game."));
addConsoleMessage(buf, DEFAULT_JUSTIFY, NOTIFY_MESSAGE);
}
// going back to multiop after setting limits up..