summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorvishal <vishal@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-31 20:18:36 +0000
committervishal <vishal@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-31 20:18:36 +0000
commitfa10e369b7b2083eab73f7587d218d61932ce83d (patch)
tree26c35ce31d49c666384e3885b1176af828fc0b0b /examples
parentb251e874ee3b29fcae4feec5985864032e90b5ea (diff)
downloadATCD-fa10e369b7b2083eab73f7587d218d61932ce83d.tar.gz
*** empty log message ***
Diffstat (limited to 'examples')
-rw-r--r--examples/QOS/QOS.dsw41
-rw-r--r--examples/QOS/QOS_Event_Handler.cpp56
-rw-r--r--examples/QOS/QOS_Event_Handler.h54
-rw-r--r--examples/QOS/QosEvent.h213
-rw-r--r--examples/QOS/Read_Handler.cpp73
-rw-r--r--examples/QOS/Read_Handler.h51
-rw-r--r--examples/QOS/client.cpp833
-rw-r--r--examples/QOS/client.dsp105
-rw-r--r--examples/QOS/server.cpp845
-rw-r--r--examples/QOS/server.dsp125
10 files changed, 2396 insertions, 0 deletions
diff --git a/examples/QOS/QOS.dsw b/examples/QOS/QOS.dsw
new file mode 100644
index 00000000000..54c94ed111f
--- /dev/null
+++ b/examples/QOS/QOS.dsw
@@ -0,0 +1,41 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "002"=.\server.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "003"=.\client.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/examples/QOS/QOS_Event_Handler.cpp b/examples/QOS/QOS_Event_Handler.cpp
new file mode 100644
index 00000000000..7d9c0824d85
--- /dev/null
+++ b/examples/QOS/QOS_Event_Handler.cpp
@@ -0,0 +1,56 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/tests/
+//
+// = FILENAME
+// QOS_Event_Handler.cpp
+//
+// = AUTHOR
+// Vishal Kachroo
+//
+// ============================================================================
+
+#include "QOS_Event_Handler.h"
+
+// Constructor.
+ACE_QOS_Event_Handler::ACE_QOS_Event_Handler ()
+{}
+
+ACE_QOS_Event_Handler::ACE_QOS_Event_Handler (const ACE_SOCK_Dgram_Mcast &dgram_mcast)
+{
+ this->read_handler_.dgram_mcast (dgram_mcast);
+}
+
+// Destructor.
+ACE_QOS_Event_Handler::~ACE_QOS_Event_Handler ()
+{
+}
+
+// Return the handle of the Dgram_Mcast. This method is
+// called internally by the reactor.
+
+ACE_HANDLE
+ACE_QOS_Event_Handler::get_handle (void) const
+{
+ return this->read_handler_.get_handle ();
+}
+
+int
+ACE_QOS_Event_Handler::handle_qos (ACE_HANDLE)
+{
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Inside handle_qos ()\nRegistering the Read Handler\n"));
+
+ if (ACE_Reactor::instance ()->register_handler (&this->read_handler_,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the read_handler_\n"),
+ -1);
+
+ return 0;
+}
diff --git a/examples/QOS/QOS_Event_Handler.h b/examples/QOS/QOS_Event_Handler.h
new file mode 100644
index 00000000000..c3915d6dbec
--- /dev/null
+++ b/examples/QOS/QOS_Event_Handler.h
@@ -0,0 +1,54 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS/
+//
+// = FILENAME
+// QOS_Event_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo
+//
+// ============================================================================
+
+#ifndef QOS_EVENT_HANDLER_H
+#define QOS_EVENT_HANDLER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/Reactor.h"
+
+#include "Read_Handler.h"
+
+ACE_RCSID(QOS_Event_Handler, QOS_Event_Handler, "$Id$")
+
+ class ACE_QOS_Event_Handler : public ACE_Event_Handler
+ {
+ public:
+ // = Initialization and Termination methods.
+ ACE_QOS_Event_Handler (void);
+ // Constructor.
+
+ ACE_QOS_Event_Handler::ACE_QOS_Event_Handler (const ACE_SOCK_Dgram_Mcast &dgram_mcast);
+ // Constructor.
+
+ ~ACE_QOS_Event_Handler (void);
+ // Destructor.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // Override this to return the handle of the Dgram_Mcast
+ // that we are using.
+
+ virtual int handle_qos (ACE_HANDLE fd);
+ // Handles a QOS event. Right now, just
+ // registers a handler for the READ events.
+
+ private:
+
+ ACE_Read_Handler read_handler_;
+
+ };
+
+#endif /* QOS_EVENT_HANDLER_H */
diff --git a/examples/QOS/QosEvent.h b/examples/QOS/QosEvent.h
new file mode 100644
index 00000000000..fe72f5c9053
--- /dev/null
+++ b/examples/QOS/QosEvent.h
@@ -0,0 +1,213 @@
+//$Id$
+
+#ifndef QOSEVENT_H
+#define QOSEVENT_H
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <qos.h>
+#include <qossp.h>
+#include <stdio.h>
+
+
+#define MY_DEFPORT (5001)
+
+
+
+// Application specific define - there is NO specific invalid send priority.
+// This value is simply used to indicate whether or not to even set priority.
+#define INVALID_SEND_PRIORITY 255
+
+
+// application specific define - there is no "default" QOS template in GQoS,
+// only for this particular application does "default" have meaning.
+#define QOS_DEFAULTNAME "default"
+
+// Use an arbitrary multicast group if none is specified on the command line
+#define DEFAULT_MULTICASTGROUP "234.5.6.7"
+
+typedef struct _SP_OPTIONS
+{
+ int iProtocol; // protocol to use
+ BOOL bQos; // enable QOS
+ BOOL bMulticast; // enable multicasting
+} SP_OPTIONS;
+
+
+typedef enum
+{
+ QOS_IOCTL_SET_DURING, // do not use ioctl to set Qos
+ QOS_IOCTL_SET_BEFORE, // set qos with ioctl before connection/accept
+ QOS_IOCTL_SET_AFTER, // set qos with ioctl after connection/accept
+ QOS_IOCTL_SET_QOS // set qos in receiver during FD_QOS, note that
+ // qos must be set prior to wsaeventselect in
+ // order to ever receive fd_qos
+} QOS_IOCTL_SET;
+
+
+typedef struct _QOS_OPTIONS
+{
+ BOOL bReceiver; // act as receiver if TRUE
+ BOOL bWaitToSend; // sender must wait for RESV before sending
+ BOOL bConfirmResv; // have receiver request RESV confirmation
+ BOOL bQueryBufferSize; // have WSAioctl return size of buffer needed
+ // when using SIO_GET_QOS (behaviour not
+ // avail on Win98).
+ BOOL bMustSetQosInAccept;// Will be set for Win98 only. Win98 currently
+ // needs valid qos structure to be set in
+ // wsaaccept condition func in lpSQos is valid
+ BOOL bDisableSignalling; // If TRUE do not emit RSVP signalling, just use
+ // traffic control
+ BOOL bAlternateQos; // Alternate between enabling and disabling QOS on
+ // a socket every N sends
+ UCHAR SendPriority; // create QOS_OBJECT_PRIORITY structure, and
+ // set valid priority 0-7
+ BOOL bSetDestaddr; // TRUE if unconnected UDP and QOS is used (not multicast)
+ BOOL bProviderSpecific; // TRUE if a provider-specific object must be set
+ BOOL bFineGrainErrorAvail; // TRUE if Win2000beta3 availability of
+ // fine grain errors on SIO_SET_QOS
+ BOOL bQosabilityIoctls; // TRUE if Win2000beta3 qosablity ioctls
+ BOOL bFixTemplate; // TRUE if Win98 to divide ToeknRate and PeakBandwidth
+ // by 8 when using WSAGetQOSByName
+ QOS_IOCTL_SET qosIoctlSet; // when to set QOS
+ CHAR szTemplate[64]; // qos template
+} QOS_OPTIONS;
+
+
+
+extern FLOWSPEC default_notraffic;
+extern FLOWSPEC default_g711;
+
+
+typedef struct _OPTIONS
+{
+ CHAR szHostname[64];
+ unsigned short port;
+ int nRepeat;
+ CHAR fillchar;
+ int nBufSize;
+ CHAR * buf;
+ DWORD dwSleep;
+ DWORD dwTotalClients;
+ QOS_OPTIONS qosOptions;
+ SP_OPTIONS spOptions;
+} OPTIONS;
+
+
+#ifdef QOSEVENT_MAIN
+
+OPTIONS default_options =
+{
+ "localhost",
+ MY_DEFPORT,
+ 1,
+ 'c',
+ 4096,
+ NULL,
+ 0,
+ 0,
+ {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, INVALID_SEND_PRIORITY,
+ TRUE, TRUE, TRUE, TRUE, FALSE, QOS_IOCTL_SET_BEFORE, QOS_DEFAULTNAME},
+ {IPPROTO_TCP, FALSE, FALSE}
+};
+
+FLOWSPEC default_notraffic =
+{
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ SERVICETYPE_NOTRAFFIC,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED
+};
+
+
+FLOWSPEC default_g711 =
+{
+ 9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368
+};
+/*
+
+FLOWSPEC default_g711 =
+ {
+ 8500,
+ 680,
+ 17000,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ SERVICETYPE_GUARANTEED,
+ 340,
+ 340
+ };
+
+
+FLOWSPEC default_g711 =
+ {
+ 68000,
+ 6800,
+ 136000,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ SERVICETYPE_GUARANTEED,
+ 340,
+ 340
+ };
+*/
+
+SOCKADDR_IN g_destaddr;
+
+#else
+
+extern FLOWSPEC default_notraffic;
+extern FLOWSPEC default_g711;
+extern SOCKADDR_IN g_destaddr;
+
+#endif
+
+
+
+extern BOOL FindServiceProvider(
+ int iProtocol,
+ BOOL bQos,
+ BOOL bMulticast,
+ WSAPROTOCOL_INFO *pProtocolInfo);
+
+extern VOID Receiver(
+ OPTIONS *pOptions,
+ WSAPROTOCOL_INFO *pProtocolInfo);
+
+extern VOID Sender(
+ OPTIONS *pOptions,
+ WSAPROTOCOL_INFO *pProtocolInfo);
+
+extern BOOL SetQos(
+ SOCKET sd,
+ QOS_OPTIONS *pQosOptions,
+ BOOL bSetQos,
+ QOS *pQos,
+ DWORD *cbQosLen);
+
+extern BOOL GetQos(
+ SOCKET sd,
+ BOOL bQueryBufferSize,
+ QOS *pQos);
+
+extern void PrintQos(
+ QOS *qos,
+ CHAR *lpszIndent);
+
+extern BOOL ChkQosSend(
+ SOCKET sd);
+
+
+
+#endif
diff --git a/examples/QOS/Read_Handler.cpp b/examples/QOS/Read_Handler.cpp
new file mode 100644
index 00000000000..7559007bf58
--- /dev/null
+++ b/examples/QOS/Read_Handler.cpp
@@ -0,0 +1,73 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS/
+//
+// = FILENAME
+// Read_Handler.cpp
+//
+// = AUTHOR
+// Vishal Kachroo
+//
+// ============================================================================
+
+#include "Read_Handler.h"
+
+// Constructor.
+ACE_Read_Handler::ACE_Read_Handler ()
+{};
+
+// Destructor.
+ACE_Read_Handler::~ACE_Read_Handler ()
+{};
+
+// Return the handle of the Dgram_Mcast. This method is
+// called internally by the reactor.
+
+ACE_HANDLE
+ACE_Read_Handler::get_handle (void) const
+{
+ return this->dgram_mcast_.get_handle ();
+}
+
+// Called when there is a READ activity on the dgram_mcast handle.
+int
+ACE_Read_Handler::handle_input (ACE_HANDLE)
+{
+ char buf[128];
+
+ const int iovcnt = 1;
+ iovec iov[iovcnt];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 128;
+
+ ACE_OS::memset (iov[0].iov_base, 0, 128);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Inside handle_input () of ACE_Read_Handler ()\n"));
+
+ // Receive message from multicast group.
+ ssize_t retcode =
+ this->dgram_mcast_.recv (iov, 1, this->remote_addr_);
+
+ if (retcode != -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Message Received %s",
+ iov[0].iov_base));
+
+ return 0;
+ }
+ else
+ return -1;
+}
+
+// Set for a dgram_mcast;
+void
+ACE_Read_Handler::dgram_mcast (const ACE_SOCK_Dgram_Mcast &dgram_mcast)
+{
+ this->dgram_mcast_ = dgram_mcast;
+}
diff --git a/examples/QOS/Read_Handler.h b/examples/QOS/Read_Handler.h
new file mode 100644
index 00000000000..7926b1b6630
--- /dev/null
+++ b/examples/QOS/Read_Handler.h
@@ -0,0 +1,51 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/tests/
+//
+// = FILENAME
+// Read_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo
+//
+// ============================================================================
+
+#ifndef READ_HANDLER_H
+#define READ_HANDLER_H
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/Event_Handler.h"
+#include "ace/Reactor.h"
+
+ACE_RCSID(Read_Handler, Read_Handler, "$Id$")
+
+ class ACE_Read_Handler : public ACE_Event_Handler
+ {
+ public:
+
+ ACE_Read_Handler (void);
+ ~ACE_Read_Handler (void);
+ // Initialization and Termination methods.
+
+ virtual int handle_input (ACE_HANDLE fd);
+ // Handles a READ event.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // Override this to return the handle of the Dgram_Mcast
+ // that we are using.
+
+ virtual void dgram_mcast (const ACE_SOCK_Dgram_Mcast &dgram_mcast);
+ // Set the dgram_mcast;
+
+ private:
+
+ ACE_SOCK_Dgram_Mcast dgram_mcast_;
+ ACE_INET_Addr remote_addr_;
+ };
+
+#endif /* READ_HANDLER_H */
diff --git a/examples/QOS/client.cpp b/examples/QOS/client.cpp
new file mode 100644
index 00000000000..642e670dd7c
--- /dev/null
+++ b/examples/QOS/client.cpp
@@ -0,0 +1,833 @@
+// $Id$
+
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/OS.h"
+
+#define QOSEVENT_MAIN
+#include "qosevent.h"
+
+static u_short SERVER_PORT = MY_DEFPORT;
+static const char *const SERVER_HOST = DEFAULT_MULTICASTGROUP;
+static const int MAX_ITERATIONS = 4;
+
+static BOOL ValidOptions(char *argv[], int argc, OPTIONS *pOptions);
+static VOID PrintOptions(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 values were
+// simply choosen from existing QOS templates available via WSAGetQosByName.
+// Notice that ProviderSpecific settings are being allowed when picking the
+// "default" template but not for "well-known" QOS templates. Also notice
+// that since data is only flowing from sender to receiver, different
+// flowspecs are filled in depending upon whether this application is
+// acting as a sender or receiver.
+//
+static VOID FillQosFlowspecDefault(
+ QOS *pQos,
+ DWORD *cbQosLen,
+ QOS_OPTIONS *pQosOptions
+ )
+{
+ if (pQosOptions->bReceiver)
+ {
+ pQos->ReceivingFlowspec = default_g711;
+ pQos->SendingFlowspec = default_notraffic;
+ }
+ else
+ {
+ pQos->SendingFlowspec = default_g711;
+ pQos->ReceivingFlowspec = default_notraffic;
+ }
+
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Enabling the QOS Signalling for the sender. \n"));
+
+ // Enable the QOS signalling.
+ pQos->SendingFlowspec.ServiceType &= ~(SERVICE_NO_QOS_SIGNALING);
+
+ pQos->ProviderSpecific.len = 0;
+ pQos->ProviderSpecific.buf = NULL;
+ *cbQosLen = sizeof(QOS) + pQos->ProviderSpecific.len;
+
+ return;
+}
+
+
+static VOID
+fill_ace_qos_flowspec_default (ACE_QoS *pQos,
+ DWORD *cbQosLen,
+ QOS_OPTIONS *pQosOptions)
+{
+ ACE_Flow_Spec ace_default_g711 (
+ 9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ 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 (QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ SERVICETYPE_NOTRAFFIC,
+ QOS_NOT_SPECIFIED,
+ 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, NULL};
+
+ pQos->provider_specific (iov);
+ *cbQosLen = sizeof(QOS) + pQos->provider_specific ().iov_len;
+
+ return;
+}
+
+BOOL SetQos(
+ ACE_HANDLE sd,
+ QOS_OPTIONS *pQosOptions,
+ BOOL bSetQos,
+ ACE_QoS *pQos,
+ DWORD *cbQosLen
+ )
+{
+
+ BOOL bError = FALSE;
+
+ // fill in default values
+ if (stricmp(pQosOptions->szTemplate, QOS_DEFAULTNAME) == 0)
+ {
+ fill_ace_qos_flowspec_default(pQos, cbQosLen, pQosOptions);
+ }
+ else
+ {
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Run the program with -q:default option\n"));
+ }
+
+ return(!bError);
+}
+
+int
+FillQoSTraffic (ACE_Flow_Spec &afc)
+{
+ afc.token_rate (default_g711.TokenRate); /* In Bytes/sec */
+ afc.token_bucket_size (default_g711.TokenBucketSize); /* In Bytes */
+ afc.peak_bandwidth (default_g711.PeakBandwidth); /* In Bytes/sec */
+ afc.latency (default_g711.Latency); /* In microseconds */
+ afc.delay_variation (default_g711.DelayVariation); /* In microseconds */
+ afc.service_type (default_g711.ServiceType);
+ afc.max_sdu_size (default_g711.MaxSduSize); /* In Bytes */
+ afc.minimum_policed_size (default_g711.MinimumPolicedSize); /* In Bytes */
+
+ return 0;
+}
+
+int
+FillQoSNoTraffic (ACE_Flow_Spec &afc)
+{
+ afc.token_rate (default_notraffic.TokenRate); /* In Bytes/sec */
+ afc.token_bucket_size (default_notraffic.TokenBucketSize); /* In Bytes */
+ afc.peak_bandwidth (default_notraffic.PeakBandwidth); /* In Bytes/sec */
+ afc.latency (default_notraffic.Latency); /* In microseconds */
+ afc.delay_variation (default_notraffic.DelayVariation); /* In microseconds */
+ afc.service_type (default_notraffic.ServiceType);
+ afc.max_sdu_size (default_notraffic.MaxSduSize); /* In Bytes */
+ afc.minimum_policed_size (default_notraffic.MinimumPolicedSize); /* In Bytes */
+
+ return 0;
+}
+
+int
+FillQoSParams (ACE_QoS_Params &qos_params,
+ iovec* iov,
+ ACE_QoS* qos)
+{
+ //qos_params.callee_data (iov);
+ qos_params.callee_data (NULL);
+ qos_params.caller_data (NULL);
+ qos_params.socket_qos (qos);
+ qos_params.group_socket_qos (NULL);
+ qos_params.flags (JL_SENDER_ONLY);
+
+ return 0;
+}
+
+int
+main (int argc, char * argv[])
+{
+ WSADATA WSAData;
+ ACE_Protocol_Info protocol_info;
+
+ OPTIONS options;
+ if (!ValidOptions(argv, argc, &options))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in ValidOptions\n"),
+ -1);
+ }
+
+ if (WSAStartup ( MAKEWORD(2,2), &WSAData) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in WSAStartup\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);
+
+#define MAXCLIENTS 4
+
+ // encapsulate socket, events, buffers, and various flags and counters that
+ // control how/when data is received into a structure
+ typedef struct _RECV_INFO
+ {
+ ACE_HANDLE sd[MAXCLIENTS+1];
+ WSAEVENT hEvents[MAXCLIENTS+1];
+ CHAR * recvbuf;
+ int nTotalClients;
+ } RECV_INFO;
+
+ RECV_INFO RecvInfo;
+
+ printf("Sender\n");
+
+ // initialize data structures
+ for (int i=0; i<MAXCLIENTS+1; i++)
+ RecvInfo.sd[i] = ACE_INVALID_HANDLE;
+
+ ACE_QoS qos;
+ QOS *pQos;
+ DWORD cbQosLen;
+
+ pQos = NULL;
+ if (options.spOptions.bQos)
+ {
+ if (QOS_IOCTL_SET_BEFORE == options.qosOptions.qosIoctlSet)
+ {
+ if (SetQos(RecvInfo.sd[0], &options.qosOptions, TRUE, &qos, &cbQosLen))
+ printf(" QOS set before accept\n");
+ pQos = NULL;
+ }
+ else if (QOS_IOCTL_SET_QOS == options.qosOptions.qosIoctlSet)
+ {
+ // this one is tricky. The intent is to send the RESV after
+ // receiving FD_QOS notification. However, unless we somehow
+ // inform the GQOSSP that we are interested in QOS, it will not
+ // send us FD_QOS when receiving a RESV. However, we do not want to
+ // send out a RESV until we explicitedly set QOS. We therefore do not
+ // want QOS signalling (i.e. RSVP messages) to be sent.
+ options.qosOptions.bDisableSignalling = TRUE;
+ if (SetQos(RecvInfo.sd[0], &options.qosOptions, TRUE, &qos, &cbQosLen))
+ {
+ printf(" QOS set qos before accept - will be set again in FD_QOS\n");
+ pQos = &qos;
+ }
+ else
+ pQos = NULL;
+ }
+ }
+ else
+ pQos = NULL;
+
+ // Opeing a new Multicast Datagram with the QoS socket opened previously.
+
+ ACE_SOCK_Dgram_Mcast dgram_mcast;
+
+ SOCKADDR_IN addr;
+
+ ZeroMemory((PVOID)&addr, sizeof(addr));
+ addr.sin_family = PF_INET; //protocol_info.iAddressFamily;
+ addr.sin_addr.s_addr = inet_addr("234.5.6.7"); //options.szHostname);
+
+ // PORT changed as opposed to the receiver.
+ addr.sin_port = htons(5002); //options.port);
+
+ ACE_INET_Addr mult_addr (&addr, sizeof (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, NULL, &qos);
+
+ // Join the multicast group if specfied. We may also specify a given QOS structure
+ // at this time.
+
+ if (dgram_mcast.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ PF_INET,
+ FROM_PROTOCOL_INFO,
+ &protocol_info,
+ 0,
+ WSA_FLAG_OVERLAPPED | WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF
+ ) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in subscribe\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ DWORD dwBytes;
+
+ // Set IP TTL
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ 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.
+ NULL, // Overlapped.
+ NULL) == SOCKET_ERROR) // 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"));
+
+ BOOL bFlag = FALSE;
+
+ // Disable LoopBack.
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ 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.
+ NULL, // Overlapped.
+ NULL) == SOCKET_ERROR) // 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"));
+
+
+ // Enable QoS on the already opened QoS enabled socket.
+
+ QOS win_qos;
+ FillQosFlowspecDefault (&win_qos, &cbQosLen, &options.qosOptions);
+
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ SIO_SET_QOS, // IO control code.
+ (LPVOID) &win_qos, // In buffer.
+ cbQosLen, // Length of in buffer.
+ NULL,
+ 0,
+ &dwBytes, // bytes returned.
+ NULL, // Overlapped.
+ NULL) == SOCKET_ERROR) // Func.
+ 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"));
+
+ WSAEVENT hevent = WSACreateEvent ();
+ ACE_OVERLAPPED ace_overlapped;
+ ace_overlapped.hEvent = hevent;
+
+ SOCKADDR_IN sendto_addr;
+ ZeroMemory((PVOID)&sendto_addr, sizeof(sendto_addr));
+ sendto_addr.sin_family = PF_INET; // protocol_info.iAddressFamily;
+ sendto_addr.sin_addr.s_addr = inet_addr("234.5.6.7"); // options.szHostname);
+ sendto_addr.sin_port = htons(5001); // options.port);
+
+ const SOCKADDR_IN c_sendto_addr = sendto_addr;
+
+ const iovec iov = {5,"Hello"};
+ size_t bytes_sent;
+
+ if (ACE_OS::sendto (dgram_mcast.get_handle (),
+ &iov,
+ 1,
+ bytes_sent,
+ 0,
+ (const struct sockaddr *) &c_sendto_addr,
+ sizeof (c_sendto_addr),
+ &ace_overlapped,
+ NULL) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in Sendto\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "SendTO : Bytes sent : %d",
+ bytes_sent));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down Sender\n"));
+ return 0;
+}
+
+
+BOOL FindServiceProvider(
+ int iProtocol,
+ BOOL bQos,
+ BOOL bMulticast,
+ ACE_Protocol_Info *pProtocolInfo
+ )
+{
+ int nRet;
+ ACE_Protocol_Info *lpProtocolBuf = NULL;
+ DWORD dwBufLen = 0;
+ DWORD dwErr;
+ BOOL bProtocolFound = FALSE;
+
+
+ // first have WSAEnumProtocols tell us how big a buffer is needed
+ nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
+ if (SOCKET_ERROR != nRet)
+ {
+ printf("WSAEnumProtocols: should not have suceeded\n");
+ }
+ else if (WSAENOBUFS != (dwErr = WSAGetLastError()))
+ {
+ // WSAEnumProtocols failed for some reason not relating to buffer size
+ printf("WSAEnumProtocols(1): %d\n", WSAGetLastError());
+ }
+ else
+ {
+ // WSAEnumProtocols failed for the "expected" reason, allocate a buffer
+ // of the needed size
+ lpProtocolBuf = (ACE_Protocol_Info *)malloc(dwBufLen);
+ if (lpProtocolBuf)
+ {
+ // now we can call WSAEnumProtocols again with the expectation it will
+ // succeed because we have allocated a big enough buffer.
+ nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
+ if (SOCKET_ERROR == nRet)
+ {
+ printf("WSAEnumProtocols(3): %d\n", WSAGetLastError());
+ }
+ else
+ {
+ // loop thru protocols, looking for a matching service provider
+ for (int i=0; i<nRet; i++)
+ {
+ printf(" sp <%s>\n", lpProtocolBuf[i].szProtocol);
+ if (AF_INET == lpProtocolBuf[i].iAddressFamily &&
+ iProtocol == lpProtocolBuf[i].iProtocol)
+ {
+ // look for
+ if (bQos && bMulticast)
+ {
+ if ((XP1_QOS_SUPPORTED == (XP1_QOS_SUPPORTED &
+ lpProtocolBuf[i].dwServiceFlags1)) &&
+ (XP1_SUPPORT_MULTIPOINT == (XP1_SUPPORT_MULTIPOINT & lpProtocolBuf[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = lpProtocolBuf[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else if (bQos)
+ {
+ if ((XP1_QOS_SUPPORTED == (XP1_QOS_SUPPORTED &
+ lpProtocolBuf[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = lpProtocolBuf[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else if (bMulticast)
+ {
+ if ((XP1_SUPPORT_MULTIPOINT == (XP1_SUPPORT_MULTIPOINT &
+ lpProtocolBuf[i].dwServiceFlags1)) &&
+ (XP1_QOS_SUPPORTED != (XP1_QOS_SUPPORTED &
+ lpProtocolBuf[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = lpProtocolBuf[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ if ((XP1_QOS_SUPPORTED != (XP1_QOS_SUPPORTED &
+ lpProtocolBuf[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = lpProtocolBuf[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ }
+ } // for
+ } // WSAEnumProtocols
+ free(lpProtocolBuf);
+ } // lpProtocolBuf
+ } // WSAEnumProtocols
+
+ if (bProtocolFound)
+ printf(" Using service provider <%s>\n\n", pProtocolInfo->szProtocol);
+
+ return(bProtocolFound);
+}
+
+
+BOOL ValidOptions(char *argv[], int argc, OPTIONS *pOptions)
+{
+ BOOL bValidOptions = TRUE;
+ OSVERSIONINFO verInfo = {0};
+
+ *pOptions = default_options;
+
+ for (int i=1; i<argc; i++)
+ {
+ if ((argv[i][0] == '-') || (argv[i][0] == '/') )
+ {
+ switch(tolower(argv[i][1]))
+ {
+ case 'b' :
+ if (strlen(argv[i]) > 3)
+ pOptions->nBufSize = 1024*atoi(&argv[i][3]);
+ break;
+
+ case 'c' :
+ pOptions->qosOptions.bAlternateQos = TRUE;
+ break;
+
+ case 'd' :
+ if (strlen(argv[i]) > 3)
+ pOptions->fillchar = argv[i][3];
+ break;
+
+ case 'e' :
+ if (strlen(argv[i]) > 3)
+ pOptions->port = atoi(&argv[i][3]);
+ break;
+
+ case 'i' :
+ if (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 (strlen(argv[i]) > 3)
+ pOptions->nRepeat = atoi(&argv[i][3]);
+ break;
+
+ case 'm' :
+ pOptions->spOptions.bMulticast = TRUE;
+ if (strlen(argv[i]) > 3)
+ strcpy(pOptions->szHostname, &argv[i][3]);
+ else
+ strcpy(pOptions->szHostname, DEFAULT_MULTICASTGROUP);
+ break;
+
+ case 'n' :
+ pOptions->qosOptions.bReceiver = FALSE;
+ // multicast group overrides hostname on -n
+ if (!pOptions->spOptions.bMulticast)
+ {
+ if (strlen(argv[i]) > 3)
+ strcpy(pOptions->szHostname, &argv[i][3]);
+ }
+ break;
+
+ case 'p' :
+ if (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 (strlen(argv[i]) > 3)
+ strcpy(pOptions->qosOptions.szTemplate, &argv[i][3]);
+ break;
+
+ case 'r' :
+ if (strlen(argv[i]) > 3)
+ {
+ if ((stricmp(argv[i], "-rsvp-confirm") == 0) ||
+ (stricmp(argv[i], "-rsvp_confirm") == 0))
+ {
+ pOptions->qosOptions.bConfirmResv = TRUE;
+ pOptions->qosOptions.bProviderSpecific = TRUE;
+ }
+ else if ((stricmp(argv[i], "-rsvp-wait") == 0) ||
+ (stricmp(argv[i], "-rsvp_wait") == 0))
+ {
+ pOptions->qosOptions.bWaitToSend = TRUE;
+ pOptions->qosOptions.bProviderSpecific = TRUE;
+ }
+ else
+ {
+ printf("Ignoring option <%s>\n", argv[i]);
+ }
+ }
+ break;
+
+ case 's' :
+ if (strlen(argv[i]) > 3)
+ pOptions->dwSleep = atoi(&argv[i][3]);
+ break;
+
+ case '?' :
+ Usage(argv[0], &default_options);
+ return(FALSE);
+ break;
+
+ default:
+ printf(" unknown options flag %s\n", argv[i]);
+ Usage(argv[0], &default_options);
+ return(FALSE);
+ break;
+ }
+ }
+ else
+ {
+ printf(" 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)
+ pOptions->nRepeat = 0; // override repeat count to continuous mode
+
+ 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;
+ }
+
+ verInfo.dwOSVersionInfoSize = sizeof(verInfo);
+ GetVersionEx(&verInfo);
+ switch (verInfo.dwPlatformId)
+ {
+ case VER_PLATFORM_WIN32_NT:
+ pOptions->qosOptions.bQueryBufferSize = TRUE;
+ pOptions->qosOptions.bMustSetQosInAccept = FALSE;
+ if (verInfo.dwBuildNumber >= 1960)
+ {
+ printf("new build\n");
+ pOptions->qosOptions.bFineGrainErrorAvail = TRUE;
+ pOptions->qosOptions.bQosabilityIoctls = TRUE;
+ }
+ else
+ {
+ pOptions->qosOptions.bFineGrainErrorAvail = FALSE;
+ pOptions->qosOptions.bQosabilityIoctls = FALSE;
+ }
+ printf("running on NT\n");
+ break;
+
+ case VER_PLATFORM_WIN32_WINDOWS:
+ pOptions->qosOptions.bQueryBufferSize = FALSE;
+ pOptions->qosOptions.bMustSetQosInAccept = TRUE;
+ pOptions->qosOptions.bFineGrainErrorAvail = FALSE;
+ pOptions->qosOptions.bQosabilityIoctls = FALSE;
+ printf("running on 9x\n");
+ break;
+
+ default:
+ printf ("requires Windows NT or Windows 98\n");
+ pOptions->qosOptions.bQueryBufferSize = FALSE;
+ pOptions->qosOptions.bMustSetQosInAccept = TRUE;
+ pOptions->qosOptions.bFineGrainErrorAvail = FALSE;
+ pOptions->qosOptions.bQosabilityIoctls = FALSE;
+ break;
+ }
+ }
+
+ if (!(pOptions->buf = (char *)malloc(pOptions->nBufSize)))
+ return(FALSE);
+ else
+ {
+ FillMemory(pOptions->buf, pOptions->nBufSize, pOptions->fillchar);
+ return(TRUE);
+ }
+}
+
+
+static VOID PrintOptions(OPTIONS *pOptions)
+{
+ printf("Options\n");
+ printf(" Protocol %d\n", pOptions->spOptions.iProtocol);
+ printf(" Port %d\n", pOptions->port);
+ if (pOptions->qosOptions.bReceiver)
+ printf(" Act as Receiver\n");
+ else
+ {
+ printf(" Act as sender and send to %s\n", pOptions->szHostname);
+ printf(" Sleep %d milliseconds between sends\n", pOptions->dwSleep);
+ printf(" Fill buffer with <%c>\n", pOptions->fillchar);
+ if (pOptions->nRepeat)
+ printf(" Repeat sending the buffer %d times\n", pOptions->nRepeat);
+ else
+ printf(" Repeat sending the buffer continually\n");
+
+ }
+ printf(" Bufsize %d (1K increments)\n", pOptions->nBufSize);
+ printf(" Multicast is %s\n", (pOptions->spOptions.bMulticast ? "Enabled" : "Disabled"));
+
+ if (pOptions->spOptions.bQos)
+ {
+ printf(" Qos template %s\n", pOptions->qosOptions.szTemplate);
+ printf(" Qos to be set ");
+ switch (pOptions->qosOptions.qosIoctlSet)
+ {
+ case QOS_IOCTL_SET_BEFORE:
+ printf("Before accept/connect/joinleaf\n");
+ break;
+ case QOS_IOCTL_SET_AFTER:
+ printf("After accept/connect/joinleaf\n");
+ break;
+ case QOS_IOCTL_SET_DURING:
+ printf("During accept/connect/joinleaf\n");
+ break;
+ case QOS_IOCTL_SET_QOS:
+ if (pOptions->qosOptions.bReceiver)
+ printf("During FD_QOS, implies QOS with no signaling set before accept/connect (eventually)\n");
+ else
+ {
+ pOptions->qosOptions.qosIoctlSet = QOS_IOCTL_SET_BEFORE;
+ printf("Before connect\n");
+ }
+ break;
+ }
+
+ if (pOptions->qosOptions.bConfirmResv )
+ printf(" RESV confirmation to be requested\n");
+ if (INVALID_SEND_PRIORITY != pOptions->qosOptions.SendPriority)
+ printf(" Qos TC SendPriority to be set to %d\n",
+ pOptions->qosOptions.SendPriority);
+ if (!pOptions->qosOptions.bReceiver)
+ {
+ if (pOptions->qosOptions.bWaitToSend)
+ printf(" Wait for RESV before sending data\n");
+ else
+ printf(" Do not wait for RESV to start sending data\n");
+ }
+ else
+ printf(" Qos must be set during Accept = %s\n",
+ (pOptions->qosOptions.bMustSetQosInAccept?"TRUE":"FALSE"));
+
+ printf(" Query for QOS buffer size: %s\n",
+ (pOptions->qosOptions.bQueryBufferSize?"TRUE":"FALSE"));
+ }
+ printf("\n");
+ return;
+}
+
+// Abstract:
+// Print out usage table for the program
+//
+VOID Usage(CHAR *szProgramname, OPTIONS *pOptions)
+{
+ printf("usage:\n %s -?\n\n", szProgramname);
+ printf(" %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",
+ szProgramname);
+ printf(" -?\t\tDisplay this help\n");
+ printf("\n");
+ printf(" -b:bufsize\tSize of send/recv buffer; in 1K increments (Def:%d)\n",
+ pOptions->nBufSize);
+ printf(" -d:c\t\tCharacter used to fill buffer (Def:%c)\n",
+ pOptions->fillchar);
+ printf(" -e:port\tEndpoint number (port) to use (Def:%d)\n",
+ pOptions->port);
+ printf(" -l:loop\tLoop count for sending buffer (0==>continuous)\n",
+ pOptions->nRepeat);
+ printf(" -m:group\tMulticast group (IP) to join (Def:%s)\n",
+ DEFAULT_MULTICASTGROUP);
+ printf(" -n:host\tAct as the client and connect to 'host' (Def:%s)\n",
+ pOptions->szHostname);
+ printf(" -p:protocol\tTCP or UDP (def:TCP)\n");
+ printf(" -s:#\t\tSleep # milliseconds between sends (def: 0)\n");
+ printf("\n");
+ printf(" -q:template\tEnable QoS and use 'template' to specify the name (Def:%s)\n",
+ pOptions->qosOptions.szTemplate);
+ printf(" -c\t\tCycle enabling/disabling QOS on sending socket (Def: no cycling)\n");
+ printf(" -i:[a|b|d|q]\tSet Qos After, Before, During accept/connect, or during FD_QOS\n\t\t\t(def: Before)\n");
+ printf(" -rsvp-confirm\t\tRequest RESV confirmation be sent (Def: no confirmation)\n");
+ printf(" -rsvp-wait\t\tWait for RESV from receiver before sending data\n");
+ return;
+}
diff --git a/examples/QOS/client.dsp b/examples/QOS/client.dsp
new file mode 100644
index 00000000000..3dd2924bf4f
--- /dev/null
+++ b/examples/QOS/client.dsp
@@ -0,0 +1,105 @@
+# Microsoft Developer Studio Project File - Name="003" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=003 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "client.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "client.mak" CFG="003 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "003 - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "003 - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "003 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
+
+!ELSEIF "$(CFG)" == "003 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Od /I "d:\vishal\ACE_wrappers" /D "WIN32" /D "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 d:\vishal\ACE_wrappers\ace\aced.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"client.exe" /pdbtype:sept /libpath:"d:\vishal\ACE_wrappers\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "003 - Win32 Release"
+# Name "003 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\client.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\QosEvent.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/examples/QOS/server.cpp b/examples/QOS/server.cpp
new file mode 100644
index 00000000000..5de2a42b1f5
--- /dev/null
+++ b/examples/QOS/server.cpp
@@ -0,0 +1,845 @@
+// $Id$
+
+#define QOSEVENT_MAIN
+
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/OS.h"
+
+#include "qosevent.h"
+#include "QOS_Event_Handler.h"
+#include "Read_Handler.h"
+
+static BOOL ValidOptions(char *argv[], int argc, OPTIONS *pOptions);
+static VOID PrintOptions(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 values were
+// simply choosen from existing QOS templates available via WSAGetQosByName.
+// Notice that ProviderSpecific settings are being allowed when picking the
+// "default" template but not for "well-known" QOS templates. Also notice
+// that since data is only flowing from sender to receiver, different
+// flowspecs are filled in depending upon whether this application is
+// acting as a sender or receiver.
+//
+static VOID FillQosFlowspecDefault(
+ QOS *pQos,
+ DWORD *cbQosLen,
+ QOS_OPTIONS *pQosOptions
+ )
+{
+ if (pQosOptions->bReceiver)
+ {
+ pQos->ReceivingFlowspec = default_g711;
+ pQos->SendingFlowspec = default_notraffic;
+ }
+ else
+ {
+ pQos->SendingFlowspec = default_g711;
+ pQos->ReceivingFlowspec = default_notraffic;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Enabling the QOS Signalling for the receiver.\n"));
+
+ // Enable the QOS signalling.
+ pQos->ReceivingFlowspec.ServiceType &= ~(SERVICE_NO_QOS_SIGNALING);
+
+ pQos->ProviderSpecific.len = 0;
+ pQos->ProviderSpecific.buf = NULL;
+ *cbQosLen = sizeof(QOS) + pQos->ProviderSpecific.len;
+
+ return;
+}
+
+
+static VOID
+fill_ace_qos_flowspec_default (ACE_QoS *pQos,
+ DWORD *cbQosLen,
+ QOS_OPTIONS *pQosOptions)
+{
+ ACE_Flow_Spec ace_default_g711 (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ 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 (QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ QOS_NOT_SPECIFIED,
+ SERVICETYPE_NOTRAFFIC,
+ QOS_NOT_SPECIFIED,
+ 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, NULL};
+
+ pQos->provider_specific (iov);
+ *cbQosLen = sizeof(QOS) + pQos->provider_specific ().iov_len;
+
+ return;
+}
+
+BOOL SetQos(
+ ACE_HANDLE sd,
+ QOS_OPTIONS *pQosOptions,
+ BOOL bSetQos,
+ ACE_QoS *pQos,
+ DWORD *cbQosLen
+ )
+{
+
+ BOOL bError = FALSE;
+
+ // fill in default values
+ if (stricmp(pQosOptions->szTemplate, QOS_DEFAULTNAME) == 0)
+ {
+ fill_ace_qos_flowspec_default(pQos, cbQosLen, pQosOptions);
+ }
+ else
+ {
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Run the program with -q:default option\n"));
+ }
+
+ return(!bError);
+}
+
+// This function is not used. Right now the ACE_Flow_Spec is constructed
+// with hardcoded values. Once the test works, it will be a good idea to replace
+// the hardcoded values with this function.
+
+int
+FillQoSTraffic (ACE_Flow_Spec &afc)
+{
+ afc.token_rate (default_g711.TokenRate); /* In Bytes/sec */
+ afc.token_bucket_size (default_g711.TokenBucketSize); /* In Bytes */
+ afc.peak_bandwidth (default_g711.PeakBandwidth); /* In Bytes/sec */
+ afc.latency (default_g711.Latency); /* In microseconds */
+ afc.delay_variation (default_g711.DelayVariation); /* In microseconds */
+ afc.service_type (default_g711.ServiceType);
+ afc.max_sdu_size (default_g711.MaxSduSize); /* In Bytes */
+ afc.minimum_policed_size (default_g711.MinimumPolicedSize); /* In Bytes */
+
+ return 0;
+}
+
+// This function is not used. Right now the ACE_Flow_Spec is constructed
+// with hardcoded values. Once the test works, it will be a good idea to replace
+// the hardcoded values with this function.
+
+int
+FillQoSNoTraffic (ACE_Flow_Spec &afc)
+{
+ afc.token_rate (default_notraffic.TokenRate); /* In Bytes/sec */
+ afc.token_bucket_size (default_notraffic.TokenBucketSize); /* In Bytes */
+ afc.peak_bandwidth (default_notraffic.PeakBandwidth); /* In Bytes/sec */
+ afc.latency (default_notraffic.Latency); /* In microseconds */
+ afc.delay_variation (default_notraffic.DelayVariation); /* In microseconds */
+ afc.service_type (default_notraffic.ServiceType);
+ afc.max_sdu_size (default_notraffic.MaxSduSize); /* In Bytes */
+ afc.minimum_policed_size (default_notraffic.MinimumPolicedSize); /* In Bytes */
+
+ return 0;
+}
+
+// This function fills up the ACE_QoS_Params with the values as in the
+// windows test.
+int
+FillQoSParams (ACE_QoS_Params &qos_params,
+ iovec* iov,
+ ACE_QoS* qos)
+{
+ //qos_params.callee_data (iov);
+ qos_params.callee_data (NULL);
+ qos_params.caller_data (NULL);
+ qos_params.socket_qos (qos);
+ qos_params.group_socket_qos (NULL);
+ qos_params.flags (JL_BOTH);
+
+ return 0;
+}
+
+
+int
+main (int argc, char * argv[])
+{
+ WSADATA WSAData;
+ ACE_Protocol_Info protocol_info;
+
+ OPTIONS options;
+ if (!ValidOptions(argv, argc, &options))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in ValidOptions\n"),
+ -1);
+ }
+
+ if (WSAStartup ( MAKEWORD(2,2), &WSAData) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in WSAStartup\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);
+
+#define MAXCLIENTS 4
+
+ typedef struct _RECV_INFO
+ {
+ ACE_HANDLE sd[MAXCLIENTS+1];
+ WSAEVENT hEvents[MAXCLIENTS+1];
+ CHAR * recvbuf;
+ int nTotalClients;
+ } RECV_INFO;
+
+ RECV_INFO RecvInfo;
+
+ printf("Receiver\n");
+
+ for (int i=0; i<MAXCLIENTS+1; i++)
+ RecvInfo.sd[i] = ACE_INVALID_HANDLE;
+
+ ACE_QoS qos;
+ QOS *pQos;
+ DWORD cbQosLen;
+
+ // By default the QOS is set as QOS_IOCTL_SET_BEFORE. I do not
+ // override this option in the commandline parameters. Is that
+ // the right thing to do.
+
+ pQos = NULL;
+ if (options.spOptions.bQos)
+ {
+ if (QOS_IOCTL_SET_BEFORE == options.qosOptions.qosIoctlSet)
+ {
+ if (SetQos(RecvInfo.sd[0], &options.qosOptions, TRUE, &qos, &cbQosLen))
+ printf(" QOS set before accept\n");
+ pQos = NULL;
+ }
+ else if (QOS_IOCTL_SET_QOS == options.qosOptions.qosIoctlSet)
+ {
+
+ // The following was the original comment in the windows code. But
+ // this does not fall in my path of execution.
+
+ // "this one is tricky. The intent is to send the RESV after
+ // receiving FD_QOS notification. However, unless we somehow
+ // inform the GQOSSP that we are interested in QOS, it will not
+ // send us FD_QOS when receiving a RESV. However, we do not want to
+ // send out a RESV until we explicitedly set QOS. We therefore do not
+ // want QOS signalling (i.e. RSVP messages) to be sent."
+
+ options.qosOptions.bDisableSignalling = TRUE;
+ if (SetQos(RecvInfo.sd[0], &options.qosOptions, TRUE, &qos, &cbQosLen))
+ {
+ printf(" QOS set qos before accept - will be set again in FD_QOS\n");
+ pQos = &qos;
+ }
+ else
+ pQos = NULL;
+ }
+ }
+ else
+ pQos = NULL;
+
+ // Opeing a new Multicast Datagram with the QoS socket opened previously.
+
+ ACE_SOCK_Dgram_Mcast dgram_mcast;
+
+ SOCKADDR_IN addr;
+
+ ZeroMemory((PVOID)&addr, sizeof(addr));
+ addr.sin_family = PF_INET; //protocol_info.iAddressFamily;
+ addr.sin_addr.s_addr = inet_addr("234.5.6.7"); //options.szHostname);
+ addr.sin_port = htons(5001); //options.port);
+
+ ACE_INET_Addr mult_addr (&addr, sizeof (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, NULL, &qos);
+
+ // The following call opens the Dgram_Mcast and calls the join_leaf ()
+ // with the qos_params supplied here.
+
+ if (dgram_mcast.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ PF_INET,
+ FROM_PROTOCOL_INFO,
+ &protocol_info,
+ 0,
+ WSA_FLAG_OVERLAPPED | WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF
+ ) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in subscribe\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ DWORD dwBytes;
+
+ // Set IP TTL
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ 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.
+ NULL, // Overlapped.
+ NULL) == SOCKET_ERROR) // 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"));
+
+ BOOL bFlag = FALSE;
+
+ // Disable LoopBack.
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ 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.
+ NULL, // Overlapped.
+ NULL) == SOCKET_ERROR) // 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"));
+
+
+ // Fill up a Windows QOS to be passed to ACE_OS::ioctl () later.
+ QOS win_qos;
+ FillQosFlowspecDefault (&win_qos, &cbQosLen, &options.qosOptions);
+
+ // Set the QOS for the socket.
+ if (ACE_OS::ioctl (dgram_mcast.get_handle (), // Socket.
+ SIO_SET_QOS, // IO control code.
+ (LPVOID) &win_qos, // In buffer.
+ cbQosLen, // Length of in buffer.
+ NULL,
+ 0,
+ &dwBytes, // bytes returned.
+ NULL, // Overlapped.
+ NULL) == SOCKET_ERROR) // Func.
+ 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"));
+
+ // 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.
+ 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);
+
+ /*
+ ACE_Read_Handler qos_read_handler;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "REgistering the Read Handler\n"));
+
+ qos_read_handler.dgram_mcast (dgram_mcast);
+
+ if (ACE_Reactor::instance ()->register_handler (&qos_read_handler,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering Read Handler\n"),
+ -1);
+ */
+
+ // Start the event loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "Running the Event Loop ... \n"));
+
+ ACE_Reactor::instance ()->run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down server logging daemon\n"));
+ return 0;
+}
+
+
+
+BOOL FindServiceProvider(
+ int iProtocol,
+ BOOL bQos,
+ BOOL bMulticast,
+ ACE_Protocol_Info *pProtocolInfo
+ )
+{
+ int nRet;
+ ACE_Protocol_Info *lpProtocolBuf = NULL;
+ DWORD dwBufLen = 0;
+ DWORD dwErr;
+ BOOL bProtocolFound = FALSE;
+
+
+ // first have WSAEnumProtocols tell us how big a buffer is needed
+ nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
+ if (SOCKET_ERROR != nRet)
+ {
+ printf("WSAEnumProtocols: should not have suceeded\n");
+ }
+ else if (WSAENOBUFS != (dwErr = WSAGetLastError()))
+ {
+ // WSAEnumProtocols failed for some reason not relating to buffer size
+ printf("WSAEnumProtocols(1): %d\n", WSAGetLastError());
+ }
+ else
+ {
+ // WSAEnumProtocols failed for the "expected" reason, allocate a buffer
+ // of the needed size
+ lpProtocolBuf = (ACE_Protocol_Info *)malloc(dwBufLen);
+ if (lpProtocolBuf)
+ {
+ // now we can call WSAEnumProtocols again with the expectation it will
+ // succeed because we have allocated a big enough buffer.
+ nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
+ if (SOCKET_ERROR == nRet)
+ {
+ printf("WSAEnumProtocols(3): %d\n", WSAGetLastError());
+ }
+ else
+ {
+ // loop thru protocols, looking for a matching service provider
+ for (int i=0; i<nRet; i++)
+ {
+ printf(" sp <%s>\n", lpProtocolBuf[i].szProtocol);
+ if (AF_INET == lpProtocolBuf[i].iAddressFamily &&
+ iProtocol == lpProtocolBuf[i].iProtocol)
+ {
+ // look for
+ if (bQos && bMulticast)
+ {
+ if ((XP1_QOS_SUPPORTED == (XP1_QOS_SUPPORTED &
+ lpProtocolBuf[i].dwServiceFlags1)) &&
+ (XP1_SUPPORT_MULTIPOINT == (XP1_SUPPORT_MULTIPOINT & lpProtocolBuf[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = lpProtocolBuf[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else if (bQos)
+ {
+ if ((XP1_QOS_SUPPORTED == (XP1_QOS_SUPPORTED &
+ lpProtocolBuf[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = lpProtocolBuf[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else if (bMulticast)
+ {
+ if ((XP1_SUPPORT_MULTIPOINT == (XP1_SUPPORT_MULTIPOINT &
+ lpProtocolBuf[i].dwServiceFlags1)) &&
+ (XP1_QOS_SUPPORTED != (XP1_QOS_SUPPORTED &
+ lpProtocolBuf[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = lpProtocolBuf[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ if ((XP1_QOS_SUPPORTED != (XP1_QOS_SUPPORTED &
+ lpProtocolBuf[i].dwServiceFlags1)))
+ {
+ *pProtocolInfo = lpProtocolBuf[i];
+ bProtocolFound = TRUE;
+ break;
+ }
+ }
+ }
+ } // for
+ } // WSAEnumProtocols
+ free(lpProtocolBuf);
+ } // lpProtocolBuf
+ } // WSAEnumProtocols
+
+ if (bProtocolFound)
+ printf(" Using service provider <%s>\n\n", pProtocolInfo->szProtocol);
+
+ return(bProtocolFound);
+}
+
+
+BOOL ValidOptions(char *argv[], int argc, OPTIONS *pOptions)
+{
+ BOOL bValidOptions = TRUE;
+ OSVERSIONINFO verInfo = {0};
+
+ *pOptions = default_options;
+
+ for (int i=1; i<argc; i++)
+ {
+ if ((argv[i][0] == '-') || (argv[i][0] == '/') )
+ {
+ switch(tolower(argv[i][1]))
+ {
+ case 'b' :
+ if (strlen(argv[i]) > 3)
+ pOptions->nBufSize = 1024*atoi(&argv[i][3]);
+ break;
+
+ case 'c' :
+ pOptions->qosOptions.bAlternateQos = TRUE;
+ break;
+
+ case 'd' :
+ if (strlen(argv[i]) > 3)
+ pOptions->fillchar = argv[i][3];
+ break;
+
+ case 'e' :
+ if (strlen(argv[i]) > 3)
+ pOptions->port = atoi(&argv[i][3]);
+ break;
+
+ case 'i' :
+ if (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 (strlen(argv[i]) > 3)
+ pOptions->nRepeat = atoi(&argv[i][3]);
+ break;
+
+ case 'm' :
+ pOptions->spOptions.bMulticast = TRUE;
+ if (strlen(argv[i]) > 3)
+ strcpy(pOptions->szHostname, &argv[i][3]);
+ else
+ strcpy(pOptions->szHostname, DEFAULT_MULTICASTGROUP);
+ break;
+
+ case 'n' :
+ pOptions->qosOptions.bReceiver = FALSE;
+ // multicast group overrides hostname on -n
+ if (!pOptions->spOptions.bMulticast)
+ {
+ if (strlen(argv[i]) > 3)
+ strcpy(pOptions->szHostname, &argv[i][3]);
+ }
+ break;
+
+ case 'p' :
+ if (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 (strlen(argv[i]) > 3)
+ strcpy(pOptions->qosOptions.szTemplate, &argv[i][3]);
+ break;
+
+ case 'r' :
+ if (strlen(argv[i]) > 3)
+ {
+ if ((stricmp(argv[i], "-rsvp-confirm") == 0) ||
+ (stricmp(argv[i], "-rsvp_confirm") == 0))
+ {
+ pOptions->qosOptions.bConfirmResv = TRUE;
+ pOptions->qosOptions.bProviderSpecific = TRUE;
+ }
+ else if ((stricmp(argv[i], "-rsvp-wait") == 0) ||
+ (stricmp(argv[i], "-rsvp_wait") == 0))
+ {
+ pOptions->qosOptions.bWaitToSend = TRUE;
+ pOptions->qosOptions.bProviderSpecific = TRUE;
+ }
+ else
+ {
+ printf("Ignoring option <%s>\n", argv[i]);
+ }
+ }
+ break;
+
+ case 's' :
+ if (strlen(argv[i]) > 3)
+ pOptions->dwSleep = atoi(&argv[i][3]);
+ break;
+
+ case '?' :
+ Usage(argv[0], &default_options);
+ return(FALSE);
+ break;
+
+ default:
+ printf(" unknown options flag %s\n", argv[i]);
+ Usage(argv[0], &default_options);
+ return(FALSE);
+ break;
+ }
+ }
+ else
+ {
+ printf(" 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)
+ pOptions->nRepeat = 0; // override repeat count to continuous mode
+
+ 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;
+ }
+
+ verInfo.dwOSVersionInfoSize = sizeof(verInfo);
+ GetVersionEx(&verInfo);
+ switch (verInfo.dwPlatformId)
+ {
+ case VER_PLATFORM_WIN32_NT:
+ pOptions->qosOptions.bQueryBufferSize = TRUE;
+ pOptions->qosOptions.bMustSetQosInAccept = FALSE;
+ if (verInfo.dwBuildNumber >= 1960)
+ {
+ printf("new build\n");
+ pOptions->qosOptions.bFineGrainErrorAvail = TRUE;
+ pOptions->qosOptions.bQosabilityIoctls = TRUE;
+ }
+ else
+ {
+ pOptions->qosOptions.bFineGrainErrorAvail = FALSE;
+ pOptions->qosOptions.bQosabilityIoctls = FALSE;
+ }
+ printf("running on NT\n");
+ break;
+
+ case VER_PLATFORM_WIN32_WINDOWS:
+ pOptions->qosOptions.bQueryBufferSize = FALSE;
+ pOptions->qosOptions.bMustSetQosInAccept = TRUE;
+ pOptions->qosOptions.bFineGrainErrorAvail = FALSE;
+ pOptions->qosOptions.bQosabilityIoctls = FALSE;
+ printf("running on 9x\n");
+ break;
+
+ default:
+ printf ("requires Windows NT or Windows 98\n");
+ pOptions->qosOptions.bQueryBufferSize = FALSE;
+ pOptions->qosOptions.bMustSetQosInAccept = TRUE;
+ pOptions->qosOptions.bFineGrainErrorAvail = FALSE;
+ pOptions->qosOptions.bQosabilityIoctls = FALSE;
+ break;
+ }
+ }
+
+ if (!(pOptions->buf = (char *)malloc(pOptions->nBufSize)))
+ return(FALSE);
+ else
+ {
+ FillMemory(pOptions->buf, pOptions->nBufSize, pOptions->fillchar);
+ return(TRUE);
+ }
+}
+
+
+static VOID PrintOptions(OPTIONS *pOptions)
+{
+ printf("Options\n");
+ printf(" Protocol %d\n", pOptions->spOptions.iProtocol);
+ printf(" Port %d\n", pOptions->port);
+ if (pOptions->qosOptions.bReceiver)
+ printf(" Act as Receiver\n");
+ else
+ {
+ printf(" Act as sender and send to %s\n", pOptions->szHostname);
+ printf(" Sleep %d milliseconds between sends\n", pOptions->dwSleep);
+ printf(" Fill buffer with <%c>\n", pOptions->fillchar);
+ if (pOptions->nRepeat)
+ printf(" Repeat sending the buffer %d times\n", pOptions->nRepeat);
+ else
+ printf(" Repeat sending the buffer continually\n");
+
+ }
+ printf(" Bufsize %d (1K increments)\n", pOptions->nBufSize);
+ printf(" Multicast is %s\n", (pOptions->spOptions.bMulticast ? "Enabled" : "Disabled"));
+
+ if (pOptions->spOptions.bQos)
+ {
+ printf(" Qos template %s\n", pOptions->qosOptions.szTemplate);
+ printf(" Qos to be set ");
+ switch (pOptions->qosOptions.qosIoctlSet)
+ {
+ case QOS_IOCTL_SET_BEFORE:
+ printf("Before accept/connect/joinleaf\n");
+ break;
+ case QOS_IOCTL_SET_AFTER:
+ printf("After accept/connect/joinleaf\n");
+ break;
+ case QOS_IOCTL_SET_DURING:
+ printf("During accept/connect/joinleaf\n");
+ break;
+ case QOS_IOCTL_SET_QOS:
+ if (pOptions->qosOptions.bReceiver)
+ printf("During FD_QOS, implies QOS with no signaling set before accept/connect (eventually)\n");
+ else
+ {
+ pOptions->qosOptions.qosIoctlSet = QOS_IOCTL_SET_BEFORE;
+ printf("Before connect\n");
+ }
+ break;
+ }
+
+ if (pOptions->qosOptions.bConfirmResv )
+ printf(" RESV confirmation to be requested\n");
+ if (INVALID_SEND_PRIORITY != pOptions->qosOptions.SendPriority)
+ printf(" Qos TC SendPriority to be set to %d\n",
+ pOptions->qosOptions.SendPriority);
+ if (!pOptions->qosOptions.bReceiver)
+ {
+ if (pOptions->qosOptions.bWaitToSend)
+ printf(" Wait for RESV before sending data\n");
+ else
+ printf(" Do not wait for RESV to start sending data\n");
+ }
+ else
+ printf(" Qos must be set during Accept = %s\n",
+ (pOptions->qosOptions.bMustSetQosInAccept?"TRUE":"FALSE"));
+
+ printf(" Query for QOS buffer size: %s\n",
+ (pOptions->qosOptions.bQueryBufferSize?"TRUE":"FALSE"));
+ }
+ printf("\n");
+ return;
+}
+
+// Abstract:
+// Print out usage table for the program
+//
+VOID Usage(CHAR *szProgramname, OPTIONS *pOptions)
+{
+ printf("usage:\n %s -?\n\n", szProgramname);
+ printf(" %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",
+ szProgramname);
+ printf(" -?\t\tDisplay this help\n");
+ printf("\n");
+ printf(" -b:bufsize\tSize of send/recv buffer; in 1K increments (Def:%d)\n",
+ pOptions->nBufSize);
+ printf(" -d:c\t\tCharacter used to fill buffer (Def:%c)\n",
+ pOptions->fillchar);
+ printf(" -e:port\tEndpoint number (port) to use (Def:%d)\n",
+ pOptions->port);
+ printf(" -l:loop\tLoop count for sending buffer (0==>continuous)\n",
+ pOptions->nRepeat);
+ printf(" -m:group\tMulticast group (IP) to join (Def:%s)\n",
+ DEFAULT_MULTICASTGROUP);
+ printf(" -n:host\tAct as the client and connect to 'host' (Def:%s)\n",
+ pOptions->szHostname);
+ printf(" -p:protocol\tTCP or UDP (def:TCP)\n");
+ printf(" -s:#\t\tSleep # milliseconds between sends (def: 0)\n");
+ printf("\n");
+ printf(" -q:template\tEnable QoS and use 'template' to specify the name (Def:%s)\n",
+ pOptions->qosOptions.szTemplate);
+ printf(" -c\t\tCycle enabling/disabling QOS on sending socket (Def: no cycling)\n");
+ printf(" -i:[a|b|d|q]\tSet Qos After, Before, During accept/connect, or during FD_QOS\n\t\t\t(def: Before)\n");
+ printf(" -rsvp-confirm\t\tRequest RESV confirmation be sent (Def: no confirmation)\n");
+ printf(" -rsvp-wait\t\tWait for RESV from receiver before sending data\n");
+ return;
+}
diff --git a/examples/QOS/server.dsp b/examples/QOS/server.dsp
new file mode 100644
index 00000000000..6850256f2a7
--- /dev/null
+++ b/examples/QOS/server.dsp
@@ -0,0 +1,125 @@
+# Microsoft Developer Studio Project File - Name="002" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=002 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "server.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "server.mak" CFG="002 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "002 - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "002 - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "002 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
+
+!ELSEIF "$(CFG)" == "002 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Od /I "d:\vishal\ACE_wrappers" /D "WIN32" /D "_DEBUG" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 d:\vishal\ACE_wrappers\ace\aced.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"d:\vishal\ACE_wrappers\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "002 - Win32 Release"
+# Name "002 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\QOS_Event_Handler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Read_Handler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\server.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\handler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QOS_Event_Handler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QosEvent.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Read_Handler.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project