diff -r 000000000000 -r b16258d2340f applayerprotocols/ftpengine/ftpprot/PICHNL.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerprotocols/ftpengine/ftpprot/PICHNL.CPP Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,307 @@ +// Copyright (c) 1998-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: +// FTP protocol engine +// Author: Philippe Gabriel +// Implements objet controling the PI channel of the FTP protocol +// Model the PI Channel as an FSM +// Transitions between states are triggered by PI methods and events +// coming from ESOCK +// +// + +/** + @file PICHNL.CPP + @internalComponent +*/ + +//#include +//#include +#include "DEBUG.H" +#include "PICHNL.H" +#include "FTPPROT.H" +#include +//#include +//#include + +// +// Definitions +// + +CPISocketRead::CPISocketRead(MPIChannelNotifier* aNotifier, + CPIChannel* aPIChannel) + : CActive(EPriorityStandard) +/** +CPISocketRead object +Read Write implementaion. +*/ + { + iNotifier = aNotifier; + iPIChannel = aPIChannel; + }; + +CPISocketRead* CPISocketRead::NewL(MPIChannelNotifier* aNotifier, + CPIChannel* aPIChannel) + { + CPISocketRead* self = new(ELeave) CPISocketRead(aNotifier,aPIChannel); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + }; + +void CPISocketRead::ConstructL() + { + CActiveScheduler::Add(this); + }; + +void CPISocketRead::DoCancel() + { + FTPPROTDEBUG(_DBGPichnl,_L("CPISocketRead::DoCancel() called")); + iSocket->CancelAll(); + }; + +void CPISocketRead::RunL() + { + FTPPROTDEBUG(_DBGPichnl,_L("CPISocketRead::RunL() called")); + if (iStatus == KErrNone) + { + // Call our notifier + iNotifier->PIChannelRcvNotification(); + } + else + { + // Uh!!! weird + Cancel(); + //Disconnect Pi Channel + iPIChannel->Disconnect(); + // Notify caller + iNotifier->PIChannelOperationError(MPIChannelNotifier::EPiConnectionReset); + } + }; + +void CPISocketRead::IssueRead(TDes8& aBuffer) +/** +Read Data from a Stream Socket +*/ + { + FTPPROTDEBUG(_DBGPichnl,_L("CPISocketRead::IssueRead() called\n")); + if (this->IsActive()) + return; + iSocket->RecvOneOrMore(aBuffer, 0, iStatus,iRcvLen); + SetActive(); + FTPPROTDEBUG(_DBGPichnl,_L("CPISocketRead::IssueRead() recv triggered\n")); + }; + +CPIChannel::CPIChannel(MPIChannelNotifier* aNotifier) + :CActive(CActive::EPriorityStandard) +/** +PI Channel object +*/ + { + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::CPIChannel called\n")); + //Initialise State + iPIChannelState = EPIChannelIdle; + iNotifier = aNotifier; + } + +CPIChannel* CPIChannel::NewL(MPIChannelNotifier* aNotifier, + RSocketServ& aSockServ) + { + CPIChannel* self = new (ELeave) CPIChannel(aNotifier); + CleanupStack::PushL(self); + self->ConstructL(aSockServ); + CleanupStack::Pop(); + return self; + } + +void CPIChannel::ConstructL(RSocketServ& aSockServ) + { + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::ConstructL called\n")); + iSockServ = aSockServ; + iReceiver = CPISocketRead::NewL(iNotifier,this); + CActiveScheduler::Add(this); + } + +CPIChannel::~CPIChannel() + { + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::~CPIChannel called\n")); + //Abort receive + if ( iReceiver ) + { + iReceiver->Cancel(); + delete iReceiver; + } + } + +void CPIChannel::RunL() + { + FTPPROTDEBUG(_DBGPichnl,_L("Mytest::RunL activated for CPIChannel\n")); + switch(iPIChannelState) + { + case EPIChannelIdle: + // Cannot be activated in that state + __ASSERT_DEBUG(FALSE, User::Panic(_L("CPIChannel"), EPIPanicOutOfState)); + break; + case EPIChannelConnecting: + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::RunL state: Connecting\n")); + // Check result of connecting request + switch (iStatus.Int()) + { + case KErrNone: + // If succeed set state to EPIChannelConnected + iPIChannelState = EPIChannelConnected; + // Call notifier + iNotifier->PIChannelOperationCompletion(MPIChannelNotifier::EPiConnectComplete); + break; + default: + // Reset channel to Idle/disconnect socket + Disconnect(); + // Notify caller + iNotifier->PIChannelOperationError(MPIChannelNotifier::EPiConnectFailed); + break; + } + break; + case EPIChannelDisconnecting: + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::RunL state: Connecting\n")); + // Assume disconnect always work + Disconnect(); + // Notify caller + iNotifier->PIChannelOperationCompletion(MPIChannelNotifier::EPiDisconnectComplete); + break; + case EPIChannelSending: + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::RunL state: EPIChannelSending\n")); + // Check result of send request + switch (iStatus.Int()) + { + case KErrNone: + // If succeed set state to EPIChannelConnected + iPIChannelState = EPIChannelConnected; + // Call notifier + iNotifier->PIChannelOperationCompletion(MPIChannelNotifier::EPiSendComplete); + break; + default: + // Reset channel to Idle/disconnect socket + Disconnect(); + // Notify caller + iNotifier->PIChannelOperationError(MPIChannelNotifier::EPiSendFailed); + break; + } + break; + default: + __ASSERT_DEBUG(FALSE, User::Panic(_L("CPIChannel::RunL"), 0)); + break; + } + } + +TBool CPIChannel::Connect(TSockAddr& aNetAddr) +/** +@return FALSE if a socket could not be openned + Caller must check the result and post an error if appropriate +*/ + { + // Check this is a valid state for this operation + __ASSERT_DEBUG((iPIChannelState == EPIChannelIdle), User::Panic(_L("CPIChannel"), EPIPanicChannelConnected)); + // Open a socket + if(KErrNone != iPiSocket.Open(iSockServ, KAfInet, KSockStream, KProtocolInetTcp)) + // Socket could not be openned, bail out + return FALSE; + // Give CPISocketRead the ref to my socket + iReceiver->SetSocket(&iPiSocket); + // Connect to peer + iPiSocket.Connect(aNetAddr, iStatus); + // Update state + iPIChannelState = EPIChannelConnecting; + // Activate the object + SetActive(); + // Everything's OK + return TRUE; + } +void CPIChannel::GetLocalAddress(TInetAddr& aLocalAddr) + { + // get my local address + // seems that LocalAddress function does not return + // the IP address until you've connected to somewhere + // hence I need this function to be called once the + // connect has succeeded to discover my IP address + iPiSocket.LocalName(aLocalAddr); + } + +TBool CPIChannel::Busy(void) +/** +@return The state of DTP Channel +*/ + { + return(iPIChannelState != EPIChannelConnected); + } + +void CPIChannel::Disconnect(void) + { + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::Disconnect called\n")); + //Close PI socket + iReceiver->Cancel(); + Cancel(); + iPiSocket.Close(); + iPIChannelState = EPIChannelIdle; + } + +void CPIChannel::SendCommand(TDes8& aCommand,TUint aSomeFlags,TBool aSendCRLF) + { + // If I'm not connected just return don't post error + if(iPIChannelState == EPIChannelIdle) + { + FTPPROTDEBUG(_DBGPichnl,_L("!!!!!Not Connected - SendCommand not triggered\n")); + return; + } + //__ASSERT_DEBUG(iPIChannelState != EPIChannelIdle, User::Panic(_L("CPIChannel"), EPIPanicChannelNotConnected)); + // Update the state + iPIChannelState = EPIChannelSending; + // Add the Telnet terminator sequence + // BIG BIG assumption here !! the buffer is big enough + // but FtpProtocol is my friend I trust it + if(aSendCRLF) + { + aCommand.Append(CR); + aCommand.Append(LF); + } + // Send the command + iPiSocket.Send(aCommand,aSomeFlags,iStatus); + // Activate the object + SetActive(); + } + + +void CPIChannel::GetNextAnswer(TDes8& aBuffer) + { + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::GetNextAnswer called\n")); + if(iPIChannelState != EPIChannelIdle) + // Fetch the reply sent by the server + iReceiver->IssueRead(aBuffer); + } + +void CPIChannel::DoCancel(void) + { + FTPPROTDEBUG(_DBGPichnl,_L("CPIChannel::DoCancel called\n")); + iReceiver->Cancel(); + switch(iPIChannelState) + { + case EPIChannelConnecting: + iPiSocket.CancelConnect(); + iPiSocket.Close(); + iPIChannelState = EPIChannelIdle; + break; + default: + break; + } + } +