]> git.proxmox.com Git - rustc.git/blame - vendor/miow/src/pipe.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / vendor / miow / src / pipe.rs
CommitLineData
487cf647
FG
1//! Interprocess Communication pipes
2//!
3//! A pipe is a section of shared memory that processes use for communication.
4//! The process that creates a pipe is the _pipe server_. A process that connects
5//! to a pipe is a _pipe client_. One process writes information to the pipe, then
6//! the other process reads the information from the pipe. This overview
7//! describes how to create, manage, and use pipes.
8//!
9//! There are two types of pipes: [anonymous pipes](#fn.anonymous.html) and
10//! [named pipes](#fn.named.html). Anonymous pipes require less overhead than
11//! named pipes, but offer limited services.
12//!
13//! # Anonymous pipes
14//!
15//! An anonymous pipe is an unnamed, one-way pipe that typically transfers data
16//! between a parent process and a child process. Anonymous pipes are always
17//! local; they cannot be used for communication over a network.
18//!
19//! # Named pipes
20//!
21//! A *named pipe* is a named, one-way or duplex pipe for communication between
22//! the pipe server and one or more pipe clients. All instances of a named pipe
23//! share the same pipe name, but each instance has its own buffers and handles,
24//! and provides a separate conduit for client/server communication. The use of
25//! instances enables multiple pipe clients to use the same named pipe
26//! simultaneously.
27//!
28//! Any process can access named pipes, subject to security checks, making named
29//! pipes an easy form of communication between related or unrelated processes.
30//!
31//! Any process can act as both a server and a client, making peer-to-peer
32//! communication possible. As used here, the term pipe server refers to a
33//! process that creates a named pipe, and the term pipe client refers to a
34//! process that connects to an instance of a named pipe.
35//!
36//! Named pipes can be used to provide communication between processes on the
37//! same computer or between processes on different computers across a network.
38//! If the server service is running, all named pipes are accessible remotely. If
39//! you intend to use a named pipe locally only, deny access to NT
40//! AUTHORITY\\NETWORK or switch to local RPC.
41//!
42//! # References
43//!
44//! - [win32 pipe docs](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/ipc/pipes.md)
45
46use crate::FALSE;
47use std::cell::RefCell;
48use std::ffi::OsStr;
49use std::fs::{File, OpenOptions};
50use std::io;
51use std::io::{Read, Write};
52use std::os::windows::ffi::OsStrExt;
53use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
54use std::time::Duration;
55
56use crate::handle::Handle;
57use crate::overlapped::Overlapped;
58
59use windows_sys::Win32::Foundation::{
60 ERROR_IO_PENDING, ERROR_NO_DATA, ERROR_PIPE_BUSY, ERROR_PIPE_CONNECTED, HANDLE,
61 INVALID_HANDLE_VALUE,
62};
63use windows_sys::Win32::Security::SECURITY_ATTRIBUTES;
64use windows_sys::Win32::Storage::FileSystem::{
65 FlushFileBuffers, FILE_FLAG_FIRST_PIPE_INSTANCE, FILE_FLAG_OVERLAPPED, PIPE_ACCESS_DUPLEX,
66 PIPE_ACCESS_INBOUND, PIPE_ACCESS_OUTBOUND,
67};
68use windows_sys::Win32::System::Pipes::{
69 ConnectNamedPipe, CreateNamedPipeW, CreatePipe, DisconnectNamedPipe, WaitNamedPipeW,
70 PIPE_REJECT_REMOTE_CLIENTS, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES,
71};
72use windows_sys::Win32::System::IO::{GetOverlappedResult, OVERLAPPED};
73
74/// Readable half of an anonymous pipe.
75#[derive(Debug)]
76pub struct AnonRead(Handle);
77
78/// Writable half of an anonymous pipe.
79#[derive(Debug)]
80pub struct AnonWrite(Handle);
81
82/// A named pipe that can accept connections.
83#[derive(Debug)]
84pub struct NamedPipe(Handle);
85
86/// A builder structure for creating a new named pipe.
87#[derive(Debug)]
88pub struct NamedPipeBuilder {
89 name: Vec<u16>,
90 dwOpenMode: u32,
91 dwPipeMode: u32,
92 nMaxInstances: u32,
93 nOutBufferSize: u32,
94 nInBufferSize: u32,
95 nDefaultTimeOut: u32,
96}
97
98/// Creates a new anonymous in-memory pipe, returning the read/write ends of the
99/// pipe.
100///
101/// The buffer size for this pipe may also be specified, but the system will
102/// normally use this as a suggestion and it's not guaranteed that the buffer
103/// will be precisely this size.
104pub fn anonymous(buffer_size: u32) -> io::Result<(AnonRead, AnonWrite)> {
105 let mut read = 0 as HANDLE;
106 let mut write = 0 as HANDLE;
107 crate::cvt(unsafe { CreatePipe(&mut read, &mut write, 0 as *mut _, buffer_size) })?;
108 Ok((AnonRead(Handle::new(read)), AnonWrite(Handle::new(write))))
109}
110
111impl Read for AnonRead {
112 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
113 self.0.read(buf)
114 }
115}
116impl<'a> Read for &'a AnonRead {
117 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
118 self.0.read(buf)
119 }
120}
121
122impl AsRawHandle for AnonRead {
123 fn as_raw_handle(&self) -> RawHandle {
124 self.0.raw() as RawHandle
125 }
126}
127impl FromRawHandle for AnonRead {
128 unsafe fn from_raw_handle(handle: RawHandle) -> AnonRead {
129 AnonRead(Handle::new(handle as HANDLE))
130 }
131}
132impl IntoRawHandle for AnonRead {
133 fn into_raw_handle(self) -> RawHandle {
134 self.0.into_raw() as RawHandle
135 }
136}
137
138impl Write for AnonWrite {
139 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
140 self.0.write(buf)
141 }
142 fn flush(&mut self) -> io::Result<()> {
143 Ok(())
144 }
145}
146impl<'a> Write for &'a AnonWrite {
147 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
148 self.0.write(buf)
149 }
150 fn flush(&mut self) -> io::Result<()> {
151 Ok(())
152 }
153}
154
155impl AsRawHandle for AnonWrite {
156 fn as_raw_handle(&self) -> RawHandle {
157 self.0.raw() as RawHandle
158 }
159}
160impl FromRawHandle for AnonWrite {
161 unsafe fn from_raw_handle(handle: RawHandle) -> AnonWrite {
162 AnonWrite(Handle::new(handle as HANDLE))
163 }
164}
165impl IntoRawHandle for AnonWrite {
166 fn into_raw_handle(self) -> RawHandle {
167 self.0.into_raw() as RawHandle
168 }
169}
170
171/// A convenience function to connect to a named pipe.
172///
173/// This function will block the calling process until it can connect to the
174/// pipe server specified by `addr`. This will use `NamedPipe::wait` internally
175/// to block until it can connect.
176pub fn connect<A: AsRef<OsStr>>(addr: A) -> io::Result<File> {
177 _connect(addr.as_ref())
178}
179
180fn _connect(addr: &OsStr) -> io::Result<File> {
181 let mut r = OpenOptions::new();
182 let mut w = OpenOptions::new();
183 let mut rw = OpenOptions::new();
184 r.read(true);
185 w.write(true);
186 rw.read(true).write(true);
187 loop {
188 let res = rw
189 .open(addr)
190 .or_else(|_| r.open(addr))
191 .or_else(|_| w.open(addr));
192 match res {
193 Ok(f) => return Ok(f),
194 Err(ref e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY as i32) => {}
195 Err(e) => return Err(e),
196 }
197
198 NamedPipe::wait(addr, Some(Duration::new(20, 0)))?;
199 }
200}
201
202impl NamedPipe {
203 /// Creates a new initial named pipe.
204 ///
205 /// This function is equivalent to:
206 ///
207 /// ```
208 /// use miow::pipe::NamedPipeBuilder;
209 ///
210 /// # let addr = "foo";
211 /// NamedPipeBuilder::new(addr)
212 /// .first(true)
213 /// .inbound(true)
214 /// .outbound(true)
215 /// .out_buffer_size(65536)
216 /// .in_buffer_size(65536)
217 /// .create();
218 /// ```
219 pub fn new<A: AsRef<OsStr>>(addr: A) -> io::Result<NamedPipe> {
220 NamedPipeBuilder::new(addr).create()
221 }
222
223 /// Waits until either a time-out interval elapses or an instance of the
224 /// specified named pipe is available for connection.
225 ///
226 /// If this function succeeds the process can create a `File` to connect to
227 /// the named pipe.
228 pub fn wait<A: AsRef<OsStr>>(addr: A, timeout: Option<Duration>) -> io::Result<()> {
229 NamedPipe::_wait(addr.as_ref(), timeout)
230 }
231
232 fn _wait(addr: &OsStr, timeout: Option<Duration>) -> io::Result<()> {
233 let addr = addr.encode_wide().chain(Some(0)).collect::<Vec<_>>();
234 let timeout = crate::dur2ms(timeout);
235 crate::cvt(unsafe { WaitNamedPipeW(addr.as_ptr() as _, timeout) }).map(|_| ())
236 }
237
238 /// Connects this named pipe to a client, blocking until one becomes
239 /// available.
240 ///
241 /// This function will call the `ConnectNamedPipe` function to await for a
242 /// client to connect. This can be called immediately after the pipe is
243 /// created, or after it has been disconnected from a previous client.
244 pub fn connect(&self) -> io::Result<()> {
245 match crate::cvt(unsafe { ConnectNamedPipe(self.0.raw(), 0 as *mut _) }) {
246 Ok(_) => Ok(()),
247 Err(ref e) if e.raw_os_error() == Some(ERROR_PIPE_CONNECTED as i32) => Ok(()),
248 Err(e) => Err(e),
249 }
250 }
251
252 /// Issue a connection request with the specified overlapped operation.
253 ///
254 /// This function will issue a request to connect a client to this server,
255 /// returning immediately after starting the overlapped operation.
256 ///
257 /// If this function immediately succeeds then `Ok(true)` is returned. If
258 /// the overlapped operation is enqueued and pending, then `Ok(false)` is
259 /// returned. Otherwise an error is returned indicating what went wrong.
260 ///
261 /// # Unsafety
262 ///
263 /// This function is unsafe because the kernel requires that the
264 /// `overlapped` pointer is valid until the end of the I/O operation. The
265 /// kernel also requires that `overlapped` is unique for this I/O operation
266 /// and is not in use for any other I/O.
267 ///
268 /// To safely use this function callers must ensure that this pointer is
269 /// valid until the I/O operation is completed, typically via completion
270 /// ports and waiting to receive the completion notification on the port.
271 pub unsafe fn connect_overlapped(&self, overlapped: *mut OVERLAPPED) -> io::Result<bool> {
272 match crate::cvt(ConnectNamedPipe(self.0.raw(), overlapped)) {
273 Ok(_) => Ok(true),
274 Err(ref e) if e.raw_os_error() == Some(ERROR_PIPE_CONNECTED as i32) => Ok(true),
275 Err(ref e) if e.raw_os_error() == Some(ERROR_IO_PENDING as i32) => Ok(false),
276 Err(ref e) if e.raw_os_error() == Some(ERROR_NO_DATA as i32) => Ok(true),
277 Err(e) => Err(e),
278 }
279 }
280
281 /// Disconnects this named pipe from any connected client.
282 pub fn disconnect(&self) -> io::Result<()> {
283 crate::cvt(unsafe { DisconnectNamedPipe(self.0.raw()) }).map(|_| ())
284 }
285
286 /// Issues an overlapped read operation to occur on this pipe.
287 ///
288 /// This function will issue an asynchronous read to occur in an overlapped
289 /// fashion, returning immediately. The `buf` provided will be filled in
290 /// with data and the request is tracked by the `overlapped` function
291 /// provided.
292 ///
293 /// If the operation succeeds immediately, `Ok(Some(n))` is returned where
294 /// `n` is the number of bytes read. If an asynchronous operation is
295 /// enqueued, then `Ok(None)` is returned. Otherwise if an error occurred
296 /// it is returned.
297 ///
298 /// When this operation completes (or if it completes immediately), another
299 /// mechanism must be used to learn how many bytes were transferred (such as
300 /// looking at the filed in the IOCP status message).
301 ///
302 /// # Unsafety
303 ///
304 /// This function is unsafe because the kernel requires that the `buf` and
305 /// `overlapped` pointers to be valid until the end of the I/O operation.
306 /// The kernel also requires that `overlapped` is unique for this I/O
307 /// operation and is not in use for any other I/O.
308 ///
309 /// To safely use this function callers must ensure that the pointers are
310 /// valid until the I/O operation is completed, typically via completion
311 /// ports and waiting to receive the completion notification on the port.
312 pub unsafe fn read_overlapped(
313 &self,
314 buf: &mut [u8],
315 overlapped: *mut OVERLAPPED,
316 ) -> io::Result<Option<usize>> {
317 self.0.read_overlapped(buf, overlapped)
318 }
319
320 /// Issues an overlapped write operation to occur on this pipe.
321 ///
322 /// This function will issue an asynchronous write to occur in an overlapped
323 /// fashion, returning immediately. The `buf` provided will be filled in
324 /// with data and the request is tracked by the `overlapped` function
325 /// provided.
326 ///
327 /// If the operation succeeds immediately, `Ok(Some(n))` is returned where
328 /// `n` is the number of bytes written. If an asynchronous operation is
329 /// enqueued, then `Ok(None)` is returned. Otherwise if an error occurred
330 /// it is returned.
331 ///
332 /// When this operation completes (or if it completes immediately), another
333 /// mechanism must be used to learn how many bytes were transferred (such as
334 /// looking at the filed in the IOCP status message).
335 ///
336 /// # Unsafety
337 ///
338 /// This function is unsafe because the kernel requires that the `buf` and
339 /// `overlapped` pointers to be valid until the end of the I/O operation.
340 /// The kernel also requires that `overlapped` is unique for this I/O
341 /// operation and is not in use for any other I/O.
342 ///
343 /// To safely use this function callers must ensure that the pointers are
344 /// valid until the I/O operation is completed, typically via completion
345 /// ports and waiting to receive the completion notification on the port.
346 pub unsafe fn write_overlapped(
347 &self,
348 buf: &[u8],
349 overlapped: *mut OVERLAPPED,
350 ) -> io::Result<Option<usize>> {
351 self.0.write_overlapped(buf, overlapped)
352 }
353
354 /// Calls the `GetOverlappedResult` function to get the result of an
355 /// overlapped operation for this handle.
356 ///
357 /// This function takes the `OVERLAPPED` argument which must have been used
358 /// to initiate an overlapped I/O operation, and returns either the
359 /// successful number of bytes transferred during the operation or an error
360 /// if one occurred.
361 ///
362 /// # Unsafety
363 ///
364 /// This function is unsafe as `overlapped` must have previously been used
365 /// to execute an operation for this handle, and it must also be a valid
366 /// pointer to an `Overlapped` instance.
367 ///
368 /// # Panics
369 ///
370 /// This function will panic
371 pub unsafe fn result(&self, overlapped: *mut OVERLAPPED) -> io::Result<usize> {
372 let mut transferred = 0;
373 let r = GetOverlappedResult(self.0.raw(), overlapped, &mut transferred, FALSE);
374 if r == 0 {
375 Err(io::Error::last_os_error())
376 } else {
377 Ok(transferred as usize)
378 }
379 }
380}
381
382thread_local! {
383 static NAMED_PIPE_OVERLAPPED: RefCell<Option<Overlapped>> = RefCell::new(None);
384}
385
386/// Call a function with a threadlocal `Overlapped`. The function `f` should be
387/// sure that the event is reset, either manually or by a thread being released.
388fn with_threadlocal_overlapped<F>(f: F) -> io::Result<usize>
389where
390 F: FnOnce(&Overlapped) -> io::Result<usize>,
391{
392 NAMED_PIPE_OVERLAPPED.with(|overlapped| {
393 let mut mborrow = overlapped.borrow_mut();
394 if let None = *mborrow {
395 let op = Overlapped::initialize_with_autoreset_event()?;
396 *mborrow = Some(op);
397 }
398 f(mborrow.as_ref().unwrap())
399 })
400}
401
402impl Read for NamedPipe {
403 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
404 // This is necessary because the pipe is opened with `FILE_FLAG_OVERLAPPED`.
405 with_threadlocal_overlapped(|overlapped| unsafe {
406 self.0
407 .read_overlapped_wait(buf, overlapped.raw() as *mut OVERLAPPED)
408 })
409 }
410}
411impl<'a> Read for &'a NamedPipe {
412 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
413 // This is necessary because the pipe is opened with `FILE_FLAG_OVERLAPPED`.
414 with_threadlocal_overlapped(|overlapped| unsafe {
415 self.0
416 .read_overlapped_wait(buf, overlapped.raw() as *mut OVERLAPPED)
417 })
418 }
419}
420
421impl Write for NamedPipe {
422 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
423 // This is necessary because the pipe is opened with `FILE_FLAG_OVERLAPPED`.
424 with_threadlocal_overlapped(|overlapped| unsafe {
425 self.0
426 .write_overlapped_wait(buf, overlapped.raw() as *mut OVERLAPPED)
427 })
428 }
429 fn flush(&mut self) -> io::Result<()> {
430 <&NamedPipe as Write>::flush(&mut &*self)
431 }
432}
433impl<'a> Write for &'a NamedPipe {
434 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
435 // This is necessary because the pipe is opened with `FILE_FLAG_OVERLAPPED`.
436 with_threadlocal_overlapped(|overlapped| unsafe {
437 self.0
438 .write_overlapped_wait(buf, overlapped.raw() as *mut OVERLAPPED)
439 })
440 }
441 fn flush(&mut self) -> io::Result<()> {
442 crate::cvt(unsafe { FlushFileBuffers(self.0.raw()) }).map(|_| ())
443 }
444}
445
446impl AsRawHandle for NamedPipe {
447 fn as_raw_handle(&self) -> RawHandle {
448 self.0.raw() as RawHandle
449 }
450}
451impl FromRawHandle for NamedPipe {
452 unsafe fn from_raw_handle(handle: RawHandle) -> NamedPipe {
453 NamedPipe(Handle::new(handle as HANDLE))
454 }
455}
456impl IntoRawHandle for NamedPipe {
457 fn into_raw_handle(self) -> RawHandle {
458 self.0.into_raw() as RawHandle
459 }
460}
461
462fn flag(slot: &mut u32, on: bool, val: u32) {
463 if on {
464 *slot |= val;
465 } else {
466 *slot &= !val;
467 }
468}
469
470impl NamedPipeBuilder {
471 /// Creates a new named pipe builder with the default settings.
472 pub fn new<A: AsRef<OsStr>>(addr: A) -> NamedPipeBuilder {
473 NamedPipeBuilder {
474 name: addr.as_ref().encode_wide().chain(Some(0)).collect(),
475 dwOpenMode: PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
476 dwPipeMode: PIPE_TYPE_BYTE,
477 nMaxInstances: PIPE_UNLIMITED_INSTANCES,
478 nOutBufferSize: 65536,
479 nInBufferSize: 65536,
480 nDefaultTimeOut: 0,
481 }
482 }
483
484 /// Indicates whether data is allowed to flow from the client to the server.
485 pub fn inbound(&mut self, allowed: bool) -> &mut Self {
486 flag(&mut self.dwOpenMode, allowed, PIPE_ACCESS_INBOUND);
487 self
488 }
489
490 /// Indicates whether data is allowed to flow from the server to the client.
491 pub fn outbound(&mut self, allowed: bool) -> &mut Self {
492 flag(&mut self.dwOpenMode, allowed, PIPE_ACCESS_OUTBOUND);
493 self
494 }
495
496 /// Indicates that this pipe must be the first instance.
497 ///
498 /// If set to true, then creation will fail if there's already an instance
499 /// elsewhere.
500 pub fn first(&mut self, first: bool) -> &mut Self {
501 flag(&mut self.dwOpenMode, first, FILE_FLAG_FIRST_PIPE_INSTANCE);
502 self
503 }
504
505 /// Indicates whether this server can accept remote clients or not.
506 pub fn accept_remote(&mut self, accept: bool) -> &mut Self {
507 flag(&mut self.dwPipeMode, !accept, PIPE_REJECT_REMOTE_CLIENTS);
508 self
509 }
510
511 /// Specifies the maximum number of instances of the server pipe that are
512 /// allowed.
513 ///
514 /// The first instance of a pipe can specify this value. A value of 255
515 /// indicates that there is no limit to the number of instances.
516 pub fn max_instances(&mut self, instances: u8) -> &mut Self {
517 self.nMaxInstances = instances as u32;
518 self
519 }
520
521 /// Specifies the number of bytes to reserver for the output buffer
522 pub fn out_buffer_size(&mut self, buffer: u32) -> &mut Self {
523 self.nOutBufferSize = buffer as u32;
524 self
525 }
526
527 /// Specifies the number of bytes to reserver for the input buffer
528 pub fn in_buffer_size(&mut self, buffer: u32) -> &mut Self {
529 self.nInBufferSize = buffer as u32;
530 self
531 }
532
533 /// Using the options in this builder, attempt to create a new named pipe.
534 ///
535 /// This function will call the `CreateNamedPipe` function and return the
536 /// result.
537 pub fn create(&mut self) -> io::Result<NamedPipe> {
538 unsafe { self.with_security_attributes(::std::ptr::null_mut()) }
539 }
540
541 /// Using the options in the builder and the provided security attributes, attempt to create a
542 /// new named pipe. This function has to be called with a valid pointer to a
543 /// `SECURITY_ATTRIBUTES` struct that will stay valid for the lifetime of this function or a
544 /// null pointer.
545 ///
546 /// This function will call the `CreateNamedPipe` function and return the
547 /// result.
548 pub unsafe fn with_security_attributes(
549 &mut self,
550 attrs: *mut SECURITY_ATTRIBUTES,
551 ) -> io::Result<NamedPipe> {
552 let h = CreateNamedPipeW(
553 self.name.as_mut_ptr(),
554 self.dwOpenMode,
555 self.dwPipeMode,
556 self.nMaxInstances,
557 self.nOutBufferSize,
558 self.nInBufferSize,
559 self.nDefaultTimeOut,
560 attrs,
561 );
562
563 if h == INVALID_HANDLE_VALUE {
564 Err(io::Error::last_os_error())
565 } else {
566 Ok(NamedPipe(Handle::new(h)))
567 }
568 }
569}
570
571#[cfg(test)]
572mod tests {
573 use std::fs::{File, OpenOptions};
574 use std::io::prelude::*;
575 use std::sync::mpsc::channel;
576 use std::thread;
577 use std::time::Duration;
578
579 use rand::{distributions::Alphanumeric, thread_rng, Rng};
580
581 use super::{anonymous, NamedPipe, NamedPipeBuilder};
582 use crate::iocp::CompletionPort;
583 use crate::Overlapped;
584
585 fn name() -> String {
586 let name = thread_rng()
587 .sample_iter(Alphanumeric)
588 .take(30)
589 .map(char::from)
590 .collect::<String>();
591 format!(r"\\.\pipe\{}", name)
592 }
593
594 #[test]
595 fn anon() {
596 let (mut read, mut write) = t!(anonymous(256));
597 assert_eq!(t!(write.write(&[1, 2, 3])), 3);
598 let mut b = [0; 10];
599 assert_eq!(t!(read.read(&mut b)), 3);
600 assert_eq!(&b[..3], &[1, 2, 3]);
601 }
602
603 #[test]
604 fn named_not_first() {
605 let name = name();
606 let _a = t!(NamedPipe::new(&name));
607 assert!(NamedPipe::new(&name).is_err());
608
609 t!(NamedPipeBuilder::new(&name).first(false).create());
610 }
611
612 #[test]
613 fn named_connect() {
614 let name = name();
615 let a = t!(NamedPipe::new(&name));
616
617 let t = thread::spawn(move || {
618 t!(File::open(name));
619 });
620
621 t!(a.connect());
622 t!(a.disconnect());
623 t!(t.join());
624 }
625
626 #[test]
627 fn named_wait() {
628 let name = name();
629 let a = t!(NamedPipe::new(&name));
630
631 let (tx, rx) = channel();
632 let t = thread::spawn(move || {
633 t!(NamedPipe::wait(&name, None));
634 t!(File::open(&name));
635 assert!(NamedPipe::wait(&name, Some(Duration::from_millis(1))).is_err());
636 t!(tx.send(()));
637 });
638
639 t!(a.connect());
640 t!(rx.recv());
641 t!(a.disconnect());
642 t!(t.join());
643 }
644
645 #[test]
646 fn named_connect_overlapped() {
647 let name = name();
648 let a = t!(NamedPipe::new(&name));
649
650 let t = thread::spawn(move || {
651 t!(File::open(name));
652 });
653
654 let cp = t!(CompletionPort::new(1));
655 t!(cp.add_handle(2, &a));
656
657 let over = Overlapped::zero();
658 unsafe {
659 t!(a.connect_overlapped(over.raw()));
660 }
661
662 let status = t!(cp.get(None));
663 assert_eq!(status.bytes_transferred(), 0);
664 assert_eq!(status.token(), 2);
665 assert_eq!(status.overlapped(), over.raw());
666 t!(t.join());
667 }
668
669 #[test]
670 fn named_read_write() {
671 let name = name();
672 let mut a = t!(NamedPipe::new(&name));
673
674 let t = thread::spawn(move || {
675 let mut f = t!(OpenOptions::new().read(true).write(true).open(name));
676 t!(f.write_all(&[1, 2, 3]));
677 let mut b = [0; 10];
678 assert_eq!(t!(f.read(&mut b)), 3);
679 assert_eq!(&b[..3], &[1, 2, 3]);
680 });
681
682 t!(a.connect());
683 let mut b = [0; 10];
684 assert_eq!(t!(a.read(&mut b)), 3);
685 assert_eq!(&b[..3], &[1, 2, 3]);
686 t!(a.write_all(&[1, 2, 3]));
687 t!(a.flush());
688 t!(a.disconnect());
689 t!(t.join());
690 }
691
692 #[test]
693 fn named_read_write_multi() {
694 for _ in 0..5 {
695 named_read_write()
696 }
697 }
698
699 #[test]
700 fn named_read_write_multi_same_thread() {
701 let name1 = name();
702 let mut a1 = t!(NamedPipe::new(&name1));
703 let name2 = name();
704 let mut a2 = t!(NamedPipe::new(&name2));
705
706 let t = thread::spawn(move || {
707 let mut f = t!(OpenOptions::new().read(true).write(true).open(name1));
708 t!(f.write_all(&[1, 2, 3]));
709 let mut b = [0; 10];
710 assert_eq!(t!(f.read(&mut b)), 3);
711 assert_eq!(&b[..3], &[1, 2, 3]);
712
713 let mut f = t!(OpenOptions::new().read(true).write(true).open(name2));
714 t!(f.write_all(&[1, 2, 3]));
715 let mut b = [0; 10];
716 assert_eq!(t!(f.read(&mut b)), 3);
717 assert_eq!(&b[..3], &[1, 2, 3]);
718 });
719
720 t!(a1.connect());
721 let mut b = [0; 10];
722 assert_eq!(t!(a1.read(&mut b)), 3);
723 assert_eq!(&b[..3], &[1, 2, 3]);
724 t!(a1.write_all(&[1, 2, 3]));
725 t!(a1.flush());
726 t!(a1.disconnect());
727
728 t!(a2.connect());
729 let mut b = [0; 10];
730 assert_eq!(t!(a2.read(&mut b)), 3);
731 assert_eq!(&b[..3], &[1, 2, 3]);
732 t!(a2.write_all(&[1, 2, 3]));
733 t!(a2.flush());
734 t!(a2.disconnect());
735
736 t!(t.join());
737 }
738
739 #[test]
740 fn named_read_overlapped() {
741 let name = name();
742 let a = t!(NamedPipe::new(&name));
743
744 let t = thread::spawn(move || {
745 let mut f = t!(File::create(name));
746 t!(f.write_all(&[1, 2, 3]));
747 });
748
749 let cp = t!(CompletionPort::new(1));
750 t!(cp.add_handle(3, &a));
751 t!(a.connect());
752
753 let mut b = [0; 10];
754 let over = Overlapped::zero();
755 unsafe {
756 t!(a.read_overlapped(&mut b, over.raw()));
757 }
758 let status = t!(cp.get(None));
759 assert_eq!(status.bytes_transferred(), 3);
760 assert_eq!(status.token(), 3);
761 assert_eq!(status.overlapped(), over.raw());
762 assert_eq!(&b[..3], &[1, 2, 3]);
763
764 t!(t.join());
765 }
766
767 #[test]
768 fn named_write_overlapped() {
769 let name = name();
770 let a = t!(NamedPipe::new(&name));
771
772 let t = thread::spawn(move || {
773 let mut f = t!(super::connect(name));
774 let mut b = [0; 10];
775 assert_eq!(t!(f.read(&mut b)), 3);
776 assert_eq!(&b[..3], &[1, 2, 3])
777 });
778
779 let cp = t!(CompletionPort::new(1));
780 t!(cp.add_handle(3, &a));
781 t!(a.connect());
782
783 let over = Overlapped::zero();
784 unsafe {
785 t!(a.write_overlapped(&[1, 2, 3], over.raw()));
786 }
787
788 let status = t!(cp.get(None));
789 assert_eq!(status.bytes_transferred(), 3);
790 assert_eq!(status.token(), 3);
791 assert_eq!(status.overlapped(), over.raw());
792
793 t!(t.join());
794 }
795}