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
RSubConnection
s). 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.
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.
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.
CSubConQosGenericParamSet
|
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.
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.
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.
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.
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.
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.
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.
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.