summaryrefslogtreecommitdiff
path: root/TAO/tao/Server_Request.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tao/Server_Request.cpp')
-rw-r--r--TAO/tao/Server_Request.cpp607
1 files changed, 607 insertions, 0 deletions
diff --git a/TAO/tao/Server_Request.cpp b/TAO/tao/Server_Request.cpp
index f94cd6709cf..95aceb59a51 100644
--- a/TAO/tao/Server_Request.cpp
+++ b/TAO/tao/Server_Request.cpp
@@ -19,3 +19,610 @@
ACE_RCSID(tao, Server_Request, "$Id$")
+#if defined (ACE_ENABLE_TIMEPROBES)
+
+static const char *TAO_Server_Request_Timeprobe_Description[] =
+ {
+ "Server_Request::Server_Request - start",
+ "Server_Request::Server_Request - end",
+ };
+
+enum
+ {
+ // Timeprobe description table start key
+ TAO_SERVER_REQUEST_START = 400,
+ TAO_SERVER_REQUEST_END
+ };
+
+// Setup Timeprobes
+ACE_TIMEPROBE_EVENT_DESCRIPTIONS (TAO_Server_Request_Timeprobe_Description,
+ TAO_SERVER_REQUEST_START);
+
+#endif /* ACE_ENABLE_TIMEPROBES */
+
+IIOP_ServerRequest::IIOP_ServerRequest (TAO_InputCDR &input,
+ TAO_OutputCDR &output,
+ TAO_ORB_Core *orb_core,
+ CORBA::Environment &env)
+ : incoming_ (&input),
+ outgoing_ (&output),
+ response_expected_ (0),
+
+#if !defined (TAO_HAS_MINIMUM_CORBA)
+
+ params_ (0),
+
+#endif /* TAO_HAS_MINIMUM_CORBA */
+
+ retval_ (0),
+ exception_ (0),
+ exception_type_ (TAO_GIOP_NO_EXCEPTION),
+ orb_core_ (orb_core),
+ service_info_ (),
+ request_id_ (0),
+ object_key_ (),
+ requesting_principal_ (0)
+{
+ ACE_FUNCTION_TIMEPROBE (TAO_SERVER_REQUEST_START);
+
+ this->parse_header (env);
+}
+
+void
+IIOP_ServerRequest::parse_header_std (CORBA::Environment &ACE_TRY_ENV)
+{
+ // Tear out the service context ... we currently ignore it, but it
+ // should probably be passed to each ORB service as appropriate
+ // (e.g. transactions, security).
+ //
+ // NOTE: As security support kicks in, this is a good place to
+ // verify a digital signature, if that is required in this security
+ // environment. It may be required even when using IPSEC security
+ // infrastructure.
+
+ TAO_InputCDR& input = *this->incoming_;
+
+ input >> this->service_info_;
+ CORBA::Boolean hdr_status = input.good_bit ();
+
+ // Get the rest of the request header ...
+
+ hdr_status = hdr_status && input.read_ulong (this->request_id_);
+ hdr_status = hdr_status && input.read_boolean (this->response_expected_);
+
+ // We use ad-hoc demarshalling here: there is no need to increase
+ // the reference count on the CDR message block, because this key
+ // will not outlive the request (or the message block).
+
+ CORBA::Long key_length;
+ hdr_status = hdr_status && input.read_long (key_length);
+ if (hdr_status)
+ {
+ this->object_key_.replace (key_length, key_length,
+ (CORBA::Octet*)input.rd_ptr (),
+ 0);
+ input.skip_bytes (key_length);
+ }
+
+ CORBA::Long length;
+ hdr_status = hdr_status && input.read_long (length);
+ if (hdr_status)
+ {
+ // Do not include NULL character at the end.
+ this->operation_.set (input.rd_ptr (),
+ length - 1,
+ 0);
+ hdr_status = input.skip_bytes (length);
+ }
+
+ if (hdr_status)
+ {
+ input >> this->requesting_principal_;
+ hdr_status = input.good_bit ();
+ }
+
+ if (!hdr_status)
+ ACE_THROW (CORBA::COMM_FAILURE (CORBA::COMPLETED_NO));
+
+}
+
+void
+IIOP_ServerRequest::parse_header_lite (CORBA::Environment &ACE_TRY_ENV)
+{
+ TAO_InputCDR& input = *this->incoming_;
+
+ CORBA::Boolean hdr_status = input.good_bit ();
+
+ // Get the rest of the request header ...
+
+ hdr_status = hdr_status && input.read_ulong (this->request_id_);
+ hdr_status = hdr_status && input.read_boolean (this->response_expected_);
+
+ // We use ad-hoc demarshalling here: there is no need to increase
+ // the reference count on the CDR message block, because this key
+ // will not outlive the request (or the message block).
+
+ CORBA::Long key_length;
+ hdr_status = hdr_status && input.read_long (key_length);
+ if (hdr_status)
+ {
+ this->object_key_.replace (key_length, key_length,
+ (CORBA::Octet*)input.rd_ptr (),
+ 0);
+ input.skip_bytes (key_length);
+ }
+
+ CORBA::Long length;
+ hdr_status = hdr_status && input.read_long (length);
+ if (hdr_status)
+ {
+ // Do not include NULL character at the end.
+ this->operation_.set (input.rd_ptr (),
+ length - 1,
+ 0);
+ hdr_status = input.skip_bytes (length);
+ }
+
+ if (!hdr_status)
+ ACE_THROW (CORBA::COMM_FAILURE (CORBA::COMPLETED_NO));
+}
+
+
+
+void
+IIOP_ServerRequest::parse_header (CORBA::Environment &env)
+{
+ if (this->orb_core_->orb_params ()->use_lite_protocol ())
+ this->parse_header_lite (env);
+ else
+ this->parse_header_std (env);
+}
+
+// This constructor is used, by the locate request code
+
+IIOP_ServerRequest::IIOP_ServerRequest (CORBA::ULong &request_id,
+ CORBA::Boolean &response_expected,
+ TAO_ObjectKey &object_key,
+ const ACE_CString &operation,
+ TAO_OutputCDR &output,
+ TAO_ORB_Core *orb_core,
+ CORBA::Environment &)
+ : operation_ (operation),
+ incoming_ (0),
+ outgoing_ (&output),
+ response_expected_ (response_expected),
+
+#if !defined (TAO_HAS_MINIMUM_CORBA)
+
+ params_ (0),
+
+#endif /* TAO_HAS_MINIMUM_CORBA */
+
+ retval_ (0),
+ exception_ (0),
+ exception_type_ (TAO_GIOP_NO_EXCEPTION),
+ orb_core_ (orb_core),
+ service_info_ (0),
+ request_id_ (request_id),
+ object_key_ (object_key),
+ requesting_principal_ (0)
+{
+}
+
+IIOP_ServerRequest::~IIOP_ServerRequest (void)
+{
+
+#if !defined (TAO_HAS_MINIMUM_CORBA)
+
+ if (this->params_)
+ CORBA::release (this->params_);
+
+#endif /* TAO_HAS_MINIMUM_CORBA */
+
+ delete this->retval_;
+ delete this->exception_;
+}
+
+CORBA::ORB_ptr
+IIOP_ServerRequest::orb (void)
+{
+ return this->orb_core_->orb ();
+}
+
+TAO_POA *
+IIOP_ServerRequest::oa (void)
+{
+ return this->orb_core_->root_poa ();
+}
+
+#if !defined (TAO_HAS_MINIMUM_CORBA)
+
+// Unmarshal in/inout params, and set up to marshal the appropriate
+// inout/out/return values later on.
+
+void
+IIOP_ServerRequest::arguments (CORBA::NVList_ptr &list,
+ CORBA::Environment &env)
+{
+ env.clear ();
+
+ // Save params for later use when marshaling the reply.
+ this->params_ = list;
+
+ // Then unmarshal each "in" and "inout" parameter.
+ for (u_int i = 0; i < list->count (); i++)
+ {
+ CORBA::NamedValue_ptr nv = list->item (i, env);
+
+ // check if it is an in or inout parameter
+ if (ACE_BIT_DISABLED (nv->flags (), CORBA::ARG_IN | CORBA::ARG_INOUT))
+ continue;
+
+ CORBA::Any_ptr any = nv->value ();
+ CORBA::TypeCode_var tc = any->type ();
+
+ // @@ (JP) The following code depends on the fact that
+ // TO_InputCDR does not contain chained message blocks.
+ char *begin, *end;
+
+ // This will be the start of a new message block.
+ begin = this->incoming_->rd_ptr ();
+
+ // Skip over the next aregument.
+ CORBA::TypeCode::traverse_status status =
+ this->incoming_->skip (tc.in (), env);
+
+ if (status != CORBA::TypeCode::TRAVERSE_CONTINUE)
+ {
+ const char* param_name = nv->name ();
+
+ if (param_name == 0)
+ param_name = "(no name given)";
+
+ ACE_ERROR ((LM_ERROR,
+ "IIOP_ServerRequest::arguments - problem while"
+ " decoding parameter %d <%s>\n", i, param_name));
+ return;
+ }
+
+ // This will be the end of the new message block.
+ end = this->incoming_->rd_ptr ();
+
+ // Allocate the new message block and set its endpoints.
+ ACE_Message_Block *cdr;
+
+ ACE_NEW (cdr,
+ ACE_Message_Block (end - begin));
+
+ cdr->rd_ptr (begin);
+
+ cdr->wr_ptr (end);
+
+ // Stick it into the Any. It gets duplicated there.
+ any->_tao_replace (tc.in (),
+ cdr,
+ 0,
+ env);
+
+ // Now we can release the original.
+ ACE_Message_Block::release (cdr);
+ }
+
+ // If any data is left over, it'd be context values ... else error.
+ // We don't support context values, so it's always an error.
+
+ // @@ (TAO) support for Contexts??
+ if (incoming_->length () != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "IIOP_ServerRequest::arguments - "
+ "%d bytes left in buffer\n", incoming_->length ()));
+ env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO));
+ }
+}
+
+// Store the result value. There's either an exception, or a result,
+// but not both of them. Results (and exceptions) can be reported
+// only after the parameter list has been provided (maybe empty).
+
+void
+IIOP_ServerRequest::set_result (const CORBA::Any &value,
+ CORBA::Environment &env)
+{
+ env.clear ();
+
+ // setting a result when another result already exists or if an exception
+ // exists is an error
+ if (this->retval_ || this->exception_)
+ env.exception (new CORBA::BAD_INV_ORDER (CORBA::COMPLETED_NO));
+ else
+ {
+ this->retval_ = new CORBA::Any (value);
+ }
+}
+
+// Store the exception value.
+
+void
+IIOP_ServerRequest::set_exception (const CORBA::Any &value,
+ CORBA::Environment &env)
+{
+ if (this->retval_ || this->exception_)
+ env.exception (new CORBA::BAD_INV_ORDER (CORBA::COMPLETED_NO));
+ else
+ {
+ // Try to narrow to ForwardRequest
+ PortableServer::ForwardRequest_ptr forward_request =
+ PortableServer::ForwardRequest::_narrow ((CORBA::Exception *) value.value ());
+
+ // If narrowing of exception succeeded
+ if (forward_request != 0)
+ {
+ this->forward_location_ = forward_request->forward_reference;
+ this->exception_type_ = TAO_GIOP_USER_EXCEPTION;
+ }
+ // Normal exception
+ else
+ {
+ this->exception_ = new CORBA::Any (value);
+
+ // @@ This cast is not safe, but we haven't implemented the >>=
+ // and <<= operators for base exceptions (yet).
+ CORBA_Exception* x = (CORBA_Exception*)value.value ();
+ if (CORBA_UserException::_narrow (x) != 0)
+ this->exception_type_ = TAO_GIOP_USER_EXCEPTION;
+ else
+ this->exception_type_ = TAO_GIOP_SYSTEM_EXCEPTION;
+ }
+ }
+}
+
+// this method will be utilized by the DSI servant to marshal outgoing
+// parameters
+
+void
+IIOP_ServerRequest::dsi_marshal (CORBA::Environment &env)
+{
+ // NOTE: if "env" is set, it takes precedence over exceptions
+ // reported using the mechanism of the ServerRequest. Only system
+ // exceptions are reported that way ...
+ //
+ // XXX Exception reporting is ambiguous; it can be cleaner than
+ // this. With both language-mapped and dynamic/explicit reporting
+ // mechanisms, one of must be tested "first" ... so an exception
+ // reported using the other mechanism could be "lost". Perhaps only
+ // the language mapped one should be used for system exceptions.
+
+
+ // only if there wasn't any exception, we proceed
+ if (this->exception_type_ == TAO_GIOP_NO_EXCEPTION &&
+ CORBA::is_nil (this->forward_location_.in ()))
+ {
+ // ... then send any return value ...
+ if (this->retval_)
+ {
+ CORBA::TypeCode_var tc = this->retval_->type ();
+ if (this->retval_->any_owns_data ())
+ {
+ (void) this->outgoing_->encode (tc.in (), retval_->value (), 0, env);
+ }
+ else
+ {
+ TAO_InputCDR cdr (retval_->_tao_get_cdr ());
+ (void) this->outgoing_->append (tc.in (), &cdr, env);
+ }
+ }
+
+ // ... Followed by "inout" and "out" parameters, left to right
+ if (this->params_)
+ {
+ for (u_int i = 0;
+ i < this->params_->count ();
+ i++)
+ {
+ CORBA::NamedValue_ptr nv = this->params_->item (i, env);
+ if (!(nv->flags () & (CORBA::ARG_INOUT|CORBA::ARG_OUT)))
+ continue;
+
+ CORBA::Any_ptr any = nv->value ();
+ CORBA::TypeCode_var tc = any->type ();
+ if (any->any_owns_data ())
+ {
+ (void) this->outgoing_->encode (tc.in (), any->value (), 0, env);
+ }
+ else
+ {
+ TAO_InputCDR cdr (any->_tao_get_cdr ());
+ (void) this->outgoing_->append (tc.in (), &cdr, env);
+ }
+ }
+ }
+ }
+}
+
+#endif /* TAO_HAS_MINIMUM_CORBA */
+
+// Extension
+void
+IIOP_ServerRequest::demarshal (CORBA::Environment &orb_env,
+ // ORB related exception reporting
+ const TAO_Call_Data_Skel *info,
+ // call description
+ ...)
+{
+ CORBA::ULong i;
+ const TAO_Param_Data_Skel *pdp;
+ va_list param_vector;
+ va_start (param_vector, info);
+
+ for (i = 0, pdp = info->params;
+ i < info->param_count;
+ i++, pdp++)
+ {
+ void *ptr = va_arg (param_vector, void *);
+
+ if ((pdp->mode == CORBA::ARG_IN)
+ || (pdp->mode == CORBA::ARG_INOUT))
+ {
+ // Then just unmarshal the value.
+ (void) incoming_->decode (pdp->tc, ptr, 0, orb_env);
+ }
+
+ if (orb_env.exception ())
+ {
+ orb_env.print_exception ("ServerRequest::demarshal - parameter decode failed");
+ return;
+ }
+ }
+ va_end (param_vector);
+}
+
+// Extension
+
+void
+IIOP_ServerRequest::marshal (CORBA::Environment &orb_env,
+ // ORB related exception reporting
+ // CORBA::Environment &skel_env,
+ // skeleton related exception reporting
+ const TAO_Call_Data_Skel *info,
+ // call description
+ ...)
+{
+ // what is "orb_env" and "skel_env"?
+ // "skel_env" holds the exception that got raised inside the operation
+ // implementation (upcall)
+ //
+ // "orb_env" is the exception that may have been raised due to things going
+ // wrong in the entire dispatch process. These are always system exceptions.
+
+ // check if we are inside with an exception. This may have happened
+ // since the upcall could have set some exception
+#if 0 /* ASG */
+ if (skel_env.exception ())
+ {
+ // We must increase the "refcnt" on the exception, because it is
+ // "owned" by both <skel_env> and (eventually) by the
+ // Server_Request.
+ CORBA::Exception_ptr exception = skel_env.exception ();
+ exception->_incr_refcnt ();
+
+ // The Any does not own the because ultimately it will be owned
+ // by the Server_Request via the call to "set_exception"
+ CORBA::Any any (skel_env.exception ()->_type (), exception);
+ this->set_exception (any, orb_env);
+ }
+#endif
+
+ // Setup a Reply message so that we can marshal all the outgoing parameters
+ // into it. If an exception was set, then that gets marshaled into the reply
+ // message and we don't do anything after that
+ this->init_reply (orb_env);
+
+#if 0 /* ASG */
+ // exception? nothing to do after this
+ if (orb_env.exception () || skel_env.exception ())
+ return;
+#endif
+ TAO_CHECK_ENV_RETURN_VOID (orb_env);
+
+ CORBA::ULong i;
+ const TAO_Param_Data_Skel *pdp;
+ va_list param_vector;
+ va_start (param_vector, info);
+
+ for (i = 0, pdp = info->params;
+ i < info->param_count;
+ i++, pdp++)
+ {
+ void *ptr = va_arg (param_vector, void *);
+
+ if (pdp->mode == 0)
+ {
+ // check if the return type is not void
+ if (pdp->tc->kind (orb_env) != CORBA::tk_void)
+ {
+ // Then just marshal the value.
+ (void) this->outgoing_->encode (pdp->tc, ptr, 0, orb_env);
+ }
+ }
+ else if ((pdp->mode == CORBA::ARG_INOUT)
+ || (pdp->mode == CORBA::ARG_OUT))
+ {
+ // Then just marshal the value.
+ (void) this->outgoing_->encode (pdp->tc, ptr, 0, orb_env);
+ }
+
+ if (orb_env.exception ())
+ {
+ orb_env.print_exception ("ServerRequest::marshal - parameter encode failed");
+ return;
+ }
+ }
+ va_end (param_vector);
+
+}
+
+void
+IIOP_ServerRequest::init_reply (CORBA::Environment &env)
+{
+ // Construct a REPLY header.
+ TAO_GIOP::start_message (TAO_GIOP::Reply,
+ *this->outgoing_,
+ this->orb_core_);
+
+ TAO_GIOP_ServiceContextList resp_ctx;
+ resp_ctx.length (0);
+ *this->outgoing_ << resp_ctx;
+ this->outgoing_->write_ulong (this->request_id_);
+
+ // Standard exceptions are caught in Connect::handle_input
+
+ // Forward exception only.
+ if (!CORBA::is_nil (this->forward_location_.in ()))
+ {
+ this->outgoing_->write_ulong (TAO_GIOP_LOCATION_FORWARD);
+
+ CORBA::Object_ptr object_ptr = this->forward_location_.in ();
+ if ((*this->outgoing_ << object_ptr) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "ServerRequest::marshal - "
+ "encoding forwarded objref failed\n"));
+ return;
+ }
+ }
+
+ // Any exception at all.
+ else if (this->exception_)
+ {
+ CORBA::TypeCode_ptr except_tc;
+
+ except_tc = this->exception_->type ();
+
+ // Finish the GIOP Reply header, then marshal the exception.
+ // XXX x->type () someday ...
+
+ this->outgoing_->write_ulong (this->exception_type_);
+
+ // we use the any's ACE_Message_Block
+ TAO_InputCDR cdr (this->exception_->_tao_get_cdr ());
+ (void) this->outgoing_->append (except_tc, &cdr, env);
+ }
+ else // Normal reply
+ // First finish the GIOP header ...
+ this->outgoing_->write_ulong (TAO_GIOP_NO_EXCEPTION);
+}
+
+CORBA::Object_ptr
+IIOP_ServerRequest::forward_location (void)
+// get the forward_location
+{
+ return CORBA::Object::_duplicate (this->forward_location_.in ());
+}
+
+CORBA::ULong
+IIOP_ServerRequest::exception_type (void)
+// get the exception type
+{
+ return this->exception_type_;
+}