commsfwsupport/commselements/commsfw/inc/cftransport.h
changeset 0 dfb7c4ff071f
child 18 9644881fedd0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwsupport/commselements/commsfw/inc/cftransport.h	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,312 @@
+// 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:
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#ifndef SYMBIAN_NETWORKING_CFTRANSPORT_H
+#define SYMBIAN_NETWORKING_CFTRANSPORT_H
+
+#include <elements/nm_address.h>
+#include <elements/nm_transport.h>
+#include <elements/metavirtctor.h>
+
+
+/** Synchronously dispatching within the same thread is strongly discouraged but relied upon by the legacy EINTSOCK interface.
+Between threads the function is supported but the dispatch is not synchronous (risk of deadlock)
+*/
+#define SYMBIAN_CFTRANSPORT_SUPPORT_SYNC_SEND
+
+namespace NetInterfaces
+	{
+	class TInterfaceControl;
+	}
+
+namespace CommsFW
+{
+
+/**
+   CFTransport panic category
+*/
+_LIT(KCFTransportPanic, "CFTransport");
+
+/** Panics generated by the Comms Channels
+*/
+enum TCFTransportPanics
+	{
+	/** Peer failing to drain input properly
+	*/
+	ECFTransPeerDrainFailure = 0,
+	/** Invalid interface registration, eg unsupported or duplicate
+	*/
+	ECFTransBadRegistration = 1,
+	/** Cookie invalid or corrupt. If null then common causes are forgetting to initialise at all or with TCFClientSignalBase-derived classes
+	failing to chain the metadata attribute table to the parent, eg END_ATTRIBUTE_TABLE_BASE(TCFSignalExtnBase, 0)
+	*/
+	ECFTransInvalidCookie = 2,
+	/** No legacy message handler registered and a legacy message was received
+	*/
+	ECFTransLegacyHandlerAbsent = 3,
+	/** Invalid worker thread id
+	*/
+	ECFTransInvalidWorkerId = 4,
+	/** No transport to worker
+	*/
+	ECFTransAbsentWorker = 5,
+	/** Attempt to register a handler for an interface already registered - must first deregister original
+	*/
+	ECFTransDuplicateHandler = 6,
+	/** Use of a function requiring the global thread register when the pointer to it has not been set.
+	Without the global register many operations on peer threads are impossible.
+	*/
+	ECFTransThreadRegisterUnspecified = 7,
+	/** RCFInterfaceBase not opened with recipient peer details
+	*/
+	ECFTransNotOpened = 8,
+	/** Internal fault not directly generated by client activity
+	*/
+	ECFTransItfClassFault = 8,
+	/** After Leave()ing from the original dispatch the recipient dispatch also left from the leave-handling
+	dispatch. This is a fatal error because a common requirement for handling the first leave is sending
+	an error signal; leaving again suggests that the code is not handling the possibility of a Leave()
+	properly, rather than explicitly opting to ignore it.
+	*/
+	ECFTransLeaveFromLeaveHandler = 9,
+	/** Message recieved for an object whose interface cookie has already been deregistered (ie object probably deleted). This indicates a protocol
+	failure: the recipient interface's must remain registered until all messages for it have been received. A common approach is the sending of a
+	sign-off message guaranteeing no further communication from a node (analogous to a TCP FIN or a CommsChan PIG)
+	*/
+	ECFTransStaleCookie = 10,
+	/** More interfaces have been deregistered than were ever registered. Because the particular cookies aren't tracked it isn't necessarily the
+	current deregistration that is at fault
+	*/
+	ECFExcessInterfaceDeregistration = 11,
+	/** Interface registration with a non-null cookie is not allowed, as it's too likely that it represents a fault such as a double registration.
+	If it really is a safe and proper use (eg of an aliased cookie) then TCookieOp::SetNull() the cookie first
+	*/
+	ECFInterfaceRegistrationOverwrite = 12,
+	/** Interface not registered for dispatch
+	*/
+	ECFInterfaceNotRegistered = 13,
+	/** Queue sizing error. This is probably an internal fault.
+	*/
+	ECFInvalidQueueSize = 14,
+	};
+
+IMPORT_C void Panic(TCFTransportPanics aReason);
+
+_LIT8(KLogFwTransport, "Trans");
+
+#ifdef SYMBIAN_TRACE_ENABLE
+// Markers to enable correlation between utrace and CDU logs.
+_LIT8(KLogFwMarker, "Mark");
+#endif
+
+typedef TUint16 TWorkerId;
+static const TUint16 KInvalidWorkerId = 0xFFFF;
+static const TUint16 KMaxWorkerId = 16;
+
+//
+// Cookies
+//
+
+class TCFMessage;
+class RCFChannelMsgQueues;
+typedef TInt TId;
+
+//
+// Thread knowledge
+//
+
+class MGlobalThreadRegister
+	{
+public:
+	virtual TWorkerId UpperBoundWorkerId() const = 0;
+	virtual RAllocator& WorkerHeap(TWorkerId aWorkerId) const = 0;
+	virtual void PanicWorker(TWorkerId aWorkerId, const TDesC& aCategory, TInt aReason) const = 0;
+	};
+
+class MWorkerThreadRegister : public MGlobalThreadRegister
+	{
+public:
+	virtual TWorkerId SelfWorkerId() const = 0;
+	};
+
+class TWorkerThreadDataBase
+	{
+public:
+	IMPORT_C void Init(TWorkerId aWorkerId, TBool aHoldingReference);
+	IMPORT_C void Clear();
+	inline TBool IsValid() const;
+public:
+	TWorkerId iWorkerId;
+	TThreadId iThreadId;
+	RThread iThread;
+	RAllocator* iHeap;
+	TBool iHoldingReference;
+	};
+
+
+class CWorkerThreadDataGlobalsBase : public CBase
+	{
+protected:
+	inline CWorkerThreadDataGlobalsBase();
+	inline ~CWorkerThreadDataGlobalsBase();
+	inline void ConstructL(TInt aWorkerDataSize, TWorkerId aUpperBoundId);
+protected:
+	TWorkerThreadDataBase* iWorkers;
+	};
+
+
+template<class TWTD, TInt TUpperThreadIdBound>
+class CWorkerThreadDataGlobals : public CWorkerThreadDataGlobalsBase, public MGlobalThreadRegister
+	{
+public:
+	static CWorkerThreadDataGlobals<TWTD, TUpperThreadIdBound>* NewL();
+
+	TWorkerId UpperBoundWorkerId() const;
+	TWTD* GetWorkerGlobals(TWorkerId aWorker) const;
+	TBool WorkerPresent(TWorkerId aId) const;
+	RAllocator& WorkerHeap(TWorkerId aWorkerId) const;
+	void PanicWorker(TWorkerId aWorkerId, const TDesC& aCategory, TInt aReason) const;
+protected:
+	CWorkerThreadDataGlobals();
+	inline void ConstructL(TInt aWorkerDataSize, TWorkerId aUpperBoundId);
+	};
+
+
+template<class TWTD, TInt TUpperThreadIdBound>
+class CWorkerThreadRegister : public CBase, public MWorkerThreadRegister
+	{
+public:
+	static CWorkerThreadRegister<TWTD, TUpperThreadIdBound>* NewL(TWorkerId aSelfId, CWorkerThreadDataGlobals<TWTD, TUpperThreadIdBound>* aGlobalThreadRegister);
+	void SetGlobalThreadRegister(CWorkerThreadDataGlobals<TWTD, TUpperThreadIdBound>* aGlobalThreadRegister);
+	TWTD* GetWorkerGlobals(TWorkerId aWorker) const;
+	TWorkerId UpperBoundWorkerId() const;
+	TBool WorkerPresent(TWorkerId aWorkerId) const;
+	RAllocator& WorkerHeap(TWorkerId aWorkerId) const;
+	void PanicWorker(TWorkerId aWorkerId, const TDesC& aCategory, TInt aReason) const;
+	TWorkerId SelfWorkerId() const;
+	TWTD* GetSelfWorkerGlobals() const;
+private:
+	CWorkerThreadRegister<TWTD, TUpperThreadIdBound>(TWorkerId aSelfId, CWorkerThreadDataGlobals<TWTD, TUpperThreadIdBound>* aGlobalThreadRegister);
+private:
+	TWorkerId iSelfId;
+	CWorkerThreadDataGlobals<TWTD, TUpperThreadIdBound>* iGlobals;
+	};
+
+//These APIs have been separated from the transport abstraction (MTransportSender)
+//and are here only to satisfy the comms transport implementation
+class MCommsTransportSender : public Messages::MTransportSender
+	{
+public:
+	virtual void PostMessage(const Messages::TRuntimeCtxId& aPostFrom, const Messages::TRuntimeCtxId& aPostTo, const Meta::SMetaData& aMessage);
+
+	//Legacy & helpers
+	virtual void PostMessage(const TCFMessage& aMessage) = 0;
+	virtual void PostMessage(const Messages::TRuntimeCtxId& aPostFrom, const Messages::TRuntimeCtxId& aPostTo, const TDesC8& aMessage) = 0;
+
+#ifdef SYMBIAN_CFTRANSPORT_SUPPORT_SYNC_SEND
+	/** The caller intends to block for some out-of-band synchronisation mechanism (eg a semaphore) and so dispatch
+	must be done immediately as part of this sending call if the peer object is running in the same worker thread, so
+	that the recipient can signal the caller if appropriate. Such synchronisation mechanisms are strongly discouraged
+	but exist in some legacy code.
+
+	@deprecated
+	*/
+	virtual void SendMessageSync(const TCFMessage& aMessage) = 0;
+#endif
+	};
+
+
+class MLegacyMessageReceiver
+	{
+public:
+	virtual void DispatchL(const TCFMessage& aMessage, TWorkerId aSenderId) = 0;
+	/** If the dispatching function Leave()s then control transfers here. This allows a carefully-written object to avoid
+	adding its own TRAP and still provide handling for a Leave, ie an efficiency gain.
+	*/
+	virtual void OnDispatchLeave(const TCFMessage& /*aMessage*/, TWorkerId /*aSenderId*/, TInt /*aFirstDispatchLeaveReason*/)
+		{
+		}
+	};
+
+
+class CCommsTransportImpl;
+class CCFTransportHooks;
+
+class CCommsTransport : public CBase //PS removed inheritance not to export virtuals and
+                                     //hide CCommsTransportImpl. Polymorphism is given
+                                     //by CCommsTransportImpl.
+	{
+public:
+	IMPORT_C static CCommsTransport* NewL(MWorkerThreadRegister& aThreadRegister, const Meta::CMetaDataVirtualCtorInPlace* aVirtCtor, CCFTransportHooks* aHooksWalker);
+	IMPORT_C ~CCommsTransport();
+
+	// From MTransportReceiver
+	IMPORT_C TInt RegisteredCount() const;
+	IMPORT_C void RegisterAddress(Messages::TRuntimeCtxId& aCookie);
+	IMPORT_C void DeregisterAddress(Messages::TRuntimeCtxId& aCookie);
+
+	// From MTransportSender
+	IMPORT_C void PostMessage(const Messages::TRuntimeCtxId& aPostFrom, const Messages::TRuntimeCtxId& aPostTo, const Meta::SMetaData& aMessage);
+
+	// TCFMessage + legacy
+	IMPORT_C void RegisterLegacyInterface(MLegacyMessageReceiver* aLegacyInterface);
+	IMPORT_C void PostMessage(const TCFMessage& aMessage);
+	
+private:
+	// TCFMessage + legacy
+	IMPORT_C void PostMessage(const Messages::TRuntimeCtxId& aPostFrom, const Messages::TRuntimeCtxId& aPostTo, const TDesC8& aMessage);
+
+#ifdef SYMBIAN_CFTRANSPORT_SUPPORT_IMPATIENCE
+	IMPORT_C TInt ImpatientPostMessage(const TCFMessage& aMessage);
+	IMPORT_C TInt ImpatientPostMessage(const Messages::TRuntimeCtxId& aPostFrom, const Messages::TRuntimeCtxId& aPostTo, const TDesC8& aMessage);
+#endif
+#ifdef SYMBIAN_CFTRANSPORT_SUPPORT_SYNC_SEND
+	IMPORT_C void SendMessageSync(const TCFMessage& aMessage);
+#endif
+
+public:
+	// Transports peer threads via message queues, normally established by the RootServer via binding commands. The Request Id
+	// identifies the specific command being responded to; some callers need to store this for delayed reporting
+	IMPORT_C TInt EstablishTransportToPeer(TWorkerId aPeerId, const RCFChannelMsgQueues& aInboundQueues, const RCFChannelMsgQueues& aOutboundQueues);
+	IMPORT_C TInt DropTransportToPeer(TWorkerId aPeerId);
+	IMPORT_C TBool PeerReachable(TWorkerId aPeerId) const;
+	IMPORT_C void SetLastRequestIdConcerningPeer(TWorkerId aPeerId, CommsFW::TId aRequestId);
+	IMPORT_C CommsFW::TId LastRequestIdConcerningPeer(TWorkerId aPeerId) const;
+	IMPORT_C void SetDropTransportPending(TWorkerId aPeerId, TBool aDropPending);
+	IMPORT_C TBool IsDropTransportPending(TWorkerId aPeerId) const;
+
+	IMPORT_C TWorkerId WorkerId() const;
+	IMPORT_C Messages::MTransportSender& GetSender();
+	IMPORT_C Messages::MTransportReceiver& GetReceiver();
+
+private:
+	CCommsTransport()
+		{
+		}
+private:
+	CCommsTransportImpl* iImpl;
+	};
+
+#include <elements/cftransport.inl>
+
+} // namespace CommsFW
+
+#endif // SYMBIAN_NETWORKING_CFTRANSPORT_H
+