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); 
    }