00001
00002
00003 #include "ace/TLI_Acceptor.h"
00004 #include "ace/Log_Msg.h"
00005 #include "ace/ACE.h"
00006 #include "ace/OS_NS_string.h"
00007 #include "ace/OS_Memory.h"
00008
00009 ACE_RCSID(ace, TLI_Acceptor, "$Id: TLI_Acceptor.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00010
00011 #if defined (ACE_HAS_TLI)
00012
00013 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00014
00015
00016
00017
00018 struct ACE_TLI_Request
00019 {
00020 struct t_call *callp_;
00021 ACE_HANDLE handle_;
00022 ACE_TLI_Request *next_;
00023 };
00024
00025 class ACE_TLI_Request_Queue
00026 {
00027 public:
00028 ACE_TLI_Request_Queue (void);
00029
00030 ACE_HANDLE open (ACE_HANDLE fd, int size);
00031 int close (void);
00032
00033 int enqueue (const char device[], int restart, int rwflag);
00034 int dequeue (ACE_TLI_Request *&ptr);
00035 int remove (int sequence_number);
00036
00037 int is_empty (void) const;
00038 int is_full (void) const;
00039
00040 ACE_TLI_Request *alloc (void);
00041 void free (ACE_TLI_Request *node);
00042
00043 void dump (void) const;
00044
00045
00046 ACE_ALLOC_HOOK_DECLARE;
00047
00048
00049 private:
00050 ACE_HANDLE handle_;
00051 int size_;
00052 int current_count_;
00053 ACE_TLI_Request *base_;
00054 ACE_TLI_Request *tail_;
00055 ACE_TLI_Request *free_list_;
00056 };
00057
00058 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Request_Queue)
00059
00060 void
00061 ACE_TLI_Request_Queue::dump (void) const
00062 {
00063 #if defined (ACE_HAS_DUMP)
00064 ACE_TRACE ("ACE_TLI_Request_Queue::dump");
00065 #endif
00066 }
00067
00068 int
00069 ACE_TLI_Request_Queue::is_empty (void) const
00070 {
00071 ACE_TRACE ("ACE_TLI_Request_Queue::is_empty");
00072 return this->current_count_ == 0;
00073 }
00074
00075 int
00076 ACE_TLI_Request_Queue::is_full (void) const
00077 {
00078 ACE_TRACE ("ACE_TLI_Request_Queue::is_full");
00079 return this->current_count_ + 1 == this->size_;
00080 }
00081
00082
00083
00084 void
00085 ACE_TLI_Request_Queue::free (ACE_TLI_Request *node)
00086 {
00087 ACE_TRACE ("ACE_TLI_Request_Queue::free");
00088 node->next_ = this->free_list_;
00089 this->free_list_ = node;
00090 }
00091
00092
00093
00094 ACE_TLI_Request *
00095 ACE_TLI_Request_Queue::alloc (void)
00096 {
00097 ACE_TRACE ("ACE_TLI_Request_Queue::alloc");
00098 ACE_TLI_Request *temp = this->free_list_;
00099 this->free_list_ = this->free_list_->next_;
00100 return temp;
00101 }
00102
00103 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Acceptor)
00104
00105 void
00106 ACE_TLI_Acceptor::dump (void) const
00107 {
00108 #if defined (ACE_HAS_DUMP)
00109 ACE_TRACE ("ACE_TLI_Acceptor::dump");
00110 #endif
00111 }
00112
00113 ACE_TLI_Acceptor::ACE_TLI_Acceptor (void)
00114 : queue_ (0)
00115 {
00116 ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
00117 }
00118
00119 int
00120 ACE_TLI_Request_Queue::dequeue (ACE_TLI_Request *&ptr)
00121 {
00122 ACE_TRACE ("ACE_TLI_Request_Queue::dequeue");
00123 ptr = this->tail_->next_;
00124 this->tail_->next_ = ptr->next_;
00125 this->current_count_--;
00126 return 0;
00127 }
00128
00129
00130
00131 static ACE_HANDLE
00132 open_new_endpoint (ACE_HANDLE listen_handle,
00133 const char dev[],
00134 struct t_call *callp,
00135 int rwf,
00136 ACE_Addr *remote_sap = 0)
00137 {
00138 ACE_TRACE ("open_new_endpoint");
00139 ACE_HANDLE fd = ACE_OS::t_open ((char *) dev,
00140 O_RDWR,
00141 0);
00142
00143 struct t_bind req, *req_p = 0;
00144 if (remote_sap != 0)
00145 {
00146 req.qlen = 0;
00147 req.addr.buf = (char *) remote_sap->get_addr ();
00148 req.addr.len = remote_sap->get_size ();
00149 req.addr.maxlen = remote_sap->get_size ();
00150 req_p = &req;
00151 }
00152
00153 if (fd == ACE_INVALID_HANDLE
00154 || ACE_OS::t_bind (fd, req_p, 0) == -1)
00155 fd = ACE_INVALID_HANDLE;
00156 #if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
00157 else if (rwf != 0 && ACE_OS::ioctl (fd,
00158 I_PUSH,
00159 const_cast<char *> ("tirdwr"))
00160 == ACE_INVALID_HANDLE)
00161 fd = ACE_INVALID_HANDLE;
00162 #else
00163 ACE_UNUSED_ARG(rwf);
00164 #endif
00165
00166 if (fd == ACE_INVALID_HANDLE)
00167 ACE_OS::t_snddis (listen_handle,
00168 callp);
00169 return fd;
00170 }
00171
00172
00173
00174 int
00175 ACE_TLI_Request_Queue::close (void)
00176 {
00177 ACE_TRACE ("ACE_TLI_Request_Queue::close");
00178 int res = 0;
00179
00180 for (int i = 0; i < this->size_; i++)
00181 {
00182 ACE_TLI_Request &item = this->base_[i];
00183
00184 item.handle_ = ACE_INVALID_HANDLE;
00185 if (ACE_OS::t_free ((char *) item.callp_,
00186 T_CALL) != 0)
00187 res = -1;
00188 }
00189
00190 delete [] this->base_;
00191 this->base_ = 0;
00192 return res;
00193 }
00194
00195 ACE_HANDLE
00196 ACE_TLI_Request_Queue::open (ACE_HANDLE f, int sz)
00197 {
00198 ACE_TRACE ("ACE_TLI_Request_Queue::open");
00199 this->handle_ = f;
00200 this->size_ = sz + 1;
00201
00202 ACE_NEW_RETURN (this->base_,
00203 ACE_TLI_Request[this->size_],
00204 ACE_INVALID_HANDLE);
00205
00206
00207
00208 for (int i = 0; i < this->size_; i++)
00209 {
00210 ACE_TLI_Request *item = &this->base_[i];
00211 this->free (item);
00212
00213 item->handle_ = ACE_INVALID_HANDLE;
00214 item->callp_ = (t_call *) ACE_OS::t_alloc (this->handle_,
00215 T_CALL,
00216 T_ALL);
00217 if (item->callp_ == 0)
00218 return ACE_INVALID_HANDLE;
00219 }
00220
00221 this->tail_ = this->alloc ();
00222 this->tail_->next_ = this->tail_;
00223 return 0;
00224 }
00225
00226 ACE_TLI_Request_Queue::ACE_TLI_Request_Queue (void)
00227 : size_ (0),
00228 current_count_ (0),
00229 base_ (0),
00230 tail_ (0),
00231 free_list_ (0)
00232 {
00233 ACE_TRACE ("ACE_TLI_Request_Queue::ACE_TLI_Request_Queue");
00234 }
00235
00236
00237
00238
00239 int
00240 ACE_TLI_Request_Queue::enqueue (const char device[],
00241 int restart, int rwflag)
00242 {
00243 ACE_TRACE ("ACE_TLI_Request_Queue::enqueue");
00244 ACE_TLI_Request *temp = this->alloc ();
00245 ACE_TLI_Request &req = *this->tail_;
00246 int res;
00247
00248 do
00249 res = ACE_OS::t_listen (this->handle_, req.callp_);
00250 while (res == -1
00251 && restart
00252 && t_errno == TSYSERR
00253 && errno == EINTR);
00254
00255 if (res != -1)
00256 {
00257 req.handle_ = open_new_endpoint (this->handle_,
00258 device,
00259 req.callp_,
00260 rwflag);
00261 if (req.handle_ != ACE_INVALID_HANDLE)
00262 {
00263 temp->next_ = this->tail_->next_;
00264 this->tail_->next_ = temp;
00265 this->tail_ = temp;
00266 this->current_count_++;
00267 return 0;
00268 }
00269 }
00270
00271
00272 this->free (temp);
00273 return -1;
00274 }
00275
00276
00277
00278
00279 int
00280 ACE_TLI_Request_Queue::remove (int sequence_number)
00281 {
00282 ACE_TRACE ("ACE_TLI_Request_Queue::remove");
00283 ACE_TLI_Request *prev = this->tail_;
00284
00285
00286 prev->callp_->sequence = sequence_number;
00287
00288 ACE_TLI_Request *temp;
00289
00290 for (temp = this->tail_->next_;
00291 temp->callp_->sequence != sequence_number;
00292 temp = temp->next_)
00293 prev = temp;
00294
00295 if (temp == this->tail_)
00296
00297 return -1;
00298 else
00299 {
00300 prev->next_ = temp->next_;
00301 ACE_OS::t_close (temp->handle_);
00302 this->current_count_--;
00303 this->free (temp);
00304 return 0;
00305 }
00306 }
00307
00308 ACE_HANDLE
00309 ACE_TLI_Acceptor::open (const ACE_Addr &remote_sap,
00310 int reuse_addr,
00311 int oflag,
00312 struct t_info *info,
00313 int qlen,
00314 const char dev[])
00315 {
00316 ACE_TRACE ("ACE_TLI_Acceptor::open");
00317 ACE_HANDLE res = 0;
00318 int one = 1;
00319
00320 this->disp_ = 0;
00321
00322 ACE_ALLOCATOR_RETURN (this->device_,
00323 ACE_OS::strdup (dev),
00324 ACE_INVALID_HANDLE);
00325 if (this->ACE_TLI::open (dev,
00326 oflag,
00327 info) == ACE_INVALID_HANDLE)
00328 res = ACE_INVALID_HANDLE;
00329 #if !defined (ACE_HAS_FORE_ATM_XTI)
00330
00331
00332
00333
00334
00335 else if (reuse_addr
00336 && this->set_option (SOL_SOCKET,
00337 SO_REUSEADDR,
00338 &one,
00339 sizeof one) == -1)
00340 res = ACE_INVALID_HANDLE;
00341 #endif
00342 else if ((this->disp_ =
00343 (struct t_discon *) ACE_OS::t_alloc (this->get_handle (),
00344 T_DIS,
00345 T_ALL)) == 0)
00346 res = ACE_INVALID_HANDLE;
00347 else
00348 {
00349 struct t_bind req;
00350
00351 #if defined (ACE_HAS_FORE_ATM_XTI)
00352
00353
00354 this->backlog_ = 1;
00355 req.qlen = 1;
00356 #else
00357 this->backlog_ = qlen;
00358 req.qlen = qlen;
00359 #endif
00360 req.addr.maxlen = remote_sap.get_size ();
00361
00362 if (remote_sap == ACE_Addr::sap_any)
00363
00364
00365 req.addr.len = 0;
00366 else
00367 {
00368 req.addr.buf = (char *) remote_sap.get_addr ();
00369 req.addr.len = remote_sap.get_size ();
00370 }
00371
00372 res = (ACE_HANDLE) ACE_OS::t_bind (this->get_handle (),
00373 &req,
00374 0);
00375 if (res != ACE_INVALID_HANDLE)
00376 {
00377 ACE_NEW_RETURN (this->queue_,
00378 ACE_TLI_Request_Queue,
00379 ACE_INVALID_HANDLE);
00380 res = this->queue_->open (this->get_handle (),
00381 this->backlog_);
00382 }
00383 }
00384 if (res == ACE_INVALID_HANDLE)
00385 this->close ();
00386 return this->get_handle ();
00387 }
00388
00389 ACE_TLI_Acceptor::ACE_TLI_Acceptor (const ACE_Addr &remote_sap,
00390 int reuse_addr,
00391 int oflag,
00392 struct t_info *info,
00393 int back,
00394 const char dev[])
00395 {
00396 ACE_TRACE ("ACE_TLI_Acceptor::ACE_TLI_Acceptor");
00397 if (this->open (remote_sap,
00398 reuse_addr,
00399 oflag,
00400 info,
00401 back,
00402 dev) == ACE_INVALID_HANDLE)
00403 ACE_ERROR ((LM_ERROR,
00404 ACE_TEXT ("%p\n"),
00405 ACE_TEXT ("ACE_TLI_Acceptor::ACE_TLI_Acceptor")));
00406 }
00407
00408 int
00409 ACE_TLI_Acceptor::close (void)
00410 {
00411 ACE_TRACE ("ACE_TLI_Acceptor::close");
00412 if (this->device_ != 0)
00413 {
00414 if (this->queue_ != 0)
00415 {
00416 this->queue_->close ();
00417 delete this->queue_;
00418 }
00419
00420 ACE_OS::t_free ((char *) this->disp_, T_DIS);
00421 ACE_OS::free (ACE_MALLOC_T (this->device_));
00422 this->disp_ = 0;
00423 this->device_ = 0;
00424 return this->ACE_TLI::close ();
00425 }
00426 return 0;
00427 }
00428
00429
00430
00431
00432 int
00433 ACE_TLI_Acceptor::handle_async_event (int restart, int rwf)
00434 {
00435 ACE_TRACE ("ACE_TLI_Acceptor::handle_async_event");
00436 int event = this->look ();
00437
00438 switch (event)
00439 {
00440 case T_DISCONNECT:
00441 this->rcvdis (this->disp_);
00442 this->queue_->remove (this->disp_->sequence);
00443 break;
00444 case T_LISTEN:
00445 this->queue_->enqueue (this->device_,
00446 restart,
00447 rwf);
00448 break;
00449 default:
00450 return -1;
00451 }
00452 return 0;
00453 }
00454
00455 int
00456 ACE_TLI_Acceptor::accept (ACE_TLI_Stream &new_tli_sap,
00457 ACE_Addr *remote_addr,
00458 ACE_Time_Value *timeout,
00459 int restart,
00460 int reset_new_handle,
00461 int rwf,
00462 netbuf *udata,
00463 netbuf *opt)
00464 {
00465 ACE_TRACE ("ACE_TLI_Acceptor::accept");
00466 ACE_UNUSED_ARG (reset_new_handle);
00467
00468 ACE_TLI_Request *req = 0;
00469 int res = 0;
00470 if (timeout != 0
00471 && ACE::handle_timed_accept (this->get_handle (),
00472 timeout,
00473 restart) == -1)
00474 return -1;
00475 else if (this->queue_->is_empty ())
00476 {
00477 req = this->queue_->alloc ();
00478
00479 do
00480 res = ACE_OS::t_listen (this->get_handle (),
00481 req->callp_);
00482 while (res == -1
00483 && restart
00484 && errno == EINTR);
00485
00486 if (res != -1)
00487 {
00488 req->handle_ = open_new_endpoint (this->get_handle (),
00489 this->device_,
00490 req->callp_,
00491 rwf
00492 #if defined (ACE_WIN32)
00493 , remote_addr
00494 #endif
00495 );
00496 if (req->handle_ == ACE_INVALID_HANDLE)
00497 res = -1;
00498 else
00499 res = 0;
00500 }
00501 }
00502 else
00503 res = this->queue_->dequeue (req);
00504
00505 if (udata != 0)
00506 ACE_OS::memcpy ((void *) &req->callp_->udata,
00507 (void *) udata,
00508 sizeof *udata);
00509 if (opt != 0)
00510 ACE_OS::memcpy ((void *) &req->callp_->opt,
00511 (void *) opt,
00512 sizeof *opt);
00513
00514 while (res != -1)
00515 {
00516 res = ACE_OS::t_accept (this->get_handle (),
00517 req->handle_,
00518 req->callp_);
00519 if (res != -1)
00520 break;
00521 else if (t_errno == TLOOK)
00522 res = this->handle_async_event (restart, rwf);
00523 else if (restart && t_errno == TSYSERR && errno == EINTR)
00524 res = 0;
00525 }
00526
00527 if (res == -1)
00528 {
00529 if (errno != EWOULDBLOCK)
00530 {
00531 new_tli_sap.set_handle (ACE_INVALID_HANDLE);
00532 if (req->handle_ != ACE_INVALID_HANDLE)
00533 ACE_OS::t_close (req->handle_);
00534 }
00535 }
00536 else
00537 {
00538 new_tli_sap.set_handle (req->handle_);
00539
00540 if (remote_addr != 0)
00541 remote_addr->set_addr ((void *) req->callp_->addr.buf,
00542 req->callp_->addr.len);
00543 }
00544
00545 req->handle_ = ACE_INVALID_HANDLE;
00546 this->queue_->free (req);
00547 new_tli_sap.set_rwflag (rwf);
00548 return new_tli_sap.get_handle () == ACE_INVALID_HANDLE ? -1 : 0;
00549 }
00550
00551 ACE_END_VERSIONED_NAMESPACE_DECL
00552
00553 #endif