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