if let Some(values) = &response.values {
js.open_array("values")?;
for value in values {
- js.append_string(value)?;
+ js.start_object()?;
+ js.set_string("ip", &print_ip_addr(&value.ip))?;
+ js.set_uint("port", value.port.into())?;
+ js.close()?;
}
js.close()?;
}
/// K(8) closest good nodes in routing table
pub nodes: Option<Vec<Node>>,
/// q = get_peers - list of compact peer infos
- pub values: Option<Vec<String>>,
+ pub values: Option<Vec<Peer>>,
/// q = get_peers - token key required for sender's future
/// announce_peer query
pub token: Option<Vec<u8>>,
pub port: u16,
}
+#[derive(Debug, Eq, PartialEq)]
+pub struct Peer {
+ pub ip: Vec<u8>,
+ pub port: u16,
+}
+
/// Parse IPv4 node structures.
pub fn parse_node(i: &[u8]) -> IResult<&[u8], Node> {
let (i, id) = take(20usize)(i)?;
))
}
+fn parse_peer(i: &[u8]) -> IResult<&[u8], Peer> {
+ let (i, ip) = if i.len() < 18 {
+ take(4usize)(i)
+ } else {
+ take(16usize)(i)
+ }?;
+ let (i, port) = be_u16(i)?;
+ Ok((
+ i,
+ Peer {
+ ip: ip.to_vec(),
+ port,
+ },
+ ))
+}
+
impl FromBencode for BitTorrentDHTRequest {
// Try to parse with a `max_depth` of one.
//
{
let mut id = None;
let mut nodes = None;
- let mut values = None;
+ let mut values = vec![];
let mut token = None;
let mut dict_dec = object.try_into_dictionary()?;
}
}
(b"values", value) => {
- values = Vec::decode_bencode_object(value)
- .context("values")
- .map(Some)?;
+ if let Object::List(mut list) = value {
+ while let Some(entry) = list.next_object()? {
+ let (_, peer) =
+ parse_peer(entry.try_into_bytes().context("values.entry")?)
+ .map_err(|_| Error::malformed_content("values.entry.peer"))?;
+ values.push(peer);
+ }
+ }
}
(b"token", value) => {
token = value
Ok(BitTorrentDHTResponse {
id: id.to_vec(),
nodes,
- values,
+ values: if values.is_empty() {
+ None
+ } else {
+ Some(values)
+ },
token,
})
}