Skip to content

Commit eb1ed1a

Browse files
pvachonwycats
authored andcommitted
Polish up sendto/recvfrom wrappers
Make the sendto/recvfrom wrappers a little more friendly to work with.
1 parent 8173e1f commit eb1ed1a

File tree

1 file changed

+50
-19
lines changed

1 file changed

+50
-19
lines changed

src/sys/socket.rs

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use std::{mem, ptr};
1+
use std::{mem, ptr, fmt};
22
use libc::{c_void, c_int, socklen_t, size_t};
33
use fcntl::{Fd, fcntl, F_SETFL, F_SETFD, FD_CLOEXEC, O_NONBLOCK};
44
use errno::{SysResult, SysError, from_ffi};
55
use features;
66

7-
pub use libc::{in_addr, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, sa_family_t, ip_mreq};
7+
pub use libc::{in_addr, sockaddr, sockaddr_storage, sockaddr_in, sockaddr_in6, sockaddr_un, sa_family_t, ip_mreq};
88

99
pub use self::consts::*;
1010

@@ -120,6 +120,12 @@ mod consts {
120120
pub const INADDR_ANY: InAddrT = 0;
121121
pub const INADDR_NONE: InAddrT = 0xffffffff;
122122
pub const INADDR_BROADCAST: InAddrT = 0xffffffff;
123+
124+
pub type SockMessageFlags = i32;
125+
// Flags for send/recv and their relatives
126+
pub const MSG_OOB: SockMessageFlags = 0x1;
127+
pub const MSG_PEEK: SockMessageFlags = 0x2;
128+
pub const MSG_DONTWAIT: SockMessageFlags = 0x40;
123129
}
124130

125131
#[cfg(any(target_os = "macos", target_os = "ios"))]
@@ -324,9 +330,7 @@ mod sa_helpers {
324330
}
325331
}
326332

327-
pub fn recvfrom(sockfd: Fd, buf: &mut [u8], addr: &mut SockAddr) -> SysResult<uint> {
328-
use libc::sockaddr_storage;
329-
333+
pub fn recvfrom(sockfd: Fd, buf: &mut [u8]) -> SysResult<(uint, SockAddr)> {
330334
let mut saddr : sockaddr_storage = unsafe { mem::zeroed() };
331335
let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
332336

@@ -338,24 +342,51 @@ pub fn recvfrom(sockfd: Fd, buf: &mut [u8], addr: &mut SockAddr) -> SysResult<ui
338342
return Err(SysError::last());
339343
}
340344

341-
match saddr.ss_family as i32 {
342-
AF_INET => { *addr = sa_helpers::to_sockaddr_ipv4(&saddr); },
343-
AF_INET6 => { *addr = sa_helpers::to_sockaddr_ipv6(&saddr); },
344-
AF_UNIX => { *addr = sa_helpers::to_sockaddr_unix(&saddr); },
345-
_ => unimplemented!()
346-
}
345+
Ok((ret as uint,
346+
match saddr.ss_family as i32 {
347+
AF_INET => { sa_helpers::to_sockaddr_ipv4(&saddr) },
348+
AF_INET6 => { sa_helpers::to_sockaddr_ipv6(&saddr) },
349+
AF_UNIX => { sa_helpers::to_sockaddr_unix(&saddr) },
350+
_ => unimplemented!()
351+
}
352+
))
353+
}
354+
355+
fn print_ipv4_addr(sin: &sockaddr_in, f: &mut fmt::Formatter) -> fmt::Result {
356+
let ip_addr = Int::from_be(sin.sin_addr.s_addr);
357+
let port = Int::from_be(sin.sin_port);
358+
359+
write!(f, "{}.{}.{}.{}:{}",
360+
(ip_addr >> 24) & 0xff,
361+
(ip_addr >> 16) & 0xff,
362+
(ip_addr >> 8) & 0xff,
363+
(ip_addr) & 0xff,
364+
port)
365+
}
347366

348-
Ok(ret as uint)
367+
impl fmt::Show for SockAddr {
368+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
369+
match *self {
370+
SockIpV4(sin) => print_ipv4_addr(&sin, f),
371+
_ => unimplemented!()
372+
}
373+
}
349374
}
350375

351-
pub fn sendto(sockfd: Fd, buf: &[u8], addr: &SockAddr) -> SysResult<uint> {
352-
let len = match *addr {
353-
SockIpV4(_) => mem::size_of::<sockaddr_in>(),
354-
SockIpV6(_) => mem::size_of::<sockaddr_in6>(),
355-
SockUnix(_) => mem::size_of::<sockaddr_un>(),
356-
} as socklen_t;
376+
///
377+
/// Generic wrapper around sendto
378+
fn sendto_sockaddr<T>(sockfd: Fd, buf: &[u8], flags: SockMessageFlags, addr: &T) -> i64 {
379+
unsafe {
380+
ffi::sendto(sockfd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags, mem::transmute(addr), mem::size_of::<T>() as socklen_t)
381+
}
382+
}
357383

358-
let ret = unsafe { ffi::sendto(sockfd, buf.as_ptr() as *const c_void, buf.len() as size_t, 0, mem::transmute(addr), len as socklen_t) };
384+
pub fn sendto(sockfd: Fd, buf: &[u8], addr: &SockAddr, flags: SockMessageFlags) -> SysResult<uint> {
385+
let ret = match *addr {
386+
SockIpV4(ref addr) => sendto_sockaddr(sockfd, buf, flags, addr),
387+
SockIpV6(ref addr) => sendto_sockaddr(sockfd, buf, flags, addr),
388+
SockUnix(ref addr) => sendto_sockaddr(sockfd, buf, flags, addr),
389+
};
359390

360391
if ret < 0 {
361392
Err(SysError::last())

0 commit comments

Comments
 (0)