[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