cloudburst/dht/krpc/
ping.rs1use core::convert::TryFrom;
16use serde_derive::{Deserialize, Serialize};
17
18use crate::dht::node::{Id, LocalId};
19
20pub const METHOD_PING: &[u8] = b"ping";
22
23#[derive(Debug, Deserialize, Serialize)]
25pub struct QueryArgs<'a> {
26 #[serde(with = "serde_bytes")]
28 pub id: &'a [u8],
29}
30
31impl<'a> QueryArgs<'a> {
32 #[must_use]
34 #[inline]
35 pub fn new(id: &'a LocalId) -> Self {
36 Self { id: &(id.0).0 }
37 }
38
39 #[must_use]
41 #[inline]
42 pub fn id(&self) -> Option<Id> {
43 Id::try_from(self.id).ok()
44 }
45}
46
47#[derive(Debug, Deserialize, Serialize)]
49pub struct RespValues<'a> {
50 #[serde(with = "serde_bytes")]
52 pub id: &'a [u8],
53}
54
55impl<'a> RespValues<'a> {
56 #[must_use]
58 #[inline]
59 pub fn new(id: &'a LocalId) -> Self {
60 Self { id: &(id.0).0 }
61 }
62
63 #[must_use]
65 #[inline]
66 pub fn id(&self) -> Option<Id> {
67 Id::try_from(self.id).ok()
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 use crate::dht::krpc::{ser, Error, Msg, Ty};
76
77 #[test]
78 fn test_serde_ping_query() -> Result<(), Error> {
79 let ping_query = b"d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe";
80
81 let msg: Msg<'_> = bt_bencode::from_slice(ping_query.as_slice())?;
82 assert_eq!(msg.tx_id(), b"aa");
83 assert_eq!(msg.ty(), Ty::Query);
84 assert_eq!(msg.client_version(), None);
85 assert_eq!(msg.method_name().unwrap(), METHOD_PING);
86 assert_eq!(
87 msg.method_name_str(),
88 Some(core::str::from_utf8(METHOD_PING).unwrap())
89 );
90
91 let query_args: QueryArgs<'_> = msg.args().unwrap()?;
92 assert_eq!(query_args.id(), Some(Id::from(*b"abcdefghij0123456789")));
93
94 let ser_query_msg = ser::QueryMsg {
95 t: b"aa".as_slice(),
96 v: None,
97 q: METHOD_PING,
98 a: query_args,
99 };
100 let ser_msg = bt_bencode::to_vec(&ser_query_msg)?;
101 assert_eq!(ser_msg, ping_query);
102
103 Ok(())
104 }
105
106 #[test]
107 fn test_serde_ping_response() -> Result<(), Error> {
108 let ping_resp = b"d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re";
109
110 let msg: Msg<'_> = bt_bencode::from_slice(&ping_resp[..])?;
111 assert_eq!(msg.tx_id(), b"aa");
112 assert_eq!(msg.ty(), Ty::Response);
113 assert_eq!(msg.client_version(), None);
114
115 let resp_values: RespValues<'_> = msg.values().unwrap()?;
116 assert_eq!(resp_values.id(), Some(Id::from(*b"mnopqrstuvwxyz123456")));
117
118 let ser_resp_msg = ser::RespMsg {
119 t: b"aa".as_slice(),
120 v: None,
121 r: &resp_values,
122 };
123 let ser_msg = bt_bencode::to_vec(&ser_resp_msg)?;
124 assert_eq!(ser_msg, ping_resp);
125
126 Ok(())
127 }
128}