Skip to content

Commit eb73213

Browse files
pvachonwycats
authored andcommitted
Add recvfrom(2) and sendto(2) wrappers
Add FFI function call wrappers for recvfrom(2) and sendto(2) to enable the use of connectionless sockets.
1 parent 5cb7c59 commit eb73213

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-4
lines changed

src/sys/socket.rs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use std::{mem, ptr};
2-
use libc::{c_int, socklen_t};
2+
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_in, sockaddr_in6, sockaddr_un, sa_family_t, ip_mreq};
7+
pub use libc::{in_addr, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, sa_family_t, ip_mreq};
88

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

1111
mod ffi {
1212
use libc::{c_int, c_void, socklen_t};
13-
pub use libc::{socket, listen, bind, accept, connect, setsockopt};
13+
pub use libc::{socket, listen, bind, accept, connect, setsockopt, sendto, recvfrom};
1414

1515
extern {
1616
pub fn getsockopt(
@@ -303,6 +303,67 @@ pub fn connect(sockfd: Fd, addr: &SockAddr) -> SysResult<()> {
303303
from_ffi(res)
304304
}
305305

306+
mod sa_helpers {
307+
use std::mem;
308+
use libc::{sockaddr_storage, sockaddr_in, sockaddr_in6, sockaddr_un};
309+
use super::{SockAddr, SockIpV6, SockIpV4, SockUnix};
310+
311+
pub fn to_sockaddr_ipv4(addr: &sockaddr_storage) -> SockAddr {
312+
let sin : &sockaddr_in = unsafe { mem::transmute(addr) };
313+
SockIpV4( *sin )
314+
}
315+
316+
pub fn to_sockaddr_ipv6(addr: &sockaddr_storage) -> SockAddr {
317+
let sin6 : &sockaddr_in6 = unsafe { mem::transmute(addr) };
318+
SockIpV6( *sin6 )
319+
}
320+
321+
pub fn to_sockaddr_unix(addr: &sockaddr_storage) -> SockAddr {
322+
let sun : &sockaddr_un = unsafe { mem::transmute(addr) };
323+
SockUnix( *sun )
324+
}
325+
}
326+
327+
pub fn recvfrom(sockfd: Fd, buf: &mut [u8], addr: &mut SockAddr) -> SysResult<uint> {
328+
use libc::sockaddr_storage;
329+
330+
let mut saddr : sockaddr_storage = unsafe { mem::zeroed() };
331+
let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
332+
333+
let ret = unsafe {
334+
ffi::recvfrom(sockfd, buf.as_ptr() as *mut c_void, buf.len() as size_t, 0, mem::transmute(&saddr), &mut len as *mut socklen_t)
335+
};
336+
337+
if ret < 0 {
338+
return Err(SysError::last());
339+
}
340+
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+
}
347+
348+
Ok(ret as uint)
349+
}
350+
351+
pub fn sendto(sockfd: Fd, buf: &[u8], addr: &SockAddr) -> SysResult<()> {
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;
357+
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) };
359+
360+
if ret < 0 {
361+
return Err(SysError::last());
362+
}
363+
364+
Ok(())
365+
}
366+
306367
#[repr(C)]
307368
pub struct linger {
308369
pub l_onoff: c_int,

src/unistd.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,6 @@ pub fn readv(fd: Fd, iov: &mut [Iovec<ToRead>]) -> SysResult<uint> {
301301
return Ok(res as uint)
302302
}
303303

304-
305304
pub fn pipe() -> SysResult<(Fd, Fd)> {
306305
unsafe {
307306
let mut res;

0 commit comments

Comments
 (0)