1 // $Id: TLI_Acceptor.cpp 80826 2008-03-04 14:51:23Z wotte $
3 #include "ace/TLI_Acceptor.h"
4 #include "ace/Log_Msg.h"
6 #include "ace/OS_NS_string.h"
7 #include "ace/OS_Memory.h"
9 ACE_RCSID(ace
, TLI_Acceptor
, "$Id: TLI_Acceptor.cpp 80826 2008-03-04 14:51:23Z wotte $")
11 #if defined (ACE_HAS_TLI)
13 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
15 // Put the actual definitions of the ACE_TLI_Request and
16 // ACE_TLI_Request_Queue classes here to hide them from clients...
18 struct ACE_TLI_Request
20 struct t_call
*callp_
;
22 ACE_TLI_Request
*next_
;
25 class ACE_TLI_Request_Queue
28 ACE_TLI_Request_Queue (void);
30 ACE_HANDLE
open (ACE_HANDLE fd
, int size
);
33 int enqueue (const char device
[], int restart
, int rwflag
);
34 int dequeue (ACE_TLI_Request
*&ptr
);
35 int remove (int sequence_number
);
37 int is_empty (void) const;
38 int is_full (void) const;
40 ACE_TLI_Request
*alloc (void);
41 void free (ACE_TLI_Request
*node
);
43 void dump (void) const;
44 // Dump the state of an object.
46 ACE_ALLOC_HOOK_DECLARE
;
47 // Declare the dynamic allocation hooks.
53 ACE_TLI_Request
*base_
;
54 ACE_TLI_Request
*tail_
;
55 ACE_TLI_Request
*free_list_
;
58 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Request_Queue
)
61 ACE_TLI_Request_Queue::dump (void) const
63 #if defined (ACE_HAS_DUMP)
64 ACE_TRACE ("ACE_TLI_Request_Queue::dump");
65 #endif /* ACE_HAS_DUMP */
69 ACE_TLI_Request_Queue::is_empty (void) const
71 ACE_TRACE ("ACE_TLI_Request_Queue::is_empty");
72 return this->current_count_
== 0;
76 ACE_TLI_Request_Queue::is_full (void) const
78 ACE_TRACE ("ACE_TLI_Request_Queue::is_full");
79 return this->current_count_
+ 1 == this->size_
; // Add 1 for the dummy.
82 // Add a node to the free list stack.
85 ACE_TLI_Request_Queue::free (ACE_TLI_Request
*node
)
87 ACE_TRACE ("ACE_TLI_Request_Queue::free");
88 node
->next_
= this->free_list_
;
89 this->free_list_
= node
;
92 // Remove a node from the free list stack.
95 ACE_TLI_Request_Queue::alloc (void)
97 ACE_TRACE ("ACE_TLI_Request_Queue::alloc");
98 ACE_TLI_Request
*temp
= this->free_list_
;
99 this->free_list_
= this->free_list_
->next_
;
103 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor
)
106 ACE_TLI_Acceptor::dump (void) const
108 #if defined (ACE_HAS_DUMP)
109 ACE_TRACE ("ACE_TLI_Acceptor::dump");
110 #endif /* ACE_HAS_DUMP */
113 ACE_TLI_Acceptor::ACE_TLI_Acceptor (void)
116 ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
120 ACE_TLI_Request_Queue::dequeue (ACE_TLI_Request
*&ptr
)
122 ACE_TRACE ("ACE_TLI_Request_Queue::dequeue");
123 ptr
= this->tail_
->next_
;
124 this->tail_
->next_
= ptr
->next_
;
125 this->current_count_
--;
129 // This is hideous...
132 open_new_endpoint (ACE_HANDLE listen_handle
,
134 struct t_call
*callp
,
136 ACE_Addr
*remote_sap
= 0)
138 ACE_TRACE ("open_new_endpoint");
139 ACE_HANDLE fd
= ACE_OS::t_open ((char *) dev
,
143 struct t_bind req
, *req_p
= 0;
147 req
.addr
.buf
= (char *) remote_sap
->get_addr ();
148 req
.addr
.len
= remote_sap
->get_size ();
149 req
.addr
.maxlen
= remote_sap
->get_size ();
153 if (fd
== ACE_INVALID_HANDLE
154 || ACE_OS::t_bind (fd
, req_p
, 0) == -1)
155 fd
= ACE_INVALID_HANDLE
;
156 #if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
157 else if (rwf
!= 0 && ACE_OS::ioctl (fd
,
159 const_cast<char *> ("tirdwr"))
160 == ACE_INVALID_HANDLE
)
161 fd
= ACE_INVALID_HANDLE
;
166 if (fd
== ACE_INVALID_HANDLE
)
167 ACE_OS::t_snddis (listen_handle
,
172 // Close down the acceptor and release resources.
175 ACE_TLI_Request_Queue::close (void)
177 ACE_TRACE ("ACE_TLI_Request_Queue::close");
180 for (int i
= 0; i
< this->size_
; i
++)
182 ACE_TLI_Request
&item
= this->base_
[i
];
184 item
.handle_
= ACE_INVALID_HANDLE
;
185 if (ACE_OS::t_free ((char *) item
.callp_
,
190 delete [] this->base_
;
196 ACE_TLI_Request_Queue::open (ACE_HANDLE f
, int sz
)
198 ACE_TRACE ("ACE_TLI_Request_Queue::open");
200 this->size_
= sz
+ 1; // Add one more for the dummy node.
202 ACE_NEW_RETURN (this->base_
,
203 ACE_TLI_Request
[this->size_
],
206 // Initialize the ACE_Queue and the free list.
208 for (int i
= 0; i
< this->size_
; i
++)
210 ACE_TLI_Request
*item
= &this->base_
[i
];
213 item
->handle_
= ACE_INVALID_HANDLE
;
214 item
->callp_
= (t_call
*) ACE_OS::t_alloc (this->handle_
,
217 if (item
->callp_
== 0)
218 return ACE_INVALID_HANDLE
;
221 this->tail_
= this->alloc ();
222 this->tail_
->next_
= this->tail_
;
226 ACE_TLI_Request_Queue::ACE_TLI_Request_Queue (void)
233 ACE_TRACE ("ACE_TLI_Request_Queue::ACE_TLI_Request_Queue");
236 // Listen for a new connection request and allocate appropriate data
237 // structures when one arrives.
240 ACE_TLI_Request_Queue::enqueue (const char device
[],
241 int restart
, int rwflag
)
243 ACE_TRACE ("ACE_TLI_Request_Queue::enqueue");
244 ACE_TLI_Request
*temp
= this->alloc ();
245 ACE_TLI_Request
&req
= *this->tail_
;
249 res
= ACE_OS::t_listen (this->handle_
, req
.callp_
);
252 && t_errno
== TSYSERR
257 req
.handle_
= open_new_endpoint (this->handle_
,
261 if (req
.handle_
!= ACE_INVALID_HANDLE
)
263 temp
->next_
= this->tail_
->next_
;
264 this->tail_
->next_
= temp
;
266 this->current_count_
++;
271 // Something must have gone wrong, so free up allocated space.
276 // Locate and remove SEQUENCE_NUMBER from the list of pending
280 ACE_TLI_Request_Queue::remove (int sequence_number
)
282 ACE_TRACE ("ACE_TLI_Request_Queue::remove");
283 ACE_TLI_Request
*prev
= this->tail_
;
285 // Put the sequence # in the dummy node to simply the search...
286 prev
->callp_
->sequence
= sequence_number
;
288 ACE_TLI_Request
*temp
;
290 for (temp
= this->tail_
->next_
;
291 temp
->callp_
->sequence
!= sequence_number
;
295 if (temp
== this->tail_
)
296 // Sequence # was not found, since we're back at the dummy node!
300 prev
->next_
= temp
->next_
;
301 ACE_OS::t_close (temp
->handle_
);
302 this->current_count_
--;
309 ACE_TLI_Acceptor::open (const ACE_Addr
&remote_sap
,
316 ACE_TRACE ("ACE_TLI_Acceptor::open");
322 ACE_ALLOCATOR_RETURN (this->device_
,
323 ACE_OS::strdup (dev
),
325 if (this->ACE_TLI::open (dev
,
327 info
) == ACE_INVALID_HANDLE
)
328 res
= ACE_INVALID_HANDLE
;
329 #if !defined (ACE_HAS_FORE_ATM_XTI)
330 // Reusing the address causes problems with FORE's API. The issue
331 // may be that t_optmgmt isn't fully supported by FORE. t_errno is
332 // TBADOPT after the t_optmgmt call so maybe options are configured
333 // differently for XTI than for TLI (at least for FORE's
334 // implementation - XTI is supposed to be a superset of TLI).
336 && this->set_option (SOL_SOCKET
,
340 res
= ACE_INVALID_HANDLE
;
341 #endif /* ACE_HAS_FORE_ATM_XTI */
342 else if ((this->disp_
=
343 (struct t_discon
*) ACE_OS::t_alloc (this->get_handle (),
346 res
= ACE_INVALID_HANDLE
;
351 #if defined (ACE_HAS_FORE_ATM_XTI)
352 // Not sure why but FORE's t_bind call won't work if t_bind.qlen
353 // != 1 Adjust the backlog accordingly.
357 this->backlog_
= qlen
;
359 #endif /* ACE_HAS_FORE_ATM_XTI */
360 req
.addr
.maxlen
= remote_sap
.get_size ();
362 if (remote_sap
== ACE_Addr::sap_any
)
363 // Note that if addr.len == 0 then ACE_TLI selects the port
368 req
.addr
.buf
= (char *) remote_sap
.get_addr ();
369 req
.addr
.len
= remote_sap
.get_size ();
372 res
= (ACE_HANDLE
) ACE_OS::t_bind (this->get_handle (),
375 if (res
!= ACE_INVALID_HANDLE
)
377 ACE_NEW_RETURN (this->queue_
,
378 ACE_TLI_Request_Queue
,
380 res
= this->queue_
->open (this->get_handle (),
384 if (res
== ACE_INVALID_HANDLE
)
386 return this->get_handle ();
389 ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr
&remote_sap
,
396 ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
397 if (this->open (remote_sap
,
402 dev
) == ACE_INVALID_HANDLE
)
403 ACE_ERROR ((LM_ERROR
,
405 ACE_TEXT ("ACE_TLI_Acceptor::ACE_TLI_Acceptor")));
409 ACE_TLI_Acceptor::close (void)
411 ACE_TRACE ("ACE_TLI_Acceptor::close");
412 if (this->device_
!= 0)
414 if (this->queue_
!= 0)
416 this->queue_
->close ();
420 ACE_OS::t_free ((char *) this->disp_
, T_DIS
);
421 ACE_OS::free (ACE_MALLOC_T (this->device_
));
424 return this->ACE_TLI::close ();
429 // Perform the logic required to handle the arrival of asynchronous
430 // events while we are trying to accept a new connection request.
433 ACE_TLI_Acceptor::handle_async_event (int restart
, int rwf
)
435 ACE_TRACE ("ACE_TLI_Acceptor::handle_async_event");
436 int event
= this->look ();
441 this->rcvdis (this->disp_
);
442 this->queue_
->remove (this->disp_
->sequence
);
445 this->queue_
->enqueue (this->device_
,
456 ACE_TLI_Acceptor::accept (ACE_TLI_Stream
&new_tli_sap
,
457 ACE_Addr
*remote_addr
,
458 ACE_Time_Value
*timeout
,
460 int reset_new_handle
,
465 ACE_TRACE ("ACE_TLI_Acceptor::accept");
466 ACE_UNUSED_ARG (reset_new_handle
);
468 ACE_TLI_Request
*req
= 0;
471 && ACE::handle_timed_accept (this->get_handle (),
475 else if (this->queue_
->is_empty ())
477 req
= this->queue_
->alloc ();
480 res
= ACE_OS::t_listen (this->get_handle (),
488 req
->handle_
= open_new_endpoint (this->get_handle (),
492 #if defined (ACE_WIN32)
494 #endif /* ACE_WIN32 */
496 if (req
->handle_
== ACE_INVALID_HANDLE
)
503 res
= this->queue_
->dequeue (req
);
506 ACE_OS::memcpy ((void *) &req
->callp_
->udata
,
510 ACE_OS::memcpy ((void *) &req
->callp_
->opt
,
516 res
= ACE_OS::t_accept (this->get_handle (),
521 else if (t_errno
== TLOOK
)
522 res
= this->handle_async_event (restart
, rwf
);
523 else if (restart
&& t_errno
== TSYSERR
&& errno
== EINTR
)
529 if (errno
!= EWOULDBLOCK
)
531 new_tli_sap
.set_handle (ACE_INVALID_HANDLE
);
532 if (req
->handle_
!= ACE_INVALID_HANDLE
)
533 ACE_OS::t_close (req
->handle_
);
538 new_tli_sap
.set_handle (req
->handle_
);
540 if (remote_addr
!= 0)
541 remote_addr
->set_addr ((void *) req
->callp_
->addr
.buf
,
542 req
->callp_
->addr
.len
);
545 req
->handle_
= ACE_INVALID_HANDLE
;
546 this->queue_
->free (req
);
547 new_tli_sap
.set_rwflag (rwf
);
548 return new_tli_sap
.get_handle () == ACE_INVALID_HANDLE
? -1 : 0;
551 ACE_END_VERSIONED_NAMESPACE_DECL
553 #endif /* ACE_HAS_TLI */