• 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::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