summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c')
-rw-r--r--3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c158
1 files changed, 105 insertions, 53 deletions
diff --git a/3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c b/3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c
index 0c31416..a75f55b 100644
--- a/3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c
+++ b/3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c
@@ -1,18 +1,19 @@
-/* $Id: miniwget.c,v 1.52 2011/06/17 22:59:42 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-2011 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>
-#ifdef WIN32
+#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
@@ -21,41 +22,43 @@
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define strncasecmp _memicmp
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#define strncasecmp memicmp
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
#endif /* #ifndef strncasecmp */
-#else /* #ifdef WIN32 */
+#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 <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
-#ifdef __ANDROID__
-#define MIN(x,y) (((x)<(y))?(x):(y))
-#endif
-
#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.
*/
@@ -68,26 +71,26 @@ getHTTPResponse(int s, int * size)
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];
- int chunksize_buf_index;
+ 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(endofheaders == 0)
{
int i;
int linestart=0;
int colon=0;
@@ -98,20 +101,20 @@ getHTTPResponse(int s, int * size)
}
memcpy(header_buf + header_buf_used, buf, n);
header_buf_used += n;
/* search for CR LF CR LF (end of headers)
* recognize also LF LF */
i = 0;
- while(i < (header_buf_used-1) && (endofheaders == 0)) {
+ while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
if(header_buf[i] == '\r') {
i++;
if(header_buf[i] == '\n') {
i++;
- if(i < header_buf_used && header_buf[i] == '\r') {
+ if(i < (int)header_buf_used && header_buf[i] == '\r') {
i++;
- if(i < header_buf_used && header_buf[i] == '\n') {
+ if(i < (int)header_buf_used && header_buf[i] == '\n') {
endofheaders = i+1;
}
}
}
} else if(header_buf[i] == '\n') {
i++;
@@ -156,18 +159,18 @@ getHTTPResponse(int s, int * size)
#ifdef DEBUG
printf("chunked transfer-encoding!\n");
#endif
chunked = 1;
}
}
- while(header_buf[i]=='\r' || header_buf[i] == '\n')
+ while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
i++;
linestart = i;
colon = linestart;
valuestart = 0;
- }
+ }
}
/* copy the remaining of the received data back to buf */
n = header_buf_used - endofheaders;
memcpy(buf, header_buf + endofheaders, n);
/* if(headers) */
}
@@ -195,13 +198,13 @@ getHTTPResponse(int s, int * size)
i++;
}
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') {
- int j;
+ 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);
@@ -222,53 +225,53 @@ getHTTPResponse(int s, int * size)
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)
+ bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
+ if((content_buf_used + bytestocopy) > content_buf_len)
{
- if(content_length >= content_buf_used + (int)bytestocopy) {
+ if(content_length >= (int)(content_buf_used + bytestocopy)) {
content_buf_len = content_length;
} else {
- content_buf_len = content_buf_used + (int)bytestocopy;
+ content_buf_len = content_buf_used + bytestocopy;
}
- content_buf = (char *)realloc((void *)content_buf,
+ content_buf = (char *)realloc((void *)content_buf,
content_buf_len);
}
memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
content_buf_used += bytestocopy;
i += bytestocopy;
chunksize -= bytestocopy;
}
}
else
{
/* not chunked */
if(content_length > 0
- && (content_buf_used + n) > content_length) {
+ && (int)(content_buf_used + n) > content_length) {
/* skipping additional bytes */
n = content_length - content_buf_used;
}
if(content_buf_used + n > content_buf_len)
{
- if(content_length >= content_buf_used + n) {
+ 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 = (char *)realloc((void *)content_buf,
content_buf_len);
}
memcpy(content_buf + content_buf_used, buf, n);
content_buf_used += n;
}
}
/* use the Content-Length header value if available */
- if(content_length > 0 && content_buf_used >= content_length)
+ if(content_length > 0 && (int)content_buf_used >= content_length)
{
#ifdef DEBUG
printf("End of HTTP content\n");
#endif
break;
}
@@ -285,26 +288,26 @@ end_of_stream:
}
/* miniwget3() :
* do all the work.
* Return NULL if something failed. */
static void *
-miniwget3(const char * url, const char * host,
+miniwget3(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
- const char * httpversion)
+ 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)
{
@@ -344,13 +347,13 @@ miniwget3(const char * url, const char * host,
* 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));
#endif
}
#endif
@@ -389,47 +392,55 @@ miniwget3(const char * url, const char * host,
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;
}
/* parseURL()
* arguments :
* 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)
return 0;
p1 = strstr(url, "://");
if(!p1)
@@ -439,13 +450,49 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
||(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 == ':')
@@ -489,38 +536,43 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
}
}
*path = p3;
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;
#ifdef DEBUG
- printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path);
+ printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
+ hostname, port, path, scope_id);
#endif
- return miniwget2(url, hostname, port, path, size, 0, 0);
+ 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;
#ifdef DEBUG
- printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path);
+ printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
+ hostname, port, path, scope_id);
#endif
- return miniwget2(url, hostname, port, path, size, addr, addrlen);
+ return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
}