Code Monkey home page Code Monkey logo

rusturn's Introduction

rusturn

rusturn Documentation Actions Status Coverage Status License: MIT

A Rust implementation of TURN server and client.

Documentation

Examples

use futures::Future;
use rustun::message::Request;
use rustun::transport::StunUdpTransporter;
use rusturn::auth::AuthParams;
use rusturn::transport::UdpOverTurnTransporter;
use stun_codec::{rfc5389, MessageDecoder, MessageEncoder};

let client_auth_params = AuthParams::new("foo", "bar")?;
let server_auth_params =
    AuthParams::with_realm_and_nonce("foo", "bar", "baz", "qux")?;

// STUN server (peer)
let stun_server = fibers_global::execute(rustun::server::UdpServer::start(
    fibers_global::handle(),
    "127.0.0.1:0".parse().unwrap(),
    rustun::server::BindingHandler,
))?;
let stun_server_addr = stun_server.local_addr();
fibers_global::spawn(stun_server.map(|_| ()).map_err(|e| panic!("{}", e)));

// TURN server
let turn_server = fibers_global::execute(rusturn::server::UdpServer::start(
    "127.0.0.1:0".parse().unwrap(),
    server_auth_params,
))?;
let turn_server_addr = turn_server.local_addr();
fibers_global::spawn(turn_server.map_err(|e| panic!("{}", e)));

// TURN client
let turn_client = fibers_global::execute(rusturn::client::UdpClient::allocate(
    turn_server_addr,
    client_auth_params
))?;
let transporter =
    UdpOverTurnTransporter::<_, MessageEncoder<_>, MessageDecoder<_>>::new(turn_client);

// STUN client (over TURN)
let stun_channel = rustun::channel::Channel::new(StunUdpTransporter::new(transporter));
let stun_client = rustun::client::Client::new(&fibers_global::handle(), stun_channel);

// BINDING request
let request = Request::<rfc5389::Attribute>::new(rfc5389::methods::BINDING);
let response = fibers_global::execute(
    stun_client.call(stun_server_addr, request)
)?;
assert!(response.is_ok(), "{:?}", response);

References

rusturn's People

Contributors

marcbrevoort-cyberhive avatar sile avatar vi 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

rusturn's Issues

turncli example wastes CPU while waiting.

$ strace -cf target/debug/examples/turncli ...
...
# ALLOCATED: server=V4(104.131.203.210:3478)
Relay address is Some(V4(104.131.203.210:62901))
# CHANNEL BOUND: peer=V4(93.84.76.218:24636)
...

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 74.01    2.685272          20    132890           epoll_wait
 18.82    0.682884          20     33833         1 nanosleep
  7.17    0.260000       11818        22           futex
  0.00    0.000000           0        18           read
  0.00    0.000000           0        45           write
...

Connection timeout

There's a connection timeout when using rusturn against a standard turn server.
I think this is due to two things.

  1. create_permission does not allow setting a permission when one already exists for a given client. Thus when we want to refresh a permission, the previous one first needs to be expired completely (causing a gap in communications) By dropping the check for existing permissions, create_permission can be called again even if the permission hasn't expired yet, resulting in a refreshed permission on the server side.

  2. timeouts seem to be coded backwards. For instance refresh for allocations times out at 10/9 the lifetime rather than at 9/10 the lifetime. This is probably the main issue.

How to test on Windows?

Hello,

I would like to test the server and client on 2 Windows 10 (x64) machine to see if a connection can be made and packets passed.

Any help would be greatly appreciated.

Using rusturn in synchronous context

Hello, I'm trying to use Rusturn in a synchronous context. This seems to work fine for creating the TURN client, however I'm having trouble with permissions creation.
if I observe network traffic on Wireshark, I see it send the first permission, and a response comes in in reply. However the second permission I try create for a different IP seems to hang.

I have tried both fibers_global::execute() and a loop of the following form,

use futures::Future;
let mut myasyncresult = turnclient.create_permission(peer.clone());
loop {
    std::thread::sleep(std::time::Duration::from_millis(100));
    match myasyncresult.poll() {
        Ok(futures::Async::NotReady) => {
            println!("poll: notready");
        }
        Ok(futures::Async::Ready(x)) => {
            println!("poll: ready: {:?}", x);
            break;
        }
        Err(e) => {
            println!("poll: err, e={:?}", e);
            break;
        }
    }
};

and this shows that once the message has been sent out, the asyncresult forever sits there printing "poll: notready", which would explain the second request not going out. Could you suggest what things I've missed might cause the incoming response data never to be processed?

Pointers on TCP client use?

I've successfully set up a rusturn UDP client relay using the example client script as starting point and have observed it relaying data.
As some networks reject UDP traffic, I have also tried the same scenario, however this time running over TCP.

However this falls flat with the following trace,

Error: Other
HISTORY:
  [0] at src/turn_message.rs:68
  [1] at /home/mrjb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/fibers_transport-0.1.3/src/tcp.rs:196
  [2] at /home/mrjb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/fibers_transport-0.1.3/src/error.rs:19 -- original_error_kind=IncompleteDecoding
  [3] at /home/mrjb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/fibers_transport-0.1.3/src/share.rs:48
  [4] at src/transport/stun.rs:46
  [5] at /home/mrjb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rustun-0.4.0/src/transport/tcp.rs:49
  [6] at /home/mrjb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rustun-0.4.0/src/channel.rs:176
  [7] at /home/mrjb/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rustun-0.4.0/src/error.rs:61 -- original_error_kind=CodecError
  [8] at src/client/allocate.rs:157
  [9] at src/client/mod.rs:101
  [10] at src/main.rs:59

(main.rs is a configured copy of the example client script, with Cargo.toml updated to pull in the dev dependencies as regular dependencies).

Further investigation on the TURN server side shows, for UDP, that the listener is aware of user auth for UDP,

2023-12-06 14:59:51.834487+00:00 [info] Accepting long-term STUN/TURN authentication [UDP, session jgu7zsp74ui2, user 1701956093:bert, client <redacted>]

whereas for TCP invariably the connection is anonymous and dropped immediately:

2023-12-06 15:40:36.360729+00:00 [info] Accepting connection: 150.143.125.194:34308 -> 172.26.7.5:3479 [TCP, session cq6qrvdnvu7m]
2023-12-06 15:40:36.362265+00:00 [info] Connection reset by peer [TCP, session cq6qrvdnvu7m, anonymous, client <redacted>]

The documentation for TcpClient and UdpClient is essentially word-for-word identical, so it's unclear where I'm going wrong here.

Digging yet further I noticed allocate.rs always uses protocol TRANSPORT_CONTROL_PROTOCOL_UDP or 17:

const TRANSPORT_PROTOCOL_UDP: u8 = 17;
...
    fn start_allocate(&mut self) -> Result<()> {
        let mut request = Request::new(rfc5766::methods::ALLOCATE);
        let requested_transport =
            rfc5766::attributes::RequestedTransport::new(TRANSPORT_PROTOCOL_UDP).into();

and have also tried if using TRANSPORT_PROTOCOL_TCP=6 would do it, but sadly this has also not resulted in a working TCP client.

Any further pointers would be much appreciated.

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.