00001 00002 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). 00003 // All rights reserved. 00004 // This component and the accompanying materials are made available 00005 // under the terms of "Eclipse Public License v1.0" 00006 // which accompanies this distribution, and is available 00007 // at the URL "http://www.eclipse.org/legal/epl-v10.html". 00008 // 00009 // Initial Contributors: 00010 // Nokia Corporation - initial contribution. 00011 // 00012 // Contributors: 00013 // 00014 // Description: 00015 // Defines CEchoEngine, CEchoRead, CEchoWrite, CTimeOutTimer 00016 // 00017 00018 #include "ECHOENG.H" 00019 00020 // 50 seconds time-out 00021 const TInt KTimeOut = 50000000; 00022 00023 /* 00024 CEchoEngine: main engine class for connection and shutdown 00025 */ 00026 EXPORT_C CEchoEngine::CEchoEngine() : CActive(EPriorityStandard) 00027 { 00028 } 00029 00030 EXPORT_C CEchoEngine* CEchoEngine::NewL(MUINotify* aConsole) 00031 { 00032 CEchoEngine* self = NewLC(aConsole); 00033 CleanupStack::Pop(); 00034 return self; 00035 } 00036 00037 EXPORT_C CEchoEngine* CEchoEngine::NewLC(MUINotify* aConsole) 00038 { 00039 CEchoEngine* self = new(ELeave) CEchoEngine; 00040 CleanupStack::PushL(self); 00041 self->ConstructL(aConsole); 00042 return self; 00043 } 00044 /* 00045 Constructs object, and opens a socket 00046 */ 00047 EXPORT_C void CEchoEngine::ConstructL(MUINotify* aConsole) 00048 { 00049 iConsole = aConsole; 00050 iEngineStatus = EComplete; 00051 00052 iTimeOut = KTimeOut; 00053 iTimer = CTimeOutTimer::NewL(EPriorityHigh, *this); 00054 CActiveScheduler::Add(this); 00055 00056 // Open channel to Socket Server 00057 User::LeaveIfError(iSocketServ.Connect()); 00058 // Open a TCP socket 00059 User::LeaveIfError(iEchoSocket.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp)); 00060 00061 iEchoRead = new CEchoRead(&iEchoSocket, aConsole); 00062 iEchoWrite = CEchoWrite::NewL(&iEchoSocket, aConsole); 00063 } 00064 00065 void CEchoEngine::DoCancel() 00066 // Cancel asychronous requests 00067 { 00068 iTimer->Cancel(); 00069 00070 // Cancel appropriate request to socket 00071 switch (iEngineStatus) 00072 { 00073 case EConnecting: 00074 iEchoSocket.CancelConnect(); 00075 break; 00076 case ELookingUp: 00077 // Cancel look up attempt 00078 iResolver.Cancel(); 00079 iResolver.Close(); 00080 break; 00081 default:; 00082 } 00083 } 00084 /* 00085 Connect to an Echo Socket by IP address 00086 */ 00087 EXPORT_C void CEchoEngine::ConnectTo(TUint32 aAddr) 00088 { 00089 // port number for test purposes - may need to be changed 00090 iAddress.SetPort(7); 00091 iAddress.SetAddress(aAddr); 00092 iEchoSocket.Connect(iAddress, iStatus); 00093 iEngineStatus = EConnecting; 00094 SetActive(); 00095 iTimer->After(iTimeOut); 00096 } 00097 00098 EXPORT_C void CEchoEngine::ConnectL(const TDesC& aServerName) 00099 // Connect to an Echo socket by hostname 00100 { 00101 // Initiate DNS 00102 User::LeaveIfError(iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp)); 00103 // DNS request for name resolution 00104 iResolver.GetByName(aServerName, iNameEntry, iStatus); 00105 00106 iEngineStatus=ELookingUp; 00107 // Request time out 00108 iTimer->After(iTimeOut); 00109 SetActive(); 00110 } 00111 00112 EXPORT_C void CEchoEngine::TestGetByAddrL(TUint32 aAddr) 00113 // Looks up hostname, and then connects to an Echo socket 00114 { 00115 // Initiate DNS 00116 User::LeaveIfError(iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp)); 00117 // DNS request for address lookup 00118 iAddress.SetAddress(aAddr); 00119 iResolver.GetByAddress(iAddress, iNameEntry, iStatus); 00120 00121 iEngineStatus=ELookingUp; 00122 // Request time out 00123 iTimer->After(iTimeOut); 00124 SetActive(); 00125 } 00126 /* 00127 Exported function wrapping call to CEchoWrite: writes character to socket 00128 */ 00129 EXPORT_C void CEchoEngine::Write(TChar aChar) 00130 { 00131 /* 00132 In this simple implementation, if iEchoWrite is already active, ignore call. 00133 Full implementation would buffer data 00134 */ 00135 if ((iEngineStatus == EConnected) && !iEchoWrite->IsActive()) 00136 iEchoWrite->IssueWrite(aChar); 00137 } 00138 /* 00139 Exported function wrapping call to CEchoRead: reads character from socket 00140 */ 00141 EXPORT_C void CEchoEngine::Read() 00142 { 00143 if ((iEngineStatus == EConnected)&&(!iEchoRead->IsActive())) 00144 iEchoRead->IssueRead(); 00145 } 00146 00147 /* 00148 Active object request complete handler. 00149 iEngineStatus flags what request was made, so its 00150 completion can be handled appropriately 00151 */ 00152 void CEchoEngine::RunL() 00153 { 00154 // Cancel TimeOut timer before completion 00155 iTimer->Cancel(); 00156 _LIT(KConnecting,"\n<CEchoEngine> Connecting\n"); 00157 _LIT(KConnectionFailed,"\n<CEchoEngine> Connection failed"); 00158 _LIT(KDNSFailed,"\n<CEchoEngine> DNS lookup failed"); 00159 _LIT(KTimedOut,"\n<CEchoEngine> Timed out\n"); 00160 _LIT(KDomainName,"\nDomain name = "); 00161 _LIT(KIPAddress,"\nIP address = "); 00162 00163 TBuf<15> ipAddr; 00164 00165 switch(iEngineStatus) 00166 { 00167 case EConnecting: 00168 // IP connection request 00169 if (iStatus == KErrNone) 00170 // Connection completed sucessfully 00171 { 00172 iConsole->PrintNotify(KConnecting); 00173 iEngineStatus = EConnected; 00174 //Start CEchoRead Active object 00175 Read(); 00176 } 00177 else 00178 { 00179 iEngineStatus = EConnectFailed; 00180 iConsole->ErrorNotifyL(KConnectionFailed, iStatus.Int()); 00181 } 00182 break; 00183 case ETimedOut: 00184 // Timeout request 00185 iConsole->ErrorNotifyL(KTimedOut, KErrTimedOut); 00186 break; 00187 case ELookingUp: 00188 iResolver.Close(); 00189 if (iStatus == KErrNone) 00190 // DNS look up successful 00191 { 00192 iNameRecord = iNameEntry(); 00193 // Extract domain name and IP address from name record 00194 iConsole->PrintNotify(KDomainName); 00195 iConsole->PrintNotify(iNameRecord.iName); 00196 TInetAddr::Cast(iNameRecord.iAddr).Output(ipAddr); 00197 iConsole->PrintNotify(KIPAddress); 00198 iConsole->PrintNotify(ipAddr); 00199 // And connect to the IP address 00200 ConnectTo(TInetAddr::Cast(iNameRecord.iAddr).Address()); 00201 } 00202 else 00203 { 00204 iStatus = ELookUpFailed; 00205 iConsole->ErrorNotifyL(KDNSFailed, iStatus.Int()); 00206 } 00207 break; 00208 00209 default:; 00210 }; 00211 } 00212 00213 CEchoEngine::~CEchoEngine() 00214 { 00215 delete iEchoRead; 00216 delete iEchoWrite; 00217 delete iTimer; 00218 iEchoSocket.Close(); 00219 iSocketServ.Close(); 00220 } 00221 00222 /* 00223 Implements MTimeOutNotify: called when timeout expired 00224 */ 00225 void CEchoEngine::TimerExpired() 00226 { 00227 Cancel(); 00228 iEngineStatus = ETimedOut; 00229 TRequestStatus* p=&iStatus; 00230 SetActive(); 00231 User::RequestComplete(p, ETimedOut); 00232 } 00233 00234 /* 00235 Shutdown connection request 00236 */ 00237 EXPORT_C void CEchoEngine::Stop() 00238 { 00239 _LIT(KETerminate,"\n<CEchoEngine> Terminating\n"); 00240 00241 iConsole->PrintNotify(KETerminate); 00242 00243 switch (iEngineStatus) 00244 { 00245 case EConnected: 00246 // Stop live connection 00247 iEchoRead->Cancel(); 00248 iEchoWrite->Cancel(); 00249 break; 00250 case EConnecting: 00251 case ELookingUp: 00252 // if request to CEchoEngine, then stop it 00253 Cancel(); 00254 break; 00255 default:; 00256 } 00257 } 00258 00259 00260 CEchoRead::CEchoRead(RSocket* aSocket, MUINotify* aConsole) 00261 :CActive(EPriorityStandard), iEchoSocket(aSocket), iConsole(aConsole) 00262 { 00263 CActiveScheduler::Add(this); 00264 } 00265 00266 00267 /* 00268 Cancel asychronous read request 00269 */ 00270 void CEchoRead::DoCancel() 00271 { 00272 iEchoSocket->CancelRead(); 00273 } 00274 /* 00275 Active object request complete handler 00276 */ 00277 void CEchoRead::RunL() 00278 { 00279 if (iStatus == KErrNone) 00280 // Character has been read from socket 00281 { 00282 _LIT(KDot,"."); 00283 iConsole->PrintNotify(KDot); 00284 TBuf16<1> Buffer; 00285 Buffer.Copy(iBuffer); 00286 iConsole->PrintNotify(Buffer); 00287 IssueRead(); 00288 } 00289 else 00290 { 00291 // Error: pass it up to user interface 00292 _LIT(KCEchoReadError,"\nCEchoRead error"); 00293 iConsole->ErrorNotifyL(KCEchoReadError, iStatus.Int()); 00294 } 00295 } 00296 /* 00297 Read data from a stream socket 00298 */ 00299 void CEchoRead::IssueRead() 00300 { 00301 if (!IsActive()) 00302 { 00303 iEchoSocket->Recv(iBuffer, 0, iStatus); 00304 SetActive(); 00305 } 00306 } 00307 /* 00308 This function is not actually used - 00309 It shows how to read data from a datagram socket 00310 */ 00311 void CEchoRead::IssueRecvFrom(TInetAddr &aAddr) 00312 00313 { 00314 iEchoSocket->RecvFrom(iBuffer,aAddr,NULL,iStatus); 00315 SetActive(); 00316 }; 00317 00318 /* 00319 CEchoWrite: active object wrapping comms write requests 00320 */ 00321 CEchoWrite::CEchoWrite() : CActive(EPriorityStandard) 00322 { 00323 00324 }; 00325 00326 CEchoWrite* CEchoWrite::NewL(RSocket* aSocket, MUINotify* aConsole) 00327 { 00328 CEchoWrite* self = NewLC(aSocket, aConsole); 00329 CleanupStack::Pop(); 00330 return self; 00331 }; 00332 00333 CEchoWrite* CEchoWrite::NewLC(RSocket* aSocket, MUINotify* aConsole) 00334 { 00335 CEchoWrite* self = new(ELeave) CEchoWrite; 00336 CleanupStack::PushL(self); 00337 self->ConstructL(aSocket, aConsole); 00338 return self; 00339 }; 00340 00341 /* 00342 ConstructL function - adds the active object to the Scheduler 00343 */ 00344 void CEchoWrite::ConstructL(RSocket* aSocket, MUINotify* aConsole) 00345 { 00346 iEchoSocket = aSocket; 00347 iConsole = aConsole; 00348 CActiveScheduler::Add(this); 00349 00350 iTimeOut = KTimeOut; 00351 iTimer = CTimeOutTimer::NewL(10, *this); 00352 iWriteStatus = EWaiting; 00353 }; 00354 00355 CEchoWrite::~CEchoWrite() 00356 { 00357 delete iTimer; 00358 } 00359 /* 00360 Cancels asychronous write request 00361 */ 00362 void CEchoWrite::DoCancel() 00363 { 00364 iEchoSocket->CancelWrite(); 00365 }; 00366 /* 00367 Implements MTimeOutNotify: called when timeout expired 00368 */ 00369 void CEchoWrite::TimerExpired() 00370 { 00371 Cancel(); 00372 iWriteStatus = ETimedOut; 00373 TRequestStatus* p=&iStatus; 00374 SetActive(); 00375 User::RequestComplete(p, ETimedOut); 00376 } 00377 /* 00378 Active object request complete handler 00379 */ 00380 void CEchoWrite::RunL() 00381 { 00382 if (iStatus == KErrNone) 00383 { 00384 _LIT(KWriteOperationTimedOut,"\nWrite operation timed out"); 00385 switch(iWriteStatus) 00386 { 00387 // Character has been written to socket 00388 case ESending: 00389 // Cancel TimeOut timer 00390 iTimer->Cancel(); 00391 iWriteStatus = EWaiting; 00392 break; 00393 // Request timed out 00394 case ETimedOut: 00395 iConsole->ErrorNotifyL(KWriteOperationTimedOut, KErrTimedOut); 00396 break; 00397 default:; 00398 }; 00399 } 00400 else 00401 { 00402 // Error: pass it up to user interface 00403 _LIT(KCEchoWriteError,"\nCEchoWrite error"); 00404 iConsole->ErrorNotifyL(KCEchoWriteError, iStatus.Int()); 00405 } 00406 } 00407 /* 00408 Write data to a stream socket 00409 */ 00410 void CEchoWrite::IssueWrite(const TChar &aChar) 00411 { 00412 // Set up buffer 00413 iBuffer.SetLength(0); 00414 iBuffer.Append(aChar); 00415 iEchoSocket->Write(iBuffer, iStatus); 00416 // Request timeout 00417 iTimer->After(iTimeOut); 00418 SetActive(); 00419 iWriteStatus = ESending; 00420 }; 00421 00422 void CEchoWrite::IssueSendTo(TInetAddr &aAddr, const TChar &aChar) 00423 // This function is not actually used - 00424 // it shows how to write data to a datagram socket 00425 { 00426 // Set up buffer 00427 iBuffer.SetLength(0); 00428 iBuffer.Append(aChar); 00429 iEchoSocket->SendTo(iBuffer,aAddr,NULL,iStatus); 00430 iTimer->After(iTimeOut); 00431 SetActive(); 00432 iWriteStatus = ESending; 00433 }; 00434 00435 /* 00436 CTimeOutTimer: timer for comms time-outs 00437 */ 00438 CTimeOutTimer::CTimeOutTimer(const TInt aPriority) 00439 : CTimer(aPriority) 00440 { 00441 } 00442 00443 CTimeOutTimer::~CTimeOutTimer() 00444 { 00445 Cancel(); 00446 } 00447 00448 CTimeOutTimer* CTimeOutTimer::NewL(const TInt aPriority, MTimeOutNotify& aTimeOutNotify) 00449 { 00450 CTimeOutTimer *p = new (ELeave) CTimeOutTimer(aPriority); 00451 CleanupStack::PushL(p); 00452 p->ConstructL(aTimeOutNotify); 00453 CleanupStack::Pop(); 00454 return p; 00455 } 00459 void CTimeOutTimer::ConstructL(MTimeOutNotify &aTimeOutNotify) 00460 { 00461 iNotify=&aTimeOutNotify; 00462 CTimer::ConstructL(); 00463 CActiveScheduler::Add(this); 00464 } 00468 void CTimeOutTimer::RunL() 00469 00470 { 00471 iNotify->TimerExpired(); 00472 } 00473
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.