Giter Site home page Giter Site logo

stun's Introduction

STUN

CI Coverage Status Hex version

STUN and TURN library for Erlang / Elixir.

Both STUN (Session Traversal Utilities for NAT) and TURN standards are used as technics to establish media connection between peers for VoIP (for example using SIP or Jingle) and WebRTC.

They are part of a more general negotiation technique know as ICE (Interactive Connectivity Establishment).

To summarize:

  • A STUN server is used to get an external network address. It does not serve as a relay for the media traffic.
  • TURN servers are used to relay traffic if direct (peer to peer) connection fails.

Build

This is a pure Erlang implementation, so you do not need to have specific C libraries installed for the STUN, TURN, ICE code.

However, this code depends on ProcessOne Fast TLS, which depends on OpenSSL 1.0.0+ library.

Generic build

You can trigger build with:

make

Usage

The following sequence describe a STUN establishment.

First, start the application and stun listener at 127.0.0.1:

1> application:start(stun).
ok
2> stun_listener:add_listener({127, 0, 0, 1}, 3478, udp, []).
ok

Then, you can form and send a BindRequest:

3> rr(stun).
[state,stun,turn]
4> random:seed(erlang:timestamp()).
undefined

You can form a transaction id. Should be always 96 bit:

5> TrID = random:uniform(1 bsl 96).
41809861624941132369239212033

You then create a BindRequest message.

16#001 is ?STUN_METHOD_BINDING, defined in include/stun.hrl

6> Msg = #stun{method = 16#001, class = request, trid = TrID}.
#stun{class = request,method = 1,magic = 554869826,
     trid = 41809861624941132369239212033,raw = <<>>,
     unsupported = [],'ALTERNATE-SERVER' = undefined,
     'CHANNEL-NUMBER' = undefined,'DATA' = undefined,
     'DONT-FRAGMENT' = false,'ERROR-CODE' = undefined,
     'LIFETIME' = undefined,'MAPPED-ADDRESS' = undefined,
     'MESSAGE-INTEGRITY' = undefined,'NONCE' = undefined,
     'REALM' = undefined,'REQUESTED-TRANSPORT' = undefined,
     'SOFTWARE' = undefined,'UNKNOWN-ATTRIBUTES' = [],
     'USERNAME' = undefined,'XOR-MAPPED-ADDRESS' = undefined,
     'XOR-PEER-ADDRESS' = [],'XOR-RELAYED-ADDRESS' = undefined}

You can then establish connection to running server:

7> {ok, Socket} = gen_udp:open(0, [binary, {ip,
7> {127,0,0,1}},{active,false}]).
{ok,#Port<0.1020>}
8> {ok, Addr} = inet:sockname(Socket).
{ok,{{127,0,0,1},41906}}

The following call is for encoding BindRequest:

9> PktOut = stun_codec:encode(Msg).
<<0,1,0,0,33,18,164,66,135,24,78,148,65,4,128,0,0,0,0,1>>

The BindRequest can then be send:

10> gen_udp:send(Socket, {127,0,0,1}, 3478, PktOut).
ok

The follow code receives the BindResponse:

11> {ok, {_, _, PktIn}} = gen_udp:recv(Socket, 0).
{ok,{{127,0,0,1},
    3478,
    <<1,1,0,32,33,18,164,66,135,24,78,148,65,4,128,0,0,0,0,
      1,128,34,0,15,...>>}}

You can then decode the BindResponse:

12> {ok, Response} = stun_codec:decode(PktIn, datagram).
{ok,#stun{class = response,method = 1,magic = 554869826,
         trid = 41809861624941132369239212033,raw = <<>>,
         unsupported = [],'ALTERNATE-SERVER' = undefined,
         'CHANNEL-NUMBER' = undefined,'DATA' = undefined,
         'DONT-FRAGMENT' = false,'ERROR-CODE' = undefined,
         'LIFETIME' = undefined,'MAPPED-ADDRESS' = undefined,
         'MESSAGE-INTEGRITY' = undefined,'NONCE' = undefined,
         'REALM' = undefined,'REQUESTED-TRANSPORT' = undefined,
         'SOFTWARE' = <<"P1 STUN library">>,
         'UNKNOWN-ATTRIBUTES' = [],'USERNAME' = undefined,
         'XOR-MAPPED-ADDRESS' = {{127,0,0,1},41906},
         'XOR-PEER-ADDRESS' = [],'XOR-RELAYED-ADDRESS' = undefined}}

Finally, checking 'XOR-MAPPED-ADDRESS' attribute, should be equal to locally binded address:

13> Addr == Response#stun.'XOR-MAPPED-ADDRESS'.
true

Development

Test

Unit test

You can run eunit test with the command:

make test

References

You can refer to IETF specifications to learn more:

  • RFC 5389: Session Traversal Utilities for NAT (STUN).
  • RFC 5766: Traversal Using Relays around NAT (TURN): Relay Extensions to STUN.
  • RFC 5245: Interactive Connectivity Establishment (ICE): A Protocol for NAT Traversal for Offer/Answer Protocols.
  • RFC 6544: TCP Candidates with Interactive Connectivity Establishment (ICE)

stun's People

Contributors

alexeyshch avatar annikahannig avatar badlop avatar facundoolano avatar fredrikaugust avatar jamielinux avatar jesseherrick avatar mremond avatar octosteve avatar prefiks avatar quanzhuo avatar santosh653 avatar triaxx avatar wcy123 avatar weiss avatar zinid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stun's Issues

lots of error_logger:info_msg logs

Hi, I'm using this app to provide a STUN/TURN server for a WebRTC client. When a client connects I get a lot of logs like:

accepted long-term STUN authentication for user
created TURN allocation for user
deleting TURN allocation for  user
created/updated TURN permission for user 

Those look as debug logs to me, is there a special reason for them to use error_logger:info_msg directly instead of ?dbg()?

I can send a PR turning them to ?dbg if you are OK with it.

Error compiling with rebar3

Hi,

Running rebar3 compile causes this error:

===> Verifying dependencies...
===> Compiling stun
===> Compiling /Users/rogerioyokomizo/projects/stun/c_src/*.c
===> clang: error: no such file or directory: 'c_src/*.c'
clang: error: no input files

Turning provider_hooks off solves the problem:
https://github.com/processone/stun/blob/master/rebar.config.script#L106

- {[provider_hooks], IsRebar3,
-	  AppendList([{pre, [
-			     {compile, {pc, compile}},
-			     {clean, {pc, clean}}
-			    ]}]), []},

IPv6 for TURN

Can you add IPv6 support in more IPv4?

And an update of all supported RFCs: https://www.process-one.net/en/ejabberd/protocols/.

There are for TURN:

Maybe I have forgotten some.

no longer compiles with elixir 1.0.5

I haven't recompiled ejabberd with elixir in a couple of weeks. Now, when I try to compile it, I get the following error:

==> p1_stun (compile)
src/stun_listener.erl:39: type dict() undefined
ERROR: compile failed while processing /home/jadams/projects/concur.io/concurio_jabber/deps/p1_stun: rebar_abort
** (Mix) Could not compile dependency p1_stun, /home/jadams/bin/rebar command failed. If you want to recompile this dependency, please run: mix deps.compile p1_stun

Phoenix deps compile fast_tls issue on windows

I was following along to a blog to install an erlang stun component using mix on
Windows 10.

ref:
https://littlelines.com/blog/2020/07/06/building-a-video-chat-app-in-phoenix-liveview

In brief:

after adding # {:stun, "~> 1.0"} to mix.xs and running mix deps.get then mix compile
I received an error message while trying to run what appears to be a batch compile
executable called cl.exe that the dependency fast_tls.c, could not be compiled due to
missing c (++?) header files (eg stdio.h ...), On further investigation this appeared to
be due to the Microsoft Visual Studio MVSC compiler tools not being in place, and
after installing some of the Microsoft Visual Studio core, I managed to create a dummy project and access the command line within the Microsoft Visual Studio env and re-ran the mix command. This appeared to advance things a little and the next error was due
to the missing openssl src files. I then applied the fix I saw to the Mac homebrew settings:

 export LDFLAGS="-L/usr/local/opt/openssl/lib -L/usr/local/lib -L/usr/local/opt/expat/lib"
 export CFLAGS="-I/usr/local/opt/openssl/include/ -I/usr/local/include -I/usr/local/opt/expat/include"
 export CPPFLAGS="-I/usr/local/opt/openssl/include/ -I/usr/local/include -I/usr/local/opt/expat/include"

for the windows environment. And then re-ran the mix compile.
But now it is clear that the MSVC compiler presumable called by the cl.exe batch file
will not allow the fast_stl.c source file to compile. Apart from spitting out a host of warnings it stops compilation with essentially these error messages:

c:/Users/Paul/Desktop/phoenix/els_umbrella/deps/fast_tls/c_src/fast_tls.c(484): error C2057: expected constant expression
c:/Users/Paul/Desktop/phoenix/els_umbrella/deps/fast_tls/c_src/fast_tls.c(484): error C2466: cannot allocate an array of constant size 0
c:/Users/Paul/Desktop/phoenix/els_umbrella/deps/fast_tls/c_src/fast_tls.c(484): error C2133: 'name': unknown size

This appears to tell me that this particular compiler is too picky when looking a memory allocation for data structures such as arrays?

Well, I was just wondering if there is another way to go to compile this source code on a Windows 10 machine without using Visual Studio? I've tried changing the so-called Platform toolset (to LLVM clang-cl an alternative lib offered by Visual Study) but this has not effect. I don't want to have to doctor the fast_tls.c code since quite clearly it compiles fine on other platforms. Or, has anyone had a similar experience in trying to compile this mix dep on a Windows platform?

Best regards.

Paul.

Originally posted by @philipmoniaga in processone/ejabberd#1107 (comment)

Failing test on Fedora Rawhide

Greetings!

I am working on updating stun in Fedora Rawhide, and I'm having a failing unit test:

/usr/bin/rebar eunit skip_deps=true -v
==> stun-1.0.23 (eunit)                   
INFO:  sh info:      
        cwd: "/home/bowlofeggs/rpmbuild/BUILD/stun-1.0.23"
        cmd: cp -R src/turn_tmp_sup.erl src/turn_sm.erl src/turn.erl src/stun_tmp_sup.erl src/stun_test.erl src/stun_sup.erl src/stun_shaper.erl src/stun_listener.erl src/stun_codec.erl src/stun_app.erl src/stun.erl ".eunit"
INFO:  Cover compiling /home/bowlofeggs/rpmbuild/BUILD/stun-1.0.23
======================== EUnit ========================
module 'stun'
module 'stun_test'
  stun_test: init_test...[0.030 s] ok
  stun_test: mk_cert_test...ok
  stun_test: add_udp_listener_test...ok
  stun_test: add_tcp_listener_test...[0.001 s] ok
  stun_test: add_tls_listener_test...ok
  stun_test: bind_udp_test...[0.001 s] ok
  stun_test: bind_tcp_test...
=INFO REPORT==== 29-Jul-2018::20:17:51 ===
accepted connection: 127.0.0.1:57465 -> 127.0.0.1:34780ok
  stun_test: bind_tls_test...
=INFO REPORT==== 29-Jul-2018::20:17:51 ===
accepted connection: 127.0.0.1:55111 -> 127.0.0.1:53490*failed*
in function stun_test:'-bind_tls_test/0-fun-1-'/2 (src/stun_test.erl, line 109)
in call from stun_test:bind_tls_test/0 (src/stun_test.erl, line 109)
**error:{assertEqual,[{module,stun_test},
              {line,109},
              {expression,"fast_tls : send ( TLSSocket , Pkt )"},
              {expected,ok},
              {value,{error,closed}}]}
  output:<<"">>

  stun_test: del_tcp_listener_test...ok
  stun_test: del_tls_listener_test...ok
  stun_test: allocate_udp_test...[0.005 s] ok
  [done in 0.200 s]
module 'stun_codec'
module 'stun_app'
module 'turn'
module 'stun_listener'
module 'stun_shaper'
module 'stun_sup'
module 'turn_sm'
module 'stun_tmp_sup'
module 'turn_tmp_sup'
=======================================================
  Failed: 1.  Skipped: 0.  Passed: 10.
Cover analysis: /home/bowlofeggs/rpmbuild/BUILD/stun-1.0.23/.eunit/index.html
Coverdata export: /home/bowlofeggs/rpmbuild/BUILD/stun-1.0.23/.eunit/cover.coverdata

=INFO REPORT==== 29-Jul-2018::20:17:51 ===
    application: fast_tls
    exited: killed
    type: temporary

=INFO REPORT==== 29-Jul-2018::20:17:51 ===
    application: p1_utils
    exited: killed
    type: temporary

=INFO REPORT==== 29-Jul-2018::20:17:51 ===
    application: stun
    exited: killed
    type: temporary
ERROR: One or more eunit tests failed.
ERROR: eunit failed while processing /home/bowlofeggs/rpmbuild/BUILD/stun-1.0.23: rebar_abort

I also saw a failing test with fast_tls, which seems like it might be relevant:

processone/fast_tls#35

Here are some of the dependencies installed:

erlang-20.3.8.2
erlang-fast_tls-1.0.23-1.fc29.x86_64
erlang-p1_utils-1.0.12-1.fc29.noarch
erlang-rebar-2.6.4-6.fc28.x86_64

ejabberd_stun crashing with badfun,undefined when receiving unexpected TURN packet

What version of ejabberd are you using?

17.07

What operating system (version) are you using?

Ubuntu 17.04

How did you install ejabberd (source, package, distribution)?

Package

What did not work as expected? Are there error messages in the log? What
was the unexpected behavior? What was the expected result?

When a TURN message with credentials is received but use_turn has not been explicitly set to true in ejabberd, the STUN process crashes:

2017-08-07 15:00:50.678 [error] <0.6671.1>@ejabberd_listener:udp_recv:319 failed to process UDP packet:
** Source: {{192,0,2,1}, 49745}
** Reason: {{badfun,undefined},[{stun,process,2,[{file,"src/stun.erl"},{line,232}]},{ejabberd_listener,udp_recv,3,[{file,"src/ejabberd_listener.erl"},{line,317}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,247}]}]}
** Packet: <<0,3,0,76,33,18,164,66,147,192,145,48,234,247,85,140,228,23,150,152,0,25,0,4,17,0,0,0,0,13,0,4,0,0,14,16,0,6,0,4,115,116,117,110,0,20,0,0,0,21,0,10,50,49,54,48,54,50,54,48,51,53,0,0,0,8,0,20,68,53,203,248,222,198,133,165,142,12,108,151,149,81,179,52,15,9,126,19,128,40,0,4,209,187,56,199>>

It seems that AuthFunc is not set, and its absence is not properly handled.

Logging issues

Hello.
My setup: ejabberd 20.07 with stun 1.0.38. compiled using rebar 2.6.4, Erlang/OTP version 23.1.

In ejabberd.yml I have: loglevel: info

The issue is that I don't see info level messages from the stun/turn library module in logs. I see only notice level ones.

For example, I see

[notice] <0.566.0>@turn:wait_for_allocate/2:194 Creating TURN allocation (lifetime: 600 seconds)
[notice] <0.565.0>@turn:terminate/3:446 Relayed 244 KiB (in 3296 B / 42 packets, out 247058 B / 2370 packets), duration: 47 seconds

but I don't see such messages as "Accepting long-term STUN/TURN authentication" as in previous versions (before switching to new logging API on Erlang/OTP 22+).

I see these messages in logs only if I manually change ?LOG_INFO to ?LOG_NOTICE in the code and recompile the stun library.

rebar debug output shows that erlang version is correctly identified as 23:

DEBUG: Matched required ERTS version: 11.1 -> .*
DEBUG: Matched required OTP release: 23 -> .*
DEBUG: Min OTP version unconfigured
DEBUG: erl_opts [debug_info,debug_info,{i,"include"},{d,'RAND_UNIFORM'}]
DEBUG: Files to compile first: []
DEBUG: Starting 3 compile worker(s)

Also the changelog states that: Add session ID, transport, username, and IP addresses to log output.
But I don't see such info. In my example you can see plain "Creating TURN allocation (lifetime: 600 seconds)" without additional info.

IPv6 for STUN

Can you add IPv6 support in more IPv4?

And an update of all supported RFCs: https://www.process-one.net/en/ejabberd/protocols/.

There are for STUN:

Maybe I have forgotten some.

hex.pm documentation page for stun shows error message

The hex.pm page for stun points at https://hexdocs.pm/stun/ and is returning errors with the text

  PAGE NOT FOUND
  Is something wrong with the package documentation? Open an issue on the project 
  the documentation belongs to. Most packages link to their repository from their 
  hex.pm page.

This impacts all releases of the stun documentation there from verson 1.0.31 as far as I can tell.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.