stresser/
stresser.rs
1use std::io::{self, ErrorKind};
2use std::net::SocketAddr;
3
4use anyhow::bail;
5use tokio::io::AsyncWriteExt;
6use tokio::net::TcpStream;
7use uuid::Uuid;
8use valence_protocol::packets::handshaking::handshake_c2s::HandshakeNextState;
9use valence_protocol::packets::handshaking::HandshakeC2s;
10use valence_protocol::packets::login::{
11 LoginCompressionS2c, LoginHelloC2s, LoginHelloS2c, LoginSuccessS2c,
12};
13use valence_protocol::packets::play::{
14 KeepAliveC2s, KeepAliveS2c, PlayerPositionLookS2c, PositionAndOnGroundC2s, TeleportConfirmC2s,
15};
16use valence_protocol::var_int::VarInt;
17use valence_protocol::{
18 CompressionThreshold, Packet, PacketDecoder, PacketEncoder, PROTOCOL_VERSION,
19};
20
21pub struct SessionParams<'a> {
22 pub socket_addr: SocketAddr,
23 pub session_name: &'a str,
24 pub read_buffer_size: usize,
25}
26
27pub async fn make_session(params: &SessionParams<'_>) -> anyhow::Result<()> {
28 let sock_addr = params.socket_addr;
29 let sess_name = params.session_name;
30 let rb_size = params.read_buffer_size;
31
32 let mut conn = match TcpStream::connect(sock_addr).await {
33 Ok(conn) => {
34 println!("{sess_name} connected");
35 conn
36 }
37 Err(err) => {
38 eprintln!("{sess_name} connection failed");
39 return Err(err.into());
40 }
41 };
42
43 conn.set_nodelay(true)?;
44
45 let mut dec = PacketDecoder::new();
46 let mut enc = PacketEncoder::new();
47
48 let server_addr_str = sock_addr.ip().to_string();
49
50 let handshake_pkt = HandshakeC2s {
51 protocol_version: VarInt(PROTOCOL_VERSION),
52 server_address: server_addr_str.as_str().into(),
53 server_port: sock_addr.port(),
54 next_state: HandshakeNextState::Login,
55 };
56
57 enc.append_packet(&handshake_pkt)?;
58
59 enc.append_packet(&LoginHelloC2s {
60 username: sess_name.into(),
61 profile_id: Some(Uuid::new_v4()),
62 })?;
63
64 let write_buf = enc.take();
65 conn.write_all(&write_buf).await?;
66
67 loop {
68 dec.reserve(rb_size);
69
70 let mut read_buf = dec.take_capacity();
71
72 conn.readable().await?;
73
74 match conn.try_read_buf(&mut read_buf) {
75 Ok(0) => return Err(io::Error::from(ErrorKind::UnexpectedEof).into()),
76 Err(e) if e.kind() == io::ErrorKind::WouldBlock => continue,
77 Err(e) => return Err(e.into()),
78 Ok(_) => (),
79 };
80
81 dec.queue_bytes(read_buf);
82
83 if let Ok(Some(frame)) = dec.try_next_packet() {
84 match frame.id {
85 LoginCompressionS2c::ID => {
86 let packet: LoginCompressionS2c = frame.decode()?;
87 let threshold = packet.threshold.0;
88
89 dec.set_compression(CompressionThreshold(threshold));
90 enc.set_compression(CompressionThreshold(threshold));
91 }
92
93 LoginSuccessS2c::ID => {
94 break;
95 }
96
97 LoginHelloS2c::ID => {
98 bail!("encryption not implemented");
99 }
100
101 _ => (),
102 }
103 }
104 }
105
106 println!("{sess_name} logged in");
107
108 loop {
109 while let Some(frame) = dec.try_next_packet()? {
110 match frame.id {
111 KeepAliveS2c::ID => {
112 let packet: KeepAliveS2c = frame.decode()?;
113 enc.clear();
114
115 enc.append_packet(&KeepAliveC2s { id: packet.id })?;
116 conn.write_all(&enc.take()).await?;
117 }
118
119 PlayerPositionLookS2c::ID => {
120 let packet: PlayerPositionLookS2c = frame.decode()?;
121 enc.clear();
122
123 enc.append_packet(&TeleportConfirmC2s {
124 teleport_id: packet.teleport_id,
125 })?;
126
127 enc.append_packet(&PositionAndOnGroundC2s {
128 position: packet.position,
129 on_ground: true,
130 })?;
131
132 conn.write_all(&enc.take()).await?;
133 }
134 _ => (),
135 }
136 }
137
138 dec.reserve(rb_size);
139
140 let mut read_buf = dec.take_capacity();
141
142 conn.readable().await?;
143
144 match conn.try_read_buf(&mut read_buf) {
145 Ok(0) => return Err(io::Error::from(ErrorKind::UnexpectedEof).into()),
146 Err(e) if e.kind() == io::ErrorKind::WouldBlock => continue,
147 Err(e) => return Err(e.into()),
148 Ok(_) => (),
149 };
150
151 dec.queue_bytes(read_buf);
152 }
153}