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

TLI_Acceptor.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // $Id: TLI_Acceptor.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $
00003 
00004 #include "ace/TLI_Acceptor.h"
00005 #include "ace/Log_Msg.h"
00006 #include "ace/ACE.h"
00007 
00008 ACE_RCSID(ace, TLI_Acceptor, "$Id: TLI_Acceptor.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $")
00009 
00010 #if defined (ACE_HAS_TLI)
00011 
00012 // Put the actual definitions of the ACE_TLI_Request and
00013 // ACE_TLI_Request_Queue classes here to hide them from clients...
00014 
00015 struct ACE_TLI_Request
00016 {
00017   struct t_call *callp_;
00018   ACE_HANDLE handle_;
00019   ACE_TLI_Request *next_;
00020 };
00021 
00022 class ACE_TLI_Request_Queue
00023 {
00024 public:
00025   ACE_TLI_Request_Queue (void);
00026 
00027   ACE_HANDLE open (ACE_HANDLE fd, int size);
00028   int close (void);
00029 
00030   int enqueue (const char device[], int restart, int rwflag);
00031   int dequeue (ACE_TLI_Request *&ptr);
00032   int remove (int sequence_number);
00033 
00034   int is_empty (void) const;
00035   int is_full (void) const;
00036 
00037   ACE_TLI_Request *alloc (void);
00038   void    free (ACE_TLI_Request *node);
00039 
00040   void dump (void) const;
00041   // Dump the state of an object.
00042 
00043   ACE_ALLOC_HOOK_DECLARE;
00044   // Declare the dynamic allocation hooks.
00045 
00046 private:
00047   ACE_HANDLE handle_;
00048   int size_;
00049   int current_count_;
00050   ACE_TLI_Request *base_;
00051   ACE_TLI_Request *tail_;
00052   ACE_TLI_Request *free_list_;
00053 };
00054 
00055 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Request_Queue)
00056 
00057 void
00058 ACE_TLI_Request_Queue::dump (void) const
00059 {
00060   ACE_TRACE ("ACE_TLI_Request_Queue::dump");
00061 }
00062 
00063 int
00064 ACE_TLI_Request_Queue::is_empty (void) const
00065 {
00066   ACE_TRACE ("ACE_TLI_Request_Queue::is_empty");
00067   return this->current_count_ == 0;
00068 }
00069 
00070 int
00071 ACE_TLI_Request_Queue::is_full (void) const
00072 {
00073   ACE_TRACE ("ACE_TLI_Request_Queue::is_full");
00074   return this->current_count_ + 1 == this->size_; // Add 1 for the dummy.
00075 }
00076 
00077 // Add a node to the free list stack.
00078 
00079 void
00080 ACE_TLI_Request_Queue::free (ACE_TLI_Request *node)
00081 {
00082   ACE_TRACE ("ACE_TLI_Request_Queue::free");
00083   node->next_ = this->free_list_;
00084   this->free_list_ = node;
00085 }
00086 
00087 // Remove a node from the free list stack.
00088 
00089 ACE_TLI_Request *
00090 ACE_TLI_Request_Queue::alloc (void)
00091 {
00092   ACE_TRACE ("ACE_TLI_Request_Queue::alloc");
00093   ACE_TLI_Request *temp = this->free_list_;
00094   this->free_list_ = this->free_list_->next_;
00095   return temp;
00096 }
00097 
00098 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor)
00099 
00100 void
00101 ACE_TLI_Acceptor::dump (void) const
00102 {
00103   ACE_TRACE ("ACE_TLI_Acceptor::dump");
00104 }
00105 
00106 ACE_TLI_Acceptor::ACE_TLI_Acceptor (void)
00107   : queue_ (0)
00108 {
00109   ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
00110 }
00111 
00112 int
00113 ACE_TLI_Request_Queue::dequeue (ACE_TLI_Request *&ptr)
00114 {
00115   ACE_TRACE ("ACE_TLI_Request_Queue::dequeue");
00116   ptr = this->tail_->next_;
00117   this->tail_->next_ = ptr->next_;
00118   this->current_count_--;
00119   return 0;
00120 }
00121 
00122 // This is hideous...
00123 
00124 static ACE_HANDLE
00125 open_new_endpoint (ACE_HANDLE listen_handle,
00126                    const char dev[],
00127                    struct t_call *callp,
00128                    int rwf,
00129                    ACE_Addr *remote_sap = 0)
00130 {
00131   ACE_TRACE ("open_new_endpoint");
00132 #if defined (ACE_PSOS)
00133   ACE_HANDLE fd = ACE_OS::t_open ((char *) dev,
00134                                   S_IRUSR | S_IWUSR,
00135                                   0);
00136 #else
00137   ACE_HANDLE fd = ACE_OS::t_open ((char *) dev,
00138                                   O_RDWR,
00139                                   0);
00140 #endif /* ACE_PSOS */
00141 
00142    struct t_bind req, *req_p = 0;
00143    if (remote_sap != 0)
00144      {
00145        req.qlen = 0;
00146        req.addr.buf = (char *) remote_sap->get_addr ();
00147        req.addr.len = remote_sap->get_size ();
00148        req.addr.maxlen = remote_sap->get_size ();
00149        req_p = &req;
00150      }
00151 
00152   if (fd == ACE_INVALID_HANDLE
00153       || ACE_OS::t_bind (fd, req_p, 0) == -1)
00154     fd = ACE_INVALID_HANDLE;
00155 #if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
00156   else if (rwf != 0 && ACE_OS::ioctl (fd,
00157                                       I_PUSH,
00158                                       ACE_const_cast (char *, "tirdwr"))
00159                                       == ACE_INVALID_HANDLE)
00160     fd = ACE_INVALID_HANDLE;
00161 #endif /* I_PUSH */
00162 
00163   if (fd == ACE_INVALID_HANDLE)
00164     ACE_OS::t_snddis (listen_handle,
00165                       callp);
00166   return fd;
00167 }
00168 
00169 // Close down the acceptor and release resources.
00170 
00171 int
00172 ACE_TLI_Request_Queue::close (void)
00173 {
00174   ACE_TRACE ("ACE_TLI_Request_Queue::close");
00175   int res = 0;
00176 
00177   for (int i = 0; i < this->size_; i++)
00178     {
00179       ACE_TLI_Request &item = this->base_[i];
00180 
00181       item.handle_ = ACE_INVALID_HANDLE;
00182       if (ACE_OS::t_free ((char *) item.callp_,
00183                           T_CALL) != 0)
00184         res = -1;
00185     }
00186 
00187   delete [] this->base_;
00188   this->base_ = 0;
00189   return res;
00190 }
00191 
00192 ACE_HANDLE
00193 ACE_TLI_Request_Queue::open (ACE_HANDLE f, int sz)
00194 {
00195   ACE_TRACE ("ACE_TLI_Request_Queue::open");
00196   this->handle_   = f;
00197   this->size_ = sz + 1; // Add one more for the dummy node.
00198 
00199   ACE_NEW_RETURN (this->base_,
00200                   ACE_TLI_Request[this->size_],
00201                   ACE_INVALID_HANDLE);
00202 
00203   // Initialize the ACE_Queue and the free list.
00204 
00205   for (int i = 0; i < this->size_; i++)
00206     {
00207       ACE_TLI_Request *item = &this->base_[i];
00208       this->free (item);
00209 
00210       item->handle_ = ACE_INVALID_HANDLE;
00211       item->callp_ = (t_call *) ACE_OS::t_alloc (this->handle_,
00212                                                  T_CALL,
00213                                                  T_ALL);
00214       if (item->callp_ == 0)
00215         return ACE_INVALID_HANDLE;
00216     }
00217 
00218   this->tail_ = this->alloc ();
00219   this->tail_->next_ = this->tail_;
00220   return 0;
00221 }
00222 
00223 ACE_TLI_Request_Queue::ACE_TLI_Request_Queue (void)
00224   : size_ (0),
00225     current_count_ (0),
00226     base_ (0),
00227     tail_ (0),
00228     free_list_ (0)
00229 {
00230   ACE_TRACE ("ACE_TLI_Request_Queue::ACE_TLI_Request_Queue");
00231 }
00232 
00233 // Listen for a new connection request and allocate appropriate data
00234 // structures when one arrives.
00235 
00236 int
00237 ACE_TLI_Request_Queue::enqueue (const char device[],
00238                                       int restart, int rwflag)
00239 {
00240   ACE_TRACE ("ACE_TLI_Request_Queue::enqueue");
00241   ACE_TLI_Request *temp = this->alloc ();
00242   ACE_TLI_Request &req  = *this->tail_;
00243   int res;
00244 
00245   do
00246     res = ACE_OS::t_listen (this->handle_, req.callp_);
00247   while (res == -1
00248          && restart
00249          && t_errno == TSYSERR
00250          && errno == EINTR);
00251 
00252   if (res != -1)
00253     {
00254       req.handle_ = open_new_endpoint (this->handle_,
00255                                        device,
00256                                        req.callp_,
00257                                        rwflag);
00258       if (req.handle_ != ACE_INVALID_HANDLE)
00259         {
00260           temp->next_ = this->tail_->next_;
00261           this->tail_->next_ = temp;
00262           this->tail_ = temp;
00263           this->current_count_++;
00264           return 0;
00265         }
00266     }
00267 
00268   // Something must have gone wrong, so free up allocated space.
00269   this->free (temp);
00270   return -1;
00271 }
00272 
00273 // Locate and remove SEQUENCE_NUMBER from the list of pending
00274 // connections.
00275 
00276 int
00277 ACE_TLI_Request_Queue::remove (int sequence_number)
00278 {
00279   ACE_TRACE ("ACE_TLI_Request_Queue::remove");
00280   ACE_TLI_Request *prev = this->tail_;
00281 
00282   // Put the sequence # in the dummy node to simply the search...
00283   prev->callp_->sequence = sequence_number;
00284 
00285   ACE_TLI_Request *temp;
00286 
00287   for (temp = this->tail_->next_;
00288        temp->callp_->sequence != sequence_number;
00289        temp = temp->next_)
00290     prev = temp;
00291 
00292   if (temp == this->tail_)
00293     // Sequence # was not found, since we're back at the dummy node!
00294     return -1;
00295   else
00296     {
00297       prev->next_ = temp->next_;
00298       ACE_OS::t_close (temp->handle_);
00299       this->current_count_--;
00300       this->free (temp);
00301       return 0;
00302     }
00303 }
00304 
00305 ACE_HANDLE
00306 ACE_TLI_Acceptor::open (const ACE_Addr &remote_sap,
00307                         int reuse_addr,
00308                         int oflag,
00309                         struct t_info *info,
00310                         int qlen,
00311                         const char dev[])
00312 {
00313   ACE_TRACE ("ACE_TLI_Acceptor::open");
00314   ACE_HANDLE res = 0;
00315   int one = 1;
00316 
00317   this->disp_ = 0;
00318 
00319   ACE_ALLOCATOR_RETURN (this->device_,
00320                         ACE_OS::strdup (dev),
00321                         ACE_INVALID_HANDLE);
00322   if (this->ACE_TLI::open (dev,
00323                            oflag,
00324                            info) == ACE_INVALID_HANDLE)
00325     res = ACE_INVALID_HANDLE;
00326 #if !defined (ACE_HAS_FORE_ATM_XTI)
00327   // Reusing the address causes problems with FORE's API. The issue
00328   // may be that t_optmgmt isn't fully supported by FORE. t_errno is
00329   // TBADOPT after the t_optmgmt call so maybe options are configured
00330   // differently for XTI than for TLI (at least for FORE's
00331   // implementation - XTI is supposed to be a superset of TLI).
00332   else if (reuse_addr
00333            && this->set_option (SOL_SOCKET,
00334                                 SO_REUSEADDR,
00335                                 &one,
00336                                 sizeof one) == -1)
00337     res = ACE_INVALID_HANDLE;
00338 #endif /* ACE_HAS_FORE_ATM_XTI */
00339   else if ((this->disp_ =
00340             (struct t_discon *) ACE_OS::t_alloc (this->get_handle (),
00341                                                  T_DIS,
00342                                                  T_ALL)) == 0)
00343     res = ACE_INVALID_HANDLE;
00344   else
00345     {
00346       struct t_bind req;
00347 
00348 #if defined (ACE_HAS_FORE_ATM_XTI)
00349       // Not sure why but FORE's t_bind call won't work if t_bind.qlen
00350       // != 1 Adjust the backlog accordingly.
00351       this->backlog_ = 1;
00352       req.qlen = 1;
00353 #else
00354       this->backlog_ = qlen;
00355       req.qlen = qlen;
00356 #endif /* ACE_HAS_FORE_ATM_XTI */
00357       req.addr.maxlen = remote_sap.get_size ();
00358 
00359       if (remote_sap == ACE_Addr::sap_any)
00360         // Note that if addr.len == 0 then ACE_TLI selects the port
00361         // number.
00362         req.addr.len = 0;
00363       else
00364         {
00365           req.addr.buf = (char *) remote_sap.get_addr ();
00366           req.addr.len = remote_sap.get_size ();
00367         }
00368 
00369       res = (ACE_HANDLE) ACE_OS::t_bind (this->get_handle (),
00370                                          &req,
00371                                          0);
00372       if (res != ACE_INVALID_HANDLE)
00373         {
00374           ACE_NEW_RETURN (this->queue_,
00375                           ACE_TLI_Request_Queue,
00376                           ACE_INVALID_HANDLE);
00377           res = this->queue_->open (this->get_handle (),
00378                                     this->backlog_);
00379         }
00380     }
00381   if (res == ACE_INVALID_HANDLE)
00382     this->close ();
00383   return this->get_handle ();
00384 }
00385 
00386 ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr &remote_sap,
00387                                     int reuse_addr,
00388                                     int oflag,
00389                                     struct t_info *info,
00390                                     int back,
00391                                     const char dev[])
00392 {
00393   ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
00394   if (this->open (remote_sap,
00395                   reuse_addr,
00396                   oflag,
00397                   info,
00398                   back,
00399                   dev) == ACE_INVALID_HANDLE)
00400     ACE_ERROR ((LM_ERROR,
00401                 ACE_LIB_TEXT ("%p\n"),
00402                 ACE_LIB_TEXT ("ACE_TLI_Acceptor::ACE_TLI_Acceptor")));
00403 }
00404 
00405 int
00406 ACE_TLI_Acceptor::close (void)
00407 {
00408   ACE_TRACE ("ACE_TLI_Acceptor::close");
00409   if (this->device_ != 0)
00410     {
00411       if (this->queue_ != 0)
00412         {
00413           this->queue_->close ();
00414           delete this->queue_;
00415         }
00416 
00417       ACE_OS::t_free ((char *) this->disp_, T_DIS);
00418       ACE_OS::free (ACE_MALLOC_T (this->device_));
00419       this->disp_ = 0;
00420       this->device_ = 0;
00421       return this->ACE_TLI::close ();
00422     }
00423   return 0;
00424 }
00425 
00426 // Perform the logic required to handle the arrival of asynchronous
00427 // events while we are trying to accept a new connection request.
00428 
00429 int
00430 ACE_TLI_Acceptor::handle_async_event (int restart, int rwf)
00431 {
00432   ACE_TRACE ("ACE_TLI_Acceptor::handle_async_event");
00433   int event = this->look ();
00434 
00435   switch (event)
00436     {
00437     case T_DISCONNECT:
00438       this->rcvdis (this->disp_);
00439       this->queue_->remove (this->disp_->sequence);
00440       break;
00441     case T_LISTEN:
00442       this->queue_->enqueue (this->device_,
00443                              restart,
00444                              rwf);
00445       break;
00446     default:
00447       return -1;
00448     }
00449   return 0;
00450 }
00451 
00452 int
00453 ACE_TLI_Acceptor::accept (ACE_TLI_Stream &new_tli_sap,
00454                           ACE_Addr *remote_addr,
00455                           ACE_Time_Value *timeout,
00456                           int restart,
00457                           int reset_new_handle,
00458                           int rwf,
00459                           netbuf *udata,
00460                           netbuf *opt)
00461 {
00462   ACE_TRACE ("ACE_TLI_Acceptor::accept");
00463   ACE_UNUSED_ARG (reset_new_handle);
00464 
00465   ACE_TLI_Request *req = 0;
00466   int res = 0;
00467   if (timeout != 0
00468       && ACE::handle_timed_accept (this->get_handle (),
00469                                    timeout,
00470                                    restart) == -1)
00471     return -1;
00472   else if (this->queue_->is_empty ())
00473     {
00474       req = this->queue_->alloc ();
00475 
00476       do
00477         res = ACE_OS::t_listen (this->get_handle (),
00478                                     req->callp_);
00479       while (res == -1
00480              && restart
00481              && errno == EINTR);
00482 
00483       if (res != -1)
00484       {
00485         req->handle_ = open_new_endpoint (this->get_handle (),
00486                                           this->device_,
00487                                           req->callp_,
00488                                           rwf
00489 #if defined (ACE_WIN32)
00490                                           , remote_addr
00491 #endif /* ACE_WIN32 */
00492                                           );
00493         if (req->handle_ == ACE_INVALID_HANDLE)
00494           res = -1;
00495         else
00496           res = 0;
00497       }
00498     }
00499   else
00500     res = this->queue_->dequeue (req);
00501 
00502   if (udata != 0)
00503     ACE_OS::memcpy ((void *) &req->callp_->udata,
00504                     (void *) udata,
00505                     sizeof *udata);
00506   if (opt != 0)
00507     ACE_OS::memcpy ((void *) &req->callp_->opt,
00508                     (void *) opt,
00509                     sizeof *opt);
00510 
00511   while (res != -1)
00512     {
00513       res = ACE_OS::t_accept (this->get_handle (),
00514                               req->handle_,
00515                               req->callp_);
00516       if (res != -1)
00517         break; // Got one!
00518       else if (t_errno == TLOOK)
00519         res = this->handle_async_event (restart, rwf);
00520       else if (restart && t_errno == TSYSERR && errno == EINTR)
00521         res = 0;
00522     }
00523 
00524   if (res == -1)
00525     {
00526       if (errno != EWOULDBLOCK)
00527         {
00528           new_tli_sap.set_handle (ACE_INVALID_HANDLE);
00529           if (req->handle_ != ACE_INVALID_HANDLE)
00530             ACE_OS::t_close (req->handle_);
00531         }
00532     }
00533   else
00534     {
00535       new_tli_sap.set_handle (req->handle_);
00536 
00537       if (remote_addr != 0)
00538         remote_addr->set_addr ((void *) req->callp_->addr.buf,
00539                                req->callp_->addr.len);
00540     }
00541 
00542   req->handle_ = ACE_INVALID_HANDLE;
00543   this->queue_->free (req);
00544   new_tli_sap.set_rwflag (rwf);
00545   return new_tli_sap.get_handle () == ACE_INVALID_HANDLE ? -1 : 0;
00546 }
00547 
00548 #endif /* ACE_HAS_TLI */

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