Merge pull request #2301 from sonndinh/remove-dup-reactor-functions
[ACE_TAO.git] / ACE / netsvcs / lib / Name_Handler.cpp
blobc0418fe8e2553781ffd94b2021c378a644548ca7
1 #include "ace/Containers.h"
2 #include "ace/Get_Opt.h"
3 #include "ace/Singleton.h"
4 #include <memory>
5 #include "Name_Handler.h"
6 #include "ace/Signal.h"
7 #include "ace/OS_NS_string.h"
9 // Simple macro that does bitwise AND -- useful in table lookup
10 #define ACE_TABLE_MAP(INDEX, MASK) (INDEX & MASK)
12 // Simple macro that does bitwise AND and then right shift bits by 3
13 #define ACE_LIST_MAP(INDEX, MASK) (((unsigned long) (INDEX & MASK)) >> 3)
15 int
16 ACE_Name_Acceptor::parse_args (int argc, ACE_TCHAR *argv[])
18 ACE_TRACE ("ACE_Name_Acceptor::parse_args");
20 int service_port = ACE_DEFAULT_SERVER_PORT;
22 ACE_LOG_MSG->open (ACE_TEXT ("Name Service"));
24 this->naming_context()->name_options()->parse_args( argc, argv );
25 service_port = this->naming_context()->name_options()->nameserver_port();
27 // dont allow to connect to another name serever
28 if(this->naming_context()->name_options()->context() == ACE_Naming_Context::NET_LOCAL)
29 this->naming_context()->name_options()->nameserver_host(ACE_TEXT ("localhost"));
31 if (this->naming_context()->open( this->naming_context()->name_options()->context() ) == -1)
32 ACE_ERROR_RETURN ((LM_ERROR,
33 ACE_TEXT ("%n:\n open naming context failed.\n")),
34 -1);
36 this->service_addr_.set (service_port);
37 return 0;
40 int
41 ACE_Name_Acceptor::init (int argc, ACE_TCHAR *argv[])
43 ACE_TRACE ("ACE_Name_Acceptor::init");
45 // Use the options hook to parse the command line arguments and set
46 // options.
47 if( this->parse_args (argc, argv) == -1 )
48 ACE_ERROR_RETURN ((LM_ERROR,
49 ACE_TEXT ("%p\n"),
50 ACE_TEXT ("ACE_Name_Acceptor::parse_args failed")),
51 -1);
53 // Set the acceptor endpoint into listen mode (use the Singleton
54 // global Reactor...).
55 if (this->open (this->service_addr_,
56 ACE_Reactor::instance (),
57 0, 0, 0,
58 &this->scheduling_strategy_,
59 ACE_TEXT ("Name Server"),
60 ACE_TEXT ("ACE naming service")) == -1)
61 ACE_ERROR_RETURN ((LM_ERROR,
62 ACE_TEXT ("%n: %p on port %d\n"),
63 ACE_TEXT ("acceptor::open failed"),
64 this->service_addr_.get_port_number ()),
65 -1);
67 // Ignore SIGPIPE so that each <SVC_HANDLER> can handle this on its
68 // own.
69 ACE_Sig_Action sig ((ACE_SignalHandler) SIG_IGN, SIGPIPE);
70 ACE_UNUSED_ARG (sig);
72 ACE_INET_Addr server_addr;
74 // Figure out what port we're really bound to.
75 if (this->acceptor ().get_local_addr (server_addr) == -1)
76 ACE_ERROR_RETURN ((LM_ERROR,
77 ACE_TEXT ("%p\n"),
78 ACE_TEXT ("get_local_addr")),
79 -1);
81 ACE_DEBUG ((LM_DEBUG,
82 ACE_TEXT ("starting up Name Server at port %d on handle %d\n"),
83 server_addr.get_port_number (),
84 this->acceptor ().get_handle ()));
85 return 0;
88 // The following is a "Factory" used by the ACE_Service_Config and
89 // svc.conf file to dynamically initialize the state of the Naming
90 // Server.
92 ACE_SVC_FACTORY_DEFINE (ACE_Name_Acceptor)
94 // Default constructor.
95 ACE_Name_Handler::ACE_Name_Handler (ACE_Thread_Manager *tm)
96 : ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> (tm)
98 ACE_TRACE ("ACE_Name_Handler::ACE_Name_Handler");
100 // Set up pointers to member functions for the top-level dispatching
101 // of client requests.
102 this->op_table_[ACE_Name_Request::BIND] = &ACE_Name_Handler::bind;
103 this->op_table_[ACE_Name_Request::REBIND] = &ACE_Name_Handler::rebind;
104 this->op_table_[ACE_Name_Request::RESOLVE] = &ACE_Name_Handler::resolve;
105 this->op_table_[ACE_Name_Request::UNBIND] = &ACE_Name_Handler::unbind;
106 this->op_table_[ACE_Name_Request::LIST_NAMES] = &ACE_Name_Handler::lists;
107 this->op_table_[ACE_Name_Request::LIST_NAME_ENTRIES] = &ACE_Name_Handler::lists_entries;
109 // Assign references to simplify subsequent code.
110 LIST_ENTRY &list_names_ref = this->list_table_[ACE_LIST_MAP (ACE_Name_Request::LIST_NAMES,
111 ACE_Name_Request::LIST_OP_MASK)];
112 LIST_ENTRY &list_values_ref = this->list_table_[ACE_LIST_MAP (ACE_Name_Request::LIST_VALUES,
113 ACE_Name_Request::LIST_OP_MASK)];
114 LIST_ENTRY &list_types_ref = this->list_table_[ACE_LIST_MAP (ACE_Name_Request::LIST_TYPES,
115 ACE_Name_Request::LIST_OP_MASK)];
117 // Set up pointers to member functions for dispatching within the
118 // LIST_{NAMES,VALUES,TYPES} methods.
120 list_names_ref.operation_ = &ACE_Naming_Context::list_names;
121 list_names_ref.request_factory_ = &ACE_Name_Handler::name_request;
122 list_names_ref.description_ = "request for LIST_NAMES\n";
124 list_values_ref.operation_ = &ACE_Naming_Context::list_values;
125 list_values_ref.request_factory_ = &ACE_Name_Handler::value_request;
126 list_values_ref.description_ = "request for LIST_VALUES\n";
128 list_types_ref.operation_ = &ACE_Naming_Context::list_types;
129 list_types_ref.request_factory_ = &ACE_Name_Handler::type_request;
130 list_types_ref.description_ = "request for LIST_TYPES\n";
133 // Activate this instance of the ACE_Name_Handler (called by the
134 // ACE_Name_Acceptor).
136 /* VIRTUAL */ int
137 ACE_Name_Handler::open (void * v)
139 ACE_TRACE ("ACE_Name_Handler::open");
141 // Call down to our parent to register ourselves with the Reactor.
142 if (ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>::open (0) == -1)
143 ACE_ERROR_RETURN ((LM_ERROR,
144 ACE_TEXT ("%p\n"),
145 ACE_TEXT ("open")),
146 -1);
148 ACE_Name_Acceptor* acceptor_ = static_cast<ACE_Name_Acceptor*>(v);
149 naming_context_ = acceptor_->naming_context();
151 return 0;
154 // Create and send a reply to the client.
156 /* VIRTUAL */ int
157 ACE_Name_Handler::send_reply (ACE_INT32 status,
158 ACE_UINT32 err)
160 ACE_TRACE ("ACE_Name_Handler::send_reply");
161 void *buf;
162 this->name_reply_.msg_type (status);
163 this->name_reply_.errnum (err);
165 this->name_reply_.init ();
166 int len = this->name_reply_.encode (buf);
168 if (len == -1)
169 return -1;
171 ssize_t n = this->peer ().send (buf, len);
173 if (n != len)
174 ACE_ERROR_RETURN ((LM_ERROR,
175 ACE_TEXT ("%p\n, expected len = %d, actual len = %d"),
176 ACE_TEXT ("send failed"),
177 len,
179 -1);
180 else
181 return 0;
184 /* VIRTUAL */ int
185 ACE_Name_Handler::send_request (ACE_Name_Request &request)
187 ACE_TRACE ("ACE_Name_Handler::send_request");
188 void *buffer;
189 ssize_t length = request.encode (buffer);
191 if (length == -1)
192 ACE_ERROR_RETURN ((LM_ERROR,
193 ACE_TEXT ("%p\n"),
194 ACE_TEXT ("encode failed")),
195 -1);
196 // Transmit request via a blocking send.
198 if (this->peer ().send_n (buffer, length) != length)
199 ACE_ERROR_RETURN ((LM_ERROR,
200 ACE_TEXT ("%p\n"),
201 ACE_TEXT ("send_n failed")),
202 -1);
203 return 0;
206 // Give up waiting (e.g., when a timeout occurs or a client shuts down
207 // unexpectedly).
209 /* VIRTUAL */ int
210 ACE_Name_Handler::abandon ()
212 ACE_TRACE ("ACE_Name_Handler::abandon");
213 return this->send_reply (-1, errno);
216 // Enable clients to limit the amount of time they'll wait
218 /* VIRTUAL */ int
219 ACE_Name_Handler::handle_timeout (const ACE_Time_Value &, const void *)
221 ACE_TRACE ("ACE_Name_Handler::handle_timeout");
222 return this->abandon ();
225 // Return the underlying ACE_HANDLE.
227 /* VIRTUAL */ ACE_HANDLE
228 ACE_Name_Handler::get_handle () const
230 ACE_TRACE ("ACE_Name_Handler::get_handle");
231 return this->peer ().get_handle ();
234 // Dispatch the appropriate operation to handle the client request.
236 /* VIRTUAL */ int
237 ACE_Name_Handler::dispatch ()
239 ACE_TRACE ("ACE_Name_Handler::dispatch");
240 // Dispatch the appropriate request.
241 int index = this->name_request_.msg_type ();
243 // Invoke the appropriate member function obtained by indexing into
244 // the op_table_. ACE_TABLE_MAP returns the same index (by bitwise
245 // AND) for list_names, list_values, and list_types since they are
246 // all handled by the same method. Similarly, it returns the same
247 // index for list_name_entries, list_value_entries, and
248 // list_type_entries.
249 return (this->*op_table_[ACE_TABLE_MAP (index,
250 ACE_Name_Request::OP_TABLE_MASK)]) ();
253 // Receive, frame, and decode the client's request. Note, this method
254 // should use non-blocking I/O.
256 /* VIRTUAL */ int
257 ACE_Name_Handler::recv_request ()
259 ACE_TRACE ("ACE_Name_Handler::recv_request");
260 // Read the first 4 bytes to get the length of the message This
261 // implementation assumes that the first 4 bytes are the length of
262 // the message.
263 ssize_t n = this->peer ().recv ((void *) &this->name_request_,
264 sizeof (ACE_UINT32));
265 switch (n)
267 case -1:
268 ACE_DEBUG ((LM_DEBUG,
269 ACE_TEXT ("****************** recv_request returned -1\n")));
270 ACE_FALLTHROUGH;
271 default:
272 ACE_ERROR ((LM_ERROR,
273 ACE_TEXT ("%p got %d bytes, expected %d bytes\n"),
274 ACE_TEXT ("recv failed"),
276 sizeof (ACE_UINT32)));
277 ACE_FALLTHROUGH;
278 case 0:
279 // We've shutdown unexpectedly, let's abandon the connection.
280 this->abandon ();
281 return -1;
282 /* NOTREACHED */
283 case sizeof (ACE_UINT32):
285 // Transform the length into host byte order.
286 ssize_t length = ACE_NTOHL (this->name_request_.length ());
288 // Do a sanity check on the length of the message.
289 if (length > (ssize_t) sizeof this->name_request_)
291 ACE_ERROR ((LM_ERROR,
292 ACE_TEXT ("length %d too long\n"),
293 length));
294 return this->abandon ();
297 // Receive the rest of the request message.
298 // @@ beware of blocking read!!!.
299 n = this->peer ().recv ((void *) (((char *) &this->name_request_)
300 + sizeof (ACE_UINT32)),
301 length - sizeof (ACE_UINT32));
303 // Subtract off the size of the part we skipped over...
304 if (n != (length - (ssize_t) sizeof (ACE_UINT32)))
306 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p expected %d, got %d\n"),
307 ACE_TEXT ("invalid length"), length, n));
308 return this->abandon ();
311 // Decode the request into host byte order.
312 if (this->name_request_.decode () == -1)
314 ACE_ERROR ((LM_ERROR,
315 ACE_TEXT ("%p\n"),
316 ACE_TEXT ("decode failed")));
317 return this->abandon ();
321 return 0;
324 // Callback method invoked by the ACE_Reactor when events arrive from
325 // the client.
327 /* VIRTUAL */ int
328 ACE_Name_Handler::handle_input (ACE_HANDLE)
330 ACE_TRACE ("ACE_Name_Handler::handle_input");
332 if (this->recv_request () == -1)
333 return -1;
334 else
335 return this->dispatch ();
339 ACE_Name_Handler::bind ()
341 ACE_TRACE ("ACE_Name_Handler::bind");
342 return this->shared_bind (0);
346 ACE_Name_Handler::rebind ()
348 ACE_TRACE ("ACE_Name_Handler::rebind");
349 int result = this->shared_bind (1);
350 return result == 1 ? 0 : result;
354 ACE_Name_Handler::shared_bind (int rebind)
356 ACE_TRACE ("ACE_Name_Handler::shared_bind");
357 ACE_NS_WString a_name (this->name_request_.name (),
358 this->name_request_.name_len () / sizeof (ACE_WCHAR_T));
359 ACE_NS_WString a_value (this->name_request_.value (),
360 this->name_request_.value_len () / sizeof (ACE_WCHAR_T));
361 int result;
362 if (rebind == 0)
364 #if 0
365 ACE_DEBUG ((LM_DEBUG,
366 ACE_TEXT ("request for BIND\n")));
367 #endif /* 0 */
368 result = this->naming_context ()->bind (a_name,
369 a_value,
370 this->name_request_.type ());
372 else
374 #if 0
375 ACE_DEBUG ((LM_DEBUG,
376 ACE_TEXT ("request for REBIND\n")));
377 #endif /* 0 */
378 result = this->naming_context ()->rebind (a_name,
379 a_value,
380 this->name_request_.type ());
381 if (result == 1)
382 result = 0;
384 if (result == 0)
385 return this->send_reply (0);
386 else
387 return this->send_reply (-1);
391 ACE_Name_Handler::resolve ()
393 ACE_TRACE ("ACE_Name_Handler::resolve");
394 #if 0
395 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("request for RESOLVE\n")));
396 #endif /* 0 */
397 ACE_NS_WString a_name (this->name_request_.name (),
398 this->name_request_.name_len () / sizeof (ACE_WCHAR_T));
400 // The following will deliver our reply back to client we
401 // pre-suppose success (indicated by type RESOLVE).
403 ACE_NS_WString avalue;
404 char *atype;
405 if (this->naming_context ()->resolve (a_name, avalue, atype) == 0)
407 std::unique_ptr<ACE_WCHAR_T[]> avalue_urep (avalue.rep ());
408 ACE_Name_Request nrq (ACE_Name_Request::RESOLVE,
411 avalue_urep.get (),
412 avalue.length () * sizeof (ACE_WCHAR_T),
413 atype, ACE_OS::strlen (atype));
414 delete[] atype;
415 return this->send_request (nrq);
418 ACE_Name_Request nrq (ACE_Name_Request::BIND, 0, 0, 0, 0, 0, 0);
419 this->send_request (nrq);
420 return 0;
424 ACE_Name_Handler::unbind ()
426 ACE_TRACE ("ACE_Name_Handler::unbind");
427 #if 0
428 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("request for UNBIND\n")));
429 #endif /* 0 */
430 ACE_NS_WString a_name (this->name_request_.name (),
431 this->name_request_.name_len () / sizeof (ACE_WCHAR_T));
433 if (this->naming_context ()->unbind (a_name) == 0)
434 return this->send_reply (0);
435 else
436 return this->send_reply (-1);
439 ACE_Name_Request
440 ACE_Name_Handler::name_request (ACE_NS_WString *one_name)
442 ACE_TRACE ("ACE_Name_Handler::name_request");
443 std::unique_ptr<ACE_WCHAR_T[]> one_name_urep (one_name->rep ());
444 return ACE_Name_Request (ACE_Name_Request::LIST_NAMES,
445 one_name_urep.get (),
446 one_name->length () * sizeof (ACE_WCHAR_T),
447 0, 0,
448 0, 0);
451 ACE_Name_Request
452 ACE_Name_Handler::value_request (ACE_NS_WString *one_value)
454 ACE_TRACE ("ACE_Name_Handler::value_request");
455 std::unique_ptr<ACE_WCHAR_T[]> one_value_urep (one_value->rep ());
456 return ACE_Name_Request (ACE_Name_Request::LIST_VALUES,
457 0, 0,
458 one_value_urep.get (),
459 one_value->length () * sizeof (ACE_WCHAR_T),
460 0, 0);
463 ACE_Name_Request
464 ACE_Name_Handler::type_request (ACE_NS_WString *one_type)
466 ACE_TRACE ("ACE_Name_Handler::type_request");
467 return ACE_Name_Request (ACE_Name_Request::LIST_TYPES,
468 0, 0,
469 0, 0,
470 std::unique_ptr<char[]> (one_type->char_rep ()).get (),
471 one_type->length ());
475 ACE_Name_Handler::lists ()
477 ACE_TRACE ("ACE_Name_Handler::lists");
479 ACE_PWSTRING_SET set;
480 ACE_NS_WString pattern (this->name_request_.name (),
481 this->name_request_.name_len () / sizeof (ACE_WCHAR_T));
483 // Get the index into the list table
484 int index = ACE_LIST_MAP (this->name_request_.msg_type (),
485 ACE_Name_Request::LIST_OP_MASK);
487 // Print the message type
488 ACE_DEBUG ((LM_DEBUG, list_table_[index].description_));
490 // Call the appropriate method
491 if ((this->naming_context ()->*list_table_[index].operation_) (set, pattern) != 0)
493 // None found so send blank request back
494 ACE_Name_Request end_rq (ACE_Name_Request::MAX_ENUM, 0, 0, 0, 0, 0, 0);
496 if (this->send_request (end_rq) == -1)
497 return -1;
499 else
501 ACE_NS_WString *one_entry = 0;
503 for (ACE_Unbounded_Set_Iterator<ACE_NS_WString> set_iterator (set);
504 set_iterator.next (one_entry) !=0;
505 set_iterator.advance())
507 ACE_Name_Request nrq ((this->*list_table_[index].request_factory_) (one_entry));
509 // Create a request by calling the appropriate method obtained
510 // by accessing into the table. Then send the request across.
511 if (this->send_request (nrq) == -1)
512 return -1;
515 // Send last message indicator.
516 ACE_Name_Request nrq (ACE_Name_Request::MAX_ENUM,
517 0, 0,
518 0, 0,
519 0, 0);
520 return this->send_request (nrq);
522 return 0;
526 ACE_Name_Handler::lists_entries ()
528 ACE_TRACE ("ACE_Name_Handler::lists_entries");
529 ACE_BINDING_SET set;
530 ACE_NS_WString pattern (this->name_request_.name (),
531 this->name_request_.name_len () / sizeof (ACE_WCHAR_T));
533 int result = -1;
535 const ACE_Name_Request::Constants msg_type =
536 static_cast<ACE_Name_Request::Constants> (this->name_request_.msg_type ());
538 // NOTE: This multi-branch conditional statement used to be
539 // (and should be) a switch statement. However, it caused
540 // Internal compiler error 980331 with egcs 1.1 (2.91.57).
541 // So, the pointer-to-member-function temporary has been removed.
542 if (msg_type == ACE_Name_Request::LIST_NAME_ENTRIES)
544 #if 0
545 ACE_DEBUG ((LM_DEBUG,
546 ACE_TEXT ("request for LIST_NAME_ENTRIES\n")));
547 #endif /* 0 */
548 result = this->naming_context ()->
549 ACE_Naming_Context::list_name_entries (set, pattern);
551 else if (msg_type == ACE_Name_Request::LIST_VALUE_ENTRIES)
553 #if 0
554 ACE_DEBUG ((LM_DEBUG,
555 ACE_TEXT ("request for LIST_VALUE_ENTRIES\n")));
556 #endif /* 0 */
557 result = this->naming_context ()->
558 ACE_Naming_Context::list_value_entries (set, pattern);
560 else if (msg_type == ACE_Name_Request::LIST_TYPE_ENTRIES)
562 #if 0
563 ACE_DEBUG ((LM_DEBUG,
564 ACE_TEXT ("request for LIST_TYPE_ENTRIES\n")));
565 #endif /* 0 */
566 result = this->naming_context ()->
567 ACE_Naming_Context::list_type_entries (set, pattern);
569 else
570 return -1;
572 if (result == 0)
574 ACE_Name_Binding *one_entry = 0;
576 for (ACE_Unbounded_Set_Iterator<ACE_Name_Binding> set_iterator (set);
577 set_iterator.next (one_entry) !=0;
578 set_iterator.advance())
580 std::unique_ptr<ACE_WCHAR_T[]> name_urep (one_entry->name_.rep ());
581 std::unique_ptr<ACE_WCHAR_T[]> value_urep (one_entry->value_.rep ());
582 ACE_Name_Request mynrq (this->name_request_.msg_type (),
583 name_urep.get (),
584 one_entry->name_.length () * sizeof (ACE_WCHAR_T),
585 value_urep.get (),
586 one_entry->value_.length () * sizeof (ACE_WCHAR_T),
587 one_entry->type_,
588 ACE_OS::strlen (one_entry->type_));
590 if (this->send_request (mynrq) == -1)
591 return -1;
594 // send last message indicator
595 ACE_Name_Request nrq (ACE_Name_Request::MAX_ENUM, 0, 0, 0, 0, 0, 0);
597 if (this->send_request (nrq) == -1)
598 return -1;
600 else
602 // None found so send blank request back.
603 ACE_Name_Request end_rq (ACE_Name_Request::MAX_ENUM, 0, 0, 0, 0, 0, 0);
605 if (this->send_request (end_rq) == -1)
606 return -1;
609 return 0;
612 ACE_Naming_Context *
613 ACE_Name_Handler::naming_context ()
615 return naming_context_;
618 ACE_Naming_Context *
619 ACE_Name_Acceptor::naming_context ()
621 return &naming_context_;
624 ACE_Name_Handler::~ACE_Name_Handler ()
626 ACE_TRACE ("ACE_Name_Handler::~ACE_Name_Handler");
627 #if 0
628 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("closing down Handle %d\n"),
629 this->get_handle ()));
630 #endif /* 0 */