1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 use std::io;
15 use std::mem::{self, size_of, MaybeUninit};
16 use std::net::{self, SocketAddr};
17 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
18 use std::time::Duration;
19
20 use libc::{
21 c_int, c_void, linger, socklen_t, AF_INET, AF_INET6, SOCK_CLOEXEC, SOCK_NONBLOCK, SOCK_STREAM,
22 SOL_SOCKET, SO_LINGER, SO_REUSEADDR,
23 };
24
25 use super::super::socket_addr::socket_addr_trans;
26 use super::{TcpListener, TcpStream};
27 use crate::source::Fd;
28
29 pub(crate) struct TcpSocket {
30 socket: c_int,
31 }
32
33 impl TcpSocket {
new_socket(addr: SocketAddr) -> io::Result<TcpSocket>34 pub(crate) fn new_socket(addr: SocketAddr) -> io::Result<TcpSocket> {
35 if addr.is_ipv4() {
36 TcpSocket::create_socket(AF_INET, SOCK_STREAM)
37 } else {
38 TcpSocket::create_socket(AF_INET6, SOCK_STREAM)
39 }
40 }
41
create_socket(domain: c_int, socket_type: c_int) -> io::Result<TcpSocket>42 pub(crate) fn create_socket(domain: c_int, socket_type: c_int) -> io::Result<TcpSocket> {
43 let socket_type = socket_type | SOCK_NONBLOCK | SOCK_CLOEXEC;
44 match syscall!(socket(domain, socket_type, 0)) {
45 Ok(socket) => Ok(TcpSocket {
46 socket: socket as c_int,
47 }),
48 Err(err) => Err(err),
49 }
50 }
51
set_reuse(&self, is_reuse: bool) -> io::Result<()>52 pub(crate) fn set_reuse(&self, is_reuse: bool) -> io::Result<()> {
53 let set_value: c_int = i32::from(is_reuse);
54
55 match syscall!(setsockopt(
56 self.socket,
57 SOL_SOCKET,
58 SO_REUSEADDR,
59 &set_value as *const c_int as *const c_void,
60 size_of::<c_int>() as socklen_t
61 )) {
62 Err(err) => Err(err),
63 Ok(_) => Ok(()),
64 }
65 }
66
bind(&self, addr: SocketAddr) -> io::Result<()>67 pub(crate) fn bind(&self, addr: SocketAddr) -> io::Result<()> {
68 let (raw_addr, addr_length) = socket_addr_trans(&addr);
69 match syscall!(bind(self.socket, raw_addr.as_ptr(), addr_length)) {
70 Err(err) => Err(err),
71 Ok(_) => Ok(()),
72 }
73 }
74
listen(self, max_connect: c_int) -> io::Result<TcpListener>75 pub(crate) fn listen(self, max_connect: c_int) -> io::Result<TcpListener> {
76 syscall!(listen(self.socket, max_connect))?;
77
78 let tcp_listener = Ok(TcpListener {
79 inner: unsafe { net::TcpListener::from_raw_fd(self.socket) },
80 });
81
82 mem::forget(self);
83
84 tcp_listener
85 }
86
connect(self, addr: SocketAddr) -> io::Result<TcpStream>87 pub(crate) fn connect(self, addr: SocketAddr) -> io::Result<TcpStream> {
88 let (raw_addr, addr_length) = socket_addr_trans(&addr);
89 match syscall!(connect(self.socket, raw_addr.as_ptr(), addr_length)) {
90 Err(err) if err.raw_os_error() != Some(libc::EINPROGRESS) => Err(err),
91 _ => {
92 let tcp_stream = Ok(TcpStream {
93 inner: unsafe { net::TcpStream::from_raw_fd(self.socket) },
94 });
95 mem::forget(self);
96 tcp_stream
97 }
98 }
99 }
100
close(&self)101 pub(crate) fn close(&self) {
102 let _ = unsafe { net::TcpStream::from_raw_fd(self.socket) };
103 }
104 }
105
106 impl AsRawFd for TcpSocket {
as_raw_fd(&self) -> RawFd107 fn as_raw_fd(&self) -> RawFd {
108 self.socket
109 }
110 }
111
112 impl FromRawFd for TcpSocket {
from_raw_fd(fd: RawFd) -> TcpSocket113 unsafe fn from_raw_fd(fd: RawFd) -> TcpSocket {
114 TcpSocket { socket: fd }
115 }
116 }
117
118 impl Drop for TcpSocket {
drop(&mut self)119 fn drop(&mut self) {
120 self.close();
121 }
122 }
123
get_sock_linger(fd: Fd) -> io::Result<Option<Duration>>124 pub(crate) fn get_sock_linger(fd: Fd) -> io::Result<Option<Duration>> {
125 let mut payload: MaybeUninit<linger> = MaybeUninit::uninit();
126 let mut len = mem::size_of::<linger>() as libc::socklen_t;
127
128 syscall!(getsockopt(
129 fd as c_int,
130 SOL_SOCKET,
131 SO_LINGER,
132 payload.as_mut_ptr().cast(),
133 &mut len,
134 ))
135 .map(|_| {
136 let linger = unsafe { payload.assume_init() };
137 from_linger(linger)
138 })
139 }
140
set_sock_linger(fd: Fd, duration: Option<Duration>) -> io::Result<()>141 pub(crate) fn set_sock_linger(fd: Fd, duration: Option<Duration>) -> io::Result<()> {
142 let payload = into_linger(duration);
143 syscall!(setsockopt(
144 fd as c_int,
145 SOL_SOCKET,
146 SO_LINGER,
147 &payload as *const linger as *const c_void,
148 mem::size_of::<linger>() as libc::socklen_t,
149 ))
150 .map(|_| ())
151 }
152
from_linger(linger: linger) -> Option<Duration>153 fn from_linger(linger: linger) -> Option<Duration> {
154 if linger.l_onoff == 0 {
155 None
156 } else {
157 Some(Duration::from_secs(linger.l_linger as u64))
158 }
159 }
160
into_linger(duration: Option<Duration>) -> linger161 fn into_linger(duration: Option<Duration>) -> linger {
162 match duration {
163 None => linger {
164 l_onoff: 0,
165 l_linger: 0,
166 },
167 Some(dur) => linger {
168 l_onoff: 1,
169 l_linger: dur.as_secs() as _,
170 },
171 }
172 }
173