@@ -104,6 +104,51 @@ impl UdpSocket {
104
104
}
105
105
}
106
106
107
+ /// Closes the reading half of this socket.
108
+ ///
109
+ /// This method will close the reading portion of this socket, causing
110
+ /// all pending and future reads to immediately return with an error.
111
+ ///
112
+ /// # Example
113
+ ///
114
+ /// ```no_run
115
+ /// # #![allow(unused_must_use)]
116
+ /// use std::io::timer;
117
+ /// use std::io::net::udp::UdpSocket;
118
+ ///
119
+ /// let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
120
+ /// let mut sock = UdpSocket::bind(addr).unwrap();
121
+ /// let sock2 = sock.clone();
122
+ ///
123
+ /// spawn(proc() {
124
+ /// // close the reading half of the socket after 1 second
125
+ /// timer::sleep(1000);
126
+ /// let mut sock = sock2;
127
+ /// sock.close_read();
128
+ /// });
129
+ ///
130
+ /// // wait for some data, will get canceled after one second
131
+ /// let mut buf = [0];
132
+ /// let _ = sock.recvfrom(buf);
133
+ /// ```
134
+ ///
135
+ /// Note that this method affects all cloned handles associated with this
136
+ /// socket, not just this one handle.
137
+ pub fn close_read ( & mut self ) -> IoResult < ( ) > {
138
+ self . obj . close_read ( ) . map_err ( IoError :: from_rtio_error)
139
+ }
140
+
141
+ /// Closes the writing half of this socket.
142
+ ///
143
+ /// This method will close the writing portion of this socket, causing
144
+ /// all future writes to immediately return with an error.
145
+ ///
146
+ /// Note that this method affects all cloned handles associated with this
147
+ /// socket, not just this one handle.
148
+ pub fn close_write ( & mut self ) -> IoResult < ( ) > {
149
+ self . obj . close_write ( ) . map_err ( IoError :: from_rtio_error)
150
+ }
151
+
107
152
/// Returns the socket address that this socket was created from.
108
153
pub fn socket_name ( & mut self ) -> IoResult < SocketAddr > {
109
154
match self . obj . socket_name ( ) {
@@ -526,6 +571,59 @@ mod test {
526
571
serv_rx. recv( ) ;
527
572
} )
528
573
574
+
575
+ iotest ! ( fn close_readwrite_smoke( ) {
576
+ let addr = next_test_ip4( ) ;
577
+ let addr2 = next_test_ip4( ) ;
578
+ let server = UdpSocket :: bind( addr) . unwrap( ) ;
579
+ let client1 = UdpSocket :: bind( addr2) . unwrap( ) ;
580
+ let client2 = client1. clone( ) ;
581
+ let mut b = [ 0 ] ;
582
+
583
+ // closing should prevent reads/writes
584
+ client1. close_write( ) . unwrap( ) ;
585
+ assert!( client1. sendto( addr, [ 0 ] ) . is_err( ) ) ;
586
+ client1. close_read( ) . unwrap( ) ;
587
+ assert!( client1. recvfrom( b) . is_err( ) ) ;
588
+
589
+ // closing should affect previous handles
590
+ assert!( client2. write( addr, [ 0 ] ) . is_err( ) ) ;
591
+ assert!( client2. recvfrom( b) . is_err( ) ) ;
592
+
593
+ // closing should affect new handles
594
+ let mut client3 = s. clone( ) ;
595
+ assert!( client3. sendto( addr, [ 0 ] ) . is_err( ) ) ;
596
+ assert!( client3. recvfrom( b) . is_err( ) ) ;
597
+
598
+ // make sure these don't die
599
+ let _ = client2. close_read( ) ;
600
+ let _ = client2. close_write( ) ;
601
+ let _ = client3. close_read( ) ;
602
+ let _ = client3. close_write( ) ;
603
+ } )
604
+
605
+ iotest ! ( fn close_read_wakes_up( ) {
606
+ let addr = next_test_ip4( ) ;
607
+ let addr2 = next_test_ip4( ) ;
608
+ let server = UdpSocket :: bind( addr) . unwrap( ) ;
609
+ let client1 = UdpSocket :: bind( addr2) . unwrap( ) ;
610
+ let client2 = client1. clone( ) ;
611
+ let mut b = [ 0 ] ;
612
+
613
+ let ( tx, rx) = channel( ) ;
614
+ spawn( proc( ) {
615
+ let mut client2 = client2;
616
+ assert!( client2. recvfrom( [ 0 ] ) . is_err( ) ) ;
617
+ tx. send( ( ) ) ;
618
+ } ) ;
619
+
620
+ // this should wake up the child task
621
+ client1. close_read( ) . unwrap( ) ;
622
+
623
+ // this test will never finish if the child doesn't wake up
624
+ rx. recv( ) ;
625
+ } )
626
+
529
627
iotest ! ( fn recvfrom_timeout( ) {
530
628
let addr1 = next_test_ip4( ) ;
531
629
let addr2 = next_test_ip4( ) ;
0 commit comments