diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/l2cap/l2sapstates.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/l2cap/l2sapstates.h Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,484 @@ +// Copyright (c) 1999-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: +// Defines classes to implement each state a L2CAP sap can +// be in. +// Note we assume for all states that the socket will only send us +// reasonable state change requests - i.e. it won't call PassiveOpen +// on a connected socket. We make no such assumption about events +// coming from the Mux +// +// + + +#ifndef L2CAPSAPSTATES_H +#define L2CAPSAPSTATES_H + +#include +#include +#include + + +#include "L2CapChannelConfig.h" +#include "L2types.h" + +class CL2CAPConnectionSAP; +class CL2CAPSAPStateFactory; + +class CL2CAPMux; + +NONSHARABLE_CLASS(TL2CAPSAPState) + { +public: + friend class CL2CAPConnectionSAP; + + TL2CAPSAPState(CL2CAPSAPStateFactory& aFactory); + + + // Events called from the SAP. As we assume that the socket + // will never send us requests which are invalid for our state, + // the default is to do nothing. Derived state classes can then + // simply implement the appropriate bits. + virtual void Start(CL2CAPConnectionSAP& aSAP) const; + + virtual TInt Ioctl(CL2CAPConnectionSAP& aSAP, TUint aLevel, TUint aName, TDes8* aOption) const; + virtual void CancelIoctl(CL2CAPConnectionSAP& aSAP, TUint aLevel, TUint aName) const; + virtual void IoctlComplete(CL2CAPConnectionSAP& aSAP, TInt aErr, TUint aLevel, TUint aName, TDesC8* aBuf) const; + + virtual void ActiveOpen(CL2CAPConnectionSAP& aSAP) const; + virtual TInt PassiveOpen(CL2CAPConnectionSAP& aSAP, TUint aQueSize) const; + virtual void Shutdown(CL2CAPConnectionSAP& aSAP) const; + virtual void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + + virtual TInt Send(CL2CAPConnectionSAP& aSAP, RMBufChain& aData, TUint aFlag) const; + virtual TInt Read(CL2CAPConnectionSAP& aSAP, RMBufChain& aData) const; + + virtual void Bound(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + virtual void ChannelConfigured(CL2CAPConnectionSAP& aSAP, + CL2CapChannelConfig& aConfig, + CL2CAPMux& aMuxer, + TL2CAPPort aLocalPort, + TL2CAPPort aRemotePort); + + virtual void ReconfiguringChannel(CL2CAPConnectionSAP& aSAP) const; + + virtual void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + virtual void CloseOutgoingSDUQueue(CL2CAPConnectionSAP& aSAP) const; + virtual void SignalHandlerError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + virtual void LinkUp(CL2CAPConnectionSAP& aSAP) const; + virtual void ChannelOpened(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the Data Controller. + virtual void NewData(CL2CAPConnectionSAP& aSAP) const; + virtual TInt NewDataAsyncCallBack(CL2CAPConnectionSAP& aSAP) const; + virtual void CanSend(CL2CAPConnectionSAP& aSAP) const; + virtual void SDUQueueClosed(CL2CAPConnectionSAP& aSAP) const; + virtual void DataPlaneError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + + // Events from the security manager. + virtual void AccessRequestComplete(CL2CAPConnectionSAP& aSignalHandler, TInt aResult) const; + + // State Transition Actions. + virtual void Enter(CL2CAPConnectionSAP& aSAP) const; + virtual void Exit(CL2CAPConnectionSAP& aSAP) const; + + // Helper function. + void NotifySocketClosed(CL2CAPConnectionSAP& aSAP) const; + +protected: + void StartCalledWhileDisconnected(CL2CAPConnectionSAP& aSAP) const; + void PanicInState(TL2CAPPanic aPanic) const; + void DebugPanicInState(TL2CAPPanic aPanic) const; + +protected: + CL2CAPSAPStateFactory& iFactory; // Used to get next state. + +private: + // Forbid copying + TL2CAPSAPState(const TL2CAPSAPState&); + const TL2CAPSAPState& operator=(const TL2CAPSAPState&) const; + }; + + + + +/** + The CLOSED state. + + This is the state that newly created saps start in, and the state + they end in after a communication has closed down or a connection + failed. + + Basically this is a quiescent state from which the sap can go to + different futures. +**/ + +NONSHARABLE_CLASS(TL2CAPSAPStateClosed) : public TL2CAPSAPState + { +public: + TL2CAPSAPStateClosed(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + void Start(CL2CAPConnectionSAP& aSAP) const; + void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + void Shutdown(CL2CAPConnectionSAP& aSAP) const; + + void ActiveOpen(CL2CAPConnectionSAP& aSAP) const; + void SDUQueueClosed(CL2CAPConnectionSAP& aSAP) const; + + void Bound(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + void SignalHandlerError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + + // Events called from the Data Controller. + TInt NewDataAsyncCallBack(CL2CAPConnectionSAP& aSAP) const; + + // State Transition Actions. + void Enter(CL2CAPConnectionSAP& aSAP) const; + }; + +NONSHARABLE_CLASS(TL2CAPSAPStateChannelPendingBase) : public TL2CAPSAPState + { +public: + TL2CAPSAPStateChannelPendingBase(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + virtual void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + virtual void Shutdown(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + virtual void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + virtual void SignalHandlerError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + }; + +NONSHARABLE_CLASS(TL2CAPSAPStatePassiveLinkPending) : public TL2CAPSAPStateChannelPendingBase + { +public: + TL2CAPSAPStatePassiveLinkPending(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP Signal Handler. + void LinkUp(CL2CAPConnectionSAP& aSAP) const; + }; + +NONSHARABLE_CLASS(TL2CAPSAPStateActiveLinkPending) : public TL2CAPSAPStateChannelPendingBase + { +public: + TL2CAPSAPStateActiveLinkPending(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP Signal Handler. + void LinkUp(CL2CAPConnectionSAP& aSAP) const; + }; + +NONSHARABLE_CLASS(TL2CAPSAPStateActiveSecMode4AccessRequestPending) : public TL2CAPSAPStateChannelPendingBase + { +public: + TL2CAPSAPStateActiveSecMode4AccessRequestPending(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + void Shutdown(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + void SignalHandlerError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + + void AccessRequestComplete(CL2CAPConnectionSAP& aSignalHandler, TInt aResult) const; + }; + +NONSHARABLE_CLASS(TL2CAPSAPStateActiveChannelRequestPending) : public TL2CAPSAPStateChannelPendingBase + { +public: + TL2CAPSAPStateActiveChannelRequestPending(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP Signal Handler. + void ChannelOpened(CL2CAPConnectionSAP& aSAP) const; + }; + +NONSHARABLE_CLASS(TL2CAPSAPStatePassiveAccessRequestPending) : public TL2CAPSAPStateChannelPendingBase + { +public: + TL2CAPSAPStatePassiveAccessRequestPending(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + void Shutdown(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + void SignalHandlerError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + + // Events from the security manager. + void AccessRequestComplete(CL2CAPConnectionSAP& aSignalHandler, TInt aResult) const; + }; + +NONSHARABLE_CLASS(TL2CAPSAPStateActiveSecMode2AccessRequestPending) : public TL2CAPSAPStateChannelPendingBase + { +public: + TL2CAPSAPStateActiveSecMode2AccessRequestPending(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + void Shutdown(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + void SignalHandlerError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + + // Events from the security manager. + void AccessRequestComplete(CL2CAPConnectionSAP& aSignalHandler, TInt aResult) const; + }; + + +NONSHARABLE_CLASS(TL2CAPSAPStatePendingOpen) : public TL2CAPSAPStateChannelPendingBase + { +public: + TL2CAPSAPStatePendingOpen(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP Signal Handler. + void ChannelConfigured(CL2CAPConnectionSAP& aSAP, + CL2CapChannelConfig& aConfig, + CL2CAPMux& aMuxer, + TL2CAPPort aLocalPort, + TL2CAPPort aRemotePort); + + // Events called from the Data Controller. + void DataPlaneError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + + // State Transition Actions. + }; + + +NONSHARABLE_CLASS(TL2CAPSAPStateListening) : public TL2CAPSAPState + { +public: + TL2CAPSAPStateListening(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + void Shutdown(CL2CAPConnectionSAP& aSAP) const; + void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the Data Controller. + + // State Transition Actions. + void Enter(CL2CAPConnectionSAP& aSAP) const; + void Exit(CL2CAPConnectionSAP& aSAP) const; + }; + + +NONSHARABLE_CLASS(TL2CAPSAPStateOpen) : public TL2CAPSAPState + { +public: + TL2CAPSAPStateOpen(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + virtual TInt Send(CL2CAPConnectionSAP& aSAP, RMBufChain& aData, TUint aFlag) const; + virtual TInt Read(CL2CAPConnectionSAP& aSAP, RMBufChain& aData) const; + + virtual void Shutdown(CL2CAPConnectionSAP& aSAP) const; + virtual void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + virtual void ReconfiguringChannel(CL2CAPConnectionSAP& aSAP) const; + virtual void ChannelConfigured(CL2CAPConnectionSAP& aSAP, + CL2CapChannelConfig& aConfig, + CL2CAPMux& aMuxer, + TL2CAPPort aLocalPort, + TL2CAPPort aRemotePort); + virtual void SignalHandlerError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + virtual void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + virtual void CloseOutgoingSDUQueue(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the Data Controller. + virtual void NewData(CL2CAPConnectionSAP& aSAP) const; + virtual TInt NewDataAsyncCallBack(CL2CAPConnectionSAP& aSAP) const; + virtual void CanSend(CL2CAPConnectionSAP& aSAP) const; + virtual void DataPlaneError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + + // State Transition Actions. + }; + +NONSHARABLE_CLASS(TL2CAPSAPStateAccepting) : public TL2CAPSAPStateOpen + { +public: + TL2CAPSAPStateAccepting(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + void Start(CL2CAPConnectionSAP& aSAP) const; + void NewData(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the SAP Signal Handler. + void ReconfiguringChannel(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the Data Controller. + TInt NewDataAsyncCallBack(CL2CAPConnectionSAP& aSAP) const; + void CanSend(CL2CAPConnectionSAP& aSAP) const; + + // State Transition Actions. + void Exit(CL2CAPConnectionSAP& aSAP) const; + }; + +/** +This state exists to determine if the other side believes the link is opened. +It won't send us data until it has finished configuring the channel. On +reception of data the Signal Handler will be informed before moving the state +machine on to fully open. +*/ +NONSHARABLE_CLASS(TL2CAPSAPStateAwaitingInitialData) : public TL2CAPSAPStateOpen + { +public: + TL2CAPSAPStateAwaitingInitialData(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP Signal Handler. + void ReconfiguringChannel(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the Data Controller. + void NewData(CL2CAPConnectionSAP& aSAP) const; + }; + +NONSHARABLE_CLASS(TL2CAPSAPStateDisconnecting) : public TL2CAPSAPState + { +public: + TL2CAPSAPStateDisconnecting(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + void Start(CL2CAPConnectionSAP& aSAP) const; + TInt Send(CL2CAPConnectionSAP& aSAP, RMBufChain& aData, TUint aFlag) const; + TInt Read(CL2CAPConnectionSAP& aSAP, RMBufChain& aData) const; + + void Shutdown(CL2CAPConnectionSAP& aSAP) const; + void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + + + // Events called from the SAP Signal Handler. + void ChannelConfigured(CL2CAPConnectionSAP& aSAP, + CL2CapChannelConfig& aConfig, + CL2CAPMux& aMuxer, + TL2CAPPort aLocalPort, + TL2CAPPort aRemotePort); + + void ReconfiguringChannel(CL2CAPConnectionSAP& aSAP) const; + + void SignalHandlerError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + void CloseOutgoingSDUQueue(CL2CAPConnectionSAP& aSAP) const; + + // Events called from the Data Controller. + void SDUQueueClosed(CL2CAPConnectionSAP& aSAP) const; + void NewData(CL2CAPConnectionSAP& aSAP) const; + TInt NewDataAsyncCallBack(CL2CAPConnectionSAP& aSAP) const; + void CanSend(CL2CAPConnectionSAP& aSAP) const; + void DataPlaneError(CL2CAPConnectionSAP& aSAP, TInt aErrorCode, MSocketNotify::TOperationBitmasks aErrorAction) const; + + // State Transition Actions. + }; + + +NONSHARABLE_CLASS(TL2CAPSAPStateError) : public TL2CAPSAPState + { +public: + TL2CAPSAPStateError(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + void Start(CL2CAPConnectionSAP& aSAP) const; + + TInt Ioctl(CL2CAPConnectionSAP& aSAP, TUint aLevel, TUint aName, TDes8* aOption) const; + void CancelIoctl(CL2CAPConnectionSAP& aSAP, TUint aLevel, TUint aName) const; + void IoctlComplete(CL2CAPConnectionSAP& aSAP, TInt aErr, TUint aLevel, TUint aName, TDesC8* aBuf) const; + + void ActiveOpen(CL2CAPConnectionSAP& aSAP) const; + TInt PassiveOpen(CL2CAPConnectionSAP& aSAP, TUint aQueSize) const; + void Shutdown(CL2CAPConnectionSAP& aSAP) const; + void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + + TInt Send(CL2CAPConnectionSAP& aSAP, RMBufChain& aData, TUint aFlag) const; + TInt Read(CL2CAPConnectionSAP& aSAP, RMBufChain& aData) const; + + // Events called from the SAP Signal Handler. + void ChannelClosed(CL2CAPConnectionSAP& aSAP) const; + + // State Transition Actions. + void Enter(CL2CAPConnectionSAP& aSAP) const; + }; + +/** + The BOUND state. + + This is the state that freshly bound saps are in. This state should + only be reached once for each sap since ESOCK doesn't allow rebinding + or unbinding of saps. + + A sap can be bound from an ESOCK point of view but not be in this state. + Then the sap will either be on the listening path or Closed. +**/ + +NONSHARABLE_CLASS(TL2CAPSAPStateBound) : public TL2CAPSAPState + { +public: + TL2CAPSAPStateBound(CL2CAPSAPStateFactory& aFactory); + + // Events called from the SAP. + TInt PassiveOpen(CL2CAPConnectionSAP& aSAP, TUint aQueSize) const; + void Shutdown(CL2CAPConnectionSAP& aSAP) const; + void FastShutdown(CL2CAPConnectionSAP& aSAP) const; + + // State Transition Actions. + void Enter(CL2CAPConnectionSAP& aSAP) const; + void Exit(CL2CAPConnectionSAP& aSAP) const; + }; + + +NONSHARABLE_CLASS(CL2CAPSAPStateFactory) : public CBase + { +friend class CL2CAPProtocol; +public: + enum TStates + { + EClosed = 0, + EPassiveLinkPending, + EActiveLinkPending, + EPassiveAccessRequestPending, + EActiveSecMode2AccessRequestPending, + EPendingOpen, + EListening, + EAccepting, + EAwaitingInitialData, + EOpen, + EDisconnecting, + EError, + EBound, + EActiveSecMode4AccessRequestPending, + EActiveChannelRequestPending, + EMaxState, + }; + + TL2CAPSAPState& GetState(const TStates aState) const; + TInt StateIndex(const TL2CAPSAPState* aState) const; + + ~CL2CAPSAPStateFactory(); + +private: + static CL2CAPSAPStateFactory* NewL(); + CL2CAPSAPStateFactory(); + + TFixedArray iStates; + }; + + +#endif