├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile.am ├── README.md ├── bootstrap.sh ├── configure.ac ├── icelib ├── LICENSE ├── Makefile.am ├── README ├── bootstrap.sh ├── configure.ac ├── coverage.sh ├── include │ ├── icelib.h │ ├── icelib_debugwebserver.h │ ├── icelib_defines.h │ └── icelibtypes.h ├── src │ ├── Makefile.am │ ├── fifo.c │ ├── icelib.c │ ├── icelib_debugwebserver.c │ ├── icelib_intern.h │ ├── icelibtypes.c │ └── timer.c └── test │ ├── Makefile.am │ ├── icelib_running_test.c │ ├── icelib_test.c │ ├── icelibtypes_test.c │ └── testmain.c ├── netfilter ├── configure.ac ├── iptablessetup.sh └── src │ └── malicenode.cc ├── samplecode ├── COPYING ├── INSTALL ├── LICENSE ├── Makefile.am ├── README ├── bootstrap.sh ├── configure.ac └── src │ ├── Makefile.am │ ├── gather.c │ ├── gather.h │ ├── ice.c │ ├── iceclient │ ├── iceclient.c │ ├── iphelper.c │ ├── iphelper.h │ ├── permissions.c │ ├── permissions.h │ ├── pumpturn.c │ ├── simple_proxy_server.c │ ├── stunclient.c │ ├── stunserver.c │ ├── testturn │ ├── testturn.c │ ├── turnclient.c │ ├── turnhelper.c │ ├── turnhelper.h │ ├── turninfo.c │ ├── turninfo.h │ ├── utils.c │ ├── utils.h │ ├── view.c │ └── view.h ├── sockaddrutil ├── LICENSE ├── Makefile.am ├── README ├── bootstrap.sh ├── configure.ac ├── coverage.sh ├── include │ └── sockaddr_util.h ├── src │ ├── Makefile.am │ └── sockaddr_util.c └── test │ ├── Makefile.am │ ├── sockaddr_test.c │ └── testmain.c ├── stunlib ├── LICENSE ├── Makefile.am ├── README ├── TODO ├── bootstrap.sh ├── configure.ac ├── coverage.sh ├── include │ ├── stun_intern.h │ ├── stun_os.h │ ├── stunclient.h │ ├── stunlib.h │ ├── stunlibapi.h │ ├── turn_intern.h │ └── turnclient.h ├── src │ ├── Makefile.am │ ├── stunclient.c │ ├── stunlib.c │ └── turnclient.c └── test │ ├── Makefile.am │ ├── testmain.c │ ├── testrealworldpackets.c │ ├── teststunclient.c │ ├── teststunserver.c │ ├── testvector.c │ ├── turn_message.c │ └── turnclienttest.c ├── testcoverage.sh └── valgrind-wrapper /.gitignore: -------------------------------------------------------------------------------- 1 | #Compiled files and libraries 2 | *.so 3 | *.la 4 | *.o 5 | *.lo 6 | 7 | #Gcov and Lcov files 8 | *.trs 9 | *.gcno 10 | *.gcda 11 | *.log 12 | lcov 13 | 14 | 15 | #Autoconf generated files 16 | Makefile 17 | configure 18 | *.in 19 | config.h 20 | config.log 21 | config.status 22 | libtool 23 | stamp-h1 24 | .deps 25 | .libs 26 | aclocal.m4 27 | build-aux 28 | m4 29 | 30 | #executables 31 | stunclient 32 | stunserver 33 | turnclient 34 | 35 | check_icelib 36 | check_stunlib 37 | check_sockaddrutil 38 | 39 | simple_proxy_server 40 | 41 | #other 42 | natlib.info 43 | *.swp 44 | *.tar.gz 45 | *.cache 46 | *.dirstamp 47 | cscope.* 48 | \#*# 49 | \.#* 50 | *~ 51 | 52 | #Codian build system 53 | INPUT/ 54 | OUTPUT/ 55 | BUILD 56 | DEPS 57 | .hg/ 58 | .hgtags 59 | .hgignore 60 | env_*.sh 61 | Jamfile 62 | Jamrules 63 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: 3 | - gcc 4 | - clang 5 | before_install: 6 | - sudo apt-get install check 7 | 8 | # Change this to your needs 9 | script: 10 | - ./bootstrap.sh 11 | - ./configure --with-check && make && make check 12 | 13 | 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Cisco. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 16 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 18 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 19 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 20 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 21 | DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of Cisco. 26 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = sockaddrutil stunlib icelib 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Code has moved and no longer maintained 3 | # Please visit: 4 | # https://github.com/NATTools 5 | # for updated and maintaned code 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | NATtool is a package that contains several stand alone submodules. 21 | 22 | -* Compiling *- 23 | run ./bootstrap.sh to crate the ./configure script. This requires that autotools and autoconfigure is intalled 24 | 25 | Then do a ./configure and make to compile 26 | 27 | For OSX the following ./configure command can be used: 28 | ./configure --with-check --enable-gcov CFLAGS="-I/opt/local/include" LDFLAGS=-"L/opt/local/lib" 29 | 30 | 31 | This will build the three libraries sockaddrutillib, stunlib and icelib. They are all standalone 32 | libs and can be build seperately if you want to. 33 | 34 | For osx it is recomended to build with a gcc version from port (MacPorts) 35 | Before running the configure script make sure: 36 | - Xcode commnd line tols are installed (xcode-select --install) 37 | - gcc is installed. (port install gcc49) 38 | - automake and libtool is installed 39 | - check is installed (port install check) 40 | 41 | 42 | ** samplecode ** 43 | Module containing sample code of library usage. Note that this directory is not part of the distribution if you do a "make dist". 44 | To build you ned to cd into the directory and do the ./configure && make dance. 45 | 46 | ** ICElib ** 47 | A implementation of RFC 5245 Interactive Connectivity Establishment (ICE): 48 | A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer 49 | Protocols 50 | 51 | ** STUNlib ** 52 | A implementation of RFC 5766 Traversal Using Relays around NAT (TURN): 53 | Relay Extensions to Session Traversal Utilities for NAT (STUN). 54 | 55 | It also has support for RFC 6156 Traversal Using Relays around NAT (TURN) 56 | Extension for IPv6. 57 | 58 | Please note that this library currently is a bit client focused. But all message parsing is the same so it is still useful for a server implementation. The client side has some of the necessary state machines implemented to make usage of the library very simple for the client side. 59 | 60 | ** Sockaddr Util ** 61 | Convenience library to make it easier to work with sockaddr structs. 62 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd icelib 3 | ./bootstrap.sh 4 | cd ../stunlib 5 | ./bootstrap.sh 6 | cd ../sockaddrutil 7 | ./bootstrap.sh 8 | mkdir m4 build-aux 9 | cd .. 10 | autoreconf --install 11 | 12 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.63]) 5 | AC_INIT([NATtools], [0.2], [palmarti@cisco.com]) 6 | 7 | AC_CONFIG_AUX_DIR([build-aux]) 8 | AC_CONFIG_MACRO_DIR([m4]) 9 | 10 | AM_INIT_AUTOMAKE([foreign -Wall -Werror]) 11 | m4_pattern_allow([AM_PROG_AR]) 12 | AM_PROG_AR 13 | LT_INIT 14 | 15 | 16 | # Checks for programs. 17 | 18 | # Checks for libraries. 19 | 20 | # Checks for header files. 21 | 22 | # Checks for typedefs, structures, and compiler characteristics. 23 | 24 | # Checks for library functions. 25 | 26 | 27 | AM_CONDITIONAL(SUBMODULE, true) 28 | 29 | AC_CONFIG_FILES([Makefile]) 30 | 31 | AC_CONFIG_SUBDIRS([sockaddrutil 32 | stunlib 33 | icelib]) 34 | 35 | 36 | 37 | #AC_CONFIG_FILES([Makefile 38 | # sockaddrutil/src/Makefile 39 | # sockaddrutil/test/Makefile]) 40 | 41 | AC_OUTPUT 42 | -------------------------------------------------------------------------------- /icelib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Cisco. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 16 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 18 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 19 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 20 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 21 | DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of Cisco. 26 | -------------------------------------------------------------------------------- /icelib/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src test . 2 | ACLOCAL_AMFLAGS = -I m4 3 | 4 | 5 | EXTRA_DIST = README LICENSE -------------------------------------------------------------------------------- /icelib/README: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /icelib/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir m4 build-aux 3 | autoreconf --install 4 | -------------------------------------------------------------------------------- /icelib/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.61]) 5 | AC_INIT([icelib], [0.2], [palmarti@cisco.com]) 6 | AC_CONFIG_SRCDIR([src/icelib.c]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | AC_CONFIG_AUX_DIR([build-aux]) 10 | AC_CONFIG_MACRO_DIR([m4]) 11 | AM_INIT_AUTOMAKE([foreign -Wall -Werror]) 12 | m4_pattern_allow([AM_PROG_AR]) 13 | AM_PROG_AR 14 | LT_INIT 15 | 16 | 17 | 18 | # Checks for programs. 19 | AC_PROG_CC 20 | AM_PROG_CC_C_O 21 | 22 | AC_CHECK_FILE(../sockaddrutil/include/sockaddr_util.h, local_sockaddr=true, local_sockaddr=false ) 23 | 24 | AM_CONDITIONAL(LOCAL_SOCKADDR, test x"$local_sockaddr" = "xtrue") 25 | 26 | 27 | 28 | AM_COND_IF(LOCAL_SOCKADDR, 29 | [], 30 | [AC_CHECK_LIB([sockaddrutil], [sockaddr_initFromString],[], [AC_MSG_FAILURE([could not find sockaddrutil])])]) 31 | 32 | 33 | AC_CHECK_FILE(../stunlib/include/stunlib.h, local_stunlib=true, local_stunlib=false ) 34 | 35 | AM_CONDITIONAL(LOCAL_STUNLIB, test x"$local_stunlib" = "xtrue") 36 | 37 | 38 | AM_COND_IF(LOCAL_STUNLIB, 39 | [], 40 | [AC_CHECK_LIB([stun], [TurnClient_Init], [], [AC_MSG_FAILURE([could not find stunlib])])]) 41 | 42 | 43 | AC_ARG_ENABLE(gcov, 44 | AS_HELP_STRING([--enable-gcov], 45 | [enable test coverage with gcov @<:@default=no@:>@]), 46 | [case "${enableval}" in 47 | yes) gcov=true ;; 48 | no) gcov=false ;; 49 | *) AC_MSG_ERROR([bad value ${enableval} for --enable-gcov]) ;; 50 | esac], 51 | [gcov=false]) 52 | 53 | AM_CONDITIONAL(GCOV, test x"$gcov" = "xtrue") 54 | 55 | # Support for running test cases using valgrind: 56 | use_valgrind=false 57 | AC_ARG_ENABLE(valgrind, 58 | [ --enable-valgrind Use valgrind when running unit tests. ], 59 | [ use_valgrind=true ]) 60 | 61 | if [[ "$use_valgrind" = "true" ]]; then 62 | AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no) 63 | 64 | if [[ "$HAVE_VALGRIND" = "no" ]]; then 65 | AC_MSG_ERROR([Valgrind not found in PATH. ]) 66 | fi 67 | fi 68 | AM_CONDITIONAL(USE_VALGRIND, $use_valgrind) 69 | 70 | 71 | 72 | AM_CONDITIONAL(CHECK, "false") 73 | AC_ARG_WITH([check], 74 | [AS_HELP_STRING([--with-check], 75 | [use Check for unit testing @<:@default=no@:>@])], 76 | [], 77 | [with_check=no]) 78 | 79 | LIBCHECK= 80 | AS_IF([test "x$with_check" != xno], 81 | [AC_CHECK_LIB([check], [srunner_create], 82 | [AC_SUBST([LIBCHECK], ["-lcheck"]) 83 | AM_CONDITIONAL(CHECK, "true") 84 | AC_DEFINE([HAVE_CHECK], [1], 85 | [Define if you have check])], 86 | [AC_MSG_FAILURE( 87 | [--with-check was given, but test for check failed])], 88 | [])]) 89 | 90 | 91 | 92 | 93 | # Checks for header files. 94 | AC_CHECK_HEADERS([netinet/in.h stdint.h stdlib.h string.h]) 95 | 96 | # Checks for typedefs, structures, and compiler characteristics. 97 | AC_HEADER_STDBOOL 98 | AC_TYPE_INT32_T 99 | AC_TYPE_SIZE_T 100 | AC_TYPE_UINT16_T 101 | AC_TYPE_UINT32_T 102 | AC_TYPE_UINT64_T 103 | AC_TYPE_UINT8_T 104 | 105 | # Checks for library functions. 106 | AC_FUNC_MALLOC 107 | AC_CHECK_FUNCS([memset strchr]) 108 | 109 | AC_CONFIG_FILES([Makefile 110 | src/Makefile 111 | test/Makefile]) 112 | 113 | 114 | AC_OUTPUT 115 | -------------------------------------------------------------------------------- /icelib/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #./configure --with-check --enable-gcov 3 | 4 | make clean 5 | make check 6 | 7 | lcov --directory test/ --capture --output-file icelib.info 8 | 9 | 10 | genhtml --output-directory lcov --no-branch-coverage icelib.info 11 | 12 | firefox -new-tab lcov/index.html -------------------------------------------------------------------------------- /icelib/include/icelib_debugwebserver.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright 2011 Cisco. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are 6 | permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | of conditions and the following disclaimer in the documentation and/or other materials 13 | provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY CISCO ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR 18 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | The views and conclusions contained in the software and documentation are those of the 26 | authors and should not be interpreted as representing official policies, either expressed 27 | or implied, of Cisco. 28 | */ 29 | 30 | #ifndef ICELIB_DEBUGWEBSERVER_H 31 | #define ICELIB_DEBUGWEBSERVER_H 32 | 33 | void ICELIB_FormatIcePage(char *resp, char *resp_head); 34 | void ICELIB_FormatValidCheckListsBodyTable(ICELIB_INSTANCE *icelib, char *s, char *content); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /icelib/include/icelib_defines.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR 17 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | #ifndef ICELIB_DEFINE_H 30 | #define ICELIB_DEFINE_H 31 | 32 | #define ICELIB_RANDOM_SEGMENT_LENGTH (32/6) 33 | 34 | #define ICE_MAX_DEBUG_STRING 200 35 | 36 | #define ICELIB_UFRAG_LENGTH (4+1) /* includes zero ('\0') termination */ 37 | #define ICELIB_PASSWD_LENGTH (22+1) /* includes zero ('\0') termination */ 38 | #define ICELIB_FOUNDATION_LENGTH (1+1) /* includes zero ('\0') termination */ 39 | 40 | #define ICE_MAX_UFRAG_PAIR_LENGTH ( ( ICE_MAX_UFRAG_LENGTH * 2) + 1) 41 | #define ICE_MAX_FOUNDATION_PAIR_LENGTH ( ( ICE_MAX_FOUNDATION_LENGTH * 2)) 42 | 43 | #define ICELIB_MAX_PAIRS 40 44 | #define ICELIB_MAX_FIFO_ELEMENTS 40 45 | #define ICELIB_MAX_COMPONENTS 5 46 | 47 | #define ICELIB_LOCAL_TYPEPREF 126 48 | #define ICELIB_PEERREF_TYPEREF 110 49 | #define ICELIB_REFLEX_TYPEREF 100 50 | #define ICELIB_RELAY_TYPEREF 0 51 | 52 | 53 | 54 | #define ICELIB_COMPLETE_WEIGHT 150 55 | /*Warning. No equal values are allowed. (Used to ensure that RTP and RTCP has the same path)*/ 56 | #define ICELIB_HOST_WEIGHT 50 57 | #define ICELIB_SRFLX_WEIGHT 25 58 | #define ICELIB_PRFLX_WEIGHT 20 59 | #define ICELIB_RELAY_WEIGHT 10 60 | #define ICELIB_TIME_MULTIPLIER_INCREASE_MS 250 61 | 62 | #define ICELIB_RTP_COMPONENT_ID 1 63 | #define ICELIB_RTCP_COMPONENT_ID 2 64 | 65 | #define ICELIB_RTP_COMPONENT_INDEX 0 66 | #define ICELIB_RTCP_COMPONENT_INDEX 1 67 | 68 | #define ICELIB_FAIL_AFTER_MS 5000 /*5 sec*/ 69 | 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /icelib/include/icelibtypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright 2011 Cisco. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are 6 | permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | of conditions and the following disclaimer in the documentation and/or other materials 13 | provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY CISCO ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR 18 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | The views and conclusions contained in the software and documentation are those of the 26 | authors and should not be interpreted as representing official policies, either expressed 27 | or implied, of Cisco. 28 | */ 29 | 30 | #ifndef ICELIBTYPES_H 31 | #define ICELIBTYPES_H 32 | 33 | #include "icelib_defines.h" 34 | #include "stunlib.h" 35 | 36 | #include 37 | #include 38 | 39 | struct console_output; 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #else 44 | #include 45 | #endif 46 | 47 | 48 | #define ICE_MAX_UFRAG_LENGTH (256+1) /*zero terminated*/ 49 | #define ICE_MAX_PASSWD_LENGTH (256+1) /*zero terminated*/ 50 | #define ICE_MAX_CANDIDATES 12 51 | #define ICE_MAX_FOUNDATION_LENGTH (32+1) /*zero terminated*/ 52 | #define ICE_MAX_MEDIALINES 6 53 | #define ICE_MAX_COMPONENTS 2 54 | 55 | 56 | //----------------------------------------------------------------------------- 57 | // 58 | //----- List of effective components in a check list 59 | // 60 | typedef struct { 61 | unsigned int numberOfComponents; 62 | uint32_t componentIds[ ICELIB_MAX_COMPONENTS]; 63 | } ICELIB_COMPONENTLIST; 64 | 65 | 66 | // 67 | //----- Timer 68 | // 69 | typedef enum { 70 | ICELIB_timerStopped, 71 | ICELIB_timerRunning, 72 | ICELIB_timerTimeout 73 | } ICELIB_timerState; 74 | 75 | 76 | typedef struct { 77 | ICELIB_timerState timerState; 78 | unsigned int timeoutValueMS; 79 | unsigned int countUpMS; 80 | unsigned int tickIntervalMS; 81 | } ICELIB_TIMER; 82 | 83 | // 84 | //----- Fifo (Triggered Checks) 85 | // 86 | typedef uint32_t ICELIB_FIFO_ELEMENT; 87 | #define ICELIB_FIFO_IS_EMPTY 0 88 | #define ICELIB_FIFO_ELEMENT_REMOVED 0xFFFFFFFF 89 | 90 | typedef struct { 91 | ICELIB_FIFO_ELEMENT elements[ ICELIB_MAX_FIFO_ELEMENTS]; 92 | unsigned int inIndex; 93 | unsigned int outIndex; 94 | bool isFull; 95 | } ICELIB_TRIGGERED_FIFO; 96 | 97 | 98 | typedef struct { 99 | ICELIB_TRIGGERED_FIFO *fifo; 100 | unsigned int index; 101 | bool atEnd; 102 | } ICELIB_TRIGGERED_FIFO_ITERATOR; 103 | 104 | typedef enum { 105 | ICELIB_logDebug = -1, 106 | ICELIB_logInfo = 0, 107 | ICELIB_logWarning = 1, 108 | ICELIB_logError = 2, 109 | ICELIB_logDisable = 3 110 | } ICELIB_logLevel; 111 | 112 | 113 | typedef enum { 114 | ICELIB_Result_None, 115 | ICELIB_Result_Error, 116 | ICELIB_Result_CandidatesReady, 117 | ICELIB_Result_Finished, 118 | ICELIB_Result_OK 119 | } ICELIB_Result; 120 | 121 | 122 | typedef struct { 123 | uint64_t ms64; 124 | uint64_t ls64; 125 | } ICELIB_uint128_t; 126 | 127 | // 128 | //----- ICE candidate pair states 129 | // 130 | typedef enum { 131 | ICELIB_PAIR_IDLE, 132 | ICELIB_PAIR_PAIRED, 133 | ICELIB_PAIR_REMOVED, 134 | ICELIB_PAIR_FROZEN, 135 | ICELIB_PAIR_WAITING, 136 | ICELIB_PAIR_INPROGRESS, 137 | ICELIB_PAIR_SUCCEEDED, 138 | ICELIB_PAIR_FAILED 139 | } ICELIB_PAIR_STATE; 140 | 141 | 142 | // 143 | //----- ICE check list states 144 | // 145 | typedef enum { 146 | ICELIB_CHECKLIST_IDLE, 147 | ICELIB_CHECKLIST_RUNNING, 148 | ICELIB_CHECKLIST_COMPLETED, 149 | ICELIB_CHECKLIST_FAILED 150 | } ICELIB_CHECKLIST_STATE; 151 | 152 | 153 | // 154 | //----- ICE states 155 | // 156 | typedef enum { 157 | ICELIB_IDLE, 158 | ICELIB_RUNNING, 159 | ICELIB_COMPLETED, 160 | ICELIB_MANGLED, 161 | ICELIB_FAILED 162 | } ICELIB_STATE; 163 | 164 | 165 | 166 | typedef enum { 167 | ICE_CAND_TYPE_NONE, 168 | ICE_CAND_TYPE_HOST, 169 | ICE_CAND_TYPE_SRFLX, 170 | ICE_CAND_TYPE_RELAY, 171 | ICE_CAND_TYPE_PRFLX 172 | } ICE_CANDIDATE_TYPE; 173 | 174 | typedef enum { 175 | ICE_TURN_IDLE, 176 | ICE_TURN_ALLOCATING, 177 | ICE_TURN_ALLOCATED, 178 | ICE_TURN_SETTING_ACTIVE, 179 | ICE_TURN_ACTIVE 180 | }ICE_TURN_STATE; 181 | 182 | 183 | /*! 184 | * ICE single candidate 185 | * 186 | * From draft-ietf-mmusic-ice-18: 187 | * 188 | * foundation = 1*32 ice-char 189 | * componentid = 1*5 digit (0..65535) 190 | * priority = 1*10 digit (0..2147483647) 191 | * connectionAddr = address including port 192 | * relAddr = host addres when sending relayed candidates (Optional, used for debugging) 193 | */ 194 | typedef struct { 195 | char foundation[ ICE_MAX_FOUNDATION_LENGTH]; 196 | uint32_t componentid; 197 | uint32_t priority; 198 | struct sockaddr_storage connectionAddr; 199 | ICE_CANDIDATE_TYPE type; 200 | struct sockaddr_storage relAddr; 201 | uint32_t userValue1; 202 | uint32_t userValue2; 203 | } ICE_CANDIDATE; 204 | 205 | typedef struct { 206 | uint32_t componentId; 207 | struct sockaddr_storage connectionAddr; 208 | ICE_CANDIDATE_TYPE type; 209 | } ICE_REMOTE_CANDIDATE; 210 | 211 | typedef struct { 212 | ICE_REMOTE_CANDIDATE remoteCandidate[ICE_MAX_COMPONENTS]; 213 | uint32_t numberOfComponents; 214 | } ICE_REMOTE_CANDIDATES; 215 | 216 | /*! 217 | * ICE candidates for a single media stream 218 | */ 219 | typedef struct { 220 | char ufrag [ ICE_MAX_UFRAG_LENGTH]; 221 | char passwd [ ICE_MAX_PASSWD_LENGTH]; 222 | ICE_CANDIDATE candidate[ ICE_MAX_CANDIDATES]; 223 | uint32_t numberOfCandidates; 224 | ICE_TURN_STATE turnState; 225 | uint32_t userValue1; 226 | uint32_t userValue2; 227 | struct sockaddr_storage defaultAddr; 228 | ICE_CANDIDATE_TYPE defaultCandType; 229 | } ICE_MEDIA_STREAM; 230 | 231 | 232 | /*! 233 | * ICE candidates for all media streams 234 | */ 235 | typedef struct { 236 | bool controlling; 237 | ICE_MEDIA_STREAM mediaStream[ ICE_MAX_MEDIALINES ]; 238 | uint32_t numberOfICEMediaLines; 239 | } ICE_MEDIA; 240 | 241 | #define ICELIB_MAX_NO_OF_TRANSID 5 242 | 243 | // 244 | //----- ICE check list and valid list pair 245 | // 246 | typedef struct { 247 | ICELIB_PAIR_STATE pairState; 248 | uint32_t pairId; 249 | uint32_t refersToPairId; 250 | bool defaultPair; 251 | bool useCandidate; 252 | bool triggeredUseCandidate; 253 | bool nominatedPair; 254 | bool sentUseCandidateAlready; 255 | uint64_t pairPriority; 256 | const ICE_CANDIDATE *pLocalCandidate; 257 | const ICE_CANDIDATE *pRemoteCandidate; 258 | StunMsgId transactionIdTable[ICELIB_MAX_NO_OF_TRANSID]; 259 | unsigned int numberOfTransactionIds; 260 | //StunMsgId transactionId; 261 | } ICELIB_LIST_PAIR; 262 | 263 | // 264 | //----- Valid List 265 | // 266 | #define ICELIB_MAX_VALID_ELEMENTS ICELIB_MAX_PAIRS 267 | typedef ICELIB_LIST_PAIR ICELIB_VALIDLIST_ELEMENT; 268 | 269 | 270 | typedef struct { 271 | ICELIB_VALIDLIST_ELEMENT elements[ ICELIB_MAX_VALID_ELEMENTS]; 272 | unsigned int numberOfElements; 273 | } ICELIB_LIST_VL; 274 | 275 | typedef struct { 276 | ICELIB_LIST_VL pairs; 277 | uint32_t nextPairId; 278 | uint32_t readyToNominateWeighting; 279 | uint32_t nominatedPathScore; 280 | } ICELIB_VALIDLIST; 281 | 282 | 283 | typedef struct { 284 | ICELIB_VALIDLIST *pValidList; 285 | unsigned int index; 286 | } ICELIB_VALIDLIST_ITERATOR; 287 | 288 | 289 | // 290 | //----- ICE check list 291 | // 292 | typedef struct { 293 | unsigned int id; 294 | const char *ufragLocal; 295 | const char *ufragRemote; 296 | const char *passwdLocal; 297 | const char *passwdRemote; 298 | ICELIB_CHECKLIST_STATE checkListState; 299 | bool timerRunning; 300 | bool stopChecks; //Almost complete, don't fire of any new checks. 301 | unsigned int numberOfPairs; 302 | ICELIB_LIST_PAIR checkListPairs[ ICELIB_MAX_PAIRS]; 303 | ICELIB_COMPONENTLIST componentList; 304 | uint32_t nextPairId; 305 | } ICELIB_CHECKLIST; 306 | 307 | // 308 | //----- One controller per media stream 309 | // 310 | typedef struct { 311 | ICELIB_CHECKLIST checkList; 312 | ICELIB_VALIDLIST validList; 313 | ICELIB_TRIGGERED_FIFO triggeredChecksFifo; 314 | ICE_MEDIA_STREAM discoveredLocalCandidates; 315 | ICE_MEDIA_STREAM discoveredRemoteCandidates; 316 | ICE_REMOTE_CANDIDATES remoteCandidates; /*When ICE is complete, the remote 317 | candidates will be stored here */ 318 | } ICELIB_STREAM_CONTROLLER; 319 | 320 | void ICELIBTYPES_ICE_MEDIA_STREAM_reset(ICE_MEDIA_STREAM *iceMediaStream); 321 | bool ICELIBTYPES_ICE_MEDIA_STREAM_isEmpty(const ICE_MEDIA_STREAM *iceMediaStream); 322 | 323 | void ICELIBTYPES_ICE_MEDIA_reset(ICE_MEDIA *iceMedia); 324 | bool ICELIBTYPES_ICE_MEDIA_isEmpty(const ICE_MEDIA *iceMedia); 325 | 326 | char const * ICELIBTYPES_ICE_CANDIDATE_TYPE_toString( const ICE_CANDIDATE_TYPE candidateType); 327 | 328 | #ifdef __cplusplus 329 | } 330 | #endif 331 | 332 | #endif 333 | -------------------------------------------------------------------------------- /icelib/src/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | if LOCAL_SOCKADDR 3 | SOCKADDR_CPPFLAGS = -I../../sockaddrutil/include 4 | endif 5 | 6 | if LOCAL_STUNLIB 7 | STUNLIB_CPPFLAGS =-I../../stunlib/include 8 | endif 9 | 10 | 11 | 12 | AM_CPPFLAGS = -I../include $(SOCKADDR_CPPFLAGS) $(STUNLIB_CPPFLAGS) -O2 -g -Wall -Wextra -Wno-unknown-pragmas -Werror-implicit-function-declaration -Werror -Wno-unused-parameter -Wdeclaration-after-statement -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes 13 | 14 | include_HEADERS = ../include/icelib.h ../include/icelibtypes.h ../include/icelib_defines.h 15 | 16 | 17 | lib_LTLIBRARIES = libice.la 18 | libice_la_SOURCES = icelib.c icelibtypes.c icelib_intern.h fifo.c timer.c 19 | libice_la_LDFLAGS = -version-info 1:0:0 20 | 21 | -------------------------------------------------------------------------------- /icelib/src/fifo.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | 30 | #include 31 | #include "icelib.h" 32 | #include "icelib_intern.h" 33 | 34 | 35 | #define fifoIncrementToNext(index) (index = (index + 1) % ICELIB_MAX_FIFO_ELEMENTS) 36 | 37 | 38 | void ICELIB_fifoClear(ICELIB_TRIGGERED_FIFO *fifo) 39 | { 40 | memset(fifo, 0, sizeof(*fifo)); 41 | } 42 | 43 | 44 | unsigned int ICELIB_fifoCount(const ICELIB_TRIGGERED_FIFO *fifo) 45 | { 46 | if (fifo->isFull) 47 | return ICELIB_MAX_FIFO_ELEMENTS; 48 | 49 | if (fifo->inIndex >= fifo->outIndex) { 50 | return fifo->inIndex - fifo->outIndex; 51 | } else { 52 | return ICELIB_MAX_FIFO_ELEMENTS - (fifo->outIndex - fifo->inIndex); 53 | } 54 | } 55 | 56 | 57 | bool ICELIB_fifoIsEmpty(const ICELIB_TRIGGERED_FIFO *fifo) 58 | { 59 | return (fifo->inIndex == fifo->outIndex) && !fifo->isFull; 60 | } 61 | 62 | 63 | bool ICELIB_fifoIsFull(const ICELIB_TRIGGERED_FIFO *fifo) 64 | { 65 | return fifo->isFull; 66 | } 67 | 68 | 69 | // 70 | //----- Return: true - no more room, fifo is full!! 71 | // false - element was inserted into fifo 72 | // 73 | bool ICELIB_fifoPut(ICELIB_TRIGGERED_FIFO *fifo, ICELIB_FIFO_ELEMENT element) 74 | { 75 | if (ICELIB_fifoIsFull(fifo)) 76 | return true; 77 | 78 | fifo->elements[ fifo->inIndex] = element; 79 | fifoIncrementToNext(fifo->inIndex); 80 | if (fifo->inIndex == fifo->outIndex) 81 | fifo->isFull = true; 82 | 83 | return false; 84 | } 85 | 86 | 87 | // 88 | //----- Return: element - fifo was not empty 89 | // ICELIB_FIFO_IS_EMPTY - fifo is empty!! 90 | // 91 | ICELIB_FIFO_ELEMENT ICELIB_fifoGet(ICELIB_TRIGGERED_FIFO *fifo) 92 | { 93 | unsigned int outPreIndex; 94 | 95 | if (ICELIB_fifoIsEmpty(fifo)) 96 | return ICELIB_FIFO_IS_EMPTY; 97 | 98 | fifo->isFull = false; 99 | outPreIndex = fifo->outIndex; 100 | fifoIncrementToNext(fifo->outIndex); 101 | 102 | return fifo->elements[ outPreIndex]; 103 | } 104 | 105 | 106 | void ICELIB_fifoIteratorConstructor(ICELIB_TRIGGERED_FIFO_ITERATOR *iterator, 107 | ICELIB_TRIGGERED_FIFO *fifo) 108 | { 109 | iterator->fifo = fifo; 110 | iterator->index = fifo->outIndex; 111 | iterator->atEnd = false; 112 | } 113 | 114 | 115 | ICELIB_FIFO_ELEMENT *pICELIB_fifoIteratorNext(ICELIB_TRIGGERED_FIFO_ITERATOR *iterator) 116 | { 117 | ICELIB_FIFO_ELEMENT *element = NULL; 118 | 119 | if (ICELIB_fifoIsEmpty(iterator->fifo)) 120 | return NULL; 121 | 122 | if (iterator->atEnd) 123 | return NULL; 124 | 125 | if (ICELIB_fifoIsFull(iterator->fifo)) { 126 | element = &iterator->fifo->elements[ iterator->index]; 127 | fifoIncrementToNext(iterator->index); 128 | if (iterator->index == iterator->fifo->inIndex) { 129 | iterator->atEnd = true; 130 | } 131 | } else { 132 | if (iterator->index == iterator->fifo->inIndex) { 133 | iterator->atEnd = true; 134 | return NULL; 135 | } 136 | 137 | element = &iterator->fifo->elements[ iterator->index]; 138 | fifoIncrementToNext(iterator->index); 139 | } 140 | 141 | return element; 142 | } 143 | 144 | 145 | void ICELIB_triggeredFifoClear(ICELIB_TRIGGERED_FIFO *fifo) 146 | { 147 | ICELIB_fifoClear(fifo); 148 | } 149 | 150 | 151 | unsigned int ICELIB_triggeredFifoCount(const ICELIB_TRIGGERED_FIFO *fifo) 152 | { 153 | return ICELIB_fifoCount(fifo); 154 | } 155 | 156 | 157 | bool ICELIB_triggeredFifoIsEmpty(const ICELIB_TRIGGERED_FIFO *fifo) 158 | { 159 | return ICELIB_fifoIsEmpty(fifo); 160 | } 161 | 162 | 163 | bool ICELIB_triggeredFifoIsFull(const ICELIB_TRIGGERED_FIFO *fifo) 164 | { 165 | return ICELIB_fifoIsFull(fifo); 166 | } 167 | 168 | 169 | // 170 | //----- Return: true - no more room, fifo is full!! 171 | // false - element was inserted into fifo 172 | // 173 | bool ICELIB_triggeredFifoPut(ICELIB_TRIGGERED_FIFO *fifo, 174 | ICELIB_LIST_PAIR *pair) 175 | { 176 | return ICELIB_fifoPut(fifo, pair->pairId); 177 | } 178 | 179 | 180 | bool ICELIB_isTriggeredFifoPairPresent(ICELIB_TRIGGERED_FIFO *fifo, 181 | ICELIB_LIST_PAIR *pair, 182 | ICELIB_CALLBACK_LOG *callbackLog) 183 | { 184 | uint32_t *pairId; 185 | ICELIB_TRIGGERED_FIFO_ITERATOR tfIterator; 186 | 187 | ICELIB_fifoIteratorConstructor(&tfIterator, fifo); 188 | 189 | while ((pairId = pICELIB_fifoIteratorNext(&tfIterator)) != NULL) { 190 | if (*pairId == pair->pairId) { 191 | ICELIB_log(callbackLog, ICELIB_logDebug, "pair already present in FIFO"); 192 | return true; 193 | } 194 | } 195 | return false; 196 | } 197 | 198 | 199 | // 200 | //----- Return: true - no more room, fifo is full!! 201 | // false - element was inserted into fifo 202 | // 203 | bool ICELIB_triggeredFifoPutIfNotPresent(ICELIB_TRIGGERED_FIFO *fifo, 204 | ICELIB_LIST_PAIR *pair, 205 | ICELIB_CALLBACK_LOG *callbackLog) 206 | { 207 | if (!ICELIB_isTriggeredFifoPairPresent(fifo, pair, callbackLog)) { 208 | return ICELIB_fifoPut(fifo, pair->pairId); 209 | } 210 | return false; 211 | } 212 | 213 | 214 | // 215 | //----- Get a pair from the triggered checks queue 216 | // 217 | // Get a pointer to the pair. 218 | // Since the fifo holds pairId's, the address of the pair is found by 219 | // looking up the pair in the check list by its pairId. 220 | // 221 | // Return: pointer to pair - fifo was not empty 222 | // NULL - fifo is empty!! 223 | // 224 | ICELIB_LIST_PAIR *pICELIB_triggeredFifoGet(ICELIB_CHECKLIST *checkList, 225 | ICELIB_CALLBACK_LOG *callbackLog, 226 | ICELIB_TRIGGERED_FIFO *fifo) 227 | { 228 | uint32_t pairId; 229 | ICELIB_LIST_PAIR *pair; 230 | 231 | do { 232 | if (ICELIB_fifoIsEmpty(fifo)) { 233 | ICELIB_log(callbackLog, ICELIB_logDebug, "Triggered Check FIFO is empty!"); 234 | return NULL; 235 | } 236 | pairId = ICELIB_fifoGet(fifo); 237 | } while (pairId == ICELIB_FIFO_ELEMENT_REMOVED); 238 | 239 | pair = ICELIB_getPairById(checkList, pairId); 240 | 241 | if (pair == NULL) { 242 | ICELIB_log1(callbackLog, ICELIB_logDebug, "Could not find pair by Id: %u", pairId); 243 | } 244 | 245 | return pair; 246 | } 247 | 248 | 249 | void ICELIB_triggeredFifoRemove(ICELIB_TRIGGERED_FIFO *fifo, 250 | ICELIB_LIST_PAIR *pair) 251 | { 252 | uint32_t *pairId; 253 | ICELIB_TRIGGERED_FIFO_ITERATOR tfIterator; 254 | 255 | ICELIB_fifoIteratorConstructor(&tfIterator, fifo); 256 | 257 | while ((pairId = pICELIB_fifoIteratorNext(&tfIterator)) != NULL) { 258 | if (*pairId == pair->pairId) { 259 | *pairId = ICELIB_FIFO_ELEMENT_REMOVED; 260 | } 261 | } 262 | } 263 | 264 | 265 | void ICELIB_triggeredfifoIteratorConstructor(ICELIB_TRIGGERED_FIFO_ITERATOR *iterator, 266 | ICELIB_TRIGGERED_FIFO *fifo) 267 | { 268 | ICELIB_fifoIteratorConstructor(iterator, fifo); 269 | } 270 | 271 | 272 | ICELIB_LIST_PAIR *pICELIB_triggeredfifoIteratorNext(ICELIB_CHECKLIST *checkList, 273 | ICELIB_CALLBACK_LOG *callbackLog, 274 | ICELIB_TRIGGERED_FIFO_ITERATOR *iterator) 275 | { 276 | uint32_t *pairId; 277 | ICELIB_LIST_PAIR *pair = NULL; 278 | 279 | pairId = pICELIB_fifoIteratorNext(iterator); 280 | 281 | if (pairId != NULL) { 282 | 283 | pair = ICELIB_getPairById(checkList, *pairId); 284 | 285 | if (pair == NULL) { 286 | ICELIB_log1(callbackLog, ICELIB_logDebug, "Could not find pair by Id: %u", *pairId); 287 | } 288 | } 289 | 290 | return pair; 291 | } 292 | -------------------------------------------------------------------------------- /icelib/src/icelib_debugwebserver.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | #include "icelib.h" 30 | #include "icelib_intern.h" 31 | #include "icelib_debugwebserver.h" 32 | 33 | #include "netaddr.h" 34 | 35 | #include 36 | 37 | static void ICELIB_FormatHeaderOk(char *resp_head, char *resp, const char *content) 38 | { 39 | sprintf(resp_head, "HTTP/1.0 200 OK\r\n"); 40 | sprintf(&resp_head[strlen(resp_head)], "Content-type: %s\r\n", content); 41 | sprintf(&resp_head[strlen(resp_head)], "Content-length: %d\r\n", strlen(resp)); 42 | sprintf(&resp_head[strlen(resp_head)], "\r\n"); 43 | } 44 | 45 | static void ICELIB_RowStart(char *s, const char *bgColour, bool isExcel) { 46 | if (!isExcel) { 47 | sprintf(&s[strlen(s)], "", bgColour); 48 | } 49 | } 50 | 51 | static void ICELIB_RowEnd(char *s, bool isExcel) 52 | { 53 | if (!isExcel) { 54 | sprintf(&s[strlen(s)], ""); 55 | } 56 | } 57 | 58 | static void ICELIB_FormatUint32_1(char *s, uint32_t val, bool isExcel, bool isTable, bool singleRow) 59 | { 60 | if (isExcel) 61 | sprintf(&s[strlen(s)], "\t %d\n", val); /* simple tab field separator */ 62 | else if (isTable) 63 | { 64 | if (singleRow) 65 | sprintf(&s[strlen(s)], "%d\n", val); /* single row */ 66 | else 67 | sprintf(&s[strlen(s)], "%d\n", val); /* continuation */ 68 | } 69 | else 70 | sprintf(&s[strlen(s)], "%d
\n", val); 71 | } 72 | 73 | 74 | static void ICELIB_FormatStr(char *s, const char *val, bool isExcel, bool isTable, bool singleRow) 75 | { 76 | if (isExcel) 77 | sprintf(&s[strlen(s)], "\t %s\n", val); /* simple tab field separator */ 78 | else if (isTable) 79 | { 80 | if (singleRow) 81 | sprintf(&s[strlen(s)], "%s\n", val); /* row */ 82 | else 83 | sprintf(&s[strlen(s)], "%s\n", val); /* row */ 84 | } 85 | else 86 | sprintf(&s[strlen(s)], "%s
\n", val); 87 | } 88 | 89 | 90 | 91 | 92 | static const char *ICELIB_IceComponentIdToStr(uint32_t componentId) 93 | { 94 | switch (componentId) 95 | { 96 | case 1: return "RTP"; 97 | case 2: return "RTCP"; 98 | default: return "???"; 99 | } 100 | } 101 | 102 | 103 | 104 | void ICELIB_FormatValidCheckListsBodyTable(ICELIB_INSTANCE *icelib, char *s, char *content) { 105 | int32_t j = 0; 106 | uint32_t i; 107 | sprintf(&s[strlen(s)], "

Session %i

\n", j); 108 | 109 | sprintf(&s[strlen(s)], "\n"); 110 | 111 | /* for all media streams */ 112 | for (i = 0; i < icelib->numberOfMediaStreams; ++i) { 113 | ICELIB_VALIDLIST *pValidList; 114 | ICELIB_VALIDLIST_ITERATOR vlIterator; 115 | ICELIB_VALIDLIST_ELEMENT *pValidPair; 116 | int j; 117 | 118 | pValidList = &icelib->streamControllers[i].validList; 119 | ICELIB_validListIteratorConstructor(&vlIterator, pValidList); 120 | 121 | /* for all valid pairs */ 122 | for (j=0; ( ( pValidPair = pICELIB_validListIteratorNext( &vlIterator)) != NULL); j++) 123 | { 124 | char addr[MAX_NET_ADDR_STRING_SIZE]; 125 | 126 | if ((i == 0) && (j == 0)) 127 | { 128 | /* table header row */ 129 | ICELIB_RowStart(&s[strlen(s)], "wheat", false); 130 | sprintf(&s[strlen(s)], "\n"); 131 | sprintf(&s[strlen(s)], "\n"); 132 | sprintf(&s[strlen(s)], "\n"); 133 | sprintf(&s[strlen(s)], "\n"); 134 | sprintf(&s[strlen(s)], "\n"); 135 | sprintf(&s[strlen(s)], "\n"); 136 | sprintf(&s[strlen(s)], "\n"); 137 | sprintf(&s[strlen(s)], "\n"); 138 | sprintf(&s[strlen(s)], "\n"); 139 | sprintf(&s[strlen(s)], "\n"); 140 | ICELIB_RowEnd(&s[strlen(s)], false); 141 | } 142 | 143 | ICELIB_RowStart(&s[strlen(s)], pValidPair->nominatedPair ? "chartreuse" : "white", false); 144 | ICELIB_FormatUint32_1(&s[strlen(s)], i, false, true, false); 145 | ICELIB_FormatUint32_1(&s[strlen(s)], pValidPair->pairId, false, true, false); 146 | ICELIB_FormatStr(&s[strlen(s)], ICELIB_toString_CheckListPairState(pValidPair->pairState), false, true, false); 147 | ICELIB_FormatUint32_1(&s[strlen(s)], pValidPair->nominatedPair ? 1 : 0, false, true, false); 148 | 149 | /* local cand */ 150 | ICELIB_FormatStr(&s[strlen(s)], 151 | ICELIB_IceComponentIdToStr(pValidPair->pLocalCandidate->componentid), false, true, false); 152 | ICELIB_FormatStr(&s[strlen(s)], 153 | ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(pValidPair->pLocalCandidate->type), false, true, false); 154 | netaddr_toString(&pValidPair->pLocalCandidate->connectionAddr, addr , sizeof( addr), true); 155 | ICELIB_FormatStr(&s[strlen(s)], addr, false, true, false); 156 | 157 | /* remote cand */ 158 | ICELIB_FormatStr(&s[strlen(s)], 159 | ICELIB_IceComponentIdToStr(pValidPair->pRemoteCandidate->componentid), false, true, false); 160 | ICELIB_FormatStr(&s[strlen(s)], 161 | ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(pValidPair->pRemoteCandidate->type), false, true, false); 162 | netaddr_toString(&pValidPair->pRemoteCandidate->connectionAddr, addr , sizeof( addr), true); 163 | ICELIB_FormatStr(&s[strlen(s)], addr, false, true, false); 164 | 165 | ICELIB_RowEnd(&s[strlen(s)], false); 166 | 167 | } /* for all valid pairs */ 168 | 169 | } /* for all media streams */ 170 | 171 | sprintf(&s[strlen(s)], "
MediaStreamPairIdStateNominatedL-CompL-TypeL-AddrR-CompR-TypeR-Addr
\n"); 172 | } 173 | 174 | void ICELIB_FormatIcePage(char *resp, char *resp_head) 175 | { 176 | /* body */ 177 | sprintf(resp, "

TANDBERG ICE DEBUGGER

\n"); 178 | sprintf(&resp[strlen(resp)], "

ICE

\n"); 179 | 180 | sprintf(&resp[strlen(resp)], "
DumpAllCheckLists\n"); 181 | sprintf(&resp[strlen(resp)], "
DumpValidCheckLists\n"); 182 | 183 | /* Create response header */ 184 | ICELIB_FormatHeaderOk(resp_head, resp, "text/html"); 185 | } 186 | -------------------------------------------------------------------------------- /icelib/src/icelibtypes.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | #include 30 | 31 | 32 | #include "sockaddr_util.h" 33 | #include "icelibtypes.h" 34 | 35 | char const * ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(const ICE_CANDIDATE_TYPE candidateType){ 36 | switch(candidateType){ 37 | case ICE_CAND_TYPE_NONE: 38 | return "NONE"; 39 | case ICE_CAND_TYPE_HOST: 40 | return "HOST"; 41 | case ICE_CAND_TYPE_SRFLX: 42 | return "SRFLX"; 43 | case ICE_CAND_TYPE_RELAY: 44 | return "RELAY"; 45 | case ICE_CAND_TYPE_PRFLX: 46 | return "PRFLX"; 47 | } 48 | return "UNKNOWN"; 49 | } 50 | 51 | bool ICELIBTYPES_ICE_MEDIA_STREAM_isEmpty(const ICE_MEDIA_STREAM *iceMediaStream) 52 | { 53 | if (iceMediaStream->numberOfCandidates > 0) { 54 | return false; 55 | } 56 | return true; 57 | } 58 | 59 | bool ICELIBTYPES_ICE_MEDIA_isEmpty(const ICE_MEDIA *iceMedia) 60 | { 61 | if (iceMedia->numberOfICEMediaLines > 0) { 62 | return false; 63 | } 64 | return true; 65 | } 66 | 67 | void ICELIBTYPES_ICE_MEDIA_STREAM_reset(ICE_MEDIA_STREAM *iceMediaStream) 68 | { 69 | memset(iceMediaStream, 0, sizeof(*iceMediaStream)); 70 | } 71 | 72 | void ICELIBTYPES_ICE_MEDIA_reset(ICE_MEDIA *iceMedia) 73 | { 74 | memset(iceMedia, 0, sizeof(*iceMedia)); 75 | } 76 | -------------------------------------------------------------------------------- /icelib/src/timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | 30 | #include 31 | #include "icelib.h" 32 | #include "icelib_intern.h" 33 | 34 | 35 | void ICELIB_timerConstructor(ICELIB_TIMER *timer, 36 | unsigned int tickIntervalMS) 37 | { 38 | memset(timer, 0, sizeof(*timer)); 39 | timer->tickIntervalMS = tickIntervalMS; 40 | timer->countUpMS = 0; 41 | timer->timerState = ICELIB_timerStopped; 42 | } 43 | 44 | 45 | void ICELIB_timerStart(ICELIB_TIMER *timer, 46 | unsigned int timeoutMS) 47 | { 48 | timer->timeoutValueMS = timeoutMS; 49 | timer->countUpMS = 0; 50 | timer->timerState = ICELIB_timerRunning; 51 | } 52 | 53 | 54 | void ICELIB_timerStop(ICELIB_TIMER *timer) 55 | { 56 | timer->timerState = ICELIB_timerStopped; 57 | } 58 | 59 | 60 | void ICELIB_timerTick(ICELIB_TIMER *timer) 61 | { 62 | if (timer->timerState == ICELIB_timerRunning) { 63 | 64 | timer->countUpMS += timer->tickIntervalMS; 65 | 66 | if (timer->countUpMS >= timer->timeoutValueMS) { 67 | timer->timerState = ICELIB_timerTimeout; 68 | } 69 | } 70 | } 71 | 72 | 73 | bool ICELIB_timerIsRunning(const ICELIB_TIMER *timer) 74 | { 75 | return timer->timerState == ICELIB_timerRunning; 76 | } 77 | 78 | 79 | bool ICELIB_timerIsTimedOut(const ICELIB_TIMER *timer) 80 | { 81 | return timer->timerState == ICELIB_timerTimeout; 82 | } 83 | -------------------------------------------------------------------------------- /icelib/test/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = subdir-objects 2 | if CHECK 3 | 4 | TESTS = check_icelib 5 | check_PROGRAMS = check_icelib 6 | 7 | check_icelib_SOURCES = icelib_test.c icelib_running_test.c icelibtypes_test.c testmain.c ../src/icelib.c ../src/fifo.c ../src/timer.c ../src/icelibtypes.c 8 | 9 | 10 | MY_LDFLAGS_1 = -lcheck 11 | MY_CFLAGS_1 = -I../include 12 | 13 | 14 | if LOCAL_SOCKADDR 15 | MY_LDFLAGS_2 = ../../sockaddrutil/src/libsockaddrutil.la 16 | MY_CFLAGS_2 = -I../../sockaddrutil/include -I../../icelib/include 17 | endif 18 | 19 | if LOCAL_STUNLIB 20 | MY_LDFLAGS_3 = ../../stunlib/src/libstun.la 21 | MY_CFLAGS_3 = -I../../stunlib/include -I../../icelib/include 22 | endif 23 | 24 | if GCOV 25 | MY_CFLAGS_4 = -I../include -fprofile-arcs -ftest-coverage 26 | MY_LDFLAGS_4 = -lgcov 27 | endif 28 | 29 | if USE_VALGRIND 30 | TESTS_ENVIRONMENT = ../../valgrind-wrapper 31 | endif 32 | 33 | AM_CPPFLAGS = $(MY_CFLAGS_1) $(MY_CFLAGS_2) $(MY_CFLAGS_3) $(MY_CFLAGS_4) 34 | check_icelib_LDFLAGS = $(MY_LDFLAGS_1) $(MY_LDFLAGS_2) $(MY_LDFLAGS_3) $(MY_LDFLAGS_4) 35 | 36 | clean-local: 37 | rm -f *.g* 38 | 39 | 40 | endif 41 | -------------------------------------------------------------------------------- /icelib/test/icelibtypes_test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "icelibtypes.h" 5 | 6 | START_TEST( candidate_toString ) 7 | { 8 | fail_unless( 0 == strcmp(ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(ICE_CAND_TYPE_NONE), "NONE") ); 9 | fail_unless( 0 == strcmp(ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(ICE_CAND_TYPE_HOST), "HOST") ); 10 | fail_unless( 0 == strcmp(ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(ICE_CAND_TYPE_SRFLX), "SRFLX") ); 11 | fail_unless( 0 == strcmp(ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(ICE_CAND_TYPE_RELAY), "RELAY") ); 12 | fail_unless( 0 == strcmp(ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(ICE_CAND_TYPE_PRFLX), "PRFLX") ); 13 | fail_unless( 0 == strcmp(ICELIBTYPES_ICE_CANDIDATE_TYPE_toString(24), "UNKNOWN") ); 14 | 15 | } 16 | END_TEST 17 | 18 | 19 | START_TEST( iceMedia_empty ) 20 | { 21 | ICE_MEDIA iceMedia; 22 | ICELIBTYPES_ICE_MEDIA_reset(&iceMedia); 23 | 24 | 25 | fail_unless( ICELIBTYPES_ICE_MEDIA_isEmpty(&iceMedia) ); 26 | 27 | iceMedia.numberOfICEMediaLines = 2; 28 | 29 | fail_if( ICELIBTYPES_ICE_MEDIA_isEmpty(&iceMedia) ); 30 | 31 | } 32 | END_TEST 33 | 34 | START_TEST( mediastream_empty ){ 35 | ICE_MEDIA_STREAM iceMediaStream; 36 | 37 | ICELIBTYPES_ICE_MEDIA_STREAM_reset(&iceMediaStream); 38 | fail_unless( ICELIBTYPES_ICE_MEDIA_STREAM_isEmpty(&iceMediaStream) ); 39 | 40 | iceMediaStream.numberOfCandidates = 3; 41 | 42 | fail_if( ICELIBTYPES_ICE_MEDIA_STREAM_isEmpty(&iceMediaStream) ); 43 | 44 | 45 | } 46 | END_TEST 47 | 48 | Suite * icelibtypes_suite (void) 49 | { 50 | Suite *s = suite_create ("ICElibtypes"); 51 | 52 | {/* Core test case */ 53 | TCase *tc_core = tcase_create ("Core"); 54 | tcase_add_test (tc_core, candidate_toString); 55 | tcase_add_test (tc_core, iceMedia_empty ); 56 | tcase_add_test (tc_core, mediastream_empty ); 57 | suite_add_tcase (s, tc_core); 58 | } 59 | 60 | return s; 61 | } 62 | -------------------------------------------------------------------------------- /icelib/test/testmain.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | Suite * icelib_suite (void); 7 | Suite * icelib_running_suite(void); 8 | Suite * icelibtypes_suite (void); 9 | 10 | int main(void){ 11 | 12 | int number_failed; 13 | Suite *s = icelib_suite (); 14 | SRunner *sr = srunner_create (s); 15 | srunner_add_suite (sr, icelibtypes_suite ()); 16 | srunner_add_suite (sr, icelib_running_suite ()); 17 | srunner_run_all (sr, CK_NORMAL); 18 | number_failed = srunner_ntests_failed (sr); 19 | srunner_free (sr); 20 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 21 | } 22 | -------------------------------------------------------------------------------- /netfilter/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.61]) 5 | AC_INIT([stun_intercept], [0.1], [palmarti@cisco.com]) 6 | AC_CONFIG_SRCDIR([src/malicenode.cc]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | #AC_CONFIG_AUX_DIR([build-aux]) 10 | AC_CONFIG_MACRO_DIR([m4]) 11 | AM_INIT_AUTOMAKE([foreign -Wall -Werror]) 12 | #LT_INIT 13 | 14 | # Checks for programs. 15 | AC_PROG_CC 16 | AC_PROG_CXX 17 | 18 | 19 | 20 | # Checks for libraries. 21 | #AC_CHECK_LIB([ssl], [SSL_library_init], [], [AC_MSG_FAILURE([could not find ssl])]) 22 | 23 | 24 | 25 | 26 | AC_CHECK_FILE(../sockaddrutil/include/sockaddr_util.h, local_sockaddr=true, local_sockaddr=false ) 27 | AM_CONDITIONAL(LOCAL_SOCKADDR, test x"$local_sockaddr" = "xtrue") 28 | AM_COND_IF(LOCAL_SOCKADDR, 29 | [], 30 | [AC_CHECK_LIB([sockaddrutil], [sockaddr_initFromString],[], [AC_MSG_FAILURE([could not find sockaddrutil])])]) 31 | 32 | 33 | AC_CHECK_FILE(../stunlib/include/stunlib.h, local_stunlib=true, local_stunlib=false ) 34 | AM_CONDITIONAL(LOCAL_STUNLIB, test x"$local_stunlib" = "xtrue") 35 | AM_COND_IF(LOCAL_STUNLIB, 36 | [], 37 | [AC_CHECK_LIB([stun], [TurnClient_Init], [], [AC_MSG_FAILURE([could not find stunlib])])]) 38 | 39 | AC_CHECK_FILE(../icelib/include/icelib.h, local_icelib=true, local_icelib=false ) 40 | AM_CONDITIONAL(LOCAL_ICELIB, test x"$local_icelib" = "xtrue") 41 | AM_COND_IF(LOCAL_ICELIB, 42 | [], 43 | [AC_CHECK_LIB([ice], [ICELIB_Constructor], [], [AC_MSG_FAILURE([could not find icelib])])]) 44 | 45 | 46 | 47 | 48 | 49 | #AC_CHECK_LIB([stun], [TurnClient_Init], [], [AC_MSG_FAILURE([could not find stunlib])]) 50 | #AC_CHECK_LIB([ice], [ICELIB_Constructor], [], [AC_MSG_FAILURE([could not find icelib])]) 51 | 52 | 53 | AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_FAILURE([could not find pthread])]) 54 | #AC_CHECK_LIB([netfilter_queue], [nfq_open], [], [AC_MSG_FAILURE([could not find netfilter_queue])]) 55 | #AC_CHECK_LIB([nfnetlink], [nfnl_fd], [], [AC_MSG_FAILURE([could not find nfnetlink])]) 56 | 57 | 58 | 59 | 60 | # Checks for header files. 61 | AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h timer.h]) 62 | 63 | # Checks for typedefs, structures, and compiler characteristics. 64 | AC_HEADER_STDBOOL 65 | AC_TYPE_SIZE_T 66 | AC_TYPE_UINT8_T 67 | 68 | # Checks for library functions. 69 | AC_CHECK_FUNCS([memset socket]) 70 | 71 | AC_CONFIG_FILES([Makefile 72 | src/Makefile]) 73 | AC_OUTPUT 74 | -------------------------------------------------------------------------------- /netfilter/iptablessetup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Flush all rules. 4 | iptables -F 5 | 6 | # Capture every STUN-packet as identified by the magic cookie, and punt them to 7 | # NFQUEUE number 0. The string module could be used instead for more clarity, 8 | # but u32 is much faster in this case. 9 | iptables -A FORWARD -p udp --match u32 --u32 "0>>22&0x3C@12=0x2112a442" -j NFQUEUE --queue-num 0 10 | -------------------------------------------------------------------------------- /netfilter/src/malicenode.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #define UDP_HEADER_SIZE 8 16 | 17 | using namespace std; 18 | 19 | uint16_t udp_checksum(char *buff, size_t len, uint16_t *src_addr, uint16_t *dest_addr); 20 | 21 | static int Callback(nfq_q_handle *myQueue, struct nfgenmsg *msg, 22 | nfq_data *pkt, void *cbData) 23 | { 24 | uint32_t id = 0; 25 | nfqnl_msg_packet_hdr *header; 26 | if ((header = nfq_get_msg_packet_hdr(pkt))) { 27 | id = ntohl(header->packet_id); 28 | } 29 | 30 | cout << "pkt recvd: " << id << endl; 31 | 32 | char *pktData; 33 | int packet_size = nfq_get_payload(pkt, &pktData); 34 | int ip_header_size = (pktData[0] & 0xF) * 4; 35 | 36 | int udp_length = (pktData[ip_header_size + 4] << 8) + pktData[ip_header_size + 5]; 37 | int udp_payload_length = udp_length - 8; 38 | int udp_data_offset = ip_header_size + UDP_HEADER_SIZE; 39 | cout << "Offset to UDP data: " << udp_data_offset << " UDP data length: " << udp_length << endl; 40 | 41 | // Not pretty... Should really rewrite to pure c. 42 | unsigned char *payload = (unsigned char *)malloc((size_t)(udp_payload_length)); 43 | 44 | memcpy(payload, &pktData[udp_data_offset], (size_t)(udp_payload_length)); 45 | 46 | bool isMsStun; 47 | if (!stunlib_isStunMsg(payload, udp_payload_length)) { 48 | cout << "NOT a STUN packet." << endl; 49 | free(payload); 50 | return nfq_set_verdict(myQueue, id, NF_ACCEPT, 0, NULL); 51 | } 52 | cout << "Is a STUN packet." << endl; 53 | 54 | StunMessage stunPkt; 55 | 56 | if (!stunlib_DecodeMessage(payload, 57 | udp_payload_length, 58 | &stunPkt, 59 | NULL, 60 | NULL)) 61 | { 62 | cout << "Something went wrong in decoding..." << endl; 63 | free(payload); 64 | return nfq_set_verdict(myQueue, id, NF_ACCEPT, 0, NULL); 65 | } 66 | 67 | cout << "Message decoded fine." << endl; 68 | 69 | /* 70 | if ((stunPkt.msgHdr.msgType == STUN_MSG_BindRequestMsg 71 | || stunPkt.msgHdr.msgType == STUN_MSG_RefreshRequestMsg) 72 | && stunPkt.hasMaliceMetadata && stunPkt.maliceMetadata.hasMDRespUP) { 73 | if (stunPkt.maliceMetadata.mdRespUP.hasFlowdataResp) { 74 | stunPkt.maliceMetadata.mdRespUP.flowdataResp.DT = 5; 75 | stunPkt.maliceMetadata.mdRespUP.flowdataResp.LT = 5; 76 | stunPkt.maliceMetadata.mdRespUP.flowdataResp.JT = 5; 77 | stunPkt.maliceMetadata.mdRespUP.flowdataResp.minBW = 42; 78 | stunPkt.maliceMetadata.mdRespUP.flowdataResp.maxBW = 31337; 79 | cout << "Changing MD-RESP-UP to some sweet, sweet bandwith and stuff." << endl; 80 | } 81 | } else if ((stunPkt.msgHdr.msgType == STUN_MSG_BindResponseMsg 82 | || stunPkt.msgHdr.msgType == STUN_MSG_RefreshResponseMsg) 83 | && stunPkt.hasMaliceMetadata && stunPkt.maliceMetadata.hasMDRespDN) { 84 | 85 | if (stunPkt.maliceMetadata.mdRespDN.hasFlowdataResp) { 86 | stunPkt.maliceMetadata.mdRespDN.flowdataResp.DT = 1; 87 | stunPkt.maliceMetadata.mdRespDN.flowdataResp.LT = 1; 88 | stunPkt.maliceMetadata.mdRespDN.flowdataResp.JT = 1; 89 | stunPkt.maliceMetadata.mdRespDN.flowdataResp.minBW = 0; 90 | stunPkt.maliceMetadata.mdRespDN.flowdataResp.maxBW = 1814; 91 | cout << "Changing MD-RESP-DN to some crappy bandwith and stuff." << endl; 92 | } 93 | } 94 | */ 95 | 96 | static const char password[] = "VOkJxbRl1RmTxUk/WvJxBt"; 97 | int msg_len = stunlib_encodeMessage(&stunPkt, 98 | payload, 99 | udp_payload_length, 100 | (unsigned char*)password, 101 | strlen(password), 102 | NULL); 103 | 104 | cout << "Reencoded message, " << msg_len << " bytes. UDP data: " << udp_payload_length << endl; 105 | memcpy(&pktData[udp_data_offset], payload, (size_t)udp_payload_length); 106 | 107 | // UDP Checksum recalculation. 108 | memset(&pktData[ip_header_size + 6], 0x00, 2); 109 | uint16_t *ip_src = (uint16_t *) (pktData + 3 * 4), *ip_dst = (uint16_t *) (pktData + 4 * 4); 110 | uint16_t checksum = htonl(udp_checksum(&pktData[ip_header_size], udp_length, ip_src, ip_dst)); 111 | pktData[ip_header_size + 6] = (checksum >> 8) & 0xFF; 112 | pktData[ip_header_size + 7] = checksum & 0xFF; 113 | 114 | free(payload); 115 | return nfq_set_verdict(myQueue, id, NF_ACCEPT, packet_size, (unsigned char*)pktData); 116 | } 117 | 118 | int main(int argc, char **argv) 119 | { 120 | struct nfq_handle *nfqHandle; 121 | 122 | struct nfq_q_handle *myQueue; 123 | struct nfnl_handle *netlinkHandle; 124 | 125 | int fd, res; 126 | char buf[4096]; 127 | 128 | if (!(nfqHandle = nfq_open())) { 129 | perror("nfq_open"); 130 | exit(1); 131 | } 132 | 133 | if (nfq_unbind_pf(nfqHandle, AF_INET) < 0) { 134 | perror("nfq_unbind_pf"); 135 | exit(1); 136 | } 137 | 138 | if (nfq_bind_pf(nfqHandle, AF_INET) < 0) { 139 | perror("nfq_bind_pf"); 140 | exit(1); 141 | } 142 | 143 | if (!(myQueue = nfq_create_queue(nfqHandle, 0, &Callback, NULL))) { 144 | perror("nfq_create_queue"); 145 | exit(1); 146 | } 147 | 148 | if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) { 149 | perror("nfq_set_mode"); 150 | exit(1); 151 | } 152 | 153 | netlinkHandle = nfq_nfnlh(nfqHandle); 154 | fd = nfnl_fd(netlinkHandle); 155 | 156 | cout << "Up and running, waiting for packets...\n\n"; 157 | while ((res = recv(fd, buf, sizeof(buf), 0)) && res >= 0) { 158 | nfq_handle_packet(nfqHandle, buf, res); 159 | } 160 | 161 | nfq_destroy_queue(myQueue); 162 | 163 | nfq_close(nfqHandle); 164 | 165 | return 0; 166 | } 167 | 168 | uint16_t udp_checksum(char *buff, size_t len, uint16_t *ip_src, uint16_t *ip_dst) 169 | { 170 | uint16_t *buf = (uint16_t *)buff; 171 | uint32_t sum; 172 | size_t length = len; 173 | 174 | sum = 0; 175 | while (len > 1) 176 | { 177 | sum += *buf++; 178 | if (sum & 0x80000000) 179 | sum = (sum & 0xFFFF) + (sum >> 16); 180 | len -= 2; 181 | } 182 | 183 | if ( len & 1 ) 184 | sum += *((uint8_t *)buf); 185 | 186 | sum += *(ip_src++); 187 | sum += *ip_src; 188 | 189 | sum += *(ip_dst++); 190 | sum += *ip_dst; 191 | 192 | sum += htons(IPPROTO_UDP); 193 | sum += htons(length); 194 | 195 | while (sum >> 16) 196 | sum = (sum & 0xFFFF) + (sum >> 16); 197 | 198 | return (uint16_t)(~sum); 199 | } 200 | -------------------------------------------------------------------------------- /samplecode/COPYING: -------------------------------------------------------------------------------- 1 | /opt/local/share/automake-1.13/COPYING -------------------------------------------------------------------------------- /samplecode/INSTALL: -------------------------------------------------------------------------------- 1 | /opt/local/share/automake-1.13/INSTALL -------------------------------------------------------------------------------- /samplecode/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2011 Cisco. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY CISCO ``AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 21 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of Cisco. -------------------------------------------------------------------------------- /samplecode/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src . 2 | ACLOCAL_AMFLAGS = -I m4 3 | 4 | EXTRA_DIST = README LICENSE -------------------------------------------------------------------------------- /samplecode/README: -------------------------------------------------------------------------------- 1 | 2 | 3 | - Simple stunserver and client implementation - 4 | Nothing fancy. Everything is done in main to show how the stun library can be used. 5 | 6 | start the stunserver on one machine 7 | connect to it with: 8 | > stunclient [ip_addr] 9 | 10 | - Simple turnclient implementation - 11 | Connect to a turnserve with: 12 | > turnclient [ip_addr] user pass -------------------------------------------------------------------------------- /samplecode/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir m4 build-aux 3 | autoreconf --install 4 | -------------------------------------------------------------------------------- /samplecode/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.61]) 5 | AC_INIT([samplecode], [0.2], [palmarti@cisco.com]) 6 | AC_CONFIG_SRCDIR([src/stunclient.c]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | AC_CONFIG_AUX_DIR([build-aux]) 10 | AC_CONFIG_MACRO_DIR([m4]) 11 | AM_INIT_AUTOMAKE([foreign -Wall -Werror]) 12 | LT_INIT 13 | 14 | # Checks for programs. 15 | AC_PROG_CC 16 | AC_PROG_CXX 17 | 18 | 19 | 20 | # Checks for libraries. 21 | AC_CHECK_LIB([ssl], [SSL_library_init], [], [AC_MSG_FAILURE([could not find ssl])]) 22 | 23 | 24 | AC_CHECK_LIB([curses], [getch], [], [AC_MSG_FAILURE([could not find curses ( sudo apt-get install libncurses5-dev?)])]) 25 | AC_CHECK_LIB([form], [new_form], [], [AC_MSG_FAILURE([could not find form])]) 26 | AC_CHECK_LIB([panel], [new_panel], [], [AC_MSG_FAILURE([could not find panel])]) 27 | AC_CHECK_LIB([menu], [new_menu], [], [AC_MSG_FAILURE([could not find menu])]) 28 | 29 | 30 | 31 | AC_CHECK_FILE(../sockaddrutil/include/sockaddr_util.h, local_sockaddr=true, local_sockaddr=false ) 32 | AM_CONDITIONAL(LOCAL_SOCKADDR, test x"$local_sockaddr" = "xtrue") 33 | AM_COND_IF(LOCAL_SOCKADDR, 34 | [], 35 | [AC_CHECK_LIB([sockaddrutil], [sockaddr_initFromString],[], [AC_MSG_FAILURE([could not find sockaddrutil])])]) 36 | 37 | 38 | AC_CHECK_FILE(../stunlib/include/stunlib.h, local_stunlib=true, local_stunlib=false ) 39 | AM_CONDITIONAL(LOCAL_STUNLIB, test x"$local_stunlib" = "xtrue") 40 | AM_COND_IF(LOCAL_STUNLIB, 41 | [], 42 | [AC_CHECK_LIB([stun], [TurnClient_Init], [], [AC_MSG_FAILURE([could not find stunlib])])]) 43 | 44 | AC_CHECK_FILE(../icelib/include/icelib.h, local_icelib=true, local_icelib=false ) 45 | AM_CONDITIONAL(LOCAL_ICELIB, test x"$local_icelib" = "xtrue") 46 | AM_COND_IF(LOCAL_ICELIB, 47 | [], 48 | [AC_CHECK_LIB([ice], [ICELIB_Constructor], [], [AC_MSG_FAILURE([could not find icelib])])]) 49 | 50 | 51 | 52 | 53 | 54 | #AC_CHECK_LIB([stun], [TurnClient_Init], [], [AC_MSG_FAILURE([could not find stunlib])]) 55 | #AC_CHECK_LIB([ice], [ICELIB_Constructor], [], [AC_MSG_FAILURE([could not find icelib])]) 56 | 57 | 58 | 59 | #AC_CHECK_LIB([curses], [getch], [], [AC_MSG_FAILURE([could not find curses ( sudo apt-get install libncurses5-dev?)])]) 60 | #AC_CHECK_LIB([form], [new_form], [], [AC_MSG_FAILURE([could not find form])]) 61 | #AC_CHECK_LIB([panel], [new_panel], [], [AC_MSG_FAILURE([could not find panel])]) 62 | #AC_CHECK_LIB([menu], [new_menu], [], [AC_MSG_FAILURE([could not find menu])]) 63 | 64 | 65 | 66 | 67 | 68 | # Checks for header files. 69 | AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h timer.h]) 70 | 71 | # Checks for typedefs, structures, and compiler characteristics. 72 | AC_HEADER_STDBOOL 73 | AC_TYPE_SIZE_T 74 | AC_TYPE_UINT8_T 75 | 76 | # Checks for library functions. 77 | AC_CHECK_FUNCS([memset socket]) 78 | 79 | AC_CONFIG_FILES([Makefile 80 | src/Makefile]) 81 | AC_OUTPUT 82 | -------------------------------------------------------------------------------- /samplecode/src/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = stunclient stunserver turnclient simple_proxy_server testturn 2 | 3 | if LOCAL_SOCKADDR 4 | AM_CPPFLAGS_1 = -I../../sockaddrutil/include 5 | LDADD_1 = ../../sockaddrutil/src/libsockaddrutil.la 6 | endif 7 | 8 | if LOCAL_STUNLIB 9 | AM_CPPFLAGS_2 = -I../../stunlib/include 10 | LDADD_2 = ../../stunlib/src/libstun.la 11 | endif 12 | 13 | if LOCAL_ICELIB 14 | AM_CPPFLAGS_3 = -I../../icelib/include 15 | LDADD_3 = ../../icelib/src/libice.la 16 | endif 17 | 18 | AM_CPPFLAGS = -I../include $(AM_CPPFLAGS_1) $(AM_CPPFLAGS_2) $(AM_CPPFLAGS_3) 19 | 20 | stunclient_LDADD = $(LDADD_3) $(LDADD_2) $(LDADD_1) 21 | stunserver_LDADD = $(LDADD_3) $(LDADD_2) $(LDADD_1) 22 | turnclient_LDADD = $(LDADD_3) $(LDADD_2) $(LDADD_1) 23 | #iceclient_LDADD = $(LDADD_3) $(LDADD_2) $(LDADD_1) 24 | testturn_LDADD = $(LDADD_3) $(LDADD_2) $(LDADD_1) 25 | 26 | 27 | stunclient_SOURCES = stunclient.c utils.c 28 | stunserver_SOURCES = stunserver.c utils.c 29 | turnclient_SOURCES = turnclient.c utils.c 30 | #iceclient_SOURCES = iceclient.c utils.c turnhelper.c gather.c 31 | testturn_SOURCES = testturn.c gather.c turninfo.c permissions.c iphelper.c view.c gather.h iphelper.h permissions.h turninfo.h view.h 32 | 33 | simple_proxy_server_SOURCES = simple_proxy_server.c 34 | -------------------------------------------------------------------------------- /samplecode/src/gather.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | 19 | #include "turnclient.h" 20 | #include "sockaddr_util.h" 21 | 22 | 23 | #include "gather.h" 24 | 25 | 26 | 27 | 28 | 29 | TURN_INSTANCE_DATA *gather(TURN_INSTANCE_DATA *tInst, 30 | struct sockaddr *host_addr, 31 | int requestedFamily, 32 | char *user, 33 | char *pass, 34 | struct turn_allocation *turnAlloc){ 35 | 36 | int stunCtx; 37 | //TurnCallBackData_T TurnCbData; 38 | 39 | 40 | 41 | TurnClient_StartAllocateTransaction(&tInst, 42 | 50, 43 | turnInfoFunc, 44 | "IceClient", 45 | turnAlloc, // *userCtx 46 | host_addr, 47 | user, 48 | pass, 49 | requestedFamily, 50 | turnSendFunc, 51 | TurnStatusCallBack, 52 | false, 53 | 0); 54 | 55 | return tInst; 56 | } 57 | 58 | 59 | 60 | 61 | void gatherAll(struct turn_info *turnInfo, 62 | void(*update_turninfo)(void), 63 | struct listenConfig *listenConfig, 64 | void (*data_handler)(unsigned char *)) 65 | { 66 | int idx = 0; 67 | 68 | if( sockaddr_isSet((struct sockaddr *)&turnInfo->localIp4) && 69 | sockaddr_isSet((struct sockaddr *)&turnInfo->remoteIp4) ) 70 | { 71 | 72 | turnInfo->turnAlloc_44.tInst = gather(turnInfo->turnAlloc_44.tInst, 73 | (struct sockaddr *)&turnInfo->remoteIp4, 74 | AF_INET, 75 | turnInfo->user, 76 | turnInfo->pass, 77 | &turnInfo->turnAlloc_44); 78 | 79 | turnInfo->turnAlloc_44.update_turninfo = update_turninfo; 80 | listenConfig->socketConfig[idx].tInst = turnInfo->turnAlloc_44.tInst; 81 | listenConfig->socketConfig[idx].sockfd = turnInfo->turnAlloc_44.sockfd; 82 | listenConfig->socketConfig[idx].user = turnInfo->user; 83 | listenConfig->socketConfig[idx].pass = turnInfo->pass; 84 | listenConfig->socketConfig[idx].realm = turnInfo->realm; 85 | 86 | idx++; 87 | 88 | turnInfo->turnAlloc_46.tInst = gather(turnInfo->turnAlloc_46.tInst, 89 | (struct sockaddr *)&turnInfo->remoteIp4, 90 | AF_INET6, 91 | turnInfo->user, 92 | turnInfo->pass, 93 | &turnInfo->turnAlloc_46); 94 | turnInfo->turnAlloc_46.update_turninfo = update_turninfo; 95 | listenConfig->socketConfig[idx].tInst = turnInfo->turnAlloc_46.tInst; 96 | listenConfig->socketConfig[idx].sockfd = turnInfo->turnAlloc_46.sockfd; 97 | listenConfig->socketConfig[idx].user = turnInfo->user; 98 | listenConfig->socketConfig[idx].pass = turnInfo->pass; 99 | listenConfig->socketConfig[idx].realm = turnInfo->realm; 100 | 101 | 102 | idx++; 103 | 104 | } 105 | 106 | if( sockaddr_isSet((struct sockaddr *)&turnInfo->localIp6) && 107 | sockaddr_isSet((struct sockaddr *)&turnInfo->remoteIp6) ) 108 | { 109 | 110 | turnInfo->turnAlloc_64.tInst = gather(turnInfo->turnAlloc_64.tInst, 111 | (struct sockaddr *)&turnInfo->remoteIp6, 112 | AF_INET, 113 | turnInfo->user, 114 | turnInfo->pass, 115 | &turnInfo->turnAlloc_64); 116 | turnInfo->turnAlloc_64.update_turninfo = update_turninfo; 117 | listenConfig->socketConfig[idx].tInst = turnInfo->turnAlloc_64.tInst; 118 | listenConfig->socketConfig[idx].sockfd = turnInfo->turnAlloc_64.sockfd; 119 | listenConfig->socketConfig[idx].user = turnInfo->user; 120 | listenConfig->socketConfig[idx].pass = turnInfo->pass; 121 | listenConfig->socketConfig[idx].realm = turnInfo->realm; 122 | idx++; 123 | 124 | turnInfo->turnAlloc_66.tInst = gather(turnInfo->turnAlloc_66.tInst, 125 | (struct sockaddr *)&turnInfo->remoteIp6, 126 | AF_INET6, 127 | turnInfo->user, 128 | turnInfo->pass, 129 | &turnInfo->turnAlloc_66); 130 | turnInfo->turnAlloc_66.update_turninfo = update_turninfo; 131 | listenConfig->socketConfig[idx].tInst = turnInfo->turnAlloc_66.tInst; 132 | listenConfig->socketConfig[idx].sockfd = turnInfo->turnAlloc_66.sockfd; 133 | listenConfig->socketConfig[idx].user = turnInfo->user; 134 | listenConfig->socketConfig[idx].pass = turnInfo->pass; 135 | listenConfig->socketConfig[idx].realm = turnInfo->realm; 136 | idx++; 137 | } 138 | 139 | listenConfig->numSockets = idx; 140 | listenConfig->data_handler = data_handler; 141 | } 142 | 143 | 144 | 145 | void releaseAll(struct turn_info *turnInfo) 146 | { 147 | if (sockaddr_isSet((struct sockaddr *)&turnInfo->turnAlloc_44.relAddrIPv4) || 148 | sockaddr_isSet((struct sockaddr *)&turnInfo->turnAlloc_44.relAddrIPv6) 149 | ){ 150 | 151 | TurnClient_Deallocate(turnInfo->turnAlloc_44.tInst); 152 | } 153 | 154 | if (sockaddr_isSet((struct sockaddr *)&turnInfo->turnAlloc_46.relAddrIPv4) || 155 | sockaddr_isSet((struct sockaddr *)&turnInfo->turnAlloc_46.relAddrIPv6) 156 | ){ 157 | 158 | TurnClient_Deallocate(turnInfo->turnAlloc_46.tInst); 159 | } 160 | 161 | if (sockaddr_isSet((struct sockaddr *)&turnInfo->turnAlloc_64.relAddrIPv4) || 162 | sockaddr_isSet((struct sockaddr *)&turnInfo->turnAlloc_64.relAddrIPv6) 163 | ){ 164 | 165 | TurnClient_Deallocate(turnInfo->turnAlloc_64.tInst); 166 | } 167 | 168 | if (sockaddr_isSet((struct sockaddr *)&turnInfo->turnAlloc_66.relAddrIPv4) || 169 | sockaddr_isSet((struct sockaddr *)&turnInfo->turnAlloc_66.relAddrIPv6) 170 | ){ 171 | 172 | TurnClient_Deallocate(turnInfo->turnAlloc_66.tInst); 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /samplecode/src/gather.h: -------------------------------------------------------------------------------- 1 | #ifndef GATHER_H 2 | #define GATHER_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | 13 | #include 14 | 15 | #include "turninfo.h" 16 | #include "iphelper.h" 17 | #include "view.h" 18 | 19 | 20 | 21 | 22 | TURN_INSTANCE_DATA *gather(TURN_INSTANCE_DATA *tInst, 23 | struct sockaddr *host_addr, 24 | int requestedFamily, 25 | char *user, 26 | char *pass, 27 | struct turn_allocation *turnAlloc); 28 | 29 | void gatherAll(struct turn_info *turnInfo, 30 | void(*update_turninfo)(void), 31 | struct listenConfig *listenConfig, 32 | void (*data_handler)(unsigned char *)); 33 | 34 | void releaseAll(struct turn_info *turnInfo); 35 | 36 | 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /samplecode/src/ice.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | #include 11 | 12 | #include "iphelper.h" 13 | #include "gather.h" 14 | 15 | 16 | static struct turn_info turnInfo; 17 | static struct listenConfig listenConfig; 18 | static pthread_t turnListenThread; 19 | 20 | 21 | 22 | ICELIB_Result sendConnectivityCheck( void *pUserData, 23 | const struct sockaddr *destination, 24 | const struct sockaddr *source, 25 | uint32_t userValue1, 26 | uint32_t userValue2, 27 | uint32_t componentId, 28 | bool useRelay, 29 | const char *pUfrag, 30 | const char *pPasswd, 31 | uint32_t peerPriority, 32 | bool useCandidate, 33 | bool iceControlling, 34 | bool iceControlled, 35 | uint64_t tieBreaker, 36 | StunMsgId transactionId) 37 | { 38 | 39 | } 40 | 41 | 42 | ICELIB_Result sendConnectivityCheckResponse(void *pUserData, 43 | uint32_t userValue1, 44 | uint32_t userValue2, 45 | uint32_t componentId, 46 | const struct sockaddr *source, 47 | const struct sockaddr *destination, 48 | const struct sockaddr *MappedAddress, 49 | uint16_t errorResponse, 50 | StunMsgId transactionId, 51 | bool useRelay, 52 | const char *pUfrag, 53 | const char *pPasswd) 54 | { 55 | 56 | } 57 | 58 | 59 | ICELIB_Result connectivityChecksComplete(void *pUserData, 60 | uint32_t userValue1, 61 | bool isControlling, 62 | bool iceFailed) 63 | { 64 | 65 | } 66 | 67 | 68 | ICELIB_Result cancelBindRequest( void *pUserData, 69 | uint32_t userValue1, 70 | StunMsgId transactionId) 71 | { 72 | 73 | 74 | } 75 | 76 | ICELIB_Result icePasswordUpdate( void *pUserData, 77 | uint32_t userValue1, 78 | uint32_t userValue2, 79 | char * password) 80 | { 81 | 82 | } 83 | 84 | 85 | ICELIB_Result iceKeepAlive( void *pUserData, 86 | uint32_t userValue1, 87 | uint32_t userValue2, 88 | uint32_t mediaIdx) 89 | { 90 | 91 | } 92 | 93 | 94 | void ice_messageCB(char *message) 95 | { 96 | 97 | } 98 | 99 | 100 | 101 | int main(int argc, char *argv[]) 102 | { 103 | ICELIB_INSTANCE iceLib; 104 | 105 | ICELIB_CONFIGURATION iceConfig; 106 | 107 | int choice = 0; 108 | int c; 109 | 110 | pthread_t turnTickThread; 111 | 112 | 113 | if (argc != 5) { 114 | fprintf(stderr,"usage: testice iface turnserver user pass\n"); 115 | exit(1); 116 | } 117 | 118 | //Our local struct where we store stuff 119 | initTurnInfo(&turnInfo); 120 | addCredentials(&turnInfo, argv[2], argv[3], argv[4]); 121 | 122 | listenConfig.update_inc_status = ice_messageCB; 123 | 124 | getRemoteTurnServerIp(&turnInfo, argv[2]); 125 | 126 | getLocalIPaddresses(&turnInfo, SOCK_DGRAM, argv[1]); 127 | 128 | //Turn setup 129 | //TurnClient_Init(TEST_THREAD_CTX, 50, 50, NULL, false, "TestIce"); 130 | //pthread_create( &turnTickThread, NULL, tickTurn, (void*) &TEST_THREAD_CTX); 131 | 132 | 133 | 134 | 135 | iceConfig.tickIntervalMS = 20; 136 | iceConfig.keepAliveIntervalS = 15; 137 | iceConfig.maxCheckListPairs = ICELIB_MAX_PAIRS; 138 | iceConfig.aggressiveNomination = false; 139 | iceConfig.iceLite = false; 140 | 141 | 142 | ICELIB_Constructor(&iceLib, 143 | &iceConfig); 144 | 145 | 146 | ICELIB_setCallbackOutgoingBindingRequest(&iceLib, 147 | sendConnectivityCheck, 148 | NULL); 149 | 150 | ICELIB_setCallbackOutgoingBindingResponse(&iceLib, 151 | sendConnectivityCheckResponse, 152 | NULL); 153 | 154 | ICELIB_setCallbackConnecitivityChecksComplete(&iceLib, 155 | connectivityChecksComplete, 156 | NULL); 157 | 158 | ICELIB_setCallbackOutgoingCancelRequest(&iceLib, 159 | cancelBindRequest, 160 | NULL); 161 | 162 | ICELIB_setCallbackPasswordUpdate(&iceLib, 163 | icePasswordUpdate, 164 | NULL); 165 | 166 | ICELIB_setCallbackKeepAlive(&iceLib, 167 | iceKeepAlive, 168 | NULL); 169 | 170 | 171 | 172 | 173 | ICELIB_addLocalMediaStream(&iceLib, 174 | 0,/*media idx*/ 175 | 1,/*userValue1*/ 176 | 1,/*userValue2*/ 177 | ICE_CAND_TYPE_HOST ); 178 | 179 | 180 | } 181 | 182 | -------------------------------------------------------------------------------- /samplecode/src/iceclient: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # iceclient - temporary wrapper script for .libs/iceclient 4 | # Generated by libtool (GNU libtool) 2.4.2 5 | # 6 | # The iceclient program cannot be directly executed until all the libtool 7 | # libraries that it depends on are installed. 8 | # 9 | # This wrapper script should never be moved out of the build directory. 10 | # If it is, it will not operate correctly. 11 | 12 | # Sed substitution that helps us do robust quoting. It backslashifies 13 | # metacharacters that are still active within double-quoted strings. 14 | sed_quote_subst='s/\([`"$\\]\)/\\\1/g' 15 | 16 | # Be Bourne compatible 17 | if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then 18 | emulate sh 19 | NULLCMD=: 20 | # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which 21 | # is contrary to our usage. Disable this feature. 22 | alias -g '${1+"$@"}'='"$@"' 23 | setopt NO_GLOB_SUBST 24 | else 25 | case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac 26 | fi 27 | BIN_SH=xpg4; export BIN_SH # for Tru64 28 | DUALCASE=1; export DUALCASE # for MKS sh 29 | 30 | # The HP-UX ksh and POSIX shell print the target directory to stdout 31 | # if CDPATH is set. 32 | (unset CDPATH) >/dev/null 2>&1 && unset CDPATH 33 | 34 | relink_command="" 35 | 36 | # This environment variable determines our operation mode. 37 | if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then 38 | # install mode needs the following variables: 39 | generated_by_libtool_version='2.4.2' 40 | notinst_deplibs=' ../../icelib/src/libice.la ../../stunlib/src/libstun.la ../../sockaddrutil/src/libsockaddrutil.la' 41 | else 42 | # When we are sourced in execute mode, $file and $ECHO are already set. 43 | if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then 44 | file="$0" 45 | 46 | # A function that is used when there is no print builtin or printf. 47 | func_fallback_echo () 48 | { 49 | eval 'cat <<_LTECHO_EOF 50 | $1 51 | _LTECHO_EOF' 52 | } 53 | ECHO="printf %s\\n" 54 | fi 55 | 56 | # Very basic option parsing. These options are (a) specific to 57 | # the libtool wrapper, (b) are identical between the wrapper 58 | # /script/ and the wrapper /executable/ which is used only on 59 | # windows platforms, and (c) all begin with the string --lt- 60 | # (application programs are unlikely to have options which match 61 | # this pattern). 62 | # 63 | # There are only two supported options: --lt-debug and 64 | # --lt-dump-script. There is, deliberately, no --lt-help. 65 | # 66 | # The first argument to this parsing function should be the 67 | # script's ../libtool value, followed by no. 68 | lt_option_debug= 69 | func_parse_lt_options () 70 | { 71 | lt_script_arg0=$0 72 | shift 73 | for lt_opt 74 | do 75 | case "$lt_opt" in 76 | --lt-debug) lt_option_debug=1 ;; 77 | --lt-dump-script) 78 | lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` 79 | test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. 80 | lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` 81 | cat "$lt_dump_D/$lt_dump_F" 82 | exit 0 83 | ;; 84 | --lt-*) 85 | $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 86 | exit 1 87 | ;; 88 | esac 89 | done 90 | 91 | # Print the debug banner immediately: 92 | if test -n "$lt_option_debug"; then 93 | echo "iceclient:iceclient:${LINENO}: libtool wrapper (GNU libtool) 2.4.2" 1>&2 94 | fi 95 | } 96 | 97 | # Used when --lt-debug. Prints its arguments to stdout 98 | # (redirection is the responsibility of the caller) 99 | func_lt_dump_args () 100 | { 101 | lt_dump_args_N=1; 102 | for lt_arg 103 | do 104 | $ECHO "iceclient:iceclient:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" 105 | lt_dump_args_N=`expr $lt_dump_args_N + 1` 106 | done 107 | } 108 | 109 | # Core function for launching the target application 110 | func_exec_program_core () 111 | { 112 | 113 | if test -n "$lt_option_debug"; then 114 | $ECHO "iceclient:iceclient:${LINENO}: newargv[0]: $progdir/$program" 1>&2 115 | func_lt_dump_args ${1+"$@"} 1>&2 116 | fi 117 | exec "$progdir/$program" ${1+"$@"} 118 | 119 | $ECHO "$0: cannot exec $program $*" 1>&2 120 | exit 1 121 | } 122 | 123 | # A function to encapsulate launching the target application 124 | # Strips options in the --lt-* namespace from $@ and 125 | # launches target application with the remaining arguments. 126 | func_exec_program () 127 | { 128 | case " $* " in 129 | *\ --lt-*) 130 | for lt_wr_arg 131 | do 132 | case $lt_wr_arg in 133 | --lt-*) ;; 134 | *) set x "$@" "$lt_wr_arg"; shift;; 135 | esac 136 | shift 137 | done ;; 138 | esac 139 | func_exec_program_core ${1+"$@"} 140 | } 141 | 142 | # Parse options 143 | func_parse_lt_options "$0" ${1+"$@"} 144 | 145 | # Find the directory that this script lives in. 146 | thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` 147 | test "x$thisdir" = "x$file" && thisdir=. 148 | 149 | # Follow symbolic links until we get to the real thisdir. 150 | file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` 151 | while test -n "$file"; do 152 | destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` 153 | 154 | # If there was a directory component, then change thisdir. 155 | if test "x$destdir" != "x$file"; then 156 | case "$destdir" in 157 | [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; 158 | *) thisdir="$thisdir/$destdir" ;; 159 | esac 160 | fi 161 | 162 | file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` 163 | file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` 164 | done 165 | 166 | # Usually 'no', except on cygwin/mingw when embedded into 167 | # the cwrapper. 168 | WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no 169 | if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then 170 | # special case for '.' 171 | if test "$thisdir" = "."; then 172 | thisdir=`pwd` 173 | fi 174 | # remove .libs from thisdir 175 | case "$thisdir" in 176 | *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; 177 | .libs ) thisdir=. ;; 178 | esac 179 | fi 180 | 181 | # Try to get the absolute directory name. 182 | absdir=`cd "$thisdir" && pwd` 183 | test -n "$absdir" && thisdir="$absdir" 184 | 185 | program='iceclient' 186 | progdir="$thisdir/.libs" 187 | 188 | 189 | if test -f "$progdir/$program"; then 190 | # Add our own library path to DYLD_LIBRARY_PATH 191 | DYLD_LIBRARY_PATH="/Users/palmarti/development/NATTools/icelib/src/.libs:/Users/palmarti/development/NATTools/stunlib/src/.libs:/Users/palmarti/development/NATTools/sockaddrutil/src/.libs:$DYLD_LIBRARY_PATH" 192 | 193 | # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH 194 | # The second colon is a workaround for a bug in BeOS R4 sed 195 | DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` 196 | 197 | export DYLD_LIBRARY_PATH 198 | 199 | if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then 200 | # Run the actual program with our arguments. 201 | func_exec_program ${1+"$@"} 202 | fi 203 | else 204 | # The program doesn't exist. 205 | $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 206 | $ECHO "This script is just a wrapper for $program." 1>&2 207 | $ECHO "See the libtool documentation for more information." 1>&2 208 | exit 1 209 | fi 210 | fi 211 | -------------------------------------------------------------------------------- /samplecode/src/iceclient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | #include 15 | #include "utils.h" 16 | #include "turnhelper.h" 17 | 18 | 19 | #define PORT "9034" // the port client will be connecting to 20 | 21 | #define MAXDATASIZE 300 22 | 23 | // get sockaddr, IPv4 or IPv6: 24 | void *get_in_addr(struct sockaddr *sa) 25 | { 26 | if (sa->sa_family == AF_INET) { 27 | return &(((struct sockaddr_in*)sa)->sin_addr); 28 | } 29 | 30 | return &(((struct sockaddr_in6*)sa)->sin6_addr); 31 | } 32 | 33 | 34 | void *proxy_handler(void *socketfd) 35 | { 36 | //Get the socket descriptor 37 | int sock = *(int*)socketfd; 38 | int read_size; 39 | char *message , client_message[2000]; 40 | 41 | //Receive a message from client 42 | while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 ) 43 | { 44 | printf("got: %s\n", client_message); 45 | 46 | 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | 53 | int connectProxy(const char * host){ 54 | int sockfd, numbytes, *new_sock; 55 | char buf[MAXDATASIZE]; 56 | struct addrinfo hints, *servinfo, *p; 57 | int rv; 58 | char s[INET6_ADDRSTRLEN]; 59 | 60 | 61 | memset(&hints, 0, sizeof hints); 62 | hints.ai_family = AF_UNSPEC; 63 | hints.ai_socktype = SOCK_STREAM; 64 | 65 | if ((rv = getaddrinfo(host, PORT, &hints, &servinfo)) != 0) { 66 | fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 67 | return 1; 68 | } 69 | 70 | // loop through all the results and connect to the first we can 71 | for(p = servinfo; p != NULL; p = p->ai_next) { 72 | if ((sockfd = socket(p->ai_family, p->ai_socktype, 73 | p->ai_protocol)) == -1) { 74 | perror("client: socket"); 75 | continue; 76 | } 77 | 78 | if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { 79 | close(sockfd); 80 | perror("client: connect"); 81 | continue; 82 | } 83 | 84 | break; 85 | } 86 | 87 | if (p == NULL) { 88 | fprintf(stderr, "client: failed to connect\n"); 89 | return 2; 90 | } 91 | 92 | inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), 93 | s, sizeof s); 94 | printf("client: connecting to %s\n", s); 95 | 96 | freeaddrinfo(servinfo); // all done with this structure 97 | 98 | 99 | pthread_t proxy_listen_thread; 100 | new_sock = malloc(1); 101 | *new_sock = sockfd; 102 | 103 | if( pthread_create( &proxy_listen_thread , NULL , proxy_handler , (void*) new_sock) < 0) 104 | { 105 | perror("could not create thread"); 106 | return 1; 107 | } 108 | return sockfd; 109 | 110 | } 111 | 112 | int closeProxy(int sockfd) 113 | { 114 | close(sockfd); 115 | 116 | return sockfd; 117 | } 118 | 119 | int sendOffer(int sockfd, char *offer, int offerLen ) 120 | { 121 | //sendsomething 122 | if (send(sockfd, offer, offerLen, 0) == -1) 123 | perror("send"); 124 | 125 | return 0; 126 | } 127 | 128 | 129 | 130 | int createOffer(char *offer, struct turnData *tData){ 131 | char addr[SOCKADDR_MAX_STRLEN]; 132 | 133 | strcpy(offer, "INVITE\n"); 134 | strcat(offer, "a=candidate UDP srflx "); 135 | strcat(offer, 136 | sockaddr_toString((struct sockaddr *)&tData->rflx, 137 | addr, 138 | sizeof(addr), 139 | true)); 140 | strcat(offer, "\n"); 141 | 142 | strcat(offer, "a=candidate UDP relay "); 143 | strcat(offer, 144 | sockaddr_toString((struct sockaddr *)&tData->relay, 145 | addr, 146 | sizeof(addr), 147 | true)); 148 | strcat(offer, "\n"); 149 | 150 | strcat(offer, "\0"); 151 | 152 | 153 | return strlen(offer); 154 | 155 | } 156 | 157 | 158 | 159 | int main(int argc, char *argv[]) 160 | { 161 | struct timespec timer; 162 | struct timespec remaining; 163 | 164 | int proxy_fd, media_fd; 165 | char c; 166 | char offer[500]; 167 | int offerLen; 168 | struct turnData tData; 169 | 170 | 171 | if (argc != 5) { 172 | fprintf(stderr,"usage: iceclient registrar turnserver user pass\n"); 173 | exit(1); 174 | } 175 | 176 | proxy_fd = connectProxy(argv[1]); 177 | 178 | tData.turn_uri = argv[2]; 179 | tData.turn_port = "3478"; 180 | tData.user = argv[3]; 181 | tData.password = argv[4]; 182 | 183 | 184 | while(1){ 185 | printf( "Press c (enter) to call (Or wait for a incomming call) :"); 186 | c = getchar( ); 187 | 188 | if(c == 'c'){ 189 | printf("Calling..."); 190 | gatherCandidates(&tData); 191 | while(tData.turn_state!=SUCCESS){ 192 | timer.tv_sec = 0; 193 | timer.tv_nsec = 50000000; 194 | nanosleep(&timer, &remaining); 195 | } 196 | 197 | printf("Got it..."); 198 | offerLen = createOffer(offer, &tData); 199 | 200 | sendOffer(proxy_fd, offer, offerLen); 201 | } 202 | if(c == 'e'){ 203 | closeProxy(proxy_fd); 204 | exit(0); 205 | } 206 | 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /samplecode/src/iphelper.h: -------------------------------------------------------------------------------- 1 | #ifndef IPADDRESS_HELPER_H 2 | #define IPADDRESS_HELPER_H 3 | 4 | #include 5 | 6 | #include "turninfo.h" 7 | 8 | 9 | 10 | #define MAX_LISTEN_SOCKETS 10 11 | 12 | 13 | typedef int (*STUN_HANDLER)(int, int); 14 | 15 | struct socketConfig{ 16 | TURN_INSTANCE_DATA *tInst; 17 | int sockfd; 18 | char* user; 19 | char* pass; 20 | char* realm; 21 | }; 22 | 23 | 24 | struct listenConfig{ 25 | struct socketConfig socketConfig[MAX_LISTEN_SOCKETS]; 26 | int numSockets; 27 | void (*data_handler)(unsigned char *); 28 | }; 29 | 30 | 31 | typedef enum IPv6_ADDR_TYPES {IPv6_ADDR_NONE, IPv6_ADDR_ULA, IPv6_ADDR_PRIVACY, IPv6_ADDR_NORMAL} IPv6_ADDR_TYPE; 32 | 33 | 34 | int getRemoteTurnServerIp(struct turn_info *turnInfo, char *fqdn); 35 | 36 | int getLocalIPaddresses(struct turn_info *turnInfo, int type, char *iface); 37 | 38 | bool getLocalInterFaceAddrs(struct sockaddr *addr, char *iface, int ai_family, IPv6_ADDR_TYPE ipv6_addr_type, bool force_privacy); 39 | 40 | int createLocalTCPSocket(int ai_family, 41 | struct turn_info *turnInfo, 42 | uint16_t port); 43 | 44 | int createLocalUDPSocket(int ai_family, 45 | const struct sockaddr * localIp, 46 | struct sockaddr *hostaddr, 47 | uint16_t port); 48 | 49 | int sendMessage(struct turn_info *turnInfo, char *dstAddr, char *message); 50 | 51 | int sendRawUDP(int sockfd, 52 | const void *buf, 53 | size_t len, 54 | const struct sockaddr * p, 55 | socklen_t t); 56 | 57 | int SendRawStun(int sockfd, 58 | const uint8_t *buf, 59 | int len, 60 | const struct sockaddr *addr, 61 | socklen_t t, 62 | void *userdata); 63 | 64 | void turnSendFunc(const uint8_t *buffer, 65 | size_t bufLen, 66 | const struct sockaddr *dstAddr, 67 | void *userCtx); 68 | 69 | void *stunListen(void *ptr); 70 | 71 | 72 | int sendKeepalive(struct turn_info *turnInfo); 73 | 74 | void TurnStatusCallBack(void *ctx, TurnCallBackData_T *retData); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /samplecode/src/permissions.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "permissions.h" 4 | 5 | static const uint32_t PERMISSIONS_THREAD_CTX = 1; 6 | 7 | void sendPermissionsAll(struct turn_info *turnInfo) 8 | { 9 | int i; 10 | const struct sockaddr *perm[MAX_PERMISSIONS]; 11 | 12 | if(turnInfo->turnAlloc_44.turnPerm.numPermissions > 0){ 13 | for (i=0;iturnAlloc_44.turnPerm.numPermissions;i++){ 14 | perm[i] = (struct sockaddr *)&turnInfo->turnAlloc_44.turnPerm.permissions[i]; 15 | } 16 | turnInfo->turnAlloc_44.turnPerm.ok = false; 17 | 18 | TurnClient_StartCreatePermissionReq(turnInfo->turnAlloc_44.tInst, 19 | turnInfo->turnAlloc_44.turnPerm.numPermissions, 20 | perm); 21 | 22 | } 23 | 24 | 25 | if(turnInfo->turnAlloc_46.turnPerm.numPermissions > 0){ 26 | for (i=0;iturnAlloc_46.turnPerm.numPermissions;i++){ 27 | perm[i] = (struct sockaddr *)&turnInfo->turnAlloc_46.turnPerm.permissions[i]; 28 | } 29 | 30 | 31 | turnInfo->turnAlloc_46.turnPerm.ok = false; 32 | TurnClient_StartCreatePermissionReq(turnInfo->turnAlloc_46.tInst, 33 | turnInfo->turnAlloc_46.turnPerm.numPermissions, 34 | perm); 35 | 36 | } 37 | 38 | if(turnInfo->turnAlloc_64.turnPerm.numPermissions > 0){ 39 | 40 | for (i=0;iturnAlloc_64.turnPerm.numPermissions;i++){ 41 | perm[i] = (struct sockaddr *)&turnInfo->turnAlloc_64.turnPerm.permissions[i]; 42 | } 43 | turnInfo->turnAlloc_64.turnPerm.ok = false; 44 | TurnClient_StartCreatePermissionReq(turnInfo->turnAlloc_64.tInst, 45 | turnInfo->turnAlloc_64.turnPerm.numPermissions, 46 | perm); 47 | 48 | } 49 | 50 | if(turnInfo->turnAlloc_66.turnPerm.numPermissions > 0){ 51 | 52 | for (i=0;iturnAlloc_66.turnPerm.numPermissions;i++){ 53 | perm[i] = (struct sockaddr *)&turnInfo->turnAlloc_66.turnPerm.permissions[i]; 54 | } 55 | 56 | turnInfo->turnAlloc_66.turnPerm.ok = false; 57 | TurnClient_StartCreatePermissionReq(turnInfo->turnAlloc_66.tInst, 58 | turnInfo->turnAlloc_66.turnPerm.numPermissions, 59 | perm); 60 | 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /samplecode/src/permissions.h: -------------------------------------------------------------------------------- 1 | #ifndef PERMISSIONS_H 2 | #define PERMISSIONS_H 3 | 4 | #include "turninfo.h" 5 | 6 | void sendPermissionsAll(struct turn_info *turnInfo) ; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /samplecode/src/pumpturn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "iphelper.h" 9 | #include "gather.h" 10 | 11 | 12 | static int keep_ticks; //Used to determine if it is time to send keepalives 13 | static void *tickTurn(void *ptr); 14 | 15 | void messageCB(char *message); 16 | void print_turnInfo(); 17 | 18 | static struct turn_info turnInfo; 19 | static struct listenConfig listenConfig; 20 | static pthread_t turnListenThread; 21 | 22 | 23 | static char rcv_message[100]; 24 | 25 | pthread_mutex_t turnInfo_mutex = PTHREAD_MUTEX_INITIALIZER; 26 | 27 | 28 | static int socket_type; 29 | 30 | int main(int argc, char *argv[]) 31 | { 32 | pthread_t turnTickThread; 33 | 34 | 35 | if (argc != 6) { 36 | fprintf(stderr,"usage: pumpturn iface [TCP|UDP] turnserver user pass\n"); 37 | exit(1); 38 | } 39 | 40 | if( strcmp(argv[2], "UDP") == 0 ){ 41 | socket_type = SOCK_DGRAM; 42 | }else{ 43 | socket_type = SOCK_STREAM; 44 | } 45 | 46 | 47 | //Our local struct where we store stuff 48 | initTurnInfo(&turnInfo); 49 | addCredentials(&turnInfo, argv[3], argv[4], argv[5]); 50 | 51 | listenConfig.update_inc_status = messageCB; 52 | 53 | getRemoteTurnServerIp(&turnInfo, argv[3]); 54 | 55 | 56 | getLocalIPaddresses(&turnInfo, socket_type, argv[1]); 57 | 58 | //Turn setup 59 | TurnClient_Init(TEST_THREAD_CTX, 50, 50, NULL, false, "PumpTurn"); 60 | pthread_create( &turnTickThread, NULL, tickTurn, (void*) &TEST_THREAD_CTX); 61 | 62 | 63 | printf("Gather!!!\n"); 64 | gatherAll(&turnInfo, &listenConfig, &print_turnInfo); 65 | pthread_create( &turnListenThread, NULL, stunListen, (void*)&listenConfig); 66 | 67 | printf("Her er jeg\n"); 68 | while(1) 69 | { 70 | getch(); 71 | } 72 | return 0; 73 | } 74 | 75 | 76 | void messageCB(char *message) 77 | { 78 | int n = sizeof(rcv_message); 79 | strncpy(rcv_message, message, n); 80 | if (n > 0) 81 | rcv_message[n - 1]= '\0'; 82 | 83 | fprintf(stdout,"%s", rcv_message); 84 | 85 | } 86 | 87 | void print_turnInfo(){ 88 | char addr[SOCKADDR_MAX_STRLEN]; 89 | pthread_mutex_lock( &turnInfo_mutex ); 90 | fprintf(stdout, "RELAY addr: '%s'\n", 91 | sockaddr_toString((struct sockaddr *)&turnInfo.turnAlloc_44.relAddr, 92 | addr, 93 | sizeof(addr), 94 | true)); 95 | pthread_mutex_unlock( &turnInfo_mutex ); 96 | } 97 | 98 | 99 | 100 | 101 | static void *tickTurn(void *ptr){ 102 | struct timespec timer; 103 | struct timespec remaining; 104 | uint32_t *ctx = (uint32_t *)ptr; 105 | 106 | timer.tv_sec = 0; 107 | timer.tv_nsec = 50000000; 108 | 109 | 110 | for(;;){ 111 | keep_ticks++; 112 | nanosleep(&timer, &remaining); 113 | TurnClient_HandleTick(*ctx); 114 | 115 | if(keep_ticks>100){ 116 | sendKeepalive(&turnInfo); 117 | keep_ticks = 0; 118 | } 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /samplecode/src/simple_proxy_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define PORT "9034" // port we're listening on 12 | 13 | // get sockaddr, IPv4 or IPv6: 14 | void *get_in_addr(struct sockaddr *sa) 15 | { 16 | if (sa->sa_family == AF_INET) { 17 | return &(((struct sockaddr_in*)sa)->sin_addr); 18 | } 19 | 20 | return &(((struct sockaddr_in6*)sa)->sin6_addr); 21 | } 22 | 23 | int main(void) 24 | { 25 | fd_set master; // master file descriptor list 26 | fd_set read_fds; // temp file descriptor list for select() 27 | int fdmax; // maximum file descriptor number 28 | 29 | int listener; // listening socket descriptor 30 | int newfd; // newly accept()ed socket descriptor 31 | struct sockaddr_storage remoteaddr; // client address 32 | socklen_t addrlen; 33 | 34 | char buf[256]; // buffer for client data 35 | int nbytes; 36 | 37 | char remoteIP[INET6_ADDRSTRLEN]; 38 | 39 | int yes=1; // for setsockopt() SO_REUSEADDR, below 40 | int i, j, rv; 41 | 42 | struct addrinfo hints, *ai, *p; 43 | 44 | FD_ZERO(&master); // clear the master and temp sets 45 | FD_ZERO(&read_fds); 46 | 47 | // get us a socket and bind it 48 | memset(&hints, 0, sizeof hints); 49 | hints.ai_family = AF_UNSPEC; 50 | hints.ai_socktype = SOCK_STREAM; 51 | hints.ai_flags = AI_PASSIVE; 52 | if ((rv = getaddrinfo(NULL, PORT, &hints, &ai)) != 0) { 53 | fprintf(stderr, "selectserver: %s\n", gai_strerror(rv)); 54 | exit(1); 55 | } 56 | 57 | for(p = ai; p != NULL; p = p->ai_next) { 58 | listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); 59 | if (listener < 0) { 60 | continue; 61 | } 62 | 63 | // lose the pesky "address already in use" error message 64 | setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); 65 | 66 | if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) { 67 | close(listener); 68 | continue; 69 | } 70 | 71 | break; 72 | } 73 | 74 | // if we got here, it means we didn't get bound 75 | if (p == NULL) { 76 | fprintf(stderr, "selectserver: failed to bind\n"); 77 | exit(2); 78 | } 79 | 80 | freeaddrinfo(ai); // all done with this 81 | 82 | // listen 83 | if (listen(listener, 10) == -1) { 84 | perror("listen"); 85 | exit(3); 86 | } 87 | 88 | // add the listener to the master set 89 | FD_SET(listener, &master); 90 | 91 | // keep track of the biggest file descriptor 92 | fdmax = listener; // so far, it's this one 93 | 94 | // main loop 95 | for(;;) { 96 | read_fds = master; // copy it 97 | if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) { 98 | perror("select"); 99 | exit(4); 100 | } 101 | 102 | // run through the existing connections looking for data to read 103 | for(i = 0; i <= fdmax; i++) { 104 | if (FD_ISSET(i, &read_fds)) { // we got one!! 105 | if (i == listener) { 106 | // handle new connections 107 | addrlen = sizeof remoteaddr; 108 | newfd = accept(listener, 109 | (struct sockaddr *)&remoteaddr, 110 | &addrlen); 111 | 112 | if (newfd == -1) { 113 | perror("accept"); 114 | } else { 115 | FD_SET(newfd, &master); // add to master set 116 | if (newfd > fdmax) { // keep track of the max 117 | fdmax = newfd; 118 | } 119 | printf("selectserver: new connection from %s on " 120 | "socket %d\n", 121 | inet_ntop(remoteaddr.ss_family, 122 | get_in_addr((struct sockaddr*)&remoteaddr), 123 | remoteIP, INET6_ADDRSTRLEN), 124 | newfd); 125 | } 126 | } else { 127 | // handle data from a client 128 | if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) { 129 | // got error or connection closed by client 130 | if (nbytes == 0) { 131 | // connection closed 132 | printf("selectserver: socket %d hung up\n", i); 133 | } else { 134 | perror("recv"); 135 | } 136 | close(i); // bye! 137 | FD_CLR(i, &master); // remove from master set 138 | } else { 139 | // we got some data from a client 140 | for(j = 0; j <= fdmax; j++) { 141 | // send to everyone! 142 | if (FD_ISSET(j, &master)) { 143 | // except the listener and ourselves 144 | if (j != listener && j != i) { 145 | if (send(j, buf, nbytes, 0) == -1) { 146 | perror("send"); 147 | } 148 | } 149 | } 150 | } 151 | } 152 | } // END handle data from client 153 | } // END got new incoming connection 154 | } // END looping through file descriptors 155 | } // END for(;;)--and you thought it would never end! 156 | 157 | return 0; 158 | } 159 | -------------------------------------------------------------------------------- /samplecode/src/stunclient.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** stunclient.c A simple STUN demo 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include "utils.h" 23 | 24 | 25 | #define SERVERPORT "4950" // the port users will be connecting to 26 | #define USERNAME "evtj:h6vY" 27 | #define PASSWORD "VOkJxbRl1RmTxUk/WvJxBt" 28 | 29 | #define MAXBUFLEN 500 30 | 31 | int sockfd; 32 | 33 | 34 | void StunStatusCallBack(void *userCtx, StunCallBackData_T *stunCbData) 35 | { 36 | //ctx points to whatever you initialized the library with. (Not used in this simple example.) 37 | if(stunCbData->stunResult == StunResult_BindOk) 38 | { 39 | char addr[SOCKADDR_MAX_STRLEN]; 40 | printf(" RFLX addr: '%s'\n", 41 | sockaddr_toString((struct sockaddr *)&stunCbData->rflxAddr, 42 | addr, 43 | sizeof(addr), 44 | true)); 45 | printf(" SRC addr: '%s'\n", 46 | sockaddr_toString((struct sockaddr *)&stunCbData->srcAddr, 47 | addr, 48 | sizeof(addr), 49 | true)); 50 | printf(" DstBase addr: '%s'\n", 51 | sockaddr_toString((struct sockaddr *)&stunCbData->dstBaseAddr, 52 | addr, 53 | sizeof(addr), 54 | true)); 55 | } 56 | else 57 | printf(" StunResult returned not OK\n"); 58 | 59 | } 60 | 61 | 62 | static void *tickStun(STUN_CLIENT_DATA *clientData) 63 | { 64 | struct timespec timer; 65 | struct timespec remaining; 66 | 67 | timer.tv_sec = 0; 68 | timer.tv_nsec = 50000000; 69 | 70 | for(;;) { 71 | nanosleep(&timer, &remaining); 72 | StunClient_HandleTick(clientData, 50); 73 | } 74 | } 75 | 76 | 77 | void teardown() 78 | { 79 | close(sockfd); 80 | printf("Quitting...\n"); 81 | exit(0); 82 | } 83 | 84 | 85 | int main(int argc, char *argv[]) 86 | { 87 | struct addrinfo *servinfo, *p; 88 | int numbytes; 89 | pthread_t stunTickThread; 90 | 91 | StunMessage stunResponse; 92 | 93 | struct sockaddr_storage their_addr; 94 | struct sockaddr my_addr; 95 | socklen_t addrLen = sizeof(my_addr); 96 | 97 | unsigned char buf[MAXBUFLEN]; 98 | 99 | const uint32_t priority = 1845494271; 100 | const uint64_t tieBreaker = 0x932FF9B151263B36LL; 101 | StunMsgId stunMsgId; 102 | char msgId[] = "\xb7\xe7\xa7\x01" 103 | "\xbc\x34\xd6\x86" 104 | "\xfa\x87\xdf\xae"; 105 | 106 | STUN_CLIENT_DATA *clientData; 107 | 108 | char addrStr[SOCKADDR_MAX_STRLEN]; 109 | 110 | DiscussData discussData; 111 | 112 | memcpy(stunMsgId.octet, msgId, sizeof(stunMsgId.octet)); 113 | 114 | if (argc != 2) { 115 | fprintf(stderr,"usage: stunclient hostname\n"); 116 | exit(1); 117 | } 118 | 119 | sockfd = createSocket(argv[1], SERVERPORT, 0, servinfo, &p); 120 | signal(SIGINT, teardown); 121 | 122 | //freeaddrinfo(servinfo); 123 | 124 | StunClient_Alloc(&clientData); 125 | 126 | pthread_create(&stunTickThread, NULL, (void *)tickStun, clientData); 127 | 128 | if (getsockname(sockfd, &my_addr, &addrLen) == -1) { 129 | perror("getsockname"); 130 | } 131 | 132 | discussData.streamType=0x004; 133 | discussData.interactivity=0x01; 134 | 135 | discussData.networkStatus_flags = 0; 136 | discussData.networkStatus_nodeCnt = 0; 137 | discussData.networkStatus_tbd = 0; 138 | discussData.networkStatus_upMaxBandwidth = 0; 139 | discussData.networkStatus_downMaxBandwidth = 0; 140 | 141 | StunClient_startBindTransaction(clientData, 142 | NULL, 143 | p->ai_addr, 144 | &my_addr, 145 | false, 146 | USERNAME, 147 | PASSWORD, 148 | priority, 149 | false, 150 | false, 151 | tieBreaker, 152 | stunMsgId, 153 | sockfd, 154 | sendRawStun, 155 | StunStatusCallBack, 156 | &discussData); 157 | 158 | while(1) 159 | { 160 | if((numbytes = recvStunMsg(sockfd, &their_addr, &stunResponse, buf, MAXBUFLEN-1)) != -1) { 161 | if( stunlib_checkIntegrity(buf, 162 | numbytes, 163 | &stunResponse, 164 | (unsigned char*)PASSWORD, 165 | sizeof(PASSWORD)) ) { 166 | printf("Integrity Check OK\n"); 167 | 168 | StunClient_HandleIncResp(clientData, &stunResponse, p->ai_addr); 169 | 170 | printDiscuss(stunResponse); 171 | 172 | break; 173 | } 174 | } 175 | } 176 | 177 | teardown(); 178 | } 179 | 180 | 181 | -------------------------------------------------------------------------------- /samplecode/src/stunserver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include "utils.h" 18 | 19 | #define MYPORT "3478" // the port users will be connecting to 20 | #define PASSWORD "VOkJxbRl1RmTxUk/WvJxBt" 21 | #define MAXBUFLEN 500 22 | 23 | int sockfd; 24 | 25 | 26 | void teardown() 27 | { 28 | close(sockfd); 29 | printf("Quitting...\n"); 30 | exit(0); 31 | } 32 | 33 | int main(void) 34 | { 35 | struct addrinfo *servinfo, *p; 36 | int numbytes; 37 | struct sockaddr_storage their_addr; 38 | unsigned char buf[MAXBUFLEN]; 39 | 40 | StunMessage stunRequest; 41 | STUN_INCOMING_REQ_DATA pReq; 42 | 43 | STUN_CLIENT_DATA *clientData; 44 | 45 | StunClient_Alloc(&clientData); 46 | 47 | signal(SIGINT, teardown); 48 | 49 | sockfd = createSocket(NULL, MYPORT, AI_PASSIVE, servinfo, &p); 50 | 51 | //freeaddrinfo(servinfo); 52 | 53 | while(1) { 54 | printf("stunserver: waiting to recvfrom...\n"); 55 | if((numbytes = recvStunMsg(sockfd, &their_addr, &stunRequest, buf, MAXBUFLEN-1)) != -1) { 56 | printf("Got bytes: %i\n", numbytes); 57 | if(stunlib_checkIntegrity(buf, numbytes, &stunRequest, (unsigned char*)PASSWORD, sizeof(PASSWORD)) ) { 58 | printf(" Integrity OK\n"); 59 | 60 | DiscussData discussData; 61 | 62 | discussData.streamType=0x004; 63 | discussData.interactivity=0x01; 64 | 65 | discussData.networkStatus_flags = 0; 66 | discussData.networkStatus_nodeCnt = 0; 67 | discussData.networkStatus_tbd = 0; 68 | discussData.networkStatus_upMaxBandwidth = 0; 69 | discussData.networkStatus_downMaxBandwidth = 0; 70 | 71 | if (stunRequest.hasNetworkStatus){ 72 | discussData.networkStatusResp_flags = stunRequest.networkStatus.flags; 73 | discussData.networkStatusResp_nodeCnt = stunRequest.networkStatus.nodeCnt; 74 | discussData.networkStatusResp_tbd = 0; 75 | discussData.networkStatusResp_upMaxBandwidth = stunRequest.networkStatus.upMaxBandwidth; 76 | discussData.networkStatusResp_downMaxBandwidth = stunRequest.networkStatus.downMaxBandwidth; 77 | } 78 | 79 | 80 | printDiscuss(stunRequest); 81 | 82 | 83 | 84 | StunServer_HandleStunIncomingBindReqMsg(clientData, 85 | &pReq, 86 | &stunRequest, 87 | false); 88 | 89 | StunServer_SendConnectivityBindingResp(clientData, 90 | sockfd, 91 | stunRequest.msgHdr.id, 92 | PASSWORD, 93 | (struct sockaddr *)&their_addr, 94 | (struct sockaddr *)&their_addr, 95 | NULL, 96 | sendRawStun, 97 | false, 98 | 200, 99 | &discussData); 100 | 101 | 102 | printf("Sending response\n\n"); 103 | } 104 | else{ 105 | printf("Integrity Failed\n"); 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /samplecode/src/testturn: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # testturn - temporary wrapper script for .libs/testturn 4 | # Generated by libtool (GNU libtool) 2.4.2 5 | # 6 | # The testturn program cannot be directly executed until all the libtool 7 | # libraries that it depends on are installed. 8 | # 9 | # This wrapper script should never be moved out of the build directory. 10 | # If it is, it will not operate correctly. 11 | 12 | # Sed substitution that helps us do robust quoting. It backslashifies 13 | # metacharacters that are still active within double-quoted strings. 14 | sed_quote_subst='s/\([`"$\\]\)/\\\1/g' 15 | 16 | # Be Bourne compatible 17 | if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then 18 | emulate sh 19 | NULLCMD=: 20 | # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which 21 | # is contrary to our usage. Disable this feature. 22 | alias -g '${1+"$@"}'='"$@"' 23 | setopt NO_GLOB_SUBST 24 | else 25 | case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac 26 | fi 27 | BIN_SH=xpg4; export BIN_SH # for Tru64 28 | DUALCASE=1; export DUALCASE # for MKS sh 29 | 30 | # The HP-UX ksh and POSIX shell print the target directory to stdout 31 | # if CDPATH is set. 32 | (unset CDPATH) >/dev/null 2>&1 && unset CDPATH 33 | 34 | relink_command="" 35 | 36 | # This environment variable determines our operation mode. 37 | if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then 38 | # install mode needs the following variables: 39 | generated_by_libtool_version='2.4.2' 40 | notinst_deplibs=' ../../icelib/src/libice.la ../../stunlib/src/libstun.la ../../sockaddrutil/src/libsockaddrutil.la' 41 | else 42 | # When we are sourced in execute mode, $file and $ECHO are already set. 43 | if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then 44 | file="$0" 45 | 46 | # A function that is used when there is no print builtin or printf. 47 | func_fallback_echo () 48 | { 49 | eval 'cat <<_LTECHO_EOF 50 | $1 51 | _LTECHO_EOF' 52 | } 53 | ECHO="printf %s\\n" 54 | fi 55 | 56 | # Very basic option parsing. These options are (a) specific to 57 | # the libtool wrapper, (b) are identical between the wrapper 58 | # /script/ and the wrapper /executable/ which is used only on 59 | # windows platforms, and (c) all begin with the string --lt- 60 | # (application programs are unlikely to have options which match 61 | # this pattern). 62 | # 63 | # There are only two supported options: --lt-debug and 64 | # --lt-dump-script. There is, deliberately, no --lt-help. 65 | # 66 | # The first argument to this parsing function should be the 67 | # script's ../libtool value, followed by no. 68 | lt_option_debug= 69 | func_parse_lt_options () 70 | { 71 | lt_script_arg0=$0 72 | shift 73 | for lt_opt 74 | do 75 | case "$lt_opt" in 76 | --lt-debug) lt_option_debug=1 ;; 77 | --lt-dump-script) 78 | lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` 79 | test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. 80 | lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` 81 | cat "$lt_dump_D/$lt_dump_F" 82 | exit 0 83 | ;; 84 | --lt-*) 85 | $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 86 | exit 1 87 | ;; 88 | esac 89 | done 90 | 91 | # Print the debug banner immediately: 92 | if test -n "$lt_option_debug"; then 93 | echo "testturn:testturn:${LINENO}: libtool wrapper (GNU libtool) 2.4.2" 1>&2 94 | fi 95 | } 96 | 97 | # Used when --lt-debug. Prints its arguments to stdout 98 | # (redirection is the responsibility of the caller) 99 | func_lt_dump_args () 100 | { 101 | lt_dump_args_N=1; 102 | for lt_arg 103 | do 104 | $ECHO "testturn:testturn:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" 105 | lt_dump_args_N=`expr $lt_dump_args_N + 1` 106 | done 107 | } 108 | 109 | # Core function for launching the target application 110 | func_exec_program_core () 111 | { 112 | 113 | if test -n "$lt_option_debug"; then 114 | $ECHO "testturn:testturn:${LINENO}: newargv[0]: $progdir/$program" 1>&2 115 | func_lt_dump_args ${1+"$@"} 1>&2 116 | fi 117 | exec "$progdir/$program" ${1+"$@"} 118 | 119 | $ECHO "$0: cannot exec $program $*" 1>&2 120 | exit 1 121 | } 122 | 123 | # A function to encapsulate launching the target application 124 | # Strips options in the --lt-* namespace from $@ and 125 | # launches target application with the remaining arguments. 126 | func_exec_program () 127 | { 128 | case " $* " in 129 | *\ --lt-*) 130 | for lt_wr_arg 131 | do 132 | case $lt_wr_arg in 133 | --lt-*) ;; 134 | *) set x "$@" "$lt_wr_arg"; shift;; 135 | esac 136 | shift 137 | done ;; 138 | esac 139 | func_exec_program_core ${1+"$@"} 140 | } 141 | 142 | # Parse options 143 | func_parse_lt_options "$0" ${1+"$@"} 144 | 145 | # Find the directory that this script lives in. 146 | thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` 147 | test "x$thisdir" = "x$file" && thisdir=. 148 | 149 | # Follow symbolic links until we get to the real thisdir. 150 | file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` 151 | while test -n "$file"; do 152 | destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` 153 | 154 | # If there was a directory component, then change thisdir. 155 | if test "x$destdir" != "x$file"; then 156 | case "$destdir" in 157 | [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; 158 | *) thisdir="$thisdir/$destdir" ;; 159 | esac 160 | fi 161 | 162 | file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` 163 | file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` 164 | done 165 | 166 | # Usually 'no', except on cygwin/mingw when embedded into 167 | # the cwrapper. 168 | WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no 169 | if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then 170 | # special case for '.' 171 | if test "$thisdir" = "."; then 172 | thisdir=`pwd` 173 | fi 174 | # remove .libs from thisdir 175 | case "$thisdir" in 176 | *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; 177 | .libs ) thisdir=. ;; 178 | esac 179 | fi 180 | 181 | # Try to get the absolute directory name. 182 | absdir=`cd "$thisdir" && pwd` 183 | test -n "$absdir" && thisdir="$absdir" 184 | 185 | program='testturn' 186 | progdir="$thisdir/.libs" 187 | 188 | 189 | if test -f "$progdir/$program"; then 190 | # Add our own library path to DYLD_LIBRARY_PATH 191 | DYLD_LIBRARY_PATH="/Users/palmarti/development/NATTools/icelib/src/.libs:/Users/palmarti/development/NATTools/stunlib/src/.libs:/Users/palmarti/development/NATTools/sockaddrutil/src/.libs:$DYLD_LIBRARY_PATH" 192 | 193 | # Some systems cannot cope with colon-terminated DYLD_LIBRARY_PATH 194 | # The second colon is a workaround for a bug in BeOS R4 sed 195 | DYLD_LIBRARY_PATH=`$ECHO "$DYLD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` 196 | 197 | export DYLD_LIBRARY_PATH 198 | 199 | if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then 200 | # Run the actual program with our arguments. 201 | func_exec_program ${1+"$@"} 202 | fi 203 | else 204 | # The program doesn't exist. 205 | $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 206 | $ECHO "This script is just a wrapper for $program." 1>&2 207 | $ECHO "See the libtool documentation for more information." 1>&2 208 | exit 1 209 | fi 210 | fi 211 | -------------------------------------------------------------------------------- /samplecode/src/testturn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "iphelper.h" 10 | #include "gather.h" 11 | #include "permissions.h" 12 | 13 | 14 | 15 | static int keep_ticks; //Used to determine if it is time to send keepalives 16 | static void *tickTurn(void *ptr); 17 | 18 | static struct turn_info turnInfo; 19 | static struct listenConfig listenConfig; 20 | static pthread_t turnListenThread; 21 | static pthread_t turnTickThread; 22 | 23 | static char permission_ip[1000]; 24 | static char message[100]; 25 | static char rcv_message[1000]; 26 | static char message_dst[50]; 27 | static int highlight = 1; 28 | 29 | 30 | pthread_mutex_t turnInfo_mutex = PTHREAD_MUTEX_INITIALIZER; 31 | 32 | void update_turnInfo(){ 33 | pthread_mutex_lock( &turnInfo_mutex ); 34 | print_status(status_win, &turnInfo); 35 | pthread_mutex_unlock( &turnInfo_mutex ); 36 | print_menu(menu_win, highlight); 37 | print_input(input_win); 38 | } 39 | 40 | 41 | void init_view(); 42 | void cleanup(); 43 | void doChoice(int choice); 44 | void messageCB(unsigned char *message); 45 | 46 | 47 | static void *tickTurn(void *ptr){ 48 | struct timespec timer; 49 | struct timespec remaining; 50 | uint32_t *ctx = (uint32_t *)ptr; 51 | struct turn_info *tInfo = (struct turn_info*)ptr; 52 | 53 | 54 | timer.tv_sec = 0; 55 | timer.tv_nsec = 50000000; 56 | 57 | for(;;){ 58 | 59 | nanosleep(&timer, &remaining); 60 | 61 | if(tInfo->turnAlloc_44.tInst != NULL){ 62 | TurnClient_HandleTick(tInfo->turnAlloc_44.tInst); 63 | } 64 | if(tInfo->turnAlloc_46.tInst != NULL){ 65 | TurnClient_HandleTick(tInfo->turnAlloc_46.tInst); 66 | } 67 | if(tInfo->turnAlloc_64.tInst != NULL){ 68 | TurnClient_HandleTick(tInfo->turnAlloc_64.tInst); 69 | } 70 | if(tInfo->turnAlloc_66.tInst != NULL){ 71 | TurnClient_HandleTick(tInfo->turnAlloc_66.tInst); 72 | } 73 | } 74 | 75 | } 76 | 77 | int main(int argc, char *argv[]) 78 | { 79 | 80 | int choice = 0; 81 | int c; 82 | 83 | //setbuf(stdout, NULL); 84 | 85 | 86 | if (argc != 5) { 87 | fprintf(stderr,"usage: testturn iface turnserver user pass\n"); 88 | exit(1); 89 | } 90 | 91 | //Our local struct where we store stuff 92 | initTurnInfo(&turnInfo); 93 | addCredentials(&turnInfo, argv[2], argv[3], argv[4]); 94 | 95 | getRemoteTurnServerIp(&turnInfo, argv[2]); 96 | 97 | //Getting privacy adresses. Set to false if not. 98 | getLocalIPaddresses(&turnInfo, SOCK_DGRAM, argv[1]); 99 | 100 | //for(;;){ sleep(2); } 101 | //Ncurses view 102 | 103 | init_view(); 104 | print_status(status_win, &turnInfo); 105 | 106 | 107 | while(1) 108 | { c = wgetch(menu_win); 109 | switch(c) 110 | { case KEY_LEFT: 111 | if(highlight == 1) 112 | highlight = n_choices; 113 | else 114 | --highlight; 115 | break; 116 | case KEY_RIGHT: 117 | if(highlight == n_choices) 118 | highlight = 1; 119 | else 120 | ++highlight; 121 | break; 122 | case 10: 123 | choice = highlight; 124 | break; 125 | default: 126 | refresh(); 127 | break; 128 | } 129 | print_menu(menu_win, highlight); 130 | print_input(input_win); 131 | if(choice != 0){ // User did a choice come out of the infinite loop 132 | doChoice(choice); 133 | } 134 | choice = 0; 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | 141 | 142 | 143 | 144 | void init_view() 145 | { 146 | int max_x, max_y; 147 | int start_menu_x = 0; 148 | int start_menu_y = 0; 149 | 150 | int start_input_x = 0; 151 | int start_input_y = 0; 152 | 153 | int start_message_x = 0; 154 | int start_message_y = 0; 155 | 156 | 157 | 158 | 159 | initscr(); 160 | start_color(); 161 | clear(); 162 | noecho(); 163 | cbreak(); /* Line buffering disabled. pass on everything */ 164 | 165 | getmaxyx(stdscr,max_y,max_x); 166 | 167 | start_menu_x = 0; 168 | start_menu_y = max_y - HEIGHT; 169 | menu_win = newwin(HEIGHT, max_x, start_menu_y, start_menu_x); 170 | keypad(menu_win, TRUE); 171 | 172 | 173 | start_input_x = 0; 174 | start_input_y = start_menu_y - 3; 175 | input_win = newwin(3, max_x, start_input_y, start_input_x); 176 | 177 | start_message_x = 0; 178 | start_message_y = start_input_y - 3; 179 | message_win = newwin(3, max_x, start_message_y, start_message_x); 180 | 181 | 182 | 183 | status_win = newwin(start_message_y-1, max_x, 0, 0); 184 | 185 | print_menu(menu_win, 1); 186 | print_input(input_win); 187 | print_message(message_win, " "); 188 | } 189 | 190 | 191 | void cleanup(){ 192 | clrtoeol(); 193 | refresh(); 194 | endwin(); 195 | 196 | close(turnInfo.turnAlloc_44.sockfd); 197 | close(turnInfo.turnAlloc_46.sockfd); 198 | close(turnInfo.turnAlloc_64.sockfd); 199 | close(turnInfo.turnAlloc_66.sockfd); 200 | system("reset"); 201 | } 202 | 203 | 204 | void doChoice(int choice) 205 | { 206 | switch(choice){ 207 | case 1: 208 | gatherAll(&turnInfo, &update_turnInfo, &listenConfig, &messageCB); 209 | pthread_create( &turnTickThread, NULL, tickTurn, (void*) &turnInfo); 210 | pthread_create( &turnListenThread, NULL, stunListen, (void*)&listenConfig); 211 | break; 212 | 213 | case 2: 214 | permission_ip[0]='\0'; 215 | 216 | //mvwprintw(input_win,1, 1, "Enter Ip adresses (enter for rflx): "); 217 | //wrefresh(input_win); 218 | //echo(); 219 | //wgetstr(input_win, permission_ip); 220 | //noecho(); 221 | fillRflxPermissions(&turnInfo); 222 | sendPermissionsAll(&turnInfo); 223 | print_status(status_win, &turnInfo); 224 | break; 225 | case 3: 226 | mvwprintw(input_win,1, 1, "Enter Message: "); 227 | wrefresh(input_win); 228 | echo(); 229 | wgetstr(input_win, message); 230 | mvwprintw(input_win,1, 1, "Enter Ip: "); 231 | wrefresh(input_win); 232 | wgetstr(input_win, message_dst); 233 | noecho(); 234 | sendMessage(&turnInfo, message_dst, message); 235 | break; 236 | case 4: 237 | releaseAll(&turnInfo); 238 | break; 239 | case 5: 240 | releaseAll(&turnInfo); 241 | cleanup(); 242 | exit(0); 243 | break; 244 | } 245 | } 246 | 247 | void messageCB(unsigned char *message) 248 | { 249 | int n = sizeof(rcv_message); 250 | memcpy(rcv_message, message, n); 251 | if (n > 0) 252 | rcv_message[n - 1]= '\0'; 253 | 254 | print_message(message_win, rcv_message); 255 | 256 | } 257 | -------------------------------------------------------------------------------- /samplecode/src/turnclient.c: -------------------------------------------------------------------------------- 1 | /* 2 | * turnclient.c -- a simple turnclient demo 3 | * 4 | * This is not a socket tutorial or a complete turnclient implementation. 5 | * Its main purpose is to show how to initialize the STUNlib to use TURN 6 | * and allocate a RELAY address on a turn server. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include "utils.h" 26 | 27 | #define SERVERPORT "3478" // the port users will be connecting to 28 | #define MAXBUFLEN 500 29 | 30 | TURN_INSTANCE_DATA *instData; 31 | 32 | int sockfd; 33 | char realm[STUN_MAX_STRING]; 34 | 35 | static void turnInfoFunc(void *userCtx, TurnInfoCategory_T category, char *ErrStr) { 36 | printf("TurnInfoCB"); 37 | printf("%s\n", ErrStr); 38 | } 39 | 40 | static void turnSendFunc(const uint8_t *buffer, 41 | size_t bufLen, 42 | const struct sockaddr *dstAddr, 43 | void *userCtx) 44 | { 45 | printf("Sending CB \n"); 46 | sendRawStun(sockfd, buffer, bufLen, dstAddr, false); 47 | } 48 | 49 | void turnCbFunc(void *userCtx, TurnCallBackData_T *turnCbData) 50 | { 51 | //ctx points to whatever you initialized the library with. (Not used in this simple example.) 52 | 53 | if ( turnCbData->turnResult == TurnResult_AllocOk ){ 54 | char addr[SOCKADDR_MAX_STRLEN]; 55 | 56 | printf("Successfull Allocation: \n"); 57 | 58 | printf(" Active TURN server: '%s'\n", 59 | sockaddr_toString((struct sockaddr *)&turnCbData->TurnResultData.AllocResp.activeTurnServerAddr, 60 | addr, 61 | sizeof(addr), 62 | true)); 63 | 64 | printf(" RFLX addr: '%s'\n", 65 | sockaddr_toString((struct sockaddr *)&turnCbData->TurnResultData.AllocResp.srflxAddr, 66 | addr, 67 | sizeof(addr), 68 | true)); 69 | 70 | printf(" RELAY addr: '%s'\n", 71 | sockaddr_toString((struct sockaddr *)&turnCbData->TurnResultData.AllocResp.relAddrIPv4, 72 | addr, 73 | sizeof(addr), 74 | true)); 75 | 76 | 77 | printf(" RELAY addr: '%s'\n", 78 | sockaddr_toString((struct sockaddr *)&turnCbData->TurnResultData.AllocResp.relAddrIPv6, 79 | addr, 80 | sizeof(addr), 81 | true)); 82 | 83 | } else if (turnCbData->turnResult == TurnResult_AllocUnauthorised) { 84 | printf("Unable to authorize. Wrong user/pass?\n"); 85 | } 86 | } 87 | 88 | 89 | static void *tickTurn( void *ptr) 90 | { 91 | struct timespec timer; 92 | struct timespec remaining; 93 | TURN_INSTANCE_DATA *instData = (TURN_INSTANCE_DATA *)ptr; 94 | timer.tv_sec = 0; 95 | timer.tv_nsec = 50000000; 96 | 97 | for(;;) { 98 | nanosleep(&timer, &remaining); 99 | TurnClient_HandleTick(instData); 100 | } 101 | 102 | } 103 | 104 | 105 | void listenAndHandleResponse(char *user, char *password) 106 | { 107 | int numbytes; 108 | struct sockaddr_storage their_addr; 109 | unsigned char buf[MAXBUFLEN]; 110 | StunMessage stunResponse; 111 | int keyLen = 16; 112 | char md5[keyLen]; 113 | if((numbytes = recvStunMsg(sockfd, &their_addr, &stunResponse, buf, MAXBUFLEN-1)) != -1) { 114 | if (stunResponse.msgHdr.msgType == STUN_MSG_DataIndicationMsg) { 115 | if (stunResponse.hasData) { 116 | //Decode and do something with the data? 117 | } 118 | } 119 | 120 | if (stunResponse.hasRealm) { 121 | memcpy(realm, stunResponse.realm.value, STUN_MAX_STRING); 122 | } 123 | 124 | if (stunResponse.hasMessageIntegrity) { 125 | printf(" Integrity attribute present.\n"); 126 | stunlib_createMD5Key((unsigned char *)md5, user, realm, password); 127 | 128 | if (stunlib_checkIntegrity(buf, numbytes, &stunResponse,(unsigned char *)md5, keyLen)) { 129 | printf(" - Integrity check OK\n"); 130 | } else { 131 | printf(" - Integrity check NOT OK\n"); 132 | } 133 | } 134 | printf(" Sending Response to TURN library\n"); 135 | TurnClient_HandleIncResp(instData, 136 | &stunResponse, 137 | buf); 138 | printf(" Response sent...(And hopefully handled)\n"); 139 | } 140 | 141 | } 142 | 143 | 144 | void handleInt() 145 | { 146 | printf("\nDeallocating...\n"); 147 | TurnClient_Deallocate(instData); 148 | // If one wants to avoid the server getting a destination unreachable ICMP message, 149 | // handle the response before quitting. 150 | // listenAndHandleResponse(); 151 | close(sockfd); 152 | printf("Quitting...\n"); 153 | exit(0); 154 | } 155 | 156 | 157 | int main(int argc, char *argv[]) 158 | { 159 | struct addrinfo *servinfo, *p; 160 | 161 | signal(SIGINT, handleInt); 162 | 163 | pthread_t turnTickThread; 164 | TurnCallBackData_T TurnCbData; 165 | 166 | sockfd = createSocket(argv[1], SERVERPORT, 0, servinfo, &p); 167 | if(sockfd == -1) { 168 | return 1; 169 | } else if(sockfd == -2) { 170 | return 2; 171 | } 172 | 173 | TurnClient_StartAllocateTransaction(&instData, 174 | 50, 175 | turnInfoFunc, 176 | "turnCLient", 177 | NULL, // *userCtx 178 | p->ai_addr, 179 | argv[2], 180 | argv[3], 181 | (AF_INET + AF_INET6), 182 | turnSendFunc, 183 | turnCbFunc, 184 | false, 185 | 0); 186 | 187 | pthread_create(&turnTickThread, NULL, &tickTurn, instData); 188 | 189 | //freeaddrinfo(servinfo); 190 | 191 | while (1) { 192 | //We listen on the socket for any response and feed it back to the library. 193 | //In a real world example this would happen in a listen thread.. 194 | 195 | listenAndHandleResponse(argv[2], argv[3]); 196 | } 197 | } 198 | 199 | 200 | -------------------------------------------------------------------------------- /samplecode/src/turnhelper.h: -------------------------------------------------------------------------------- 1 | #ifndef TURNHELPER_H 2 | #define TURNHELPER_H 3 | 4 | #include 5 | 6 | typedef enum {IDLE, RUNNING, SUCCESS, ERROR} state_t; 7 | 8 | struct turnData{ 9 | 10 | int sockfd; 11 | char *turn_uri; 12 | char *turn_port; 13 | char *user; 14 | char *password; 15 | 16 | 17 | 18 | state_t turn_state; 19 | struct sockaddr_storage active_turn_server; 20 | struct sockaddr_storage rflx; 21 | struct sockaddr_storage relay; 22 | TURN_INSTANCE_DATA *instData; 23 | 24 | }; 25 | 26 | 27 | struct mediaStream{ 28 | struct sockaddr_storage localIPv4; 29 | struct sockaddr_storage localIPv6; 30 | struct turnData *tData_44; 31 | struct turnData *tData_46; 32 | struct turnData *tData_64; 33 | struct turnData *tData_66; 34 | }; 35 | 36 | 37 | void turnCbFunc(void *userCtx, TurnCallBackData_T *turnCbData); 38 | 39 | static void *handleTurnResponse(void *ptr); 40 | 41 | int gatherCandidates(struct turnData *tData); 42 | 43 | static void turnSendFunc(const uint8_t *buffer, 44 | size_t bufLen, 45 | const struct sockaddr *dstAddr, 46 | void *userCtx); 47 | 48 | 49 | static void *tickTurn( void *ptr); 50 | 51 | 52 | static void turnInfoFunc(void *userCtx, TurnInfoCategory_T category, char *ErrStr); 53 | 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /samplecode/src/turninfo.h: -------------------------------------------------------------------------------- 1 | #ifndef TURNINFO_H 2 | #define TURNINFO_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum turn_ip_type{ 9 | turn_44 = 1, 10 | turn_46 = 2, 11 | turn_64 = 4, 12 | turn_66 = 8, 13 | }; 14 | 15 | #define FQDN_MAX_LEN 1024 16 | #define MAX_PERMISSIONS 10 17 | 18 | struct turn_permissions{ 19 | 20 | int numPermissions; 21 | struct sockaddr_storage permissions[MAX_PERMISSIONS]; 22 | bool ok; 23 | }; 24 | 25 | 26 | 27 | 28 | struct turn_allocation{ 29 | TURN_INSTANCE_DATA *tInst; 30 | int sockfd; 31 | struct sockaddr_storage activeTurnServerAddr; 32 | struct sockaddr_storage hostAddr; 33 | struct sockaddr_storage rflxAddr; 34 | struct sockaddr_storage relAddrIPv4; 35 | struct sockaddr_storage relAddrIPv6; 36 | struct turn_permissions turnPerm; 37 | 38 | void (*update_turninfo)(void); 39 | }; 40 | 41 | struct turn_info{ 42 | //Fully Qualified Domain Name 43 | char fqdn[FQDN_MAX_LEN]; 44 | 45 | char user[STUN_MSG_MAX_USERNAME_LENGTH]; 46 | char pass[STUN_MSG_MAX_PASSWORD_LENGTH]; 47 | char realm[STUN_MAX_STRING]; 48 | //TURN server IP adresses (As resolved by the FQDN) 49 | struct sockaddr_storage remoteIp4; 50 | struct sockaddr_storage remoteIp6; 51 | 52 | //Local IP adresses 53 | struct sockaddr_storage localIp4; 54 | struct sockaddr_storage localIp6; 55 | struct sockaddr_storage localIp6_ula; 56 | 57 | 58 | //Socket stuff 59 | //int numSockets; 60 | 61 | struct turn_allocation turnAlloc_44; 62 | struct turn_allocation turnAlloc_46; 63 | struct turn_allocation turnAlloc_64; 64 | struct turn_allocation turnAlloc_66; 65 | 66 | }; 67 | 68 | void initTurnInfo(struct turn_info *turnInfo); 69 | 70 | void addCredentials(struct turn_info *turnInfod, char *fqdn, char *user, char *pass); 71 | 72 | void printAllocationResult(struct turn_allocation *result); 73 | void printTurnInfo( struct turn_info *turnInfo ); 74 | //void wprintTurnInfow( WINDOW *win, struct turn_info *turnInfo ); 75 | 76 | void fillPermissions(struct turn_info *turnInfo, char *string); 77 | void fillRflxPermissions(struct turn_info *turnInfo); 78 | 79 | void turnInfoFunc(void *userCtx, TurnInfoCategory_T category, char *ErrStr); 80 | 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /samplecode/src/utils.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "utils.h" 4 | 5 | int createSocket(char host[], char port[], int ai_flags, struct addrinfo *servinfo, struct addrinfo **p) 6 | { 7 | struct addrinfo hints; 8 | int rv, sockfd; 9 | memset(&hints, 0, sizeof hints); 10 | hints.ai_family = AF_INET; 11 | hints.ai_socktype = SOCK_DGRAM; 12 | hints.ai_flags = ai_flags; // use my IP if not 0 13 | 14 | if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) { 15 | fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 16 | return -1; 17 | } 18 | 19 | // loop through all the results and bind to the first we can 20 | for((*p) = servinfo; (*p) != NULL; (*p) = (*p)->ai_next) { 21 | if ((sockfd = socket((*p)->ai_family, (*p)->ai_socktype, 22 | (*p)->ai_protocol)) == -1) { 23 | perror("socket"); 24 | continue; 25 | } 26 | 27 | if (ai_flags != 0 && bind(sockfd, (*p)->ai_addr, (*p)->ai_addrlen) == -1) { 28 | close(sockfd); 29 | perror("bind"); 30 | continue; 31 | } 32 | 33 | break; 34 | } 35 | 36 | if ((*p) == NULL) { 37 | fprintf(stderr, "failed to bind socket\n"); 38 | return -2; 39 | } 40 | 41 | return sockfd; 42 | } 43 | 44 | 45 | void sendRawStun(int sockHandle, 46 | const uint8_t *buf, 47 | int bufLen, 48 | const struct sockaddr *dstAddr, 49 | bool useRelay) 50 | { 51 | int tos = 0x28; 52 | int numbytes; 53 | char addrStr[SOCKADDR_MAX_STRLEN]; 54 | 55 | 56 | setsockopt(sockHandle, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); 57 | 58 | if ((numbytes = sendto(sockHandle, buf, bufLen, 0, dstAddr, sizeof(*dstAddr))) == -1) { 59 | perror("sendto"); 60 | exit(1); 61 | } 62 | 63 | sockaddr_toString(dstAddr, addrStr, SOCKADDR_MAX_STRLEN, true); 64 | //printf("Sending Raw (To: '%s'(%i), Bytes:%i/%i )\n", addrStr, sockHandle, numbytes, bufLen); 65 | 66 | //return numbytes; 67 | } 68 | 69 | int recvStunMsg(int sockfd, struct sockaddr_storage *their_addr, StunMessage *stunResponse, unsigned char *buf, int buflen) 70 | { 71 | socklen_t addr_len = sizeof their_addr; 72 | int numbytes; 73 | 74 | if ((numbytes = recvfrom(sockfd, buf, buflen , 0, (struct sockaddr *)their_addr, &addr_len)) == -1) { 75 | perror("recvfrom"); 76 | exit(1); 77 | } 78 | 79 | //printf("Got a packet that is %d bytes long\n", numbytes); 80 | if (stunlib_isStunMsg(buf, numbytes)) { 81 | //printf(" Packet is STUN\n"); 82 | 83 | stunlib_DecodeMessage(buf, numbytes, stunResponse, NULL, NULL); 84 | 85 | return numbytes; 86 | } 87 | 88 | return -1; 89 | } 90 | 91 | 92 | 93 | 94 | void printDiscuss(StunMessage stunRequest) 95 | { 96 | if (stunRequest.hasStreamType) 97 | { 98 | printf(" StreamType \n"); 99 | printf(" Type: %#06x \n", stunRequest.streamType.type); 100 | printf(" Interactivity: %#04x \n", stunRequest.streamType.interactivity); 101 | 102 | } 103 | 104 | if (stunRequest.hasNetworkStatus){ 105 | printf(" NetworkStatus \n"); 106 | printf(" Flags: %#04x \n", stunRequest.networkStatus.flags); 107 | printf(" NodeCnt: %i \n", stunRequest.networkStatus.nodeCnt); 108 | printf(" UpMax: %i \n", stunRequest.networkStatus.upMaxBandwidth); 109 | printf(" DownMax: %i \n", stunRequest.networkStatus.downMaxBandwidth); 110 | } 111 | } 112 | 113 | -------------------------------------------------------------------------------- /samplecode/src/utils.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef UTILS_H 3 | #define UTILS_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | int recvStunMsg(int sockfd, struct sockaddr_storage *their_addr, StunMessage *stunResponse, unsigned char *buf, int buflen); 15 | int createSocket(char host[], char port[], int ai_flags, struct addrinfo *servinfo, struct addrinfo **p); 16 | void sendRawStun(int sockHandle, 17 | const uint8_t *buf, 18 | int bufLen, 19 | const struct sockaddr *dstAddr, 20 | bool useRelay); 21 | void printDiscuss(StunMessage stunRequest); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /samplecode/src/view.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | 5 | #include "view.h" 6 | 7 | 8 | int printPermissionsw(WINDOW *win, int startx, int starty, struct turn_permissions *perm) 9 | { 10 | char addr[SOCKADDR_MAX_STRLEN]; 11 | int i; 12 | 13 | init_pair(1, COLOR_CYAN, COLOR_BLACK); 14 | 15 | mvwprintw(win, starty, startx,"Permissions:"); 16 | startx = startx + 13; 17 | mvwprintw(win, starty, startx, "'%i'", 18 | perm->numPermissions); 19 | 20 | 21 | /* 22 | for (i=0;i<=perm->numPermissions;i++){ 23 | 24 | 25 | if( sockaddr_toString((struct sockaddr *)&perm->permissions[i], 26 | addr, 27 | sizeof(addr), 28 | false) ) { 29 | 30 | //mvwprintw(win, starty, startx, "'%s'", 31 | // addr); 32 | startx = startx + strlen(addr) + 3; 33 | 34 | mvwprintw(win, starty, startx, "'%s'", 35 | test); 36 | 37 | startx = startx + strlen(test) + 3; 38 | } 39 | 40 | } 41 | */ 42 | 43 | if(perm->ok){ 44 | //mvwchgat(win, starty, 0, -1, A_BLINK, 1, NULL); 45 | } 46 | 47 | return ++starty; 48 | 49 | 50 | } 51 | 52 | 53 | 54 | int printAllocationResultw(WINDOW *win, int startx, int starty, struct turn_allocation *alloc) 55 | { 56 | 57 | char addr[SOCKADDR_MAX_STRLEN]; 58 | 59 | mvwprintw(win, starty++, startx,"Active TURN server: '%s'\n", 60 | sockaddr_toString((struct sockaddr *)&alloc->activeTurnServerAddr, 61 | addr, 62 | sizeof(addr), 63 | true)); 64 | 65 | mvwprintw(win, starty++, startx,"HOST addr: '%s'\n", 66 | sockaddr_toString((struct sockaddr *)&alloc->hostAddr, 67 | addr, 68 | sizeof(addr), 69 | true)); 70 | 71 | 72 | mvwprintw(win, starty++, startx,"RFLX addr: '%s'\n", 73 | sockaddr_toString((struct sockaddr *)&alloc->rflxAddr, 74 | addr, 75 | sizeof(addr), 76 | true)); 77 | 78 | mvwprintw(win, starty++, startx,"RELAY addr: '%s'\n", 79 | sockaddr_toString((struct sockaddr *)&alloc->relAddrIPv4, 80 | addr, 81 | sizeof(addr), 82 | true)); 83 | 84 | mvwprintw(win, starty++, startx,"RELAY addr: '%s'\n", 85 | sockaddr_toString((struct sockaddr *)&alloc->relAddrIPv6, 86 | addr, 87 | sizeof(addr), 88 | true)); 89 | 90 | mvwprintw(win, starty++, startx,"Permissions: %i", alloc->turnPerm.numPermissions); 91 | 92 | return starty; 93 | } 94 | 95 | 96 | void wprintTurnInfow( WINDOW *win, struct turn_info *turnInfo ) 97 | { 98 | char addr[SOCKADDR_MAX_STRLEN]; 99 | int starty = 1; 100 | int startx = 2; 101 | 102 | mvwprintw(win, 103 | starty++, 104 | startx, 105 | "TURN Server : '%s'\n", 106 | turnInfo->fqdn); 107 | mvwprintw(win, 108 | starty++, 109 | startx, 110 | "TURN Server IPv4: '%s'\n", 111 | sockaddr_toString((struct sockaddr *)&turnInfo->remoteIp4, 112 | addr, 113 | sizeof(addr), 114 | true)); 115 | 116 | mvwprintw(win, 117 | starty++, 118 | startx,"TURN Server IPv6: '%s'\n", 119 | sockaddr_toString((struct sockaddr *)&turnInfo->remoteIp6, 120 | addr, 121 | sizeof(addr), 122 | true)); 123 | 124 | 125 | mvwprintw(win, 126 | starty++, 127 | startx,"Local IPv4 : '%s'\n", 128 | sockaddr_toString((struct sockaddr *)&turnInfo->localIp4, 129 | addr, 130 | sizeof(addr), 131 | false)); 132 | 133 | mvwprintw(win, 134 | starty++, 135 | startx, 136 | "Local IPv6 : '%s'\n", 137 | sockaddr_toString((struct sockaddr *)&turnInfo->localIp6, 138 | addr, 139 | sizeof(addr), 140 | false)); 141 | 142 | mvwprintw(win, 143 | starty++, 144 | startx, 145 | "Local IPv6 (ULA): '%s'\n", 146 | sockaddr_toString((struct sockaddr *)&turnInfo->localIp6_ula, 147 | addr, 148 | sizeof(addr), 149 | false)); 150 | 151 | mvwprintw(win, starty++, startx,"TURN 44 Result"); 152 | starty = printAllocationResultw(win, startx+5, starty, &turnInfo->turnAlloc_44); 153 | //starty = printPermissionsw(win, startx+5, starty, &turnInfo->turnAlloc_44.turnPerm); 154 | 155 | mvwprintw(win, starty++, startx,"TURN 46 Result"); 156 | starty = printAllocationResultw(win, startx+5, starty, &turnInfo->turnAlloc_46); 157 | //starty = printPermissionsw(win, startx+5, starty, &turnInfo->turnAlloc_46.turnPerm); 158 | 159 | mvwprintw(win, starty++, startx,"TURN 64 Result"); 160 | starty = printAllocationResultw(win, startx+5, starty, &turnInfo->turnAlloc_64); 161 | //starty = printPermissionsw(win, startx+5, starty, &turnInfo->turnAlloc_64.turnPerm); 162 | 163 | mvwprintw(win, starty++, startx,"TURN 66 Result"); 164 | starty = printAllocationResultw(win, startx+5, starty, &turnInfo->turnAlloc_66); 165 | //starty = printPermissionsw(win, startx+5, starty, &turnInfo->turnAlloc_66.turnPerm); 166 | 167 | } 168 | 169 | 170 | void print_status(WINDOW *status_win, struct turn_info *turnInfo) 171 | { 172 | werase(status_win); 173 | box(status_win, 0, 0); 174 | 175 | // 176 | wprintTurnInfow(status_win, turnInfo); 177 | box(status_win, 0, 0); 178 | 179 | wrefresh(status_win); 180 | } 181 | 182 | 183 | void print_input(WINDOW *input_win) 184 | { 185 | werase(input_win); 186 | box(input_win, 0, 0); 187 | mvwprintw(input_win, 0, 2, "Input"); 188 | 189 | wrefresh(input_win); 190 | } 191 | 192 | void print_menu(WINDOW *menu_win, int highlight) 193 | { 194 | int x, y, i; 195 | 196 | x = 2; 197 | y = 2; 198 | box(menu_win, 0, 0); 199 | mvwprintw(menu_win, 0, 2, "Menu (Use left/right arrow keys)"); 200 | for(i = 0; i < n_choices; ++i) 201 | { 202 | if(highlight == i + 1) /* High light the present choice */ 203 | { 204 | wattron(menu_win, A_REVERSE); 205 | mvwprintw(menu_win, y, x, "%s", choices[i]); 206 | wattroff(menu_win, A_REVERSE); 207 | } 208 | else 209 | mvwprintw(menu_win, y, x, "%s", choices[i]); 210 | //++y; 211 | x = x+strlen(choices[i])+1; 212 | 213 | } 214 | wrefresh(menu_win); 215 | } 216 | 217 | void print_message(WINDOW *message_win, char *message) 218 | { 219 | 220 | box(message_win, 0, 0); 221 | mvwprintw(message_win, 0, 2, "Incomming Messages"); 222 | mvwprintw(message_win, 1, 1, "%s", message); 223 | wrefresh(message_win); 224 | 225 | 226 | 227 | } 228 | -------------------------------------------------------------------------------- /samplecode/src/view.h: -------------------------------------------------------------------------------- 1 | #ifndef VIEW_H 2 | #define VIEW_H 3 | 4 | 5 | #include 6 | 7 | #include "turninfo.h" 8 | 9 | #define WIDTH 60 10 | #define HEIGHT 5 11 | 12 | 13 | 14 | static char *choices[] = { 15 | "Gather All", 16 | "Send Permissions", 17 | "Send Message", 18 | "Release", 19 | "Exit", 20 | }; 21 | 22 | static int n_choices = sizeof(choices) / sizeof(char *); 23 | 24 | 25 | 26 | void print_menu(WINDOW *menu_win, int highlight); 27 | void print_input(WINDOW *input_win); 28 | void print_message(WINDOW *input_win, char *message); 29 | void print_status(WINDOW *status_win, struct turn_info *turnInfo); 30 | void releaseAll(struct turn_info *turnInfo); 31 | 32 | 33 | 34 | static WINDOW *status_win; 35 | static WINDOW *input_win; 36 | static WINDOW *menu_win; 37 | static WINDOW *message_win; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /sockaddrutil/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Cisco. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 16 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 18 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 19 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 20 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 21 | DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of Cisco. 26 | -------------------------------------------------------------------------------- /sockaddrutil/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src test . 2 | ACLOCAL_AMFLAGS = -I m4 3 | 4 | EXTRA_DIST = README LICENSE 5 | 6 | -------------------------------------------------------------------------------- /sockaddrutil/README: -------------------------------------------------------------------------------- 1 | 2 | Building on OSX 3 | To be able to build with check and gcov use macports and intall gcc and other libs. 4 | (Need check to do unittesting). 5 | 6 | for gcov to work properlyou should call ./configure like this: 7 | ./configure --with-check --enable-gcov CC=gcc-mp-4.6 CFLAGS=-fno-strict-aliasing 8 | 9 | 10 | -------------------------------------------------------------------------------- /sockaddrutil/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir m4 build-aux 3 | autoreconf --install 4 | -------------------------------------------------------------------------------- /sockaddrutil/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.61) 5 | AC_INIT([sockaddrutillib],[0.2],[palmarti@cisco.com]) 6 | AC_CONFIG_SRCDIR([src/sockaddr_util.c]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | AC_CONFIG_AUX_DIR([build-aux]) 10 | AC_CONFIG_MACRO_DIR([m4]) 11 | AM_INIT_AUTOMAKE([foreign -Wall -Werror]) 12 | m4_pattern_allow([AM_PROG_AR]) 13 | AM_PROG_AR 14 | LT_INIT 15 | 16 | 17 | 18 | # Checks for programs. 19 | AC_PROG_CC 20 | AM_PROG_CC_C_O 21 | 22 | 23 | AC_ARG_ENABLE(gcov, 24 | AS_HELP_STRING([--enable-gcov], 25 | [enable test coverage with gcov @<:@default=no@:>@]), 26 | [case "${enableval}" in 27 | yes) gcov=true ;; 28 | no) gcov=false ;; 29 | *) AC_MSG_ERROR([bad value ${enableval} for --enable-gcov]) ;; 30 | esac], 31 | [gcov=false]) 32 | 33 | AM_CONDITIONAL(GCOV, test x"$gcov" = "xtrue") 34 | 35 | 36 | # Support for running test cases using valgrind: 37 | use_valgrind=false 38 | AC_ARG_ENABLE(valgrind, 39 | [ --enable-valgrind Use valgrind when running unit tests. ], 40 | [ use_valgrind=true ]) 41 | 42 | if [[ "$use_valgrind" = "true" ]]; then 43 | AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no) 44 | 45 | if [[ "$HAVE_VALGRIND" = "no" ]]; then 46 | AC_MSG_ERROR([Valgrind not found in PATH. ]) 47 | fi 48 | fi 49 | AM_CONDITIONAL(USE_VALGRIND, $use_valgrind) 50 | 51 | 52 | AM_CONDITIONAL(CHECK, "false") 53 | AC_ARG_WITH([check], 54 | [AS_HELP_STRING([--with-check], 55 | [use Check for unit testing @<:@default=no@:>@])], 56 | [], 57 | [with_check=no]) 58 | 59 | LIBCHECK= 60 | AS_IF([test "x$with_check" != xno], 61 | [AC_CHECK_LIB([check], [srunner_create], 62 | [AC_SUBST([LIBCHECK], ["-lcheck"]) 63 | AM_CONDITIONAL(CHECK, "true") 64 | AC_DEFINE([HAVE_CHECK], [1], 65 | [Define if you have check])], 66 | [AC_MSG_FAILURE( 67 | [--with-check was given, but test for check failed])], 68 | [])]) 69 | 70 | 71 | 72 | 73 | 74 | # Checks for header files. 75 | AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h]) 76 | 77 | # Checks for typedefs, structures, and compiler characteristics. 78 | AC_HEADER_STDBOOL 79 | AC_TYPE_SIZE_T 80 | AC_TYPE_UINT16_T 81 | AC_TYPE_UINT32_T 82 | AC_TYPE_UINT8_T 83 | 84 | # Checks for library functions. 85 | AC_FUNC_MALLOC 86 | AC_CHECK_FUNCS([strchr]) 87 | 88 | 89 | 90 | 91 | 92 | AC_CONFIG_FILES([Makefile 93 | src/Makefile 94 | test/Makefile]) 95 | AC_OUTPUT 96 | -------------------------------------------------------------------------------- /sockaddrutil/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #./configure --with-check --enable-gcov 3 | 4 | make clean 5 | make check 6 | 7 | lcov --directory test/ --capture --output-file sockaddrutil.info 8 | 9 | 10 | genhtml --output-directory lcov --no-branch-coverage sockaddrutil.info 11 | 12 | firefox -new-tab lcov/index.html -------------------------------------------------------------------------------- /sockaddrutil/include/sockaddr_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | 30 | 31 | #ifndef SOCKADDR_UTIL_H 32 | #define SOCKADDR_UTIL_H 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #else 41 | #include 42 | #endif 43 | 44 | 45 | /*static const uint32_t SOCKADDR_MAX_STRLEN = INET6_ADDRSTRLEN + 8; //port, :, [];*/ 46 | #define SOCKADDR_MAX_STRLEN INET6_ADDRSTRLEN + 8 47 | 48 | 49 | void sockaddr_reset(struct sockaddr_storage * sa); 50 | 51 | /* 52 | * Initialize a sockaddr_in (IPv4) as any ("0.0.0.0:0"). 53 | * Remember to put aside enough memory. (sockaddr_storage) 54 | */ 55 | void sockaddr_initAsIPv4Any(struct sockaddr_in * sa); 56 | 57 | 58 | 59 | void sockaddr_initAsIPv6Any(struct sockaddr_in6 * sa); 60 | 61 | /* 62 | * Initialize a sockaddr from string. 63 | * Remember to put aside enough memory. (sockaddr_storage) 64 | */ 65 | bool sockaddr_initFromString(struct sockaddr *sa, 66 | const char *addr_str); 67 | 68 | /* 69 | * Initialize a sockaddr from a IPv4 string 70 | */ 71 | bool sockaddr_initFromIPv4String(struct sockaddr_in *sa, 72 | const char *addr_str); 73 | 74 | /* 75 | * Initialize a sockaddr from a IPv6 string 76 | */ 77 | bool sockaddr_initFromIPv6String(struct sockaddr_in6 *sa, 78 | const char *addr_str); 79 | 80 | 81 | /* 82 | * Initialize IPv4 sockaddr from a int addr and a int port. 83 | * (Use htons and htonl if your data is stored in host format) 84 | * 85 | */ 86 | bool sockaddr_initFromIPv4Int(struct sockaddr_in *sa, 87 | uint32_t addr, 88 | uint16_t port); 89 | 90 | 91 | /* 92 | * Initialize IPv6 sockaddr from a int addr and a int port. 93 | * (Use htons and htonl if your data is stored in host format) 94 | * 95 | */ 96 | bool sockaddr_initFromIPv6Int(struct sockaddr_in6 *sin, 97 | const uint8_t ipaddr[16], 98 | uint16_t port); 99 | 100 | 101 | /* 102 | * Checks if the address part is the same. 103 | * No checking of ports or transport protocol 104 | */ 105 | 106 | bool sockaddr_sameAddr(const struct sockaddr * a, 107 | const struct sockaddr * b); 108 | 109 | 110 | /* 111 | * Check if the port is the same. 112 | * 113 | */ 114 | bool sockaddr_samePort(const struct sockaddr * a, 115 | const struct sockaddr * b); 116 | 117 | /* 118 | * Get port from address 119 | * 120 | */ 121 | unsigned int 122 | sockaddr_ipPort (const struct sockaddr * a); 123 | 124 | /* 125 | * Check if two sockaddr are alike 126 | * (IP proto, port and address) 127 | * 128 | */ 129 | bool sockaddr_alike(const struct sockaddr * a, 130 | const struct sockaddr * b); 131 | 132 | /* 133 | * Checks if a sockaddr is reasonably initialized 134 | * 135 | */ 136 | bool sockaddr_isSet(const struct sockaddr * sa); 137 | 138 | /* 139 | * Checks if a sockaddr has the address of 'any' 140 | * 141 | */ 142 | bool sockaddr_isAddrAny(const struct sockaddr * sa); 143 | 144 | 145 | /* 146 | * Checks if a sockaddr loop-back 147 | * 148 | */ 149 | bool sockaddr_isAddrLoopBack(const struct sockaddr * sa); 150 | 151 | 152 | /* 153 | * Checks if a sockaddr is private (RFC 1918) 154 | * 155 | */ 156 | bool sockaddr_isAddrPrivate(const struct sockaddr * sa); 157 | 158 | 159 | /* 160 | * Checks if a sockaddr is a IPv6 link local address 161 | * Will return false if it is a IPv4 addr 162 | */ 163 | bool sockaddr_isAddrLinkLocal(const struct sockaddr * sa); 164 | 165 | /* 166 | * Checks if a sockaddr is a IPv6 site local address 167 | * Will return false if it is a IPv4 addr 168 | */ 169 | 170 | bool sockaddr_isAddrSiteLocal(const struct sockaddr * sa); 171 | 172 | /* 173 | * Checks if a sockaddr is a IPv6 ULA address 174 | * Will return false if it is a IPv4 addr 175 | */ 176 | bool sockaddr_isAddrULA(const struct sockaddr * sa); 177 | 178 | /* 179 | * Get IPv6 Flags. 180 | * Will return 0 in case if failure or IPv4 addr 181 | */ 182 | int sockaddr_getIPv6Flags(const struct sockaddr * sa, const char* ifa_name, int ifa_len); 183 | 184 | /* 185 | * Checks if a sockaddr is a IPv6 temporary address 186 | * Will return false if it is a IPv4 addr 187 | */ 188 | bool sockaddr_isAddrTemporary(const struct sockaddr * sa, const char* ifa_name, int ifa_len); 189 | 190 | 191 | /* 192 | * Checks if a sockaddr is a IPv6 deprecated address 193 | * Will return false if it is a IPv4 addr 194 | */ 195 | bool sockaddr_isAddrDeprecated(const struct sockaddr * sa, const char* ifa_name, int ifa_len); 196 | 197 | /* 198 | * Converts a sockaddr to string 199 | * If add port is true the IPv6 string will contain [], 200 | * if not the IPv6 address is printed without[] 201 | */ 202 | const char *sockaddr_toString( const struct sockaddr *sa, 203 | char *dest, 204 | size_t destlen, 205 | bool addport); 206 | 207 | /* 208 | * Copy a sockaddr from src to dst 209 | */ 210 | void sockaddr_copy(struct sockaddr * dst, 211 | const struct sockaddr * src); 212 | 213 | 214 | /* 215 | * Set the port portion of a sockaddr 216 | */ 217 | void sockaddr_setPort(struct sockaddr * sa, 218 | uint16_t port); 219 | 220 | #ifdef __cplusplus 221 | } 222 | #endif 223 | 224 | #endif 225 | -------------------------------------------------------------------------------- /sockaddrutil/src/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | 3 | 4 | AM_CPPFLAGS = -I../include -O2 -g -Wall -Wextra -Wno-unknown-pragmas -Werror-implicit-function-declaration -Werror -Wno-unused-parameter -Wdeclaration-after-statement -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes 5 | 6 | 7 | include_HEADERS = ../include/sockaddr_util.h 8 | 9 | lib_LTLIBRARIES = libsockaddrutil.la 10 | libsockaddrutil_la_SOURCES = sockaddr_util.c 11 | 12 | -------------------------------------------------------------------------------- /sockaddrutil/test/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = subdir-objects 2 | if CHECK 3 | 4 | TESTS = check_sockaddrutil 5 | 6 | check_PROGRAMS = check_sockaddrutil 7 | check_sockaddrutil_SOURCES = sockaddr_test.c testmain.c ../src/sockaddr_util.c 8 | 9 | if GCOV 10 | AM_CPPFLAGS = -I../include -fprofile-arcs -ftest-coverage 11 | check_sockaddrutil_LDFLAGS = -lcheck -lgcov 12 | else 13 | AM_CPPFLAGS = -I../include 14 | check_sockaddrutil_LDFLAGS = -lcheck 15 | endif 16 | 17 | if USE_VALGRIND 18 | TESTS_ENVIRONMENT = ../../valgrind-wrapper 19 | endif 20 | 21 | include_HEADERS = ../include/sockaddr_util.h 22 | 23 | 24 | endif 25 | clean-local: 26 | rm -f *.g* 27 | 28 | -------------------------------------------------------------------------------- /sockaddrutil/test/testmain.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | Suite * sockaddr_suite (void); 8 | 9 | int main(void){ 10 | 11 | int number_failed; 12 | Suite *s = sockaddr_suite (); 13 | SRunner *sr = srunner_create (s); 14 | srunner_run_all (sr, CK_NORMAL); 15 | number_failed = srunner_ntests_failed (sr); 16 | srunner_free (sr); 17 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /stunlib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Cisco. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 16 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 18 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 19 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 20 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 21 | DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of Cisco. 26 | -------------------------------------------------------------------------------- /stunlib/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src test . 2 | ACLOCAL_AMFLAGS = -I m4 3 | 4 | EXTRA_DIST = README LICENSE -------------------------------------------------------------------------------- /stunlib/README: -------------------------------------------------------------------------------- 1 | 2 | 3 | Building on OSX 4 | - need macports with gcc, check, openssl +++ 5 | - call configure like this: 6 | ./configure --with-check --enable-gcov CC=gcc-mp-4.6 CFLAGS="-fno-strict-aliasing -I/usr/local/include" LDFLAGS=-"L/opt/local/lib -lcrypto -lz" 7 | -------------------------------------------------------------------------------- /stunlib/TODO: -------------------------------------------------------------------------------- 1 | 2 | - Do propper SASL_prep of password -------------------------------------------------------------------------------- /stunlib/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir m4 build-aux 3 | autoreconf --install 4 | -------------------------------------------------------------------------------- /stunlib/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.61]) 5 | AC_INIT([stunlib], [0.2], [palmarti@cisco.com]) 6 | AC_CONFIG_SRCDIR([include/stunlib.h]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | AC_CONFIG_AUX_DIR([build-aux]) 10 | AC_CONFIG_MACRO_DIR([m4]) 11 | AM_INIT_AUTOMAKE([foreign -Wall -Werror]) 12 | m4_pattern_allow([AM_PROG_AR]) 13 | AM_PROG_AR 14 | LT_INIT 15 | 16 | # Checks for programs. 17 | AC_PROG_CC 18 | AM_PROG_CC_C_O 19 | 20 | 21 | AC_ARG_ENABLE(gcov, 22 | AS_HELP_STRING([--enable-gcov], 23 | [enable test coverage with gcov @<:@default=no@:>@]), 24 | [case "${enableval}" in 25 | yes) gcov=true ;; 26 | no) gcov=false ;; 27 | *) AC_MSG_ERROR([bad value ${enableval} for --enable-gcov]) ;; 28 | esac], 29 | [gcov=false]) 30 | 31 | AM_CONDITIONAL(GCOV, test x"$gcov" = "xtrue") 32 | 33 | # Support for running test cases using valgrind: 34 | use_valgrind=false 35 | AC_ARG_ENABLE(valgrind, 36 | [ --enable-valgrind Use valgrind when running unit tests. ], 37 | [ use_valgrind=true ]) 38 | 39 | if [[ "$use_valgrind" = "true" ]]; then 40 | AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no) 41 | 42 | if [[ "$HAVE_VALGRIND" = "no" ]]; then 43 | AC_MSG_ERROR([Valgrind not found in PATH. ]) 44 | fi 45 | fi 46 | AM_CONDITIONAL(USE_VALGRIND, $use_valgrind) 47 | 48 | AM_CONDITIONAL(CHECK, "false") 49 | AC_ARG_WITH([check], 50 | [AS_HELP_STRING([--with-check], 51 | [use Check for unit testing @<:@default=no@:>@])], 52 | [], 53 | [with_check=no]) 54 | 55 | LIBCHECK= 56 | AS_IF([test "x$with_check" != xno], 57 | [AC_CHECK_LIB([check], [srunner_create], 58 | [AC_SUBST([LIBCHECK], ["-lcheck"]) 59 | AM_CONDITIONAL(CHECK, "true") 60 | AC_DEFINE([HAVE_CHECK], [1], 61 | [Define if you have check])], 62 | [AC_MSG_FAILURE( 63 | [--with-check was given, but test for check failed])], 64 | [])]) 65 | 66 | # Checks for libraries. 67 | #AC_CHECK_LIB([check], [srunner_create]) 68 | 69 | AC_CHECK_FILE(../sockaddrutil/include/sockaddr_util.h, local_sockaddr=true, local_sockaddr=false ) 70 | 71 | AM_CONDITIONAL(LOCAL_SOCKADDR, test x"$local_sockaddr" = "xtrue") 72 | 73 | 74 | 75 | AM_COND_IF(LOCAL_SOCKADDR, 76 | [], 77 | [AC_CHECK_LIB([sockaddrutil], [sockaddr_initFromString],[], [AC_MSG_FAILURE([could not find sockaddrutil])])]) 78 | 79 | dnl AC_CHECK_LIB([ssl], [SSL_library_init], [], [AC_MSG_FAILURE([could not find ssl])]) 80 | 81 | AC_CHECK_LIB([crypto], [MD5], [], [AC_MSG_FAILURE([could not find crypto])]) 82 | AC_CHECK_LIB([z], [crc32], [], [AC_MSG_FAILURE([could not find libz])]) 83 | 84 | dnl AC_CHECK_LIB([gsasl], [gsasl_check_version], [], [AC_MSG_FAILURE([could not find gsasl])]) 85 | 86 | 87 | 88 | # Checks for header files. 89 | AC_CHECK_HEADERS([netinet/in.h stddef.h stdint.h stdlib.h string.h]) 90 | 91 | # Checks for typedefs, structures, and compiler characteristics. 92 | AC_HEADER_STDBOOL 93 | AC_TYPE_INT32_T 94 | AC_TYPE_SIZE_T 95 | AC_TYPE_UINT16_T 96 | AC_TYPE_UINT32_T 97 | AC_TYPE_UINT64_T 98 | AC_TYPE_UINT8_T 99 | 100 | # Checks for library functions. 101 | AC_CHECK_FUNCS([memset]) 102 | 103 | AC_CONFIG_FILES([Makefile 104 | src/Makefile 105 | test/Makefile]) 106 | 107 | AC_OUTPUT 108 | -------------------------------------------------------------------------------- /stunlib/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #./configure --with-check --enable-gcov 3 | 4 | make clean 5 | make check 6 | 7 | lcov --directory test/ --capture --output-file stunlib.info 8 | 9 | 10 | genhtml --output-directory lcov --no-branch-coverage stunlib.info 11 | 12 | firefox -new-tab lcov/index.html -------------------------------------------------------------------------------- /stunlib/include/stun_intern.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | #ifndef STUN_INTERN_H 30 | #define STUN_INTERN_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #define STUNCLIENT_CTX_UNKNOWN -1 39 | #define STUN_MAX_ERR_STRLEN 256 /* max size of string in STUN_INFO_FUNC */ 40 | 41 | /* Internal STUN signals, inputs to stun bind client. */ 42 | typedef enum { 43 | STUN_SIGNAL_BindReq, 44 | STUN_SIGNAL_BindResp, 45 | STUN_SIGNAL_BindRespError, 46 | STUN_SIGNAL_TimerTick, 47 | STUN_SIGNAL_TimerRetransmit, 48 | STUN_SIGNAL_ICMPResp, 49 | STUN_SIGNAL_DeAllocate, 50 | STUN_SIGNAL_Cancel, 51 | 52 | STUN_SIGNAL_Illegal = -1 53 | } STUN_SIGNAL; 54 | 55 | 56 | typedef struct 57 | { 58 | struct sockaddr_storage srcAddr; 59 | StunMessage stunRespMessage; 60 | uint32_t ICMPtype; 61 | uint32_t ttl; 62 | } 63 | StunRespStruct; 64 | 65 | 66 | 67 | /* Internal STUN states */ 68 | typedef enum { 69 | STUN_STATE_Idle = 0, 70 | STUN_STATE_WaitBindResp, 71 | STUN_STATE_Cancelled, 72 | STUN_STATE_End /* must be last */ 73 | } STUN_STATE; 74 | 75 | 76 | /* Internal message formats */ 77 | typedef struct { 78 | uint32_t threadCtx; 79 | void *userCtx; 80 | struct sockaddr_storage serverAddr; 81 | struct sockaddr_storage baseAddr; 82 | bool useRelay; 83 | char ufrag[300]; /* TBD = ICE_MAX_UFRAG_LENGTH*/ 84 | char password[300]; /* TBD = ICE_MAX_PASSWD_LENGTH*/ 85 | uint32_t peerPriority; 86 | bool useCandidate; 87 | bool iceControlling; 88 | uint64_t tieBreaker; 89 | uint8_t ttl; 90 | StunMsgId transactionId; 91 | uint32_t sockhandle; 92 | STUN_SENDFUNC sendFunc; 93 | STUNCB stunCbFunc; 94 | DiscussData *discussData; /*NULL allowed if none present */ 95 | bool addSoftware; 96 | } StunBindReqStuct; 97 | 98 | struct StunClientStats 99 | { 100 | uint32_t InProgress; 101 | uint32_t BindReqSent; 102 | uint32_t BindReqSent_ViaRelay; 103 | uint32_t BindRespReceived; 104 | uint32_t BindRespReceived_AfterCancel; 105 | uint32_t BindRespReceived_InIdle; 106 | uint32_t BindRespReceived_ViaRelay; 107 | uint32_t BindRespErrReceived; 108 | uint32_t ICMPReceived; 109 | uint32_t BindReqReceived; 110 | uint32_t BindReqReceived_ViaRelay; 111 | uint32_t BindRespSent; 112 | uint32_t BindRespSent_ViaRelay; 113 | uint32_t Retransmits; 114 | uint32_t Failures; 115 | }; 116 | 117 | typedef struct 118 | { 119 | STUN_STATE state; 120 | bool inUse; 121 | uint32_t inst; 122 | StunBindReqStuct stunBindReq; 123 | 124 | uint8_t stunReqMsgBuf[STUN_MAX_PACKET_SIZE]; /* encoded STUN request */ 125 | int stunReqMsgBufLen; /* of encoded STUN request */ 126 | 127 | STUN_USER_CREDENTIALS userCredentials; 128 | bool authenticated; 129 | 130 | /* returned in allocate resp */ 131 | struct sockaddr_storage rflxAddr; 132 | 133 | /* timers */ 134 | int32_t TimerRetransmit; 135 | uint32_t retransmits; 136 | 137 | /* RTT Info */ 138 | struct timeval start; 139 | struct timeval stop; 140 | 141 | /* icmp */ 142 | uint32_t ICMPtype; 143 | uint32_t ttl; 144 | 145 | /* DISCUSS */ 146 | bool hasDiscuss; 147 | DiscussData discussData; 148 | 149 | struct StunClientStats stats; 150 | 151 | STUN_CLIENT_DATA *client; 152 | 153 | 154 | } STUN_TRANSACTION_DATA; 155 | 156 | 157 | struct STUN_CLIENT_DATA 158 | { 159 | STUN_TRANSACTION_DATA data [MAX_STUN_TRANSACTIONS]; 160 | 161 | 162 | /*duplicated for logging on unknown transactions etc.*/ 163 | STUN_INFO_FUNC_PTR Log_cb; 164 | void * logUserData; 165 | struct StunClientStats stats; 166 | }; 167 | 168 | 169 | /********************************************/ 170 | /****** instance data ******** (internal) */ 171 | /********************************************/ 172 | 173 | 174 | /* state function */ 175 | typedef void (*STUN_STATE_FUNC)(STUN_TRANSACTION_DATA *pInst, STUN_SIGNAL sig, uint8_t *payload); 176 | 177 | /* entry in state table */ 178 | typedef struct 179 | { 180 | STUN_STATE_FUNC Statefunc; 181 | const char *StateStr; 182 | } 183 | STUN_STATE_TABLE; 184 | 185 | 186 | 187 | #ifdef __cplusplus 188 | } 189 | #endif 190 | 191 | 192 | #endif /* STUN_INTERN_H */ 193 | -------------------------------------------------------------------------------- /stunlib/include/stun_os.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | #ifndef STUN_OS_H 30 | #define STUN_OS_H 31 | 32 | 33 | #ifndef WIN32 34 | #include 35 | #else 36 | #undef WIN32_LEAN_AND_MEAN 37 | #define WIN32_LEAN_AND_MEAN 38 | 39 | #include 40 | #endif 41 | 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #else 46 | #include 47 | #endif 48 | 49 | #if defined(WIN32) 50 | typedef CRITICAL_SECTION STUN_MUTEX; 51 | #else 52 | /* linux, .. */ 53 | typedef pthread_mutex_t STUN_MUTEX; 54 | #endif 55 | 56 | bool Stun_MutexCreate(STUN_MUTEX *m, char *name); 57 | bool Stun_MutexLock (STUN_MUTEX *m); 58 | bool Stun_MutexUnlock(STUN_MUTEX *m); 59 | bool Stun_MutexDestroy(STUN_MUTEX *m); 60 | 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | 67 | #endif /* STUN_OS_H */ 68 | -------------------------------------------------------------------------------- /stunlib/include/stunlibapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | 30 | 31 | #ifndef STUNLIBAPI_H 32 | #define STUNLIBAPI_H 33 | 34 | #include "stunlib.h" 35 | #include "turnclient.h" 36 | #include "stunclient.h" 37 | #include "stunfifo.h" 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /stunlib/include/turn_intern.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Cisco. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY CISCO ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those of the 25 | authors and should not be interpreted as representing official policies, either expressed 26 | or implied, of Cisco. 27 | */ 28 | 29 | #ifndef TURN_INTERN_H 30 | #define TURN_INTERN_H 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | #define Dflt_TimerResMsec 50 37 | #define NoStunErrorCode 0xffffffff 38 | 39 | /* make sure both the following timers are < 5 minutes */ 40 | #define TURN_REFRESH_CHANNEL_TIMER_SEC (3*60) /* 3 min (spec. is 10 min) */ 41 | #define TURN_REFRESH_PERMISSION_TIMER_SEC (4*60) /* 4 min (spec. is 5 min) */ 42 | 43 | #define TURN_RETRANS_TIMEOUT_RELEASE_MSEC 150 44 | #define TURN_RETRIES_RELEASE 2 45 | 46 | 47 | /* Internal TURN signals, inputs to turn client. */ 48 | typedef enum { 49 | TURN_SIGNAL_AllocateReq, 50 | TURN_SIGNAL_AllocateResp, 51 | TURN_SIGNAL_AllocateRespError, 52 | TURN_SIGNAL_CreatePermissionReq, 53 | TURN_SIGNAL_CreatePermissionResp, 54 | TURN_SIGNAL_CreatePermissionRespError, 55 | TURN_SIGNAL_ChannelBindReq, 56 | TURN_SIGNAL_ChannelBindResp, 57 | TURN_SIGNAL_ChannelBindRespError, 58 | TURN_SIGNAL_RefreshResp, 59 | TURN_SIGNAL_RefreshRespError, 60 | TURN_SIGNAL_TimerTick, 61 | TURN_SIGNAL_TimerRetransmit, 62 | TURN_SIGNAL_TimerRefreshAlloc, 63 | TURN_SIGNAL_TimerRefreshChannel, 64 | TURN_SIGNAL_TimerRefreshPermission, 65 | TURN_SIGNAL_TimerStunKeepAlive, 66 | TURN_SIGNAL_DeAllocate, 67 | 68 | TURN_SIGNAL_Illegal = -1 69 | } TURN_SIGNAL; 70 | 71 | /* Internal message formats */ 72 | typedef struct { 73 | struct sockaddr_storage serverAddr; 74 | char username[STUN_MSG_MAX_USERNAME_LENGTH]; 75 | char password[STUN_MSG_MAX_PASSWORD_LENGTH]; 76 | int ai_family; /* AF_INET/AF_INET6 */ 77 | TURN_SEND_FUNC sendFunc; 78 | void *userCtx; 79 | TURN_CB_FUNC turnCbFunc; 80 | uint32_t threadCtx; 81 | bool evenPortAndReserve; 82 | uint64_t reservationToken; 83 | } TurnAllocateReqStuct; 84 | 85 | 86 | /* Internal TURN states */ 87 | typedef enum { 88 | TURN_STATE_Idle = 0, 89 | TURN_STATE_WaitAllocRespNotAuth, 90 | TURN_STATE_WaitAllocResp, 91 | TURN_STATE_Allocated, 92 | TURN_STATE_WaitAllocRefreshResp, 93 | TURN_STATE_WaitChanBindResp, 94 | TURN_STATE_WaitCreatePermResp, 95 | TURN_STATE_WaitReleaseResp, 96 | TURN_STATE_End /* must be last */ 97 | } TURN_STATE; 98 | 99 | 100 | 101 | /********************************************/ 102 | /****** instance data ******** (internal) */ 103 | /********************************************/ 104 | 105 | 106 | typedef struct 107 | { 108 | uint16_t channelNumber; 109 | struct sockaddr_storage peerTrnspAddr; 110 | bool createPermission; 111 | } 112 | TurnChannelBindInfo_T; 113 | 114 | typedef struct 115 | { 116 | uint32_t numberOfPeers; 117 | struct sockaddr_storage peerTrnspAddr[TURN_MAX_PERMISSION_PEERS]; 118 | } 119 | TurnCreatePermissionInfo_T; 120 | 121 | 122 | struct TURN_INSTANCE_DATA 123 | { 124 | char softwareVersionStr[100]; 125 | unsigned long id; 126 | TURN_INFO_FUNC infoFunc; 127 | 128 | TURN_STATE state; 129 | bool inUse; 130 | TurnAllocateReqStuct turnAllocateReq; 131 | StunMsgId StunReqTransId; /* transaction id of request */ 132 | StunMsgId PrevRespTransId; /* transaction id of last received */ 133 | uint8_t stunReqMsgBuf[STUN_MAX_PACKET_SIZE]; /* encoded STUN request */ 134 | int stunReqMsgBufLen; /* of encoded STUN request */ 135 | bool pendingChannelBind; 136 | STUN_USER_CREDENTIALS userCredentials; 137 | bool authenticated; 138 | bool permissionsInstalled; 139 | bool channelBound; 140 | bool createPermissionCallbackCalled; 141 | bool channelBindCallbackCalled; 142 | /* returned in allocate resp */ 143 | 144 | struct sockaddr_storage srflxAddr; 145 | struct sockaddr_storage relAddr_IPv4; 146 | struct sockaddr_storage relAddr_IPv6; 147 | 148 | uint32_t lifetime; /* Seconds */ 149 | TurnChannelBindInfo_T channelBindInfo; 150 | TurnCreatePermissionInfo_T createPermInfo; 151 | /* timers */ 152 | uint32_t timerResMsec; 153 | int32_t TimerRetransmit; 154 | int32_t TimerRefreshAlloc; 155 | int32_t TimerRefreshChannel; 156 | int32_t TimerRefreshPermission; 157 | int32_t TimerStunKeepAlive; 158 | int retransmits; 159 | int failures; 160 | uint64_t token; 161 | 162 | bool doStunKeepAlive; 163 | 164 | TurnCallBackData_T turnCbData; 165 | 166 | void *userData; 167 | }; 168 | 169 | 170 | /* state function */ 171 | typedef void (*TURN_STATE_FUNC)(TURN_INSTANCE_DATA *pInst, TURN_SIGNAL sig, uint8_t *payload, uint8_t *origMsgBuf); 172 | 173 | /* entry in state table */ 174 | typedef struct 175 | { 176 | TURN_STATE_FUNC Statefunc; 177 | const char *StateStr; 178 | } 179 | TURN_STATE_TABLE; 180 | 181 | 182 | void TurnClientSimulateSig(void *instance, TURN_SIGNAL sig); 183 | 184 | 185 | #ifdef __cplusplus 186 | } 187 | #endif 188 | 189 | 190 | #endif /* TURN_INTERN_H */ 191 | -------------------------------------------------------------------------------- /stunlib/src/Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | if LOCAL_SOCKADDR 3 | MY_AM_CPPFLAGS = -I../../sockaddrutil/include 4 | endif 5 | 6 | AM_CPPFLAGS = $(MY_AM_CPPFLAGS) -I../include -O2 -g -Wall -Wextra -Wno-unknown-pragmas -Werror-implicit-function-declaration -Werror -Wno-unused-parameter -Wdeclaration-after-statement -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes 7 | 8 | 9 | 10 | 11 | 12 | 13 | include_HEADERS = ../include/stunclient.h ../include/stun_intern.h ../include/stunlib.h ../include/turnclient.h ../include/stunlibapi.h ../include/turn_intern.h 14 | 15 | 16 | 17 | 18 | 19 | lib_LTLIBRARIES = libstun.la 20 | libstun_la_SOURCES = stunclient.c stunlib.c turnclient.c 21 | libstun_la_LDFLAGS = -version-info 1:0:0 22 | 23 | -------------------------------------------------------------------------------- /stunlib/test/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = subdir-objects 2 | if CHECK 3 | MY_CFLAGS_1 = -I../include 4 | MY_LDFLAGS_1 = -lcheck 5 | TESTS = check_stunlib 6 | check_PROGRAMS = check_stunlib 7 | check_stunlib_SOURCES = turnclienttest.c testvector.c turn_message.c testmain.c testrealworldpackets.c teststunclient.c teststunserver.c ../src/stunclient.c ../src/stunlib.c ../src/turnclient.c 8 | 9 | if LOCAL_SOCKADDR 10 | MY_LDFLAGS_2 = ../../sockaddrutil/src/libsockaddrutil.la 11 | MY_CFLAGS_2 = -I../include -I../../sockaddrutil/include 12 | endif 13 | 14 | if GCOV 15 | MY_CFLAGS_3 = -fprofile-arcs -ftest-coverage 16 | MY_LDFLAGS_3 = -lgcov 17 | else 18 | 19 | endif 20 | 21 | if USE_VALGRIND 22 | TESTS_ENVIRONMENT = ../../valgrind-wrapper 23 | endif 24 | 25 | AM_CPPFLAGS = $(MY_CFLAGS_1) $(MY_CFLAGS_2) $(MY_CFLAGS_3) 26 | check_stunlib_LDFLAGS = $(MY_LDFLAGS_1) $(MY_LDFLAGS_2) $(MY_LDFLAGS_3) 27 | 28 | 29 | clean-local: 30 | rm -f *.g* 31 | 32 | 33 | endif 34 | -------------------------------------------------------------------------------- /stunlib/test/testmain.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | Suite * stunlib_suite (void); 8 | Suite * turnclient_suite (void); 9 | Suite * turnmessage_suite (void); 10 | Suite * realworldmsg_suite (void); 11 | Suite * stunclient_suite (void); 12 | Suite * stunserver_suite (void); 13 | 14 | 15 | int main(void){ 16 | 17 | int number_failed; 18 | //SRunner *sr = srunner_create (turnmessage_suite ()); 19 | SRunner *sr = srunner_create (stunlib_suite ()); 20 | //SRunner *sr = srunner_create (s); 21 | srunner_add_suite (sr, turnclient_suite ()); 22 | srunner_add_suite (sr, turnmessage_suite ()); 23 | srunner_add_suite (sr, realworldmsg_suite ()); 24 | srunner_add_suite (sr, stunclient_suite ()); 25 | srunner_add_suite (sr, stunserver_suite ()); 26 | srunner_run_all (sr, CK_NORMAL); 27 | number_failed = srunner_ntests_failed (sr); 28 | srunner_free (sr); 29 | return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 30 | } 31 | -------------------------------------------------------------------------------- /stunlib/test/testrealworldpackets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "stunlib.h" 7 | 8 | static unsigned char turnResp[] = 9 | "\x01\x03\x00\x5c" 10 | "\x21\x12\xa4\x42" 11 | "\x32\x7b\x23\xc6" 12 | "\x00\x01\x00\x00" 13 | "\x51\x1a\x45\xa3" 14 | "\x00\x16\x00\x08" 15 | "\x00\x01\xf4\x87" 16 | "\x2b\x3d\xa8\x69" 17 | "\x00\x0d\x00\x04" 18 | "\x00\x00\x02\x58" 19 | "\x00\x20\x00\x08" 20 | "\x00\x01\xf6\x75" 21 | "\x2b\x24\xfe\x5f" 22 | "\x80\x22\x00\x1d" 23 | "\x72\x65\x73\x74" 24 | "\x75\x6e\x64\x20" 25 | "\x76\x30\x2e\x34" 26 | "\x2e\x32\x20\x28" 27 | "\x78\x38\x36\x5f" 28 | "\x36\x34\x2f\x6c" 29 | "\x69\x6e\x75\x78" 30 | "\x29\x00\x00\x00" 31 | "\x00\x08\x00\x14" 32 | "\x86\xfa\x92\x69" 33 | "\x64\x64\x80\xb8" 34 | "\xaf\xf2\xff\x06" 35 | "\xef\x3d\x5c\x17" 36 | "\xd1\x0d\xf2\xa0"; 37 | 38 | Suite * realworldmsg_suite(void); 39 | 40 | START_TEST (integrity_turn_response) 41 | { 42 | StunMessage stunResponse; 43 | bool isMsStun; 44 | int numbytes = sizeof(turnResp); 45 | const char user[] = "turnuser"; 46 | const char password[] = "turnpass"; 47 | const char realm[] = "ice.qa"; 48 | int keyLen = 16; 49 | char md5[keyLen]; 50 | 51 | fail_unless(stunlib_isStunMsg(turnResp, numbytes)); 52 | 53 | fail_unless(stunlib_DecodeMessage(turnResp, numbytes, &stunResponse, NULL, NULL)); 54 | 55 | stunlib_createMD5Key((unsigned char *)md5, user, realm, password); 56 | 57 | fail_unless(stunlib_checkIntegrity(turnResp, numbytes, &stunResponse, (unsigned char *)md5, keyLen)); 58 | } 59 | END_TEST 60 | 61 | Suite * realworldmsg_suite(void) 62 | { 63 | Suite *s = suite_create("Realworld STUN-message test"); 64 | 65 | TCase *tc_realworld = tcase_create("Integrity"); 66 | tcase_add_test(tc_realworld, integrity_turn_response); 67 | suite_add_tcase(s, tc_realworld); 68 | 69 | return s; 70 | } 71 | -------------------------------------------------------------------------------- /stunlib/test/teststunserver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "stunclient.h" 7 | #include "sockaddr_util.h" 8 | 9 | Suite * stunclient_suite (void); 10 | 11 | #define MAX_INSTANCES 50 12 | #define TEST_THREAD_CTX 1 13 | 14 | #define TEST_IPv4_ADDR 15 | #define TEST_IPv4_PORT 16 | #define TEST_IPv6_ADDR 17 | 18 | typedef struct 19 | { 20 | uint32_t a; 21 | uint8_t b; 22 | } 23 | AppCtx_T; 24 | 25 | static AppCtx_T AppCtx[MAX_INSTANCES]; 26 | static StunCallBackData_T StunCbData[MAX_INSTANCES]; 27 | 28 | static AppCtx_T CurrAppCtx; 29 | 30 | static StunMsgId LastTransId; 31 | static struct sockaddr_storage LastAddress; 32 | static bool runningAsIPv6; 33 | 34 | static const uint8_t StunCookie[] = STUN_MAGIC_COOKIE_ARRAY; 35 | 36 | StunResult_T stunResult; 37 | 38 | struct sockaddr_storage stunServerAddr; 39 | 40 | DiscussData discussData; 41 | 42 | STUN_CLIENT_DATA *stunInstance; 43 | #define STUN_TICK_INTERVAL_MS 50 44 | 45 | /* 46 | static void StunStatusCallBack(void *ctx, StunCallBackData_T *retData) 47 | { 48 | stunResult = retData->stunResult; 49 | //printf("Got STUN status callback\n");// (Result (%i)\n", retData->stunResult); 50 | } 51 | */ 52 | /* Callback for management info */ 53 | /* 54 | static void PrintStunInfo(StunInfoCategory_T category, char *InfoStr) 55 | { 56 | //fprintf(stderr, "%s\n", ErrStr); 57 | } 58 | */ 59 | static void SendRawStun(int sockfd, 60 | const uint8_t *buf, 61 | int len, 62 | const struct sockaddr *addr, 63 | bool useRelay, 64 | const uint8_t ttl) 65 | { 66 | char addr_str[SOCKADDR_MAX_STRLEN]; 67 | /* find the transaction id so we can use this in the simulated resp */ 68 | 69 | memcpy(&LastTransId, &buf[8], STUN_MSG_ID_SIZE); 70 | 71 | sockaddr_copy((struct sockaddr *)&LastAddress, addr); 72 | 73 | sockaddr_toString(addr, addr_str, SOCKADDR_MAX_STRLEN, true); 74 | 75 | //printf("Sendto: '%s'\n", addr_str); 76 | 77 | } 78 | 79 | static void setup (void) 80 | { 81 | stunResult = StunResult_Empty; 82 | runningAsIPv6 = false; 83 | sockaddr_initFromString((struct sockaddr*)&stunServerAddr, "193.200.93.152:3478"); 84 | 85 | StunClient_Alloc(&stunInstance); 86 | 87 | } 88 | 89 | static void teardown (void) 90 | { 91 | stunResult = StunResult_Empty; 92 | StunClient_free(stunInstance); 93 | } 94 | 95 | 96 | static void setupIPv6 (void) 97 | { 98 | stunResult = StunResult_Empty; 99 | runningAsIPv6 = true; 100 | sockaddr_initFromString((struct sockaddr*)&stunServerAddr, "[2001:470:dc88:2:226:18ff:fe92:6d53]:3478"); 101 | StunClient_Alloc(&stunInstance); 102 | 103 | } 104 | 105 | static void teardownIPv6 (void) 106 | { 107 | stunResult = StunResult_Empty; 108 | StunClient_free(stunInstance); 109 | } 110 | 111 | 112 | START_TEST (HandleReq_Valid) 113 | { 114 | STUN_INCOMING_REQ_DATA pReq; 115 | StunMessage stunMsg; 116 | stunMsg.hasUsername = true; 117 | stunMsg.username.sizeValue = 10; 118 | strncpy(stunMsg.username.value, "testPerson", stunMsg.username.sizeValue); 119 | stunMsg.username.value[stunMsg.username.sizeValue]= '\0'; 120 | stunMsg.hasPriority = true; 121 | stunMsg.priority.value = 1; 122 | 123 | bool fromRelay = false; 124 | 125 | fail_unless (StunServer_HandleStunIncomingBindReqMsg(stunInstance, 126 | &pReq, 127 | &stunMsg, 128 | fromRelay)); 129 | 130 | char ufrag[STUN_MAX_STRING] = "testPerson"; 131 | fail_unless (strcmp(pReq.ufrag, ufrag) == 0); 132 | 133 | //fail_unless (stunInstance->stats.BindReqReceived); 134 | //fail_unless (stunInstance->stats.BindReqReceived_ViaRelay == 0); 135 | 136 | fromRelay = true; 137 | fail_unless (StunServer_HandleStunIncomingBindReqMsg(stunInstance, 138 | &pReq, 139 | &stunMsg, 140 | fromRelay)); 141 | 142 | //fail_unless (stunInstance->stats.BindReqReceived == 2); 143 | //fail_unless (stunInstance->stats.BindReqReceived_ViaRelay == 1); 144 | } 145 | END_TEST 146 | 147 | 148 | START_TEST (HandleReq_InValid) 149 | { 150 | STUN_INCOMING_REQ_DATA pReq; 151 | StunMessage stunMsg; 152 | stunMsg.hasUsername = false; 153 | stunMsg.username.sizeValue = 10; 154 | strncpy(stunMsg.username.value, "testPerson", stunMsg.username.sizeValue); 155 | stunMsg.username.value[stunMsg.username.sizeValue]= '\0'; 156 | stunMsg.hasPriority = true; 157 | stunMsg.priority.value = 1; 158 | 159 | bool fromRelay = false; 160 | 161 | fail_unless (!StunServer_HandleStunIncomingBindReqMsg(stunInstance, 162 | &pReq, 163 | &stunMsg, 164 | fromRelay)); 165 | 166 | //fail_unless (stunInstance->stats.BindReqReceived == 0); 167 | //fail_unless (stunInstance->stats.BindReqReceived_ViaRelay == 0); 168 | 169 | fromRelay = true; 170 | stunMsg.hasUsername = true; 171 | stunMsg.hasPriority = false; 172 | fail_unless (!StunServer_HandleStunIncomingBindReqMsg(stunInstance, 173 | &pReq, 174 | &stunMsg, 175 | fromRelay)); 176 | 177 | //fail_unless (stunInstance->stats.BindReqReceived == 0); 178 | //fail_unless (stunInstance->stats.BindReqReceived_ViaRelay == 0); 179 | } 180 | END_TEST 181 | 182 | 183 | START_TEST (SendResp_Valid) 184 | { 185 | bool useRelay = false; 186 | 187 | 188 | 189 | fail_unless (StunServer_SendConnectivityBindingResp(stunInstance, 190 | 0, // sockhandle 191 | LastTransId, 192 | "pem", 193 | (struct sockaddr *)&stunServerAddr, 194 | (struct sockaddr *)&stunServerAddr, 195 | NULL, 196 | SendRawStun, 197 | useRelay, 198 | 0, // responseCode 199 | NULL)); 200 | 201 | } 202 | END_TEST 203 | 204 | START_TEST (SendDiscussResp_Valid) 205 | { 206 | bool useRelay = false; 207 | 208 | discussData.streamType=0x004; 209 | discussData.interactivity=0x01; 210 | 211 | discussData.networkStatus_flags = 0; 212 | discussData.networkStatus_nodeCnt = 0; 213 | discussData.networkStatus_tbd = 0; 214 | discussData.networkStatus_upMaxBandwidth = 0; 215 | discussData.networkStatus_downMaxBandwidth = 0; 216 | 217 | 218 | fail_unless (StunServer_SendConnectivityBindingResp(stunInstance, 219 | 0, // sockhandle 220 | LastTransId, 221 | "pem", 222 | (struct sockaddr *)&stunServerAddr, 223 | (struct sockaddr *)&stunServerAddr, 224 | NULL, 225 | SendRawStun, 226 | useRelay, 227 | 0, // responseCode 228 | &discussData)); 229 | 230 | } 231 | END_TEST 232 | 233 | 234 | 235 | START_TEST (SendResp_InValid) 236 | { 237 | 238 | } 239 | 240 | END_TEST 241 | Suite * stunserver_suite (void) 242 | { 243 | Suite *s = suite_create ("Stunserver"); 244 | 245 | 246 | {/* handle request */ 247 | 248 | TCase *ss_handleReq = tcase_create ("Stunserver handle incomming request"); 249 | 250 | tcase_add_checked_fixture (ss_handleReq, setup, teardown); 251 | 252 | tcase_add_test (ss_handleReq, HandleReq_Valid); 253 | tcase_add_test (ss_handleReq, HandleReq_InValid); 254 | 255 | suite_add_tcase (s, ss_handleReq); 256 | 257 | } 258 | 259 | {/* send response */ 260 | 261 | TCase *ss_sendResp = tcase_create ("Stunserver send response"); 262 | 263 | tcase_add_checked_fixture (ss_sendResp, setup, teardown); 264 | 265 | tcase_add_test (ss_sendResp, SendResp_Valid); 266 | tcase_add_test (ss_sendResp, SendResp_InValid); 267 | 268 | suite_add_tcase (s, ss_sendResp); 269 | 270 | } 271 | 272 | {/* send response IPv6*/ 273 | 274 | TCase *ss_sendRespIPv6 = tcase_create ("Stunserver send response IPv6"); 275 | 276 | tcase_add_checked_fixture (ss_sendRespIPv6, setupIPv6, teardownIPv6); 277 | 278 | tcase_add_test (ss_sendRespIPv6, SendResp_Valid); 279 | tcase_add_test (ss_sendRespIPv6, SendResp_InValid); 280 | 281 | suite_add_tcase (s, ss_sendRespIPv6); 282 | 283 | } 284 | {/* send Discuss response */ 285 | 286 | TCase *ss_sendDiscussResp = tcase_create ("Stunserver send Discuss response"); 287 | 288 | tcase_add_checked_fixture (ss_sendDiscussResp, setup, teardown); 289 | 290 | tcase_add_test (ss_sendDiscussResp, SendDiscussResp_Valid); 291 | 292 | 293 | suite_add_tcase (s, ss_sendDiscussResp); 294 | 295 | } 296 | 297 | return s; 298 | } 299 | -------------------------------------------------------------------------------- /stunlib/test/turn_message.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "stunlib.h" 9 | 10 | Suite * turnmessage_suite (void); 11 | 12 | 13 | static unsigned char allocate_resp[] = 14 | "\x01\x03\x00\x5c" 15 | "\x21\x12\xa4\x42" 16 | "\x64\x3c\x98\x69" 17 | "\x00\x01\x00\x00" 18 | "\x07\x5d\xfe\x0c" 19 | "\x00\x16\x00\x08" 20 | "\x00\x01\xf3\x10" 21 | "\x7c\x4f\xc4\x88" 22 | "\x00\x0d\x00\x04" 23 | "\x00\x00\x02\x58" 24 | "\x00\x20\x00\x08" 25 | "\x00\x01\x6d\x8a" 26 | "\x74\xb4\x2c\xa0" 27 | "\x80\x22\x00\x1d" 28 | "\x72\x65\x73\x74" 29 | "\x75\x6e\x64\x20" 30 | "\x76\x30\x2e\x31" 31 | "\x2e\x30\x20\x28" 32 | "\x78\x38\x36\x5f" 33 | "\x36\x34\x2f\x6c" 34 | "\x69\x6e\x75\x78" 35 | "\x29\x00\x00\x00" 36 | "\x00\x08\x00\x14" 37 | "\x9d\x89\xb4\x21" 38 | "\x26\x5c\xe2\x20" 39 | "\xd0\x45\xc1\x2c" 40 | "\x98\xbd\xcd\x2f" 41 | "\xce\xb4\x8f\x50"; 42 | 43 | static unsigned char requested_addrFamilyReq[] = 44 | "\x01\x03\x00\x28" 45 | "\x21\x12\xa4\x42" 46 | "\x64\x3c\x98\x69" 47 | "\x00\x01\x00\x00" 48 | "\x07\x5d\xfe\x0c" 49 | "\x00\x17\x00\x04" 50 | "\x01\x00\x00\x00" 51 | "\x00\x08\x00\x14" 52 | "\x1c\xea\x86\x3f" 53 | "\x2e\xc8\x4f\x3d" 54 | "\xbd\x85\x8c\x41" 55 | "\x3a\x4a\xe9\xbc" 56 | "\xd4\xa1\x28\xa6" 57 | "\x80\x28\x00\x04" 58 | "\x38\x98\xd0\x62"; 59 | 60 | 61 | static unsigned char requested_addrFamilyReq_IPv6[] = 62 | "\x01\x03\x00\x28" 63 | "\x21\x12\xa4\x42" 64 | "\x64\x3c\x98\x69" 65 | "\x00\x01\x00\x00" 66 | "\x07\x5d\xfe\x0c" 67 | "\x00\x17\x00\x04" 68 | "\x02\x00\x00\x00" 69 | "\x00\x08\x00\x14" 70 | "\xfc\x8f\x30\x45" 71 | "\x80\x06\x80\x29" 72 | "\x97\x6b\x5c\x90" 73 | "\xd2\x19\xc0\xba" 74 | "\x7c\x37\x6e\xab" 75 | "\x80\x28\x00\x04" 76 | "\xd3\x60\x20\xf1"; 77 | 78 | static char password[] = "pem\0"; 79 | static char user[] = "pem\0"; 80 | static char realm[] = "medianetworkservices.com\0"; 81 | 82 | 83 | static const unsigned char idOctet[] = 84 | "\x64\x3c\x98\x69" 85 | "\x00\x01\x00\x00" 86 | "\x07\x5d\xfe\x0c" 87 | "\x00\x16"; 88 | 89 | const char *software_restund= "restund v0.1.0 (x86_64/linux)\0"; 90 | 91 | START_TEST(encode_integrity) 92 | { 93 | StunMessage stunMsg, decodeStunMsg; 94 | 95 | unsigned char stunBuf[120]; 96 | struct sockaddr_storage a,b; 97 | 98 | sockaddr_initFromString((struct sockaddr*)&a, 99 | "85.166.136.226:19608"); 100 | 101 | 102 | sockaddr_initFromString((struct sockaddr*)&b, 103 | "93.93.96.202:53762"); 104 | 105 | 106 | 107 | memset(&stunMsg, 0, sizeof(StunMessage)); 108 | 109 | 110 | stunMsg.msgHdr.msgType = STUN_MSG_AllocateResponseMsg; 111 | memcpy(&stunMsg.msgHdr.id.octet,&idOctet,12); 112 | 113 | /*Relay Address*/ 114 | stunMsg.hasXorRelayAddressIPv4 = true; 115 | stunlib_setIP4Address(&stunMsg.xorRelayAddressIPv4, 116 | htonl(((struct sockaddr_in *)&b)->sin_addr.s_addr), 117 | htons(((struct sockaddr_in *)&b)->sin_port)); 118 | 119 | /*Lifetime*/ 120 | stunMsg.hasLifetime = true; 121 | stunMsg.lifetime.value = 600; 122 | 123 | 124 | /*Mapped Address*/ 125 | stunMsg.hasXorMappedAddress = true; 126 | stunlib_setIP4Address(&stunMsg.xorMappedAddress, 127 | htonl(((struct sockaddr_in *)&a)->sin_addr.s_addr), 128 | htons(((struct sockaddr_in *)&a)->sin_port)); 129 | 130 | 131 | 132 | 133 | fail_unless( stunlib_addSoftware(&stunMsg, software_restund, '\x20') ); 134 | 135 | 136 | fail_unless( stunlib_encodeMessage(&stunMsg, 137 | stunBuf, 138 | 120, 139 | (unsigned char*)password, 140 | strlen(password), 141 | NULL)); 142 | 143 | 144 | 145 | fail_unless( stunlib_DecodeMessage( stunBuf, 146 | 120, 147 | &decodeStunMsg, 148 | NULL, 149 | NULL )); 150 | 151 | fail_unless( stunlib_checkIntegrity(stunBuf, 152 | 120, 153 | &decodeStunMsg, 154 | (unsigned char*)password, 155 | sizeof(password)) ); 156 | 157 | 158 | } 159 | END_TEST 160 | 161 | START_TEST(decode_integrity) 162 | { 163 | 164 | StunMessage stunMsg; 165 | int keyLen = 16; 166 | char md5[keyLen]; 167 | 168 | 169 | 170 | stunlib_createMD5Key((unsigned char *)md5, user, realm, password); 171 | 172 | fail_unless( stunlib_DecodeMessage( allocate_resp, 173 | sizeof(allocate_resp), 174 | &stunMsg, 175 | NULL, 176 | NULL)); 177 | 178 | fail_unless( stunlib_checkIntegrity(allocate_resp, 179 | sizeof(allocate_resp), 180 | &stunMsg, 181 | (unsigned char*)md5, 182 | keyLen) ); 183 | 184 | } 185 | END_TEST 186 | 187 | START_TEST(encode_requestedAddrFamily) 188 | { 189 | StunMessage stunMsg, decodeStunMsg; 190 | 191 | unsigned char stunBuf[120]; 192 | 193 | memset(&stunMsg, 0, sizeof(StunMessage)); 194 | 195 | 196 | stunMsg.msgHdr.msgType = STUN_MSG_AllocateResponseMsg; 197 | memcpy(&stunMsg.msgHdr.id.octet,&idOctet,12); 198 | 199 | /*Add RequestedAddrFamily*/ 200 | fail_if( stunlib_addRequestedAddrFamily(&stunMsg, 76) ); 201 | fail_unless( stunlib_addRequestedAddrFamily(&stunMsg, AF_INET) ); 202 | 203 | fail_unless( stunlib_encodeMessage(&stunMsg, 204 | stunBuf, 205 | 120, 206 | (unsigned char*)password, 207 | strlen(password), 208 | NULL)); 209 | 210 | fail_unless( memcmp(stunBuf, requested_addrFamilyReq, 60 ) == 0 ); 211 | } 212 | END_TEST 213 | 214 | START_TEST(encode_requestedAddrFamily_IPv6) 215 | { 216 | StunMessage stunMsg, decodeStunMsg; 217 | 218 | unsigned char stunBuf[120]; 219 | 220 | memset(&stunMsg, 0, sizeof(StunMessage)); 221 | 222 | 223 | stunMsg.msgHdr.msgType = STUN_MSG_AllocateResponseMsg; 224 | memcpy(&stunMsg.msgHdr.id.octet,&idOctet,12); 225 | 226 | /*Add RequestedAddrFamily*/ 227 | fail_if( stunlib_addRequestedAddrFamily(&stunMsg, 76) ); 228 | fail_unless( stunlib_addRequestedAddrFamily(&stunMsg, AF_INET6) ); 229 | 230 | fail_unless( stunlib_encodeMessage(&stunMsg, 231 | stunBuf, 232 | 120, 233 | (unsigned char*)password, 234 | strlen(password), 235 | NULL)); 236 | 237 | fail_unless( memcmp(stunBuf, requested_addrFamilyReq_IPv6, 60 ) == 0 ); 238 | } 239 | END_TEST 240 | 241 | 242 | START_TEST(decode_requestedAddrFamily) 243 | { 244 | StunMessage stunMsg; 245 | 246 | fail_unless( stunlib_DecodeMessage( requested_addrFamilyReq, 247 | 60, 248 | &stunMsg, 249 | NULL, 250 | NULL )); 251 | 252 | fail_unless( stunMsg.hasRequestedAddrFamilyIPv4 ); 253 | fail_unless( stunMsg.requestedAddrFamilyIPv4.family == 0x1 ); 254 | 255 | } 256 | END_TEST 257 | 258 | 259 | START_TEST(decode_requestedAddrFamily_IPv6) 260 | { 261 | StunMessage stunMsg; 262 | 263 | fail_unless( stunlib_DecodeMessage( requested_addrFamilyReq_IPv6, 264 | 60, 265 | &stunMsg, 266 | NULL, 267 | NULL )); 268 | 269 | fail_unless( stunMsg.hasRequestedAddrFamilyIPv6 ); 270 | fail_unless( stunMsg.requestedAddrFamilyIPv6.family == 0x2 ); 271 | 272 | } 273 | END_TEST 274 | 275 | 276 | 277 | 278 | Suite * turnmessage_suite (void){ 279 | 280 | Suite *s = suite_create ("TURN message"); 281 | 282 | {/* INTEGRITY */ 283 | 284 | TCase *tc_integrity = tcase_create ("Alloctate Sucsess Integrity"); 285 | 286 | tcase_add_test (tc_integrity, encode_integrity); 287 | tcase_add_test (tc_integrity, decode_integrity); 288 | 289 | suite_add_tcase (s, tc_integrity); 290 | 291 | } 292 | {/* Requested Addr Family */ 293 | 294 | TCase *tc_requestedAddrFamily = tcase_create ("Requested Address Family"); 295 | 296 | tcase_add_test (tc_requestedAddrFamily, encode_requestedAddrFamily); 297 | tcase_add_test (tc_requestedAddrFamily, encode_requestedAddrFamily_IPv6); 298 | 299 | tcase_add_test (tc_requestedAddrFamily, decode_requestedAddrFamily); 300 | tcase_add_test (tc_requestedAddrFamily, decode_requestedAddrFamily_IPv6); 301 | 302 | suite_add_tcase (s, tc_requestedAddrFamily); 303 | 304 | } 305 | return s; 306 | } 307 | -------------------------------------------------------------------------------- /testcoverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #./configure --with-check --enable-gcov 3 | make clean 4 | make check 5 | 6 | lcov --directory sockaddrutil --directory stunlib --directory icelib --capture --output-file natlib.info 7 | 8 | genhtml --output-directory lcov --no-branch-coverage natlib.info 9 | -------------------------------------------------------------------------------- /valgrind-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Run in valgrind, with leak checking enabled 4 | libtool --mode=execute valgrind -q --leak-check=full "$@" 2> .valgrind-log 5 | 6 | # Save the test result 7 | result="$?" 8 | 9 | # Valgrind should generate no error messages 10 | log_contents="`cat .valgrind-log`" 11 | 12 | if [ "$log_contents" != "" ]; then 13 | cat .valgrind-log >&2 14 | result=1 15 | fi 16 | 17 | rm -f .valgrind-log 18 | 19 | exit $result 20 | --------------------------------------------------------------------------------