1cac7dca0Sopenharmony_ci// Copyright (c) 2023 Huawei Device Co., Ltd. 2cac7dca0Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 3cac7dca0Sopenharmony_ci// you may not use this file except in compliance with the License. 4cac7dca0Sopenharmony_ci// You may obtain a copy of the License at 5cac7dca0Sopenharmony_ci// 6cac7dca0Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 7cac7dca0Sopenharmony_ci// 8cac7dca0Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 9cac7dca0Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 10cac7dca0Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11cac7dca0Sopenharmony_ci// See the License for the specific language governing permissions and 12cac7dca0Sopenharmony_ci// limitations under the License. 13cac7dca0Sopenharmony_ci 14cac7dca0Sopenharmony_ciuse std::os::windows::io::RawSocket; 15cac7dca0Sopenharmony_ciuse std::pin::Pin; 16cac7dca0Sopenharmony_ciuse std::sync::{Arc, Mutex, Once}; 17cac7dca0Sopenharmony_ciuse std::{io, net}; 18cac7dca0Sopenharmony_ci 19cac7dca0Sopenharmony_ciuse crate::sys::windows::selector::{SelectorInner, SockState}; 20cac7dca0Sopenharmony_ciuse crate::{Interest, Selector, Token}; 21cac7dca0Sopenharmony_ci 22cac7dca0Sopenharmony_ci/// Initialise the network stack for Windows. 23cac7dca0Sopenharmony_cipub(crate) fn init() { 24cac7dca0Sopenharmony_ci static INIT: Once = Once::new(); 25cac7dca0Sopenharmony_ci INIT.call_once(|| { 26cac7dca0Sopenharmony_ci drop(net::UdpSocket::bind("127.0.0.1:0")); 27cac7dca0Sopenharmony_ci }); 28cac7dca0Sopenharmony_ci} 29cac7dca0Sopenharmony_ci 30cac7dca0Sopenharmony_ci#[derive(Clone)] 31cac7dca0Sopenharmony_cipub(crate) struct NetState { 32cac7dca0Sopenharmony_ci /// State is None if the socket has not been Registered. 33cac7dca0Sopenharmony_ci inner: Option<Box<NetInner>>, 34cac7dca0Sopenharmony_ci} 35cac7dca0Sopenharmony_ci 36cac7dca0Sopenharmony_ciimpl NetState { 37cac7dca0Sopenharmony_ci /// Creates a new `NetState` with None. 38cac7dca0Sopenharmony_ci pub(crate) fn new() -> NetState { 39cac7dca0Sopenharmony_ci NetState { inner: None } 40cac7dca0Sopenharmony_ci } 41cac7dca0Sopenharmony_ci 42cac7dca0Sopenharmony_ci /// Register the socket to [`Selector`] 43cac7dca0Sopenharmony_ci /// If inner is Some, this function returns Err(AlreadyExists). 44cac7dca0Sopenharmony_ci /// If register success, Set the inner to Some. 45cac7dca0Sopenharmony_ci pub fn register( 46cac7dca0Sopenharmony_ci &mut self, 47cac7dca0Sopenharmony_ci selector: &Selector, 48cac7dca0Sopenharmony_ci token: Token, 49cac7dca0Sopenharmony_ci interests: Interest, 50cac7dca0Sopenharmony_ci socket: RawSocket, 51cac7dca0Sopenharmony_ci ) -> io::Result<()> { 52cac7dca0Sopenharmony_ci match self.inner { 53cac7dca0Sopenharmony_ci Some(_) => Err(io::ErrorKind::AlreadyExists.into()), 54cac7dca0Sopenharmony_ci None => selector.register(socket, token, interests).map(|state| { 55cac7dca0Sopenharmony_ci self.inner = Some(Box::new(state)); 56cac7dca0Sopenharmony_ci }), 57cac7dca0Sopenharmony_ci } 58cac7dca0Sopenharmony_ci } 59cac7dca0Sopenharmony_ci 60cac7dca0Sopenharmony_ci /// Deregister the socket 61cac7dca0Sopenharmony_ci pub fn deregister(&mut self) -> io::Result<()> { 62cac7dca0Sopenharmony_ci match self.inner.as_mut() { 63cac7dca0Sopenharmony_ci Some(state) => { 64cac7dca0Sopenharmony_ci { 65cac7dca0Sopenharmony_ci let mut sock_state = state.state.lock().unwrap(); 66cac7dca0Sopenharmony_ci sock_state.start_drop(); 67cac7dca0Sopenharmony_ci } 68cac7dca0Sopenharmony_ci self.inner = None; 69cac7dca0Sopenharmony_ci Ok(()) 70cac7dca0Sopenharmony_ci } 71cac7dca0Sopenharmony_ci None => Err(io::ErrorKind::NotFound.into()), 72cac7dca0Sopenharmony_ci } 73cac7dca0Sopenharmony_ci } 74cac7dca0Sopenharmony_ci 75cac7dca0Sopenharmony_ci /// The IO operation does not really report an error when Err(WouldBlock) 76cac7dca0Sopenharmony_ci /// occurs. We need to re-register the current IO operation. 77cac7dca0Sopenharmony_ci pub(crate) fn try_io<T, F, R>(&self, task: F, io: &T) -> io::Result<R> 78cac7dca0Sopenharmony_ci where 79cac7dca0Sopenharmony_ci F: FnOnce(&T) -> io::Result<R>, 80cac7dca0Sopenharmony_ci { 81cac7dca0Sopenharmony_ci let result = task(io); 82cac7dca0Sopenharmony_ci if let Err(ref e) = result { 83cac7dca0Sopenharmony_ci if e.kind() == io::ErrorKind::WouldBlock { 84cac7dca0Sopenharmony_ci self.inner.as_ref().map_or(Ok(()), |net_inner| { 85cac7dca0Sopenharmony_ci net_inner.selector.reregister( 86cac7dca0Sopenharmony_ci net_inner.state.clone(), 87cac7dca0Sopenharmony_ci net_inner.token, 88cac7dca0Sopenharmony_ci net_inner.interests, 89cac7dca0Sopenharmony_ci ) 90cac7dca0Sopenharmony_ci })?; 91cac7dca0Sopenharmony_ci } 92cac7dca0Sopenharmony_ci } 93cac7dca0Sopenharmony_ci result 94cac7dca0Sopenharmony_ci } 95cac7dca0Sopenharmony_ci} 96cac7dca0Sopenharmony_ci 97cac7dca0Sopenharmony_ci/// This structure used to re-register the socket when Err(WouldBlock) occurs 98cac7dca0Sopenharmony_ci#[derive(Clone)] 99cac7dca0Sopenharmony_cipub(crate) struct NetInner { 100cac7dca0Sopenharmony_ci selector: Arc<SelectorInner>, 101cac7dca0Sopenharmony_ci token: Token, 102cac7dca0Sopenharmony_ci interests: Interest, 103cac7dca0Sopenharmony_ci state: Pin<Arc<Mutex<SockState>>>, 104cac7dca0Sopenharmony_ci} 105cac7dca0Sopenharmony_ci 106cac7dca0Sopenharmony_ciimpl NetInner { 107cac7dca0Sopenharmony_ci pub(crate) fn new( 108cac7dca0Sopenharmony_ci selector: Arc<SelectorInner>, 109cac7dca0Sopenharmony_ci token: Token, 110cac7dca0Sopenharmony_ci interests: Interest, 111cac7dca0Sopenharmony_ci state: Pin<Arc<Mutex<SockState>>>, 112cac7dca0Sopenharmony_ci ) -> NetInner { 113cac7dca0Sopenharmony_ci NetInner { 114cac7dca0Sopenharmony_ci selector, 115cac7dca0Sopenharmony_ci token, 116cac7dca0Sopenharmony_ci interests, 117cac7dca0Sopenharmony_ci state, 118cac7dca0Sopenharmony_ci } 119cac7dca0Sopenharmony_ci } 120cac7dca0Sopenharmony_ci} 121cac7dca0Sopenharmony_ci 122cac7dca0Sopenharmony_ciimpl Drop for NetInner { 123cac7dca0Sopenharmony_ci fn drop(&mut self) { 124cac7dca0Sopenharmony_ci let mut sock_state = self.state.lock().unwrap(); 125cac7dca0Sopenharmony_ci sock_state.start_drop(); 126cac7dca0Sopenharmony_ci } 127cac7dca0Sopenharmony_ci} 128