1 | //! Simple TCP echo server to check memory leaks using Valgrind. |
2 | use std::{thread::sleep, time::Duration}; |
3 | |
4 | use tokio::{ |
5 | io::{AsyncReadExt, AsyncWriteExt}, |
6 | net::{TcpListener, TcpSocket}, |
7 | runtime::Builder, |
8 | sync::oneshot, |
9 | }; |
10 | |
11 | const TCP_ENDPOINT: &str = "127.0.0.1:8080" ; |
12 | const NUM_MSGS: usize = 100; |
13 | const MSG_SIZE: usize = 1024; |
14 | |
15 | fn main() { |
16 | let rt = Builder::new_multi_thread().enable_io().build().unwrap(); |
17 | let rt2 = Builder::new_multi_thread().enable_io().build().unwrap(); |
18 | |
19 | rt.spawn(async { |
20 | let listener = TcpListener::bind(TCP_ENDPOINT).await.unwrap(); |
21 | let (mut socket, _) = listener.accept().await.unwrap(); |
22 | let (mut rd, mut wr) = socket.split(); |
23 | while tokio::io::copy(&mut rd, &mut wr).await.is_ok() {} |
24 | }); |
25 | |
26 | // wait a bit so that the listener binds. |
27 | sleep(Duration::from_millis(100)); |
28 | |
29 | // create a channel to let the main thread know that all the messages were sent and received. |
30 | let (tx, mut rx) = oneshot::channel(); |
31 | |
32 | rt2.spawn(async { |
33 | let addr = TCP_ENDPOINT.parse().unwrap(); |
34 | let socket = TcpSocket::new_v4().unwrap(); |
35 | let mut stream = socket.connect(addr).await.unwrap(); |
36 | |
37 | let mut buff = [0; MSG_SIZE]; |
38 | for _ in 0..NUM_MSGS { |
39 | let one_mega_random_bytes: Vec<u8> = |
40 | (0..MSG_SIZE).map(|_| rand::random::<u8>()).collect(); |
41 | stream |
42 | .write_all(one_mega_random_bytes.as_slice()) |
43 | .await |
44 | .unwrap(); |
45 | stream.read(&mut buff).await.unwrap(); |
46 | } |
47 | tx.send(()).unwrap(); |
48 | }); |
49 | |
50 | loop { |
51 | // check that we're done. |
52 | match rx.try_recv() { |
53 | Err(oneshot::error::TryRecvError::Empty) => (), |
54 | Err(oneshot::error::TryRecvError::Closed) => panic!("channel got closed..." ), |
55 | Ok(()) => break, |
56 | } |
57 | } |
58 | } |
59 | |