Restore build on FreeBSD.
[getmangos.git] / dep / ACE_wrappers / ace / TLI_Acceptor.cpp
bloba12b12d23ce710155caf33b631e48a509812dc52
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"
5 #include "ace/ACE.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_;
21 ACE_HANDLE handle_;
22 ACE_TLI_Request *next_;
25 class ACE_TLI_Request_Queue
27 public:
28 ACE_TLI_Request_Queue (void);
30 ACE_HANDLE open (ACE_HANDLE fd, int size);
31 int close (void);
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.
49 private:
50 ACE_HANDLE handle_;
51 int size_;
52 int current_count_;
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)
60 void
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 */
68 int
69 ACE_TLI_Request_Queue::is_empty (void) const
71 ACE_TRACE ("ACE_TLI_Request_Queue::is_empty");
72 return this->current_count_ == 0;
75 int
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.
84 void
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.
94 ACE_TLI_Request *
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_;
100 return temp;
103 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor)
105 void
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)
114 : queue_ (0)
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_--;
126 return 0;
129 // This is hideous...
131 static ACE_HANDLE
132 open_new_endpoint (ACE_HANDLE listen_handle,
133 const char dev[],
134 struct t_call *callp,
135 int rwf,
136 ACE_Addr *remote_sap = 0)
138 ACE_TRACE ("open_new_endpoint");
139 ACE_HANDLE fd = ACE_OS::t_open ((char *) dev,
140 O_RDWR,
143 struct t_bind req, *req_p = 0;
144 if (remote_sap != 0)
146 req.qlen = 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 ();
150 req_p = &req;
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,
158 I_PUSH,
159 const_cast<char *> ("tirdwr"))
160 == ACE_INVALID_HANDLE)
161 fd = ACE_INVALID_HANDLE;
162 #else
163 ACE_UNUSED_ARG(rwf);
164 #endif /* I_PUSH */
166 if (fd == ACE_INVALID_HANDLE)
167 ACE_OS::t_snddis (listen_handle,
168 callp);
169 return fd;
172 // Close down the acceptor and release resources.
175 ACE_TLI_Request_Queue::close (void)
177 ACE_TRACE ("ACE_TLI_Request_Queue::close");
178 int res = 0;
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_,
186 T_CALL) != 0)
187 res = -1;
190 delete [] this->base_;
191 this->base_ = 0;
192 return res;
195 ACE_HANDLE
196 ACE_TLI_Request_Queue::open (ACE_HANDLE f, int sz)
198 ACE_TRACE ("ACE_TLI_Request_Queue::open");
199 this->handle_ = f;
200 this->size_ = sz + 1; // Add one more for the dummy node.
202 ACE_NEW_RETURN (this->base_,
203 ACE_TLI_Request[this->size_],
204 ACE_INVALID_HANDLE);
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];
211 this->free (item);
213 item->handle_ = ACE_INVALID_HANDLE;
214 item->callp_ = (t_call *) ACE_OS::t_alloc (this->handle_,
215 T_CALL,
216 T_ALL);
217 if (item->callp_ == 0)
218 return ACE_INVALID_HANDLE;
221 this->tail_ = this->alloc ();
222 this->tail_->next_ = this->tail_;
223 return 0;
226 ACE_TLI_Request_Queue::ACE_TLI_Request_Queue (void)
227 : size_ (0),
228 current_count_ (0),
229 base_ (0),
230 tail_ (0),
231 free_list_ (0)
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_;
246 int res;
249 res = ACE_OS::t_listen (this->handle_, req.callp_);
250 while (res == -1
251 && restart
252 && t_errno == TSYSERR
253 && errno == EINTR);
255 if (res != -1)
257 req.handle_ = open_new_endpoint (this->handle_,
258 device,
259 req.callp_,
260 rwflag);
261 if (req.handle_ != ACE_INVALID_HANDLE)
263 temp->next_ = this->tail_->next_;
264 this->tail_->next_ = temp;
265 this->tail_ = temp;
266 this->current_count_++;
267 return 0;
271 // Something must have gone wrong, so free up allocated space.
272 this->free (temp);
273 return -1;
276 // Locate and remove SEQUENCE_NUMBER from the list of pending
277 // connections.
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;
292 temp = temp->next_)
293 prev = temp;
295 if (temp == this->tail_)
296 // Sequence # was not found, since we're back at the dummy node!
297 return -1;
298 else
300 prev->next_ = temp->next_;
301 ACE_OS::t_close (temp->handle_);
302 this->current_count_--;
303 this->free (temp);
304 return 0;
308 ACE_HANDLE
309 ACE_TLI_Acceptor::open (const ACE_Addr &remote_sap,
310 int reuse_addr,
311 int oflag,
312 struct t_info *info,
313 int qlen,
314 const char dev[])
316 ACE_TRACE ("ACE_TLI_Acceptor::open");
317 ACE_HANDLE res = 0;
318 int one = 1;
320 this->disp_ = 0;
322 ACE_ALLOCATOR_RETURN (this->device_,
323 ACE_OS::strdup (dev),
324 ACE_INVALID_HANDLE);
325 if (this->ACE_TLI::open (dev,
326 oflag,
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).
335 else if (reuse_addr
336 && this->set_option (SOL_SOCKET,
337 SO_REUSEADDR,
338 &one,
339 sizeof one) == -1)
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 (),
344 T_DIS,
345 T_ALL)) == 0)
346 res = ACE_INVALID_HANDLE;
347 else
349 struct t_bind req;
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.
354 this->backlog_ = 1;
355 req.qlen = 1;
356 #else
357 this->backlog_ = qlen;
358 req.qlen = 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
364 // number.
365 req.addr.len = 0;
366 else
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 (),
373 &req,
375 if (res != ACE_INVALID_HANDLE)
377 ACE_NEW_RETURN (this->queue_,
378 ACE_TLI_Request_Queue,
379 ACE_INVALID_HANDLE);
380 res = this->queue_->open (this->get_handle (),
381 this->backlog_);
384 if (res == ACE_INVALID_HANDLE)
385 this->close ();
386 return this->get_handle ();
389 ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr &remote_sap,
390 int reuse_addr,
391 int oflag,
392 struct t_info *info,
393 int back,
394 const char dev[])
396 ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
397 if (this->open (remote_sap,
398 reuse_addr,
399 oflag,
400 info,
401 back,
402 dev) == ACE_INVALID_HANDLE)
403 ACE_ERROR ((LM_ERROR,
404 ACE_TEXT ("%p\n"),
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 ();
417 delete this->queue_;
420 ACE_OS::t_free ((char *) this->disp_, T_DIS);
421 ACE_OS::free (ACE_MALLOC_T (this->device_));
422 this->disp_ = 0;
423 this->device_ = 0;
424 return this->ACE_TLI::close ();
426 return 0;
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 ();
438 switch (event)
440 case T_DISCONNECT:
441 this->rcvdis (this->disp_);
442 this->queue_->remove (this->disp_->sequence);
443 break;
444 case T_LISTEN:
445 this->queue_->enqueue (this->device_,
446 restart,
447 rwf);
448 break;
449 default:
450 return -1;
452 return 0;
456 ACE_TLI_Acceptor::accept (ACE_TLI_Stream &new_tli_sap,
457 ACE_Addr *remote_addr,
458 ACE_Time_Value *timeout,
459 int restart,
460 int reset_new_handle,
461 int rwf,
462 netbuf *udata,
463 netbuf *opt)
465 ACE_TRACE ("ACE_TLI_Acceptor::accept");
466 ACE_UNUSED_ARG (reset_new_handle);
468 ACE_TLI_Request *req = 0;
469 int res = 0;
470 if (timeout != 0
471 && ACE::handle_timed_accept (this->get_handle (),
472 timeout,
473 restart) == -1)
474 return -1;
475 else if (this->queue_->is_empty ())
477 req = this->queue_->alloc ();
480 res = ACE_OS::t_listen (this->get_handle (),
481 req->callp_);
482 while (res == -1
483 && restart
484 && errno == EINTR);
486 if (res != -1)
488 req->handle_ = open_new_endpoint (this->get_handle (),
489 this->device_,
490 req->callp_,
492 #if defined (ACE_WIN32)
493 , remote_addr
494 #endif /* ACE_WIN32 */
496 if (req->handle_ == ACE_INVALID_HANDLE)
497 res = -1;
498 else
499 res = 0;
502 else
503 res = this->queue_->dequeue (req);
505 if (udata != 0)
506 ACE_OS::memcpy ((void *) &req->callp_->udata,
507 (void *) udata,
508 sizeof *udata);
509 if (opt != 0)
510 ACE_OS::memcpy ((void *) &req->callp_->opt,
511 (void *) opt,
512 sizeof *opt);
514 while (res != -1)
516 res = ACE_OS::t_accept (this->get_handle (),
517 req->handle_,
518 req->callp_);
519 if (res != -1)
520 break; // Got one!
521 else if (t_errno == TLOOK)
522 res = this->handle_async_event (restart, rwf);
523 else if (restart && t_errno == TSYSERR && errno == EINTR)
524 res = 0;
527 if (res == -1)
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_);
536 else
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 */