{"id":15470464,"url":"https://github.com/processone/stun","last_synced_at":"2025-05-14T20:09:21.563Z","repository":{"id":7843747,"uuid":"9215418","full_name":"processone/stun","owner":"processone","description":"STUN and TURN library for Erlang / Elixir","archived":false,"fork":false,"pushed_at":"2025-03-30T22:14:03.000Z","size":369,"stargazers_count":249,"open_issues_count":0,"forks_count":62,"subscribers_count":33,"default_branch":"master","last_synced_at":"2025-04-13T15:59:50.234Z","etag":null,"topics":["erlang","ice","stun","turn"],"latest_commit_sha":null,"homepage":"http://www.ejabberd.im","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/processone.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-04-04T10:00:32.000Z","updated_at":"2025-03-30T22:14:04.000Z","dependencies_parsed_at":"2024-01-23T13:39:59.368Z","dependency_job_id":"3875a532-c9ca-49a1-9c77-f2b2393cce02","html_url":"https://github.com/processone/stun","commit_stats":{"total_commits":287,"total_committers":17,"mean_commits":16.88235294117647,"dds":0.5714285714285714,"last_synced_commit":"356b681a050f751ff7116ec50c4682e630c2efe3"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/processone%2Fstun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/processone%2Fstun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/processone%2Fstun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/processone%2Fstun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/processone","download_url":"https://codeload.github.com/processone/stun/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248741200,"owners_count":21154252,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erlang","ice","stun","turn"],"created_at":"2024-10-02T02:04:49.841Z","updated_at":"2025-04-13T15:59:55.013Z","avatar_url":"https://github.com/processone.png","language":"Erlang","readme":"# STUN\n\n[![CI](https://github.com/processone/stun/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/processone/stun/actions/workflows/ci.yml)\n[![Coverage Status](https://coveralls.io/repos/processone/stun/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/processone/stun?branch=master)\n[![Hex version](https://img.shields.io/hexpm/v/stun.svg \"Hex version\")](https://hex.pm/packages/stun)\n\nSTUN and TURN library for Erlang / Elixir.\n\nBoth [STUN](https://en.wikipedia.org/wiki/STUN) (Session Traversal\nUtilities for NAT) and\n[TURN](https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT)\nstandards are used as technics to establish media connection between\npeers for VoIP (for example using\n[SIP](https://en.wikipedia.org/wiki/Session_Initiation_Protocol) or\n[Jingle](http://xmpp.org/about-xmpp/technology-overview/jingle/)) and\n[WebRTC](https://en.wikipedia.org/wiki/WebRTC).\n\nThey are part of a more general negotiation technique know as\n[ICE](https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment)\n(Interactive Connectivity Establishment).\n\nTo summarize:\n\n* A STUN server is used to get an external network address. It does\n  not serve as a relay for the media traffic.\n* TURN servers are used to relay traffic if direct (peer to peer)\n  connection fails.\n\n## Build\n\nThis is a pure Erlang implementation, so you do not need to have\nspecific C libraries installed for the STUN, TURN, ICE code.\n\nHowever, this code depends on ProcessOne\n[Fast TLS](https://github.com/processone/fast_tls), which depends on\nOpenSSL 1.0.0+ library.\n\n### Generic build\n\nYou can trigger build with:\n\n    make\n\n# Usage\n\nThe following sequence describe a STUN establishment.\n\nFirst, start the application and stun listener at 127.0.0.1:\n\n```\n1\u003e application:start(stun).\nok\n2\u003e stun_listener:add_listener({127, 0, 0, 1}, 3478, udp, []).\nok\n```\n\nThen, you can form and send a BindRequest:\n\n```\n3\u003e rr(stun).\n[state,stun,turn]\n4\u003e random:seed(erlang:timestamp()).\nundefined\n```\n\nYou can form a transaction id. Should be always 96 bit:\n\n```\n5\u003e TrID = random:uniform(1 bsl 96).\n41809861624941132369239212033\n```\n\nYou then create a BindRequest message.\n\n`16#001` is `?STUN_METHOD_BINDING`, defined in `include/stun.hrl`\n\n```\n6\u003e Msg = #stun{method = 16#001, class = request, trid = TrID}.\n#stun{class = request,method = 1,magic = 554869826,\n     trid = 41809861624941132369239212033,raw = \u003c\u003c\u003e\u003e,\n     unsupported = [],'ALTERNATE-SERVER' = undefined,\n     'CHANNEL-NUMBER' = undefined,'DATA' = undefined,\n     'DONT-FRAGMENT' = false,'ERROR-CODE' = undefined,\n     'LIFETIME' = undefined,'MAPPED-ADDRESS' = undefined,\n     'MESSAGE-INTEGRITY' = undefined,'NONCE' = undefined,\n     'REALM' = undefined,'REQUESTED-TRANSPORT' = undefined,\n     'SOFTWARE' = undefined,'UNKNOWN-ATTRIBUTES' = [],\n     'USERNAME' = undefined,'XOR-MAPPED-ADDRESS' = undefined,\n     'XOR-PEER-ADDRESS' = [],'XOR-RELAYED-ADDRESS' = undefined}\n```\n\nYou can then establish connection to running server:\n\n```\n7\u003e {ok, Socket} = gen_udp:open(0, [binary, {ip,\n7\u003e {127,0,0,1}},{active,false}]).\n{ok,#Port\u003c0.1020\u003e}\n8\u003e {ok, Addr} = inet:sockname(Socket).\n{ok,{{127,0,0,1},41906}}\n```\n\nThe following call is for encoding BindRequest:\n\n```\n9\u003e PktOut = stun_codec:encode(Msg).\n\u003c\u003c0,1,0,0,33,18,164,66,135,24,78,148,65,4,128,0,0,0,0,1\u003e\u003e\n```\n\nThe BindRequest can then be send:\n\n```\n10\u003e gen_udp:send(Socket, {127,0,0,1}, 3478, PktOut).\nok\n```\n\nThe follow code receives the BindResponse:\n\n```\n11\u003e {ok, {_, _, PktIn}} = gen_udp:recv(Socket, 0).\n{ok,{{127,0,0,1},\n    3478,\n    \u003c\u003c1,1,0,32,33,18,164,66,135,24,78,148,65,4,128,0,0,0,0,\n      1,128,34,0,15,...\u003e\u003e}}\n```\n\nYou can then decode the BindResponse:\n\n```\n12\u003e {ok, Response} = stun_codec:decode(PktIn, datagram).\n{ok,#stun{class = response,method = 1,magic = 554869826,\n         trid = 41809861624941132369239212033,raw = \u003c\u003c\u003e\u003e,\n         unsupported = [],'ALTERNATE-SERVER' = undefined,\n         'CHANNEL-NUMBER' = undefined,'DATA' = undefined,\n         'DONT-FRAGMENT' = false,'ERROR-CODE' = undefined,\n         'LIFETIME' = undefined,'MAPPED-ADDRESS' = undefined,\n         'MESSAGE-INTEGRITY' = undefined,'NONCE' = undefined,\n         'REALM' = undefined,'REQUESTED-TRANSPORT' = undefined,\n         'SOFTWARE' = \u003c\u003c\"P1 STUN library\"\u003e\u003e,\n         'UNKNOWN-ATTRIBUTES' = [],'USERNAME' = undefined,\n         'XOR-MAPPED-ADDRESS' = {{127,0,0,1},41906},\n         'XOR-PEER-ADDRESS' = [],'XOR-RELAYED-ADDRESS' = undefined}}\n```\n\nFinally, checking 'XOR-MAPPED-ADDRESS' attribute, should be equal to locally\nbinded address:\n\n```\n13\u003e Addr == Response#stun.'XOR-MAPPED-ADDRESS'.\ntrue\n```\n\n## Development\n\n### Test\n\n#### Unit test\n\nYou can run eunit test with the command:\n\n    make test\n\n# References\n\nYou can refer to IETF specifications to learn more:\n\n* [RFC 5389](https://tools.ietf.org/html/rfc5389): Session Traversal\n  Utilities for NAT (STUN).\n* [RFC 5766](https://tools.ietf.org/html/rfc5766): Traversal Using\n  Relays around NAT (TURN): Relay Extensions to STUN.\n* [RFC 5245](https://tools.ietf.org/html/rfc5245): Interactive\n  Connectivity Establishment (ICE): A Protocol for NAT Traversal for\n  Offer/Answer Protocols.\n* [RFC 6544](https://tools.ietf.org/html/rfc6544): TCP Candidates with\n  Interactive Connectivity Establishment (ICE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprocessone%2Fstun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprocessone%2Fstun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprocessone%2Fstun/lists"}