1 #include "ace/Containers.h"
2 #include "ace/Get_Opt.h"
3 #include "ace/Singleton.h"
4 #include "ace/Auto_Ptr.h"
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)
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")),
36 this->service_addr_
.set (service_port
);
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
47 if( this->parse_args (argc
, argv
) == -1 )
48 ACE_ERROR_RETURN ((LM_ERROR
,
50 ACE_TEXT ("ACE_Name_Acceptor::parse_args failed")),
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 (),
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 ()),
67 // Ignore SIGPIPE so that each <SVC_HANDLER> can handle this on its
69 ACE_Sig_Action
sig ((ACE_SignalHandler
) SIG_IGN
, SIGPIPE
);
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
,
78 ACE_TEXT ("get_local_addr")),
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 ()));
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
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).
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
,
148 ACE_Name_Acceptor
* acceptor_
= static_cast<ACE_Name_Acceptor
*>(v
);
149 naming_context_
= acceptor_
->naming_context();
154 // Create and send a reply to the client.
157 ACE_Name_Handler::send_reply (ACE_INT32 status
,
160 ACE_TRACE ("ACE_Name_Handler::send_reply");
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
);
171 ssize_t n
= this->peer ().send (buf
, len
);
174 ACE_ERROR_RETURN ((LM_ERROR
,
175 ACE_TEXT ("%p\n, expected len = %d, actual len = %d"),
176 ACE_TEXT ("send failed"),
185 ACE_Name_Handler::send_request (ACE_Name_Request
&request
)
187 ACE_TRACE ("ACE_Name_Handler::send_request");
189 ssize_t length
= request
.encode (buffer
);
192 ACE_ERROR_RETURN ((LM_ERROR
,
194 ACE_TEXT ("encode failed")),
196 // Transmit request via a blocking send.
198 if (this->peer ().send_n (buffer
, length
) != length
)
199 ACE_ERROR_RETURN ((LM_ERROR
,
201 ACE_TEXT ("send_n failed")),
206 // Give up waiting (e.g., when a timeout occurs or a client shuts down
210 ACE_Name_Handler::abandon (void)
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
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 (void) 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.
237 ACE_Name_Handler::dispatch (void)
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.
257 ACE_Name_Handler::recv_request (void)
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
263 ssize_t n
= this->peer ().recv ((void *) &this->name_request_
,
264 sizeof (ACE_UINT32
));
268 ACE_DEBUG ((LM_DEBUG
,
269 ACE_TEXT ("****************** recv_request returned -1\n")));
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
)));
279 // We've shutdown unexpectedly, let's abandon the connection.
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"),
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
,
316 ACE_TEXT ("decode failed")));
317 return this->abandon ();
324 // Callback method invoked by the ACE_Reactor when events arrive from
328 ACE_Name_Handler::handle_input (ACE_HANDLE
)
330 ACE_TRACE ("ACE_Name_Handler::handle_input");
332 if (this->recv_request () == -1)
335 return this->dispatch ();
339 ACE_Name_Handler::bind (void)
341 ACE_TRACE ("ACE_Name_Handler::bind");
342 return this->shared_bind (0);
346 ACE_Name_Handler::rebind (void)
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
));
365 ACE_DEBUG ((LM_DEBUG
,
366 ACE_TEXT ("request for BIND\n")));
368 result
= this->naming_context ()->bind (a_name
,
370 this->name_request_
.type ());
375 ACE_DEBUG ((LM_DEBUG
,
376 ACE_TEXT ("request for REBIND\n")));
378 result
= this->naming_context ()->rebind (a_name
,
380 this->name_request_
.type ());
385 return this->send_reply (0);
387 return this->send_reply (-1);
391 ACE_Name_Handler::resolve (void)
393 ACE_TRACE ("ACE_Name_Handler::resolve");
395 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("request for RESOLVE\n")));
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
;
405 if (this->naming_context ()->resolve (a_name
, avalue
, atype
) == 0)
407 ACE_Auto_Basic_Array_Ptr
<ACE_WCHAR_T
> avalue_urep (avalue
.rep ());
408 ACE_Name_Request
nrq (ACE_Name_Request::RESOLVE
,
412 avalue
.length () * sizeof (ACE_WCHAR_T
),
413 atype
, ACE_OS::strlen (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
);
424 ACE_Name_Handler::unbind (void)
426 ACE_TRACE ("ACE_Name_Handler::unbind");
428 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("request for UNBIND\n")));
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);
436 return this->send_reply (-1);
440 ACE_Name_Handler::name_request (ACE_NS_WString
*one_name
)
442 ACE_TRACE ("ACE_Name_Handler::name_request");
443 ACE_Auto_Basic_Array_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
),
452 ACE_Name_Handler::value_request (ACE_NS_WString
*one_value
)
454 ACE_TRACE ("ACE_Name_Handler::value_request");
455 ACE_Auto_Basic_Array_Ptr
<ACE_WCHAR_T
> one_value_urep (one_value
->rep ());
456 return ACE_Name_Request (ACE_Name_Request::LIST_VALUES
,
458 one_value_urep
.get (),
459 one_value
->length () * sizeof (ACE_WCHAR_T
),
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
,
470 ACE_Auto_Basic_Array_Ptr
<char> (one_type
->char_rep ()).get (),
471 one_type
->length ());
475 ACE_Name_Handler::lists (void)
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)
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)
515 // Send last message indicator.
516 ACE_Name_Request
nrq (ACE_Name_Request::MAX_ENUM
,
520 return this->send_request (nrq
);
526 ACE_Name_Handler::lists_entries (void)
528 ACE_TRACE ("ACE_Name_Handler::lists_entries");
530 ACE_NS_WString
pattern (this->name_request_
.name (),
531 this->name_request_
.name_len () / sizeof (ACE_WCHAR_T
));
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
)
545 ACE_DEBUG ((LM_DEBUG
,
546 ACE_TEXT ("request for LIST_NAME_ENTRIES\n")));
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
)
554 ACE_DEBUG ((LM_DEBUG
,
555 ACE_TEXT ("request for LIST_VALUE_ENTRIES\n")));
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
)
563 ACE_DEBUG ((LM_DEBUG
,
564 ACE_TEXT ("request for LIST_TYPE_ENTRIES\n")));
566 result
= this->naming_context ()->
567 ACE_Naming_Context::list_type_entries (set
, pattern
);
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 ACE_Auto_Basic_Array_Ptr
<ACE_WCHAR_T
>
581 name_urep (one_entry
->name_
.rep ());
582 ACE_Auto_Basic_Array_Ptr
<ACE_WCHAR_T
>
583 value_urep (one_entry
->value_
.rep ());
584 ACE_Name_Request
mynrq (this->name_request_
.msg_type (),
586 one_entry
->name_
.length () * sizeof (ACE_WCHAR_T
),
588 one_entry
->value_
.length () * sizeof (ACE_WCHAR_T
),
590 ACE_OS::strlen (one_entry
->type_
));
592 if (this->send_request (mynrq
) == -1)
596 // send last message indicator
597 ACE_Name_Request
nrq (ACE_Name_Request::MAX_ENUM
, 0, 0, 0, 0, 0, 0);
599 if (this->send_request (nrq
) == -1)
604 // None found so send blank request back.
605 ACE_Name_Request
end_rq (ACE_Name_Request::MAX_ENUM
, 0, 0, 0, 0, 0, 0);
607 if (this->send_request (end_rq
) == -1)
615 ACE_Name_Handler::naming_context (void)
617 return naming_context_
;
621 ACE_Name_Acceptor::naming_context (void)
623 return &naming_context_
;
626 ACE_Name_Handler::~ACE_Name_Handler (void)
628 ACE_TRACE ("ACE_Name_Handler::~ACE_Name_Handler");
630 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("closing down Handle %d\n"),
631 this->get_handle ()));