dbus_bytestream/
address.rs

1use std::io;
2use std::net::{SocketAddr, ToSocketAddrs};
3use std::path::{Path, PathBuf};
4use std::string;
5use std::str::FromStr;
6use std::str::Split;
7use std::vec;
8
9use rustc_serialize::hex::{FromHex,FromHexError};
10
11#[derive(Debug, PartialEq)]
12pub enum UnescapeError {
13    ShortEscapeSequence,
14    EscapeNotUtf8,
15    HexConversionError
16}
17
18impl From<FromHexError> for UnescapeError {
19    fn from(_: FromHexError) -> Self {
20        UnescapeError::HexConversionError
21    }
22}
23
24impl From<string::FromUtf8Error> for UnescapeError {
25    fn from(_: string::FromUtf8Error) -> Self {
26        UnescapeError::EscapeNotUtf8
27    }
28}
29
30fn dbus_unescape(buf: &[u8]) -> Result<Vec<u8>, UnescapeError> {
31    let mut out = Vec::with_capacity(buf.len());
32    let mut i = buf.iter();
33    while let Some(c) = i.next() {
34        if *c == b'%' {
35            let c1 = *try!(i.next().ok_or(UnescapeError::ShortEscapeSequence));
36            let c2 = *try!(i.next().ok_or(UnescapeError::ShortEscapeSequence));
37            let x = try!(String::from_utf8(vec!(c1, c2)));
38            out.push(*try!(x.from_hex()).get(0).unwrap());
39        } else {
40            out.push(*c);
41        }
42    }
43    Ok(out)
44}
45
46fn dbus_unescape_str(s: &str) -> Result<String, UnescapeError> {
47    let vec = try!(dbus_unescape(s.as_bytes()));
48    String::from_utf8(vec).map_err(From::from)
49}
50
51#[derive(Debug, PartialEq)]
52pub enum Error {
53    UnescapeError(UnescapeError),
54    BadTransportSeparator,
55    MalformedKeyValue,
56    UnknownTransport,
57    UnknownOption,
58    MissingOption,
59    ConflictingOptions,
60}
61
62pub type ServerAddressError = (Error, String);
63
64impl From<UnescapeError> for ServerAddressError {
65    fn from(e: UnescapeError) -> Self {
66        (Error::UnescapeError(e), "".to_owned())
67    }
68}
69
70
71/// Iterator over key value pairs of the form "key=val,key=val"
72struct AddrKeyVals<'a> {
73    str: Split<'a, char>,
74}
75
76impl<'a> AddrKeyVals<'a> {
77    fn new(s: &'a str) -> Self {
78        AddrKeyVals { str: s.split(',') }
79    }
80
81    fn get_next(&mut self) -> Option<&'a str> {
82        loop {
83            let kvs = self.str.next();
84            if kvs.is_none() || kvs.unwrap() != "" {
85                return kvs;
86            }
87        }
88    }
89}
90
91impl<'a> Iterator for AddrKeyVals<'a> {
92    type Item = Result<(String, String), ServerAddressError>;
93
94    fn next(&mut self) -> Option<Self::Item> {
95        let kvs = self.get_next();
96        if kvs.is_none() {
97            return None;
98        }
99        let mut keyval = kvs.unwrap().split('=');
100        if keyval.clone().count() != 2 {
101            return Some(Err((Error::MalformedKeyValue, kvs.unwrap().to_owned())));
102        }
103
104        let key = dbus_unescape_str(keyval.next().unwrap());
105        if let Err(e) = key {
106            return Some(Err(From::from(e)));
107        }
108        let val = dbus_unescape_str(keyval.next().unwrap());
109        if let Err(e) = val {
110            return Some(Err(From::from(e)));
111        }
112        // Unwrap is ok because we just checked that there are two elements
113        Some(Ok((key.unwrap(), val.unwrap())))
114    }
115}
116
117/// A DBus Unix address
118#[derive(Debug)]
119pub struct UnixAddress {
120    path: PathBuf,
121}
122
123impl<'a> UnixAddress {
124    /// Returns the Unix path
125    pub fn path(&'a self) -> &'a Path {
126        self.path.as_path()
127    }
128}
129
130impl FromStr for UnixAddress {
131    type Err = ServerAddressError;
132
133    /// Constructs a UnixAddress from a key=value option string
134    fn from_str(opts: &str) -> Result<Self, ServerAddressError> {
135        let keyvals = AddrKeyVals::new(opts);
136        let mut path = None;
137        let mut abs = false;
138        for kv in keyvals {
139            let kv = try!(kv);
140
141            match kv.0.as_ref() {
142                "path" | "abstract" => {
143                    if path.is_none() {
144                        path = Some(kv.1);
145                    } else {
146                        return Err((Error::ConflictingOptions,
147                                    "Duplicate path/abstract specified".to_owned()));
148                    }
149                },
150                "guid" => {}, // Ignore for now
151                _ => return Err((Error::UnknownOption, kv.0))
152            }
153            if kv.0 == "abstract" {
154                abs = true;
155            }
156        }
157        if path == None {
158            Err((Error::MissingOption, "No path for unix socket".to_owned()))
159        } else {
160            let mut path = path.unwrap();
161            if abs {
162                path = "\0".to_owned() + &path;
163            }
164            Ok(UnixAddress { path: PathBuf::from(path) })
165        }
166    }
167}
168
169/// A DBus Tcp address
170#[derive(Debug)]
171pub struct TcpAddress {
172    host: String,
173    port: String,
174}
175
176impl ToSocketAddrs for TcpAddress {
177    type Iter = vec::IntoIter<SocketAddr>;
178    /// Returns the Tcp path
179    fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
180        (self.host.clone() + ":" + &self.port).to_socket_addrs()
181    }
182}
183
184impl FromStr for TcpAddress {
185    type Err = ServerAddressError;
186
187    /// Constructs a TcpAddress from a key=value option string
188    fn from_str(opts: &str) -> Result<Self, ServerAddressError> {
189        let mut host = None;
190        let mut port = None;
191        for kv in AddrKeyVals::new(opts) {
192            let kv = try!(kv);
193
194            match kv.0.as_ref() {
195                "host" => {
196                    if host.is_none() {
197                        host = Some(kv.1);
198                    } else {
199                        return Err((Error::ConflictingOptions,
200                                    "Duplicate host specified".to_owned()));
201                    }
202                },
203                "port" => {
204                    if port.is_none() {
205                        port = Some(kv.1);
206                    } else {
207                        return Err((Error::ConflictingOptions,
208                                    "Duplicate port specified".to_owned()));
209                    }
210                },
211                "guid" => {}, // Ignore for now
212                _ => return Err((Error::UnknownOption, kv.0))
213            }
214        }
215        if host == None {
216            Err((Error::MissingOption, "No host for tcp socket".to_owned()))
217        } else if port == None {
218            Err((Error::MissingOption, "No port for tcp socket".to_owned()))
219        } else {
220            Ok(TcpAddress { host: host.unwrap(), port: port.unwrap() })
221        }
222    }
223}
224
225#[derive(Debug)]
226pub enum ServerAddress {
227    Unix(UnixAddress),
228    Tcp(TcpAddress),
229}
230
231impl FromStr for ServerAddress {
232    type Err = ServerAddressError;
233
234    fn from_str(s: &str) -> Result<Self, Self::Err> {
235        let mut sp = s.split(':');
236        if sp.clone().count() != 2 {
237            return Err((Error::BadTransportSeparator, s.to_owned()));
238        }
239        // Unwrap is ok because we just checked that there are two elements
240        let transport = sp.next().unwrap();
241        let opts = sp.next().unwrap();
242
243        match transport {
244            "unix" => Ok(ServerAddress::Unix(try!(UnixAddress::from_str(opts)))),
245            "tcp" => Ok(ServerAddress::Tcp(try!(TcpAddress::from_str(opts)))),
246            _ => Err((Error::UnknownTransport, transport.to_owned())),
247        }
248    }
249}
250
251#[test]
252fn test_unescape() {
253    assert_eq!(dbus_unescape(b"hello").unwrap(), b"hello");
254    assert_eq!(dbus_unescape(b"\\").unwrap(), b"\\");
255    assert_eq!(dbus_unescape(b"%61").unwrap(), b"a");
256    assert_eq!(dbus_unescape(b"%5c").unwrap(), b"\\");
257    assert_eq!(dbus_unescape(b"%").unwrap_err(), UnescapeError::ShortEscapeSequence);
258    assert_eq!(dbus_unescape(b"%1").unwrap_err(), UnescapeError::ShortEscapeSequence);
259}
260
261#[test]
262fn test_key_vals() {
263    let mut a = AddrKeyVals::new("one=two").map(Result::unwrap);
264    assert_eq!(a.next().unwrap(), ("one".to_string(), "two".to_string()));
265    assert_eq!(a.next(), None);
266
267    let mut a = AddrKeyVals::new("foo=bar,").map(Result::unwrap);
268    assert_eq!(a.next().unwrap(), ("foo".to_string(), "bar".to_string()));
269    assert_eq!(a.next(), None);
270
271    let mut a = AddrKeyVals::new("foo=bar,a=b").map(Result::unwrap);
272    assert_eq!(a.next().unwrap(), ("foo".to_string(), "bar".to_string()));
273    assert_eq!(a.next().unwrap(), ("a".to_string(), "b".to_string()));
274    assert_eq!(a.next(), None);
275
276    let mut a = AddrKeyVals::new("foobar,a=b");
277    assert_eq!(a.next().unwrap().unwrap_err().0, Error::MalformedKeyValue);
278}
279
280#[test]
281fn test_server_address() {
282    assert_eq!(ServerAddress::from_str("unix").unwrap_err().0, Error::BadTransportSeparator);
283    ServerAddress::from_str("unix:path=/var/run/dbus/system_bus_socket").unwrap();
284    assert_eq!(ServerAddress::from_str("unix:path=/var/run/dbus/system_bus_socket,foo=bar").unwrap_err().0, Error::UnknownOption);
285    assert_eq!(ServerAddress::from_str("unix:").unwrap_err().0, Error::MissingOption);
286}