Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SPIPE_Acceptor.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // SPIPE_Acceptor.cpp
00003 // $Id: SPIPE_Acceptor.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $
00004 
00005 #include "ace/SPIPE_Acceptor.h"
00006 #include "ace/Log_Msg.h"
00007 
00008 ACE_RCSID(ace, SPIPE_Acceptor, "$Id: SPIPE_Acceptor.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $")
00009 
00010 ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (void)
00011 #if (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00012   : sa_ (0), pipe_handle_ (ACE_INVALID_HANDLE)
00013 #endif /* ACE_WIN32 */
00014 {
00015   ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor");
00016 }
00017 
00018 int
00019 ACE_SPIPE_Acceptor::remove (void)
00020 {
00021   ACE_TRACE ("ACE_SPIPE_Acceptor::remove");
00022 #if defined (ACE_HAS_STREAM_PIPES)
00023   int result = this->close ();
00024 
00025   // Remove the underlying file.
00026   return ACE_OS::unlink (this->local_addr_.get_path_name ()) == -1 
00027     || result == -1 ? -1 : 0;
00028 #else
00029   this->close ();
00030   return 0;
00031 #endif
00032 }
00033 
00034 ACE_ALLOC_HOOK_DEFINE (ACE_SPIPE_Acceptor)
00035 
00036 void
00037 ACE_SPIPE_Acceptor::dump (void) const
00038 {
00039   ACE_TRACE ("ACE_SPIPE_Acceptor::dump");
00040 }
00041 
00042 // General purpose routine for performing server ACE_SPIPE creation.
00043 
00044 int
00045 ACE_SPIPE_Acceptor::open (const ACE_SPIPE_Addr &local_sap, 
00046                           int reuse_addr,
00047                           int perms,
00048                           LPSECURITY_ATTRIBUTES sa,
00049                           int pipe_mode)
00050 {
00051   ACE_TRACE ("ACE_SPIPE_Acceptor::open");
00052   ACE_UNUSED_ARG (reuse_addr);
00053 
00054   this->local_addr_ = local_sap;
00055   this->set_handle (ACE_INVALID_HANDLE);
00056 #if (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00057   this->sa_ = sa;
00058   this->pipe_mode_ = pipe_mode;
00059 #else
00060   ACE_UNUSED_ARG (sa);
00061   ACE_UNUSED_ARG (pipe_mode);
00062 #endif /* ACE_WIN32 */
00063 
00064   return this->create_new_instance (perms);
00065 }
00066 
00067 int
00068 ACE_SPIPE_Acceptor::create_new_instance (int perms)
00069 {
00070 #if defined (ACE_HAS_STREAM_PIPES)
00071   ACE_HANDLE spipe[2];
00072   char module[] = "connld";
00073 
00074   ACE_HANDLE handle = ACE_OS::creat (this->local_addr_.get_path_name (),
00075                                      perms);
00076   if (handle == ACE_INVALID_HANDLE)
00077     return -1;
00078   else if (ACE_OS::close (handle) == -1)
00079     return -1;
00080   else if (ACE_OS::pipe (spipe) == -1)
00081     return -1;
00082   else if (ACE_OS::ioctl (spipe[0],
00083                           I_PUSH,
00084                           module) == -1)
00085     return -1;
00086   else if (ACE_OS::fattach (spipe[0],
00087                             this->local_addr_.get_path_name ()) == -1)
00088     return -1;
00089 
00090   this->set_handle (spipe[1]);
00091   return 0;
00092 
00093 #elif (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00094   // Create a new instance of the Named Pipe (WIN32).  A new instance
00095   // of the named pipe must be created for every client process.  If
00096   // an instance of the named pipe that is already connected to a
00097   // client process is reused with a new client process,
00098   // ::ConnectNamedPipe () would fail.
00099  
00100   ACE_UNUSED_ARG (perms);
00101   ACE_TRACE ("ACE_SPIPE_Acceptor::create_new_instance");
00102   int status;
00103 
00104   // Create a new instance of the named pipe
00105   this->pipe_handle_ =
00106 #if defined (ACE_USES_WCHAR)
00107     ::CreateNamedPipeW (
00108 #else /* ACE_USES_WCHAR */
00109     ::CreateNamedPipeA (
00110 #endif /* ACE_USES_WCHAR */
00111                         this->local_addr_.get_path_name (),
00112                         PIPE_ACCESS_DUPLEX
00113                         | FILE_FLAG_OVERLAPPED,
00114                         pipe_mode_,
00115                         PIPE_UNLIMITED_INSTANCES,
00116                         1024 * 10,
00117                         1024 * 10,
00118                         ACE_DEFAULT_TIMEOUT,
00119                         this->sa_);
00120 
00121   if (this->pipe_handle_ == ACE_INVALID_HANDLE)
00122     return -1;
00123   else
00124     {
00125       // Start the Connect (analogous to listen () for a socket).
00126       // Completion is noted by the event being signalled.  If a
00127       // client connects before this call, the error status will be
00128       // ERROR_PIPE_CONNECTED.  If the client also disconnects before
00129       // this call, the error status will be ERROR_NO_DATA.  In both
00130       // cases, that fact is remembered via already_connected_ and
00131       // noted when the user calls accept().  Else the error status
00132       // should be ERROR_IO_PENDING and the OS will signal the event
00133       // when it's done.
00134       this->already_connected_ = 0;
00135       this->set_handle (this->event_.handle ());
00136       this->overlapped_.hEvent = this->event_.handle ();
00137       this->event_.reset ();
00138 
00139       BOOL result = ::ConnectNamedPipe (this->pipe_handle_,
00140                                         &this->overlapped_);
00141       ACE_UNUSED_ARG (result);
00142       // ConnectNamePipe is suppose to always
00143       // "fail" when passed in overlapped i/o
00144       ACE_ASSERT (!result);
00145 
00146       status = ::GetLastError ();
00147       switch (status) 
00148         {
00149         case ERROR_IO_PENDING:
00150           break;
00151         case ERROR_PIPE_CONNECTED:
00152         case ERROR_NO_DATA:
00153           this->already_connected_ = 1;
00154           // Set the associated event as signaled so any reactors or
00155           // proactors waiting for this will respond.
00156           this->event_.signal ();
00157           break;
00158         default:
00159           ACE_ASSERT (FALSE);    // An undocumented error was returned.
00160           this->close ();        // Sets handle to ACE_INVALID_HANDLE.
00161           break;
00162         }
00163     }
00164   return this->get_handle () == ACE_INVALID_HANDLE ? -1 : 0;
00165 #else
00166   ACE_UNUSED_ARG (perms);
00167   ACE_NOTSUP_RETURN (-1);
00168 #endif /* ACE_HAS_STREAM_PIPES */
00169 }
00170 
00171 int
00172 ACE_SPIPE_Acceptor::close (void)
00173 {
00174   ACE_TRACE ("ACE_SPIPE_Acceptor::close");
00175 
00176 #if (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00177   // Substitute the pipe handle back in so it's closed properly.
00178   this->set_handle (this->pipe_handle_);
00179   this->pipe_handle_ = ACE_INVALID_HANDLE;
00180 #endif /* ACE_WIN32 */
00181 
00182   // This behavior is shared by UNIX and Win32...
00183   int result = this->ACE_SPIPE::close ();
00184   this->set_handle (ACE_INVALID_HANDLE);
00185 
00186 #if defined (ACE_HAS_STREAM_PIPES)
00187   ACE_OS::fdetach (this->local_addr_.get_path_name ());
00188 #endif /* ACE_HAS_STREAM_PIPES */
00189   return result;
00190 }
00191 
00192 ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor (const ACE_SPIPE_Addr &local_sap, 
00193                                         int reuse_addr,
00194                                         int perms,
00195                                         LPSECURITY_ATTRIBUTES sa,
00196                                         int pipe_mode)
00197 {
00198   ACE_TRACE ("ACE_SPIPE_Acceptor::ACE_SPIPE_Acceptor");
00199 
00200   if (this->open (local_sap, reuse_addr, perms, sa, pipe_mode) == -1)
00201     ACE_ERROR ((LM_ERROR,
00202                 ACE_LIB_TEXT ("%p\n"),
00203                 ACE_LIB_TEXT ("ACE_SPIPE_Acceptor")));
00204 }
00205 
00206 // General purpose routine for accepting new connections.
00207 
00208 int
00209 ACE_SPIPE_Acceptor::accept (ACE_SPIPE_Stream &new_io, 
00210                             ACE_SPIPE_Addr *remote_addr,
00211                             ACE_Time_Value *timeout, 
00212                             int restart,
00213                             int reset_new_handle)
00214 {
00215   ACE_TRACE ("ACE_SPIPE_Acceptor::accept");
00216   ACE_UNUSED_ARG (reset_new_handle);
00217 
00218 #if defined (ACE_HAS_STREAM_PIPES)
00219   strrecvfd r_handle;
00220 
00221   // Note that if THIS->MILLI_SECOND_DELAY == -1 we block on
00222   // ACE_OS::ioctl (). Otherwise, we will wait for the desired number
00223   // of milli seconds using ACE_OS::poll.
00224 
00225   if (timeout != 0 && 
00226       ACE::handle_timed_accept (this->get_handle (),
00227                                 timeout,
00228                                 restart) == -1)
00229     return -1;
00230   else if (ACE_OS::ioctl (this->get_handle (),
00231                           I_RECVFD,
00232                           &r_handle) == -1)
00233     return -1;
00234 
00235   new_io.set_handle (r_handle.fd);
00236   new_io.local_addr_ = this->local_addr_;
00237   new_io.remote_addr_.set_size (sizeof r_handle.gid + sizeof r_handle.uid);
00238   new_io.remote_addr_.group_id (r_handle.gid);
00239   new_io.remote_addr_.user_id (r_handle.uid);
00240 
00241   // This is for compatibility with ACE_SOCK_Acceptor and
00242   // ACE_TLI_Acceptor.
00243   if (remote_addr != 0)
00244     *remote_addr = new_io.remote_addr_;
00245 
00246   return 0;
00247 #elif (defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0))
00248   ACE_UNUSED_ARG (restart);
00249   ACE_UNUSED_ARG (remote_addr);
00250 
00251   // Check to see if we have a valid pipe
00252   if (this->pipe_handle_ == ACE_INVALID_HANDLE)
00253     return -1;
00254 
00255   // open () started the Connect in asynchronous mode.  Wait for the event
00256   // in the OVERLAPPED structure to be signalled, then grab the status.
00257   if (this->already_connected_ == 0)
00258     {
00259       if (timeout != 0)
00260         {
00261           ACE_Time_Value abstime (ACE_OS::gettimeofday () + *timeout);
00262           if (this->event_.wait (&abstime) == -1)
00263             return -1;
00264         }
00265       else
00266         if (this->event_.wait () == -1)
00267           return -1;
00268 
00269       // Should be here with the ConnectNamedPipe operation complete.
00270       // Steal the already_connected_ flag to record the results.
00271       DWORD unused;
00272       this->already_connected_ = ::GetOverlappedResult (this->pipe_handle_,
00273                                                         &this->overlapped_,
00274                                                         &unused,
00275                                                         FALSE);
00276     }
00277 
00278   if (this->already_connected_)
00279     {
00280       new_io.set_handle (this->pipe_handle_);
00281       this->pipe_handle_ = ACE_INVALID_HANDLE;
00282       new_io.local_addr_ = this->local_addr_;
00283 
00284       // Create a new instance of the pipe for the next connection.
00285       this->create_new_instance ();
00286       return 0;
00287     }
00288   return -1;
00289 #else
00290   ACE_UNUSED_ARG (restart);
00291   ACE_UNUSED_ARG (timeout);
00292   ACE_UNUSED_ARG (remote_addr);
00293   ACE_UNUSED_ARG (new_io);
00294   ACE_NOTSUP_RETURN (-1);
00295 #endif /* ACE_HAS_STREAM_PIPES */
00296 }

Generated on Mon Jun 16 11:21:22 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002