miniupnpc: update getDevicesFromMiniSSDPD() to process longer minissdpd responses

This commit is contained in:
Thomas Bernard 2015-06-16 17:33:59 +02:00
parent edd7c7bbdc
commit 27e2aa3841
4 changed files with 138 additions and 20 deletions

View File

@ -1,6 +1,10 @@
$Id: Changelog.txt,v 1.206 2015/05/22 10:23:47 nanard Exp $
miniUPnP client Changelog.
2015/06/16:
update getDevicesFromMiniSSDPD() to process longer minissdpd
responses
2015/05/22:
add searchalltypes param to upnpDiscoverDevices()
increments API_VERSION to 13

View File

@ -1,7 +1,7 @@
/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
* copyright (c) 2005-2011 Thomas Bernard
* copyright (c) 2005-2015 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#ifndef CODELENGTH_H_INCLUDED
@ -10,10 +10,30 @@
/* Encode length by using 7bit per Byte :
* Most significant bit of each byte specifies that the
* following byte is part of the code */
/* n : unsigned
* p : unsigned char *
*/
#define DECODELENGTH(n, p) n = 0; \
do { n = (n << 7) | (*p & 0x7f); } \
while((*(p++)&0x80) && (n<(1<<25)));
/* n : unsigned
* READ : function/macro to read one byte (unsigned char)
*/
#define DECODELENGTH_READ(n, READ) \
n = 0; \
do { \
unsigned char c; \
READ(c); \
n = (n << 7) | (c & 0x07f); \
if(!(c&0x80)) break; \
} while(n<(1<<25));
/* n : unsigned
* p : unsigned char *
* p_limit : unsigned char *
*/
#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \
n = 0; \
do { \
@ -21,11 +41,14 @@
n = (n << 7) | (*(p) & 0x7f); \
} while((*((p)++)&0x80) && (n<(1<<25)));
/* n : unsigned
* p : unsigned char *
*/
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
if(n>=16384) *(p++) = (n >> 14) | 0x80; \
if(n>=128) *(p++) = (n >> 7) | 0x80; \
*(p++) = n & 0x7f;
#endif
#endif /* CODELENGTH_H_INCLUDED */

View File

@ -46,14 +46,59 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
{
struct UPNPDev * tmp;
struct UPNPDev * devlist = NULL;
unsigned char buffer[4*1024]; /* is that enough ? */
unsigned char buffer[256];
ssize_t n;
unsigned char * p;
unsigned char * url;
unsigned int bufferindex;
unsigned int i, ndev;
unsigned int urlsize, stsize, usnsize, l;
int s;
struct sockaddr_un addr;
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
struct timeval timeout;
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
/* macros used to read from unix socket */
#define READ_BYTE_BUFFER(c) \
if(bufferindex >= n) { \
n = read(s, buffer, sizeof(buffer)); \
if(n<=0) break; \
bufferindex = 0; \
} \
c = buffer[bufferindex++];
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif /* MIN */
#define READ_COPY_BUFFER(dst, len) \
for(l = len, p = (unsigned char *)dst; l > 0; ) { \
unsigned int lcopy; \
if(bufferindex >= n) { \
n = read(s, buffer, sizeof(buffer)); \
if(n<=0) break; \
bufferindex = 0; \
} \
lcopy = MIN(l, (n - bufferindex)); \
memcpy(p, buffer + bufferindex, lcopy); \
l -= lcopy; \
p += lcopy; \
bufferindex += lcopy; \
}
#define READ_DISCARD_BUFFER(len) \
for(l = len; l > 0; ) { \
unsigned int lcopy; \
if(bufferindex >= n) { \
n = read(s, buffer, sizeof(buffer)); \
if(n<=0) break; \
bufferindex = 0; \
} \
lcopy = MIN(l, (n - bufferindex)); \
l -= lcopy; \
bufferindex += lcopy; \
}
s = socket(AF_UNIX, SOCK_STREAM, 0);
if(s < 0)
@ -62,6 +107,21 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
perror("socket(unix)");
return NULL;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout */
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 /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
/* TODO : check if we need to handle the EINTR */
@ -85,6 +145,10 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
if(p + stsize > buffer + sizeof(buffer))
{
/* devtype is too long ! */
#ifdef DEBUG
fprintf(stderr, "devtype is too long ! stsize=%u sizeof(buffer)=%u\n",
stsize, (unsigned)sizeof(buffer));
#endif /* DEBUG */
close(s);
return NULL;
}
@ -105,36 +169,66 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
return NULL;
}
ndev = buffer[0];
p = buffer + 1;
bufferindex = 1;
for(i = 0; i < ndev; i++)
{
if(p+2>=buffer+sizeof(buffer))
DECODELENGTH_READ(urlsize, READ_BYTE_BUFFER);
if(n<=0) {
break;
DECODELENGTH(urlsize, p);
if(p+urlsize+2>=buffer+sizeof(buffer))
}
#ifdef DEBUG
printf(" urlsize=%u", urlsize);
#endif /* DEBUG */
url = malloc(urlsize);
if(url == NULL) {
break;
url = p;
p += urlsize;
DECODELENGTH(stsize, p);
if(p+stsize+2>=buffer+sizeof(buffer))
}
READ_COPY_BUFFER(url, urlsize);
if(n<=0) {
free(url);
break;
}
DECODELENGTH_READ(stsize, READ_BYTE_BUFFER);
if(n<=0) {
free(url);
break;
}
#ifdef DEBUG
printf(" stsize=%u", stsize);
#endif /* DEBUG */
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
if(tmp == NULL) {
free(url);
break;
}
tmp->pNext = devlist;
tmp->descURL = tmp->buffer;
tmp->st = tmp->buffer + 1 + urlsize;
memcpy(tmp->buffer, url, urlsize);
tmp->buffer[urlsize] = '\0';
memcpy(tmp->buffer + urlsize + 1, p, stsize);
p += stsize;
free(url);
url = NULL;
READ_COPY_BUFFER(tmp->buffer + urlsize + 1, stsize);
if(n<=0) {
free(tmp);
break;
}
tmp->buffer[urlsize+1+stsize] = '\0';
tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */
devlist = tmp;
/* added for compatibility with recent versions of MiniSSDPd
* >= 2007/12/19 */
DECODELENGTH(usnsize, p);
p += usnsize;
if(p>buffer + sizeof(buffer))
DECODELENGTH_READ(usnsize, READ_BYTE_BUFFER);
if(n<=0) {
break;
}
#ifdef DEBUG
printf(" usnsize=%u\n", usnsize);
#endif /* DEBUG */
READ_DISCARD_BUFFER(usnsize);
if(n<=0) {
break;
}
}
close(s);
return devlist;

View File

@ -63,9 +63,6 @@
#include <errno.h>
#define closesocket close
#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