1 #include "tao/Messaging/AMH_Response_Handler.h"
2 #include "tao/TAO_Server_Request.h"
3 #include "tao/Transport.h"
5 #include "tao/ORB_Core.h"
7 #include "tao/GIOP_Message_Base.h"
8 #include "tao/Pluggable_Messaging_Utils.h"
9 #include "tao/GIOP_Utils.h"
10 #include "tao/debug.h"
11 #include "tao/Buffer_Allocator_T.h"
12 #include "tao/SystemException.h"
13 #include "tao/PortableServer/ForwardRequestC.h"
15 #include "ace/Copy_Disabled.h"
17 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
19 TAO_AMH_Response_Handler::TAO_AMH_Response_Handler ()
20 : reply_status_ (GIOP::NO_EXCEPTION
)
23 , response_expected_ (false)
24 , transport_ (nullptr)
27 , rh_reply_status_ (TAO_RS_UNINITIALIZED
)
28 , allocator_ (nullptr)
32 TAO_AMH_Response_Handler::~TAO_AMH_Response_Handler ()
34 this->transport_
->remove_reference ();
36 // Since we are destroying the object we put a huge lock around the
37 // whole destruction process (just paranoid).
39 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
41 if (!this->response_expected_
) //oneway ?
46 // If the ResponseHandler is being destroyed before a reply has
47 // been sent to the client, we send a system exception
48 // CORBA::NO_RESPONSE, with minor code to indicate the problem.
49 if (this->rh_reply_status_
== TAO_RS_SENT
)
55 // If sending the exception to the client fails, then we just give
56 // up, release the transport and return.
59 CORBA::NO_RESPONSE
ex (CORBA::SystemException::_tao_minor_code
60 (TAO_AMH_REPLY_LOCATION_CODE
,
63 this->_tao_rh_send_exception (ex
);
71 TAO_AMH_Response_Handler::init(TAO_ServerRequest
&server_request
,
72 TAO_AMH_BUFFER_ALLOCATOR
* allocator
)
74 mesg_base_
= server_request
.mesg_base_
;
75 request_id_
= server_request
.request_id_
;
76 response_expected_
= server_request
.response_expected_
;
77 transport_
= server_request
.transport ();
78 orb_core_
= server_request
.orb_core ();
79 allocator_
= allocator
;
81 TAO_GIOP_Message_Version v
;
82 server_request
.outgoing()->get_version(v
);
83 this->_tao_out
.set_version(v
.major
, v
.minor
);
84 this->transport_
->assign_translators (0, &this->_tao_out
);
85 this->transport_
->add_reference ();
89 TAO_AMH_Response_Handler::_tao_rh_init_reply ()
92 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
93 if (this->rh_reply_status_
!= TAO_RS_UNINITIALIZED
)
95 // Looks like someone is trying to call an AMH method
98 // We assume that the servant has already processed the
99 // request and is now trying to send back the reply. Hence we
100 // say that the operation has completed but let the server
101 // anyway that it is not doing something right.
102 throw ::CORBA::BAD_INV_ORDER
103 (CORBA::SystemException::_tao_minor_code
104 (TAO_AMH_REPLY_LOCATION_CODE
,
106 CORBA::COMPLETED_YES
);
110 // Construct our reply generator.
111 TAO_Pluggable_Reply_Params_Base reply_params
;
112 reply_params
.request_id_
= this->request_id_
;
113 reply_params
.service_context_notowned (&(this->reply_service_context_
.service_info ()));
114 reply_params
.argument_flag_
= this->argument_flag_
;
115 reply_params
.reply_status (this->reply_status_
);
118 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
120 this->mesg_base_
->generate_reply_header (this->_tao_out
, reply_params
);
122 // We are done initialising the reply
123 this->rh_reply_status_
= TAO_RS_INITIALIZED
;
129 TAO_AMH_Response_Handler::_tao_rh_send_reply ()
132 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
134 // If the reply has not been initialised, raise an exception to the
135 // server-app saying it is not doing something right.
136 if (this->rh_reply_status_
!= TAO_RS_INITIALIZED
)
138 throw ::CORBA::BAD_INV_ORDER (
139 CORBA::SystemException::_tao_minor_code (
140 TAO_AMH_REPLY_LOCATION_CODE
,
142 CORBA::COMPLETED_YES
);
144 this->rh_reply_status_
= TAO_RS_SENDING
;
148 int result
= this->transport_
->send_message (this->_tao_out
,
151 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY
));
155 if (TAO_debug_level
> 0)
157 // No exception but some kind of error, yet a response
161 ACE_TEXT ("TAO: (%P|%t) %p: cannot send NO_EXCEPTION reply\n"),
162 ACE_TEXT ("TAO_AMH_Response_Handler::_tao_rh_send_reply")
168 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
169 this->rh_reply_status_
= TAO_RS_SENT
;
174 TAO_AMH_Response_Handler::_tao_rh_send_exception (const CORBA::Exception
&ex
)
177 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
178 if (this->rh_reply_status_
!= TAO_RS_UNINITIALIZED
)
180 throw ::CORBA::BAD_INV_ORDER (
181 CORBA::SystemException::_tao_minor_code (
182 TAO_AMH_REPLY_LOCATION_CODE
,
184 CORBA::COMPLETED_YES
);
186 this->rh_reply_status_
= TAO_RS_SENDING
;
189 TAO_Pluggable_Reply_Params_Base reply_params
;
190 reply_params
.request_id_
= this->request_id_
;
191 reply_params
.svc_ctx_
.length (0);
192 reply_params
.service_context_notowned (&this->reply_service_context_
.service_info ());
193 reply_params
.argument_flag_
= true;
194 // @@ It appears as if there should be a more efficient way to do
195 // this: the caller already knows this because it is part of the
196 // ExceptionHolder information.
198 #if !defined (CORBA_E_COMPACT) && !defined (CORBA_E_MICRO) && (TAO_HAS_MINIMUM_POA == 0)
199 const PortableServer::ForwardRequest
*fr
=
200 PortableServer::ForwardRequest::_downcast (&ex
);
203 reply_params
.reply_status (GIOP::LOCATION_FORWARD
);
204 if (this->mesg_base_
->generate_reply_header (this->_tao_out
,
207 throw ::CORBA::INTERNAL ();
209 this->_tao_out
<< fr
->forward_reference
;
214 if (CORBA::SystemException::_downcast (&ex
))
216 reply_params
.reply_status (GIOP::SYSTEM_EXCEPTION
);
220 reply_params
.reply_status (GIOP::USER_EXCEPTION
);
222 if (this->mesg_base_
->generate_exception_reply (this->_tao_out
,
226 throw ::CORBA::INTERNAL ();
229 // Send the Exception
230 if (this->transport_
->send_message (this->_tao_out
,
233 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY
)) == -1)
235 if (TAO_debug_level
> 0)
236 TAOLIB_ERROR ((LM_ERROR
,
237 ACE_TEXT ("TAO: (%P|%t|%N|%l): ")
238 ACE_TEXT ("TAO_AMH_Response_Handler:")
239 ACE_TEXT (" could not send exception reply\n")));
243 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
244 this->rh_reply_status_
= TAO_RS_SENT
;
249 TAO_AMH_Response_Handler::_tao_rh_send_location_forward (CORBA::Object_ptr fwd
,
250 CORBA::Boolean is_perm
)
253 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
254 if (this->rh_reply_status_
!= TAO_RS_UNINITIALIZED
)
256 throw ::CORBA::BAD_INV_ORDER (
257 CORBA::SystemException::_tao_minor_code (
258 TAO_AMH_REPLY_LOCATION_CODE
,
260 CORBA::COMPLETED_YES
);
262 this->rh_reply_status_
= TAO_RS_SENDING
;
265 TAO_Pluggable_Reply_Params_Base reply_params
;
266 reply_params
.request_id_
= this->request_id_
;
267 reply_params
.svc_ctx_
.length (0);
268 reply_params
.service_context_notowned (&this->reply_service_context_
.service_info ());
269 reply_params
.argument_flag_
= true;
272 reply_params
.reply_status (GIOP::LOCATION_FORWARD_PERM
);
276 reply_params
.reply_status (GIOP::LOCATION_FORWARD
);
279 if (this->mesg_base_
->generate_reply_header (this->_tao_out
,
282 throw ::CORBA::INTERNAL ();
285 if (!(this->_tao_out
<< fwd
))
287 if (TAO_debug_level
> 0)
288 TAOLIB_ERROR ((LM_ERROR
,
289 ACE_TEXT ("TAO (%P|%t) ERROR: Unable to marshal ")
290 ACE_TEXT ("forward reference.\n")));
294 // Send the Exception
295 if (this->transport_
->send_message (this->_tao_out
,
298 TAO_Message_Semantics (TAO_Message_Semantics::TAO_REPLY
)) == -1)
300 if (TAO_debug_level
> 0)
301 TAOLIB_ERROR ((LM_ERROR
,
302 ACE_TEXT ("TAO: (%P|%t|%N|%l): ")
303 ACE_TEXT ("TAO_AMH_Response_Handler: could not send ")
304 ACE_TEXT ("location forward reply\n")));
308 ACE_GUARD (TAO_SYNCH_MUTEX
, ace_mon
, this->mutex_
);
309 this->rh_reply_status_
= TAO_RS_SENT
;
314 TAO_AMH_Response_Handler::_remove_ref ()
316 if (--this->refcount_
== 0)
318 if (this->allocator_
)
320 TAO::TAO_Buffer_Allocator
<TAO_AMH_Response_Handler
, TAO_AMH_BUFFER_ALLOCATOR
> allocator (this->allocator_
);
322 allocator
.release (this);
334 ARH_Refcount_Functor::operator () (TAO_AMH_Response_Handler
*arh
) noexcept
336 (void) arh
->_remove_ref ();
340 TAO_END_VERSIONED_NAMESPACE_DECL