www.pudn.com > NetTest2nd.rar > socketsengine.cpp
/* Copyright (c) 2001, Nokia. All rights reserved */ #include#include "SocketsEngine.h" #include "TimeOutTimer.h" #include "SocketsReader.h" #include "SocketsWriter.h" #include "Sockets.pan" #include "UINotifier.h" const TInt CSocketsEngine::KTimeOut = 30000000; // 30 seconds time-out _LIT(KDefaultServerName, "10.0.0.172"); const TInt CSocketsEngine::KDefaultPortNumber = 80; _LIT(KErrConnectionFailed, "CSocketsEngine\nConn. failed"); _LIT(KErrDNSFailed, "CSocketsEngine\nDNS lookup failed"); _LIT(KErrSocketTimeout, "CSocketsEngine\nTimed out"); _LIT(KErrSocketDisconnected, "CSocketsEngine\nDisconnected"); _LIT(KErrSocketRead, "CSocketsEngine\nRead Error"); _LIT(KErrSocketWriteTO, "CSocketsEngine\nTime Out on write"); _LIT(KErrSocketWriteFailed, "CSocketsEngine\nWrite Error"); _LIT(KStrDomainName, "Domain name = "); _LIT(KStrIPAddr, "\r\nIP address = "); _LIT(KStrNewLine, "\r\n"); _LIT(KStrNotConnected, "Not connected"); _LIT(KStrConnecting, "Connecting"); _LIT(KStrConnected, "Connected"); _LIT(KStrLookingUp, "Looking up"); CSocketsEngine* CSocketsEngine::NewL(MUINotifier& aConsole) { CSocketsEngine* self = CSocketsEngine::NewLC(aConsole); CleanupStack::Pop(self); return self; } CSocketsEngine* CSocketsEngine::NewLC(MUINotifier& aConsole) { CSocketsEngine* self = new (ELeave) CSocketsEngine(aConsole); CleanupStack::PushL(self); self->ConstructL(); return self; } CSocketsEngine::CSocketsEngine(MUINotifier& aConsole) : CActive(EPriorityStandard), iConsole(aConsole), iPort(KDefaultPortNumber), iServerName(KDefaultServerName) { } CSocketsEngine::~CSocketsEngine() { Cancel(); delete iSocketsReader; iSocketsReader = NULL; delete iSocketsWriter; iSocketsWriter = NULL; delete iTimer; iTimer = NULL; iSocketServ.Close(); } void CSocketsEngine::ConstructL() { ChangeStatus(ENotConnected); // Start a timer iTimer = CTimeOutTimer::NewL(EPriorityHigh, *this); CActiveScheduler::Add(this); // Open channel to Socket Server User::LeaveIfError(iSocketServ.Connect()); // Create socket read and write active objects iSocketsReader = CSocketsReader::NewL(*this, iSocket); iSocketsWriter = CSocketsWriter::NewL(*this, iSocket); } void CSocketsEngine::ConnectL() { // Initiate connection process if (iEngineStatus == ENotConnected) { TInetAddr addr; if (addr.Input(iServerName) == KErrNone) { // server name is already a valid ip address ConnectL(addr.Address()); } else // need to look up name using dns { // Initiate DNS User::LeaveIfError(iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp)); // DNS request for name resolution iResolver.GetByName(iServerName, iNameEntry, iStatus); ChangeStatus(ELookingUp); // Request time out iTimer->After(KTimeOut); SetActive(); } } } void CSocketsEngine::ConnectL(TUint32 aAddr) // { // Initiate attempt to connect to a socket by IP address if (iEngineStatus == ENotConnected) { // Open a TCP socket User::LeaveIfError(iSocket.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp)); // Set up address information iAddress.SetPort(iPort); iAddress.SetAddress(aAddr); // Initiate socket connection iSocket.Connect(iAddress, iStatus); ChangeStatus(EConnecting); // Start a timeout iTimer->After(KTimeOut); SetActive(); } } void CSocketsEngine::Disconnect() { __ASSERT_ALWAYS(iEngineStatus == EConnected, User::Panic(KPanicSocketsEngine, ESocketsBadState)); // cancel all outstanding operations // since we are connected, the only possibilities are read and write iSocketsReader->Cancel(); iSocketsWriter->Cancel(); iSocket.Close(); ChangeStatus(ENotConnected); } // from CActive void CSocketsEngine::DoCancel() { iTimer->Cancel(); // Cancel appropriate request to socket switch (iEngineStatus) { case EConnecting: iSocket.CancelConnect(); iSocket.Close(); break; case ELookingUp: // Cancel look up attempt iResolver.Cancel(); iResolver.Close(); break; default: User::Panic(KPanicSocketsEngine, ESocketsBadStatus); break; } ChangeStatus(ENotConnected); } void CSocketsEngine::WriteL(const TDesC8& aData) { // Write data to socket if (iEngineStatus == EConnected) { iSocketsWriter->IssueWriteL(aData); } } void CSocketsEngine::Read() { // Initiate read of data from socket if ((iEngineStatus == EConnected) && (!iSocketsReader->IsActive())) { iSocketsReader->Start(); } } // from CActive void CSocketsEngine::RunL() { // Active object request complete handler. // iEngineStatus flags what request was made, so its // completion can be handled appropriately iTimer->Cancel(); // Cancel TimeOut timer before completion switch(iEngineStatus) { case EConnecting: // IP connection request if (iStatus == KErrNone) // Connection completed successfully { ChangeStatus(EConnected); Read(); //Start CSocketsReader Active object } else { iSocket.Close(); iConsole.ErrorNotify(KErrConnectionFailed, iStatus.Int()); ChangeStatus(ENotConnected); } break; case ELookingUp: iResolver.Close(); if (iStatus == KErrNone) { // DNS look up successful iNameRecord = iNameEntry(); // Extract domain name and IP address from name record Print(KStrDomainName); Print(iNameRecord.iName); TBuf<15> ipAddr; TInetAddr::Cast(iNameRecord.iAddr).Output(ipAddr); Print(KStrIPAddr); Print(ipAddr); Print(KStrNewLine); // And connect to the IP address ChangeStatus(ENotConnected); ConnectL(TInetAddr::Cast(iNameRecord.iAddr).Address()); } else { // DNS lookup failed iConsole.ErrorNotify(KErrDNSFailed, iStatus.Int()); ChangeStatus(ENotConnected); } break; default: User::Panic(KPanicSocketsEngine, ESocketsBadStatus); break; }; } void CSocketsEngine::TimerExpired() { Cancel(); iConsole.ErrorNotify(KErrSocketTimeout, KErrTimedOut); } void CSocketsEngine::ReportError(MEngineNotifier::TErrorType aErrorType, TInt aErrorCode) { // No recovery or retries are attempted in this example so we just // disconnect and inform the user Disconnect(); switch (aErrorType) { case MEngineNotifier::EDisconnected: iConsole.ErrorNotify(KErrSocketDisconnected, aErrorCode); break; case MEngineNotifier::EGeneralReadError: iConsole.ErrorNotify(KErrSocketRead, aErrorCode); break; case MEngineNotifier::ETimeOutOnWrite: iConsole.ErrorNotify(KErrSocketWriteTO, aErrorCode); break; case MEngineNotifier::EGeneralWriteError: iConsole.ErrorNotify(KErrSocketWriteFailed, aErrorCode); break; default: User::Panic(KPanicSocketsEngine, ESocketsBadStatus); break; } } void CSocketsEngine::ResponseReceived(const TDesC8& aBuffer) { iConsole.RecvNotify(aBuffer); } void CSocketsEngine::ChangeStatus(TSocketsEngineState aNewStatus) { // Update the status (and the status display) switch (aNewStatus) { case ENotConnected: iConsole.SetStatus(KStrNotConnected); break; case EConnecting: iConsole.SetStatus(KStrConnecting); break; case EConnected: iConsole.SetStatus(KStrConnected); break; case ELookingUp: iConsole.SetStatus(KStrLookingUp); break; default: User::Panic(KPanicSocketsEngine, ESocketsBadStatus); break; } iEngineStatus = aNewStatus; } void CSocketsEngine::Print(const TDesC& aDes) { // Print some text on the console iConsole.PrintNotify(aDes, CEikGlobalTextEditor::EItalic); } void CSocketsEngine::SetServerName(const TDesC& aName) { iServerName.Copy(aName); } const TDesC& CSocketsEngine::ServerName() const { return iServerName; } void CSocketsEngine::SetPort(TInt aPort) { iPort = aPort; } TInt CSocketsEngine::Port() const { return iPort; } TBool CSocketsEngine::Connected() const { return (iEngineStatus == EConnected); }