messagingappbase/obexmtms/btmtm/btclient/source/btcmtm.cpp
changeset 0 72b543305e3a
child 23 238255e8b033
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 2004-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 // btcmtm.cpp
       
    15 //
       
    16 
       
    17 //class include
       
    18 #include <btcmtm.h>
       
    19 
       
    20 //system includes
       
    21 #include <e32std.h>
       
    22 #include <e32base.h>
       
    23 #include <txtrich.h>	// CRichText
       
    24 
       
    25 #include <mtmuids.h>	// KUidMtmQueryCanSendMsg
       
    26 #include <msvreg.h>		// CRegisteredMtmDll
       
    27 #include <mtmdef.h>		// KUidMtmQueryxxx & TMsvPartList flags
       
    28 #include <msvuids.h>	// KUidMsvMessageEntry
       
    29 #include "btmtmcmds.h"	//EBtMtmCmdSend
       
    30 
       
    31 //user includes
       
    32 #include <btheader.h>
       
    33 #include "btmsgtypeuid.h" //KUidMsgTypeBt
       
    34 #include <cobexsendoperation.h>
       
    35 
       
    36 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  
       
    37 #include "msvconsts.h"
       
    38 #include <mtmuidsdef.hrh>
       
    39 #endif
       
    40 
       
    41 const TUint8 KObexConnectionIDHeader = 0xCB;
       
    42 
       
    43 CBtClientMtm::CBtClientMtm(CRegisteredMtmDll& aRegisteredMtmDll, CMsvSession& aMsvSession)
       
    44 : CObexClientMtm(aRegisteredMtmDll, aMsvSession, KUidMsgTypeBt)
       
    45 /**
       
    46  * Constructor--not for use by client applications
       
    47  *
       
    48  * @param aRegisteredMtmDll Registration data for MTM DLL.
       
    49  * @param aMsvSession CMsvSession of the client requesting the object. 
       
    50  */
       
    51 	{
       
    52 	}
       
    53 
       
    54 void CBtClientMtm::InitialiseHeaderL()
       
    55 /**
       
    56  * Deletes the old header, then creates a new CBtHeader.
       
    57  *
       
    58  * @leave KErrXXX System-wide error codes if allocation fails
       
    59  */
       
    60 	{
       
    61 	delete iHeader;
       
    62 	iHeader = 0;
       
    63 
       
    64 	iHeader = CBtHeader::NewL();
       
    65 	}
       
    66 
       
    67 EXPORT_C CBtClientMtm* CBtClientMtm::NewL(CRegisteredMtmDll& aRegisteredMtmDll, CMsvSession& aMsvSession)
       
    68 /**
       
    69  * Canonical NewL factory function. 
       
    70  *
       
    71  * @param aRegisteredMtmDll Reference to registration data for MTM DLL.
       
    72  * @param aMsvSession Reference to CMsvSession of the client requesting the object.
       
    73  * @return Pointer to a new, constructed CBtClientMtm
       
    74  * @leave Leaves if no memory is available.
       
    75  */
       
    76 	{
       
    77 	CBtClientMtm* self = new(ELeave) CBtClientMtm(aRegisteredMtmDll, aMsvSession);
       
    78 	CleanupStack::PushL(self);
       
    79 	self->ConstructL();
       
    80 	CleanupStack::Pop();
       
    81 	return self;
       
    82 	}
       
    83 
       
    84 CMsvOperation* CBtClientMtm::InvokeAsyncFunctionL(TInt aFunctionId, 
       
    85 												    const CMsvEntrySelection& aSelection,
       
    86 													TDes8& aParameter, 
       
    87 												    TRequestStatus& aCompletionStatus)
       
    88 /**
       
    89  * Starts an asynchronous function as an active object. Only works for EBtcCmdSend.
       
    90  *
       
    91  * @param aFunctionId Identifier of the function to be invoked. Only supports EBtcCmdSend and
       
    92  * KMTMStandardFunctionsSendMessage.
       
    93  * @param aSelection Selction of message entries for the requested function to operate on.
       
    94  * @param aParameter Buffer containing input and output parameters.
       
    95  * @param aCompletionStatus Canonical TRequestStatus used for control of the active object.
       
    96  * @return Pointer to a new asynchronously completing CMsvOperation. If failed, this is a completed operation with 
       
    97  * status set to the relevant error code.
       
    98  * @leave Leaves if no memory is available, or if the specified aFunctionId is unsupported.
       
    99  */	{
       
   100 	__TEST_INVARIANT_VIRTUAL
       
   101 
       
   102 	CMsvOperation* op = NULL;
       
   103 	switch (aFunctionId)
       
   104 		{
       
   105 	case KMTMStandardFunctionsSendMessage:
       
   106 			{
       
   107 			// parameter ignored, it's assumed that the 1st addressee will contain all the
       
   108 			// required information to send this item. Only the 1st item in the selection
       
   109 			// list is sent.
       
   110 			CreateMessageOperationL(op, aSelection, aCompletionStatus);
       
   111 			break;
       
   112 			}
       
   113 	case EBtMtmCmdSend:
       
   114 			{
       
   115 			/*
       
   116 			In order to get our password over the client-server boundary without breaking the client interface
       
   117 			we will repack the client side package buffer into a server package buffer.
       
   118 			*/
       
   119 			TPckgBuf<CBtClientMtm::SBtcCmdSendServerParams> serverParams;
       
   120 
       
   121 			TPckgBuf<CBtClientMtm::SBtcCmdSendParams>& clientParams = (TPckgBuf<CBtClientMtm::SBtcCmdSendParams>&)aParameter;
       
   122 
       
   123 			/* at this point, it may be worth checking the length of the supplied password
       
   124 			and leaving with KErrArgument if it's longer than allowed */
       
   125 			if(!clientParams().iConnectPassword || clientParams().iConnectPassword->Length() > KBlueToothObexPasswordLength)
       
   126 				User::Leave(KErrArgument);
       
   127 				
       
   128 			serverParams().iTimeouts = clientParams().iTimeouts;
       
   129 			serverParams().iRemoteObexPort = clientParams().iRemoteObexPort;
       
   130 			serverParams().iConnectPassword = *(clientParams().iConnectPassword);
       
   131 
       
   132 			op = Session().TransferCommandL(aSelection,	aFunctionId, serverParams,
       
   133 											aCompletionStatus);
       
   134 			break;
       
   135 			}
       
   136 	default:
       
   137 		User::Leave(KErrNotSupported);
       
   138 		}
       
   139 	return(op); // ownership of op is passed to caller
       
   140 	}
       
   141 
       
   142 
       
   143 void CBtClientMtm::CreateMessageOperationL(
       
   144 	CMsvOperation*& aOperation, const CMsvEntrySelection& aSelection, TRequestStatus& aCompletionStatus)
       
   145 	{		
       
   146 	// must have at least 1 addressee (if more than 1 the others are ignored)
       
   147 	if (AddresseeList().Count() == 0)
       
   148 		{
       
   149 		User::Leave(KErrArgument);
       
   150 		}
       
   151 	
       
   152 	// extract and parse addressee information
       
   153 	TPckgBuf<CBtClientMtm::SBtcCmdSendServerParams> serverParams;
       
   154 	serverParams().iRemoteObexPort = 0;
       
   155 	
       
   156 	// Set some default values for the timeouts in case they have not been added to
       
   157 	// the addressee.
       
   158 	serverParams().iTimeouts.iConnectTimeout = 0;
       
   159 	serverParams().iTimeouts.iPutTimeout = 0;
       
   160 
       
   161 	// address already saved when addressee was added (and we know there is at least one)
       
   162 	TBuf8<KBlueToothObexDeviceAddressLength> addressIgnored; 
       
   163 	TBuf<KBlueToothObexPasswordLength> password;
       
   164 	ParseDestinationL(AddresseeList()[0], addressIgnored, password, 
       
   165 		serverParams().iTimeouts.iConnectTimeout, 
       
   166 		serverParams().iTimeouts.iPutTimeout);
       
   167 
       
   168 	serverParams().iConnectPassword = password;
       
   169 			
       
   170 	// obex send operation wrapper, supporting standard progress
       
   171 	CObexSendOperation* send = new(ELeave) CObexSendOperation(Session(), aCompletionStatus);
       
   172 	CleanupStack::PushL(send);
       
   173 	// start the send operation
       
   174 	CMsvOperation* op = 
       
   175 		Session().TransferCommandL(aSelection,	EBtMtmCmdSend, serverParams, send->iStatus);
       
   176 	CleanupStack::PushL(op);
       
   177 	send->Start(op);
       
   178 	CleanupStack::Pop(2, send); // op, send
       
   179 	aOperation = send;
       
   180 	}
       
   181 
       
   182 void CBtClientMtm::AddAddresseeL(const TDesC& anAddressee)
       
   183 	{
       
   184 	// check addressee parses ok - checks all fields (that are there)
       
   185 	TBuf8<KBlueToothObexDeviceAddressLength> address;
       
   186 	TBuf<KBlueToothObexPasswordLength> ignored1;
       
   187 	TInt ignored2(0);
       
   188 	TInt ignored3(0);
       
   189 	ParseDestinationL(anAddressee, address, ignored1, ignored2, ignored3);
       
   190 	
       
   191 	// parses ok, try to save it - fails if there is already an addressee
       
   192 	CObexClientMtm::AddAddresseeL(anAddressee);	
       
   193 
       
   194 	// parses and saves ok, store device address in header
       
   195 	iHeader->SetAddrL(address);
       
   196 	}
       
   197 
       
   198 /**
       
   199  * Parse bluetooth addressee field
       
   200  *
       
   201  * @param aFieldTag Field tag ID (see TBtClientMtmAddresseeFieldType).
       
   202  * @param aField The next field (descriptor buffer of the correct size for the given field).
       
   203  * @param aFieldList Addressee field list.
       
   204  * @leave Leaves with KErrArgument if parameter or formatting incorrect.
       
   205  */
       
   206 TBool CBtClientMtm::ParseDestinationFieldL(TUint16 aFieldTag, TDes8& aField, TPtrC& aFieldList)
       
   207 	{
       
   208 	TBool isDeviceAddress = (aFieldTag == EDeviceAddress);
       
   209 
       
   210 	aField.Zero();
       
   211 	TInt length = aFieldList.Length();
       
   212 	if (!isDeviceAddress)
       
   213 		{
       
   214 		// end of field list
       
   215 		if (length == 0)
       
   216 			{
       
   217 			return EFalse;
       
   218 			}
       
   219 		// expecting tag
       
   220 		if (length < 2 || aFieldList[0] != ':' || aFieldList[1] != aFieldTag)
       
   221 			{
       
   222 			User::Leave(KErrArgument);
       
   223 			}
       
   224 		// remove tag and marker
       
   225 		aFieldList.Set(aFieldList.Right(aFieldList.Length() - 2));	
       
   226 		}
       
   227 
       
   228 	// locate next tag		
       
   229 	TInt fieldLength = aFieldList.Locate(':');
       
   230 	if (fieldLength == KErrNotFound)
       
   231 		{
       
   232 		fieldLength = aFieldList.Length();
       
   233 		}
       
   234 
       
   235 	// twice as many bytes
       
   236 	TInt fieldLength8 = fieldLength << 1;
       
   237 	if (fieldLength8 > aField.MaxLength())
       
   238 		{
       
   239 		User::Leave(KErrArgument);
       
   240 		}
       
   241 	
       
   242 	// copy field	
       
   243 	aField.Copy((TUint8*)aFieldList.Ptr(), fieldLength8);
       
   244 
       
   245 	// remove field from field list
       
   246 	aFieldList.Set(aFieldList.Right(aFieldList.Length() - fieldLength));	
       
   247 	
       
   248 	return ETrue;
       
   249 	}	
       
   250 	
       
   251 /**
       
   252  * Parse bluetooth addressing information from addressee list.
       
   253  *
       
   254  * @param aDeviceAddress Device address (6 bytes).
       
   255  * @param aPassword Password (max length 16).
       
   256  * @param aConnectTimeout Connection timeout.
       
   257  * @param aPutTimeout Put timeout.
       
   258  * @leave Leaves with KErrArgument if parameter or formatting incorrect.
       
   259  */
       
   260 void CBtClientMtm::ParseDestinationL(const TDesC& aFieldsToParse, TDes8& aDeviceAddress, 
       
   261 								   TDes16& aPassword, TInt& aConnectTimeout, TInt& aPutTimeout)
       
   262 	{
       
   263 	TPtrC16 fields(aFieldsToParse);
       
   264 
       
   265 	// get device address
       
   266 	if (ParseDestinationFieldL(EDeviceAddress, aDeviceAddress, fields))
       
   267 		{
       
   268 		// get password
       
   269 		TPtr8 password((TUint8*)aPassword.Ptr(), aPassword.MaxLength()<<1);
       
   270 		if (ParseDestinationFieldL(EPassword, password, fields))
       
   271 			{
       
   272 			aPassword.SetLength(password.Length()>>1);
       
   273 			// get connection timeout
       
   274 			TPckg<TInt> connectTimeout(aConnectTimeout);
       
   275 			TBool parsedOk = EFalse;
       
   276 
       
   277 			// The connect timeout can have a field tag defined by ETimeout, or a
       
   278 			// field tag defined by EAlternativeConnectTimeout. This is because an
       
   279 			// older version of code looked for the wrong tag (EAlternativeConnectTimeout),
       
   280 			// and we need to remain backward compatible with it.
       
   281 			TRAPD(err, parsedOk = ParseDestinationFieldL(ETimeout, connectTimeout, fields));
       
   282 
       
   283 			if (err == KErrArgument)
       
   284 				{
       
   285 				parsedOk = ParseDestinationFieldL(EAlternativeConnectTimeout, connectTimeout, fields);
       
   286 				}
       
   287 			else
       
   288 				{
       
   289 				User::LeaveIfError(err);
       
   290 				}
       
   291 
       
   292 			if (parsedOk)
       
   293 				{
       
   294 				// get put timeout
       
   295 				TPckg<TInt> putTimeout(aPutTimeout);
       
   296 				ParseDestinationFieldL(EPutTimeout, putTimeout, fields);
       
   297 				}
       
   298 			}
       
   299 		}
       
   300 	}
       
   301 
       
   302 
       
   303 
       
   304 #ifdef _DEBUG
       
   305 void CBtClientMtm::TestInvariant() const
       
   306 	{
       
   307 	__ASSERT_DEBUG(iMsvEntry &&
       
   308 				   iHeader &&
       
   309 				   (iMsvEntry->Entry().iMtm == KUidMsgTypeBt) &&
       
   310 				   (iMsvEntry->Entry().iType == KUidMsvMessageEntry),
       
   311 				   User::Invariant());
       
   312 	}
       
   313 #endif //_DEBUG
       
   314