Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / TAO / tao / TAO_Server_Request.cpp
blob8f5ba8ab4c73b47a8865aebfe110b3db54ffee22
1 // -*- C++ -*-
2 #include "tao/TAO_Server_Request.h"
3 #include "tao/ORB_Core.h"
4 #include "tao/Timeprobe.h"
5 #include "tao/debug.h"
6 #include "tao/GIOP_Message_Base.h"
7 #include "tao/GIOP_Utils.h"
8 #include "tao/Stub.h"
9 #include "tao/operation_details.h"
10 #include "tao/Transport.h"
11 #include "tao/CDR.h"
12 #include "tao/SystemException.h"
13 #include <cstring>
15 #if TAO_HAS_INTERCEPTORS == 1
16 #include "tao/PortableInterceptorC.h"
17 #include "tao/ServerRequestInterceptor_Adapter.h"
18 #endif
20 #if !defined (__ACE_INLINE__)
21 # include "tao/TAO_Server_Request.inl"
22 #endif /* ! __ACE_INLINE__ */
24 #if defined (ACE_ENABLE_TIMEPROBES)
26 static const char * TAO_Server_Request_Timeprobe_Description[] =
28 "TAO_ServerRequest::TAO_ServerRequest - start",
29 "TAO_ServerRequest::TAO_ServerRequest - end",
32 enum
34 // Timeprobe description table start key.
35 TAO_SERVER_REQUEST_START = 400,
36 TAO_SERVER_REQUEST_END
39 // Setup Timeprobes
40 ACE_TIMEPROBE_EVENT_DESCRIPTIONS (TAO_Server_Request_Timeprobe_Description,
41 TAO_SERVER_REQUEST_START);
43 #endif /* ACE_ENABLE_TIMEPROBES */
45 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
47 TAO_ServerRequest::TAO_ServerRequest (TAO_GIOP_Message_Base *mesg_base,
48 TAO_InputCDR &input,
49 TAO_OutputCDR &output,
50 TAO_Transport *transport,
51 TAO_ORB_Core *orb_core)
52 : mesg_base_ (mesg_base),
53 operation_ (nullptr),
54 operation_len_ (0),
55 release_operation_ (false),
56 is_forwarded_ (false),
57 incoming_ (&input),
58 outgoing_ (&output),
59 response_expected_ (false),
60 deferred_reply_ (false),
61 sync_with_server_ (false),
62 is_queued_ (false),
63 is_dsi_ (false),
64 // @@ We shouldn't be using GIOP specific types here. Need to be revisited.
65 reply_status_ (GIOP::NO_EXCEPTION),
66 orb_core_ (orb_core),
67 request_id_ (0),
68 profile_ (orb_core),
69 requesting_principal_ (nullptr),
70 dsi_nvlist_align_ (0),
71 operation_details_ (nullptr),
72 argument_flag_ (true)
73 #if TAO_HAS_INTERCEPTORS == 1
74 , interceptor_count_ (0)
75 , rs_pi_current_ (nullptr)
76 , caught_exception_ (nullptr)
77 , pi_reply_status_ (-1)
78 #endif /* TAO_HAS_INTERCEPTORS == 1 */
79 , transport_(transport) //already duplicated in TAO_Transport::process_parsed_messages ()
81 ACE_FUNCTION_TIMEPROBE (TAO_SERVER_REQUEST_START);
82 // No-op.
85 // This constructor is used, by the locate request code.
86 TAO_ServerRequest::TAO_ServerRequest (TAO_GIOP_Message_Base *mesg_base,
87 CORBA::ULong request_id,
88 CORBA::Boolean response_expected,
89 CORBA::Boolean deferred_reply,
90 TAO::ObjectKey &object_key,
91 const char *operation,
92 TAO_OutputCDR &output,
93 TAO_Transport *transport,
94 TAO_ORB_Core *orb_core,
95 int &parse_error)
96 : mesg_base_ (mesg_base),
97 operation_ (CORBA::string_dup (operation)),
98 operation_len_ (operation == nullptr ? 0 : std::strlen (operation)),
99 release_operation_ (true),
100 is_forwarded_ (false),
101 incoming_ (nullptr),
102 outgoing_ (&output),
103 response_expected_ (response_expected),
104 deferred_reply_ (deferred_reply),
105 sync_with_server_ (false),
106 is_queued_ (false),
107 is_dsi_ (false),
108 reply_status_ (GIOP::NO_EXCEPTION),
109 orb_core_ (orb_core),
110 request_id_ (request_id),
111 profile_ (orb_core),
112 requesting_principal_ (nullptr),
113 dsi_nvlist_align_ (0),
114 operation_details_ (nullptr),
115 argument_flag_ (true)
116 #if TAO_HAS_INTERCEPTORS == 1
117 , interceptor_count_ (0)
118 , rs_pi_current_ (nullptr)
119 , caught_exception_ (nullptr)
120 , pi_reply_status_ (-1)
121 #endif /* TAO_HAS_INTERCEPTORS == 1 */
122 , transport_(transport) //already duplicated in TAO_Transport::process_parsed_messages ()
124 this->profile_.object_key (object_key);
125 parse_error = 0;
128 // Constructor used in Thru-POA collocation code.
129 TAO_ServerRequest::TAO_ServerRequest (TAO_ORB_Core * orb_core,
130 TAO_Operation_Details const & details,
131 CORBA::Object_ptr target)
132 : mesg_base_ (nullptr),
133 operation_ (details.opname ()),
134 operation_len_ (details.opname_len ()),
135 release_operation_ (false),
136 is_forwarded_ (false),
137 incoming_ (nullptr),
138 outgoing_ (nullptr),
139 response_expected_ (details.response_flags () == TAO_TWOWAY_RESPONSE_FLAG
140 || details.response_flags () == static_cast<CORBA::Octet> (Messaging::SYNC_WITH_SERVER)
141 || details.response_flags () == static_cast<CORBA::Octet> (Messaging::SYNC_WITH_TARGET)),
142 deferred_reply_ (false),
143 sync_with_server_ (details.response_flags () == static_cast<CORBA::Octet> (Messaging::SYNC_WITH_SERVER)),
144 is_queued_ (false),
145 is_dsi_ (false),
146 reply_status_ (GIOP::NO_EXCEPTION),
147 orb_core_ (orb_core),
148 request_id_ (0),
149 profile_ (orb_core),
150 requesting_principal_ (nullptr),
151 dsi_nvlist_align_ (0),
152 operation_details_ (&details),
153 argument_flag_ (false)
154 #if TAO_HAS_INTERCEPTORS == 1
155 , interceptor_count_ (0)
156 , rs_pi_current_ (nullptr)
157 , caught_exception_ (nullptr)
158 , pi_reply_status_ (-1)
159 #endif /* TAO_HAS_INTERCEPTORS == 1 */
160 , transport_ (nullptr)
162 // Have to use a const_cast<>. *sigh*
163 this->profile_.object_key (
164 const_cast<TAO::ObjectKey &> (target->_stubobj ()->object_key ()));
166 // Shallow copy the request service context list. This way the operation
167 // details and server request share the request context.
168 IOP::ServiceContextList & dest_request_contexts =
169 this->request_service_context_.service_info ();
171 IOP::ServiceContextList & src_request_contexts =
172 (const_cast <TAO_Operation_Details&> (details)).request_service_info ();
174 dest_request_contexts.replace (src_request_contexts.maximum (),
175 src_request_contexts.length (),
176 src_request_contexts.get_buffer (),
177 false /* Do not release. */);
179 // Don't shallow copy the reply service context. It is probably empty,
180 // when then during the request it is used, the buffer gets allocated and
181 // then the operation details don't get the reply service context
184 TAO_ServerRequest::~TAO_ServerRequest ()
186 #if TAO_HAS_INTERCEPTORS == 1
187 if (this->rs_pi_current_)
189 TAO::ServerRequestInterceptor_Adapter *interceptor_adapter =
190 this->orb_core_->serverrequestinterceptor_adapter ();
192 if (interceptor_adapter)
194 interceptor_adapter->deallocate_pi_current (
195 this->rs_pi_current_);
198 #endif /* TAO_HAS_INTERCEPTORS == 1 */
199 if (this->release_operation_)
200 CORBA::string_free (const_cast<char*> (this->operation_));
203 CORBA::ORB_ptr
204 TAO_ServerRequest::orb ()
206 return this->orb_core_->orb ();
209 TAO_Service_Context &
210 TAO_ServerRequest::reply_service_context ()
212 if (!operation_details_)
214 return this->reply_service_context_;
216 else
218 return const_cast <TAO_Operation_Details*> (
219 this->operation_details_)->reply_service_context ();
224 void
225 TAO_ServerRequest::init_reply ()
227 if (!this->outgoing_)
228 return; // Collocated
230 // Construct our reply generator.
231 TAO_Pluggable_Reply_Params_Base reply_params;
233 // We put all the info that we have in to this <reply_params> and
234 // call the <write_reply_header> in the
235 // pluggable_messaging_interface. One point to be noted however is
236 // that, it was the pluggable_messaging classes who created us and
237 // delegated us to do work on its behalf. But we would be calling
238 // back. As we don't have a LOCK or any such things we can call
239 // pluggable_messaging guys again. We would be on the same thread of
240 // invocation. So *theoretically* there should not be a problem.
241 reply_params.request_id_ = this->request_id_;
242 reply_params.is_dsi_ = this->is_dsi_;
243 reply_params.dsi_nvlist_align_ = this->dsi_nvlist_align_;
245 // Send back the reply service context.
246 reply_params.service_context_notowned (&this->reply_service_info ());
248 // Are we going to marshall any data with the reply?
249 reply_params.argument_flag_ = this->argument_flag_;
251 // Forward exception only.
252 if (this->is_forwarded_)
254 CORBA::Boolean const permanent_forward_condition =
255 this->orb_core_->is_permanent_forward_condition (this->forward_location_.in (),
256 this->request_service_context ());
258 reply_params.reply_status (
259 permanent_forward_condition
260 ? GIOP::LOCATION_FORWARD_PERM
261 : GIOP::LOCATION_FORWARD);
263 // Any exception at all.
264 else
266 reply_params.reply_status (this->reply_status_);
269 this->outgoing_->message_attributes (this->request_id_,
270 nullptr,
271 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY),
272 nullptr);
274 // Construct a REPLY header.
275 this->mesg_base_->generate_reply_header (*this->outgoing_, reply_params);
277 // Finish the GIOP Reply header, then marshal the exception.
278 if (reply_params.reply_status () == GIOP::LOCATION_FORWARD ||
279 reply_params.reply_status () == GIOP::LOCATION_FORWARD_PERM)
281 // Marshal the forward location pointer.
282 CORBA::Object_ptr object_ptr = this->forward_location_.in ();
284 if ((*this->outgoing_ << object_ptr) == 0)
286 TAOLIB_DEBUG ((LM_DEBUG,
287 ACE_TEXT ("TAO (%P|%t) - ServerRequest::init_reply, ")
288 ACE_TEXT ("TAO_GIOP_ServerRequest::marshal - ")
289 ACE_TEXT ("marshal encoding forwarded objref failed\n")));
292 this->transport_->assign_translators (nullptr, this->outgoing_);
295 void
296 TAO_ServerRequest::send_no_exception_reply ()
298 // Construct our reply generator.
299 TAO_Pluggable_Reply_Params_Base reply_params;
300 reply_params.request_id_ = this->request_id_;
301 reply_params.is_dsi_ = this->is_dsi_;
302 reply_params.dsi_nvlist_align_ = this->dsi_nvlist_align_;
304 // Change this to pass back the same thing we received, as well as
305 // leave a comment why this is important!
306 reply_params.svc_ctx_.length (0);
308 // Send back the reply service context.
309 reply_params.service_context_notowned (&this->reply_service_info ());
311 reply_params.reply_status (GIOP::NO_EXCEPTION);
313 // No data anyway.
314 reply_params.argument_flag_ = false;
316 this->outgoing_->message_attributes (this->request_id_,
317 nullptr,
318 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY),
319 nullptr);
321 // Construct a REPLY header.
322 this->mesg_base_->generate_reply_header (*this->outgoing_, reply_params);
324 this->outgoing_->more_fragments (false);
326 // Send the message.
327 int const result = this->transport_->send_message (*this->outgoing_,
328 nullptr,
329 this,
330 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY));
332 if (result == -1)
334 if (TAO_debug_level > 0)
336 // No exception but some kind of error, yet a response
337 // is required.
338 TAOLIB_ERROR ((
339 LM_ERROR,
340 ACE_TEXT ("TAO (%P|%t) - ServerRequest::send_no_exception_reply, ")
341 ACE_TEXT ("cannot send NO_EXCEPTION reply\n")));
346 void
347 TAO_ServerRequest::tao_send_reply ()
349 if (this->collocated ())
350 return; // No transport in the collocated case.
352 this->outgoing_->more_fragments (false);
354 int const result = this->transport_->send_message (*this->outgoing_,
355 nullptr,
356 this,
357 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY));
358 if (result == -1)
360 if (TAO_debug_level > 0)
362 // No exception but some kind of error, yet a response
363 // is required.
364 TAOLIB_ERROR ((LM_ERROR,
365 ACE_TEXT ("TAO (%P|%t) - ServerRequest::tao_send_reply, ")
366 ACE_TEXT ("cannot send reply\n")));
371 void
372 TAO_ServerRequest::tao_send_reply_exception (const CORBA::Exception &ex)
374 if (this->response_expected_ && !this->collocated ())
376 // A copy of the reply parameters
377 TAO_Pluggable_Reply_Params_Base reply_params;
379 reply_params.request_id_ = this->request_id_;
380 reply_params.svc_ctx_.length (0);
382 // Send back the reply service context.
383 reply_params.service_context_notowned (&this->reply_service_info ());
385 // We are going to send some data
386 reply_params.argument_flag_ = true;
388 // Make a default reply status
390 // Check whether we are able to downcast the exception
391 if (CORBA::SystemException::_downcast (&ex) != nullptr)
393 reply_params.reply_status (GIOP::SYSTEM_EXCEPTION);
395 else
397 reply_params.reply_status (GIOP::USER_EXCEPTION);
400 // Create a new output CDR stream
401 #if defined(ACE_INITIALIZE_MEMORY_BEFORE_USE)
402 // Only inititialize the buffer if we're compiling with a profiler.
403 // Otherwise, there is no real need to do so, especially since
404 // we can avoid the initialization overhead at runtime if we
405 // are not compiling with memory profiler support.
406 char repbuf[ACE_CDR::DEFAULT_BUFSIZE] = { 0 };
407 #else
408 char repbuf[ACE_CDR::DEFAULT_BUFSIZE];
409 #endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
410 TAO_GIOP_Message_Version gv;
411 if (this->outgoing_)
412 this->outgoing_->get_version (gv);
414 TAO_OutputCDR output (repbuf,
415 sizeof repbuf,
416 TAO_ENCAP_BYTE_ORDER,
417 this->orb_core_->output_cdr_buffer_allocator (),
418 this->orb_core_->output_cdr_dblock_allocator (),
419 this->orb_core_->output_cdr_msgblock_allocator (),
420 this->orb_core_->orb_params ()->cdr_memcpy_tradeoff (),
421 this->mesg_base_->fragmentation_strategy (),
422 gv.major,
423 gv.minor);
425 this->transport_->assign_translators (nullptr, &output);
429 // Make the reply message
430 if (this->mesg_base_->generate_exception_reply (*this->outgoing_,
431 reply_params,
432 ex) == -1)
434 TAOLIB_ERROR ((LM_ERROR,
435 ACE_TEXT ("TAO (%P|%t) - ServerRequest::")
436 ACE_TEXT ("tao_send_reply_exception, ")
437 ACE_TEXT ("could not make exception reply\n")));
440 this->outgoing_->more_fragments (false);
442 // Send the message
443 if (this->transport_->send_message (*this->outgoing_,
444 nullptr,
445 this,
446 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY)) == -1)
448 TAOLIB_ERROR ((LM_ERROR,
449 ACE_TEXT ("TAO (%P|%t) - ServerRequest::")
450 ACE_TEXT ("tao_send_reply_exception, ")
451 ACE_TEXT ("could not send exception reply\n")));
454 catch (const ::CORBA::BAD_PARAM &bp_ex)
456 TAOLIB_ERROR ((LM_ERROR,
457 ACE_TEXT ("TAO (%P|%t) - ServerRequest::")
458 ACE_TEXT ("tao_send_reply_exception, ")
459 ACE_TEXT ("could not marshal exception reply\n")));
460 this->tao_send_reply_exception (bp_ex);
463 else if (TAO_debug_level > 0)
465 // It is unfortunate that an exception (probably a system
466 // exception) was thrown by the upcall code (even by the
467 // user) when the client was not expecting a response.
468 // However, in this case, we cannot close the connection
469 // down, since it really isn't the client's fault.
470 TAOLIB_ERROR ((LM_ERROR,
471 ACE_TEXT ("TAO (%P|%t) - ServerRequest::tao_send_reply_exception, ")
472 ACE_TEXT ("exception thrown ")
473 ACE_TEXT ("but client is not waiting a response\n")));
477 #if TAO_HAS_INTERCEPTORS == 1
478 void
479 TAO_ServerRequest::send_cached_reply (CORBA::OctetSeq &s)
481 #if defined(ACE_INITIALIZE_MEMORY_BEFORE_USE)
482 // Only inititialize the buffer if we're compiling with Purify.
483 // Otherwise, there is no real need to do so, especially since
484 // we can avoid the initialization overhead at runtime if we
485 // are not compiling with Purify support.
486 char repbuf[ACE_CDR::DEFAULT_BUFSIZE] = { 0 };
487 #else
488 char repbuf[ACE_CDR::DEFAULT_BUFSIZE];
489 #endif /* ACE_HAS_PURIFY */
490 TAO_GIOP_Message_Version gv;
491 if (this->outgoing_)
493 this->outgoing_->get_version (gv);
495 TAO_OutputCDR output (repbuf,
496 sizeof repbuf,
497 TAO_ENCAP_BYTE_ORDER,
498 this->orb_core_->output_cdr_buffer_allocator (),
499 this->orb_core_->output_cdr_dblock_allocator (),
500 this->orb_core_->output_cdr_msgblock_allocator (),
501 this->orb_core_->orb_params ()->cdr_memcpy_tradeoff (),
502 this->mesg_base_->fragmentation_strategy (),
503 gv.major,
504 gv.minor);
506 this->transport_->assign_translators (nullptr, &output);
508 // A copy of the reply parameters
509 TAO_Pluggable_Reply_Params_Base reply_params;
511 reply_params.request_id_ = this->request_id_;
513 reply_params.svc_ctx_.length (0);
515 // Send back the empty reply service context.
516 reply_params.service_context_notowned (&this->reply_service_info ());
518 // We are going to send some data
519 reply_params.argument_flag_ = true;
521 // Make a default reply status
522 reply_params.reply_status (GIOP::NO_EXCEPTION);
524 this->outgoing_->message_attributes (this->request_id_,
525 nullptr,
526 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY),
527 nullptr);
529 // Make the reply message
530 if (this->mesg_base_->generate_reply_header (*this->outgoing_,
531 reply_params) == -1)
533 TAOLIB_ERROR ((LM_ERROR,
534 ACE_TEXT ("TAO (%P|%t) - ServerRequest::send_cached_reply, ")
535 ACE_TEXT ("could not make cached reply\n")));
538 /// Append reply here....
539 this->outgoing_->write_octet_array (
540 s.get_buffer (),
541 s.length ());
543 if (!this->outgoing_->good_bit ())
545 TAOLIB_ERROR ((LM_ERROR,
546 ACE_TEXT ("TAO (%P|%t) - ServerRequest::send_cached_reply, ")
547 ACE_TEXT ("could not marshal reply\n")));
550 this->outgoing_->more_fragments (false);
552 // Send the message
553 if (this->transport_->send_message (*this->outgoing_,
554 nullptr,
555 this,
556 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY)) == -1)
558 TAOLIB_ERROR ((LM_ERROR,
559 ACE_TEXT ("TAO (%P|%t) - ServerRequest::send_cached_reply, ")
560 ACE_TEXT ("could not send cached reply\n")));
564 void
565 TAO_ServerRequest::caught_exception (CORBA::Exception *exception)
567 if (CORBA::SystemException::_downcast (exception) != nullptr)
568 this->pi_reply_status_ = PortableInterceptor::SYSTEM_EXCEPTION;
569 else if (CORBA::UserException::_downcast (exception) != nullptr)
570 this->pi_reply_status_ = PortableInterceptor::USER_EXCEPTION;
572 this->caught_exception_ = exception;
575 TAO::PICurrent_Impl *
576 TAO_ServerRequest::rs_pi_current ()
578 if (!this->rs_pi_current_)
580 TAO::ServerRequestInterceptor_Adapter *interceptor_adapter =
581 this->orb_core_->serverrequestinterceptor_adapter ();
583 if (interceptor_adapter)
585 this->rs_pi_current_ = interceptor_adapter->allocate_pi_current ();
589 return this->rs_pi_current_;
592 #endif /* TAO_HAS_INTERCEPTORS */
594 #if TAO_HAS_ZIOP == 1
595 CORBA::Policy_ptr
596 TAO_ServerRequest::clientCompressionEnablingPolicy ()
598 return this->clientCompressionEnablingPolicy_.in ();
601 void
602 TAO_ServerRequest::clientCompressionEnablingPolicy (CORBA::Policy_ptr policy)
604 this->clientCompressionEnablingPolicy_ = policy;
607 CORBA::Policy_ptr
608 TAO_ServerRequest::clientCompressorIdLevelListPolicy ()
610 return this->clientCompressorIdLevelListPolicy_.in ();
613 void
614 TAO_ServerRequest::clientCompressorIdLevelListPolicy (CORBA::Policy_ptr policy)
616 this->clientCompressorIdLevelListPolicy_ = policy;
618 #endif /* TAO_HAS_ZIOP == 1 */
620 TAO_END_VERSIONED_NAMESPACE_DECL