serialserver/c32serialserver/SCOMM/CS_STD.H
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 1997-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 //
       
    15 
       
    16 
       
    17 
       
    18 // Defines global internals for C32. 
       
    19 
       
    20 #ifndef CS_STD_H
       
    21 #define CS_STD_H
       
    22 
       
    23 /** @file
       
    24  *
       
    25  * @internalComponent
       
    26  */
       
    27 
       
    28 #include <cs_port.h>
       
    29 #include "COMMIPC.H"
       
    30 #include <cfmsgs.h>
       
    31 #include <cfshared.h>
       
    32 #include <cfutil.h>
       
    33 #include "cs_thread.h"	// CC32Workerthread, CCommChannelHandler
       
    34 #include <e32cmn.h>				// RFastLock
       
    35 
       
    36 
       
    37 
       
    38 #ifndef __WINS__
       
    39 #define VERBOSE
       
    40 #endif	// __WINS__
       
    41 
       
    42 // time for player to close all owned sessions. Is sent in msg from dealer to player so that player can 
       
    43 // determine if it should still process the message. If player doesn't see this msg until after timer 
       
    44 // expires, player does not process msg. Also, dealer won't process response and close session if this 
       
    45 // timer has expired before dealer sees response (I don't quite see why this needs to be the case? 
       
    46 // Surely this is only a problem if session close delay has also expired? ). 8 secs is derived from 
       
    47 // being "a long time" for this sort of operation.
       
    48 const TUint32 KC32SessionCloseDelay = 16*1000*1000;
       
    49 // time for session to clean up all subsessions from workers wrt this session. The client is normally 
       
    50 // held inside their Close() call until c32 completes the close. Must be longer than player close deadline 
       
    51 // since at expiration client is released and after that, csys accessing client memory will be dangerous. 
       
    52 // Is 8 secs longer than session close player deadline since this is how long it takes some test CSYs to 
       
    53 // perform their closure.
       
    54 const TUint32 KC32SessionClosePlayerDeadline = 8*1000*1000;
       
    55 
       
    56 // Short delay on asynchronous callback to allow for any others to run
       
    57 // In practice, the yield itself is normally enough
       
    58 const TInt KCommServerShutdownLatencyMicroSeconds = 100 * 1000;	
       
    59 
       
    60 _LIT(KCommServer, "!CommServer");
       
    61 _LIT(KCSYExtension, ".CSY" );
       
    62 _LIT8(KCSYExtension8, ".CSY" );
       
    63 _LIT8(KRoleLabel, "Role");
       
    64 _LIT8(KDealerRole, "Dealer");
       
    65 _LIT8(KPlayerRole, "Player");
       
    66 //_LIT8(KDealerPlayerRole, "DealerPlayer");  // maybe one day
       
    67 _LIT8(KWorkerIdLabel, "WorkerId");
       
    68 _LIT8(KCSYListLabel, "CSYList");
       
    69 
       
    70 
       
    71 void PanicClient(TInt aPanic, const RMessagePtr2& aMessage);
       
    72 void SafeComplete(const RMessagePtr2& aMessage, TInt aCompletionCode);
       
    73 TInt AddCSYExtension(TFileName& aFilename, const RMessage2& aMessage);
       
    74 
       
    75 
       
    76 
       
    77 /**
       
    78  * External representation of the state of a CPort object.
       
    79  */
       
    80 struct TCommDebugInfo 
       
    81 	{
       
    82 	TInternalCommAccess iMode;  //< The current main access mode of the port
       
    83 	TInt iAccessCount;          //< Number of open clients
       
    84 	TCommRole iRole;            //< DCE or DTE
       
    85 	TInt iOutstandingCommands;  //< Number of outstanding Opens, Closes, Waits etc.
       
    86 						        //< (excludes SetAccess requests)
       
    87 	};
       
    88 
       
    89 class CCommSubSession;
       
    90 class CC32Player;
       
    91 class CPort;
       
    92 
       
    93 class RNullableMessage : public RMessage2
       
    94 	{
       
    95 public:
       
    96 	void NullHandle() const
       
    97 		{
       
    98 		// Although this casting away of const looks awful it's in keeping with the ability to Complete() const
       
    99 		// messages - perhaps iHandle should have been mutable?
       
   100 		const_cast<RNullableMessage&>(*this).iHandle = 0;
       
   101 		}
       
   102 	};
       
   103 
       
   104 
       
   105 NONSHARABLE_CLASS(CCommSubSession) : public CBase
       
   106 /**
       
   107 @class
       
   108 CCommSubSession
       
   109 @internalComponent
       
   110 */
       
   111 	{
       
   112 	friend class CCommSession;
       
   113 	friend class CC32Player;
       
   114 public:
       
   115 	// Reference counting methods formerly supplied by CObject.
       
   116 	inline void Open();
       
   117 	inline void Close();
       
   118 	inline TInt AccessCount() const;
       
   119 
       
   120 #ifdef _DEBUG
       
   121 	virtual ~CCommSubSession();
       
   122 #endif
       
   123 
       
   124 	inline CCommSession* Session() const;
       
   125 	inline CC32Player& Player() const;
       
   126 
       
   127 	/** 
       
   128 		Type identifier for the derived sub-session objects. Used e.g. in containers to identify
       
   129 		what is stored.
       
   130 
       
   131 		@see CCommSubSession::Type()
       
   132 	*/
       
   133 	enum TSubSessionType 
       
   134 		{ 
       
   135 		ENull, 
       
   136 		EAny, 
       
   137 		ECPort 
       
   138 		};
       
   139 
       
   140 	TSubSessionType Type() const
       
   141 		{
       
   142 		return CCommSubSession::ECPort;
       
   143 		}
       
   144 
       
   145 
       
   146 	static CCommSubSession* NewL(CCommSession* aSession, CPort* aPort, CC32Player* aPlayer);
       
   147 
       
   148 private:
       
   149 	CCommSubSession(CCommSession* aSession, CPort* aPort, CC32Player* aPlayer);
       
   150 	void RemoveAndDestroy();
       
   151 private:
       
   152 	CC32Player* iPlayer;	//< The Player responsible for this sub-session instance.
       
   153 	TInt iAccessCount;		//< Reference counting on the sub-session. If it goes to 0 the sub-session will be destroyed.
       
   154 	CPort* iPort;
       
   155 	CCommSession* iSession;
       
   156 	};
       
   157 
       
   158 //
       
   159 // CC32SubSessionIx - Subsession index
       
   160 //
       
   161 
       
   162 /**
       
   163 @class
       
   164 CC32SubSessionIx
       
   165 This sub-session container will maintain its own array of TEntry cells in memory as arrays provide for
       
   166 quick access in some situations. There will be two types of cells in the array; cells carrying pointers
       
   167 to sub-sessions and a virtual list of free cells.
       
   168 This layout means that with a handle, the entry holding the sub-session can be looked up in the container
       
   169 directly and if needing to insert a new entry the first free cell is indicated by iFreeListHead.
       
   170 The array will grow with EIndexGranularity each time it runs out of free entries. However, it maintains a high
       
   171 watermark and will never shrink.
       
   172 The handles are defined by TSubSessionHandle, which in the current architectures is a 32 bit word, constructed
       
   173 as needed. It is simple to deduct from the context so there is no need to store it.
       
   174 
       
   175 0        8        16              31
       
   176 |--------|--------|----------------|
       
   177    Type     Magic       Index
       
   178 
       
   179 The three components comprising the handle are:
       
   180     - Type	- 8 bit value. One of the members of CCommSubSession::TSubSessionType.
       
   181     - Magic	- 8 bit value. Ensures that handles are not re-used immediately. Each time an entry is re-cycled this value increments, rolling around when reaching max.
       
   182     - Index	- 16 bit value. The position in the array.
       
   183 @see CCommSubSession::TSubSessionType
       
   184 */
       
   185 NONSHARABLE_CLASS(CC32SubSessionIx) : public CBase
       
   186 	{
       
   187 public:
       
   188 	typedef TInt TSubSessionHandle;
       
   189 	enum { KTypeBits = 8, KMagicBits = 8, KIndexBits = 16 };
       
   190 	enum { KIndexLimit = 1 << KIndexBits };
       
   191 	enum { KMagicMask = (1 << KMagicBits) - 1 };
       
   192 public:
       
   193 	~CC32SubSessionIx();
       
   194 
       
   195 	void InitialiseL();
       
   196 	inline void Lock() const;
       
   197 	inline void Unlock() const;
       
   198 	
       
   199 	CCommSubSession* At(TInt aHandle, CCommSubSession::TSubSessionType aType) const;
       
   200 	TInt Find(CCommSubSession* aSubSession, TSubSessionHandle& aHandle) const;
       
   201 
       
   202 	TInt Add(CCommSubSession* aSubSession, TSubSessionHandle& aHandle);
       
   203 	CCommSubSession* Remove(TSubSessionHandle aHandle);
       
   204 
       
   205 	NONSHARABLE_CLASS(TIter)
       
   206 		{
       
   207 	public:
       
   208 		TIter(CC32SubSessionIx& aContainer);
       
   209 		void SetToFirst();
       
   210 		CCommSubSession* operator++(TInt);
       
   211 		CCommSubSession* Next(TSubSessionHandle& aHandle);
       
   212 	private:
       
   213 		TInt iPos;
       
   214 		CC32SubSessionIx& iContainer;
       
   215 		};
       
   216 
       
   217 	friend class TIter;
       
   218 private:
       
   219 	enum { EIndexGranularity = 8 };
       
   220 
       
   221 	/** @class
       
   222 	CC32SubSessionIx::TEntry
       
   223 	One entry in the container. If iType is CCommSubSession::ENull, then it is a member of the free-list 
       
   224 	and iNextFree is the index of the next free TEntry instance otherwise it is an iObject* and points 
       
   225 	to a sub-session instance.
       
   226 	iType can be one those defined in CCommSubSession::TSubSessionType.
       
   227 	@see CCommSubSession::TSubSessionType
       
   228 	*/
       
   229 	class TEntry
       
   230 		{
       
   231 	public:
       
   232 		union
       
   233 			{
       
   234 			CCommSubSession* iObject;
       
   235 			TInt iNextFree;
       
   236 			};
       
   237 		TUint8 iType;
       
   238 		TUint16 iMagic;
       
   239 		};
       
   240 private:
       
   241 	inline TSubSessionHandle MakeHandle(TInt aIndex, TInt aMagic, TInt aType) const
       
   242 		{
       
   243 		return (((aIndex << KMagicBits) | aMagic) << KTypeBits) | aType;
       
   244 		}
       
   245 	inline TInt IndexFromHandle(TInt aHandle) const
       
   246 		{
       
   247 		return aHandle >> (KTypeBits + KMagicBits);
       
   248 		}
       
   249 	TEntry* At(TSubSessionHandle aHandle) const;
       
   250 	TInt ExpandArray();
       
   251 
       
   252 private:
       
   253 	class RWorkerLock : public RFastLock
       
   254 		{
       
   255 	public:
       
   256 		// overriden functions
       
   257 		inline void Wait();
       
   258 
       
   259 		inline void Signal();
       
   260 		// end overriden functions
       
   261 		
       
   262 		inline void AssertLockHeld() const;
       
   263 		
       
   264 		
       
   265 #ifdef _DEBUG
       
   266 	private:
       
   267 		// RFastLock does not nest, ie if the current holder attempts to re-acquire they deadlock
       
   268 		// We check for this in debug builds only as the cost of doing so likely negates the benefits
       
   269 		// of using the class over & above semaphores
       
   270 		TThreadId iHolder;
       
   271 #endif
       
   272 		};
       
   273 
       
   274 private:
       
   275 	TEntry* iIx;
       
   276 	TInt iSize;
       
   277 	TInt iActiveCount;			//< Number of active sub-sessions stored in this container.
       
   278 	TInt iFreeListHead;			//< Pointer to the first item/cell in the virtual free list.
       
   279 	mutable RWorkerLock iLock;
       
   280 	};
       
   281 
       
   282 
       
   283 
       
   284 
       
   285 /**
       
   286  * Main Comms Server object.  Constructed on process initialisation; never deleted.
       
   287  */
       
   288 class CC32WorkerThread;
       
   289 class CC32ThreadManager;
       
   290 class CC32Server : public CPolicyServer
       
   291 	{
       
   292 public:
       
   293 	enum {EPriority=1000}; //< priority of this Active Object
       
   294 public:
       
   295 	// from CServer
       
   296 	virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
       
   297 	~CC32Server();
       
   298 public:
       
   299 	inline CC32WorkerThread& WorkerThread() const;
       
   300 	inline CommsFW::TWorkerId WorkerId() const;
       
   301 	
       
   302 protected://virtuals from CPolicyServer
       
   303 	CPolicyServer::TCustomResult CustomSecurityCheckL(const RMessage2& aMsg, TInt& aAction, TSecurityInfo& aMissing);
       
   304 protected:
       
   305 	CC32Server(CC32WorkerThread* aOwnerThread, TInt aPriority);
       
   306 	void ConstructL(CC32ThreadManager* aThreadManager);
       
   307 
       
   308 private:
       
   309 	CC32WorkerThread* iOwnerThread;
       
   310 	CC32ThreadManager* iThreadManager;
       
   311 	TInt iThreadHandles;	
       
   312 
       
   313 private:
       
   314 	static const TUint iRangeCount;
       
   315 	static const TInt iRanges[];
       
   316 	static const TUint8 iElementsIndex[];
       
   317 	static const CPolicyServer::TPolicyElement iElements[];
       
   318 	static const CPolicyServer::TPolicy iPolicy;
       
   319 	};
       
   320 
       
   321 
       
   322 class CC32ThreadManager;
       
   323 /**
       
   324  * A client session.
       
   325  * Corresponds to an RCommSession object in the client.
       
   326  */
       
   327 class CCommSession : public CSession2
       
   328 	{
       
   329 	friend class CCommSubSession;
       
   330     friend class CC32Dealer;
       
   331 	typedef CSession2 inherited;
       
   332 
       
   333 public:
       
   334 	static CCommSession* NewL(CC32ThreadManager* aThreadManager);
       
   335 	virtual void ServiceL(const RMessage2 &aMessage);
       
   336 	virtual void ServiceError(const RMessage2& aMessage, TInt aError);
       
   337 	virtual ~CCommSession();
       
   338 	CCommSession(CC32ThreadManager* aThreadManager);
       
   339 	void ConstructL();
       
   340 	void LoadCommModuleL(const RMessage2& aMessage, CommsFW::TWorkerId aWorker, TBool defaulted, const TDesC& aFilename);
       
   341 	void CloseCommModuleL(const RMessage2& aMessage);
       
   342 	void NewPortL(const RMessage2& aMessage);
       
   343 
       
   344 	void NumPorts(const RMessage2& aMessage);
       
   345 	void PortInfo(const RMessage2& aMessage,TInt aPortNum);
       
   346 	void PortInfoL(const RMessage2& aMessage,const TPortName& aPortName);
       
   347 	TInt Write(TInt aPos, const RMessagePtr2& aMessage, const TDesC8& aDes, TInt aOffset=0);
       
   348 	TInt Read(TInt aPos, const RMessagePtr2& aMessage, TDes8& aDes, TInt aOffset=0);
       
   349 	TInt Write(TInt aPos, const RMessagePtr2& aMessage, const TDesC16& aDes, TInt aOffset=0);
       
   350 	TInt Read(TInt aPos, const RMessagePtr2& aMessage, TDes16& aDes,TInt aOffset=0);
       
   351 	TInt ExtractPortNameAndNumber(const RMessagePtr2& aMessage, TDes& aPortName, TUint& aPortNumber, TInt& aLength);
       
   352 	
       
   353 public:
       
   354 	inline const CC32Dealer& Dealer() const;
       
   355 	CC32WorkerThread& C32WorkerThread() const;
       
   356 	CommsFW::TWorkerId WorkerId() const;
       
   357 	inline CC32SubSessionIx& SubSessions();
       
   358 
       
   359 	// RCommServ related APIs
       
   360 	TInt AddCSYToSessionL(const TDesC& aCSYFileName, TBool& aIsDuplicate);		//< LoadCommModule
       
   361 	TInt RemoveCSYFromSession(const TDesC& aCSYFileName, TBool& aIsLast);	//< used by UnLoadCommModule
       
   362 	
       
   363 	// Apply a callback function to subsessions of the session, either matching the worker id, or all
       
   364 	// if aPeerId == ENullWorkerId
       
   365 	typedef void (*TSubSessionProcessor)(CCommSession* aSession, CCommSubSession* aSubSession, TInt aSubSessionHandle, TAny* aArg);
       
   366 	void ProcessSubSessions(CommsFW::TWorkerId aPeerId, TSubSessionProcessor aSubSessionProcessor, TAny* aPtr);
       
   367 
       
   368 	// Callbacks used with ProcessSubSessions()
       
   369 	static void ForgetSubSession(CCommSession* aSession, CCommSubSession* aSubSession, TInt aSubSessionHandle, TAny* aArg);
       
   370 	static void CountSubSessions(CCommSession* aSession, CCommSubSession* aSubSession, TInt aSubSessionHandle, TAny* aArg);
       
   371 
       
   372 	// Called by worker when it has received a SessionCloseRespMsg
       
   373 	void SessionCloseResp(CommsFW::TWorkerId aPlayerId);
       
   374 
       
   375 	typedef RPointerArray<HBufC> RCSYFileNameContainer; //< unlike ThreadManager, CSY names stored in 16-bit since in all cases they come in 16-bit
       
   376 														//(ie, we never have to compare with ThreadManager CSY list, which is 8-bit since based from 8-bit ini file)
       
   377 	
       
   378 	void CompleteDisconnect();
       
   379 
       
   380 	TBool IsPlayerInDisconnectList(CommsFW::TWorkerId aPlayerId) const;
       
   381 	TBool IsDisconnectListEmpty() const;
       
   382 	TInt DisconnectPlayers();
       
   383 
       
   384 protected:
       
   385 	void Disconnect();
       
   386 	// Override of default behaviour for session disconnection
       
   387 	virtual void Disconnect(const RMessage2& aMessage);
       
   388 
       
   389 	void ForwardMessageL(const RMessage2& aMessage, CCommSubSession* aSS, CommsFW::TWorkerId aWorker);
       
   390 	void ForwardMessageL(const RMessage2& aMessage, CCommSubSession& aSubSess);
       
   391 	void SafeComplete(const RMessagePtr2& aMessage, TInt aCompletionCode);
       
   392 	void DontCompleteCurrentRequest();
       
   393 
       
   394 private:
       
   395 	CC32ThreadManager* iThreadManager;	//< ThreadManager for lookup, located in dealer
       
   396 	CCommSubSession* SubSessionFromHandle(TUint aHandle, CCommSubSession::TSubSessionType aType) const;
       
   397 	void CloseSubSessionL(const RMessage2& aMessage, CCommSubSession::TSubSessionType aType);
       
   398 
       
   399 	void AddPlayerToDisconnectList(CommsFW::TWorkerId aPlayerId);
       
   400 	void RemovePlayerFromDisconnectList(CommsFW::TWorkerId aPlayerId);
       
   401 	
       
   402 	/** 
       
   403 	@class
       
   404 	CCommSession::CC32SessionCloseTimer
       
   405 	This timer times out after double the deadline given to the Players to return a Session Close response.
       
   406 	*/
       
   407     NONSHARABLE_CLASS(CC32SessionCloseTimer) : public CTimer
       
   408     	{
       
   409 	public:
       
   410 	    static CC32SessionCloseTimer* NewL(CCommSession* aSession);
       
   411 		void Start();
       
   412 	protected:
       
   413 	    void RunL();
       
   414 	private:
       
   415 	    CC32SessionCloseTimer(CCommSession* aSession);
       
   416 	    CCommSession* iSession;
       
   417     	};
       
   418 
       
   419     /** Timer starting when SessionClosed message is sent to players.
       
   420 	If not all the expected responses come back within the deadline set in the Session
       
   421 	Close message, the CC32SessionCloseTimer will fire and the session will be deleted by 
       
   422 	the Dealer. This is usually due to a Player somehow being unreliable and shouldn't 
       
   423 	normally happen. The purpose of the timeout is to avoid blocking clients.
       
   424 	*/
       
   425     CC32SessionCloseTimer* iSessionCloseTimer;
       
   426 	TBool iComplete;				//< check if the current message can be completed
       
   427 	CC32SubSessionIx iSubSessions;	//< Container of subsessions belonging to this session. 
       
   428 									//< They can potentially belong to different Players.
       
   429 	TUint32 iDisconnectPlayers;	    //< Set of Players to notify of session death	
       
   430 	RMessage2 iDisconnectMessage;	//< EDisConnect Message to complete session destruction
       
   431 	RCSYFileNameContainer iCsyCon;	//< CSYs loaded in this session, used to check on unload whether CSY was loaded. Duplicates allowed, order unimportant.
       
   432 	};
       
   433 
       
   434 
       
   435 /**
       
   436  * Active Scheduler class with specialised error handling.
       
   437  */
       
   438 class CCommScheduler : public CActiveScheduler
       
   439 	{
       
   440 public:
       
   441 	static CCommScheduler* New();
       
   442     void Error(TInt anError) const;
       
   443 	};
       
   444 
       
   445 /**
       
   446  * Owner object for all the CPort Objects.
       
   447  * There is one instance of this, owned by the CCommSession object.
       
   448  * It has no explicit destructor because the C32 thread will never finish unless panicked
       
   449  */
       
   450 NONSHARABLE_CLASS (CPortManager) : public CBase
       
   451 	{
       
   452 public:
       
   453 	static CPortManager* NewL();
       
   454 	CSerial* LoadCommModuleL(const TDesC& aFileName);
       
   455 	CSerial* GetSerialL(const TDesC& aName);
       
   456 	CPort* GetPortL(const TDesC& aName, TUint aPort, CSerial *aSerial, TUint aMode, TUint aRole, CCommSession* aSession);
       
   457 	TInt PortInfo(const TPortName& aName, TSerialInfo& aSerial);
       
   458 	~CPortManager();
       
   459 
       
   460 private:
       
   461 	CObjectConIx* iContainer;
       
   462 	CObjectCon* iPorts;
       
   463 	CObjectCon* iProviders;
       
   464 
       
   465 private:
       
   466 	void ConstructL();
       
   467 
       
   468 	};
       
   469 
       
   470 #ifdef __MARM__
       
   471 const TInt KCommTimerGranularity = 31000;
       
   472 #else
       
   473 const TInt KCommTimerGranularity = 80000;
       
   474 #endif
       
   475 
       
   476 
       
   477 #include "cs_std.inl"
       
   478 
       
   479 #endif // CS_STD_H
       
   480