netdoc: add an iterator that can parse annotated microdescs

This commit is contained in:
Nick Mathewson 2020-06-07 18:57:26 -04:00
parent 78aa76ab36
commit 624843668a
2 changed files with 127 additions and 1 deletions

View File

@ -48,6 +48,15 @@ pub struct Microdesc {
// pr is obsolete and doesn't go here any more.
}
/// A microdescriptor annotated with additional data
///
/// TODO: rename this.
#[allow(dead_code)]
pub struct AnnotatedMicrodesc {
md: Microdesc,
ann: MicrodescAnnotation,
}
decl_keyword! {
/// Keyword type for recognized objects in microdescriptors.
MicrodescKW {
@ -84,6 +93,12 @@ lazy_static! {
};
}
impl Default for MicrodescAnnotation {
fn default() -> Self {
MicrodescAnnotation { last_listed: None }
}
}
impl MicrodescAnnotation {
#[allow(dead_code)]
fn parse_from_reader(
@ -206,14 +221,86 @@ impl Microdesc {
})
}
}
/// An iterator that parses one or more (possible annnotated)
/// microdescriptors from a string.
pub struct MicrodescReader<'a> {
annotated: bool,
reader: NetDocReader<'a, MicrodescKW>,
}
/// Indicates whether we should parse an annotated list of votes or a
/// non-annotated list.
///
/// TODO: Move this.
#[derive(PartialEq, Debug)]
pub enum AllowAnnotations {
/// Parsing a document where items might be annotated.
///
/// Annotations are a list of zero or more items with keywords
/// beginning with @ that precede the items that are actually part
/// of the document.
AnnotationsAllowed,
/// Parsing a document where annotations are not allowed.
AnnotationsNotAllowed,
}
impl<'a> MicrodescReader<'a> {
/// Construct a MicrodescReader to take microdescriptors from a string
/// 's'.
pub fn new(s: &'a str, allow: AllowAnnotations) -> Self {
let reader = NetDocReader::new(s);
let annotated = allow == AllowAnnotations::AnnotationsAllowed;
MicrodescReader { annotated, reader }
}
fn take_annotation(&mut self) -> Result<MicrodescAnnotation> {
if self.annotated {
MicrodescAnnotation::parse_from_reader(&mut self.reader)
} else {
Ok(MicrodescAnnotation::default())
}
}
fn take_annotated_microdesc(&mut self) -> Result<AnnotatedMicrodesc> {
let ann = self.take_annotation()?;
let md = Microdesc::parse_from_reader(&mut self.reader)?;
Ok(AnnotatedMicrodesc { md, ann })
// TODO need to advance to next likely md.
}
}
impl<'a> Iterator for MicrodescReader<'a> {
type Item = Result<AnnotatedMicrodesc>;
fn next(&mut self) -> Option<Self::Item> {
// If there is no next token, we're at the end.
self.reader.iter().peek()?;
Some(self.take_annotated_microdesc())
}
}
#[cfg(test)]
mod test {
use super::*;
const TESTDATA: &str = include_str!("../testdata/microdesc1.txt");
const TESTDATA2: &str = include_str!("../testdata/microdesc2.txt");
#[test]
fn parse_arbitrary() -> Result<()> {
fn parse_single() -> Result<()> {
let _md = Microdesc::parse(TESTDATA)?;
Ok(())
}
#[test]
fn parse_multi() -> Result<()> {
let mut n: u32 = 0;
for md in MicrodescReader::new(TESTDATA2, AllowAnnotations::AnnotationsAllowed) {
md?;
n += 1;
}
assert_eq!(n, 4);
Ok(())
// TODO: test actual contents.
}
}

39
tor-netdoc/testdata/microdesc2.txt vendored Normal file
View File

@ -0,0 +1,39 @@
@last-listed 2020-01-27 18:52:09
onion-key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAMaCi6KwIpOaPFhyMJsJC+r516p0kZXnEuaJLgSR5uakJDW31qDlwD29
dDLBwT4RmiD+OPNSjBpdEIJDbaDNGdgQLpdLgpl7v5ONoOQ3cRlbySOLmZ/7fYeW
DE+4eDLemIqU2e3lEOnb/bpCdQ309FX5OiKDcNy8tqtWgoOdOE0/AgMBAAE=
-----END RSA PUBLIC KEY-----
ntor-onion-key XoldZTBKOhiUYWZgFD969XV/4IvBgEXHhV7o3ruebEc=
family $06804E6383EE94E83C9453F39B1E524C272D6D84 $0D12D8E72DED99EE31BB0C57789352BED0CEEEFF $113143469021882C3A4B82F084F8125B08EE471E $4BFC9C631A93FF4BA3AA84BC6931B4310C38A263 $530277866466A1425F43A73DBFCB5FC7410C9852 $5BA19B5D5AB0CB9EF8EA33DA77585B75449400B0 $763B7D67A6B2D19B3E9EA57D1FBDC48F3B85B559 $7AA7FC80E3E0D32E929D2CC094EACF529C95264C $8CF987FF43FB7F3D9AA4C4F3D96FFDF247A9A6C2 $9661AC95717798884F3E3727D360DD98D66727CC $96E095D5CDBFC3988DEB708EC155346472402C32 $97AEE1EEFBCBB6FF8FA482029830E8E10A961883 $B1045E12FA4EA0D457A74013866CB41DC0D290BF $B27CF1DCEECD50F7992B07D720D7F6BF0EDF9D40 $BE0AC3B6692085308CA766F9E03736D1CAAED6F3 $C282248597D1C8522A2A7525E61C8B77BBC37614 $C8AE26D4819504D0157AD4C5DE7D5A0A7E190D10 $D24D0C28AB48768CF8B79DD762D61DB4FD015677 $DE847D94E78B2E560AB87D272DC90192D3144F17 $F34E681AF8226DEBC9135A48F61DEF9F68966BA5 $FEDF4998951A750D5D7974DF243035499E84882E
p accept 43,80,443,853,873,993,995,1194,2086,3128,5222-5223,5269,8000,8008,8080,8232-8233,8443,8888,9418,11371
p6 accept 43,80,443,853,873,993,995,1194,2086,3128,5222-5223,5269,8000,8008,8080,8232-8233,8443,8888,9418,11371
id ed25519 LYX9yI5sG8+0aJf8odum0TVPkyYdaKeeC1vBcN2SMIQ
@last-listed 2020-01-27 18:52:09
onion-key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAMJi4/MtSJv4lYgLfq+z+2S90cGwIJJfp/mIxx0wX/q7jX6MWGG4+NQx
gofp3zxAEgglTfdTsvFFzQN4PjVkuwyFmmcYukVmS86e35nmPT3Yq3DPSXBRCtX5
mMXC68bQT+npnPnoafxMdQddWCATkSD8wBrUKix4nOOaOcoD73SfAgMBAAE=
-----END RSA PUBLIC KEY-----
ntor-onion-key siPT+/px5J0pgsTdAWxCNRHbghZ98E6QY2Ioxl7Y2x0=
id ed25519 eQEthL1Cz57iO7GZ8RtS5lNiBVGCW9KH+VCBpOikywc
@last-listed 2020-01-27 18:52:10
onion-key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALWooFgPxb0v6TR6PtAlLZWQ5vsX8oTJCiD4yg1bPv2MA2KnquQj+lys
H0yh/8MH814J/qFkjgTFt7An3U5VRnOyD9BAAJuT7FsqAFTlPzn2hK/PliE/K2/N
XMeaV6brBOcYvhMR9EWV+zBRpvkkQWqSqNlVjZi78fD1s/y0TjzTAgMBAAE=
-----END RSA PUBLIC KEY-----
ntor-onion-key mp9h+hzj2D18B/dLvu4RlEaTktzqrSThY5hc0cSEoBg=
id ed25519 3B+5CwspC+alleI5eA7jvxp6aGBC8QvF1D3wKBSwEDQ
@last-listed 2020-01-27 18:52:09
onion-key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAMESE/ElGU2kyaq0VJ7mwGvns6mhMm75ZyYDbR+Eaa3b18PVOslR4aEv
3RJAt9N4Ph7N2VHZHVxwPKWViVDhZNMvOD5PJLb587KmTvD77Eo6MSh6umxy6xvo
GfgJJlyrlBQdvxRZVfEmUvjdZixbJUCI9ydxQG7hBk1n89dgLnTJAgMBAAE=
-----END RSA PUBLIC KEY-----
ntor-onion-key wcEKLkC4GnqCN0LJxRecweZgYmTg4whSxzFmhAmJYGQ=
id ed25519 1az7VeHFAgB0KwtxH+nQJSi3dw8rIl4iT5sMqeodTDg