obex/obexprotocol/obex/src/TObexServerStateObexConnecting.cpp
author hgs
Tue, 19 Oct 2010 11:00:12 +0800
changeset 57 f6055a57ae18
parent 0 d0791faffa3f
permissions -rw-r--r--
201041_03

// Copyright (c) 2005-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:
//

#include <obex.h>
#include "obexserverstatemachine.h"

/**
@file
@internalComponent

OBEX Connecting State
This state is entered during an OBEX connection attempt. The authentication state machine is
invoked via ParseConnectPacket and PrepareConnect packet.
A successful CONNECT will move the machine to Ready.
A CONNECT requiring a user password will move the machine to WaitForUserPassword
Other CONNECT results may stay in this state or move the machine to TransportConnected
A DISCONNECT will be processed
An ABORT will cause a Protocol Error
Any other OBEX operation will be answered with an OBEX error code
*/

TObexServerStateObexConnecting::TObexServerStateObexConnecting()
	{
#ifdef __FLOG_ACTIVE
	_LIT8(KName, "ObexConnecting");
	iName = KName;
#endif
	}

void TObexServerStateObexConnecting::Entry(CObexServerStateMachine& aContext)
	{
	// Reset the Connect State Machine
	aContext.Owner().SetConnectState(CObex::EConnTransport);
	// Chain on to Connect to process packet
	Connect(aContext, aContext.LastReceivedPacket());
	}

void TObexServerStateObexConnecting::Connect(CObexServerStateMachine& aContext, CObexPacket& aPacket)
	{
	// Process connect packet
	// This will return KErrNone if the packet is OK
	//                  a positive number if an OBEX error should be returned to the Client
	//				    a negative number if a Symbian error should be raised (as a Protocol Error)
	TInt parseConnectResult = aContext.Owner().ParseConnectPacket(aPacket);
	if (parseConnectResult == KErrNone)
		{
		FLOG(_L("OnPacketReceive ParseConnectPacket succesfull\r\n"));
		aContext.Transport().SendPacket().Init(CObex::EOpConnect); 
		// PrepareConnectPacket will check the present state and request
		// Auth, or check Auth as necessary and will return:
		//		An error & connect state set to EWaitForUserInput if a User Password is required  
		//		No error and connect state set to EConnObex if the connection was successful
		//		Connect state set to EConnTransport if there is an error packet to send back to the client
		//		Other connect states will return a packet to send and stay in the current state
		TInt err = aContext.Owner().PrepareConnectPacket(aContext.Transport().SendPacket());
		if ((err == KErrNone)	|| (aContext.Owner().GetConnectState() == CObex::EConnTransport)
								|| (aContext.Owner().GetConnectState() == CObex::EWaitForUserInput))
			{
			FLOG(_L("OnPacketReceive PrepareConnectPacket SUCCESS\r\n"));
			// If not waiting for user input, send the resultant packet
			if ( aContext.Owner().GetConnectState() != CObex::EWaitForUserInput )
				{
				aContext.Transport().SendPacket().SetFinal();
				aContext.Transport().Send();
				}
			// Move this (operation) state machine according to result of authentication state machine
			switch (aContext.Owner().GetConnectState())
				{
				case CObex::EConnTransport:
					aContext.ChangeState(CObexServerStateMachine::ETransportConnected);
					break;
				case CObex::EConnObex:
					aContext.ChangeState(CObexServerStateMachine::EReady);
					break;
				case CObex::EWaitForUserInput:
					aContext.ChangeState(CObexServerStateMachine::EWaitForUserPassword);
					break;
				}
			}
		else 
			{
			FTRACE( if (err)
						{
						FPrint(_L("OnPacketReceive PrepareConnectPacket FAILED"));
						}
					else
						{
						FPrint(_L("OnPacketReceive PrepareConnectPacket OK but state is %d"), aContext.Owner().GetConnectState());
						}
					);
			// Raising a Protocol Error will cause a Reset event resulting in a move to Disconnected.
			// So any code after this call will potentially be executed in a different state.
			aContext.Owner().Error(err);
			}
		}
	else if (parseConnectResult > 0) // so it's an OBEX error code
		{
		FLOG(_L("OnPacketReceive ParseConnectPacket FAILED (OBEX error)\r\n"));
		
		aContext.Transport().SendPacket().Init(parseConnectResult); 
		TInt rsp = aContext.Owner().PrepareErroredConnectPacket(aContext.Transport().SendPacket());
		if (rsp == KErrNone)	
   			{
			aContext.Transport().SendPacket().SetFinal();
			aContext.Transport().Send();
			aContext.ChangeState(CObexServerStateMachine::ETransportConnected);
			}			
		else
			{
			aContext.Owner().Error(rsp);	
			}
		}
	else // parseConnectResult < 0 so it's a Symbian error code
		{
		FLOG(_L("OnPacketReceive ParseConnectPacket FAILED (Symbian error)\r\n"));
		// Raising a Protocol Error will cause a Reset event resulting in a move to Disconnected.
		// So any code after this call will potentially be executed in a different state.
		aContext.Owner().Error(KErrAbort);
		}
	}

void TObexServerStateObexConnecting::Disconnect(CObexServerStateMachine& aContext, CObexPacket& aPacket)
	{
	// Process disconnect
	PerformDisconnect(aContext, aPacket);
	}

void TObexServerStateObexConnecting::Put(CObexServerStateMachine& aContext, CObexPacket& /*aPacket*/)
	{
	// Send ERespBadRequest and return to ETransportConnected
	aContext.Transport().Send(ERespBadRequest);
	aContext.ChangeState(CObexServerStateMachine::ETransportConnected);
	}

void TObexServerStateObexConnecting::Get(CObexServerStateMachine& aContext, CObexPacket& /*aPacket*/)
	{
	// Send ERespConflict and return to ETransportConnected
	aContext.Transport().Send(ERespConflict);
	aContext.ChangeState(CObexServerStateMachine::ETransportConnected);
	}

void TObexServerStateObexConnecting::SetPath(CObexServerStateMachine& aContext, CObexPacket& /*aPacket*/)
	{
	// Send ERespConflict and return to ETransportConnected
	aContext.Transport().Send(ERespConflict);
	aContext.ChangeState(CObexServerStateMachine::ETransportConnected);
	}

void TObexServerStateObexConnecting::Abort(CObexServerStateMachine& aContext)
	{
	// Send ERespSuccess
	// Any other response would, according to the spec,
	// require the Obex client to bring down the transport.
	// Our attempt is to be resilient if an 'Abort'
	// is sent erroneously whilst we are in this state.
	aContext.Transport().Send(ERespSuccess);
	aContext.ChangeState(CObexServerStateMachine::ETransportConnected);
	}
	
void TObexServerStateObexConnecting::OverrideRequestHandling(CObexServerStateMachine& aContext, TObexResponse aResponse)
	{
	// Send the server applications response and return to Transport Connected
	aContext.Transport().Send(aResponse);
	aContext.ChangeState(CObexServerStateMachine::ETransportConnected);
	}