mod acceptor;
mod event;
mod pkt_kind;
mod socket;
pub use acceptor::TsEventAcceptor;
pub use event::{Event, EventId};
pub use pkt_kind::TsPacketKind;
pub use socket::TsEventSocket;
use crate::services::{DEFAULT_BOOTID_HEX, DEFAULT_UNK0_HEX};
#[repr(u8)]
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum AgentIdStatus {
Unchanged = 0x1,
Changed = 0x2,
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct TsConnectInfo {
pub cid: [u8; 16],
pub unk0: [u8; 16],
pub aid: [u8; 16],
pub bootid: [u8; 16],
pub pt: [u8; 8],
}
impl TsConnectInfo {
pub fn new_simple(cid: [u8; 16]) -> Self {
Self {
cid,
unk0: hex::decode(DEFAULT_UNK0_HEX).unwrap().try_into().unwrap(),
aid: [0; 16],
bootid: hex::decode(DEFAULT_BOOTID_HEX).unwrap().try_into().unwrap(),
pt: [0; 8],
}
}
pub fn new_custom(
cid: [u8; 16],
unk0: [u8; 16],
aid: [u8; 16],
bootid: [u8; 16],
pt: [u8; 8],
) -> Self {
Self {
cid,
unk0,
aid,
bootid,
pt,
}
}
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct TsConnectResponse {
pub agent_id_status: AgentIdStatus,
pub aid: [u8; 16],
}
#[cfg(test)]
mod tests {
use super::*;
use crate::framing::{CloudProtoError, CloudProtoSocket};
use futures_util::{SinkExt, StreamExt};
use tokio::spawn;
#[tokio::test]
async fn test_simple_client_server() -> Result<(), CloudProtoError> {
let (client, server) = tokio::io::duplex(16 * 1024);
let cid = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8];
let old_aid = [4, 4, 4, 4, 2, 2, 2, 2, 8, 8, 8, 8, 1, 1, 1, 1];
let new_aid = [9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0];
let server_task = spawn(async move {
let (server, info) = TsEventAcceptor::listen(CloudProtoSocket::new(server)).await?;
assert_eq!(info.cid, cid);
assert_eq!(info.aid, old_aid);
let mut sock = server
.accept(TsConnectResponse {
agent_id_status: AgentIdStatus::Changed,
aid: new_aid,
})
.await?;
let ev = sock.next().await.unwrap()?;
assert_eq!(ev.event_id, Some(EventId::AgentOnline));
sock.send(Event::new(
EventId::LfoDownloadFromManifestRecord,
vec![1, 2, 3],
))
.await?;
Ok::<_, CloudProtoError>(sock) });
let mut client = TsEventSocket::connect(
CloudProtoSocket::new(client),
TsConnectInfo::new_custom(cid, [0; 16], old_aid, [0; 16], [0; 8]),
)
.await?;
client
.send(Event::new(EventId::AgentOnline, vec![]))
.await?;
let ev = client.next().await.unwrap()?;
assert_eq!(ev.event_id, Some(EventId::LfoDownloadFromManifestRecord));
assert_eq!(ev.data, &[1, 2, 3]);
server_task.await.expect("Server task join error!")?;
Ok(())
}
}