diff -r 6a20128ce557 -r ebfee66fde93 messagingappbase/obexmtms/btmtm/btclient/source/btcmtm.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingappbase/obexmtms/btmtm/btclient/source/btcmtm.cpp Fri Jun 04 10:25:39 2010 +0100 @@ -0,0 +1,314 @@ +// Copyright (c) 2004-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: +// btcmtm.cpp +// + +//class include +#include + +//system includes +#include +#include +#include // CRichText + +#include // KUidMtmQueryCanSendMsg +#include // CRegisteredMtmDll +#include // KUidMtmQueryxxx & TMsvPartList flags +#include // KUidMsvMessageEntry +#include "btmtmcmds.h" //EBtMtmCmdSend + +//user includes +#include +#include "btmsgtypeuid.h" //KUidMsgTypeBt +#include + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "msvconsts.h" +#include +#endif + +const TUint8 KObexConnectionIDHeader = 0xCB; + +CBtClientMtm::CBtClientMtm(CRegisteredMtmDll& aRegisteredMtmDll, CMsvSession& aMsvSession) +: CObexClientMtm(aRegisteredMtmDll, aMsvSession, KUidMsgTypeBt) +/** + * Constructor--not for use by client applications + * + * @param aRegisteredMtmDll Registration data for MTM DLL. + * @param aMsvSession CMsvSession of the client requesting the object. + */ + { + } + +void CBtClientMtm::InitialiseHeaderL() +/** + * Deletes the old header, then creates a new CBtHeader. + * + * @leave KErrXXX System-wide error codes if allocation fails + */ + { + delete iHeader; + iHeader = 0; + + iHeader = CBtHeader::NewL(); + } + +EXPORT_C CBtClientMtm* CBtClientMtm::NewL(CRegisteredMtmDll& aRegisteredMtmDll, CMsvSession& aMsvSession) +/** + * Canonical NewL factory function. + * + * @param aRegisteredMtmDll Reference to registration data for MTM DLL. + * @param aMsvSession Reference to CMsvSession of the client requesting the object. + * @return Pointer to a new, constructed CBtClientMtm + * @leave Leaves if no memory is available. + */ + { + CBtClientMtm* self = new(ELeave) CBtClientMtm(aRegisteredMtmDll, aMsvSession); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +CMsvOperation* CBtClientMtm::InvokeAsyncFunctionL(TInt aFunctionId, + const CMsvEntrySelection& aSelection, + TDes8& aParameter, + TRequestStatus& aCompletionStatus) +/** + * Starts an asynchronous function as an active object. Only works for EBtcCmdSend. + * + * @param aFunctionId Identifier of the function to be invoked. Only supports EBtcCmdSend and + * KMTMStandardFunctionsSendMessage. + * @param aSelection Selection of message entries for the requested function to operate on. + * @param aParameter Buffer containing input and output parameters. + * @param aCompletionStatus Canonical TRequestStatus used for control of the active object. + * @return Pointer to a new asynchronously completing CMsvOperation. If failed, this is a completed operation with + * status set to the relevant error code. + * @leave Leaves if no memory is available, or if the specified aFunctionId is unsupported. + */ { + __TEST_INVARIANT_VIRTUAL + + CMsvOperation* op = NULL; + switch (aFunctionId) + { + case KMTMStandardFunctionsSendMessage: + { + // parameter ignored, it's assumed that the 1st addressee will contain all the + // required information to send this item. Only the 1st item in the selection + // list is sent. + CreateMessageOperationL(op, aSelection, aCompletionStatus); + break; + } + case EBtMtmCmdSend: + { + /* + In order to get our password over the client-server boundary without breaking the client interface + we will repack the client side package buffer into a server package buffer. + */ + TPckgBuf serverParams; + + TPckgBuf& clientParams = (TPckgBuf&)aParameter; + + /* at this point, it may be worth checking the length of the supplied password + and leaving with KErrArgument if it's longer than allowed */ + if(!clientParams().iConnectPassword || clientParams().iConnectPassword->Length() > KBlueToothObexPasswordLength) + User::Leave(KErrArgument); + + serverParams().iTimeouts = clientParams().iTimeouts; + serverParams().iRemoteObexPort = clientParams().iRemoteObexPort; + serverParams().iConnectPassword = *(clientParams().iConnectPassword); + + op = Session().TransferCommandL(aSelection, aFunctionId, serverParams, + aCompletionStatus); + break; + } + default: + User::Leave(KErrNotSupported); + } + return(op); // ownership of op is passed to caller + } + + +void CBtClientMtm::CreateMessageOperationL( + CMsvOperation*& aOperation, const CMsvEntrySelection& aSelection, TRequestStatus& aCompletionStatus) + { + // must have at least 1 addressee (if more than 1 the others are ignored) + if (AddresseeList().Count() == 0) + { + User::Leave(KErrArgument); + } + + // extract and parse addressee information + TPckgBuf serverParams; + serverParams().iRemoteObexPort = 0; + + // Set some default values for the timeouts in case they have not been added to + // the addressee. + serverParams().iTimeouts.iConnectTimeout = 0; + serverParams().iTimeouts.iPutTimeout = 0; + + // address already saved when addressee was added (and we know there is at least one) + TBuf8 addressIgnored; + TBuf password; + ParseDestinationL(AddresseeList()[0], addressIgnored, password, + serverParams().iTimeouts.iConnectTimeout, + serverParams().iTimeouts.iPutTimeout); + + serverParams().iConnectPassword = password; + + // obex send operation wrapper, supporting standard progress + CObexSendOperation* send = new(ELeave) CObexSendOperation(Session(), aCompletionStatus); + CleanupStack::PushL(send); + // start the send operation + CMsvOperation* op = + Session().TransferCommandL(aSelection, EBtMtmCmdSend, serverParams, send->iStatus); + CleanupStack::PushL(op); + send->Start(op); + CleanupStack::Pop(2, send); // op, send + aOperation = send; + } + +void CBtClientMtm::AddAddresseeL(const TDesC& anAddressee) + { + // check addressee parses ok - checks all fields (that are there) + TBuf8 address; + TBuf ignored1; + TInt ignored2(0); + TInt ignored3(0); + ParseDestinationL(anAddressee, address, ignored1, ignored2, ignored3); + + // parses ok, try to save it - fails if there is already an addressee + CObexClientMtm::AddAddresseeL(anAddressee); + + // parses and saves ok, store device address in header + iHeader->SetAddrL(address); + } + +/** + * Parse bluetooth addressee field + * + * @param aFieldTag Field tag ID (see TBtClientMtmAddresseeFieldType). + * @param aField The next field (descriptor buffer of the correct size for the given field). + * @param aFieldList Addressee field list. + * @leave Leaves with KErrArgument if parameter or formatting incorrect. + */ +TBool CBtClientMtm::ParseDestinationFieldL(TUint16 aFieldTag, TDes8& aField, TPtrC& aFieldList) + { + TBool isDeviceAddress = (aFieldTag == EDeviceAddress); + + aField.Zero(); + TInt length = aFieldList.Length(); + if (!isDeviceAddress) + { + // end of field list + if (length == 0) + { + return EFalse; + } + // expecting tag + if (length < 2 || aFieldList[0] != ':' || aFieldList[1] != aFieldTag) + { + User::Leave(KErrArgument); + } + // remove tag and marker + aFieldList.Set(aFieldList.Right(aFieldList.Length() - 2)); + } + + // locate next tag + TInt fieldLength = aFieldList.Locate(':'); + if (fieldLength == KErrNotFound) + { + fieldLength = aFieldList.Length(); + } + + // twice as many bytes + TInt fieldLength8 = fieldLength << 1; + if (fieldLength8 > aField.MaxLength()) + { + User::Leave(KErrArgument); + } + + // copy field + aField.Copy((TUint8*)aFieldList.Ptr(), fieldLength8); + + // remove field from field list + aFieldList.Set(aFieldList.Right(aFieldList.Length() - fieldLength)); + + return ETrue; + } + +/** + * Parse bluetooth addressing information from addressee list. + * + * @param aDeviceAddress Device address (6 bytes). + * @param aPassword Password (max length 16). + * @param aConnectTimeout Connection timeout. + * @param aPutTimeout Put timeout. + * @leave Leaves with KErrArgument if parameter or formatting incorrect. + */ +void CBtClientMtm::ParseDestinationL(const TDesC& aFieldsToParse, TDes8& aDeviceAddress, + TDes16& aPassword, TInt& aConnectTimeout, TInt& aPutTimeout) + { + TPtrC16 fields(aFieldsToParse); + + // get device address + if (ParseDestinationFieldL(EDeviceAddress, aDeviceAddress, fields)) + { + // get password + TPtr8 password((TUint8*)aPassword.Ptr(), aPassword.MaxLength()<<1); + if (ParseDestinationFieldL(EPassword, password, fields)) + { + aPassword.SetLength(password.Length()>>1); + // get connection timeout + TPckg connectTimeout(aConnectTimeout); + TBool parsedOk = EFalse; + + // The connect timeout can have a field tag defined by ETimeout, or a + // field tag defined by EAlternativeConnectTimeout. This is because an + // older version of code looked for the wrong tag (EAlternativeConnectTimeout), + // and we need to remain backward compatible with it. + TRAPD(err, parsedOk = ParseDestinationFieldL(ETimeout, connectTimeout, fields)); + + if (err == KErrArgument) + { + parsedOk = ParseDestinationFieldL(EAlternativeConnectTimeout, connectTimeout, fields); + } + else + { + User::LeaveIfError(err); + } + + if (parsedOk) + { + // get put timeout + TPckg putTimeout(aPutTimeout); + ParseDestinationFieldL(EPutTimeout, putTimeout, fields); + } + } + } + } + + + +#ifdef _DEBUG +void CBtClientMtm::TestInvariant() const + { + __ASSERT_DEBUG(iMsvEntry && + iHeader && + (iMsvEntry->Entry().iMtm == KUidMsgTypeBt) && + (iMsvEntry->Entry().iType == KUidMsvMessageEntry), + User::Invariant()); + } +#endif //_DEBUG +