summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsma <sma@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2013-05-16 09:01:45 +0000
committersma <sma@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2013-05-16 09:01:45 +0000
commit1efdd1ac4f544644c62c929bddea94f4a69e4187 (patch)
tree02ee4a57e76f0e688bb0e2765085c8672000e6a3
parente8b3f3495ae8c13b09ffe85e7eb8072ff08d3d98 (diff)
downloadATCD-1efdd1ac4f544644c62c929bddea94f4a69e4187.tar.gz
Thu May 16 09:01:00 UTC 2013 Simon Massey <simon dot massey at prismtech dot com> add -ORBListenerInterface to UDP/MIOP
-rw-r--r--TAO/ChangeLog27
-rw-r--r--TAO/bin/tao_other_tests.lst1
-rw-r--r--TAO/docs/Options.html37
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp58
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h7
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp65
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h4
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.cpp186
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.h13
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/McastHello.cpp65
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/McastHello.h47
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/McastLocal.mpc34
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/README19
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/Test.idl26
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/client.cpp92
-rwxr-xr-xTAO/orbsvcs/tests/Miop/McastLocal/run_test.pl126
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/server.cpp121
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/svc_client.conf6
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/svc_server1.conf6
-rw-r--r--TAO/orbsvcs/tests/Miop/McastLocal/svc_server2.conf6
-rw-r--r--TAO/tao/params.cpp50
-rw-r--r--TAO/tao/params.h5
22 files changed, 906 insertions, 95 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog
index db34adb5734..45548a5157b 100644
--- a/TAO/ChangeLog
+++ b/TAO/ChangeLog
@@ -1,3 +1,30 @@
+Thu May 16 09:01:00 UTC 2013 Simon Massey <simon dot massey at prismtech dot com>
+
+ * docs/Options.html:
+ * tao/params.h:
+ * tao/params.cpp:
+ * orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h:
+ * orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp:
+ * orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h:
+ * orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp:
+ * orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.h:
+ * orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.cpp:
+ * orbsvcs/tests/Miop/McastLocal/client.cpp:
+ * orbsvcs/tests/Miop/McastLocal/McastHello.cpp:
+ * orbsvcs/tests/Miop/McastLocal/McastHello.h:
+ * orbsvcs/tests/Miop/McastLocal/McastLocal.mpc:
+ * orbsvcs/tests/Miop/McastLocal/README:
+ * orbsvcs/tests/Miop/McastLocal/run_test.pl:
+ * orbsvcs/tests/Miop/McastLocal/server.cpp:
+ * orbsvcs/tests/Miop/McastLocal/svc_client.conf:
+ * orbsvcs/tests/Miop/McastLocal/svc_server1.conf:
+ * orbsvcs/tests/Miop/McastLocal/svc_server2.conf:
+ * orbsvcs/tests/Miop/McastLocal/Test.idl:
+ * bin/tao_other_tests.lst:
+
+ Provide UIPMC Factory configuration option -ORBListenerInterfaces
+ see docs/Options.html for details.
+
Wed May 15 18:21:40 UTC 2013 Johnny Willemsen <jwillemsen@remedy.nl>
* tao/Exception.cpp:
diff --git a/TAO/bin/tao_other_tests.lst b/TAO/bin/tao_other_tests.lst
index deca7a3ed5a..68ff86d2cfd 100644
--- a/TAO/bin/tao_other_tests.lst
+++ b/TAO/bin/tao_other_tests.lst
@@ -205,6 +205,7 @@ TAO/orbsvcs/tests/Security/EndpointPolicy/run_test.pl: SSL !STATIC !DISABLE_INTE
TAO/orbsvcs/tests/Security/Null_Cipher/run_test.pl: SSL !STATIC !DISABLE_INTERCEPTORS !ACE_FOR_TAO !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO
TAO/orbsvcs/tests/Security/MT_BiDir_SSL/run_test.pl: SSL !STATIC !DISABLE_INTERCEPTORS !ACE_FOR_TAO !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO !GIOP10 !DISABLE_BIDIR !LynxOS
TAO/orbsvcs/tests/Miop/McastHello/run_test.pl: !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO !STATIC !NO_MCAST
+TAO/orbsvcs/tests/Miop/McastLocal/run_test.pl: !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO !STATIC !NO_MCAST
TAO/orbsvcs/tests/Miop/McastZIOP/run_test.pl: !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO !STATIC !NO_MCAST ZLIB
TAO/orbsvcs/tests/Miop/McastPreferredInterfaces/run_test.pl: !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO !STATIC !NO_MCAST
TAO/orbsvcs/tests/Miop/McastPreferredInterfaces/run_test_ipv6.pl: !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO !STATIC !NO_MCAST IPV6
diff --git a/TAO/docs/Options.html b/TAO/docs/Options.html
index 7d075cabdff..50938b3278b 100644
--- a/TAO/docs/Options.html
+++ b/TAO/docs/Options.html
@@ -1842,7 +1842,9 @@ strategy.
</tr>
<tr>
<td ALIGN="left"><code>&#8209;ORBListenOnAll</code> <em>0 | 1</em></td>
- <td ALIGN="left">This is a server-side (listener) option that by default is disabled.
+ <td ALIGN="left">This is a server-side (listener) option that by default is disabled; however
+ this option only takes effect where no <code>&#8209;ORBListenerInterfaces</code>
+ directives (if any, see below) match the actual multicast address being set-up.
<p>If disabled (<em>0</em>) the multicast address will be listened for only on the default multicast
interface associated with the <CODE>INADDR_ANY</CODE> local address (normally the first such
local interface on the system), the loopback interface is normally excluded.</p>
@@ -1850,6 +1852,39 @@ strategy.
interface(s) which are multicast enabled (again the loopback interface is normally excluded).
</td>
</tr>
+ <tr>
+ <td ALIGN="left"><code>&#8209;ORBListenerInterfaces</code> <em>targetNetwork=localNetwork[,...] | CopyPreferredInterfaces</em></td>
+ <td ALIGN="left">This is a server-side (listener) option that specifies, on a multihomed host,
+ which network/interface(s) are to be used to listen for communications from the multicast addressed
+ remote client(s). If this option is unspecified (or if none of the given
+ <em>targetNetwork=localNetwork</em> patterns match the current addresses being set-up for
+ the attempted listener) then the default listener will be set-up as specified or defaulted with the
+ <code>&#8209;ORBListenOnAll</code> see above.
+ Otherwise when TAO attempts to establish the listeners for a <em>targetNetwork</em> multicast
+ address(es), it will use the local ip address(es) matching the <em>localNetwork</em> string. Simple
+ wildcards can be used for both parameters, and multiple paired <em>targetNetwork=localNetwork</em>
+ strings can be specified using comma separators (no embedded spaces allowed) or via additional
+ <code>&#8209;ORBListenerInterfaces</code> directives. It is also possiable to specify loopback
+ and/or multiple interfaces at the same time for each listener established via such
+ <code>&#8209;ORBListenerInterfaces</code> directives.
+ <p>
+ For example, for a machine with two network cards identified by the ip addresses
+ <code>192.168.1.10</code> and <code>192.168.1.20</code>, you can use the single directive
+ <code>&#8209;ORBListenerInterfaces 239.255.*=*10,224.255.*=*20</code> or the pair of directives
+ <code>&#8209;ORBListenerInterfaces 239.255.*=*10 &#8209;ORBListenerInterfaces 224.255.*=*20</code>
+ to establish the link to listen for <em>239.255.*</em> multicast addresses on the first interface, and
+ <em>224.255.*</em> multicast addresses on the second interface.</p>
+ <em>targetNetwork</em> can use any string, but must typically match the value writen into the IOR and so
+ will usually be a dotted decimal multicast address in the administrative "site local" range,
+ (<em>224.255.0.0</em> to <em>238.255.255.255</em>) or (<em>239.255.0.0</em> to <em>239.255.255.255</em>).
+ <p><em>localNetwork</em> must use a local dotted decimal address, because it will be matched with
+ the local ip interfaces.</p>
+ The same client-side (sender) assignments as specified by the ORB_init supplied command line option(s)
+ <code>&#8209;ORBPreferredInterfaces</code> can be duplicated by specifying the single special
+ <em>CopyPreferredInterfaces</em> parameter as in <code>&#8209;ORBListenerInterfaces CopyPreferredInterfaces</code>
+ (which may be prefixed and/or postfixed by other <code>&#8209;ORBListenerInterfaces <em>targetNetwork=localNetwork</em></code>
+ options as required).
+ </tr>
</tbody>
</table>
</blockquote>
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp
index 9b0629baa60..22aae4554e0 100644
--- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.cpp
@@ -17,14 +17,16 @@
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
TAO_UIPMC_Acceptor::TAO_UIPMC_Acceptor (
- bool listen_on_all_ifs)
+ bool listen_on_all_ifs,
+ const char *listener_interfaces)
: TAO_Acceptor (IOP::TAG_UIPMC),
addrs_ (0),
hosts_ (0),
endpoint_count_ (0),
version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR),
orb_core_ (0),
- listen_on_all_ (listen_on_all_ifs)
+ listen_on_all_ (listen_on_all_ifs),
+ listener_interfaces_ (listener_interfaces)
{
}
@@ -228,6 +230,56 @@ TAO_UIPMC_Acceptor::open_i (
const ACE_INET_Addr &addr,
ACE_Reactor *reactor)
{
+ // Check for the special "CopyPreferredInterfaces" token(s) stored in the
+ // listener_interfaces_ string. If found, subsitute each one for the actual
+ // -ORBPreferredInterfaces string set on the ORB_init command line.
+ for (ACE_CString::size_type foundToken =
+ this->listener_interfaces_.find (CopyPreferredInterfaceToken);
+ ACE_CString::npos != foundToken;
+ foundToken =
+ this->listener_interfaces_.find (CopyPreferredInterfaceToken))
+ {
+ ACE_CString
+ left = this->listener_interfaces_.substr (0, foundToken),
+ right = this->listener_interfaces_.substr (foundToken +
+ static_cast<ACE_CString::size_type> (
+ sizeof (CopyPreferredInterfaceToken)-1u ));
+ const char *preferred_interfaces =
+ this->orb_core_->orb_params ()->preferred_interfaces ();
+ if (preferred_interfaces && preferred_interfaces[0])
+ {
+ // Subsitute the token for the actual string, if not null
+ // left/right will always end/start with a ','
+ this->listener_interfaces_ =
+ left + preferred_interfaces + right;
+ }
+ else
+ {
+ // No preferred_interfaces specified
+ if (',' == right[0]) // Right is not null
+ {
+ // Need to remove the token, AND one of the seporating ','
+ this->listener_interfaces_ =
+ left + right.substr (1);
+ }
+ else // Since right must also be a null string
+ {
+ const ACE_CString::size_type length= left.length ();
+ if (length)
+ {
+ // Since we only have the left, remove the trailing ','
+ this->listener_interfaces_ = left.substr (0, length-1);
+ }
+ else
+ {
+ // Since BOTH left and right are empty, removing the
+ // token leaves an empty string.
+ this->listener_interfaces_ = "";
+ }
+ }
+ }
+ } // End loop replacing all preferred_interfaces tokens.
+
// Create our connection handler and pass it our configurtion options.
TAO_UIPMC_Mcast_Connection_Handler *connection_handler = 0;
ACE_NEW_RETURN (connection_handler,
@@ -235,6 +287,8 @@ TAO_UIPMC_Acceptor::open_i (
-1);
connection_handler->local_addr (addr);
connection_handler->listen_on_all (this->listen_on_all_);
+ connection_handler->listener_interfaces (
+ this->listener_interfaces_.c_str ());
if (connection_handler->open (0))
{
ORBSVCS_DEBUG ((LM_ERROR,
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h
index 92cfacea3fc..aa3add29a2f 100644
--- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Acceptor.h
@@ -32,6 +32,9 @@
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+// Note [] as sizeof used to infer length
+static const char CopyPreferredInterfaceToken[]= "$$$$";
+
// TAO UIPMC_Acceptor concrete call definition
/**
@@ -45,7 +48,8 @@ class TAO_PortableGroup_Export TAO_UIPMC_Acceptor : public TAO_Acceptor
{
public:
/// Constructor.
- TAO_UIPMC_Acceptor (bool listen_on_all_ifs);
+ TAO_UIPMC_Acceptor (bool listen_on_all_ifs,
+ const char *listener_interfaces);
/// Destructor.
~TAO_UIPMC_Acceptor (void);
@@ -143,6 +147,7 @@ protected:
private:
bool listen_on_all_;
+ ACE_CString listener_interfaces_;
};
TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp
index 7dc9964246c..bd89d905f7b 100644
--- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.cpp
@@ -5,8 +5,10 @@
#include "orbsvcs/PortableGroup/UIPMC_Acceptor.h"
#include "orbsvcs/PortableGroup/UIPMC_Connector.h"
#include "tao/ORB_Constants.h"
+#include "tao/params.h" // TAO_ORB_Parameters::check_preferred_interfaces_string ()
#include "ace/OS_NS_strings.h"
#include "ace/UUID.h"
+#include "ace/Arg_Shifter.h"
static const char the_prefix[] = "uipmc";
@@ -16,7 +18,8 @@ TAO_UIPMC_Protocol_Factory::TAO_UIPMC_Protocol_Factory (void)
: TAO_Protocol_Factory (IOP::TAG_UIPMC),
major_ (TAO_DEF_GIOP_MAJOR),
minor_ (TAO_DEF_GIOP_MINOR),
- listen_on_all_(false)
+ listen_on_all_ (false),
+ listener_interfaces_ ()
{
}
@@ -48,7 +51,9 @@ TAO_UIPMC_Protocol_Factory::make_acceptor (void)
{
TAO_Acceptor *acceptor = 0;
ACE_NEW_RETURN (acceptor,
- TAO_UIPMC_Acceptor (this->listen_on_all_),
+ TAO_UIPMC_Acceptor (
+ this->listen_on_all_,
+ this->listener_interfaces_.c_str ()),
0);
return acceptor;
@@ -58,25 +63,65 @@ int
TAO_UIPMC_Protocol_Factory::init (int argc,
ACE_TCHAR* argv [])
{
- for (int curarg = 0; curarg < argc; ++curarg)
+ ACE_Arg_Shifter arg_shifter (argc, argv);
+
+ while (arg_shifter.is_anything_left ())
{
+ const ACE_TCHAR *current_arg = 0;
+
// This option lets you override the default
- if (ACE_OS::strcasecmp (argv[curarg],
- ACE_TEXT ("-ORBListenOnAll")) == 0)
+ if (0 != (current_arg = arg_shifter.get_the_parameter
+ (ACE_TEXT("-ORBListenOnAll"))))
+ {
+ this->listen_on_all_ = !!ACE_OS::atoi (current_arg);
+ arg_shifter.consume_arg ();
+ }
+ else if (0 != (current_arg = arg_shifter.get_the_parameter
+ (ACE_TEXT("-ORBListenerInterfaces"))) ||
+ 0 != (current_arg = arg_shifter.get_the_parameter
+ (ACE_TEXT("-ORBListenerInterface"))) ||
+ 0 != (current_arg = arg_shifter.get_the_parameter
+ (ACE_TEXT("-ORBListenInterfaces"))) ||
+ 0 != (current_arg = arg_shifter.get_the_parameter
+ (ACE_TEXT("-ORBListenInterface"))) )
{
- ++curarg;
- if (curarg < argc)
+ if (0 == ACE_OS::strcasecmp (current_arg, ACE_TEXT ("CopyPreferredInterfaces")) ||
+ 0 == ACE_OS::strcasecmp (current_arg, ACE_TEXT ("CopyPreferredInterface")) )
{
- if (curarg < argc)
- this->listen_on_all_ = (bool) ACE_OS::atoi (argv[curarg]);
+ // Add a special token (see TAO_UIPMC_Acceptor) which will be
+ // subsituted (when we have access to the orb->params).
+ if (this->listener_interfaces_.length ())
+ this->listener_interfaces_+= ',';
+ this->listener_interfaces_+= CopyPreferredInterfaceToken;
}
+ else
+ {
+ const char *const always_char = ACE_TEXT_ALWAYS_CHAR (current_arg);
+ if (TAO_ORB_Parameters::check_preferred_interfaces_string (always_char))
+ {
+ // Append any valid string to those already specified
+ // (by other -ORBListenerInterfaces options that have been
+ // seen previously)
+ if (this->listener_interfaces_.length ())
+ this->listener_interfaces_+= ',';
+ this->listener_interfaces_+= always_char;
+ }
+ else
+ ORBSVCS_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TAO_UIPMC_Protocol_Factory::init - ")
+ ACE_TEXT ("ignoring invalid -ORBListenerInterfaces %C\n"),
+ always_char));
+ }
+
+ arg_shifter.consume_arg ();
}
else
{
ORBSVCS_DEBUG ((LM_DEBUG,
ACE_TEXT ("TAO_UIPMC_Protocol_Factory::init - ")
ACE_TEXT ("ignoring unknown option <%s>\n"),
- argv[curarg]));
+ arg_shifter.get_current ()));
+ arg_shifter.ignore_arg ();
}
}
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h
index 3b08b2e64e2..1caf60ae296 100644
--- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Factory.h
@@ -60,9 +60,13 @@ private:
/// compatibility with old clients.
int major_;
int minor_;
+
/// Should we override the default behaviour (whatever it is) to listen on
/// all interfaces
bool listen_on_all_;
+
+ /// Any specified and valid -ORBListenerInterfaces option string
+ ACE_CString listener_interfaces_;
};
TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.cpp
index 134a37ff253..9e388afa55e 100644
--- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.cpp
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.cpp
@@ -17,6 +17,10 @@
#include "tao/Base_Transport_Property.h"
#include "tao/Resume_Handle.h"
#include "tao/Protocols_Hooks.h"
+#include "tao/IIOP_Endpoint.h" // TAO_IIOP_Endpoint::find_preferred_interfaces ()
+
+#include "ace/Vector_T.h"
+
TAO_BEGIN_VERSIONED_NAMESPACE_DECL
@@ -24,13 +28,18 @@ TAO_UIPMC_Mcast_Connection_Handler::TAO_UIPMC_Mcast_Connection_Handler (
ACE_Thread_Manager *t)
: TAO_UIPMC_MCAST_SVC_HANDLER (t, 0 , 0),
TAO_Connection_Handler (0),
- listen_on_all_(false)
+ listen_on_all_ (false),
+ listener_interfaces_ ()
{
// This constructor should *never* get called, it is just here to
// make the compiler happy: the default implementation of the
// Creation_Strategy requires a constructor with that signature, we
// don't use that implementation, but some (most?) compilers
// instantiate it anyway.
+ ORBSVCS_DEBUG ((LM_DEBUG,
+ ACE_TEXT("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler, ")
+ ACE_TEXT("this constructor should never be called.\n")
+ ACE_TEXT(" Check svc.conf configuration.\n") ));
ACE_ASSERT (0);
}
@@ -38,11 +47,12 @@ TAO_UIPMC_Mcast_Connection_Handler::TAO_UIPMC_Mcast_Connection_Handler (
TAO_ORB_Core *orb_core)
: TAO_UIPMC_MCAST_SVC_HANDLER (orb_core->thr_mgr (), 0, 0),
TAO_Connection_Handler (orb_core),
- listen_on_all_(false)
+ listen_on_all_ (false),
+ listener_interfaces_ ()
{
TAO_UIPMC_Mcast_Transport *specific_transport = 0;
- ACE_NEW(specific_transport,
- TAO_UIPMC_Mcast_Transport (this, orb_core));
+ ACE_NEW (specific_transport,
+ TAO_UIPMC_Mcast_Transport (this, orb_core));
// store this pointer (indirectly increment ref count)
this->transport (specific_transport);
@@ -59,7 +69,7 @@ TAO_UIPMC_Mcast_Connection_Handler::~TAO_UIPMC_Mcast_Connection_Handler (void)
ORBSVCS_ERROR ((LM_ERROR,
ACE_TEXT ("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::")
ACE_TEXT ("~UIPMC_Mcast_Connection_Handler, ")
- ACE_TEXT ("release_os_resources() failed '%m'\n")));
+ ACE_TEXT ("release_os_resources() failed (Errno: '%m')\n")));
}
}
@@ -94,72 +104,133 @@ TAO_UIPMC_Mcast_Connection_Handler::open_handler (void *v)
}
int
-TAO_UIPMC_Mcast_Connection_Handler::open (void*)
+TAO_UIPMC_Mcast_Connection_Handler::open (void *)
{
- if (this->listen_on_all_)
+ // Stingify the target multicast group IP address
+ char target_multicast_group[INET6_ADDRSTRLEN];
+ this->local_addr_.get_host_addr (target_multicast_group, sizeof target_multicast_group);
+
+ // Check if we are supposed to be listening on specified interface(s)
+ CORBA::ULong preferred_size= 0u;
+ if (this->listener_interfaces_[0])
+ {
+ // Since we have been told to match some targetNetwork=localNetwork listener interface
+ // strings, attempt to match the actual targetHost and our actual network interface cards
+ // to see how many joins we need to attempt.
+ ACE_Vector<ACE_CString> preferred;
+ TAO_IIOP_Endpoint::find_preferred_interfaces (
+ target_multicast_group,
+ this->listener_interfaces_,
+ preferred);
+ preferred_size= preferred.size ();
+
+#ifndef ALLOW_UNICAST_MIOP
+ // If we are attempting to join ANY preferred listener interfaces, at least one join must
+ // complete in the loop below for a successful outcome. If we have NO valid preferred
+ // listener interfaces, then we are concidered successful HERE so as to allow the
+ // default join to be attempted later.
+ bool success= !preferred_size;
+#endif // ALLOW_UNICAST_MIOP
+ for (CORBA::ULong i= 0u; i < preferred_size; ++i)
+ if (0 == this->peer ().join (this->local_addr_, 1, preferred[i].c_str ()))
+ {
+ success= true; // At least one perferred listener interface join succeeded
+ if (TAO_debug_level > 5)
+ ORBSVCS_DEBUG ((LM_DEBUG,
+ ACE_TEXT("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::open, ")
+ ACE_TEXT("listening for multicast %C:%u on %C\n"),
+ target_multicast_group,
+ this->local_addr_.get_port_number (),
+ preferred[i].c_str ()
+ ));
+ }
+ else if (TAO_debug_level)
+ ORBSVCS_DEBUG ((LM_ERROR,
+ ACE_TEXT("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::open, ")
+ ACE_TEXT("failed to join multicast %C:%u on %C (Errno: '%m')\n"),
+ target_multicast_group,
+ this->local_addr_.get_port_number (),
+ preferred[i].c_str ()
+ ));
+
+#ifndef ALLOW_UNICAST_MIOP
+ if (!success)
+ return -1; // No joins worked, we are not listening.
+#endif // ALLOW_UNICAST_MIOP
+ }
+
+ // If we have NO valid preferred listener interfaces matches, then we attempt the
+ // normal default join to the system default/all interface(s).
+ if (!preferred_size)
{
- this->peer ().opts(ACE_SOCK_Dgram_Mcast::OPT_NULLIFACE_ALL | this->peer ().opts());
+ if (this->listen_on_all_)
+ this->peer ().opts(ACE_SOCK_Dgram_Mcast::OPT_NULLIFACE_ALL | this->peer ().opts());
+
+ if (0 == this->peer ().join (this->local_addr_))
+ {
+ if (TAO_debug_level > 5)
+ ORBSVCS_DEBUG ((LM_DEBUG,
+ ACE_TEXT("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::open, ")
+ ACE_TEXT("listening for multicast %C:%u on %C\n"),
+ target_multicast_group,
+ this->local_addr_.get_port_number (),
+ ((this->listen_on_all_) ? "All" : "Default")
+ ));
+ }
+ else
+ {
+ if (TAO_debug_level)
+ ORBSVCS_DEBUG ((LM_ERROR,
+ ACE_TEXT("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::open, ")
+ ACE_TEXT("failed to join multicast %C:%u on %C (Errno: '%m')\n"),
+ target_multicast_group,
+ this->local_addr_.get_port_number (),
+ ((this->listen_on_all_) ? "All" : "Default")
+ ));
+
+#ifndef ALLOW_UNICAST_MIOP
+ return -1; // No joins worked, we are not listening.
+#endif // ALLOW_UNICAST_MIOP
+ }
}
+ // Attempt to set the socket's receive buffer size.
TAO_MIOP_Resource_Factory *const factory =
ACE_Dynamic_Service<TAO_MIOP_Resource_Factory>::instance (
- this->orb_core ()->configuration(),
+ this->orb_core ()->configuration (),
ACE_TEXT ("MIOP_Resource_Factory"));
TAO_DIOP_Protocol_Properties protocol_properties;
protocol_properties.recv_buffer_size_ =
factory->receive_buffer_size () ?
factory->receive_buffer_size () :
this->orb_core ()->orb_params ()->sock_rcvbuf_size ();
-
- if (this->peer ().join (this->local_addr_) == 0)
- {
- if (TAO_debug_level > 5)
- {
- char tmp[INET6_ADDRSTRLEN];
- this->local_addr_.get_host_addr (tmp, sizeof tmp);
- ORBSVCS_DEBUG ((LM_DEBUG,
- ACE_TEXT("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::open, ")
- ACE_TEXT("subscribed to multicast group at %C:%u\n"),
- tmp,
- this->local_addr_.get_port_number ()
- ));
- }
- }
-#ifndef ALLOW_UNICAST_MIOP
- else
- {
- char tmp[INET6_ADDRSTRLEN];
- this->local_addr_.get_host_addr (tmp, sizeof tmp);
- ORBSVCS_DEBUG ((LM_ERROR,
- ACE_TEXT("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::open, ")
- ACE_TEXT("failed to subscribe to multicast group at %C:%u '%m'\n"),
- tmp,
- this->local_addr_.get_port_number ()
+ if (-1 == this->set_socket_option (
+ this->peer (),
+ 0,
+ protocol_properties.recv_buffer_size_))
+ ORBSVCS_ERROR ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::")
+ ACE_TEXT ("open, failed to set RCVBUF ")
+ ACE_TEXT ("for multicast %C:%u (Errno: '%m')\n"),
+ target_multicast_group,
+ this->local_addr_.get_port_number ()
));
- return -1;
- }
-#endif // ALLOW_UNICAST_MIOP
- if (this->set_socket_option (this->peer (),
- 0,
- protocol_properties.recv_buffer_size_) == -1)
- {
- return -1;
- }
-
- // The socket has to be set in non-blocking mode in order to work with
+ // The socket also has to be set in non-blocking mode in order to work with
// TAO_UIPMC_Mcast_Transport::handle_input().
if (this->peer ().enable (ACE_NONBLOCK) == -1)
{
- if (TAO_debug_level)
- ORBSVCS_ERROR ((LM_ERROR,
- ACE_TEXT ("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::")
- ACE_TEXT ("open, failed to set to non-blocking mode ")
- ACE_TEXT ("'%m'\n")));
-
- return -1;
+ ORBSVCS_ERROR ((LM_ERROR,
+ ACE_TEXT ("TAO (%P|%t) - UIPMC_Mcast_Connection_Handler::")
+ ACE_TEXT ("open, failed to set non-blocking ")
+ ACE_TEXT ("for multicast %C:%u (Errno: '%m')\n"),
+ target_multicast_group,
+ this->local_addr_.get_port_number ()
+ ));
+ return -1; // Can't work without this setting.
}
+ // Pass the connection over to the transport.
this->transport ()->id ((size_t) this->peer ().get_handle ());
return 0;
}
@@ -198,8 +269,9 @@ TAO_UIPMC_Mcast_Connection_Handler::handle_output (ACE_HANDLE handle)
}
int
-TAO_UIPMC_Mcast_Connection_Handler::handle_timeout (const ACE_Time_Value &,
- const void *)
+TAO_UIPMC_Mcast_Connection_Handler::handle_timeout (
+ const ACE_Time_Value &,
+ const void *)
{
// Using this to ensure this instance will be deleted (if necessary)
// only after reset_state(). Without this, when this refcount==1 -
@@ -279,4 +351,10 @@ TAO_UIPMC_Mcast_Connection_Handler::listen_on_all(bool value)
this->listen_on_all_ = value;
}
+void
+TAO_UIPMC_Mcast_Connection_Handler::listener_interfaces (const char *value)
+{
+ this->listener_interfaces_ = value;
+}
+
TAO_END_VERSIONED_NAMESPACE_DECL
diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.h b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.h
index 91653af3549..2ec8a772b73 100644
--- a/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.h
+++ b/TAO/orbsvcs/orbsvcs/PortableGroup/UIPMC_Mcast_Connection_Handler.h
@@ -52,9 +52,7 @@ class TAO_PortableGroup_Export TAO_UIPMC_Mcast_Connection_Handler :
public TAO_UIPMC_MCAST_SVC_HANDLER,
public TAO_Connection_Handler
{
-
public:
-
TAO_UIPMC_Mcast_Connection_Handler (ACE_Thread_Manager* t = 0);
/// Constructor. arg parameter is used by the Acceptor to pass the
@@ -100,14 +98,13 @@ public:
void local_addr (const ACE_INET_Addr &addr);
/// Set this to listen on all interfaces
- void listen_on_all(bool value);
+ void listen_on_all (bool value);
- // UIPMC Additions - End
+ /// Set this to specify ListenerInterfaces pairs
+ /// (Same as -ORBPreferredInterfaces but for listeners)
+ void listener_interfaces (const char *);
protected:
-
- // UIPMC Additions - Begin
-
// This is always the remote address
ACE_INET_Addr addr_;
@@ -117,6 +114,8 @@ protected:
// Should we listen on all interfaces
bool listen_on_all_;
+ // Which interfaces are to be listening for the group address
+ ACE_CString listener_interfaces_;
// UIPMC Additions - End
//@{
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/McastHello.cpp b/TAO/orbsvcs/tests/Miop/McastLocal/McastHello.cpp
new file mode 100644
index 00000000000..f195a6e5c9a
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/McastHello.cpp
@@ -0,0 +1,65 @@
+//
+// $Id$
+//
+#include "McastHello.h"
+
+
+
+McastHello::McastHello (CORBA::ORB_ptr orb,
+ int instance)
+ : orb_ (CORBA::ORB::_duplicate (orb)),
+ instance_ (instance),
+ small_request_status_ (0),
+ large_request_status_ (0)
+{
+}
+
+void
+McastHello::send_forty_two (CORBA::Long forty_two)
+{
+ if (this->small_request_status_ == 0 &&
+ forty_two == 42)
+ {
+ this->small_request_status_ = 1;
+ }
+ else
+ this->small_request_status_ = 0;
+}
+
+void
+McastHello::send_large_octet_array (const Test::Octets &payload)
+{
+ CORBA::Boolean valid_payload = 1;
+ for (CORBA::ULong i = 0; i < payload.length (); ++i)
+ {
+ if ((CORBA::ULong) payload [i] != i % 256)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "ERROR: (%P|%t) McastHello::send_large_octet_array, "
+ "unexpected value at index %d (%d != %d)\n",
+ i, payload [i], i % 256));
+ valid_payload = 0;
+ break;
+ }
+ }
+
+ if (this->large_request_status_ == 0 &&
+ valid_payload == 1)
+ {
+ this->large_request_status_ = 1;
+ }
+ else
+ this->large_request_status_ = 0;
+}
+
+void
+McastHello::shutdown (void)
+{
+ this->orb_->shutdown (0);
+}
+
+CORBA::Boolean
+McastHello::get_status ()
+{
+ return this->large_request_status_ && this->small_request_status_;
+}
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/McastHello.h b/TAO/orbsvcs/tests/Miop/McastLocal/McastHello.h
new file mode 100644
index 00000000000..c6a85237a95
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/McastHello.h
@@ -0,0 +1,47 @@
+//
+// $Id$
+//
+
+#ifndef MCASTHELLO_H
+#define MCASTHELLO_H
+#include /**/ "ace/pre.h"
+
+#include "TestS.h"
+
+/// Implement the Test::McastHello interface
+class McastHello
+ : public virtual POA_Test::McastHello
+{
+public:
+ /// Constructor
+ McastHello (CORBA::ORB_ptr orb,
+ int instance);
+
+ // = The skeleton methods
+ virtual void send_forty_two (CORBA::Long forty_two);
+
+ virtual void shutdown (void);
+
+ /// Return whether all test requests have been received successfully.
+ CORBA::Boolean get_status ();
+
+ // Silence the builds
+ void send_large_octet_array (const Test::Octets &);
+
+private:
+ /// Use an ORB reference to convert strings to objects and shutdown
+ /// the application.
+ CORBA::ORB_var orb_;
+
+ /// The instance number. (Useful when debugging multiple servants)
+ int instance_;
+
+ /// Track the success/failure of the small request.
+ CORBA::Boolean small_request_status_;
+
+ /// Track the success/failure of the large request.
+ CORBA::Boolean large_request_status_;
+};
+
+#include /**/ "ace/post.h"
+#endif /* MCASTHELLO_H */
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/McastLocal.mpc b/TAO/orbsvcs/tests/Miop/McastLocal/McastLocal.mpc
new file mode 100644
index 00000000000..71b6551358b
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/McastLocal.mpc
@@ -0,0 +1,34 @@
+// -*- MPC -*-
+// $Id$
+
+project(*idl): taoidldefaults {
+ IDL_Files {
+ Test.idl
+ }
+ custom_only = 1
+}
+
+project(*server): orbsvcsexe, portablegroup, portableserver {
+ after += *idl
+ exename = server
+ Source_Files {
+ McastHello.cpp
+ TestS.cpp
+ TestC.cpp
+ server.cpp
+ }
+ IDL_Files {
+ }
+}
+
+project(*client): orbsvcsexe, portablegroup, portableserver {
+ after += *idl
+ exename = client
+ Source_Files {
+ TestC.cpp
+ client.cpp
+ }
+ IDL_Files {
+ }
+}
+
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/README b/TAO/orbsvcs/tests/Miop/McastLocal/README
new file mode 100644
index 00000000000..c9a64727ba0
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/README
@@ -0,0 +1,19 @@
+/**
+$Id$
+
+@page McastLocal Test README File
+
+This test is a copy of the McastHello test but modified so that the
+servers are listening only on the loopback interface (via the
+ "-ORBListenerInterface *=127.0.0.1" in the svc_server1.conf for server1
+and the
+ "-ORBListenerInterface CopyPreferredInterfaces" in the svc_server2.conf
+and the server2's otherwise redundant command line
+ "-ORBPreferredInterface *=127.0.0.1" orb_init parameter).
+The client has also been modified to send the broadcast out on the
+loopback interface (via its
+ "-ORBPreferredInterface *=127.0.0.1" orb_init parameter).
+
+This is testing that these configuartion options are correctly working
+for MIOP.
+**/
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/Test.idl b/TAO/orbsvcs/tests/Miop/McastLocal/Test.idl
new file mode 100644
index 00000000000..e3babc5d5a2
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/Test.idl
@@ -0,0 +1,26 @@
+//
+// $Id$
+//
+
+/// Put the interfaces in a module, to avoid global namespace pollution
+module Test
+{
+ /// A sequence of octets for sending large messages.
+ typedef sequence<octet> Octets;
+
+ /// A very simple interface
+ interface McastHello
+ {
+ /// A method to test out a small request
+ oneway void send_forty_two (in long forty_two);
+
+ /// A method to test bigger requests
+ oneway void send_large_octet_array (in Octets payload);
+
+ /// A method to shutdown the ORB
+ /**
+ * This method is used to simplify the test shutdown process
+ */
+ oneway void shutdown ();
+ };
+};
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/client.cpp b/TAO/orbsvcs/tests/Miop/McastLocal/client.cpp
new file mode 100644
index 00000000000..38b253edba4
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/client.cpp
@@ -0,0 +1,92 @@
+// $Id$
+
+#include "TestC.h"
+#include "ace/Get_Opt.h"
+#include "tao/Object_T.h"
+#include "orbsvcs/PortableGroup/MIOP.h"
+
+
+
+#define MAX_MIOP_OCTET_SEQUENCE (ACE_MAX_DGRAM_SIZE - 272 /* MIOP_MAX_HEADER_SIZE */)
+
+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;
+
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-k <ior> "
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates successful parsing of the command line
+ return 0;
+}
+
+int
+ACE_TMAIN(int argc, ACE_TCHAR *argv[])
+{
+ try
+ {
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv);
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ CORBA::Object_var tmp =
+ orb->string_to_object(ior);
+
+ /* Do an unchecked narrow since there's no way to do an is_a on
+ * a multicast reference (yet...).
+ */
+ Test::McastHello_var hello =
+ TAO::Narrow_Utils<Test::McastHello>::unchecked_narrow (
+ tmp.in ());
+
+ if (CORBA::is_nil (hello.in ()))
+ {
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Nil Test::Hello reference <%s>\n",
+ ior),
+ 1);
+ }
+
+ hello->send_forty_two (42);
+
+ Test::Octets payload (MAX_MIOP_OCTET_SEQUENCE);
+ payload.length (MAX_MIOP_OCTET_SEQUENCE);
+
+ for (CORBA::ULong j = 0; j != MAX_MIOP_OCTET_SEQUENCE; ++j)
+ {
+ payload[j] = j % 256;
+ }
+
+ hello->send_large_octet_array (payload);
+
+ hello->shutdown ();
+
+ orb->destroy ();
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception ("Exception caught:");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/run_test.pl b/TAO/orbsvcs/tests/Miop/McastLocal/run_test.pl
new file mode 100755
index 00000000000..0f377557daa
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/run_test.pl
@@ -0,0 +1,126 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "$ENV{ACE_ROOT}/bin";
+use PerlACE::TestTarget;
+
+$status = 0;
+$debug_level = '0';
+
+foreach $i (@ARGV) {
+ if ($i eq '-debug') {
+ $debug_level = '10';
+ }
+}
+
+my $server1 = PerlACE::TestTarget::create_target (1) || die "Create target 1 failed\n";
+my $server2 = PerlACE::TestTarget::create_target (2) || die "Create target 2 failed\n";
+my $client = PerlACE::TestTarget::create_target (3) || die "Create target 3 failed\n";
+
+my $ior1file = "server1.ior";
+my $ior2file = "server2.ior.unused";
+
+#Files which used by server1
+my $server1_ior1file = $server1->LocalFile ($ior1file);
+$server1->DeleteFile($ior1file);
+
+#Files which used by server2
+my $server2_ior2file = $server2->LocalFile ($ior2file);
+$server2->DeleteFile($ior2file);
+
+#Files which used by server2
+my $client_ior1file = $client->LocalFile ($ior1file);
+$client->DeleteFile($ior1file);
+
+$SV1 = $server1->CreateProcess ("server",
+ "-ORBdebuglevel $debug_level " .
+ "-ORBSvcconf svc_server1.conf " .
+ "-o $server1_ior1file");
+
+$SV2 = $server2->CreateProcess ("server",
+ "-ORBdebuglevel $debug_level " .
+ "-ORBSvcconf svc_server2.conf " .
+ "-ORBPreferredInterfaces *=127.0.0.1 " .
+ "-o $server2_ior2file");
+
+$CL = $client->CreateProcess ("client",
+ "-ORBSvcconf svc_client.conf " .
+ "-ORBPreferredInterfaces *=127.0.0.1 " .
+ "-k file://$ior1file");
+
+$server_status = $SV1->Spawn ();
+
+if ($server_status != 0) {
+ print STDERR "ERROR: server returned $server_status\n";
+ exit 1;
+}
+
+$server_status = $SV2->Spawn ();
+
+if ($server_status != 0) {
+ print STDERR "ERROR: server returned $server_status\n";
+ exit 1;
+}
+
+sub KillServers{
+ $SV1->Kill (); $SV1->TimedWait (1);
+ $SV2->Kill (); $SV2->TimedWait (1);
+}
+
+if ($server1->WaitForFileTimed ($ior1file,
+ $server1->ProcessStartWaitInterval()) == -1) {
+ print STDERR "ERROR: cannot find file <$server1_ior1file>\n";
+ KillServers ();
+ exit 1;
+}
+
+if ($server2->WaitForFileTimed ($ior2file,
+ $server2->ProcessStartWaitInterval()) == -1) {
+ print STDERR "ERROR: cannot find file <$server2_ior2file>\n";
+ KillServers ();
+ exit 1;
+}
+
+if ($server1->GetFile ($ior1file) == -1) {
+ print STDERR "ERROR: cannot retrieve file <$server1_ior1file>\n";
+ KillServers ();
+ exit 1;
+}
+if ($client->PutFile ($ior1file) == -1) {
+ print STDERR "ERROR: cannot set file <$client_ior1file>\n";
+ KillServers ();
+ exit 1;
+}
+
+
+$client_status = $CL->SpawnWaitKill ($client->ProcessStartWaitInterval() + 285);
+
+if ($client_status != 0) {
+ print STDERR "ERROR: client returned $client_status\n";
+ $status = 1;
+}
+
+$server_status = $SV1->WaitKill ($server1->ProcessStopWaitInterval());
+
+if ($server_status != 0) {
+ print STDERR "ERROR: server returned $server_status\n";
+ $status = 1;
+}
+
+$server_status = $SV2->WaitKill ($server2->ProcessStopWaitInterval());
+
+if ($server_status != 0) {
+ print STDERR "ERROR: server returned $server_status\n";
+ $status = 1;
+}
+
+
+$server1->DeleteFile($ior1file);
+$server2->DeleteFile($ior2file);
+$client->DeleteFile($ior1file);
+
+exit $status;
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/server.cpp b/TAO/orbsvcs/tests/Miop/McastLocal/server.cpp
new file mode 100644
index 00000000000..c29b43793c7
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/server.cpp
@@ -0,0 +1,121 @@
+// $Id$
+
+#include "McastHello.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "orbsvcs/PortableGroup/MIOP.h"
+#include "orbsvcs/PortableGroup/GOA.h"
+
+static const ACE_TCHAR *ior_output_file = ACE_TEXT("test.ior");
+
+// Use a multicast address in the administrative "site local" range, 239.255.0.0 to
+// 239.255.255.255. The range 224.255.0.0 to 238.255.255.255 should also be valid
+// too.
+//static const char *group_ior = "corbaloc:miop:1.0@1.0-TestDomain-1/239.255.0.1:16000";
+static const ACE_TCHAR *group_ior = ACE_TEXT("corbaloc:miop:1.0@1.0-TestDomain-1/224.1.239.2:1234");
+
+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 'g':
+ group_ior = get_opts.opt_arg ();
+ break;
+
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-o <iorfile>"
+ "-g <group ior corbaloc>"
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates successful parsing of the command line
+ return 0;
+}
+
+int
+ACE_TMAIN(int argc, ACE_TCHAR *argv[])
+{
+ try
+ {
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv);
+
+ CORBA::Object_var poa_object =
+ orb->resolve_initial_references("RootPOA");
+
+ PortableGroup::GOA_var root_poa =
+ PortableGroup::GOA::_narrow (poa_object.in ());
+
+ if (CORBA::is_nil (root_poa.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Panic: nil RootPOA\n"),
+ 1);
+
+ PortableServer::POAManager_var poa_manager =
+ root_poa->the_POAManager ();
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ CORBA::Object_var group1 =
+ orb->string_to_object (group_ior);
+
+ // Output the Group IOR to the <ior_output_file>
+ 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", ACE_TEXT_ALWAYS_CHAR (group_ior));
+ ACE_OS::fclose (output_file);
+
+ PortableServer::ObjectId_var id =
+ root_poa->create_id_for_reference (group1.in ());
+
+ // Create and activate an instance of our servant.
+ McastHello server_impl (orb.in (), 0);
+
+ root_poa->activate_object_with_id (id.in (),
+ &server_impl);
+
+
+ poa_manager->activate ();
+
+ orb->run ();
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) server - event loop finished\n"));
+
+ root_poa->destroy (1, 1);
+
+ orb->destroy ();
+
+ // Validate that our servants got the right requests.
+ if (server_impl.get_status () == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Multicast Servant did not receive expected requests!\n"),
+ 1);
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) server - Success!\n"));
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception ("Exception caught:");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/svc_client.conf b/TAO/orbsvcs/tests/Miop/McastLocal/svc_client.conf
new file mode 100644
index 00000000000..84ef77cf1c6
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/svc_client.conf
@@ -0,0 +1,6 @@
+# $Id$
+
+dynamic UIPMC_Factory Service_Object * TAO_PortableGroup:_make_TAO_UIPMC_Protocol_Factory() ""
+static Resource_Factory "-ORBProtocolFactory IIOP_Factory -ORBProtocolFactory UIPMC_Factory"
+#static PortableGroup_Loader ""
+dynamic PortableGroup_Loader Service_Object * TAO_PortableGroup:_make_TAO_PortableGroup_Loader() ""
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/svc_server1.conf b/TAO/orbsvcs/tests/Miop/McastLocal/svc_server1.conf
new file mode 100644
index 00000000000..db74ea90e3f
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/svc_server1.conf
@@ -0,0 +1,6 @@
+# $Id$
+
+dynamic UIPMC_Factory Service_Object * TAO_PortableGroup:_make_TAO_UIPMC_Protocol_Factory() "-ORBListenerInterfaces *=127.0.0.1"
+static Resource_Factory "-ORBProtocolFactory IIOP_Factory -ORBProtocolFactory UIPMC_Factory"
+#static PortableGroup_Loader ""
+dynamic PortableGroup_Loader Service_Object * TAO_PortableGroup:_make_TAO_PortableGroup_Loader() ""
diff --git a/TAO/orbsvcs/tests/Miop/McastLocal/svc_server2.conf b/TAO/orbsvcs/tests/Miop/McastLocal/svc_server2.conf
new file mode 100644
index 00000000000..01848bc7c5f
--- /dev/null
+++ b/TAO/orbsvcs/tests/Miop/McastLocal/svc_server2.conf
@@ -0,0 +1,6 @@
+# $Id$
+
+dynamic UIPMC_Factory Service_Object * TAO_PortableGroup:_make_TAO_UIPMC_Protocol_Factory() "-ORBListenerInterfaces CopyPreferredInterfaces"
+static Resource_Factory "-ORBProtocolFactory IIOP_Factory -ORBProtocolFactory UIPMC_Factory"
+#static PortableGroup_Loader ""
+dynamic PortableGroup_Loader Service_Object * TAO_PortableGroup:_make_TAO_PortableGroup_Loader() ""
diff --git a/TAO/tao/params.cpp b/TAO/tao/params.cpp
index bc286c1a0e5..4eaa9a473c9 100644
--- a/TAO/tao/params.cpp
+++ b/TAO/tao/params.cpp
@@ -217,30 +217,28 @@ TAO_ORB_Parameters::parse_and_add_endpoints (const ACE_CString &endpoints,
}
bool
-TAO_ORB_Parameters::preferred_interfaces (const char *s)
+TAO_ORB_Parameters::check_preferred_interfaces_string (const char *s)
{
// Validates that s contains one or more comma separated
// interfaces each consisting of a string with a single
// assignment separator ('=' or ':')
// Any other char is legal, although '*' and '?' will be
// treated as wildcards.
- const char* p = s;
bool expect_assign = false;
bool expect_comma = false;
bool expect_char = true;
bool expect_wild = true;
bool found_remote = false;
- while (*p != 0)
- {
- switch (*p)
+
+ for (const char *p = s; *p; ++p) switch (*p)
{
#if !defined (ACE_HAS_IPV6)
- // Can't use this as assignment operator when IPv6 decimal
- // addresses may be involved.
+ // Can't use this as assignment operator when IPv6 decimal
+ // addresses may be involved.
case ':':
#endif /* ACE_HAS_IPV6 */
case '=':
- if (! expect_assign)
+ if (!expect_assign)
return false;
found_remote = true;
expect_assign = false;
@@ -248,8 +246,9 @@ TAO_ORB_Parameters::preferred_interfaces (const char *s)
expect_comma = false;
expect_wild = true;
break;
+
case ',':
- if (! expect_comma)
+ if (!expect_comma)
return false;
found_remote = false;
expect_assign = false;
@@ -257,32 +256,45 @@ TAO_ORB_Parameters::preferred_interfaces (const char *s)
expect_comma = false;
expect_wild = true;
break;
+
case '*':
case '?':
- if (! expect_wild)
+ if (!expect_wild)
return false;
- expect_assign = ! found_remote;
+ expect_assign = !found_remote;
expect_char = true;
expect_comma = found_remote;
expect_wild = false;
break;
+
default:
- if (! expect_char)
+ if (!expect_char)
return false;
- expect_assign = ! found_remote;
+ expect_assign = !found_remote;
expect_char = true;
expect_comma = found_remote;
expect_wild = true;
break;
}
- ++p;
- }
- if (!expect_comma || expect_assign)
- return false;
- this->pref_network_ = s;
+ return expect_comma && !expect_assign;
+}
+
+bool
+TAO_ORB_Parameters::preferred_interfaces (const char *s)
+{
+ const bool valid= check_preferred_interfaces_string (s);
+ if (valid)
+ {
+ // Append any valid string to those already specified
+ // (by other -ORBPreferredInterfaces options that have been
+ // seen previously)
+ if (this->pref_network_.length ())
+ this->pref_network_+= ',';
+ this->pref_network_+= s;
+ }
- return true;
+ return valid;
}
const char *
diff --git a/TAO/tao/params.h b/TAO/tao/params.h
index b9c91ebaaa1..ffb2e0fa690 100644
--- a/TAO/tao/params.h
+++ b/TAO/tao/params.h
@@ -211,10 +211,13 @@ public:
void disable_rt_collocation_resolver (bool);
/// Accepts the list of preferred interfaces and does a simple
- /// semantic check on the string
+ /// semantic check on the string before setting. Also the getter.
bool preferred_interfaces (const char *s);
const char *preferred_interfaces (void) const;
+ /// Utility function called by the preferred interfaces setter
+ static bool check_preferred_interfaces_string (const char *);
+
void enforce_pref_interfaces (bool p);
bool enforce_pref_interfaces (void) const;