applayerprotocols/ftpengine/ftpprot/DTPCHNL.CPP
changeset 0 b16258d2340f
--- /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 <in_sock.h>
+//#include <c32comm.h>
+#include "DEBUG.H"
+#include "DTPCHNL.H"
+#include "FTPPROT.H"
+//#include <es_sock.h>
+
+//
+// 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;
+		}
+
+	}