Code Monkey home page Code Monkey logo

rust-raknet's Introduction

rust-raknet Build Status ChatOnDiscord Crate Crate

RakNet Protocol implementation by Rust.

Raknet is a reliable udp transport protocol that is generally used for communication between game clients and servers, and is used by Minecraft Bedrock Edtion for underlying communication.

Raknet protocol supports various reliability options, and has better transmission performance than TCP in unstable network environments. This project is an incomplete implementation of the protocol by reverse engineering.

Requires >= Tokio 1.x asynchronous runtime support.

Reference : http://www.jenkinssoftware.com/raknet/manual/index.html

This project is not affiliated with Jenkins Software LLC nor RakNet.

Features

  • Async
  • MIT License
  • Pure Rust implementation
  • Fast Retransmission
  • Selective Retransmission (TCP/Full Retransmission)
  • Non-delayed ACK (TCP/Delayed ACK)
  • RTO Not Doubled (TCP/RTO Doubled)
  • Linux/Windows/Mac/BSD support
  • Compatible with Minecraft

Get Started

# Cargo.toml
[dependencies]
rust-raknet = "*"

Documentation : https://docs.rs/rust-raknet/latest/rust_raknet/

Reliability

  • unreliable
  • unreliable sequenced
  • reliable
  • reliable ordered
  • reliable sequenced

Example

//server

async fn serve(){
    let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
    listener.listen().await;
    loop{
        let socket = listener.accept().await.unwrap();
        let buf = socket.recv().await.unwrap();
        if buf[0] == 0xfe{
            //do something
        }
    }
    listener.close().await.unwrap();
}
//client

async fn connect(){
    let socket = RaknetSocket::connect("127.0.0.1:19132".parse().unwrap()).await.unwrap();
    socket.send(&[0xfe], Reliability::ReliableOrdered).await.unwrap();
    let buf = socket.recv().await.unwrap();
    if buf[0] == 0xfe{
        //do something
    }
    socket.close().await.unwrap();
}

Benchmark

Use Tcp to compare with this project. Set the server packet loss rate to 50%, the client connects to the server, and the server sends an 800-byte packet every 30ms, a total of 100 times. The client counts the delay time of each received data, and calculates the average time of receiving 100 times. The following results are obtained.

Test code: https://github.com/b23r0/rust-raknet/blob/main/example/test_benchmark/src/main.rs

Result:

image

(June 12, 2022)

In the network environment with high packet loss rate, this project can reduce the delay time by about 50% compared with TCP.

Contributing

Options :

  • Report a BUG
  • Submit an ISSUE about suggestion
  • Submit a improved PR
  • Add an example of using rust-raknet
  • Supplement the documentation about using rust-raknet

Thanks go to these wonderful people.


b23r0

nounfve

Contributions of any kind are welcome! If you've ever wanted to contribute to open source, and a great cause, now is your chance!

Donation

BTC : 1HeroYcNYMhjsq8RYCx1stSaRZnQd9B9Eq

ETH : 0x9999997B3deF7b69c09D7a9CA65E5242fb04a764

rust-raknet's People

Contributors

b23r0 avatar jrcarl624 avatar nounfve 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

rust-raknet's Issues

Couldn't connect to server with `unwrap()` called on `Result` on a `Err` value

Created simple packet listener, my code:

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt::init();
    let mut socket = rust_raknet::RaknetListener::bind("0.0.0.0:19132".parse().unwrap()).await.unwrap();
    socket.listen().await;

    while let Ok(mut s) = socket.accept().await {
        tracing::info!("Accepted connection from {:?}", s.local_addr());

        let mut connection = rust_raknet::RaknetSocket::connect(&"51.210.143.233:19132".parse().unwrap()).await.unwrap();
        loop {
            if let Ok(buf) = s.recv().await {
                tracing::info!("FROM CLIENT: {:?}", &buf);
                connection.send(buf.as_slice(), Reliability::Reliable).await;
            }

            if let Ok(buf) = connection.recv().await {
                tracing::info!("FROM SERVER: {:?}", &buf);
                s.send(buf.as_slice(), Reliability::Reliable).await;
            }
        }
    }
}

Error:

thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: ReadPacketBufferError', C:\Users\dolabaeb\.cargo\registry\src\github.com-1ecc6299db9ec823\rust-raknet-0.3.1\src\socket.rs:357:137

On line https://github.com/b23r0/rust-raknet/blob/main/src/socket.rs#L371

Error with example proxy

Cloning library directly from master branch, building proxy.exe with --release on Windows 10 21H2 (19044.1645) and connecting to it through PC version Minecraft 1.18.12 and getting this error:

thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: ReadPacketBufferError', C:\Users\dolabaeb\CLionProjects\rust-raknet\src\socket.rs:371:137
stack backtrace:
   0:     0x7ff7082c2fff - std::backtrace_rs::backtrace::dbghelp::trace
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\..\..\backtrace\src\backtrace\dbghelp.rs:98
   1:     0x7ff7082c2fff - std::backtrace_rs::backtrace::trace_unsynchronized
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\..\..\backtrace\src\backtrace\mod.rs:66
   2:     0x7ff7082c2fff - std::sys_common::backtrace::_print_fmt
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\sys_common\backtrace.rs:67
   3:     0x7ff7082c2fff - std::sys_common::backtrace::_print::impl$0::fmt
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\sys_common\backtrace.rs:46
   4:     0x7ff7082d5c2a - core::fmt::write
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\core\src\fmt\mod.rs:1168
   5:     0x7ff7082bccb8 - std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\io\mod.rs:1660
   6:     0x7ff7082c5b5b - std::sys_common::backtrace::_print
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\sys_common\backtrace.rs:49
   7:     0x7ff7082c5b5b - std::sys_common::backtrace::print
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\sys_common\backtrace.rs:36
   8:     0x7ff7082c5b5b - std::panicking::default_hook::closure$1
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\panicking.rs:211
   9:     0x7ff7082c5654 - std::panicking::default_hook
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\panicking.rs:228
  10:     0x7ff7082c605c - std::panicking::rust_panic_with_hook
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\panicking.rs:606
  11:     0x7ff7082c5f1b - std::panicking::begin_panic_handler::closure$0
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\panicking.rs:502
  12:     0x7ff7082c3947 - std::sys_common::backtrace::__rust_end_short_backtrace<std::panicking::begin_panic_handler::closure$0,never$>
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\sys_common\backtrace.rs:139
  13:     0x7ff7082c5c19 - std::panicking::begin_panic_handler
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\panicking.rs:498
  14:     0x7ff7082e0520 - core::panicking::panic_fmt
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\core\src\panicking.rs:116
  15:     0x7ff7082e05c3 - core::result::unwrap_failed
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\core\src\result.rs:1690
  16:     0x7ff70827bf58 - rust_raknet::socket::RaknetSocket::start_receiver::{{closure}}::hdf180a56c8e969e1
  17:     0x7ff70826bd5a - std::panicking::try::hc206c013b6ddaf57
  18:     0x7ff7082713c8 - tokio::runtime::task::harness::Harness<T,S>::complete::hdd4b53e814e17a2e
  19:     0x7ff70826f180 - tokio::runtime::task::harness::Harness<T,S>::poll::h4b79a9f0313f8bda
  20:     0x7ff7082899e7 - std::thread::local::LocalKey<T>::with::hee90645ce63d04a6
  21:     0x7ff7082a7867 - tokio::runtime::thread_pool::worker::Context::run::hf532ea944e9ceb7b
  22:     0x7ff7082a659f - tokio::runtime::thread_pool::worker::Context::run::hf532ea944e9ceb7b
  23:     0x7ff70828f878 - tokio::macros::scoped_tls::ScopedKey<T>::set::h9c078d3da8ad3cf1
  24:     0x7ff7082a5f6a - tokio::runtime::thread_pool::worker::run::h7190bbc6b2ab57df
  25:     0x7ff70828a565 - tokio::runtime::task::core::CoreStage<T>::poll::h8158559ae3fc7af7
  26:     0x7ff708286616 - std::panicking::try::h285da934742423c5
  27:     0x7ff70829df00 - tokio::runtime::task::harness::Harness<T,S>::poll::he531c6aa5d8b0e33
  28:     0x7ff708299d7c - tokio::runtime::blocking::pool::Inner::run::hc60e1a36e26a7d78
  29:     0x7ff70829c7e5 - std::sys_common::backtrace::__rust_begin_short_backtrace::h471c0fb8d6991f35
  30:     0x7ff708288ca3 - <tokio::io::driver::scheduled_io::Readiness as core::ops::drop::Drop>::drop::h9c7660bf59f3dba4
  31:     0x7ff7082c9b5c - alloc::boxed::impl$44::call_once
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\library\alloc\src\boxed.rs:1854
  32:     0x7ff7082c9b5c - alloc::boxed::impl$44::call_once
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\library\alloc\src\boxed.rs:1854
  33:     0x7ff7082c9b5c - std::sys::windows::thread::impl$0::new::thread_start
                               at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a\/library\std\src\sys\windows\thread.rs:58
  34:     0x7ffe55f57034 - BaseThreadInitThunk
  35:     0x7ffe56522651 - RtlUserThreadStart

proxy.exe -l 0.0.0.0:19132 -r 146.59.254.235:19132
IP address is Europe HiveMC server

RaknetListener#accept() freezes for ever and don't accept any new connections.

I've made normal client server application that uses rust-raknet, but once the first client is accepted by the RaknetListener, the listener stop accepting new connections.

So I made a test program that binds a RaknetListener and accepts clients in a loop and reads data from them and prints it. And i've added loop that connects clients to the listener. This test program also stop accepting new connections after few clients that got accepted. Code below:

let mut server = rust_raknet::RaknetListener::bind(&"0.0.0.0:1337".parse().unwrap()).await.unwrap();
    server.listen().await;
    log::info!("Listening on {}", server.local_addr().unwrap());
    
    tokio::spawn(async move {
        loop {
            log::info!("Accepting...");
            let client = server.accept().await.unwrap();
            log::info!("Accepted: {}", client.peer_addr().unwrap());
            tokio::spawn(async move {
                loop {
                    let msg = client.recv().await;
                    log::info!("Received: {:?}", msg);
                    if msg.is_err() {
                        break; // Stop the task
                    }
                }
            });
        }
    });

    tokio::time::sleep(std::time::Duration::from_secs(2)).await; // Wait some time for the server to start accepting connections

    loop {
        tokio::time::sleep(std::time::Duration::from_millis(100)).await;
        tokio::spawn(async move {
            log::info!("Connecting new client...");
            let client = rust_raknet::RaknetSocket::connect(&"127.0.0.1:1337".parse().unwrap()).await.unwrap();
            log::info!("Connected to {}", client.peer_addr().unwrap());
            client.send(&[0xFE, 0x02, 0x03, 0x04], rust_raknet::Reliability::ReliableOrdered).await.unwrap();
            let _ = client.close().await;
        });
    }

Typo 'Adrees' in 3 files

In files server.rs, socket.rs and error.rs there are typos BindAdreesError that should be BindAddressError I guess

Publish To Cargo

My last commit was never published, so I have to use a git submodule.

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.