void filter_object::test<1>()
 {
     set_test_name("LLEventMatching");
     LLEventPump& driver(pumps.obtain("driver"));
     listener0.reset(0);
     // Listener isn't derived from LLEventTrackable specifically to test
     // various connection-management mechanisms. But that means we have a
     // couple of transient Listener objects, one of which is listening to
     // a persistent LLEventPump. Capture those connections in local
     // LLTempBoundListener instances so they'll disconnect
     // on destruction.
     LLTempBoundListener temp1(
         listener0.listenTo(driver));
     // Construct a pattern LLSD: desired Event must have a key "foo"
     // containing string "bar"
     LLEventMatching filter(driver, LLSD().insert("foo", "bar"));
     listener1.reset(0);
     LLTempBoundListener temp2(
         listener1.listenTo(filter));
     driver.post(1);
     check_listener("direct", listener0, LLSD(1));
     check_listener("filtered", listener1, LLSD(0));
     // Okay, construct an LLSD map matching the pattern
     LLSD data;
     data["foo"] = "bar";
     data["random"] = 17;
     driver.post(data);
     check_listener("direct", listener0, data);
     check_listener("filtered", listener1, data);
 }
 void filter_object::test<3>()
 {
     set_test_name("LLEventTimeout::eventAfter()");
     LLEventPump& driver(pumps.obtain("driver"));
     TestEventTimeout filter(driver);
     listener0.reset(0);
     LLTempBoundListener temp1(
         listener0.listenTo(filter));
     filter.eventAfter(20, LLSD("timeout"));
     // Okay, (fake) timer is ticking. 'filter' can only sense the timer
     // when we pump mainloop. Do that right now to take the logic path
     // before either the anticipated event arrives or the timer expires.
     mainloop.post(17);
     check_listener("no timeout 1", listener0, LLSD(0));
     // Expected event arrives...
     driver.post(1);
     check_listener("event passed thru", listener0, LLSD(1));
     // Should have canceled the timer. Verify that by asserting that the
     // time has expired, then pumping mainloop again.
     filter.forceTimeout();
     mainloop.post(17);
     check_listener("no timeout 2", listener0, LLSD(1));
     // Set timer again.
     filter.eventAfter(20, LLSD("timeout"));
     // Now let the timer expire.
     filter.forceTimeout();
     // Notice the timeout.
     mainloop.post(17);
     check_listener("timeout", listener0, LLSD("timeout"));
     // Timing out cancels the timer. Verify that.
     listener0.reset(0);
     filter.forceTimeout();
     mainloop.post(17);
     check_listener("no timeout 3", listener0, LLSD(0));
 }
Exemple #3
0
/**
 * g_socket_listener_accept_socket_async:
 * @listener: a #GSocketListener
 * @cancellable: (allow-none): a #GCancellable, or %NULL
 * @callback: (scope async): a #GAsyncReadyCallback
 * @user_data: (closure): user data for the callback
 *
 * This is the asynchronous version of g_socket_listener_accept_socket().
 *
 * When the operation is finished @callback will be
 * called. You can then call g_socket_listener_accept_socket_finish()
 * to get the result of the operation.
 *
 * Since: 2.22
 */
void
g_socket_listener_accept_socket_async (GSocketListener     *listener,
				       GCancellable        *cancellable,
				       GAsyncReadyCallback  callback,
				       gpointer             user_data)
{
  GTask *task;
  GList *sources;
  GError *error = NULL;

  task = g_task_new (listener, cancellable, callback, user_data);

  if (!check_listener (listener, &error))
    {
      g_task_return_error (task, error);
      g_object_unref (task);
      return;
    }

  sources = add_sources (listener,
			 accept_ready,
			 task,
			 cancellable,
			 g_main_context_get_thread_default ());
  g_task_set_task_data (task, sources, (GDestroyNotify) free_sources);
}
Exemple #4
0
/**
 * g_socket_listener_add_socket:
 * @listener: a #GSocketListener
 * @socket: a listening #GSocket
 * @source_object: (allow-none): Optional #GObject identifying this source
 * @error: #GError for error reporting, or %NULL to ignore.
 *
 * Adds @socket to the set of sockets that we try to accept
 * new clients from. The socket must be bound to a local
 * address and listened to.
 *
 * @source_object will be passed out in the various calls
 * to accept to identify this particular source, which is
 * useful if you're listening on multiple addresses and do
 * different things depending on what address is connected to.
 *
 * Returns: %TRUE on success, %FALSE on error.
 *
 * Since: 2.22
 */
gboolean
g_socket_listener_add_socket (GSocketListener  *listener,
			      GSocket          *socket,
			      GObject          *source_object,
			      GError          **error)
{
  if (!check_listener (listener, error))
    return FALSE;

  /* TODO: Check that socket it is bound & not closed? */

  if (g_socket_is_closed (socket))
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
			   _("Added socket is closed"));
      return FALSE;
    }

  g_object_ref (socket);
  g_ptr_array_add (listener->priv->sockets, socket);

  if (source_object)
    g_object_set_qdata_full (G_OBJECT (socket), source_quark,
			     g_object_ref (source_object), g_object_unref);


  if (G_SOCKET_LISTENER_GET_CLASS (listener)->changed)
    G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener);

  return TRUE;
}
Exemple #5
0
/**
 * g_socket_listener_add_address:
 * @listener: a #GSocketListener
 * @address: a #GSocketAddress
 * @type: a #GSocketType
 * @protocol: a #GSocketProtocol
 * @source_object: (allow-none): Optional #GObject identifying this source
 * @effective_address: (out) (allow-none): location to store the address that was bound to, or %NULL.
 * @error: #GError for error reporting, or %NULL to ignore.
 *
 * Creates a socket of type @type and protocol @protocol, binds
 * it to @address and adds it to the set of sockets we're accepting
 * sockets from.
 *
 * Note that adding an IPv6 address, depending on the platform,
 * may or may not result in a listener that also accepts IPv4
 * connections.  For more deterministic behavior, see
 * g_socket_listener_add_inet_port().
 *
 * @source_object will be passed out in the various calls
 * to accept to identify this particular source, which is
 * useful if you're listening on multiple addresses and do
 * different things depending on what address is connected to.
 *
 * If successful and @effective_address is non-%NULL then it will
 * be set to the address that the binding actually occurred at.  This
 * is helpful for determining the port number that was used for when
 * requesting a binding to port 0 (ie: "any port").  This address, if
 * requested, belongs to the caller and must be freed.
 *
 * Returns: %TRUE on success, %FALSE on error.
 *
 * Since: 2.22
 */
gboolean
g_socket_listener_add_address (GSocketListener  *listener,
			       GSocketAddress   *address,
			       GSocketType       type,
			       GSocketProtocol   protocol,
			       GObject          *source_object,
                               GSocketAddress  **effective_address,
			       GError          **error)
{
  GSocketAddress *local_address;
  GSocketFamily family;
  GSocket *socket;

  if (!check_listener (listener, error))
    return FALSE;

  family = g_socket_address_get_family (address);
  socket = g_socket_new (family, type, protocol, error);
  if (socket == NULL)
    return FALSE;

  g_socket_set_listen_backlog (socket, listener->priv->listen_backlog);

  if (!g_socket_bind (socket, address, TRUE, error) ||
      !g_socket_listen (socket, error))
    {
      g_object_unref (socket);
      return FALSE;
    }

  local_address = NULL;
  if (effective_address)
    {
      local_address = g_socket_get_local_address (socket, error);
      if (local_address == NULL)
	{
	  g_object_unref (socket);
	  return FALSE;
	}
    }

  if (!g_socket_listener_add_socket (listener, socket,
				     source_object,
				     error))
    {
      if (local_address)
	g_object_unref (local_address);
      g_object_unref (socket);
      return FALSE;
    }

  if (effective_address)
    *effective_address = local_address;

  g_object_unref (socket); /* add_socket refs this */

  return TRUE;
}
 void filter_object::test<4>()
 {
     set_test_name("LLEventTimeout::errorAfter()");
     WrapLLErrs capture;
     LLEventPump& driver(pumps.obtain("driver"));
     TestEventTimeout filter(driver);
     listener0.reset(0);
     LLTempBoundListener temp1(
         listener0.listenTo(filter));
     filter.errorAfter(20, "timeout");
     // Okay, (fake) timer is ticking. 'filter' can only sense the timer
     // when we pump mainloop. Do that right now to take the logic path
     // before either the anticipated event arrives or the timer expires.
     mainloop.post(17);
     check_listener("no timeout 1", listener0, LLSD(0));
     // Expected event arrives...
     driver.post(1);
     check_listener("event passed thru", listener0, LLSD(1));
     // Should have canceled the timer. Verify that by asserting that the
     // time has expired, then pumping mainloop again.
     filter.forceTimeout();
     mainloop.post(17);
     check_listener("no timeout 2", listener0, LLSD(1));
     // Set timer again.
     filter.errorAfter(20, "timeout");
     // Now let the timer expire.
     filter.forceTimeout();
     // Notice the timeout.
     std::string threw;
     try
     {
         mainloop.post(17);
     }
     catch (const WrapLLErrs::FatalException& e)
     {
         threw = e.what();
     }
     ensure_contains("errorAfter() timeout exception", threw, "timeout");
     // Timing out cancels the timer. Verify that.
     listener0.reset(0);
     filter.forceTimeout();
     mainloop.post(17);
     check_listener("no timeout 3", listener0, LLSD(0));
 }
Exemple #7
0
/**
 * g_socket_listener_accept_socket:
 * @listener: a #GSocketListener
 * @source_object: (out) (transfer none) (allow-none): location where #GObject pointer will be stored, or %NULL.
 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
 * @error: #GError for error reporting, or %NULL to ignore.
 *
 * Blocks waiting for a client to connect to any of the sockets added
 * to the listener. Returns the #GSocket that was accepted.
 *
 * If you want to accept the high-level #GSocketConnection, not a #GSocket,
 * which is often the case, then you should use g_socket_listener_accept()
 * instead.
 *
 * If @source_object is not %NULL it will be filled out with the source
 * object specified when the corresponding socket or address was added
 * to the listener.
 *
 * If @cancellable is not %NULL, then the operation can be cancelled by
 * triggering the cancellable object from another thread. If the operation
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
 *
 * Returns: (transfer full): a #GSocket on success, %NULL on error.
 *
 * Since: 2.22
 */
GSocket *
g_socket_listener_accept_socket (GSocketListener  *listener,
				 GObject         **source_object,
				 GCancellable     *cancellable,
				 GError          **error)
{
  GSocket *accept_socket, *socket;

  g_return_val_if_fail (G_IS_SOCKET_LISTENER (listener), NULL);

  if (!check_listener (listener, error))
    return NULL;

  if (listener->priv->sockets->len == 1)
    {
      accept_socket = listener->priv->sockets->pdata[0];
      if (!g_socket_condition_wait (accept_socket, G_IO_IN,
				    cancellable, error))
	return NULL;
    }
  else
    {
      GList *sources;
      struct AcceptData data;
      GMainLoop *loop;

      if (listener->priv->main_context == NULL)
	listener->priv->main_context = g_main_context_new ();

      loop = g_main_loop_new (listener->priv->main_context, FALSE);
      data.loop = loop;
      sources = add_sources (listener,
			     accept_callback,
			     &data,
			     cancellable,
			     listener->priv->main_context);
      g_main_loop_run (loop);
      accept_socket = data.socket;
      free_sources (sources);
      g_main_loop_unref (loop);
    }

  if (!(socket = g_socket_accept (accept_socket, cancellable, error)))
    return NULL;

  if (source_object)
    *source_object = g_object_get_qdata (G_OBJECT (accept_socket), source_quark);

  return socket;
}
 void filter_object::test<2>()
 {
     set_test_name("LLEventTimeout::actionAfter()");
     LLEventPump& driver(pumps.obtain("driver"));
     TestEventTimeout filter(driver);
     listener0.reset(0);
     LLTempBoundListener temp1(
         listener0.listenTo(filter));
     // Use listener1.call() as the Action for actionAfter(), since it
     // already provides a way to sense the call
     listener1.reset(0);
     // driver --> filter --> listener0
     filter.actionAfter(20,
                        boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
     // Okay, (fake) timer is ticking. 'filter' can only sense the timer
     // when we pump mainloop. Do that right now to take the logic path
     // before either the anticipated event arrives or the timer expires.
     mainloop.post(17);
     check_listener("no timeout 1", listener1, LLSD(0));
     // Expected event arrives...
     driver.post(1);
     check_listener("event passed thru", listener0, LLSD(1));
     // Should have canceled the timer. Verify that by asserting that the
     // time has expired, then pumping mainloop again.
     filter.forceTimeout();
     mainloop.post(17);
     check_listener("no timeout 2", listener1, LLSD(0));
     // Verify chained actionAfter() calls, that is, that a second
     // actionAfter() resets the timer established by the first
     // actionAfter().
     filter.actionAfter(20,
                        boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
     // Since our TestEventTimeout class isn't actually manipulating time
     // (quantities of seconds), only a bool "elapsed" flag, sense that by
     // forcing the flag between actionAfter() calls.
     filter.forceTimeout();
     // Pumping mainloop here would result in a timeout (as we'll verify
     // below). This state simulates a ticking timer that has not yet timed
     // out. But now, before a mainloop event lets 'filter' recognize
     // timeout on the previous actionAfter() call, pretend we're pushing
     // that timeout farther into the future.
     filter.actionAfter(20,
                        boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
     // Look ma, no timeout!
     mainloop.post(17);
     check_listener("no timeout 3", listener1, LLSD(0));
     // Now let the updated actionAfter() timer expire.
     filter.forceTimeout();
     // Notice the timeout.
     mainloop.post(17);
     check_listener("timeout", listener1, LLSD("timeout"));
     // Timing out cancels the timer. Verify that.
     listener1.reset(0);
     filter.forceTimeout();
     mainloop.post(17);
     check_listener("no timeout 4", listener1, LLSD(0));
     // Reset the timer and then cancel() it.
     filter.actionAfter(20,
                        boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
     // neither expired nor satisified
     mainloop.post(17);
     check_listener("no timeout 5", listener1, LLSD(0));
     // cancel
     filter.cancel();
     // timeout!
     filter.forceTimeout();
     mainloop.post(17);
     check_listener("no timeout 6", listener1, LLSD(0));
 }
Exemple #9
0
/**
 * g_socket_listener_add_inet_port:
 * @listener: a #GSocketListener
 * @port: an IP port number (non-zero)
 * @source_object: (allow-none): Optional #GObject identifying this source
 * @error: #GError for error reporting, or %NULL to ignore.
 *
 * Helper function for g_socket_listener_add_address() that
 * creates a TCP/IP socket listening on IPv4 and IPv6 (if
 * supported) on the specified port on all interfaces.
 *
 * @source_object will be passed out in the various calls
 * to accept to identify this particular source, which is
 * useful if you're listening on multiple addresses and do
 * different things depending on what address is connected to.
 *
 * Returns: %TRUE on success, %FALSE on error.
 *
 * Since: 2.22
 */
gboolean
g_socket_listener_add_inet_port (GSocketListener  *listener,
				 guint16           port,
				 GObject          *source_object,
				 GError          **error)
{
  gboolean need_ipv4_socket = TRUE;
  GSocket *socket4 = NULL;
  GSocket *socket6;

  g_return_val_if_fail (listener != NULL, FALSE);
  g_return_val_if_fail (port != 0, FALSE);

  if (!check_listener (listener, error))
    return FALSE;

  /* first try to create an IPv6 socket */
  socket6 = g_socket_new (G_SOCKET_FAMILY_IPV6,
                          G_SOCKET_TYPE_STREAM,
                          G_SOCKET_PROTOCOL_DEFAULT,
                          NULL);

  if (socket6 != NULL)
    /* IPv6 is supported on this platform, so if we fail now it is
     * a result of being unable to bind to our port.  Don't fail
     * silently as a result of this!
     */
    {
      GInetAddress *inet_address;
      GSocketAddress *address;
      gboolean result;

      inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
      address = g_inet_socket_address_new (inet_address, port);
      g_object_unref (inet_address);

      g_socket_set_listen_backlog (socket6, listener->priv->listen_backlog);

      result = g_socket_bind (socket6, address, TRUE, error) &&
               g_socket_listen (socket6, error);

      g_object_unref (address);

      if (!result)
        {
          g_object_unref (socket6);

          return FALSE;
        }

      if (source_object)
        g_object_set_qdata_full (G_OBJECT (socket6), source_quark,
                                 g_object_ref (source_object),
                                 g_object_unref);

      /* If this socket already speaks IPv4 then we are done. */
      if (g_socket_speaks_ipv4 (socket6))
        need_ipv4_socket = FALSE;
    }

  if (need_ipv4_socket)
    /* We are here for exactly one of the following reasons:
     *
     *   - our platform doesn't support IPv6
     *   - we successfully created an IPv6 socket but it's V6ONLY
     *
     * In either case, we need to go ahead and create an IPv4 socket
     * and fail the call if we can't bind to it.
     */
    {
      socket4 = g_socket_new (G_SOCKET_FAMILY_IPV4,
                              G_SOCKET_TYPE_STREAM,
                              G_SOCKET_PROTOCOL_DEFAULT,
                              error);

      if (socket4 != NULL)
        /* IPv4 is supported on this platform, so if we fail now it is
         * a result of being unable to bind to our port.  Don't fail
         * silently as a result of this!
         */
        {
          GInetAddress *inet_address;
          GSocketAddress *address;
          gboolean result;

          inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
          address = g_inet_socket_address_new (inet_address, port);
          g_object_unref (inet_address);

          g_socket_set_listen_backlog (socket4,
                                       listener->priv->listen_backlog);

          result = g_socket_bind (socket4, address, TRUE, error) &&
                   g_socket_listen (socket4, error);

          g_object_unref (address);

          if (!result)
            {
              g_object_unref (socket4);

              if (socket6 != NULL)
                g_object_unref (socket6);

              return FALSE;
            }

          if (source_object)
            g_object_set_qdata_full (G_OBJECT (socket4), source_quark,
                                     g_object_ref (source_object),
                                     g_object_unref);
        }
      else
        /* Ok.  So IPv4 is not supported on this platform.  If we
         * succeeded at creating an IPv6 socket then that's OK, but
         * otherwise we need to tell the user we failed.
         */
        {
          if (socket6 != NULL)
            g_clear_error (error);
          else
            return FALSE;
        }
    }

  g_assert (socket6 != NULL || socket4 != NULL);

  if (socket6 != NULL)
    g_ptr_array_add (listener->priv->sockets, socket6);

  if (socket4 != NULL)
    g_ptr_array_add (listener->priv->sockets, socket4);

  if (G_SOCKET_LISTENER_GET_CLASS (listener)->changed)
    G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener);

  return TRUE;
}
Exemple #10
0
int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
  int status = 0;

  try {
    ACE_DEBUG((LM_INFO,"(%P|%t) %T subscriber main\n"));

    ::DDS::DomainParticipantFactory_var dpf = TheParticipantFactoryWithArgs(argc, argv);

    //      TheServiceParticipant->liveliness_factor(100);

    // let the Service_Participant (in above line) strip out -DCPSxxx parameters
    // and then get application specific parameters.
    parse_args(argc, argv);

    if (!topics) {
      ACE_ERROR((LM_ERROR,
                 ACE_TEXT("(%P|%t) Must run with one or more of the following: -s1 -s2 -s3 -s4 -s5 -p6 -p7\n")));
      return 1;
    }

    ::T1::Foo1TypeSupport_var fts1;
    ::T4::Foo4TypeSupport_var fts4;

    if (topics & (TOPIC_T1 | TOPIC_T3 | TOPIC_T4| TOPIC_T5)) {
      fts1 = new ::T1::Foo1TypeSupportImpl;
    }

    if (topics & TOPIC_T2) {
      fts4 = new ::T4::Foo4TypeSupportImpl;
    }

    ::DDS::DomainParticipant_var dp =
        dpf->create_participant(MY_DOMAIN,
                                PARTICIPANT_QOS_DEFAULT,
                                ::DDS::DomainParticipantListener::_nil(),
                                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);

    if (CORBA::is_nil(dp)) {
      ACE_ERROR((LM_ERROR,
                 ACE_TEXT("(%P|%t) create_participant failed.\n")));
      return 1;
    }

    if (topics & (TOPIC_T1 | TOPIC_T3 | TOPIC_T4 | TOPIC_T5)) {
      if (::DDS::RETCODE_OK != fts1->register_type(dp, MY_TYPE1)) {
        ACE_ERROR((LM_ERROR,
                   ACE_TEXT("Failed to register the Foo1TypeSupport.")));
        return 1;
      }
    }

    if (topics & TOPIC_T2) {
      if (::DDS::RETCODE_OK != fts4->register_type(dp, MY_TYPE4)) {
        ACE_ERROR((LM_ERROR,
                   ACE_TEXT("Failed to register the Foo4TypeSupport.")));
        return 1;
      }
    }

    ::DDS::Topic_var topic1;
    ::DDS::Topic_var topic2;
    ::DDS::Topic_var topic3;
    ::DDS::Topic_var topic4;
    ::DDS::Topic_var topic5;
    ::DDS::Topic_var topic6;
    ::DDS::Topic_var topic7;

    if (topics & TOPIC_T1) {
      topic1 = dp->create_topic(MY_TOPIC1, MY_TYPE1, TOPIC_QOS_DEFAULT,
                                ::DDS::TopicListener::_nil(),
                                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(topic1)) {
        return 1;
      }
    }

    if (topics & TOPIC_T2) {
      topic2 = dp->create_topic(MY_TOPIC2, MY_TYPE4, TOPIC_QOS_DEFAULT,
                                ::DDS::TopicListener::_nil(),
                                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(topic2)) {
        return 1;
      }
    }

    if (topics & TOPIC_T3) {
      topic3 = dp->create_topic(MY_TOPIC3, MY_TYPE1, TOPIC_QOS_DEFAULT,
                                ::DDS::TopicListener::_nil(),
                                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(topic3)) {
        return 1;
      }
    }

    if (topics & TOPIC_T4) {
      topic4 = dp->create_topic(MY_TOPIC4, MY_TYPE1, TOPIC_QOS_DEFAULT,
                                ::DDS::TopicListener::_nil(),
                                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(topic4)) {
        return 1;
      }
    }

    if (topics & TOPIC_T5) {
      topic5 = dp->create_topic(MY_TOPIC5, MY_TYPE1, TOPIC_QOS_DEFAULT,
                                ::DDS::TopicListener::_nil(),
                                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(topic5)) {
        return 1;
      }
    }

    if (publish_topics & TOPIC_T6) {
      topic6 = dp->create_topic(MY_TOPIC6, MY_TYPE1, TOPIC_QOS_DEFAULT,
                                ::DDS::TopicListener::_nil(),
                                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(topic6)) {
        return 1;
      }
    }

    if (publish_topics & TOPIC_T7) {
      topic7 = dp->create_topic(MY_TOPIC7, MY_TYPE1, TOPIC_QOS_DEFAULT,
                                ::DDS::TopicListener::_nil(),
                                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(topic7)) {
        return 1;
      }
    }

    ////////////////////////////////////////////////////////////////////////////
    // Create the publisher and datawriter
    ////////////////////////////////////////////////////////////////////////////
    ::DDS::Publisher_var pub =
      dp->create_publisher(PUBLISHER_QOS_DEFAULT,
                           ::DDS::PublisherListener::_nil(),
                           ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
    if (CORBA::is_nil(pub)) {
      ACE_ERROR_RETURN((LM_ERROR,
                        ACE_TEXT("(%P|%t) create_publisher failed.\n")),
                       1);
    }

    ::DDS::DataWriterQos dw_qos;
    pub->get_default_datawriter_qos(dw_qos);

    dw_qos.resource_limits.max_samples_per_instance = max_samples_per_instance;

    dw_qos.liveliness.lease_duration.sec = LEASE_DURATION_SEC;
    dw_qos.liveliness.lease_duration.nanosec = 0;

    int num_writers(0);

    ::DDS::DataWriter_var dw1;
    ::DDS::DataWriter_var dw2;

    if (publish_topics & TOPIC_T6) {
      dw1 = pub->create_datawriter(topic6, dw_qos,
                                  ::DDS::DataWriterListener::_nil(),
                                  ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(dw1)) {
        ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) create_datawriter failed.\n")));
        return 1;
      }
      ++num_writers;
    }

    if (publish_topics & TOPIC_T7) {
      dw2 = pub->create_datawriter(topic7, dw_qos,
                                   ::DDS::DataWriterListener::_nil(),
                                   ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
      if (CORBA::is_nil(dw2)) {
        ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) create_datawriter failed.\n")));
        return 1;
      }
      ++num_writers;
    }

    Writer** writers = new Writer*[num_writers];

    int idx(0);

    if (publish_topics & TOPIC_T6) {
      writers[idx++] = new Writer(dw1, 1, num_ops_per_thread);
    }

    if (publish_topics & TOPIC_T7) {
      writers[idx++] = new Writer(dw2, 1, num_ops_per_thread);
    }

    for (int i = 0; i < num_writers; ++i) {
      writers[i]->start();
    }


    ////////////////////////////////////////////////////////////////////////////
    // Create the subscriber
    ////////////////////////////////////////////////////////////////////////////
    ::DDS::Subscriber_var sub =
        dp->create_subscriber(SUBSCRIBER_QOS_DEFAULT,
                              ::DDS::SubscriberListener::_nil(),
                              ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
    if (CORBA::is_nil(sub)) {
      ACE_ERROR_RETURN((LM_ERROR,
                        ACE_TEXT("(%P|%t) create_subscriber failed.\n")),
                       1);
    }

    // Create the Datareaders
    ::DDS::DataReaderQos dr_qos;
    sub->get_default_datareader_qos(dr_qos);

    dr_qos.resource_limits.max_samples_per_instance = max_samples_per_instance;

    dr_qos.liveliness.lease_duration.sec = LEASE_DURATION_SEC;
    dr_qos.liveliness.lease_duration.nanosec = 0;

    dr_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS;

    ::DDS::DataReader_var dr1;
    ::DDS::DataReader_var dr2_1;
    ::DDS::DataReader_var dr2_2;
    ::DDS::DataReader_var dr2_3;
    ::DDS::DataReader_var dr3;
    ::DDS::DataReader_var dr4;
    ::DDS::DataReader_var dr5;

    ::DDS::DataReaderListener_var drl1 =
        new DataReaderListenerImpl1(num_ops_per_thread);
    ::DDS::DataReaderListener_var drl2_1 =
        new DataReaderListenerImpl4(num_ops_per_thread);
    ::DDS::DataReaderListener_var drl2_2 =
        new DataReaderListenerImpl4(num_ops_per_thread);
    ::DDS::DataReaderListener_var drl2_3 =
        new DataReaderListenerImpl4(num_ops_per_thread);
    ::DDS::DataReaderListener_var drl3 =
        new DataReaderListenerImpl1(num_ops_per_thread);
    ::DDS::DataReaderListener_var drl4 =
        new DataReaderListenerImpl1(num_ops_per_thread);
    ::DDS::DataReaderListener_var drl5 =
        new DataReaderListenerImpl1(num_ops_per_thread);

    if (topics & TOPIC_T1) {
      dr1 = sub->create_datareader(topic1, dr_qos, drl1,
                                   ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
    }

    if (topics & TOPIC_T2) {
      dr2_1 = sub->create_datareader(topic2, dr_qos, drl2_1,
                                     ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);

      dr2_2 = sub->create_datareader(topic2, dr_qos, drl2_2,
                                     ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);

      dr2_3 = sub->create_datareader(topic2, dr_qos, drl2_3,
                                     ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
    }

    if (topics & TOPIC_T3) {
      dr3 = sub->create_datareader(topic3, dr_qos, drl3,
                                   ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
    }

    if (topics & TOPIC_T4) {
      dr4 = sub->create_datareader(topic4, dr_qos, drl4,
                                   ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
    }

    if (topics & TOPIC_T5) {
      dr5 = sub->create_datareader(topic5, dr_qos, drl5,
                                   ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
    }

    if (topics & TOPIC_T1) {
      const DataReaderListenerImpl* const drl_servant =
        dynamic_cast<const DataReaderListenerImpl*>(drl1.in());
      if (!check_listener(drl_servant, num_ops_per_thread, ACE_TEXT(MY_TOPIC1)))
        status = 1;
    }

    if (topics & TOPIC_T2) {
      const DataReaderListenerImpl* const drl2_1srv =
        dynamic_cast<const DataReaderListenerImpl*>(drl2_1.in());
      if (!check_listener(drl2_1srv, num_ops_per_thread, ACE_TEXT(MY_TOPIC2)))
        status = 1;

      const DataReaderListenerImpl* const drl2_2srv =
        dynamic_cast<const DataReaderListenerImpl*>(drl2_2.in());
      if (!check_listener(drl2_2srv, num_ops_per_thread, ACE_TEXT(MY_TOPIC2)))
        status = 1;

      const DataReaderListenerImpl* const drl2_3srv =
        dynamic_cast<const DataReaderListenerImpl*>(drl2_3.in());
      if (!check_listener(drl2_3srv, num_ops_per_thread, ACE_TEXT(MY_TOPIC2)))
        status = 1;
    }

    if (topics & TOPIC_T3) {
      const DataReaderListenerImpl* const drl_servant =
        dynamic_cast<const DataReaderListenerImpl*>(drl3.in());
      if (!check_listener(drl_servant, num_ops_per_thread, ACE_TEXT(MY_TOPIC3)))
        status = 1;
    }

    if (topics & TOPIC_T4) {
      const DataReaderListenerImpl* const drl_servant =
        dynamic_cast<const DataReaderListenerImpl*>(drl4.in());
      if (!check_listener(drl_servant, num_ops_per_thread, ACE_TEXT(MY_TOPIC4)))
        status = 1;
    }

    if (topics & TOPIC_T5) {
      const DataReaderListenerImpl* const drl_servant =
        dynamic_cast<const DataReaderListenerImpl*>(drl5.in());
      if (!check_listener(drl_servant, num_ops_per_thread, ACE_TEXT(MY_TOPIC5)))
        status = 1;
    }

    if (topics & TOPIC_T1) {
      wait_for_file(ACE_TEXT(MY_TOPIC1), pub_finished_filename);
    }

    if (topics & TOPIC_T2) {
      wait_for_file(ACE_TEXT(MY_TOPIC2), pub_finished_filename);
    }

    if (topics & TOPIC_T3) {
      wait_for_file(ACE_TEXT(MY_TOPIC3), pub_finished_filename);
    }

    if (topics & TOPIC_T4) {
      wait_for_file(ACE_TEXT(MY_TOPIC4), pub_finished_filename);
    }

    if (topics & TOPIC_T5) {
      wait_for_file(ACE_TEXT(MY_TOPIC5), pub_finished_filename);
    }

    if (publish_topics) {
      bool writers_finished = false;

      while (!writers_finished && num_writers) {
        writers_finished = true;

        for (int m = 0; m < num_writers; m++) {
          writers_finished = writers_finished && writers[m]->is_finished();
        }

        if (!writers_finished) ACE_OS::sleep(small_time);
      }
    }

    if (publish_topics & TOPIC_T6) {
      ACE_TString t6_filename = ACE_TEXT(MY_TOPIC6) + pub_finished_filename;
      FILE* writers_completed =
        ACE_OS::fopen(t6_filename.c_str(), ACE_TEXT("w"));
      if (writers_completed == 0) {
        ACE_ERROR((LM_ERROR,
                   ACE_TEXT("(%P|%t) ERROR: Unable to create publisher ")
                   ACE_TEXT("completed file\n")));
        status = 1;
      } else {
        ACE_OS::fclose(writers_completed);
      }
    }

    if (publish_topics & TOPIC_T7) {
      ACE_TString t7_filename = ACE_TEXT(MY_TOPIC7) + pub_finished_filename;
      FILE* writers_completed =
        ACE_OS::fopen(t7_filename.c_str(), ACE_TEXT("w"));
      if (writers_completed == 0) {
        ACE_ERROR((LM_ERROR,
                   ACE_TEXT("(%P|%t) ERROR: Unable to create publisher ")
                   ACE_TEXT("completed file\n")));
        status = 1;
      } else {
        ACE_OS::fclose(writers_completed);
      }
    }

    ACE_DEBUG((LM_DEBUG, "(%P|%t) delete contained entities on pub\n"));
    pub->delete_contained_entities();

    for (int n = 0; n < num_writers; ++n) {
      delete writers[n];
    }
    delete [] writers;

    dp->delete_contained_entities();

    dpf->delete_participant(dp);

    TheServiceParticipant->shutdown();

  } catch (const TestException&) {
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT("(%P|%t) TestException caught in main.cpp.\n")));
    return 1;

  } catch (const CORBA::Exception& ex) {
    ex._tao_print_exception ("Exception caught in main.cpp:");
    return 1;
  }

  return status;
}