[Freeswitch-svn] [commit] r13510 - in freeswitch/trunk/libs: libnatpmp miniupnpc miniupnpc/man3

FreeSWITCH SVN mikej at freeswitch.org
Fri May 29 13:14:46 PDT 2009


Author: mikej
Date: Fri May 29 15:14:45 2009
New Revision: 13510

Log:
add pnp libs

Added:
   freeswitch/trunk/libs/libnatpmp/
   freeswitch/trunk/libs/libnatpmp/Changelog.txt
   freeswitch/trunk/libs/libnatpmp/LICENCE
   freeswitch/trunk/libs/libnatpmp/Makefile
   freeswitch/trunk/libs/libnatpmp/build.bat
   freeswitch/trunk/libs/libnatpmp/declspec.h
   freeswitch/trunk/libs/libnatpmp/getgateway.c
   freeswitch/trunk/libs/libnatpmp/getgateway.h
   freeswitch/trunk/libs/libnatpmp/natpmp.c
   freeswitch/trunk/libs/libnatpmp/natpmp.def
   freeswitch/trunk/libs/libnatpmp/natpmp.h
   freeswitch/trunk/libs/libnatpmp/natpmpc.c
   freeswitch/trunk/libs/libnatpmp/testgetgateway.c
   freeswitch/trunk/libs/libnatpmp/wingettimeofday.c
   freeswitch/trunk/libs/miniupnpc/
   freeswitch/trunk/libs/miniupnpc/Changelog.txt
   freeswitch/trunk/libs/miniupnpc/LICENCE
   freeswitch/trunk/libs/miniupnpc/Makefile
   freeswitch/trunk/libs/miniupnpc/Makefile.mingw
   freeswitch/trunk/libs/miniupnpc/README
   freeswitch/trunk/libs/miniupnpc/bsdqueue.h
   freeswitch/trunk/libs/miniupnpc/codelength.h
   freeswitch/trunk/libs/miniupnpc/declspec.h
   freeswitch/trunk/libs/miniupnpc/igd_desc_parse.c
   freeswitch/trunk/libs/miniupnpc/igd_desc_parse.h
   freeswitch/trunk/libs/miniupnpc/man3/
   freeswitch/trunk/libs/miniupnpc/man3/miniupnpc.3
   freeswitch/trunk/libs/miniupnpc/mingw32make.bat
   freeswitch/trunk/libs/miniupnpc/minisoap.c
   freeswitch/trunk/libs/miniupnpc/minisoap.h
   freeswitch/trunk/libs/miniupnpc/minissdpc.c
   freeswitch/trunk/libs/miniupnpc/minissdpc.h
   freeswitch/trunk/libs/miniupnpc/miniupnpc.c
   freeswitch/trunk/libs/miniupnpc/miniupnpc.def
   freeswitch/trunk/libs/miniupnpc/miniupnpc.h
   freeswitch/trunk/libs/miniupnpc/miniupnpcmodule.c
   freeswitch/trunk/libs/miniupnpc/miniupnpcstrings.h
   freeswitch/trunk/libs/miniupnpc/miniwget.c
   freeswitch/trunk/libs/miniupnpc/miniwget.h
   freeswitch/trunk/libs/miniupnpc/minixml.c
   freeswitch/trunk/libs/miniupnpc/minixml.h
   freeswitch/trunk/libs/miniupnpc/minixmlvalid.c
   freeswitch/trunk/libs/miniupnpc/pymoduletest.py
   freeswitch/trunk/libs/miniupnpc/setup.py
   freeswitch/trunk/libs/miniupnpc/setupmingw32.py   (contents, props changed)
   freeswitch/trunk/libs/miniupnpc/testigddescparse.c
   freeswitch/trunk/libs/miniupnpc/testminixml.c
   freeswitch/trunk/libs/miniupnpc/testupnpigd.py   (contents, props changed)
   freeswitch/trunk/libs/miniupnpc/testupnpreplyparse.c
   freeswitch/trunk/libs/miniupnpc/updateminiupnpcstrings.sh   (contents, props changed)
   freeswitch/trunk/libs/miniupnpc/upnpc.c
   freeswitch/trunk/libs/miniupnpc/upnpcommands.c
   freeswitch/trunk/libs/miniupnpc/upnpcommands.h
   freeswitch/trunk/libs/miniupnpc/upnperrors.c
   freeswitch/trunk/libs/miniupnpc/upnperrors.h
   freeswitch/trunk/libs/miniupnpc/upnpreplyparse.c
   freeswitch/trunk/libs/miniupnpc/upnpreplyparse.h

Added: freeswitch/trunk/libs/libnatpmp/Changelog.txt
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/Changelog.txt	Fri May 29 15:14:45 2009
@@ -0,0 +1,43 @@
+$Id: Changelog.txt,v 1.14 2009/03/10 10:15:30 nanard Exp $
+
+2009/03/10:
+  Trying to have windows get gateway working if not using DHCP
+
+2009/02/27:
+  dont include declspec.h if not under WIN32.
+
+2009/01/23:
+  Prefixed the libraries name with lib
+
+2008/10/06:
+  Fixed a memory leak in getdefaultgateway() (USE_SYSCTL_NET_ROUTE)
+
+2008/07/03:
+  Adding WIN32 code from Robbie Hanson
+
+2008/06/30:
+  added a Solaris implementation for getgateway().
+  added a LICENCE file to the distribution
+
+2008/05/29:
+  Anonymous unions are forbidden in ANSI C. That was causing problems with
+  non-GCC compilers.
+
+2008/04/28:
+  introduced strnatpmperr()
+  improved natpmpc.c sample
+  make install now install the binary
+
+2007/12/13:
+  Fixed getgateway.c for working under OS X ;)
+  Fixed values for NATPMP_PROTOCOL_TCP and NATPMP_PROTOCOL_UDP
+
+2007/12/11:
+  Fixed getgateway.c for compilation under Mac OS X
+
+2007/12/01:
+  added some comments in .h
+
+2007/11/30:
+  implemented almost everything
+

Added: freeswitch/trunk/libs/libnatpmp/LICENCE
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/LICENCE	Fri May 29 15:14:45 2009
@@ -0,0 +1,26 @@
+Copyright (c) 2007-2008, Thomas BERNARD 
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * The name of the author may not be used to endorse or promote products
+	  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+

Added: freeswitch/trunk/libs/libnatpmp/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/Makefile	Fri May 29 15:14:45 2009
@@ -0,0 +1,75 @@
+# $Id: Makefile,v 1.7 2009/01/23 19:05:04 nanard Exp $
+# This Makefile is designed for use with GNU make
+# libnatpmp
+# (c) 2007-2009 Thomas Bernard
+# http://miniupnp.free.fr/libnatpmp.html
+
+CC = gcc
+INSTALL = install
+
+# APIVERSION is used in soname
+APIVERSION = 0
+CFLAGS = -O -fPIC -Wall -DENABLE_STRNATPMPERR
+
+LIBOBJS = natpmp.o getgateway.o
+
+OBJS = $(LIBOBJS) testgetgateway.o natpmpc.o
+
+STATICLIB = libnatpmp.a
+SHAREDLIB = libnatpmp.so
+SONAME = $(SHAREDLIB).$(APIVERSION)
+
+HEADERS = natpmp.h
+
+EXECUTABLES = testgetgateway natpmpc-shared natpmpc-static
+
+INSTALLPREFIX ?= $(PREFIX)/usr
+INSTALLDIRINC = $(INSTALLPREFIX)/include
+INSTALLDIRLIB = $(INSTALLPREFIX)/lib
+INSTALLDIRBIN = $(INSTALLPREFIX)/bin
+
+.PHONY:	all clean depend install cleaninstall
+
+all: $(STATICLIB) $(SHAREDLIB) $(EXECUTABLES)
+
+clean:
+	$(RM) $(OBJS) $(EXECUTABLES) $(STATICLIB) $(SHAREDLIB)
+
+depend:
+	makedepend -f$(MAKEFILE_LIST) -Y $(OBJS:.o=.c) 2>/dev/null
+
+install:	$(HEADERS) $(STATICLIB) $(SHAREDLIB)
+	$(INSTALL) -d $(INSTALLDIRINC)
+	$(INSTALL) --mode=644 $(HEADERS) $(INSTALLDIRINC)
+	$(INSTALL) -d $(INSTALLDIRLIB)
+	$(INSTALL) --mode=644 $(STATICLIB) $(INSTALLDIRLIB)
+	$(INSTALL) --mode=644 $(SHAREDLIB) $(INSTALLDIRLIB)/$(SONAME)
+	$(INSTALL) --mode=755 natpmpc-shared $(INSTALLDIRBIN)/natpmpc
+	ln --symbolic --force $(SONAME) $(INSTALLDIRLIB)/$(SHAREDLIB)
+
+cleaninstall:
+	$(RM) $(addprefix $(INSTALLDIRINC), $(HEADERS))
+	$(RM) $(INSTALLDIRLIB)/$(SONAME)
+	$(RM) $(INSTALLDIRLIB)/$(SHAREDLIB)
+	$(RM) $(INSTALLDIRLIB)/$(STATICLIB)
+
+testgetgateway:	testgetgateway.o getgateway.o
+
+natpmpc-static:	natpmpc.o $(STATICLIB)
+	$(CC) -o $@ $^
+
+natpmpc-shared:	natpmpc.o $(SHAREDLIB)
+	$(CC) -o $@ $^
+
+$(STATICLIB):	$(LIBOBJS)
+	$(AR) crs $@ $?
+
+$(SHAREDLIB):	$(LIBOBJS)
+	$(CC) -shared -Wl,-soname,$(SONAME) -o $@ $^
+
+# DO NOT DELETE
+
+natpmp.o: natpmp.h getgateway.h
+getgateway.o: getgateway.h
+testgetgateway.o: getgateway.h
+natpmpc.o: natpmp.h

Added: freeswitch/trunk/libs/libnatpmp/build.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/build.bat	Fri May 29 15:14:45 2009
@@ -0,0 +1,17 @@
+ at echo Compile getgateway
+gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR getgateway.c
+gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR testgetgateway.c
+gcc -o testgetgateway getgateway.o testgetgateway.o -lws2_32
+
+ at echo Compile natpmp:
+gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR getgateway.c
+gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR natpmp.c
+gcc -c -Wall -Os -DWIN32 -DSTATICLIB -DENABLE_STRNATPMPERR natpmpc.c
+gcc -c -Wall -Os -DWIN32 wingettimeofday.c
+gcc -o natpmpc getgateway.o natpmp.o natpmpc.o wingettimeofday.o -lws2_32
+
+ at echo Create natpmp.dll:
+gcc -c -Wall -Os -DWIN32 -DENABLE_STRNATPMPERR -DNATPMP_EXPORTS getgateway.c
+gcc -c -Wall -Os -DWIN32 -DENABLE_STRNATPMPERR -DNATPMP_EXPORTS natpmp.c
+dllwrap -k --driver-name gcc --def natpmp.def --output-def natpmp.dll.def --implib natpmp.lib -o natpmp.dll getgateway.o natpmp.o wingettimeofday.o -lws2_32
+

Added: freeswitch/trunk/libs/libnatpmp/declspec.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/declspec.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,15 @@
+#ifndef __DECLSPEC_H__
+#define __DECLSPEC_H__
+
+#if defined(WIN32) && !defined(STATICLIB)
+	#ifdef NATPMP_EXPORTS
+		#define LIBSPEC __declspec(dllexport)
+	#else
+		#define LIBSPEC __declspec(dllimport)
+	#endif
+#else
+	#define LIBSPEC
+#endif
+
+#endif
+

Added: freeswitch/trunk/libs/libnatpmp/getgateway.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/getgateway.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,423 @@
+/* $Id: getgateway.c,v 1.13 2009/03/10 10:15:31 nanard Exp $ */
+/* libnatpmp
+ * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp at free.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+#include <stdio.h>
+#include <ctype.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#endif
+#include <sys/param.h>
+/* There is no portable method to get the default route gateway.
+ * So below are three differents functions implementing this.
+ * Parsing /proc/net/route is for linux.
+ * sysctl is the way to access such informations on BSD systems.
+ * Many systems should provide route information through raw PF_ROUTE
+ * sockets. */
+#ifdef __linux__
+#define USE_PROC_NET_ROUTE
+#undef USE_SOCKET_ROUTE
+#undef USE_SYSCTL_NET_ROUTE
+#endif
+
+#ifdef BSD
+#undef USE_PROC_NET_ROUTE
+#define USE_SOCKET_ROUTE
+#undef USE_SYSCTL_NET_ROUTE
+#endif
+
+#ifdef __APPLE__
+#undef USE_PROC_NET_ROUTE
+#undef USE_SOCKET_ROUTE
+#define USE_SYSCTL_NET_ROUTE
+#endif
+
+#if (defined(sun) && defined(__SVR4))
+#undef USE_PROC_NET_ROUTE
+#define USE_SOCKET_ROUTE
+#undef USE_SYSCTL_NET_ROUTE
+#endif
+
+#ifdef WIN32
+#undef USE_PROC_NET_ROUTE
+#undef USE_SOCKET_ROUTE
+#undef USE_SYSCTL_NET_ROUTE
+#define USE_WIN32_CODE
+#endif
+
+#ifdef USE_SYSCTL_NET_ROUTE
+#include <stdlib.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#endif
+#ifdef USE_SOCKET_ROUTE
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/route.h>
+#endif
+#ifdef WIN32
+#include <unknwn.h>
+#include <winreg.h>
+#define MAX_KEY_LENGTH 255
+#define MAX_VALUE_LENGTH 16383
+#endif
+#include "getgateway.h"
+
+#ifndef WIN32
+#define SUCCESS (0)
+#define FAILED  (-1)
+#endif
+
+#ifdef USE_PROC_NET_ROUTE
+int getdefaultgateway(in_addr_t * addr)
+{
+	unsigned long d, g;
+	char buf[256];
+	int line = 0;
+	FILE * f;
+	char * p;
+	f = fopen("/proc/net/route", "r");
+	if(!f)
+		return FAILED;
+	while(fgets(buf, sizeof(buf), f)) {
+		if(line > 0) {
+			p = buf;
+			while(*p && !isspace(*p))
+				p++;
+			while(*p && isspace(*p))
+				p++;
+			if(sscanf(p, "%lx%lx", &d, &g)==2) {
+				if(d == 0) { /* default */
+					*addr = g;
+					fclose(f);
+					return SUCCESS;
+				}
+			}
+		}
+		line++;
+	}
+	/* default route not found ! */
+	if(f)
+		fclose(f);
+	return FAILED;
+}
+#endif /* #ifdef USE_PROC_NET_ROUTE */
+
+
+#ifdef USE_SYSCTL_NET_ROUTE
+
+#define ROUNDUP(a) \
+	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+
+int getdefaultgateway(in_addr_t * addr)
+{
+#if 0
+	/* net.route.0.inet.dump.0.0 ? */
+	int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
+	             NET_RT_DUMP, 0, 0/*tableid*/};
+#endif
+	/* net.route.0.inet.flags.gateway */
+	int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
+	             NET_RT_FLAGS, RTF_GATEWAY};
+	size_t l;
+	char * buf, * p;
+	struct rt_msghdr * rt;
+	struct sockaddr * sa;
+	struct sockaddr * sa_tab[RTAX_MAX];
+	int i;
+	int r = FAILED;
+	if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
+		return FAILED;
+	}
+	if(l>0) {
+		buf = malloc(l);
+		if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
+			free(buf);
+			return FAILED;
+		}
+		for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
+			rt = (struct rt_msghdr *)p;
+			sa = (struct sockaddr *)(rt + 1);
+			for(i=0; i<RTAX_MAX; i++) {
+				if(rt->rtm_addrs & (1 << i)) {
+					sa_tab[i] = sa;
+					sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
+				} else {
+					sa_tab[i] = NULL;
+				}
+			}
+			if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
+              && sa_tab[RTAX_DST]->sa_family == AF_INET
+              && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {
+				if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
+					*addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
+					r = SUCCESS;
+				}
+			}
+		}
+		free(buf);
+	}
+	return r;
+}
+#endif /* #ifdef USE_SYSCTL_NET_ROUTE */
+
+
+#ifdef USE_SOCKET_ROUTE
+/* Thanks to Darren Kenny for this code */
+#define NEXTADDR(w, u) \
+        if (rtm_addrs & (w)) {\
+            l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\
+        }
+
+#define rtm m_rtmsg.m_rtm
+
+struct {
+  struct rt_msghdr m_rtm;
+  char       m_space[512];
+} m_rtmsg;
+
+int getdefaultgateway(in_addr_t *addr)
+{
+  int s, seq, l, rtm_addrs, i;
+  pid_t pid;
+  struct sockaddr so_dst, so_mask;
+  char *cp = m_rtmsg.m_space; 
+  struct sockaddr *gate = NULL, *sa;
+  struct rt_msghdr *msg_hdr;
+
+  pid = getpid();
+  seq = 0;
+  rtm_addrs = RTA_DST | RTA_NETMASK;
+
+  memset(&so_dst, 0, sizeof(so_dst));
+  memset(&so_mask, 0, sizeof(so_mask));
+  memset(&rtm, 0, sizeof(struct rt_msghdr));
+
+  rtm.rtm_type = RTM_GET;
+  rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
+  rtm.rtm_version = RTM_VERSION;
+  rtm.rtm_seq = ++seq;
+  rtm.rtm_addrs = rtm_addrs; 
+
+  so_dst.sa_family = AF_INET;
+  so_mask.sa_family = AF_INET;
+
+  NEXTADDR(RTA_DST, so_dst);
+  NEXTADDR(RTA_NETMASK, so_mask);
+
+  rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
+
+  s = socket(PF_ROUTE, SOCK_RAW, 0);
+
+  if (write(s, (char *)&m_rtmsg, l) < 0) {
+      close(s);
+      return FAILED;
+  }
+
+  do {
+    l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
+  } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
+                        
+  close(s);
+
+  msg_hdr = &rtm;
+
+  cp = ((char *)(msg_hdr + 1));
+  if (msg_hdr->rtm_addrs) {
+    for (i = 1; i; i <<= 1)
+      if (i & msg_hdr->rtm_addrs) {
+        sa = (struct sockaddr *)cp;
+        if (i == RTA_GATEWAY )
+          gate = sa;
+
+        cp += sizeof(struct sockaddr);
+      }
+  } else {
+      return FAILED;
+  }
+
+
+  if (gate != NULL ) {
+      *addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr;
+      return SUCCESS;
+  } else {
+      return FAILED;
+  }
+}
+#endif /* #ifdef USE_SOCKET_ROUTE */
+
+#ifdef USE_WIN32_CODE
+int getdefaultgateway(in_addr_t * addr)
+{
+	HKEY networkCardsKey;
+	HKEY networkCardKey;
+	HKEY interfacesKey;
+	HKEY interfaceKey;
+	DWORD i = 0;
+	DWORD numSubKeys = 0;
+	TCHAR keyName[MAX_KEY_LENGTH];
+	DWORD keyNameLength = MAX_KEY_LENGTH;
+	TCHAR keyValue[MAX_VALUE_LENGTH];
+	DWORD keyValueLength = MAX_VALUE_LENGTH;
+	DWORD keyValueType = REG_SZ;
+	TCHAR gatewayValue[MAX_VALUE_LENGTH];
+	DWORD gatewayValueLength = MAX_VALUE_LENGTH;
+	DWORD gatewayValueType = REG_MULTI_SZ;
+	int done = 0;
+	
+	char networkCardsPath[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
+	char interfacesPath[] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
+	
+	// The windows registry lists its primary network devices in the following location:
+	// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
+	// 
+	// Each network device has its own subfolder, named with an index, with various properties:
+	// -NetworkCards
+	//   -5
+	//     -Description = Broadcom 802.11n Network Adapter
+	//     -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D}
+	//   -8
+	//     -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller
+	//     -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD}
+	// 
+	// The above service name is the name of a subfolder within:
+	// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
+	// 
+	// There may be more subfolders in this interfaces path than listed in the network cards path above:
+	// -Interfaces
+	//   -{3a539854-6a70-11db-887c-806e6f6e6963}
+	//     -DhcpIPAddress = 0.0.0.0
+	//     -[more]
+	//   -{E35A72F8-5065-4097-8DFE-C7790774EE4D}
+	//     -DhcpIPAddress = 10.0.1.4
+	//     -DhcpDefaultGateway = 10.0.1.1
+	//     -[more]
+	//   -{86226414-5545-4335-A9D1-5BD7120119AD}
+	//     -DhcpIpAddress = 10.0.1.5
+	//     -DhcpDefaultGateay = 10.0.1.1
+	//     -[more]
+	// 
+	// In order to extract this information, we enumerate each network card, and extract the ServiceName value.
+	// This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value.
+	// Once one is found, we're done.
+	// 
+	// It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value.
+	// However, the technique used is the technique most cited on the web, and we assume it to be more correct.
+	
+	if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key 
+	                                 networkCardsPath,   // Name of registry subkey to open
+	                                 0,                  // Reserved - must be zero
+	                                 KEY_READ,           // Mask - desired access rights
+	                                 &networkCardsKey))  // Pointer to output key
+	{
+		// Unable to open network cards keys
+		return -1;
+	}
+	
+	if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key
+	                                 interfacesPath,     // Name of registry subkey to open
+	                                 0,                  // Reserved - must be zero
+	                                 KEY_READ,           // Mask - desired access rights
+	                                 &interfacesKey))    // Pointer to output key
+	{
+		// Unable to open interfaces key
+		RegCloseKey(networkCardsKey);
+		return -1;
+	}
+	
+	// Figure out how many subfolders are within the NetworkCards folder
+	RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+	
+	//printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys);
+	
+	// Enumrate through each subfolder within the NetworkCards folder
+	for(i = 0; i < numSubKeys && !done; i++)
+	{
+		keyNameLength = MAX_KEY_LENGTH;
+		if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key
+		                                 i,               // Index of subkey to retrieve
+		                                 keyName,         // Buffer that receives the name of the subkey
+		                                 &keyNameLength,  // Variable that receives the size of the above buffer
+		                                 NULL,            // Reserved - must be NULL
+		                                 NULL,            // Buffer that receives the class string
+		                                 NULL,            // Variable that receives the size of the above buffer
+		                                 NULL))           // Variable that receives the last write time of subkey
+		{
+			if(RegOpenKeyEx(networkCardsKey,  keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS)
+			{
+				keyValueLength = MAX_VALUE_LENGTH;
+				if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey,   // Open registry key
+				                                    "ServiceName",    // Name of key to query
+				                                    NULL,             // Reserved - must be NULL
+				                                    &keyValueType,    // Receives value type
+				                                    keyValue,         // Receives value
+				                                    &keyValueLength)) // Receives value length in bytes
+				{
+					//printf("keyValue: %s\n", keyValue);
+					
+					if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS)
+					{
+						gatewayValueLength = MAX_VALUE_LENGTH;
+						if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey,         // Open registry key
+						                                    "DhcpDefaultGateway", // Name of key to query
+						                                    NULL,                 // Reserved - must be NULL
+						                                    &gatewayValueType,    // Receives value type
+						                                    gatewayValue,         // Receives value
+						                                    &gatewayValueLength)) // Receives value length in bytes
+						{
+							// Check to make sure it's a string
+							if(gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ)
+							{
+								//printf("gatewayValue: %s\n", gatewayValue);
+								done = 1;
+							}
+						}
+						else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey,         // Open registry key
+						                                    "DefaultGateway", // Name of key to query
+						                                    NULL,                 // Reserved - must be NULL
+						                                    &gatewayValueType,    // Receives value type
+						                                    gatewayValue,         // Receives value
+						                                    &gatewayValueLength)) // Receives value length in bytes
+						{
+							// Check to make sure it's a string
+							if(gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ)
+							{
+								//printf("gatewayValue: %s\n", gatewayValue);
+								done = 1;
+							}
+						}
+						RegCloseKey(interfaceKey);
+					}
+				}
+				RegCloseKey(networkCardKey);
+			}
+		}
+	}
+	
+	RegCloseKey(interfacesKey);
+	RegCloseKey(networkCardsKey);
+	
+	if(done)
+	{
+		*addr = inet_addr(gatewayValue);
+		return 0;
+	}
+	
+	return -1;
+}
+#endif /* #ifdef USE_WIN32_CODE */
+

Added: freeswitch/trunk/libs/libnatpmp/getgateway.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/getgateway.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,31 @@
+/* $Id: getgateway.h,v 1.3 2008/07/02 22:33:06 nanard Exp $ */
+/* libnatpmp
+ * Copyright (c) 2007, Thomas BERNARD <miniupnp at free.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+#ifndef __GETGATEWAY_H__
+#define __GETGATEWAY_H__
+
+#ifdef WIN32
+#include <stdint.h>
+#define in_addr_t uint32_t
+#endif
+#include "declspec.h"
+
+/* getdefaultgateway() :
+ * return value :
+ *    0 : success
+ *   -1 : failure    */
+LIBSPEC int getdefaultgateway(in_addr_t * addr);
+
+#endif

Added: freeswitch/trunk/libs/libnatpmp/natpmp.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/natpmp.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,339 @@
+/* $Id: natpmp.c,v 1.8 2008/07/02 22:33:06 nanard Exp $ */
+/* libnatpmp
+ * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp at free.fr>
+ * http://miniupnp.free.fr/libnatpmp.html
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#ifdef WIN32
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <io.h>
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ECONNREFUSED WSAECONNREFUSED
+#else
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#define closesocket close
+#endif
+#include "natpmp.h"
+#include "getgateway.h"
+
+int initnatpmp(natpmp_t * p)
+{
+#ifdef WIN32
+	u_long ioctlArg = 1;
+#else
+	int flags; 
+#endif
+	struct sockaddr_in addr;
+	if(!p)
+		return NATPMP_ERR_INVALIDARGS;
+	memset(p, 0, sizeof(natpmp_t));
+	p->s = socket(PF_INET, SOCK_DGRAM, 0);
+	if(p->s < 0)
+		return NATPMP_ERR_SOCKETERROR;
+#ifdef WIN32
+	if(ioctlsocket(p->s, FIONBIO, &ioctlArg) == SOCKET_ERROR)
+		return NATPMP_ERR_FCNTLERROR;
+#else
+	if((flags = fcntl(p->s, F_GETFL, 0)) < 0)
+		return NATPMP_ERR_FCNTLERROR;
+	if(fcntl(p->s, F_SETFL, flags | O_NONBLOCK) < 0)
+		return NATPMP_ERR_FCNTLERROR;
+#endif
+
+	if(getdefaultgateway(&(p->gateway)) < 0)
+		return NATPMP_ERR_CANNOTGETGATEWAY;
+	
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(NATPMP_PORT);
+	addr.sin_addr.s_addr = p->gateway;
+	if(connect(p->s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+		return NATPMP_ERR_CONNECTERR;
+	return 0;
+}
+
+int closenatpmp(natpmp_t * p)
+{
+	if(!p)
+		return NATPMP_ERR_INVALIDARGS;
+	if(closesocket(p->s) < 0)
+		return NATPMP_ERR_CLOSEERR;
+	return 0;
+}
+
+int sendpendingrequest(natpmp_t * p)
+{
+	int r;
+/*	struct sockaddr_in addr;*/
+	if(!p)
+		return NATPMP_ERR_INVALIDARGS;
+/*	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(NATPMP_PORT);
+	addr.sin_addr.s_addr = p->gateway;
+	r = (int)sendto(p->s, p->pending_request, p->pending_request_len, 0,
+	                   (struct sockaddr *)&addr, sizeof(addr));*/
+	r = (int)send(p->s, p->pending_request, p->pending_request_len, 0);
+	return (r<0) ? NATPMP_ERR_SENDERR : r;
+}
+
+int sendnatpmprequest(natpmp_t * p)
+{
+	int n;
+	if(!p)
+		return NATPMP_ERR_INVALIDARGS;
+	/* TODO : check if no request is allready pending */
+	p->has_pending_request = 1;
+	p->try_number = 1;
+	n = sendpendingrequest(p);
+	gettimeofday(&p->retry_time, NULL);	// check errors !
+	p->retry_time.tv_usec += 250000;	/* add 250ms */
+	if(p->retry_time.tv_usec >= 1000000) {
+		p->retry_time.tv_usec -= 1000000;
+		p->retry_time.tv_sec++;
+	}
+	return n;
+}
+
+int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout)
+{
+	struct timeval now;
+	if(!p || !timeout)
+		return NATPMP_ERR_INVALIDARGS;
+	if(!p->has_pending_request)
+		return NATPMP_ERR_NOPENDINGREQ;
+	if(gettimeofday(&now, NULL) < 0)
+		return NATPMP_ERR_GETTIMEOFDAYERR;
+	timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec;
+	timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec;
+	if(timeout->tv_usec < 0) {
+		timeout->tv_usec += 1000000;
+		timeout->tv_sec--;
+	}
+	return 0;
+}
+
+int sendpublicaddressrequest(natpmp_t * p)
+{
+	if(!p)
+		return NATPMP_ERR_INVALIDARGS;
+	//static const unsigned char request[] = { 0, 0 };
+	p->pending_request[0] = 0;
+	p->pending_request[1] = 0;
+	p->pending_request_len = 2;
+	// TODO: return 0 instead of sizeof(request) ??
+	return sendnatpmprequest(p);
+}
+
+int sendnewportmappingrequest(natpmp_t * p, int protocol,
+                              uint16_t privateport, uint16_t publicport,
+							  uint32_t lifetime)
+{
+	if(!p || (protocol!=NATPMP_PROTOCOL_TCP && protocol!=NATPMP_PROTOCOL_UDP))
+		return NATPMP_ERR_INVALIDARGS;
+	p->pending_request[0] = 0;
+	p->pending_request[1] = protocol;
+	p->pending_request[2] = 0;
+	p->pending_request[3] = 0;
+	*((uint16_t *)(p->pending_request + 4)) = htons(privateport);
+	*((uint16_t *)(p->pending_request + 6)) = htons(publicport);
+	*((uint32_t *)(p->pending_request + 8)) = htonl(lifetime);
+	p->pending_request_len = 12;
+	return sendnatpmprequest(p);
+}
+
+int readnatpmpresponse(natpmp_t * p, natpmpresp_t * response)
+{
+	unsigned char buf[16];
+	struct sockaddr_in addr;
+	socklen_t addrlen = sizeof(addr);
+	int n;
+	if(!p)
+		return NATPMP_ERR_INVALIDARGS;
+	n = recvfrom(p->s, buf, sizeof(buf), 0,
+	             (struct sockaddr *)&addr, &addrlen);
+	if(n<0)
+		switch(errno) {
+		/*case EAGAIN:*/
+		case EWOULDBLOCK:
+			n = NATPMP_TRYAGAIN;
+			break;
+		case ECONNREFUSED:
+			n = NATPMP_ERR_NOGATEWAYSUPPORT;
+			break;
+		default:
+			n = NATPMP_ERR_RECVFROM;
+		}
+	/* check that addr is correct (= gateway) */
+	else if(addr.sin_addr.s_addr != p->gateway)
+		n = NATPMP_ERR_WRONGPACKETSOURCE;
+	else {
+		response->resultcode = ntohs(*((uint16_t *)(buf + 2)));
+		response->epoch = ntohl(*((uint32_t *)(buf + 4)));
+		if(buf[0] != 0)
+			n = NATPMP_ERR_UNSUPPORTEDVERSION;
+		else if(buf[1] < 128 || buf[1] > 130)
+			n = NATPMP_ERR_UNSUPPORTEDOPCODE;
+		else if(response->resultcode != 0) {
+			switch(response->resultcode) {
+			case 1:
+				n = NATPMP_ERR_UNSUPPORTEDVERSION;
+				break;
+			case 2:
+				n = NATPMP_ERR_NOTAUTHORIZED;
+				break;
+			case 3:
+				n = NATPMP_ERR_NETWORKFAILURE;
+				break;
+			case 4:
+				n = NATPMP_ERR_OUTOFRESOURCES;
+				break;
+			case 5:
+				n = NATPMP_ERR_UNSUPPORTEDOPCODE;
+				break;
+			default:
+				n = NATPMP_ERR_UNDEFINEDERROR;
+			}
+		} else {
+			response->type = buf[1] & 0x7f;
+			if(buf[1] == 128)
+				//response->publicaddress.addr = *((uint32_t *)(buf + 8));
+				response->pnu.publicaddress.addr.s_addr = *((uint32_t *)(buf + 8));
+			else {
+				response->pnu.newportmapping.privateport = ntohs(*((uint16_t *)(buf + 8)));
+				response->pnu.newportmapping.mappedpublicport = ntohs(*((uint16_t *)(buf + 10)));
+				response->pnu.newportmapping.lifetime = ntohl(*((uint32_t *)(buf + 12)));
+			}
+			n = 0;
+		}
+	}
+	return n;
+}
+
+int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response)
+{
+	int n;
+	if(!p || !response)
+		return NATPMP_ERR_INVALIDARGS;
+	if(!p->has_pending_request)
+		return NATPMP_ERR_NOPENDINGREQ;
+	n = readnatpmpresponse(p, response);
+	if(n<0) {
+		if(n==NATPMP_TRYAGAIN) {
+			struct timeval now;
+			gettimeofday(&now, NULL);	// check errors !
+			if(timercmp(&now, &p->retry_time, >=)) {
+				int delay, r;
+				if(p->try_number >= 9) {
+					return NATPMP_ERR_NOGATEWAYSUPPORT;
+				}
+				/*printf("retry! %d\n", p->try_number);*/
+				delay = 250 * (1<<p->try_number);	// ms
+				/*for(i=0; i<p->try_number; i++)
+					delay += delay;*/
+				p->retry_time.tv_sec += (delay / 1000);
+				p->retry_time.tv_usec += (delay % 1000) * 1000;
+				if(p->retry_time.tv_usec >= 1000000) {
+					p->retry_time.tv_usec -= 1000000;
+					p->retry_time.tv_sec++;
+				}
+				p->try_number++;
+				r = sendpendingrequest(p);
+				if(r<0)
+					return r;
+			}
+		}
+	} else {
+		p->has_pending_request = 0;
+	}
+	return n;
+}
+
+#ifdef ENABLE_STRNATPMPERR
+const char * strnatpmperr(int r)
+{
+	const char * s;
+	switch(r) {
+	case NATPMP_ERR_INVALIDARGS:
+		s = "invalid arguments";
+		break;
+	case NATPMP_ERR_SOCKETERROR:
+		s = "socket() failed";
+		break;
+	case NATPMP_ERR_CANNOTGETGATEWAY:
+		s = "cannot get default gateway ip address";
+		break;
+	case NATPMP_ERR_CLOSEERR:
+#ifdef WIN32
+		s = "closesocket() failed";
+#else
+		s = "close() failed";
+#endif
+		break;
+	case NATPMP_ERR_RECVFROM:
+		s = "recvfrom() failed";
+		break;
+	case NATPMP_ERR_NOPENDINGREQ:
+		s = "no pending request";
+		break;
+	case NATPMP_ERR_NOGATEWAYSUPPORT:
+		s = "the gateway does not support nat-pmp";
+		break;
+	case NATPMP_ERR_CONNECTERR:
+		s = "connect() failed";
+		break;
+	case NATPMP_ERR_WRONGPACKETSOURCE:
+		s = "packet not received from the default gateway";
+		break;
+	case NATPMP_ERR_SENDERR:
+		s = "send() failed";
+		break;
+	case NATPMP_ERR_FCNTLERROR:
+		s = "fcntl() failed";
+		break;
+	case NATPMP_ERR_GETTIMEOFDAYERR:
+		s = "gettimeofday() failed";
+		break;
+	case NATPMP_ERR_UNSUPPORTEDVERSION:
+		s = "unsupported nat-pmp version error from server";
+		break;
+	case NATPMP_ERR_UNSUPPORTEDOPCODE:
+		s = "unsupported nat-pmp opcode error from server";
+		break;
+	case NATPMP_ERR_UNDEFINEDERROR:
+		s = "undefined nat-pmp server error";
+		break;
+	case NATPMP_ERR_NOTAUTHORIZED:
+		s = "not authorized";
+		break;
+	case NATPMP_ERR_NETWORKFAILURE:
+		s = "network failure";
+		break;
+	case NATPMP_ERR_OUTOFRESOURCES:
+		s = "nat-pmp server out of resources";
+		break;
+	default:
+		s = "Unknown libnatpmp error";
+	}
+	return s;
+}
+#endif
+

Added: freeswitch/trunk/libs/libnatpmp/natpmp.def
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/natpmp.def	Fri May 29 15:14:45 2009
@@ -0,0 +1,11 @@
+LIBRARY
+; libnatpmp library
+
+EXPORTS
+  initnatpmp
+  closenatpmp
+  sendpublicaddressrequest
+  sendnewportmappingrequest
+  getnatpmprequesttimeout
+  readnatpmpresponseorretry
+  strnatpmperr

Added: freeswitch/trunk/libs/libnatpmp/natpmp.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/natpmp.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,187 @@
+/* $Id: natpmp.h,v 1.11 2009/02/27 22:38:05 nanard Exp $ */
+/* libnatpmp
+ * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp at free.fr>
+ * http://miniupnp.free.fr/libnatpmp.html
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+#ifndef __NATPMP_H__
+#define __NATPMP_H__
+
+/* NAT-PMP Port as defined by the NAT-PMP draft */
+#define NATPMP_PORT (5351)
+
+#include <time.h>
+#include <sys/time.h>
+#ifdef WIN32
+#include <winsock2.h>
+#include <stdint.h>
+#define in_addr_t uint32_t
+#include "declspec.h"
+#else
+#define LIBSPEC
+#include <netinet/in.h>
+#endif
+
+typedef struct {
+	int s;	/* socket */
+	in_addr_t gateway;	/* default gateway (IPv4) */
+	int has_pending_request;
+	unsigned char pending_request[12];
+	int pending_request_len;
+	int try_number;
+	struct timeval retry_time;
+} natpmp_t;
+
+typedef struct {
+	uint16_t type;	/* NATPMP_RESPTYPE_* */
+	uint16_t resultcode;	/* NAT-PMP response code */
+	uint32_t epoch;	/* Seconds since start of epoch */
+	union {
+		struct {
+			//in_addr_t addr;
+			struct in_addr addr;
+		} publicaddress;
+		struct {
+			uint16_t privateport;
+			uint16_t mappedpublicport;
+			uint32_t lifetime;
+		} newportmapping;
+	} pnu;
+} natpmpresp_t;
+
+/* possible values for type field of natpmpresp_t */
+#define NATPMP_RESPTYPE_PUBLICADDRESS (0)
+#define NATPMP_RESPTYPE_UDPPORTMAPPING (1)
+#define NATPMP_RESPTYPE_TCPPORTMAPPING (2)
+
+/* Values to pass to sendnewportmappingrequest() */
+#define NATPMP_PROTOCOL_UDP (1)
+#define NATPMP_PROTOCOL_TCP (2)
+
+/* return values */
+/* NATPMP_ERR_INVALIDARGS : invalid arguments passed to the function */
+#define NATPMP_ERR_INVALIDARGS (-1)
+/* NATPMP_ERR_SOCKETERROR : socket() failed. check errno for details */
+#define NATPMP_ERR_SOCKETERROR (-2)
+/* NATPMP_ERR_CANNOTGETGATEWAY : can't get default gateway IP */
+#define NATPMP_ERR_CANNOTGETGATEWAY (-3)
+/* NATPMP_ERR_CLOSEERR : close() failed. check errno for details */
+#define NATPMP_ERR_CLOSEERR (-4)
+/* NATPMP_ERR_RECVFROM : recvfrom() failed. check errno for details */
+#define NATPMP_ERR_RECVFROM (-5)
+/* NATPMP_ERR_NOPENDINGREQ : readnatpmpresponseorretry() called while
+ * no NAT-PMP request was pending */
+#define NATPMP_ERR_NOPENDINGREQ (-6)
+/* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */
+#define NATPMP_ERR_NOGATEWAYSUPPORT (-7)
+/* NATPMP_ERR_CONNECTERR : connect() failed. check errno for details */
+#define NATPMP_ERR_CONNECTERR (-8)
+/* NATPMP_ERR_WRONGPACKETSOURCE : packet not received from the network gateway */
+#define NATPMP_ERR_WRONGPACKETSOURCE (-9)
+/* NATPMP_ERR_SENDERR : send() failed. check errno for details */
+#define NATPMP_ERR_SENDERR (-10)
+/* NATPMP_ERR_FCNTLERROR : fcntl() failed. check errno for details */
+#define NATPMP_ERR_FCNTLERROR (-11)
+/* NATPMP_ERR_GETTIMEOFDAYERR : gettimeofday() failed. check errno for details */
+#define NATPMP_ERR_GETTIMEOFDAYERR (-12)
+
+/* */
+#define NATPMP_ERR_UNSUPPORTEDVERSION (-14)
+#define NATPMP_ERR_UNSUPPORTEDOPCODE (-15)
+
+/* Errors from the server : */
+#define NATPMP_ERR_UNDEFINEDERROR (-49)
+#define NATPMP_ERR_NOTAUTHORIZED (-51)
+#define NATPMP_ERR_NETWORKFAILURE (-52)
+#define NATPMP_ERR_OUTOFRESOURCES (-53)
+
+/* NATPMP_TRYAGAIN : no data available for the moment. try again later */
+#define NATPMP_TRYAGAIN (-100)
+
+/* initnatpmp()
+ * initialize a natpmp_t object
+ * Return values :
+ * 0 = OK
+ * NATPMP_ERR_INVALIDARGS
+ * NATPMP_ERR_SOCKETERROR
+ * NATPMP_ERR_FCNTLERROR
+ * NATPMP_ERR_CANNOTGETGATEWAY
+ * NATPMP_ERR_CONNECTERR */
+LIBSPEC int initnatpmp(natpmp_t * p);
+
+/* closenatpmp()
+ * close resources associated with a natpmp_t object
+ * Return values :
+ * 0 = OK
+ * NATPMP_ERR_INVALIDARGS
+ * NATPMP_ERR_CLOSEERR */
+LIBSPEC int closenatpmp(natpmp_t * p);
+
+/* sendpublicaddressrequest()
+ * send a public address NAT-PMP request to the network gateway
+ * Return values :
+ * 2 = OK (size of the request)
+ * NATPMP_ERR_INVALIDARGS
+ * NATPMP_ERR_SENDERR */
+LIBSPEC int sendpublicaddressrequest(natpmp_t * p);
+
+/* sendnewportmappingrequest()
+ * send a new port mapping NAT-PMP request to the network gateway
+ * Arguments :
+ * protocol is either NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP,
+ * lifetime is in seconds.
+ * To remove a port mapping, set lifetime to zero.
+ * To remove all port mappings to the host, set lifetime and both ports
+ * to zero.
+ * Return values :
+ * 12 = OK (size of the request)
+ * NATPMP_ERR_INVALIDARGS
+ * NATPMP_ERR_SENDERR */
+LIBSPEC int sendnewportmappingrequest(natpmp_t * p, int protocol,
+                              uint16_t privateport, uint16_t publicport,
+							  uint32_t lifetime);
+
+/* getnatpmprequesttimeout()
+ * fills the timeval structure with the timeout duration of the
+ * currently pending NAT-PMP request.
+ * Return values :
+ * 0 = OK
+ * NATPMP_ERR_INVALIDARGS
+ * NATPMP_ERR_GETTIMEOFDAYERR
+ * NATPMP_ERR_NOPENDINGREQ */
+LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout);
+
+/* readnatpmpresponseorretry()
+ * fills the natpmpresp_t structure if possible
+ * Return values :
+ * 0 = OK
+ * NATPMP_TRYAGAIN
+ * NATPMP_ERR_INVALIDARGS
+ * NATPMP_ERR_NOPENDINGREQ
+ * NATPMP_ERR_NOGATEWAYSUPPORT
+ * NATPMP_ERR_RECVFROM
+ * NATPMP_ERR_WRONGPACKETSOURCE
+ * NATPMP_ERR_UNSUPPORTEDVERSION
+ * NATPMP_ERR_UNSUPPORTEDOPCODE
+ * NATPMP_ERR_NOTAUTHORIZED
+ * NATPMP_ERR_NETWORKFAILURE
+ * NATPMP_ERR_OUTOFRESOURCES
+ * NATPMP_ERR_UNSUPPORTEDOPCODE
+ * NATPMP_ERR_UNDEFINEDERROR */
+LIBSPEC int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response);
+
+#ifdef ENABLE_STRNATPMPERR
+LIBSPEC const char * strnatpmperr(int t);
+#endif
+
+#endif

Added: freeswitch/trunk/libs/libnatpmp/natpmpc.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/natpmpc.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,202 @@
+/* $Id: natpmpc.c,v 1.6 2008/07/02 22:33:06 nanard Exp $ */
+/* libnatpmp
+ * Copyright (c) 2007-2008, Thomas BERNARD <miniupnp at free.fr>
+ * http://miniupnp.free.fr/libnatpmp.html
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include "natpmp.h"
+
+void usage(FILE * out, const char * argv0)
+{
+	fprintf(out, "Usage :\n");
+	fprintf(out, "  %s\n", argv0);
+	fprintf(out, "\tdisplay the public IP address.\n");
+	fprintf(out, "  %s -h\n", argv0);
+	fprintf(out, "\tdisplay this help screen.\n");
+	fprintf(out, "  %s -a <public port> <private port> <protocol> [lifetime]\n", argv0);
+	fprintf(out, "\tadd a port mapping.\n");
+	fprintf(out, "\n  In order to remove a mapping, set it with a lifetime of 0 seconds.\n");
+	fprintf(out, "  To remove all mappings for your machine, use 0 as private port and lifetime.\n");
+}
+
+/* sample code for using libnatpmp */
+int main(int argc, char * * argv)
+{
+	natpmp_t natpmp;
+	natpmpresp_t response;
+	int r;
+	int sav_errno;
+	struct timeval timeout;
+	fd_set fds;
+	int i;
+	int protocol = 0;
+	uint16_t privateport = 0;
+	uint16_t publicport = 0;
+	uint32_t lifetime = 3600;
+	int command = 0;
+
+#ifdef WIN32
+	WSADATA wsaData;
+	int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+	if(nResult != NO_ERROR)
+	{
+		fprintf(stderr, "WSAStartup() failed.\n");
+		return -1;
+	}
+#endif
+
+	/* argument parsing */
+	for(i=1; i<argc; i++) {
+		if(argv[i][0] == '-') {
+			switch(argv[i][1]) {
+			case 'h':
+				usage(stdout, argv[0]);
+				return 0;
+			case 'a':
+				command = 'a';
+				if(argc < i + 3) {
+					fprintf(stderr, "Not enough arguments for option -a\n");
+					return 1;
+				}
+				i++;
+				if(1 != sscanf(argv[i], "%hu", &publicport)) {
+					fprintf(stderr, "%s is not a correct 16bits unsigned integer\n", argv[i]);
+					return 1;
+				}
+				i++;
+				if(1 != sscanf(argv[i], "%hu", &privateport)) {
+					fprintf(stderr, "%s is not a correct 16bits unsigned integer\n", argv[i]);
+					return 1;
+				}
+				i++;
+				if(0 == strcasecmp(argv[i], "tcp"))
+					protocol = NATPMP_PROTOCOL_TCP;
+				else if(0 == strcasecmp(argv[i], "udp"))
+					protocol = NATPMP_PROTOCOL_UDP;
+				else {
+					fprintf(stderr, "%s is not a valid protocol\n", argv[i]);
+					return 1;
+				}
+				if(argc >= i) {
+					i++;
+					if(1 != sscanf(argv[i], "%u", &lifetime)) {
+						fprintf(stderr, "%s is not a correct 32bits unsigned integer\n", argv[i]);
+					}
+				}
+				break;
+			default:
+				fprintf(stderr, "Unknown option %s\n", argv[i]);
+				usage(stderr, argv[0]);
+				return 1;
+			}
+		} else {
+			fprintf(stderr, "Unknown option %s\n", argv[i]);
+			usage(stderr, argv[0]);
+			return 1;
+		}
+	}
+
+	/* initnatpmp() */
+	r = initnatpmp(&natpmp);
+	printf("initnatpmp() returned %d (%s)\n", r, r?"FAILED":"SUCCESS");
+	if(r<0)
+		return 1;
+
+	/* sendpublicaddressrequest() */
+	r = sendpublicaddressrequest(&natpmp);
+	printf("sendpublicaddressrequest returned %d (%s)\n",
+	       r, r==2?"SUCCESS":"FAILED");
+	if(r<0)
+		return 1;
+
+	do {
+		FD_ZERO(&fds);
+		FD_SET(natpmp.s, &fds);
+		getnatpmprequesttimeout(&natpmp, &timeout);
+		select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
+		r = readnatpmpresponseorretry(&natpmp, &response);
+		sav_errno = errno;
+		printf("readnatpmpresponseorretry returned %d (%s)\n",
+		       r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED"));
+		if(r<0 && r!=NATPMP_TRYAGAIN) {
+#ifdef ENABLE_STRNATPMPERR
+			fprintf(stderr, "readnatpmpresponseorretry() failed : %s\n",
+			        strnatpmperr(r));
+#endif
+			fprintf(stderr, "  errno=%d '%s'\n", 
+			        sav_errno, strerror(sav_errno));
+		}
+	} while(r==NATPMP_TRYAGAIN);
+	if(r<0)
+		return 1;
+
+	/* TODO : check that response.type == 0 */
+	printf("Public IP address : %s\n", inet_ntoa(response.pnu.publicaddress.addr));
+	printf("epoch = %u\n", response.epoch);
+
+	if(command == 'a') {
+		/* sendnewportmappingrequest() */
+		r = sendnewportmappingrequest(&natpmp, protocol,
+        	                      privateport, publicport,
+								  lifetime);
+		printf("sendnewportmappingrequest returned %d (%s)\n",
+		       r, r==12?"SUCCESS":"FAILED");
+		if(r < 0)
+			return 1;
+
+		do {
+			FD_ZERO(&fds);
+			FD_SET(natpmp.s, &fds);
+			getnatpmprequesttimeout(&natpmp, &timeout);
+			select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
+			r = readnatpmpresponseorretry(&natpmp, &response);
+			printf("readnatpmpresponseorretry returned %d (%s)\n",
+			       r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED"));
+		} while(r==NATPMP_TRYAGAIN);
+		if(r<0) {
+#ifdef ENABLE_STRNATPMPERR
+			fprintf(stderr, "readnatpmpresponseorretry() failed : %s\n",
+			        strnatpmperr(r));
+#endif
+			return 1;
+		}
+	
+		printf("Mapped public port %hu protocol %s to local port %hu "
+		       "liftime %u\n",
+	    	   response.pnu.newportmapping.mappedpublicport,
+			   response.type == NATPMP_RESPTYPE_UDPPORTMAPPING ? "UDP" :
+			    (response.type == NATPMP_RESPTYPE_TCPPORTMAPPING ? "TCP" :
+			     "UNKNOWN"),
+			   response.pnu.newportmapping.privateport,
+			   response.pnu.newportmapping.lifetime);
+		printf("epoch = %u\n", response.epoch);
+	}
+
+	r = closenatpmp(&natpmp);
+	printf("closenatpmp() returned %d (%s)\n", r, r==0?"SUCCESS":"FAILED");
+	if(r<0)
+		return 1;
+
+	return 0;
+}
+

Added: freeswitch/trunk/libs/libnatpmp/testgetgateway.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/testgetgateway.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,42 @@
+/* $Id: testgetgateway.c,v 1.4 2008/07/02 22:33:06 nanard Exp $ */
+/* libnatpmp
+ * Copyright (c) 2007, Thomas BERNARD <miniupnp at free.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+#include <stdio.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include "getgateway.h"
+
+int main(int argc, char * * argv)
+{
+	struct in_addr gatewayaddr;
+	int r;
+#ifdef WIN32
+	uint32_t temp = 0;
+	r = getdefaultgateway(&temp);
+	gatewayaddr.S_un.S_addr = temp;
+#else
+	r = getdefaultgateway(&(gatewayaddr.s_addr));
+#endif
+	if(r>=0)
+		printf("default gateway : %s\n", inet_ntoa(gatewayaddr));
+	else
+		fprintf(stderr, "getdefaultgateway() failed\n");
+	return 0;
+}
+

Added: freeswitch/trunk/libs/libnatpmp/wingettimeofday.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/libnatpmp/wingettimeofday.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,25 @@
+#ifdef WIN32
+#include <sys/time.h>
+
+typedef struct _FILETIME {
+    unsigned long dwLowDateTime;
+    unsigned long dwHighDateTime;
+} FILETIME;
+
+void __stdcall GetSystemTimeAsFileTime(FILETIME*);
+  
+//void gettimeofday(struct timeval* p, void* tz /* IGNORED */);
+
+void gettimeofday(struct timeval* p, void* tz /* IGNORED */) {
+  union {
+   long long ns100; /*time since 1 Jan 1601 in 100ns units */
+   FILETIME ft;
+  } _now;
+
+  GetSystemTimeAsFileTime( &(_now.ft) );
+  p->tv_usec=(long)((_now.ns100 / 10LL) % 1000000LL );
+  p->tv_sec= (long)((_now.ns100-(116444736000000000LL))/10000000LL);
+  return;
+}
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/Changelog.txt
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/Changelog.txt	Fri May 29 15:14:45 2009
@@ -0,0 +1,250 @@
+$Id: Changelog.txt,v 1.80 2009/04/17 21:21:19 nanard Exp $
+miniUPnP client Changelog.
+
+2009/04/17:
+  updating python module
+  Use strtoull() when using C99
+
+2009/02/28:
+  Fixed miniwget.c for compiling under sun
+
+2008/12/18:
+  cleanup in Makefile (thanks to Paul de Weerd)
+  minissdpc.c : win32 compatibility
+  miniupnpc.c : changed xmlns prefix from 'm' to 'u'
+  Removed NDEBUG (using DEBUG)
+
+2008/10/14:
+  Added the ExternalHost argument to DeletePortMapping()
+
+2008/10/11:
+  Added the ExternalHost argument to AddPortMapping()
+  Put a correct User-Agent: header in HTTP requests.
+
+VERSION 1.2 :
+
+2008/10/07:
+  Update docs
+
+2008/09/25:
+  Integrated sameport patch from Dario Meloni : Added a "sameport"
+  argument to upnpDiscover().
+
+2008/07/18:
+  small modif to make Clang happy :)
+
+2008/07/17:
+  #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... 
+
+2008/07/14:
+  include declspec.h in installation (to /usr/include/miniupnpc)
+
+VERSION 1.1 :
+
+2008/07/04:
+  standard options for install/ln instead of gnu-specific stuff.
+
+2008/07/03:
+  now builds a .dll and .lib with win32. (mingw32)
+
+2008/04/28:
+  make install now install the binary of the upnpc tool
+
+2008/04/27:
+  added testupnpigd.py
+  added error strings for miniupnpc "internal" errors
+  improved python module error/exception reporting.
+
+2008/04/23:
+  Completely rewrite igd_desc_parse.c in order to be compatible with 
+  Linksys WAG200G
+  Added testigddescparse
+  updated python module
+
+VERSION 1.0 :
+
+2008/02/21:
+  put some #ifdef DEBUG around DisplayNameValueList()
+
+2008/02/18:
+  Improved error reporting in upnpcommands.c
+  UPNP_GetStatusInfo() returns LastConnectionError
+
+2008/02/16:
+  better error handling in minisoap.c
+  improving display of "valid IGD found" in upnpc.c
+
+2008/02/03:
+  Fixing UPNP_GetValidIGD()
+  improved make install :)
+
+2007/12/22:
+  Adding upnperrors.c/h to provide a strupnperror() function 
+  used to translate UPnP error codes to string.
+
+2007/12/19:
+  Fixing getDevicesFromMiniSSDPD()
+  improved error reporting of UPnP functions
+
+2007/12/18:
+  It is now possible to specify a different location for MiniSSDPd socket.
+  working with MiniSSDPd is now more efficient.
+  python module improved.
+
+2007/12/16:
+  improving error reporting
+
+2007/12/13:
+  Try to improve compatibility by using HTTP/1.0 instead of 1.1 and
+  XML a bit different for SOAP.
+
+2007/11/25:
+  fixed select() call for linux
+
+2007/11/15:
+  Added -fPIC to CFLAG for better shared library code.
+
+2007/11/02:
+  Fixed a potential socket leak in miniwget2()
+
+2007/10/16:
+  added a parameter to upnpDiscover() in order to allow the use of another
+  interface than the default multicast interface.
+
+2007/10/12:
+  Fixed the creation of symbolic link in Makefile
+
+2007/10/08:
+  Added man page
+
+2007/10/02:
+  fixed memory bug in GetUPNPUrls()
+
+2007/10/01:
+  fixes in the Makefile
+  Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly.
+  Added SONAME in the shared library to please debian :)
+  fixed MS Windows compilation (minissdpd is not available under MS Windows).
+
+2007/09/25:
+  small change to Makefile to be able to install in a different location
+  (default is /usr)
+
+2007/09/24:
+  now compiling both shared and static library
+
+2007/09/19:
+  Cosmetic changes on upnpc.c
+
+2007/09/02:
+  adapting to new miniSSDPd (release version ?)
+
+2007/08/31:
+  Usage of miniSSDPd to skip discovery process.
+
+2007/08/27:
+  fixed python module to allow compilation with Python older than Python 2.4
+
+2007/06/12:
+  Added a python module.
+
+2007/05/19:
+  Fixed compilation under MinGW
+
+2007/05/15:
+  fixed a memory leak in AddPortMapping()
+  Added testupnpreplyparse executable to check the parsing of
+  upnp soap messages
+  minixml now ignore namespace prefixes.
+
+2007/04/26:
+  upnpc now displays external ip address with -s or -l
+
+2007/04/11:
+  changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210"
+
+2007/03/19:
+  cleanup in miniwget.c
+
+2007/03/01:
+  Small typo fix...
+
+2007/01/30:
+  Now parsing the HTTP header from SOAP responses in order to
+  get content-length value.
+
+2007/01/29:
+  Fixed the Soap Query to speedup the HTTP request.
+  added some Win32 DLL stuff...
+
+2007/01/27:
+  Fixed some WIN32 compatibility issues
+
+2006/12/14:
+  Added UPNPIGD_IsConnected() function in miniupnp.c/.h
+  Added UPNP_GetValidIGD() in miniupnp.c/.h
+  cleaned upnpc.c main(). now using UPNP_GetValidIGD()
+
+2006/12/07:
+  Version 1.0-RC1 released
+
+2006/12/03:
+  Minor changes to compile under SunOS/Solaris
+
+2006/11/30:
+  made a minixml parser validator program
+  updated minixml to handle attributes correctly
+
+2006/11/22:
+  Added a -r option to the upnpc sample thanks to Alexander Hubmann.
+
+2006/11/19:
+  Cleanup code to make it more ANSI C compliant
+
+2006/11/10:
+  detect and display local lan address.
+
+2006/11/04:
+  Packets and Bytes Sent/Received are now unsigned int.
+
+2006/11/01:
+  Bug fix thanks to Giuseppe D'Angelo
+
+2006/10/31:
+  C++ compatibility for .h files.
+  Added a way to get ip Address on the LAN used to reach the IGD.
+
+2006/10/25:
+  Added M-SEARCH to the services in the discovery process.
+
+2006/10/22:
+  updated the Makefile to use makedepend, added a "make install"
+  update Makefile
+
+2006/10/20:
+  fixing the description url parsing thanks to patch sent by
+  Wayne Dawe.
+  Fixed/translated some comments.
+  Implemented a better discover process, first looking
+  for IGD then for root devices (as some devices only reply to
+  M-SEARCH for root devices).
+
+2006/09/02:
+  added freeUPNPDevlist() function.
+
+2006/08/04:
+  More command line arguments checking
+
+2006/08/01:
+  Added the .bat file to compile under Win32 with minGW32
+
+2006/07/31:
+  Fixed the rootdesc parser (igd_desc_parse.c)
+
+2006/07/20:
+  parseMSEARCHReply() is now returning the ST: line as well
+  starting changes to detect several UPnP devices on the network
+
+2006/07/19:
+  using GetCommonLinkProperties to get down/upload bitrate
+

Added: freeswitch/trunk/libs/miniupnpc/LICENCE
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/LICENCE	Fri May 29 15:14:45 2009
@@ -0,0 +1,26 @@
+Copyright (c) 2005-2008, Thomas BERNARD 
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * The name of the author may not be used to endorse or promote products
+	  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+

Added: freeswitch/trunk/libs/miniupnpc/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/Makefile	Fri May 29 15:14:45 2009
@@ -0,0 +1,127 @@
+# $Id: Makefile,v 1.48 2008/12/18 17:46:13 nanard Exp $
+# MiniUPnP Project
+# http://miniupnp.free.fr/
+# (c) 2005-2007 Thomas Bernard
+# to install use :
+# $ PREFIX=/tmp/dummylocation make install
+# or
+# $ INSTALLPREFIX=/usr/local make install
+# or 
+# make install (will go to /usr/bin, /usr/lib, etc...)
+CC ?= gcc
+#AR = gar
+#CFLAGS = -fPIC -O -Wall -g -DDEBUG
+CFLAGS ?= -fPIC -O -Wall -DNDEBUG
+INSTALL = install
+#following libs are needed on Solaris
+#LDLIBS=-lsocket -lnsl -lresolv
+
+# APIVERSION is used to build SONAME
+APIVERSION = 4
+
+SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \
+       upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \
+	   minixmlvalid.c testupnpreplyparse.c minissdpc.c \
+	   upnperrors.c testigddescparse.c
+
+LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \
+          miniupnpc.o upnpreplyparse.o upnpcommands.o minissdpc.o \
+		  upnperrors.o
+
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+# HEADERS to install
+HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \
+          upnpreplyparse.h upnperrors.h declspec.h
+LIBRARY = libminiupnpc.a
+SHAREDLIBRARY = libminiupnpc.so
+SONAME = $(SHAREDLIBRARY).$(APIVERSION)
+EXECUTABLES = upnpc-static upnpc-shared \
+              testminixml minixmlvalid testupnpreplyparse \
+			  testigddescparse
+
+INSTALLPREFIX ?= $(PREFIX)/usr
+INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc
+INSTALLDIRLIB = $(INSTALLPREFIX)/lib
+INSTALLDIRBIN = $(INSTALLPREFIX)/bin
+
+.PHONY:	install clean depend all installpythonmodule
+
+all:	validateminixml $(LIBRARY) $(EXECUTABLES)
+
+pythonmodule:	$(LIBRARY) miniupnpcmodule.c setup.py
+	python setup.py build
+	touch $@
+
+installpythonmodule:	pythonmodule
+	python setup.py install
+
+validateminixml:	minixmlvalid
+	@echo "minixml validation test"
+	./minixmlvalid
+	touch $@
+
+clean:
+		$(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS)
+		# clean python stuff
+		$(RM) pythonmodule validateminixml
+		$(RM) -r build/ dist/
+		#python setup.py clean
+
+install:	$(LIBRARY) $(SHAREDLIBRARY)
+	$(INSTALL) -d $(INSTALLDIRINC)
+	$(INSTALL) -m 644 $(HEADERS) $(INSTALLDIRINC)
+	$(INSTALL) -d $(INSTALLDIRLIB)
+	$(INSTALL) -m 644 $(LIBRARY) $(INSTALLDIRLIB)
+	$(INSTALL) -m 644 $(SHAREDLIBRARY) $(INSTALLDIRLIB)/$(SONAME)
+	$(INSTALL) -d $(INSTALLDIRBIN)
+	$(INSTALL) -m 755 upnpc-shared $(INSTALLDIRBIN)/upnpc
+	ln -fs $(SONAME) $(INSTALLDIRLIB)/$(SHAREDLIBRARY)
+
+cleaninstall:
+	$(RM) -r $(INSTALLDIRINC)
+	$(RM) $(INSTALLDIRLIB)/$(LIBRARY)
+	$(RM) $(INSTALLDIRLIB)/$(SHAREDLIBRARY)
+
+depend:
+	makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null
+
+$(LIBRARY):	$(LIBOBJS)
+	$(AR) crs $@ $?
+
+$(SHAREDLIBRARY):	$(LIBOBJS)
+	$(CC) -shared -Wl,-soname,$(SONAME) -o $@ $^
+
+upnpc-static:	upnpc.o $(LIBRARY)
+	$(CC) -o $@ $^
+
+upnpc-shared:	upnpc.o $(SHAREDLIBRARY)
+	$(CC) -o $@ $^
+
+testminixml:	minixml.o igd_desc_parse.o testminixml.o
+
+minixmlvalid:	minixml.o minixmlvalid.o
+
+testupnpreplyparse:	testupnpreplyparse.o minixml.o upnpreplyparse.o
+
+testigddescparse:	testigddescparse.o igd_desc_parse.o minixml.o
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+igd_desc_parse.o: igd_desc_parse.h
+miniupnpc.o: miniupnpc.h declspec.h igd_desc_parse.h minissdpc.h miniwget.h
+miniupnpc.o: minisoap.h minixml.h upnpcommands.h upnpreplyparse.h
+minixml.o: minixml.h
+minisoap.o: minisoap.h miniupnpcstrings.h
+miniwget.o: miniupnpc.h declspec.h igd_desc_parse.h miniupnpcstrings.h
+upnpc.o: miniwget.h declspec.h miniupnpc.h igd_desc_parse.h upnpcommands.h
+upnpc.o: upnpreplyparse.h upnperrors.h
+upnpcommands.o: upnpcommands.h upnpreplyparse.h declspec.h miniupnpc.h
+upnpcommands.o: igd_desc_parse.h
+upnpreplyparse.o: upnpreplyparse.h minixml.h
+testminixml.o: minixml.h igd_desc_parse.h
+minixmlvalid.o: minixml.h
+testupnpreplyparse.o: upnpreplyparse.h
+minissdpc.o: minissdpc.h miniupnpc.h declspec.h igd_desc_parse.h codelength.h
+upnperrors.o: upnperrors.h declspec.h upnpcommands.h upnpreplyparse.h
+testigddescparse.o: igd_desc_parse.h minixml.h

Added: freeswitch/trunk/libs/miniupnpc/Makefile.mingw
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/Makefile.mingw	Fri May 29 15:14:45 2009
@@ -0,0 +1,74 @@
+# $Id: Makefile.mingw,v 1.9 2008/07/02 23:31:15 nanard Exp $
+# Miniupnp project.
+# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+# (c) 2005-2008 Thomas Bernard
+CC = gcc
+#CFLAGS = -Wall -g -DDEBUG
+CFLAGS = -Wall -Os -DNDEBUG
+LDLIBS = -lws2_32
+# -lwsock32
+PYTHON=\utils\python25\python
+OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \
+     miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o
+OBJSDLL=$(addprefix dll/, $(OBJS))
+
+all:	init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll
+
+init:
+	mkdir dll
+	echo "" > init
+
+clean:
+	del upnpc testminixml *.o
+	del dll/*.o
+
+libminiupnpc.a:	$(OBJS)
+	$(AR) cr $@ $?
+
+pythonmodule:	libminiupnpc.a
+	$(PYTHON) setupmingw32.py build --compiler=mingw32
+	$(PYTHON) setupmingw32.py install --skip-build
+
+miniupnpc.dll:	libminiupnpc.a $(OBJSDLL)
+	dllwrap -k --driver-name gcc --def miniupnpc.def \
+	--output-def miniupnpc.dll.def --implib miniupnpc.lib -o $@ \
+	$(OBJSDLL) $(LDLIBS)
+
+miniupnpc.lib:	miniupnpc.dll
+	echo $@ generated with $<
+
+dll/upnpc.o:	upnpc.o
+	echo $@ generated with $<
+
+.c.o:
+	$(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $<
+	$(CC) $(CFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $<
+
+upnpc.o:
+	$(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $<
+	$(CC) $(CFLAGS) -c -o dll/$@ $<
+
+upnpc-static:	upnpc.o libminiupnpc.a
+	$(CC) -o $@ $^ $(LDLIBS)
+
+upnpc-shared:	dll/upnpc.o miniupnpc.lib
+	$(CC) -o $@ $^ $(LDLIBS)
+
+minixml.o:	minixml.c minixml.h
+
+upnpc.o:	upnpc.c miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h upnpreplyparse.h upnpcommands.h
+
+miniwget.o:	miniwget.c miniwget.h
+
+minisoap.o:	minisoap.c minisoap.h
+
+miniupnpc.o:	miniupnpc.c miniupnpc.h minisoap.h miniwget.h minixml.h
+
+igd_desc_parse.o:	igd_desc_parse.c igd_desc_parse.h
+
+testminixml:	minixml.o igd_desc_parse.o testminixml.c
+
+upnpreplyparse.o:	upnpreplyparse.c upnpreplyparse.h minixml.h
+
+upnpcommands.o:	upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h
+

Added: freeswitch/trunk/libs/miniupnpc/README
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/README	Fri May 29 15:14:45 2009
@@ -0,0 +1,54 @@
+Project: miniupnp
+Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+Author: Thomas Bernard
+Copyright (c) 2005-2008 Thomas Bernard
+This software is subject to the conditions detailed in the
+LICENCE 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.
+bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system.
+
+* miniupnp Client *
+
+To compile, simply run 'gmake' (could be 'make').
+Under win32, to compile with MinGW, type "mingw32make.bat".
+The compilation is known to work under linux, FreeBSD,
+OpenBSD, MacOS X and cygwin.
+To install the library and headers on the system use :
+> su
+> make install
+> exit
+
+alternatively, to install in a specific location, use :
+> INSTALLPREFIX=/usr/local make install
+
+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,
+upnpcommands.h and miniwget.h :
+- upnpDiscover()
+- miniwget()
+- parserootdesc()
+- GetUPNPUrls()
+- UPNP_* (calling UPNP methods)
+
+Note : use #include <miniupnpc/miniupnpc.h> etc... for the includes
+and -lminiupnpc for the link
+
+Discovery process is speeded up when MiniSSDPd is running on the machine.
+
+* Python module *
+
+you can build a python module with 'make pythonmodule' 
+and install it with 'make installpythonmodule'.
+setup.py (and setupmingw32.py) are included in the distribution.
+
+
+Feel free to contact me if you have any problem :
+e-mail : miniupnp at free.fr
+
+If you are using libminiupnpc in your application, please
+send me an email !
+
+

Added: freeswitch/trunk/libs/miniupnpc/bsdqueue.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/bsdqueue.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,531 @@
+/*	$OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $	*/
+/*	$NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $	*/
+
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef	_SYS_QUEUE_H_
+#define	_SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists, 
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+#ifdef QUEUE_MACRO_DEBUG
+#define _Q_INVALIDATE(a) (a) = ((void *)-1)
+#else
+#define _Q_INVALIDATE(a)
+#endif
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+ 
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#ifdef SLIST_ENTRY
+#undef SLIST_ENTRY
+#endif
+
+#define SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+ 
+/*
+ * Singly-linked List access methods.
+ */
+#define	SLIST_FIRST(head)	((head)->slh_first)
+#define	SLIST_END(head)		NULL
+#define	SLIST_EMPTY(head)	(SLIST_FIRST(head) == SLIST_END(head))
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for((var) = SLIST_FIRST(head);					\
+	    (var) != SLIST_END(head);					\
+	    (var) = SLIST_NEXT(var, field))
+
+#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
+	for ((varp) = &SLIST_FIRST((head));				\
+	    ((var) = *(varp)) != SLIST_END(head);			\
+	    (varp) = &SLIST_NEXT((var), field))
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_INIT(head) {						\
+	SLIST_FIRST(head) = SLIST_END(head);				\
+}
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
+	(slistelm)->field.sle_next = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.sle_next = (head)->slh_first;			\
+	(head)->slh_first = (elm);					\
+} while (0)
+
+#define	SLIST_REMOVE_NEXT(head, elm, field) do {			\
+	(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;	\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	(head)->slh_first = (head)->slh_first->field.sle_next;		\
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do {			\
+	if ((head)->slh_first == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->slh_first;		\
+									\
+		while (curelm->field.sle_next != (elm))			\
+			curelm = curelm->field.sle_next;		\
+		curelm->field.sle_next =				\
+		    curelm->field.sle_next->field.sle_next;		\
+		_Q_INVALIDATE((elm)->field.sle_next);			\
+	}								\
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List access methods
+ */
+#define	LIST_FIRST(head)		((head)->lh_first)
+#define	LIST_END(head)			NULL
+#define	LIST_EMPTY(head)		(LIST_FIRST(head) == LIST_END(head))
+#define	LIST_NEXT(elm, field)		((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field)					\
+	for((var) = LIST_FIRST(head);					\
+	    (var)!= LIST_END(head);					\
+	    (var) = LIST_NEXT(var, field))
+
+/*
+ * List functions.
+ */
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST(head) = LIST_END(head);				\
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
+		(listelm)->field.le_next->field.le_prev =		\
+		    &(elm)->field.le_next;				\
+	(listelm)->field.le_next = (elm);				\
+	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	(elm)->field.le_next = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &(elm)->field.le_next;		\
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do {				\
+	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
+		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+	(head)->lh_first = (elm);					\
+	(elm)->field.le_prev = &(head)->lh_first;			\
+} while (0)
+
+#define LIST_REMOVE(elm, field) do {					\
+	if ((elm)->field.le_next != NULL)				\
+		(elm)->field.le_next->field.le_prev =			\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = (elm)->field.le_next;			\
+	_Q_INVALIDATE((elm)->field.le_prev);				\
+	_Q_INVALIDATE((elm)->field.le_next);				\
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do {				\
+	if (((elm2)->field.le_next = (elm)->field.le_next) != NULL)	\
+		(elm2)->field.le_next->field.le_prev =			\
+		    &(elm2)->field.le_next;				\
+	(elm2)->field.le_prev = (elm)->field.le_prev;			\
+	*(elm2)->field.le_prev = (elm2);				\
+	_Q_INVALIDATE((elm)->field.le_prev);				\
+	_Q_INVALIDATE((elm)->field.le_next);				\
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *sqh_first;	/* first element */			\
+	struct type **sqh_last;	/* addr of last next element */		\
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type)						\
+struct {								\
+	struct type *sqe_next;	/* next element */			\
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define	SIMPLEQ_FIRST(head)	    ((head)->sqh_first)
+#define	SIMPLEQ_END(head)	    NULL
+#define	SIMPLEQ_EMPTY(head)	    (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define	SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field)				\
+	for((var) = SIMPLEQ_FIRST(head);				\
+	    (var) != SIMPLEQ_END(head);					\
+	    (var) = SIMPLEQ_NEXT(var, field))
+
+/*
+ * Simple queue functions.
+ */
+#define	SIMPLEQ_INIT(head) do {						\
+	(head)->sqh_first = NULL;					\
+	(head)->sqh_last = &(head)->sqh_first;				\
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(head)->sqh_first = (elm);					\
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.sqe_next = NULL;					\
+	*(head)->sqh_last = (elm);					\
+	(head)->sqh_last = &(elm)->field.sqe_next;			\
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(listelm)->field.sqe_next = (elm);				\
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do {			\
+	if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+		(head)->sqh_last = &(head)->sqh_first;			\
+} while (0)
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+}
+
+#define TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+/* 
+ * tail queue access methods 
+ */
+#define	TAILQ_FIRST(head)		((head)->tqh_first)
+#define	TAILQ_END(head)			NULL
+#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define	TAILQ_EMPTY(head)						\
+	(TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field)					\
+	for((var) = TAILQ_FIRST(head);					\
+	    (var) != TAILQ_END(head);					\
+	    (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for((var) = TAILQ_LAST(head, headname);				\
+	    (var) != TAILQ_END(head);					\
+	    (var) = TAILQ_PREV(var, headname, field))
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_INIT(head) do {						\
+	(head)->tqh_first = NULL;					\
+	(head)->tqh_last = &(head)->tqh_first;				\
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
+		(head)->tqh_first->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(head)->tqh_first = (elm);					\
+	(elm)->field.tqe_prev = &(head)->tqh_first;			\
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.tqe_next = NULL;					\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &(elm)->field.tqe_next;			\
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+		(elm)->field.tqe_next->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_next = (elm);				\
+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	(elm)->field.tqe_next = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do {				\
+	if (((elm)->field.tqe_next) != NULL)				\
+		(elm)->field.tqe_next->field.tqe_prev =			\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+	_Q_INVALIDATE((elm)->field.tqe_prev);				\
+	_Q_INVALIDATE((elm)->field.tqe_next);				\
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do {			\
+	if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)	\
+		(elm2)->field.tqe_next->field.tqe_prev =		\
+		    &(elm2)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm2)->field.tqe_next;		\
+	(elm2)->field.tqe_prev = (elm)->field.tqe_prev;			\
+	*(elm2)->field.tqe_prev = (elm2);				\
+	_Q_INVALIDATE((elm)->field.tqe_prev);				\
+	_Q_INVALIDATE((elm)->field.tqe_next);				\
+} while (0)
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head)					\
+	{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue access methods 
+ */
+#define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
+#define	CIRCLEQ_LAST(head)		((head)->cqh_last)
+#define	CIRCLEQ_END(head)		((void *)(head))
+#define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
+#define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
+#define	CIRCLEQ_EMPTY(head)						\
+	(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
+
+#define CIRCLEQ_FOREACH(var, head, field)				\
+	for((var) = CIRCLEQ_FIRST(head);				\
+	    (var) != CIRCLEQ_END(head);					\
+	    (var) = CIRCLEQ_NEXT(var, field))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
+	for((var) = CIRCLEQ_LAST(head);					\
+	    (var) != CIRCLEQ_END(head);					\
+	    (var) = CIRCLEQ_PREV(var, field))
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_INIT(head) do {						\
+	(head)->cqh_first = CIRCLEQ_END(head);				\
+	(head)->cqh_last = CIRCLEQ_END(head);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
+	(elm)->field.cqe_prev = (listelm);				\
+	if ((listelm)->field.cqe_next == CIRCLEQ_END(head))		\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
+	(listelm)->field.cqe_next = (elm);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm);				\
+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
+	if ((listelm)->field.cqe_prev == CIRCLEQ_END(head))		\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
+	(listelm)->field.cqe_prev = (elm);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.cqe_next = (head)->cqh_first;			\
+	(elm)->field.cqe_prev = CIRCLEQ_END(head);			\
+	if ((head)->cqh_last == CIRCLEQ_END(head))			\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(head)->cqh_first->field.cqe_prev = (elm);		\
+	(head)->cqh_first = (elm);					\
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.cqe_next = CIRCLEQ_END(head);			\
+	(elm)->field.cqe_prev = (head)->cqh_last;			\
+	if ((head)->cqh_first == CIRCLEQ_END(head))			\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(head)->cqh_last->field.cqe_next = (elm);		\
+	(head)->cqh_last = (elm);					\
+} while (0)
+
+#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
+	if ((elm)->field.cqe_next == CIRCLEQ_END(head))			\
+		(head)->cqh_last = (elm)->field.cqe_prev;		\
+	else								\
+		(elm)->field.cqe_next->field.cqe_prev =			\
+		    (elm)->field.cqe_prev;				\
+	if ((elm)->field.cqe_prev == CIRCLEQ_END(head))			\
+		(head)->cqh_first = (elm)->field.cqe_next;		\
+	else								\
+		(elm)->field.cqe_prev->field.cqe_next =			\
+		    (elm)->field.cqe_next;				\
+	_Q_INVALIDATE((elm)->field.cqe_prev);				\
+	_Q_INVALIDATE((elm)->field.cqe_next);				\
+} while (0)
+
+#define CIRCLEQ_REPLACE(head, elm, elm2, field) do {			\
+	if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==		\
+	    CIRCLEQ_END(head))						\
+		(head).cqh_last = (elm2);				\
+	else								\
+		(elm2)->field.cqe_next->field.cqe_prev = (elm2);	\
+	if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==		\
+	    CIRCLEQ_END(head))						\
+		(head).cqh_first = (elm2);				\
+	else								\
+		(elm2)->field.cqe_prev->field.cqe_next = (elm2);	\
+	_Q_INVALIDATE((elm)->field.cqe_prev);				\
+	_Q_INVALIDATE((elm)->field.cqe_next);				\
+} while (0)
+
+#endif	/* !_SYS_QUEUE_H_ */

Added: freeswitch/trunk/libs/miniupnpc/codelength.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/codelength.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,24 @@
+/* $Id: codelength.h,v 1.1 2008/10/06 22:04:06 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * copyright (c) 2005-2008 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#ifndef __CODELENGTH_H__
+#define __CODELENGTH_H__
+
+/* Encode length by using 7bit per Byte :
+ * Most significant bit of each byte specifies that the
+ * following byte is part of the code */
+#define DECODELENGTH(n, p) n = 0; \
+                           do { n = (n << 7) | (*p & 0x7f); } \
+                           while(*(p++)&0x80);
+
+#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
+

Added: freeswitch/trunk/libs/miniupnpc/declspec.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/declspec.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,15 @@
+#ifndef __DECLSPEC_H__
+#define __DECLSPEC_H__
+
+#if defined(WIN32) && !defined(STATICLIB)
+	#ifdef MINIUPNP_EXPORTS
+		#define LIBSPEC __declspec(dllexport)
+	#else
+		#define LIBSPEC __declspec(dllimport)
+	#endif
+#else
+	#define LIBSPEC
+#endif
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/igd_desc_parse.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/igd_desc_parse.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,113 @@
+/* $Id: igd_desc_parse.c,v 1.8 2008/04/23 11:51:06 nanard Exp $ */
+/* Project : miniupnp
+ * http://miniupnp.free.fr/
+ * Author : Thomas Bernard
+ * Copyright (c) 2005-2008 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * 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)
+{
+	struct IGDdatas * datas = (struct IGDdatas *)d;
+	memcpy( datas->cureltname, name, 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';
+	}
+}
+
+/* End element handler :
+ * update nesting level counter and update parser state if
+ * service element is parsed */
+void IGDendelt(void * d, const char * name, int l)
+{
+	struct IGDdatas * datas = (struct IGDdatas *)d;
+	datas->level--;
+	/*printf("endelt %2d %.*s\n", datas->level, l, name);*/
+	if( (l==7) && !memcmp(name, "service", l) )
+	{
+		/*
+		if( datas->state < 1
+			&& !strcmp(datas->servicetype,
+				//	"urn:schemas-upnp-org:service:WANIPConnection:1") )
+				"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
+			datas->state ++;
+		*/
+		if(0==strcmp(datas->servicetype_tmp,
+				"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,
+				"urn:schemas-upnp-org:service:WANIPConnection:1")
+				 || 0==strcmp(datas->servicetype_tmp,
+				"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);
+		}
+	}
+}
+
+/* Data handler :
+ * copy data depending on the current element name and state */
+void IGDdata(void * d, const char * data, int l)
+{
+	struct IGDdatas * datas = (struct IGDdatas *)d;
+	char * dstmember = 0;
+	/*printf("%2d %s : %.*s\n",
+           datas->level, datas->cureltname, l, data);	*/
+	if( !strcmp(datas->cureltname, "URLBase") )
+		dstmember = datas->urlbase;
+	else if( !strcmp(datas->cureltname, "serviceType") )
+		dstmember = datas->servicetype_tmp;
+	else if( !strcmp(datas->cureltname, "controlURL") )
+		dstmember = datas->controlurl_tmp;
+	else if( !strcmp(datas->cureltname, "eventSubURL") )
+		dstmember = datas->eventsuburl_tmp;
+	else if( !strcmp(datas->cureltname, "SCPDURL") )
+		dstmember = datas->scpdurl_tmp;
+/*	else if( !strcmp(datas->cureltname, "deviceType") )
+		dstmember = datas->devicetype_tmp;*/
+	if(dstmember)
+	{
+		if(l>=MINIUPNPC_URL_MAXSIZE)
+			l = MINIUPNPC_URL_MAXSIZE-1;
+		memcpy(dstmember, data, l);
+		dstmember[l] = '\0';
+	}
+}
+
+void printIGD(struct IGDdatas * d)
+{
+	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);
+}
+
+

Added: freeswitch/trunk/libs/miniupnpc/igd_desc_parse.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/igd_desc_parse.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,47 @@
+/* $Id: igd_desc_parse.h,v 1.6 2008/04/23 11:51:07 nanard Exp $ */
+/* Project : miniupnp
+ * http://miniupnp.free.fr/
+ * Author : Thomas Bernard
+ * Copyright (c) 2005-2008 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided in this distribution.
+ * */
+#ifndef __IGD_DESC_PARSE_H__
+#define __IGD_DESC_PARSE_H__
+
+/* Structure to store the result of the parsing of UPnP
+ * descriptions of Internet Gateway Devices */
+#define MINIUPNPC_URL_MAXSIZE (128)
+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];*/
+	/* "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];*/
+	/* 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];*/
+};
+
+void IGDstartelt(void *, const char *, int);
+void IGDendelt(void *, const char *, int);
+void IGDdata(void *, const char *, int);
+void printIGD(struct IGDdatas *);
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/man3/miniupnpc.3
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/man3/miniupnpc.3	Fri May 29 15:14:45 2009
@@ -0,0 +1,52 @@
+\" $Id: miniupnpc.3,v 1.2 2008/10/07 13:51:55 nanard Exp $
+.TH miniupnpc 3
+.SH NAME
+miniupnpc \- UPnP client library
+.SH SYNOPSIS
+.SH DESCRIPTION
+The miniupnpc library implement the UPnP protocol defined
+to dialog with Internet Gateway Devices. It also has
+the ability to use data gathered by minissdpd(1) about
+UPnP devices up on the network in order to skip the
+long UPnP device discovery process.
+.PP
+At first, upnpDiscover(3) has to be used to discover UPnP IGD present
+on the network. Then UPNP_GetValidIGD(3) to select the right one.
+Alternatively, UPNP_GetIGDFromUrl(3) could be used to bypass discovery
+process if the root description url of the device to use is known.
+Then all the UPNP_* functions can be used, such as
+UPNP_GetConnectionTypeInfo(3), UPNP_AddPortMapping(3), etc...
+.SH "HEADER FILES"
+.IP miniupnpc.h
+That's the main header file for the miniupnpc library API.
+It contains all the functions and structures related to device discovery.
+.IP upnpcommands.h
+This header file contain the UPnP IGD methods that are accessible
+through the miniupnpc API. The name of the C functions are matching
+the UPnP methods names. ie: GetGenericPortMappingEntry is
+UPNP_GetGenericPortMappingEntry.
+.SH "API FUNCTIONS"
+.IP "struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int sameport);"
+execute the discovery process.
+delay (in millisecond) is the maximum time for waiting any device response.
+If available, device list will be obtained from MiniSSDPd.
+Default path for minissdpd socket will be used if minissdpdsock argument is NULL.
+If multicastif is not NULL, it will be used instead of the default multicast interface for sending SSDP discover packets.
+If sameport is not null, SSDP packets will be sent from the source port 1900 (same as destination port) otherwise system assign a source port.
+.IP "void freeUPNPDevlist(struct UPNPDev * devlist);"
+free the list returned by upnpDiscover().
+.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);"
+browse the list of device returned by upnpDiscover(), find
+a live UPnP internet gateway device and fill structures passed as arguments
+with data used for UPNP methods invokation.
+.IP "int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);"
+permit to bypass the upnpDiscover() call if the xml root description
+URL of the UPnP IGD is known.
+Fill structures passed as arguments
+with data used for UPNP methods invokation.
+.IP "void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);"
+.IP "void FreeUPNPUrls(struct UPNPUrls *);"
+
+.SH "SEE ALSO"
+minissdpd(1)
+.SH BUGS

Added: freeswitch/trunk/libs/miniupnpc/mingw32make.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/mingw32make.bat	Fri May 29 15:14:45 2009
@@ -0,0 +1,7 @@
+ at mingw32-make -f Makefile.mingw %1
+ at if errorlevel 1 goto end
+ at strip upnpc-static.exe
+ at upx --best upnpc-static.exe
+ at strip upnpc-shared.exe
+ at upx --best upnpc-shared.exe
+:end

Added: freeswitch/trunk/libs/miniupnpc/minisoap.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/minisoap.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,113 @@
+/* $Id: minisoap.c,v 1.16 2008/10/11 16:39:29 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas Bernard
+ * Copyright (c) 2005 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided in this distribution.
+ *
+ * Minimal SOAP implementation for UPnP protocol.
+ */
+#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#include <io.h>
+#include <winsock2.h>
+#define snprintf _snprintf
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+#include "minisoap.h"
+#include "miniupnpcstrings.h"
+
+/* only for malloc */
+#include <stdlib.h>
+
+#ifdef WIN32
+#define PRINT_SOCKET_ERROR(x)    printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#else
+#define PRINT_SOCKET_ERROR(x) perror(x)
+#endif
+
+/* httpWrite sends the headers and the body to the socket
+ * and returns the number of bytes sent */
+static int
+httpWrite(int fd, const char * body, int bodysize,
+          const char * headers, int headerssize)
+{
+	int n = 0;
+	/*n = write(fd, headers, headerssize);*/
+	/*if(bodysize>0)
+		n += write(fd, body, bodysize);*/
+	/* Note : my old linksys router only took into account
+	 * soap request that are sent into only one packet */
+	char * p;
+	/* TODO: AVOID MALLOC */
+	p = malloc(headerssize+bodysize);
+	if(!p)
+	  return 0;
+	memcpy(p, headers, headerssize);
+	memcpy(p+headerssize, body, bodysize);
+	/*n = write(fd, p, headerssize+bodysize);*/
+	n = send(fd, p, headerssize+bodysize, 0);
+	if(n<0) {
+	  PRINT_SOCKET_ERROR("send");
+	}
+	/* disable send on the socket */
+	/* draytek routers dont seems to like that... */
+#if 0
+#ifdef WIN32
+	if(shutdown(fd, SD_SEND)<0) {
+#else
+	if(shutdown(fd, SHUT_WR)<0)	{ /*SD_SEND*/
+#endif
+		PRINT_SOCKET_ERROR("shutdown");
+	}
+#endif
+	free(p);
+	return n;
+}
+
+/* self explanatory  */
+int soapPostSubmit(int fd,
+                   const char * url,
+				   const char * host,
+				   unsigned short port,
+				   const char * action,
+				   const char * body)
+{
+	int bodysize;
+	char headerbuf[512];
+	int headerssize;
+	char portstr[8];
+	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 */
+    /* 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"*/
+	                   "Host: %s%s\r\n"
+					   "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
+	                   "Content-Length: %d\r\n"
+					   "Content-Type: text/xml\r\n"
+					   "SOAPAction: \"%s\"\r\n"
+					   "Connection: Close\r\n"
+					   "Cache-Control: no-cache\r\n"	/* ??? */
+					   "Pragma: no-cache\r\n"
+					   "\r\n",
+					   url, host, portstr, bodysize, action);
+#ifdef DEBUG
+	printf("SOAP request : headersize=%d bodysize=%d\n",
+	       headerssize, bodysize);
+	/*printf("%s", headerbuf);*/
+#endif
+	return httpWrite(fd, body, bodysize, headerbuf, headerssize);
+}
+
+

Added: freeswitch/trunk/libs/miniupnpc/minisoap.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/minisoap.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,15 @@
+/* $Id: minisoap.h,v 1.3 2006/11/19 22:32:34 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas Bernard
+ * Copyright (c) 2005 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided in this distribution. */
+#ifndef __MINISOAP_H__
+#define __MINISOAP_H__
+
+/*int httpWrite(int, const char *, int, const char *);*/
+int soapPostSubmit(int, const char *, const char *, unsigned short,
+				   const char *, const char *);
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/minissdpc.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/minissdpc.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,109 @@
+/* $Id: minissdpc.c,v 1.7 2008/12/18 17:45:48 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * copyright (c) 2005-2008 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+/*#include <syslog.h>*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#ifdef WIN32
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <io.h>
+#else
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
+#include "minissdpc.h"
+#include "miniupnpc.h"
+
+#include "codelength.h"
+
+struct UPNPDev *
+getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
+{
+	struct UPNPDev * tmp;
+	struct UPNPDev * devlist = NULL;
+	unsigned char buffer[2048];
+	ssize_t n;
+	unsigned char * p;
+	unsigned char * url;
+	unsigned int i;
+	unsigned int urlsize, stsize, usnsize, l;
+	int s;
+	struct sockaddr_un addr;
+
+	s = socket(AF_UNIX, SOCK_STREAM, 0);
+	if(s < 0)
+	{
+		/*syslog(LOG_ERR, "socket(unix): %m");*/
+		perror("socket(unix)");
+		return NULL;
+	}
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
+	if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
+	{
+		/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
+		close(s);
+		return NULL;
+	}
+	stsize = strlen(devtype);
+	buffer[0] = 1; /* request type 1 : request devices/services by type */
+	p = buffer + 1;
+	l = stsize;	CODELENGTH(l, p);
+	memcpy(p, devtype, stsize);
+	p += stsize;
+	if(write(s, buffer, p - buffer) < 0)
+	{
+		/*syslog(LOG_ERR, "write(): %m");*/
+		perror("minissdpc.c: write()");
+		close(s);
+		return NULL;
+	}
+	n = read(s, buffer, sizeof(buffer));
+	if(n<=0)
+	{
+		perror("minissdpc.c: read()");
+		close(s);
+		return NULL;
+	}
+	p = buffer + 1;
+	for(i = 0; i < buffer[0]; i++)
+	{
+		if(p+2>=buffer+sizeof(buffer))
+			break;
+		DECODELENGTH(urlsize, p);
+		if(p+urlsize+2>=buffer+sizeof(buffer))
+			break;
+		url = p;
+		p += urlsize;
+		DECODELENGTH(stsize, p);
+		if(p+stsize+2>=buffer+sizeof(buffer))
+			break;
+		tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
+		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;
+		tmp->buffer[urlsize+1+stsize] = '\0';
+		devlist = tmp;
+		/* added for compatibility with recent versions of MiniSSDPd 
+		 * >= 2007/12/19 */
+		DECODELENGTH(usnsize, p);
+		p += usnsize;
+		if(p>buffer + sizeof(buffer))
+			break;
+	}
+	close(s);
+	return devlist;
+}
+

Added: freeswitch/trunk/libs/miniupnpc/minissdpc.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/minissdpc.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,15 @@
+/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */
+/* Project: miniupnp
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * Author: Thomas Bernard
+ * Copyright (c) 2005-2007 Thomas Bernard
+ * This software is subjects to the conditions detailed
+ * in the LICENCE file provided within this distribution */
+#ifndef __MINISSDPC_H__
+#define __MINISSDPC_H__
+
+struct UPNPDev *
+getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath);
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/miniupnpc.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/miniupnpc.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,747 @@
+/* $Id: miniupnpc.c,v 1.57 2008/12/18 17:46:36 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * copyright (c) 2005-2007 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+/* Win32 Specific includes and defines */
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <io.h>
+#define snprintf _snprintf
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define strncasecmp _memicmp
+#else
+#define strncasecmp memicmp
+#endif
+#define MAXHOSTNAMELEN 64
+#else
+/* Standard POSIX includes */
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <poll.h>
+#include <netdb.h>
+#define closesocket close
+#endif
+#include "miniupnpc.h"
+#include "minissdpc.h"
+#include "miniwget.h"
+#include "minisoap.h"
+#include "minixml.h"
+#include "upnpcommands.h"
+
+#ifdef WIN32
+#define PRINT_SOCKET_ERROR(x)    printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#else
+#define PRINT_SOCKET_ERROR(x) perror(x)
+#endif
+
+#define SOAPPREFIX "s"
+#define SERVICEPREFIX "u"
+#define SERVICEPREFIX2 'u'
+
+/* root description parsing */
+void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
+{
+	struct xmlparser parser;
+	/* xmlparser object */
+	parser.xmlstart = buffer;
+	parser.xmlsize = bufsize;
+	parser.data = data;
+	parser.starteltfunc = IGDstartelt;
+	parser.endeltfunc = IGDendelt;
+	parser.datafunc = IGDdata;
+	parser.attfunc = 0;
+	parsexml(&parser);
+#ifdef DEBUG
+	printIGD(data);
+#endif
+}
+
+/* Content-length: nnn */
+static int getcontentlenfromline(const char * p, int n)
+{
+	static const char contlenstr[] = "content-length";
+	const char * p2 = contlenstr;
+	int a = 0;
+	while(*p2)
+	{
+		if(n==0)
+			return -1;
+		if(*p2 != *p && *p2 != (*p + 32))
+			return -1;
+		p++; p2++; n--;
+	}
+	if(n==0)
+		return -1;
+	if(*p != ':')
+		return -1;
+	p++; n--;
+	while(*p == ' ')
+	{
+		if(n==0)
+			return -1;
+		p++; n--;
+	}
+	while(*p >= '0' && *p <= '9')
+	{
+		if(n==0)
+			return -1;
+		a = (a * 10) + (*p - '0');
+		p++; n--;
+	}
+	return a;
+}
+
+static void
+getContentLengthAndHeaderLength(char * p, int n,
+                                int * contentlen, int * headerlen)
+{
+	char * line;
+	int linelen;
+	int r;
+	line = p;
+	while(line < p + n)
+	{
+		linelen = 0;
+		while(line[linelen] != '\r' && line[linelen] != '\r')
+		{
+			if(line+linelen >= p+n)
+				return;
+			linelen++;
+		}
+		r = getcontentlenfromline(line, linelen);
+		if(r>0)
+			*contentlen = r;
+		line = line + linelen + 2;
+		if(line[0] == '\r' && line[1] == '\n')
+		{
+			*headerlen = (line - p) + 2;
+			return;
+		}
+	}
+}
+
+/* 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)
+{
+	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 n;
+	int contentlen, headerlen;	/* for the response */
+	snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
+	if(args==NULL)
+	{
+		/*soapbodylen = */snprintf(soapbody, sizeof(soapbody),
+						"<?xml version=\"1.0\"?>\r\n"
+	    	              "<" SOAPPREFIX ":Envelope "
+						  "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+						  SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
+						  "<" SOAPPREFIX ":Body>"
+						  "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">"
+						  "</" SERVICEPREFIX ":%s>"
+						  "</" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>"
+					 	  "\r\n", action, service, action);
+	}
+	else
+	{
+		char * p;
+		const char * pe, * pv;
+		int soapbodylen;
+		soapbodylen = snprintf(soapbody, sizeof(soapbody),
+						"<?xml version=\"1.0\"?>\r\n"
+	    	            "<" SOAPPREFIX ":Envelope "
+						"xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+						SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
+						"<" SOAPPREFIX ":Body>"
+						"<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">",
+						action, service);
+		p = soapbody + soapbodylen;
+		while(args->elt)
+		{
+			/* check that we are never overflowing the string... */
+			if(soapbody + sizeof(soapbody) <= p + 100)
+			{
+				/* we keep a margin of at least 100 bytes */
+				*bufsize = 0;
+				return -1;
+			}
+			*(p++) = '<';
+			pe = args->elt;
+			while(*pe)
+				*(p++) = *(pe++);
+			*(p++) = '>';
+			if((pv = args->val))
+			{
+				while(*pv)
+					*(p++) = *(pv++);
+			}
+			*(p++) = '<';
+			*(p++) = '/';
+			pe = args->elt;
+			while(*pe)
+				*(p++) = *(pe++);
+			*(p++) = '>';
+			args++;
+		}
+		*(p++) = '<';
+		*(p++) = '/';
+		*(p++) = SERVICEPREFIX2;
+		*(p++) = ':';
+		pe = action;
+		while(*pe)
+			*(p++) = *(pe++);
+		strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
+		        soapbody + sizeof(soapbody) - p);
+	}
+	if(!parseURL(url, hostname, &port, &path)) return -1;
+	if(s<0)
+	{
+		s = socket(PF_INET, SOCK_STREAM, 0);
+		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);
+	if(n<=0) {
+#ifdef DEBUG
+		printf("Error sending SOAP request\n");
+#endif
+		closesocket(s);
+		return -1;
+	}
+
+	contentlen = -1;
+	headerlen = -1;
+	buf = buffer;
+	buffree = *bufsize;
+	*bufsize = 0;
+	while ((n = ReceiveData(s, buf, buffree, 5000)) > 0) {
+		buffree -= n;
+		buf += n;
+		*bufsize += n;
+		getContentLengthAndHeaderLength(buffer, *bufsize,
+		                                &contentlen, &headerlen);
+#ifdef DEBUG
+		printf("received n=%dbytes bufsize=%d ContLen=%d HeadLen=%d\n",
+		       n, *bufsize, contentlen, headerlen);
+#endif
+		/* break if we received everything */
+		if(contentlen > 0 && headerlen > 0 && *bufsize >= contentlen+headerlen)
+			break;
+	}
+	
+	closesocket(s);
+	return 0;
+}
+
+/* parseMSEARCHReply()
+ * the last 4 arguments are filled during the parsing :
+ *    - location/locationsize : "location:" field of the SSDP reply packet
+ *    - st/stsize : "st:" field of the SSDP reply packet.
+ * The strings are NOT null terminated */
+static void
+parseMSEARCHReply(const char * reply, int size,
+                  const char * * location, int * locationsize,
+			      const char * * st, int * stsize)
+{
+	int a, b, i;
+	i = 0;
+	a = i;	/* start of the line */
+	b = 0;
+	while(i<size)
+	{
+		switch(reply[i])
+		{
+		case ':':
+				if(b==0)
+				{
+					b = i; /* end of the "header" */
+					/*for(j=a; j<b; j++)
+					{
+						putchar(reply[j]);
+					}
+					*/
+				}
+				break;
+		case '\x0a':
+		case '\x0d':
+				if(b!=0)
+				{
+					/*for(j=b+1; j<i; j++)
+					{
+						putchar(reply[j]);
+					}
+					putchar('\n');*/
+					do { b++; } while(reply[b]==' ');
+					if(0==strncasecmp(reply+a, "location", 8))
+					{
+						*location = reply+b;
+						*locationsize = i-b;
+					}
+					else if(0==strncasecmp(reply+a, "st", 2))
+					{
+						*st = reply+b;
+						*stsize = i-b;
+					}
+					b = 0;
+				}
+				a = i+1;
+				break;
+		default:
+				break;
+		}
+		i++;
+	}
+}
+
+/* port upnp discover : SSDP protocol */
+#define PORT 1900
+#define XSTR(s) STR(s)
+#define STR(s) #s
+#define UPNP_MCAST_ADDR "239.255.255.250"
+
+/* upnpDiscover() :
+ * return a chained list of all devices found or NULL if
+ * 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,
+                              const char * minissdpdsock, int sameport)
+{
+	struct UPNPDev * tmp;
+	struct UPNPDev * devlist = 0;
+	int opt = 1;
+	static const char MSearchMsgFmt[] = 
+	"M-SEARCH * HTTP/1.1\r\n"
+	"HOST: " UPNP_MCAST_ADDR ":" XSTR(PORT) "\r\n"
+	"ST: %s\r\n"
+	"MAN: \"ssdp:discover\"\r\n"
+	"MX: 3\r\n"
+	"\r\n";
+	static const char * const deviceList[] = {
+		"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
+		"urn:schemas-upnp-org:service:WANIPConnection:1",
+		"urn:schemas-upnp-org:service:WANPPPConnection:1",
+		"upnp:rootdevice",
+		0
+	};
+	int deviceIndex = 0;
+	char bufr[1536];	/* reception and emission buffer */
+	int sudp;
+	int n;
+	struct sockaddr_in sockudp_r, sockudp_w;
+
+#ifndef WIN32
+	/* first try to get infos from minissdpd ! */
+	if(!minissdpdsock)
+		minissdpdsock = "/var/run/minissdpd.sock";
+	while(!devlist && deviceList[deviceIndex]) {
+		devlist = getDevicesFromMiniSSDPD(deviceList[deviceIndex],
+		                                  minissdpdsock);
+		/* We return what we have found if it was not only a rootdevice */
+		if(devlist && !strstr(deviceList[deviceIndex], "rootdevice"))
+			return devlist;
+		deviceIndex++;
+	}
+	deviceIndex = 0;
+#endif
+	/* fallback to direct discovery */
+#ifdef WIN32
+	sudp = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+#else
+	sudp = socket(PF_INET, SOCK_DGRAM, 0);
+#endif
+	if(sudp < 0)
+	{
+		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);
+
+#ifdef WIN32
+	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
+#else
+	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
+#endif
+	{
+		PRINT_SOCKET_ERROR("setsockopt");
+		return NULL;
+	}
+
+	if(multicastif)
+	{
+		struct in_addr mc_if;
+		mc_if.s_addr = inet_addr(multicastif);
+    	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");
+		}
+	}
+
+	/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
+    if (bind(sudp, (struct sockaddr *)&sockudp_r, sizeof(struct sockaddr_in)) != 0)
+	{
+        PRINT_SOCKET_ERROR("bind");
+		closesocket(sudp);
+		return NULL;
+    }
+
+	/* receiving SSDP response packet */
+	for(n = 0;;)
+	{
+	if(n == 0)
+	{
+		/* sending the SSDP M-SEARCH packet */
+		n = snprintf(bufr, sizeof(bufr),
+		             MSearchMsgFmt, deviceList[deviceIndex++]);
+		/*printf("Sending %s", bufr);*/
+		n = sendto(sudp, bufr, n, 0,
+		           (struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in));
+		if (n < 0) {
+			PRINT_SOCKET_ERROR("sendto");
+			closesocket(sudp);
+			return devlist;
+		}
+	}
+	/* Waiting for SSDP REPLY packet to M-SEARCH */
+	n = ReceiveData(sudp, bufr, sizeof(bufr), delay);
+	if (n < 0) {
+		/* error */
+		closesocket(sudp);
+		return devlist;
+	} else if (n == 0) {
+		/* no data or Time Out */
+		if (devlist || (deviceList[deviceIndex] == 0)) {
+			/* no more device type to look for... */
+			closesocket(sudp);
+			return devlist;
+		}
+	} else {
+		const char * descURL=NULL;
+		int urlsize=0;
+		const char * st=NULL;
+		int stsize=0;
+        /*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */
+		parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize);
+		if(st&&descURL)
+		{
+			/*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
+			       stsize, st, urlsize, descURL); */
+			tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
+			tmp->pNext = devlist;
+			tmp->descURL = tmp->buffer;
+			tmp->st = tmp->buffer + 1 + urlsize;
+			memcpy(tmp->buffer, descURL, urlsize);
+			tmp->buffer[urlsize] = '\0';
+			memcpy(tmp->buffer + urlsize + 1, st, stsize);
+			tmp->buffer[urlsize+1+stsize] = '\0';
+			devlist = tmp;
+		}
+	}
+	}
+}
+
+/* freeUPNPDevlist() should be used to
+ * free the chained list returned by upnpDiscover() */
+void freeUPNPDevlist(struct UPNPDev * devlist)
+{
+	struct UPNPDev * next;
+	while(devlist)
+	{
+		next = devlist->pNext;
+		free(devlist);
+		devlist = next;
+	}
+}
+
+static void
+url_cpy_or_cat(char * dst, const char * src, int n)
+{
+	if(  (src[0] == 'h')
+	   &&(src[1] == 't')
+	   &&(src[2] == 't')
+	   &&(src[3] == 'p')
+	   &&(src[4] == ':')
+	   &&(src[5] == '/')
+	   &&(src[6] == '/'))
+	{
+		strncpy(dst, src, n);
+	}
+	else
+	{
+		int l = strlen(dst);
+		if(src[0] != '/')
+			dst[l++] = '/';
+		if(l<=n)
+			strncpy(dst + l, src, n - l);
+	}
+}
+
+/* Prepare the Urls for usage...
+ */
+void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
+                 const char * descURL)
+{
+	char * p;
+	int n1, n2, n3;
+	n1 = strlen(data->urlbase);
+	if(n1==0)
+		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);
+
+	urls->ipcondescURL = (char *)malloc(n1);
+	urls->controlURL = (char *)malloc(n2);
+	urls->controlURL_CIF = (char *)malloc(n3);
+	/* maintenant on chope la desc du WANIPConnection */
+	if(data->urlbase[0] != '\0')
+		strncpy(urls->ipcondescURL, data->urlbase, n1);
+	else
+		strncpy(urls->ipcondescURL, descURL, n1);
+	p = strchr(urls->ipcondescURL+7, '/');
+	if(p) p[0] = '\0';
+	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->controlURL, data->controlurl, n2);
+
+	url_cpy_or_cat(urls->controlURL_CIF, data->controlurl_CIF, 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);
+#endif
+}
+
+void
+FreeUPNPUrls(struct UPNPUrls * urls)
+{
+	if(!urls)
+		return;
+	free(urls->controlURL);
+	urls->controlURL = 0;
+	free(urls->ipcondescURL);
+	urls->ipcondescURL = 0;
+	free(urls->controlURL_CIF);
+	urls->controlURL_CIF = 0;
+}
+
+
+int ReceiveData(int socket, char * data, int length, int timeout)
+{
+    int n;
+#ifndef WIN32
+    struct pollfd fds[1]; /* for the poll */
+    fds[0].fd = socket;
+    fds[0].events = POLLIN;
+    n = poll(fds, 1, timeout);
+    if(n < 0)
+    {
+        PRINT_SOCKET_ERROR("poll");
+        return -1;
+    }
+    else if(n == 0)
+    {
+        return 0;
+    }
+#else
+    fd_set socketSet;
+    TIMEVAL timeval;
+    FD_ZERO(&socketSet);
+    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)
+    {
+        PRINT_SOCKET_ERROR("select");
+        return -1;
+    }
+    else if(n == 0)
+    {
+        return 0;
+    }    
+#endif
+	n = recv(socket, data, length, 0);
+	if(n<0)
+	{
+		PRINT_SOCKET_ERROR("recv");
+	}
+	return n;
+}
+
+int
+UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
+{
+	char status[64];
+	unsigned int uptime;
+	status[0] = '\0';
+	UPNP_GetStatusInfo(urls->controlURL, data->servicetype,
+	                   status, &uptime, NULL);
+	if(0 == strcmp("Connected", status))
+	{
+		return 1;
+	}
+	else
+		return 0;
+}
+
+
+/* UPNP_GetValidIGD() :
+ * return values :
+ *     0 = NO IGD found
+ *     1 = A valid connected IGD has been found
+ *     2 = A valid IGD has been found but it reported as
+ *         not connected
+ *     3 = an UPnP device has been found but was not recognized as an IGD
+ *
+ * In any non zero return case, the urls and data structures
+ * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
+ * free allocated memory.
+ */
+int
+UPNP_GetValidIGD(struct UPNPDev * devlist,
+                 struct UPNPUrls * urls,
+				 struct IGDdatas * data,
+				 char * lanaddr, int lanaddrlen)
+{
+	char * descXML;
+	int descXMLsize = 0;
+	struct UPNPDev * dev;
+	int ndev = 0;
+	int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
+	if(!devlist)
+	{
+#ifdef DEBUG
+		printf("Empty devlist\n");
+#endif
+		return 0;
+	}
+	for(state = 1; state <= 3; state++)
+	{
+		for(dev = devlist; dev; dev = dev->pNext)
+		{
+			/* we should choose an internet gateway device.
+		 	* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
+			descXML = miniwget_getaddr(dev->descURL, &descXMLsize,
+			   	                        lanaddr, lanaddrlen);
+			if(descXML)
+			{
+				ndev++;
+				memset(data, 0, sizeof(struct IGDdatas));
+				memset(urls, 0, sizeof(struct UPNPUrls));
+				parserootdesc(descXML, descXMLsize, data);
+				free(descXML);
+				descXML = NULL;
+				if(0==strcmp(data->servicetype_CIF,
+				   "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
+				   || state >= 3 )
+				{
+				  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));
+			}
+#ifdef DEBUG
+			else
+			{
+				printf("error getting XML description %s\n", dev->descURL);
+			}
+#endif
+		}
+	}
+	return 0;
+}
+
+/* UPNP_GetIGDFromUrl()
+ * Used when skipping the discovery process.
+ * return value :
+ *   0 - Not ok
+ *   1 - OK */
+int
+UPNP_GetIGDFromUrl(const char * rootdescurl,
+                   struct UPNPUrls * urls,
+                   struct IGDdatas * data,
+                   char * lanaddr, int lanaddrlen)
+{
+	char * descXML;
+	int descXMLsize = 0;
+	descXML = miniwget_getaddr(rootdescurl, &descXMLsize,
+	   	                       lanaddr, lanaddrlen);
+	if(descXML) {
+		memset(data, 0, sizeof(struct IGDdatas));
+		memset(urls, 0, sizeof(struct UPNPUrls));
+		parserootdesc(descXML, descXMLsize, data);
+		free(descXML);
+		descXML = NULL;
+		GetUPNPUrls(urls, data, rootdescurl);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+

Added: freeswitch/trunk/libs/miniupnpc/miniupnpc.def
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/miniupnpc.def	Fri May 29 15:14:45 2009
@@ -0,0 +1,31 @@
+LIBRARY
+; miniupnpc library
+
+EXPORTS
+; miniupnpc
+   upnpDiscover
+   freeUPNPDevlist
+   parserootdesc
+   UPNP_GetValidIGD
+   UPNP_GetIGDFromUrl
+   GetUPNPUrls
+   FreeUPNPUrls
+; miniwget
+   miniwget
+   miniwget_getaddr
+; upnpcommands
+   UPNP_GetTotalBytesSent
+   UPNP_GetTotalBytesReceived
+   UPNP_GetTotalPacketsSent
+   UPNP_GetTotalPacketsReceived
+   UPNP_GetStatusInfo
+   UPNP_GetConnectionTypeInfo
+   UPNP_GetExternalIPAddress
+   UPNP_GetLinkLayerMaxBitRates
+   UPNP_AddPortMapping
+   UPNP_DeletePortMapping
+   UPNP_GetPortMappingNumberOfEntries
+   UPNP_GetSpecificPortMappingEntry
+   UPNP_GetGenericPortMappingEntry 
+; upnperrors
+   strupnperror
\ No newline at end of file

Added: freeswitch/trunk/libs/miniupnpc/miniupnpc.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/miniupnpc.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,110 @@
+/* $Id: miniupnpc.h,v 1.18 2008/09/25 18:02:50 nanard Exp $ */
+/* Project: miniupnp
+ * http://miniupnp.free.fr/
+ * Author: Thomas Bernard
+ * Copyright (c) 2005-2006 Thomas Bernard
+ * This software is subjects to the conditions detailed
+ * in the LICENCE file provided within this distribution */
+#ifndef __MINIUPNPC_H__
+#define __MINIUPNPC_H__
+
+#include "declspec.h"
+#include "igd_desc_parse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Structures definitions : */
+struct UPNParg { const char * elt; const char * val; };
+
+int simpleUPnPcommand(int, const char *, const char *,
+                      const char *, struct UPNParg *,
+                      char *, int *);
+
+struct UPNPDev {
+	struct UPNPDev * pNext;
+	char * descURL;
+	char * st;
+	char buffer[2];
+};
+
+/* upnpDiscover()
+ * discover UPnP devices on the network.
+ * The discovered devices are returned as a chained list.
+ * It is up to the caller to free the list with freeUPNPDevlist().
+ * delay (in millisecond) is the maximum time for waiting any device
+ * response.
+ * If available, device list will be obtained from MiniSSDPd.
+ * Default path for minissdpd socket will be used if minissdpdsock argument
+ * is NULL.
+ * If multicastif is not NULL, it will be used instead of the default
+ * multicast interface for sending SSDP discover packets.
+ * If sameport is not null, SSDP packets will be sent from the source port
+ * 1900 (same as destination port) otherwise system assign a source port. */
+LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
+                                      const char * minissdpdsock, int sameport);
+/* freeUPNPDevlist()
+ * free list returned by upnpDiscover() */
+LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
+
+/* parserootdesc() :
+ * parse root XML description of a UPnP device and fill the IGDdatas
+ * structure. */
+LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
+
+/* structure used to get fast access to urls
+ * controlURL: controlURL of the WANIPConnection
+ * ipcondescURL: url of the description of the WANIPConnection
+ * controlURL_CIF: controlURL of the WANCommonInterfaceConfig
+ */
+struct UPNPUrls {
+	char * controlURL;
+	char * ipcondescURL;
+	char * controlURL_CIF;
+};
+
+/* UPNP_GetValidIGD() :
+ * return values :
+ *     0 = NO IGD found
+ *     1 = A valid connected IGD has been found
+ *     2 = A valid IGD has been found but it reported as
+ *         not connected
+ *     3 = an UPnP device has been found but was not recognized as an IGD
+ *
+ * In any non zero return case, the urls and data structures
+ * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
+ * free allocated memory.
+ */
+LIBSPEC int
+UPNP_GetValidIGD(struct UPNPDev * devlist,
+                 struct UPNPUrls * urls,
+				 struct IGDdatas * data,
+				 char * lanaddr, int lanaddrlen);
+
+/* UPNP_GetIGDFromUrl()
+ * Used when skipping the discovery process.
+ * return value :
+ *   0 - Not ok
+ *   1 - OK */
+LIBSPEC int
+UPNP_GetIGDFromUrl(const char * rootdescurl,
+                   struct UPNPUrls * urls,
+                   struct IGDdatas * data,
+                   char * lanaddr, int lanaddrlen);
+
+LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);
+
+LIBSPEC void FreeUPNPUrls(struct UPNPUrls *);
+
+/* Reads data from the specified socket. 
+ * Returns the number of bytes read if successful, zero if no bytes were 
+ * read or if we timed out. Returns negative if there was an error. */
+int ReceiveData(int socket, char * data, int length, int timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/miniupnpcmodule.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/miniupnpcmodule.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,460 @@
+/* $Id: miniupnpcmodule.c,v 1.13 2009/04/17 20:59:42 nanard Exp $*/
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * website : http://miniupnp.tuxfamily.org/
+ * copyright (c) 2007 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#include <Python.h>
+#define STATICLIB
+#include "structmember.h"
+#include "miniupnpc.h"
+#include "upnpcommands.h"
+#include "upnperrors.h"
+
+/* for compatibility with Python < 2.4 */
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
+#endif
+
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
+#endif
+
+typedef struct {
+    PyObject_HEAD
+    /* Type-specific fields go here. */
+	struct UPNPDev * devlist;
+	struct UPNPUrls urls;
+	struct IGDdatas data;
+	unsigned int discoverdelay;	/* value passed to upnpDiscover() */
+	char lanaddr[16];	/* our ip address on the LAN */
+	char * multicastif;
+	char * minissdpdsocket;
+} UPnPObject;
+
+static PyMemberDef UPnP_members[] = {
+	{"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
+	 READONLY, "ip address on the LAN"
+	},
+	{"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
+	 0/*READWRITE*/, "value in ms used to wait for SSDP responses"
+	},
+	/* T_STRING is allways readonly :( */
+	{"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
+	 0, "IP of the network interface to be used for multicast operations"
+	},
+	{"minissdpdsocket", T_STRING, offsetof(UPnPObject, multicastif),
+	 0, "path of the MiniSSDPd unix socket"
+	},
+	{NULL}
+};
+
+static void
+UPnPObject_dealloc(UPnPObject *self)
+{
+	freeUPNPDevlist(self->devlist);
+	FreeUPNPUrls(&self->urls);
+	self->ob_type->tp_free((PyObject*)self);
+}
+
+static PyObject *
+UPnP_discover(UPnPObject *self)
+{
+	struct UPNPDev * dev;
+	int i;
+	PyObject *res = NULL;
+	if(self->devlist)
+	{
+		freeUPNPDevlist(self->devlist);
+		self->devlist = 0;
+	}
+	self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
+	                             0/* multicast if*/,
+	                             0/*minissdpd socket*/,
+								 0/*sameport flag*/);
+	/* Py_RETURN_NONE ??? */
+	for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
+		i++;
+	res = Py_BuildValue("i", i);
+	return res;
+}
+
+static PyObject *
+UPnP_selectigd(UPnPObject *self)
+{
+	if(UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
+	                    self->lanaddr, sizeof(self->lanaddr)))
+	{
+		return Py_BuildValue("s", self->urls.controlURL);
+	}
+	else
+	{
+		/* TODO: have our own exception type ! */
+		PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
+		return NULL;
+	}
+}
+
+static PyObject *
+UPnP_totalbytesent(UPnPObject *self)
+{
+	return Py_BuildValue("I",
+	           UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
+			                          self->data.servicetype_CIF));
+}
+
+static PyObject *
+UPnP_totalbytereceived(UPnPObject *self)
+{
+	return Py_BuildValue("I",
+	           UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
+			                          self->data.servicetype_CIF));
+}
+
+static PyObject *
+UPnP_totalpacketsent(UPnPObject *self)
+{
+	return Py_BuildValue("I",
+	           UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
+			                          self->data.servicetype_CIF));
+}
+
+static PyObject *
+UPnP_totalpacketreceived(UPnPObject *self)
+{
+	return Py_BuildValue("I",
+	           UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
+			                          self->data.servicetype_CIF));
+}
+
+static PyObject *
+UPnP_statusinfo(UPnPObject *self)
+{
+	char status[64];
+	char lastconnerror[64];
+	unsigned int uptime = 0;
+	int r;
+	status[0] = '\0';
+	lastconnerror[0] = '\0';
+	r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.servicetype,
+	                   status, &uptime, lastconnerror);
+	if(r==UPNPCOMMAND_SUCCESS) {
+		return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
+	} else {
+		/* TODO: have our own exception type ! */
+		PyErr_SetString(PyExc_Exception, strupnperror(r));
+		return NULL;
+	}
+}
+
+static PyObject *
+UPnP_connectiontype(UPnPObject *self)
+{
+	char connectionType[64];
+	int r;
+	connectionType[0] = '\0';
+	r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
+	                               self->data.servicetype,
+	                               connectionType);
+	if(r==UPNPCOMMAND_SUCCESS) {
+		return Py_BuildValue("s", connectionType);
+	} else {
+		/* TODO: have our own exception type ! */
+		PyErr_SetString(PyExc_Exception, strupnperror(r));
+		return NULL;
+	}
+}
+
+static PyObject *
+UPnP_externalipaddress(UPnPObject *self)
+{
+	char externalIPAddress[16];
+	int r;
+	externalIPAddress[0] = '\0';
+	r = UPNP_GetExternalIPAddress(self->urls.controlURL,
+	                              self->data.servicetype,
+	                              externalIPAddress);
+	if(r==UPNPCOMMAND_SUCCESS) {
+		return Py_BuildValue("s", externalIPAddress);
+	} else {
+		/* TODO: have our own exception type ! */
+		PyErr_SetString(PyExc_Exception, strupnperror(r));
+		return NULL;
+	}
+}
+
+/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
+ *                remoteHost) 
+ * protocol is 'UDP' or 'TCP' */
+static PyObject *
+UPnP_addportmapping(UPnPObject *self, PyObject *args)
+{
+	char extPort[6];
+	unsigned short ePort;
+	char inPort[6];
+	unsigned short iPort;
+	const char * proto;
+	const char * host;
+	const char * desc;
+	const char * remoteHost;
+	int r;
+	if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
+	                                     &host, &iPort, &desc, &remoteHost))
+        return NULL;
+	sprintf(extPort, "%hu", ePort);
+	sprintf(inPort, "%hu", iPort);
+	r = UPNP_AddPortMapping(self->urls.controlURL, self->data.servicetype,
+	                        extPort, inPort, host, desc, proto, remoteHost);
+	if(r==UPNPCOMMAND_SUCCESS)
+	{
+		Py_RETURN_TRUE;
+	}
+	else
+	{
+		// TODO: RAISE an Exception. See upnpcommands.h for errors codes.
+		// upnperrors.c
+		//Py_RETURN_FALSE;
+		/* TODO: have our own exception type ! */
+		PyErr_SetString(PyExc_Exception, strupnperror(r));
+		return NULL;
+	}
+}
+
+/* DeletePortMapping(extPort, proto, removeHost='')
+ * proto = 'UDP', 'TCP' */
+static PyObject *
+UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
+{
+	char extPort[6];
+	unsigned short ePort;
+	const char * proto;
+	const char * remoteHost = "";
+	int r;
+	if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
+		return NULL;
+	sprintf(extPort, "%hu", ePort);
+	r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.servicetype,
+	                           extPort, proto, remoteHost);
+	if(r==UPNPCOMMAND_SUCCESS) {
+		Py_RETURN_TRUE;
+	} else {
+		/* TODO: have our own exception type ! */
+		PyErr_SetString(PyExc_Exception, strupnperror(r));
+		return NULL;
+	}
+}
+
+static PyObject *
+UPnP_getportmappingnumberofentries(UPnPObject *self)
+{
+	unsigned int n = 0;
+	int r;
+	r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
+	                                   self->data.servicetype,
+									   &n);
+	if(r==UPNPCOMMAND_SUCCESS) {
+		return Py_BuildValue("I", n);
+	} else {
+		/* TODO: have our own exception type ! */
+		PyErr_SetString(PyExc_Exception, strupnperror(r));
+		return NULL;
+	}
+}
+
+/* GetSpecificPortMapping(ePort, proto) 
+ * proto = 'UDP' or 'TCP' */
+static PyObject *
+UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
+{
+	char extPort[6];
+	unsigned short ePort;
+	const char * proto;
+	char intClient[16];
+	char intPort[6];
+	unsigned short iPort;
+	if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto))
+		return NULL;
+	sprintf(extPort, "%hu", ePort);
+	UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
+	                                 self->data.servicetype,
+									 extPort, proto,
+									 intClient, intPort);
+	if(intClient[0])
+	{
+		iPort = (unsigned short)atoi(intPort);
+		return Py_BuildValue("(s,H)", intClient, iPort);
+	}
+	else
+	{
+		Py_RETURN_NONE;
+	}
+}
+
+/* GetGenericPortMapping(index) */
+static PyObject *
+UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
+{
+	int i, r;
+	char index[8];
+	char intClient[16];
+	char intPort[6];
+	unsigned short iPort;
+	char extPort[6];
+	unsigned short ePort;
+	char protocol[4];
+	char desc[80];
+	char enabled[6];
+	char rHost[64];
+	char duration[16];	/* lease duration */
+	unsigned int dur;
+	if(!PyArg_ParseTuple(args, "i", &i))
+		return NULL;
+	snprintf(index, sizeof(index), "%d", i);
+	rHost[0] = '\0'; enabled[0] = '\0';
+	duration[0] = '\0'; desc[0] = '\0';
+	extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
+	r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
+	                                    self->data.servicetype,
+										index,
+										extPort, intClient, intPort,
+										protocol, desc, enabled, rHost,
+										duration);
+	if(r==UPNPCOMMAND_SUCCESS)
+	{
+		ePort = (unsigned short)atoi(extPort);
+		iPort = (unsigned short)atoi(intPort);
+		dur = (unsigned int)strtoul(duration, 0, 0);
+		return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
+		                     ePort, protocol, intClient, iPort,
+		                     desc, enabled, rHost, dur);
+	}
+	else
+	{
+		Py_RETURN_NONE;
+	}
+}
+
+/* miniupnpc.UPnP object Method Table */
+static PyMethodDef UPnP_methods[] = {
+    {"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
+     "discover UPnP IGD devices on the network"
+    },
+	{"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
+	 "select a valid UPnP IGD among discovered devices"
+	},
+	{"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
+	 "return the total number of bytes sent by UPnP IGD"
+	},
+	{"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
+	 "return the total number of bytes received by UPnP IGD"
+	},
+	{"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
+	 "return the total number of packets sent by UPnP IGD"
+	},
+	{"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
+	 "return the total number of packets received by UPnP IGD"
+	},
+	{"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
+	 "return status and uptime"
+	},
+	{"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
+	 "return IGD WAN connection type"
+	},
+	{"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
+	 "return external IP address"
+	},
+	{"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
+	 "add a port mapping"
+	},
+	{"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
+	 "delete a port mapping"
+	},
+	{"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
+	 "-- non standard --"
+	},
+	{"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
+	 "get details about a specific port mapping entry"
+	},
+	{"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
+	 "get all details about the port mapping at index"
+	},
+    {NULL}  /* Sentinel */
+};
+
+static PyTypeObject UPnPType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "miniupnpc.UPnP",          /*tp_name*/
+    sizeof(UPnPObject),        /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)UPnPObject_dealloc,/*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,        /*tp_flags*/
+    "UPnP objects",            /* tp_doc */
+    0,		                   /* tp_traverse */
+    0,		                   /* tp_clear */
+    0,		                   /* tp_richcompare */
+    0,		                   /* tp_weaklistoffset */
+    0,		                   /* tp_iter */
+    0,		                   /* tp_iternext */
+    UPnP_methods,              /* tp_methods */
+    UPnP_members,              /* tp_members */
+    0,                         /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    0,/*(initproc)UPnP_init,*/      /* tp_init */
+    0,                         /* tp_alloc */
+#ifndef WIN32
+    PyType_GenericNew,/*UPnP_new,*/      /* tp_new */
+#else
+    0,
+#endif
+};
+
+/* module methods */
+static PyMethodDef miniupnpc_methods[] = {
+    {NULL}  /* Sentinel */
+};
+
+#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+initminiupnpc(void) 
+{
+    PyObject* m;
+
+#ifdef WIN32
+    UPnPType.tp_new = PyType_GenericNew;
+#endif
+    if (PyType_Ready(&UPnPType) < 0)
+        return;
+
+    m = Py_InitModule3("miniupnpc", miniupnpc_methods,
+                       "miniupnpc module.");
+
+    Py_INCREF(&UPnPType);
+    PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
+}
+

Added: freeswitch/trunk/libs/miniupnpc/miniupnpcstrings.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/miniupnpcstrings.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,15 @@
+/* $Id: miniupnpcstrings.h,v 1.2 2008/10/14 17:39:04 nanard Exp $ */
+/* Project: miniupnp
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * Author: Thomas Bernard
+ * Copyright (c) 2005-2008 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"
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/miniwget.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/miniwget.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,222 @@
+/* $Id: miniwget.c,v 1.22 2009/02/28 10:36:35 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas Bernard
+ * Copyright (c) 2005 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 "miniupnpc.h"
+#ifdef WIN32
+#include <winsock2.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
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#define closesocket close
+#endif
+#if defined(__sun) || defined(sun)
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#endif
+
+#include "miniupnpcstrings.h"
+
+/* miniwget2() :
+ * */
+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 buf[2048];
+    int s;
+	struct sockaddr_in dest;
+	struct hostent *hp;
+	*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);
+	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;
+
+		len = sizeof(saddr);
+		getsockname(s, (struct sockaddr *)&saddr, &len);
+#ifndef WIN32
+		inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
+#else
+	/* 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),
+                            NULL, addr_str, (DWORD *)&addr_str_len))
+		{
+		    printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
+		}*/
+		strncpy(addr_str, inet_ntoa(saddr.sin_addr), addr_str_len);
+#endif
+#ifdef DEBUG
+		printf("address miniwget : %s\n", addr_str);
+#endif
+	}
+
+	snprintf(buf, sizeof(buf),
+                 "GET %s HTTP/1.1\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);
+	{
+		int n, 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)
+				{
+					if(buf[i]=='\r' && buf[i+1]=='\n'
+					   && buf[i+2]=='\r' && buf[i+3]=='\n')
+					{
+						headers = 0;	/* end */
+						if(i<n-4)
+						{
+							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;
+	}
+}
+
+/* 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 
+ *
+ * Return values :
+ *    0 - Failure
+ *    1 - Success         */
+int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
+{
+	char * p1, *p2, *p3;
+	p1 = strstr(url, "://");
+	if(!p1)
+		return 0;
+	p1 += 3;
+	if(  (url[0]!='h') || (url[1]!='t')
+	   ||(url[2]!='t') || (url[3]!='p'))
+		return 0;
+	p2 = strchr(p1, ':');
+	p3 = strchr(p1, '/');
+	if(!p3)
+		return 0;
+	memset(hostname, 0, MAXHOSTNAMELEN + 1);
+	if(!p2 || (p2>p3))
+	{
+		strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
+		*port = 80;
+	}
+	else
+	{
+		strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
+		*port = 0;
+		p2++;
+		while( (*p2 >= '0') && (*p2 <= '9'))
+		{
+			*port *= 10;
+			*port += (unsigned short)(*p2 - '0');
+			p2++;
+		}
+	}
+	*path = p3;
+	return 1;
+}
+
+void * miniwget(const char * url, int * size)
+{
+	unsigned short port;
+	char * path;
+	/* protocol://host:port/chemin */
+	char hostname[MAXHOSTNAMELEN+1];
+	*size = 0;
+	if(!parseURL(url, hostname, &port, &path))
+		return NULL;
+	return miniwget2(url, hostname, port, path, size, 0, 0);
+}
+
+void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
+{
+	unsigned short port;
+	char * path;
+	/* protocol://host:port/chemin */
+	char hostname[MAXHOSTNAMELEN+1];
+	*size = 0;
+	if(addr)
+		addr[0] = '\0';
+	if(!parseURL(url, hostname, &port, &path))
+		return NULL;
+	return miniwget2(url, hostname, port, path, size, addr, addrlen);
+}
+

Added: freeswitch/trunk/libs/miniupnpc/miniwget.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/miniwget.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,28 @@
+/* $Id: miniwget.h,v 1.5 2007/01/29 20:27:23 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas Bernard
+ * Copyright (c) 2005 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided in this distribution.
+ * */
+#ifndef __MINIWGET_H__
+#define __MINIWGET_H__
+
+#include "declspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBSPEC void * miniwget(const char *, int *);
+
+LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int);
+
+int parseURL(const char *, char *, unsigned short *, char * *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/minixml.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/minixml.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,191 @@
+/* $Id: minixml.c,v 1.6 2007/05/15 18:14:08 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 
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * The name of the author may not be used to endorse or promote products
+	  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "minixml.h"
+
+/* 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)
+{
+	const char * attname;
+	int attnamelen;
+	const char * attvalue;
+	int attvaluelen;
+	while(p->xml < p->xmlend)
+	{
+		if(*p->xml=='/' || *p->xml=='>')
+			return 0;
+		if( !IS_WHITE_SPACE(*p->xml) )
+		{
+			char sep;
+			attname = p->xml;
+			attnamelen = 0;
+			while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
+			{
+				attnamelen++; p->xml++;
+				if(p->xml >= p->xmlend)
+					return -1;
+			}
+			while(*(p->xml++) != '=')
+			{
+				if(p->xml >= p->xmlend)
+					return -1;
+			}
+			while(IS_WHITE_SPACE(*p->xml))
+			{
+				p->xml++;
+				if(p->xml >= p->xmlend)
+					return -1;
+			}
+			sep = *p->xml;
+			if(sep=='\'' || sep=='\"')
+			{
+				p->xml++;
+				if(p->xml >= p->xmlend)
+					return -1;
+				attvalue = p->xml;
+				attvaluelen = 0;
+				while(*p->xml != sep)
+				{
+					attvaluelen++; p->xml++;
+					if(p->xml >= p->xmlend)
+						return -1;
+				}
+			}
+			else
+			{
+				attvalue = p->xml;
+				attvaluelen = 0;
+				while(   !IS_WHITE_SPACE(*p->xml)
+					  && *p->xml != '>' && *p->xml != '/')
+				{
+					attvaluelen++; p->xml++;
+					if(p->xml >= p->xmlend)
+						return -1;
+				}
+			}
+			/*printf("%.*s='%.*s'\n",
+			       attnamelen, attname, attvaluelen, attvalue);*/
+			if(p->attfunc)
+				p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
+		}
+		p->xml++;
+	}
+	return -1;
+}
+
+/* parseelt parse the xml stream and
+ * call the callback functions when needed... */
+void parseelt(struct xmlparser * p)
+{
+	int i;
+	const char * elementname;
+	while(p->xml < (p->xmlend - 1))
+	{
+		if((p->xml)[0]=='<' && (p->xml)[1]!='?')
+		{
+			i = 0; elementname = ++p->xml;
+			while( !IS_WHITE_SPACE(*p->xml)
+				  && (*p->xml!='>') && (*p->xml!='/')
+				 )
+			{
+				i++; p->xml++;
+				if (p->xml >= p->xmlend)
+					return;
+				/* to ignore namespace : */
+				if(*p->xml==':')
+				{
+					i = 0;
+					elementname = ++p->xml;
+				}
+			}
+			if(i>0)
+			{
+				if(p->starteltfunc)
+					p->starteltfunc(p->data, elementname, i);
+				if(parseatt(p))
+					return;
+				if(*p->xml!='/')
+				{
+					const char * data;
+					i = 0; data = ++p->xml;
+					if (p->xml >= p->xmlend)
+						return;
+					while( IS_WHITE_SPACE(*p->xml) )
+					{
+						p->xml++;
+						if (p->xml >= p->xmlend)
+							return;
+					}
+					while(*p->xml!='<')
+					{
+						i++; p->xml++;
+						if (p->xml >= p->xmlend)
+							return;
+					}
+					if(i>0 && p->datafunc)
+						p->datafunc(p->data, data, i);
+				}
+			}
+			else if(*p->xml == '/')
+			{
+				i = 0; elementname = ++p->xml;
+				if (p->xml >= p->xmlend)
+					return;
+				while((*p->xml != '>'))
+				{
+					i++; p->xml++;
+					if (p->xml >= p->xmlend)
+						return;
+				}
+				if(p->endeltfunc)
+					p->endeltfunc(p->data, elementname, i);
+				p->xml++;
+			}
+		}
+		else
+		{
+			p->xml++;
+		}
+	}
+}
+
+/* the parser must be initialized before calling this function */
+void parsexml(struct xmlparser * parser)
+{
+	parser->xml = parser->xmlstart;
+	parser->xmlend = parser->xmlstart + parser->xmlsize;
+	parseelt(parser);
+}
+
+

Added: freeswitch/trunk/libs/miniupnpc/minixml.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/minixml.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,37 @@
+/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */
+/* minimal xml parser
+ *
+ * Project : miniupnp
+ * Website : http://miniupnp.free.fr/
+ * Author : Thomas Bernard
+ * Copyright (c) 2005 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided in this distribution.
+ * */
+#ifndef __MINIXML_H__
+#define __MINIXML_H__
+#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
+
+/* if a callback function pointer is set to NULL,
+ * the function is not called */
+struct xmlparser {
+	const char *xmlstart;
+	const char *xmlend;
+	const char *xml;	/* pointer to current character */
+	int xmlsize;
+	void * data;
+	void (*starteltfunc) (void *, const char *, int);
+	void (*endeltfunc) (void *, const char *, int);
+	void (*datafunc) (void *, const char *, int);
+	void (*attfunc) (void *, const char *, int, const char *, int);
+};
+
+/* parsexml()
+ * the xmlparser structure must be initialized before the call
+ * the following structure members have to be initialized :
+ * xmlstart, xmlsize, data, *func
+ * xml is for internal usage, xmlend is computed automatically */
+void parsexml(struct xmlparser *);
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/minixmlvalid.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/minixmlvalid.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,149 @@
+/* $Id: minixmlvalid.c,v 1.2 2006/11/30 11:31:55 nanard Exp $ */
+/* MiniUPnP Project
+ * http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
+ * minixmlvalid.c :
+ * validation program for the minixml parser
+ *
+ * (c) 2006 Thomas Bernard */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "minixml.h"
+
+/* xml event structure */
+struct event {
+	enum { ELTSTART, ELTEND, ATT, CHARDATA } type;
+	const char * data;
+	int len;
+};
+
+struct eventlist {
+	int n;
+	struct event * events;
+};
+
+/* compare 2 xml event lists
+ * return 0 if the two lists are equals */
+int evtlistcmp(struct eventlist * a, struct eventlist * b)
+{
+	int i;
+	struct event * ae, * be;
+	if(a->n != b->n)
+		return 1;
+	for(i=0; i<a->n; i++)
+	{
+		ae = a->events + i;
+		be = b->events + i;
+		if(  (ae->type != be->type)
+		   ||(ae->len != be->len)
+		   ||memcmp(ae->data, be->data, ae->len))
+		{
+			printf("Found a difference : %d '%.*s' != %d '%.*s'\n",
+			       ae->type, ae->len, ae->data,
+			       be->type, be->len, be->data);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/* Test data */
+static const char xmldata[] =
+"<xmlroot>\n"
+" <elt1 att1=\"attvalue1\" att2=\"attvalue2\">"
+"character data"
+"</elt1> \n \t"
+"<elt1b/>"
+"<elt2a> \t<elt2b>chardata1</elt2b><elt2b>chardata2</elt2b></elt2a>"
+"</xmlroot>";
+
+static const struct event evtref[] =
+{
+	{ELTSTART, "xmlroot", 7},
+	{ELTSTART, "elt1", 4},
+	/* attributes */
+	{CHARDATA, "character data", 14},
+	{ELTEND, "elt1", 4},
+	{ELTSTART, "elt1b", 5},
+	{ELTSTART, "elt2a", 5},
+	{ELTSTART, "elt2b", 5},
+	{CHARDATA, "chardata1", 9},
+	{ELTEND, "elt2b", 5},
+	{ELTSTART, "elt2b", 5},
+	{CHARDATA, "chardata2", 9},
+	{ELTEND, "elt2b", 5},
+	{ELTEND, "elt2a", 5},
+	{ELTEND, "xmlroot", 7}
+};	
+
+void startelt(void * data, const char * p, int l)
+{
+	struct eventlist * evtlist = data;
+	struct event * evt;
+	evt = evtlist->events + evtlist->n;
+	/*printf("startelt : %.*s\n", l, p);*/
+	evt->type = ELTSTART;
+	evt->data = p;
+	evt->len = l;
+	evtlist->n++;
+}
+
+void endelt(void * data, const char * p, int l)
+{
+	struct eventlist * evtlist = data;
+	struct event * evt;
+	evt = evtlist->events + evtlist->n;
+	/*printf("endelt : %.*s\n", l, p);*/
+	evt->type = ELTEND;
+	evt->data = p;
+	evt->len = l;
+	evtlist->n++;
+}
+
+void chardata(void * data, const char * p, int l)
+{
+	struct eventlist * evtlist = data;
+	struct event * evt;
+	evt = evtlist->events + evtlist->n;
+	/*printf("chardata : '%.*s'\n", l, p);*/
+	evt->type = CHARDATA;
+	evt->data = p;
+	evt->len = l;
+	evtlist->n++;
+}
+
+int testxmlparser(const char * xml, int size)
+{
+	int r;
+	struct eventlist evtlist;
+	struct eventlist evtlistref;
+	struct xmlparser parser;
+	evtlist.n = 0;
+	evtlist.events = malloc(sizeof(struct event)*100);
+	memset(&parser, 0, sizeof(parser));
+	parser.xmlstart = xml;
+	parser.xmlsize = size;
+	parser.data = &evtlist;
+	parser.starteltfunc = startelt;
+	parser.endeltfunc = endelt;
+	parser.datafunc = chardata;
+	parsexml(&parser);
+	printf("%d events\n", evtlist.n);
+	/* compare */
+	evtlistref.n = sizeof(evtref)/sizeof(struct event);
+	evtlistref.events = (struct event *)evtref;
+	r = evtlistcmp(&evtlistref, &evtlist);
+	free(evtlist.events);
+	return r;
+}
+
+int main(int argc, char * * argv)
+{
+	int r;
+	r = testxmlparser(xmldata, sizeof(xmldata)-1);
+	if(r)
+		printf("minixml validation test failed\n");
+	return r;
+}
+

Added: freeswitch/trunk/libs/miniupnpc/pymoduletest.py
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/pymoduletest.py	Fri May 29 15:14:45 2009
@@ -0,0 +1,52 @@
+#! /usr/bin/python
+# MiniUPnP project
+# Author : Thomas Bernard
+# This Sample code is public domain.
+# website : http://miniupnp.tuxfamily.org/
+
+# import the python miniupnpc module
+import miniupnpc
+import sys
+
+# create the object
+u = miniupnpc.UPnP()
+print 'inital(default) values :'
+print ' discoverdelay', u.discoverdelay
+print ' lanaddr', u.lanaddr
+print ' multicastif', u.multicastif
+print ' minissdpdsocket', u.minissdpdsocket
+u.discoverdelay = 200;
+#u.minissdpdsocket = '../minissdpd/minissdpd.sock'
+# discovery process, it usualy takes several seconds (2 seconds or more)
+print 'Discovering... delay=%ums' % u.discoverdelay
+print u.discover(), 'device(s) detected'
+# select an igd
+try:
+  u.selectigd()
+except Exception, e:
+  print 'Exception :', e
+  sys.exit(1)
+# display information about the IGD and the internet connection
+print 'local ip address :', u.lanaddr
+print 'external ip address :', u.externalipaddress()
+print u.statusinfo(), u.connectiontype()
+
+#print u.addportmapping(64000, 'TCP',
+#                       '192.168.1.166', 63000, 'port mapping test', '')
+#print u.deleteportmapping(64000, 'TCP')
+
+port = 0
+proto = 'UDP'
+# list the redirections :
+i = 0
+while True:
+	p = u.getgenericportmapping(i)
+	if p==None:
+		break
+	print i, p
+	(port, proto, (ihost,iport), desc, c, d, e) = p
+	#print port, desc
+	i = i + 1
+
+print u.getspecificportmapping(port, proto)
+

Added: freeswitch/trunk/libs/miniupnpc/setup.py
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/setup.py	Fri May 29 15:14:45 2009
@@ -0,0 +1,15 @@
+#! /usr/bin/python
+# $Id: setup.py,v 1.3 2009/04/17 20:59:42 nanard Exp $
+# the MiniUPnP Project (c) 2007 Thomas Bernard
+# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
+#
+# python script to build the miniupnpc module under unix
+#
+# replace libminiupnpc.a by libminiupnpc.so for shared library usage
+from distutils.core import setup, Extension
+setup(name="miniupnpc", version="1.3",
+      ext_modules=[
+	         Extension(name="miniupnpc", sources=["miniupnpcmodule.c"],
+			           extra_objects=["libminiupnpc.a"])
+			 ])
+

Added: freeswitch/trunk/libs/miniupnpc/setupmingw32.py
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/setupmingw32.py	Fri May 29 15:14:45 2009
@@ -0,0 +1,15 @@
+#! /usr/bin/python
+# $Id: setupmingw32.py,v 1.1 2007/06/12 23:04:13 nanard Exp $
+# the MiniUPnP Project (c) 2007 Thomas Bernard
+# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
+#
+# python script to build the miniupnpc module under unix
+#
+from distutils.core import setup, Extension
+setup(name="miniupnpc", version="1.0-RC6",
+      ext_modules=[
+	         Extension(name="miniupnpc", sources=["miniupnpcmodule.c"],
+	                   libraries=["ws2_32"],
+			           extra_objects=["libminiupnpc.a"])
+			 ])
+

Added: freeswitch/trunk/libs/miniupnpc/testigddescparse.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/testigddescparse.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,57 @@
+/* $Id: testigddescparse.c,v 1.1 2008/04/23 11:53:45 nanard Exp $ */
+/* Project : miniupnp
+ * http://miniupnp.free.fr/
+ * Author : Thomas Bernard
+ * Copyright (c) 2008 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 "igd_desc_parse.h"
+#include "minixml.h"
+
+int test_igd_desc_parse(char * buffer, int len)
+{
+	struct IGDdatas igd;
+	struct xmlparser parser;
+	memset(&igd, 0, sizeof(struct IGDdatas));
+	memset(&parser, 0, sizeof(struct xmlparser));
+	parser.xmlstart = buffer;
+	parser.xmlsize = len;
+	parser.data = &igd;
+	parser.starteltfunc = IGDstartelt;
+	parser.endeltfunc = IGDendelt;
+	parser.datafunc = IGDdata; 
+	parsexml(&parser);
+	printIGD(&igd);
+	return 0;
+}
+
+int main(int argc, char * * argv)
+{
+	FILE * f;
+	char * buffer;
+	int len;
+	int r = 0;
+	if(argc<2) {
+		fprintf(stderr, "Usage: %s file.xml\n", argv[0]);
+		return 1;
+	}
+	f = fopen(argv[1], "r");
+	if(!f) {
+		fprintf(stderr, "Cannot open %s for reading.\n", argv[1]);
+		return 1;
+	}
+	fseek(f, 0, SEEK_END);
+	len = ftell(f);
+	fseek(f, 0, SEEK_SET);
+	buffer = malloc(len);
+	fread(buffer, 1, len, f);
+	fclose(f);
+	r = test_igd_desc_parse(buffer, len);
+	free(buffer);
+	return r;
+}
+

Added: freeswitch/trunk/libs/miniupnpc/testminixml.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/testminixml.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,88 @@
+/* $Id: testminixml.c,v 1.6 2006/11/19 22:32:35 nanard Exp $
+ * testminixml.c
+ * test program for the "minixml" functions.
+ * Author : Thomas Bernard.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "minixml.h"
+#include "igd_desc_parse.h"
+
+#ifdef WIN32
+#define NO_BZERO
+#endif
+
+#ifdef NO_BZERO
+#define bzero(p, n) memset(p, 0, n)
+#endif
+
+/* ---------------------------------------------------------------------- */
+void printeltname1(void * d, const char * name, int l)
+{
+	int i;
+	printf("element ");
+	for(i=0;i<l;i++)
+		putchar(name[i]);
+}
+void printeltname2(void * d, const char * name, int l)
+{
+	int i;
+	putchar('/');
+	for(i=0;i<l;i++)
+		putchar(name[i]);
+	putchar('\n');
+}
+void printdata(void *d, const char * data, int l)
+{
+	int i;
+	printf("data : ");
+	for(i=0;i<l;i++)
+		putchar(data[i]);
+	putchar('\n');
+}
+
+void burptest(const char * buffer, int bufsize)
+{
+	struct IGDdatas data;
+	struct xmlparser parser;
+	/*objet IGDdatas */
+	bzero(&data, sizeof(struct IGDdatas));
+	/* objet xmlparser */
+	parser.xmlstart = buffer;
+	parser.xmlsize = bufsize;
+	parser.data = &data;
+	/*parser.starteltfunc = printeltname1;
+	parser.endeltfunc = printeltname2;
+	parser.datafunc = printdata; */
+	parser.starteltfunc = IGDstartelt;
+	parser.endeltfunc = IGDendelt;
+	parser.datafunc = IGDdata; 
+	parsexml(&parser);
+	printIGD(&data);
+}
+
+/* ----- main ---- */
+#define XML_MAX_SIZE (8192)
+int main(int argc, char * * argv)
+{
+	FILE * f;
+	char buffer[XML_MAX_SIZE];
+	int bufsize;
+	if(argc<2)
+	{
+		printf("usage:\t%s file.xml\n", argv[0]);
+		return 1;
+	}
+	f = fopen(argv[1], "r");
+	if(!f)
+	{
+		printf("cannot open file %s\n", argv[1]);
+		return 1;
+	}
+	bufsize = (int)fread(buffer, 1, XML_MAX_SIZE, f);
+	fclose(f);
+	burptest(buffer, bufsize);
+	return 0;
+}
+

Added: freeswitch/trunk/libs/miniupnpc/testupnpigd.py
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/testupnpigd.py	Fri May 29 15:14:45 2009
@@ -0,0 +1,84 @@
+#! /usr/bin/python
+# $Id: testupnpigd.py,v 1.4 2008/10/11 10:27:20 nanard Exp $
+# MiniUPnP project
+# Author : Thomas Bernard
+# This Sample code is public domain.
+# website : http://miniupnp.tuxfamily.org/
+
+# import the python miniupnpc module
+import miniupnpc
+import socket
+import BaseHTTPServer
+
+# function definition
+def list_redirections():
+	i = 0
+	while True:
+		p = u.getgenericportmapping(i)
+		if p==None:
+			break
+		print i, p
+		i = i + 1
+
+#define the handler class for HTTP connections
+class handler_class(BaseHTTPServer.BaseHTTPRequestHandler):
+	def do_GET(self):
+		self.send_response(200)
+		self.end_headers()
+		self.wfile.write("OK MON GARS")
+
+# create the object
+u = miniupnpc.UPnP()
+#print 'inital(default) values :'
+#print ' discoverdelay', u.discoverdelay
+#print ' lanaddr', u.lanaddr
+#print ' multicastif', u.multicastif
+#print ' minissdpdsocket', u.minissdpdsocket
+u.discoverdelay = 200;
+
+try:
+	print 'Discovering... delay=%ums' % u.discoverdelay
+	ndevices = u.discover()
+	print ndevices, 'device(s) detected'
+
+	# select an igd
+	u.selectigd()
+	# display information about the IGD and the internet connection
+	print 'local ip address :', u.lanaddr
+	externalipaddress = u.externalipaddress()
+	print 'external ip address :', externalipaddress
+	print u.statusinfo(), u.connectiontype()
+
+	#instanciate a HTTPd object. The port is assigned by the system.
+	httpd = BaseHTTPServer.HTTPServer((u.lanaddr, 0), handler_class)
+	eport = httpd.server_port
+
+	# find a free port for the redirection
+	r = u.getspecificportmapping(eport, 'TCP')
+	while r != None and eport < 65536:
+		eport = eport + 1
+		r = u.getspecificportmapping(eport, 'TCP')
+
+	print 'trying to redirect %s port %u TCP => %s port %u TCP' % (externalipaddress, eport, u.lanaddr, httpd.server_port)
+
+	b = u.addportmapping(eport, 'TCP', u.lanaddr, httpd.server_port,
+	                    'UPnP IGD Tester port %u' % eport, '')
+	if b:
+		print 'Success. Now waiting for some HTTP request on http://%s:%u' % (externalipaddress ,eport)
+		try:
+			httpd.handle_request()
+			httpd.server_close()
+		except KeyboardInterrupt, details:
+			print "CTRL-C exception!", details
+		b = u.deleteportmapping(eport, 'TCP')
+		if b:
+			print 'Successfully deleted port mapping'
+		else:
+			print 'Failed to remove port mapping'
+	else:
+		print 'Failed'
+
+	httpd.server_close()
+
+except Exception, e:
+	print 'Exception :', e

Added: freeswitch/trunk/libs/miniupnpc/testupnpreplyparse.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/testupnpreplyparse.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,44 @@
+/* $Id: testupnpreplyparse.c,v 1.2 2008/02/21 13:05:27 nanard Exp $ */
+/* MiniUPnP project
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * (c) 2006-2007 Thomas Bernard
+ * This software is subject to the conditions detailed
+ * in the LICENCE file provided within the distribution */
+#include <stdio.h>
+#include <stdlib.h>
+#include "upnpreplyparse.h"
+
+void
+test_parsing(const char * buf, int len)
+{
+	struct NameValueParserData pdata;
+	ParseNameValue(buf, len, &pdata);
+	ClearNameValueList(&pdata);
+}
+
+int main(int argc, char * * argv)
+{
+	FILE * f;
+	char buffer[4096];
+	int l;
+	if(argc<2)
+	{
+		fprintf(stderr, "Usage: %s file.xml\n", argv[0]);
+		return 1;
+	}
+	f = fopen(argv[1], "r");
+	if(!f)
+	{
+		fprintf(stderr, "Error : can not open file %s\n", argv[1]);
+		return 2;
+	}
+	l = fread(buffer, 1, sizeof(buffer)-1, f);
+	fclose(f);
+	buffer[l] = '\0';
+#ifdef DEBUG
+	DisplayNameValueList(buffer, l);
+#endif
+	test_parsing(buffer, l);
+	return 0;
+}
+

Added: freeswitch/trunk/libs/miniupnpc/updateminiupnpcstrings.sh
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/updateminiupnpcstrings.sh	Fri May 29 15:14:45 2009
@@ -0,0 +1,36 @@
+#! /bin/sh
+# $Id: updateminiupnpcstrings.sh,v 1.1 2008/10/11 16:39:29 nanard Exp $
+
+FILE=miniupnpcstrings.h
+
+# detecting the OS name and version
+OS_NAME=`uname -s`
+OS_VERSION=`uname -r`
+if [ -f /etc/debian_version ]; then
+	OS_NAME=Debian
+	OS_VERSION=`cat /etc/debian_version`
+fi
+# use lsb_release (Linux Standard Base) when available
+LSB_RELEASE=`which lsb_release`
+if [ 0 -eq $? ]; then
+	OS_NAME=`${LSB_RELEASE} -i -s`
+	OS_VERSION=`${LSB_RELEASE} -r -s`
+	case $OS_NAME in
+		Debian)
+			#OS_VERSION=`${LSB_RELEASE} -c -s`
+			;;
+		Ubuntu)
+			#OS_VERSION=`${LSB_RELEASE} -c -s`
+			;;
+	esac
+fi
+
+echo "Detected OS [$OS_NAME] version [$OS_VERSION]"
+
+EXPR="s/OS_STRING\s\".*\"/OS_STRING \"${OS_NAME}\/${OS_VERSION}\"/"
+#echo $EXPR
+echo "Backuping $FILE to $FILE.bak."
+cp $FILE $FILE.bak
+echo "setting OS_STRING macro value to ${OS_NAME}/${OS_VERSION} in $FILE."
+cat $FILE.bak | sed -e "$EXPR" > $FILE
+

Added: freeswitch/trunk/libs/miniupnpc/upnpc.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/upnpc.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,374 @@
+/* $Id: upnpc.c,v 1.65 2008/10/14 18:05:27 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas Bernard
+ * Copyright (c) 2005-2008 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>
+#ifdef WIN32
+#include <winsock2.h>
+#define snprintf _snprintf
+#endif
+#include "miniwget.h"
+#include "miniupnpc.h"
+#include "upnpcommands.h"
+#include "upnperrors.h"
+
+/* protofix() checks if protocol is "UDP" or "TCP" 
+ * returns NULL if not */
+const char * protofix(const char * proto)
+{
+	static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
+	static const char proto_udp[4] = { 'U', 'D', 'P', 0};
+	int i, b;
+	for(i=0, b=1; i<4; i++)
+		b = b && (   (proto[i] == proto_tcp[i]) 
+		          || (proto[i] == (proto_tcp[i] | 32)) );
+	if(b)
+		return proto_tcp;
+	for(i=0, b=1; i<4; i++)
+		b = b && (   (proto[i] == proto_udp[i])
+		          || (proto[i] == (proto_udp[i] | 32)) );
+	if(b)
+		return proto_udp;
+	return 0;
+}
+
+static void DisplayInfos(struct UPNPUrls * urls,
+                         struct IGDdatas * data)
+{
+	char externalIPAddress[16];
+	char connectionType[64];
+	char status[64];
+	char lastconnerr[64];
+	unsigned int uptime;
+	unsigned int brUp, brDown;
+	int r;
+	UPNP_GetConnectionTypeInfo(urls->controlURL,
+	                           data->servicetype,
+							   connectionType);
+	if(connectionType[0])
+		printf("Connection Type : %s\n", connectionType);
+	else
+		printf("GetConnectionTypeInfo failed.\n");
+	UPNP_GetStatusInfo(urls->controlURL, data->servicetype,
+	                   status, &uptime, lastconnerr);
+	printf("Status : %s, uptime=%u, LastConnectionError : %s\n",
+	       status, uptime, lastconnerr);
+	UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->servicetype_CIF,
+			&brDown, &brUp);
+	printf("MaxBitRateDown : %u bps   MaxBitRateUp %u bps\n", brDown, brUp);
+	r = UPNP_GetExternalIPAddress(urls->controlURL,
+	                          data->servicetype,
+							  externalIPAddress);
+	if(r != UPNPCOMMAND_SUCCESS)
+		printf("GetExternalIPAddress() returned %d\n", r);
+	if(externalIPAddress[0])
+		printf("ExternalIPAddress = %s\n", externalIPAddress);
+	else
+		printf("GetExternalIPAddress failed.\n");
+}
+
+static void GetConnectionStatus(struct UPNPUrls * urls,
+                               struct IGDdatas * data)
+{
+	unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
+	DisplayInfos(urls, data);
+	bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->servicetype_CIF);
+	bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->servicetype_CIF);
+	packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->servicetype_CIF);
+	packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->servicetype_CIF);
+	printf("Bytes:   Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
+	printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
+}
+
+static void ListRedirections(struct UPNPUrls * urls,
+                             struct IGDdatas * data)
+{
+	int r;
+	int i = 0;
+	char index[6];
+	char intClient[16];
+	char intPort[6];
+	char extPort[6];
+	char protocol[4];
+	char desc[80];
+	char enabled[6];
+	char rHost[64];
+	char duration[16];
+	/*unsigned int num=0;
+	UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
+	printf("PortMappingNumberOfEntries : %u\n", num);*/
+	do {
+		snprintf(index, 6, "%d", i);
+		rHost[0] = '\0'; enabled[0] = '\0';
+		duration[0] = '\0'; desc[0] = '\0';
+		extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
+		r = UPNP_GetGenericPortMappingEntry(urls->controlURL, data->servicetype,
+		                               index,
+		                               extPort, intClient, intPort,
+									   protocol, desc, enabled,
+									   rHost, duration);
+		if(r==0)
+		/*
+			printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
+			       "     desc='%s' rHost='%s'\n",
+			       i, protocol, extPort, intClient, intPort,
+				   enabled, duration,
+				   desc, rHost);
+				   */
+			printf("%2d %s %5s->%s:%-5s '%s' '%s'\n",
+			       i, protocol, extPort, intClient, intPort,
+			       desc, rHost);
+		else
+			printf("GetGenericPortMappingEntry() returned %d (%s)\n",
+			       r, strupnperror(r));
+		i++;
+	} while(r==0);
+}
+
+/* Test function 
+ * 1 - get connection type
+ * 2 - get extenal ip address
+ * 3 - Add port mapping
+ * 4 - get this port mapping from the IGD */
+static void SetRedirectAndTest(struct UPNPUrls * urls,
+                               struct IGDdatas * data,
+							   const char * iaddr,
+							   const char * iport,
+							   const char * eport,
+                               const char * proto)
+{
+	char externalIPAddress[16];
+	char intClient[16];
+	char intPort[6];
+	int r;
+
+	if(!iaddr || !iport || !eport || !proto)
+	{
+		fprintf(stderr, "Wrong arguments\n");
+		return;
+	}
+	proto = protofix(proto);
+	if(!proto)
+	{
+		fprintf(stderr, "invalid protocol\n");
+		return;
+	}
+	
+	UPNP_GetExternalIPAddress(urls->controlURL,
+	                          data->servicetype,
+							  externalIPAddress);
+	if(externalIPAddress[0])
+		printf("ExternalIPAddress = %s\n", externalIPAddress);
+	else
+		printf("GetExternalIPAddress failed.\n");
+	
+	r = UPNP_AddPortMapping(urls->controlURL, data->servicetype,
+	                        eport, iport, iaddr, 0, proto, 0);
+	if(r!=UPNPCOMMAND_SUCCESS)
+		printf("AddPortMapping(%s, %s, %s) failed with code %d\n",
+		       eport, iport, iaddr, r);
+
+	r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
+	                                 data->servicetype,
+    	                             eport, proto,
+									 intClient, intPort);
+	if(r!=UPNPCOMMAND_SUCCESS)
+		printf("GetSpecificPortMappingEntry() failed with code %d\n", r);
+	
+	if(intClient[0]) {
+		printf("InternalIP:Port = %s:%s\n", intClient, intPort);
+		printf("external %s:%s %s is redirected to internal %s:%s\n",
+		       externalIPAddress, eport, proto, intClient, intPort);
+	}
+}
+
+static void
+RemoveRedirect(struct UPNPUrls * urls,
+               struct IGDdatas * data,
+			   const char * eport,
+			   const char * proto)
+{
+	int r;
+	if(!proto || !eport)
+	{
+		fprintf(stderr, "invalid arguments\n");
+		return;
+	}
+	proto = protofix(proto);
+	if(!proto)
+	{
+		fprintf(stderr, "protocol invalid\n");
+		return;
+	}
+	r = UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto, 0);
+	printf("UPNP_DeletePortMapping() returned : %d\n", r);
+}
+
+
+/* sample upnp client program */
+int main(int argc, char ** argv)
+{
+	char command = 0;
+	char ** commandargv = 0;
+	int commandargc = 0;
+	struct UPNPDev * devlist = 0;
+	char lanaddr[16];	/* my ip address on the LAN */
+	int i;
+	const char * rootdescurl = 0;
+	const char * multicastif = 0;
+	const char * minissdpdpath = 0;
+
+#ifdef WIN32
+	WSADATA wsaData;
+	int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+	if(nResult != NO_ERROR)
+	{
+		fprintf(stderr, "WSAStartup() failed.\n");
+		return -1;
+	}
+#endif
+    printf("upnpc : miniupnpc library test client. (c) 2006-2008 Thomas Bernard\n");
+    printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
+	       "for more information.\n");
+	/* command line processing */
+	for(i=1; i<argc; i++)
+	{
+		if(argv[i][0] == '-')
+		{
+			if(argv[i][1] == 'u')
+				rootdescurl = argv[++i];
+			else if(argv[i][1] == 'm')
+				multicastif = argv[++i];
+			else if(argv[i][1] == 'p')
+				minissdpdpath = argv[++i];
+			else
+			{
+				command = argv[i][1];
+				i++;
+				commandargv = argv + i;
+				commandargc = argc - i;
+				break;
+			}
+		}
+		else
+		{
+			fprintf(stderr, "option '%s' invalid\n", argv[i]);
+		}
+	}
+
+	if(!command || (command == 'a' && commandargc<4)
+	   || (command == 'd' && argc<2)
+	   || (command == 'r' && argc<2))
+	{
+		fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol\n\t\tAdd port redirection\n", argv[0]);
+		fprintf(stderr, "       \t%s [options] -d external_port protocol\n\t\tDelete port redirection\n", argv[0]);
+		fprintf(stderr, "       \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
+		fprintf(stderr, "       \t%s [options] -l\n\t\tList redirections\n", argv[0]);
+		fprintf(stderr, "       \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
+		fprintf(stderr, "\nprotocol is UDP or TCP\n");
+		fprintf(stderr, "Options:\n");
+		fprintf(stderr, "  -u url : bypass discovery process by providing the XML root description url.\n");
+		fprintf(stderr, "  -m address : provide ip address of the interface to use for sending SSDP multicast packets.\n");
+		fprintf(stderr, "  -p path : use this path for MiniSSDPd socket.\n");
+		return 1;
+	}
+
+	if( rootdescurl
+	  || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0)))
+	{
+		struct UPNPDev * device;
+		struct UPNPUrls urls;
+		struct IGDdatas data;
+		if(devlist)
+		{
+			printf("List of UPNP devices found on the network :\n");
+			for(device = devlist; device; device = device->pNext)
+			{
+				printf(" desc: %s\n st: %s\n\n",
+					   device->descURL, device->st);
+			}
+		}
+		i = 1;
+		if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
+		  || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
+		{
+			switch(i) {
+			case 1:
+				printf("Found valid IGD : %s\n", urls.controlURL);
+				break;
+			case 2:
+				printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
+				printf("Trying to continue anyway\n");
+				break;
+			case 3:
+				printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
+				printf("Trying to continue anyway\n");
+				break;
+			default:
+				printf("Found device (igd ?) : %s\n", urls.controlURL);
+				printf("Trying to continue anyway\n");
+			}
+			printf("Local LAN ip address : %s\n", lanaddr);
+			#if 0
+			printf("getting \"%s\"\n", urls.ipcondescURL);
+			descXML = miniwget(urls.ipcondescURL, &descXMLsize);
+			if(descXML)
+			{
+				/*fwrite(descXML, 1, descXMLsize, stdout);*/
+				free(descXML); descXML = NULL;
+			}
+			#endif
+
+			switch(command)
+			{
+			case 'l':
+				DisplayInfos(&urls, &data);
+				ListRedirections(&urls, &data);
+				break;
+			case 'a':
+				SetRedirectAndTest(&urls, &data,
+				                   commandargv[0], commandargv[1],
+				                   commandargv[2], commandargv[3]);
+				break;
+			case 'd':
+				RemoveRedirect(&urls, &data, commandargv[0], commandargv[1]);
+				break;
+			case 's':
+				GetConnectionStatus(&urls, &data);
+				break;
+			case 'r':
+				for(i=0; i<commandargc; i+=2)
+				{
+					/*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/
+					SetRedirectAndTest(&urls, &data,
+					                   lanaddr, commandargv[i],
+									   commandargv[i], commandargv[i+1]);
+				}
+				break;
+			default:
+				fprintf(stderr, "Unknown switch -%c\n", command);
+			}
+
+			FreeUPNPUrls(&urls);
+		}
+		else
+		{
+			fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
+		}
+		freeUPNPDevlist(devlist); devlist = 0;
+	}
+	else
+	{
+		fprintf(stderr, "No IGD UPnP Device found on the network !\n");
+	}
+
+	/*puts("************* HOP ***************");*/
+
+	return 0;
+}
+

Added: freeswitch/trunk/libs/miniupnpc/upnpcommands.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/upnpcommands.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,573 @@
+/* $Id: upnpcommands.c,v 1.24 2009/04/17 21:21:19 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas Bernard
+ * Copyright (c) 2005-2009 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided in this distribution.
+ * */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "upnpcommands.h"
+#include "miniupnpc.h"
+
+static UNSIGNED_INTEGER
+my_atoui(const char * s)
+{
+	return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0;
+}
+
+/*
+ * */
+UNSIGNED_INTEGER
+UPNP_GetTotalBytesSent(const char * controlURL,
+					const char * servicetype)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	unsigned int r = 0;
+	char * p;
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");
+	r = my_atoui(p);
+	ClearNameValueList(&pdata);
+	return r;
+}
+
+/*
+ * */
+UNSIGNED_INTEGER
+UPNP_GetTotalBytesReceived(const char * controlURL,
+						const char * servicetype)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	unsigned int r = 0;
+	char * p;
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");
+	r = my_atoui(p);
+	ClearNameValueList(&pdata);
+	return r;
+}
+
+/*
+ * */
+UNSIGNED_INTEGER
+UPNP_GetTotalPacketsSent(const char * controlURL,
+						const char * servicetype)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	unsigned int r = 0;
+	char * p;
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");
+	r = my_atoui(p);
+	ClearNameValueList(&pdata);
+	return r;
+}
+
+/*
+ * */
+UNSIGNED_INTEGER
+UPNP_GetTotalPacketsReceived(const char * controlURL,
+						const char * servicetype)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	unsigned int r = 0;
+	char * p;
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");
+	r = my_atoui(p);
+	ClearNameValueList(&pdata);
+	return r;
+}
+
+/* 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)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	char * up;
+	char * err;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+
+	if(!status && !uptime)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	up = GetValueFromNameValueList(&pdata, "NewUptime");
+	p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");
+	err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");
+	if(p && up)
+	  ret = UPNPCOMMAND_SUCCESS;
+
+	if(status) {
+		if(p){
+			strncpy(status, p, 64 );
+			status[63] = '\0';
+		}else
+			status[0]= '\0';
+	}
+
+	if(uptime) {
+		if(up)
+			sscanf(up,"%u",uptime);
+		else
+			uptime = 0;
+	}
+
+	if(lastconnerror) {
+		if(err) {
+			strncpy(lastconnerror, err, 64 );
+			lastconnerror[63] = '\0';
+		} else
+			lastconnerror[0] = '\0';
+	}
+
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+	ClearNameValueList(&pdata);
+	return ret;
+}
+
+/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
+ * returns the connection type */
+int UPNP_GetConnectionTypeInfo(const char * controlURL,
+                               const char * servicetype,
+                               char * connectionType)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+
+	if(!connectionType)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "GetConnectionTypeInfo", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	p = GetValueFromNameValueList(&pdata, "NewConnectionType");
+	/*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
+	/* PossibleConnectionTypes will have several values.... */
+	if(p) {
+		strncpy(connectionType, p, 64 );
+		connectionType[63] = '\0';
+		ret = UPNPCOMMAND_SUCCESS;
+	} else
+		connectionType[0] = '\0';
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+	ClearNameValueList(&pdata);
+	return ret;
+}
+
+/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
+ * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
+ * 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)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+	char * down;
+	char * up;
+	char * p;
+
+	if(!bitrateDown && !bitrateUp)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	/* shouldn't we use GetCommonLinkProperties ? */
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "GetCommonLinkProperties", 0, buffer, &bufsize);
+	                  /*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize);*/
+	/*DisplayNameValueList(buffer, bufsize);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
+	/*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/
+	down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");
+	up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate");
+	/*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/
+	/*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus");*/
+	if(down && up)
+		ret = UPNPCOMMAND_SUCCESS;
+
+	if(bitrateDown)
+	{
+		if(down)
+			sscanf(down,"%u",bitrateDown);
+		else
+			*bitrateDown = 0;
+	}
+
+	if(bitrateUp)
+	{
+		if(up)
+			sscanf(up,"%u",bitrateUp);
+		else
+			*bitrateUp = 0;
+	}
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+	ClearNameValueList(&pdata);
+	return ret;
+}
+
+
+/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
+ * if the third arg is not null the value is copied to it.
+ * at least 16 bytes must be available
+ * 
+ * Return values :
+ * 0 : SUCCESS
+ * NON ZERO : ERROR Either an UPnP error code or an unknown error.
+ *
+ * 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)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+
+	if(!extIpAdd || !controlURL || !servicetype)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
+	p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");
+	if(p) {
+		strncpy(extIpAdd, p, 16 );
+		extIpAdd[15] = '\0';
+		ret = UPNPCOMMAND_SUCCESS;
+	} else
+		extIpAdd[0] = '\0';
+
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+
+	ClearNameValueList(&pdata);
+	return ret;
+}
+
+int
+UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
+                    const char * extPort,
+					const char * inPort,
+					const char * inClient,
+					const char * desc,
+					const char * proto,
+                    const char * remoteHost)
+{
+	struct UPNParg * AddPortMappingArgs;
+	char buffer[4096];
+	int bufsize = 4096;
+	struct NameValueParserData pdata;
+	const char * resVal;
+	int ret;
+
+	if(!inPort || !inClient || !proto || !extPort)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
+	AddPortMappingArgs[0].elt = "NewRemoteHost";
+	AddPortMappingArgs[0].val = remoteHost;
+	AddPortMappingArgs[1].elt = "NewExternalPort";
+	AddPortMappingArgs[1].val = extPort;
+	AddPortMappingArgs[2].elt = "NewProtocol";
+	AddPortMappingArgs[2].val = proto;
+	AddPortMappingArgs[3].elt = "NewInternalPort";
+	AddPortMappingArgs[3].val = inPort;
+	AddPortMappingArgs[4].elt = "NewInternalClient";
+	AddPortMappingArgs[4].val = inClient;
+	AddPortMappingArgs[5].elt = "NewEnabled";
+	AddPortMappingArgs[5].val = "1";
+	AddPortMappingArgs[6].elt = "NewPortMappingDescription";
+	AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
+	AddPortMappingArgs[7].elt = "NewLeaseDuration";
+	AddPortMappingArgs[7].val = "0";
+	simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	/*buffer[bufsize] = '\0';*/
+	/*puts(buffer);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+	resVal = GetValueFromNameValueList(&pdata, "errorCode");
+	if(resVal) {
+		/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(resVal, "%d", &ret);
+	} else {
+		ret = UPNPCOMMAND_SUCCESS;
+	}
+	ClearNameValueList(&pdata);
+	free(AddPortMappingArgs);
+	return ret;
+}
+
+int
+UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
+                       const char * extPort, const char * proto,
+                       const char * remoteHost)
+{
+	/*struct NameValueParserData pdata;*/
+	struct UPNParg * DeletePortMappingArgs;
+	char buffer[4096];
+	int bufsize = 4096;
+	struct NameValueParserData pdata;
+	const char * resVal;
+	int ret;
+
+	if(!extPort || !proto)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg));
+	DeletePortMappingArgs[0].elt = "NewRemoteHost";
+	DeletePortMappingArgs[0].val = remoteHost;
+	DeletePortMappingArgs[1].elt = "NewExternalPort";
+	DeletePortMappingArgs[1].val = extPort;
+	DeletePortMappingArgs[2].elt = "NewProtocol";
+	DeletePortMappingArgs[2].val = proto;
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "DeletePortMapping",
+					  DeletePortMappingArgs, buffer, &bufsize);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+	resVal = GetValueFromNameValueList(&pdata, "errorCode");
+	if(resVal) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(resVal, "%d", &ret);
+	} else {
+		ret = UPNPCOMMAND_SUCCESS;
+	}
+	ClearNameValueList(&pdata);
+	free(DeletePortMappingArgs);
+	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)
+{
+	struct NameValueParserData pdata;
+	struct UPNParg * GetPortMappingArgs;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	int r = UPNPCOMMAND_UNKNOWN_ERROR;
+	if(!index)
+		return UPNPCOMMAND_INVALID_ARGS;
+	intClient[0] = '\0';
+	intPort[0] = '\0';
+	GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
+	GetPortMappingArgs[0].elt = "NewPortMappingIndex";
+	GetPortMappingArgs[0].val = index;
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "GetGenericPortMappingEntry",
+					  GetPortMappingArgs, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
+	if(p && rHost)
+	{
+		strncpy(rHost, p, 64);
+		rHost[63] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewExternalPort");
+	if(p && extPort)
+	{
+		strncpy(extPort, p, 6);
+		extPort[5] = '\0';
+		r = UPNPCOMMAND_SUCCESS;
+	}
+	p = GetValueFromNameValueList(&pdata, "NewProtocol");
+	if(p && protocol)
+	{
+		strncpy(protocol, p, 4);
+		protocol[3] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewInternalClient");
+	if(p && intClient)
+	{
+		strncpy(intClient, p, 16);
+		intClient[15] = '\0';
+		r = 0;
+	}
+	p = GetValueFromNameValueList(&pdata, "NewInternalPort");
+	if(p && intPort)
+	{
+		strncpy(intPort, p, 6);
+		intPort[5] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewEnabled");
+	if(p && enabled)
+	{
+		strncpy(enabled, p, 4);
+		enabled[3] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
+	if(p && desc)
+	{
+		strncpy(desc, p, 80);
+		desc[79] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
+	if(p && duration)
+	{
+		strncpy(duration, p, 16);
+		duration[15] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		r = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &r);
+	}
+	ClearNameValueList(&pdata);
+	free(GetPortMappingArgs);
+	return r;
+}
+
+int UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries)
+{
+ 	struct NameValueParserData pdata;
+ 	char buffer[4096];
+ 	int bufsize = 4096;
+ 	char* p;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+ 	simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize);
+#ifdef DEBUG
+	DisplayNameValueList(buffer, bufsize);
+#endif
+ 	ParseNameValue(buffer, bufsize, &pdata);
+
+ 	p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");
+ 	if(numEntries && p) {
+		*numEntries = 0;
+ 		sscanf(p, "%u", numEntries);
+		ret = UPNPCOMMAND_SUCCESS;
+ 	}
+
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+
+ 	ClearNameValueList(&pdata);
+	return ret;
+}
+
+/* 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
+UPNP_GetSpecificPortMappingEntry(const char * controlURL,
+                                 const char * servicetype,
+                                 const char * extPort,
+							     const char * proto,
+                                 char * intClient,
+                                 char * intPort)
+{
+	struct NameValueParserData pdata;
+	struct UPNParg * GetPortMappingArgs;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+
+	if(!intPort || !intClient || !extPort || !proto)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
+	GetPortMappingArgs[0].elt = "NewRemoteHost";
+	GetPortMappingArgs[1].elt = "NewExternalPort";
+	GetPortMappingArgs[1].val = extPort;
+	GetPortMappingArgs[2].elt = "NewProtocol";
+	GetPortMappingArgs[2].val = proto;
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "GetSpecificPortMappingEntry",
+					  GetPortMappingArgs, buffer, &bufsize);
+	/*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */
+	/*DisplayNameValueList(buffer, bufsize);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+
+	p = GetValueFromNameValueList(&pdata, "NewInternalClient");
+	if(p) {
+		strncpy(intClient, p, 16);
+		intClient[15] = '\0';
+		ret = UPNPCOMMAND_SUCCESS;
+	} else
+		intClient[0] = '\0';
+
+	p = GetValueFromNameValueList(&pdata, "NewInternalPort");
+	if(p) {
+		strncpy(intPort, p, 6);
+		intPort[5] = '\0';
+	} else
+		intPort[0] = '\0';
+
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+
+	ClearNameValueList(&pdata);
+	free(GetPortMappingArgs);
+	return ret;
+}
+
+

Added: freeswitch/trunk/libs/miniupnpc/upnpcommands.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/upnpcommands.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,193 @@
+/* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */
+/* Miniupnp project : http://miniupnp.free.fr/
+ * Author : Thomas Bernard
+ * Copyright (c) 2005-2008 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided within this distribution */
+#ifndef __UPNPCOMMANDS_H__
+#define __UPNPCOMMANDS_H__
+
+#include "upnpreplyparse.h"
+#include "declspec.h"
+
+/* MiniUPnPc return codes : */
+#define UPNPCOMMAND_SUCCESS (0)
+#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
+#define UPNPCOMMAND_INVALID_ARGS (-2)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+#define UNSIGNED_INTEGER unsigned long long
+#define STRTOUI	strtoull
+#else
+#define UNSIGNED_INTEGER unsigned int
+#define STRTOUI	strtoul
+#endif
+
+LIBSPEC UNSIGNED_INTEGER
+UPNP_GetTotalBytesSent(const char * controlURL,
+					const char * servicetype);
+
+LIBSPEC UNSIGNED_INTEGER
+UPNP_GetTotalBytesReceived(const char * controlURL,
+						const char * servicetype);
+
+LIBSPEC UNSIGNED_INTEGER
+UPNP_GetTotalPacketsSent(const char * controlURL,
+					const char * servicetype);
+
+LIBSPEC UNSIGNED_INTEGER
+UPNP_GetTotalPacketsReceived(const char * controlURL,
+					const char * servicetype);
+
+/* UPNP_GetStatusInfo()
+ * status and lastconnerror are 64 byte buffers
+ * Return values :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error code */
+LIBSPEC int
+UPNP_GetStatusInfo(const char * controlURL,
+			       const char * servicetype,
+				   char * status,
+				   unsigned int * uptime,
+                   char * lastconnerror);
+
+/* UPNP_GetConnectionTypeInfo()
+ * argument connectionType is a 64 character buffer
+ * Return Values :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error code */
+LIBSPEC int
+UPNP_GetConnectionTypeInfo(const char * controlURL,
+                           const char * servicetype,
+						   char * connectionType);
+
+/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
+ * if the third arg is not null the value is copied to it.
+ * at least 16 bytes must be available 
+ *
+ * Return values :
+ * 0 : SUCCESS
+ * NON ZERO : ERROR Either an UPnP error code or an unknown error.
+ * 
+ * possible UPnP Errors :
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 501 Action Failed - See UPnP Device Architecture section on Control. */
+LIBSPEC int
+UPNP_GetExternalIPAddress(const char * controlURL,
+                          const char * servicetype,
+                          char * extIpAdd);
+
+/* UPNP_GetLinkLayerMaxBitRates()
+ * call WANCommonInterfaceConfig:1#GetCommonLinkProperties
+ *
+ * return values :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error Code. */
+LIBSPEC int
+UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
+							const char* servicetype,
+							unsigned int * bitrateDown,
+							unsigned int * bitrateUp);
+
+/* UPNP_AddPortMapping()
+ * if desc is NULL, it will be defaulted to "libminiupnpc"
+ * remoteHost is usually NULL because IGD don't support it.
+ *
+ * Return values :
+ * 0 : SUCCESS
+ * NON ZERO : ERROR. Either an UPnP error code or an unknown error.
+ * 
+ * List of possible UPnP errors for AddPortMapping :
+ * errorCode errorDescription (short) - Description (long)
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 501 Action Failed - See UPnP Device Architecture section on Control.
+ * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
+ *                                   wild-carded
+ * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
+ * 718 ConflictInMappingEntry - The port mapping entry specified conflicts
+ *                     with a mapping assigned previously to another client
+ * 724 SamePortValuesRequired - Internal and External port values
+ *                              must be the same 
+ * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
+ *                  permanent lease times on port mappings
+ * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
+ *                             and cannot be a specific IP address or DNS name
+ * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
+ *                                        cannot be a specific port value */
+LIBSPEC int
+UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
+                    const char * extPort,
+				    const char * inPort,
+					const char * inClient,
+					const char * desc,
+                    const char * proto,
+                    const char * remoteHost);
+
+/* UPNP_DeletePortMapping()
+ * Use same argument values as what was used for AddPortMapping().
+ * remoteHost is usually NULL because IGD don't support it.
+ * Return Values :
+ * 0 : SUCCESS
+ * NON ZERO : error. Either an UPnP error code or an undefined error.
+ *
+ * List of possible UPnP errors for DeletePortMapping :
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 714 NoSuchEntryInArray - The specified value does not exist in the array */
+LIBSPEC int
+UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
+                       const char * extPort, const char * proto,
+                       const char * remoteHost);
+
+/* UPNP_GetPortMappingNumberOfEntries()
+ * not supported by all routers */
+LIBSPEC int
+UPNP_GetPortMappingNumberOfEntries(const char* controlURL, const char* servicetype, unsigned int * num);
+
+/* 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
+ *
+ * return value :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error Code. */
+LIBSPEC int
+UPNP_GetSpecificPortMappingEntry(const char * controlURL,
+                                 const char * servicetype,
+                                 const char * extPort,
+                                 const char * proto,
+                                 char * intClient,
+                                 char * intPort);
+
+/* UPNP_GetGenericPortMappingEntry()
+ *
+ * return value :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error Code.
+ *
+ * Possible UPNP Error codes :
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
+ */
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/upnperrors.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/upnperrors.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,66 @@
+/* $Id: upnperrors.c,v 1.3 2008/04/27 17:21:51 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * copyright (c) 2007 Thomas Bernard
+ * All Right reserved.
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#include <string.h>
+#include "upnperrors.h"
+#include "upnpcommands.h"
+
+const char * strupnperror(int err)
+{
+	const char * s = NULL;
+	switch(err) {
+	case UPNPCOMMAND_SUCCESS:
+		s = "Success";
+		break;
+	case UPNPCOMMAND_UNKNOWN_ERROR:
+		s = "Miniupnpc Unknown Error";
+		break;
+	case UPNPCOMMAND_INVALID_ARGS:
+		s = "Miniupnpc Invalid Arguments";
+		break;
+	case 401:
+		s = "Invalid Action";
+		break;
+	case 402:
+		s = "Invalid Args";
+		break;
+	case 501:
+		s = "Action Failed";
+		break;
+	case 713:
+		s = "SpecifiedArrayIndexInvalid";
+		break;
+	case 714:
+		s = "NoSuchEntryInArray";
+		break;
+	case 715:
+		s = "WildCardNotPermittedInSrcIP";
+		break;
+	case 716:
+		s = "WildCardNotPermittedInExtPort";
+		break;
+	case 718:
+		s = "ConflictInMappingEntry";
+		break;
+	case 724:
+		s = "SamePortValuesRequired";
+		break;
+	case 725:
+		s = "OnlyPermanentLeasesSupported";
+		break;
+	case 726:
+		s = "RemoteHostOnlySupportsWildcard";
+		break;
+	case 727:
+		s = "ExternalPortOnlySupportsWildcard";
+		break;
+	default:
+		s = NULL;
+	}
+	return s;
+}

Added: freeswitch/trunk/libs/miniupnpc/upnperrors.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/upnperrors.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,26 @@
+/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */
+/* (c) 2007 Thomas Bernard
+ * All rights reserved.
+ * MiniUPnP Project.
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#ifndef __UPNPERRORS_H__
+#define __UPNPERRORS_H__
+
+#include "declspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* strupnperror()
+ * Return a string description of the UPnP error code 
+ * or NULL for undefinded errors */
+LIBSPEC const char * strupnperror(int err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Added: freeswitch/trunk/libs/miniupnpc/upnpreplyparse.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/upnpreplyparse.c	Fri May 29 15:14:45 2009
@@ -0,0 +1,127 @@
+/* $Id: upnpreplyparse.c,v 1.10 2008/02/21 13:05:27 nanard Exp $ */
+/* MiniUPnP project
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * (c) 2006 Thomas Bernard 
+ * This software is subject to the conditions detailed
+ * in the LICENCE file provided within the distribution */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "upnpreplyparse.h"
+#include "minixml.h"
+
+static void
+NameValueParserStartElt(void * d, const char * name, int l)
+{
+    struct NameValueParserData * data = (struct NameValueParserData *)d;
+    if(l>63)
+        l = 63;
+    memcpy(data->curelt, name, l);
+    data->curelt[l] = '\0';
+}
+
+static void
+NameValueParserGetData(void * d, const char * datas, int l)
+{
+    struct NameValueParserData * data = (struct NameValueParserData *)d;
+    struct NameValue * nv;
+    nv = malloc(sizeof(struct NameValue));
+    if(l>63)
+        l = 63;
+    strncpy(nv->name, data->curelt, 64);
+	nv->name[63] = '\0';
+    memcpy(nv->value, datas, l);
+    nv->value[l] = '\0';
+    LIST_INSERT_HEAD( &(data->head), nv, entries);
+}
+
+void
+ParseNameValue(const char * buffer, int bufsize,
+                    struct NameValueParserData * data)
+{
+    struct xmlparser parser;
+    LIST_INIT(&(data->head));
+    /* init xmlparser object */
+    parser.xmlstart = buffer;
+    parser.xmlsize = bufsize;
+    parser.data = data;
+    parser.starteltfunc = NameValueParserStartElt;
+    parser.endeltfunc = 0;
+    parser.datafunc = NameValueParserGetData;
+	parser.attfunc = 0;
+    parsexml(&parser);
+}
+
+void
+ClearNameValueList(struct NameValueParserData * pdata)
+{
+    struct NameValue * nv;
+    while((nv = pdata->head.lh_first) != NULL)
+    {
+        LIST_REMOVE(nv, entries);
+        free(nv);
+    }
+}
+
+char * 
+GetValueFromNameValueList(struct NameValueParserData * pdata,
+                          const char * Name)
+{
+    struct NameValue * nv;
+    char * p = NULL;
+    for(nv = pdata->head.lh_first;
+        (nv != NULL) && (p == NULL);
+        nv = nv->entries.le_next)
+    {
+        if(strcmp(nv->name, Name) == 0)
+            p = nv->value;
+    }
+    return p;
+}
+
+#if 0
+/* useless now that minixml ignores namespaces by itself */
+char *
+GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
+                                  const char * Name)
+{
+	struct NameValue * nv;
+	char * p = NULL;
+	char * pname;
+	for(nv = pdata->head.lh_first;
+	    (nv != NULL) && (p == NULL);
+		nv = nv->entries.le_next)
+	{
+		pname = strrchr(nv->name, ':');
+		if(pname)
+			pname++;
+		else
+			pname = nv->name;
+		if(strcmp(pname, Name)==0)
+			p = nv->value;
+	}
+	return p;
+}
+#endif
+
+/* debug all-in-one function 
+ * do parsing then display to stdout */
+#ifdef DEBUG
+void
+DisplayNameValueList(char * buffer, int bufsize)
+{
+    struct NameValueParserData pdata;
+    struct NameValue * nv;
+    ParseNameValue(buffer, bufsize, &pdata);
+    for(nv = pdata.head.lh_first;
+        nv != NULL;
+        nv = nv->entries.le_next)
+    {
+        printf("%s = %s\n", nv->name, nv->value);
+    }
+    ClearNameValueList(&pdata);
+}
+#endif
+

Added: freeswitch/trunk/libs/miniupnpc/upnpreplyparse.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/miniupnpc/upnpreplyparse.h	Fri May 29 15:14:45 2009
@@ -0,0 +1,62 @@
+/* $Id: upnpreplyparse.h,v 1.8 2008/02/21 13:05:27 nanard Exp $ */
+/* MiniUPnP project
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * (c) 2006 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)
+#include "bsdqueue.h"
+#else
+#include <sys/queue.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct NameValue {
+    LIST_ENTRY(NameValue) entries;
+    char name[64];
+    char value[64];
+};
+
+struct NameValueParserData {
+    LIST_HEAD(listhead, NameValue) head;
+    char curelt[64];
+};
+
+/* ParseNameValue() */
+void
+ParseNameValue(const char * buffer, int bufsize,
+               struct NameValueParserData * data);
+
+/* ClearNameValueList() */
+void
+ClearNameValueList(struct NameValueParserData * pdata);
+
+/* GetValueFromNameValueList() */
+char *
+GetValueFromNameValueList(struct NameValueParserData * pdata,
+                          const char * Name);
+
+/* GetValueFromNameValueListIgnoreNS() */
+char *
+GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
+                                  const char * Name);
+
+/* DisplayNameValueList() */
+#ifdef DEBUG
+void
+DisplayNameValueList(char * buffer, int bufsize);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+



More information about the Freeswitch-svn mailing list