bittorrent-dht: fix values decoding, as a list of peers

The "values" field is not a string, but instead peer information in
compact format. Decode this properly and then properly format in the
log.
pull/8113/head
Jason Ish 4 years ago committed by Victor Julien
parent 4a0859beeb
commit 2f9eb5d1dd

@ -100,7 +100,10 @@ fn log_bittorrent_dht(
if let Some(values) = &response.values { if let Some(values) = &response.values {
js.open_array("values")?; js.open_array("values")?;
for value in 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()?; js.close()?;
} }

@ -52,7 +52,7 @@ pub struct BitTorrentDHTResponse {
/// K(8) closest good nodes in routing table /// K(8) closest good nodes in routing table
pub nodes: Option<Vec<Node>>, pub nodes: Option<Vec<Node>>,
/// q = get_peers - list of compact peer infos /// 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 /// q = get_peers - token key required for sender's future
/// announce_peer query /// announce_peer query
pub token: Option<Vec<u8>>, pub token: Option<Vec<u8>>,
@ -73,6 +73,12 @@ pub struct Node {
pub port: u16, pub port: u16,
} }
#[derive(Debug, Eq, PartialEq)]
pub struct Peer {
pub ip: Vec<u8>,
pub port: u16,
}
/// Parse IPv4 node structures. /// Parse IPv4 node structures.
pub fn parse_node(i: &[u8]) -> IResult<&[u8], Node> { pub fn parse_node(i: &[u8]) -> IResult<&[u8], Node> {
let (i, id) = take(20usize)(i)?; let (i, id) = take(20usize)(i)?;
@ -88,6 +94,22 @@ pub fn parse_node(i: &[u8]) -> IResult<&[u8], Node> {
)) ))
} }
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 { impl FromBencode for BitTorrentDHTRequest {
// Try to parse with a `max_depth` of one. // Try to parse with a `max_depth` of one.
// //
@ -191,7 +213,7 @@ impl FromBencode for BitTorrentDHTResponse {
{ {
let mut id = None; let mut id = None;
let mut nodes = None; let mut nodes = None;
let mut values = None; let mut values = vec![];
let mut token = None; let mut token = None;
let mut dict_dec = object.try_into_dictionary()?; let mut dict_dec = object.try_into_dictionary()?;
@ -210,9 +232,14 @@ impl FromBencode for BitTorrentDHTResponse {
} }
} }
(b"values", value) => { (b"values", value) => {
values = Vec::decode_bencode_object(value) if let Object::List(mut list) = value {
.context("values") while let Some(entry) = list.next_object()? {
.map(Some)?; 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) => { (b"token", value) => {
token = value token = value
@ -229,7 +256,11 @@ impl FromBencode for BitTorrentDHTResponse {
Ok(BitTorrentDHTResponse { Ok(BitTorrentDHTResponse {
id: id.to_vec(), id: id.to_vec(),
nodes, nodes,
values, values: if values.is_empty() {
None
} else {
Some(values)
},
token, token,
}) })
} }

Loading…
Cancel
Save