|
1 // Copyright (c) 2000-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 // server.cpp |
|
15 // Transient server example - server implementation |
|
16 // |
|
17 // |
|
18 |
|
19 #include "SendProxyserver.h" |
|
20 #include "MSERVER.H" |
|
21 |
|
22 |
|
23 |
|
24 inline CShutdown::CShutdown() |
|
25 :CTimer(-1) |
|
26 {CActiveScheduler::Add(this);} |
|
27 |
|
28 |
|
29 inline void CShutdown::ConstructL() |
|
30 {CTimer::ConstructL();} |
|
31 |
|
32 |
|
33 inline void CShutdown::Start() |
|
34 {After(KSendProxyShutdownDelay);} |
|
35 |
|
36 |
|
37 inline CSendProxyServer::CSendProxyServer() |
|
38 :CServer2(0,ESharableSessions) |
|
39 {} |
|
40 |
|
41 |
|
42 |
|
43 EXPORT_C TInt RMessage2Derv::GetiArgs(TInt aPos) const |
|
44 { |
|
45 return iArgs[aPos]; |
|
46 } |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 inline CSendProxyServerSession::CSendProxyServerSession() : iSessionCount(0), iCommand( ENoCommandPending ) |
|
52 {} |
|
53 |
|
54 |
|
55 inline CSendProxyServer& CSendProxyServerSession::Server() |
|
56 {return *static_cast<CSendProxyServer*>(const_cast<CServer2*>(CSession2::Server()));} |
|
57 |
|
58 |
|
59 inline TBool CSendProxyServerSession::ReceivePending() const |
|
60 {return !iReceiveMsg.IsNull();} |
|
61 |
|
62 |
|
63 |
|
64 TInt RMsvServerSessionTest::SendReceive( TInt aFunction,const TIpcArgs& aArgs ) const |
|
65 { |
|
66 return RMsvServerSession::SendReceive( aFunction,aArgs ); |
|
67 } |
|
68 |
|
69 TInt RMsvServerSessionTest::SendReceive( TInt aFunction ) const |
|
70 { |
|
71 return RMsvServerSession::SendReceive( aFunction ); |
|
72 } |
|
73 // All we want is to access. Since RSessionBase::SendReceive is protected so is RMsvServerSession::SendReceive |
|
74 // So as long as we derive from RSessionBase base we should be get access to SendReceive. |
|
75 |
|
76 |
|
77 void RMsvServerSessionTest::SendReceive( TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aRequestStatus ) const |
|
78 { |
|
79 RMsvServerSession::SendReceive( aFunction,aArgs,aRequestStatus ); |
|
80 } |
|
81 |
|
82 void RMsvServerSessionTest::SendReceive( TInt aFunction,TRequestStatus& aRequestStatus) const |
|
83 { |
|
84 return RMsvServerSession::SendReceive( aFunction,aRequestStatus ); |
|
85 } |
|
86 |
|
87 |
|
88 void RMsvServerSessionTest::SendReceiveAsync( TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aRequestStatus ) const |
|
89 { |
|
90 RMsvServerSession::SendReceive( aFunction,aArgs,aRequestStatus ); |
|
91 User::WaitForRequest(aRequestStatus); |
|
92 // Lets pretend sync for simplicity sake. |
|
93 } |
|
94 |
|
95 void RMsvServerSessionTest::SendReceiveAsync( TInt aFunction,TRequestStatus& aRequestStatus) const |
|
96 { |
|
97 RMsvServerSession::SendReceive( aFunction,aRequestStatus ); |
|
98 User::WaitForRequest(aRequestStatus); |
|
99 // Lets pretend sync for simplicity sake. |
|
100 } |
|
101 |
|
102 |
|
103 TInt RMsvServerSessionTest::CreateSession(const TDesC& aServer,const TVersion& aVersion,TInt aAsyncMessageSlots) |
|
104 { |
|
105 return RMsvServerSession::CreateSession(aServer, aVersion, aAsyncMessageSlots); |
|
106 } |
|
107 |
|
108 |
|
109 |
|
110 // |
|
111 |
|
112 |
|
113 TInt StartMsvServer() |
|
114 { |
|
115 |
|
116 TInt err = KErrNone ; |
|
117 // EKA2 is simple No path required |
|
118 TBuf<32> serverFile; |
|
119 |
|
120 serverFile.Copy(_L("!") ); |
|
121 serverFile.Copy( KMsvServerNameExe ); |
|
122 |
|
123 _LIT(KExe,".exe"); |
|
124 serverFile.Append(KExe); |
|
125 RProcess server; |
|
126 err = server.Create(serverFile,_L("")); |
|
127 if(err != KErrNone) |
|
128 return err; |
|
129 |
|
130 // Synchronise with the server |
|
131 TRequestStatus reqStatus; |
|
132 server.Rendezvous(reqStatus); |
|
133 server.Resume(); |
|
134 //Server will call the reciprocal static synchronise call |
|
135 User::WaitForRequest(reqStatus); |
|
136 //server.Close(); |
|
137 if(reqStatus.Int() != KErrNone) |
|
138 { |
|
139 return reqStatus.Int(); |
|
140 } |
|
141 |
|
142 return err; |
|
143 } |
|
144 |
|
145 |
|
146 void CSendProxyServerSession::CreateL() |
|
147 // |
|
148 // 2nd phase construct for sessions - called by the CServer framework |
|
149 // |
|
150 { |
|
151 |
|
152 // Start up the messaging server that all messages will be forwarded to. |
|
153 TInt error = iMsvServerSession.CreateSession( KMsvServerName, iMsvServerSession.Version(), 2); |
|
154 if (error==KErrNone) |
|
155 { // Session has been started. Server was already running. |
|
156 } |
|
157 else |
|
158 { |
|
159 error=StartMsvServer(); |
|
160 |
|
161 if (error!=KErrNone) |
|
162 { // Leave |
|
163 User::LeaveIfError(error); |
|
164 } |
|
165 else |
|
166 { |
|
167 |
|
168 TInt error = iMsvServerSession.CreateSession( KMsvServerName, iMsvServerSession.Version(), 2); |
|
169 if (error!=KErrNone) |
|
170 { // Leave |
|
171 User::LeaveIfError(error); |
|
172 } |
|
173 } |
|
174 } |
|
175 |
|
176 |
|
177 Server().AddSession(); |
|
178 |
|
179 } |
|
180 |
|
181 |
|
182 CSendProxyServerSession::~CSendProxyServerSession() |
|
183 { |
|
184 iMsvServerSession.Close(); |
|
185 Server().DropSession(); |
|
186 } |
|
187 |
|
188 |
|
189 |
|
190 void CSendProxyServerSession::ServiceL(const RMessage2& aMessage) |
|
191 // |
|
192 // Handle a client request. |
|
193 // Leaving is handled by CSendProxyServer::ServiceError() which reports |
|
194 // the error code to the client |
|
195 // |
|
196 { |
|
197 TInt messageFunction = aMessage.Function(); |
|
198 |
|
199 if (messageFunction==ESendData) |
|
200 { // We are setting up buffers as next time we actually execute the command. |
|
201 // _ASSERT( iCommand == ENoCommandPending ); |
|
202 // Make sure we do not have another command pending. |
|
203 iCommand = (TSendProxyMessages) aMessage.Int0(); //???? fix casts |
|
204 iFlags = aMessage.Int1(); |
|
205 aMessage.Complete( KErrNone ); |
|
206 } |
|
207 else if (messageFunction==EGetServerSecureId) |
|
208 { // This must done for the proxy server. |
|
209 // We are not passing the data on to the messaging server |
|
210 |
|
211 TSecureId cServerSecureId; |
|
212 TPckg<TSecureId> buf(cServerSecureId); |
|
213 |
|
214 aMessage.ReadL(0,buf); |
|
215 |
|
216 cServerSecureId = RProcess().SecureId(); |
|
217 aMessage.WriteL(0,buf); |
|
218 |
|
219 aMessage.Complete( KErrNone ); |
|
220 } |
|
221 else if (messageFunction==EGetServerCapabilities) |
|
222 { // return the capabilities for the proxy server. |
|
223 // We are not passing the data on to the messaging server |
|
224 |
|
225 TInt32 cServerCaps; |
|
226 TPckg<TInt32> buf(cServerCaps); |
|
227 |
|
228 aMessage.ReadL(0,buf); |
|
229 |
|
230 ReadCapabilities(cServerCaps); |
|
231 |
|
232 aMessage.WriteL(0,buf); |
|
233 |
|
234 aMessage.Complete( KErrNone ); |
|
235 } |
|
236 else if ( messageFunction==EReceive ) |
|
237 { |
|
238 if (ReceivePending()) |
|
239 PanicClient(aMessage,EPanicAlreadyReceiving); |
|
240 else |
|
241 { |
|
242 iReceiveMsg=aMessage; |
|
243 iReceiveLen=aMessage.Int1(); |
|
244 } |
|
245 } |
|
246 else if ( messageFunction==ECancelReceive ) |
|
247 { |
|
248 if (ReceivePending()) |
|
249 iReceiveMsg.Complete(KErrCancel); |
|
250 aMessage.Complete( KErrNone ); |
|
251 } |
|
252 else |
|
253 { // We are expected to execute a command. |
|
254 TInt complete = DoCommandL( (const RMessage2Derv&) aMessage ); |
|
255 |
|
256 // Indicate that we succesfully executed a full command and can take another. |
|
257 iCommand = ENoCommandPending; |
|
258 iFlags = 0; |
|
259 aMessage.Complete( complete ); |
|
260 } |
|
261 |
|
262 } |
|
263 |
|
264 |
|
265 void CSendProxyServerSession::ReadCapabilities(TInt32& aServerCaps) |
|
266 { |
|
267 aServerCaps=0; |
|
268 |
|
269 if (RProcess().HasCapability(ECapabilityTCB)) |
|
270 aServerCaps |= (1<<ECapabilityTCB); |
|
271 |
|
272 if (RProcess().HasCapability(ECapabilityCommDD)) |
|
273 aServerCaps |= (1<<ECapabilityCommDD); |
|
274 |
|
275 if (RProcess().HasCapability(ECapabilityPowerMgmt)) |
|
276 aServerCaps |= (1<<ECapabilityPowerMgmt); |
|
277 |
|
278 if (RProcess().HasCapability(ECapabilityMultimediaDD)) |
|
279 aServerCaps |= (1<<ECapabilityMultimediaDD); |
|
280 |
|
281 if (RProcess().HasCapability(ECapabilityReadDeviceData)) |
|
282 aServerCaps |= (1<<ECapabilityReadDeviceData); |
|
283 |
|
284 if (RProcess().HasCapability(ECapabilityWriteDeviceData)) |
|
285 aServerCaps |= (1<<ECapabilityWriteDeviceData); |
|
286 |
|
287 if (RProcess().HasCapability(ECapabilityDRM)) |
|
288 aServerCaps |= (1<<ECapabilityDRM); |
|
289 |
|
290 if (RProcess().HasCapability(ECapabilityTrustedUI)) |
|
291 aServerCaps |= (1<<ECapabilityTrustedUI); |
|
292 |
|
293 if (RProcess().HasCapability(ECapabilityProtServ)) |
|
294 aServerCaps |= (1<<ECapabilityProtServ); |
|
295 |
|
296 if (RProcess().HasCapability(ECapabilityDiskAdmin)) |
|
297 aServerCaps |= (1<<ECapabilityDiskAdmin); |
|
298 |
|
299 if (RProcess().HasCapability(ECapabilityNetworkControl)) |
|
300 aServerCaps |= (1<<ECapabilityNetworkControl); |
|
301 |
|
302 if (RProcess().HasCapability(ECapabilityAllFiles)) |
|
303 aServerCaps |= (1<<ECapabilityAllFiles); |
|
304 |
|
305 if (RProcess().HasCapability(ECapabilitySwEvent)) |
|
306 aServerCaps |= (1<<ECapabilitySwEvent); |
|
307 |
|
308 if (RProcess().HasCapability(ECapabilityNetworkServices)) |
|
309 aServerCaps |= (1<<ECapabilityNetworkServices); |
|
310 |
|
311 if (RProcess().HasCapability(ECapabilityLocalServices)) |
|
312 aServerCaps |= (1<<ECapabilityLocalServices); |
|
313 |
|
314 if (RProcess().HasCapability(ECapabilityReadUserData)) |
|
315 aServerCaps |= (1<<ECapabilityReadUserData); |
|
316 |
|
317 if (RProcess().HasCapability(ECapabilityWriteUserData)) |
|
318 aServerCaps |= (1<<ECapabilityWriteUserData); |
|
319 |
|
320 if (RProcess().HasCapability(ECapabilityLocation)) |
|
321 aServerCaps |= (1<<ECapabilityLocation); |
|
322 |
|
323 if (RProcess().HasCapability(ECapabilitySurroundingsDD)) |
|
324 aServerCaps |= (1<<ECapabilitySurroundingsDD); |
|
325 |
|
326 if (RProcess().HasCapability(ECapabilityUserEnvironment)) |
|
327 aServerCaps |= (1<<ECapabilityUserEnvironment); |
|
328 |
|
329 |
|
330 } |
|
331 |
|
332 |
|
333 //************* |
|
334 |
|
335 |
|
336 void CSendProxyServerSession::SetupTIpcArgL(const RMessage2Derv& aMessage, TInt aPos, TIpcArgs& atipcArgs ) |
|
337 { |
|
338 const TInt mask = ( 1<<TIpcArgs::KBitsPerType )-1; |
|
339 |
|
340 const TInt bits_shift = (aPos * TIpcArgs::KBitsPerType ); |
|
341 const TInt type_flags = ( iFlags >> bits_shift ) & mask ; |
|
342 |
|
343 |
|
344 if ( type_flags == TIpcArgs::EUnspecified ) |
|
345 { // Unspecified so must be TInt. |
|
346 TInt tmp = aMessage.GetiArgs(aPos); |
|
347 atipcArgs.Set( aPos, (TAny*) tmp); |
|
348 } |
|
349 else if ( type_flags == TIpcArgs::EDesC8 ) |
|
350 { // We have a read only descriptor can not use GetDesMaxLength on it. |
|
351 |
|
352 TInt maxLength1 = aMessage.GetDesLength(aPos); |
|
353 HBufC8* buffer1 = HBufC8::NewL(maxLength1); |
|
354 iBuffer8[aPos].Assign(buffer1); |
|
355 // Owns the buffer. |
|
356 |
|
357 TPtr8 ptrBuffer1= (buffer1->Des()); |
|
358 |
|
359 aMessage.ReadL( aPos, ptrBuffer1 ); |
|
360 atipcArgs.Set( aPos, buffer1); |
|
361 // buffer is considered constant so internal flags in atipcArgs will be okay. |
|
362 } |
|
363 else if ( type_flags == TIpcArgs::EDes8 ) |
|
364 { // Just generate a descriptor and copy the contents into it. |
|
365 // We need GetDesMaxLength because it is read/write and somebody will right more than the current length. |
|
366 |
|
367 TInt maxLength2 = aMessage.GetDesMaxLength(aPos); |
|
368 |
|
369 HBufC8* buffer2 = HBufC8::NewL(maxLength2); |
|
370 iBuffer8[aPos].Assign(buffer2); |
|
371 // we want the buffer to read/write which is why we use RBuf8. |
|
372 // The RBuf8 takes ownership of the HBuf. |
|
373 |
|
374 iTPtr8[aPos] = new (ELeave) TPtr8(buffer2->Des()); |
|
375 |
|
376 aMessage.ReadL( aPos, *(iTPtr8[aPos]) ); |
|
377 atipcArgs.Set( aPos, iTPtr8[aPos] ); |
|
378 |
|
379 } |
|
380 else if ( type_flags == TIpcArgs::EDesC16 ) |
|
381 { // We have a read only descriptor can not use GetDesMaxLength on it. |
|
382 |
|
383 TInt maxLength3 = aMessage.GetDesLength(aPos); |
|
384 HBufC16* buffer3 = HBufC16::NewL(maxLength3); |
|
385 iBuffer16[aPos].Assign(buffer3); |
|
386 // Owns the buffer. |
|
387 |
|
388 TPtr16 ptrBuffer3= (buffer3->Des()); |
|
389 |
|
390 aMessage.ReadL( aPos, ptrBuffer3 ); |
|
391 atipcArgs.Set( aPos, buffer3); |
|
392 // buffer is considered constant so internal flags in atipcArgs will be okay. |
|
393 } |
|
394 else if ( type_flags == TIpcArgs::EDes16 ) |
|
395 { // Just generate a descriptor and copy the contents into it. |
|
396 // We need GetDesMaxLength because it is read/write and somebody will right more than the current length. |
|
397 |
|
398 TInt maxLength4 = aMessage.GetDesMaxLength(aPos); |
|
399 |
|
400 HBufC16* buffer4 = HBufC16::NewL(maxLength4); |
|
401 iBuffer16[aPos].Assign(buffer4); |
|
402 // we want the buffer to read/write which is why we use RBuf16. |
|
403 // The RBuf16 takes ownership of the HBuf. |
|
404 |
|
405 iTPtr16[aPos] = new (ELeave) TPtr16(buffer4->Des()); |
|
406 |
|
407 aMessage.ReadL( aPos, *(iTPtr16[aPos]) ); |
|
408 atipcArgs.Set( aPos, iTPtr16[aPos] ); |
|
409 |
|
410 } |
|
411 else if ( type_flags == TIpcArgs::EHandle ) |
|
412 { |
|
413 TInt tmp = aMessage.GetiArgs(aPos); |
|
414 atipcArgs.Set( aPos, tmp); |
|
415 } |
|
416 else |
|
417 { // Unknown error. |
|
418 User::LeaveIfError(KErrGeneral); |
|
419 } |
|
420 |
|
421 } |
|
422 |
|
423 void CSendProxyServerSession::SetupTIpcArgsL(const RMessage2Derv& aMessage, TIpcArgs& atipcArgs) |
|
424 { |
|
425 SetupTIpcArgL( aMessage, 0, atipcArgs ); |
|
426 SetupTIpcArgL( aMessage, 1, atipcArgs ); |
|
427 SetupTIpcArgL( aMessage, 2, atipcArgs ); |
|
428 SetupTIpcArgL( aMessage, 3, atipcArgs ); |
|
429 } |
|
430 |
|
431 |
|
432 //************* |
|
433 |
|
434 void CSendProxyServerSession::SetupReturnTIpcArgL(const RMessage2Derv& aMessage, TInt aPos ) |
|
435 { |
|
436 const TInt mask = ( 1<<TIpcArgs::KBitsPerType )-1; |
|
437 |
|
438 const TInt bits_shift = (aPos * TIpcArgs::KBitsPerType ); |
|
439 const TInt type_flags = ( iFlags >> bits_shift ) & mask ; |
|
440 |
|
441 if (type_flags == TIpcArgs::EUnspecified) |
|
442 { // Do nothing can not write back to the args of a message. |
|
443 } |
|
444 else if ( type_flags == TIpcArgs::EDesC8 ) |
|
445 { // We have constant descriptor no action required as we can not change it. |
|
446 } |
|
447 else if ( type_flags == TIpcArgs::EDes8 ) |
|
448 { // We have a read/write descriptor we need to copy back any changes. |
|
449 aMessage.WriteL( aPos, *(iTPtr8[aPos]) ); |
|
450 } |
|
451 else if ( type_flags == TIpcArgs::EDesC16 ) |
|
452 { // We have constant descriptor no action required as we can not change it. |
|
453 } |
|
454 else if ( type_flags == TIpcArgs::EDes16 ) |
|
455 { // We have a read/write descriptor we need to copy back any changes. |
|
456 aMessage.WriteL( aPos, *(iTPtr16[aPos]) ); |
|
457 } |
|
458 else if ( type_flags == TIpcArgs::EHandle ) |
|
459 { //Do nothing as handles should not change. |
|
460 } |
|
461 else |
|
462 { // may need to implement 16 bit descriptors etc. |
|
463 User::LeaveIfError(KErrGeneral); |
|
464 } |
|
465 |
|
466 } |
|
467 |
|
468 |
|
469 void CSendProxyServerSession::SetupReturnTIpcArgsL(const RMessage2Derv& aMessage) |
|
470 { |
|
471 SetupReturnTIpcArgL( aMessage, 0 ); |
|
472 SetupReturnTIpcArgL( aMessage, 1 ); |
|
473 SetupReturnTIpcArgL( aMessage, 2 ); |
|
474 SetupReturnTIpcArgL( aMessage, 3 ); |
|
475 } |
|
476 |
|
477 |
|
478 void CSendProxyServerSession::ClearBuffer(TInt aPos) |
|
479 { |
|
480 |
|
481 iBuffer8[aPos].Close(); |
|
482 delete iTPtr8[aPos]; |
|
483 iTPtr8[aPos]=0; |
|
484 |
|
485 iBuffer16[aPos].Close(); |
|
486 delete iTPtr16[aPos]; |
|
487 iTPtr16[aPos]=0; |
|
488 |
|
489 } |
|
490 |
|
491 |
|
492 |
|
493 void CSendProxyServerSession::ClearBuffers() |
|
494 { |
|
495 |
|
496 ClearBuffer( 0 ); |
|
497 ClearBuffer( 1 ); |
|
498 ClearBuffer( 2 ); |
|
499 ClearBuffer( 3 ); |
|
500 |
|
501 } |
|
502 |
|
503 |
|
504 TInt CSendProxyServerSession::DoCommandL(const RMessage2Derv& aMessage ) |
|
505 { |
|
506 TInt complete=KErrNone; |
|
507 |
|
508 switch (iCommand) |
|
509 { |
|
510 |
|
511 case ESend: |
|
512 { |
|
513 |
|
514 TIpcArgs tipcArgs; |
|
515 SetupTIpcArgsL( ( (const RMessage2Derv&) aMessage ), tipcArgs); |
|
516 complete = iMsvServerSession.SendReceive( aMessage.Function(), tipcArgs ); |
|
517 SetupReturnTIpcArgsL( (const RMessage2Derv&) aMessage); |
|
518 ClearBuffers(); |
|
519 break; |
|
520 } |
|
521 |
|
522 case ESendAsyncWait: |
|
523 { |
|
524 |
|
525 TIpcArgs tipcArgs1; |
|
526 SetupTIpcArgsL( ( (const RMessage2Derv&) aMessage ), tipcArgs1); |
|
527 |
|
528 TRequestStatus requestStatus=KRequestPending; |
|
529 iMsvServerSession.SendReceive( aMessage.Function(), tipcArgs1 , requestStatus ); |
|
530 User::WaitForRequest(requestStatus); |
|
531 SetupReturnTIpcArgsL( (const RMessage2Derv&) aMessage); |
|
532 ClearBuffers(); |
|
533 complete = requestStatus.Int(); |
|
534 |
|
535 break; |
|
536 } |
|
537 default: |
|
538 { |
|
539 complete=KErrGeneral; |
|
540 PanicClient(aMessage,EPanicIllegalFunction); |
|
541 break; |
|
542 } |
|
543 } |
|
544 |
|
545 return complete; |
|
546 } |
|
547 |
|
548 void CSendProxyServerSession::ServiceError(const RMessage2& aMessage,TInt aError) |
|
549 // |
|
550 // Handle an error from CSendProxyServerSession::ServiceL() |
|
551 // A bad descriptor error implies a badly programmed client, so panic it; |
|
552 // otherwise use the default handling (report the error to the client) |
|
553 // |
|
554 { |
|
555 if (aError==KErrBadDescriptor) |
|
556 PanicClient(aMessage,EPanicBadDescriptor); |
|
557 CSession2::ServiceError(aMessage,aError); |
|
558 } |
|
559 |
|
560 void CShutdown::RunL() |
|
561 // |
|
562 // Initiate server exit when the timer expires |
|
563 // |
|
564 { |
|
565 CActiveScheduler::Stop(); |
|
566 } |
|
567 |
|
568 CServer2* CSendProxyServer::NewLC() |
|
569 { |
|
570 CSendProxyServer* self=new(ELeave) CSendProxyServer; |
|
571 CleanupStack::PushL(self); |
|
572 self->ConstructL(); |
|
573 return self; |
|
574 } |
|
575 |
|
576 |
|
577 //********************************** |
|
578 |
|
579 void CSendProxyServer::ConstructL() |
|
580 // |
|
581 // 2nd phase construction - ensure the timer and server objects are running |
|
582 // |
|
583 { |
|
584 StartL(KSendProxyServerName); |
|
585 |
|
586 iShutdown.ConstructL(); |
|
587 // ensure that the server still exits even if the 1st client fails to connect |
|
588 iShutdown.Start(); |
|
589 } |
|
590 |
|
591 |
|
592 CSession2* CSendProxyServer::NewSessionL(const TVersion&,const RMessage2&) const |
|
593 // |
|
594 // Cretae a new client session. This should really check the version number. |
|
595 // |
|
596 { |
|
597 return new(ELeave) CSendProxyServerSession(); |
|
598 } |
|
599 |
|
600 void CSendProxyServer::AddSession() |
|
601 // |
|
602 // A new session is being created |
|
603 // Cancel the shutdown timer if it was running |
|
604 // |
|
605 { |
|
606 ++iSessionCount; |
|
607 iShutdown.Cancel(); |
|
608 } |
|
609 |
|
610 void CSendProxyServer::DropSession() |
|
611 // |
|
612 // A session is being destroyed |
|
613 // Start the shutdown timer if it is the last session. |
|
614 // |
|
615 { |
|
616 if (--iSessionCount==0) |
|
617 iShutdown.Start(); |
|
618 } |
|
619 |
|
620 |
|
621 |
|
622 void PanicClient(const RMessagePtr2& aMessage,TSendProxyServerPanic aPanic) |
|
623 // |
|
624 // RMessagePtr2::Panic() also completes the message. This is: |
|
625 // (a) important for efficient cleanup within the kernel |
|
626 // (b) a problem if the message is completed a second time |
|
627 // |
|
628 { |
|
629 _LIT(KPanic,"SendProxyServer"); |
|
630 aMessage.Panic(KPanic,aPanic); |
|
631 } |
|
632 |
|
633 |
|
634 //****************************** |
|
635 |
|
636 |
|
637 static void RunServerL() |
|
638 // |
|
639 // Perform all server initialisation, in particular creation of the |
|
640 // scheduler and server and then run the scheduler |
|
641 // |
|
642 { |
|
643 |
|
644 // naming the server thread after the server helps to debug panics |
|
645 User::LeaveIfError(User::RenameThread(KSendProxyServerName)); |
|
646 // |
|
647 // create and install the active scheduler we need |
|
648 CActiveScheduler* s=new(ELeave) CActiveScheduler; |
|
649 CleanupStack::PushL(s); |
|
650 CActiveScheduler::Install(s); |
|
651 // |
|
652 // create the server (leave it on the cleanup stack) |
|
653 CSendProxyServer::NewLC(); |
|
654 // |
|
655 // Initialisation complete, now signal the client |
|
656 #ifdef __SENDPROXYSERVER_NO_PROCESSES__ |
|
657 RThread::Rendezvous(KErrNone); |
|
658 #else |
|
659 RProcess::Rendezvous(KErrNone); |
|
660 #endif |
|
661 // |
|
662 // Ready to run |
|
663 CActiveScheduler::Start(); |
|
664 // |
|
665 // Cleanup the server and scheduler |
|
666 CleanupStack::PopAndDestroy(2); |
|
667 |
|
668 } |
|
669 |
|
670 |
|
671 |
|
672 //**************************************** |
|
673 |
|
674 |
|
675 TInt E32Main() |
|
676 // |
|
677 // Server process entry-point |
|
678 // |
|
679 { |
|
680 __UHEAP_MARK; |
|
681 // |
|
682 CTrapCleanup* cleanup=CTrapCleanup::New(); |
|
683 TInt r=KErrNoMemory; |
|
684 if (cleanup) |
|
685 { |
|
686 TRAP(r,RunServerL()); |
|
687 delete cleanup; |
|
688 } |
|
689 // |
|
690 __UHEAP_MARKEND; |
|
691 return r; |
|
692 } |
|
693 |
|
694 #ifdef __SENDPROXYSERVER_NO_PROCESSES__ |
|
695 |
|
696 // The server binary is an "EPOCEXE" target type |
|
697 // Thus the server parameter passing and startup code for WINS and EPOC are |
|
698 // significantly different. |
|
699 // |
|
700 // In EKA1 WINS, the EPOCEXE target is a DLL with an entry point called WinsMain, |
|
701 // taking no parameters and returning TInt. This is not really valid as a thread |
|
702 // function which takes a TAny* parameter which we need. |
|
703 // |
|
704 // So the DLL entry-point WinsMain() is used to return a TInt representing the |
|
705 // real thread function within the DLL. This is good as long as |
|
706 // sizeof(TInt)>=sizeof(TThreadFunction). |
|
707 // |
|
708 |
|
709 static TInt ThreadFunction(TAny*) |
|
710 // |
|
711 // WINS thread entry-point function. |
|
712 // |
|
713 { |
|
714 return E32Main(); |
|
715 } |
|
716 |
|
717 IMPORT_C TInt WinsMain(); |
|
718 EXPORT_C TInt WinsMain() |
|
719 // |
|
720 // WINS DLL entry-point. Just return the real thread function |
|
721 // cast to TInt |
|
722 // |
|
723 { |
|
724 return reinterpret_cast<TInt>(&ThreadFunction); |
|
725 } |
|
726 |
|
727 TInt E32Dll(TDllReason) |
|
728 { |
|
729 return KErrNone; |
|
730 } |
|
731 |
|
732 #endif |