Skip to content

Commit f85e9bf

Browse files
committed
More socket APIs
1 parent 86b960d commit f85e9bf

File tree

6 files changed

+141
-10
lines changed

6 files changed

+141
-10
lines changed

src/fcntl.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ bitflags!(
3434
)
3535

3636
mod ffi {
37-
pub use libc::{open, close};
37+
pub use libc::open;
3838
}
3939

4040
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> {
4646

4747
Ok(fd)
4848
}
49-
50-
pub fn close(fd: Fd) -> SysResult<()> {
51-
let res = unsafe { ffi::close(fd) };
52-
from_ffi(res)
53-
}

src/features.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extern crate libc;
66
pub use errno::{SysResult, SysError};
77

88
pub mod errno;
9+
pub mod features;
910
pub mod fcntl;
1011
pub mod mount;
1112
pub mod sched;

src/sys/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod epoll;
2+
pub mod socket;
23
pub mod stat;
34
pub mod utsname;

src/sys/socket.rs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#![cfg(target_os = "linux")]
2+
3+
use std::{mem, ptr};
4+
use libc::{c_int, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, socklen_t};
5+
use fcntl::Fd;
6+
use errno::{SysResult, SysError, from_ffi};
7+
8+
mod ffi {
9+
use libc::{c_int, sockaddr, socklen_t};
10+
11+
extern {
12+
pub fn socket(domain: c_int, ty: c_int, proto: c_int) -> c_int;
13+
14+
pub fn listen(sockfd: c_int, backlog: c_int) -> c_int;
15+
16+
pub fn bind(sockfd: c_int, addr: *const sockaddr, addrlen: socklen_t) -> c_int;
17+
18+
pub fn accept(
19+
sockfd: c_int,
20+
addr: *const sockaddr,
21+
addrlen: *mut socklen_t) -> c_int;
22+
23+
pub fn accept4(
24+
sockfd: c_int,
25+
addr: *const sockaddr,
26+
addrlen: *mut socklen_t,
27+
flags: c_int) -> c_int;
28+
}
29+
}
30+
31+
pub type AddressFamily = c_int;
32+
33+
pub static AF_UNIX: AddressFamily = 1;
34+
pub static AF_LOCAL: AddressFamily = AF_UNIX;
35+
pub static AF_INET: AddressFamily = 2;
36+
pub static AF_INET6: AddressFamily = 10;
37+
38+
pub type SockType = c_int;
39+
40+
pub static SOCK_STREAM: SockType = 1;
41+
pub static SOCK_DGRAM: SockType = 1;
42+
pub static SOCK_SEQPACKET: SockType = 1;
43+
pub static SOCK_RAW: SockType = 1;
44+
pub static SOCK_RDM: SockType = 1;
45+
46+
// Extra flags - Linux 2.6.27
47+
bitflags!(
48+
flags SockFlag: c_int {
49+
static SOCK_NONBLOCK = 0o0004000,
50+
static SOCK_CLOEXEC = 0o2000000
51+
}
52+
)
53+
54+
pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag) -> SysResult<Fd> {
55+
// TODO: Check the kernel version
56+
let res = unsafe { ffi::socket(domain, ty | flags.bits(), 0) };
57+
58+
if res < 0 {
59+
return Err(SysError::last());
60+
}
61+
62+
Ok(res)
63+
}
64+
65+
pub fn listen(sockfd: Fd, backlog: uint) -> SysResult<()> {
66+
let res = unsafe { ffi::listen(sockfd, backlog as c_int) };
67+
from_ffi(res)
68+
}
69+
70+
pub enum BindAddr<'a> {
71+
BindIpV4(&'a sockaddr_in),
72+
BindIpV6(&'a sockaddr_in6),
73+
BindUnix(&'a sockaddr_un)
74+
}
75+
76+
pub fn bind(sockfd: Fd, addr: BindAddr) -> SysResult<()> {
77+
let res = unsafe {
78+
match addr {
79+
BindIpV4(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in>() as socklen_t),
80+
BindIpV6(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_in6>() as socklen_t),
81+
BindUnix(addr) => ffi::bind(sockfd, mem::transmute(addr), mem::size_of::<sockaddr_un>() as socklen_t)
82+
}
83+
};
84+
85+
from_ffi(res)
86+
}
87+
88+
pub fn accept(sockfd: Fd) -> SysResult<Fd> {
89+
let res = unsafe { ffi::accept(sockfd, ptr::null(), ptr::mut_null()) };
90+
91+
if res < 0 {
92+
return Err(SysError::last());
93+
}
94+
95+
Ok(res)
96+
}
97+
98+
pub fn accept4(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> {
99+
// TODO: Check the kernel version
100+
let res = unsafe { ffi::accept4(sockfd, ptr::null(), ptr::mut_null(), flags.bits) };
101+
102+
if res < 0 {
103+
return Err(SysError::last());
104+
}
105+
106+
Ok(res)
107+
}

src/unistd.rs

+30-4
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@
33
use std::ptr;
44
use std::c_str::{CString, ToCStr};
55
use std::path::Path;
6-
use libc::{c_char};
6+
use libc::{c_char, c_void, size_t};
77
use fcntl::{Fd, OFlag};
88
use syscall::{syscall, SysPivotRoot};
9-
use {SysResult, SysError};
9+
use errno::{SysResult, SysError, from_ffi};
1010

1111
mod ffi {
1212
use libc::{c_char, c_int};
13+
pub use libc::{close, read, write};
1314

1415
extern {
16+
// duplicate a file descriptor
17+
// doc: http://man7.org/linux/man-pages/man2/dup.2.html
1518
pub fn dup(oldfd: c_int) -> c_int;
16-
1719
pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;
18-
1920
pub fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int;
2021

2122
// change working directory
@@ -107,3 +108,28 @@ pub fn pivot_root(new_root: &Path, put_old: &Path) -> SysResult<()> {
107108

108109
Ok(())
109110
}
111+
112+
pub fn close(fd: Fd) -> SysResult<()> {
113+
let res = unsafe { ffi::close(fd) };
114+
from_ffi(res)
115+
}
116+
117+
pub fn read(fd: Fd, buf: &mut [u8]) -> SysResult<uint> {
118+
let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };
119+
120+
if res < 0 {
121+
return Err(SysError::last());
122+
}
123+
124+
return Ok(res as uint)
125+
}
126+
127+
pub fn write(fd: Fd, buf: &[u8]) -> SysResult<uint> {
128+
let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };
129+
130+
if res < 0 {
131+
return Err(SysError::last());
132+
}
133+
134+
return Ok(res as uint)
135+
}

0 commit comments

Comments
 (0)