1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 use libc
::{self, c_int, size_t}
;
19 use sys
::fd
::FileDesc
;
20 use sys_common
::{AsInner, FromInner, IntoInner}
;
21 use sys_common
::net
::{getsockopt, setsockopt}
;
24 pub use sys
::{cvt, cvt_r}
;
26 pub type wrlen_t
= size_t
;
28 pub struct Socket(FileDesc
);
32 pub fn cvt_gai(err
: c_int
) -> io
::Result
<()> {
33 if err
== 0 { return Ok(()) }
36 str::from_utf8(CStr
::from_ptr(c
::gai_strerror(err
)).to_bytes()).unwrap()
39 Err(io
::Error
::new(io
::ErrorKind
::Other
,
40 &format
!("failed to lookup address information: {}",
45 pub fn new(addr
: &SocketAddr
, ty
: c_int
) -> io
::Result
<Socket
> {
46 let fam
= match *addr
{
47 SocketAddr
::V4(..) => libc
::AF_INET
,
48 SocketAddr
::V6(..) => libc
::AF_INET6
,
51 let fd
= try
!(cvt(libc
::socket(fam
, ty
, 0)));
52 let fd
= FileDesc
::new(fd
);
58 pub fn accept(&self, storage
: *mut libc
::sockaddr
,
59 len
: *mut libc
::socklen_t
) -> io
::Result
<Socket
> {
60 let fd
= try
!(cvt_r(|| unsafe {
61 libc
::accept(self.0.raw(), storage
, len
)
63 let fd
= FileDesc
::new(fd
);
68 pub fn duplicate(&self) -> io
::Result
<Socket
> {
69 let fd
= try
!(cvt(unsafe { libc::dup(self.0.raw()) }
));
70 let fd
= FileDesc
::new(fd
);
75 pub fn read(&self, buf
: &mut [u8]) -> io
::Result
<usize> {
79 pub fn set_timeout(&self, dur
: Option
<Duration
>, kind
: libc
::c_int
) -> io
::Result
<()> {
80 let timeout
= match dur
{
82 if dur
.as_secs() == 0 && dur
.subsec_nanos() == 0 {
83 return Err(io
::Error
::new(io
::ErrorKind
::InvalidInput
,
84 "cannot set a 0 duration timeout"));
87 let secs
= if dur
.as_secs() > libc
::time_t
::max_value() as u64 {
88 libc
::time_t
::max_value()
90 dur
.as_secs() as libc
::time_t
92 let mut timeout
= libc
::timeval
{
94 tv_usec
: (dur
.subsec_nanos() / 1000) as libc
::suseconds_t
,
96 if timeout
.tv_sec
== 0 && timeout
.tv_usec
== 0 {
108 setsockopt(self, libc
::SOL_SOCKET
, kind
, timeout
)
111 pub fn timeout(&self, kind
: libc
::c_int
) -> io
::Result
<Option
<Duration
>> {
112 let raw
: libc
::timeval
= try
!(getsockopt(self, libc
::SOL_SOCKET
, kind
));
113 if raw
.tv_sec
== 0 && raw
.tv_usec
== 0 {
116 let sec
= raw
.tv_sec
as u64;
117 let nsec
= (raw
.tv_usec
as u32) * 1000;
118 Ok(Some(Duration
::new(sec
, nsec
)))
123 impl AsInner
<c_int
> for Socket
{
124 fn as_inner(&self) -> &c_int { self.0.as_inner() }
127 impl FromInner
<c_int
> for Socket
{
128 fn from_inner(fd
: c_int
) -> Socket { Socket(FileDesc::new(fd)) }
131 impl IntoInner
<c_int
> for Socket
{
132 fn into_inner(self) -> c_int { self.0.into_raw() }