authorisation/userpromptservice/examples/integration/tmsgserver/tmsgserver.cpp
changeset 8 35751d3474b7
equal deleted inserted replaced
2:675a964f4eb5 8:35751d3474b7
       
     1 /*
       
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * Example code
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include "tmsgcommon.h"
       
    21 #include "tmsgserver.h"
       
    22 #include <e32cmn.h>
       
    23 #include <e32debug.h>
       
    24 
       
    25 inline CShutdown::CShutdown() :CTimer(-1) {CActiveScheduler::Add(this);}
       
    26 inline void CShutdown::ConstructL() {CTimer::ConstructL();}
       
    27 inline void CShutdown::Start() {After(KMyShutdownDelay);}
       
    28 
       
    29 void CShutdown::RunL()
       
    30 	{
       
    31 	CActiveScheduler::Stop();
       
    32 	}
       
    33 
       
    34 
       
    35 // CMsgServer ****************************************************************
       
    36 inline UserPromptService::RUpsSession& CMsgServer::Ups() {return iUps;}
       
    37 
       
    38 const TInt CMsgServer::iRanges[KPolicyRanges] =
       
    39 	{
       
    40 	ESendMsg,			// network services requried
       
    41 	ECancelSendMsg,		// no capability needed to request
       
    42 	ESeperatorEndAll
       
    43 	};
       
    44 
       
    45 const TUint8 CMsgServer::iElementsIndex[KPolicyRanges] = 
       
    46 	{
       
    47 	0,								// capability check for networkservices
       
    48 	EAlwaysPass,					// no check needed to cancel a request
       
    49 	CPolicyServer::ENotSupported	
       
    50 	};
       
    51 
       
    52 static const TInt KMsgServerCustomFailureAction = -1;
       
    53 
       
    54 const CPolicyServer::TPolicyElement CMsgServer::iPolicyElements[KPolicyElements] =
       
    55 	{
       
    56 	{_INIT_SECURITY_POLICY_C1(ECapabilityNetworkServices), KMsgServerCustomFailureAction}
       
    57 	};
       
    58 
       
    59 const CPolicyServer::TPolicy CMsgServer::iPolicy =
       
    60 	{
       
    61 	CPolicyServer::EAlwaysPass, // so that any client can connect	
       
    62 	KPolicyRanges,									 
       
    63 	iRanges,
       
    64 	iElementsIndex,
       
    65 	iPolicyElements,
       
    66 	};
       
    67 
       
    68 
       
    69 CMsgServer::CMsgServer()
       
    70 	: CPolicyServer(EPriorityStandard, iPolicy, ESharableSessions)
       
    71 	{
       
    72 	}
       
    73 
       
    74 CMsgServer::~CMsgServer()
       
    75 	{
       
    76 	iUps.Close();
       
    77 	}
       
    78 
       
    79 CMsgServer* CMsgServer::NewLC()
       
    80 	{
       
    81 	CMsgServer* self = new(ELeave) CMsgServer();
       
    82 	CleanupStack::PushL(self);
       
    83 	self->ConstructL();
       
    84 	return self;
       
    85 	}
       
    86 
       
    87 void CMsgServer::ConstructL() 
       
    88 	{
       
    89 	// Create the RUpsSession
       
    90 	// A sub-session is created for each client
       
    91 	User::LeaveIfError(iUps.Connect());
       
    92 
       
    93 	StartL(KMsgServerName);
       
    94 	iShutdown.ConstructL();
       
    95 	iShutdown.Start();	
       
    96 	}
       
    97 
       
    98 CPolicyServer::TCustomResult CMsgServer::CustomFailureActionL(const RMessage2& aMessage, TInt /*aAction*/, const TSecurityInfo& /*aMissing*/)
       
    99 /** This function is only invoked for requests that allow UPS authorisation. The 
       
   100  * message may be rejected later if the user denies the request.
       
   101  */
       
   102 	{
       
   103 	CSession2* s = aMessage.Session();
       
   104 	__ASSERT_ALWAYS(s != NULL, User::Invariant());
       
   105 	CMsgServerSession* session = static_cast<CMsgServerSession*>(s);
       
   106 	session->SetPlatsecResult(EFalse);	
       
   107 	return CPolicyServer::EPass;	// The request may be rejected later by the UPS
       
   108 	}
       
   109 
       
   110 CSession2* CMsgServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
       
   111 	{
       
   112 	TVersion v(KMsgServerVersionMajor, KMsgServerVersionMinor, KMsgServerVersionBuild);
       
   113 	if (!User::QueryVersionSupported(v,aVersion))
       
   114 		{
       
   115 		User::Leave(KErrNotSupported);		
       
   116 		}
       
   117 	return new(ELeave) CMsgServerSession();
       
   118 	}
       
   119 
       
   120 void CMsgServer::AddSession()
       
   121 	{
       
   122 	++iSessionCount;
       
   123 	iShutdown.Cancel();
       
   124 	}
       
   125 
       
   126 void CMsgServer::DropSession()
       
   127 	{
       
   128 	if (--iSessionCount==0)	iShutdown.Start();
       
   129 	}
       
   130 
       
   131 void PanicClient(const RMessagePtr2& aMessage,TMsgServerPanic aPanic)
       
   132 	{
       
   133 	aMessage.Panic(KMsgServerName,aPanic);
       
   134 	}
       
   135 
       
   136 // CMsgServerSession *********************************************************
       
   137 inline CMsgServer& CMsgServerSession::Server()
       
   138 {return *static_cast<CMsgServer*>(const_cast<CServer2*>(CSession2::Server()));}
       
   139 
       
   140 CMsgServerSession::CMsgServerSession()
       
   141 	: iPlatsecResult(ETrue)
       
   142 	{
       
   143 	}
       
   144 
       
   145 CMsgServerSession::~CMsgServerSession()
       
   146 	{
       
   147 	delete iProcessor;	
       
   148 	iAuth.Close();
       
   149 	Server().DropSession();
       
   150 	}
       
   151 
       
   152 void CMsgServerSession::CreateL()
       
   153 	{
       
   154 	Server().AddSession();
       
   155 	iProcessor = CMsgProcessor::NewL(iAuth);
       
   156 	}
       
   157 
       
   158 void CMsgServerSession::ServiceL(const RMessage2& aMessage)
       
   159 	{
       
   160 	if (! iAuthInitialised)
       
   161 		{
       
   162 		RThread client;
       
   163 		aMessage.ClientL(client);
       
   164 		CleanupClosePushL(client);
       
   165 		User::LeaveIfError(iAuth.Initialise(Server().Ups(), client));
       
   166 		CleanupStack::PopAndDestroy(&client);
       
   167 		iAuthInitialised = ETrue;
       
   168 		}	
       
   169 	
       
   170 	iProcessor->ProcessL(aMessage, iPlatsecResult);
       
   171 	// Reset to 'passed' for next message because SetPlatsecResult is only ever called
       
   172 	// when a check fails.
       
   173 	iPlatsecResult = ETrue;	
       
   174 	}
       
   175 
       
   176 void CMsgServerSession::SetPlatsecResult(TBool aResult)
       
   177 	{
       
   178 	iPlatsecResult = aResult;
       
   179 	}
       
   180 
       
   181 // CMsgProcessor *********************************************************((((
       
   182 CMsgProcessor* CMsgProcessor::NewL(UserPromptService::RUpsSubsession& aAuth)
       
   183 	{
       
   184 	CMsgProcessor* self = new(ELeave) CMsgProcessor(aAuth);
       
   185 	CleanupStack::PushL(self);
       
   186 	self->ConstructL();
       
   187 	CleanupStack::Pop(self);
       
   188 	return self;
       
   189 	}
       
   190 
       
   191 CMsgProcessor::CMsgProcessor(UserPromptService::RUpsSubsession& aAuth)
       
   192 	: CActive(EPriorityStandard), iState(EIdle), iAuth(aAuth)
       
   193 	{
       
   194 	CActiveScheduler::Add(this);
       
   195 	}
       
   196 
       
   197 void CMsgProcessor::ConstructL()
       
   198 	{
       
   199 	User::LeaveIfError(iTimer.CreateLocal());
       
   200 	}
       
   201 
       
   202 CMsgProcessor::~CMsgProcessor()
       
   203 	{	
       
   204 	Deque();
       
   205 	Reset();
       
   206 	iTimer.Close();
       
   207 	}
       
   208 
       
   209 TInt CMsgProcessor::RunError(TInt aError)
       
   210 	{
       
   211 	if (iState != EIdle) iMessage.Complete(aError);
       
   212 
       
   213 	Reset();
       
   214 	return KErrNone;
       
   215 	}
       
   216 
       
   217 void CMsgProcessor::Reset() 
       
   218 /**
       
   219  * Resets the processor for the next message.
       
   220  */
       
   221 	{
       
   222 	iMsgTo.Close();
       
   223 	iMsgBody.Close();
       
   224 	iState = EIdle;
       
   225 	}
       
   226 
       
   227 void CMsgProcessor::RunL()
       
   228 	{
       
   229 	User::LeaveIfError(iStatus.Int());
       
   230 	switch (iState)
       
   231 		{
       
   232 		case EAuthorising:			
       
   233 			// Check whether the request was authorised before proceeding
       
   234 			if (iDecision == EUpsDecSessionNo || iDecision == EUpsDecNo)
       
   235 				{ // The user or UPS denied the client's request so fail with security error.				  
       
   236 				iMessage.Complete(KErrPermissionDenied);
       
   237 				Reset();
       
   238 				}
       
   239 			else
       
   240 				{ // Request authorised so carry on as normal
       
   241 				SendL();	
       
   242 				}
       
   243 			break;
       
   244 		case ESending:						
       
   245 			// Message send so complete request and return
       
   246 			iMessage.Complete(KErrNone);
       
   247 			Reset();
       
   248 			break;
       
   249 		default: // invalid state - should never happen
       
   250 			__ASSERT_ALWAYS(EFalse, User::Invariant()); 
       
   251 			break;
       
   252 		}
       
   253 	}
       
   254 
       
   255 void CMsgProcessor::DoCancel()
       
   256 	{
       
   257 	switch (iState)
       
   258 		{
       
   259 		case EIdle:
       
   260 			break; // nothing to do
       
   261 		case EAuthorising:
       
   262 			iAuth.CancelPrompt();			
       
   263 			break;
       
   264 		case ESending:
       
   265 			iTimer.Cancel();
       
   266 			break;
       
   267 		default: // invalid state - should never happen
       
   268 			__ASSERT_ALWAYS(EFalse, User::Invariant());
       
   269 		}
       
   270 	if (iState != EIdle) iMessage.Complete(KErrCancel);
       
   271 	Reset();
       
   272 	}
       
   273 
       
   274 void CMsgProcessor::GetParamsL(const RMessage2& aMessage)
       
   275 /**
       
   276  * Reads the parameters for sending a message. This data is also needed for the authorisation prompt
       
   277  */
       
   278 	{
       
   279 	TInt l = aMessage.GetDesLength(0);
       
   280 	if (l <= 0) User::Leave(KErrArgument);
       
   281 	iMsgTo.CreateL(l);
       
   282 	aMessage.ReadL(0, iMsgTo);
       
   283 	l = aMessage.GetDesLength(1);
       
   284 	if (l <= 0) User::Leave(KErrArgument);
       
   285 	iMsgBody.CreateL(l);
       
   286 	aMessage.ReadL(1, iMsgBody);
       
   287 	}
       
   288 
       
   289 void CMsgProcessor::AuthoriseL(const RMessage2& aMessage, TBool aPlatsecResult)
       
   290 /**
       
   291  * Implementation of the new authorisation state
       
   292  * @param	aMessage		The message handle containing the SendMsg parameters
       
   293  * @param	aPlatsecResult	Whether the client has the correct capabilities etc
       
   294  */
       
   295 	{
       
   296 	iState = EAuthorising;
       
   297 	iPlatsecResult = aPlatsecResult;
       
   298 	iMessage = aMessage;
       
   299 	GetParamsL(iMessage);	// message parameters are used to identify the request 
       
   300 	iAuth.Authorise(iPlatsecResult, TUid::Uid(KServiceId), iMsgTo, iDecision, iStatus);
       
   301 	SetActive();
       
   302 	}
       
   303 
       
   304 void CMsgProcessor::SendL() 
       
   305 /**
       
   306  * Simulatate the sending of a message by displaying the body
       
   307  * to the screen and waiting for three seconds.
       
   308  * 
       
   309  * No changes necessary to support user prompts.
       
   310  */
       
   311 	{
       
   312 	iState = ESending;
       
   313 	HBufC* tmp = HBufC::NewMaxLC(iMsgTo.Length() + iMsgBody.Length() + 3);
       
   314 	tmp->Des().Format(_L("%S: %S"), &iMsgTo, &iMsgBody);
       
   315 	User::LeaveIfError(User::InfoPrint(*tmp));
       
   316 	CleanupStack::PopAndDestroy(tmp);
       
   317 	iTimer.After(iStatus, 3 * 1000 * 1000);
       
   318 	SetActive();
       
   319 	}
       
   320 
       
   321 void CMsgProcessor::ProcessL(const RMessage2& aMessage, TBool aPlatsecResult)
       
   322 	{
       
   323 	switch (aMessage.Function())
       
   324 		{
       
   325 		case ESendMsg:
       
   326 			if (iState == EIdle)
       
   327 				{ // The first state is now authorisation				
       
   328 				AuthoriseL(aMessage, aPlatsecResult);
       
   329 				}
       
   330 			else
       
   331 				{ // Concurrent requests not supported
       
   332 				aMessage.Complete(KErrInUse); 
       
   333 				}
       
   334 			break;
       
   335 		case ECancelSendMsg:
       
   336 			Cancel();
       
   337 			aMessage.Complete(KErrNone);
       
   338 			break;
       
   339 		default:
       
   340 			User::Leave(KErrNotSupported);
       
   341 		}
       
   342 	}
       
   343 
       
   344 static void RunServerL()
       
   345 	{
       
   346 	// normal server startup code
       
   347 	User::LeaveIfError(RThread::RenameMe(KMsgServerName));
       
   348 	CActiveScheduler* s=new(ELeave) CActiveScheduler;
       
   349 	CleanupStack::PushL(s);
       
   350 	CActiveScheduler::Install(s);	
       
   351 	CMsgServer::NewLC();
       
   352 	RProcess::Rendezvous(KErrNone);
       
   353 	CActiveScheduler::Start();
       
   354 	CleanupStack::PopAndDestroy(2, s); 
       
   355 	}
       
   356 
       
   357 TInt E32Main()
       
   358 	{
       
   359 	__UHEAP_MARK;
       
   360 	CTrapCleanup* cleanup=CTrapCleanup::New();
       
   361 	TInt r=KErrNoMemory;
       
   362 	if (cleanup)
       
   363 		{
       
   364 		TRAP(r,RunServerL());
       
   365 		delete cleanup;
       
   366 		}
       
   367 	__UHEAP_MARKEND;
       
   368 	return r;
       
   369 	}
       
   370