sl@0: /* sl@0: * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: sl@0: #include "randsvr.h" sl@0: #include "randcliserv.h" sl@0: #include <e32math.h> sl@0: #include "randsvrimpl.h" sl@0: sl@0: sl@0: //const TInt KFastTickTimer=1000000; // These are testing numbers! sl@0: //const TInt KSlowTickTimer=30000000; sl@0: const TInt KThreshold=1024; sl@0: sl@0: const TInt KFastTickTimer=30000000; // These are the real numbers! sl@0: const TInt KSlowTickTimer=0x7fffffff; sl@0: sl@0: sl@0: void SignalClient() sl@0: // sl@0: // Signal the owning thread that the server has started successfully sl@0: // This may itself fail sl@0: // sl@0: { sl@0: RProcess::Rendezvous(KErrNone); sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt RunRandomServer(TAny* /*aUnused*/) sl@0: { sl@0: CTrapCleanup* cleanup=CTrapCleanup::New(); sl@0: if (!cleanup) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: TInt ret = User::RenameThread(KRandomServerName); sl@0: sl@0: __ASSERT_ALWAYS(ret==KErrNone,User::Panic(KRandomServerName,KErrServerTerminated)); sl@0: sl@0: if (CRandomScheduler::New()) sl@0: return KErrNoMemory; sl@0: ret = CRandomServer::New(); sl@0: if (ret != KErrNone ) sl@0: return ret; sl@0: // Initialisation complete, now signal the client sl@0: SignalClient(); sl@0: sl@0: CRandomScheduler::Start(); sl@0: delete cleanup; sl@0: return KErrNone; sl@0: } sl@0: sl@0: TBool CRandomScheduler::New(void) sl@0: { sl@0: CRandomScheduler* rs; sl@0: rs=new CRandomScheduler; sl@0: CRandomScheduler::Install(rs); sl@0: return (rs == NULL); sl@0: } sl@0: sl@0: void CRandomScheduler::Error(TInt /*aError*/) const sl@0: { sl@0: User::Panic(KRandomServerName, 3); sl@0: } sl@0: sl@0: CRandomServer::CRandomServer(void) : CServer2(EPriorityLow) sl@0: { sl@0: } sl@0: sl@0: CRandomServer::~CRandomServer(void) sl@0: { sl@0: // This should never happen....but in case it does: sl@0: delete iHash; sl@0: delete iTicker; sl@0: delete iPool; sl@0: } sl@0: sl@0: TInt CRandomServer::New(void) sl@0: { sl@0: CRandomServer* self; sl@0: self=new CRandomServer; sl@0: if (!self) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: TRAPD(ret,self->ConstructL()); sl@0: if (ret) sl@0: { sl@0: return ret; sl@0: } sl@0: sl@0: return self->Start(KRandomServerName); sl@0: } sl@0: sl@0: void CRandomServer::ConstructL(void) sl@0: { sl@0: iPool=new (ELeave) TUint8[KRandomPoolSize]; sl@0: iHash=CSHA1::NewL(); sl@0: iPoolIn=0; sl@0: iPoolOut=0; sl@0: iTicker=CPeriodic::NewL(EPriorityLow); sl@0: TCallBack callback(Tick,this); sl@0: iTicker->Start(KFastTickTimer,KFastTickTimer,callback); // **** these figures might need tweaking! sl@0: iQuality=0; sl@0: iFast=ETrue; sl@0: } sl@0: sl@0: TInt CRandomServer::Tick(TAny* aServer) sl@0: { sl@0: CRandomServer* svr=(CRandomServer*)aServer; sl@0: svr->Stir(); sl@0: svr->iQuality+=30; sl@0: if (svr->iFast) sl@0: { sl@0: if (svr->iQuality>KThreshold) sl@0: { sl@0: TCallBack callback(Tick,svr); sl@0: svr->iTicker->Cancel(); sl@0: svr->iTicker->Start(KSlowTickTimer,KSlowTickTimer,callback); // **** these figures might need tweaking! sl@0: svr->iFast=EFalse; sl@0: } sl@0: } sl@0: if (svr->iQuality>(KRandomPoolSize<<3)) sl@0: { sl@0: svr->iQuality=(KRandomPoolSize<<3); sl@0: } sl@0: return ETrue; sl@0: } sl@0: sl@0: CSession2* CRandomServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const sl@0: { sl@0: return CRandomSession::NewL(const_cast<CRandomServer*>(this)); sl@0: //CRandomSession::NewL(CONST_CAST(CRandomServer*,this),Message().Client()); sl@0: } sl@0: sl@0: TPtrC8 CRandomServer::GetRandom(void) sl@0: { sl@0: TPtr8 res(&iPool[iPoolOut],iHash->HashSize(),iHash->HashSize()); sl@0: iPoolOut+=iHash->HashSize(); sl@0: if ((iPoolOut+iHash->HashSize())>KRandomPoolSize) sl@0: { sl@0: iPoolOut=0; sl@0: } sl@0: return iHash->Hash(res); sl@0: } sl@0: sl@0: CMessageDigest* CRandomServer::Hash(void) const sl@0: { sl@0: return iHash; sl@0: } sl@0: sl@0: void CRandomServer::Stir(void) sl@0: { sl@0: TInt rnd; sl@0: rnd=Math::Random(); sl@0: TPtrC8 r((TUint8*)&rnd,sizeof(TInt)); sl@0: iHash->Hash(r); sl@0: TPtr8 dest(&iPool[iPoolIn],iHash->HashSize()); sl@0: dest.Copy(iHash->Hash(dest)); sl@0: iPoolIn+=iHash->HashSize(); sl@0: if ((iPoolIn+iHash->HashSize())>KRandomPoolSize) sl@0: { sl@0: iPoolIn=0; sl@0: } sl@0: } sl@0: sl@0: CRandomSession* CRandomSession::NewL(CRandomServer* aServer) sl@0: { sl@0: CRandomSession* self; sl@0: self=new (ELeave) CRandomSession(aServer); sl@0: return self; sl@0: } sl@0: sl@0: CRandomSession::CRandomSession(CRandomServer* aServer) : CSession2(), iServer(aServer) sl@0: { sl@0: } sl@0: sl@0: CRandomSession::~CRandomSession(void) sl@0: { sl@0: } sl@0: sl@0: void CRandomSession::ServiceL(const RMessage2& aMessage) sl@0: { sl@0: switch (aMessage.Function()) sl@0: { sl@0: case KRandomRequest: sl@0: { sl@0: TInt ret = FillBuffer(aMessage); sl@0: aMessage.Complete(ret); sl@0: break; sl@0: } sl@0: default: sl@0: aMessage.Complete(KErrNotSupported); sl@0: break; sl@0: }; sl@0: } sl@0: sl@0: TInt CRandomSession::FillBuffer(const RMessage2& aMessage) sl@0: { sl@0: TInt length = aMessage.Int1(); sl@0: if (length < 0 || length > KRandomBlockSize) sl@0: return KErrArgument; sl@0: iServer->iQuality -= length; sl@0: if (iServer->iQuality<0) sl@0: { sl@0: iServer->iQuality=0; sl@0: } sl@0: if (!iServer->iFast) sl@0: { sl@0: if (iServer->iQuality<KThreshold) sl@0: { sl@0: TCallBack callback(CRandomServer::Tick,iServer); sl@0: iServer->iTicker->Cancel(); sl@0: iServer->iTicker->Start(KFastTickTimer,KFastTickTimer,callback); // **** these figures might need tweaking! sl@0: iServer->iFast=ETrue; sl@0: } sl@0: } sl@0: TBuf8<KRandomBlockSize> buf(0); sl@0: iServer->Stir(); sl@0: TInt i; sl@0: TInt hashsize=iServer->Hash()->HashSize(); sl@0: for (i=0; i+hashsize < length; i+=hashsize) sl@0: { sl@0: buf.Append(iServer->GetRandom()); sl@0: iServer->Stir(); sl@0: } sl@0: TPtrC8 ptr(iServer->GetRandom().Ptr(), length-i); sl@0: buf.Append(ptr); sl@0: sl@0: TRAPD(ret, aMessage.WriteL(0, buf)); sl@0: return ret; sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main(void) sl@0: { sl@0: return RunRandomServer(NULL); sl@0: }