Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ace / SPIPE_Acceptor.cpp
blobc65f5d89f5c00612235ad700756ee4d4a8a6741b
1 #include "ace/SPIPE_Acceptor.h"
2 #include "ace/Log_Category.h"
3 #include "ace/OS_NS_sys_stat.h"
4 #include "ace/OS_NS_sys_time.h"
5 #if defined (ACE_HAS_ALLOC_HOOKS)
6 # include "ace/Malloc_Base.h"
7 #endif /* ACE_HAS_ALLOC_HOOKS */
9 #if defined (ACE_HAS_STREAM_PIPES)
10 # include "ace/OS_NS_unistd.h"
11 #endif // ACE_HAS_STREAM_PIPES
14 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
16 ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor ()
17 #if defined (ACE_HAS_WIN32_NAMED_PIPES)
18 : sa_ (0), pipe_handle_ (ACE_INVALID_HANDLE)
19 #endif /* ACE_HAS_WIN32_NAMED_PIPES */
21 ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor");
24 int
25 ACE_SPIPE_Acceptor::remove ()
27 ACE_TRACE ("ACE_SPIPE_Acceptor::remove");
28 #if defined (ACE_HAS_STREAM_PIPES)
29 int result = this->close ();
31 // Remove the underlying file.
32 return ACE_OS::unlink (this->local_addr_.get_path_name ()) == -1
33 || result == -1 ? -1 : 0;
34 #else
35 this->close ();
36 return 0;
37 #endif
40 ACE_ALLOC_HOOK_DEFINE (ACE_SPIPE_Acceptor)
42 void
43 ACE_SPIPE_Acceptor::dump () const
45 #if defined (ACE_HAS_DUMP)
46 ACE_TRACE ("ACE_SPIPE_Acceptor::dump");
47 #endif /* ACE_HAS_DUMP */
50 // General purpose routine for performing server ACE_SPIPE creation.
52 int
53 ACE_SPIPE_Acceptor::open (const ACE_SPIPE_Addr &local_sap,
54 int reuse_addr,
55 int perms,
56 LPSECURITY_ATTRIBUTES sa,
57 int pipe_mode)
59 ACE_TRACE ("ACE_SPIPE_Acceptor::open");
60 ACE_UNUSED_ARG (reuse_addr);
62 this->local_addr_ = local_sap;
63 this->set_handle (ACE_INVALID_HANDLE);
64 #if defined (ACE_HAS_WIN32_NAMED_PIPES)
65 this->sa_ = sa;
66 this->pipe_mode_ = pipe_mode;
67 #else
68 ACE_UNUSED_ARG (sa);
69 ACE_UNUSED_ARG (pipe_mode);
70 #endif /* ACE_HAS_WIN32_NAMED_PIPES */
72 return this->create_new_instance (perms);
75 int
76 ACE_SPIPE_Acceptor::create_new_instance (int perms)
78 #if defined (ACE_HAS_STREAM_PIPES)
79 ACE_HANDLE spipe[2];
80 char module[] = "connld";
82 ACE_HANDLE handle = ACE_OS::creat (this->local_addr_.get_path_name (),
83 perms);
84 if (handle == ACE_INVALID_HANDLE)
85 return -1;
86 else if (ACE_OS::close (handle) == -1)
87 return -1;
88 else if (ACE_OS::pipe (spipe) == -1)
89 return -1;
90 else if (ACE_OS::ioctl (spipe[0],
91 I_PUSH,
92 module) == -1)
93 return -1;
94 else if (-1 == ACE_OS::fattach(spipe[0],
95 ACE_TEXT_ALWAYS_CHAR (
96 this->local_addr_.get_path_name ())))
97 return -1;
99 this->set_duplex_handle (spipe[0]);
100 this->set_handle (spipe[1]);
101 return 0;
103 #elif defined (ACE_HAS_WIN32_NAMED_PIPES)
104 // Create a new instance of the Named Pipe (WIN32). A new instance
105 // of the named pipe must be created for every client process. If
106 // an instance of the named pipe that is already connected to a
107 // client process is reused with a new client process,
108 // ::ConnectNamedPipe () would fail.
110 ACE_UNUSED_ARG (perms);
111 ACE_TRACE ("ACE_SPIPE_Acceptor::create_new_instance");
112 int status;
114 // Create a new instance of the named pipe
115 this->pipe_handle_ =
116 #if defined (ACE_USES_WCHAR)
117 ::CreateNamedPipeW (
118 #else /* ACE_USES_WCHAR */
119 ::CreateNamedPipeA (
120 #endif /* ACE_USES_WCHAR */
121 this->local_addr_.get_path_name (),
122 PIPE_ACCESS_DUPLEX
123 | FILE_FLAG_OVERLAPPED,
124 pipe_mode_,
125 PIPE_UNLIMITED_INSTANCES,
126 1024 * 10,
127 1024 * 10,
128 ACE_DEFAULT_TIMEOUT,
129 this->sa_);
131 if (this->pipe_handle_ == ACE_INVALID_HANDLE)
132 return -1;
133 else
135 // Start the Connect (analogous to listen () for a socket).
136 // Completion is noted by the event being signalled. If a
137 // client connects before this call, the error status will be
138 // ERROR_PIPE_CONNECTED. If the client also disconnects before
139 // this call, the error status will be ERROR_NO_DATA. In both
140 // cases, that fact is remembered via already_connected_ and
141 // noted when the user calls accept(). Else the error status
142 // should be ERROR_IO_PENDING and the OS will signal the event
143 // when it's done.
144 this->already_connected_ = 0;
145 this->set_handle (this->event_.handle ());
146 this->overlapped_.hEvent = this->event_.handle ();
147 this->event_.reset ();
149 BOOL result = ::ConnectNamedPipe (this->pipe_handle_,
150 &this->overlapped_);
151 ACE_UNUSED_ARG (result);
152 // ConnectNamePipe is suppose to always
153 // "fail" when passed in overlapped i/o
154 ACE_ASSERT (!result);
156 status = ::GetLastError ();
157 switch (status)
159 case ERROR_IO_PENDING:
160 break;
161 case ERROR_PIPE_CONNECTED:
162 case ERROR_NO_DATA:
163 this->already_connected_ = 1;
164 // Set the associated event as signaled so any reactors or
165 // proactors waiting for this will respond.
166 this->event_.signal ();
167 break;
168 default:
169 ACE_ASSERT (FALSE); // An undocumented error was returned.
170 this->close (); // Sets handle to ACE_INVALID_HANDLE.
171 break;
174 return this->get_handle () == ACE_INVALID_HANDLE ? -1 : 0;
175 #else
176 ACE_UNUSED_ARG (perms);
177 ACE_NOTSUP_RETURN (-1);
178 #endif /* ACE_HAS_STREAM_PIPES */
182 ACE_SPIPE_Acceptor::close ()
184 ACE_TRACE ("ACE_SPIPE_Acceptor::close");
186 #if defined (ACE_HAS_WIN32_NAMED_PIPES)
188 // Check to see if we have a valid pipe; if not, nothing to do.
189 if (this->pipe_handle_ == ACE_INVALID_HANDLE)
190 return -1;
192 // Substitute the pipe handle back in so it's closed properly in the
193 // ACE_OS wrapper. But leave the pipe_handle_ value so we can clean up the
194 // hanging overlapped operation afterwards.
195 this->set_handle (this->pipe_handle_);
197 #endif /* ACE_HAS_WIN32_NAMED_PIPES */
199 // This behavior is shared by UNIX and Win32...
200 int result = this->ACE_SPIPE::close ();
201 this->set_handle (ACE_INVALID_HANDLE);
203 #if defined (ACE_HAS_STREAM_PIPES)
204 ACE_OS::fdetach (ACE_TEXT_ALWAYS_CHAR (this->local_addr_.get_path_name ()));
205 #elif defined (ACE_HAS_WIN32_NAMED_PIPES)
207 // open () started the Connect in asynchronous mode, and accept() restarts
208 // the ConnectNamedPipe in overlapped mode. To avoid leaving a hanging
209 // overlapped operation that'll write into members of this object,
210 // wait for the event in the OVERLAPPED structure to be signalled.
211 if (this->already_connected_ == 0)
213 if (this->event_.wait () != -1)
215 // Should be here with the ConnectNamedPipe operation complete.
216 // Steal the already_connected_ flag to record the results.
217 DWORD unused;
218 ::GetOverlappedResult (this->pipe_handle_,
219 &this->overlapped_,
220 &unused,
221 FALSE);
223 this->pipe_handle_ = ACE_INVALID_HANDLE;
224 this->already_connected_ = 0;
226 #endif /* ACE_HAS_STREAM_PIPES */
228 return result;
231 ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (const ACE_SPIPE_Addr &local_sap,
232 int reuse_addr,
233 int perms,
234 LPSECURITY_ATTRIBUTES sa,
235 int pipe_mode)
237 ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor");
239 if (this->open (local_sap, reuse_addr, perms, sa, pipe_mode) == -1)
240 ACELIB_ERROR ((LM_ERROR,
241 ACE_TEXT ("%p\n"),
242 ACE_TEXT ("ACE_SPIPE_Acceptor")));
245 // General purpose routine for accepting new connections.
248 ACE_SPIPE_Acceptor::accept (ACE_SPIPE_Stream &new_io,
249 ACE_SPIPE_Addr *remote_addr,
250 ACE_Time_Value *timeout,
251 bool restart,
252 bool reset_new_handle)
254 ACE_TRACE ("ACE_SPIPE_Acceptor::accept");
255 ACE_UNUSED_ARG (reset_new_handle);
257 #if defined (ACE_HAS_STREAM_PIPES)
258 strrecvfd r_handle;
260 // Note that if THIS->MILLI_SECOND_DELAY == -1 we block on
261 // ACE_OS::ioctl (). Otherwise, we will wait for the desired number
262 // of milli seconds using ACE_OS::poll.
264 if (timeout != 0 &&
265 ACE::handle_timed_accept (this->get_handle (),
266 timeout,
267 restart) == -1)
268 return -1;
269 else if (ACE_OS::ioctl (this->get_handle (),
270 I_RECVFD,
271 &r_handle) == -1)
272 return -1;
274 new_io.set_handle (r_handle.fd);
275 new_io.local_addr_ = this->local_addr_;
276 new_io.remote_addr_.set_size (sizeof r_handle.gid + sizeof r_handle.uid);
277 new_io.remote_addr_.group_id (r_handle.gid);
278 new_io.remote_addr_.user_id (r_handle.uid);
280 // This is for compatibility with ACE_SOCK_Acceptor and
281 // ACE_TLI_Acceptor.
282 if (remote_addr != 0)
283 *remote_addr = new_io.remote_addr_;
285 return 0;
286 #elif defined (ACE_HAS_WIN32_NAMED_PIPES)
287 ACE_UNUSED_ARG (restart);
288 ACE_UNUSED_ARG (remote_addr);
290 // Check to see if we have a valid pipe
291 if (this->pipe_handle_ == ACE_INVALID_HANDLE)
292 return -1;
294 // open () started the Connect in asynchronous mode. Wait for the event
295 // in the OVERLAPPED structure to be signalled, then grab the status.
296 if (this->already_connected_ == 0)
298 if (timeout != 0)
300 ACE_Time_Value abstime (ACE_OS::gettimeofday () + *timeout);
301 if (this->event_.wait (&abstime) == -1)
302 return -1;
304 else
305 if (this->event_.wait () == -1)
306 return -1;
308 // Should be here with the ConnectNamedPipe operation complete.
309 // Steal the already_connected_ flag to record the results.
310 DWORD unused;
311 this->already_connected_ = ::GetOverlappedResult (this->pipe_handle_,
312 &this->overlapped_,
313 &unused,
314 FALSE);
317 if (this->already_connected_)
319 new_io.set_handle (this->pipe_handle_);
320 this->pipe_handle_ = ACE_INVALID_HANDLE;
321 new_io.local_addr_ = this->local_addr_;
323 // Create a new instance of the pipe for the next connection.
324 this->create_new_instance ();
325 return 0;
327 return -1;
328 #else
329 ACE_UNUSED_ARG (restart);
330 ACE_UNUSED_ARG (timeout);
331 ACE_UNUSED_ARG (remote_addr);
332 ACE_UNUSED_ARG (new_io);
333 ACE_NOTSUP_RETURN (-1);
334 #endif /* ACE_HAS_STREAM_PIPES */
337 ACE_END_VERSIONED_NAMESPACE_DECL