about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLuqman Aden <me@luqman.ca>2013-07-25 02:33:43 -0400
committerLuqman Aden <me@luqman.ca>2013-07-25 05:57:52 -0400
commit61e741cf714020107c6cda12793351fa5b8c7782 (patch)
tree9d603295e8567bb9648fef359bc58e4194132e15
parent4a726f0573dcfcd01ae9b37266014df0e26f2e22 (diff)
downloadrust-61e741cf714020107c6cda12793351fa5b8c7782.tar.gz
rust-61e741cf714020107c6cda12793351fa5b8c7782.zip
libstd: Implement {peer, socket}_name for new rt tcp & udp.
-rw-r--r--src/libstd/rt/io/net/tcp.rs38
-rw-r--r--src/libstd/rt/io/net/udp.rs13
-rw-r--r--src/libstd/rt/rtio.rs4
-rw-r--r--src/libstd/rt/uv/async.rs2
-rw-r--r--src/libstd/rt/uv/idle.rs2
-rw-r--r--src/libstd/rt/uv/mod.rs6
-rw-r--r--src/libstd/rt/uv/net.rs22
-rw-r--r--src/libstd/rt/uv/timer.rs2
-rw-r--r--src/libstd/rt/uv/uvio.rs134
-rw-r--r--src/libstd/rt/uv/uvll.rs48
-rw-r--r--src/rt/rust_uv.cpp60
-rw-r--r--src/rt/rustrt.def.in9
12 files changed, 227 insertions, 113 deletions
diff --git a/src/libstd/rt/io/net/tcp.rs b/src/libstd/rt/io/net/tcp.rs
index 2425c909bf3..5251b6d9ded 100644
--- a/src/libstd/rt/io/net/tcp.rs
+++ b/src/libstd/rt/io/net/tcp.rs
@@ -14,8 +14,9 @@ use rt::io::net::ip::IpAddr;
 use rt::io::{Reader, Writer, Listener};
 use rt::io::{io_error, read_error, EndOfFile};
 use rt::rtio::{IoFactory, IoFactoryObject,
-               RtioTcpListener, RtioTcpListenerObject,
-               RtioTcpStream, RtioTcpStreamObject};
+               RtioSocket, RtioTcpListener,
+               RtioTcpListenerObject, RtioTcpStream,
+               RtioTcpStreamObject};
 use rt::local::Local;
 
 pub struct TcpStream(~RtioTcpStreamObject);
@@ -42,6 +43,28 @@ impl TcpStream {
             }
         }
     }
+
+    pub fn peer_name(&mut self) -> Option<IpAddr> {
+        match (***self).peer_name() {
+            Ok(pn) => Some(pn),
+            Err(ioerr) => {
+                rtdebug!("failed to get peer name: %?", ioerr);
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+
+    pub fn socket_name(&mut self) -> Option<IpAddr> {
+        match (***self).socket_name() {
+            Ok(sn) => Some(sn),
+            Err(ioerr) => {
+                rtdebug!("failed to get socket name: %?", ioerr);
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
 }
 
 impl Reader for TcpStream {
@@ -90,6 +113,17 @@ impl TcpListener {
             }
         }
     }
+
+    pub fn socket_name(&mut self) -> Option<IpAddr> {
+        match (***self).socket_name() {
+            Ok(sn) => Some(sn),
+            Err(ioerr) => {
+                rtdebug!("failed to get socket name: %?", ioerr);
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
 }
 
 impl Listener<TcpStream> for TcpListener {
diff --git a/src/libstd/rt/io/net/udp.rs b/src/libstd/rt/io/net/udp.rs
index 59649dee5b9..d78adbbbe4d 100644
--- a/src/libstd/rt/io/net/udp.rs
+++ b/src/libstd/rt/io/net/udp.rs
@@ -13,7 +13,7 @@ use result::{Ok, Err};
 use rt::io::net::ip::IpAddr;
 use rt::io::{Reader, Writer};
 use rt::io::{io_error, read_error, EndOfFile};
-use rt::rtio::{RtioUdpSocketObject, RtioUdpSocket, IoFactory, IoFactoryObject};
+use rt::rtio::{RtioSocket, RtioUdpSocketObject, RtioUdpSocket, IoFactory, IoFactoryObject};
 use rt::local::Local;
 
 pub struct UdpSocket(~RtioUdpSocketObject);
@@ -53,6 +53,17 @@ impl UdpSocket {
     pub fn connect(self, other: IpAddr) -> UdpStream {
         UdpStream { socket: self, connectedTo: other }
     }
+
+    pub fn socket_name(&mut self) -> Option<IpAddr> {
+        match (***self).socket_name() {
+            Ok(sn) => Some(sn),
+            Err(ioerr) => {
+                rtdebug!("failed to get socket name: %?", ioerr);
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
 }
 
 pub struct UdpStream {
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
index aa8b9dc3a94..73b38c4a40d 100644
--- a/src/libstd/rt/rtio.rs
+++ b/src/libstd/rt/rtio.rs
@@ -59,7 +59,7 @@ pub trait RtioTcpListener : RtioSocket {
 pub trait RtioTcpStream : RtioSocket {
     fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError>;
     fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
-    fn peer_name(&mut self) -> IpAddr;
+    fn peer_name(&mut self) -> Result<IpAddr, IoError>;
     fn control_congestion(&mut self);
     fn nodelay(&mut self);
     fn keepalive(&mut self, delay_in_seconds: uint);
@@ -67,7 +67,7 @@ pub trait RtioTcpStream : RtioSocket {
 }
 
 pub trait RtioSocket {
-    fn socket_name(&mut self) -> IpAddr;
+    fn socket_name(&mut self) -> Result<IpAddr, IoError>;
 }
 
 pub trait RtioUdpSocket : RtioSocket {
diff --git a/src/libstd/rt/uv/async.rs b/src/libstd/rt/uv/async.rs
index 81428509e33..47e0a240e45 100644
--- a/src/libstd/rt/uv/async.rs
+++ b/src/libstd/rt/uv/async.rs
@@ -34,7 +34,7 @@ impl AsyncWatcher {
 
         extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
             let mut watcher: AsyncWatcher = NativeHandle::from_native_handle(handle);
-            let status = status_to_maybe_uv_error(watcher.native_handle(), status);
+            let status = status_to_maybe_uv_error(watcher, status);
             let data = watcher.get_watcher_data();
             let cb = data.async_cb.get_ref();
             (*cb)(watcher, status);
diff --git a/src/libstd/rt/uv/idle.rs b/src/libstd/rt/uv/idle.rs
index 28b101f686d..b73be9f7250 100644
--- a/src/libstd/rt/uv/idle.rs
+++ b/src/libstd/rt/uv/idle.rs
@@ -43,7 +43,7 @@ impl IdleWatcher {
             let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
             let data = idle_watcher.get_watcher_data();
             let cb: &IdleCallback = data.idle_cb.get_ref();
-            let status = status_to_maybe_uv_error(handle, status);
+            let status = status_to_maybe_uv_error(idle_watcher, status);
             (*cb)(idle_watcher, status);
         }
     }
diff --git a/src/libstd/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs
index 0eaf0dd3ab6..aacd747087e 100644
--- a/src/libstd/rt/uv/mod.rs
+++ b/src/libstd/rt/uv/mod.rs
@@ -282,14 +282,14 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
 }
 
 /// Given a uv handle, convert a callback status to a UvError
-// XXX: Follow the pattern below by parameterizing over T: Watcher, not T
-pub fn status_to_maybe_uv_error<T>(handle: *T, status: c_int) -> Option<UvError> {
+pub fn status_to_maybe_uv_error<T, U: Watcher + NativeHandle<*T>>(handle: U,
+                                                                 status: c_int) -> Option<UvError> {
     if status != -1 {
         None
     } else {
         unsafe {
             rtdebug!("handle: %x", handle as uint);
-            let loop_ = uvll::get_loop_for_uv_handle(handle);
+            let loop_ = uvll::get_loop_for_uv_handle(handle.native_handle());
             rtdebug!("loop: %x", loop_ as uint);
             let err = uvll::last_error(loop_);
             Some(UvError(err))
diff --git a/src/libstd/rt/uv/net.rs b/src/libstd/rt/uv/net.rs
index 86891a9df8a..dbfe36acbeb 100644
--- a/src/libstd/rt/uv/net.rs
+++ b/src/libstd/rt/uv/net.rs
@@ -22,7 +22,7 @@ use str;
 use from_str::{FromStr};
 use num;
 
-enum UvIpAddr {
+pub enum UvIpAddr {
     UvIpv4(*sockaddr_in),
     UvIpv6(*sockaddr_in6),
 }
@@ -32,8 +32,8 @@ fn sockaddr_to_UvIpAddr(addr: *uvll::sockaddr) -> UvIpAddr {
         assert!((is_ip4_addr(addr) || is_ip6_addr(addr)));
         assert!(!(is_ip4_addr(addr) && is_ip6_addr(addr)));
         match addr {
-            _ if is_ip4_addr(addr) => UvIpv4(as_sockaddr_in(addr)),
-            _ if is_ip6_addr(addr) => UvIpv6(as_sockaddr_in6(addr)),
+            _ if is_ip4_addr(addr) => UvIpv4(addr as *uvll::sockaddr_in),
+            _ if is_ip6_addr(addr) => UvIpv6(addr as *uvll::sockaddr_in6),
             _ => fail!(),
         }
     }
@@ -133,7 +133,7 @@ fn uv_ip_as_ip<T>(addr: UvIpAddr, f: &fn(IpAddr) -> T) -> T {
     f(ip)
 }
 
-fn uv_ip_to_ip(addr: UvIpAddr) -> IpAddr {
+pub fn uv_ip_to_ip(addr: UvIpAddr) -> IpAddr {
     use util;
     uv_ip_as_ip(addr, util::id)
 }
@@ -154,7 +154,7 @@ fn test_ip6_conversion() {
     assert_eq!(ip6, ip_as_uv_ip(ip6, uv_ip_to_ip));
 }
 
-// uv_stream t is the parent class of uv_tcp_t, uv_pipe_t, uv_tty_t
+// uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t, uv_tty_t
 // and uv_file_t
 pub struct StreamWatcher(*uvll::uv_stream_t);
 impl Watcher for StreamWatcher { }
@@ -180,7 +180,7 @@ impl StreamWatcher {
             rtdebug!("buf len: %d", buf.len as int);
             let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream);
             let cb = stream_watcher.get_watcher_data().read_cb.get_ref();
-            let status = status_to_maybe_uv_error(stream, nread as c_int);
+            let status = status_to_maybe_uv_error(stream_watcher, nread as c_int);
             (*cb)(stream_watcher, nread as int, buf, status);
         }
     }
@@ -210,7 +210,7 @@ impl StreamWatcher {
             let mut stream_watcher = write_request.stream();
             write_request.delete();
             let cb = stream_watcher.get_watcher_data().write_cb.take_unwrap();
-            let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status);
+            let status = status_to_maybe_uv_error(stream_watcher, status);
             cb(stream_watcher, status);
         }
     }
@@ -302,7 +302,7 @@ impl TcpWatcher {
                 let mut stream_watcher = connect_request.stream();
                 connect_request.delete();
                 let cb = stream_watcher.get_watcher_data().connect_cb.take_unwrap();
-                let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status);
+                let status = status_to_maybe_uv_error(stream_watcher, status);
                 cb(stream_watcher, status);
             }
         }
@@ -325,7 +325,7 @@ impl TcpWatcher {
             rtdebug!("connection_cb");
             let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle);
             let cb = stream_watcher.get_watcher_data().connect_cb.get_ref();
-            let status = status_to_maybe_uv_error(handle, status);
+            let status = status_to_maybe_uv_error(stream_watcher, status);
             (*cb)(stream_watcher, status);
         }
     }
@@ -402,7 +402,7 @@ impl UdpWatcher {
             rtdebug!("buf len: %d", buf.len as int);
             let mut udp_watcher: UdpWatcher = NativeHandle::from_native_handle(handle);
             let cb = udp_watcher.get_watcher_data().udp_recv_cb.get_ref();
-            let status = status_to_maybe_uv_error(handle, nread as c_int);
+            let status = status_to_maybe_uv_error(udp_watcher, nread as c_int);
             let addr = uv_ip_to_ip(sockaddr_to_UvIpAddr(addr));
             (*cb)(udp_watcher, nread as int, buf, addr, flags as uint, status);
         }
@@ -437,7 +437,7 @@ impl UdpWatcher {
             let mut udp_watcher = send_request.handle();
             send_request.delete();
             let cb = udp_watcher.get_watcher_data().udp_send_cb.take_unwrap();
-            let status = status_to_maybe_uv_error(udp_watcher.native_handle(), status);
+            let status = status_to_maybe_uv_error(udp_watcher, status);
             cb(udp_watcher, status);
         }
     }
diff --git a/src/libstd/rt/uv/timer.rs b/src/libstd/rt/uv/timer.rs
index bc5399327a0..eaa5e77a6da 100644
--- a/src/libstd/rt/uv/timer.rs
+++ b/src/libstd/rt/uv/timer.rs
@@ -43,7 +43,7 @@ impl TimerWatcher {
             let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
             let data = watcher.get_watcher_data();
             let cb = data.timer_cb.get_ref();
-            let status = status_to_maybe_uv_error(handle, status);
+            let status = status_to_maybe_uv_error(watcher, status);
             (*cb)(watcher, status);
         }
     }
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index 9c386b4bed1..9f2316d6227 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -19,6 +19,7 @@ use rt::io::IoError;
 use rt::io::net::ip::IpAddr;
 use rt::uv::*;
 use rt::uv::idle::IdleWatcher;
+use rt::uv::net::{UvIpv4, UvIpv6};
 use rt::rtio::*;
 use rt::sched::Scheduler;
 use rt::io::{standard_error, OtherIoError};
@@ -220,7 +221,9 @@ impl IoFactory for UvIoFactory {
                 rtdebug!("connect: in connect callback");
                 if status.is_none() {
                     rtdebug!("status is none");
-                    let res = Ok(~UvTcpStream(stream_watcher));
+                    let tcp_watcher =
+                        NativeHandle::from_native_handle(stream_watcher.native_handle());
+                    let res = Ok(~UvTcpStream(tcp_watcher));
 
                     // Store the stream in the task's stack
                     unsafe { (*result_cell_ptr).put_back(res); }
@@ -286,7 +289,6 @@ impl IoFactory for UvIoFactory {
     }
 }
 
-// FIXME #6090: Prefer newtype structs but Drop doesn't work
 pub struct UvTcpListener {
     watcher: TcpWatcher,
     listening: bool,
@@ -320,8 +322,33 @@ impl Drop for UvTcpListener {
 }
 
 impl RtioSocket for UvTcpListener {
-    // XXX implement
-    fn socket_name(&mut self) -> IpAddr { fail!(); }
+    fn socket_name(&mut self) -> Result<IpAddr, IoError> {
+        // Allocate a sockaddr_storage
+        // since we don't know if it's ipv4 or ipv6
+        let r_addr = unsafe { uvll::malloc_sockaddr_storage() };
+
+        let r = unsafe {
+            uvll::rust_uv_tcp_getsockname(self.watcher.native_handle(),
+                                          r_addr as *uvll::sockaddr_storage)
+        };
+
+        if r != 0 {
+            let status = status_to_maybe_uv_error(self.watcher, r);
+            return Err(uv_error_to_io_error(status.unwrap()));
+        }
+
+        let addr = unsafe {
+            if uvll::is_ip6_addr(r_addr as *uvll::sockaddr) {
+                net::uv_ip_to_ip(UvIpv6(r_addr as *uvll::sockaddr_in6))
+            } else {
+                net::uv_ip_to_ip(UvIpv4(r_addr as *uvll::sockaddr_in))
+            }
+        };
+
+        unsafe { uvll::free_sockaddr_storage(r_addr); }
+
+        Ok(addr)
+    }
 }
 
 impl RtioTcpListener for UvTcpListener {
@@ -344,9 +371,8 @@ impl RtioTcpListener for UvTcpListener {
             let maybe_stream = if status.is_none() {
                 let mut loop_ = server_stream_watcher.event_loop();
                 let client_tcp_watcher = TcpWatcher::new(&mut loop_);
-                let client_tcp_watcher = client_tcp_watcher.as_stream();
                 // XXX: Need's to be surfaced in interface
-                server_stream_watcher.accept(client_tcp_watcher);
+                server_stream_watcher.accept(client_tcp_watcher.as_stream());
                 Ok(~UvTcpStream(client_tcp_watcher))
             } else {
                 Err(standard_error(OtherIoError))
@@ -365,8 +391,7 @@ impl RtioTcpListener for UvTcpListener {
     fn dont_accept_simultaneously(&mut self) { fail!(); }
 }
 
-// FIXME #6090: Prefer newtype structs but Drop doesn't work
-pub struct UvTcpStream(StreamWatcher);
+pub struct UvTcpStream(TcpWatcher);
 
 impl Drop for UvTcpStream {
     fn drop(&self) {
@@ -374,7 +399,7 @@ impl Drop for UvTcpStream {
         let scheduler = Local::take::<Scheduler>();
         do scheduler.deschedule_running_task_and_then |_, task| {
             let task_cell = Cell::new(task);
-            do self.close {
+            do self.as_stream().close {
                 let scheduler = Local::take::<Scheduler>();
                 scheduler.resume_blocked_task_immediately(task_cell.take());
             }
@@ -383,8 +408,33 @@ impl Drop for UvTcpStream {
 }
 
 impl RtioSocket for UvTcpStream {
-    // XXX implement
-    fn socket_name(&mut self) -> IpAddr { fail!(); }
+    fn socket_name(&mut self) -> Result<IpAddr, IoError> {
+        // Allocate a sockaddr_storage
+        // since we don't know if it's ipv4 or ipv6
+        let r_addr = unsafe { uvll::malloc_sockaddr_storage() };
+
+        let r = unsafe {
+            uvll::rust_uv_tcp_getsockname(self.native_handle(),
+                                          r_addr as *uvll::sockaddr_storage)
+        };
+
+        if r != 0 {
+            let status = status_to_maybe_uv_error(**self, r);
+            return Err(uv_error_to_io_error(status.unwrap()));
+        }
+
+        let addr = unsafe {
+            if uvll::is_ip6_addr(r_addr as *uvll::sockaddr) {
+                net::uv_ip_to_ip(UvIpv6(r_addr as *uvll::sockaddr_in6))
+            } else {
+                net::uv_ip_to_ip(UvIpv4(r_addr as *uvll::sockaddr_in))
+            }
+        };
+
+        unsafe { uvll::free_sockaddr_storage(r_addr); }
+
+        Ok(addr)
+    }
 }
 
 impl RtioTcpStream for UvTcpStream {
@@ -404,7 +454,7 @@ impl RtioTcpStream for UvTcpStream {
             let alloc: AllocCallback = |_| unsafe {
                 slice_to_uv_buf(*buf_ptr)
             };
-            let mut watcher = **self;
+            let mut watcher = self.as_stream();
             do watcher.read_start(alloc) |mut watcher, nread, _buf, status| {
 
                 // Stop reading so that no read callbacks are
@@ -440,7 +490,7 @@ impl RtioTcpStream for UvTcpStream {
         do scheduler.deschedule_running_task_and_then |_, task| {
             let task_cell = Cell::new(task);
             let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
-            let mut watcher = **self;
+            let mut watcher = self.as_stream();
             do watcher.write(buf) |_watcher, status| {
                 let result = if status.is_none() {
                     Ok(())
@@ -459,8 +509,35 @@ impl RtioTcpStream for UvTcpStream {
         return result_cell.take();
     }
 
+    fn peer_name(&mut self) -> Result<IpAddr, IoError> {
+        // Allocate a sockaddr_storage
+        // since we don't know if it's ipv4 or ipv6
+        let r_addr = unsafe { uvll::malloc_sockaddr_storage() };
+
+        let r = unsafe {
+            uvll::rust_uv_tcp_getpeername(self.native_handle(),
+                                          r_addr as *uvll::sockaddr_storage)
+        };
+
+        if r != 0 {
+            let status = status_to_maybe_uv_error(**self, r);
+            return Err(uv_error_to_io_error(status.unwrap()));
+        }
+
+        let addr = unsafe {
+            if uvll::is_ip6_addr(r_addr as *uvll::sockaddr) {
+                net::uv_ip_to_ip(UvIpv6(r_addr as *uvll::sockaddr_in6))
+            } else {
+                net::uv_ip_to_ip(UvIpv4(r_addr as *uvll::sockaddr_in))
+            }
+        };
+
+        unsafe { uvll::free_sockaddr_storage(r_addr); }
+
+        Ok(addr)
+    }
+
     // XXX implement
-    fn peer_name(&mut self) -> IpAddr { fail!(); }
     fn control_congestion(&mut self) { fail!(); }
     fn nodelay(&mut self) { fail!(); }
     fn keepalive(&mut self, _delay_in_seconds: uint) { fail!(); }
@@ -484,8 +561,33 @@ impl Drop for UvUdpSocket {
 }
 
 impl RtioSocket for UvUdpSocket {
-    // XXX implement
-    fn socket_name(&mut self) -> IpAddr { fail!(); }
+    fn socket_name(&mut self) -> Result<IpAddr, IoError> {
+        // Allocate a sockaddr_storage
+        // since we don't know if it's ipv4 or ipv6
+        let r_addr = unsafe { uvll::malloc_sockaddr_storage() };
+
+        let r = unsafe {
+            uvll::rust_uv_udp_getsockname(self.native_handle(),
+                                          r_addr as *uvll::sockaddr_storage)
+        };
+
+        if r != 0 {
+            let status = status_to_maybe_uv_error(**self, r);
+            return Err(uv_error_to_io_error(status.unwrap()));
+        }
+
+        let addr = unsafe {
+            if uvll::is_ip6_addr(r_addr as *uvll::sockaddr) {
+                net::uv_ip_to_ip(UvIpv6(r_addr as *uvll::sockaddr_in6))
+            } else {
+                net::uv_ip_to_ip(UvIpv4(r_addr as *uvll::sockaddr_in))
+            }
+        };
+
+        unsafe { uvll::free_sockaddr_storage(r_addr); }
+
+        Ok(addr)
+    }
 }
 
 impl RtioUdpSocket for UvUdpSocket {
diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs
index 1f27a577684..72d96e59c36 100644
--- a/src/libstd/rt/uv/uvll.rs
+++ b/src/libstd/rt/uv/uvll.rs
@@ -77,6 +77,7 @@ pub type uv_udp_recv_cb = *u8;
 pub type sockaddr = c_void;
 pub type sockaddr_in = c_void;
 pub type sockaddr_in6 = c_void;
+pub type sockaddr_storage = c_void;
 pub type uv_membership = c_void;
 
 #[deriving(Eq)]
@@ -233,14 +234,10 @@ pub unsafe fn get_udp_handle_from_send_req(send_req: *uv_udp_send_t) -> *uv_udp_
     return rust_uv_get_udp_handle_from_send_req(send_req);
 }
 
-pub unsafe fn udp_get_sockname(handle: *uv_udp_t, name: *sockaddr_in) -> c_int {
+pub unsafe fn udp_get_sockname(handle: *uv_udp_t, name: *sockaddr_storage) -> c_int {
     return rust_uv_udp_getsockname(handle, name);
 }
 
-pub unsafe fn udp_get_sockname6(handle: *uv_udp_t, name: *sockaddr_in6) -> c_int {
-    return rust_uv_udp_getsockname6(handle, name);
-}
-
 pub unsafe fn udp_set_membership(handle: *uv_udp_t, multicast_addr: *c_char,
                                  interface_addr: *c_char, membership: uv_membership) -> c_int {
     return rust_uv_udp_set_membership(handle, multicast_addr, interface_addr, membership);
@@ -280,22 +277,14 @@ pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in6) -> c
     return rust_uv_tcp_bind6(tcp_server_ptr, addr_ptr);
 }
 
-pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in) -> c_int {
+pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_storage) -> c_int {
     return rust_uv_tcp_getpeername(tcp_handle_ptr, name);
 }
 
-pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in6) ->c_int {
-    return rust_uv_tcp_getpeername6(tcp_handle_ptr, name);
-}
-
-pub unsafe fn tcp_getsockname(handle: *uv_tcp_t, name: *sockaddr_in) -> c_int {
+pub unsafe fn tcp_getsockname(handle: *uv_tcp_t, name: *sockaddr_storage) -> c_int {
     return rust_uv_tcp_getsockname(handle, name);
 }
 
-pub unsafe fn tcp_getsockname6(handle: *uv_tcp_t, name: *sockaddr_in6) -> c_int {
-    return rust_uv_tcp_getsockname6(handle, name);
-}
-
 pub unsafe fn tcp_nodelay(handle: *uv_tcp_t, enable: c_int) -> c_int {
     return rust_uv_tcp_nodelay(handle, enable);
 }
@@ -373,14 +362,6 @@ pub unsafe fn is_ip6_addr(addr: *sockaddr) -> bool {
     match rust_uv_is_ipv6_sockaddr(addr) { 0 => false, _ => true }
 }
 
-pub unsafe fn as_sockaddr_in(addr: *sockaddr) -> *sockaddr_in {
-    return rust_uv_sockaddr_as_sockaddr_in(addr);
-}
-
-pub unsafe fn as_sockaddr_in6(addr: *sockaddr) -> *sockaddr_in6 {
-    return rust_uv_sockaddr_as_sockaddr_in6(addr);
-}
-
 pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in {
     do ip.as_c_str |ip_buf| {
         rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int)
@@ -392,6 +373,14 @@ pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 {
     }
 }
 
+pub unsafe fn malloc_sockaddr_storage() -> *sockaddr_storage {
+    rust_uv_malloc_sockaddr_storage()
+}
+
+pub unsafe fn free_sockaddr_storage(ss: *sockaddr_storage) {
+    rust_uv_free_sockaddr_storage(ss);
+}
+
 pub unsafe fn free_ip4_addr(addr: *sockaddr_in) {
     rust_uv_free_ip4_addr(addr);
 }
@@ -520,10 +509,8 @@ extern {
     fn rust_uv_tcp_connect6(req: *uv_connect_t, handle: *uv_tcp_t, cb: *u8,
                             addr: *sockaddr_in6) -> c_int;
     fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, addr: *sockaddr_in6) -> c_int;
-    fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in) -> c_int;
-    fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in6) ->c_int;
-    fn rust_uv_tcp_getsockname(handle: *uv_tcp_t, name: *sockaddr_in) -> c_int;
-    fn rust_uv_tcp_getsockname6(handle: *uv_tcp_t, name: *sockaddr_in6) -> c_int;
+    fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_storage) -> c_int;
+    fn rust_uv_tcp_getsockname(handle: *uv_tcp_t, name: *sockaddr_storage) -> c_int;
     fn rust_uv_tcp_nodelay(handle: *uv_tcp_t, enable: c_int) -> c_int;
     fn rust_uv_tcp_keepalive(handle: *uv_tcp_t, enable: c_int, delay: c_uint) -> c_int;
     fn rust_uv_tcp_simultaneous_accepts(handle: *uv_tcp_t, enable: c_int) -> c_int;
@@ -538,8 +525,7 @@ extern {
     fn rust_uv_udp_recv_start(server: *uv_udp_t, on_alloc: *u8, on_recv: *u8) -> c_int;
     fn rust_uv_udp_recv_stop(server: *uv_udp_t) -> c_int;
     fn rust_uv_get_udp_handle_from_send_req(req: *uv_udp_send_t) -> *uv_udp_t;
-    fn rust_uv_udp_getsockname(handle: *uv_udp_t, name: *sockaddr_in) -> c_int;
-    fn rust_uv_udp_getsockname6(handle: *uv_udp_t, name: *sockaddr_in6) -> c_int;
+    fn rust_uv_udp_getsockname(handle: *uv_udp_t, name: *sockaddr_storage) -> c_int;
     fn rust_uv_udp_set_membership(handle: *uv_udp_t, multicast_addr: *c_char,
                                   interface_addr: *c_char, membership: uv_membership) -> c_int;
     fn rust_uv_udp_set_multicast_loop(handle: *uv_udp_t, on: c_int) -> c_int;
@@ -548,8 +534,8 @@ extern {
 
     fn rust_uv_is_ipv4_sockaddr(addr: *sockaddr) -> c_int;
     fn rust_uv_is_ipv6_sockaddr(addr: *sockaddr) -> c_int;
-    fn rust_uv_sockaddr_as_sockaddr_in(addr: *sockaddr) -> *sockaddr_in;
-    fn rust_uv_sockaddr_as_sockaddr_in6(addr: *sockaddr) -> *sockaddr_in6;
+    fn rust_uv_malloc_sockaddr_storage() -> *sockaddr_storage;
+    fn rust_uv_free_sockaddr_storage(ss: *sockaddr_storage);
 
     fn rust_uv_listen(stream: *c_void, backlog: c_int, cb: *u8) -> c_int;
     fn rust_uv_accept(server: *c_void, client: *c_void) -> c_int;
diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp
index 95e38a9903c..a7f5db9dc5f 100644
--- a/src/rt/rust_uv.cpp
+++ b/src/rt/rust_uv.cpp
@@ -282,29 +282,19 @@ rust_uv_tcp_bind6
 
 extern "C" int
 rust_uv_tcp_getpeername
-(uv_tcp_t* handle, sockaddr_in* name) {
+(uv_tcp_t* handle, sockaddr_storage* name) {
+    // sockaddr_storage is big enough to hold either
+    // sockaddr_in or sockaddr_in6
     int namelen = sizeof(sockaddr_in);
     return uv_tcp_getpeername(handle, (sockaddr*)name, &namelen);
 }
 
 extern "C" int
-rust_uv_tcp_getpeername6
-(uv_tcp_t* handle, sockaddr_in6* name) {
-    int namelen = sizeof(sockaddr_in6);
-    return uv_tcp_getpeername(handle, (sockaddr*)name, &namelen);
-}
-
-extern "C" int
 rust_uv_tcp_getsockname
-(uv_tcp_t* handle, sockaddr_in* name) {
-    int namelen = sizeof(sockaddr_in);
-    return uv_tcp_getsockname(handle, (sockaddr*)name, &namelen);
-}
-
-extern "C" int
-rust_uv_tcp_getsockname6
-(uv_tcp_t* handle, sockaddr_in6* name) {
-    int namelen = sizeof(sockaddr_in6);
+(uv_tcp_t* handle, sockaddr_storage* name) {
+    // sockaddr_storage is big enough to hold either
+    // sockaddr_in or sockaddr_in6
+    int namelen = sizeof(sockaddr_storage);
     return uv_tcp_getsockname(handle, (sockaddr*)name, &namelen);
 }
 
@@ -370,15 +360,10 @@ rust_uv_get_udp_handle_from_send_req(uv_udp_send_t* send_req) {
 
 extern "C" int
 rust_uv_udp_getsockname
-(uv_udp_t* handle, sockaddr_in* name) {
-    int namelen = sizeof(sockaddr_in);
-    return uv_udp_getsockname(handle, (sockaddr*)name, &namelen);
-}
-
-extern "C" int
-rust_uv_udp_getsockname6
-(uv_udp_t* handle, sockaddr_in6* name) {
-    int namelen = sizeof(sockaddr_in6);
+(uv_udp_t* handle, sockaddr_storage* name) {
+    // sockaddr_storage is big enough to hold either
+    // sockaddr_in or sockaddr_in6
+    int namelen = sizeof(sockaddr_storage);
     return uv_udp_getsockname(handle, (sockaddr*)name, &namelen);
 }
 
@@ -609,6 +594,17 @@ rust_uv_ip6_addrp(const char* ip, int port) {
   return addrp;
 }
 
+extern "C" struct sockaddr_storage *
+rust_uv_malloc_sockaddr_storage() {
+    struct sockaddr_storage *ss = (sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
+    return ss;
+}
+
+extern "C" void
+rust_uv_free_sockaddr_storage(struct sockaddr_storage *ss) {
+    free(ss);
+}
+
 extern "C" void
 rust_uv_free_ip4_addr(sockaddr_in *addrp) {
   free(addrp);
@@ -669,18 +665,6 @@ rust_uv_is_ipv6_sockaddr(sockaddr* addr) {
     return addr->sa_family == AF_INET6;
 }
 
-extern "C" sockaddr_in*
-rust_uv_sockaddr_as_sockaddr_in(sockaddr* addr) {
-//    return (sockaddr_in*)addr->sa_data;
-    return (sockaddr_in*)addr;
-}
-
-extern "C" sockaddr_in6*
-rust_uv_sockaddr_as_sockaddr_in6(sockaddr* addr) {
-    //return (sockaddr_in6*)addr->sa_data;
-    return (sockaddr_in6*)addr;
-}
-
 extern "C" bool
 rust_uv_is_ipv4_addrinfo(addrinfo* input) {
     return input->ai_family == AF_INET;
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index db9fe247952..804f448d261 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -106,7 +106,6 @@ rust_uv_tcp_bind
 rust_uv_tcp_connect6
 rust_uv_tcp_bind6
 rust_uv_tcp_getsockname
-rust_uv_tcp_getsockname6
 rust_uv_tcp_nodelay
 rust_uv_tcp_keepalive
 rust_uv_tcp_simultaneous_accepts
@@ -119,15 +118,14 @@ rust_uv_udp_recv_start
 rust_uv_udp_recv_stop
 rust_uv_get_udp_handle_from_send_req
 rust_uv_udp_getsockname
-rust_uv_udp_getsockname6
 rust_uv_udp_set_membership
 rust_uv_udp_set_multicast_loop
 rust_uv_udp_set_multicast_ttl
 rust_uv_udp_set_broadcast
 rust_uv_is_ipv4_sockaddr
 rust_uv_is_ipv6_sockaddr
-rust_uv_sockaddr_as_sockaddr_in
-rust_uv_sockaddr_as_sockaddr_in6
+rust_uv_malloc_sockaddr_storage
+rust_uv_free_sockaddr_storage
 rust_uv_listen
 rust_uv_accept
 rust_uv_write
@@ -204,7 +202,6 @@ rust_update_gc_metadata
 rust_uv_ip4_port
 rust_uv_ip6_port
 rust_uv_tcp_getpeername
-rust_uv_tcp_getpeername6
 linenoise
 linenoiseSetCompletionCallback
 linenoiseAddCompletion
@@ -267,4 +264,4 @@ rust_drop_global_args_lock
 rust_set_exit_status_newrt
 rust_get_exit_status_newrt
 rust_take_change_dir_lock
-rust_drop_change_dir_lock
\ No newline at end of file
+rust_drop_change_dir_lock