diff -r 000000000000 -r af10295192d8 networkcontrol/qoslib/src/qos_channel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkcontrol/qoslib/src/qos_channel.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,468 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "pfqos_stream.h" +#include "qoslib_glob.h" +#include "qoslib.h" +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif + +//lint -e{708} does not like union initializers +const TIp6Addr KInet6AddrMask = {{{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}}; + + + +// +CChannel::CChannel(CQoSMan* aManager) + { + iManager = aManager; + iPending = ENone; + iCapabilities = 0; + iObserver = NULL; + iChannelId = -1; + iStatus = EInit; + } + +CChannel::~CChannel() + { + iManager->RemoveQoSChannel(this); + } + +CChannel* CChannel::NewL(CQoSMan* aManager, RSocket& aSocket, + CQoSParameters* aSpec) + { + CChannel* channel = new (ELeave) CChannel(aManager); + CleanupStack::PushL(channel); + channel->ConstructL(aSocket, aSpec); + CleanupStack::Pop(); + return channel; + } + +void CChannel::ConstructL(RSocket& aSocket, CQoSParameters* aSpec) + { + if (aSpec) + { + iPolicy.CopyL(*aSpec); + } + + TInt ret = iRequestSelector.SetAddr(aSocket); + if (ret != KErrNone) + { + User::Leave(ret); + } + } + +TInt CChannel::Close() + { + CRequest* request=NULL; + TRAPD(err, request = CRequest::NewL(NULL, KQoSDefaultBufSize)); + if (err == KErrNone) + { + request->iMsg->Init(EPfqosDeleteChannel); + request->iMsg->AddChannel(iChannelId); + iPending = EPendingDelete; + iManager->Send(request); + } + return err; + } + +void CChannel::ProcessEvent(TPfqosMessage& aMsg) + { + iCapabilities = aMsg.iEvent.iExt->event_value; + switch (aMsg.iEvent.iExt->event_type) + { + + case KPfqosEventFailure: + if (iStatus == EChannelCreated) + { + iStatus = EInit; + } + if (iObserver && (iEventMask & EQoSEventFailure)) + { + ParseExtensions(aMsg, iPolicy); + CQoSFailureEvent event(iPolicy, + aMsg.iBase.iMsg->pfqos_msg_errno); + iObserver->Event(event); + } + break; + + case KPfqosEventConfirm: + if (iStatus == EChannelCreated) + { + iStatus = EChannelReady; + } + if (iObserver && iEventMask & EQoSEventConfirm) + { + ParseExtensions(aMsg, iPolicy); + CQoSConfirmEvent event(iPolicy); + iObserver->Event(event); + } + break; + + case KPfqosEventAdapt: + if (iStatus == EChannelCreated) + { + iStatus = EChannelReady; + } + if (iObserver && iEventMask & EQoSEventAdapt) + { + ParseExtensions(aMsg, iPolicy); + CQoSAdaptEvent event(iPolicy, + aMsg.iBase.iMsg->pfqos_msg_errno); + iObserver->Event(event); + } + break; + + case KPfqosEventJoin: + if (iObserver && iEventMask & EQoSEventJoin) + { + TInt reason = aMsg.iBase.iMsg->pfqos_msg_errno; + TQoSSelector sel; + CreateSelector(sel, aMsg); + CQoSJoinEvent event(sel, reason); + iObserver->Event(event); + } + break; + + case KPfqosEventLeave: + if (iObserver && iEventMask & EQoSEventLeave) + { + TInt reason = aMsg.iBase.iMsg->pfqos_msg_errno; + TQoSSelector sel; + CreateSelector(sel, aMsg); + CQoSLeaveEvent event(sel, reason); + iObserver->Event(event); + } + break; + + default: + return; + } + } + +void CChannel::ProcessReply(TPfqosMessage& aMsg) + { + TInt aErrorCode = aMsg.iBase.iMsg->pfqos_msg_errno; + + if (aErrorCode) + { + NotifyError(aErrorCode); + } + else + { + switch (iPending) + { + case EPendingOpenExisting: + iPending = ENone; + iChannelId = aMsg.iChannel.iExt->channel_id; + // mmm + iStatus = EChannelReady; + // mmm + + if (iObserver && iEventMask & EQoSEventChannel) + { + ParseExtensions(aMsg, iPolicy); + CQoSChannelEvent event(&iPolicy, KErrNone); + iObserver->Event(event); + } + break; + + case EPendingOpenExistingSetQoS: + iChannelId = aMsg.iChannel.iExt->channel_id; + iStatus = EChannelCreated; + if (iObserver && iEventMask & EQoSEventChannel) + { + CQoSChannelEvent event(NULL, KErrNone); + iObserver->Event(event); + } + TRAPD(err, iManager->SetQoSL(*this)); + //lint -e{961} does not like missing final 'else' + if (err == KErrNone) + { + iPending = EPendingSetPolicy; + } + else if (iObserver && iEventMask & EQoSEventFailure) + { + CQoSFailureEvent event(iPolicy, err); + iObserver->Event(event); + } + break; + + case EPendingOpen: + { + _LIT(KText1, "CChannel::ProcessReply"); + __ASSERT_ALWAYS((aMsg.iChannel.iExt != NULL), + User::Panic(KText1, 0)); + iPending = ENone; + iChannelId = aMsg.iChannel.iExt->channel_id; + iStatus = EChannelCreated; + } + break; + + case EPendingDelete: + delete this; + break; + + case EPendingSetPolicy: + case EPendingJoin: + case EPendingLeave: + default: + iPending = ENone; + break; + } + } + } + + +TBool CChannel::Match(TInt aChannelId) + { + if (aChannelId >= 0 && aChannelId == iChannelId) + { + return ETrue; + } + return EFalse; + } + + +TBool CChannel::MatchReply(const TPfqosMessage& aMsg, TUint8 aMsgType) + { + //lint -e{961} does not like missing final 'else' + if (((iPending == EPendingOpenExisting && + aMsgType == EPfqosOpenExistingChannel) || + (iPending == EPendingOpenExistingSetQoS && + aMsgType == EPfqosOpenExistingChannel) || + (iPending == EPendingOpen && aMsgType == EPfqosCreateChannel) || + (iPending == EPendingJoin && aMsgType == EPfqosJoin) || + (iPending == EPendingLeave && aMsgType == EPfqosLeave)) && + (iRequestSelector.GetDst().Match(*aMsg.iDstAddr.iAddr)) && + (iRequestSelector.GetSrc().Match(*aMsg.iSrcAddr.iAddr)) && + (iRequestSelector.Protocol() == aMsg.iSelector.iExt->protocol) && + (iRequestSelector.GetDst().Port() == aMsg.iDstAddr.iAddr->Port()) && + (iRequestSelector.GetSrc().Port() == aMsg.iSrcAddr.iAddr->Port()) && + (iRequestSelector.MaxPortDst() == + aMsg.iDstAddr.iExt->pfqos_port_max) && + (iRequestSelector.MaxPortSrc() == + aMsg.iSrcAddr.iExt->pfqos_port_max)) + { + return ETrue; + } + else if (((iPending == EPendingDelete && + aMsgType == EPfqosDeleteChannel) || + (iPending == EPendingSetPolicy && + aMsgType == EPfqosConfigChannel))// || + && (iChannelId == aMsg.iChannel.iExt->channel_id)) + { + return ETrue; + } + + return EFalse; + } + +TInt CChannel::OpenExisting() + { + TRAPD(err, iManager->OpenExistingL(*this, iRequestSelector)); + if (err == KErrNone) + { + iPending = EPendingOpenExisting; + } + return err; + } + +TInt CChannel::SetQoS(CQoSParameters& aPolicy) + { + if (iPending) + { + if (iPending == EPendingOpenExisting) + { + TRAPD(err, iPolicy.CopyL(aPolicy)); + if (err == KErrNone) + { + iPending = EPendingOpenExistingSetQoS; + } + return err; + } + else + { + return KErrInUse; + } + } + TRAPD(err, iPolicy.CopyL(aPolicy)); + if (err != KErrNone) + { + return err; + } + if (iStatus == EInit) + { + TRAP(err, iManager->CreateL(*this, iRequestSelector)); + if (err == KErrNone) + { + iPending = EPendingOpen; + } + } + else + { + TRAP(err, iManager->SetQoSL(*this)); + if (err == KErrNone) + { + iPending = EPendingSetPolicy; + } + } + return err; + } + +TInt CChannel::Join(RSocket& aSocket) + { + if (iStatus != EChannelReady) + { + return KErrNotReady; + } + if (iPending != ENone) + { + return KErrInUse; + } + TInt err = iRequestSelector.SetAddr(aSocket); + if (err != KErrNone) + { + return err; + } + TRAP(err, iManager->JoinL(*this, iRequestSelector)); + if (err == KErrNone) + { + iPending = EPendingJoin; + } + return err; + } + +TInt CChannel::Leave(RSocket& aSocket) + { + if (iStatus != EChannelReady) + { + return KErrNotReady; + } + if (iPending != ENone) + { + return KErrInUse; + } + TInt err = iRequestSelector.SetAddr(aSocket); + if (err != KErrNone) + { + return err; + } + TRAP(err, iManager->LeaveL(*this, iRequestSelector)); + if (err == KErrNone) + { + iPending = EPendingLeave; + } + return err; + } + +TInt CChannel::GetCapabilities(TUint& aCapabilities) + { + aCapabilities = iCapabilities; + return KErrNone; + } + +void CChannel::NotifyError(TInt aReason) + { + TPendingStatus status = iPending; + iPending = ENone; + + if (aReason) + { + switch (status) + { + case EPendingSetPolicy: + if (iObserver && iEventMask & EQoSEventFailure) + { + CQoSFailureEvent event(iPolicy, aReason); + iObserver->Event(event); + } + break; + + case EPendingOpen: + if (iObserver && iEventMask & EQoSEventFailure) + { + CQoSFailureEvent event(iPolicy, aReason); + iObserver->Event(event); + } + break; + + case EPendingJoin: + if (iObserver && iEventMask & EQoSEventJoin) + { + CQoSJoinEvent event(iRequestSelector, aReason); + iObserver->Event(event); + } + break; + + case EPendingLeave: + if (iObserver && iEventMask & EQoSEventLeave) + { + CQoSLeaveEvent event(iRequestSelector, aReason); + iObserver->Event(event); + } + break; + + case EPendingOpenExisting: + if (iObserver && iEventMask & EQoSEventChannel) + { + CQoSChannelEvent event(NULL, aReason); + iObserver->Event(event); + } + break; + + case EPendingOpenExistingSetQoS: + TRAPD(err, iManager->CreateL(*this, iRequestSelector)); + //lint -e{961} does not like missing final 'else' + if (err == KErrNone) + { + iPending = EPendingOpen; + } + else if (iObserver && iEventMask & EQoSEventFailure) + { + CQoSFailureEvent event(iPolicy, err); + iObserver->Event(event); + } + break; + + default: + break; + } + } + } + + +void CChannel::CreateSelector(TQoSSelector& aSelector, + const TPfqosMessage& aMsg) + { + TInetAddr src; + TInetAddr srcmask; + + src = *aMsg.iSrcAddr.iAddr; + src.SetFamily(KAFUnspec); + src.SetAddress(KInet6AddrNone); + srcmask.SetAddress(KInet6AddrMask); + aSelector.SetAddr(src, + srcmask, + *aMsg.iDstAddr.iAddr, + *aMsg.iDstAddr.iPrefix, + aMsg.iSelector.iExt->protocol, + aMsg.iSrcAddr.iExt->pfqos_port_max, + aMsg.iDstAddr.iExt->pfqos_port_max); + aSelector.SetIapId(aMsg.iSelector.iExt->iap_id); + } +