diff options
author | vishal <vishal@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-08-31 20:18:36 +0000 |
---|---|---|
committer | vishal <vishal@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-08-31 20:18:36 +0000 |
commit | fa10e369b7b2083eab73f7587d218d61932ce83d (patch) | |
tree | 26c35ce31d49c666384e3885b1176af828fc0b0b /examples | |
parent | b251e874ee3b29fcae4feec5985864032e90b5ea (diff) | |
download | ATCD-fa10e369b7b2083eab73f7587d218d61932ce83d.tar.gz |
*** empty log message ***
Diffstat (limited to 'examples')
-rw-r--r-- | examples/QOS/QOS.dsw | 41 | ||||
-rw-r--r-- | examples/QOS/QOS_Event_Handler.cpp | 56 | ||||
-rw-r--r-- | examples/QOS/QOS_Event_Handler.h | 54 | ||||
-rw-r--r-- | examples/QOS/QosEvent.h | 213 | ||||
-rw-r--r-- | examples/QOS/Read_Handler.cpp | 73 | ||||
-rw-r--r-- | examples/QOS/Read_Handler.h | 51 | ||||
-rw-r--r-- | examples/QOS/client.cpp | 833 | ||||
-rw-r--r-- | examples/QOS/client.dsp | 105 | ||||
-rw-r--r-- | examples/QOS/server.cpp | 845 | ||||
-rw-r--r-- | examples/QOS/server.dsp | 125 |
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 |