⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 symsock.cpp

📁 Simple Jabber Client for Symbian Platform
💻 CPP
字号:
/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  Jabber
 *  Copyright (C) 2004 Xie Tian Lu  http://sabber.jabberstudio.org/
 */

#include "symsock.h"
#include "sockstream.h"
#include "osutil.h"

const TInt KTimeOut = 20000000; // 30 seconds time-out
					 
//-------------------------------------------------------------------------------------------
// CSymSocket class for connection and shutdown
//-------------------------------------------------------------------------------------------

CSymSocket::CSymSocket() : CActive( EPriorityStandard )
{
}

CSymSocket::~CSymSocket()
{
	DoCancel();
	delete iReader;
	delete iWriter;
	delete iTimer;
	iSocket.Close();
	iSocketServ.Close();
}

CSymSocket* CSymSocket::NewL( MUINotify* aConsole, TUint aRCacheSize, TUint aWCachSize )
{
	CSymSocket* self = NewLC( aConsole, aRCacheSize, aWCachSize );
	CleanupStack::Pop();
	return self;
}

CSymSocket* CSymSocket::NewLC( MUINotify* aConsole, TUint aRCacheSize, TUint aWCachSize )
{
	CSymSocket* self = new (ELeave) CSymSocket;
	CleanupStack::PushL(self);
	self->ConstructL( aConsole, aRCacheSize, aWCachSize );
	return self;
}

/**
 * Construct object, and open a socket 
 */
void CSymSocket::ConstructL( MUINotify* aConsole, TUint aRCacheSize, TUint aWCacheSize )
{
	iProtocol = KProtocolInetTcp;
	iUi = aConsole;
	iSocketStatus = ESocketUnknown;

	iTimeOut = KTimeOut; 
	iTimer = CTimeOutTimer::NewL(EPriorityHigh, *this);
	CActiveScheduler::Add(this); 

	// Open channel to Socket Server
	User::LeaveIfError( iSocketServ.Connect() );
	
	iReader = CSockReader::NewL( &iSocket, this, aRCacheSize );
	iWriter = CSockWriter::NewL( &iSocket, this, aWCacheSize );
	iSocketStatus = ESocketUnknown;
}

/**
 * Cancel asychronous requests
 */
void CSymSocket::DoCancel()
{
	if ( iTimer )
		iTimer->Cancel();

	// Cancel appropriate request to socket
	switch ( iSocketStatus )
	{
		case EConnecting:
			iSocket.CancelConnect();
		break;

		case ELookingUp:
			// Cancel look up attempt
			iResolver.Cancel();
			iResolver.Close();
		break;
		default:;
	}
}

void CSymSocket::SetServer( const TDesC& aServerName, TUint16 aPort, TUint aProtocol )
{
	iProtocol = aProtocol;

	User::LeaveIfError( iResolver.Open( iSocketServ, KAfInet, KProtocolInetTcp ) );
	// DNS request for name resolution
	if ( KErrNone != iResolver.GetByName( aServerName, iNameEntry ) ) {
		iSocketStatus = ELookUpFailed;
	} else {
		iNameRecord = iNameEntry();
		iAddress.SetAddress( TInetAddr::Cast(iNameRecord.iAddr).Address() );
	}
	iResolver.Close();
	iAddress.SetPort( aPort );
}

void CSymSocket::SetServerName( const TDesC& aServerName )
{
	User::LeaveIfError( iResolver.Open( iSocketServ, KAfInet, KProtocolInetUdp ) );

	// DNS request for name resolution
	if ( KErrNone != iResolver.GetByName( aServerName, iNameEntry ) ) {
		iSocketStatus = ELookUpFailed;
	} else {
		iNameRecord = iNameEntry();
		iAddress.SetAddress( TInetAddr::Cast(iNameRecord.iAddr).Address() );
	}

	iResolver.Close();
}

void CSymSocket::SetServerPort( TUint16 port )
{
	iAddress.SetPort( port );
}

void CSymSocket::ConnectL()
{
	// Open a TCP/UDP socket
	if ( iProtocol == KProtocolInetUdp ) {
		User::LeaveIfError( iSocket.Open( iSocketServ, KAfInet, KSockDatagram, KProtocolInetUdp ) );
		iAddress.SetAddress( KInetAddrAny );
		//iAddress.SetAddress( INET_ADDR( 218,106,172,228 ) );
		//iAddress.SetAddress( INET_ADDR( 192,168,0,91 ) );
		iAddress.SetPort( 2468 );
		iSocket.Bind( iAddress );
		iSocketStatus = EConnected;
		//SYS_TRACE1( 0, "udp socket created" );
	} else {
		User::LeaveIfError( iSocket.Open( iSocketServ, KAfInet, KSockStream, KProtocolInetTcp ) );
		iSocket.Connect( iAddress, iStatus );
		iSocketStatus = EConnecting;
		iTimer->After(iTimeOut);
		SetActive();
	}
}

/**
 * Shutdown connection request
 */
void CSymSocket::Stop()
{
	switch ( iSocketStatus )
	{
		case EConnected:
			// Stop live connection
			iReader->Cancel();
			iWriter->Cancel();
		break;
		
		case EConnecting:
		case ELookingUp:
			// if request to CEchoEngine, then stop it
			Cancel();
		break;
	
		default:;
	}
}

void CSymSocket::Close()
{
	iReader->Cancel();
	iWriter->Cancel();
	iSocket.Close();
	iSocketStatus = ESocketUnknown;
}

int CSymSocket::Send( const char* buf, int len, int flags ) 
{
	if ( iSocketStatus == EWriteFailed || iSocketStatus == EReadFailed )
		return -1;

	return iWriter->Send( buf, len );
}

int CSymSocket::Recv( char* buf, int len, int flags )
{
	if ( iSocketStatus == EReadFailed || iSocketStatus == EWriteFailed )
		return -1;

	return iReader->Recv( buf, len );
}

int CSymSocket::SendTo( const char* buf, int len, TInetAddr dest )
{
	return iWriter->SendTo( dest, buf, len );
}

int CSymSocket::RecvFrom( char* buf, int len, TInetAddr& from )
{	
	return iReader->RecvFrom( from, buf, len );
}

/*
int CSymSocket::SendTo( const char* ip, short port, const char* buf, int len, int flags )
{
	return 0;
}

int CSymSocket::RecvFrom( char* ip, short& port, char* buf, int len, int flags )
{
	return 0;
}
*/

/**
 * Active object request complete handler.
 * iEngineStatus flags what request was made, so its
 * completion can be handled appropriately
 */
void CSymSocket::RunL()
{
	iTimer->Cancel(); // Cancel TimeOut timer before completion

	TBuf<15> ipAddr;

	switch( iSocketStatus )
	{
		case EConnecting:				// IP connection request
			if (iStatus == KErrNone)	// Connection completed sucessfully
			{
				iSocketStatus = EConnected;
				iUi->Notify( iSocketStatus );
			}
			else
			{
				iSocketStatus = EConnectFailed;
				iUi->ConnectFailed();
			}
		break;

		case ETimeout:
			iSocketStatus = ETimeout;
			iUi->ConnectTimeout();
		break;
		
		case ELookingUp:
			iResolver.Close();
			if (iStatus == KErrNone)	// DNS look up successful
			{
				iNameRecord = iNameEntry();
				TInetAddr::Cast(iNameRecord.iAddr).Output(ipAddr);
			}
			else
			{	
				iSocketStatus = ELookUpFailed;
			}
		break;

		default:;
	}

	//( ( CUUClientAppUi* )iUi )->Notify( iSocketStatus );
}

TSymSocketState CSymSocket::GetCurStatus()
{
	return iSocketStatus;
}

/**
 * Implements MTimeOutNotify: called when timeout expired
 */
void CSymSocket::TimerExpired()
{
	Cancel();
	iSocketStatus = ETimeout;
	TRequestStatus* p = &iStatus;		
	
	// Signal CSymSocket::RunL() imediately
	SetActive();
	User::RequestComplete( p, ETimeout );
}

void CSymSocket::SocketEvent( TSymSocketState aState )
{
	switch ( aState ) 
	{
	case EReadFailed:
		iSocketStatus = EReadFailed;
	break;

	case EWriteFailed:
		iSocketStatus = EWriteFailed;
	break;
	}
}

TInt CSymSocket::HasSocketClosed()
{
	return iSocketStatus == ESocketUnknown;
}

TUint CSymSocket::GetProtocol()
{
	return iProtocol;
}


//-------------------------------------------------------------------------------------------
// sock util functions
//-------------------------------------------------------------------------------------------


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -