networkcontrol/qoslib/src/qos_channel.cpp
changeset 0 af10295192d8
--- /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);
+	}
+