diff --git a/src/nameinfo.rs b/src/nameinfo.rs index cac4bdf0..8516222c 100644 --- a/src/nameinfo.rs +++ b/src/nameinfo.rs @@ -24,81 +24,133 @@ use err::LookupError; /// Retrieving names or services that contain non-UTF8 locales is currently not /// supported (as String is returned). Raise an issue if this is a concern for /// you. +#[cfg(target_env = "uclibc")] +pub fn getnameinfo(sock: &SocketAddr, flags: u32) -> Result<(String, String), LookupError> { + // Convert the socket into our type, so we can get a sockaddr_in{,6} ptr. + let sock: SockAddr = (*sock).into(); + let c_sock = sock.as_ptr(); + let c_sock_len = sock.len(); + + // Hard code maximums, as they aren't defined in libc/winapi. + + // Allocate buffers for name and service strings. + let mut c_host = [0 as c_char; 1024 as usize]; + // No NI_MAXSERV, so use suggested value. + let mut c_service = [0 as c_char; 32 as usize]; + + // Prime windows. + #[cfg(windows)] + ::win::init_winsock(); + + unsafe { + LookupError::match_gai_error(c_getnameinfo( + c_sock, + c_sock_len, + c_host.as_mut_ptr(), + c_host.len() as _, + c_service.as_mut_ptr(), + c_service.len() as _, + flags, + ))?; + } + + let host = unsafe { CStr::from_ptr(c_host.as_ptr()) }; + let service = unsafe { CStr::from_ptr(c_service.as_ptr()) }; + + let host = match str::from_utf8(host.to_bytes()) { + Ok(name) => Ok(name.to_owned()), + Err(_) => Err(io::Error::new( + io::ErrorKind::Other, + "Host UTF8 parsing failed", + )), + }?; + + let service = match str::from_utf8(service.to_bytes()) { + Ok(service) => Ok(service.to_owned()), + Err(_) => Err(io::Error::new( + io::ErrorKind::Other, + "Service UTF8 parsing failed", + )), + }?; + + Ok((host, service)) +} + +#[cfg(not(target_env = "uclibc"))] pub fn getnameinfo(sock: &SocketAddr, flags: i32) -> Result<(String, String), LookupError> { - // Convert the socket into our type, so we can get a sockaddr_in{,6} ptr. - let sock: SockAddr = (*sock).into(); - let c_sock = sock.as_ptr(); - let c_sock_len = sock.len(); - - // Hard code maximums, as they aren't defined in libc/winapi. - - // Allocate buffers for name and service strings. - let mut c_host = [0 as c_char; 1024 as usize]; - // No NI_MAXSERV, so use suggested value. - let mut c_service = [0 as c_char; 32 as usize]; - - // Prime windows. - #[cfg(windows)] - ::win::init_winsock(); - - unsafe { - LookupError::match_gai_error( - c_getnameinfo( - c_sock, c_sock_len, - c_host.as_mut_ptr(), - c_host.len() as _, - c_service.as_mut_ptr(), - c_service.len() as _, - flags - ) - )?; - } - - let host = unsafe { - CStr::from_ptr(c_host.as_ptr()) - }; - let service = unsafe { - CStr::from_ptr(c_service.as_ptr()) - }; - - let host = match str::from_utf8(host.to_bytes()) { - Ok(name) => Ok(name.to_owned()), - Err(_) => Err(io::Error::new(io::ErrorKind::Other, - "Host UTF8 parsing failed")) - }?; - - let service = match str::from_utf8(service.to_bytes()) { - Ok(service) => Ok(service.to_owned()), - Err(_) => Err(io::Error::new(io::ErrorKind::Other, - "Service UTF8 parsing failed")) - }?; - - Ok((host, service)) + // Convert the socket into our type, so we can get a sockaddr_in{,6} ptr. + let sock: SockAddr = (*sock).into(); + let c_sock = sock.as_ptr(); + let c_sock_len = sock.len(); + + // Hard code maximums, as they aren't defined in libc/winapi. + + // Allocate buffers for name and service strings. + let mut c_host = [0 as c_char; 1024 as usize]; + // No NI_MAXSERV, so use suggested value. + let mut c_service = [0 as c_char; 32 as usize]; + + // Prime windows. + #[cfg(windows)] + ::win::init_winsock(); + + unsafe { + LookupError::match_gai_error(c_getnameinfo( + c_sock, + c_sock_len, + c_host.as_mut_ptr(), + c_host.len() as _, + c_service.as_mut_ptr(), + c_service.len() as _, + flags, + ))?; + } + + let host = unsafe { CStr::from_ptr(c_host.as_ptr()) }; + let service = unsafe { CStr::from_ptr(c_service.as_ptr()) }; + + let host = match str::from_utf8(host.to_bytes()) { + Ok(name) => Ok(name.to_owned()), + Err(_) => Err(io::Error::new( + io::ErrorKind::Other, + "Host UTF8 parsing failed", + )), + }?; + + let service = match str::from_utf8(service.to_bytes()) { + Ok(service) => Ok(service.to_owned()), + Err(_) => Err(io::Error::new( + io::ErrorKind::Other, + "Service UTF8 parsing failed", + )), + }?; + + Ok((host, service)) } #[test] fn test_getnameinfo() { - use std::net::{IpAddr, SocketAddr}; + use std::net::{IpAddr, SocketAddr}; - let ip: IpAddr = "127.0.0.1".parse().unwrap(); - let port = 22; - let socket: SocketAddr = (ip, port).into(); + let ip: IpAddr = "127.0.0.1".parse().unwrap(); + let port = 22; + let socket: SocketAddr = (ip, port).into(); - let (name, service) = match getnameinfo(&socket, 0) { - Ok((n, s)) => (n, s), - Err(e) => panic!("Failed to lookup socket {:?}", e), - }; + let (name, service) = match getnameinfo(&socket, 0) { + Ok((n, s)) => (n, s), + Err(e) => panic!("Failed to lookup socket {:?}", e), + }; - assert_eq!(service, "ssh"); + assert_eq!(service, "ssh"); - #[cfg(unix)] - { - assert_eq!(name, "localhost"); - } + #[cfg(unix)] + { + assert_eq!(name, "localhost"); + } - #[cfg(windows)] - { - let hostname = ::hostname::get_hostname().unwrap(); - assert_eq!(name, hostname); - } + #[cfg(windows)] + { + let hostname = ::hostname::get_hostname().unwrap(); + assert_eq!(name, hostname); + } }