examples/Networking/TcpIp/EchoClientEngine/ECHOENG.CPP

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         

Generated by  doxygen 1.6.2