miniupnpc: update getDevicesFromMiniSSDPD() to process longer minissdpd responses
This commit is contained in:
parent
edd7c7bbdc
commit
27e2aa3841
|
@ -1,6 +1,10 @@
|
||||||
$Id: Changelog.txt,v 1.206 2015/05/22 10:23:47 nanard Exp $
|
$Id: Changelog.txt,v 1.206 2015/05/22 10:23:47 nanard Exp $
|
||||||
miniUPnP client Changelog.
|
miniUPnP client Changelog.
|
||||||
|
|
||||||
|
2015/06/16:
|
||||||
|
update getDevicesFromMiniSSDPD() to process longer minissdpd
|
||||||
|
responses
|
||||||
|
|
||||||
2015/05/22:
|
2015/05/22:
|
||||||
add searchalltypes param to upnpDiscoverDevices()
|
add searchalltypes param to upnpDiscoverDevices()
|
||||||
increments API_VERSION to 13
|
increments API_VERSION to 13
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */
|
/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */
|
||||||
/* Project : miniupnp
|
/* Project : miniupnp
|
||||||
* Author : Thomas BERNARD
|
* 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
|
* This software is subjet to the conditions detailed in the
|
||||||
* provided LICENCE file. */
|
* provided LICENCE file. */
|
||||||
#ifndef CODELENGTH_H_INCLUDED
|
#ifndef CODELENGTH_H_INCLUDED
|
||||||
|
@ -10,10 +10,30 @@
|
||||||
/* Encode length by using 7bit per Byte :
|
/* Encode length by using 7bit per Byte :
|
||||||
* Most significant bit of each byte specifies that the
|
* Most significant bit of each byte specifies that the
|
||||||
* following byte is part of the code */
|
* following byte is part of the code */
|
||||||
|
|
||||||
|
/* n : unsigned
|
||||||
|
* p : unsigned char *
|
||||||
|
*/
|
||||||
#define DECODELENGTH(n, p) n = 0; \
|
#define DECODELENGTH(n, p) n = 0; \
|
||||||
do { n = (n << 7) | (*p & 0x7f); } \
|
do { n = (n << 7) | (*p & 0x7f); } \
|
||||||
while((*(p++)&0x80) && (n<(1<<25)));
|
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) \
|
#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \
|
||||||
n = 0; \
|
n = 0; \
|
||||||
do { \
|
do { \
|
||||||
|
@ -21,11 +41,14 @@
|
||||||
n = (n << 7) | (*(p) & 0x7f); \
|
n = (n << 7) | (*(p) & 0x7f); \
|
||||||
} while((*((p)++)&0x80) && (n<(1<<25)));
|
} while((*((p)++)&0x80) && (n<(1<<25)));
|
||||||
|
|
||||||
|
|
||||||
|
/* n : unsigned
|
||||||
|
* p : unsigned char *
|
||||||
|
*/
|
||||||
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
|
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
|
||||||
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
|
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
|
||||||
if(n>=16384) *(p++) = (n >> 14) | 0x80; \
|
if(n>=16384) *(p++) = (n >> 14) | 0x80; \
|
||||||
if(n>=128) *(p++) = (n >> 7) | 0x80; \
|
if(n>=128) *(p++) = (n >> 7) | 0x80; \
|
||||||
*(p++) = n & 0x7f;
|
*(p++) = n & 0x7f;
|
||||||
|
|
||||||
#endif
|
#endif /* CODELENGTH_H_INCLUDED */
|
||||||
|
|
||||||
|
|
|
@ -46,14 +46,59 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
|
||||||
{
|
{
|
||||||
struct UPNPDev * tmp;
|
struct UPNPDev * tmp;
|
||||||
struct UPNPDev * devlist = NULL;
|
struct UPNPDev * devlist = NULL;
|
||||||
unsigned char buffer[4*1024]; /* is that enough ? */
|
unsigned char buffer[256];
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
unsigned char * p;
|
unsigned char * p;
|
||||||
unsigned char * url;
|
unsigned char * url;
|
||||||
|
unsigned int bufferindex;
|
||||||
unsigned int i, ndev;
|
unsigned int i, ndev;
|
||||||
unsigned int urlsize, stsize, usnsize, l;
|
unsigned int urlsize, stsize, usnsize, l;
|
||||||
int s;
|
int s;
|
||||||
struct sockaddr_un addr;
|
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);
|
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if(s < 0)
|
if(s < 0)
|
||||||
|
@ -62,6 +107,21 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
|
||||||
perror("socket(unix)");
|
perror("socket(unix)");
|
||||||
return NULL;
|
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;
|
addr.sun_family = AF_UNIX;
|
||||||
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
|
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
|
||||||
/* TODO : check if we need to handle the EINTR */
|
/* 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))
|
if(p + stsize > buffer + sizeof(buffer))
|
||||||
{
|
{
|
||||||
/* devtype is too long ! */
|
/* 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);
|
close(s);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -105,37 +169,67 @@ getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ndev = buffer[0];
|
ndev = buffer[0];
|
||||||
p = buffer + 1;
|
bufferindex = 1;
|
||||||
for(i = 0; i < ndev; i++)
|
for(i = 0; i < ndev; i++)
|
||||||
{
|
{
|
||||||
if(p+2>=buffer+sizeof(buffer))
|
DECODELENGTH_READ(urlsize, READ_BYTE_BUFFER);
|
||||||
|
if(n<=0) {
|
||||||
break;
|
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;
|
break;
|
||||||
url = p;
|
}
|
||||||
p += urlsize;
|
READ_COPY_BUFFER(url, urlsize);
|
||||||
DECODELENGTH(stsize, p);
|
if(n<=0) {
|
||||||
if(p+stsize+2>=buffer+sizeof(buffer))
|
free(url);
|
||||||
break;
|
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);
|
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
|
||||||
|
if(tmp == NULL) {
|
||||||
|
free(url);
|
||||||
|
break;
|
||||||
|
}
|
||||||
tmp->pNext = devlist;
|
tmp->pNext = devlist;
|
||||||
tmp->descURL = tmp->buffer;
|
tmp->descURL = tmp->buffer;
|
||||||
tmp->st = tmp->buffer + 1 + urlsize;
|
tmp->st = tmp->buffer + 1 + urlsize;
|
||||||
memcpy(tmp->buffer, url, urlsize);
|
memcpy(tmp->buffer, url, urlsize);
|
||||||
tmp->buffer[urlsize] = '\0';
|
tmp->buffer[urlsize] = '\0';
|
||||||
memcpy(tmp->buffer + urlsize + 1, p, stsize);
|
free(url);
|
||||||
p += stsize;
|
url = NULL;
|
||||||
|
READ_COPY_BUFFER(tmp->buffer + urlsize + 1, stsize);
|
||||||
|
if(n<=0) {
|
||||||
|
free(tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
tmp->buffer[urlsize+1+stsize] = '\0';
|
tmp->buffer[urlsize+1+stsize] = '\0';
|
||||||
tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */
|
tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */
|
||||||
devlist = tmp;
|
devlist = tmp;
|
||||||
/* added for compatibility with recent versions of MiniSSDPd
|
/* added for compatibility with recent versions of MiniSSDPd
|
||||||
* >= 2007/12/19 */
|
* >= 2007/12/19 */
|
||||||
DECODELENGTH(usnsize, p);
|
DECODELENGTH_READ(usnsize, READ_BYTE_BUFFER);
|
||||||
p += usnsize;
|
if(n<=0) {
|
||||||
if(p>buffer + sizeof(buffer))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf(" usnsize=%u\n", usnsize);
|
||||||
|
#endif /* DEBUG */
|
||||||
|
READ_DISCARD_BUFFER(usnsize);
|
||||||
|
if(n<=0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
close(s);
|
close(s);
|
||||||
return devlist;
|
return devlist;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,9 +63,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#define closesocket close
|
#define closesocket close
|
||||||
#endif /* #else _WIN32 */
|
#endif /* #else _WIN32 */
|
||||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||||
/* Amiga OS specific stuff */
|
/* Amiga OS specific stuff */
|
||||||
#define TIMEVAL struct timeval
|
#define TIMEVAL struct timeval
|
||||||
|
|
Loading…
Reference in New Issue