Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/processone/stun
STUN and TURN library for Erlang / Elixir
https://github.com/processone/stun
erlang ice stun turn
Last synced: about 1 month ago
JSON representation
STUN and TURN library for Erlang / Elixir
- Host: GitHub
- URL: https://github.com/processone/stun
- Owner: processone
- License: apache-2.0
- Created: 2013-04-04T10:00:32.000Z (over 11 years ago)
- Default Branch: master
- Last Pushed: 2024-07-17T08:59:40.000Z (4 months ago)
- Last Synced: 2024-10-08T14:42:04.588Z (about 1 month ago)
- Topics: erlang, ice, stun, turn
- Language: Erlang
- Homepage: http://www.ejabberd.im
- Size: 326 KB
- Stars: 244
- Watchers: 34
- Forks: 62
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# STUN
[![CI](https://github.com/processone/stun/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/processone/stun/actions/workflows/ci.yml)
[![Coverage Status](https://coveralls.io/repos/processone/stun/badge.svg?branch=master&service=github)](https://coveralls.io/github/processone/stun?branch=master)
[![Hex version](https://img.shields.io/hexpm/v/stun.svg "Hex version")](https://hex.pm/packages/stun)STUN and TURN library for Erlang / Elixir.
Both [STUN](https://en.wikipedia.org/wiki/STUN) (Session Traversal
Utilities for NAT) and
[TURN](https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT)
standards are used as technics to establish media connection between
peers for VoIP (for example using
[SIP](https://en.wikipedia.org/wiki/Session_Initiation_Protocol) or
[Jingle](http://xmpp.org/about-xmpp/technology-overview/jingle/)) and
[WebRTC](https://en.wikipedia.org/wiki/WebRTC).They are part of a more general negotiation technique know as
[ICE](https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment)
(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](https://github.com/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](https://tools.ietf.org/html/rfc5389): Session Traversal
Utilities for NAT (STUN).
* [RFC 5766](https://tools.ietf.org/html/rfc5766): Traversal Using
Relays around NAT (TURN): Relay Extensions to STUN.
* [RFC 5245](https://tools.ietf.org/html/rfc5245): Interactive
Connectivity Establishment (ICE): A Protocol for NAT Traversal for
Offer/Answer Protocols.
* [RFC 6544](https://tools.ietf.org/html/rfc6544): TCP Candidates with
Interactive Connectivity Establishment (ICE)