asyncio/local/
mod.rs

1use prelude::{Protocol, SockAddr};
2use core::Socket;
3use ffi::{AF_UNIX, SockAddrImpl, sockaddr_un};
4use error::{invalid_argument};
5
6use std::io;
7use std::fmt;
8use std::mem;
9use std::slice;
10use std::ffi::{CStr, CString};
11use std::marker::PhantomData;
12
13/// The endpoint of UNIX domain socket.
14#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
15pub struct LocalEndpoint<P: Protocol> {
16    sun: SockAddrImpl<sockaddr_un>,
17    _marker: PhantomData<P>,
18}
19
20impl<P: Protocol> LocalEndpoint<P> {
21    /// Returns a `LocalEndpoint`.
22    ///
23    /// # Example
24    ///
25    /// ```
26    /// use asyncio::local::LocalStreamEndpoint;
27    ///
28    /// assert!(LocalStreamEndpoint::new("file name").is_ok());
29    /// assert!(LocalStreamEndpoint::new("file name very long                                                                                                  ").is_err());
30    /// ```
31    pub fn new<T>(path_name: T) -> io::Result<LocalEndpoint<P>>
32        where T: AsRef<str>
33    {
34        match CString::new(path_name.as_ref()) {
35            Ok(ref s) if s.as_bytes().len() < (mem::size_of::<sockaddr_un>() - 2) => {
36                let src = s.as_bytes_with_nul();
37                let mut ep = LocalEndpoint {
38                    sun: SockAddrImpl::new(AF_UNIX, src.len() + 2),
39                    _marker: PhantomData,
40                };
41                let dst = unsafe { slice::from_raw_parts_mut(
42                    ep.sun.sun_path.as_mut_ptr() as *mut u8,
43                    src.len()
44                ) };
45                dst.clone_from_slice(src);
46                Ok(ep)
47            }
48            _ => Err(invalid_argument()),
49        }
50    }
51
52    /// Returns a path_name associated with the endpoint.
53    ///
54    /// # Example
55    ///
56    /// ```
57    /// use asyncio::local::LocalStreamEndpoint;
58    ///
59    /// let ep = LocalStreamEndpoint::new("foo.sock").unwrap();
60    /// assert_eq!(ep.path(), "foo.sock");
61    /// ```
62    pub fn path(&self) -> &str {
63        let cstr = unsafe { CStr::from_ptr(self.sun.sun_path.as_ptr()) };
64        cstr.to_str().unwrap()
65    }
66}
67
68impl<P: Protocol> SockAddr for LocalEndpoint<P> {
69    type SockAddr = sockaddr_un;
70
71    fn as_ref(&self) -> &Self::SockAddr {
72        &*self.sun
73    }
74
75    unsafe fn as_mut(&mut self) -> &mut Self::SockAddr {
76        &mut *self.sun
77    }
78
79    fn capacity(&self) -> usize {
80        self.sun.capacity()
81    }
82
83    fn size(&self) -> usize {
84        self.sun.size()
85    }
86
87    unsafe fn resize(&mut self, size: usize) {
88        debug_assert!(size <= self.capacity());
89        self.sun.resize(size)
90    }
91}
92
93impl<P: Protocol> fmt::Display for LocalEndpoint<P> {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        write!(f, "{}", self.path())
96    }
97}
98
99/// A category of an local protocol.
100pub trait LocalProtocol : Protocol {
101    type Socket : Socket<Self>;
102}
103
104mod dgram;
105pub use self::dgram::*;
106
107mod stream;
108pub use self::stream::*;
109
110mod seq_packet;
111pub use self::seq_packet::*;
112
113mod connect_pair;
114pub use self::connect_pair::*;
115
116
117#[test]
118fn test_local_endpoint_limit() {
119    assert_eq!(LocalStreamEndpoint::new("foo").unwrap(),
120               LocalStreamEndpoint::new("foo").unwrap());
121    assert!(LocalDgramEndpoint::new("").is_ok());
122    let s = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
123    assert!(LocalSeqPacketEndpoint::new(&s[..103]).is_ok());
124    assert!(LocalSeqPacketEndpoint::new(&s[..108]).is_err());
125}