async/
async.rs

1/// https://docs.microsoft.com/en-us/windows/win32/wininet/asynchronous-example-application
2
3
4#[cfg(not(feature = "unicode"))]
5use std::ffi::{OsStr, CString};
6
7#[cfg(feature = "unicode")]
8use widestring::U16CString;
9
10use win_inet::{InternetOpenType, WinINet, WinINetRequest, InternetStatus, INTERNET_ASYNC_RESULT};
11
12fn main() {
13    if let Err(e) = work() {
14        eprintln!("{}", e);
15    }
16}
17use std::sync::Barrier;
18static mut barrier: Option<Barrier> = None;
19
20fn work() -> std::io::Result<()> {
21  unsafe {
22    barrier = Some(Barrier::new(2));
23  }
24
25    #[cfg(feature = "unicode")]
26    let (agent, host, method, path) = (
27      U16CString::from_str("Hello, world!").unwrap(),
28      U16CString::from_str("drak.li").unwrap(),
29      U16CString::from_str("GET").unwrap(),
30      U16CString::from_str("/").unwrap()
31    );
32    #[cfg(not(feature = "unicode"))]
33    let (agent, host, method, path) = (
34      CString::new("Hello, world!").unwrap(),
35      CString::new("drak.li").unwrap(),
36      CString::new("GET").unwrap(),
37      CString::new("/").unwrap()
38    );
39
40    let mut agent = WinINet::new(
41      &agent,
42      InternetOpenType::Preconfig,
43      None,
44      None,
45    )?;
46    agent.set_callback(Some(callback));
47    let c = agent.connect(&host, 80, None, None)?;
48    let r = c.request(&method, &path, false)?;
49    
50    println!("open...");
51    if let Err(e) = r.open() {
52      if e.raw_os_error() != Some(win_inet::ERROR_IO_PENDING) {
53        return Err(e);
54      }
55      println!("wait");
56      unsafe {barrier.as_ref()}.unwrap().wait();
57    }
58
59    println!("send...");
60    unsafe {
61      barrier = Some(Barrier::new(2));
62    }
63    if let Err(e) = r.send() {
64      if e.raw_os_error() != Some(win_inet::ERROR_IO_PENDING) {
65        return Err(e);
66      }
67      println!("wait2");
68      unsafe {barrier.as_ref()}.unwrap().wait();
69    }
70    println!("recv...");
71    unsafe {
72      barrier = Some(Barrier::new(2));
73    }
74    if let Err(e) = r.recv() {
75      if e.raw_os_error() != Some(win_inet::ERROR_IO_PENDING) {
76        return Err(e);
77      }
78      println!("wait3");
79      unsafe {barrier.as_ref()}.unwrap().wait();
80
81    }
82    Ok(())
83}
84unsafe extern "system" fn callback(
85    handle: win_inet::HINTERNET,
86    context: usize,
87    status: u32,
88    info: win_inet::LPVOID,
89    info_len: u32,
90) {
91    if status == InternetStatus::RequestComplete as u32 {
92      let ares = &*(info as *mut INTERNET_ASYNC_RESULT);
93      println!("{} Request complete {} {:?}", context, ares.dwError, handle);
94      if let Some(w) = barrier.as_ref() {
95        w.wait();
96      }
97      //let r = &*(context as *const WinINetRequest);
98      return;
99    }
100    if status == InternetStatus::HandleCreated as u32 {
101      let ares = &*(info as *mut INTERNET_ASYNC_RESULT);
102      println!("{} Handle created {}", context, ares.dwError);
103      return;
104    }
105    println!(
106        "{} {} {:?} {} {:?}",
107        context, status, info, info_len, handle
108    );
109}