summaryrefslogtreecommitdiff
path: root/examples/QOS/client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/QOS/client.cpp')
-rw-r--r--examples/QOS/client.cpp897
1 files changed, 642 insertions, 255 deletions
diff --git a/examples/QOS/client.cpp b/examples/QOS/client.cpp
index 5315f115f5e..f902a3ba814 100644
--- a/examples/QOS/client.cpp
+++ b/examples/QOS/client.cpp
@@ -14,18 +14,23 @@
//
// ============================================================================
-
-#include "ace/OS.h"
-#include "ace/QoS_Session.h"
-#include "ace/QoS_Session_Factory.h"
-#include "ace/QoS_Session_Impl.h"
-#include "ace/QoS_Decorator.h"
#include "ace/SOCK_Dgram_Mcast_QoS.h"
+#include "ace/OS.h"
+
+#define QOSEVENT_MAIN
+#include "QosEvent.h"
+#include "Sender_QOS_Event_Handler.h"
+
+static const char *const SERVER_HOST = DEFAULT_MULTICASTGROUP;
+static const int MAX_ITERATIONS = 4;
-#include "QoS_Util.h"
-#include "Fill_ACE_QoS.h"
-#include "QoS_Signal_Handler.h"
-#include "Sender_QoS_Event_Handler.h"
+static int ValidOptions (char *argv[],
+ int argc,
+ OPTIONS *pOptions);
+static void Usage (char *szProgramname,
+ OPTIONS *pOptions);
+
+static const u_short PORT = ACE_DEFAULT_SERVER_PORT;
// To open QOS sockets administrative access is required on the
// machine. Fill in default values for QoS structure. The default
@@ -37,7 +42,90 @@
// depending upon whether this application is acting as a sender or
// receiver.
-// This function fills up the ACE_QoS_Params with the supplied iovec and ACE_QoS.
+static int
+fill_ace_qos_flowspec_default (ACE_QoS *pQos,
+ QOS_OPTIONS *pQosOptions)
+{
+ ACE_Flow_Spec ace_default_g711 (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_GUARANTEED,
+ // SERVICETYPE_CONTROLLEDLOAD
+ // doesnt work here for a yet unknown
+ // reason.
+ 368,
+ 368,
+ 25, // TTL. ACE specific. Not used on NT.
+ 1 // Priority. ACE specific. Not used on NT.
+ );
+
+ ACE_Flow_Spec ace_default_notraffic (ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_SERVICETYPE_NOTRAFFIC,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ 25, // TTL. ACE specific. Not used on NT.
+ 1); // Priority. ACE specific. Not used on NT.
+ if (pQosOptions->bReceiver)
+ {
+ pQos->receiving_flowspec (ace_default_g711);
+ pQos->sending_flowspec (ace_default_notraffic);
+ }
+ else
+ {
+ pQos->sending_flowspec (ace_default_g711);
+ pQos->receiving_flowspec (ace_default_notraffic);
+ }
+
+ const iovec iov = {0, 0};
+ pQos->provider_specific (iov);
+
+ return 0;
+}
+
+int SetQos (QOS_OPTIONS *pQosOptions,
+ ACE_QoS *pQos)
+{
+ int bError = FALSE;
+
+ // fill in default values
+ if (ACE_OS::strcasecmp (pQosOptions->szTemplate,
+ QOS_DEFAULTNAME) == 0)
+ fill_ace_qos_flowspec_default (pQos,
+ pQosOptions);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Run the program with -q:default option\n"));
+ return !bError;
+}
+
+// Fill up the ACE_Flow_Spec with the default_g711 values as defined
+// in the QoSEvent.h
+
+int
+FillQoSTraffic (ACE_Flow_Spec &afc)
+{
+ afc = default_g711;
+ return 0;
+}
+
+// Fill up the ACE_Flow_Spec with the default_notraffic values
+// as defined in the QoSEvent.h
+
+int
+FillQoSNoTraffic (ACE_Flow_Spec &afc)
+{
+ afc = default_notraffic;
+ return 0;
+}
+
+// This function fills up the ACE_QoS_Params with the supplied
+// iovec and ACE_QoS.
int
FillQoSParams (ACE_QoS_Params &qos_params,
@@ -48,7 +136,7 @@ FillQoSParams (ACE_QoS_Params &qos_params,
qos_params.caller_data (0);
qos_params.socket_qos (qos);
qos_params.group_socket_qos (0);
- qos_params.flags (ACE_JL_BOTH);
+ qos_params.flags (ACE_JL_SENDER_ONLY);
return 0;
}
@@ -56,278 +144,577 @@ FillQoSParams (ACE_QoS_Params &qos_params,
int
main (int argc, char * argv[])
{
+ ACE_Protocol_Info protocol_info;
+
+ OPTIONS options;
+
+ if (!ValidOptions (argv,
+ argc,
+ &options))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in ValidOptions\n"),
+ -1);
+
+ if (FindServiceProvider (options.spOptions.iProtocol,
+ options.spOptions.bQos,
+ options.spOptions.bMulticast,
+ &protocol_info) == FALSE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in FindServiceProvider\n"),
+ -1);
ACE_DEBUG ((LM_DEBUG,
"Sender\n"));
- QoS_Util qos_util(argc, argv);
+ ACE_QoS qos;
+
+ // By default the QOS is set as QOS_IOCTL_SET_BEFORE.
+ if (options.spOptions.bQos)
+ {
+ if (QOS_IOCTL_SET_BEFORE == options.qosOptions.qosIoctlSet)
+ {
+ if (SetQos (&options.qosOptions,
+ &qos))
+ ACE_DEBUG ((LM_DEBUG,
+ " QOS set before accept\n"));
+ }
+ else if (QOS_IOCTL_SET_QOS == options.qosOptions.qosIoctlSet)
+ {
+ options.qosOptions.bDisableSignalling = TRUE;
+ if (SetQos (&options.qosOptions,
+ &qos))
+ ACE_DEBUG ((LM_DEBUG,
+ " QOS set qos before accept - will be "
+ "set again in FD_QOS\n"));
+ }
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Use the -q:default option to enable the QOS\n"),
+ -1);
- if (qos_util.parse_args () == -1)
+ // Opening a new Multicast Datagram. It is absolutely necessary that
+ // the sender and the receiver subscribe to the same multicast
+ // addresses to make sure the "multicast sessions" for the two are
+ // the same. This is used to match the RESV<->PATH states.
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast;
+
+ // The windows example code uses PF_INET for the address family.
+ // Winsock.h defines PF_INET to be AF_INET. Is there really a
+ // difference between the protocol families and the address families
+ // ? The following code internally uses AF_INET as a default for the
+ // underlying socket.
+ ACE_INET_Addr mult_addr (options.port,
+ options.szHostname);
+
+ // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
+ // through subscribe.
+ ACE_QoS_Params qos_params;
+ FillQoSParams (qos_params,
+ 0,
+ &qos);
+
+ // The following call opens the Dgram_Mcast and calls the
+ // <ACE_OS::join_leaf> with the qos_params supplied here.
+ if (dgram_mcast.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ AF_INET,
+ ACE_FROM_PROTOCOL_INFO,
+ &protocol_info,
+ 0,
+ ACE_OVERLAPPED_SOCKET_FLAG
+ | ACE_FLAG_MULTIPOINT_C_LEAF
+ | ACE_FLAG_MULTIPOINT_D_LEAF) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
- "Error in parsing args\n"),
+ "Error in subscribe\n"),
-1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ u_long dwBytes;
+
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ ACE_SIO_MULTICAST_SCOPE, // IO control code.
+ &nIP_TTL, // In buffer.
+ sizeof (nIP_TTL), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Multicast scope ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds \n"));
+
+ int bFlag = FALSE;
+
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
+ &bFlag, // In buffer.
+ sizeof (bFlag), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Loopback ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Disable Loopback with ACE_OS::ioctl call succeeds \n"));
- // This is a multicast application.
- if (qos_util.multicast_flag ())
- {
- Fill_ACE_QoS fill_ace_qos;
-
- // The application adds the flow specs that it wants into the
- // Fill_ACE_QoS. The Fill_ACE_QoS indexes the flow specs by the flow
- // spec names. Here the new flowspec being added is g_711.
- ACE_CString g_711 ("g_711");
-
- switch (fill_ace_qos.map ().bind (g_711,
- new ACE_Flow_Spec (9200,
- 708,
- 18400,
- 0,
- 0,
- ACE_SERVICETYPE_CONTROLLEDLOAD,
- 368,
- 368,
- 25,
- 1)))
- {
- case 1 :
- ACE_ERROR_RETURN ((LM_ERROR,
- "Unable to bind the new flow spec\n"
- "The Flow Spec name already exists\n"),
- -1);
- break;
- case -1 :
- ACE_ERROR_RETURN ((LM_ERROR,
- "Unable to bind the new flow spec\n"),
- -1);
- break;
- }
-
- ACE_DEBUG ((LM_DEBUG,
- "g_711 Flow Spec bound successfully\n"));
-
- // This is a sender. So we fill in the sending QoS parameters.
- ACE_QoS ace_qos_sender;
-
- if (fill_ace_qos.fill_simplex_sender_qos (ace_qos_sender,
- g_711) !=0)
- ACE_ERROR_RETURN ((LM_ERROR,
- "Unable to fill simplex sender qos\n"),
- -1);
- else
- ACE_DEBUG ((LM_DEBUG,
- "Filled up the Sender QoS parameters\n"));
-
- // Opening a new Multicast Datagram. It is absolutely necessary that
- // the sender and the receiver subscribe to the same multicast
- // addresses to make sure the "multicast sessions" for the two are
- // the same. This is used to match the RESV<->PATH states.
- ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos;
-
- // Multicast Session Address specified by user at command line.
- // If this address is not specified,
- // <localhost:ACE_DEFAULT_MULTICAST_PORT> is assumed.
- ACE_INET_Addr mult_addr (*(qos_util.mult_session_addr ()));
-
- // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
- // through subscribe.
-
- ACE_QoS_Params qos_params;
- FillQoSParams (qos_params, 0, &ace_qos_sender);
-
- // Create a QoS Session Factory.
- ACE_QoS_Session_Factory session_factory;
-
- // Ask the factory to create a QoS session. This could be RAPI or
- // GQoS based on the parameter passed.
- ACE_QoS_Session *qos_session =
- session_factory.create_session (ACE_QoS_Session_Factory::ACE_RAPI_SESSION);
-
- // Create a destination address for the QoS session. The same
- // address should be used for the subscribe call later. A copy is
- // made below only to distinguish the two usages of the dest
- // address.
+ // Fill up an ACE_QoS and pass it to the overloaded ACE_OS::ioctl ()
+ // that uses the I/O control code as SIO_SET_QOS.
+ ACE_QoS ace_qos;
- ACE_INET_Addr dest_addr (mult_addr);
+ // Make sure the flowspec is set in the correct direction. Since
+ // this is the sender, sending flowspec is set to g711 and receiving
+ // flowspec is set to no traffic.
+ ACE_Flow_Spec sending_flowspec;
+ ACE_Flow_Spec receiving_flowspec;
+ const iovec iov = {0, 0};
- // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
- // Protocol]. Initialize the QoS session.
- if (qos_session->open (mult_addr,
- IPPROTO_UDP) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- "Error in opening the QoS session\n"),
- -1);
- else
- ACE_DEBUG ((LM_DEBUG,
- "QoS session opened successfully\n"));
-
- // The following call opens the Dgram_Mcast and calls the
- // <ACE_OS::join_leaf> with the qos_params supplied here. Note the
- // QoS session object is passed into this call. This subscribes the
- // underlying socket to the passed in QoS session. For joining
- // multiple multicast sessions, the following subscribe call should
- // be made with different multicast addresses and a new QoS session
- // object should be passed in for each such call. The QoS session
- // objects can be created only through the session factory. Care
- // should be taken that the mult_addr for the subscribe() call
- // matches the dest_addr of the QoS session object. If this is not
- // done, the subscribe call will fail. A more abstract version of
- // subscribe will be added that constrains the various features of
- // GQoS like different flags etc.
-
- if (dgram_mcast_qos.subscribe (mult_addr,
- qos_params,
- 1,
- 0,
- AF_INET,
- // ACE_FROM_PROTOCOL_INFO,
- 0,
- 0, // ACE_Protocol_Info,
- 0,
- ACE_OVERLAPPED_SOCKET_FLAG
- | ACE_FLAG_MULTIPOINT_C_LEAF
- | ACE_FLAG_MULTIPOINT_D_LEAF,
- qos_session) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- "Error in subscribe\n"),
- -1);
- else
- ACE_DEBUG ((LM_DEBUG,
- "Dgram_Mcast subscribe succeeds \n"));
+ FillQoSTraffic (sending_flowspec);
+ FillQoSNoTraffic (receiving_flowspec);
- int nIP_TTL = 25;
- char achInBuf [BUFSIZ];
- u_long dwBytes;
+ ace_qos.sending_flowspec (sending_flowspec);
+ ace_qos.receiving_flowspec (receiving_flowspec);
+ ace_qos.provider_specific (iov);
- // Should this be abstracted into QoS objects ?? Doesnt seem to have
- // to do anything directly with QoS.
- if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
- ACE_SIO_MULTICAST_SCOPE, // IO control code.
- &nIP_TTL, // In buffer.
- sizeof (nIP_TTL), // Length of in buffer.
- achInBuf, // Out buffer.
- BUFSIZ, // Length of Out buffer.
- &dwBytes, // bytes returned.
- 0, // Overlapped.
- 0) == -1) // Func.
- ACE_ERROR ((LM_ERROR,
- "Error in Multicast scope ACE_OS::ioctl() \n"));
- else
- ACE_DEBUG ((LM_DEBUG,
- "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds \n"));
-
- int bFlag = 0;
-
- // Should this be abstracted into QoS objects ?? Doesnt seem to have
- // to do anything directly with QoS.
- if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
- ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
- &bFlag, // In buffer.
- sizeof (bFlag), // Length of in buffer.
- achInBuf, // Out buffer.
- BUFSIZ, // Length of Out buffer.
- &dwBytes, // bytes returned.
- 0, // Overlapped.
- 0) == -1) // Func.
- ACE_ERROR ((LM_ERROR,
- "Error in Loopback ACE_OS::ioctl() \n"));
- else
- ACE_DEBUG ((LM_DEBUG,
- "Disable Loopback with ACE_OS::ioctl call succeeds \n"));
-
- // This is a sender.
- qos_session->flags (ACE_QoS_Session::ACE_QOS_SENDER);
-
- ACE_QoS_Manager qos_manager = dgram_mcast_qos.qos_manager ();
-
- // Since we are using RSVP, it is imperative that the client
- // application have the option of supplying the source sender
- // port for the RSVP messages. A default will be chosen by the
- // ACE API if this is not done.
- qos_session->source_port (qos_util.source_port ());
-
- // Set the QoS for the session. Replaces the ioctl () call that
- // was being made previously.
- if (qos_session->qos (&dgram_mcast_qos,
- &qos_manager,
- ace_qos_sender) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- "Unable to set QoS\n"),
- -1);
- else
- ACE_DEBUG ((LM_DEBUG,
- "Setting QOS succeeds.\n"));
-
- // Register a signal handler that helps to gracefully close the open
- // QoS sessions.
- QoS_Signal_Handler qos_signal_handler (qos_session);
-
- // Register the usual SIGINT signal handler with the Reactor for
- // the application to gracefully release the QoS session and
- // shutdown.
- if (ACE_Reactor::instance ()->register_handler
- (SIGINT, &qos_signal_handler) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- "Error in registering the Signal Handler.\n"),
- -1);
+ // Set the QOS according to the supplied ACE_QoS. The I/O control
+ // code used under the hood is SIO_SET_QOS.
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ ACE_SIO_SET_QOS,
+ ace_qos, // ACE_QoS.
+ &dwBytes) == -1) // bytes returned.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Qos set ACE_OS::ioctl() %d\n",
+ dwBytes));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting Default QOS with ACE_OS::ioctl succeeds \n"));
- // Handler to process QoS and Data events for the reciever.
- Sender_QoS_Event_Handler qos_event_handler (dgram_mcast_qos,
- qos_session);
+ // Instantiate a QOS Event Handler and pass the Dgram_Mcast into it.
+ ACE_QOS_Event_Handler qos_event_handler (dgram_mcast);
+
+ // Register the QOS Handler with the Reactor for the QOS_MASK. Note
+ // the receiver registers for both QOS_MASK as well as READ_MASK.
- // Decorate the above handler with QoS functionality.
- ACE_QoS_Decorator qos_decorator (&qos_event_handler,
- qos_session);
+ if (ACE_Reactor::instance ()->register_handler
+ (&qos_event_handler,
+ ACE_Event_Handler::QOS_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering QOS Handler\n"),
+ -1);
- // Initialize the Decorator.
- if (qos_decorator.init () != 0)
- ACE_ERROR_RETURN ((LM_ERROR,
- "QoS Decorator init () failed.\n"),
- -1);
+ // Start the event loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "Running the Event Loop ... \n"));
- // Register the decorated Event Handler with the Reactor.
- if (ACE_Reactor::instance ()->register_handler (&qos_decorator,
- ACE_Event_Handler::QOS_MASK |
- ACE_Event_Handler::READ_MASK) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- "Error in registering the Decorator with the Reactor\n"),
- -1);
+ ACE_Reactor::instance ()->run_event_loop ();
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down Sender\n"));
+ return 0;
+}
+int
+FindServiceProvider(int iProtocol,
+ int bQos,
+ int bMulticast,
+ ACE_Protocol_Info *pProtocolInfo)
+{
-// // Instantiate a QOS Event Handler and pass the Dgram_Mcast and QoS
-// // session object into it.
-// ACE_QOS_Event_Handler qos_event_handler (dgram_mcast_qos,
-// qos_session);
+ ACE_Protocol_Info *protocol_buffer = 0;
-// ACE_RAPI_Event_Handler rapi_event_handler (qos_session);
+ u_long buffer_length = 0;
+ u_long dwErr;
+ int bProtocolFound = FALSE;
-// // Register the RAPI Event Handler with the Reactor. This
-// // handles the QoS events.
-// if (ACE_Reactor::instance ()->register_handler
-// (&rapi_event_handler,
-// ACE_Event_Handler::QOS_MASK | ACE_Event_Handler::READ_MASK) == -1)
-// ACE_ERROR_RETURN ((LM_ERROR,
-// "Error in registering the RAPI Event Handler\n"),
-// -1);
-
- // Start the event loop.
- ACE_DEBUG ((LM_DEBUG,
- "Running the Event Loop ... \n"));
+ // first have enum_protocols () tell us how big a buffer is needed.
+ int ret_val = ACE_OS::enum_protocols (0,
+ protocol_buffer,
+ &buffer_length);
+ if (ret_val != -1)
+ ACE_DEBUG ((LM_DEBUG,
+ "enum_protocols () : should not have suceeded\n"));
+
+ else if (ACE_ENOBUFS != (dwErr = ACE_OS::set_errno_to_wsa_last_error ()))
+ // enum_protocols () failed for some reason not relating to buffer size
+ ACE_DEBUG ((LM_DEBUG,
+ "enum_protocols () : failed for a reason other than "
+ "inadequate buffer size : %d\n",
+ ACE_OS::set_errno_to_wsa_last_error ()));
+ else
+ {
+ if (buffer_length > 0)
+ {
+ void *ptr = 0;
+ ACE_NEW_RETURN (ptr,
+ char [buffer_length],
+ 0);
+ protocol_buffer = (ACE_Protocol_Info *) ptr;
+ }
+
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Buffer length returned by enum_protocols () is"
+ "less than or equal to zero\n"),
+ -1);
+
+ if (protocol_buffer)
+ {
+ // now we can call enum_protocols () again with the
+ // expectation it will succeed because we have allocated a
+ // big enough buffer.
+ ret_val = ACE_OS::enum_protocols (0,
+ protocol_buffer,
+ &buffer_length);
+ if (ret_val == -1)
+ ACE_DEBUG ((LM_DEBUG,
+ "enum_protocols () : failed even after allocating"
+ " a big enough buffer : %d\n",
+ ACE_OS::set_errno_to_wsa_last_error ()));
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Size allocated for the Protocol Buffer = %d\n"
+ "\nList of transport protocols "
+ "returned by enum_protocols () : \n",
+ buffer_length));
+
+ // Loop thru protocols, looking for a matching service
+ // provider.
+ for (int i = 0; i < ret_val; i++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ " sp <%s>\n",
+ protocol_buffer[i].szProtocol));
+
+ if (AF_INET == protocol_buffer[i].iAddressFamily
+ && iProtocol == protocol_buffer[i].iProtocol)
+ {
+ // look for
+ if (bQos && bMulticast)
+ {
+ if ((ACE_XP1_QOS_SUPPORTED == ((ACE_XP1_QOS_SUPPORTED
+ & protocol_buffer[i].dwServiceFlags1)))
+ && (ACE_XP1_SUPPORT_MULTIPOINT == (ACE_XP1_SUPPORT_MULTIPOINT &
+ protocol_buffer[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = protocol_buffer[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else if (bQos)
+ {
+ if (ACE_XP1_QOS_SUPPORTED == (ACE_XP1_QOS_SUPPORTED
+ & protocol_buffer[i].dwServiceFlags1))
+ {
+ *pProtocolInfo = protocol_buffer[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else if (bMulticast)
+ {
+ if ((ACE_XP1_SUPPORT_MULTIPOINT == (ACE_XP1_SUPPORT_MULTIPOINT &
+ protocol_buffer[i].dwServiceFlags1))
+ && (ACE_XP1_QOS_SUPPORTED != (ACE_XP1_QOS_SUPPORTED &
+ protocol_buffer[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = protocol_buffer[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else if ((ACE_XP1_QOS_SUPPORTED != (ACE_XP1_QOS_SUPPORTED
+ & protocol_buffer[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = protocol_buffer[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+
+ } // for loop.
+
+ } // ACE_OS::enum_protocols ().
- ACE_Reactor::instance ()->run_event_loop ();
+ ACE_OS::free (protocol_buffer);
- ACE_DEBUG ((LM_DEBUG,
- "(%P|%t) shutting down server logging daemon\n"));
- }
- else
+ } // protocol_buffer
+
+ } // ACE_OS::enum_protocols ().
+
+ if (bProtocolFound)
ACE_DEBUG ((LM_DEBUG,
- "Specify a -m option for multicast application\n"));
- return 0;
+ "\n Using service provider <%s>\n\n",
+ pProtocolInfo->szProtocol));
+
+ return bProtocolFound;
+
}
+int
+ValidOptions (char *argv[],
+ int argc,
+ OPTIONS *pOptions)
+{
+ *pOptions = default_options;
+ for (int i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-' || argv[i][0] == '/')
+ {
+ switch (ACE_OS::to_lower (argv[i][1]))
+ {
+ case 'b' :
+ if (ACE_OS::strlen (argv[i]) > 3)
+ pOptions->nBufSize = 1024 * ACE_OS::atoi (&argv[i][3]);
+ break;
+
+ case 'c' :
+ pOptions->qosOptions.bAlternateQos = TRUE;
+ break;
+
+ case 'd' :
+ if (ACE_OS::strlen (argv[i]) > 3)
+ pOptions->fillchar = argv[i][3];
+ break;
+
+ case 'e' :
+ if (ACE_OS::strlen (argv[i]) > 3)
+ pOptions->port = ACE_OS::atoi (&argv[i][3]);
+ break;
+
+ case 'i' :
+ if (ACE_OS::strlen (argv[i]) > 3)
+ {
+ if ('a' == argv[i][3] || 'A' == argv[i][3])
+ pOptions->qosOptions.qosIoctlSet = QOS_IOCTL_SET_AFTER;
+ else if ('b' == argv[i][3] || 'B' == argv[i][3])
+ pOptions->qosOptions.qosIoctlSet = QOS_IOCTL_SET_BEFORE;
+ else if ('d' == argv[i][3] || 'D' == argv[i][3])
+ pOptions->qosOptions.qosIoctlSet = QOS_IOCTL_SET_DURING;
+ else if ('q' == argv[i][3] || 'Q' == argv[i][3])
+ pOptions->qosOptions.qosIoctlSet = QOS_IOCTL_SET_QOS;
+ else
+ pOptions->qosOptions.qosIoctlSet = QOS_IOCTL_SET_BEFORE;
+ }
+ break;
+
+ case 'l' :
+ if (ACE_OS::strlen (argv[i]) > 3)
+ pOptions->nRepeat = ACE_OS::atoi (&argv[i][3]);
+ break;
+
+ case 'm' :
+ pOptions->spOptions.bMulticast = TRUE;
+ if (ACE_OS::strlen (argv[i]) > 3)
+ ACE_OS::strcpy (pOptions->szHostname,
+ &argv[i][3]);
+ else
+ ACE_OS::strcpy (pOptions->szHostname,
+ DEFAULT_MULTICASTGROUP);
+ break;
+
+ case 'n' :
+ pOptions->qosOptions.bReceiver = FALSE;
+ // multicast group overrides hostname on -n
+ if (!pOptions->spOptions.bMulticast
+ && ACE_OS::strlen (argv[i]) > 3)
+ ACE_OS::strcpy (pOptions->szHostname,
+ &argv[i][3]);
+ break;
+
+ case 'p' :
+ if (ACE_OS::strlen (argv[i]) > 3)
+ {
+ if ('u' == argv[i][3] || 'U' == argv[i][3])
+ pOptions->spOptions.iProtocol = IPPROTO_UDP;
+ else if ('t' == argv[i][3] || 'T' == argv[i][3])
+ pOptions->spOptions.iProtocol = IPPROTO_TCP;
+ else
+ pOptions->spOptions.iProtocol = IPPROTO_TCP;
+ }
+ break;
+
+ case 'q' :
+ pOptions->spOptions.bQos = TRUE;
+ if (ACE_OS::strlen (argv[i]) > 3)
+ ACE_OS::strcpy (pOptions->qosOptions.szTemplate,
+ &argv[i][3]);
+ break;
+
+ case 'r' :
+ if (ACE_OS::strlen (argv[i]) > 3)
+ {
+ if (ACE_OS::strcasecmp (argv[i],
+ "-rsvp-confirm") == 0
+ || ACE_OS::strcasecmp (argv[i],
+ "-rsvp_confirm") == 0)
+ {
+ pOptions->qosOptions.bConfirmResv = TRUE;
+ pOptions->qosOptions.bProviderSpecific = TRUE;
+ }
+ else if (ACE_OS::strcasecmp (argv[i],
+ "-rsvp-wait") == 0
+ || ACE_OS::strcasecmp (argv[i],
+ "-rsvp_wait") == 0)
+ {
+ pOptions->qosOptions.bWaitToSend = TRUE;
+ pOptions->qosOptions.bProviderSpecific = TRUE;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Ignoring option <%s>\n",
+ argv[i]));
+ }
+ break;
+
+ case 's' :
+ if (ACE_OS::strlen (argv[i]) > 3)
+ pOptions->dwSleep =
+ ACE_OS::atoi (&argv[i][3]);
+ break;
+
+ case '?' :
+ Usage (argv[0],
+ &default_options);
+ return FALSE;
+ break;
+
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ " unknown options flag %s\n",
+ argv[i]));
+ Usage (argv[0],
+ &default_options);
+ return FALSE;
+ break;
+ }
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ " unknown option %s\n",
+ argv[i]));
+ Usage (argv[0],
+ &default_options);
+ return FALSE;
+ }
+ }
+ if (pOptions->qosOptions.bReceiver)
+ pOptions->fillchar = 0;
+ if (pOptions->spOptions.bMulticast)
+ {
+ pOptions->spOptions.iProtocol = IPPROTO_UDP;
+ pOptions->qosOptions.bSetDestaddr = FALSE;
+ }
+ if (IPPROTO_TCP == pOptions->spOptions.iProtocol)
+ {
+ pOptions->spOptions.bMulticast = FALSE;
+ pOptions->qosOptions.bSetDestaddr = FALSE;
+ }
+ else if (!pOptions->spOptions.bMulticast)
+ pOptions->qosOptions.bSetDestaddr = TRUE;
+
+ if (pOptions->spOptions.bQos)
+ {
+ if (pOptions->qosOptions.bReceiver
+ && pOptions->qosOptions.bWaitToSend)
+ pOptions->qosOptions.bWaitToSend = FALSE;
+ // not a valid receiver option
+
+ if (!pOptions->qosOptions.bReceiver
+ && pOptions->qosOptions.bConfirmResv)
+ pOptions->qosOptions.bWaitToSend = FALSE;
+ // not a valid sender option
+
+ if (pOptions->qosOptions.bAlternateQos)
+ // override repeat count to continuous mode
+ pOptions->nRepeat = 0;
+
+ if (IPPROTO_UDP == pOptions->spOptions.iProtocol
+ && !pOptions->spOptions.bMulticast)
+ // Using UDP, there WSAAccept will not be called, therefore
+ // do not wait to set qos.
+ pOptions->qosOptions.qosIoctlSet =
+ QOS_IOCTL_SET_BEFORE;
+
+ pOptions->qosOptions.bFineGrainErrorAvail = TRUE;
+ pOptions->qosOptions.bQosabilityIoctls = TRUE;
+ ACE_DEBUG ((LM_DEBUG,
+ "running on NT\n"));
+ }
+
+ if (pOptions->nBufSize > 0)
+ ACE_NEW_RETURN (pOptions->buf,
+ char[pOptions->nBufSize],
+ 0);
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Buffer size to be allocated is less than or"
+ "equal to zero\n"),
+ -1);
+ if (pOptions->buf == 0)
+ return FALSE;
+ else
+ {
+ ACE_OS::memset (pOptions->buf,
+ pOptions->fillchar,
+ pOptions->nBufSize);
+ return TRUE;
+ }
+}
+
+// Print out usage table for the program.
+
+void
+Usage (char *szProgramname,
+ OPTIONS *pOptions)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "usage:\n %s -?\n\n"
+ " %s [-b:#] [-d:c] [-e:#] [-l:#] [-m:group] "
+ "[-n:host] [-s:#] [-u]\n\t[-q:template [-i:[a|b|d|q]]"
+ "[-c] [-rsvp-confirm] [-rsvp-wait]]\n\n",
+ " -?\t\tDisplay this help\n\n"
+ " -b:bufsize\tSize of send/recv buffer; in 1K increments (Def:%d)\n"
+ " -d:c\t\tCharacter used to fill buffer (Def:%c)\n"
+ " -e:port\tEndpoint number (port) to use (Def:%d)\n"
+ " -l:loop\tLoop count for sending buffer (0==>continuous)\n"
+ " -m:group\tMulticast group (IP) to join (Def:%s)\n"
+ " -n:host\tAct as the client and connect to 'host' (Def:%s)\n"
+ " -p:protocol\tTCP or UDP (def:TCP)\n"
+ " -s:#\t\tSleep # milliseconds between sends (def: 0)\n"
+ " -q:template\tEnable QoS and use 'template' to specify the name (Def:%s)\n"
+ " -c\t\tCycle enabling/disabling QOS on sending socket (Def: no cycling)\n"
+ " -i:[a|b|d|q]\tSet Qos After, Before, During accept/connect, or during FD_QOS\n\t\t\t(def: Before)\n"
+ " -rsvp-confirm\t\tRequest RESV confirmation be sent (Def: no confirmation)\n"
+ " -rsvp-wait\t\tWait for RESV from receiver before sending data\n",
+ szProgramname,
+ szProgramname,
+ pOptions->nBufSize,
+ pOptions->fillchar,
+ pOptions->port,
+ pOptions->nRepeat,
+ DEFAULT_MULTICASTGROUP,
+ pOptions->szHostname,
+ pOptions->qosOptions.szTemplate));
+ return;
+}