[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[vidalia-svn] r4251: Update the included version of miniupnpc to 1.4.20100407. (vidalia/trunk/src/miniupnpc)
Author: edmanm
Date: 2010-04-09 19:17:13 -0400 (Fri, 09 Apr 2010)
New Revision: 4251
Added:
vidalia/trunk/src/miniupnpc/connecthostport.c
vidalia/trunk/src/miniupnpc/connecthostport.h
Modified:
vidalia/trunk/src/miniupnpc/CMakeLists.txt
vidalia/trunk/src/miniupnpc/igd_desc_parse.c
vidalia/trunk/src/miniupnpc/igd_desc_parse.h
vidalia/trunk/src/miniupnpc/minisoap.c
vidalia/trunk/src/miniupnpc/minissdpc.c
vidalia/trunk/src/miniupnpc/miniupnpc.c
vidalia/trunk/src/miniupnpc/miniupnpc.h
vidalia/trunk/src/miniupnpc/miniupnpcmodule.c
vidalia/trunk/src/miniupnpc/miniupnpcstrings.h
vidalia/trunk/src/miniupnpc/miniwget.c
vidalia/trunk/src/miniupnpc/minixml.c
vidalia/trunk/src/miniupnpc/upnpcommands.c
vidalia/trunk/src/miniupnpc/upnpreplyparse.h
Log:
Update the included version of miniupnpc to 1.4.20100407.
Modified: vidalia/trunk/src/miniupnpc/CMakeLists.txt
===================================================================
--- vidalia/trunk/src/miniupnpc/CMakeLists.txt 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/CMakeLists.txt 2010-04-09 23:17:13 UTC (rev 4251)
@@ -21,6 +21,7 @@
upnpcommands.c
upnperrors.c
upnpreplyparse.c
+ connecthostport.c
)
if (NOT WIN32)
set(miniupnpc_SRCS ${miniupnpc_SRCS} minissdpc.c)
Added: vidalia/trunk/src/miniupnpc/connecthostport.c
===================================================================
--- vidalia/trunk/src/miniupnpc/connecthostport.c (rev 0)
+++ vidalia/trunk/src/miniupnpc/connecthostport.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -0,0 +1,221 @@
+/* $Id: connecthostport.c,v 1.2 2010/04/05 00:08:15 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas Bernard
+ * Copyright (c) 2010 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided in this distribution. */
+
+/* use getaddrinfo() or gethostbyname()
+ * uncomment the following line in order to use gethostbyname() */
+/* #define USE_GETHOSTBYNAME */
+
+#include <string.h>
+#include <stdio.h>
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <io.h>
+#define snprintf _snprintf
+#define herror
+#define socklen_t int
+#else /* #ifdef WIN32 */
+#include <unistd.h>
+#include <errno.h>
+#define closesocket close
+#include <netdb.h>
+/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
+ * during the connect() call */
+#define MINIUPNPC_IGNORE_EINTR
+#ifndef USE_GETHOSTBYNAME
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* #ifndef USE_GETHOSTBYNAME */
+#endif /* #else WIN32 */
+
+/* definition of PRINT_SOCKET_ERROR */
+#ifdef WIN32
+#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#else
+#define PRINT_SOCKET_ERROR(x) perror(x)
+#endif
+
+#if defined(__amigaos__) || defined(__amigaos4__)
+#define herror(A) printf("%s\n", A)
+#endif
+
+#include "connecthostport.h"
+
+/* 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 s, n;
+#ifdef USE_GETHOSTBYNAME
+ struct sockaddr_in dest;
+ struct hostent *hp;
+#else /* #ifdef USE_GETHOSTBYNAME */
+ char port_str[8];
+ struct addrinfo *ai, *p;
+ struct addrinfo hints;
+#endif /* #ifdef USE_GETHOSTBYNAME */
+#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
+ struct timeval timeout;
+#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
+
+#ifdef USE_GETHOSTBYNAME
+ hp = gethostbyname(host);
+ if(hp == NULL)
+ {
+ herror(host);
+ return -1;
+ }
+ 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);
+ if(s < 0)
+ {
+ PRINT_SOCKET_ERROR("socket");
+ 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 /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
+ 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) {
+ PRINT_SOCKET_ERROR("getsockopt");
+ closesocket(s);
+ return -1;
+ }
+ if(err != 0) {
+ errno = err;
+ n = -1;
+ }
+ }
+#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
+ if(n<0)
+ {
+ PRINT_SOCKET_ERROR("connect");
+ closesocket(s);
+ return -1;
+ }
+#else /* #ifdef USE_GETHOSTBYNAME */
+ /* use getaddrinfo() instead of gethostbyname() */
+ memset(&hints, 0, sizeof(hints));
+ /* hints.ai_flags = AI_ADDRCONFIG; */
+#ifdef AI_NUMERICSERV
+ hints.ai_flags = AI_NUMERICSERV;
+#endif
+ hints.ai_socktype = SOCK_STREAM;
+ 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(n != 0)
+ {
+#ifdef WIN32
+ fprintf(stderr, "getaddrinfo() error : %d\n", n);
+#else
+ fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n));
+#endif
+ return -1;
+ }
+ s = -1;
+ for(p = ai; p; p = p->ai_next)
+ {
+ s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
+ if(s < 0)
+ continue;
+#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 /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
+ n = connect(s, p->ai_addr, p->ai_addrlen);
+#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);
+ freeaddrinfo(ai);
+ return -1;
+ }
+ if(err != 0) {
+ errno = err;
+ n = -1;
+ }
+ }
+#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
+ if(n < 0)
+ {
+ closesocket(s);
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+ freeaddrinfo(ai);
+ if(s < 0)
+ {
+ PRINT_SOCKET_ERROR("socket");
+ return -1;
+ }
+ if(n < 0)
+ {
+ PRINT_SOCKET_ERROR("connect");
+ return -1;
+ }
+#endif /* #ifdef USE_GETHOSTBYNAME */
+ return s;
+}
+
Property changes on: vidalia/trunk/src/miniupnpc/connecthostport.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: vidalia/trunk/src/miniupnpc/connecthostport.h
===================================================================
--- vidalia/trunk/src/miniupnpc/connecthostport.h (rev 0)
+++ vidalia/trunk/src/miniupnpc/connecthostport.h 2010-04-09 23:17:13 UTC (rev 4251)
@@ -0,0 +1,17 @@
+/* $Id: connecthostport.h,v 1.1 2010/04/04 23:21:03 nanard Exp $ */
+/* Project: miniupnp
+ * http://miniupnp.free.fr/
+ * Author: Thomas Bernard
+ * Copyright (c) 2010 Thomas Bernard
+ * This software is subjects to the conditions detailed
+ * in the LICENCE file provided within this distribution */
+#ifndef __CONNECTHOSTPORT_H__
+#define __CONNECTHOSTPORT_H__
+
+/* 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);
+
+#endif
+
Property changes on: vidalia/trunk/src/miniupnpc/connecthostport.h
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: vidalia/trunk/src/miniupnpc/igd_desc_parse.c
===================================================================
--- vidalia/trunk/src/miniupnpc/igd_desc_parse.c 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/igd_desc_parse.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -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.10 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.
- * */
+ * 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 @@
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 @@
"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 @@
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 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(" 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("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->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);
}
Modified: vidalia/trunk/src/miniupnpc/igd_desc_parse.h
===================================================================
--- vidalia/trunk/src/miniupnpc/igd_desc_parse.h 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/igd_desc_parse.h 2010-04-09 23:17:13 UTC (rev 4251)
@@ -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);
Modified: vidalia/trunk/src/miniupnpc/minisoap.c
===================================================================
--- vidalia/trunk/src/miniupnpc/minisoap.c 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/minisoap.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,7 +1,7 @@
-/* $Id: minisoap.c,v 1.16 2008/10/11 16:39:29 nanard Exp $ */
+/* $Id: minisoap.c,v 1.18 2009/12/04 11:29:18 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.
*
@@ -84,14 +84,17 @@
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/1.1\r\n" */
+ "POST %s HTTP/1.0\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"
Modified: vidalia/trunk/src/miniupnpc/minissdpc.c
===================================================================
--- vidalia/trunk/src/miniupnpc/minissdpc.c 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/minissdpc.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,7 +1,7 @@
-/* $Id: minissdpc.c,v 1.7 2008/12/18 17:45:48 nanard Exp $ */
+/* $Id: minissdpc.c,v 1.13 2009/12/04 16:57:29 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
- * copyright (c) 2005-2008 Thomas Bernard
+ * copyright (c) 2005-2009 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
/*#include <syslog.h>*/
@@ -10,10 +10,24 @@
#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 <ws2tcpip.h>
#include <io.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 {
+ uint16_t sun_family;
+ char sun_path[UNIX_PATH_LEN];
+};
#else
#include <sys/socket.h>
#include <sys/un.h>
@@ -47,6 +61,7 @@
}
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
+ /* TODO : check if we need to handle the EINTR */
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
{
/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
@@ -57,6 +72,12 @@
buffer[0] = 1; /* request type 1 : request devices/services by type */
p = buffer + 1;
l = stsize; CODELENGTH(l, p);
+ if(p + stsize > buffer + sizeof(buffer))
+ {
+ /* devtype is too long ! */
+ close(s);
+ return NULL;
+ }
memcpy(p, devtype, stsize);
p += stsize;
if(write(s, buffer, p - buffer) < 0)
Modified: vidalia/trunk/src/miniupnpc/miniupnpc.c
===================================================================
--- vidalia/trunk/src/miniupnpc/miniupnpc.c 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/miniupnpc.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,42 +1,79 @@
-/* $Id: miniupnpc.c,v 1.57 2008/12/18 17:46:36 nanard Exp $ */
+/* $Id: miniupnpc.c,v 1.78 2010/04/05 20:36:59 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas BERNARD
- * copyright (c) 2005-2007 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__)
+#ifndef __cplusplus
+#define _XOPEN_SOURCE 600
+#endif
+#endif
+#ifndef __BSD_VISIBLE
+#define __BSD_VISIBLE 1
+#endif
+#endif
+
+#ifdef __APPLE__
+#define _DARWIN_C_SOURCE
+#endif
+
+#include <stdlib.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#ifdef WIN32
/* Win32 Specific includes and defines */
#include <winsock2.h>
-#include <Ws2tcpip.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>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <netdb.h>
+#if !defined(__amigaos__) && !defined(__amigaos4__)
#include <poll.h>
-#include <netdb.h>
+#endif
+#include <strings.h>
+#include <errno.h>
#define closesocket close
+#define MINIUPNPC_IGNORE_EINTR
+#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());
@@ -49,7 +86,7 @@
#define SERVICEPREFIX2 'u'
/* root description parsing */
-void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
+LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
{
struct xmlparser parser;
/* xmlparser object */
@@ -66,7 +103,8 @@
#endif
}
-/* Content-length: nnn */
+/* 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";
@@ -101,6 +139,10 @@
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)
@@ -139,7 +181,6 @@
const char * action, struct UPNParg * args,
char * buffer, int * bufsize)
{
- struct sockaddr_in dest;
char hostname[MAXHOSTNAMELEN+1];
unsigned short port = 0;
char * path;
@@ -149,6 +190,7 @@
int buffree;
int n;
int contentlen, headerlen; /* for the response */
+
snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
if(args==NULL)
{
@@ -217,23 +259,12 @@
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;
}
- dest.sin_family = AF_INET;
- dest.sin_port = htons(port);
- dest.sin_addr.s_addr = inet_addr(hostname);
- if(connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr))<0)
- {
- PRINT_SOCKET_ERROR("connect");
- closesocket(s);
- *bufsize = 0;
- return -1;
- }
}
n = soapPostSubmit(s, path, hostname, port, soapact, soapbody);
@@ -340,7 +371,7 @@
* no devices was found.
* It is up to the caller to free the chained list
* delay is in millisecond (poll) */
-struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
+LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
const char * minissdpdsock, int sameport)
{
struct UPNPDev * tmp;
@@ -351,7 +382,7 @@
"HOST: " UPNP_MCAST_ADDR ":" XSTR(PORT) "\r\n"
"ST: %s\r\n"
"MAN: \"ssdp:discover\"\r\n"
- "MX: 3\r\n"
+ "MX: %u\r\n"
"\r\n";
static const char * const deviceList[] = {
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
@@ -364,9 +395,15 @@
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;
+ int rv;
+ struct addrinfo hints, *servinfo, *p;
+#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";
@@ -391,17 +428,67 @@
PRINT_SOCKET_ERROR("socket");
return NULL;
}
- /* reception */
- memset(&sockudp_r, 0, sizeof(struct sockaddr_in));
- sockudp_r.sin_family = AF_INET;
- 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);
+ /* reception */
+ 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)
+ 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;
+ }
+#if 0
+ /* 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);
+#endif
+#ifdef WIN32
+/* This code could help us to use the right Network interface for
+ * SSDP multicast traffic */
+/* TODO : 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;
+ IN_ADDR IPAddr;
+ int i;
+ printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
+ 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 );
+ printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
+ for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
+ 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");
+ }
+ free(pIPAddrTable);
+ pIPAddrTable = NULL;
+ }
+ }
+*/
+#endif
#ifdef WIN32
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
@@ -417,7 +504,10 @@
{
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");
@@ -425,13 +515,15 @@
}
/* 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);
return NULL;
}
+ /* Calculating maximum response time in seconds */
+ mx = ((unsigned int)delay) / 1000u;
/* receiving SSDP response packet */
for(n = 0;;)
{
@@ -439,8 +531,9 @@
{
/* sending the SSDP M-SEARCH packet */
n = snprintf(bufr, sizeof(bufr),
- MSearchMsgFmt, deviceList[deviceIndex++]);
+ MSearchMsgFmt, deviceList[deviceIndex++], mx);
/*printf("Sending %s", bufr);*/
+#if 0
n = sendto(sudp, bufr, n, 0,
(struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in));
if (n < 0) {
@@ -448,6 +541,31 @@
closesocket(sudp);
return devlist;
}
+#endif
+ 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;
+ }
}
/* Waiting for SSDP REPLY packet to M-SEARCH */
n = ReceiveData(sudp, bufr, sizeof(bufr), delay);
@@ -489,7 +607,7 @@
/* freeUPNPDevlist() should be used to
* free the chained list returned by upnpDiscover() */
-void freeUPNPDevlist(struct UPNPDev * devlist)
+LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist)
{
struct UPNPDev * next;
while(devlist)
@@ -525,7 +643,7 @@
/* Prepare the Urls for usage...
*/
-void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
+LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
const char * descURL)
{
char * p;
@@ -535,9 +653,9 @@
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);
@@ -552,23 +670,23 @@
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
}
-void
+LIBSPEC void
FreeUPNPUrls(struct UPNPUrls * urls)
{
if(!urls)
@@ -585,11 +703,17 @@
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 */
- fds[0].fd = socket;
- fds[0].events = POLLIN;
- n = poll(fds, 1, timeout);
+#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");
@@ -606,7 +730,6 @@
FD_SET(socket, &socketSet);
timeval.tv_sec = timeout / 1000;
timeval.tv_usec = (timeout % 1000) * 1000;
- /*n = select(0, &socketSet, NULL, NULL, &timeval);*/
n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
if(n < 0)
{
@@ -632,7 +755,7 @@
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))
{
@@ -655,7 +778,7 @@
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
* free allocated memory.
*/
-int
+LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls,
struct IGDdatas * data,
@@ -689,7 +812,7 @@
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 )
{
@@ -703,6 +826,25 @@
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));
}
Modified: vidalia/trunk/src/miniupnpc/miniupnpc.h
===================================================================
--- vidalia/trunk/src/miniupnpc/miniupnpc.h 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/miniupnpc.h 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,4 +1,4 @@
-/* $Id: miniupnpc.h,v 1.18 2008/09/25 18:02:50 nanard Exp $ */
+/* $Id: miniupnpc.h,v 1.19 2009/10/10 19:15:35 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
@@ -102,6 +102,10 @@
* read or if we timed out. Returns negative if there was an error. */
int ReceiveData(int socket, char * data, int length, int timeout);
+/* return 0 or 1 */
+LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
+
+
#ifdef __cplusplus
}
#endif
Modified: vidalia/trunk/src/miniupnpc/miniupnpcmodule.c
===================================================================
--- vidalia/trunk/src/miniupnpc/miniupnpcmodule.c 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/miniupnpcmodule.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,8 +1,8 @@
-/* $Id: miniupnpcmodule.c,v 1.13 2009/04/17 20:59:42 nanard Exp $*/
+/* $Id: miniupnpcmodule.c,v 1.14 2009/10/16 09:02:47 nanard Exp $*/
/* Project : miniupnp
* Author : Thomas BERNARD
* website : http://miniupnp.tuxfamily.org/
- * copyright (c) 2007 Thomas Bernard
+ * copyright (c) 2007-2009 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#include <Python.h>
@@ -72,11 +72,13 @@
{
freeUPNPDevlist(self->devlist);
self->devlist = 0;
- }
+ }
+ Py_BEGIN_ALLOW_THREADS
self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
0/* multicast if*/,
0/*minissdpd socket*/,
0/*sameport flag*/);
+ Py_END_ALLOW_THREADS
/* Py_RETURN_NONE ??? */
for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
i++;
@@ -87,8 +89,12 @@
static PyObject *
UPnP_selectigd(UPnPObject *self)
{
- if(UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
- self->lanaddr, sizeof(self->lanaddr)))
+ int r;
+Py_BEGIN_ALLOW_THREADS
+ r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
+ self->lanaddr, sizeof(self->lanaddr));
+Py_END_ALLOW_THREADS
+ if(r)
{
return Py_BuildValue("s", self->urls.controlURL);
}
@@ -103,33 +109,45 @@
static PyObject *
UPnP_totalbytesent(UPnPObject *self)
{
- return Py_BuildValue("I",
- UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
- self->data.servicetype_CIF));
+ UNSIGNED_INTEGER i;
+Py_BEGIN_ALLOW_THREADS
+ i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
+ self->data.servicetype_CIF);
+Py_END_ALLOW_THREADS
+ return Py_BuildValue("I", i);
}
static PyObject *
UPnP_totalbytereceived(UPnPObject *self)
{
- return Py_BuildValue("I",
- UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
- self->data.servicetype_CIF));
+ UNSIGNED_INTEGER i;
+Py_BEGIN_ALLOW_THREADS
+ i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
+ self->data.servicetype_CIF);
+Py_END_ALLOW_THREADS
+ return Py_BuildValue("I", i);
}
static PyObject *
UPnP_totalpacketsent(UPnPObject *self)
{
- return Py_BuildValue("I",
- UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
- self->data.servicetype_CIF));
+ UNSIGNED_INTEGER i;
+Py_BEGIN_ALLOW_THREADS
+ i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
+ self->data.servicetype_CIF);
+Py_END_ALLOW_THREADS
+ return Py_BuildValue("I", i);
}
static PyObject *
UPnP_totalpacketreceived(UPnPObject *self)
{
- return Py_BuildValue("I",
- UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
- self->data.servicetype_CIF));
+ UNSIGNED_INTEGER i;
+Py_BEGIN_ALLOW_THREADS
+ i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
+ self->data.servicetype_CIF);
+Py_END_ALLOW_THREADS
+ return Py_BuildValue("I", i);
}
static PyObject *
@@ -141,8 +159,10 @@
int r;
status[0] = '\0';
lastconnerror[0] = '\0';
+Py_BEGIN_ALLOW_THREADS
r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.servicetype,
status, &uptime, lastconnerror);
+Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
} else {
@@ -158,9 +178,11 @@
char connectionType[64];
int r;
connectionType[0] = '\0';
+Py_BEGIN_ALLOW_THREADS
r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
self->data.servicetype,
connectionType);
+Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
return Py_BuildValue("s", connectionType);
} else {
@@ -176,9 +198,11 @@
char externalIPAddress[16];
int r;
externalIPAddress[0] = '\0';
+Py_BEGIN_ALLOW_THREADS
r = UPNP_GetExternalIPAddress(self->urls.controlURL,
self->data.servicetype,
externalIPAddress);
+Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
return Py_BuildValue("s", externalIPAddress);
} else {
@@ -206,10 +230,12 @@
if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
&host, &iPort, &desc, &remoteHost))
return NULL;
+Py_BEGIN_ALLOW_THREADS
sprintf(extPort, "%hu", ePort);
sprintf(inPort, "%hu", iPort);
r = UPNP_AddPortMapping(self->urls.controlURL, self->data.servicetype,
extPort, inPort, host, desc, proto, remoteHost);
+Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS)
{
Py_RETURN_TRUE;
@@ -237,9 +263,11 @@
int r;
if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
return NULL;
+Py_BEGIN_ALLOW_THREADS
sprintf(extPort, "%hu", ePort);
r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.servicetype,
extPort, proto, remoteHost);
+Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
Py_RETURN_TRUE;
} else {
@@ -254,9 +282,11 @@
{
unsigned int n = 0;
int r;
+Py_BEGIN_ALLOW_THREADS
r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
self->data.servicetype,
&n);
+Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS) {
return Py_BuildValue("I", n);
} else {
@@ -279,11 +309,13 @@
unsigned short iPort;
if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto))
return NULL;
+Py_BEGIN_ALLOW_THREADS
sprintf(extPort, "%hu", ePort);
UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
self->data.servicetype,
extPort, proto,
intClient, intPort);
+Py_END_ALLOW_THREADS
if(intClient[0])
{
iPort = (unsigned short)atoi(intPort);
@@ -314,6 +346,7 @@
unsigned int dur;
if(!PyArg_ParseTuple(args, "i", &i))
return NULL;
+Py_BEGIN_ALLOW_THREADS
snprintf(index, sizeof(index), "%d", i);
rHost[0] = '\0'; enabled[0] = '\0';
duration[0] = '\0'; desc[0] = '\0';
@@ -324,6 +357,7 @@
extPort, intClient, intPort,
protocol, desc, enabled, rHost,
duration);
+Py_END_ALLOW_THREADS
if(r==UPNPCOMMAND_SUCCESS)
{
ePort = (unsigned short)atoi(extPort);
Modified: vidalia/trunk/src/miniupnpc/miniupnpcstrings.h
===================================================================
--- vidalia/trunk/src/miniupnpc/miniupnpcstrings.h 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/miniupnpcstrings.h 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,15 +1,15 @@
-/* $Id: miniupnpcstrings.h,v 1.2 2008/10/14 17:39:04 nanard Exp $ */
+/* $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-2008 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__
-#define OS_STRING "Debian/4.0"
-#define MINIUPNPC_VERSION_STRING "1.2"
+#define OS_STRING "Darwin/10.3.0"
+#define MINIUPNPC_VERSION_STRING "1.4"
#endif
Modified: vidalia/trunk/src/miniupnpc/miniwget.c
===================================================================
--- vidalia/trunk/src/miniupnpc/miniwget.c 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/miniwget.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,39 +1,49 @@
-/* $Id: miniwget.c,v 1.22 2009/02/28 10:36:35 nanard Exp $ */
+/* $Id: miniwget.c,v 1.36 2010/04/05 12:34:05 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2005 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 "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
+#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 <arpa/inet.h>
#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
#define closesocket close
-#endif
+/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
+ * during the connect() call */
+#define MINIUPNPC_IGNORE_EINTR
+#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() :
- * */
+ * do all the work.
+ * Return NULL if something failed. */
static void *
miniwget2(const char * url, const char * host,
unsigned short port, const char * path,
@@ -41,44 +51,29 @@
{
char buf[2048];
int s;
- struct sockaddr_in dest;
- struct hostent *hp;
+ int n;
+ int len;
+ int sent;
+
*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;
- }
- dest.sin_family = AF_INET;
- dest.sin_port = htons(port);
- if(connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in))<0)
- {
- perror("connect");
- closesocket(s);
- return NULL;
- }
/* get address for caller ! */
if(addr_str)
{
- struct sockaddr_in saddr;
- socklen_t len;
+ struct sockaddr saddr;
+ socklen_t saddrlen;
- len = sizeof(saddr);
- getsockname(s, (struct sockaddr *)&saddr, &len);
-#ifndef WIN32
- inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
-#else
+ saddrlen = sizeof(saddr);
+ if(getsockname(s, &saddr, &saddrlen) < 0)
+ {
+ perror("getsockname");
+ }
+ 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),
@@ -86,25 +81,56 @@
{
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
printf("address miniwget : %s\n", addr_str);
#endif
}
- snprintf(buf, sizeof(buf),
- "GET %s HTTP/1.1\r\n"
+ len = snprintf(buf, sizeof(buf),
+ "GET %s HTTP/1.0\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);
- /*write(s, buf, strlen(buf));*/
- send(s, buf, strlen(buf), 0);
+ sent = 0;
+ /* sending the HTTP request */
+ while(sent < len)
{
- int n, headers=1;
+ n = send(s, buf+sent, len-sent, 0);
+ if(n < 0)
+ {
+ perror("send");
+ closesocket(s);
+ return NULL;
+ }
+ else
+ {
+ sent += n;
+ }
+ }
+ {
+ /* TODO : in order to support HTTP/1.1, chunked transfer encoding
+ * must be supported. That means parsing of headers must be
+ * added. */
+ int headers=1;
char * respbuffer = NULL;
int allreadyread = 0;
/*while((n = recv(s, buf, 2048, 0)) > 0)*/
@@ -115,12 +141,14 @@
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);
Modified: vidalia/trunk/src/miniupnpc/minixml.c
===================================================================
--- vidalia/trunk/src/miniupnpc/minixml.c 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/minixml.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,10 +1,10 @@
-/* $Id: minixml.c,v 1.6 2007/05/15 18:14:08 nanard Exp $ */
+/* $Id: minixml.c,v 1.7 2009/10/10 19:15:35 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-2007, Thomas BERNARD
+Copyright (c) 2005-2009, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,7 @@
/* parseatt : used to parse the argument list
* return 0 (false) in case of success and -1 (true) if the end
* of the xmlbuffer is reached. */
-int parseatt(struct xmlparser * p)
+static int parseatt(struct xmlparser * p)
{
const char * attname;
int attnamelen;
@@ -106,7 +106,7 @@
/* parseelt parse the xml stream and
* call the callback functions when needed... */
-void parseelt(struct xmlparser * p)
+static void parseelt(struct xmlparser * p)
{
int i;
const char * elementname;
Modified: vidalia/trunk/src/miniupnpc/upnpcommands.c
===================================================================
--- vidalia/trunk/src/miniupnpc/upnpcommands.c 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/upnpcommands.c 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,4 +1,4 @@
-/* $Id: upnpcommands.c,v 1.24 2009/04/17 21:21:19 nanard Exp $ */
+/* $Id: upnpcommands.c,v 1.25 2009/07/09 16:00:42 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2009 Thomas Bernard
@@ -19,7 +19,7 @@
/*
* */
-UNSIGNED_INTEGER
+LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesSent(const char * controlURL,
const char * servicetype)
{
@@ -39,7 +39,7 @@
/*
* */
-UNSIGNED_INTEGER
+LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalBytesReceived(const char * controlURL,
const char * servicetype)
{
@@ -59,7 +59,7 @@
/*
* */
-UNSIGNED_INTEGER
+LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsSent(const char * controlURL,
const char * servicetype)
{
@@ -79,7 +79,7 @@
/*
* */
-UNSIGNED_INTEGER
+LIBSPEC UNSIGNED_INTEGER
UPNP_GetTotalPacketsReceived(const char * controlURL,
const char * servicetype)
{
@@ -99,11 +99,12 @@
/* UPNP_GetStatusInfo() call the corresponding UPNP method
* returns the current status and uptime */
-int UPNP_GetStatusInfo(const char * controlURL,
- const char * servicetype,
- char * status,
- unsigned int * uptime,
- char * lastconnerror)
+LIBSPEC int
+UPNP_GetStatusInfo(const char * controlURL,
+ const char * servicetype,
+ char * status,
+ unsigned int * uptime,
+ char * lastconnerror)
{
struct NameValueParserData pdata;
char buffer[4096];
@@ -159,9 +160,10 @@
/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
* returns the connection type */
-int UPNP_GetConnectionTypeInfo(const char * controlURL,
- const char * servicetype,
- char * connectionType)
+LIBSPEC int
+UPNP_GetConnectionTypeInfo(const char * controlURL,
+ const char * servicetype,
+ char * connectionType)
{
struct NameValueParserData pdata;
char buffer[4096];
@@ -198,7 +200,11 @@
* One of the values can be null
* Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
* We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
-int UPNP_GetLinkLayerMaxBitRates(const char * controlURL, const char * servicetype, unsigned int * bitrateDown, unsigned int* bitrateUp)
+LIBSPEC int
+UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
+ const char * servicetype,
+ unsigned int * bitrateDown,
+ unsigned int* bitrateUp)
{
struct NameValueParserData pdata;
char buffer[4096];
@@ -226,16 +232,14 @@
if(down && up)
ret = UPNPCOMMAND_SUCCESS;
- if(bitrateDown)
- {
+ if(bitrateDown) {
if(down)
sscanf(down,"%u",bitrateDown);
else
*bitrateDown = 0;
}
- if(bitrateUp)
- {
+ if(bitrateUp) {
if(up)
sscanf(up,"%u",bitrateUp);
else
@@ -262,9 +266,10 @@
* 402 Invalid Args - See UPnP Device Architecture section on Control.
* 501 Action Failed - See UPnP Device Architecture section on Control.
*/
-int UPNP_GetExternalIPAddress(const char * controlURL,
- const char * servicetype,
- char * extIpAdd)
+LIBSPEC int
+UPNP_GetExternalIPAddress(const char * controlURL,
+ const char * servicetype,
+ char * extIpAdd)
{
struct NameValueParserData pdata;
char buffer[4096];
@@ -297,7 +302,7 @@
return ret;
}
-int
+LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
@@ -351,7 +356,7 @@
return ret;
}
-int
+LIBSPEC int
UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
const char * extPort, const char * proto,
const char * remoteHost)
@@ -391,17 +396,18 @@
return ret;
}
-int UPNP_GetGenericPortMappingEntry(const char * controlURL,
- const char * servicetype,
- const char * index,
- char * extPort,
- char * intClient,
- char * intPort,
- char * protocol,
- char * desc,
- char * enabled,
- char * rHost,
- char * duration)
+LIBSPEC int
+UPNP_GetGenericPortMappingEntry(const char * controlURL,
+ const char * servicetype,
+ const char * index,
+ char * extPort,
+ char * intClient,
+ char * intPort,
+ char * protocol,
+ char * desc,
+ char * enabled,
+ char * rHost,
+ char * duration)
{
struct NameValueParserData pdata;
struct UPNParg * GetPortMappingArgs;
@@ -480,7 +486,10 @@
return r;
}
-int UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries)
+LIBSPEC int
+UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
+ const char * servicetype,
+ unsigned int * numEntries)
{
struct NameValueParserData pdata;
char buffer[4096];
@@ -513,7 +522,7 @@
/* 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 */
-int
+LIBSPEC int
UPNP_GetSpecificPortMappingEntry(const char * controlURL,
const char * servicetype,
const char * extPort,
Modified: vidalia/trunk/src/miniupnpc/upnpreplyparse.h
===================================================================
--- vidalia/trunk/src/miniupnpc/upnpreplyparse.h 2010-04-09 06:59:53 UTC (rev 4250)
+++ vidalia/trunk/src/miniupnpc/upnpreplyparse.h 2010-04-09 23:17:13 UTC (rev 4251)
@@ -1,14 +1,14 @@
-/* $Id: upnpreplyparse.h,v 1.8 2008/02/21 13:05:27 nanard Exp $ */
+/* $Id: upnpreplyparse.h,v 1.10 2009/07/09 16:01:50 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * (c) 2006 Thomas Bernard
+ * (c) 2006-2009 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef __UPNPREPLYPARSE_H__
#define __UPNPREPLYPARSE_H__
-#if defined(NO_SYS_QUEUE_H) || defined(WIN32)
+#if defined(NO_SYS_QUEUE_H) || defined(WIN32) || defined(__HAIKU__)
#include "bsdqueue.h"
#else
#include <sys/queue.h>