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::net::SocketAddr; 15 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; 16 use std::{io, mem, net}; 17 18 use libc::{c_int, AF_INET, AF_INET6, SOCK_CLOEXEC, SOCK_DGRAM, SOCK_NONBLOCK}; 19 20 use super::super::socket_addr::socket_addr_trans; 21 use crate::UdpSocket; 22 23 pub(crate) struct UdpSock { 24 socket: c_int, 25 } 26 27 impl UdpSock { new_socket(addr: SocketAddr) -> io::Result<UdpSock>28 pub(crate) fn new_socket(addr: SocketAddr) -> io::Result<UdpSock> { 29 if addr.is_ipv4() { 30 UdpSock::create_socket(AF_INET, SOCK_DGRAM) 31 } else { 32 UdpSock::create_socket(AF_INET6, SOCK_DGRAM) 33 } 34 } 35 create_socket(domain: c_int, socket_type: c_int) -> io::Result<UdpSock>36 pub(crate) fn create_socket(domain: c_int, socket_type: c_int) -> io::Result<UdpSock> { 37 let socket_type = socket_type | SOCK_NONBLOCK | SOCK_CLOEXEC; 38 match syscall!(socket(domain, socket_type, 0)) { 39 Ok(socket) => Ok(UdpSock { 40 socket: socket as c_int, 41 }), 42 Err(err) => Err(err), 43 } 44 } 45 bind(self, addr: SocketAddr) -> io::Result<UdpSocket>46 pub(crate) fn bind(self, addr: SocketAddr) -> io::Result<UdpSocket> { 47 let (raw_addr, addr_length) = socket_addr_trans(&addr); 48 match syscall!(bind(self.socket, raw_addr.as_ptr(), addr_length)) { 49 Err(err) if err.raw_os_error() != Some(libc::EINPROGRESS) => Err(err), 50 _ => { 51 let udp_socket = Ok(UdpSocket { 52 inner: unsafe { net::UdpSocket::from_raw_fd(self.socket) }, 53 }); 54 mem::forget(self); 55 udp_socket 56 } 57 } 58 } 59 close(&self)60 pub(crate) fn close(&self) { 61 let _ = unsafe { net::UdpSocket::from_raw_fd(self.socket) }; 62 } 63 } 64 65 impl AsRawFd for UdpSock { as_raw_fd(&self) -> RawFd66 fn as_raw_fd(&self) -> RawFd { 67 self.socket 68 } 69 } 70 71 impl FromRawFd for UdpSock { from_raw_fd(fd: RawFd) -> UdpSock72 unsafe fn from_raw_fd(fd: RawFd) -> UdpSock { 73 UdpSock { socket: fd } 74 } 75 } 76 77 impl Drop for UdpSock { drop(&mut self)78 fn drop(&mut self) { 79 self.close(); 80 } 81 } 82