1 #include "ace/TLI_Acceptor.h"
2 #include "ace/Log_Category.h"
4 #include "ace/OS_NS_string.h"
5 #include "ace/OS_Memory.h"
7 #if defined (ACE_HAS_TLI)
9 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
11 // Put the actual definitions of the ACE_TLI_Request and
12 // ACE_TLI_Request_Queue classes here to hide them from clients...
14 struct ACE_TLI_Request
16 struct t_call
*callp_
;
18 ACE_TLI_Request
*next_
;
21 class ACE_TLI_Request_Queue
24 ACE_TLI_Request_Queue ();
26 ACE_HANDLE
open (ACE_HANDLE fd
, int size
);
29 int enqueue (const char device
[], bool restart
, int rwflag
);
30 int dequeue (ACE_TLI_Request
*&ptr
);
31 int remove (int sequence_number
);
33 int is_empty () const;
36 ACE_TLI_Request
*alloc ();
37 void free (ACE_TLI_Request
*node
);
40 // Dump the state of an object.
42 ACE_ALLOC_HOOK_DECLARE
;
43 // Declare the dynamic allocation hooks.
49 ACE_TLI_Request
*base_
;
50 ACE_TLI_Request
*tail_
;
51 ACE_TLI_Request
*free_list_
;
54 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Request_Queue
)
57 ACE_TLI_Request_Queue::dump () const
59 #if defined (ACE_HAS_DUMP)
60 ACE_TRACE ("ACE_TLI_Request_Queue::dump");
61 #endif /* ACE_HAS_DUMP */
65 ACE_TLI_Request_Queue::is_empty () const
67 ACE_TRACE ("ACE_TLI_Request_Queue::is_empty");
68 return this->current_count_
== 0;
72 ACE_TLI_Request_Queue::is_full () const
74 ACE_TRACE ("ACE_TLI_Request_Queue::is_full");
75 return this->current_count_
+ 1 == this->size_
; // Add 1 for the dummy.
78 // Add a node to the free list stack.
81 ACE_TLI_Request_Queue::free (ACE_TLI_Request
*node
)
83 ACE_TRACE ("ACE_TLI_Request_Queue::free");
84 node
->next_
= this->free_list_
;
85 this->free_list_
= node
;
88 // Remove a node from the free list stack.
91 ACE_TLI_Request_Queue::alloc ()
93 ACE_TRACE ("ACE_TLI_Request_Queue::alloc");
94 ACE_TLI_Request
*temp
= this->free_list_
;
95 this->free_list_
= this->free_list_
->next_
;
99 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor
)
102 ACE_TLI_Acceptor::dump () const
104 #if defined (ACE_HAS_DUMP)
105 ACE_TRACE ("ACE_TLI_Acceptor::dump");
106 #endif /* ACE_HAS_DUMP */
109 ACE_TLI_Acceptor::ACE_TLI_Acceptor ()
112 ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
116 ACE_TLI_Request_Queue::dequeue (ACE_TLI_Request
*&ptr
)
118 ACE_TRACE ("ACE_TLI_Request_Queue::dequeue");
119 ptr
= this->tail_
->next_
;
120 this->tail_
->next_
= ptr
->next_
;
121 this->current_count_
--;
125 // This is hideous...
128 open_new_endpoint (ACE_HANDLE listen_handle
,
130 struct t_call
*callp
,
132 ACE_Addr
*remote_sap
= 0)
134 ACE_TRACE ("open_new_endpoint");
135 ACE_HANDLE fd
= ACE_OS::t_open ((char *) dev
,
139 struct t_bind req
, *req_p
= 0;
143 req
.addr
.buf
= (char *) remote_sap
->get_addr ();
144 req
.addr
.len
= remote_sap
->get_size ();
145 req
.addr
.maxlen
= remote_sap
->get_size ();
149 if (fd
== ACE_INVALID_HANDLE
150 || ACE_OS::t_bind (fd
, req_p
, 0) == -1)
151 fd
= ACE_INVALID_HANDLE
;
152 #if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
153 else if (rwf
!= 0 && ACE_OS::ioctl (fd
,
155 const_cast<char *> ("tirdwr"))
156 == ACE_INVALID_HANDLE
)
157 fd
= ACE_INVALID_HANDLE
;
162 if (fd
== ACE_INVALID_HANDLE
)
163 ACE_OS::t_snddis (listen_handle
,
168 // Close down the acceptor and release resources.
171 ACE_TLI_Request_Queue::close ()
173 ACE_TRACE ("ACE_TLI_Request_Queue::close");
176 for (int i
= 0; i
< this->size_
; i
++)
178 ACE_TLI_Request
&item
= this->base_
[i
];
180 item
.handle_
= ACE_INVALID_HANDLE
;
181 if (ACE_OS::t_free ((char *) item
.callp_
,
186 delete [] this->base_
;
192 ACE_TLI_Request_Queue::open (ACE_HANDLE f
, int sz
)
194 ACE_TRACE ("ACE_TLI_Request_Queue::open");
196 this->size_
= sz
+ 1; // Add one more for the dummy node.
198 ACE_NEW_RETURN (this->base_
,
199 ACE_TLI_Request
[this->size_
],
202 // Initialize the ACE_Queue and the free list.
204 for (int i
= 0; i
< this->size_
; i
++)
206 ACE_TLI_Request
*item
= &this->base_
[i
];
209 item
->handle_
= ACE_INVALID_HANDLE
;
210 item
->callp_
= (t_call
*) ACE_OS::t_alloc (this->handle_
,
213 if (item
->callp_
== 0)
214 return ACE_INVALID_HANDLE
;
217 this->tail_
= this->alloc ();
218 this->tail_
->next_
= this->tail_
;
222 ACE_TLI_Request_Queue::ACE_TLI_Request_Queue ()
229 ACE_TRACE ("ACE_TLI_Request_Queue::ACE_TLI_Request_Queue");
232 // Listen for a new connection request and allocate appropriate data
233 // structures when one arrives.
236 ACE_TLI_Request_Queue::enqueue (const char device
[],
237 bool restart
, int rwflag
)
239 ACE_TRACE ("ACE_TLI_Request_Queue::enqueue");
240 ACE_TLI_Request
*temp
= this->alloc ();
241 ACE_TLI_Request
&req
= *this->tail_
;
245 res
= ACE_OS::t_listen (this->handle_
, req
.callp_
);
248 && t_errno
== TSYSERR
253 req
.handle_
= open_new_endpoint (this->handle_
,
257 if (req
.handle_
!= ACE_INVALID_HANDLE
)
259 temp
->next_
= this->tail_
->next_
;
260 this->tail_
->next_
= temp
;
262 this->current_count_
++;
267 // Something must have gone wrong, so free up allocated space.
272 // Locate and remove SEQUENCE_NUMBER from the list of pending
276 ACE_TLI_Request_Queue::remove (int sequence_number
)
278 ACE_TRACE ("ACE_TLI_Request_Queue::remove");
279 ACE_TLI_Request
*prev
= this->tail_
;
281 // Put the sequence # in the dummy node to simply the search...
282 prev
->callp_
->sequence
= sequence_number
;
284 ACE_TLI_Request
*temp
;
286 for (temp
= this->tail_
->next_
;
287 temp
->callp_
->sequence
!= sequence_number
;
291 if (temp
== this->tail_
)
292 // Sequence # was not found, since we're back at the dummy node!
296 prev
->next_
= temp
->next_
;
297 ACE_OS::t_close (temp
->handle_
);
298 this->current_count_
--;
305 ACE_TLI_Acceptor::open (const ACE_Addr
&remote_sap
,
312 ACE_TRACE ("ACE_TLI_Acceptor::open");
318 ACE_ALLOCATOR_RETURN (this->device_
,
319 ACE_OS::strdup (dev
),
321 if (this->ACE_TLI::open (dev
,
323 info
) == ACE_INVALID_HANDLE
)
324 res
= ACE_INVALID_HANDLE
;
325 #if !defined (ACE_HAS_FORE_ATM_XTI)
326 // Reusing the address causes problems with FORE's API. The issue
327 // may be that t_optmgmt isn't fully supported by FORE. t_errno is
328 // TBADOPT after the t_optmgmt call so maybe options are configured
329 // differently for XTI than for TLI (at least for FORE's
330 // implementation - XTI is supposed to be a superset of TLI).
332 && this->set_option (SOL_SOCKET
,
336 res
= ACE_INVALID_HANDLE
;
337 #endif /* ACE_HAS_FORE_ATM_XTI */
338 else if ((this->disp_
=
339 (struct t_discon
*) ACE_OS::t_alloc (this->get_handle (),
342 res
= ACE_INVALID_HANDLE
;
347 #if defined (ACE_HAS_FORE_ATM_XTI)
348 // Not sure why but FORE's t_bind call won't work if t_bind.qlen
349 // != 1 Adjust the backlog accordingly.
353 this->backlog_
= qlen
;
355 #endif /* ACE_HAS_FORE_ATM_XTI */
356 req
.addr
.maxlen
= remote_sap
.get_size ();
358 if (remote_sap
== ACE_Addr::sap_any
)
359 // Note that if addr.len == 0 then ACE_TLI selects the port
364 req
.addr
.buf
= (char *) remote_sap
.get_addr ();
365 req
.addr
.len
= remote_sap
.get_size ();
368 res
= (ACE_HANDLE
) ACE_OS::t_bind (this->get_handle (),
371 if (res
!= ACE_INVALID_HANDLE
)
373 ACE_NEW_RETURN (this->queue_
,
374 ACE_TLI_Request_Queue
,
376 res
= this->queue_
->open (this->get_handle (),
380 if (res
== ACE_INVALID_HANDLE
)
382 return this->get_handle ();
385 ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr
&remote_sap
,
392 ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
393 if (this->open (remote_sap
,
398 dev
) == ACE_INVALID_HANDLE
)
399 ACELIB_ERROR ((LM_ERROR
,
401 ACE_TEXT ("ACE_TLI_Acceptor::ACE_TLI_Acceptor")));
405 ACE_TLI_Acceptor::close ()
407 ACE_TRACE ("ACE_TLI_Acceptor::close");
408 if (this->device_
!= 0)
410 if (this->queue_
!= 0)
412 this->queue_
->close ();
416 ACE_OS::t_free ((char *) this->disp_
, T_DIS
);
417 ACE_OS::free (ACE_MALLOC_T (this->device_
));
420 return this->ACE_TLI::close ();
425 // Perform the logic required to handle the arrival of asynchronous
426 // events while we are trying to accept a new connection request.
429 ACE_TLI_Acceptor::handle_async_event (bool restart
, int rwf
)
431 ACE_TRACE ("ACE_TLI_Acceptor::handle_async_event");
432 int event
= this->look ();
437 this->rcvdis (this->disp_
);
438 this->queue_
->remove (this->disp_
->sequence
);
441 this->queue_
->enqueue (this->device_
,
452 ACE_TLI_Acceptor::accept (ACE_TLI_Stream
&new_tli_sap
,
453 ACE_Addr
*remote_addr
,
454 ACE_Time_Value
*timeout
,
456 bool reset_new_handle
,
461 ACE_TRACE ("ACE_TLI_Acceptor::accept");
462 ACE_UNUSED_ARG (reset_new_handle
);
464 ACE_TLI_Request
*req
= 0;
467 && ACE::handle_timed_accept (this->get_handle (),
471 else if (this->queue_
->is_empty ())
473 req
= this->queue_
->alloc ();
476 res
= ACE_OS::t_listen (this->get_handle (),
484 req
->handle_
= open_new_endpoint (this->get_handle (),
488 #if defined (ACE_WIN32)
490 #endif /* ACE_WIN32 */
492 if (req
->handle_
== ACE_INVALID_HANDLE
)
499 res
= this->queue_
->dequeue (req
);
502 ACE_OS::memcpy ((void *) &req
->callp_
->udata
,
506 ACE_OS::memcpy ((void *) &req
->callp_
->opt
,
512 res
= ACE_OS::t_accept (this->get_handle (),
517 else if (t_errno
== TLOOK
)
518 res
= this->handle_async_event (restart
, rwf
);
519 else if (restart
&& t_errno
== TSYSERR
&& errno
== EINTR
)
525 if (errno
!= EWOULDBLOCK
)
527 new_tli_sap
.set_handle (ACE_INVALID_HANDLE
);
528 if (req
->handle_
!= ACE_INVALID_HANDLE
)
529 ACE_OS::t_close (req
->handle_
);
534 new_tli_sap
.set_handle (req
->handle_
);
536 if (remote_addr
!= 0)
537 remote_addr
->set_addr ((void *) req
->callp_
->addr
.buf
,
538 req
->callp_
->addr
.len
);
541 req
->handle_
= ACE_INVALID_HANDLE
;
542 this->queue_
->free (req
);
543 new_tli_sap
.set_rwflag (rwf
);
544 return new_tli_sap
.get_handle () == ACE_INVALID_HANDLE
? -1 : 0;
547 ACE_END_VERSIONED_NAMESPACE_DECL
549 #endif /* ACE_HAS_TLI */