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, net};
17 
18 use libc::{c_int, AF_INET, AF_INET6, SOCK_DGRAM};
19 
20 use super::super::socket_addr::socket_addr_trans;
21 use crate::sys::socket::socket_new;
22 use crate::UdpSocket;
23 
24 pub(crate) struct UdpSock {
25     socket: c_int,
26 }
27 
28 impl UdpSock {
new_socket(addr: SocketAddr) -> io::Result<UdpSock>29     pub(crate) fn new_socket(addr: SocketAddr) -> io::Result<UdpSock> {
30         if addr.is_ipv4() {
31             UdpSock::create_socket(AF_INET, SOCK_DGRAM)
32         } else {
33             UdpSock::create_socket(AF_INET6, SOCK_DGRAM)
34         }
35     }
36 
create_socket(domain: c_int, socket_type: c_int) -> io::Result<UdpSock>37     pub(crate) fn create_socket(domain: c_int, socket_type: c_int) -> io::Result<UdpSock> {
38         let socket = socket_new(domain, socket_type)?;
39         Ok(UdpSock {
40             socket: socket as c_int,
41         })
42     }
43 
bind(self, addr: SocketAddr) -> io::Result<UdpSocket>44     pub(crate) fn bind(self, addr: SocketAddr) -> io::Result<UdpSocket> {
45         let udp_socket = UdpSocket {
46             inner: unsafe { net::UdpSocket::from_raw_fd(self.socket) },
47         };
48         let (raw_addr, addr_length) = socket_addr_trans(&addr);
49         match syscall!(bind(self.socket, raw_addr.as_ptr(), addr_length)) {
50             Err(err) if err.raw_os_error() != Some(libc::EINPROGRESS) => Err(err),
51             _ => Ok(udp_socket),
52         }
53     }
54 }
55 
56 impl AsRawFd for UdpSock {
as_raw_fd(&self) -> RawFd57     fn as_raw_fd(&self) -> RawFd {
58         self.socket
59     }
60 }
61 
62 impl FromRawFd for UdpSock {
from_raw_fd(fd: RawFd) -> UdpSock63     unsafe fn from_raw_fd(fd: RawFd) -> UdpSock {
64         UdpSock { socket: fd }
65     }
66 }
67