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