Skip to main content

rust_raknet/
lib.rs

1//! An asynchronous implementation of the RakNet transport protocol in Rust.
2//!
3//! RakNet provides reliable and ordered delivery modes over UDP and is used by
4//! Minecraft Bedrock Edition. This library implements the connection handshake,
5//! packet reliability, fragmentation, and listener/client APIs.
6//!
7//! The library requires the Tokio 1.x asynchronous runtime.
8//!
9//! # Features
10//!
11//! - Asynchronous client and server APIs
12//! - Five RakNet reliability modes
13//! - Selective retransmission and fast acknowledgements
14//! - IPv4 and IPv6 socket addresses
15//!
16//! # Getting started
17//!
18//! ```toml
19//! [dependencies]
20//! rust-raknet = "1.4.0"
21//! ```
22//!
23//! # Reliability modes
24//!
25//! - Unreliable
26//! - Unreliable sequenced
27//! - Reliable
28//! - Reliable ordered
29//! - Reliable sequenced
30//!
31//! This project is not affiliated with Jenkins Software LLC or RakNet.
32//! See the [RakNet protocol reference](http://www.jenkinssoftware.com/raknet/manual/index.html).
33
34mod arq;
35#[cfg(feature = "blocking")]
36pub mod blocking;
37mod datatype;
38pub mod error;
39mod fragment;
40mod log;
41mod packet;
42#[cfg(feature = "recovery-policy")]
43mod recovery_options;
44#[cfg(feature = "send-policy")]
45mod send_options;
46mod sequence;
47mod server;
48mod socket;
49mod udp;
50mod utils;
51
52pub use crate::arq::Reliability;
53pub use crate::log::enable_raknet_log;
54#[cfg(feature = "recovery-policy")]
55pub use crate::recovery_options::RecoveryOptions;
56#[cfg(feature = "send-policy")]
57pub use crate::send_options::{SendOptions, SendOptionsError};
58pub use crate::server::*;
59pub use crate::socket::*;
60pub use bytes::Bytes;
61
62#[test]
63fn test_raknet_error_implements_std_error() {
64    fn assert_error<T: std::error::Error>() {}
65    assert_error::<error::RaknetError>();
66    assert_eq!(
67        error::RaknetError::NotListen.to_string(),
68        "the RakNet listener is not listening"
69    );
70}
71
72#[tokio::test]
73async fn test_listener_updates_motd_after_listen() {
74    let mut listener = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
75        .await
76        .unwrap();
77    let local_addr = listener.local_addr().unwrap();
78    listener.listen().await;
79
80    let motd = "MCPE;Updated MOTD;486;1.20.0;0;20;123;World;Survival;1;19132;";
81    listener.set_full_motd(motd.to_owned()).await.unwrap();
82
83    let (_, received_motd) = tokio::time::timeout(
84        std::time::Duration::from_secs(3),
85        RaknetSocket::ping(&local_addr),
86    )
87    .await
88    .expect("server did not answer the unconnected ping")
89    .unwrap();
90    assert_eq!(received_motd, motd);
91
92    listener.close().await.unwrap();
93}
94
95#[tokio::test]
96async fn test_listener_accepts_more_than_one_queue_of_connections() {
97    const CONNECTIONS: usize = 12;
98
99    let mut listener = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
100        .await
101        .unwrap();
102    let local_addr = listener.local_addr().unwrap();
103    listener.listen().await;
104
105    let accept_task = tokio::spawn(async move {
106        let mut accepted = Vec::with_capacity(CONNECTIONS);
107        for _ in 0..CONNECTIONS {
108            accepted.push(
109                tokio::time::timeout(std::time::Duration::from_secs(5), listener.accept())
110                    .await
111                    .expect("listener stopped accepting connections")
112                    .unwrap(),
113            );
114        }
115        (accepted, listener)
116    });
117
118    let mut clients = Vec::with_capacity(CONNECTIONS);
119    for _ in 0..CONNECTIONS {
120        clients.push(
121            tokio::time::timeout(
122                std::time::Duration::from_secs(5),
123                RaknetSocket::connect(&local_addr),
124            )
125            .await
126            .expect("client connection timed out")
127            .unwrap(),
128        );
129    }
130
131    let (accepted, mut listener) =
132        tokio::time::timeout(std::time::Duration::from_secs(5), accept_task)
133            .await
134            .expect("listener accept loop timed out")
135            .unwrap();
136    assert_eq!(accepted.len(), CONNECTIONS);
137
138    for socket in clients {
139        socket.close().await.unwrap();
140    }
141    for socket in accepted {
142        socket.close().await.unwrap();
143    }
144    listener.close().await.unwrap();
145}
146
147#[tokio::test]
148async fn test_connect() {
149    let mut server = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
150        .await
151        .unwrap();
152    let local_addr = server.local_addr().unwrap();
153    server.listen().await;
154
155    let notify = std::sync::Arc::new(tokio::sync::Notify::new());
156    let notify2 = notify.clone();
157
158    tokio::spawn(async move {
159        let client1 = server.accept().await.unwrap();
160        assert!(client1.local_addr().unwrap() == local_addr);
161        client1
162            .send(&[0xfe, 2, 3], Reliability::Reliable)
163            .await
164            .unwrap();
165        notify2.notified().await;
166    });
167    let client2 = RaknetSocket::connect(&local_addr).await.unwrap();
168    assert!(client2.peer_addr().unwrap() == local_addr);
169    let buf = client2.recv().await.unwrap();
170    assert!(buf == vec![0xfe, 2, 3]);
171
172    notify.notify_one();
173}
174
175#[tokio::test]
176async fn test_send_recv_fragment_data() {
177    let mut server = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
178        .await
179        .unwrap();
180    let local_addr = server.local_addr().unwrap();
181    server.listen().await;
182
183    let notify = std::sync::Arc::new(tokio::sync::Notify::new());
184    let notify2 = notify.clone();
185
186    tokio::spawn(async move {
187        let client1 = server.accept().await.unwrap();
188        assert!(client1.local_addr().unwrap() == local_addr);
189
190        let mut a = vec![3u8; 1000];
191        let mut b = vec![2u8; 1000];
192        let mut c = vec![0xfe; 1000];
193        b.append(&mut a);
194        c.append(&mut b);
195
196        client1
197            .send(&c, Reliability::ReliableOrdered)
198            .await
199            .unwrap();
200
201        notify2.notified().await;
202    });
203    let client2 = RaknetSocket::connect(&local_addr).await.unwrap();
204    assert!(client2.peer_addr().unwrap() == local_addr);
205    let buf = client2.recv().await.unwrap();
206    assert!(buf.len() == 3000);
207    assert!(buf[0..1000] == vec![0xfe; 1000]);
208    assert!(buf[1000..2000] == vec![2u8; 1000]);
209    assert!(buf[2000..3000] == vec![3u8; 1000]);
210
211    notify.notify_one();
212}
213
214#[tokio::test]
215async fn test_send_recv_more_reliability_type_packet() {
216    let mut server = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
217        .await
218        .unwrap();
219    let local_addr = server.local_addr().unwrap();
220    server.listen().await;
221
222    let notify = std::sync::Arc::new(tokio::sync::Notify::new());
223    let notify2 = notify.clone();
224
225    tokio::spawn(async move {
226        let client1 = server.accept().await.unwrap();
227        assert!(client1.local_addr().unwrap() == local_addr);
228
229        client1
230            .send(&[0xfe, 1, 2, 3], Reliability::Unreliable)
231            .await
232            .unwrap();
233        let data = client1.recv().await.unwrap();
234        assert!(data == [0xfe, 4, 5, 6].to_vec());
235
236        client1
237            .send(&[0xfe, 7, 8, 9], Reliability::UnreliableSequenced)
238            .await
239            .unwrap();
240        let data = client1.recv().await.unwrap();
241        assert!(data == [0xfe, 10, 11, 12].to_vec());
242
243        client1
244            .send(&[0xfe, 13, 14, 15], Reliability::Reliable)
245            .await
246            .unwrap();
247        let data = client1.recv().await.unwrap();
248        assert!(data == [0xfe, 16, 17, 18].to_vec());
249
250        let mut a = vec![3u8; 1000];
251        let mut b = vec![2u8; 1000];
252        let mut c = vec![0xfe; 1000];
253        b.append(&mut a);
254        c.append(&mut b);
255
256        client1
257            .send(&c, Reliability::ReliableOrdered)
258            .await
259            .unwrap();
260
261        let buf = client1.recv().await.unwrap();
262        assert!(buf.len() == 3000);
263        assert!(buf[0..1000] == vec![0xfe; 1000]);
264        assert!(buf[1000..2000] == vec![2u8; 1000]);
265        assert!(buf[2000..3000] == vec![3u8; 1000]);
266
267        client1
268            .send(&[0xfe, 19, 20, 21], Reliability::ReliableSequenced)
269            .await
270            .unwrap();
271        let data = client1.recv().await.unwrap();
272        assert!(data == [0xfe, 22, 23, 24].to_vec());
273
274        notify2.notified().await;
275    });
276    let client2 = RaknetSocket::connect(&local_addr).await.unwrap();
277    assert!(client2.peer_addr().unwrap() == local_addr);
278
279    let buf = client2.recv().await.unwrap();
280    assert!(buf == [0xfe, 1, 2, 3]);
281
282    client2
283        .send(&[0xfe, 4, 5, 6], Reliability::Unreliable)
284        .await
285        .unwrap();
286
287    let buf = client2.recv().await.unwrap();
288    assert!(buf == [0xfe, 7, 8, 9]);
289
290    client2
291        .send(&[0xfe, 10, 11, 12], Reliability::UnreliableSequenced)
292        .await
293        .unwrap();
294
295    let buf = client2.recv().await.unwrap();
296    assert!(buf == [0xfe, 13, 14, 15]);
297
298    client2
299        .send(&[0xfe, 16, 17, 18], Reliability::Reliable)
300        .await
301        .unwrap();
302
303    let buf = client2.recv().await.unwrap();
304    assert!(buf.len() == 3000);
305    assert!(buf[0..1000] == vec![0xfe; 1000]);
306    assert!(buf[1000..2000] == vec![2u8; 1000]);
307    assert!(buf[2000..3000] == vec![3u8; 1000]);
308
309    let mut a = vec![3u8; 1000];
310    let mut b = vec![2u8; 1000];
311    let mut c = vec![0xfe; 1000];
312    b.append(&mut a);
313    c.append(&mut b);
314
315    client2
316        .send(&c, Reliability::ReliableOrdered)
317        .await
318        .unwrap();
319
320    let buf = client2.recv().await.unwrap();
321    assert!(buf == [0xfe, 19, 20, 21]);
322
323    client2
324        .send(&[0xfe, 22, 23, 24], Reliability::ReliableSequenced)
325        .await
326        .unwrap();
327
328    notify.notify_one();
329}
330
331#[tokio::test]
332async fn test_loss_packet1() {
333    let notify = std::sync::Arc::new(tokio::sync::Notify::new());
334    let notify2 = notify.clone();
335    let mut server = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
336        .await
337        .unwrap();
338    let local_addr = server.local_addr().unwrap();
339    server.listen().await;
340    tokio::spawn(async move {
341        let mut client1 = server.accept().await.unwrap();
342        // Simulate 20% packet loss.
343        client1.set_loss_rate(2);
344
345        for i in 0..10 {
346            let mut flag = vec![0xfe_u8];
347            let mut data = vec![i as u8; 2000];
348            flag.append(&mut data);
349            client1
350                .send(&flag, Reliability::ReliableOrdered)
351                .await
352                .unwrap();
353
354            let data = client1.recv().await.unwrap();
355            assert!(data == flag);
356        }
357
358        notify2.notified().await;
359    });
360    let mut client2 = RaknetSocket::connect(&local_addr).await.unwrap();
361    // Simulate 20% packet loss.
362    client2.set_loss_rate(2);
363
364    for i in 0..10 {
365        let mut flag = vec![0xfe_u8];
366        let mut data = vec![i as u8; 2000];
367        flag.append(&mut data);
368        client2
369            .send(&flag, Reliability::ReliableOrdered)
370            .await
371            .unwrap();
372
373        let data = client2.recv().await.unwrap();
374        assert!(data == flag);
375    }
376    notify.notify_one();
377}
378
379#[tokio::test]
380async fn test_loss_packet2() {
381    let notify = std::sync::Arc::new(tokio::sync::Notify::new());
382    let notify2 = notify.clone();
383    let mut server = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
384        .await
385        .unwrap();
386    let local_addr = server.local_addr().unwrap();
387    server.listen().await;
388    tokio::spawn(async move {
389        let mut client1 = server.accept().await.unwrap();
390        // Simulate 20% packet loss.
391        client1.set_loss_rate(2);
392
393        for i in 0..10 {
394            let mut flag = vec![0xfe_u8];
395            let mut data = vec![i as u8; 2000];
396            flag.append(&mut data);
397            client1
398                .send(&flag, Reliability::ReliableOrdered)
399                .await
400                .unwrap();
401        }
402
403        for i in 0..10 {
404            let mut flag = vec![0xfe_u8];
405            let mut data = vec![i as u8; 2000];
406            flag.append(&mut data);
407            let data = client1.recv().await.unwrap();
408            assert!(data == flag);
409        }
410        notify2.notified().await;
411    });
412    let mut client2 = RaknetSocket::connect(&local_addr).await.unwrap();
413    // Simulate 20% packet loss.
414    client2.set_loss_rate(2);
415
416    for i in 0..10 {
417        let mut flag = vec![0xfe_u8];
418        let mut data = vec![i as u8; 2000];
419        flag.append(&mut data);
420        client2
421            .send(&flag, Reliability::ReliableOrdered)
422            .await
423            .unwrap();
424    }
425
426    for i in 0..10 {
427        let mut flag = vec![0xfe_u8];
428        let mut data = vec![i as u8; 2000];
429        flag.append(&mut data);
430        let data = client2.recv().await.unwrap();
431        assert!(data == flag);
432    }
433    notify.notify_one();
434}
435
436#[tokio::test]
437async fn test_loss_packet_with_sequenced() {
438    let notify = std::sync::Arc::new(tokio::sync::Notify::new());
439    let notify2 = notify.clone();
440    let mut server = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
441        .await
442        .unwrap();
443    let local_addr = server.local_addr().unwrap();
444    server.listen().await;
445    tokio::spawn(async move {
446        let mut client1 = server.accept().await.unwrap();
447        // Simulate 20% packet loss.
448        client1.set_loss_rate(2);
449
450        for i in 0..100 {
451            let mut flag = vec![0xfe_u8];
452            let mut data = vec![i as u8; 20];
453            flag.append(&mut data);
454            client1
455                .send(&flag, Reliability::ReliableSequenced)
456                .await
457                .unwrap();
458        }
459
460        let mut last = 0;
461        for i in 0..50 {
462            let mut flag = vec![0xfe_u8];
463            let mut data = vec![i as u8; 20];
464            flag.append(&mut data);
465            let data = client1.recv().await.unwrap();
466            assert!(data[1] >= last);
467            last = data[1];
468        }
469        notify2.notified().await;
470    });
471    let mut client2 = RaknetSocket::connect(&local_addr).await.unwrap();
472    // Simulate 20% packet loss.
473    client2.set_loss_rate(2);
474
475    for i in 0..100 {
476        let mut flag = vec![0xfe_u8];
477        let mut data = vec![i as u8; 20];
478        flag.append(&mut data);
479        client2
480            .send(&flag, Reliability::ReliableSequenced)
481            .await
482            .unwrap();
483    }
484
485    let mut last = 0;
486    for i in 0..50 {
487        let mut flag = vec![0xfe_u8];
488        let mut data = vec![i as u8; 20];
489        flag.append(&mut data);
490        let data = client2.recv().await.unwrap();
491        assert!(data[1] >= last);
492        last = data[1];
493    }
494    notify.notify_one();
495}
496
497#[tokio::test]
498async fn test_raknet_server_close() {
499    for _ in 0..10 {
500        let mut server = RaknetListener::bind(&"127.0.0.1:19132".parse().unwrap())
501            .await
502            .unwrap();
503        server.listen().await;
504        let client = RaknetSocket::connect(&"127.0.0.1:19132".parse().unwrap())
505            .await
506            .unwrap();
507        let mut a = vec![3u8; 1000];
508        let mut b = vec![2u8; 1000];
509        let mut c = vec![0xfe; 1000];
510        b.append(&mut a);
511        c.append(&mut b);
512        client.send(&c, Reliability::ReliableOrdered).await.unwrap();
513
514        let client2 = server.accept().await.unwrap();
515        let buf = client2.recv().await.unwrap();
516        assert!(buf.len() == 3000);
517        assert!(buf[0..1000] == vec![0xfe; 1000]);
518        assert!(buf[1000..2000] == vec![2u8; 1000]);
519        assert!(buf[2000..3000] == vec![3u8; 1000]);
520
521        server.close().await.unwrap();
522        client.close().await.unwrap();
523    }
524
525    let mut server1 = RaknetListener::bind(&"127.0.0.1:19132".parse().unwrap())
526        .await
527        .unwrap();
528    server1.listen().await;
529    server1.close().await.unwrap();
530    let mut server2 = RaknetListener::bind(&"127.0.0.1:19132".parse().unwrap())
531        .await
532        .unwrap();
533    server2.listen().await;
534}
535
536#[tokio::test]
537async fn test_send_recv_full_packet() {
538    let mut server = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
539        .await
540        .unwrap();
541    let remote_addr = format!("127.0.0.1:{}", server.local_addr().unwrap().port());
542    tokio::spawn(async move {
543        server.listen().await;
544        let client = server.accept().await.unwrap();
545
546        // Complete delivery requires ordered reliability; sequenced mode may
547        // discard superseded messages during retransmission.
548        for _ in 0..50 {
549            client
550                .send(&vec![0xfe; 1000], Reliability::ReliableOrdered)
551                .await
552                .unwrap();
553        }
554        client.flush().await.unwrap();
555
556        client.close().await.unwrap();
557        server.close().await.unwrap();
558    });
559
560    let client = RaknetSocket::connect(&remote_addr.parse().unwrap())
561        .await
562        .unwrap();
563
564    for _ in 0..50 {
565        let buf = client.recv().await.unwrap();
566        assert!(buf == [0xfe; 1000]);
567    }
568}
569
570#[tokio::test]
571async fn test_send_recv_with_flush() {
572    let mut server = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
573        .await
574        .unwrap();
575    let remote_addr = format!("127.0.0.1:{}", server.local_addr().unwrap().port());
576    let s1 = std::sync::Arc::new(tokio::sync::Semaphore::new(1));
577    let s2 = s1.clone();
578    tokio::spawn(async move {
579        server.listen().await;
580        let client = server.accept().await.unwrap();
581
582        for _ in 0..50 {
583            #[allow(unused_must_use)]
584            {
585                s1.acquire().await.unwrap();
586            }
587            client
588                .send(&vec![0xfe; 1000], Reliability::ReliableSequenced)
589                .await
590                .unwrap();
591            client.flush().await.unwrap();
592        }
593
594        client.close().await.unwrap();
595        for _ in 0..5 {
596            client
597                .send(&vec![0xfe; 1000], Reliability::ReliableSequenced)
598                .await
599                .unwrap();
600            match match client.flush().await {
601                Ok(_) => panic!("incorrect return"),
602                Err(e) => e,
603            } {
604                error::RaknetError::ConnectionClosed => {}
605                _ => panic!("incorrect return"),
606            };
607        }
608        server.close().await.unwrap();
609    });
610
611    let client = RaknetSocket::connect(&remote_addr.parse().unwrap())
612        .await
613        .unwrap();
614
615    for _ in 0..50 {
616        let buf = client.recv().await.unwrap();
617        assert!(buf == [0xfe; 1000]);
618        s2.add_permits(1);
619    }
620}
621
622/*
623#[tokio::test]
624async fn chore2(){
625
626    enbale_raknet_log(true);
627    let mut listener = RaknetListener::bind("0.0.0.0:19199".parse().unwrap()).await.unwrap();
628    listener.listen().await;
629    loop{
630        let mut client1 = listener.accept().await.unwrap();
631        let mut client2 = RaknetSocket::connect(&"192.168.199.127:19132".parse().unwrap()).await.unwrap();
632        tokio::spawn(async move {
633            println!("build connection");
634            loop{
635                tokio::select!{
636                    a = client1.recv() => {
637                        let a = match a{
638                            Ok(p) => p,
639                            Err(_) => {
640                                client2.close().await.unwrap();
641                                break;
642                            },
643                        };
644                        match client2.send(&a, Reliability::ReliableOrdered).await{
645                            Ok(p) => p,
646                            Err(_) => {
647                                client1.close().await.unwrap();
648                                break;
649                            },
650                        };
651                    },
652                    b = client2.recv() => {
653                        let b = match b{
654                            Ok(p) => p,
655                            Err(_) => {
656                                client1.close().await.unwrap();
657                                break;
658                            },
659                        };
660                        match client1.send(&b, Reliability::ReliableOrdered).await{
661                            Ok(p) => p,
662                            Err(_) => {
663                                client2.close().await.unwrap();
664                                break;
665                            },
666                        };
667                    }
668                }
669            }
670            println!("close connection");
671        });
672    }
673
674
675}
676*/
677
678#[cfg(feature = "send-policy")]
679#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
680async fn mixed_send_options_preserve_reliable_order_and_deliver_unreliable_data() {
681    use std::sync::Arc;
682    let mut listener = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
683        .await
684        .unwrap();
685    listener.listen().await;
686    let address = listener.local_addr().unwrap();
687    let options = SendOptions::default()
688        .with_in_flight_limits(128, 8192)
689        .unwrap()
690        .with_queue_budgets(4096, 2048)
691        .unwrap()
692        .with_flush_budget(2048)
693        .unwrap();
694    let client = Arc::new(RaknetSocket::connect(&address).await.unwrap());
695    assert_eq!(client.send_options().await, None);
696    client.set_send_options(options).await.unwrap();
697    assert_eq!(client.send_options().await, Some(options));
698    let server = listener.accept().await.unwrap();
699    let reliable = client.clone();
700    let send_reliable = tokio::spawn(async move {
701        for index in 0..100u8 {
702            let mut data = [0xfe; 128];
703            data[1] = 0;
704            data[2] = index;
705            reliable
706                .send(&data, Reliability::ReliableOrdered)
707                .await
708                .unwrap();
709        }
710        reliable.flush().await.unwrap();
711    });
712    let unreliable = client.clone();
713    let send_unreliable = tokio::spawn(async move {
714        for index in 0..100u8 {
715            let mut data = [0xfe; 64];
716            data[1] = 1;
717            data[2] = index;
718            unreliable
719                .send(&data, Reliability::Unreliable)
720                .await
721                .unwrap();
722            tokio::task::yield_now().await;
723        }
724    });
725    tokio::time::timeout(std::time::Duration::from_secs(5), async {
726        let mut ordered = 0u8;
727        let mut unordered = 0usize;
728        for _ in 0..200 {
729            let data = server.recv().await.unwrap();
730            if data[1] == 0 {
731                assert_eq!(data[2], ordered);
732                ordered += 1;
733            } else {
734                unordered += 1;
735            }
736        }
737        assert_eq!(ordered, 100);
738        assert_eq!(unordered, 100);
739        send_reliable.await.unwrap();
740        send_unreliable.await.unwrap();
741    })
742    .await
743    .unwrap();
744    client.close().await.unwrap();
745    server.close().await.unwrap();
746    listener.close().await.unwrap();
747}
748
749#[cfg(feature = "send-policy")]
750#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
751async fn unreliable_batch_streams_beyond_the_queue_reserve() {
752    let mut listener = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
753        .await
754        .unwrap();
755    listener.listen().await;
756    let client = RaknetSocket::connect(&listener.local_addr().unwrap())
757        .await
758        .unwrap();
759    client
760        .set_send_options(
761            SendOptions::default()
762                .with_queue_budgets(4096, 2048)
763                .unwrap(),
764        )
765        .await
766        .unwrap();
767    let server = listener.accept().await.unwrap();
768    let messages = (0..100u8)
769        .map(|i| {
770            let mut d = vec![0xfe; 64];
771            d[1] = i;
772            d
773        })
774        .collect::<Vec<_>>();
775    let borrowed = messages.iter().map(Vec::as_slice).collect::<Vec<_>>();
776    tokio::time::timeout(std::time::Duration::from_secs(5), async {
777        client
778            .send_batch(&borrowed, Reliability::Unreliable)
779            .await
780            .unwrap();
781        let mut received = std::collections::HashSet::new();
782        for _ in 0..100 {
783            let data = server.recv().await.unwrap();
784            assert_eq!(data.len(), 64);
785            assert!(received.insert(data[1]));
786        }
787    })
788    .await
789    .unwrap();
790    client.close().await.unwrap();
791    server.close().await.unwrap();
792    listener.close().await.unwrap();
793}