diff -r 000000000000 -r b16258d2340f applayerprotocols/ftpengine/ftpprot/DTPCHNL.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerprotocols/ftpengine/ftpprot/DTPCHNL.CPP Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,330 @@ +// 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 DTP channel of the FTP protocol +// Model the DTP Channel as an FSM +// +// + +/** + @file DTPCHNL.CPP + @internalComponent +*/ + +//#include +//#include +#include "DEBUG.H" +#include "DTPCHNL.H" +#include "FTPPROT.H" +//#include + +// +// Definitions +// + +CDTPChannel::CDTPChannel(MDTPChannelNotifier* aNotifier, + CFTPSetError* aCFTPSetError) + :CActive(CActive::EPriorityStandard) +/** +DTP Channel object +*/ + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::CDTPChannel called\n")); + //Initialise State + iDTPChannelState = EDTPChannelIdle; + iNotifier = aNotifier; + iCFTPSetError = aCFTPSetError; + } + +CDTPChannel* CDTPChannel::NewL(MDTPChannelNotifier* aNotifier, + CFTPSetError* aCFTPSetError, + RSocketServ& aSockServ) + { + CDTPChannel* self = new (ELeave) CDTPChannel(aNotifier, + aCFTPSetError); + CleanupStack::PushL(self); + self->ConstructL(aSockServ); + CleanupStack::Pop(); + return self; + } + +void CDTPChannel::ConstructL(RSocketServ& aSockServ) + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::ConstructL called\n")); + iSockServ = aSockServ; + CActiveScheduler::Add(this); + } + +CDTPChannel::~CDTPChannel() + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::~CDTPChannel called\n")); + Disconnect(); + } + +void CDTPChannel::DoCancel(void) + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::DoCancel -state: ")); + switch(iDTPChannelState) + { + case EDTPChannelConnected: + case EDTPChannelIdle: + case EDTPChannelShutingDown: + FTPPROTDEBUG(_DBGDtpchnl,_L(" No req pending\n")); + //Nothing to do + break; + case EDTPChannelConnecting: + case EDTPChannelListening: + case EDTPChannelReceiving: + case EDTPChannelSending: + FTPPROTDEBUG(_DBGDtpchnl,_L("Req pending - Canceling all ")); + // Cancel all request + iDTPTransferSocket.CancelAll(); + // Close all sockets + iDTPListenSocket.Close(); + iDTPTransferSocket.Close(); + // Reset state + iDTPChannelState = EDTPChannelIdle; + break; + default: + FTPPROTDEBUG(_DBGDtpchnl,_L("INVALID STATE\n ")); + // Cannot be activated in that state + __ASSERT_DEBUG(FALSE, User::Panic(_L("DTPChannel"), EDTPPanicChannelOutOfState)); + break; + } + } + +TBool CDTPChannel::Connect(TSockAddr& aNetAddr) + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::Connect called\n")); + if(KErrNone != iDTPTransferSocket.Open(iSockServ, KAfInet, KSockStream, KProtocolInetTcp)) + return FALSE; + // Connect to peer + iDTPTransferSocket.Connect(aNetAddr, iStatus); + // Update state + iDTPChannelState = EDTPChannelConnecting; + // Activate the object + SetActive(); + return TRUE; + } + +void CDTPChannel::Accept(void) + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::Accept called\n")); + iDTPListenSocket.Accept(iDTPTransferSocket, iStatus); + // Activate the object + SetActive(); + } + +TUint CDTPChannel::ListeningPort(void) + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::ListeningPort called\n")); + if(KErrNone != iDTPListenSocket.Open(iSockServ, KAfInet, KSockStream, KProtocolInetTcp)) + return 0; + if(KErrNone != iDTPTransferSocket.Open(iSockServ)) + return 0; + iLocalAddress.SetPort(0); + if(KErrNone != iDTPListenSocket.Bind(iLocalAddress)) + { + Disconnect(); + return 0; + } + if(KErrNone != iDTPListenSocket.Listen(1)) + { + Disconnect(); + return 0; + } + iDTPChannelState = EDTPChannelListening; + return iDTPListenSocket.LocalPort(); + } + +void CDTPChannel::Disconnect(void) + { + Cancel(); + iDTPListenSocket.Close(); + iDTPTransferSocket.Close(); + iDTPChannelState = EDTPChannelIdle; + } + +void CDTPChannel::Send(TDesC8& aBuffer) + { + iDTPTransferSocket.Send(aBuffer,0,iStatus); + iDTPChannelState = EDTPChannelSending; + SetActive(); + } + +void CDTPChannel::SendEOF(void) + { + // Following line caused the connection to be closed with a + // RST, SunOS ftpd complained about that + // iDTPTransferSocket.Shutdown(RSocket::ENormal,iStatus); + // Following line to stop on a sending socket + // iDTPTransferSocket.Shutdown(RSocket::EStopOutput,iStatus); + // Following line to stop on a sending socket + iDTPTransferSocket.Shutdown(RSocket::EStopInput,iStatus); + iDTPChannelState = EDTPChannelShutingDown; + SetActive(); + } + +void CDTPChannel::Recv(TDes8& aBuffer) + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::Recv called\n")); + iDTPTransferSocket.RecvOneOrMore(aBuffer, 0, iStatus,iRcvLen); + iDTPChannelState = EDTPChannelReceiving; + SetActive(); + } + +TBool CDTPChannel::Closed(void) +/** +@return The state of DTP Channel +*/ + { + return(iDTPChannelState==EDTPChannelIdle); + } + +TBool CDTPChannel::Connected(void) +/** +@return The state of DTP Channel +*/ + { + return((iDTPChannelState==EDTPChannelConnected) + || (iDTPChannelState==EDTPChannelSending) + || (iDTPChannelState==EDTPChannelReceiving)); + } + +void CDTPChannel::RunL() + { + FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::RunL -state: ")); + switch(iDTPChannelState) + { + case EDTPChannelIdle: + FTPPROTDEBUG(_DBGDtpchnl,_L(" Idle -PANIC-\n")); + // Cannot be activated in that state + __ASSERT_DEBUG(FALSE, User::Panic(_L("DTPChannel"), EDTPPanicChannelOutOfState)); + // Do error recovery + break; + case EDTPChannelConnecting: + FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelConnecting ")); + // Check result of connecting request + switch (iStatus.Int()) + { + case KErrNone: + FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n")); + // If succeed change state + iDTPChannelState = EDTPChannelConnected; + // Call notifier + iNotifier->DTPChannelOperationCompletion(MDTPChannelNotifier::EDtpConnectComplete); + break; + default: + FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus:<%d>\n "),iStatus.Int()); + // Disconnect DTP Channel + Disconnect(); + iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpConnectFailed); + break; + } + break; + case EDTPChannelListening: + FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelListening ")); + // Close listening socket immediately + // Don't want open ports hangin round + iDTPListenSocket.Close(); + // Check result of accepting request + switch (iStatus.Int()) + { + case KErrNone: + FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n")); + // If succeed change state + iDTPChannelState = EDTPChannelConnected; + // Call notifier + iNotifier->DTPChannelOperationCompletion(MDTPChannelNotifier::EDtpAcceptComplete); + break; + default: + FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus:<%d>\n "),iStatus.Int()); + // Disconnect DTP Channel + Disconnect(); + iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpConnectFailed); + break; + } + break; + case EDTPChannelReceiving: + FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelReceiving ")); + switch (iStatus.Int()) + { + case KErrNone: + FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n")); + // Packet received - Call notifier + iNotifier->DTPChannelXferNotification(MDTPChannelNotifier::EDtpRcvMoreData); + break; + case KErrEof: + FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:KErrEof\n")); + // Disconnect DTP Channel + Disconnect(); + // Server closed the DTP Channel - Call notifier + iNotifier->DTPChannelXferNotification(MDTPChannelNotifier::EDtpRcvComplete); + break; + default: + FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus: <%d>\n"),iStatus.Int()); + // Disconnect DTP Channel + Disconnect(); + // Notify caller + iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpRecvAborted); + break; + } + break; + case EDTPChannelSending: + FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelSending ")); + switch (iStatus.Int()) + { + case KErrNone: + FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n")); + // Packet sent - Call notifier + iNotifier->DTPChannelXferNotification(MDTPChannelNotifier::EDtpSendComplete); + break; + default: + FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus: <%d>"),iStatus.Int()); + // Disconnect DTP Channel + Disconnect(); + // Notify caller + iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpSendAborted); + break; + } + break; + case EDTPChannelShutingDown: + FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelShutingDown ")); + // Whatever shutdown returns Disconnect DTP Channel + Disconnect(); + switch (iStatus.Int()) + { + // Only do a shutdown on a SendEOF operation + case KErrNone: + FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n")); + // DTP transfer socket closed Ok - Call notifier + iNotifier->DTPChannelXferNotification(MDTPChannelNotifier::EDtpSendEOFComplete); + break; + default: + // Something wrong with the shutdown, can't assume the peer received the file ok + FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus: <%d>\n"),iStatus.Int()); + // Notify caller + iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpSendAborted); + break; + } + break; + default: + FTPPROTDEBUG(_DBGDtpchnl,_L("INVALID STATE\n ")); + // Cannot be activated in that state + __ASSERT_DEBUG(FALSE, User::Panic(_L("DTPChannel"), EDTPPanicChannelOutOfState)); + break; + } + + }