TLI_Acceptor.cpp

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

Generated on Thu Nov 9 09:42:08 2006 for ACE by doxygen 1.3.6