summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
authorCarl Lerche <me@carllerche.com>2015-02-22 12:57:01 -0800
committerCarl Lerche <me@carllerche.com>2015-02-22 12:57:01 -0800
commiteb278aa4d74be7644c05e4b44af803e1ce2f2133 (patch)
treec38ac16569fcfd1d4c4c111a0e50265da03c23f5 /src/sys
parent6af51aa23225504022acdbcecc9f2e5d559522c4 (diff)
downloadnix-eb278aa4d74be7644c05e4b44af803e1ce2f2133.zip
Implement round trip SockAddr conversions
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/socket.rs101
1 files changed, 81 insertions, 20 deletions
diff --git a/src/sys/socket.rs b/src/sys/socket.rs
index ff2d7ee7..6450ff2c 100644
--- a/src/sys/socket.rs
+++ b/src/sys/socket.rs
@@ -5,7 +5,7 @@ use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{c_void, c_int, socklen_t, size_t, ssize_t};
use std::{fmt, mem, net, ptr, path};
-use std::ffi::AsOsStr;
+use std::ffi::{AsOsStr, CStr, OsStr};
use std::os::unix::prelude::*;
/*
@@ -63,14 +63,30 @@ pub enum SockAddr {
SockUnix(sockaddr_un)
}
-/// Convert a value into a socket address
-pub trait AsSockAddr {
- fn as_sock_addr(&self) -> NixResult<SockAddr>;
+/// A trait for values which can be converted or resolved to a SockAddr.
+pub trait ToSockAddr {
+ /// Converts the value to a SockAddr
+ fn to_sock_addr(&self) -> NixResult<SockAddr>;
+
+ /// Converts and yields the value as a SockAddr
+ fn with_sock_addr<T, F: FnOnce(&SockAddr) -> T>(&self, action: F) -> NixResult<T> {
+ Ok(action(&try!(self.to_sock_addr())))
+ }
+}
+
+impl ToSockAddr for SockAddr {
+ fn to_sock_addr(&self) -> NixResult<SockAddr> {
+ Ok(*self)
+ }
+
+ fn with_sock_addr<T, F: FnOnce(&SockAddr) -> T>(&self, action: F) -> NixResult<T> {
+ Ok(action(self))
+ }
}
/// Convert a path into a unix domain socket address
-impl AsSockAddr for path::Path {
- fn as_sock_addr(&self) -> NixResult<SockAddr> {
+impl ToSockAddr for path::Path {
+ fn to_sock_addr(&self) -> NixResult<SockAddr> {
let bytes = self.as_os_str().as_bytes();
Ok(SockAddr::SockUnix(unsafe {
@@ -96,8 +112,8 @@ impl AsSockAddr for path::Path {
}
/// Convert an inet address into a socket address
-impl AsSockAddr for net::SocketAddr {
- fn as_sock_addr(&self) -> NixResult<SockAddr> {
+impl ToSockAddr for net::SocketAddr {
+ fn to_sock_addr(&self) -> NixResult<SockAddr> {
use std::net::IpAddr;
use std::num::Int;
@@ -122,6 +138,47 @@ impl AsSockAddr for net::SocketAddr {
}
}
+/// Convert from a socket address
+pub trait FromSockAddr {
+ fn from_sock_addr(addr: &SockAddr) -> Option<Self>;
+}
+
+impl FromSockAddr for net::SocketAddr {
+ fn from_sock_addr(addr: &SockAddr) -> Option<net::SocketAddr> {
+ use std::net::{IpAddr, Ipv4Addr};
+ use std::num::Int;
+
+ match *addr {
+ SockAddr::SockIpV4(ref addr) => {
+ let ip = Int::from_be(addr.sin_addr.s_addr);
+ let ip = Ipv4Addr::new(
+ ((ip >> 24) as u8) & 0xff,
+ ((ip >> 16) as u8) & 0xff,
+ ((ip >> 8) as u8) & 0xff,
+ ((ip >> 0) as u8) & 0xff);
+
+ Some(net::SocketAddr::new(IpAddr::V4(ip), addr.sin_port))
+ }
+ SockAddr::SockIpV6(_) => unimplemented!(),
+ _ => None,
+ }
+ }
+}
+
+impl FromSockAddr for path::PathBuf {
+ fn from_sock_addr(addr: &SockAddr) -> Option<path::PathBuf> {
+ if let SockAddr::SockUnix(ref addr) = *addr {
+ unsafe {
+ let bytes = CStr::from_ptr(addr.sun_path.as_ptr()).to_bytes();
+ let osstr = <OsStr as OsStrExt>::from_bytes(bytes);
+ return Some(path::PathBuf::new(osstr));
+ }
+ }
+
+ None
+ }
+}
+
/*
*
* ===== Consts =====
@@ -347,15 +404,17 @@ pub fn listen(sockfd: Fd, backlog: usize) -> NixResult<()> {
from_ffi(res)
}
-pub fn bind(sockfd: Fd, addr: &SockAddr) -> NixResult<()> {
+pub fn bind<A: ToSockAddr>(sockfd: Fd, addr: &A) -> NixResult<()> {
use self::SockAddr::*;
let res = unsafe {
- match *addr {
- SockIpV4(ref addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in>() as socklen_t),
- SockIpV6(ref addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in6>() as socklen_t),
- SockUnix(ref addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_un>() as socklen_t)
- }
+ try!(addr.with_sock_addr(|addr| {
+ match *addr {
+ SockIpV4(ref addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in>() as socklen_t),
+ SockIpV6(ref addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in6>() as socklen_t),
+ SockUnix(ref addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_un>() as socklen_t)
+ }
+ }))
};
from_ffi(res)
@@ -422,15 +481,17 @@ fn accept4_polyfill(sockfd: Fd, flags: SockFlag) -> NixResult<Fd> {
Ok(res)
}
-pub fn connect(sockfd: Fd, addr: &SockAddr) -> NixResult<()> {
+pub fn connect<A: ToSockAddr>(sockfd: Fd, addr: &A) -> NixResult<()> {
use self::SockAddr::*;
let res = unsafe {
- match *addr {
- SockIpV4(ref addr) => ffi::connect(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in>() as socklen_t),
- SockIpV6(ref addr) => ffi::connect(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in6>() as socklen_t),
- SockUnix(ref addr) => ffi::connect(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_un>() as socklen_t)
- }
+ try!(addr.with_sock_addr(|addr| {
+ match *addr {
+ SockIpV4(ref addr) => ffi::connect(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in>() as socklen_t),
+ SockIpV6(ref addr) => ffi::connect(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in6>() as socklen_t),
+ SockUnix(ref addr) => ffi::connect(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_un>() as socklen_t)
+ }
+ }))
};
from_ffi(res)