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