Skip to main content

deserialize_packet

Function deserialize_packet 

Source
pub fn deserialize_packet<P: ProtocolPacket + Debug>(
    stream: &mut Cursor<&[u8]>,
) -> Result<P, Box<ReadPacketError>>
Examples found in repository?
azalea-protocol/examples/packet_logger.rs (lines 360-362)
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}