diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/avdtp/avdtpTransportSession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/avdtp/avdtpTransportSession.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,496 @@ +// Copyright (c) 2003-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: +// Implements the avdtp transport session base class +// +// + +/** + @file + @internalComponent +*/ + +#include +#include +#include "avdtpTransportSession.h" +#include "avdtp.h" +#include "avdtpsap.h" +#include "avdtpStream.h" +#include "avdtpSignallingChannel.h" +#include "avdtputil.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_AVDTP); +#endif + +CTransportSession::CTransportSession(CAvdtpProtocol& aProtocol, + CAvdtpSAP& aSAP, + TAvdtpTransportSessionType aSessionType) +: iSAP(aSAP), iProtocol(aProtocol), iSAPShutdown(ENone) + { + LOG_FUNC + iAddress.SetSession(aSessionType); + } + +CTransportSession::~CTransportSession() + { + LOG_FUNC + } + +void CTransportSession::ConstructL() + { + LOG_FUNC + // put any common stuff here + } + +void CTransportSession::FastShutdown() + { + LOG_FUNC + // just note whether we need to tell sap later or now to close + iSAP.DetachSession(); + + iSAPShutdown = EImmediate; + // and proceed normally - we now own ourselves... + DoShutdown(); + } + +void CTransportSession::Shutdown() + { + LOG_FUNC + iSAPShutdown = ENormal; + // and proceed normally - we now own ourselves... + DoShutdown(); + } + +TInt CTransportSession::GetOption(TUint /*aLevel*/, TUint /*aName*/, TDes8& /*aOption*/) const + { + LOG_FUNC + return KErrNotSupported; + } + +TInt CTransportSession::SetOption(TUint /*aLevel*/, TUint /*aName*/, const TDesC8& /*aOption*/) + { + LOG_FUNC + return KErrNotSupported; + } + +void CTransportSession::Start() + { + LOG_FUNC + //gulp + } + +void CTransportSession::Ioctl(TUint /*aLevel*/, TUint /*aName*/, const TDesC8* /*aOption*/) + { + LOG_FUNC + // default is to error as not supported + iSAP.Error(KErrNotSupported); + } + +void CTransportSession::CancelIoctl(TUint /*aLevel*/, TUint /*aName*/) + { + LOG_FUNC + // do nothing + } + +/** +Stream says this session is ready +Record the address we're serving and tell user +*/ +void CTransportSession::Ready(const TBTDevAddr& aRemoteDev) + { + LOG_FUNC + iAddress.SetBTAddr(aRemoteDev); + iSAP.Ready(); + } + + +void CTransportSession::LocalName(TAvdtpSockAddr& aAddr) const + { + LOG_FUNC + // in this current design, local=remote + RemName(aAddr); + } + +void CTransportSession::RemName(TAvdtpSockAddr& aAddr) const + { + LOG_FUNC + // in this current design, local=remote + aAddr = iAddress; + } + +TInt CTransportSession::SetLocalName(TAvdtpSockAddr& aAddr) + { + LOG_FUNC + // in this current design, local=remote + return SetRemoteName(aAddr); + } + +TInt CTransportSession::SetRemoteName(TAvdtpSockAddr& aAddr) + { + LOG_FUNC + // can't trample of session type - that's immutable + aAddr.SetSession(SessionType()); + iAddress = aAddr; + return KErrNone; + } + + +RPacketPool::RPacketPool() + { + LOG_FUNC + } + +TInt RPacketPool::Create(TUint aSize, TBool aBalk) + { + LOG_FUNC + LOG2(_L("Creating packet pool, size %d, balk %d"), aSize, aBalk); + __ASSERT_DEBUG(iPool.Count()==0, Panic(EAvdtpTransportSessionPacketPoolNotZeroSize)); + iNewestIndex=0; + TInt res = AllocatePool(aSize); + if (res==KErrNone) + { + iBalk=aBalk; + } + return res; + } + +TInt RPacketPool::AllocatePool(TUint aSize) + { + LOG_FUNC + TRAPD(err,AllocatePoolL(aSize)); + return err; + } + +void RPacketPool::AllocatePoolL(TUint aSize) + { + LOG_FUNC + // allocates the size requested or fails + for (TUint count = 0; countCount()-1) + { + iOldestIndex = Count()-1; + } + } + } + return res; + } + +TInt RPacketPool::OldestIndex() const + { + LOG_FUNC + // if balking, one in front of the newest index (modulo poolsize). else zeroth + return iOldestIndex; + } + +TInt RPacketPool::Remove(RMBufChain& aReturnedMBufChain) + { + LOG_FUNC + LOG(_L("Removing oldest packet")); + // return the oldest chain to the client + aReturnedMBufChain.Assign(iPool[OldestIndex()]); + // move the oldestindex on, modulo poolsize + ++iOldestIndex; + iOldestIndex %= iPool.Count(); + LOG1(_L("Oldest packet index = %d"), OldestIndex()); + return KErrNone; + } + +void RPacketPool::Close() + { + LOG_FUNC + while (iPool.Count()) + { + // delete the head entry each time + DestroyEntry(0); + } + iPool.Close(); + } + +void RPacketPool::DestroyEntry(TUint aIndex) + { + LOG_FUNC + iPool[aIndex].Free(); + iPool.Remove(aIndex); + } + +void RPacketPool::CreateEntryL() + { + LOG_FUNC + RMBufChain chain; + // don't need to alloc the chains as the entries claim ownership of inbound ones + TInt err = iPool.Append(chain); + if (err!=KErrNone) + { + chain.Free(); + User::Leave(err); + } + } + +TInt RPacketPool::Resize(TUint aSize) + { + LOG_FUNC + TInt res = KErrNone; + // try to grow/shrink the pool + if (aSize=(aSize-1);index--) + { + DestroyEntry(index); + } + } + else if (aSize > iPool.Count()) + { + LOG1(_L("Growing pool to %d entries"), aSize); + // grow if possible + for (TUint index=0;index<(aSize-iPool.Count());index++) + { + TRAP(res,CreateEntryL()); + } + } + if (res==KErrNone) + { + LOG(_L("Resize sucessful")); + iOldestIndex = 0; + iNewestIndex = iOldestIndex; + } + return res; + } + +CUserPlaneTransportSession::CUserPlaneTransportSession(CAvdtpProtocol& aProtocol, + CAvdtpSAP& aSAP, + TAvdtpTransportSessionType aType, + CAVStream& aStream) +: CTransportSession(aProtocol,aSAP, aType), iStream(&aStream) + { + LOG_FUNC + SetSEID(iStream->RemoteSEID()); + }; + + +void CUserPlaneTransportSession::ConstructL() + { + LOG_FUNC + // acquire TSID from stream or by ourselves + iStream->GetTSID(iTSID, SessionType()); + // we don't need a TSID if not muxing + } + + +TInt CUserPlaneTransportSession::ActiveOpen() + { + // check for race - between an ACP stream establishment, and GAVDP attaching + // sessions, the stream may have been released... so check if still there + // if so, forward active open to derivers + TAvdtpSockAddr addr; + RemName(addr); + + return iProtocol.FindStream(addr) ? DoActiveOpen() : KErrDisconnected; + } + + +void CUserPlaneTransportSession::ReceivePacketLost() + { + // Default impl. No action taken. + } + +void CUserPlaneTransportSession::NewData(RMBufChain& aChain) + { + LOG_FUNC + + if (EImmediate != iSAPShutdown) + { + TInt wrapped; // Used to indicate if packet pool wrapped around + TInt poolErr = iReceivePool.Add(aChain, wrapped); + if (poolErr==KErrNone) + { + iSAP.NewData(1); + } + else + { + // The data can't be added to the revc pool. Free the chain + // and notify the base session (i.e., media, reporting, recovery) + // that a data packet has been dropped. + aChain.Free(); + ReceivePacketLost(); + } + } + else + { + //Fast Shutdown in progress, do not pass any more data to the socket. + //therefore free the chain. + aChain.Free(); + } + } + +TInt CUserPlaneTransportSession::GetData(RMBufChain& aData) + { + LOG_FUNC + // fetch from pool + return iReceivePool.Remove(aData); + } + + +/** +we handle the channelerror, rather than the channel +as we do not want to necessarily abandon ALL *streams* to the same remote +just because one channel errored +*/ +void CUserPlaneTransportSession::ChannelError(TInt aError) + { + LOG_FUNC + if (iStream) + { + // this transport session is a user-plane one + __ASSERT_DEBUG(SessionType()!=ESignalling, Panic(EAvdtpBadTransportSessionUpcallFromTransportChannel)); + iStream->NotifyUserPlaneTransportSessionsError(this, aError); + iStream = NULL; + LeaveTransportChannel(); + } + // else the stream has gone from an earlier Release, and we're still here for client + } + +void CUserPlaneTransportSession::StreamError(TInt aError) + { + LOG_FUNC + if (iStream) + { + iStream->ClearSession(*this);//this will cause the iSession pointer in the stream to be null'd + } + // backcall from stream - default is to unbind and pass onto SAP + iStream = NULL; + if (iSAPShutdown!=EImmediate) + { + iSAP.Error(aError); + iSAP.SessionDisconnect(); + } + LeaveTransportChannel(); + } + + +void CUserPlaneTransportSession::DoShutdown() + { + LOG_FUNC + if (iStream) + { + // remove ourselves from the stream + iStream->DropSession(SessionType(), *this); + iStream = NULL; + } + else + { + /* If we don't have a stream pointer, then the logical channel underneath + us has gone away, and we've just been detached from the socket, so we need + to delete ourself */ + StreamReleased(); + } + } + +/* +Called from stream after Release has completed +*/ +void CUserPlaneTransportSession::StreamReleased() + { + LOG_FUNC + LeaveTransportChannel(); + + switch (iSAPShutdown) + { + case ENormal: + iSAP.CanClose(); + break; + + case EImmediate: + delete this; + break; + + case ENone: + iStream = NULL; + iSAP.SessionDisconnect(); + break; + } + } + +void CUserPlaneTransportSession::LeaveTransportChannel() + { + LOG_FUNC + if (iTransportChannel) + { + // he session is now removed from the stream + // time to detach from the channel + iTransportChannel->DetachTransportSession(*this, SessionType()); + iTransportChannel = NULL; + } + } + + +CUserPlaneTransportSession::~CUserPlaneTransportSession() + { + LOG_FUNC + if (iStream) + { + iStream->ClearSession(*this);//this will cause the iSession pointer in the stream to be null'd + } + iTSID.Close(); + iSendPool.Close(); + iReceivePool.Close(); + }