summaryrefslogtreecommitdiff
path: root/ace/TLI_Acceptor.cpp
diff options
context:
space:
mode:
authorlevine <levine@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1996-10-21 21:41:34 +0000
committerlevine <levine@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1996-10-21 21:41:34 +0000
commita5fdebc5f6375078ec1763850a4ca23ec7fe6458 (patch)
treebcf0a25c3d45a209a6e3ac37b233a4812f29c732 /ace/TLI_Acceptor.cpp
downloadATCD-a5fdebc5f6375078ec1763850a4ca23ec7fe6458.tar.gz
Initial revision
Diffstat (limited to 'ace/TLI_Acceptor.cpp')
-rw-r--r--ace/TLI_Acceptor.cpp456
1 files changed, 456 insertions, 0 deletions
diff --git a/ace/TLI_Acceptor.cpp b/ace/TLI_Acceptor.cpp
new file mode 100644
index 00000000000..4fce1af33d2
--- /dev/null
+++ b/ace/TLI_Acceptor.cpp
@@ -0,0 +1,456 @@
+// TLI_Acceptor.cpp
+// $Id$
+
+
+#define ACE_BUILD_DLL
+#include "ace/TLI_Acceptor.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_HAS_TLI)
+
+// 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);
+
+ int open (int 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:
+ int 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
+{
+ ACE_TRACE ("ACE_TLI_Request_Queue::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
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::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_TRACE ("open_new_endpoint");
+ ACE_HANDLE fd;
+
+ if ((fd = ACE_OS::t_open ((char *) dev, O_RDWR, 0)) == ACE_INVALID_HANDLE
+ || ACE_OS::t_bind (fd, 0, 0) == ACE_INVALID_HANDLE)
+ fd = ACE_INVALID_HANDLE;
+#if defined (I_PUSH)
+ else if (rwf != 0 && ACE_OS::ioctl (fd, I_PUSH, "tirdwr") == ACE_INVALID_HANDLE)
+ fd = ACE_INVALID_HANDLE;
+#endif /* I_PUSH */
+
+ if (fd == ACE_INVALID_HANDLE)
+ ACE_OS::t_snddis (listen_handle, callp);
+ return fd;
+}
+
+// Close down the acceptor and release resources.
+
+ACE_INLINE 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 = ACE_INVALID_HANDLE;
+ }
+ 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_INLINE
+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 == ACE_INVALID_HANDLE && restart && t_errno == TSYSERR && errno == EINTR);
+
+ if (res != ACE_INVALID_HANDLE)
+ {
+ 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 ACE_INVALID_HANDLE;
+}
+
+// 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");
+ int res = 0;
+ int one = 1;
+
+ this->disp_ = 0;
+
+ if ((this->device_ = ACE_OS::strdup (dev)) == 0)
+ res = ACE_INVALID_HANDLE;
+ else if (this->ACE_TLI::open (dev, oflag, info) == ACE_INVALID_HANDLE)
+ res = ACE_INVALID_HANDLE;
+ else if (reuse_addr
+ && this->set_option (SOL_SOCKET, SO_REUSEADDR,
+ &one, sizeof one) == ACE_INVALID_HANDLE)
+ res = ACE_INVALID_HANDLE;
+ 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;
+
+ this->backlog_ = qlen;
+ req.qlen = qlen;
+ 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.len = remote_sap.get_size ();
+ req.addr.buf = (char *) remote_sap.get_addr ();
+ }
+
+ res = ACE_OS::t_bind (this->get_handle (), &req, 0);
+ if (res != ACE_INVALID_HANDLE)
+ {
+ ACE_NEW_RETURN (this->queue_, ACE_TLI_Request_Queue, -1);
+
+ 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, "%p\n", "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;
+
+ switch (event = this->look ())
+ {
+ 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 rwf,
+ netbuf *udata,
+ netbuf *opt)
+{
+ ACE_TRACE ("ACE_TLI_Acceptor::accept");
+ 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 == ACE_INVALID_HANDLE
+ && restart
+ && errno == EINTR);
+
+ if (res != ACE_INVALID_HANDLE)
+ res = req->handle_ = open_new_endpoint (this->get_handle (),
+ this->device_, req->callp_, rwf);
+ }
+ 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 != ACE_INVALID_HANDLE)
+ if ((res = ACE_OS::t_accept (this->get_handle (), req->handle_,
+ req->callp_)) != ACE_INVALID_HANDLE)
+ 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 == ACE_INVALID_HANDLE)
+ {
+ 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;
+}
+
+#endif /* ACE_HAS_TLI */