diff options
author | Carl Lerche <me@carllerche.com> | 2014-08-17 03:07:38 -0700 |
---|---|---|
committer | Carl Lerche <me@carllerche.com> | 2014-08-17 03:07:38 -0700 |
commit | f85e9bfbe5bfef4d8ce5985d29d9a173aa4d5fb0 (patch) | |
tree | 69abaf785d30e7aa8335fb7af4f7074a01629bb4 | |
parent | 86b960d04ce31abd70d4922e364a7e8be1a6d6c5 (diff) | |
download | nix-f85e9bfbe5bfef4d8ce5985d29d9a173aa4d5fb0.zip |
More socket APIs
-rw-r--r-- | src/fcntl.rs | 7 | ||||
-rw-r--r-- | src/features.rs | 1 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/sys/mod.rs | 1 | ||||
-rw-r--r-- | src/sys/socket.rs | 107 | ||||
-rw-r--r-- | src/unistd.rs | 34 |
6 files changed, 141 insertions, 10 deletions
diff --git a/src/fcntl.rs b/src/fcntl.rs index f4f0fded..486b95fe 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -34,7 +34,7 @@ bitflags!( ) mod ffi { - pub use libc::{open, close}; + pub use libc::open; } pub fn open(path: &Path, oflag: OFlag, mode: FilePermission) -> SysResult<Fd> { @@ -46,8 +46,3 @@ pub fn open(path: &Path, oflag: OFlag, mode: FilePermission) -> SysResult<Fd> { Ok(fd) } - -pub fn close(fd: Fd) -> SysResult<()> { - let res = unsafe { ffi::close(fd) }; - from_ffi(res) -} diff --git a/src/features.rs b/src/features.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/features.rs @@ -0,0 +1 @@ + @@ -6,6 +6,7 @@ extern crate libc; pub use errno::{SysResult, SysError}; pub mod errno; +pub mod features; pub mod fcntl; pub mod mount; pub mod sched; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 9d19e35d..5023cce8 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -1,3 +1,4 @@ pub mod epoll; +pub mod socket; pub mod stat; pub mod utsname; diff --git a/src/sys/socket.rs b/src/sys/socket.rs new file mode 100644 index 00000000..66ee48e2 --- /dev/null +++ b/src/sys/socket.rs @@ -0,0 +1,107 @@ +#![cfg(target_os = "linux")] + +use std::{mem, ptr}; +use libc::{c_int, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, socklen_t}; +use fcntl::Fd; +use errno::{SysResult, SysError, from_ffi}; + +mod ffi { + use libc::{c_int, sockaddr, socklen_t}; + + extern { + pub fn socket(domain: c_int, ty: c_int, proto: c_int) -> c_int; + + pub fn listen(sockfd: c_int, backlog: c_int) -> c_int; + + pub fn bind(sockfd: c_int, addr: *const sockaddr, addrlen: socklen_t) -> c_int; + + pub fn accept( + sockfd: c_int, + addr: *const sockaddr, + addrlen: *mut socklen_t) -> c_int; + + pub fn accept4( + sockfd: c_int, + addr: *const sockaddr, + addrlen: *mut socklen_t, + flags: c_int) -> c_int; + } +} + +pub type AddressFamily = c_int; + +pub static AF_UNIX: AddressFamily = 1; +pub static AF_LOCAL: AddressFamily = AF_UNIX; +pub static AF_INET: AddressFamily = 2; +pub static AF_INET6: AddressFamily = 10; + +pub type SockType = c_int; + +pub static SOCK_STREAM: SockType = 1; +pub static SOCK_DGRAM: SockType = 1; +pub static SOCK_SEQPACKET: SockType = 1; +pub static SOCK_RAW: SockType = 1; +pub static SOCK_RDM: SockType = 1; + +// Extra flags - Linux 2.6.27 +bitflags!( + flags SockFlag: c_int { + static SOCK_NONBLOCK = 0o0004000, + static SOCK_CLOEXEC = 0o2000000 + } +) + +pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag) -> SysResult<Fd> { + // TODO: Check the kernel version + let res = unsafe { ffi::socket(domain, ty | flags.bits(), 0) }; + + if res < 0 { + return Err(SysError::last()); + } + + Ok(res) +} + +pub fn listen(sockfd: Fd, backlog: uint) -> SysResult<()> { + let res = unsafe { ffi::listen(sockfd, backlog as c_int) }; + from_ffi(res) +} + +pub enum BindAddr<'a> { + BindIpV4(&'a sockaddr_in), + BindIpV6(&'a sockaddr_in6), + BindUnix(&'a sockaddr_un) +} + +pub fn bind(sockfd: Fd, addr: BindAddr) -> SysResult<()> { + let res = unsafe { + match addr { + BindIpV4(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in>() as socklen_t), + BindIpV6(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in6>() as socklen_t), + BindUnix(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_un>() as socklen_t) + } + }; + + from_ffi(res) +} + +pub fn accept(sockfd: Fd) -> SysResult<Fd> { + let res = unsafe { ffi::accept(sockfd, ptr::null(), ptr::mut_null()) }; + + if res < 0 { + return Err(SysError::last()); + } + + Ok(res) +} + +pub fn accept4(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> { + // TODO: Check the kernel version + let res = unsafe { ffi::accept4(sockfd, ptr::null(), ptr::mut_null(), flags.bits) }; + + if res < 0 { + return Err(SysError::last()); + } + + Ok(res) +} diff --git a/src/unistd.rs b/src/unistd.rs index f4c4daa1..4b141f17 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -3,19 +3,20 @@ use std::ptr; use std::c_str::{CString, ToCStr}; use std::path::Path; -use libc::{c_char}; +use libc::{c_char, c_void, size_t}; use fcntl::{Fd, OFlag}; use syscall::{syscall, SysPivotRoot}; -use {SysResult, SysError}; +use errno::{SysResult, SysError, from_ffi}; mod ffi { use libc::{c_char, c_int}; + pub use libc::{close, read, write}; extern { + // duplicate a file descriptor + // doc: http://man7.org/linux/man-pages/man2/dup.2.html pub fn dup(oldfd: c_int) -> c_int; - pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int; - pub fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int; // change working directory @@ -107,3 +108,28 @@ pub fn pivot_root(new_root: &Path, put_old: &Path) -> SysResult<()> { Ok(()) } + +pub fn close(fd: Fd) -> SysResult<()> { + let res = unsafe { ffi::close(fd) }; + from_ffi(res) +} + +pub fn read(fd: Fd, buf: &mut [u8]) -> SysResult<uint> { + let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) }; + + if res < 0 { + return Err(SysError::last()); + } + + return Ok(res as uint) +} + +pub fn write(fd: Fd, buf: &[u8]) -> SysResult<uint> { + let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) }; + + if res < 0 { + return Err(SysError::last()); + } + + return Ok(res as uint) +} |