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