|
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 |