--- /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 <networking/qoslib_internal.h>
+#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);
+ }
+