Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / TLI_Acceptor.cpp
blob1075346b0d4b3c468c788bb45cd93a03bc2a404b
1 #include "ace/TLI_Acceptor.h"
2 #include "ace/Log_Category.h"
3 #include "ace/ACE.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_;
17 ACE_HANDLE handle_;
18 ACE_TLI_Request *next_;
21 class ACE_TLI_Request_Queue
23 public:
24 ACE_TLI_Request_Queue ();
26 ACE_HANDLE open (ACE_HANDLE fd, int size);
27 int close ();
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;
34 int is_full () const;
36 ACE_TLI_Request *alloc ();
37 void free (ACE_TLI_Request *node);
39 void dump () const;
40 // Dump the state of an object.
42 ACE_ALLOC_HOOK_DECLARE;
43 // Declare the dynamic allocation hooks.
45 private:
46 ACE_HANDLE handle_;
47 int size_;
48 int current_count_;
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)
56 void
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 */
64 int
65 ACE_TLI_Request_Queue::is_empty () const
67 ACE_TRACE ("ACE_TLI_Request_Queue::is_empty");
68 return this->current_count_ == 0;
71 int
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.
80 void
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.
90 ACE_TLI_Request *
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_;
96 return temp;
99 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor)
101 void
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 ()
110 : queue_ (0)
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_--;
122 return 0;
125 // This is hideous...
127 static ACE_HANDLE
128 open_new_endpoint (ACE_HANDLE listen_handle,
129 const char dev[],
130 struct t_call *callp,
131 int rwf,
132 ACE_Addr *remote_sap = 0)
134 ACE_TRACE ("open_new_endpoint");
135 ACE_HANDLE fd = ACE_OS::t_open ((char *) dev,
136 O_RDWR,
139 struct t_bind req, *req_p = 0;
140 if (remote_sap != 0)
142 req.qlen = 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 ();
146 req_p = &req;
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,
154 I_PUSH,
155 const_cast<char *> ("tirdwr"))
156 == ACE_INVALID_HANDLE)
157 fd = ACE_INVALID_HANDLE;
158 #else
159 ACE_UNUSED_ARG(rwf);
160 #endif /* I_PUSH */
162 if (fd == ACE_INVALID_HANDLE)
163 ACE_OS::t_snddis (listen_handle,
164 callp);
165 return fd;
168 // Close down the acceptor and release resources.
171 ACE_TLI_Request_Queue::close ()
173 ACE_TRACE ("ACE_TLI_Request_Queue::close");
174 int res = 0;
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_,
182 T_CALL) != 0)
183 res = -1;
186 delete [] this->base_;
187 this->base_ = 0;
188 return res;
191 ACE_HANDLE
192 ACE_TLI_Request_Queue::open (ACE_HANDLE f, int sz)
194 ACE_TRACE ("ACE_TLI_Request_Queue::open");
195 this->handle_ = f;
196 this->size_ = sz + 1; // Add one more for the dummy node.
198 ACE_NEW_RETURN (this->base_,
199 ACE_TLI_Request[this->size_],
200 ACE_INVALID_HANDLE);
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];
207 this->free (item);
209 item->handle_ = ACE_INVALID_HANDLE;
210 item->callp_ = (t_call *) ACE_OS::t_alloc (this->handle_,
211 T_CALL,
212 T_ALL);
213 if (item->callp_ == 0)
214 return ACE_INVALID_HANDLE;
217 this->tail_ = this->alloc ();
218 this->tail_->next_ = this->tail_;
219 return 0;
222 ACE_TLI_Request_Queue::ACE_TLI_Request_Queue ()
223 : size_ (0),
224 current_count_ (0),
225 base_ (0),
226 tail_ (0),
227 free_list_ (0)
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_;
242 int res;
245 res = ACE_OS::t_listen (this->handle_, req.callp_);
246 while (res == -1
247 && restart
248 && t_errno == TSYSERR
249 && errno == EINTR);
251 if (res != -1)
253 req.handle_ = open_new_endpoint (this->handle_,
254 device,
255 req.callp_,
256 rwflag);
257 if (req.handle_ != ACE_INVALID_HANDLE)
259 temp->next_ = this->tail_->next_;
260 this->tail_->next_ = temp;
261 this->tail_ = temp;
262 this->current_count_++;
263 return 0;
267 // Something must have gone wrong, so free up allocated space.
268 this->free (temp);
269 return -1;
272 // Locate and remove SEQUENCE_NUMBER from the list of pending
273 // connections.
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;
288 temp = temp->next_)
289 prev = temp;
291 if (temp == this->tail_)
292 // Sequence # was not found, since we're back at the dummy node!
293 return -1;
294 else
296 prev->next_ = temp->next_;
297 ACE_OS::t_close (temp->handle_);
298 this->current_count_--;
299 this->free (temp);
300 return 0;
304 ACE_HANDLE
305 ACE_TLI_Acceptor::open (const ACE_Addr &remote_sap,
306 int reuse_addr,
307 int oflag,
308 struct t_info *info,
309 int qlen,
310 const char dev[])
312 ACE_TRACE ("ACE_TLI_Acceptor::open");
313 ACE_HANDLE res = 0;
314 int one = 1;
316 this->disp_ = 0;
318 ACE_ALLOCATOR_RETURN (this->device_,
319 ACE_OS::strdup (dev),
320 ACE_INVALID_HANDLE);
321 if (this->ACE_TLI::open (dev,
322 oflag,
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).
331 else if (reuse_addr
332 && this->set_option (SOL_SOCKET,
333 SO_REUSEADDR,
334 &one,
335 sizeof one) == -1)
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 (),
340 T_DIS,
341 T_ALL)) == 0)
342 res = ACE_INVALID_HANDLE;
343 else
345 struct t_bind req;
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.
350 this->backlog_ = 1;
351 req.qlen = 1;
352 #else
353 this->backlog_ = qlen;
354 req.qlen = 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
360 // number.
361 req.addr.len = 0;
362 else
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 (),
369 &req,
371 if (res != ACE_INVALID_HANDLE)
373 ACE_NEW_RETURN (this->queue_,
374 ACE_TLI_Request_Queue,
375 ACE_INVALID_HANDLE);
376 res = this->queue_->open (this->get_handle (),
377 this->backlog_);
380 if (res == ACE_INVALID_HANDLE)
381 this->close ();
382 return this->get_handle ();
385 ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr &remote_sap,
386 int reuse_addr,
387 int oflag,
388 struct t_info *info,
389 int back,
390 const char dev[])
392 ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
393 if (this->open (remote_sap,
394 reuse_addr,
395 oflag,
396 info,
397 back,
398 dev) == ACE_INVALID_HANDLE)
399 ACELIB_ERROR ((LM_ERROR,
400 ACE_TEXT ("%p\n"),
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 ();
413 delete this->queue_;
416 ACE_OS::t_free ((char *) this->disp_, T_DIS);
417 ACE_OS::free (ACE_MALLOC_T (this->device_));
418 this->disp_ = 0;
419 this->device_ = 0;
420 return this->ACE_TLI::close ();
422 return 0;
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 ();
434 switch (event)
436 case T_DISCONNECT:
437 this->rcvdis (this->disp_);
438 this->queue_->remove (this->disp_->sequence);
439 break;
440 case T_LISTEN:
441 this->queue_->enqueue (this->device_,
442 restart,
443 rwf);
444 break;
445 default:
446 return -1;
448 return 0;
452 ACE_TLI_Acceptor::accept (ACE_TLI_Stream &new_tli_sap,
453 ACE_Addr *remote_addr,
454 ACE_Time_Value *timeout,
455 bool restart,
456 bool reset_new_handle,
457 int rwf,
458 netbuf *udata,
459 netbuf *opt)
461 ACE_TRACE ("ACE_TLI_Acceptor::accept");
462 ACE_UNUSED_ARG (reset_new_handle);
464 ACE_TLI_Request *req = 0;
465 int res = 0;
466 if (timeout != 0
467 && ACE::handle_timed_accept (this->get_handle (),
468 timeout,
469 restart) == -1)
470 return -1;
471 else if (this->queue_->is_empty ())
473 req = this->queue_->alloc ();
476 res = ACE_OS::t_listen (this->get_handle (),
477 req->callp_);
478 while (res == -1
479 && restart
480 && errno == EINTR);
482 if (res != -1)
484 req->handle_ = open_new_endpoint (this->get_handle (),
485 this->device_,
486 req->callp_,
488 #if defined (ACE_WIN32)
489 , remote_addr
490 #endif /* ACE_WIN32 */
492 if (req->handle_ == ACE_INVALID_HANDLE)
493 res = -1;
494 else
495 res = 0;
498 else
499 res = this->queue_->dequeue (req);
501 if (udata != 0)
502 ACE_OS::memcpy ((void *) &req->callp_->udata,
503 (void *) udata,
504 sizeof *udata);
505 if (opt != 0)
506 ACE_OS::memcpy ((void *) &req->callp_->opt,
507 (void *) opt,
508 sizeof *opt);
510 while (res != -1)
512 res = ACE_OS::t_accept (this->get_handle (),
513 req->handle_,
514 req->callp_);
515 if (res != -1)
516 break; // Got one!
517 else if (t_errno == TLOOK)
518 res = this->handle_async_event (restart, rwf);
519 else if (restart && t_errno == TSYSERR && errno == EINTR)
520 res = 0;
523 if (res == -1)
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_);
532 else
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 */