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#[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 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 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
99pub 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}