• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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};
16 use std::net::{self, SocketAddr};
17 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
18 
19 use libc::{
20     c_int, c_void, socklen_t, AF_INET, AF_INET6, SOCK_CLOEXEC, SOCK_NONBLOCK, SOCK_STREAM,
21     SOL_SOCKET, SO_REUSEADDR,
22 };
23 
24 use super::super::socket_addr::socket_addr_trans;
25 use super::{TcpListener, TcpStream};
26 
27 pub(crate) struct TcpSocket {
28     socket: c_int,
29 }
30 
31 impl TcpSocket {
new_socket(addr: SocketAddr) -> io::Result<TcpSocket>32     pub(crate) fn new_socket(addr: SocketAddr) -> io::Result<TcpSocket> {
33         if addr.is_ipv4() {
34             TcpSocket::create_socket(AF_INET, SOCK_STREAM)
35         } else {
36             TcpSocket::create_socket(AF_INET6, SOCK_STREAM)
37         }
38     }
39 
create_socket(domain: c_int, socket_type: c_int) -> io::Result<TcpSocket>40     pub(crate) fn create_socket(domain: c_int, socket_type: c_int) -> io::Result<TcpSocket> {
41         let socket_type = socket_type | SOCK_NONBLOCK | SOCK_CLOEXEC;
42         match syscall!(socket(domain, socket_type, 0)) {
43             Ok(socket) => Ok(TcpSocket {
44                 socket: socket as c_int,
45             }),
46             Err(err) => Err(err),
47         }
48     }
49 
set_reuse(&self, is_reuse: bool) -> io::Result<()>50     pub(crate) fn set_reuse(&self, is_reuse: bool) -> io::Result<()> {
51         let set_value: c_int = i32::from(is_reuse);
52 
53         match syscall!(setsockopt(
54             self.socket,
55             SOL_SOCKET,
56             SO_REUSEADDR,
57             &set_value as *const c_int as *const c_void,
58             size_of::<c_int>() as socklen_t
59         )) {
60             Err(err) => Err(err),
61             Ok(_) => Ok(()),
62         }
63     }
64 
bind(&self, addr: SocketAddr) -> io::Result<()>65     pub(crate) fn bind(&self, addr: SocketAddr) -> io::Result<()> {
66         let (raw_addr, addr_length) = socket_addr_trans(&addr);
67         match syscall!(bind(self.socket, raw_addr.as_ptr(), addr_length)) {
68             Err(err) => Err(err),
69             Ok(_) => Ok(()),
70         }
71     }
72 
listen(self, max_connect: c_int) -> io::Result<TcpListener>73     pub(crate) fn listen(self, max_connect: c_int) -> io::Result<TcpListener> {
74         syscall!(listen(self.socket, max_connect))?;
75 
76         let tcp_listener = Ok(TcpListener {
77             inner: unsafe { net::TcpListener::from_raw_fd(self.socket) },
78         });
79 
80         mem::forget(self);
81 
82         tcp_listener
83     }
84 
connect(self, addr: SocketAddr) -> io::Result<TcpStream>85     pub(crate) fn connect(self, addr: SocketAddr) -> io::Result<TcpStream> {
86         let (raw_addr, addr_length) = socket_addr_trans(&addr);
87         match syscall!(connect(self.socket, raw_addr.as_ptr(), addr_length)) {
88             Err(err) if err.raw_os_error() != Some(libc::EINPROGRESS) => Err(err),
89             _ => {
90                 let tcp_stream = Ok(TcpStream {
91                     inner: unsafe { net::TcpStream::from_raw_fd(self.socket) },
92                 });
93                 mem::forget(self);
94                 tcp_stream
95             }
96         }
97     }
98 
close(&self)99     pub(crate) fn close(&self) {
100         let _ = unsafe { net::TcpStream::from_raw_fd(self.socket) };
101     }
102 }
103 
104 impl AsRawFd for TcpSocket {
as_raw_fd(&self) -> RawFd105     fn as_raw_fd(&self) -> RawFd {
106         self.socket
107     }
108 }
109 
110 impl FromRawFd for TcpSocket {
from_raw_fd(fd: RawFd) -> TcpSocket111     unsafe fn from_raw_fd(fd: RawFd) -> TcpSocket {
112         TcpSocket { socket: fd }
113     }
114 }
115 
116 impl Drop for TcpSocket {
drop(&mut self)117     fn drop(&mut self) {
118         self.close();
119     }
120 }
121