|
1 | 1 | #![cfg(all(windows, feature = "os-poll", feature = "os-ext"))]
|
2 | 2 |
|
| 3 | +use std::ffi::OsStr; |
3 | 4 | use std::fs::OpenOptions;
|
4 | 5 | use std::io::{self, Read, Write};
|
| 6 | +use std::os::windows::ffi::OsStrExt; |
5 | 7 | use std::os::windows::fs::OpenOptionsExt;
|
6 |
| -use std::os::windows::io::{FromRawHandle, IntoRawHandle}; |
| 8 | +use std::os::windows::io::{FromRawHandle, IntoRawHandle, RawHandle}; |
7 | 9 | use std::time::Duration;
|
8 | 10 |
|
9 | 11 | use mio::windows::NamedPipe;
|
10 | 12 | use mio::{Events, Interest, Poll, Token};
|
11 | 13 | use rand::Rng;
|
12 |
| -use windows_sys::Win32::{Foundation::ERROR_NO_DATA, Storage::FileSystem::FILE_FLAG_OVERLAPPED}; |
| 14 | +use windows_sys::Win32::Foundation::ERROR_NO_DATA; |
| 15 | +use windows_sys::Win32::Storage::FileSystem::{ |
| 16 | + CreateFileW, FILE_FLAG_FIRST_PIPE_INSTANCE, FILE_FLAG_OVERLAPPED, OPEN_EXISTING, |
| 17 | + PIPE_ACCESS_DUPLEX, |
| 18 | +}; |
| 19 | +use windows_sys::Win32::System::Pipes::{ |
| 20 | + CreateNamedPipeW, PIPE_READMODE_MESSAGE, PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, |
| 21 | +}; |
13 | 22 |
|
14 | 23 | fn _assert_kinds() {
|
15 | 24 | fn _assert_send<T: Send>() {}
|
@@ -43,6 +52,38 @@ fn client(name: &str) -> NamedPipe {
|
43 | 52 | unsafe { NamedPipe::from_raw_handle(file.into_raw_handle()) }
|
44 | 53 | }
|
45 | 54 |
|
| 55 | +fn pipe_msg_mode() -> (NamedPipe, NamedPipe) { |
| 56 | + let num: u64 = rand::thread_rng().gen(); |
| 57 | + let name = format!(r"\\.\pipe\my-pipe-{}", num); |
| 58 | + let name: Vec<_> = OsStr::new(&name).encode_wide().chain(Some(0)).collect(); |
| 59 | + unsafe { |
| 60 | + let h = CreateNamedPipeW( |
| 61 | + name.as_ptr(), |
| 62 | + PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED, |
| 63 | + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, |
| 64 | + PIPE_UNLIMITED_INSTANCES, |
| 65 | + 65536, |
| 66 | + 65536, |
| 67 | + 0, |
| 68 | + std::ptr::null_mut(), |
| 69 | + ); |
| 70 | + |
| 71 | + let server = NamedPipe::from_raw_handle(h as RawHandle); |
| 72 | + |
| 73 | + let h = CreateFileW( |
| 74 | + name.as_ptr(), |
| 75 | + PIPE_ACCESS_DUPLEX, |
| 76 | + 0, |
| 77 | + std::ptr::null_mut(), |
| 78 | + OPEN_EXISTING, |
| 79 | + FILE_FLAG_OVERLAPPED, |
| 80 | + 0, |
| 81 | + ); |
| 82 | + let client = NamedPipe::from_raw_handle(h as RawHandle); |
| 83 | + (server, client) |
| 84 | + } |
| 85 | +} |
| 86 | + |
46 | 87 | fn pipe() -> (NamedPipe, NamedPipe) {
|
47 | 88 | let (pipe, name) = server();
|
48 | 89 | (pipe, client(&name))
|
@@ -108,6 +149,45 @@ fn write_then_read() {
|
108 | 149 | assert_eq!(&buf[..4], b"1234");
|
109 | 150 | }
|
110 | 151 |
|
| 152 | +#[test] |
| 153 | +fn read_sz_greater_than_default_buf_size() { |
| 154 | + let (mut server, mut client) = pipe_msg_mode(); |
| 155 | + let mut poll = t!(Poll::new()); |
| 156 | + t!(poll.registry().register( |
| 157 | + &mut server, |
| 158 | + Token(0), |
| 159 | + Interest::READABLE | Interest::WRITABLE, |
| 160 | + )); |
| 161 | + t!(poll.registry().register( |
| 162 | + &mut client, |
| 163 | + Token(1), |
| 164 | + Interest::READABLE | Interest::WRITABLE, |
| 165 | + )); |
| 166 | + |
| 167 | + let mut events = Events::with_capacity(128); |
| 168 | + let msg = (0..4106) |
| 169 | + .map(|e| e.to_string()) |
| 170 | + .collect::<Vec<_>>() |
| 171 | + .join(""); |
| 172 | + |
| 173 | + t!(poll.poll(&mut events, None)); |
| 174 | + assert_eq!(t!(client.write(msg.as_bytes())), 15314); |
| 175 | + |
| 176 | + loop { |
| 177 | + t!(poll.poll(&mut events, None)); |
| 178 | + let events = events.iter().collect::<Vec<_>>(); |
| 179 | + if let Some(event) = events.iter().find(|e| e.token() == Token(0)) { |
| 180 | + if event.is_readable() { |
| 181 | + break; |
| 182 | + } |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + let mut buf = [0; 15314]; |
| 187 | + assert_eq!(t!(server.read(&mut buf)), 15314); |
| 188 | + assert_eq!(&buf[..15314], msg.as_bytes()); |
| 189 | +} |
| 190 | + |
111 | 191 | #[test]
|
112 | 192 | fn connect_before_client() {
|
113 | 193 | let (mut server, name) = server();
|
|
0 commit comments