< QOS Programming | QOS Programming Main | QOS Program Example >


 

 

Generic Quality of Service (QOS) 10 Part 4

 

 

What do we have in this chapter 10 part 4?

  1. QOS Templates

 

QOS Templates

 

Winsock provides several predefined QOS structures, referred to as templates, that an application can query by name. These templates define the QOS parameters for some common audio and video codecs, such as G711 and H263QCIF. The function WSAGetQOSByName() is defined as:

 

BOOL WSAGetQOSByName(

    SOCKET s,

    LPWSABUF lpQOSName,

    LPQOS lpQOS

);

 

If you don't know the name of the installed templates, you can use this function to first enumerate all template names. To do this, provide a sufficiently large buffer in lpQOSName with its first character set to the null character and pass a null pointer for lpQOS, as in the following code:

 

WSABUF  wbuf;

char    cbuf[1024];

 

cbuf[0] = '\0';

wbuf.buf = cbuf;

wbuf.len = 1024;

WSAGetQOSByName(s, &wbuf, NULL);

 

Upon return, the character buffer is filled with an array of strings separated by a null character, and the entire list is terminated by another null character. As a result, the last string entry will have two consecutive null characters. From here you can get the names of all of the installed templates and query for a specific one. The following code looks up the G711 template:

 

QOS     qos;

WSABUF  wbuf;

 

wbuf.buf = "G711";

wbuf.len = 4;

WSAGetQOSByName(s, &wbuf, &qos);

 

If the requested QOS template does not exist, the lookup returns FALSE and the error is WSAEINVAL. Upon success, the function returns TRUE.  The following program example illustrates how to enumerate the installed QOS templates. Create a new empty Win32 console mode application and add the project/solution name.

 

Generic Quality of Service (QOS): Creating a new empty Win32 console mode application project for QOS template

 

Add the following source code.

 

// Description:

//    This sample illustrates how to call the WSAGetQOSByName

//    first to enumerate the installed templates and then how

//    to retrieve the QOS template for a given template.

//    This module relies on the PrintQos() function to print

//    the template information.

//

// Command line arguments: none

//

// Link to ws2_32.lib

#include <winsock2.h>

#include <windows.h>

#include <qos.h>

#include <qossp.h>

#include <stdio.h>

 

#include "provider.h"

#include "printqos.h"

 

// Function: main

// Description:

//    Load Winsock, find the QOS enabled provider, and first

//    enumerate all the installed QOS templates. Next it

//    retrieves the QOS template.

int main(int argc, char **argv)

{

    WSAPROTOCOL_INFO *wsa=NULL;

    char              buf1[16000], *ptr;

    WSABUF       wbuf1, wbuf2;

    SOCKET        s;

    WSADATA    wsdata;

    QOS               qos;

 

    // Load Winsock

    if (WSAStartup(MAKEWORD(2,2), &wsdata) != 0)

    {

        printf("Unable to load Winsock, error %d\n", GetLastError());

        return -1;

    }

    else

        printf("WSAStartup() is OK!\n");

 

    // Find a provider

    wsa = FindProtocolInfo(AF_INET, SOCK_STREAM, IPPROTO_TCP, XP1_QOS_SUPPORTED);

    if (!wsa)

    {

        printf("unable to find a suitable provider!\n");

        return -1;

    }

    else

         printf("FindProtocolInfo() is OK!\n");

 

    // Create a QOS socket

    s = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, wsa, 0, WSA_FLAG_OVERLAPPED);

    if (s == INVALID_SOCKET)

    {

        printf("WSASocket() failed with error code %d\n", WSAGetLastError());

        return -1;

    }

    else

        printf("WSASocket() is OK!\n");

 

    // Enumerate all templates first

    wbuf1.buf = buf1;

    wbuf1.len = 16000;

 

    // Note that for Windows Vista, this function is no longer supported.

    // If this function is called, it always returns with an error of WSAEOPNOTSUPP

    // http://msdn.microsoft.com/en-us/library/aa374496(VS.85).aspx

    if (WSAGetQOSByName(s, &wbuf1, NULL) == FALSE)

    {

        printf("WSAGetQOSByName() failed with error code %d\n", WSAGetLastError());

        return -1;

    }

    else

    {

        printf("WSAGetQOSByName() looks fine!\n");

        ptr = buf1;

        while (*ptr)

        {

            // Get a single template name and call the function to retrieve QOS for that template

            printf("Template: %s\n", ptr);

            wbuf2.buf = ptr;

            wbuf2.len = strlen(ptr)+1;

            if (WSAGetQOSByName(s, &wbuf2, &qos) == FALSE)

            {

                printf("WSAGetQOSByName() failed with error code %d\n", WSAGetLastError());

                return -1;

            }

            PrintQos(&qos);

 

            while (*ptr++);

        }

    }

 

    if(closesocket(s) == 0)

        printf("closesocket(s) is OK!\n");

    else

        printf("closesocket(s) failed with error code %d\n",WSAGetLastError());

 

    if(WSACleanup() == 0)

         printf("WSACleanup() is OK!\n");

    else

         printf("WSACleanup() failed with error code %d\n", WSAGetLastError());

    return 0;

}

 

Add the provider header file, provider.h.

 

Generic Quality of Service (QOS): Creating a new empty Win32 console mode application project for QOS template - adding provider.h header file

 

Then add the source code.

 

// Sample: Function prototypes for Winsock catalog support routines

//

// Files:

//      provider.h      - this file

//

// Description:

//      This file contains the prototype for Winsock provider related

//      support routines.

//

#ifndef _PROVIDER_H_

#define _PROVIDER_H_

 

WSAPROTOCOL_INFO *FindProtocolInfo(int af, int type, int protocol, DWORD flags);

 

#endif

 

Next, add the provider.cpp, the provider.h definition file.

 

Generic Quality of Service (QOS): Creating a new empty Win32 console mode application project for QOS template - adding the provider.cpp definition file

 

Add the source code.

 

// Description:

//    This module contains a single routine FindProtocolInfo which

//    enumerates all Winsock providers and searches for an entry

//    of the given address family, socket type, protocol, and flags

//    (such as QOS support).

//

// Command line arguments:

//    None

//

#include <winsock2.h>

#include <windows.h>

#include <qos.h>

#include <qossp.h>

#include "provider.h"

#include <stdio.h>

 

// Function: FindProtocolInfo

// Description:

//    This function searches the Winsock catalog for

//    a provider of the given address family, socket type,

//    protocol and flags. The flags field is a bitwise

//    OR of all the attributes that you request such as

//    multipoint or QOS support.

WSAPROTOCOL_INFO *FindProtocolInfo(int af, int type, int protocol, DWORD flags)

{

    DWORD             protosz=0, nprotos, i;

    WSAPROTOCOL_INFO *buf=NULL;

    int               ret;

    static WSAPROTOCOL_INFO pinfo;

 

    // Find out the size of the buffer needed to enumerate all entries.

    ret = WSAEnumProtocols(NULL, NULL, &protosz);

    if (ret != SOCKET_ERROR)

    {

        printf("Not supposed to be here!\n");

        return NULL;

    }

 

    // Allocate the necessary buffer

    buf = (WSAPROTOCOL_INFO *)LocalAlloc(LPTR, protosz);

    if (!buf)

    {

        printf("LocalAlloc() for buffer failed with error code %d\n", GetLastError());

        return NULL;

    }

    else

        printf("LocalAlloc() for buffer is OK!\n");

 

    nprotos = protosz / sizeof(WSAPROTOCOL_INFO);

 

    // Make the real call

    ret = WSAEnumProtocols(NULL, buf, &protosz);

    if (ret == SOCKET_ERROR)

    {

        printf("WSAEnumProtocols() failed with error code %d\n", WSAGetLastError());

        LocalFree(buf);

        return NULL;

    }

    else

        printf("WSAEnumProtocols() is OK!\n");

 

    // Search through the catalog entries returned for the requested attributes.

    for(i=0; i < nprotos ;i++)

    {

        if ((buf[i].iAddressFamily == af) && (buf[i].iSocketType == type) &&

            (buf[i].iProtocol == protocol))

        {

            if ((buf[i].dwServiceFlags1 & flags) == flags)

            {

                memcpy(&pinfo, &buf[i], sizeof(WSAPROTOCOL_INFO));

                LocalFree(buf);

                return &pinfo;

            }

        }

    }

    LocalFree(buf);

    return NULL;

}

 

Then, add the printqos.h header file.

 

Generic Quality of Service (QOS): Creating a new empty Win32 console mode application project for QOS template - adding the printqos.h header file

 

Then, add the prototypes code.

 

// Sample: Function definitions for QOS print routines

// Files:

//      printqos.h      - this file

// Description:

//      This file contains function prototypes for support routines

//      that print various QOS structure. These functions are

//      implemented in printqos.cpp

#ifndef _PRINTQOS_H_

#define _PRINTQOS_H_

 

#define SERVICETYPE_STR_LEN        256

 

// QOS and FLOWSPEC print functions

void  PrintQos(QOS *pqos);

void  PrintFlowspec(FLOWSPEC *pflow, int indent);

void  PrintProviderSpecific(WSABUF *provider, int indent);

char *GetServiceTypeStr(SERVICETYPE type);

 

// Provider specific object functions

void PrintRsvpStatus     (RSVP_STATUS_INFO *status, int indent);

void PrintRsvpResv       (RSVP_RESERVE_INFO *reserve, int indent);

void PrintRsvpAdspec     (RSVP_ADSPEC *adspec, int indent);

void PrintRsvpPolicy     (RSVP_POLICY_INFO *policy, int indent);

 

void PrintQosSDMode      (QOS_SD_MODE *sd, int indent);

void PrintQosDestAddr    (QOS_DESTADDR *dest, int indent);

 

void PrintAdGeneralParams(AD_GENERAL_PARAMS *params, int indent);

 

#endif

 

Finally, add the definition file, printqos.cpp for printqos.h.

 

---------------------------------------------------------------

Generic Quality of Service (QOS): Creating a new empty Win32 console mode application project for QOS template - adding the printqos definition file

 

Add the source code.

 

// Module Name: printqos.cpp

// Description:

//    This file contains routines used to print out the QOS data

//    structure from top to bottom. This includes the provider

//    specific structures. This file contains only support routines.

#include <winsock2.h>

#include <windows.h>

#include <qos.h>

#include <qossp.h>

#include "printqos.h"

#include <stdio.h>

 

#define MAX_INDENT        128

 

// Function: PrintQos

// Description:

//    This is the top level function. It prints out the sending and

//    receiving FLOWSPEC structures and initiates printing of the

//    provider specific data.

void PrintQos(QOS *pqos)

{

    if (pqos == NULL)

        return;

    printf("Sending Flowspec:\n");

    PrintFlowspec(&pqos->SendingFlowspec, 1);

    printf("Receiving Flowspec:\n");

    PrintFlowspec(&pqos->ReceivingFlowspec, 1);

    printf("Provider Specific (len = %d bytes):\n", pqos->ProviderSpecific.len);

    PrintProviderSpecific(&pqos->ProviderSpecific, 1);

    printf("\n\n");

}

 

// Function: PrintFlowspec

// Description: Prints the FLOWSPEC structure.

void PrintFlowspec(FLOWSPEC *pflow, int indent)

{

    char    szIndent[MAX_INDENT];

 

    memset(szIndent, ' ', MAX_INDENT);

    szIndent[indent * 3] = 0;

 

    if (pflow->TokenRate == QOS_NOT_SPECIFIED)

        printf("%sTokenRate          = QOS_NOT_SPECIFIED\n", szIndent);

    else

        printf("%sTokenRate          = %d bytes/sec\n", szIndent, pflow->TokenRate);

    if (pflow->TokenBucketSize == QOS_NOT_SPECIFIED)

        printf("%sTokenBucketSize    = QOS_NOT_SPECIFIED\n", szIndent);

    else

        printf("%sTokenBucketSize    = %d bytes\n", szIndent, pflow->TokenBucketSize);

    if (pflow->PeakBandwidth == QOS_NOT_SPECIFIED)

        printf("%sPeakBandwidth      = QOS_NOT_SPECIFIED\n", szIndent);

    else

        printf("%sPeakBandwidth      = %d bytes/sec\n", szIndent, pflow->PeakBandwidth);

    if (pflow->Latency == QOS_NOT_SPECIFIED)

        printf("%sLatency            = QOS_NOT_SPECIFIED\n", szIndent);

    else

        printf("%sLatency            = %d microseconds\n", szIndent, pflow->Latency);

    if (pflow->DelayVariation == QOS_NOT_SPECIFIED)

        printf("%sDelayVariation     = QOS_NOT_SPECIFIED\n", szIndent);

    else

        printf("%sDelayVariation     = %d microseconds\n", szIndent, pflow->DelayVariation);

 

    printf("%sServiceType        = %s\n", szIndent, GetServiceTypeStr(pflow->ServiceType));

 

    if (pflow->MaxSduSize == QOS_NOT_SPECIFIED)

        printf("%sMaxSduSize         = QOS_NOT_SPECIFIED\n", szIndent);

    else

        printf("%sMaxSduSize         = %d bytes\n", szIndent, pflow->MaxSduSize);

    if (pflow->MinimumPolicedSize == QOS_NOT_SPECIFIED)

        printf("%sMinimumPolicedSize = QOS_NOT_SPECIFIED\n", szIndent);

    else

        printf("%sMinimumPolicedSize = %d bytes\n", szIndent, pflow->MinimumPolicedSize);

}

 

// Function: PrintProviderSpecific

// Description:

//    Prints provider specific data. This is done by looking at

//    the WSABUF structure.  If the len is 0 there is no data.

//    Otherwise, the first structure in the data is a QOS_OBJECT_HDR

//    so we can cast the pointer as this object and find out

//    specifically what object it is. Each header has its length

//    so we can find the start of the next QOS_OBJECT_HDR.

static void PrintProviderSpecific(WSABUF *provider, int indent)

{

    QOS_OBJECT_HDR  *objhdr=NULL;

    char            *bufptr=NULL, szIndent[MAX_INDENT];

    BOOL             bDone = FALSE;

    DWORD            objcount=0;

 

    memset(szIndent, ' ', MAX_INDENT);

    szIndent[indent * 3] = 0;

 

    // If the buffer is empty, exit

    if (provider->len == 0)

    {

        printf("%sEmpty Provider Specific!\n", szIndent);

        return;

    }

 

    // Setup some pointers to the first object header

    bufptr = (char *)provider->buf;

    objhdr = (QOS_OBJECT_HDR *)bufptr;

 

    // Loop until we run out of objects

    while (!bDone)

    {

        // Decode which object is present and call the appropriate print routine

        switch (objhdr->ObjectType)

        {

            case RSVP_OBJECT_STATUS_INFO:

                PrintRsvpStatus((RSVP_STATUS_INFO *)objhdr, indent+1);

                break;

            case RSVP_OBJECT_RESERVE_INFO:

                PrintRsvpResv((RSVP_RESERVE_INFO *)objhdr, indent+1);

                break;

            case RSVP_OBJECT_ADSPEC:

                PrintRsvpAdspec((RSVP_ADSPEC *)objhdr, indent+1);

                break;

            case RSVP_OBJECT_POLICY_INFO:

                PrintRsvpPolicy((RSVP_POLICY_INFO *)objhdr, indent+1);

                break;

                //          case QOS_OBJECT_PRIORITY:

                //                PrintQosPriority((QOS_PRIORITY *)objhdr, indent+1);

                //                break;

            case QOS_OBJECT_SD_MODE:

                PrintQosSDMode((QOS_SD_MODE *)objhdr, indent+1);

                break;

                //            case QOS_OBJECT_TRAFFIC_CLASS:

                //                PrintQosTrafficClass((QOS_TRAFFIC_CLASS *)objhdr, indent+1);

                //                break;

            case QOS_OBJECT_DESTADDR:

                PrintQosDestAddr((QOS_DESTADDR *)objhdr, indent+1);

                break;

            case QOS_OBJECT_END_OF_LIST:

                bDone = TRUE;

                break;

            default:

                break;

        }

 

        // Update the pointers to the next object

        bufptr += objhdr->ObjectLength;

        objcount += objhdr->ObjectLength;

        objhdr = (QOS_OBJECT_HDR *)bufptr;

        // Check to see if we've exceeded the length of the object

        if (objcount >= provider->len)

            bDone = TRUE;

    }

    return;

}

 

// Function: GetServiceTypeStr

// Description:

//    This function is used by the PrintFlowspec call. It simply

//    returns a string for the ServiceType as opposed to printing

//    the integer value.

static char *GetServiceTypeStr(SERVICETYPE type)

{

    static char szServiceType[SERVICETYPE_STR_LEN];

 

    if ((type & SERVICETYPE_BESTEFFORT) == SERVICETYPE_BESTEFFORT)

        strcpy_s(szServiceType, sizeof(szServiceType), "SERVICETYPE_BESTEFFORT");

    else if ((type & SERVICETYPE_CONTROLLEDLOAD) == SERVICETYPE_CONTROLLEDLOAD)

        strcpy_s(szServiceType, sizeof(szServiceType), "SERVICETYPE_CONTROLLEDLOAD");

    else if ((type & SERVICETYPE_GUARANTEED) == SERVICETYPE_GUARANTEED)

        strcpy_s(szServiceType, sizeof(szServiceType), "SERVICETYPE_GUARANTEED");

    else if ((type & SERVICETYPE_NETWORK_UNAVAILABLE) == SERVICETYPE_NETWORK_UNAVAILABLE)

        strcpy_s(szServiceType, sizeof(szServiceType), "SERVICETYPE_NETWORK_UNAVAILABLE");

    else if ((type & SERVICETYPE_GENERAL_INFORMATION) == SERVICETYPE_GENERAL_INFORMATION)

        strcpy_s(szServiceType, sizeof(szServiceType), "SERVICETYPE_GENERAL_INFORMATION");

    else if ((type & SERVICETYPE_NOCHANGE) == SERVICETYPE_NOCHANGE)

        strcpy_s(szServiceType, sizeof(szServiceType), "SERVICETYPE_NOCHANGE");

    else if ((type & SERVICETYPE_NONCONFORMING) == SERVICETYPE_NONCONFORMING)

        strcpy_s(szServiceType, sizeof(szServiceType), "SERVICETYPE_NONCONFORMING");

    else if ((type & SERVICETYPE_NOTRAFFIC) == SERVICETYPE_NOTRAFFIC)

        strcpy_s(szServiceType, sizeof(szServiceType), "SERVICETYPE_NOTRAFFIC");

    else

        strcpy_s(szServiceType, sizeof(szServiceType), "Unknown");

 

    if ((type & SERVICE_NO_TRAFFIC_CONTROL) == SERVICE_NO_TRAFFIC_CONTROL)

        strcat_s(szServiceType, sizeof(szServiceType), " | SERVICE_NO_TRAFFIC_CONTROL");

    else if ((type & SERVICE_NO_QOS_SIGNALING) == SERVICE_NO_QOS_SIGNALING)

        strcat_s(szServiceType, sizeof(szServiceType), " | SERVICE__NO_QOS_SIGNALING");

    return szServiceType;

}

 

// Function: PrintRsvpStatus

// Description: Prints the RSVP_STATUS_INFO object.

static void PrintRsvpStatus(RSVP_STATUS_INFO *status, int indent)

{

    char    szIndent[MAX_INDENT];

 

    memset(szIndent, ' ', MAX_INDENT);

    szIndent[indent * 3] = 0;

 

    printf("%sStatus Code = ", szIndent);

    switch (status->StatusCode)

    {

        case WSA_QOS_RECEIVERS:             // at least one RESV has arrived

            printf("WSA_QOS_RECEIVERS\n");

            break;

        case WSA_QOS_SENDERS:               // at least one PATH has arrived

            printf("WSA_QOS_SENDERS\n");

            break;

        case WSA_QOS_NO_SENDERS:            // there are no senders

            printf("WSA_QOS_NO_SENDERS\n");

            break;

        case WSA_QOS_NO_RECEIVERS:          // there are no receivers

            printf("WSA_QOS_NO_RECEIVERS\n");

            break;

        case WSA_QOS_REQUEST_CONFIRMED:     // Reserve has been confirmed

            printf("WSA_QOS_REQUEST_CONFIRMED\n");

            break;

        case WSA_QOS_ADMISSION_FAILURE:     // error due to lack of resources

            printf("WSA_QOS_ADMISSION_FAILURE\n");

            break;

        case WSA_QOS_POLICY_FAILURE:        // rejected for admin reasons

            printf("WSA_QOS_POLICY_FAILURE\n");

            break;

        case WSA_QOS_BAD_STYLE:             // unknown or conflicting style

            printf("WSA_QOS_BAD_STYLE\n");

            break;

        case WSA_QOS_BAD_OBJECT:            // problem with some part of the filterspec/providerspecific buffer in general

            printf("WSA_QOS_BAD_OBJECT\n");

            break;

        case WSA_QOS_TRAFFIC_CTRL_ERROR:    // problem with some part of the flowspec

            printf("WSA_QOS_TRAFFIC_CTRL_ERROR\n");

            break;

        case WSA_QOS_GENERIC_ERROR:         // general error

            printf("WSA_QOS_GENERIC_ERROR\n");

            break;

        default:

            printf("Unknown RSVP StatusCode %lu\n", status->StatusCode);

            break;

    }

    printf("%sExtendedStatus1 = %lu\n", szIndent, status->ExtendedStatus1);

    printf("%sExtendedStatus2 = %lu\n", szIndent, status->ExtendedStatus2);

 

    return;

}

 

// Function: PrintRsvpResv

// Description: Prints the RSVP_RESERVE_INFO object.

static void PrintRsvpResv(RSVP_RESERVE_INFO *resv, int indent)

{

    SOCKADDR_IN   addr;

    DWORD         dwIPv6Len, i, j;

    char          szIPv6[128], szIndent[MAX_INDENT];

 

    memset(szIndent, ' ', MAX_INDENT);

    szIndent[indent * 3] = 0;

 

    printf("%sStyle = ", szIndent);

    switch (resv->Style)                // filter style

    {

        case RSVP_DEFAULT_STYLE:

            // Use the default for this socket type

            printf("RSVP_DEFAULT_STYLE\n");

            break;

        case RSVP_WILDCARD_STYLE:

            printf("RSVP_WILDCARD_STYLE\n");

            break;

        case RSVP_FIXED_FILTER_STYLE:

            printf("RSVP_FIXED_FILTER_STYLE\n");

            break;

        case RSVP_SHARED_EXPLICIT_STYLE:

            printf("RSVP_SHARED_EXPLICIT_STYLE\n");

            break;

        default:

            printf("Unknown style %d\n", resv->Style);

            break;

    }

 

    printf("%sConfirmRequest = %s\n", szIndent, (resv->ConfirmRequest ? "yes":"no"));

    printf("%sNumFlowDesc = %lu\n", szIndent, resv->NumFlowDesc);

 

    // Print out the flow descriptors (if any) associated with the filter

    for(i=0; i < resv->NumFlowDesc ;i++)

    {

        PrintFlowspec(&resv->FlowDescList[i].FlowSpec, indent+1);

        printf("%s  NumFilters = %lu\n", szIndent, resv->FlowDescList[i].NumFilters);

        for(j=0; j < resv->FlowDescList[i].NumFilters ;j++)

        {

            printf("%s  FilterType = ", szIndent);

            switch (resv->FlowDescList[i].FilterList[j].Type)

            {

                case FILTERSPECV4:

                    addr.sin_addr.s_addr = resv->FlowDescList[i].FilterList[j].FilterSpecV4.Address.Addr;

                    printf("%s    FILTERSPECV4\n", szIndent);

                    printf("%s      Address = %s\n", szIndent, inet_ntoa(addr.sin_addr));

                    printf("%s      Port    = %d\n", szIndent, ntohs(resv->FlowDescList[i].FilterList[j].FilterSpecV4.Port));

                    break;

                case FILTERSPECV6:

                    printf("%s    FILTERSPECV6\n", szIndent);

                    WSAAddressToString(

                        (LPSOCKADDR)&resv->FlowDescList[i].FilterList[j].FilterSpecV6.Address, sizeof(IN_ADDR_IPV6),

                        NULL, (LPWSTR)szIPv6, &dwIPv6Len);

                    printf("%s      Address = %s\n", szIndent, szIPv6);

                    printf("%s      Port    = %hu\n", szIndent, resv->FlowDescList[i].FilterList[j].FilterSpecV6.Port);

                    break;

                case FILTERSPECV6_FLOW:

                    printf("%s    FILTERSPECV6_FLOW\n", szIndent);

                    WSAAddressToString(

                        (LPSOCKADDR)&resv->FlowDescList[i].FilterList[j].FilterSpecV6Flow.Address, sizeof(IN_ADDR_IPV6),

                        NULL, (LPWSTR)szIPv6, &dwIPv6Len);

                    printf("%s      Address = %s\n", szIndent, szIPv6);

                    printf("%s      FlowLabel = %s\n", szIndent, resv->FlowDescList[i].FilterList[j].FilterSpecV6Flow.FlowLabel);

                    break;

                case FILTERSPECV4_GPI:

                    addr.sin_addr.s_addr = resv->FlowDescList[i].FilterList[j].FilterSpecV4Gpi.Address.Addr;

                    printf("%s    FILTERSPECV4_GPI\n", szIndent);

                    printf("%s      Address = %s\n", szIndent, inet_ntoa(addr.sin_addr));

                    printf("%s      Port    = %d\n", szIndent,

                        resv->FlowDescList[i].FilterList[j].FilterSpecV4Gpi.GeneralPortId);

                    break;

                case FILTERSPECV6_GPI:

                    printf("%s    FILTERSPECV6_GPI\n", szIndent);

                    WSAAddressToString(

                        (LPSOCKADDR)&resv->FlowDescList[i].FilterList[j].FilterSpecV6Gpi.Address, sizeof(IN_ADDR_IPV6),

                        NULL, (LPWSTR)szIPv6, &dwIPv6Len);

                    printf("%s      Address = %s\n", szIndent, szIPv6);

                    printf("%s      Port    = %hu\n", szIndent, resv->FlowDescList[i].FilterList[j].FilterSpecV6Gpi.GeneralPortId);

                    break;

            }

        }

    }

    return;

}

 

// Function: PrintRsvpAdspec

// Description: Prints the RSVP_ADSPEC object.

static void PrintRsvpAdspec(RSVP_ADSPEC *adspec, int indent)

{

    DWORD   i;

    char    szIndent[MAX_INDENT];

 

    memset(szIndent, ' ', MAX_INDENT);

    szIndent[indent * 3] = 0;

 

    printf("%sGeneralParams\n", szIndent);

    PrintAdGeneralParams(&adspec->GeneralParams, indent+1);

 

    printf("%sNumberOfServices = %d\n", szIndent, adspec->NumberOfServices);

    for(i=0; i < adspec->NumberOfServices ;i++)

    {

        printf("%s  Services[%d].Length = %lu\n", szIndent, i, adspec->Services[i].Length);

        printf("%s  Services[%d].ServiceType = %s\n", szIndent, i, GetServiceTypeStr(adspec->Services[i].Service));

        printf("%s  Services[%d].Overrides\n",  szIndent, i);

 

        PrintAdGeneralParams(&adspec->Services[i].Overrides, indent+1);

 

        if (adspec->Services[i].Service == SERVICETYPE_GUARANTEED)

        {

            printf("%s     Services[%lu].CTotal = %lu\n", szIndent, i, adspec->Services[i].Guaranteed.CTotal);

            printf("%s     Services[%lu].DTotal = %lu\n", szIndent, i, adspec->Services[i].Guaranteed.DTotal);

            printf("%s     Services[%lu].CSum   = %lu\n", szIndent, i, adspec->Services[i].Guaranteed.CSum);

            printf("%s     Services[%lu].DSum   = %lu\n", szIndent, i, adspec->Services[i].Guaranteed.DSum);

        }

        else

        {

            printf("%s     Services[%lu].ParamBuffer[ ].ParameterId = %lu\n", szIndent, i, adspec->Services[i].ParamBuffer->ParameterId);

            printf("%s     Services[%lu].ParamBuffer[ ].Length      = %lu\n", szIndent, i, adspec->Services[i].ParamBuffer->Length);

        }

    }

    return;

}

 

// Function: PrintAdGeneralParams

// Description: Print AD_GENERAL_PARAMS object.

static void PrintAdGeneralParams(AD_GENERAL_PARAMS *params, int indent)

{

    char    szIndent[MAX_INDENT];

 

    memset(szIndent, ' ', MAX_INDENT);

    szIndent[indent * 3] = 0;

 

    printf("%sIntServAwareHopCount  = 0x%X\n", szIndent, params->IntServAwareHopCount);

 

    if (params->PathBandwidthEstimate == POSITIVE_INFINITY_RATE)

        printf("%sPathBandwidthEstimate = POSITIVE INFINITY\n", szIndent);

    else

        printf("%sPathBandwidthEstimate = 0x%X\n", szIndent, params->PathBandwidthEstimate);

 

    printf("%sMinimumLatency        = 0x%X\n", szIndent, params->MinimumLatency);

    printf("%sPathMTU               = 0x%X\n", szIndent, params->PathMTU);

    printf("%sFlags                 = %lu\n", szIndent, params->Flags);

 

    return;

}

 

// Function: PrintRsvpPolicy

// Description: Print the RSVP_POLICY_INFO object.

static void PrintRsvpPolicy(RSVP_POLICY_INFO *policy, int indent)

{

    return;

}

 

// Function: PrintQosSDMode

// Description: Print the QOS_SD_MODE object.

static void PrintQosSDMode(QOS_SD_MODE *sd, int indent)

{

    char    szIndent[MAX_INDENT];

 

    memset(szIndent, ' ', MAX_INDENT);

    szIndent[indent * 3] = 0;

 

    printf("%sShapeDiscard Mode = ", szIndent);

    switch (sd->ShapeDiscardMode)

    {

        case TC_NONCONF_BORROW:       // use best effort for non conforming

            printf("TC_NONCONF_BORROW\n");

            break;

        case TC_NONCONF_SHAPE:        // hold data until it conforms

            printf("TC_NONCONF_SHAPE\n");

            break;

        case TC_NONCONF_DISCARD:      // drop any non-conforming data

            printf("TC_NONCONF_DISCARD\n");

            break;

        default:

            printf("Unknown traffic class %lu\n", sd->ShapeDiscardMode);

            break;

    }

    return;

}

 

// Function: PrintQosDestAddr

// Description: Print the QOS_DESTADDR structure.

static void PrintQosDestAddr(QOS_DESTADDR *dest, int indent)

{

    char    szIndent[MAX_INDENT];

 

    memset(szIndent, ' ', MAX_INDENT);

    szIndent[indent * 3] = 0;

 

    printf("%sDestAddress     = %s\n", szIndent, inet_ntoa(((SOCKADDR_IN *)dest->SocketAddress)->sin_addr));

    printf("%sDestAddress Len = %lu\n", szIndent, dest->SocketAddressLength);

    return;

}

 

Build and run the project.

 

Generic Quality of Service (QOS): A sample QOS template program output

 

In addition, you can install your own QOS template so that other applications can query for it by name. Two functions do this: WSCInstallQOSTemplate() and WSCRemoveQOSTemplate(). The first one installs a QOS template, and the second removes it. The prototypes are:

 

BOOL WSCInstallQOSTemplate(

    const LPGUID lpProviderId,

    LPWSABUF lpQOSName,

    LPQOS lpQOS

);

 

BOOL WSCRemoveQOSTemplate(const LPGUID lpProviderId, LPWSABUF lpQOSName);

 

These two functions are fairly self-explanatory. To install a template, call WSCInstallQOSTemplate() with a GUID, the name of the template, and the QOS parameters. The GUID is a unique identifier for this template that utilities such as UUIDGEN can generate. To remove the template, simply supply the template name along with the same GUID used in the installation process to WSCRemoveQOSTemplate(). Both functions return TRUE when successful.

 

 

 

Related reference:

 

MSDN QOS reference.

 


< QOS Programming | QOS Programming Main | QOS Program Example >