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::windows::io::FromRawSocket;
16 use std::os::windows::raw;
17 use std::{io, net};
18 
19 use crate::sys::winapi::{
20     bind as win_bind, closesocket, ioctlsocket, socket, ADDRESS_FAMILY, AF_INET, AF_INET6, FIONBIO,
21     INVALID_SOCKET, SOCKET, SOCKET_ERROR, SOCK_DGRAM,
22 };
23 use crate::sys::windows::net::init;
24 use crate::sys::windows::socket_addr::socket_addr_trans;
25 
26 #[derive(Debug)]
27 pub(crate) struct UdpSock {
28     socket: SOCKET,
29 }
30 
31 impl UdpSock {
32     /// Gets new socket
new_socket(addr: SocketAddr) -> io::Result<UdpSock>33     pub(crate) fn new_socket(addr: SocketAddr) -> io::Result<UdpSock> {
34         if addr.is_ipv4() {
35             Self::create_socket(AF_INET, SOCK_DGRAM)
36         } else {
37             Self::create_socket(AF_INET6, SOCK_DGRAM)
38         }
39     }
40 
create_socket(domain: ADDRESS_FAMILY, socket_type: u16) -> io::Result<UdpSock>41     fn create_socket(domain: ADDRESS_FAMILY, socket_type: u16) -> io::Result<UdpSock> {
42         init();
43 
44         let socket = socket_syscall!(
45             socket(domain as i32, socket_type as i32, 0),
46             PartialEq::eq,
47             INVALID_SOCKET
48         )?;
49 
50         match socket_syscall!(ioctlsocket(socket, FIONBIO, &mut 1), PartialEq::ne, 0) {
51             Err(err) => {
52                 let _ = unsafe { closesocket(socket) };
53                 Err(err)
54             }
55             Ok(_) => Ok(UdpSock { socket }),
56         }
57     }
58 
59     /// System call gets net::UdpSocket
bind(self, addr: SocketAddr) -> io::Result<net::UdpSocket>60     pub(crate) fn bind(self, addr: SocketAddr) -> io::Result<net::UdpSocket> {
61         let socket = unsafe { net::UdpSocket::from_raw_socket(self.socket as raw::SOCKET) };
62 
63         let (raw_addr, addr_length) = socket_addr_trans(&addr);
64         socket_syscall!(
65             win_bind(self.socket, raw_addr.as_ptr(), addr_length),
66             PartialEq::eq,
67             SOCKET_ERROR
68         )?;
69         Ok(socket)
70     }
71 }
72