Giter Site home page Giter Site logo

esl / jerboa Goto Github PK

View Code? Open in Web Editor NEW
14.0 17.0 6.0 322 KB

STUN/TURN encoder, decoder and client library in Elixir

Home Page: https://www.erlang-solutions.com/products/mongooseim.html

License: Other

Elixir 99.90% Shell 0.10%
stun turn ice elixir client

jerboa's Introduction

Jerboa

Build Status Inline docs Coverage Status Ebert

Documentation

STUN/TURN encoder, decoder and client library by Erlang Solutions

Jerboa aims to provide simple APIs for common STUN/TURN use cases. It is used by Fennec for encoding and decoding of STUN messages, as well as a testing tool.

Installation

Jerboa is available on Hex. To use it, just add it to your dependencies:

def deps do
  [{:jerboa, "~> 0.3.0"}]
end

Checklist of STUN/TURN/ICE methods supported by Jerboa's encoder/decoder

  • Binding
  • Allocate
  • Refresh
  • Send
  • Data
  • CreatePermission
  • ChannelBind

Checklist of STUN/TURN/ICE attributes supported by Jerboa's encoder/decoder

Comprehension Required

  • XOR-MAPPED-ADDRESS
  • MESSAGE-INTEGRITY
  • ERROR-CODE
  • UNKNOWN-ATTRIBUTES
  • REALM
  • NONCE
  • CHANNEL-NUMBER
  • LIFETIME
  • XOR-PEER-ADDRESS
  • DATA
  • XOR-RELAYED-ADDRESS
  • EVEN-PORT
  • REQUESTED-TRANSPORT
  • DONT-FRAGMENT
  • RESERVATION-TOKEN
  • PRIORITY
  • USE-CANDIDATE
  • ICE-CONTROLLED
  • ICE-CONTROLLING

Comprehension Optional

  • SOFTWARE
  • ALTERNATE-SERVER
  • FINGERPRINT

License

Copyright 2016-2017 Erlang Solutions Ltd.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

jerboa's People

Contributors

acollectionofatoms avatar arkgil avatar erszcz avatar gustawlippa avatar michalwski avatar nelsonvides avatar

Stargazers

 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

jerboa's Issues

Implement missing TURN attributes required for server-side processing

Some of the TURN attributes which are not implemented yet must be validated by the server. Currently when Fennec encounters message with such attributes it will crash, because Jerboa raises on unknown RFC (as per RFC, unknown comprehension required attributes indicate that the message should be dropped).

For start, we need to implement three of them:

  • DONT-FRAGMENT - #68
  • RESERVATION-TOKEN - #69
  • EVEN-PORT - #70

Allow other values in REQUESTED-TRANSPORT :protocol field

Right now our implementation of REQUESTED-TRANSPORT attribute only allows :udp as a selected protocol. Every other value will raise during encoding, and raise or return an error when decoding such message.

It seemed convenient at the beginning - we aimed to be compliant only with original TURN RFC (for start) which allows only UDP as a requested relay transport.

However, this approach is not so good when working on a server side of things. There is a special error code which needs to be sent back by the server when it doesn't understand, provide or allow relay over requested transport protocol.

We need figure out how to decode this attribute when we don't know the protocol included, so that the server can use Jerboa to decode such message and respond appropriately.

Consider Moving Exceptions Near Where They're Used

When revising the documentation and on other occasions (recently) it would have been really helpful to see where we use the exception.

We moved them into their own file because we wanted shorter names.

To resolve both we can move them back into the same file as they're used but put them below the module they're used in. I.e. not nested in it.

List of supported STUN methods

To be fair with anyone using our library, we should keep a list of methods supported by it. It could be a checklist, so that we know what is left to implement.

Test w/ More Explicit Assertions

Some of our recent testing is more explicit and clearer:

  alias Jerboa.Test.Helper.XORMappedAddress, as: XORMAHelper
  alias Jerboa.Test.Helper.Attribute, as: AHelper

  test "IPv4 XORMappedAddress as a TLV" do
    attr = XORMAHelper.struct(4)

    bin = Attribute.encode %Format{}, attr

    assert type(bin) === 0x0020
    assert length_(bin) === AHelper.total(address: 32, other: 32)
  end

Older testing did something like the following (repetitive between cases too):

  test "IPv4 XORMappedAddress as a TLV" do
     f = :ipv4
     a = {0, 0, 0, 0}
     p = 0
     attr = %Attribute.XORMappedAddress{family: f, address: a, port: p}
 
     bin = Attribute.encode %Format{}, attr
 
     assert <<0x0020::16, 8::16, _::64>> = bin
   end

Let's change this everywhere with separate assertions (and improve the helper modules) for readability.

Rename Jerboa.Format struct

Currently %Jerboa.Format{} is a struct which carries information about decoded or not-yet-encoded STUN message. However its name does not represent its meaning.

@Dzol @michalwski any ideas?

Extract Common Test Helpers and Properties

Some helpers reside in the helper directory.

Where there are common helper functions, e.g. repeated across test files, let's move them under this directory. They could potentially help to isolate and build property test generators too.

Remove Attribute struct wrapper for decoded attributes

Right now all attributes are represented as (e.g.):

%Attribute{
  name: XORMappedAddress,
  value: %XORMappedAddress{...}  
}

which adds unnecessary complexity, because name of attribute could be easily taken out of value struct. My idea is to get rid of Attribute wrapper completely.

Validate arguments passed to Client.* functions

Right now there are not validations, so passing bad arguments results in crash of client process in most cases. We could also look into narrowing the scope of Client.ip, or create the new type for IPv4 addresses, because we don't support IPv6 TURN extension (yet?).

Introduce High Level Validation

Currently Jerboa only does encoding + decoding (all this is under the format directory) but there are higher level concerns.

Only certain STUN classes are permissible on each STUN method (e.g. we can't have a binding indication). The Format modules are wholly and exclusively responsible for encoding + decoding so this is not their concern.

We need to introduce a layer to handle this logic which is more akin to the kind of validation a parser does (as opposed to a scanner/lexer which is sort of what we have at the moment).

Parts common to server and client can make their way into Jerboa (though I expect this is going to be quite thin).

Documentation for errors

Jerboa.Format.decode/1 returns various errors wrapped in a {:error, _} tuple, and Jerboa.Format.decode!/1 raises them. However these errors are not documented, so the only way to know what is wrong is to either read an error message or name of exception struct.

It would be nice to have each of errors documented, when they are raised etc. In addition we could improve typespecs of functions which may return those errors.

@Dzol @michalwski thoughts?

Client for binding method over UDP

Introduce a simple client process, talking only over UDP, using only binding requests. I think for now we should not be bothered by specific recommendations of RFC.

MESSAGE-INTEGRITY attribute

It seems that to support long-term credentials, which we certainly want to do, we need to implement MESSAGE-INTEGRITY attribute.

It's one of two "hardcore" attributes, meaning that it needs to be calculated after the rest of a message is encoded, which at this point breaks a flow of our encoder/decoder.

This is something which needs to be discussed.

Discussion

I've done an experiment with Protocols by using the to encoding/decoding the attributes. See protocol-based-attrs branch. I'm gonna look into it if it gives us any advantages.

Encoding/decoding for LIFETIME attribute

In https://tools.ietf.org/html/rfc5389#page-10 there is:

  def encode(p, a = %Attribute.XORMappedAddress{}) do
    encode_(0x0020, Attribute.XORMappedAddress.encode(p, a))
  end

  def decode(params, 0x0020, v) do
    Attribute.XORMappedAddress.decode params, v
  end

This task is about adding one clause to each of these functions, and creating a module with functions responsible for encoding and decoding Lifetime attribute's value, similar to what XORMappedAddress module does.

More info:

Implement an easy way to find out that the message integrity was verified

There are issues with server side processing of decoded messages, especially of current design of how verifying message integrity works. Currently there are three cases of decoding messages with MI:

  1. STUN message doesn't have message integrity attribute - in this case decoding will always pass and there is no way to know if we actually verified it or not
  2. STUN message has message integrity attribute, but required values (username, realm and secret) aren't in the message or aren't provided in options list - in this case decoding will fail

note: secret can only be provided in options list

  1. STUN message has message integrity; username, realm and secret are in the message or were provided in the options list but message integrity was invalid - again, decoding fails

there are actually 4 cases, the last one is when message integrity is successfully verified

This all works well with client side code, because TURN client doesn't require the server to include message integrity - we just pass the secret every time, and if there is a message integrity, we try to verify it.

On the server side we would like to know if the message was verified after decoding it. Right now there is no way to know if decoded message was verified. My proposal it add :verified? field to Jerboa.Params struct.

In the first of mentioned situations, this field would be set to false, because there is nothing to verify - the request wasn't autenticated.
In the second example the decoding should succeed, but the field will be set to false again.
In the third case we could also let the decoding pass and set this flag to false.

/cc @rslota @mentels

Explanation + examples of STUN usage

As @Arkham suggested, we should probably add an explanation of STUN protocol and its use cases to the README, for people not familiar with it. The same thing for TURN, once we implement it.

Wiki for Development Guide

ExDocs are for the client and encoding/decoding APIs.

Let's introduce a brief guide on developing internals.

Encoding/decoding for XOR-PEER-ADDRESS attribute

Refer to #40.

This attribute, same as XOR-RELAYED-ADDRESS (#41) are encoded the same way as XOR-MAPPED-ADDRESS, so encoding and decoding of these should be moved to single module, and these specific modules could delegate to that.

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.