[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