From 99aa8c60282c7b8072eb35eb9ac815702f5bf586 Mon Sep 17 00:00:00 2001 From: "William R. Otte" Date: Tue, 4 Mar 2008 14:51:23 +0000 Subject: undoing accidental deletion --- ACE/ace/TLI_Acceptor.cpp | 553 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 553 insertions(+) create mode 100644 ACE/ace/TLI_Acceptor.cpp (limited to 'ACE/ace/TLI_Acceptor.cpp') diff --git a/ACE/ace/TLI_Acceptor.cpp b/ACE/ace/TLI_Acceptor.cpp new file mode 100644 index 00000000000..b6820c5db4e --- /dev/null +++ b/ACE/ace/TLI_Acceptor.cpp @@ -0,0 +1,553 @@ +// $Id$ + +#include "ace/TLI_Acceptor.h" +#include "ace/Log_Msg.h" +#include "ace/ACE.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_Memory.h" + +ACE_RCSID(ace, TLI_Acceptor, "$Id$") + +#if defined (ACE_HAS_TLI) + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// Put the actual definitions of the ACE_TLI_Request and +// ACE_TLI_Request_Queue classes here to hide them from clients... + +struct ACE_TLI_Request +{ + struct t_call *callp_; + ACE_HANDLE handle_; + ACE_TLI_Request *next_; +}; + +class ACE_TLI_Request_Queue +{ +public: + ACE_TLI_Request_Queue (void); + + ACE_HANDLE open (ACE_HANDLE fd, int size); + int close (void); + + int enqueue (const char device[], int restart, int rwflag); + int dequeue (ACE_TLI_Request *&ptr); + int remove (int sequence_number); + + int is_empty (void) const; + int is_full (void) const; + + ACE_TLI_Request *alloc (void); + void free (ACE_TLI_Request *node); + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_HANDLE handle_; + int size_; + int current_count_; + ACE_TLI_Request *base_; + ACE_TLI_Request *tail_; + ACE_TLI_Request *free_list_; +}; + +ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Request_Queue) + +void +ACE_TLI_Request_Queue::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_TLI_Request_Queue::dump"); +#endif /* ACE_HAS_DUMP */ +} + +int +ACE_TLI_Request_Queue::is_empty (void) const +{ + ACE_TRACE ("ACE_TLI_Request_Queue::is_empty"); + return this->current_count_ == 0; +} + +int +ACE_TLI_Request_Queue::is_full (void) const +{ + ACE_TRACE ("ACE_TLI_Request_Queue::is_full"); + return this->current_count_ + 1 == this->size_; // Add 1 for the dummy. +} + +// Add a node to the free list stack. + +void +ACE_TLI_Request_Queue::free (ACE_TLI_Request *node) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::free"); + node->next_ = this->free_list_; + this->free_list_ = node; +} + +// Remove a node from the free list stack. + +ACE_TLI_Request * +ACE_TLI_Request_Queue::alloc (void) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::alloc"); + ACE_TLI_Request *temp = this->free_list_; + this->free_list_ = this->free_list_->next_; + return temp; +} + +ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor) + +void +ACE_TLI_Acceptor::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_TLI_Acceptor::dump"); +#endif /* ACE_HAS_DUMP */ +} + +ACE_TLI_Acceptor::ACE_TLI_Acceptor (void) + : queue_ (0) +{ + ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor"); +} + +int +ACE_TLI_Request_Queue::dequeue (ACE_TLI_Request *&ptr) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::dequeue"); + ptr = this->tail_->next_; + this->tail_->next_ = ptr->next_; + this->current_count_--; + return 0; +} + +// This is hideous... + +static ACE_HANDLE +open_new_endpoint (ACE_HANDLE listen_handle, + const char dev[], + struct t_call *callp, + int rwf, + ACE_Addr *remote_sap = 0) +{ + ACE_TRACE ("open_new_endpoint"); + ACE_HANDLE fd = ACE_OS::t_open ((char *) dev, + O_RDWR, + 0); + + struct t_bind req, *req_p = 0; + if (remote_sap != 0) + { + req.qlen = 0; + req.addr.buf = (char *) remote_sap->get_addr (); + req.addr.len = remote_sap->get_size (); + req.addr.maxlen = remote_sap->get_size (); + req_p = &req; + } + + if (fd == ACE_INVALID_HANDLE + || ACE_OS::t_bind (fd, req_p, 0) == -1) + fd = ACE_INVALID_HANDLE; +#if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI) + else if (rwf != 0 && ACE_OS::ioctl (fd, + I_PUSH, + const_cast ("tirdwr")) + == ACE_INVALID_HANDLE) + fd = ACE_INVALID_HANDLE; +#else + ACE_UNUSED_ARG(rwf); +#endif /* I_PUSH */ + + if (fd == ACE_INVALID_HANDLE) + ACE_OS::t_snddis (listen_handle, + callp); + return fd; +} + +// Close down the acceptor and release resources. + +int +ACE_TLI_Request_Queue::close (void) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::close"); + int res = 0; + + for (int i = 0; i < this->size_; i++) + { + ACE_TLI_Request &item = this->base_[i]; + + item.handle_ = ACE_INVALID_HANDLE; + if (ACE_OS::t_free ((char *) item.callp_, + T_CALL) != 0) + res = -1; + } + + delete [] this->base_; + this->base_ = 0; + return res; +} + +ACE_HANDLE +ACE_TLI_Request_Queue::open (ACE_HANDLE f, int sz) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::open"); + this->handle_ = f; + this->size_ = sz + 1; // Add one more for the dummy node. + + ACE_NEW_RETURN (this->base_, + ACE_TLI_Request[this->size_], + ACE_INVALID_HANDLE); + + // Initialize the ACE_Queue and the free list. + + for (int i = 0; i < this->size_; i++) + { + ACE_TLI_Request *item = &this->base_[i]; + this->free (item); + + item->handle_ = ACE_INVALID_HANDLE; + item->callp_ = (t_call *) ACE_OS::t_alloc (this->handle_, + T_CALL, + T_ALL); + if (item->callp_ == 0) + return ACE_INVALID_HANDLE; + } + + this->tail_ = this->alloc (); + this->tail_->next_ = this->tail_; + return 0; +} + +ACE_TLI_Request_Queue::ACE_TLI_Request_Queue (void) + : size_ (0), + current_count_ (0), + base_ (0), + tail_ (0), + free_list_ (0) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::ACE_TLI_Request_Queue"); +} + +// Listen for a new connection request and allocate appropriate data +// structures when one arrives. + +int +ACE_TLI_Request_Queue::enqueue (const char device[], + int restart, int rwflag) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::enqueue"); + ACE_TLI_Request *temp = this->alloc (); + ACE_TLI_Request &req = *this->tail_; + int res; + + do + res = ACE_OS::t_listen (this->handle_, req.callp_); + while (res == -1 + && restart + && t_errno == TSYSERR + && errno == EINTR); + + if (res != -1) + { + req.handle_ = open_new_endpoint (this->handle_, + device, + req.callp_, + rwflag); + if (req.handle_ != ACE_INVALID_HANDLE) + { + temp->next_ = this->tail_->next_; + this->tail_->next_ = temp; + this->tail_ = temp; + this->current_count_++; + return 0; + } + } + + // Something must have gone wrong, so free up allocated space. + this->free (temp); + return -1; +} + +// Locate and remove SEQUENCE_NUMBER from the list of pending +// connections. + +int +ACE_TLI_Request_Queue::remove (int sequence_number) +{ + ACE_TRACE ("ACE_TLI_Request_Queue::remove"); + ACE_TLI_Request *prev = this->tail_; + + // Put the sequence # in the dummy node to simply the search... + prev->callp_->sequence = sequence_number; + + ACE_TLI_Request *temp; + + for (temp = this->tail_->next_; + temp->callp_->sequence != sequence_number; + temp = temp->next_) + prev = temp; + + if (temp == this->tail_) + // Sequence # was not found, since we're back at the dummy node! + return -1; + else + { + prev->next_ = temp->next_; + ACE_OS::t_close (temp->handle_); + this->current_count_--; + this->free (temp); + return 0; + } +} + +ACE_HANDLE +ACE_TLI_Acceptor::open (const ACE_Addr &remote_sap, + int reuse_addr, + int oflag, + struct t_info *info, + int qlen, + const char dev[]) +{ + ACE_TRACE ("ACE_TLI_Acceptor::open"); + ACE_HANDLE res = 0; + int one = 1; + + this->disp_ = 0; + + ACE_ALLOCATOR_RETURN (this->device_, + ACE_OS::strdup (dev), + ACE_INVALID_HANDLE); + if (this->ACE_TLI::open (dev, + oflag, + info) == ACE_INVALID_HANDLE) + res = ACE_INVALID_HANDLE; +#if !defined (ACE_HAS_FORE_ATM_XTI) + // Reusing the address causes problems with FORE's API. The issue + // may be that t_optmgmt isn't fully supported by FORE. t_errno is + // TBADOPT after the t_optmgmt call so maybe options are configured + // differently for XTI than for TLI (at least for FORE's + // implementation - XTI is supposed to be a superset of TLI). + else if (reuse_addr + && this->set_option (SOL_SOCKET, + SO_REUSEADDR, + &one, + sizeof one) == -1) + res = ACE_INVALID_HANDLE; +#endif /* ACE_HAS_FORE_ATM_XTI */ + else if ((this->disp_ = + (struct t_discon *) ACE_OS::t_alloc (this->get_handle (), + T_DIS, + T_ALL)) == 0) + res = ACE_INVALID_HANDLE; + else + { + struct t_bind req; + +#if defined (ACE_HAS_FORE_ATM_XTI) + // Not sure why but FORE's t_bind call won't work if t_bind.qlen + // != 1 Adjust the backlog accordingly. + this->backlog_ = 1; + req.qlen = 1; +#else + this->backlog_ = qlen; + req.qlen = qlen; +#endif /* ACE_HAS_FORE_ATM_XTI */ + req.addr.maxlen = remote_sap.get_size (); + + if (remote_sap == ACE_Addr::sap_any) + // Note that if addr.len == 0 then ACE_TLI selects the port + // number. + req.addr.len = 0; + else + { + req.addr.buf = (char *) remote_sap.get_addr (); + req.addr.len = remote_sap.get_size (); + } + + res = (ACE_HANDLE) ACE_OS::t_bind (this->get_handle (), + &req, + 0); + if (res != ACE_INVALID_HANDLE) + { + ACE_NEW_RETURN (this->queue_, + ACE_TLI_Request_Queue, + ACE_INVALID_HANDLE); + res = this->queue_->open (this->get_handle (), + this->backlog_); + } + } + if (res == ACE_INVALID_HANDLE) + this->close (); + return this->get_handle (); +} + +ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr &remote_sap, + int reuse_addr, + int oflag, + struct t_info *info, + int back, + const char dev[]) +{ + ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor"); + if (this->open (remote_sap, + reuse_addr, + oflag, + info, + back, + dev) == ACE_INVALID_HANDLE) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("ACE_TLI_Acceptor::ACE_TLI_Acceptor"))); +} + +int +ACE_TLI_Acceptor::close (void) +{ + ACE_TRACE ("ACE_TLI_Acceptor::close"); + if (this->device_ != 0) + { + if (this->queue_ != 0) + { + this->queue_->close (); + delete this->queue_; + } + + ACE_OS::t_free ((char *) this->disp_, T_DIS); + ACE_OS::free (ACE_MALLOC_T (this->device_)); + this->disp_ = 0; + this->device_ = 0; + return this->ACE_TLI::close (); + } + return 0; +} + +// Perform the logic required to handle the arrival of asynchronous +// events while we are trying to accept a new connection request. + +int +ACE_TLI_Acceptor::handle_async_event (int restart, int rwf) +{ + ACE_TRACE ("ACE_TLI_Acceptor::handle_async_event"); + int event = this->look (); + + switch (event) + { + case T_DISCONNECT: + this->rcvdis (this->disp_); + this->queue_->remove (this->disp_->sequence); + break; + case T_LISTEN: + this->queue_->enqueue (this->device_, + restart, + rwf); + break; + default: + return -1; + } + return 0; +} + +int +ACE_TLI_Acceptor::accept (ACE_TLI_Stream &new_tli_sap, + ACE_Addr *remote_addr, + ACE_Time_Value *timeout, + int restart, + int reset_new_handle, + int rwf, + netbuf *udata, + netbuf *opt) +{ + ACE_TRACE ("ACE_TLI_Acceptor::accept"); + ACE_UNUSED_ARG (reset_new_handle); + + ACE_TLI_Request *req = 0; + int res = 0; + if (timeout != 0 + && ACE::handle_timed_accept (this->get_handle (), + timeout, + restart) == -1) + return -1; + else if (this->queue_->is_empty ()) + { + req = this->queue_->alloc (); + + do + res = ACE_OS::t_listen (this->get_handle (), + req->callp_); + while (res == -1 + && restart + && errno == EINTR); + + if (res != -1) + { + req->handle_ = open_new_endpoint (this->get_handle (), + this->device_, + req->callp_, + rwf +#if defined (ACE_WIN32) + , remote_addr +#endif /* ACE_WIN32 */ + ); + if (req->handle_ == ACE_INVALID_HANDLE) + res = -1; + else + res = 0; + } + } + else + res = this->queue_->dequeue (req); + + if (udata != 0) + ACE_OS::memcpy ((void *) &req->callp_->udata, + (void *) udata, + sizeof *udata); + if (opt != 0) + ACE_OS::memcpy ((void *) &req->callp_->opt, + (void *) opt, + sizeof *opt); + + while (res != -1) + { + res = ACE_OS::t_accept (this->get_handle (), + req->handle_, + req->callp_); + if (res != -1) + break; // Got one! + else if (t_errno == TLOOK) + res = this->handle_async_event (restart, rwf); + else if (restart && t_errno == TSYSERR && errno == EINTR) + res = 0; + } + + if (res == -1) + { + if (errno != EWOULDBLOCK) + { + new_tli_sap.set_handle (ACE_INVALID_HANDLE); + if (req->handle_ != ACE_INVALID_HANDLE) + ACE_OS::t_close (req->handle_); + } + } + else + { + new_tli_sap.set_handle (req->handle_); + + if (remote_addr != 0) + remote_addr->set_addr ((void *) req->callp_->addr.buf, + req->callp_->addr.len); + } + + req->handle_ = ACE_INVALID_HANDLE; + this->queue_->free (req); + new_tli_sap.set_rwflag (rwf); + return new_tli_sap.get_handle () == ACE_INVALID_HANDLE ? -1 : 0; +} + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* ACE_HAS_TLI */ -- cgit v1.2.1