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