summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Mesnier <mesnier_p@ociweb.com>2013-10-28 21:54:55 +0000
committerPhil Mesnier <mesnier_p@ociweb.com>2013-10-28 21:54:55 +0000
commita0e47b6083ed8ea2044b56a5fd4602ff17026d31 (patch)
tree273b19e3092fd6c85e0e636c607826b95f0b526c
parenta6b86261e177f3b4d8f65409735dfc43784cffc2 (diff)
downloadATCD-a0e47b6083ed8ea2044b56a5fd4602ff17026d31.tar.gz
Mon Oct 28 21:27:19 UTC 2013 Phil Mesnier <mesnier_p@ociweb.com>
* NEWS: * TAO_IDL/ast/ast_operation.cpp: * TAO_IDL/be/be_visitor_operation/ami_cs.cpp: * TAO_IDL/be/be_visitor_operation/operation.cpp: * TAO_IDL/include/ast_operation.h: Add explicit detection of IN or INOUT operation arguments. If there are none, then extend the Invocation Adatpter constructor call to set the new has_in_args flag to false. For backwards compatibility that flag is defaulted to true. * interop-tests/CdrOutArg: Added a new test to demonstrate the fix. There is no explicit regression test for this problem since every CORBA request invokes this code. * tao/GIOP_Message_Generator_Parser_12.cpp: * tao/Invocation_Adapter.h: * tao/Invocation_Adapter.inl: * tao/Invocation_Adapter.cpp: * tao/Messaging/Asynch_Invocation_Adapter.h: * tao/Messaging/Asynch_Invocation_Adapter.cpp: * tao/operation_details.h: * tao/operation_details.inl: Add a new flag, has_in_args, which is true if any of the operation aguments send data with the request. The CDR buffer taking the request is aligned after the header only if there is an IN argument.
-rw-r--r--TAO/ChangeLog33
-rw-r--r--TAO/NEWS7
-rw-r--r--TAO/TAO_IDL/ast/ast_operation.cpp17
-rw-r--r--TAO/TAO_IDL/be/be_visitor_operation/ami_cs.cpp7
-rw-r--r--TAO/TAO_IDL/be/be_visitor_operation/operation.cpp15
-rw-r--r--TAO/TAO_IDL/include/ast_operation.h6
-rw-r--r--TAO/interop-tests/CdrOutArg/README17
-rw-r--r--TAO/interop-tests/CdrOutArg/coa.mwc4
-rw-r--r--TAO/interop-tests/CdrOutArg/idl/test.idl32
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/CdrOutArg.mpc44
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/Client_ORBInitializer.cpp40
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/Client_ORBInitializer.h44
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/Server_ORBInitializer.cpp36
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/Server_ORBInitializer.h44
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/client.cpp91
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/client_interceptor.cpp121
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/client_interceptor.h63
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/server.cpp121
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/server_interceptor.cpp92
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/server_interceptor.h58
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/test_i.cpp20
-rw-r--r--TAO/interop-tests/CdrOutArg/tao/test_i.h42
-rw-r--r--TAO/tao/GIOP_Message_Generator_Parser_12.cpp2
-rw-r--r--TAO/tao/Invocation_Adapter.cpp1
-rw-r--r--TAO/tao/Invocation_Adapter.h5
-rw-r--r--TAO/tao/Invocation_Adapter.inl4
-rw-r--r--TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp6
-rw-r--r--TAO/tao/Messaging/Asynch_Invocation_Adapter.h3
-rw-r--r--TAO/tao/operation_details.h6
-rw-r--r--TAO/tao/operation_details.inl24
30 files changed, 997 insertions, 8 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog
index 1c80fcd6c57..a5f7699d574 100644
--- a/TAO/ChangeLog
+++ b/TAO/ChangeLog
@@ -1,3 +1,36 @@
+Mon Oct 28 21:27:19 UTC 2013 Phil Mesnier <mesnier_p@ociweb.com>
+
+ * NEWS:
+
+ * TAO_IDL/ast/ast_operation.cpp:
+ * TAO_IDL/be/be_visitor_operation/ami_cs.cpp:
+ * TAO_IDL/be/be_visitor_operation/operation.cpp:
+ * TAO_IDL/include/ast_operation.h:
+
+ Add explicit detection of IN or INOUT operation arguments. If there
+ are none, then extend the Invocation Adatpter constructor call to
+ set the new has_in_args flag to false. For backwards compatibility
+ that flag is defaulted to true.
+
+ * interop-tests/CdrOutArg:
+
+ Added a new test to demonstrate the fix. There is no explicit
+ regression test for this problem since every CORBA request invokes
+ this code.
+
+ * tao/GIOP_Message_Generator_Parser_12.cpp:
+ * tao/Invocation_Adapter.h:
+ * tao/Invocation_Adapter.inl:
+ * tao/Invocation_Adapter.cpp:
+ * tao/Messaging/Asynch_Invocation_Adapter.h:
+ * tao/Messaging/Asynch_Invocation_Adapter.cpp:
+ * tao/operation_details.h:
+ * tao/operation_details.inl:
+
+ Add a new flag, has_in_args, which is true if any of the operation
+ aguments send data with the request. The CDR buffer taking the
+ request is aligned after the header only if there is an IN argument.
+
Mon Oct 28 16:33:43 UTC 2013 Phil Mesnier <mesnier_p@ociweb.com>
* orbsvcs/FT_Naming_Service/FT_Naming_Service.cpp:
diff --git a/TAO/NEWS b/TAO/NEWS
index 07ece43dda4..440d255b469 100644
--- a/TAO/NEWS
+++ b/TAO/NEWS
@@ -4,7 +4,12 @@ USER VISIBLE CHANGES BETWEEN TAO-2.2.2 and TAO-2.2.3
USER VISIBLE CHANGES BETWEEN TAO-2.2.1 and TAO-2.2.2
====================================================
-. None
+. Fix for extra CDR padding bytes following a request header when there are no
+ IN or INOUT arguments in the request. This happened when a request had at least
+ one OUT argument, and also had a service context that ended off a CDR alignment
+ boundary. While this is not a problem for TAO-TAO messaging, some non-TAO
+ servers will reject such requests with a MARSHAL exception. See bug 4141 for more
+ information.
USER VISIBLE CHANGES BETWEEN TAO-2.2.0 and TAO-2.2.1
====================================================
diff --git a/TAO/TAO_IDL/ast/ast_operation.cpp b/TAO/TAO_IDL/ast/ast_operation.cpp
index 037629214bd..a1196fcfa78 100644
--- a/TAO/TAO_IDL/ast/ast_operation.cpp
+++ b/TAO/TAO_IDL/ast/ast_operation.cpp
@@ -109,6 +109,7 @@ AST_Operation::AST_Operation (AST_Type *rt,
pd_context (0),
pd_exceptions (0),
argument_count_ (-1),
+ has_in_arguments_ (false),
has_native_ (0)
{
AST_PredefinedType *pdt = 0;
@@ -159,6 +160,15 @@ AST_Operation::argument_count (void)
return this->argument_count_;
}
+// Return the IN/INOUT member flag.
+bool
+AST_Operation::has_in_arguments (void)
+{
+ this->compute_argument_attr ();
+
+ return this->has_in_arguments_;
+}
+
int
AST_Operation::count_arguments_with_direction (int direction_mask)
{
@@ -258,6 +268,13 @@ AST_Operation::compute_argument_attr (void)
arg = AST_Argument::narrow_from_decl (d);
+ if (arg->direction() == AST_Argument::dir_IN ||
+ arg->direction() == AST_Argument::dir_INOUT)
+ {
+ this->has_in_arguments_ = true;
+ }
+
+
type = AST_Type::narrow_from_decl (arg->field_type ());
if (type->node_type () == AST_Decl::NT_native)
diff --git a/TAO/TAO_IDL/be/be_visitor_operation/ami_cs.cpp b/TAO/TAO_IDL/be/be_visitor_operation/ami_cs.cpp
index 0391d3ce521..2895f81d563 100644
--- a/TAO/TAO_IDL/be/be_visitor_operation/ami_cs.cpp
+++ b/TAO/TAO_IDL/be/be_visitor_operation/ami_cs.cpp
@@ -210,6 +210,13 @@ be_visitor_operation_ami_cs::visit_operation (be_operation *node)
*os << " | TAO::TAO_CO_THRU_POA_STRATEGY";
}
+ if (!node->has_in_arguments ())
+ {
+ *os << "," << be_nl
+ << "TAO::TAO_ASYNCHRONOUS_CALLBACK_INVOCATION," << be_nl
+ << "false";
+ }
+
*os << be_uidt_nl
<< ");" << be_uidt;
diff --git a/TAO/TAO_IDL/be/be_visitor_operation/operation.cpp b/TAO/TAO_IDL/be/be_visitor_operation/operation.cpp
index e47803ccefc..7e64f339b65 100644
--- a/TAO/TAO_IDL/be/be_visitor_operation/operation.cpp
+++ b/TAO/TAO_IDL/be/be_visitor_operation/operation.cpp
@@ -294,8 +294,21 @@ be_visitor_operation::gen_stub_operation_body (
if (node->flags () == AST_Operation::OP_oneway)
{
+ *os << "," << be_nl;
+ *os << "TAO::TAO_ONEWAY_INVOCATION" << be_nl;
+ }
+
+ if (!node->has_in_arguments ())
+ {
+ if (node->flags () != AST_Operation::OP_oneway)
+ {
+ *os << "," << be_nl;
+ *os << "TAO::TAO_TWOWAY_INVOCATION" << be_nl;
+ }
+
*os << "," << be_nl
- << "TAO::TAO_ONEWAY_INVOCATION";
+ << "TAO::TAO_SYNCHRONOUS_INVOCATION," << be_nl
+ << "false";
}
*os << be_uidt_nl
diff --git a/TAO/TAO_IDL/include/ast_operation.h b/TAO/TAO_IDL/include/ast_operation.h
index 75fae11e3de..fd3efc4b572 100644
--- a/TAO/TAO_IDL/include/ast_operation.h
+++ b/TAO/TAO_IDL/include/ast_operation.h
@@ -111,6 +111,9 @@ public:
/// Return the number of arguments
virtual int argument_count (void);
+ /// Return the flag indicating a request sends argument data
+ virtual bool has_in_arguments (void);
+
/// Count the number of arguments of a certain type.
/**
* @param direction_mask limit the direction (IN, OUT or INOUT) of
@@ -165,6 +168,9 @@ protected:
int argument_count_;
// Number of arguments.
+ bool has_in_arguments_;
+ // True if any arguments are IN or INOUT
+
int has_native_;
// Is any argument of type native.
diff --git a/TAO/interop-tests/CdrOutArg/README b/TAO/interop-tests/CdrOutArg/README
new file mode 100644
index 00000000000..06130222890
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/README
@@ -0,0 +1,17 @@
+# $Id$
+
+This test validates that TAO does not add unneeded CDR alignment bytes as pad when the
+only arguments to an operation are out args. The interceptors are necessary to add some
+service conotext data that would otherwise require padding. Prior to the fix, and Orbix
+server would throw a MARSHAL exception even though the extra bytes are counted in the
+message length.
+
+To build, use MPC to compile a client in the tao directory, then use Orbix defined tools
+to build the server in the orbix directory.
+
+Tu run, issue the following commands, a successful test will have no exceptions and will
+terminate the server upon completion.
+
+ orbix/server -o test.ior
+
+ tao/client -k file://test.ior
diff --git a/TAO/interop-tests/CdrOutArg/coa.mwc b/TAO/interop-tests/CdrOutArg/coa.mwc
new file mode 100644
index 00000000000..b66da202755
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/coa.mwc
@@ -0,0 +1,4 @@
+// $Id$
+workspace {
+ tao/CdrOutArg.mpc
+}
diff --git a/TAO/interop-tests/CdrOutArg/idl/test.idl b/TAO/interop-tests/CdrOutArg/idl/test.idl
new file mode 100644
index 00000000000..bc825597432
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/idl/test.idl
@@ -0,0 +1,32 @@
+
+//=============================================================================
+/**
+ * @file test.idl
+ *
+ * $Id$
+ *
+ * Test to verify the correctness of the fix for bug 4141
+ *
+ * @author Phil Mesnier <mesnier_p@ociweb.com>
+ */
+//=============================================================================
+
+
+module Interop
+{
+
+ interface CDR_Out_Arg
+ {
+ // = TITLE
+ // A test idl for checking interceptor visually.
+ //
+ // = DESCRIPTION
+ //
+
+ void get_out (out long arg);
+ // Normal operation.
+
+ oneway void shutdown ();
+ // shutdown the ORB
+ };
+};
diff --git a/TAO/interop-tests/CdrOutArg/tao/CdrOutArg.mpc b/TAO/interop-tests/CdrOutArg/tao/CdrOutArg.mpc
new file mode 100644
index 00000000000..fe508ffe2bf
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/CdrOutArg.mpc
@@ -0,0 +1,44 @@
+// -*- MPC -*-
+// $Id$
+
+project(*idl): taoidldefaults {
+ IDL_Files {
+ ../idl/test.idl
+ }
+
+ Modify_Custom(IDL) {
+ output_follows_input = 0
+ }
+
+ custom_only = 1
+}
+
+project(*Server): taoserver, pi_server, interceptors {
+ after += *idl
+ Source_Files {
+ test_i.cpp
+ Server_ORBInitializer.cpp
+ server_interceptor.cpp
+ server.cpp
+ }
+ Source_Files {
+ testC.cpp
+ testS.cpp
+ }
+ IDL_Files {
+ }
+}
+
+project(*Client): taoclient, pi, interceptors {
+ after += *idl
+ Source_Files {
+ Client_ORBInitializer.cpp
+ client_interceptor.cpp
+ client.cpp
+ }
+ Source_Files {
+ testC.cpp
+ }
+ IDL_Files {
+ }
+}
diff --git a/TAO/interop-tests/CdrOutArg/tao/Client_ORBInitializer.cpp b/TAO/interop-tests/CdrOutArg/tao/Client_ORBInitializer.cpp
new file mode 100644
index 00000000000..45170534be6
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/Client_ORBInitializer.cpp
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+//
+// $Id$
+//
+
+#include "Client_ORBInitializer.h"
+#include "client_interceptor.h"
+
+Client_ORBInitializer::Client_ORBInitializer (void)
+{
+}
+
+void
+Client_ORBInitializer::pre_init (
+ PortableInterceptor::ORBInitInfo_ptr)
+{
+}
+
+void
+Client_ORBInitializer::post_init (
+ PortableInterceptor::ORBInitInfo_ptr info)
+{
+
+ CORBA::String_var orb_id =
+ info->orb_id ();
+
+ PortableInterceptor::ClientRequestInterceptor_ptr interceptor =
+ PortableInterceptor::ClientRequestInterceptor::_nil ();
+
+ // Install the Echo client request interceptor
+ ACE_NEW_THROW_EX (interceptor,
+ Echo_Client_Request_Interceptor (orb_id.in ()),
+ CORBA::NO_MEMORY ());
+
+ PortableInterceptor::ClientRequestInterceptor_var
+ client_interceptor = interceptor;
+
+ info->add_client_request_interceptor (client_interceptor.in ());
+}
+
diff --git a/TAO/interop-tests/CdrOutArg/tao/Client_ORBInitializer.h b/TAO/interop-tests/CdrOutArg/tao/Client_ORBInitializer.h
new file mode 100644
index 00000000000..c6cc9c9ebb8
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/Client_ORBInitializer.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+//
+// $Id$
+//
+
+#ifndef TAO_CLIENT_ORB_INITIALIZER_H
+#define TAO_CLIENT_ORB_INITIALIZER_H
+#include /**/ "ace/pre.h"
+
+#include "tao/PI/PI.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "tao/LocalObject.h"
+
+// This is to remove "inherits via dominance" warnings from MSVC.
+// MSVC is being a little too paranoid.
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+/// Client ORB initializer.
+class Client_ORBInitializer :
+ public virtual PortableInterceptor::ORBInitializer,
+ public virtual ::CORBA::LocalObject
+{
+public:
+ /// Constructor
+ Client_ORBInitializer (void);
+
+ virtual void pre_init (PortableInterceptor::ORBInitInfo_ptr info);
+
+ virtual void post_init (PortableInterceptor::ORBInitInfo_ptr info);
+};
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+#endif /* TAO_CLIENT_ORB_INITIALIZER_H */
diff --git a/TAO/interop-tests/CdrOutArg/tao/Server_ORBInitializer.cpp b/TAO/interop-tests/CdrOutArg/tao/Server_ORBInitializer.cpp
new file mode 100644
index 00000000000..ad369d2b7ed
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/Server_ORBInitializer.cpp
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+//
+// $Id$
+//
+
+#include "Server_ORBInitializer.h"
+#include "server_interceptor.h"
+
+Server_ORBInitializer::Server_ORBInitializer (void)
+{
+}
+
+void
+Server_ORBInitializer::pre_init (
+ PortableInterceptor::ORBInitInfo_ptr)
+{
+}
+
+void
+Server_ORBInitializer::post_init (
+ PortableInterceptor::ORBInitInfo_ptr info)
+{
+ PortableInterceptor::ServerRequestInterceptor_ptr interceptor =
+ PortableInterceptor::ServerRequestInterceptor::_nil ();
+
+ // Install the Echo server request interceptor
+ ACE_NEW_THROW_EX (interceptor,
+ Echo_Server_Request_Interceptor,
+ CORBA::NO_MEMORY ());
+
+ PortableInterceptor::ServerRequestInterceptor_var
+ server_interceptor = interceptor;
+
+ info->add_server_request_interceptor (server_interceptor.in ());
+}
+
diff --git a/TAO/interop-tests/CdrOutArg/tao/Server_ORBInitializer.h b/TAO/interop-tests/CdrOutArg/tao/Server_ORBInitializer.h
new file mode 100644
index 00000000000..6bffdffaf04
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/Server_ORBInitializer.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+//
+// $Id$
+//
+
+#ifndef TAO_SERVER_ORB_INITIALIZER_H
+#define TAO_SERVER_ORB_INITIALIZER_H
+#include /**/ "ace/pre.h"
+
+#include "tao/PI/PI.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "tao/LocalObject.h"
+
+// This is to remove "inherits via dominance" warnings from MSVC.
+// MSVC is being a little too paranoid.
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+/// Server ORB initializer.
+class Server_ORBInitializer :
+ public virtual PortableInterceptor::ORBInitializer,
+ public virtual ::CORBA::LocalObject
+{
+public:
+ /// Constructor
+ Server_ORBInitializer (void);
+
+ virtual void pre_init (PortableInterceptor::ORBInitInfo_ptr info);
+
+ virtual void post_init (PortableInterceptor::ORBInitInfo_ptr info);
+};
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+#endif /* TAO_SERVER_ORB_INITIALIZER_H */
diff --git a/TAO/interop-tests/CdrOutArg/tao/client.cpp b/TAO/interop-tests/CdrOutArg/tao/client.cpp
new file mode 100644
index 00000000000..106eb7505fa
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/client.cpp
@@ -0,0 +1,91 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "testC.h"
+#include "Client_ORBInitializer.h"
+
+#include "tao/ORBInitializer_Registry.h"
+
+const ACE_TCHAR *ior = ACE_TEXT("file://test.ior");
+
+int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("k:"));
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'k':
+ ior = get_opts.opt_arg ();
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-k <ior> "
+ "\n",
+ argv [0]),
+ -1);
+ }
+ return 0;
+}
+
+int
+ACE_TMAIN(int argc, ACE_TCHAR *argv[])
+{
+ try
+ {
+ PortableInterceptor::ORBInitializer_ptr temp_initializer;
+
+ ACE_NEW_RETURN (temp_initializer,
+ Client_ORBInitializer,
+ -1); // No exceptions yet!
+ PortableInterceptor::ORBInitializer_var initializer =
+ temp_initializer;
+
+ PortableInterceptor::register_orb_initializer (initializer.in ());
+
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv);
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ CORBA::Object_var object =
+ orb->string_to_object (ior);
+
+ Interop::CDR_Out_Arg_var server =
+ Interop::CDR_Out_Arg::_narrow (object.in ());
+
+ if (CORBA::is_nil (server.in ()))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Object reference <%s> is nil.\n",
+ ior),
+ 1);
+ }
+
+ CORBA::Long lv;
+ CORBA::Long_out arg (lv);
+
+ server->get_out (arg);
+
+ ACE_DEBUG ((LM_DEBUG, "first call passed\n"));
+
+ server->get_out (arg);
+
+ ACE_DEBUG ((LM_DEBUG, "second call passed\n"));
+
+ server->shutdown ();
+
+ orb->destroy ();
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception ("Caught exception in client:");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/TAO/interop-tests/CdrOutArg/tao/client_interceptor.cpp b/TAO/interop-tests/CdrOutArg/tao/client_interceptor.cpp
new file mode 100644
index 00000000000..d119e7ce4c3
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/client_interceptor.cpp
@@ -0,0 +1,121 @@
+// $Id$
+
+#include "client_interceptor.h"
+#include "tao/OctetSeqC.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+
+const IOP::ServiceId service_id = 0xdeadbeef;
+const char *request_msg = "12345678";
+
+Echo_Client_Request_Interceptor::
+Echo_Client_Request_Interceptor (const char *id)
+ : myname_ ("Echo_Client_Interceptor"),
+ orb_id_ (CORBA::string_dup (id))
+{
+}
+
+Echo_Client_Request_Interceptor::~Echo_Client_Request_Interceptor (void)
+{
+}
+
+char *
+Echo_Client_Request_Interceptor::name (void)
+{
+ return CORBA::string_dup (this->myname_);
+}
+
+void
+Echo_Client_Request_Interceptor::destroy (void)
+{
+}
+
+void
+Echo_Client_Request_Interceptor::send_poll (
+ PortableInterceptor::ClientRequestInfo_ptr)
+{
+}
+
+void
+Echo_Client_Request_Interceptor::send_request (
+ PortableInterceptor::ClientRequestInfo_ptr ri)
+{
+
+ if (CORBA::is_nil (this->orb_.in ()))
+ {
+ int argc = 0;
+ ACE_TCHAR **argv = 0;
+ this->orb_ = CORBA::ORB_init (argc, argv,
+ this->orb_id_.in ());
+ }
+
+ CORBA::String_var operation = ri->operation ();
+
+ CORBA::Object_var target = ri->target ();
+
+ CORBA::String_var ior =
+ this->orb_->object_to_string (target.in ());
+
+#if 0
+ ACE_DEBUG ((LM_DEBUG,
+ "%C.send_request "
+ "from \"%C\" on object: %C\n",
+ this->myname_,
+ operation.in (),
+ ior.in ()));
+#endif /*if 0*/
+
+
+
+ // Populate target member of the ClientRequestInfo.
+
+ // Make the context to send the context to the target
+ IOP::ServiceContext sc;
+ sc.context_id = ::service_id;
+
+ CORBA::ULong string_len = ACE_OS::strlen (request_msg) + 1;
+ CORBA::Octet *buf = CORBA::OctetSeq::allocbuf (string_len);
+ ACE_OS::strcpy (reinterpret_cast<char *> (buf), request_msg);
+
+ sc.context_data.replace (string_len, string_len, buf, 1);
+
+ // Add this context to the service context list.
+ ri->add_request_service_context (sc, 0);
+
+ // Check that the request service context can be retrieved.
+ IOP::ServiceContext_var sc2 =
+ ri->get_request_service_context (::service_id);
+
+ const char *buf2 =
+ reinterpret_cast<const char *> (sc2->context_data.get_buffer ());
+
+ if (ACE_OS::strcmp (buf2, request_msg) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "ERROR: Expected request service context to be: %C.\n"
+ " Got: %C\n",
+ request_msg,
+ buf2));
+ }
+
+}
+
+void
+Echo_Client_Request_Interceptor::receive_reply (
+ PortableInterceptor::ClientRequestInfo_ptr )
+{
+}
+
+void
+Echo_Client_Request_Interceptor::receive_other (
+ PortableInterceptor::ClientRequestInfo_ptr)
+{
+}
+
+void
+Echo_Client_Request_Interceptor::receive_exception (
+ PortableInterceptor::ClientRequestInfo_ptr )
+{
+}
+
diff --git a/TAO/interop-tests/CdrOutArg/tao/client_interceptor.h b/TAO/interop-tests/CdrOutArg/tao/client_interceptor.h
new file mode 100644
index 00000000000..25510e64609
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/client_interceptor.h
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifndef TAO_CLIENT_INTERCEPTOR_H
+#define TAO_CLIENT_INTERCEPTOR_H
+
+#include "tao/PI/PI.h"
+#include "tao/PortableInterceptorC.h"
+#include "tao/LocalObject.h"
+#include "tao/ORB.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+class Echo_Client_Request_Interceptor
+ : public virtual PortableInterceptor::ClientRequestInterceptor,
+ public virtual ::CORBA::LocalObject
+{
+ // = Client-side echo interceptor. For checking interceptor visually only.
+public:
+ Echo_Client_Request_Interceptor (const char *orb_id);
+ // ctor.
+
+ virtual ~Echo_Client_Request_Interceptor ();
+ // dtor.
+
+ virtual char * name (void);
+ // Canonical name of the interceptor.
+
+ virtual void destroy (void);
+
+ virtual void send_poll (PortableInterceptor::ClientRequestInfo_ptr);
+
+ virtual void send_request (PortableInterceptor::ClientRequestInfo_ptr ri);
+
+ virtual void receive_reply (PortableInterceptor::ClientRequestInfo_ptr ri);
+
+ virtual void receive_other (PortableInterceptor::ClientRequestInfo_ptr);
+
+ virtual void receive_exception (PortableInterceptor::ClientRequestInfo_ptr ri);
+
+private:
+ const char *myname_;
+
+ CORBA::String_var orb_id_;
+ // The ID of the ORB where this interceptor was created, usually
+ // obtained from the ORBInitInfo
+
+ CORBA::ORB_var orb_;
+};
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#endif /* TAO_CLIENT_INTERCEPTOR_H */
diff --git a/TAO/interop-tests/CdrOutArg/tao/server.cpp b/TAO/interop-tests/CdrOutArg/tao/server.cpp
new file mode 100644
index 00000000000..7b9a6ad3c05
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/server.cpp
@@ -0,0 +1,121 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "test_i.h"
+#include "Server_ORBInitializer.h"
+
+#include "tao/ORBInitializer_Registry.h"
+#include "ace/OS_NS_stdio.h"
+
+const ACE_TCHAR *ior_output_file = ACE_TEXT("test.ior");
+
+int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("o:"));
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'o':
+ ior_output_file = get_opts.opt_arg ();
+ break;
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-o <iorfile>"
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates successful parsing of the command line
+ return 0;
+}
+
+int
+ACE_TMAIN(int argc, ACE_TCHAR *argv[])
+{
+ try
+ {
+ PortableInterceptor::ORBInitializer_ptr temp_initializer;
+
+ ACE_NEW_RETURN (temp_initializer,
+ Server_ORBInitializer,
+ -1); // No exceptions yet!
+ PortableInterceptor::ORBInitializer_var initializer =
+ temp_initializer;
+
+ PortableInterceptor::register_orb_initializer (initializer.in ());
+
+ // Now we can create the ORB
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv);
+
+ CORBA::Object_var poa_object =
+ orb->resolve_initial_references ("RootPOA");
+
+ if (CORBA::is_nil (poa_object.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Unable to initialize the POA.\n"),
+ 1);
+
+ PortableServer::POA_var root_poa =
+ PortableServer::POA::_narrow (poa_object.in ());
+
+ PortableServer::POAManager_var poa_manager =
+ root_poa->the_POAManager ();
+
+ poa_manager->activate ();
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ CDR_Out_Arg_i server_impl (orb.in ());
+
+ PortableServer::ObjectId_var id =
+ root_poa->activate_object (&server_impl);
+
+ CORBA::Object_var test_obj =
+ root_poa->id_to_reference (id.in ());
+
+ Interop::CDR_Out_Arg_var server =
+ Interop::CDR_Out_Arg::_narrow (test_obj.in ());
+
+ CORBA::String_var ior =
+ orb->object_to_string (server.in ());
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Interop::CDR_Out_Arg: <%C>\n",
+ ior.in ()));
+
+ // If the ior_output_file exists, output the ior to it
+ if (ior_output_file != 0)
+ {
+ FILE *output_file= ACE_OS::fopen (ior_output_file, "w");
+ if (output_file == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Cannot open output file for writing IOR: %s",
+ ior_output_file),
+ 1);
+ ACE_OS::fprintf (output_file, "%s", ior.in ());
+ ACE_OS::fclose (output_file);
+ }
+
+ orb->run ();
+
+ ACE_DEBUG ((LM_DEBUG, "event loop finished\n"));
+
+ root_poa->destroy (1, 1);
+
+ orb->destroy ();
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception ("Caught exception in server:");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/TAO/interop-tests/CdrOutArg/tao/server_interceptor.cpp b/TAO/interop-tests/CdrOutArg/tao/server_interceptor.cpp
new file mode 100644
index 00000000000..e21b78a994c
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/server_interceptor.cpp
@@ -0,0 +1,92 @@
+// $Id$
+
+#include "server_interceptor.h"
+#include "tao/OctetSeqC.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+
+const IOP::ServiceId service_id = 0xdeadbeef;
+const char *request_msg = "12345678";
+
+
+Echo_Server_Request_Interceptor::Echo_Server_Request_Interceptor (void)
+ : myname_ ("Echo_Server_Interceptor")
+{
+}
+
+Echo_Server_Request_Interceptor::~Echo_Server_Request_Interceptor (void)
+{
+}
+
+char *
+Echo_Server_Request_Interceptor::name (void)
+{
+ return CORBA::string_dup (this->myname_);
+}
+
+void
+Echo_Server_Request_Interceptor::destroy (void)
+{
+}
+
+void
+Echo_Server_Request_Interceptor::receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri)
+{
+
+ CORBA::String_var operation = ri->operation ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%C.receive_request_service_contexts from "
+ "\"%C\"\n",
+ this->myname_,
+ operation.in ()));
+
+ IOP::ServiceId id = ::service_id;
+ IOP::ServiceContext_var sc =
+ ri->get_request_service_context (id);
+
+ const char *buf =
+ reinterpret_cast<const char *> (sc->context_data.get_buffer ());
+#if 0
+ ACE_DEBUG ((LM_DEBUG,
+ " Received service context: %C\n",
+ buf));
+#endif /*if 0*/
+
+ if (ACE_OS::strcmp (buf, request_msg) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "ERROR: Echo_Server_Request_Interceptor::receive_request_service_contexts: "
+ "Expected request service context to be: %C\n",
+ request_msg));
+ }
+
+}
+
+
+void
+Echo_Server_Request_Interceptor::receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr)
+{
+ // Do nothing
+}
+
+void
+Echo_Server_Request_Interceptor::send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr )
+{
+}
+
+void
+Echo_Server_Request_Interceptor::send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr )
+{
+}
+
+void
+Echo_Server_Request_Interceptor::send_other (
+ PortableInterceptor::ServerRequestInfo_ptr)
+{
+}
diff --git a/TAO/interop-tests/CdrOutArg/tao/server_interceptor.h b/TAO/interop-tests/CdrOutArg/tao/server_interceptor.h
new file mode 100644
index 00000000000..12d511c2291
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/server_interceptor.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifndef TAO_SERVER_INTERCEPTOR_H
+#define TAO_SERVER_INTERCEPTOR_H
+
+#include "tao/PI_Server/PI_Server.h"
+#include "tao/PortableInterceptorC.h"
+#include "tao/LocalObject.h"
+#include "tao/ORB.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+class Echo_Server_Request_Interceptor
+ : public virtual PortableInterceptor::ServerRequestInterceptor,
+ public virtual ::CORBA::LocalObject
+{
+ // = Server-side echo interceptor. For checking interceptor visually only.
+public:
+ Echo_Server_Request_Interceptor (void);
+ // cotr.
+
+ ~Echo_Server_Request_Interceptor ();
+ // dotr.
+
+ virtual char * name (void);
+ // Canonical name of the interceptor.
+
+ virtual void destroy (void);
+
+ virtual void receive_request (PortableInterceptor::ServerRequestInfo_ptr ri);
+
+ virtual void receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr);
+
+ virtual void send_reply (PortableInterceptor::ServerRequestInfo_ptr ri);
+
+ virtual void send_exception (PortableInterceptor::ServerRequestInfo_ptr ri);
+
+ virtual void send_other (PortableInterceptor::ServerRequestInfo_ptr);
+
+private:
+ const char *myname_;
+};
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#endif /* TAO_SERVER_INTERCEPTOR_H */
diff --git a/TAO/interop-tests/CdrOutArg/tao/test_i.cpp b/TAO/interop-tests/CdrOutArg/tao/test_i.cpp
new file mode 100644
index 00000000000..8d4e9c83763
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/test_i.cpp
@@ -0,0 +1,20 @@
+// $Id$
+
+#include "test_i.h"
+
+CDR_Out_Arg_i::CDR_Out_Arg_i (CORBA::ORB_ptr orb)
+ : orb_ (CORBA::ORB::_duplicate (orb))
+{
+}
+
+void
+CDR_Out_Arg_i::get_out (CORBA::Long_out arg)
+{
+ arg = 100;
+}
+
+void
+CDR_Out_Arg_i::shutdown (void)
+{
+ this->orb_->shutdown (0);
+}
diff --git a/TAO/interop-tests/CdrOutArg/tao/test_i.h b/TAO/interop-tests/CdrOutArg/tao/test_i.h
new file mode 100644
index 00000000000..2d1c46e48bd
--- /dev/null
+++ b/TAO/interop-tests/CdrOutArg/tao/test_i.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file test_i.h
+ *
+ * $Id$
+ *
+ * @author Phil Mesnier
+ */
+//=============================================================================
+
+
+#ifndef CDR_OUT_ARG_TEST_I_H
+#define CDR_OUT_ARG_TEST_I_H
+
+#include "testS.h"
+
+/**
+ * @class CDR_Out_Arg_i
+ *
+ * Implements the CDR_Out_Arg interface
+ */
+class CDR_Out_Arg_i : public POA_Interop::CDR_Out_Arg
+{
+
+public:
+
+ CDR_Out_Arg_i (CORBA::ORB_ptr orb);
+
+ void get_out (CORBA::Long_out arg);
+
+ void shutdown (void);
+
+private:
+
+ /// The ORB pseudo-reference (for shutdown).
+ CORBA::ORB_var orb_;
+
+};
+
+#endif /* TAO_INTERCEPTOR_TEST_I_H */
diff --git a/TAO/tao/GIOP_Message_Generator_Parser_12.cpp b/TAO/tao/GIOP_Message_Generator_Parser_12.cpp
index 88c604c5e3a..30013e41745 100644
--- a/TAO/tao/GIOP_Message_Generator_Parser_12.cpp
+++ b/TAO/tao/GIOP_Message_Generator_Parser_12.cpp
@@ -83,7 +83,7 @@ TAO_GIOP_Message_Generator_Parser_12::write_request_header (
return false;
// We align the pointer only if the operation has arguments.
- if (opdetails.argument_flag ()
+ if (opdetails.in_argument_flag ()
&& msg.align_write_ptr (TAO_GIOP_MESSAGE_ALIGN_PTR) == -1)
{
return false;
diff --git a/TAO/tao/Invocation_Adapter.cpp b/TAO/tao/Invocation_Adapter.cpp
index f72485b9884..5ea580f11b1 100644
--- a/TAO/tao/Invocation_Adapter.cpp
+++ b/TAO/tao/Invocation_Adapter.cpp
@@ -41,6 +41,7 @@ namespace TAO
this->op_len_,
this->args_,
this->number_args_,
+ this->has_in_args_,
ex_data,
ex_count);
diff --git a/TAO/tao/Invocation_Adapter.h b/TAO/tao/Invocation_Adapter.h
index b1ec5f7db19..ff8364806a5 100644
--- a/TAO/tao/Invocation_Adapter.h
+++ b/TAO/tao/Invocation_Adapter.h
@@ -110,7 +110,8 @@ namespace TAO
size_t op_len,
int collocation_opportunity,
TAO::Invocation_Type type = TAO_TWOWAY_INVOCATION,
- TAO::Invocation_Mode mode = TAO_SYNCHRONOUS_INVOCATION);
+ TAO::Invocation_Mode mode = TAO_SYNCHRONOUS_INVOCATION,
+ bool has_in_args = true);
virtual ~Invocation_Adapter (void);
@@ -262,6 +263,8 @@ namespace TAO
*/
int const number_args_;
+ bool has_in_args_;
+
/// Name of the operation.
char const * operation_;
diff --git a/TAO/tao/Invocation_Adapter.inl b/TAO/tao/Invocation_Adapter.inl
index 7acff3aa75a..afc66efda9e 100644
--- a/TAO/tao/Invocation_Adapter.inl
+++ b/TAO/tao/Invocation_Adapter.inl
@@ -15,10 +15,12 @@ namespace TAO
size_t op_len,
int collocation_opportunity,
Invocation_Type type,
- Invocation_Mode mode)
+ Invocation_Mode mode,
+ bool has_in_args)
: target_ (target)
, args_ (args)
, number_args_ (arg_number)
+ , has_in_args_ (has_in_args)
, operation_ (operation)
, op_len_ (op_len)
, collocation_opportunity_ (collocation_opportunity)
diff --git a/TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp b/TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp
index 0de1273408c..5a760c4b7e2 100644
--- a/TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp
+++ b/TAO/tao/Messaging/Asynch_Invocation_Adapter.cpp
@@ -28,7 +28,8 @@ namespace TAO
const char *operation,
size_t op_len,
int collocation_opportunity,
- Invocation_Mode m)
+ Invocation_Mode m,
+ bool has_in_args)
: Invocation_Adapter (target,
args,
arg_number,
@@ -36,7 +37,8 @@ namespace TAO
op_len,
collocation_opportunity,
TAO_TWOWAY_INVOCATION,
- m)
+ m,
+ has_in_args)
, safe_rd_ ()
{
}
diff --git a/TAO/tao/Messaging/Asynch_Invocation_Adapter.h b/TAO/tao/Messaging/Asynch_Invocation_Adapter.h
index c562f2fcba8..fe3b1545ffe 100644
--- a/TAO/tao/Messaging/Asynch_Invocation_Adapter.h
+++ b/TAO/tao/Messaging/Asynch_Invocation_Adapter.h
@@ -68,7 +68,8 @@ namespace TAO
const char *operation,
size_t op_len,
int collocation_opportunity,
- TAO::Invocation_Mode mode = TAO_ASYNCHRONOUS_CALLBACK_INVOCATION);
+ TAO::Invocation_Mode mode = TAO_ASYNCHRONOUS_CALLBACK_INVOCATION,
+ bool has_in_args = true);
void invoke (Messaging::ReplyHandler_ptr reply_handler_ptr,
const TAO_Reply_Handler_Stub &reply_handler_stub);
diff --git a/TAO/tao/operation_details.h b/TAO/tao/operation_details.h
index f7ee74f340f..05c71072d6b 100644
--- a/TAO/tao/operation_details.h
+++ b/TAO/tao/operation_details.h
@@ -76,6 +76,7 @@ public:
CORBA::ULong len,
TAO::Argument **args = 0,
CORBA::ULong num_args = 0,
+ CORBA::Boolean has_in_args = true,
TAO::Exception_Data *ex_data = 0,
CORBA::ULong ex_count = 0);
@@ -88,6 +89,7 @@ public:
/// Return the flag that indicates whether the operation has any
/// arguments
CORBA::Boolean argument_flag (void) const;
+ CORBA::Boolean in_argument_flag (void) const;
/// Set the response flags
void response_flags (CORBA::Octet flags);
@@ -209,6 +211,9 @@ private:
/// Number of arguments including the return value
CORBA::ULong num_args_;
+ /// A flag indicating any args are sent with the request
+ CORBA::Boolean has_in_args_;
+
/// The type of exceptions that the operations can throw.
TAO::Exception_Data *ex_data_;
@@ -232,6 +237,7 @@ private:
/// The optional reply dispatcher
TAO_Reply_Dispatcher *reply_dispatcher_;
+
};
TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/tao/operation_details.inl b/TAO/tao/operation_details.inl
index 3c9d6f6a35e..cbd733b5838 100644
--- a/TAO/tao/operation_details.inl
+++ b/TAO/tao/operation_details.inl
@@ -9,6 +9,7 @@ TAO_Operation_Details::TAO_Operation_Details (const char *name,
CORBA::ULong len,
TAO::Argument **args,
CORBA::ULong num,
+ CORBA::Boolean has_in_args,
TAO::Exception_Data *data,
CORBA::ULong count)
: opname_ (name)
@@ -18,6 +19,7 @@ TAO_Operation_Details::TAO_Operation_Details (const char *name,
, addressing_mode_ (TAO_Target_Specification::Key_Addr)
, args_ (args)
, num_args_ (num)
+ , has_in_args_ (has_in_args)
, ex_data_ (data)
, ex_count_ (count)
, use_stub_args_ (args ? true : false)
@@ -48,6 +50,28 @@ TAO_Operation_Details::argument_flag (void) const
return (this->num_args_ > 1);
}
+#if 1
+ACE_INLINE CORBA::Boolean
+TAO_Operation_Details::in_argument_flag (void) const
+{
+ return this->has_in_args_ && this->num_args_ > 1;
+}
+#else
+ACE_INLINE CORBA::Boolean
+TAO_Operation_Details::in_argument_flag (void) const
+{
+ for (CORBA::ULong i = 1; i < this->num_args_ && !this->has_in_args_; i++)
+ {
+ if (dynamic_cast<TAO::InArgument *>(args_[i]) != 0 ||
+ dynamic_cast<TAO::InoutArgument *>(args_[i]))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+#endif // TAO_IGNORE_IN_ARGS
+
ACE_INLINE TAO_Service_Context &
TAO_Operation_Details::request_service_context (void)
{