1use prelude::{Protocol, SockAddr, Endpoint};
2use ffi::{SockAddrImpl, sockaddr_in, sockaddr_in6, sockaddr_storage, gethostname, AF_INET, AF_INET6, };
3use core::IoContext;
4
5use std::io;
6use std::fmt;
7use std::mem;
8use std::marker::PhantomData;
9
10mod addr;
11pub use self::addr::*;
12
13pub trait IpProtocol : Protocol + Eq {
14 fn v4() -> Self;
15
16 fn v6() -> Self;
17
18 fn is_v4(&self) -> bool {
19 self == &Self::v4()
20 }
21
22 fn is_v6(&self) -> bool {
23 self == &Self::v6()
24 }
25}
26
27#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
29pub struct IpEndpoint<P> {
30 ss: SockAddrImpl<sockaddr_storage>,
31 _marker: PhantomData<P>,
32}
33
34impl<P: Protocol> IpEndpoint<P> {
35 pub fn new<T>(addr: T, port: u16) -> Self
44 where T: IntoEndpoint<P>,
45 {
46 addr.into_endpoint(port)
47 }
48
49 pub fn is_v4(&self) -> bool {
63 self.ss.ss_family as i32 == AF_INET
64 }
65
66 pub fn is_v6(&self) -> bool {
80 self.ss.ss_family as i32 == AF_INET6
81 }
82
83 pub fn addr(&self) -> IpAddr {
85 match self.ss.ss_family as i32 {
86 AF_INET => unsafe {
87 let sin: &sockaddr_in = mem::transmute(&*self.ss);
88 let bytes: [u8; 4] = mem::transmute(sin.sin_addr);
89 IpAddr::V4(IpAddrV4::from(bytes))
90 },
91 AF_INET6 => unsafe {
92 let sin6: &sockaddr_in6 = mem::transmute(&*self.ss);
93 let bytes: [u8; 16] = mem::transmute(sin6.sin6_addr);
94 IpAddr::V6(IpAddrV6::from(bytes, sin6.sin6_scope_id))
95 },
96 _ => panic!("Invalid address family ({}).", self.ss.ss_family),
97 }
98 }
99
100 pub fn port(&self) -> u16 {
102 let sin: &sockaddr_in = unsafe { mem::transmute(&*self.ss) };
103 u16::from_be(sin.sin_port)
104 }
105
106 fn from_v4(addr: &IpAddrV4, port: u16) -> IpEndpoint<P> {
107 let mut ep = IpEndpoint {
108 ss: SockAddrImpl::new(AF_INET, mem::size_of::<sockaddr_in>()),
109 _marker: PhantomData,
110 };
111 unsafe {
112 let sin: &mut sockaddr_in = mem::transmute(&mut *ep.ss);
113 sin.sin_port = port.to_be();
114 sin.sin_addr = mem::transmute(addr.as_bytes().clone());
115 sin.sin_zero = [0; 8];
116 }
117 ep
118 }
119
120 fn from_v6(addr: &IpAddrV6, port: u16) -> IpEndpoint<P> {
121 let mut ep = IpEndpoint {
122 ss: SockAddrImpl::new(AF_INET6, mem::size_of::<sockaddr_in6>()),
123 _marker: PhantomData,
124 };
125 unsafe {
126 let sin6: &mut sockaddr_in6 = mem::transmute(&mut *ep.ss);
127 sin6.sin6_port = port.to_be();
128 sin6.sin6_flowinfo = 0;
129 sin6.sin6_addr = mem::transmute(addr.as_bytes().clone());
130 sin6.sin6_scope_id = addr.get_scope_id();
131 }
132 ep
133 }
134}
135
136impl<P: Protocol> SockAddr for IpEndpoint<P> {
137 type SockAddr = sockaddr_storage;
138
139 fn as_ref(&self) -> &Self::SockAddr {
140 &*self.ss
141 }
142
143 unsafe fn as_mut(&mut self) -> &mut Self::SockAddr {
144 &mut *self.ss
145 }
146
147 fn capacity(&self) -> usize {
148 self.ss.capacity()
149 }
150
151 fn size(&self) -> usize {
152 self.ss.size()
153 }
154
155 unsafe fn resize(&mut self, size: usize) {
156 debug_assert!(size <= self.capacity());
157 self.ss.resize(size)
158 }
159}
160
161impl<P: Protocol> fmt::Display for IpEndpoint<P> {
162 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
163 match self.addr() {
164 IpAddr::V4(addr) => write!(f, "{}:{}", addr, self.port()),
165 IpAddr::V6(addr) => write!(f, "[{}]:{}", addr, self.port()),
166 }
167 }
168}
169
170impl<P: IpProtocol> Endpoint<P> for IpEndpoint<P> {
171 fn protocol(&self) -> P {
172 if self.is_v4() {
173 P::v4()
174 } else if self.is_v6() {
175 P::v6()
176 } else {
177 unreachable!("Invalid address family ({}).", self.ss.ss_family);
178 }
179 }
180}
181
182pub trait IntoEndpoint<P: Protocol> {
184 fn into_endpoint(self, port: u16) -> IpEndpoint<P>;
185}
186
187impl<P: IpProtocol> IntoEndpoint<P> for P {
188 fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
189 if self.is_v4() {
190 IpEndpoint::from_v4(&IpAddrV4::any(), port)
191 } else if self.is_v6() {
192 IpEndpoint::from_v6(&IpAddrV6::any(), port)
193 } else {
194 unreachable!("Invalid protocol");
195 }
196 }
197}
198
199impl<P: Protocol> IntoEndpoint<P> for IpAddrV4 {
200 fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
201 IpEndpoint::from_v4(&self, port)
202 }
203}
204
205impl<P: Protocol> IntoEndpoint<P> for IpAddrV6 {
206 fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
207 IpEndpoint::from_v6(&self, port)
208 }
209}
210
211impl<P: Protocol> IntoEndpoint<P> for IpAddr {
212 fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
213 match self {
214 IpAddr::V4(addr) => IpEndpoint::from_v4(&addr, port),
215 IpAddr::V6(addr) => IpEndpoint::from_v6(&addr, port),
216 }
217 }
218}
219
220impl<'a, P: Protocol> IntoEndpoint<P> for &'a IpAddrV4 {
221 fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
222 IpEndpoint::from_v4(self, port)
223 }
224}
225
226impl<'a, P: Protocol> IntoEndpoint<P> for &'a IpAddrV6 {
227 fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
228 IpEndpoint::from_v6(self, port)
229 }
230}
231
232impl<'a, P: Protocol> IntoEndpoint<P> for &'a IpAddr {
233 fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
234 match self {
235 &IpAddr::V4(ref addr) => IpEndpoint::from_v4(addr, port),
236 &IpAddr::V6(ref addr) => IpEndpoint::from_v6(addr, port),
237 }
238 }
239}
240
241pub fn host_name(_: &IoContext) -> io::Result<String> {
253 gethostname()
254}
255
256mod resolver;
257pub use self::resolver::*;
258
259mod tcp;
260pub use self::tcp::*;
261
262mod udp;
263pub use self::udp::*;
264
265mod icmp;
266pub use self::icmp::*;
267
268mod options;
269pub use self::options::*;
270
271#[test]
272fn test_host_name() {
273 let ctx = &IoContext::new().unwrap();
274 host_name(ctx).unwrap();
275}
276
277#[test]
278fn test_endpoint_v4() {
279 let ep = UdpEndpoint::new(IpAddrV4::new(1,2,3,4), 10);
280 assert!(ep.is_v4());
281 assert!(!ep.is_v6());
282 assert_eq!(ep.addr(), IpAddr::V4(IpAddrV4::new(1,2,3,4)));
283 assert_eq!(ep.port(), 10);
284}
285
286#[test]
287fn test_endpoint_v6() {
288 let ep = TcpEndpoint::new(IpAddrV6::new(1,2,3,4,5,6,7,8), 10);
289 assert!(ep.is_v6());
290 assert!(!ep.is_v4());
291 assert_eq!(ep.addr(), IpAddr::V6(IpAddrV6::new(1,2,3,4,5,6,7,8)));
292 assert_eq!(ep.port(), 10);
293}
294
295#[test]
296fn test_endpoint_cmp() {
297 let a = IcmpEndpoint::new(IpAddrV6::new(1,2,3,4,5,6,7,8), 10);
298 let b = IcmpEndpoint::new(IpAddrV6::with_scope_id(1,2,3,4,5,6,7,8,1), 10);
299 let c = IcmpEndpoint::new(IpAddrV6::new(1,2,3,4,5,6,7,8), 11);
300 assert!(a == a && b == b && c == c);
301 assert!(a != b && b != c);
302 assert!(a < b);
303 assert!(b < c);
304}