asyncio/ip/
tcp.rs

1use prelude::Protocol;
2use ffi::{IntoI32, AF_UNSPEC, AF_INET, AF_INET6, SOCK_STREAM,
3          IPPROTO_TCP, AI_PASSIVE, AI_NUMERICSERV};
4use stream_socket::StreamSocket;
5use socket_listener::SocketListener;
6use ip::{IpProtocol, IpEndpoint, Resolver, ResolverIter, ResolverQuery, Passive};
7
8use std::io;
9use std::fmt;
10use std::mem;
11
12/// The Transmission Control Protocol.
13///
14/// # Examples
15/// In this example, Create a TCP server socket and accept a connection by client.
16///
17/// ```rust,no_run
18/// use asyncio::{IoContext, Protocol, Endpoint};
19/// use asyncio::ip::{IpProtocol, Tcp, TcpEndpoint, TcpSocket, TcpListener};
20/// use asyncio::socket_base::ReuseAddr;
21///
22/// let ctx = &IoContext::new().unwrap();
23/// let ep = TcpEndpoint::new(Tcp::v4(), 12345);
24/// let soc = TcpListener::new(ctx, ep.protocol()).unwrap();
25///
26/// soc.set_option(ReuseAddr::new(true)).unwrap();
27/// soc.bind(&ep).unwrap();
28/// soc.listen().unwrap();
29///
30/// let (acc, ep) = soc.accept().unwrap();
31/// ```
32///
33/// # Examples
34/// In this example, Create a TCP client socket and connect to TCP server.
35///
36/// ```rust,no_run
37/// use asyncio::{IoContext, Protocol, Endpoint};
38/// use asyncio::ip::{IpProtocol, IpAddrV4, Tcp, TcpEndpoint, TcpSocket};
39///
40/// let ctx = &IoContext::new().unwrap();
41/// let soc = TcpSocket::new(ctx, Tcp::v4()).unwrap();
42///
43/// let _ = soc.connect(&TcpEndpoint::new(IpAddrV4::loopback(), 12345));
44/// ```
45///
46/// # Examples
47/// In this example, Resolve a TCP hostname and connect to TCP server.
48///
49/// ```rust,no_run
50/// use asyncio::{IoContext, Protocol, Endpoint};
51/// use asyncio::ip::{Tcp, TcpEndpoint, TcpSocket, TcpResolver};
52///
53/// let ctx = &IoContext::new().unwrap();
54/// let re = TcpResolver::new(ctx);
55/// let (soc, ep) = re.connect(("localhost", "12345")).unwrap();
56/// ```
57#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
58pub struct Tcp {
59    family: i32,
60}
61
62impl Protocol for Tcp {
63    type Endpoint = IpEndpoint<Self>;
64
65    fn family_type(&self) -> i32 {
66        self.family
67    }
68
69    fn socket_type(&self) -> i32 {
70        SOCK_STREAM as i32
71    }
72
73    fn protocol_type(&self) -> i32 {
74        IPPROTO_TCP.i32()
75    }
76
77    unsafe fn uninitialized(&self) -> Self::Endpoint {
78        mem::uninitialized()
79    }
80}
81
82impl IpProtocol for Tcp {
83    /// Represents a TCP for IPv4.
84    ///
85    /// # Examples
86    ///
87    /// ```
88    /// use asyncio::Endpoint;
89    /// use asyncio::ip::{IpProtocol, IpAddrV4, Tcp, TcpEndpoint};
90    ///
91    /// let ep = TcpEndpoint::new(IpAddrV4::any(), 0);
92    /// assert_eq!(Tcp::v4(), ep.protocol());
93    /// ```
94    fn v4() -> Tcp {
95        Tcp { family: AF_INET as i32 }
96    }
97
98    /// Represents a TCP for IPv6.
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// use asyncio::Endpoint;
104    /// use asyncio::ip::{IpProtocol, IpAddrV6, Tcp, TcpEndpoint};
105    ///
106    /// let ep = TcpEndpoint::new(IpAddrV6::any(), 0);
107    /// assert_eq!(Tcp::v6(), ep.protocol());
108    /// ```
109    fn v6() -> Tcp {
110        Tcp { family: AF_INET6 as i32 }
111    }
112}
113
114impl fmt::Debug for Tcp {
115    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116        if self.is_v4() {
117            write!(f, "TCPv4")
118        } else if self.is_v6() {
119            write!(f, "TCPv6")
120        } else {
121            unreachable!("Invalid address family ({}).", self.family);
122        }
123    }
124}
125
126impl fmt::Debug for IpEndpoint<Tcp> {
127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128        write!(f, "Endpoint(TCP/{})", self)
129    }
130}
131
132impl fmt::Debug for Resolver<Tcp, StreamSocket<Tcp>> {
133    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134        write!(f, "Resolver(TCP)")
135    }
136}
137
138impl ResolverQuery<Tcp> for (Passive, u16) {
139    fn iter(self) -> io::Result<ResolverIter<Tcp>> {
140        let port = self.1.to_string();
141        ResolverIter::new(&Tcp { family: AF_UNSPEC }, "", &port, AI_PASSIVE | AI_NUMERICSERV)
142    }
143}
144
145impl<'a> ResolverQuery<Tcp> for (Passive, &'a str) {
146    fn iter(self) -> io::Result<ResolverIter<Tcp>> {
147        ResolverIter::new(&Tcp { family: AF_UNSPEC }, "", self.1, AI_PASSIVE)
148    }
149}
150
151impl<'a, 'b> ResolverQuery<Tcp> for (&'a str, &'b str) {
152    fn iter(self) -> io::Result<ResolverIter<Tcp>> {
153        ResolverIter::new(&Tcp { family: AF_UNSPEC }, self.0, self.1, 0)
154    }
155}
156
157/// The TCP endpoint type.
158pub type TcpEndpoint = IpEndpoint<Tcp>;
159
160/// The TCP socket type.
161pub type TcpSocket = StreamSocket<Tcp>;
162
163/// The TCP listener type.
164pub type TcpListener = SocketListener<Tcp, StreamSocket<Tcp>>;
165
166/// The TCP resolver type.
167pub type TcpResolver = Resolver<Tcp, StreamSocket<Tcp>>;
168
169#[test]
170fn test_tcp() {
171    assert!(Tcp::v4() == Tcp::v4());
172    assert!(Tcp::v6() == Tcp::v6());
173    assert!(Tcp::v4() != Tcp::v6());
174}
175
176#[test]
177fn test_tcp_resolver() {
178    use IoContext;
179    use ip::*;
180
181    let ctx = &IoContext::new().unwrap();
182    let re = TcpResolver::new(ctx);
183    for ep in re.resolve(("127.0.0.1", "80")).unwrap() {
184        assert!(ep == TcpEndpoint::new(IpAddrV4::loopback(), 80));
185    }
186    for ep in re.resolve(("::1", "80")).unwrap() {
187        assert!(ep == TcpEndpoint::new(IpAddrV6::loopback(), 80));
188    }
189    for ep in re.resolve(("localhost", "http")).unwrap() {
190        assert!(ep.addr().is_loopback());
191        assert!(ep.port() == 80);
192    }
193}
194
195#[test]
196fn test_getsockname_v4() {
197    use prelude::Endpoint;
198    use core::IoContext;
199    use socket_base::ReuseAddr;
200    use ip::*;
201
202    let ctx = &IoContext::new().unwrap();
203    let ep = TcpEndpoint::new(IpAddrV4::any(), 12344);
204    let soc = TcpSocket::new(ctx, ep.protocol()).unwrap();
205    soc.set_option(ReuseAddr::new(true)).unwrap();
206    soc.bind(&ep).unwrap();
207    assert_eq!(soc.local_endpoint().unwrap(), ep);
208}
209
210#[test]
211fn test_getsockname_v6() {
212    use prelude::Endpoint;
213    use core::IoContext;
214    use socket_base::ReuseAddr;
215    use ip::*;
216
217    let ctx = &IoContext::new().unwrap();
218    let ep = TcpEndpoint::new(IpAddrV6::any(), 12346);
219    let soc = TcpSocket::new(ctx, ep.protocol()).unwrap();
220    soc.set_option(ReuseAddr::new(true)).unwrap();
221    soc.bind(&ep).unwrap();
222    assert_eq!(soc.local_endpoint().unwrap(), ep);
223}
224
225#[test]
226fn test_receive_error_when_not_connected() {
227    use core::IoContext;
228    use async::wrap;
229    use ip::Tcp;
230
231    use std::io;
232    use std::sync::{Arc, Mutex};
233
234    let ctx = &IoContext::new().unwrap();
235    let soc = Arc::new(Mutex::new(StreamSocket::new(ctx, Tcp::v4()).unwrap()));
236
237    let mut buf = [0; 256];
238    assert!(soc.lock().unwrap().receive(&mut buf, 0).is_err());
239
240    fn handler(_: Arc<Mutex<StreamSocket<Tcp>>>, res: io::Result<usize>) {
241        assert!(res.is_err());
242    }
243    soc.lock().unwrap().async_receive(&mut buf, 0, wrap(handler, &soc));
244
245    ctx.run();
246}
247
248#[test]
249fn test_send_error_when_not_connected() {
250    use core::IoContext;
251    use async::wrap;
252    use ip::Tcp;
253
254    use std::io;
255    use std::sync::{Arc, Mutex};
256
257    let ctx = &IoContext::new().unwrap();
258    let soc = Arc::new(Mutex::new(StreamSocket::new(ctx, Tcp::v4()).unwrap()));
259
260    let mut buf = [0; 256];
261    assert!(soc.lock().unwrap().send(&mut buf, 0).is_err());
262
263    fn handler(_: Arc<Mutex<StreamSocket<Tcp>>>, res: io::Result<usize>) {
264        assert!(res.is_err());
265    }
266    soc.lock().unwrap().async_send(&mut buf, 0, wrap(handler, &soc));
267
268    ctx.run();
269}
270
271#[test]
272fn test_format() {
273    use core::IoContext;
274
275    let ctx = &IoContext::new().unwrap();
276    println!("{:?}", Tcp::v4());
277    println!("{:?}", TcpEndpoint::new(Tcp::v4(), 12345));
278    println!("{:?}", TcpSocket::new(ctx, Tcp::v4()).unwrap());
279    println!("{:?}", TcpListener::new(ctx, Tcp::v4()).unwrap());
280    println!("{:?}", TcpResolver::new(ctx));
281}