3 Copyright 2001, 2002, 2003, 2004, 2009, 2012, 2014 Red Hat Inc.
5 Written by Robert Collins <rbtcollins@hotmail.com>
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
13 /* to allow this to link into cygwin and the .dll, a little magic is needed. */
14 #ifdef __OUTSIDE_CYGWIN__
21 #include <sys/types.h>
28 #include <sys/cygwin.h>
31 #include "transport.h"
32 #include "transport_pipes.h"
34 #ifndef __INSIDE_CYGWIN__
35 #include "cygserver.h"
36 #include "cygserver_ipc.h"
41 #ifdef __INSIDE_CYGWIN__
42 #define SET_ERRNO(err) set_errno (err)
44 #define SET_ERRNO(err) errno = (err)
49 MAX_WAIT_NAMED_PIPE_RETRY
= 64,
50 WAIT_NAMED_PIPE_TIMEOUT
= 10 // milliseconds
53 #ifndef __INSIDE_CYGWIN__
55 transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe
)
57 _is_accepted_endpoint (true),
58 _is_listening_endpoint (false)
61 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
62 _pipe_name
[0] = L
'\0';
65 #endif /* !__INSIDE_CYGWIN__ */
67 transport_layer_pipes::transport_layer_pipes ()
69 _is_accepted_endpoint (false),
70 _is_listening_endpoint (false)
72 wchar_t cyg_instkey
[18];
74 wchar_t *p
= wcpcpy (_pipe_name
, PIPE_NAME_PREFIX
);
75 if (!cygwin_internal (CW_GET_INSTKEY
, cyg_instkey
))
76 wcpcpy (wcpcpy (p
, cyg_instkey
), PIPE_NAME_SUFFIX
);
79 transport_layer_pipes::~transport_layer_pipes ()
84 #ifndef __INSIDE_CYGWIN__
86 static HANDLE listen_pipe
;
87 static HANDLE connect_pipe
;
90 transport_layer_pipes::listen ()
93 assert (!_is_accepted_endpoint
);
94 assert (!_is_listening_endpoint
);
96 _is_listening_endpoint
= true;
98 debug ("Try to create named pipe: %ls", _pipe_name
);
100 /* We have to create the first instance of the listening pipe here, and
101 we also have to create at least one instance of the client side to avoid
103 See https://cygwin.com/ml/cygwin/2012-11/threads.html#00144 */
105 CreateNamedPipeW (_pipe_name
,
106 PIPE_ACCESS_DUPLEX
| FILE_FLAG_FIRST_PIPE_INSTANCE
,
107 PIPE_TYPE_BYTE
| PIPE_WAIT
, PIPE_UNLIMITED_INSTANCES
,
108 0, 0, 1000, &sec_all_nih
);
109 if (listen_pipe
!= INVALID_HANDLE_VALUE
)
111 connect_pipe
= CreateFileW (_pipe_name
, GENERIC_READ
| GENERIC_WRITE
, 0,
112 &sec_all_nih
, OPEN_EXISTING
, 0, NULL
);
113 if (connect_pipe
== INVALID_HANDLE_VALUE
)
115 CloseHandle (listen_pipe
);
116 listen_pipe
= INVALID_HANDLE_VALUE
;
120 if (listen_pipe
== INVALID_HANDLE_VALUE
)
122 system_printf ("failed to create named pipe: "
123 "is the daemon already running?");
130 class transport_layer_pipes
*
131 transport_layer_pipes::accept (bool *const recoverable
)
134 assert (!_is_accepted_endpoint
);
135 assert (_is_listening_endpoint
);
137 debug ("Try to create named pipe instance: %ls", _pipe_name
);
139 const HANDLE accept_pipe
=
140 CreateNamedPipeW (_pipe_name
, PIPE_ACCESS_DUPLEX
,
141 PIPE_TYPE_BYTE
| PIPE_WAIT
, PIPE_UNLIMITED_INSTANCES
,
142 0, 0, 1000, &sec_all_nih
);
144 if (accept_pipe
== INVALID_HANDLE_VALUE
)
146 debug_printf ("error creating pipe (%u).", GetLastError ());
147 *recoverable
= true; // FIXME: case analysis?
151 if (!ConnectNamedPipe (accept_pipe
, NULL
)
152 && GetLastError () != ERROR_PIPE_CONNECTED
)
154 debug_printf ("error connecting to pipe (%u)", GetLastError ());
155 (void) CloseHandle (accept_pipe
);
156 *recoverable
= true; // FIXME: case analysis?
160 return new transport_layer_pipes (accept_pipe
);
163 #endif /* !__INSIDE_CYGWIN__ */
166 transport_layer_pipes::close ()
168 // verbose: debug_printf ("closing pipe %p", _hPipe);
172 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
174 #ifndef __INSIDE_CYGWIN__
176 if (_is_accepted_endpoint
)
178 (void) FlushFileBuffers (_hPipe
); // Blocks until client reads.
179 (void) DisconnectNamedPipe (_hPipe
);
180 (void) CloseHandle (_hPipe
);
183 (void) CloseHandle (_hPipe
);
185 #else /* __INSIDE_CYGWIN__ */
187 assert (!_is_accepted_endpoint
);
188 (void) ForceCloseHandle (_hPipe
);
190 #endif /* __INSIDE_CYGWIN__ */
197 transport_layer_pipes::read (void *const buf
, const size_t len
)
199 // verbose: debug_printf ("reading from pipe %p", _hPipe);
202 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
203 assert (!_is_listening_endpoint
);
206 if (!ReadFile (_hPipe
, buf
, len
, &count
, NULL
))
208 debug_printf ("error reading from pipe (%u)", GetLastError ());
209 SET_ERRNO (EINVAL
); // FIXME?
217 transport_layer_pipes::write (void *const buf
, const size_t len
)
219 // verbose: debug_printf ("writing to pipe %p", _hPipe);
222 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
223 assert (!_is_listening_endpoint
);
226 if (!WriteFile (_hPipe
, buf
, len
, &count
, NULL
))
228 debug_printf ("error writing to pipe, error = %u", GetLastError ());
229 SET_ERRNO (EINVAL
); // FIXME?
237 * This routine holds a static variable, assume_cygserver, that is set
238 * if the transport has good reason to think that cygserver is
239 * running, i.e. if if successfully connected to it with the previous
240 * attempt. If this is set, the code tries a lot harder to get a
241 * connection, making the assumption that any failures are just
242 * congestion and overloading problems.
246 transport_layer_pipes::connect ()
249 assert (!_is_accepted_endpoint
);
250 assert (!_is_listening_endpoint
);
252 static bool assume_cygserver
= false;
257 debug_printf ("Try to connect to named pipe: %W", _pipe_name
);
260 _hPipe
= CreateFileW (_pipe_name
,
261 GENERIC_READ
| GENERIC_WRITE
,
262 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
265 SECURITY_IMPERSONATION
,
268 if (_hPipe
!= INVALID_HANDLE_VALUE
)
271 #ifdef __INSIDE_CYGWIN__
272 ProtectHandle (_hPipe
);
274 assume_cygserver
= true;
280 if (!assume_cygserver
&& GetLastError () != ERROR_PIPE_BUSY
)
282 debug_printf ("Error opening the pipe (%u)", GetLastError ());
286 /* Note: `If no instances of the specified named pipe exist, the
287 * WaitNamedPipe function returns immediately, regardless of the
288 * time-out value.' Thus the explicit Sleep if the call fails
289 * with ERROR_FILE_NOT_FOUND.
291 while (retries
!= MAX_WAIT_NAMED_PIPE_RETRY
292 && !(rc
= WaitNamedPipeW (_pipe_name
, WAIT_NAMED_PIPE_TIMEOUT
)))
294 if (GetLastError () == ERROR_FILE_NOT_FOUND
)
295 Sleep (0); // Give the server a chance.
301 assert (retries
== MAX_WAIT_NAMED_PIPE_RETRY
);
303 system_printf ("lost connection to cygserver, error = %u",
306 assume_cygserver
= false;
311 #ifndef __INSIDE_CYGWIN__
314 transport_layer_pipes::impersonate_client ()
317 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
318 assert (_is_accepted_endpoint
);
320 if (_hPipe
&& !ImpersonateNamedPipeClient (_hPipe
))
322 debug_printf ("Failed to Impersonate client, (%u)", GetLastError ());
330 transport_layer_pipes::revert_to_self ()
332 assert (_is_accepted_endpoint
);
334 if (!RevertToSelf ())
336 debug_printf ("Failed to RevertToSelf, (%u)", GetLastError ());
342 #endif /* !__INSIDE_CYGWIN__ */