pub struct RawReadConnection {
pub read_stream: OwnedReadHalf,
pub buffer: Cursor<Vec<u8>>,
pub compression_threshold: Option<u32>,
pub dec_cipher: Option<Aes128CfbDec>,
}Fields§
§read_stream: OwnedReadHalf§buffer: Cursor<Vec<u8>>§compression_threshold: Option<u32>§dec_cipher: Option<Aes128CfbDec>Implementations§
Source§impl RawReadConnection
impl RawReadConnection
Sourcepub async fn read(&mut self) -> Result<Box<[u8]>, Box<ReadPacketError>>
pub async fn read(&mut self) -> Result<Box<[u8]>, Box<ReadPacketError>>
Examples found in repository?
azalea-protocol/examples/packet_logger.rs (line 351)
205async fn proxy_conn(
206 mut client_conn: Connection<ServerboundLoginPacket, ClientboundLoginPacket>,
207) -> Result<(), Box<dyn Error>> {
208 // resolve TARGET_ADDR
209 let parsed_target_addr = ServerAddr::try_from(TARGET_ADDR).unwrap();
210 let resolved_target_addr = resolve_address(&parsed_target_addr).await?;
211
212 let mut server_conn = Connection::new(&resolved_target_addr).await?;
213
214 let account = if ACCOUNT.contains('@') {
215 Account::microsoft(ACCOUNT).await?
216 } else {
217 Account::offline(ACCOUNT)
218 };
219 println!("got account: {:?}", account);
220
221 server_conn
222 .write(ServerboundIntention {
223 protocol_version: PROTOCOL_VERSION,
224 hostname: parsed_target_addr.host,
225 port: parsed_target_addr.port,
226 intention: ClientIntention::Login,
227 })
228 .await?;
229 let mut server_conn = server_conn.login();
230
231 // login
232 server_conn
233 .write(ServerboundHello {
234 name: account.username().to_owned(),
235 profile_id: account.uuid(),
236 })
237 .await?;
238
239 let (server_conn, login_finished) = loop {
240 let packet = server_conn.read().await?;
241
242 println!("got packet: {:?}", packet);
243
244 match packet {
245 ClientboundLoginPacket::Hello(p) => {
246 debug!("Got encryption request");
247 let e = azalea_crypto::encrypt(&p.public_key, &p.challenge).unwrap();
248
249 if let Some(access_token) = account.access_token() {
250 // keep track of the number of times we tried
251 // authenticating so we can give up after too many
252 let mut attempts: usize = 1;
253
254 while let Err(e) = {
255 server_conn
256 .authenticate(&access_token, &account.uuid(), e.secret_key, &p, None)
257 .await
258 } {
259 if attempts >= 2 {
260 // if this is the second attempt and we failed
261 // both times, give up
262 return Err(e.into());
263 }
264 if matches!(
265 e,
266 ClientSessionServerError::InvalidSession
267 | ClientSessionServerError::ForbiddenOperation
268 ) {
269 // uh oh, we got an invalid session and have
270 // to reauthenticate now
271 account.refresh().await?;
272 } else {
273 return Err(e.into());
274 }
275 attempts += 1;
276 }
277 }
278
279 server_conn
280 .write(ServerboundKey {
281 key_bytes: e.encrypted_public_key,
282 encrypted_challenge: e.encrypted_challenge,
283 })
284 .await?;
285
286 server_conn.set_encryption_key(e.secret_key);
287 }
288 ClientboundLoginPacket::LoginCompression(p) => {
289 debug!("Got compression request {:?}", p.compression_threshold);
290 server_conn.set_compression_threshold(p.compression_threshold);
291 }
292 ClientboundLoginPacket::LoginFinished(p) => {
293 debug!(
294 "Got profile {:?}. handshake is finished and we're now switching to the configuration state",
295 p.game_profile
296 );
297 // server_conn.write(ServerboundLoginAcknowledged {}).await?;
298 break (server_conn.config(), p);
299 }
300 ClientboundLoginPacket::LoginDisconnect(p) => {
301 error!("Got disconnect {p:?}");
302 return Err("Disconnected".into());
303 }
304 ClientboundLoginPacket::CustomQuery(p) => {
305 debug!("Got custom query {:?}", p);
306 // replying to custom query is done in
307 // packet_handling::login::process_packet_events
308 }
309 ClientboundLoginPacket::CookieRequest(p) => {
310 debug!("Got cookie request {:?}", p);
311
312 server_conn
313 .write(packets::login::ServerboundCookieResponse {
314 key: p.key,
315 // cookies aren't implemented
316 payload: None,
317 })
318 .await?;
319 }
320 }
321 };
322
323 // give the client the login_finished
324 println!("got the login_finished: {:?}", login_finished);
325 client_conn.write(login_finished).await?;
326 let client_conn = client_conn.config();
327
328 info!("started direct bridging");
329
330 // bridge packets
331 let listen_raw_reader = client_conn.reader.raw;
332 let listen_raw_writer = client_conn.writer.raw;
333
334 let target_raw_reader = server_conn.reader.raw;
335 let target_raw_writer = server_conn.writer.raw;
336
337 let packet_logs_txt = Arc::new(tokio::sync::Mutex::new(
338 File::create("combined.txt").await.unwrap(),
339 ));
340
341 let packet_logs_txt_clone = packet_logs_txt.clone();
342 let copy_listen_to_target = tokio::spawn(async move {
343 let mut listen_raw_reader = listen_raw_reader;
344 let mut target_raw_writer = target_raw_writer;
345
346 let packet_logs_txt = packet_logs_txt_clone;
347
348 let mut serverbound_parsed_txt = File::create("serverbound.txt").await.unwrap();
349
350 loop {
351 let packet = match listen_raw_reader.read().await {
352 Ok(p) => p,
353 Err(e) => {
354 error!("Error reading packet from listen: {e}");
355 return;
356 }
357 };
358
359 // decode as a game packet
360 let decoded_packet = azalea_protocol::read::deserialize_packet::<ServerboundGamePacket>(
361 &mut Cursor::new(&packet),
362 );
363
364 if let Ok(decoded_packet) = decoded_packet {
365 let timestamp = chrono::Utc::now();
366 let _ = serverbound_parsed_txt
367 .write_all(format!("{timestamp} {:?}\n", decoded_packet).as_bytes())
368 .await;
369 let _ = packet_logs_txt
370 .lock()
371 .await
372 .write_all(format!("{timestamp} <- {:?}\n", decoded_packet).as_bytes())
373 .await;
374 }
375
376 match target_raw_writer.write(&packet).await {
377 Ok(_) => {}
378 Err(e) => {
379 error!("Error writing packet to target: {e}");
380 return;
381 }
382 }
383 }
384 });
385
386 // write to clientbound.txt in a separate task so it doesn't block receiving
387 // packets
388 let (clientbound_tx, mut clientbound_rx) = tokio::sync::mpsc::unbounded_channel::<Box<[u8]>>();
389 let copy_clientbound_to_file = tokio::spawn(async move {
390 let mut clientbound_parsed_txt = File::create("clientbound.txt").await.unwrap();
391
392 loop {
393 let Some(packet) = clientbound_rx.recv().await else {
394 return;
395 };
396
397 // decode as a game packet
398 let decoded_packet = azalea_protocol::read::deserialize_packet::<ClientboundGamePacket>(
399 &mut Cursor::new(&packet),
400 );
401
402 if let Ok(decoded_packet) = decoded_packet {
403 let timestamp = chrono::Utc::now();
404 let _ = clientbound_parsed_txt
405 .write_all(format!("{timestamp} {decoded_packet:?}\n").as_bytes())
406 .await;
407 let _ = packet_logs_txt
408 .lock()
409 .await
410 .write_all(format!("{timestamp} -> {decoded_packet:?}\n").as_bytes())
411 .await;
412 }
413 }
414 });
415
416 let copy_remote_to_local = tokio::spawn(async move {
417 let mut target_raw_reader = target_raw_reader;
418 let mut listen_raw_writer = listen_raw_writer;
419
420 loop {
421 let packet = match target_raw_reader.read().await {
422 Ok(p) => p,
423 Err(e) => {
424 error!("Error reading packet from target: {e}");
425 return;
426 }
427 };
428
429 clientbound_tx.send(packet.clone()).unwrap();
430
431 match listen_raw_writer.write(&packet).await {
432 Ok(_) => {}
433 Err(e) => {
434 error!("Error writing packet to listen: {e}");
435 return;
436 }
437 }
438 }
439 });
440
441 tokio::try_join!(
442 copy_listen_to_target,
443 copy_remote_to_local,
444 copy_clientbound_to_file
445 )?;
446
447 Ok(())
448}pub fn try_read(&mut self) -> Result<Option<Box<[u8]>>, Box<ReadPacketError>>
Auto Trait Implementations§
impl Freeze for RawReadConnection
impl RefUnwindSafe for RawReadConnection
impl Send for RawReadConnection
impl Sync for RawReadConnection
impl Unpin for RawReadConnection
impl UnsafeUnpin for RawReadConnection
impl UnwindSafe for RawReadConnection
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Converts
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Converts
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Converts
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Converts
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Converts this type into the system output type.