Update miniupnpc to version 1.5.

Thanks to pabs for the needed changes to netplay.cpp (refs #2513).
master
cybersphinx 2011-04-23 15:36:30 +02:00
parent 583c318c2e
commit d180026116
17 changed files with 800 additions and 371 deletions

View File

@ -1,6 +1,89 @@
$Id: Changelog.txt,v 1.95 2009/10/30 09:18:18 nanard Exp $
$Id: Changelog.txt,v 1.125 2010/12/21 16:13:13 nanard Exp $
miniUPnP client Changelog.
2010/12/21:
use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo
2010/12/11:
Improvements on getHTTPResponse() code.
2010/12/09:
new code for miniwget that handle Chunked transfer encoding
using getHTTPResponse() in SOAP call code
Adding MANIFEST.in for 'python setup.py bdist_rpm'
2010/11/25:
changes to minissdpc.c to compile under Win32.
see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729
2010/09/17:
Various improvement to Makefile from Michał Górny
2010/08/05:
Adding the script "external-ip.sh" from Reuben Hawkins
2010/06/09:
update to python module to match modification made on 2010/04/05
update to Java test code to match modification made on 2010/04/05
all UPNP_* function now return an error if the SOAP request failed
at HTTP level.
2010/04/17:
Using GetBestRoute() under win32 in order to find the
right interface to use.
2010/04/12:
Retrying with HTTP/1.1 if HTTP/1.0 failed. see
http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703
2010/04/07:
avoid returning duplicates in upnpDiscover()
2010/04/05:
Create a connecthostport.h/.c with connecthostport() function
and use it in miniwget and miniupnpc.
Use getnameinfo() instead of inet_ntop or inet_ntoa
Work to make miniupnpc IPV6 compatible...
Add java test code.
Big changes in order to support device having both WANIPConnection
and WANPPPConnection.
2010/04/04:
Use getaddrinfo() instead of gethostbyname() in miniwget.
2010/01/06:
#define _DARWIN_C_SOURCE for Mac OS X
2009/12/19:
Improve MinGW32 build
2009/12/11:
adding a MSVC9 project to build the static library and executable
2009/12/10:
Fixing some compilation stuff for Windows/MinGW
2009/12/07:
adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS
some fixes for Windows when using virtual ethernet adapters (it is the
case with VMWare installed).
2009/12/04:
some fixes for AmigaOS compilation
Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked
transfer encoding)
2009/12/03:
updating printIDG and testigddescparse.c for debug.
modifications to compile under AmigaOS
adding a testminiwget program
Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked
transfer encoding
2009/11/26:
fixing updateminiupnpcstrings.sh to take into account
which command that does not return an error code.
VERSION 1.4 : released 2009/10/30
2009/10/16:

View File

@ -1,10 +1,11 @@
AM_CPPFLAGS = -DSTATICLIB $(SDL_CFLAGS) $(WZ_CPPFLAGS)
AM_CFLAGS = -DSTATICLIB $(WZ_CFLAGS)
AM_CFLAGS = -DSTATICLIB $(WZ_CFLAGS) -UDEBUG
noinst_LIBRARIES = libminiupnpc.a
noinst_HEADERS = \
bsdqueue.h \
codelength.h \
connecthostport.h \
declspec.h \
igd_desc_parse.h \
minisoap.h \
@ -18,6 +19,7 @@ noinst_HEADERS = \
upnpreplyparse.h
libminiupnpc_a_SOURCES = \
connecthostport.c \
igd_desc_parse.c \
minisoap.c \
minissdpc.c \

View File

@ -1,9 +1,9 @@
Project: miniupnp
Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
Author: Thomas Bernard
Copyright (c) 2005-2008 Thomas Bernard
Copyright (c) 2005-2009 Thomas Bernard
This software is subject to the conditions detailed in the
LICENCE file provided within this distribution.
LICENSE file provided within this distribution.
For the comfort of Win32 users, bsdqueue.h is included in the distribution.
Its licence is included in the header of the file.
@ -11,10 +11,12 @@ bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system.
* miniupnp Client *
To compile, simply run 'gmake' (could be 'make').
To compile, simply run 'gmake' (could be 'make' on your system).
Under win32, to compile with MinGW, type "mingw32make.bat".
The compilation is known to work under linux, FreeBSD,
OpenBSD, MacOS X and cygwin.
OpenBSD, MacOS X, AmigaOS and cygwin.
The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3.
To install the library and headers on the system use :
> su
> make install
@ -25,7 +27,7 @@ alternatively, to install in a specific location, use :
upnpc.c is a sample client using the libminiupnpc.
To use the libminiupnpc in your application, link it with
libminiupnpc.a and use the following functions found in miniupnpc.h,
libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h,
upnpcommands.h and miniwget.h :
- upnpDiscover()
- miniwget()

View File

@ -5,9 +5,7 @@
#ifdef MINIUPNP_EXPORTS
#define LIBSPEC __declspec(dllexport)
#else
// NOTE: with the cross compiler, even if we have -DSTATICLIB, for some odd reason it still does this
// #define LIBSPEC __declspec(dllimport) which is not what we want. So we hack the line like so.
#define LIBSPEC
#define LIBSPEC __declspec(dllimport)
#endif
#else
#define LIBSPEC

View File

@ -1,18 +1,15 @@
/* $Id: igd_desc_parse.c,v 1.8 2008/04/23 11:51:06 nanard Exp $ */
/* $Id: igd_desc_parse.c,v 1.11 2010/12/11 17:56:51 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2008 Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
* LICENCE file provided in this distribution. */
#include "igd_desc_parse.h"
#include <stdio.h>
#include <string.h>
/* TODO : rewrite this code so it correctly handle descriptions with
* both WANIPConnection and/or WANPPPConnection */
/* Start element handler :
* update nesting level counter and copy element name */
void IGDstartelt(void * d, const char * name, int l)
@ -22,10 +19,10 @@ void IGDstartelt(void * d, const char * name, int l)
datas->cureltname[l] = '\0';
datas->level++;
if( (l==7) && !memcmp(name, "service", l) ) {
datas->controlurl_tmp[0] = '\0';
datas->eventsuburl_tmp[0] = '\0';
datas->scpdurl_tmp[0] = '\0';
datas->servicetype_tmp[0] = '\0';
datas->tmp.controlurl[0] = '\0';
datas->tmp.eventsuburl[0] = '\0';
datas->tmp.scpdurl[0] = '\0';
datas->tmp.servicetype[0] = '\0';
}
}
@ -46,20 +43,18 @@ void IGDendelt(void * d, const char * name, int l)
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
datas->state ++;
*/
if(0==strcmp(datas->servicetype_tmp,
if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) {
memcpy(datas->controlurl_CIF, datas->controlurl_tmp, MINIUPNPC_URL_MAXSIZE);
memcpy(datas->eventsuburl_CIF, datas->eventsuburl_tmp, MINIUPNPC_URL_MAXSIZE);
memcpy(datas->scpdurl_CIF, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE);
memcpy(datas->servicetype_CIF, datas->servicetype_tmp, MINIUPNPC_URL_MAXSIZE);
} else if(0==strcmp(datas->servicetype_tmp,
memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service));
} else if(0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANIPConnection:1")
|| 0==strcmp(datas->servicetype_tmp,
|| 0==strcmp(datas->tmp.servicetype,
"urn:schemas-upnp-org:service:WANPPPConnection:1") ) {
memcpy(datas->controlurl, datas->controlurl_tmp, MINIUPNPC_URL_MAXSIZE);
memcpy(datas->eventsuburl, datas->eventsuburl_tmp, MINIUPNPC_URL_MAXSIZE);
memcpy(datas->scpdurl, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE);
memcpy(datas->servicetype, datas->servicetype_tmp, MINIUPNPC_URL_MAXSIZE);
if(datas->first.servicetype[0] == '\0') {
memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service));
} else {
memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service));
}
}
}
}
@ -75,13 +70,13 @@ void IGDdata(void * d, const char * data, int l)
if( !strcmp(datas->cureltname, "URLBase") )
dstmember = datas->urlbase;
else if( !strcmp(datas->cureltname, "serviceType") )
dstmember = datas->servicetype_tmp;
dstmember = datas->tmp.servicetype;
else if( !strcmp(datas->cureltname, "controlURL") )
dstmember = datas->controlurl_tmp;
dstmember = datas->tmp.controlurl;
else if( !strcmp(datas->cureltname, "eventSubURL") )
dstmember = datas->eventsuburl_tmp;
dstmember = datas->tmp.eventsuburl;
else if( !strcmp(datas->cureltname, "SCPDURL") )
dstmember = datas->scpdurl_tmp;
dstmember = datas->tmp.scpdurl;
/* else if( !strcmp(datas->cureltname, "deviceType") )
dstmember = datas->devicetype_tmp;*/
if(dstmember)
@ -95,19 +90,25 @@ void IGDdata(void * d, const char * data, int l)
void printIGD(struct IGDdatas * d)
{
printf("urlbase = %s\n", d->urlbase);
printf("urlbase = '%s'\n", d->urlbase);
printf("WAN Device (Common interface config) :\n");
/*printf(" deviceType = %s\n", d->devicetype_CIF);*/
printf(" serviceType = %s\n", d->servicetype_CIF);
printf(" controlURL = %s\n", d->controlurl_CIF);
printf(" eventSubURL = %s\n", d->eventsuburl_CIF);
printf(" SCPDURL = %s\n", d->scpdurl_CIF);
printf("WAN Connection Device (IP or PPP Connection):\n");
/*printf(" deviceType = %s\n", d->devicetype);*/
printf(" servicetype = %s\n", d->servicetype);
printf(" controlURL = %s\n", d->controlurl);
printf(" eventSubURL = %s\n", d->eventsuburl);
printf(" SCPDURL = %s\n", d->scpdurl);
/*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/
printf(" serviceType = '%s'\n", d->CIF.servicetype);
printf(" controlURL = '%s'\n", d->CIF.controlurl);
printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl);
printf(" SCPDURL = '%s'\n", d->CIF.scpdurl);
printf("primary WAN Connection Device (IP or PPP Connection):\n");
/*printf(" deviceType = '%s'\n", d->first.devicetype);*/
printf(" servicetype = '%s'\n", d->first.servicetype);
printf(" controlURL = '%s'\n", d->first.controlurl);
printf(" eventSubURL = '%s'\n", d->first.eventsuburl);
printf(" SCPDURL = '%s'\n", d->first.scpdurl);
printf("secondary WAN Connection Device (IP or PPP Connection):\n");
/*printf(" deviceType = '%s'\n", d->second.devicetype);*/
printf(" servicetype = '%s'\n", d->second.servicetype);
printf(" controlURL = '%s'\n", d->second.controlurl);
printf(" eventSubURL = '%s'\n", d->second.eventsuburl);
printf(" SCPDURL = '%s'\n", d->second.scpdurl);
}

View File

@ -1,8 +1,8 @@
/* $Id: igd_desc_parse.h,v 1.6 2008/04/23 11:51:07 nanard Exp $ */
/* $Id: igd_desc_parse.h,v 1.7 2010/04/05 20:36:59 nanard Exp $ */
/* Project : miniupnp
* http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2008 Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -12,30 +12,28 @@
/* Structure to store the result of the parsing of UPnP
* descriptions of Internet Gateway Devices */
#define MINIUPNPC_URL_MAXSIZE (128)
struct IGDdatas_service {
char controlurl[MINIUPNPC_URL_MAXSIZE];
char eventsuburl[MINIUPNPC_URL_MAXSIZE];
char scpdurl[MINIUPNPC_URL_MAXSIZE];
char servicetype[MINIUPNPC_URL_MAXSIZE];
/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/
};
struct IGDdatas {
char cureltname[MINIUPNPC_URL_MAXSIZE];
char urlbase[MINIUPNPC_URL_MAXSIZE];
int level;
/*int state;*/
/* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
char controlurl_CIF[MINIUPNPC_URL_MAXSIZE];
char eventsuburl_CIF[MINIUPNPC_URL_MAXSIZE];
char scpdurl_CIF[MINIUPNPC_URL_MAXSIZE];
char servicetype_CIF[MINIUPNPC_URL_MAXSIZE];
/*char devicetype_CIF[MINIUPNPC_URL_MAXSIZE];*/
struct IGDdatas_service CIF;
/* "urn:schemas-upnp-org:service:WANIPConnection:1"
* "urn:schemas-upnp-org:service:WANPPPConnection:1" */
char controlurl[MINIUPNPC_URL_MAXSIZE];
char eventsuburl[MINIUPNPC_URL_MAXSIZE];
char scpdurl[MINIUPNPC_URL_MAXSIZE];
char servicetype[MINIUPNPC_URL_MAXSIZE];
/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/
struct IGDdatas_service first;
/* if both WANIPConnection and WANPPPConnection are present */
struct IGDdatas_service second;
/* tmp */
char controlurl_tmp[MINIUPNPC_URL_MAXSIZE];
char eventsuburl_tmp[MINIUPNPC_URL_MAXSIZE];
char scpdurl_tmp[MINIUPNPC_URL_MAXSIZE];
char servicetype_tmp[MINIUPNPC_URL_MAXSIZE];
/*char devicetype_tmp[MINIUPNPC_URL_MAXSIZE];*/
struct IGDdatas_service tmp;
};
void IGDstartelt(void *, const char *, int);

View File

@ -1,7 +1,7 @@
/* $Id: minisoap.c,v 1.16 2008/10/11 16:39:29 nanard Exp $ */
/* $Id: minisoap.c,v 1.20 2010/12/11 17:56:51 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* Copyright (c) 2005-2009 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
*
@ -21,8 +21,6 @@
#include "minisoap.h"
#include "miniupnpcstrings.h"
#undef DEBUG
/* only for malloc */
#include <stdlib.h>
@ -77,7 +75,8 @@ int soapPostSubmit(int fd,
const char * host,
unsigned short port,
const char * action,
const char * body)
const char * body,
const char * httpversion)
{
int bodysize;
char headerbuf[512];
@ -86,14 +85,16 @@ int soapPostSubmit(int fd,
bodysize = (int)strlen(body);
/* We are not using keep-alive HTTP connections.
* HTTP/1.1 needs the header Connection: close to do that.
* This is the default with HTTP/1.0 */
* This is the default with HTTP/1.0
* Using HTTP/1.1 means we need to support chunked transfer-encoding :
* When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked
* transfer encoding. */
/* Connection: Close is normally there only in HTTP/1.1 but who knows */
portstr[0] = '\0';
if(port != 80)
snprintf(portstr, sizeof(portstr), ":%hu", port);
headerssize = snprintf(headerbuf, sizeof(headerbuf),
"POST %s HTTP/1.1\r\n"
/* "POST %s HTTP/1.0\r\n"*/
"POST %s HTTP/%s\r\n"
"Host: %s%s\r\n"
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"Content-Length: %d\r\n"
@ -103,10 +104,14 @@ int soapPostSubmit(int fd,
"Cache-Control: no-cache\r\n" /* ??? */
"Pragma: no-cache\r\n"
"\r\n",
url, host, portstr, bodysize, action);
url, httpversion, host, portstr, bodysize, action);
#ifdef DEBUG
printf("SOAP request : headersize=%d bodysize=%d\n",
/*printf("SOAP request : headersize=%d bodysize=%d\n",
headerssize, bodysize);
*/
printf("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);*/
#endif
return httpWrite(fd, body, bodysize, headerbuf, headerssize);

View File

@ -1,4 +1,4 @@
/* $Id: minisoap.h,v 1.3 2006/11/19 22:32:34 nanard Exp $ */
/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
@ -9,7 +9,7 @@
/*int httpWrite(int, const char *, int, const char *);*/
int soapPostSubmit(int, const char *, const char *, unsigned short,
const char *, const char *);
const char *, const char *, const char *);
#endif

View File

@ -1,4 +1,4 @@
/* $Id: minissdpc.c,v 1.10 2009/09/21 12:57:42 nanard Exp $ */
/* $Id: minissdpc.c,v 1.14 2010/11/25 09:57:25 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2009 Thomas Bernard
@ -8,15 +8,22 @@
#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
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
// Warzone additions
#include "lib/framework/types.h"
typedef SSIZE_T ssize_t;
// end WZ
#include <winsock.h>
#include <stdint.h>
#endif
#if defined(__amigaos__) || defined(__amigaos4__)
#include <sys/socket.h>
#endif
#if defined(__amigaos__)
#define uint16_t unsigned short
#endif
/* Hack */
#define UNIX_PATH_LEN 108
struct sockaddr_un {
@ -26,7 +33,6 @@ struct sockaddr_un {
#else
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#endif
#include "minissdpc.h"

View File

@ -1,9 +1,9 @@
/* $Id: miniupnpc.c,v 1.66 2009/10/10 19:15:34 nanard Exp $ */
/* $Id: miniupnpc.c,v 1.85 2010/12/21 16:13:14 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2009 Thomas Bernard
* copyright (c) 2005-2010 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
* provided LICENSE file. */
#define __EXTENSIONS__ 1
#if !defined(MACOSX) && !defined(__sun)
#if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__) && !defined(__NetBSD__)
@ -16,8 +16,6 @@
#endif
#endif
#include "lib/framework/wzglobal.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -26,43 +24,52 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#include <iphlpapi.h>
#define snprintf _snprintf
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define strncasecmp _memicmp
#else
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#define strncasecmp memicmp
#endif
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#define MAXHOSTNAMELEN 64
#else
#else /* #ifdef WIN32 */
/* Standard POSIX includes */
#include <unistd.h>
#if defined(__amigaos__) && !defined(__amigaos4__)
/* Amiga OS 3 specific stuff */
#define socklen_t int
#else
#include <sys/select.h>
#endif
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/param.h>
#ifdef WZ_OS_MAC
# undef _POSIX_C_SOURCE
# include <netinet/in.h>
#else
# include <netinet/in.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <netdb.h>
#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
#endif
#include <strings.h>
#include <errno.h>
#define closesocket close
#define MINIUPNPC_IGNORE_EINTR
#endif
#endif /* #else WIN32 */
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
#include <sys/time.h>
#endif
#if defined(__amigaos__) || defined(__amigaos4__)
/* Amiga OS specific stuff */
#define TIMEVAL struct timeval
#endif
#include "miniupnpc.h"
#include "minissdpc.h"
#include "miniwget.h"
#include "minisoap.h"
#include "minixml.h"
#include "upnpcommands.h"
#include "connecthostport.h"
#ifdef WIN32
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
@ -92,7 +99,9 @@ LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * d
#endif
}
/* Content-length: nnn */
#if 0
/* getcontentlenfromline() : parse the Content-Length HTTP header line.
* Content-length: nnn */
static int getcontentlenfromline(const char * p, int n)
{
static const char contlenstr[] = "content-length";
@ -127,6 +136,10 @@ static int getcontentlenfromline(const char * p, int n)
return a;
}
/* getContentLengthAndHeaderLength()
* retrieve header length and content length from an HTTP response
* TODO : retrieve Transfer-Encoding: header value, in order to support
* HTTP/1.1, chunked transfer encoding must be supported. */
static void
getContentLengthAndHeaderLength(char * p, int n,
int * contentlen, int * headerlen)
@ -155,29 +168,27 @@ getContentLengthAndHeaderLength(char * p, int n,
}
}
}
#endif
/* simpleUPnPcommand :
/* simpleUPnPcommand2 :
* not so simple !
* return values :
* 0 - OK
* -1 - error */
int simpleUPnPcommand(int s, const char * url, const char * service,
static int simpleUPnPcommand2(int s, const char * url, const char * service,
const char * action, struct UPNParg * args,
char * buffer, int * bufsize)
char * buffer, int * bufsize, const char * httpversion)
{
struct sockaddr_in dest;
char hostname[MAXHOSTNAMELEN+1];
unsigned short port = 0;
char * path;
char soapact[128];
char soapbody[2048];
char * buf;
int buffree;
/*int buffree;*/
int n;
int contentlen, headerlen; /* for the response */
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
struct timeval timeout;
#endif
/*int contentlen, headerlen;*/ /* for the response */
snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
if(args==NULL)
{
@ -246,68 +257,15 @@ int simpleUPnPcommand(int s, const char * url, const char * service,
if(!parseURL(url, hostname, &port, &path)) return -1;
if(s<0)
{
s = socket(PF_INET, SOCK_STREAM, 0);
if(s<0)
s = connecthostport(hostname, port);
if(s < 0)
{
PRINT_SOCKET_ERROR("socket");
*bufsize = 0;
return -1;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
}
#endif
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
dest.sin_addr.s_addr = inet_addr(hostname);
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr));
#ifdef MINIUPNPC_IGNORE_EINTR
while(n < 0 && errno == EINTR)
{
socklen_t len;
fd_set wset;
int err;
FD_ZERO(&wset);
FD_SET(s, &wset);
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
continue;
/*len = 0;*/
/*n = getpeername(s, NULL, &len);*/
len = sizeof(err);
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
PRINT_SOCKET_ERROR("getsockopt");
closesocket(s);
return -1;
}
if(err != 0) {
errno = err;
n = -1;
} else {
n = 0;
}
}
#endif
if(n < 0)
{
PRINT_SOCKET_ERROR("connect");
closesocket(s);
*bufsize = 0;
return -1;
}
}
n = soapPostSubmit(s, path, hostname, port, soapact, soapbody);
n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
if(n<=0) {
#ifdef DEBUG
printf("Error sending SOAP request\n");
@ -316,6 +274,7 @@ int simpleUPnPcommand(int s, const char * url, const char * service,
return -1;
}
#if 0
contentlen = -1;
headerlen = -1;
buf = buffer;
@ -335,11 +294,56 @@ int simpleUPnPcommand(int s, const char * url, const char * service,
if(contentlen > 0 && headerlen > 0 && *bufsize >= contentlen+headerlen)
break;
}
#endif
buf = getHTTPResponse(s, &n);
if(n > 0 && buf)
{
#ifdef DEBUG
printf("SOAP Response :\n%.*s\n", n, buf);
#endif
if(*bufsize > n)
{
memcpy(buffer, buf, n);
*bufsize = n;
}
else
{
memcpy(buffer, buf, *bufsize);
}
free(buf);
buf = 0;
}
closesocket(s);
return 0;
}
/* simpleUPnPcommand :
* not so simple !
* return values :
* 0 - OK
* -1 - error */
int simpleUPnPcommand(int s, const char * url, const char * service,
const char * action, struct UPNParg * args,
char * buffer, int * bufsize)
{
int result;
/*int origbufsize = *bufsize;*/
result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.1");
/*
result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.0");
if (result < 0 || *bufsize == 0)
{
#if DEBUG
printf("Error or no result from SOAP request; retrying with HTTP/1.1\n");
#endif
*bufsize = origbufsize;
result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.1");
}
*/
return result;
}
/* parseMSEARCHReply()
* the last 4 arguments are filled during the parsing :
* - location/locationsize : "location:" field of the SSDP reply packet
@ -435,10 +439,19 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
char bufr[1536]; /* reception and emission buffer */
int sudp;
int n;
struct sockaddr_in sockudp_r, sockudp_w;
struct sockaddr sockudp_r;
unsigned int mx;
#ifdef NO_GETADDRINFO
struct sockaddr_in sockudp_w;
#else
int rv;
struct addrinfo hints, *servinfo, *p;
#endif
#ifdef WIN32
MIB_IPFORWARDROW ip_forward;
#endif
#ifndef WIN32
#if !defined(WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
/* first try to get infos from minissdpd ! */
if(!minissdpdsock)
minissdpdsock = "/var/run/minissdpd.sock";
@ -464,16 +477,78 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
return NULL;
}
/* reception */
memset(&sockudp_r, 0, sizeof(struct sockaddr_in));
sockudp_r.sin_family = AF_INET;
memset(&sockudp_r, 0, sizeof(struct sockaddr));
if(0/*ipv6*/) {
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
p->sin6_family = AF_INET6;
if(sameport)
sockudp_r.sin_port = htons(PORT);
sockudp_r.sin_addr.s_addr = INADDR_ANY;
/* emission */
memset(&sockudp_w, 0, sizeof(struct sockaddr_in));
sockudp_w.sin_family = AF_INET;
sockudp_w.sin_port = htons(PORT);
sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
p->sin6_port = htons(PORT);
p->sin6_addr = in6addr_any;//IN6ADDR_ANY_INIT;/*INADDR_ANY;*/
} else {
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
p->sin_family = AF_INET;
if(sameport)
p->sin_port = htons(PORT);
p->sin_addr.s_addr = INADDR_ANY;
}
#ifdef WIN32
/* This code could help us to use the right Network interface for
* SSDP multicast traffic */
/* Get IP associated with the index given in the ip_forward struct
* in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
if(GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR) {
DWORD dwRetVal = 0;
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
#ifdef DEBUG
IN_ADDR IPAddr;
#endif
int i;
#ifdef DEBUG
printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
#endif
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE));
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
free(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize);
}
if(pIPAddrTable) {
dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
#ifdef DEBUG
printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
#endif
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
#ifdef DEBUG
printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr);
printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize);
printf("\tType and State[%d]:", i);
printf("\n");
#endif
if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) {
/* Set the address of this interface to be used */
struct in_addr mc_if;
memset(&mc_if, 0, sizeof(mc_if));
mc_if.s_addr = pIPAddrTable->table[i].dwAddr;
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) {
PRINT_SOCKET_ERROR("setsockopt");
}
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr;
#ifndef DEBUG
break;
#endif
}
}
free(pIPAddrTable);
pIPAddrTable = NULL;
}
}
#endif
#ifdef WIN32
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
@ -489,7 +564,10 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
{
struct in_addr mc_if;
mc_if.s_addr = inet_addr(multicastif);
sockudp_r.sin_addr.s_addr = mc_if.s_addr;
if(0/*ipv6*/) {
} else {
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
}
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
{
PRINT_SOCKET_ERROR("setsockopt");
@ -497,7 +575,7 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
}
/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
if (bind(sudp, (struct sockaddr *)&sockudp_r, sizeof(struct sockaddr_in)) != 0)
if (bind(sudp, &sockudp_r, 0/*ipv6*/?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)) != 0)
{
PRINT_SOCKET_ERROR("bind");
closesocket(sudp);
@ -515,6 +593,13 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
n = snprintf(bufr, sizeof(bufr),
MSearchMsgFmt, deviceList[deviceIndex++], mx);
/*printf("Sending %s", bufr);*/
#ifdef NO_GETADDRINFO
/* the following code is not using getaddrinfo */
/* emission */
memset(&sockudp_w, 0, sizeof(struct sockaddr_in));
sockudp_w.sin_family = AF_INET;
sockudp_w.sin_port = htons(PORT);
sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
n = sendto(sudp, bufr, n, 0,
(struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in));
if (n < 0) {
@ -522,6 +607,32 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
closesocket(sudp);
return devlist;
}
#else /* #ifdef NO_GETADDRINFO */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // AF_INET6 or AF_INET
hints.ai_socktype = SOCK_DGRAM;
/*hints.ai_flags = */
if ((rv = getaddrinfo(UPNP_MCAST_ADDR, XSTR(PORT), &hints, &servinfo)) != 0) {
#ifdef WIN32
fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
#else
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
#endif
return devlist;
}
for(p = servinfo; p; p = p->ai_next) {
n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen);
if (n < 0) {
PRINT_SOCKET_ERROR("sendto");
continue;
}
}
freeaddrinfo(servinfo);
if(n < 0) {
closesocket(sudp);
return devlist;
}
#endif /* #ifdef NO_GETADDRINFO */
}
/* Waiting for SSDP REPLY packet to M-SEARCH */
n = ReceiveData(sudp, bufr, sizeof(bufr), delay);
@ -545,8 +656,21 @@ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize);
if(st&&descURL)
{
/*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
stsize, st, urlsize, descURL); */
#ifdef DEBUG
printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
stsize, st, urlsize, descURL);
#endif
for(tmp=devlist; tmp; tmp = tmp->pNext) {
if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
tmp->descURL[urlsize] == '\0' &&
memcmp(tmp->st, st, stsize) == 0 &&
tmp->st[stsize] == '\0')
break;
}
/* at the exit of the loop above, tmp is null if
* no duplicate device was found */
if(tmp)
continue;
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
tmp->pNext = devlist;
tmp->descURL = tmp->buffer;
@ -609,9 +733,9 @@ LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
n1 = strlen(descURL);
n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */
n2 = n1; n3 = n1;
n1 += strlen(data->scpdurl);
n2 += strlen(data->controlurl);
n3 += strlen(data->controlurl_CIF);
n1 += strlen(data->first.scpdurl);
n2 += strlen(data->first.controlurl);
n3 += strlen(data->CIF.controlurl);
urls->ipcondescURL = (char *)malloc(n1);
urls->controlURL = (char *)malloc(n2);
@ -626,19 +750,19 @@ LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
strncpy(urls->controlURL, urls->ipcondescURL, n2);
strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3);
url_cpy_or_cat(urls->ipcondescURL, data->scpdurl, n1);
url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1);
url_cpy_or_cat(urls->controlURL, data->controlurl, n2);
url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2);
url_cpy_or_cat(urls->controlURL_CIF, data->controlurl_CIF, n3);
url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3);
#ifdef DEBUG
printf("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL,
strlen(urls->ipcondescURL), n1);
printf("urls->controlURL='%s' %d n2=%d\n", urls->controlURL,
strlen(urls->controlURL), n2);
printf("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF,
strlen(urls->controlURL_CIF), n3);
printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL,
(unsigned)strlen(urls->ipcondescURL), n1);
printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL,
(unsigned)strlen(urls->controlURL), n2);
printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF,
(unsigned)strlen(urls->controlURL_CIF), n3);
#endif
}
@ -659,7 +783,7 @@ FreeUPNPUrls(struct UPNPUrls * urls)
int ReceiveData(int socket, char * data, int length, int timeout)
{
int n;
#ifndef WIN32
#if !defined(WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
struct pollfd fds[1]; /* for the poll */
#ifdef MINIUPNPC_IGNORE_EINTR
do {
@ -711,7 +835,7 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
char status[64];
unsigned int uptime;
status[0] = '\0';
UPNP_GetStatusInfo(urls->controlURL, data->servicetype,
UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
status, &uptime, NULL);
if(0 == strcmp("Connected", status))
{
@ -768,7 +892,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
parserootdesc(descXML, descXMLsize, data);
free(descXML);
descXML = NULL;
if(0==strcmp(data->servicetype_CIF,
if(0==strcmp(data->CIF.servicetype,
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
|| state >= 3 )
{
@ -782,6 +906,25 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
if((state >= 2) || UPNPIGD_IsConnected(urls, data))
return state;
FreeUPNPUrls(urls);
if(data->second.servicetype[0] != '\0') {
#ifdef DEBUG
printf("We tried %s, now we try %s !\n",
data->first.servicetype, data->second.servicetype);
#endif
/* swaping WANPPPConnection and WANIPConnection ! */
memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service));
memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service));
memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service));
GetUPNPUrls(urls, data, dev->descURL);
#ifdef DEBUG
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL,
UPNPIGD_IsConnected(urls, data));
#endif
if((state >= 2) || UPNPIGD_IsConnected(urls, data))
return state;
FreeUPNPUrls(urls);
}
}
memset(data, 0, sizeof(struct IGDdatas));
}

View File

@ -11,8 +11,6 @@
#include "declspec.h"
#include "igd_desc_parse.h"
#undef DEBUG
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -20,7 +20,7 @@
#define OS_STRING "Other/unknown"
#endif
#define MINIUPNPC_VERSION_STRING "1.4"
#define MINIUPNPC_VERSION_STRING "1.5"
#endif

View File

@ -1,140 +1,308 @@
/* $Id: miniwget.c,v 1.28 2009/10/10 19:15:35 nanard Exp $ */
/* $Id: miniwget.c,v 1.41 2010/12/12 23:52:02 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2009 Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
* LICENCE file provided in this distribution. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "miniupnpc.h"
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#define MAXHOSTNAMELEN 64
#define MIN(x,y) (((x)<(y))?(x):(y))
#define snprintf _snprintf
#define herror
#define socklen_t int
#else
#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 */
#include <unistd.h>
#include <sys/param.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 <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.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
#endif /* #else WIN32 */
#if defined(__sun) || defined(sun)
#define MIN(x,y) (((x)<(y))?(x):(y))
#endif
#include "miniupnpcstrings.h"
#include "miniwget.h"
#include "connecthostport.h"
/* miniwget2() :
* */
/*
* Read a HTTP response from a socket.
* Process Content-Length and Transfer-encoding headers.
*/
void *
getHTTPResponse(int s, int * size)
{
char buf[2048];
int n;
int headers = 1;
int chunked = 0;
int content_length = -1;
unsigned int chunksize = 0;
unsigned int bytestocopy = 0;
/* buffers : */
char * header_buf;
int header_buf_len = 2048;
int header_buf_used = 0;
char * content_buf;
int content_buf_len = 2048;
int content_buf_used = 0;
header_buf = malloc(header_buf_len);
content_buf = malloc(content_buf_len);
while((n = ReceiveData(s, buf, 2048, 5000)) > 0)
{
if(headers)
{
int i;
int linestart=0;
int colon=0;
int valuestart=0;
if(header_buf_used + n > header_buf_len) {
header_buf = realloc(header_buf, header_buf_used + n);
header_buf_len = header_buf_used + n;
}
memcpy(header_buf + header_buf_used, buf, n);
header_buf_used += n;
for(i = 0; i < (header_buf_used-3); i++) {
if(colon <= linestart && header_buf[i]==':')
{
colon = i;
while(i < (n-3)
&& (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')
{
if(colon > linestart && valuestart > colon)
{
#ifdef DEBUG
printf("header='%.*s', value='%.*s'\n",
colon-linestart, header_buf+linestart,
i-valuestart, header_buf+valuestart);
#endif
if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart))
{
content_length = atoi(header_buf+valuestart);
#ifdef DEBUG
printf("Content-Length: %d\n", content_length);
#endif
}
else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
&& 0==strncasecmp(buf+valuestart, "chunked", 7))
{
#ifdef DEBUG
printf("chunked transfer-encoding!\n");
#endif
chunked = 1;
}
}
linestart = i+2;
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;
}
}
}
}
}
else
{
/* content */
if(chunked)
{
int i = 0;
while(i < n)
{
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(buf[i] >= '0' && buf[i] <= '9')
chunksize = (chunksize << 4) + (buf[i] - '0');
else
chunksize = (chunksize << 4) + ((buf[i] | 32) - 'a' + 10);
i++;
}
while(i<n && buf[i] != '\r') i++; /* discarding chunk-extension */
if(i<n && buf[i] == '\r') i++;
if(i<n && buf[i] == '\n') i++;
#ifdef DEBUG
printf("chunksize = %u (%x)\n", chunksize, chunksize);
#endif
if(chunksize == 0)
{
#ifdef DEBUG
printf("end of HTTP content - %d %d\n", i, n);
/*printf("'%.*s'\n", n-i, buf+i);*/
#endif
goto end_of_stream;
}
}
bytestocopy = ((int)chunksize < n - i)?chunksize:(n - i);
if((int)(content_buf_used + bytestocopy) > content_buf_len)
{
content_buf = (char *)realloc((void *)content_buf,
content_buf_used + bytestocopy);
content_buf_len = content_buf_used + bytestocopy;
}
memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
content_buf_used += bytestocopy;
i += bytestocopy;
chunksize -= bytestocopy;
}
}
else
{
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;
}
memcpy(content_buf + content_buf_used, buf, n);
content_buf_used += n;
}
}
if(content_length > 0 && content_buf_used >= content_length)
{
#ifdef DEBUG
printf("End of HTTP content\n");
#endif
break;
}
}
end_of_stream:
free(header_buf); header_buf = NULL;
*size = content_buf_used;
if(content_buf_used == 0)
{
free(content_buf);
content_buf = NULL;
}
return content_buf;
}
/* miniwget3() :
* do all the work.
* Return NULL if something failed. */
static void *
miniwget2(const char * url, const char * host,
miniwget3(const char * url, 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, const char * httpversion)
{
char buf[2048];
int s;
struct sockaddr_in dest;
struct hostent *hp;
int n;
int len;
int sent;
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
struct timeval timeout;
#endif
*size = 0;
hp = gethostbyname(host);
if(hp==NULL)
{
herror(host);
return NULL;
}
/* memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length); */
memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
s = socket(PF_INET, SOCK_STREAM, 0);
s = connecthostport(host, port);
if(s < 0)
{
perror("socket");
return NULL;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
perror("setsockopt");
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
perror("setsockopt");
}
#endif
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
#ifdef MINIUPNPC_IGNORE_EINTR
while(n < 0 && errno == EINTR)
{
socklen_t len;
fd_set wset;
int err;
FD_ZERO(&wset);
FD_SET(s, &wset);
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
continue;
/*len = 0;*/
/*n = getpeername(s, NULL, &len);*/
len = sizeof(err);
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
perror("getsockopt");
closesocket(s);
return NULL;
}
if(err != 0) {
errno = err;
n = -1;
}
}
#endif
if(n<0)
{
perror("connect");
closesocket(s);
return NULL;
}
/* get address for caller ! */
if(addr_str)
{
struct sockaddr_in saddr;
struct sockaddr saddr;
socklen_t saddrlen;
saddrlen = sizeof(saddr);
if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
if(getsockname(s, &saddr, &saddrlen) < 0)
{
perror("getsockname");
}
else
{
#ifndef WIN32
inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
#else
#if defined(__amigaos__) && !defined(__amigaos4__)
/* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
* But his function make a string with the port : nn.nn.nn.nn:port */
/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
@ -142,7 +310,20 @@ miniwget2(const char * url, const char * host,
{
printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
}*/
strncpy(addr_str, inet_ntoa(saddr.sin_addr), addr_str_len);
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,
addr_str, addr_str_len,
NULL, 0,
NI_NUMERICHOST | NI_NUMERICSERV);
if(n != 0) {
#ifdef WIN32
fprintf(stderr, "getnameinfo() failed : %d\n", n);
#else
fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
#endif
}
#endif
}
#ifdef DEBUG
@ -151,13 +332,13 @@ miniwget2(const char * url, const char * host,
}
len = snprintf(buf, sizeof(buf),
"GET %s HTTP/1.1\r\n"
"GET %s HTTP/%s\r\n"
"Host: %s:%d\r\n"
"Connection: Close\r\n"
"User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
"\r\n",
path, host, port);
path, httpversion, host, port);
sent = 0;
/* sending the HTTP request */
while(sent < len)
@ -174,53 +355,36 @@ miniwget2(const char * url, const char * host,
sent += n;
}
}
{
int headers=1;
char * respbuffer = NULL;
int allreadyread = 0;
/*while((n = recv(s, buf, 2048, 0)) > 0)*/
while((n = ReceiveData(s, buf, 2048, 5000)) > 0)
{
if(headers)
{
int i=0;
while(i<n-3)
{
/* searching for the end of the HTTP headers */
if(buf[i]=='\r' && buf[i+1]=='\n'
&& buf[i+2]=='\r' && buf[i+3]=='\n')
{
headers = 0; /* end */
if(i<n-4)
{
/* Copy the content into respbuffet */
respbuffer = (char *)realloc((void *)respbuffer,
allreadyread+(n-i-4));
memcpy(respbuffer+allreadyread, buf + i + 4, n-i-4);
allreadyread += (n-i-4);
}
break;
}
i++;
}
}
else
{
respbuffer = (char *)realloc((void *)respbuffer,
allreadyread+n);
memcpy(respbuffer+allreadyread, buf, n);
allreadyread += n;
}
}
*size = allreadyread;
#ifdef DEBUG
printf("%d bytes read\n", *size);
#endif
closesocket(s);
return respbuffer;
}
return getHTTPResponse(s, size);
}
/* miniwget2() :
* Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
static void *
miniwget2(const char * url, const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len)
{
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 (*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");
}
*/
return respbuffer;
}
/* parseURL()
* arguments :
* url : source string not modified
@ -234,9 +398,6 @@ miniwget2(const char * url, const char * host,
int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
{
char * p1, *p2, *p3;
if (!url)
return 0;
p1 = strstr(url, "://");
if(!p1)
return 0;

View File

@ -1,4 +1,4 @@
/* $Id: miniwget.h,v 1.5 2007/01/29 20:27:23 nanard Exp $ */
/* $Id: miniwget.h,v 1.6 2010/12/09 16:11:33 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
@ -14,6 +14,8 @@
extern "C" {
#endif
LIBSPEC void * getHTTPResponse(int s, int * size);
LIBSPEC void * miniwget(const char *, int *);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int);

View File

@ -1,7 +1,7 @@
/* $Id: upnpcommands.c,v 1.25 2009/07/09 16:00:42 nanard Exp $ */
/* $Id: upnpcommands.c,v 1.26 2010/06/09 10:59:09 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2009 Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -28,7 +28,9 @@ UPNP_GetTotalBytesSent(const char * controlURL,
int bufsize = 4096;
unsigned int r = 0;
char * p;
simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, buffer, &bufsize) < 0) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");
@ -48,7 +50,9 @@ UPNP_GetTotalBytesReceived(const char * controlURL,
int bufsize = 4096;
unsigned int r = 0;
char * p;
simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, buffer, &bufsize) < 0) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");
@ -68,7 +72,9 @@ UPNP_GetTotalPacketsSent(const char * controlURL,
int bufsize = 4096;
unsigned int r = 0;
char * p;
simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, buffer, &bufsize) < 0) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");
@ -88,7 +94,9 @@ UPNP_GetTotalPacketsReceived(const char * controlURL,
int bufsize = 4096;
unsigned int r = 0;
char * p;
simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, buffer, &bufsize) < 0) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");
@ -117,7 +125,9 @@ UPNP_GetStatusInfo(const char * controlURL,
if(!status && !uptime)
return UPNPCOMMAND_INVALID_ARGS;
simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize) < 0) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
/*DisplayNameValueList(buffer, bufsize);*/
up = GetValueFromNameValueList(&pdata, "NewUptime");
@ -174,8 +184,10 @@ UPNP_GetConnectionTypeInfo(const char * controlURL,
if(!connectionType)
return UPNPCOMMAND_INVALID_ARGS;
simpleUPnPcommand(-1, controlURL, servicetype,
"GetConnectionTypeInfo", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype,
"GetConnectionTypeInfo", 0, buffer, &bufsize) < 0) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
p = GetValueFromNameValueList(&pdata, "NewConnectionType");
/*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
@ -218,9 +230,11 @@ UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
return UPNPCOMMAND_INVALID_ARGS;
/* shouldn't we use GetCommonLinkProperties ? */
simpleUPnPcommand(-1, controlURL, servicetype,
"GetCommonLinkProperties", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype,
"GetCommonLinkProperties", 0, buffer, &bufsize) < 0) {
/*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize);*/
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
/*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
@ -280,7 +294,9 @@ UPNP_GetExternalIPAddress(const char * controlURL,
if(!extIpAdd || !controlURL || !servicetype)
return UPNPCOMMAND_INVALID_ARGS;
simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize) < 0) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
/*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
@ -338,7 +354,10 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
AddPortMappingArgs[7].elt = "NewLeaseDuration";
AddPortMappingArgs[7].val = "0";
simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize) < 0) {
free(AddPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
/*buffer[bufsize] = '\0';*/
/*puts(buffer);*/
@ -379,9 +398,12 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
DeletePortMappingArgs[1].val = extPort;
DeletePortMappingArgs[2].elt = "NewProtocol";
DeletePortMappingArgs[2].val = proto;
simpleUPnPcommand(-1, controlURL, servicetype,
if(simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePortMapping",
DeletePortMappingArgs, buffer, &bufsize);
DeletePortMappingArgs, buffer, &bufsize) < 0 ) {
free(DeletePortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
resVal = GetValueFromNameValueList(&pdata, "errorCode");
@ -422,9 +444,12 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
GetPortMappingArgs[0].elt = "NewPortMappingIndex";
GetPortMappingArgs[0].val = index;
simpleUPnPcommand(-1, controlURL, servicetype,
if(simpleUPnPcommand(-1, controlURL, servicetype,
"GetGenericPortMappingEntry",
GetPortMappingArgs, buffer, &bufsize);
GetPortMappingArgs, buffer, &bufsize) < 0) {
free(GetPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
if(p && rHost)
@ -496,7 +521,9 @@ UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
int bufsize = 4096;
char* p;
int ret = UPNPCOMMAND_UNKNOWN_ERROR;
simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize);
if(simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize) < 0) {
return UPNPCOMMAND_HTTP_ERROR;
}
#ifdef DEBUG
DisplayNameValueList(buffer, bufsize);
#endif
@ -546,10 +573,12 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
GetPortMappingArgs[1].val = extPort;
GetPortMappingArgs[2].elt = "NewProtocol";
GetPortMappingArgs[2].val = proto;
simpleUPnPcommand(-1, controlURL, servicetype,
if(simpleUPnPcommand(-1, controlURL, servicetype,
"GetSpecificPortMappingEntry",
GetPortMappingArgs, buffer, &bufsize);
/*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */
GetPortMappingArgs, buffer, &bufsize) < 0) {
free(GetPortMappingArgs);
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);

View File

@ -1,7 +1,7 @@
/* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */
/* $Id: upnpcommands.h,v 1.18 2010/06/09 10:59:09 nanard Exp $ */
/* Miniupnp project : http://miniupnp.free.fr/
* Author : Thomas Bernard
* Copyright (c) 2005-2008 Thomas Bernard
* Copyright (c) 2005-2010 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided within this distribution */
#ifndef __UPNPCOMMANDS_H__
@ -14,6 +14,7 @@
#define UPNPCOMMAND_SUCCESS (0)
#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
#define UPNPCOMMAND_INVALID_ARGS (-2)
#define UPNPCOMMAND_HTTP_ERROR (-3)
#ifdef __cplusplus
extern "C" {

View File

@ -41,9 +41,9 @@
#include "netlog.h"
#include "netsocket.h"
#include "miniupnpc/miniwget.h"
#include "miniupnpc/miniupnpc.h"
#include "miniupnpc/upnpcommands.h"
#include <miniupnpc/miniwget.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
#include "lib/exceptionhandler/dumpinfo.h"
#include "src/multistat.h"
@ -964,9 +964,9 @@ static bool upnp_add_redirect(int port)
int r;
debug(LOG_NET, "upnp_add_redir(%d)\n", port);
UPNP_GetExternalIPAddress(urls.controlURL, data.servicetype, externalIP);
UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIP);
sprintf(port_str, "%d", port);
r = UPNP_AddPortMapping(urls.controlURL, data.servicetype,
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port_str, port_str, lanaddr, "Warzone 2100", "TCP", 0);
if (r != UPNPCOMMAND_SUCCESS)
{
@ -982,7 +982,7 @@ static void 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.servicetype, port_str, "TCP", 0);
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port_str, "TCP", 0);
}
void NETaddRedirects(void)