[asterisk-commits] [svn-commits] branch mogorman/asterisk-xmpp r17737 - in /team/mogorman/asterisk-xmpp: confi...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Apr 5 19:44:19 MST 2006


Author: mogorman
Date: Wed Apr  5 21:44:17 2006
New Revision: 17737

URL: http://svn.digium.com/view/asterisk?rev=17737&view=rev
Log:
adding stun client support for asterisk.

Added:
    team/mogorman/asterisk-xmpp/configs/stun.conf.sample   (with props)
    team/mogorman/asterisk-xmpp/res/res_stun.c   (with props)
    team/mogorman/asterisk-xmpp/res/stun/
    team/mogorman/asterisk-xmpp/res/stun/Makefile   (with props)
    team/mogorman/asterisk-xmpp/res/stun/client.cpp   (with props)
    team/mogorman/asterisk-xmpp/res/stun/main.c   (with props)
    team/mogorman/asterisk-xmpp/res/stun/stun.cpp   (with props)
    team/mogorman/asterisk-xmpp/res/stun/stun.h   (with props)
    team/mogorman/asterisk-xmpp/res/stun/stunwrapper.cpp   (with props)
    team/mogorman/asterisk-xmpp/res/stun/udp.cpp   (with props)
    team/mogorman/asterisk-xmpp/res/stun/udp.h   (with props)
Modified:
    team/mogorman/asterisk-xmpp/res/res_xmpp.c

Added: team/mogorman/asterisk-xmpp/configs/stun.conf.sample
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/configs/stun.conf.sample?rev=17737&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/configs/stun.conf.sample (added)
+++ team/mogorman/asterisk-xmpp/configs/stun.conf.sample Wed Apr  5 21:44:17 2006
@@ -1,0 +1,6 @@
+
+[general]
+
+;server = googletalk ;; stun server to connect to.
+;port = 1234 ;; Specific port
+;interfaces = all ;;all interfaces

Propchange: team/mogorman/asterisk-xmpp/configs/stun.conf.sample
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mogorman/asterisk-xmpp/configs/stun.conf.sample
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mogorman/asterisk-xmpp/configs/stun.conf.sample
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/mogorman/asterisk-xmpp/res/res_stun.c
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/res_stun.c?rev=17737&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/res/res_stun.c (added)
+++ team/mogorman/asterisk-xmpp/res/res_stun.c Wed Apr  5 21:44:17 2006
@@ -1,0 +1,113 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Copyright (C) 2005-2006, Digium, Inc.
+ *
+ * Matthew O'Gorman <mogorman at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief STUN client support for Asterisk.
+ * \author Matthew O'Gorman <mogorman at digium.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/time.h>
+#include <time.h>
+#include <ctype.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/channel.h"
+#include "asterisk/file.h"
+#include "asterisk/config.h"
+#include "asterisk/callerid.h"
+#include "asterisk/lock.h"
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+#include "asterisk/cli.h"
+#include "asterisk/app.h"
+#include "asterisk/pbx.h"
+#include "asterisk/md5.h"
+#include "asterisk/acl.h"
+#include "asterisk/utils.h"
+#include "asterisk/module.h"
+#include "asterisk/astobj.h"
+
+#define STUN_CONFIG "stun.conf"
+
+AST_MUTEX_DEFINE_STATIC(actionlock);
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+static char *tdesc = "STUN - Asterisk STUN Client Interface";
+
+static int open_port( unsigned int port, unsigned int srcip, int verbose)
+{
+	return 1;
+}
+
+static int close_socket(int fd)
+{
+	return close(fd);
+}
+
+static int send_message(int fd, char *message, int len, unsigned int dstip, unsigned int dstport, int verbose)
+{
+	return 1;
+}
+
+static int get_message(int fd, char *buffer, int* len, unsigned int srcip, unsigned int srcport, int verbose)
+{
+	return 1;
+}
+
+int unload_module(void)
+{
+	return 0;
+}
+
+int load_module(void)
+{
+	return 0;
+}
+
+int reload_module(void)
+{
+	return 0;
+}
+
+char *description(void)
+{
+	return tdesc;
+}
+
+int usecount(void)
+{
+	int res;
+	STANDARD_USECOUNT(res);
+	return res;
+}
+
+char *key()
+{
+	return ASTERISK_GPL_KEY;
+}

Propchange: team/mogorman/asterisk-xmpp/res/res_stun.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mogorman/asterisk-xmpp/res/res_stun.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mogorman/asterisk-xmpp/res/res_stun.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/mogorman/asterisk-xmpp/res/res_xmpp.c
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/res_xmpp.c?rev=17737&r1=17736&r2=17737&view=diff
==============================================================================
--- team/mogorman/asterisk-xmpp/res/res_xmpp.c (original)
+++ team/mogorman/asterisk-xmpp/res/res_xmpp.c Wed Apr  5 21:44:17 2006
@@ -371,7 +371,7 @@
 								iks *x;
 								x = iks_new ("auth");
 								iks_insert_attrib (x, "xmlns", IKS_NS_XMPP_SASL);
-								int len = strlen (client->jid->user) + strlen (client->password) + 2;
+								int len = strlen (client->jid->user) + strlen (client->password) + 3;
 								char *s = ast_malloc (80+len);
 								char *base64;
 								iks_insert_attrib (x, "mechanism", "PLAIN");

Added: team/mogorman/asterisk-xmpp/res/stun/Makefile
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/stun/Makefile?rev=17737&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/res/stun/Makefile (added)
+++ team/mogorman/asterisk-xmpp/res/stun/Makefile Wed Apr  5 21:44:17 2006
@@ -1,0 +1,42 @@
+
+# if you change this version, change in stun.h too 
+VERSION=0.96.a
+
+#CXXFLAGS+=-O2
+#LDFLAGS+=-O2 -lssl
+STUNLIB=libstun.a
+
+#
+# Alternatively, for debugging.
+#
+CXXFLAGS+=-g -O -Wall
+LDFLAGS+=-g -O -Wall
+# for solaris
+#LDFLAGS+= -lnsl -lsocket
+
+
+all: client libstunwrapper
+
+clean:
+	- rm *.o client 
+
+client: client.o stun.o udp.o 
+	$(CXX) $(LDFLAGS) -o $@  $^
+
+
+%.o:%.cpp
+	$(CXX)  -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+libstun.a: stun.o udp.o
+	ar rv $@ $<
+
+libstunwrapper: stunwrapper.o
+	 ar crv libstunwrapper.a stunwrapper.o	
+
+%:RCS/%
+	co $@
+
+# Dependancies
+client.o: stun.h udp.h 
+stun.o: stun.h udp.h
+udp.o: stun.h udp.h 

Propchange: team/mogorman/asterisk-xmpp/res/stun/Makefile
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mogorman/asterisk-xmpp/res/stun/Makefile
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mogorman/asterisk-xmpp/res/stun/Makefile
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/mogorman/asterisk-xmpp/res/stun/client.cpp
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/stun/client.cpp?rev=17737&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/res/stun/client.cpp (added)
+++ team/mogorman/asterisk-xmpp/res/stun/client.cpp Wed Apr  5 21:44:17 2006
@@ -1,0 +1,395 @@
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <cstdlib>   
+
+#ifdef WIN32
+#include <time.h>
+#else
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <errno.h>
+#endif
+
+#include "udp.h"
+#include "stun.h"
+
+using namespace std;
+
+
+void
+usage()
+{
+   cerr << "Usage:" << endl
+	<< "    ./client stunServerHostname [testNumber] [-v] [-p srcPort] [-i nicAddr1] [-i nicAddr2] [-i nicAddr3]" << endl
+	<< "For example, if the STUN server was larry.gloo.net, you could do:" << endl
+	<< "    ./client larry.gloo.net" << endl
+	<< "The testNumber is just used for special tests." << endl
+	<< " test 1 runs test 1 from the RFC. For example:" << endl
+	<< "    ./client larry.gloo.net 0" << endl << endl
+        << endl;
+}
+
+#define MAX_NIC 3
+
+int
+main(int argc, char* argv[])
+{
+   assert( sizeof(UInt8 ) == 1 );
+   assert( sizeof(UInt16) == 2 );
+   assert( sizeof(UInt32) == 4 );
+    
+   initNetwork();
+    
+   cout << "STUN client version " << STUN_VERSION << endl;
+   
+   int testNum = 0;
+   bool verbose = false;
+	
+   StunAddress4 stunServerAddr;
+   stunServerAddr.addr=0;
+
+   int srcPort=0;
+   StunAddress4 sAddr[MAX_NIC];
+   int retval[MAX_NIC];
+   int numNic=0;
+
+   for ( int i=0; i<MAX_NIC; i++ )
+   {
+      sAddr[i].addr=0; 
+      sAddr[i].port=0; 
+      retval[i]=0;
+   }
+   
+   for ( int arg = 1; arg<argc; arg++ )
+   {
+      if ( !strcmp( argv[arg] , "-v" ) )
+      {
+         verbose = true;
+      }
+      else if ( !strcmp( argv[arg] , "-i" ) )
+      {
+         arg++;
+         if ( argc <= arg ) 
+         {
+            usage();
+            exit(-1);
+         }
+         if ( numNic >= MAX_NIC )
+         {  
+            cerr << "Can not have more than "<<  MAX_NIC <<" -i options" << endl;
+            usage();
+            exit(-1);
+         }
+         
+         stunParseServerName(argv[arg], sAddr[numNic++]);
+      }
+      else if ( !strcmp( argv[arg] , "-p" ) )
+      {
+         arg++;
+         if ( argc <= arg ) 
+         {
+            usage();
+            exit(-1);
+         }
+         srcPort = strtol( argv[arg], NULL, 10);
+      }
+      else    
+      {
+        char* ptr;
+        int t =  strtol( argv[arg], &ptr, 10 );
+        if ( *ptr == 0 )
+        { 
+           // conversion worked
+           testNum = t;
+           cout << "running test number " << testNum  << endl; 
+        }
+        else
+        {
+           bool ret = stunParseServerName( argv[arg], stunServerAddr);
+           if ( ret != true )
+           {
+              cerr << argv[arg] << " is not a valid host name " << endl;
+              usage();
+              exit(-1);
+           }
+	}	
+      }
+   }
+
+   if ( srcPort == 0 )
+   {
+      srcPort = stunRandomPort();
+   }
+   
+   if ( numNic == 0 )
+   {
+      // use default 
+      numNic = 1;
+   }
+   
+   for ( int nic=0; nic<numNic; nic++ )
+   {
+      sAddr[nic].port=srcPort;
+      if ( stunServerAddr.addr == 0 )
+      {
+         usage();
+         exit(-1);
+      }
+   
+      if (testNum==0)
+      {
+         bool presPort=false;
+         bool hairpin=false;
+		
+         NatType stype = stunNatType( stunServerAddr, verbose, &presPort, &hairpin, 
+                                      srcPort, &sAddr[nic]);
+		
+         if ( nic == 0 )
+         {
+            cout << "Primary: ";
+         }
+         else
+         {
+            cout << "Secondary: ";
+         }
+         
+         switch (stype)
+         {
+            case StunTypeFailure:
+               cout << "Some stun error detetecting NAT type";
+	       retval[nic] = -1;
+               exit(-1);
+               break;
+            case StunTypeUnknown:
+               cout << "Some unknown type error detetecting NAT type";
+	       retval[nic] = 0xEE;
+               break;
+            case StunTypeOpen:
+               cout << "Open";
+	       retval[nic] = 0x00; 
+               break;
+            case StunTypeIndependentFilter:
+               cout << "Independent Mapping, Independent Filter";
+               if ( presPort ) cout << ", preserves ports"; else cout << ", random port";
+               if ( hairpin  ) cout << ", will hairpin"; else cout << ", no hairpin";
+               retval[nic] = 0x02;
+               break;
+            case StunTypeDependentFilter:
+               cout << "Independedt Mapping, Address Dependendent Filter";
+               if ( presPort ) cout << ", preserves ports"; else cout << ", random port";
+               if ( hairpin  ) cout << ", will hairpin"; else cout << ", no hairpin";
+               retval[nic] = 0x04;
+               break;
+            case StunTypePortDependedFilter:
+               cout << "Indepndent Mapping, Port Dependent Filter";
+               if ( presPort ) cout << ", preserves ports"; else cout << ", random port";
+               if ( hairpin  ) cout << ", will hairpin"; else cout << ", no hairpin";
+               retval[nic] = 0x06;
+               break;
+            case StunTypeDependentMapping:
+               cout << "Dependent Mapping";
+               if ( presPort ) cout << ", preserves ports"; else cout << ", random port";
+               if ( hairpin  ) cout << ", will hairpin"; else cout << ", no hairpin";
+               retval[nic] = 0x08;
+               break;
+            case StunTypeFirewall:
+               cout << "Firewall";
+               retval[nic] = 0x0A;
+               break;
+            case StunTypeBlocked:
+               cout << "Blocked or could not reach STUN server";
+               retval[nic] = 0x0C;
+               break;
+            default:
+               cout << stype;
+               cout << "Unkown NAT type";
+               retval[nic] = 0x0E;  // Unknown NAT type
+               break;
+         }
+         cout << "\t"; cout.flush();
+         
+         if (!hairpin)
+         {
+             retval[nic] |= 0x10;
+         }       
+
+         if (presPort)
+         {
+             retval[nic] |= 0x01;
+         }
+      }
+      else if (testNum==100)
+      {
+         Socket myFd = openPort(srcPort,sAddr[nic].addr,verbose);
+      
+         StunMessage req;
+         memset(&req, 0, sizeof(StunMessage));
+      
+         StunAtrString username;
+         StunAtrString password;
+         username.sizeValue = 0;
+         password.sizeValue = 0;
+      
+         stunBuildReqSimple( &req, username, 
+                             false , false , 
+                             0x0c );
+      
+         char buf[STUN_MAX_MESSAGE_SIZE];
+         int len = STUN_MAX_MESSAGE_SIZE;
+      
+         len = stunEncodeMessage( req, buf, len, password,verbose );
+      
+         if ( verbose )
+         {
+            cout << "About to send msg of len " << len 
+                 << " to " << stunServerAddr << endl;
+         }
+      
+         while (1)
+         {
+            for ( int i=0; i<100; i++ )
+            {
+               sendMessage( myFd,
+                            buf, len, 
+                            stunServerAddr.addr, 
+                            stunServerAddr.port,verbose );
+            }
+#ifdef WIN32 // !cj! TODO - should fix this up in windows
+            clock_t now = clock();
+            assert( CLOCKS_PER_SEC == 1000 );
+            while ( clock() <= now+10 ) { };
+#else
+            usleep(10*1000);
+#endif
+         }
+      }
+      else if (testNum==-2)
+      {
+         const int numPort = 5;
+         int fd[numPort];
+         StunAddress4 mappedAddr;
+         
+         for( int i=0; i<numPort; i++ )
+         {
+            fd[i] = stunOpenSocket( stunServerAddr, &mappedAddr,
+                                    (srcPort==0)?0:(srcPort+i), &sAddr[nic],
+                                    verbose );
+            cout << "Got port at " << mappedAddr.port << endl;
+         }
+          
+         for( int i=0; i<numPort; i++ )
+         {
+            closesocket(fd[i]);
+         }
+      }
+      else if (testNum==-1)
+      {
+         int fd3,fd4;
+         StunAddress4 mappedAddr;
+         
+         bool ok = stunOpenSocketPair(stunServerAddr,
+                                      &mappedAddr,
+                                      &fd3,
+                                      &fd4,
+                                      srcPort, 
+                                      &sAddr[nic],
+                                      verbose);
+         if ( ok )
+         {
+            closesocket(fd3);
+            closesocket(fd4);
+            cout << "Got port pair at " << mappedAddr.port << endl;
+         }
+         else
+         {
+            cerr << "Opened a stun socket pair FAILED" << endl;
+         }
+      }
+      else
+      {
+         stunTest( stunServerAddr,testNum,verbose,&(sAddr[nic]) );
+      }
+   } // end of for loop 
+   cout << endl;
+   
+   UInt32 ret=0;
+   for ( int i=numNic-1; i>=0; i-- )
+   {
+      if ( retval[i] == -1 )
+      {
+         ret = 0xFFFFFFFF;
+         break;
+      }
+      ret = ret << 8;
+      ret = ret | ( retval[i] & 0xFF );
+   }
+   
+   cout << "Return value is " << hex << "0x";
+   cout.fill('0');
+   cout.width(6);
+   cout << ret << dec << endl;
+   cout.fill(' ');
+   
+   return ret;
+}
+
+
+/* ====================================================================
+ * The Vovida Software License, Version 1.0 
+ * 
+ * Copyright (c) 2000 Vovida Networks, Inc.  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. The names "VOCAL", "Vovida Open Communication Application Library",
+ *    and "Vovida Open Communication Application Library (VOCAL)" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact vocal at vovida.org.
+ *
+ * 4. Products derived from this software may not be called "VOCAL", nor
+ *    may "VOCAL" appear in their name, without prior written
+ *    permission of Vovida Networks, Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
+ * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
+ * IN EXCESS OF $1,000, NOR FOR ANY 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.
+ * 
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by Vovida
+ * Networks, Inc. and many individuals on behalf of Vovida Networks,
+ * Inc.  For more information on Vovida Networks, Inc., please see
+ * <http://www.vovida.org/>.
+ *
+ */
+
+// Local Variables:
+// mode:c++
+// c-file-style:"ellemtel"
+// c-file-offsets:((case-label . +))
+// indent-tabs-mode:nil
+// End:

Propchange: team/mogorman/asterisk-xmpp/res/stun/client.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mogorman/asterisk-xmpp/res/stun/client.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mogorman/asterisk-xmpp/res/stun/client.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/mogorman/asterisk-xmpp/res/stun/main.c
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/stun/main.c?rev=17737&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/res/stun/main.c (added)
+++ team/mogorman/asterisk-xmpp/res/stun/main.c Wed Apr  5 21:44:17 2006
@@ -1,0 +1,7 @@
+#include <stdio.h>
+
+int main() {
+	printf("HELLO \n");
+	printf("HELLO %d\n",CgetSrcPort());
+	return 0;
+}

Propchange: team/mogorman/asterisk-xmpp/res/stun/main.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mogorman/asterisk-xmpp/res/stun/main.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mogorman/asterisk-xmpp/res/stun/main.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/mogorman/asterisk-xmpp/res/stun/stun.cpp
URL: http://svn.digium.com/view/asterisk/team/mogorman/asterisk-xmpp/res/stun/stun.cpp?rev=17737&view=auto
==============================================================================
--- team/mogorman/asterisk-xmpp/res/stun/stun.cpp (added)
+++ team/mogorman/asterisk-xmpp/res/stun/stun.cpp Wed Apr  5 21:44:17 2006
@@ -1,0 +1,2496 @@
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <cstdlib>   
+#include <errno.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <stdlib.h>
+#include <io.h>
+#include <time.h>
+#else
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h> 
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <net/if.h>
+
+#endif
+
+
+#if defined(__sparc__) || defined(WIN32)
+#define NOSSL
+#endif
+#define NOSSL
+
+#include "udp.h"
+#include "stun.h"
+
+
+using namespace std;
+
+
+static void
+computeHmac(char* hmac, const char* input, int length, const char* key, int keySize);
+
+static bool 
+stunParseAtrAddress( char* body, unsigned int hdrLen,  StunAtrAddress4& result )
+{
+   if ( hdrLen != 8 )
+   {
+      clog << "hdrLen wrong for Address" <<endl;
+      return false;
+   }
+   result.pad = *body++;
+   result.family = *body++;
+   if (result.family == IPv4Family)
+   {
+      UInt16 nport;
+      memcpy(&nport, body, 2); body+=2;
+      result.ipv4.port = ntohs(nport);
+		
+      UInt32 naddr;
+      memcpy(&naddr, body, 4); body+=4;
+      result.ipv4.addr = ntohl(naddr);
+      return true;
+   }
+   else if (result.family == IPv6Family)
+   {
+      clog << "ipv6 not supported" << endl;
+   }
+   else
+   {
+      clog << "bad address family: " << result.family << endl;
+   }
+	
+   return false;
+}
+
+static bool 
+stunParseAtrChangeRequest( char* body, unsigned int hdrLen,  StunAtrChangeRequest& result )
+{
+   if ( hdrLen != 4 )
+   {
+      clog << "hdr length = " << hdrLen << " expecting " << sizeof(result) << endl;
+		
+      clog << "Incorrect size for ChangeRequest" << endl;
+      return false;
+   }
+   else
+   {
+      memcpy(&result.value, body, 4);
+      result.value = ntohl(result.value);
+      return true;
+   }
+}
+
+static bool 
+stunParseAtrError( char* body, unsigned int hdrLen,  StunAtrError& result )
+{
+   if ( hdrLen >= sizeof(result) )
+   {
+      clog << "head on Error too large" << endl;
+      return false;
+   }
+   else
+   {
+      memcpy(&result.pad, body, 2); body+=2;
+      result.pad = ntohs(result.pad);
+      result.errorClass = *body++;
+      result.number = *body++;
+		
+      result.sizeReason = hdrLen - 4;
+      memcpy(&result.reason, body, result.sizeReason);
+      result.reason[result.sizeReason] = 0;
+      return true;
+   }
+}
+
+static bool 
+stunParseAtrUnknown( char* body, unsigned int hdrLen,  StunAtrUnknown& result )
+{
+   if ( hdrLen >= sizeof(result) )
+   {
+      return false;
+   }
+   else
+   {
+      if (hdrLen % 4 != 0) return false;
+      result.numAttributes = hdrLen / 4;
+      for (int i=0; i<result.numAttributes; i++)
+      {
+         memcpy(&result.attrType[i], body, 2); body+=2;
+         result.attrType[i] = ntohs(result.attrType[i]);
+      }
+      return true;
+   }
+}
+
+
+static bool 
+stunParseAtrString( char* body, unsigned int hdrLen,  StunAtrString& result )
+{
+   if ( hdrLen >= STUN_MAX_STRING )
+   {
+      clog << "String is too large" << endl;
+      return false;
+   }
+   else
+   {
+      if (hdrLen % 4 != 0)
+      {
+         clog << "Bad length string " << hdrLen << endl;
+         return false;
+      }
+		
+      result.sizeValue = hdrLen;
+      memcpy(&result.value, body, hdrLen);
+      result.value[hdrLen] = 0;
+      return true;
+   }
+}
+
+
+static bool 
+stunParseAtrIntegrity( char* body, unsigned int hdrLen,  StunAtrIntegrity& result )
+{
+   if ( hdrLen != 20)
+   {
+      clog << "MessageIntegrity must be 20 bytes" << endl;
+      return false;
+   }
+   else
+   {
+      memcpy(&result.hash, body, hdrLen);
+      return true;
+   }
+}
+
+
+bool
+stunParseMessage( char* buf, unsigned int bufLen, StunMessage& msg, bool verbose)
+{
+   if (verbose) clog << "Received stun message: " << bufLen << " bytes" << endl;
+   memset(&msg, 0, sizeof(msg));
+	
+   if (sizeof(StunMsgHdr) > bufLen)
+   {
+      clog << "Bad message" << endl;
+      return false;
+   }
+	
+   memcpy(&msg.msgHdr, buf, sizeof(StunMsgHdr));
+   msg.msgHdr.msgType = ntohs(msg.msgHdr.msgType);
+   msg.msgHdr.msgLength = ntohs(msg.msgHdr.msgLength);
+	
+   if (msg.msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen)
+   {
+      clog << "Message header length doesn't match message size: "
+           << msg.msgHdr.msgLength << " - " << bufLen << endl;
+      return false;
+   }
+	
+   char* body = buf + sizeof(StunMsgHdr);
+   unsigned int size = msg.msgHdr.msgLength;
+	
+   //clog << "bytes after header = " << size << endl;
+	
+   while ( size > 0 )
+   {
+      // !jf! should check that there are enough bytes left in the buffer
+		
+      StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body);
+		
+      unsigned int attrLen = ntohs(attr->length);
+      int atrType = ntohs(attr->type);
+		
+      //if (verbose) clog << "Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl;
+      if ( attrLen+4 > size ) 
+      {
+         clog << "claims attribute is larger than size of message " 
+              <<"(attribute type="<<atrType<<")"<< endl;
+         return false;
+      }
+		
+      body += 4; // skip the length and type in attribute header
+      size -= 4;
+		
+      switch ( atrType )
+      {
+         case MappedAddress:
+            msg.hasMappedAddress = true;
+            if ( stunParseAtrAddress(  body,  attrLen,  msg.mappedAddress )== false )
+            {
+               clog << "problem parsing MappedAddress" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "MappedAddress = " << msg.mappedAddress.ipv4 << endl;
+            }
+					
+            break;  
+
+         case ResponseAddress:
+            msg.hasResponseAddress = true;
+            if ( stunParseAtrAddress(  body,  attrLen,  msg.responseAddress )== false )
+            {
+               clog << "problem parsing ResponseAddress" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "ResponseAddress = " << msg.responseAddress.ipv4 << endl;
+            }
+            break;  
+				
+         case ChangeRequest:
+            msg.hasChangeRequest = true;
+            if (stunParseAtrChangeRequest( body, attrLen, msg.changeRequest) == false)
+            {
+               clog << "problem parsing ChangeRequest" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "ChangeRequest = " << msg.changeRequest.value << endl;
+            }
+            break;
+				
+         case SourceAddress:
+            msg.hasSourceAddress = true;
+            if ( stunParseAtrAddress(  body,  attrLen,  msg.sourceAddress )== false )
+            {
+               clog << "problem parsing SourceAddress" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "SourceAddress = " << msg.sourceAddress.ipv4 << endl;
+            }
+            break;  
+				
+         case ChangedAddress:
+            msg.hasChangedAddress = true;
+            if ( stunParseAtrAddress(  body,  attrLen,  msg.changedAddress )== false )
+            {
+               clog << "problem parsing ChangedAddress" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "ChangedAddress = " << msg.changedAddress.ipv4 << endl;
+            }
+            break;  
+				
+         case Username: 
+            msg.hasUsername = true;
+            if (stunParseAtrString( body, attrLen, msg.username) == false)
+            {
+               clog << "problem parsing Username" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "Username = " << msg.username.value << endl;
+            }
+					
+            break;
+				
+         case Password: 
+            msg.hasPassword = true;
+            if (stunParseAtrString( body, attrLen, msg.password) == false)
+            {
+               clog << "problem parsing Password" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "Password = " << msg.password.value << endl;
+            }
+            break;
+				
+         case MessageIntegrity:
+            msg.hasMessageIntegrity = true;
+            if (stunParseAtrIntegrity( body, attrLen, msg.messageIntegrity) == false)
+            {
+               clog << "problem parsing MessageIntegrity" << endl;
+               return false;
+            }
+            else
+            {
+               //if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl;
+            }
+					
+            // read the current HMAC
+            // look up the password given the user of given the transaction id 
+            // compute the HMAC on the buffer
+            // decide if they match or not
+            break;
+				
+         case ErrorCode:
+            msg.hasErrorCode = true;
+            if (stunParseAtrError(body, attrLen, msg.errorCode) == false)
+            {
+               clog << "problem parsing ErrorCode" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "ErrorCode = " << int(msg.errorCode.errorClass) 
+                                 << " " << int(msg.errorCode.number) 
+                                 << " " << msg.errorCode.reason << endl;
+            }
+					
+            break;
+				
+         case UnknownAttribute:
+            msg.hasUnknownAttributes = true;
+            if (stunParseAtrUnknown(body, attrLen, msg.unknownAttributes) == false)
+            {
+               clog << "problem parsing UnknownAttribute" << endl;
+               return false;
+            }
+            break;
+				
+         case ReflectedFrom:
+            msg.hasReflectedFrom = true;
+            if ( stunParseAtrAddress(  body,  attrLen,  msg.reflectedFrom ) == false )
+            {
+               clog << "problem parsing ReflectedFrom" << endl;
+               return false;
+            }
+            break;  
+				
+         case XorMappedAddress:
+            msg.hasXorMappedAddress = true;
+            if ( stunParseAtrAddress(  body,  attrLen,  msg.xorMappedAddress ) == false )
+            {
+               clog << "problem parsing XorMappedAddress" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "XorMappedAddress = " << msg.mappedAddress.ipv4 << endl;
+            }
+            break;  
+
+         case XorOnly:
+            msg.xorOnly = true;
+            if (verbose) 
+            {
+               clog << "xorOnly = true" << endl;
+            }
+            break;  
+				
+         case ServerName: 
+            msg.hasServerName = true;
+            if (stunParseAtrString( body, attrLen, msg.serverName) == false)
+            {
+               clog << "problem parsing ServerName" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "ServerName = " << msg.serverName.value << endl;
+            }
+            break;
+				
+         case SecondaryAddress:
+            msg.hasSecondaryAddress = true;
+            if ( stunParseAtrAddress(  body,  attrLen,  msg.secondaryAddress ) == false )
+            {
+               clog << "problem parsing secondaryAddress" << endl;
+               return false;
+            }
+            else
+            {
+               if (verbose) clog << "SecondaryAddress = " << msg.secondaryAddress.ipv4 << endl;
+            }
+            break;  
+					
+         default:
+            if (verbose) clog << "Unknown attribute: " << atrType << endl;
+            if ( atrType <= 0x7FFF ) 
+            {
+               return false;
+            }
+      }
+		
+      body += attrLen;
+      size -= attrLen;
+   }
+    
+   return true;
+}
+
+
+static char* 
+encode16(char* buf, UInt16 data)
+{
+   UInt16 ndata = htons(data);
+   memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt16));
+   return buf + sizeof(UInt16);
+}
+
+static char* 
+encode32(char* buf, UInt32 data)
+{
+   UInt32 ndata = htonl(data);
+   memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt32));
+   return buf + sizeof(UInt32);
+}
+
+
+static char* 
+encode(char* buf, const char* data, unsigned int length)
+{
+   memcpy(buf, data, length);
+   return buf + length;
+}
+
+
+static char* 
+encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4& atr)
+{
+   ptr = encode16(ptr, type);
+   ptr = encode16(ptr, 8);
+   *ptr++ = atr.pad;
+   *ptr++ = IPv4Family;
+   ptr = encode16(ptr, atr.ipv4.port);
+   ptr = encode32(ptr, atr.ipv4.addr);
+	
+   return ptr;
+}
+
+static char* 
+encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest& atr)
+{
+   ptr = encode16(ptr, ChangeRequest);
+   ptr = encode16(ptr, 4);
+   ptr = encode32(ptr, atr.value);
+   return ptr;
+}
+
+static char* 
+encodeAtrError(char* ptr, const StunAtrError& atr)
+{
+   ptr = encode16(ptr, ErrorCode);
+   ptr = encode16(ptr, 6 + atr.sizeReason);
+   ptr = encode16(ptr, atr.pad);
+   *ptr++ = atr.errorClass;
+   *ptr++ = atr.number;
+   ptr = encode(ptr, atr.reason, atr.sizeReason);
+   return ptr;
+}
+
+
+static char* 
+encodeAtrUnknown(char* ptr, const StunAtrUnknown& atr)
+{
+   ptr = encode16(ptr, UnknownAttribute);
+   ptr = encode16(ptr, 2+2*atr.numAttributes);
+   for (int i=0; i<atr.numAttributes; i++)
+   {
+      ptr = encode16(ptr, atr.attrType[i]);
+   }
+   return ptr;
+}
+
+
+static char* 
+encodeXorOnly(char* ptr)
+{
+   ptr = encode16(ptr, XorOnly );
+   return ptr;
+}
+
+
+static char* 
+encodeAtrString(char* ptr, UInt16 type, const StunAtrString& atr)
+{
+   assert(atr.sizeValue % 4 == 0);
+	
+   ptr = encode16(ptr, type);
+   ptr = encode16(ptr, atr.sizeValue);
+   ptr = encode(ptr, atr.value, atr.sizeValue);
+   return ptr;
+}
+
+
+static char* 
+encodeAtrIntegrity(char* ptr, const StunAtrIntegrity& atr)
+{
+   ptr = encode16(ptr, MessageIntegrity);
+   ptr = encode16(ptr, 20);
+   ptr = encode(ptr, atr.hash, sizeof(atr.hash));
+   return ptr;
+}
+
+
+unsigned int
+stunEncodeMessage( const StunMessage& msg, 
+                   char* buf, 
+                   unsigned int bufLen, 
+                   const StunAtrString& password, 
+                   bool verbose)
+{
+   assert(bufLen >= sizeof(StunMsgHdr));
+   char* ptr = buf;
+	
+   ptr = encode16(ptr, msg.msgHdr.msgType);
+   char* lengthp = ptr;
+   ptr = encode16(ptr, 0);
+   ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id));
+	
+   if (verbose) clog << "Encoding stun message: " << endl;
+   if (msg.hasMappedAddress)
+   {
+      if (verbose) clog << "Encoding MappedAddress: " << msg.mappedAddressipv4 << endl;
+      ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress);
+   }
+   if (msg.hasResponseAddress)
+   {
+      if (verbose) clog << "Encoding ResponseAddress: " << msg.responseAddress.ipv4 << endl;
+      ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress);
+   }
+   if (msg.hasChangeRequest)
+   {
+      if (verbose) clog << "Encoding ChangeRequest: " << msg.changeRequestvalue << endl;
+      ptr = encodeAtrChangeRequest(ptr, msg.changeRequest);
+   }
+   if (msg.hasSourceAddress)
+   {
+      if (verbose) clog << "Encoding SourceAddress: " << msg.sourceAddressipv4 << endl;
+      ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress);
+   }
+   if (msg.hasChangedAddress)
+   {
+      if (verbose) clog << "Encoding ChangedAddress: " << msg.changedAddress.ipv4 << endl;
+      ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress);
+   }
+   if (msg.hasUsername)
+   {
+      if (verbose) clog << "Encoding Username: " << msg.username.value << endl;
+      ptr = encodeAtrString(ptr, Username, msg.username);
+   }
+   if (msg.hasPassword)
+   {
+      if (verbose) clog << "Encoding Password: " << msg.password.value << endl;
+      ptr = encodeAtrString(ptr, Password, msg.password);
+   }
+   if (msg.hasErrorCode)
+   {
+      if (verbose) clog << "Encoding ErrorCode: class=" 
+			<< int(msg.errorCode.errorClass)  
+			<< " number=" << int(msg.errorCode.number) 
+			<< " reason=" 
+			<< msg.errorCode.reason 
+			<< endl;
+		
+      ptr = encodeAtrError(ptr, msg.errorCode);
+   }
+   if (msg.hasUnknownAttributes)
+   {
+      if (verbose) clog << "Encoding UnknownAttribute: ???" << endl;
+      ptr = encodeAtrUnknown(ptr, msg.unknownAttributes);
+   }
+   if (msg.hasReflectedFrom)
+   {
+      if (verbose) clog << "Encoding ReflectedFrom: " << msg.reflectedFromipv4 << endl;
+      ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom);
+   }
+   if (msg.hasXorMappedAddress)
+   {
+      if (verbose) clog << "Encoding XorMappedAddress: " << msg.xorMappedAddress.ipv4 << endl;
+      ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress);
+   }
+   if (msg.xorOnly)
+   {
+      if (verbose) clog << "Encoding xorOnly: " << endl;
+      ptr = encodeXorOnly( ptr );
+   }
+   if (msg.hasServerName)
+   {
+      if (verbose) clog << "Encoding ServerName: " << msg.serverName.value << endl;
+      ptr = encodeAtrString(ptr, ServerName, msg.serverName);
+   }
+   if (msg.hasSecondaryAddress)
+   {
+      if (verbose) clog << "Encoding SecondaryAddress: " << msg.secondaryAddress.ipv4 << endl;
+      ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress);
+   }
+
+   if (password.sizeValue > 0)
+   {
+      if (verbose) clog << "HMAC with password: " << password.value << endl;
+		
+      StunAtrIntegrity integrity;
+      computeHmac(integrity.hash, buf, int(ptr-buf) , password.value, password.sizeValue);
+      ptr = encodeAtrIntegrity(ptr, integrity);
+   }
+   if (verbose) clog << endl;
+	
+   encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr)));
+   return int(ptr - buf);
+}

[... 2880 lines stripped ...]
_______________________________________________
--Bandwidth and Colocation provided by Easynews.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits


More information about the asterisk-commits mailing list