Skip to content

Commit

Permalink
feat: turn rest api rfc support; (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
mycrl authored Sep 14, 2024
1 parent 0c98a15 commit d7b9785
Show file tree
Hide file tree
Showing 22 changed files with 539 additions and 385 deletions.
15 changes: 6 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
-
uses: actions/checkout@v4
-
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
Expand Down Expand Up @@ -70,23 +70,23 @@ jobs:
-
name: Upload artifact (Linux)
if: runner.os == 'Linux' && matrix.arch == 'x86_64'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: linux-x86_64
path: |
./target/release/turn-server-linux-x86_64
-
name: Upload artifact (Linux)
if: runner.os == 'Linux' && matrix.arch == 'aarch64'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: linux-x86_64
name: linux-aarch64
path: |
./target/aarch64-unknown-linux-gnu/release/turn-server-linux-aarch64
-
name: Upload artifact (Windows)
if: runner.os == 'Windows' && matrix.arch == 'x86_64'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: windows-x86_64
path: |
Expand All @@ -95,12 +95,9 @@ jobs:
needs: build
runs-on: ubuntu-latest
steps:
-
name: Checkout code
uses: actions/checkout@v3
-
name: Download All Artifacts
uses: actions/download-artifact@v4.1.7
uses: actions/download-artifact@v4
with:
path: artifacts
-
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ If you have extensive standard support requirements for turn servers and need mo
* [start the server](./docs/start-the-server.md)
* [configure](./docs/configure.md)
* [rest api](./docs/rest-api.md)
* [web hooks](./docs/web-hooks.md)
* [http hooks](./docs/http-hooks.md)
* [driver](./drivers)

## Features
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
* [Start the server](start-the-server.md)
* [Configure](configure.md)
* [REST API](rest-api.md)
* [Web Hooks](web-hooks.md)
* [HTTP Hooks](http-hooks.md)
44 changes: 32 additions & 12 deletions docs/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ external = "127.0.0.1:3478"
# environment.
bind = "127.0.0.1:3000"

# web hooks url
# hooks url
#
# This option is used to specify the http address of the hooks service.
#
Expand All @@ -62,16 +62,25 @@ bind = "127.0.0.1:3000"
# An enum representing the available verbosity levels of the logger.
level = "info"

[auth]
# Static authentication key value (string) that applies only to the TURN
# REST API.
#
# If set, the turn server will not request external services via the HTTP
# Hooks API to obtain the key.
#
# static_auth_secret = ""

# static user password
#
# This option can be used to specify the
# static identity authentication information used by the turn server for
# verification. Note: this is a high-priority authentication method, turn
# The server will try to use static authentication first, and then use
# external control service authentication.
[auth]
user1 = "test"
user2 = "test"
[auth.static_credentials]
# user1 = "test"
# user2 = "test"
```

## Configuration keys
Expand All @@ -80,7 +89,7 @@ user2 = "test"

### `turn.realm`

* Type: strings
* Type: string
* Default: "localhost"

This option describes the realm of the turn service. For the definition of realm, please refer to [RFC](https://datatracker.ietf.org/doc/html/rfc5766#section-3).
Expand All @@ -98,23 +107,23 @@ This option describes the interface to which the turn service is bound. A turn s

### `[turn.interfaces.transport]`

* Type: enum of strings
* Type: enum of string

Describes the transport protocol used by the interface. The value can be `udp` or `tcp`, which correspond to udp turn and tcp turn respectively, and choose whether to bind the turn service to a udp socket or a tcp socket.

***

### `[turn.interfaces.bind]`

* Type: strings
* Type: string

The IP address and port number bound to the interface. This is the address to which the internal socket is bound.

***

### `[turn.interfaces.external]`

* Type: strings
* Type: string

bind is used to bind to the address of your local NIC, for example, you have two NICs A and B on your server, the IP address of NIC A is 192.168.1.2, and the address of NIC B is 192.168.1.3, if you bind to NIC A, you should bind to the address of 192.168.1.2, and bind to 0.0.0.0 means that it listens to all of them at the same time.

Expand All @@ -126,7 +135,7 @@ As for why bind and external are needed, this is because for the stun protocol,

### `api.bind`

* Type: strings
* Type: string
* Default: "127.0.0.1:3000"

Describes the address to which the turn api server is bound.
Expand All @@ -139,7 +148,7 @@ The turn service provides an external REST API. External parties can control the

### `api.hooks`

* Type: strings
* Type: string
* Default: None

Describes the address of external Web Hooks. The default value is empty. The purpose of Web Hooks is to allow the turn service to push to external services when authentication is required and event updates occur.
Expand All @@ -152,15 +161,26 @@ The turn service provides an external REST API. External parties can control the

### `log.level`

* Type: enum of strings
* Type: enum of string
* Default: "info"

Describes the log level of the turn service. Possible values ​​are `"error"`, `"warn"`, `"info"`, `"debug"`, `"trace"`.

***

### `auth`
### `auth.static_credentials`

* Type: key values

Describes static authentication information, with username and password as key pair. Static identity authentication is authentication information provided to the turn service in advance. The turn service will first look for this table when it needs to authenticate the turn session. If it cannot find it, it will use Web Hooks for external authentication.

***

### `auth.static_auth_secret`

* Type: string
* Default: None

Static authentication key value (string) that applies only to the TURN REST API.

If set, the turn server will not request external services via the HTTP Hooks API to obtain the key.
57 changes: 57 additions & 0 deletions docs/http-hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Web Hooks

#### Global Request Headers

* `realm` - <sup>string</sup> - turn server realm
* `rid` - <sup>string</sup> - The runtime ID of the turn server

rid: A new ID is generated each time the server is started. This is a random string. Its main function is to determine whether the turn server has been restarted.

***

### GET - `/password?addr=&name=`

Get the current user's password, which is mainly used to provide authentication for the turn server.

***

### POST - `/events` - Events

binding request:

* `kind` - <sup>string</sup> - "binding"
* `addr` - <sup>string</sup> - The IP address and port number of the UDP or TCP connection used by the client.

allocate request:

* `kind` - <sup>string</sup> - "allocated"
* `name` - <sup>string</sup> - The username used for the turn session.
* `addr` - <sup>string</sup> - The IP address and port number of the UDP or TCP connection used by the client.
* `port` - <sup>uint16</sup> - The port to which the request is assigned.

channel binding request:

* `kind` - <sup>string</sup> - "channel_bind"
* `name` - <sup>string</sup> - The username used for the turn session.
* `addr` - <sup>string</sup> - The IP address and port number of the UDP or TCP connection used by the client.
* `channel` - <sup>uint16</sup> - The channel to which the request is binding.

create permission request:

* `kind` - <sup>string</sup> - "create_permission"
* `name` - <sup>string</sup> - The username used for the turn session.
* `addr` - <sup>string</sup> - The IP address and port number of the UDP or TCP connection used by the client.
* `relay` - <sup>uint16</sup> - The port number of the other side specified when the privilege was created.

refresh request:

* `kind` - <sup>string</sup> - "refresh"
* `name` - <sup>string</sup> - The username used for the turn session.
* `addr` - <sup>string</sup> - The IP address and port number of the UDP or TCP connection used by the client.
* `expiration` - <sup>uint32</sup> - Time to expiration in seconds.

session closed:

* `kind` - <sup>string</sup> - "abort"
* `name` - <sup>string</sup> - The username used for the turn session.
* `addr` - <sup>string</sup> - The IP address and port number of the UDP or TCP connection used by the client.
57 changes: 0 additions & 57 deletions docs/web-hooks.md

This file was deleted.

6 changes: 3 additions & 3 deletions stun/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl<'a, 'b> MessageWriter<'a> {
// long key,
// digest the message buffer,
// create the new MessageIntegrity attribute.
let hmac_output = util::hmac_sha1(auth, vec![self.raw])?.into_bytes();
let hmac_output = util::hmac_sha1(auth, &[self.raw])?.into_bytes();
let property_buf = hmac_output.as_slice();

// write MessageIntegrity attribute.
Expand Down Expand Up @@ -325,14 +325,14 @@ impl<'a, 'b> MessageReader<'a, 'b> {

// create multiple submit.
let size_buf = (self.valid_offset + 4).to_be_bytes();
let body = vec![
let body = [
&self.buf[0..2],
&size_buf,
&self.buf[4..self.valid_offset as usize],
];

// digest the message buffer.
let hmac_output = util::hmac_sha1(auth, body)?.into_bytes();
let hmac_output = util::hmac_sha1(auth, &body)?.into_bytes();
let property_buf = hmac_output.as_slice();

// Compare local and original attribute.
Expand Down
4 changes: 2 additions & 2 deletions stun/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ pub fn long_key(username: &str, key: &str, realm: &str) -> [u8; 16] {
/// 0x74, 0xe2, 0x3c, 0x26, 0xc5, 0xb1, 0x03, 0xb2, 0x6d,
/// ];
///
/// let hmac_output = stun::util::hmac_sha1(&key, vec![&buffer])
/// let hmac_output = stun::util::hmac_sha1(&key, &[&buffer])
/// .unwrap()
/// .into_bytes();
/// assert_eq!(hmac_output.as_slice(), &sign);
/// ```
pub fn hmac_sha1(key: &[u8], source: Vec<&[u8]>) -> Result<CtOutput<Hmac<sha1::Sha1>>, StunError> {
pub fn hmac_sha1(key: &[u8], source: &[&[u8]]) -> Result<CtOutput<Hmac<sha1::Sha1>>, StunError> {
match Hmac::<sha1::Sha1>::new_from_slice(key) {
Err(_) => Err(StunError::ShaFailed),
Ok(mut mac) => {
Expand Down
1 change: 1 addition & 0 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"
publish = false

[dependencies]
base64 = "0.22.1"
once_cell = "1.18.0"
tokio = { version = "1", features = ["full"] }
stun = { path = "../stun", version = "1" }
Expand Down
Loading

0 comments on commit d7b9785

Please sign in to comment.