Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


Using the QoS API

This document gives an introduction to using the RSubConnection API for QoS.

[Top]


QoS API Overview

This document gives an introduction to using the RSubConnection API for QoS.

Quality of Service (QoS) in release 9.1 and later of Symbian OS is implemented by setting parameters on a channel (a "sub-connection", RSubConnection) within a connection (RConnection). RConnection contains one or more sub-connections (a default sub-connection, which is created automatically with the RConnection plus any added RSubConnections). Each sub-connection has properties. To set those properties you apply an RSubConParameterBundle to the RSubConnection. The parameter bundle consists of families of parameters. A "family" is a connected set of parameters, such as QoS. At present only two families are defined, Quality of Service (KSubConQoSFamily) and Authorisation (KSubConAuthorisationFamily).

The RSubConnection API provides the functionality to divide a Connection (provided by the RConnection API) into channels that have properties such as bandwidth and latency.

Each family of parameters can consist of the values you would like to have (ERequested) and the minimum you're willing to accept (EAcceptable). If you don't specify the EAcceptable then the ERequested will be used as the minimum acceptable. When the parameters have been applied and the sub-connection is used then the parameter family will be updated with a third set of values, the EGranted (which will be somewhere between the EAcceptable and the ERequested) or an event will be raised to say that the parameters have been rejected/could not be granted. As this may be some time after the initial request, asynchronous event notification is used to tell your application what has been negotiated. Your application should monitor for the granted/rejected event notification.

There is an overlap between the RSubConnection API and the RConnection API as both provide sub-connection management. The RConnection API provides overall sub-connection management for an entire connection whereas the RSubConnection API allows the individual setting of properties of a sub-connection as well as the ability to associate sockets (RSocket) with sub-connections. The sockets are then able to take advantage of the sub-connection's properties when they send and receive data.

The RSocket API has been updated, to allow it to be created with a sub-connection as well as a connection. A client is able to start a sub-connection via RSubConnection and associate individual RSocket objects with that sub-connection. This ensures that all data flowing over those objects uses the particular sub-connection previously started by the application. This is implemented using a new RSocket::Open(…) method which takes an additional argument specifying the sub-connection to use for the object in question. The socket will not actually be added to the sub-connection until such time as the socket is used.

As well as opening sub-connections explicitly via RSubConnection, applications may also attach to the default sub-connection (e.g. in GPRS, the default could be the Primary PDP context without a TFT), and modify and retrieve its properties.

Parameters that apply to an RSubConnection are grouped together into "families" (CSubConParameterFamily). Each parameter family contains parameter sets that are either "generic" (parameters that are independent of the underlying technology) or "extension" (a group of parameters specific to a technology). There will always be one generic parameter set in a family and there will be zero or more extension parameter sets.

An RSubConnection is updated by filling in an RSubConParameterBundle and calling RSubConnection::SetParameters(). When the CSubConParameterFamily constructor is called, it adds the family to the named bundle automatically. The bundle takes ownership of the family and when the bundle is destroyed, it will destroy the parameter family.

For example, a particular bundle may contain a QoS family. The QoS family may contain (for example) one generic and two extension parameter sets. Each of those parameter sets may exist as ERequested, EAcceptable, and EGranted. Remember that the EGranted parameter set is created and updated by the underlying communications link and so should not be changed by your application.

RSubConParameterBundle

An instance of a parameter bundle can only be applied as a single action. That is, if one parameter family is added to the bundle and a call is made to RSubConnection::SetParameters(); to add another family or an additional extension set to the existing parameter family, it must be added to the original RSubConParameterBundle instance and another call made to RSubConnection::SetParameters(). If the original parameter bundle is not available you may create a totally new parameter bundle and (optionally) make a call to RSubConnection::GetParameters() to obtain the current settings. When a family is added to the bundle, the bundle will take ownership of that object. All added CSubConParameterFamily objects will be destroyed when the parameter bundle is destroyed.

The AddFamilyL() and FindFamily() methods do just as their names suggest. It is unlikely that the AddFamilyL() call will ever be required since the constructor of CSubConParameterFamily adds the family to the passed in parameter bundle automatically. It is present mainly for internal use.

The ClearAllParameters() method will clear parameters of the given parameter set type from all families that the bundle owns.

The Load() and Store() methods are used for serialisation of the parameter bundle, whilst Length() will return the number of bytes the serialised data will occupy.

CSubConParameterFamily

An application could add a parameter set of the type ERequested to request an ideal level of bandwidth and latency, and a parameter set type of EAcceptable could be added to indicate the bare minimum required for the application to operate. A parameter set of the type EGranted must never be added by an application. The sub-connection's parameter bundle will be updated with parameter sets of this (granted) type when the negotiated settings change, such as when the sub-connection is established/used.

Before a call to SetParameters() is made on the sub-connection the family must at least contain a parameter set of the type ERequested. If the parameter set type EAcceptable is omitted the requested values will used as the acceptable values. This means that if you request a bandwidth of 256k and only 128k is available, an event will be returned saying that the requested bandwidth is not available (CSubConGenEventParamsRejected). Any parameter sets of the type EGranted will be ignored by a call to SetParameters().

When a generic or extension set is added to the family, the parameter family object will take ownership of that parameter set. All added parameter sets will be deleted along with the parameter family.

The LoadL() method is used to create a new CSubConParameterFamily from a previously serialised object. It will be added to the given bundle, which will taken ownership of the new family.

The SetGenericSetL() and AddExtensionSetL() methods are used to add parameter sets to the family. If the type of parameter set added/set is the same as a parameter set type already contained by the CSubConParameterFamily the method will leave with KErrAlreadyExists. For example, if an extension set is added for the type ERequested, then another extension set (of the same type) is also added for ERequested the method will leave.

The GetGenericSet() and FindExtensionSet() methods are used to retrieve a parameter set from the parameter family. If there is no generic set or extension set of the specified type then NULL is returned.

The ClearAllParameters() method will clear both generic and extension parameter sets of the given parameter set type from the family.

Id() will return the family identifier.

The Load() and Store() methods are used for serialisation of the parameter family, whilst Length() will return the number of bytes the serialised data will occupy.

Remember that an RSubConnection is updated by filling in an RSubConParameterBundle and calling RSubConnection::SetParameters(). This means that changes to parameter sets will only be applied when SetParameters() is called. Also note that retrieving the EGranted parameters will only be effective once the sub-connection is used and the CSubConGenEventParamsGranted event has been sent.

[Top]


Using RSubConnection

The Open() method is used to open an RSubConnection object on an ESOCK session. The RConnection used for this must already be active. A sub-connection type is passed as a parameter to this method to select whether to attach to the default sub-connection (the RConnection), or create a new one. As with most of the calls in the RSubConnection API a system wide error code is returned, returning KErrNone upon success.

The Add() method is used to move a socket from the default sub-connection to the RSubConnection. The Remove() method will return the socket to the default sub-connection. Although these methods both return system wide error codes, the error code only represents the success or failure of the request and initialisation to perform the action. The action of moving the socket is completed asynchronously, and the socket must be connected in order for the call to complete. It is not permitted to move a socket from one sub-connection to another, nor is it permitted to move a socket to a sub-connection that has been opened on a different RConnection. When the socket has been added, or has been removed from a sub-connection, the events CSubConGenEventDataClientJoining, or CSubConGenEventDataClientLeaving respectively will be notified.

The GetParameters() and SetParameters() methods are used to retrieve and set bundles of properties on the sub-connection. GetParameters() will return KErrNotReady if no properties have been negotiated. This may not happen until the sub-connection has been used. The SetParameters() method, like the Add() and Remove() methods returns an error code indicating the success or failure of the request to perform the action. Upon negotiation of the properties either the CSubConGenEventParamsGranted or CSubConGenEventParamsRejected event will be notified for each family within the parameter bundle. A call to the SetParameters() method may not result in any negotiation until such time as the sub-connection is used.

The EventNotification() methods are used to asynchronously register for event notifications. The methods support filtering of events in two different ways, via a boolean flag to receive notification of generic or all events, and via an array of TEventFilter’s. These are described with the code examples below (see Registering for events – Using filters). In order to avoid missing any notifications it is recommended to re-register for notifications before handling the received notification. Registration for event notifications is cancelled with the CancelEventNotification() method.

Generic control of the sub-connection is provided by the Control() method. Use of this method is dependant upon support provided by the underlying sub-connection provider technology.

[Top]


Events

CSubConGenEventDataClientJoined, CSubConGenEventDataClientLeft

These two events derive from CSubConGenEventDataClientBase, which provides the functionality for both. The source and destination end points of the data client are presented with this event, along with the IAP ID of the connection on which it was created.

CSubConNotificationEvent

Both generic and extension sub-connection events derive from this class. The rules for generic and extension events are the same as for parameter sets. That is, a generic event MUST be able to be understood by all technologies.

The IsGeneric() method identifies whether the event is generic.

The GroupId() method returns the UID of the factory that contains the event, and Id() returns the class type Id within that factory. These two pieces of information comprise the STypeId of the event.

CSubConGenEventParamsGranted

Notification of this event occurs after a request to SetParameters() has been made and negotiation with the network has been completed. A notification will be received for each family contained in the parameter bundle that was negotiated successfully. This event presents a generic set and zero or more extension sets (providing they are supported by the underlying sub-connection provider technology) of the parameter family identified by the Id returned from GetFamily().

CSubConGenEventParamsRejected

Notification of this event occurs after a request to SetParameters() has been made and negotiation with the network has failed for some reason. It could be an error within the handset software/configuration, or that the network could not provide the acceptable (minimum) level of QoS. The reason for failure and the parameter family are presented by the accessor methods Error() and FamilyId(). Like the CSubConGenEventParamsGranted event, a notification for CSubConGenEventParamsRejected is received for each family in the parameter bundle that could not be negotiated successfully.

CSubConGenEventParamsChanged

This event occurs when the properties of a parameter family has been renegotiated due to some event on the network. It is not sent in response to a request to change the properties. The change could be the result of an error or just that the level of QoS has improved/worsened. If a new set of parameters are available they’ll be presented as with the CSubConGenEventParamsGranted event. The error status is presented via the Error() method.

CSubConGenEventSubConDown

This event occurs when the underlying sub-connection has been lost. This could be due to request for it to be closed, or some error on the network. The error status is presented via the Error() method.

[Top]


QoS Parameters

CSubConQosGenericParamSet

Parameter

Description

Bandwidth

Bandwidth the client requires

Maximum Burst Size

Maximum size of a burst of data the client can handle

Average Packet Size

Average packet size required (e.g. codec use)

Maximum Packet Size

Maximum packet size the client can handle

Delay

Acceptable Delay/Latency

Delay Variation

Acceptable variation in delay (also known as jitter)

Priority

Relative priority the client expects to give this channel compared to it’s other channels

Header mode

Specify whether the header size should be calculated by the QoS module or specified by the client. Default is to let the QoS module calculate it.

Name

Identity of a “well known” set of QoS Parameters.

The first seven parameters are available as both Up and Down link parameters.

If an extension parameter set is added to the family that contains conceptually identical parameters to those in the generic set, it is recommended that you set both instances (generic and extension) of those parameters.

CSubConQosIPLinkR99ParamSet / CSubConQosR99ParamSet

Getter and setter methods are provided for each parameter.

Note: This class is called CSubConQosIPLinkR99ParamSet in Symbian OS v9.2 and earlier and CSubConQosR99ParamSet from 9.3 onwards. The constants used for it are KSubConIPParamsUid and KSubConQosIPLinkR99ParamsType.

The following parameter sets are available in Symbian OS v9.3 onwards.

CSubConQosR5ParamSet

It inherits from the release 4/99 set CSubConQosR99ParamSet. Although it is possible to add both this parameter set and the R4/R99 one, it is not necessary and should not be done.

CSubConIMSExtParamSet

This class contains the IM CN Signalling Indicator flag.

[Top]


Code Examples

[Top]


Attaching to the default Sub-Connection

In the following example, the application wants to connect to the default sub-connection to set its properties. The application simply tries to connect a socket over the connection (which uses the default sub-connection) after it has set properties on the default sub-connection. An example of parameter creation can be found further down this page (Creating and setting properties for a Sub-Connection).

RSocketServ ss;
RConnection conn;
RSubConnection subconn;
RSocket sock;
TRequestStatus status;

// Connect to ESOCK
ss.Connect();

// Open an Connection
conn.Open(ss, KAfInet);

// Start the connection
conn.Start(status);
User::WaitForRequest(status);

// Attach to the default sub-connection
subconn.Open(ss, RSubConnection::EAttachToDefault, conn);

// Set Properties of the default sub-connection
subconn.SetParameters(…);

// Open a TCP socket on the connection (this is the same as using the default sub-connection)
sock.Open(ss, KAfInet, KSockStream, KProtocolInetTcp, conn);

_LIT(KRasAddr,"10.159.24.13");
const TInt KEchoPort = 7;

TInetAddr destAddr;
destAddr.Input(KRasAddr);
destAddr.SetPort(KEchoPort);

// Request the Socket to connect to the destination over the default sub-connection
sock.Connect(destAddr, status);

Note: Error handling is not included to aid clarity.

[Top]


Creating a new sub-connection - Socket connected over the sub-connection

The following example shows how an application can use a sub-connection explicitly via an RSubConnection instance, and tie an RSocket to the sub-connection that has had its properties set. The socket is connected over the sub-connection in this case (if the underlying technology allows this).

RSocketServ ss;
RConnection conn;
RSubConnection subconn;
RSocket sock;
TRequestStatus status;

// Connect to ESOCK
ss.Connect();

// Open an Connection
conn.Open(ss, KAfInet);

// Start the connection
conn.Start(status);
User::WaitForRequest(status);

// Create a new sub-connection
subconn.Open(ss, RSubConnection::ECreateNew, conn);

// Set Properties of the sub-connection
subconn.SetParameters(…);

// Open a TCP socket on the sub-connection
sock.Open(ss, KAfInet, KSockStream, KProtocolInetTcp, subconn);

_LIT(KRasAddr,"10.159.24.13");
const TInt KEchoPort = 7;

TInetAddr destAddr;
destAddr.Input(KRasAddr);
destAddr.SetPort(KEchoPort);

// Request the Socket to connect to the destination over the sub-connection
sock.Connect(destAddr, status);

Note: Error handling is not included to aid clarity.

[Top]


Creating a new sub-connection - Adding an already connected socket

The following example shows how an application can use a sub-connection explicitly via an RSubConnection instance, and tie an already connected RSocket to the sub-connection that has had its properties set (parameter creation is described in separate section):

RSocketServ ss;
RConnection conn;
RSubConnection subconn;
RSocket sock;
TRequestStatus status;

// Connect to ESOCK
ss.Connect();

// Open an Connection
conn.Open(ss, KAfInet);

// Start the connection
conn.Start(status);
User::WaitForRequest(status);

// Open a TCP socket on the connection
sock.Open(ss, KAfInet, KSockStream, KProtocolInetTcp, conn);

_LIT(KRasAddr,"10.159.24.13");
const TInt KEchoPort = 7;

TInetAddr destAddr;
destAddr.Input(KRasAddr);
destAddr.SetPort(KEchoPort);

// Connect the Socket to the destination over the connection (default sub-connection)
sock.Connect(destAddr, status);

// Create a new sub-connection
subconn.Open(ss, RSubConnection::ECreateNew, conn);

// Set Properties of the sub-connection
subconn.SetParameters(…);

// Move the connected socket onto the new sub-connection
TRequestStatus status;
subconn.Add(sock, status);

// Wait for socket to added
User::WaitForRequest(status);

Note: Error handling is not included to aid clarity.

[Top]


Creating and setting properties for a Sub-Connection

The following example shows how an application can create Quality of Service properties and assign them to a sub-connection:

// Create the container for all sub connection parameters
RSubConParameterBundle subconParams;
CleanupClosePushL(subconParams);

// Create a container for QoS sub connection parameters (Param bundle takes ownership)
CSubConParameterFamily* qosFamily = CSubConParameterFamily::NewL(subconParams,
    KSubConQoSFamily);

// Create the requested generic parameter set for QoS (Qos family takes ownership)
CSubConQosGenericParamSet* reqGenericParams = CSubConQosGenericParamSet::NewL(*qosFamily,                               
    CSubConParameterFamily::ERequested);

// Set the requested Generic Parameters
reqGenericParams->SetDownlinkBandwidth(128);
reqGenericParams->SetUplinkBandwidth(64);

// Create the acceptable generic parameter set for QoS (Qos family takes ownership)
CSubConQosGenericParamSet* accGenericParams = CSubConQosGenericParamSet::NewL(*qosFamily,                               
    CSubConParameterFamily::EAcceptable);

// Set the acceptable Generic Parameters
accGenericParams->SetDownlinkBandwidth(48);
accGenericParams->SetUplinkBandwidth(32);

// Create a requested technology specific parameter set for QoS (Qos family takes ownership)
CSubConQosR99ParamSet* reqRel99Params = CSubConQosR99ParamSet::NewL(*qosFamily,
    CSubConParameterFamily::ERequested);

// Set the requested Technology Specific Params
reqRel99Params->SetMaxSDUSize(1024);

// Create a acceptable technology specific parameter set for QoS (Qos family takes ownership)
CSubConQosR99ParamSet* accRel99Params = CSubConQosR99ParamSet::NewL(*qosFamily,
    CSubConParameterFamily::EAcceptable);

// Set the acceptable Technology Specific Params
accRel99Params->SetMaxSDUSize(512);

// Now open the sub-connection as normal…
………
………
// Create a new sub-connection
subconn.Open(ss, RSubConnection::ECreateNew, conn);

// Set Properties of the sub-connection
subconn.SetParameters(subconParams);

// Destroy parameters
CleanupStack::PopAndDestroy();         // subconParams

// Open a TCP socket on the sub-connection
sock.Open(ss, KAfInet, KSockStream, KProtocolInetTcp, subconn);

_LIT(KRasAddr,"10.159.24.13");
const TInt KEchoPort = 7;

TInetAddr destAddr;
destAddr.Input(KRasAddr);
destAddr.SetPort(KEchoPort);

// Connect the Socket to the destination over the sub-connection
sock.Connect(destAddr, status);
User::WaitForRequest(status);

// Fetch the granted qos
RSubConParameterBundle grantedParams;
subconn.GetParameters(grantedParams);

Note: Error handling is not included to aid clarity.

[Top]


Registering for events – Simple case

The following example shows the simplest case of how an application can register for events occurring on a sub-connection. In this example the application registers for notification of all events.

// Create the container for all sub connection parameters
RSubConParameterBundle subconParams;
CleanupClosePushL(subconParams);

………
………
// Create and initialise parameters sets as above
………
………

// Create a new sub-connection
subconn.Open(ss, RSubConnection::ECreateNew, conn);

TNotificationEventBuf eventBuffer;
TRequestStatus eventStatus;
subconn.EventNotification(eventBuffer, EFalse, eventStatus);

// Set Properties of the sub-connection
subconn.SetParameters(subconParams);

// Destroy parameters
CleanupStack::PopAndDestroy();         // subconParams

// Open and connect a TCP socket on the sub-connection
sock.Open(ss, KAfInet, KSockStream, KProtocolInetTcp, subconn);
sock.Connect(destAddr, status);
User::WaitForRequest(status);

// Negotiation may not occur until a socket is assigned to the sub-connection
// First event should be cSubConGenEventDataClientJoining
User::WaitForRequest(eventStatus);

// Next we’d expect a CSubconGenEventParamsGranted/ CSubconGenEventParamsRejected
subconn.EventNotification(eventBuffer, EFalse, eventStatus);
User::WaitForRequest(eventStatus);

Note: Error handling is not included to aid clarity.

[Top]


Registering for events – Using filters

The following example shows how to register for specific events by using filters. In this example the application registers for notification when sub-connection parameters have been granted or rejected. Each TEventFilter contains the factory Uid of the events and a mask of event Ids bitwise OR’d together.

// Create the container for all sub connection parameters
RSubConParameterBundle subconParams;
CleanupClosePushL(subconParams);

………
………
// Create and initialise parameters sets as above
………
………

// Create a new sub-connection
subconn.Open(ss, RSubConnection::ECreateNew, conn);

// Create event filter
TEventFilter filter;
filter.iEventGroupUid = KSubConnGenericEventsImplUid;
filter.iEventMask = KSubConGenericEventParamsRejected | KSubConGenericEventParamsGranted;

// Register for event
TNotificationEventBuf eventBuffer;
TRequestStatus eventStatus;
subconn.EventNotification(eventBuffer, &filter, 1, eventStatus);

// Set Properties of the sub-connection
subconn.SetParameters(subconParams);

// Destroy parameters
CleanupStack::PopAndDestroy();         // subconParams

// Open and connect a TCP socket on the sub-connection
sock.Open(ss, KAfInet, KSockStream, KProtocolInetTcp, subconn);
sock.Connect(destAddr, status);
User::WaitForRequest(status);

// Event should be CSubconGenEventParamsGranted/CSubconGenEventParamsRejected
User::WaitForRequest(eventStatus);

Note: Error handling is not included to aid clarity.

[Top]


Extracting information from received events

The following example shows how to extract the information contained within an event notification once it has been received.

// Create the container for all sub connection parameters
RSubConParameterBundle subconParams;
CleanupClosePushL(subconParams);

………
………
// Create and initialise parameters sets as above
………
………

// Create a new sub-connection
subconn.Open(ss, RSubConnection::ECreateNew, conn);

// Create filter, register for events, and set parameters as above
……
subconn.EventNotification(eventBuffer, &filter, 1, eventStatus);
……

// Open and connect a TCP socket on the sub-connection
……

// Receive the event notification
User::WaitForRequest(eventStatus);

CSubConNotificationEvent* event;
event = CSubConNotificationEvent::NewL(eventBuffer);
CleanupStack::PushL (event);

if (event->GroupId() == KSubConnGenericEventsImplUid
    && event->Id() == CSubConGenEventParamsRejected)
    {
    CSubConGenEventParamsRejected* rejectedEvent =
        static_cast< CSubConGenEventParamsRejected*>(event);

    TInt error = rejectedEvent->Error();
    ……
    // Do something with the error
    ……
    }

CleanupStack::PopAndDestroy (event);

Note: Error handling is not included to aid clarity.