applayerprotocols/ftpengine/ftpprot/DTPCHNL.CPP
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // FTP protocol engine
       
    15 // Author:	Philippe Gabriel
       
    16 // Implements objet controling the DTP channel of the FTP protocol
       
    17 // Model the DTP Channel as an FSM
       
    18 // 
       
    19 //
       
    20 
       
    21 /**
       
    22  @file DTPCHNL.CPP
       
    23  @internalComponent
       
    24 */
       
    25 
       
    26 //#include <in_sock.h>
       
    27 //#include <c32comm.h>
       
    28 #include "DEBUG.H"
       
    29 #include "DTPCHNL.H"
       
    30 #include "FTPPROT.H"
       
    31 //#include <es_sock.h>
       
    32 
       
    33 //
       
    34 // Definitions
       
    35 //
       
    36 
       
    37 CDTPChannel::CDTPChannel(MDTPChannelNotifier* aNotifier,
       
    38 					 	 CFTPSetError* aCFTPSetError)
       
    39 						 :CActive(CActive::EPriorityStandard)
       
    40 /**
       
    41 DTP Channel object
       
    42 */			
       
    43 	{
       
    44 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::CDTPChannel called\n"));
       
    45 	//Initialise State
       
    46 	iDTPChannelState = EDTPChannelIdle;
       
    47 	iNotifier = aNotifier;
       
    48 	iCFTPSetError = aCFTPSetError;
       
    49 	}
       
    50 
       
    51 CDTPChannel* CDTPChannel::NewL(MDTPChannelNotifier* aNotifier,
       
    52 							   CFTPSetError* aCFTPSetError,
       
    53 							   RSocketServ& aSockServ)
       
    54 	{
       
    55 	CDTPChannel* self = new (ELeave) CDTPChannel(aNotifier,
       
    56 												 aCFTPSetError);
       
    57     CleanupStack::PushL(self);
       
    58     self->ConstructL(aSockServ);
       
    59     CleanupStack::Pop();
       
    60 	return self;
       
    61 	} 
       
    62 
       
    63 void CDTPChannel::ConstructL(RSocketServ& aSockServ)
       
    64 	{
       
    65 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::ConstructL called\n"));
       
    66 	iSockServ = aSockServ;
       
    67 	CActiveScheduler::Add(this);
       
    68 	} 
       
    69 
       
    70 CDTPChannel::~CDTPChannel()
       
    71 	{
       
    72 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::~CDTPChannel called\n"));
       
    73 	Disconnect();
       
    74 	}
       
    75 
       
    76 void CDTPChannel::DoCancel(void)
       
    77 	{
       
    78 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::DoCancel -state: "));
       
    79 		switch(iDTPChannelState)
       
    80 		{
       
    81 		case	EDTPChannelConnected:
       
    82 		case	EDTPChannelIdle:
       
    83 		case	EDTPChannelShutingDown:
       
    84 				FTPPROTDEBUG(_DBGDtpchnl,_L(" No req pending\n"));
       
    85 				//Nothing to do
       
    86 				break;
       
    87 		case	EDTPChannelConnecting:
       
    88 		case	EDTPChannelListening:
       
    89 		case	EDTPChannelReceiving:
       
    90 		case	EDTPChannelSending:
       
    91 				FTPPROTDEBUG(_DBGDtpchnl,_L("Req pending - Canceling all "));
       
    92 				// Cancel all request
       
    93 				iDTPTransferSocket.CancelAll();
       
    94 				// Close all sockets
       
    95 				iDTPListenSocket.Close();
       
    96 				iDTPTransferSocket.Close();
       
    97 				// Reset state
       
    98 				iDTPChannelState = EDTPChannelIdle;
       
    99 				break;
       
   100 		default:
       
   101 				FTPPROTDEBUG(_DBGDtpchnl,_L("INVALID STATE\n "));
       
   102 				// Cannot be activated in that state
       
   103 				__ASSERT_DEBUG(FALSE, User::Panic(_L("DTPChannel"), EDTPPanicChannelOutOfState));
       
   104 				break;
       
   105 		}
       
   106 	}
       
   107 
       
   108 TBool CDTPChannel::Connect(TSockAddr& aNetAddr)
       
   109 	{
       
   110 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::Connect called\n"));
       
   111 	if(KErrNone != iDTPTransferSocket.Open(iSockServ, KAfInet, KSockStream, KProtocolInetTcp))
       
   112 		return FALSE;
       
   113 	// Connect to peer
       
   114 	iDTPTransferSocket.Connect(aNetAddr, iStatus);
       
   115 	// Update state
       
   116 	iDTPChannelState = EDTPChannelConnecting;
       
   117 	// Activate the object
       
   118 	SetActive();
       
   119 	return TRUE;
       
   120 	}
       
   121 
       
   122 void CDTPChannel::Accept(void)	
       
   123 	{
       
   124 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::Accept called\n"));
       
   125 	iDTPListenSocket.Accept(iDTPTransferSocket, iStatus);
       
   126 	// Activate the object
       
   127 	SetActive();
       
   128 	}
       
   129 
       
   130 TUint CDTPChannel::ListeningPort(void)
       
   131 	{
       
   132 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::ListeningPort called\n"));
       
   133 	if(KErrNone != iDTPListenSocket.Open(iSockServ, KAfInet, KSockStream, KProtocolInetTcp))
       
   134 		return 0;
       
   135 	if(KErrNone != iDTPTransferSocket.Open(iSockServ))
       
   136 		return 0;
       
   137 	iLocalAddress.SetPort(0);
       
   138 	if(KErrNone != iDTPListenSocket.Bind(iLocalAddress))
       
   139 		{
       
   140 		Disconnect();
       
   141 		return 0;
       
   142 		}
       
   143 	if(KErrNone != iDTPListenSocket.Listen(1))
       
   144 		{
       
   145 		Disconnect();
       
   146 		return 0;
       
   147 		}
       
   148 	iDTPChannelState = EDTPChannelListening;
       
   149 	return iDTPListenSocket.LocalPort();
       
   150 	}
       
   151 
       
   152 void CDTPChannel::Disconnect(void)
       
   153 	{
       
   154 	Cancel();
       
   155 	iDTPListenSocket.Close();
       
   156 	iDTPTransferSocket.Close();
       
   157 	iDTPChannelState = EDTPChannelIdle;
       
   158 	}	
       
   159 
       
   160 void CDTPChannel::Send(TDesC8& aBuffer)
       
   161 	{
       
   162 	iDTPTransferSocket.Send(aBuffer,0,iStatus);
       
   163 	iDTPChannelState = EDTPChannelSending;
       
   164 	SetActive();	
       
   165 	}
       
   166 
       
   167 void CDTPChannel::SendEOF(void)
       
   168 	{
       
   169 	// Following line caused the connection to be closed with a 
       
   170 	// RST, SunOS ftpd complained about that 
       
   171 	// iDTPTransferSocket.Shutdown(RSocket::ENormal,iStatus);
       
   172 	// Following line to stop on a sending socket
       
   173 	// iDTPTransferSocket.Shutdown(RSocket::EStopOutput,iStatus);
       
   174 	// Following line to stop on a sending socket
       
   175 	iDTPTransferSocket.Shutdown(RSocket::EStopInput,iStatus);
       
   176 	iDTPChannelState = EDTPChannelShutingDown;
       
   177 	SetActive();	
       
   178 	}
       
   179 
       
   180 void CDTPChannel::Recv(TDes8& aBuffer)
       
   181 	{
       
   182 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::Recv called\n"));
       
   183 	iDTPTransferSocket.RecvOneOrMore(aBuffer, 0, iStatus,iRcvLen);
       
   184 	iDTPChannelState = EDTPChannelReceiving;
       
   185 	SetActive();	
       
   186 	}
       
   187 
       
   188 TBool CDTPChannel::Closed(void) 
       
   189 /**
       
   190 @return The state of DTP Channel
       
   191 */
       
   192 	{
       
   193 	return(iDTPChannelState==EDTPChannelIdle);
       
   194 	}
       
   195 
       
   196 TBool CDTPChannel::Connected(void) 
       
   197 /**
       
   198 @return The state of DTP Channel
       
   199 */
       
   200 	{
       
   201 	return((iDTPChannelState==EDTPChannelConnected)
       
   202 		|| (iDTPChannelState==EDTPChannelSending)
       
   203 		|| (iDTPChannelState==EDTPChannelReceiving));
       
   204 	}
       
   205 
       
   206 void CDTPChannel::RunL()
       
   207 	{
       
   208 	FTPPROTDEBUG(_DBGDtpchnl,_L("CDTPChannel::RunL -state: "));
       
   209 		switch(iDTPChannelState)
       
   210 		{
       
   211 		case	EDTPChannelIdle:
       
   212 				FTPPROTDEBUG(_DBGDtpchnl,_L(" Idle -PANIC-\n"));
       
   213 				// Cannot be activated in that state
       
   214 				__ASSERT_DEBUG(FALSE, User::Panic(_L("DTPChannel"), EDTPPanicChannelOutOfState));
       
   215 				// Do error recovery
       
   216 				break;
       
   217 		case	EDTPChannelConnecting:
       
   218 				FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelConnecting "));
       
   219 				// Check result of connecting request
       
   220 				switch (iStatus.Int())
       
   221 					{
       
   222 					case KErrNone:
       
   223 						FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n"));
       
   224 						// If succeed change state
       
   225 						iDTPChannelState = EDTPChannelConnected;
       
   226 						// Call notifier
       
   227 						iNotifier->DTPChannelOperationCompletion(MDTPChannelNotifier::EDtpConnectComplete);
       
   228 						break;
       
   229 					default:
       
   230 						FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus:<%d>\n "),iStatus.Int());
       
   231 						// Disconnect DTP Channel
       
   232 						Disconnect();
       
   233 						iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpConnectFailed);
       
   234 						break;
       
   235 					}
       
   236 				break;
       
   237 		case	EDTPChannelListening:
       
   238 				FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelListening "));
       
   239 				// Close listening socket immediately
       
   240 				// Don't want open ports hangin round
       
   241 				iDTPListenSocket.Close();
       
   242 				// Check result of accepting request
       
   243 				switch (iStatus.Int())
       
   244 					{
       
   245 					case KErrNone:
       
   246 						FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n"));
       
   247 						// If succeed change state
       
   248 						iDTPChannelState = EDTPChannelConnected;
       
   249 						// Call notifier
       
   250 						iNotifier->DTPChannelOperationCompletion(MDTPChannelNotifier::EDtpAcceptComplete);
       
   251 						break;
       
   252 					default:
       
   253 						FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus:<%d>\n "),iStatus.Int());
       
   254 						// Disconnect DTP Channel
       
   255 						Disconnect();
       
   256 						iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpConnectFailed);
       
   257 						break;
       
   258 					}
       
   259 				break;
       
   260 		case	EDTPChannelReceiving:
       
   261 				FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelReceiving "));
       
   262 				switch (iStatus.Int())
       
   263 					{
       
   264 					case KErrNone:
       
   265 						FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n"));
       
   266 						// Packet received - Call notifier
       
   267 						iNotifier->DTPChannelXferNotification(MDTPChannelNotifier::EDtpRcvMoreData);
       
   268 						break;
       
   269 					case KErrEof:
       
   270 						FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:KErrEof\n"));
       
   271 						// Disconnect DTP Channel
       
   272 						Disconnect();
       
   273 						// Server closed the DTP Channel - Call notifier
       
   274 						iNotifier->DTPChannelXferNotification(MDTPChannelNotifier::EDtpRcvComplete);
       
   275 						break;
       
   276 					default:
       
   277 						FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus: <%d>\n"),iStatus.Int());
       
   278 						// Disconnect DTP Channel
       
   279 						Disconnect();
       
   280 						// Notify caller
       
   281 						iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpRecvAborted);
       
   282 						break;
       
   283 					}
       
   284 				break;
       
   285 		case	EDTPChannelSending:
       
   286 				FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelSending "));
       
   287 				switch (iStatus.Int())
       
   288 					{
       
   289 					case KErrNone:
       
   290 						FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n"));
       
   291 						// Packet sent - Call notifier
       
   292 						iNotifier->DTPChannelXferNotification(MDTPChannelNotifier::EDtpSendComplete);
       
   293 						break;
       
   294 					default:
       
   295 						FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus: <%d>"),iStatus.Int());
       
   296 						// Disconnect DTP Channel
       
   297 						Disconnect();
       
   298 						// Notify caller
       
   299 						iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpSendAborted);
       
   300 						break;
       
   301 					}
       
   302 				break;
       
   303 		case	EDTPChannelShutingDown:
       
   304 				FTPPROTDEBUG(_DBGDtpchnl,_L("EDTPChannelShutingDown "));
       
   305 				// Whatever shutdown returns Disconnect DTP Channel
       
   306 				Disconnect();
       
   307 				switch (iStatus.Int())
       
   308 					{
       
   309 					// Only do a shutdown on a SendEOF operation
       
   310 					case KErrNone:
       
   311 						FTPPROTDEBUG(_DBGDtpchnl,_L("iStatus:OK\n"));
       
   312 						// DTP transfer socket closed Ok - Call notifier
       
   313 						iNotifier->DTPChannelXferNotification(MDTPChannelNotifier::EDtpSendEOFComplete);
       
   314 						break;
       
   315 					default:
       
   316 						// Something wrong with the shutdown, can't assume the peer received the file ok
       
   317 						FTPPROTDEBUG1(_DBGDtpchnl,_L("FAILED iStatus: <%d>\n"),iStatus.Int());
       
   318 						// Notify caller
       
   319 						iNotifier->DTPChannelOperationError(MDTPChannelNotifier::EDtpSendAborted);
       
   320 						break;
       
   321 					}
       
   322 				break;
       
   323 			default:
       
   324 				FTPPROTDEBUG(_DBGDtpchnl,_L("INVALID STATE\n "));
       
   325 				// Cannot be activated in that state
       
   326 				__ASSERT_DEBUG(FALSE, User::Panic(_L("DTPChannel"), EDTPPanicChannelOutOfState));
       
   327 				break;
       
   328 		}
       
   329 
       
   330 	}