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