This release addresses the following:
- Multiple concurrent file transfer bug fixes. i.e. one device is concurrently receiving multiple files from multiple devices
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
// INCLUDES
#include "SIPExSocketEngine.h"
#include "SIPExSocketWriter.h"
#include "SIPExSocketReader.h"
#include "SIPExTimeOutTimer.h"
#include <e32svr.h>
#include <commdbconnpref.h>
// CONSTANTS
const TInt KGamePort( 10011 );
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::NewL
// Creates the instance of class and returns it.
// -----------------------------------------------------------------------------
//
EXPORT_C CSIPExSocketEngine* CSIPExSocketEngine::NewL(
MSIPExSocketEngineObserver& aObserver )
{
CSIPExSocketEngine* self = CSIPExSocketEngine::NewLC( aObserver );
CleanupStack::Pop(self);
return self;
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::NewLC
// Creates the instance of class and pushes it to the CleanupStack and return
// it.
// -----------------------------------------------------------------------------
//
EXPORT_C CSIPExSocketEngine* CSIPExSocketEngine::NewLC(
MSIPExSocketEngineObserver& aObserver )
{
CSIPExSocketEngine* self = new (ELeave) CSIPExSocketEngine( aObserver );
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::CSIPExSocketEngine
// Calls base classes constructor with priority value. Add class to the
// active sheduler.
// -----------------------------------------------------------------------------
//
CSIPExSocketEngine::CSIPExSocketEngine( MSIPExSocketEngineObserver& aObserver )
: CActive( EPriorityStandard ), iObserver( aObserver )
{
CActiveScheduler::Add( this );
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::~CSIPExSocketEngine
// Cancels any outstanding requests and deletes members.
// -----------------------------------------------------------------------------
//
EXPORT_C CSIPExSocketEngine::~CSIPExSocketEngine()
{
Cancel();
if ( iTimer )
{
iTimer->Cancel();
delete iTimer;
}
if ( iWriter )
{
iWriter->Cancel();
delete iWriter;
}
if ( iReader )
{
iReader->Cancel();
delete iReader;
}
iListenSocket.Close();
iDataSocket.Close();
iConnection.Close();
iSocketServer.Close();
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::ConstructL
// The socketserver is connected and members created.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::ConstructL()
{
iState = ENotConnected;
iTimer = CSIPExTimeOutTimer::NewL( *this );
// Open channel to Socket Server
User::LeaveIfError( iSocketServer.Connect() );
iReader = CSIPExSocketReader::NewL( iDataSocket, *this );
iWriter = CSIPExSocketWriter::NewL( iDataSocket, *this );
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::DoCancel
// From CActive. Cancels any outstanding request according the engine state.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::DoCancel()
{
iTimer->Cancel();
// Cancel appropriate request to socket
switch ( iState )
{
case EConnecting:
iDataSocket.CancelConnect();
break;
case EListening:
iListenSocket.CancelAccept();
break;
default:
break;
}
iConnection.Close();
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::RunL
// From CActive. Handles the state changes and notifing the observer.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::RunL()
{
iTimer->Cancel();
switch( iState )
{
case EConnecting:
if( iStatus.Int() == KErrNone )
{
ChangeStateAndNotify( EConnected );
Read();
}
else
{
ChangeStateAndNotify( ENotConnected );
}
break;
case EListening:
{
iListenSocket.Close();
if( iStatus.Int() == KErrNone )
{
ChangeStateAndNotify( EConnected );
Read();
}
else
{
ChangeStateAndNotify( ENotConnected );
}
}
break;
case ETimedOut:
if( iStatus.Int() == KErrNone )
{
iObserver.SocketState( ETimedOut );
iState = ENotConnected;
}
else
{
ChangeStateAndNotify( ENotConnected );
}
break;
default:
iObserver.SocketState( iStatus.Int() );
}
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::ConnectL
// Connects the socket to the remote host. Asynchronous.
// -----------------------------------------------------------------------------
//
EXPORT_C void CSIPExSocketEngine::ConnectL(
const TUint32 aIapId,
const TInetAddr& aIPAddress )
{
if( iState != ENotConnected )
{
return;
}
// Make first sure that underlying interface is active
StartInterfaceL( aIapId );
// Open a TCP socket
User::LeaveIfError( iDataSocket.Open(
iSocketServer, KAfInet, KSockStream, KProtocolInetTcp, iConnection ) );
iAddress = aIPAddress;
iAddress.SetPort( KGamePort );
// The Connect() allocate local address automatically if
// not bind yet.
iDataSocket.Connect( iAddress, iStatus );
iState = EConnecting;
SetActive();
iTimer->After( KTimeOut );
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::Write
// Starts the asynchronous writing
// -----------------------------------------------------------------------------
//
EXPORT_C void CSIPExSocketEngine::Write( const TDesC8& aTxt )
{
if( iState == EConnected && !iWriter->IsActive() )
{
iWriter->Write( aTxt );
}
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::Read
// Starts the asynchronous reading.
// -----------------------------------------------------------------------------
//
EXPORT_C void CSIPExSocketEngine::Read()
{
if( iState == EConnected && !iReader->IsActive() )
{
iReader->Read();
}
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::Stop
// Cancelling any outstanding read/write request.
// -----------------------------------------------------------------------------
//
EXPORT_C void CSIPExSocketEngine::Stop()
{
switch( iState )
{
case EConnected:
{
iWriter->Cancel();
iReader->Cancel();
TRequestStatus status;
iDataSocket.Shutdown( RSocket::EImmediate, status );
User::WaitForRequest( status);
iConnection.Close();
ChangeStateAndNotify( ENotConnected );
}
break;
case EListening:
case EConnecting:
Cancel();
break;
default:
break;
}
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::StartListeningL
// Resolves the local address and starts listening game port. Asynchronous.
// -----------------------------------------------------------------------------
//
EXPORT_C TInetAddr& CSIPExSocketEngine::StartListeningL( const TUint32 aIapId )
{
StartInterfaceL( aIapId );
ResolveLocalIPAddressL();
iAddress.SetPort( KGamePort );
User::LeaveIfError( iListenSocket.Open(
iSocketServer, KAfInet, KSockStream, KProtocolInetTcp ) );
User::LeaveIfError( iDataSocket.Open( iSocketServer ) );
User::LeaveIfError( iListenSocket.Bind( iAddress ) );
User::LeaveIfError( iListenSocket.Listen( 1 ) );
iListenSocket.Accept( iDataSocket, iStatus );
iState = EListening;
SetActive();
return iAddress;
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::StartInterfaceL
// Activates PDP ctx
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::StartInterfaceL( const TUint32 aIapId )
{
if( !iConnection.SubSessionHandle() )
{
User::LeaveIfError( iConnection.Open( iSocketServer ) );
}
TCommDbConnPref prefs;
prefs.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
prefs.SetDirection( ECommDbConnectionDirectionOutgoing );
prefs.SetIapId( aIapId );
User::LeaveIfError( iConnection.Start( prefs ) );
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::ResolveLocalIPAddressL
// Resolves the local IP address.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::ResolveLocalIPAddressL()
{
RHostResolver hostResolver;
TNameEntry entry;
User::LeaveIfError( hostResolver.Open( iSocketServer, KAfInet,
KProtocolInetTcp, iConnection ));
CleanupClosePushL( hostResolver );
User::LeaveIfError( hostResolver.GetByName( TPtrC(), entry ) );
if ( !TInetAddr::Cast( entry().iAddr ).IsWildAddr() )
{
iAddress = TInetAddr::Cast( entry().iAddr );
}
CleanupStack::PopAndDestroy(); // hostResolver
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::TimerExpired
// Callback from the timeout notifier. Completes the request with error code
// KErrNone and state ETimedOut.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::TimerExpired()
{
Cancel();
iState = ETimedOut;
TRequestStatus* status = &iStatus;
SetActive();
User::RequestComplete( status, KErrNone );
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::MessageReceived
// Notifies the observer.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::MessageReceived( TDesC8& aBuffer )
{
iObserver.SocketData( aBuffer );
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::ErrorInReading
// Completes the request with error code.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::ErrorInReading( TInt aError )
{
TRequestStatus* status = &iStatus;
SetActive();
User::RequestComplete( status, aError );
}
// From MWriterNotifier
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::WriteDone
//
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::WriteDone()
{
// Nothing to do
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::ErrorInWriting
// Completes the request with error code.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::ErrorInWriting( TInt aError )
{
TRequestStatus* status = &iStatus;
SetActive();
User::RequestComplete( status, aError );
}
// -----------------------------------------------------------------------------
// CSIPExSocketEngine::ChangeStateAndNotify
// Changes new state and notifies observer.
// -----------------------------------------------------------------------------
//
void CSIPExSocketEngine::ChangeStateAndNotify( TSocketEngineState aNewState )
{
iState = aNewState;
iObserver.SocketState( iState );
}
// End of file