networkcontrol/qoslib/src/qos_channel.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "pfqos_stream.h"
       
    17 #include "qoslib_glob.h"
       
    18 #include "qoslib.h"
       
    19 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    20 #include <networking/qoslib_internal.h>
       
    21 #endif
       
    22 
       
    23 //lint -e{708} does not like union initializers
       
    24 const TIp6Addr KInet6AddrMask = {{{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
       
    25 								0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}};
       
    26 
       
    27 
       
    28 
       
    29 //
       
    30 CChannel::CChannel(CQoSMan* aManager)
       
    31 	{
       
    32 	iManager = aManager;
       
    33 	iPending = ENone;
       
    34 	iCapabilities = 0;
       
    35 	iObserver = NULL;
       
    36 	iChannelId = -1;
       
    37 	iStatus = EInit;
       
    38 	}
       
    39 
       
    40 CChannel::~CChannel()
       
    41 	{
       
    42 	iManager->RemoveQoSChannel(this);
       
    43 	}
       
    44 
       
    45 CChannel* CChannel::NewL(CQoSMan* aManager, RSocket& aSocket, 
       
    46 	CQoSParameters* aSpec)
       
    47 	{
       
    48 	CChannel* channel = new (ELeave) CChannel(aManager);
       
    49 	CleanupStack::PushL(channel);
       
    50 	channel->ConstructL(aSocket, aSpec);
       
    51 	CleanupStack::Pop();
       
    52 	return channel;
       
    53 	}
       
    54 
       
    55 void CChannel::ConstructL(RSocket& aSocket, CQoSParameters* aSpec)
       
    56 	{
       
    57 	if (aSpec)
       
    58 		{
       
    59 		iPolicy.CopyL(*aSpec);
       
    60 		}
       
    61 
       
    62 	TInt ret = iRequestSelector.SetAddr(aSocket);
       
    63 	if (ret != KErrNone)
       
    64 		{
       
    65 		User::Leave(ret);
       
    66 		}
       
    67 	}
       
    68 
       
    69 TInt CChannel::Close()
       
    70 	{
       
    71 	CRequest* request=NULL;
       
    72 	TRAPD(err, request = CRequest::NewL(NULL, KQoSDefaultBufSize));
       
    73 	if (err == KErrNone)
       
    74 		{
       
    75 		request->iMsg->Init(EPfqosDeleteChannel);
       
    76 		request->iMsg->AddChannel(iChannelId);
       
    77 		iPending = EPendingDelete;
       
    78 		iManager->Send(request);
       
    79 		}
       
    80 	return err;
       
    81 	}
       
    82 
       
    83 void CChannel::ProcessEvent(TPfqosMessage& aMsg)
       
    84 	{
       
    85 	iCapabilities = aMsg.iEvent.iExt->event_value;
       
    86 	switch (aMsg.iEvent.iExt->event_type)
       
    87 		{
       
    88 		
       
    89 		case KPfqosEventFailure:
       
    90 			if (iStatus == EChannelCreated)
       
    91 				{
       
    92 				iStatus = EInit;
       
    93 				}
       
    94 			if (iObserver && (iEventMask & EQoSEventFailure))
       
    95 				{
       
    96 				ParseExtensions(aMsg, iPolicy);
       
    97 				CQoSFailureEvent event(iPolicy, 
       
    98 					aMsg.iBase.iMsg->pfqos_msg_errno);
       
    99 				iObserver->Event(event);
       
   100 				}
       
   101 			break;
       
   102 		
       
   103 		case KPfqosEventConfirm:
       
   104 			if (iStatus == EChannelCreated)
       
   105 				{
       
   106 				iStatus = EChannelReady;
       
   107 				}
       
   108 			if (iObserver && iEventMask & EQoSEventConfirm)
       
   109 				{
       
   110 				ParseExtensions(aMsg, iPolicy);
       
   111 				CQoSConfirmEvent event(iPolicy);
       
   112 				iObserver->Event(event);
       
   113 				}
       
   114 			break;
       
   115 		
       
   116 		case KPfqosEventAdapt:
       
   117 			if (iStatus == EChannelCreated)
       
   118 				{
       
   119 				iStatus = EChannelReady;
       
   120 				}
       
   121 			if (iObserver && iEventMask & EQoSEventAdapt)
       
   122 				{
       
   123 				ParseExtensions(aMsg, iPolicy);
       
   124 				CQoSAdaptEvent event(iPolicy, 
       
   125 					aMsg.iBase.iMsg->pfqos_msg_errno);
       
   126 				iObserver->Event(event);
       
   127 				}
       
   128 			break;
       
   129 		
       
   130 		case KPfqosEventJoin:
       
   131 			if (iObserver && iEventMask & EQoSEventJoin)
       
   132 				{
       
   133 				TInt reason = aMsg.iBase.iMsg->pfqos_msg_errno;
       
   134 				TQoSSelector sel;
       
   135 				CreateSelector(sel, aMsg);
       
   136 				CQoSJoinEvent event(sel, reason);
       
   137 				iObserver->Event(event);
       
   138 				}
       
   139 			break;
       
   140 		
       
   141 		case KPfqosEventLeave:
       
   142 			if (iObserver && iEventMask & EQoSEventLeave)
       
   143 				{
       
   144 				TInt reason = aMsg.iBase.iMsg->pfqos_msg_errno;
       
   145 				TQoSSelector sel;
       
   146 				CreateSelector(sel, aMsg);
       
   147 				CQoSLeaveEvent event(sel, reason);
       
   148 				iObserver->Event(event);
       
   149 				}
       
   150 			break;
       
   151 		
       
   152 		default:
       
   153 			return;
       
   154 		}
       
   155 	}
       
   156 
       
   157 void CChannel::ProcessReply(TPfqosMessage& aMsg)
       
   158 	{
       
   159 	TInt aErrorCode = aMsg.iBase.iMsg->pfqos_msg_errno;
       
   160 
       
   161 	if (aErrorCode)
       
   162 		{
       
   163 		NotifyError(aErrorCode);
       
   164 		}
       
   165 	else
       
   166 		{
       
   167 		switch (iPending)
       
   168 			{
       
   169 			case EPendingOpenExisting:
       
   170 				iPending = ENone;
       
   171 				iChannelId = aMsg.iChannel.iExt->channel_id;
       
   172 				// mmm
       
   173 				iStatus = EChannelReady;
       
   174 				// mmm
       
   175 				
       
   176 				if (iObserver && iEventMask & EQoSEventChannel)
       
   177 					{
       
   178 					ParseExtensions(aMsg, iPolicy);
       
   179 					CQoSChannelEvent event(&iPolicy, KErrNone);
       
   180 					iObserver->Event(event);
       
   181 					}
       
   182 				break;
       
   183 		
       
   184 			case EPendingOpenExistingSetQoS:
       
   185 				iChannelId = aMsg.iChannel.iExt->channel_id;
       
   186 				iStatus = EChannelCreated;
       
   187 				if (iObserver && iEventMask & EQoSEventChannel)
       
   188 					{
       
   189 					CQoSChannelEvent event(NULL, KErrNone);
       
   190 					iObserver->Event(event);
       
   191 					}
       
   192 				TRAPD(err, iManager->SetQoSL(*this));
       
   193 				//lint -e{961} does not like missing final 'else'
       
   194 				if (err == KErrNone)
       
   195 					{
       
   196 					iPending = EPendingSetPolicy;
       
   197 					}
       
   198 				else if (iObserver && iEventMask & EQoSEventFailure)
       
   199 					{
       
   200 					CQoSFailureEvent event(iPolicy, err);
       
   201 					iObserver->Event(event);
       
   202 					}
       
   203 				break;
       
   204 		
       
   205 			case EPendingOpen:
       
   206 				{
       
   207 				_LIT(KText1, "CChannel::ProcessReply");
       
   208 				__ASSERT_ALWAYS((aMsg.iChannel.iExt != NULL), 
       
   209 					User::Panic(KText1, 0));
       
   210 				iPending = ENone;
       
   211 				iChannelId = aMsg.iChannel.iExt->channel_id;
       
   212 				iStatus = EChannelCreated;
       
   213 				}
       
   214 				break;
       
   215 		
       
   216 			case EPendingDelete:
       
   217 				delete this;
       
   218 				break;
       
   219 		
       
   220 			case EPendingSetPolicy:
       
   221 			case EPendingJoin:
       
   222 			case EPendingLeave:
       
   223 			default:
       
   224 				iPending = ENone;
       
   225 				break;
       
   226 			}
       
   227 		}
       
   228 	}
       
   229 
       
   230 
       
   231 TBool CChannel::Match(TInt aChannelId)
       
   232 	{
       
   233 	if (aChannelId >= 0 && aChannelId == iChannelId)
       
   234 		{
       
   235 		return ETrue;
       
   236 		}
       
   237 	return EFalse;
       
   238 	}
       
   239 
       
   240 
       
   241 TBool CChannel::MatchReply(const TPfqosMessage& aMsg, TUint8 aMsgType)
       
   242 	{
       
   243 	//lint -e{961} does not like missing final 'else'
       
   244 	if (((iPending == EPendingOpenExisting && 
       
   245 		  aMsgType == EPfqosOpenExistingChannel) ||
       
   246 		 (iPending == EPendingOpenExistingSetQoS && 
       
   247 		  aMsgType == EPfqosOpenExistingChannel) ||
       
   248 		 (iPending == EPendingOpen && aMsgType == EPfqosCreateChannel) ||
       
   249 		 (iPending == EPendingJoin && aMsgType == EPfqosJoin) || 
       
   250 		 (iPending == EPendingLeave && aMsgType == EPfqosLeave)) && 
       
   251 		 (iRequestSelector.GetDst().Match(*aMsg.iDstAddr.iAddr)) &&
       
   252 		 (iRequestSelector.GetSrc().Match(*aMsg.iSrcAddr.iAddr)) &&
       
   253 		 (iRequestSelector.Protocol() == aMsg.iSelector.iExt->protocol) &&
       
   254 		 (iRequestSelector.GetDst().Port() == aMsg.iDstAddr.iAddr->Port()) &&
       
   255 		 (iRequestSelector.GetSrc().Port() == aMsg.iSrcAddr.iAddr->Port()) &&
       
   256 		 (iRequestSelector.MaxPortDst() == 
       
   257 		  aMsg.iDstAddr.iExt->pfqos_port_max) &&
       
   258 		 (iRequestSelector.MaxPortSrc() == 
       
   259 		  aMsg.iSrcAddr.iExt->pfqos_port_max))
       
   260 		 {
       
   261 		return ETrue;
       
   262 		}
       
   263 	else if (((iPending == EPendingDelete && 
       
   264 			   aMsgType == EPfqosDeleteChannel) ||
       
   265 			  (iPending == EPendingSetPolicy && 
       
   266 			   aMsgType == EPfqosConfigChannel))// ||
       
   267 		   && (iChannelId == aMsg.iChannel.iExt->channel_id))
       
   268 		{
       
   269 		return ETrue;
       
   270 		}
       
   271 
       
   272 	return EFalse;
       
   273 	}
       
   274 
       
   275 TInt CChannel::OpenExisting()
       
   276 	{
       
   277 	TRAPD(err, iManager->OpenExistingL(*this, iRequestSelector));
       
   278 	if (err == KErrNone)
       
   279 		{
       
   280 		iPending = EPendingOpenExisting;
       
   281 		}
       
   282 	return err;
       
   283 	}
       
   284 
       
   285 TInt CChannel::SetQoS(CQoSParameters& aPolicy)
       
   286 	{
       
   287 	if (iPending)
       
   288 		{
       
   289 		if (iPending == EPendingOpenExisting)
       
   290 			{
       
   291 			TRAPD(err, iPolicy.CopyL(aPolicy));
       
   292 			if (err == KErrNone)
       
   293 				{
       
   294 				iPending = EPendingOpenExistingSetQoS;
       
   295 				}
       
   296 			return err;
       
   297 			}
       
   298 		else
       
   299 			{
       
   300 			return KErrInUse;
       
   301 			}
       
   302 		}
       
   303 	TRAPD(err, iPolicy.CopyL(aPolicy));
       
   304 	if (err != KErrNone)
       
   305 		{
       
   306 		return err;
       
   307 		}
       
   308 	if (iStatus == EInit)
       
   309 		{
       
   310 		TRAP(err, iManager->CreateL(*this, iRequestSelector));
       
   311 		if (err == KErrNone)
       
   312 			{
       
   313 			iPending = EPendingOpen;
       
   314 			}
       
   315 		}
       
   316 	else
       
   317 		{
       
   318 		TRAP(err, iManager->SetQoSL(*this));
       
   319 		if (err == KErrNone)
       
   320 			{
       
   321 			iPending = EPendingSetPolicy;
       
   322 			}
       
   323 		}
       
   324 	return err;
       
   325 	}
       
   326 
       
   327 TInt CChannel::Join(RSocket& aSocket)
       
   328 	{
       
   329 	if (iStatus != EChannelReady)
       
   330 		{
       
   331 		return KErrNotReady;
       
   332 		}
       
   333 	if (iPending != ENone)
       
   334 		{
       
   335 		return KErrInUse;
       
   336 		}
       
   337 	TInt err = iRequestSelector.SetAddr(aSocket);
       
   338 	if (err != KErrNone)
       
   339 		{
       
   340 		return err;
       
   341 		}
       
   342 	TRAP(err, iManager->JoinL(*this, iRequestSelector));
       
   343 	if (err == KErrNone)
       
   344 		{
       
   345 		iPending = EPendingJoin;
       
   346 		}
       
   347 	return err;
       
   348 	}
       
   349 
       
   350 TInt CChannel::Leave(RSocket& aSocket)
       
   351 	{
       
   352 	if (iStatus != EChannelReady)
       
   353 		{
       
   354 		return KErrNotReady;
       
   355 		}
       
   356 	if (iPending != ENone)
       
   357 		{
       
   358 		return KErrInUse;
       
   359 		}
       
   360 	TInt err = iRequestSelector.SetAddr(aSocket);
       
   361 	if (err != KErrNone)
       
   362 		{
       
   363 		return err;
       
   364 		}
       
   365 	TRAP(err, iManager->LeaveL(*this, iRequestSelector));
       
   366 	if (err == KErrNone)
       
   367 		{
       
   368 		iPending = EPendingLeave;
       
   369 		}
       
   370 	return err;
       
   371 	}
       
   372 
       
   373 TInt CChannel::GetCapabilities(TUint& aCapabilities)
       
   374 	{
       
   375 	aCapabilities = iCapabilities;
       
   376 	return KErrNone;
       
   377 	}
       
   378 
       
   379 void CChannel::NotifyError(TInt aReason)
       
   380 	{
       
   381 	TPendingStatus status = iPending;
       
   382 	iPending = ENone;
       
   383 
       
   384 	if (aReason)
       
   385 		{
       
   386 		switch (status)
       
   387 			{
       
   388 			case EPendingSetPolicy:
       
   389 				if (iObserver && iEventMask & EQoSEventFailure)
       
   390 					{
       
   391 					CQoSFailureEvent event(iPolicy, aReason);
       
   392 					iObserver->Event(event);
       
   393 					}
       
   394 				break;
       
   395 		
       
   396 			case EPendingOpen:
       
   397 				if (iObserver && iEventMask & EQoSEventFailure)
       
   398 					{
       
   399 					CQoSFailureEvent event(iPolicy, aReason);
       
   400 					iObserver->Event(event);
       
   401 					}
       
   402 				break;
       
   403 		
       
   404 			case EPendingJoin:
       
   405 				if (iObserver && iEventMask & EQoSEventJoin)
       
   406 					{
       
   407 					CQoSJoinEvent event(iRequestSelector, aReason);
       
   408 					iObserver->Event(event);
       
   409 					}
       
   410 				break;
       
   411 		
       
   412 			case EPendingLeave:
       
   413 				if (iObserver && iEventMask & EQoSEventLeave)
       
   414 					{
       
   415 					CQoSLeaveEvent event(iRequestSelector, aReason);
       
   416 					iObserver->Event(event);
       
   417 					}
       
   418 				break;
       
   419 		
       
   420 			case EPendingOpenExisting:
       
   421 				if (iObserver && iEventMask & EQoSEventChannel)
       
   422 					{
       
   423 					CQoSChannelEvent event(NULL, aReason);
       
   424 					iObserver->Event(event);
       
   425 					}
       
   426 				break;
       
   427 		
       
   428 			case EPendingOpenExistingSetQoS:
       
   429 				TRAPD(err, iManager->CreateL(*this, iRequestSelector));
       
   430 				//lint -e{961} does not like missing final 'else'
       
   431 				if (err == KErrNone)
       
   432 					{
       
   433 					iPending = EPendingOpen;
       
   434 					}
       
   435 				else if (iObserver && iEventMask & EQoSEventFailure)
       
   436 					{
       
   437 					CQoSFailureEvent event(iPolicy, err);
       
   438 					iObserver->Event(event);
       
   439 					}
       
   440 				break;
       
   441 		
       
   442 			default:
       
   443 				break;
       
   444 			}
       
   445 		}
       
   446 	}
       
   447 
       
   448 
       
   449 void CChannel::CreateSelector(TQoSSelector& aSelector, 
       
   450 	const TPfqosMessage& aMsg)
       
   451 	{
       
   452 	TInetAddr src;
       
   453 	TInetAddr srcmask;
       
   454 	
       
   455 	src = *aMsg.iSrcAddr.iAddr;
       
   456 	src.SetFamily(KAFUnspec);
       
   457 	src.SetAddress(KInet6AddrNone);
       
   458 	srcmask.SetAddress(KInet6AddrMask);
       
   459 	aSelector.SetAddr(src, 
       
   460 			  srcmask, 
       
   461 			  *aMsg.iDstAddr.iAddr, 
       
   462 			  *aMsg.iDstAddr.iPrefix, 
       
   463 			  aMsg.iSelector.iExt->protocol, 
       
   464 			  aMsg.iSrcAddr.iExt->pfqos_port_max,
       
   465 			  aMsg.iDstAddr.iExt->pfqos_port_max);
       
   466 	aSelector.SetIapId(aMsg.iSelector.iExt->iap_id);
       
   467 	}
       
   468