obex/obexprotocol/obex/src/OBEX.CPP
changeset 0 d0791faffa3f
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     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  @file
       
    18  @internalComponent
       
    19 */
       
    20 
       
    21 
       
    22 #include <charconv.h>
       
    23 #include <utf.h>
       
    24 #include <obex.h>
       
    25 #include <obex/internal/obexinternalheader.h>
       
    26 #include <obextransportinfo.h>
       
    27 #include <obexirtransportinfo.h>
       
    28 #include <obex/transport/obextransportcontrollerbase.h>
       
    29 #include <obex/internal/obexpacket.h>
       
    30 #include "logger.h"
       
    31 #include "obexsetpathdata.h"
       
    32 #include "OBEXUTIL.H"
       
    33 #include "authentication.h"
       
    34 #include <ecom/ecom.h>
       
    35 
       
    36 #ifdef __FLOG_ACTIVE
       
    37 _LIT8(KLogComponent, "OBEX");
       
    38 #endif
       
    39 
       
    40 /**
       
    41 Constructor - set initial values and copy in protocol policy information
       
    42 @internalComponent
       
    43 */
       
    44 CObex::CObex()
       
    45 	{
       
    46 #ifdef _DEBUG
       
    47 	CObexLog::Connect();
       
    48 #endif
       
    49 	FLOG(_L("Creating CObex"));
       
    50 	SetConnectState(EConnIdle);
       
    51 	}
       
    52 
       
    53 void CObex::ConstructL(TObexTransportInfo& aObexTransportInfo)
       
    54 	{
       
    55 	iTransportController = CObexTransportControllerBase::NewL(aObexTransportInfo);
       
    56 	iAuthEngine = CObexAuthenticator::NewL();
       
    57 	iSuppressedObexAuthElements = EObexNoSuppressedAuthElements;
       
    58 	}
       
    59 
       
    60 /** 
       
    61 Destructor. 
       
    62 */
       
    63 CObex::~CObex()
       
    64 	{
       
    65 	
       
    66 	delete iTransportController;
       
    67 	delete iAuthEngine;
       
    68 	delete iChallPassword;
       
    69 	delete iRespPassword;
       
    70 	delete iRemoteUID;
       
    71 	delete iRemoteRealm;
       
    72 	delete iRxChallenge;
       
    73 	
       
    74 	// This must be done AFTER destroying the transport controller.
       
    75 	REComSession::FinalClose();
       
    76 
       
    77 	// iNotifyHandler is deleted in the derived classes where it is instantiated
       
    78 
       
    79 #ifdef _DEBUG
       
    80 	CObexLog::Close();
       
    81 #endif
       
    82 	}
       
    83 
       
    84 /** 
       
    85 Get the socket address of the remote device.
       
    86 
       
    87 This is the address of the device OBEX is connected to over an IrDA or Bluetooth 
       
    88 socket. 
       
    89 
       
    90 @param aAddr Socket address. 
       
    91 
       
    92 @publishedAll
       
    93 @released
       
    94 */
       
    95 EXPORT_C void CObex::RemoteAddr(TSockAddr& aAddr)
       
    96 	{
       
    97 	LOG_LINE
       
    98 	LOG_FUNC
       
    99 	
       
   100 	// iTransportController must be valid for all the CObex life cycle 
       
   101 	__ASSERT_DEBUG(iTransportController, IrOBEXUtil::Fault(ETransportControllerNotCreated));
       
   102 		
       
   103 	iTransportController->RemoteAddr(aAddr);
       
   104 	}
       
   105 
       
   106 /** 
       
   107 Sets the local Who field.
       
   108 
       
   109 This is used to identify the local end of the OBEX session when the OBEX connection 
       
   110 is made. If it is required, set it before establishing the connection.
       
   111 
       
   112 @param aInfo Who field
       
   113 @return KErrNone or KErrArgument if aInfo is empty  
       
   114 
       
   115 @publishedAll
       
   116 @released
       
   117 */
       
   118 EXPORT_C TInt CObex::SetLocalWho(const TDesC8& aInfo)
       
   119 	{ 
       
   120 	LOG_LINE
       
   121 	LOG_FUNC
       
   122 
       
   123 	if(aInfo.Length())
       
   124 		{ iLocalInfo.iWho.Copy(aInfo); return KErrNone;} 
       
   125 	else
       
   126 		return KErrArgument;
       
   127 	}
       
   128 
       
   129 /** 
       
   130 Indicates if the Server / Client is currently authenticating the OBEX
       
   131 connection.
       
   132 
       
   133 @return ETrue if the Server / Client is currently authenticating the OBEX connection otherwise EFalse.
       
   134 
       
   135 @publishedAll
       
   136 @released
       
   137 */
       
   138 EXPORT_C TBool CObex::IsAuthenticating() const
       
   139 	{
       
   140 	return (ConnectState() >= EConnChallRxed && ConnectState() <= EWaitForUserInput);
       
   141 	}
       
   142 	
       
   143 
       
   144 /**
       
   145 @param aPassword Password to use in challenge response
       
   146 @internalComponent
       
   147 */
       
   148 void CObex::PrepareChallResponseL(const TDesC& aPassword)
       
   149 	{
       
   150 
       
   151 	FLOG(_L("CObex::PrepareChallResponse\r\n"));
       
   152 	iOutgoingChallResp.Zero(); 
       
   153 	TRequestDigest response;
       
   154 	delete iRespPassword;
       
   155 	iRespPassword = NULL;
       
   156 	iRespPassword = HBufC8::NewL(aPassword.Length());
       
   157 	TPtr8 ptr = iRespPassword->Des();
       
   158 	CnvUtfConverter::ConvertFromUnicodeToUtf8(ptr, aPassword);
       
   159 	
       
   160 	iAuthEngine->GenerateResponseL(ptr, iIncomingNonce, response);
       
   161 	FLOG(_L("PrepareChallResponse: Digest response generated"));
       
   162 
       
   163 	FLOG(_L("PrepareChallResponse: Adding response hash"));
       
   164 	iOutgoingChallResp.Append(KObexRespTag); //0x00
       
   165 	iOutgoingChallResp.Append(KObexRespSize); //16
       
   166 	iOutgoingChallResp.Append(response);
       
   167 
       
   168 	//only reply with UserID if requested
       
   169 	if (iUserIDRequested )
       
   170 		{
       
   171 		FLOG(_L("PrepareChallResponse: User ID required, adding zero length field"));
       
   172 		iOutgoingChallResp.Append(KObexRespUserIDTag); //0x01
       
   173 		//Fixme, add in the size of the user ID
       
   174 		iOutgoingChallResp.Append(0); //assume no UserID size of 0
       
   175 		//any user ID would have to be inserted here
       
   176 		//iOutgoingChallResp.Append(userID); //Fixme what is the user ID?
       
   177 		}
       
   178 	
       
   179 	FLOG(_L("PrepareChallResponse: Adding nonce of challenge we're replying to"));
       
   180 	iOutgoingChallResp.Append(KObexRespNonceTag);
       
   181 	iOutgoingChallResp.Append(KObexNonceSize);
       
   182 	iOutgoingChallResp.Append(iIncomingNonce);
       
   183 
       
   184 	FLOG(_L(" PrepareChallResponse - complete response generated"));
       
   185 	}
       
   186 
       
   187 /**
       
   188 @internalComponent
       
   189 */
       
   190 TInt CObex::GenerateChallenge(CObexPacket& aPacket)
       
   191 	{
       
   192 	TInt retValue = KErrNone;
       
   193 
       
   194 	FLOG(_L("CObex::GenerateChallenge\r\n"));
       
   195 	iOutgoingNonce.Zero();
       
   196 	iAuthEngine->GenerateNonce(iOutgoingNonce);
       
   197 	//now pack all the data together for the overall challenge
       
   198 	TBuf8<KObexChallHeaderSize> outGoingHeader; //this size assumes no Realm data
       
   199 	outGoingHeader.Zero();
       
   200 	outGoingHeader.Append(KObexChallNonceTag);
       
   201 	outGoingHeader.Append(KObexNonceSize);
       
   202 	outGoingHeader.Append(iOutgoingNonce);
       
   203 	
       
   204 	// Add authentication header only if the client has not disallowed it
       
   205 	if (!(iSuppressedObexAuthElements & EObexSuppressChallengeOptionsAuthElement))
       
   206 		{		
       
   207 		outGoingHeader.Append(KObexChallOptionsTag);
       
   208 		outGoingHeader.Append(1); //size is always 1
       
   209 		outGoingHeader.Append(0); //all options off
       
   210 		}
       
   211 		
       
   212 	// Add realm header only if the client has not disallowed it	
       
   213 	if (!(iSuppressedObexAuthElements & EObexSuppressRealmAuthElement))
       
   214 		{
       
   215 		outGoingHeader.Append(KObexChallRealmTag);
       
   216 		outGoingHeader.Append(0); //no realm so size = 0
       
   217 		}
       
   218 
       
   219 	TObexInternalHeader hdr;
       
   220 	hdr.Set(TObexInternalHeader::EAuthChallenge, (const_cast<TUint8*> (outGoingHeader.Ptr())), outGoingHeader.Size());
       
   221 	if(!aPacket.InsertData(hdr))
       
   222 		retValue = KErrOverflow;
       
   223 		
       
   224 	return (retValue);
       
   225 	}
       
   226 
       
   227 /**
       
   228 @internalComponent
       
   229 */
       
   230 void CObex::ProcessChallResponseL(const TObexInternalHeader& hdr)
       
   231 	{
       
   232 	FLOG(_L("CObex::ProcessChallResponse"));
       
   233 	TBool retValue = ETrue;
       
   234 	TInt responseSize = hdr.HVSize();
       
   235 	TInt elementsLeft = responseSize;	//keep track of how many elements still to be removed
       
   236 
       
   237 	if ( responseSize > KChallResponseSize )
       
   238 		{
       
   239 		retValue = EFalse;
       
   240 		FLOG(_L("ProcessChallResponse - Response header too big FAILED"));
       
   241 		}
       
   242 	else if (responseSize < KMinChallResponseSize)
       
   243 		{ 
       
   244 		retValue = EFalse;
       
   245 		FLOG(_L("ProcessChallResponse - Response header too small FAILED"));
       
   246 		}
       
   247 
       
   248 	//get the response 
       
   249 	iIncomingChallResp.Zero();
       
   250 	iIncomingChallResp.Copy(hdr.HVByteSeq(), responseSize);
       
   251 	
       
   252 	//there is no reason to assume that the data is going to arrive
       
   253 	//in any particular order
       
   254 	TInt extractionPosn = 0;
       
   255 
       
   256 	//ensure space enough for the tag and size  
       
   257 	while ((extractionPosn <  (responseSize-1) ) && retValue)
       
   258 		{
       
   259 		switch (iIncomingChallResp[extractionPosn++])
       
   260 			{
       
   261 			case KObexRespTag:
       
   262 				{
       
   263 				elementsLeft--; //moved passed the tag
       
   264 				if ((iIncomingChallResp[extractionPosn++] == KObexRespSize)&&
       
   265 					(elementsLeft > KObexRespSize)) //must be greater to allow for size field
       
   266 					{
       
   267 					elementsLeft--; //moved passed the size
       
   268 					FLOG(_L("ProcessChallResponse - iIncoming Request Response extracted"));
       
   269 					iIncomingRequestDigest.Zero();
       
   270 					iIncomingRequestDigest.Append((TUint8*)iIncomingChallResp.Ptr() + extractionPosn, KObexRespSize);
       
   271 					extractionPosn += KObexRespSize;
       
   272 					elementsLeft -= KObexRespSize;
       
   273 					}
       
   274 				else
       
   275 					{
       
   276 					FLOG(_L("ProcessChallResponse - iIncoming Request Response extraction FAILED"));
       
   277 					retValue = EFalse;
       
   278 					}
       
   279 				}
       
   280 				break;
       
   281 			case KObexRespUserIDTag:
       
   282 				{
       
   283 				elementsLeft--; //moved passed the tag
       
   284 				TInt userIDSize = iIncomingChallResp[extractionPosn++];
       
   285 				if ( userIDSize > 0)
       
   286 					{
       
   287 					elementsLeft--; //moved passed the User ID size
       
   288 					if (( userIDSize > 0 )&&(userIDSize <= elementsLeft ))
       
   289 						{
       
   290 						elementsLeft -= userIDSize;
       
   291 						FLOG(_L("ProcessChallResponse - iIncoming ASCII UserID Extracted"));
       
   292 						delete iRemoteUID;
       
   293 						iRemoteUID = NULL;
       
   294 						iRemoteUID = HBufC::NewL(userIDSize); 
       
   295 						TPtrC8 ptr((TUint8*)iIncomingChallResp.Ptr() + extractionPosn, userIDSize);
       
   296 						TPtr ptrUID((TUint16*)iRemoteUID->Ptr(), userIDSize);
       
   297 						CnvUtfConverter::ConvertToUnicodeFromUtf8(ptrUID, ptr);
       
   298 						extractionPosn += userIDSize;
       
   299 						}
       
   300 					}
       
   301 				else
       
   302 					{
       
   303 					retValue = EFalse;
       
   304 					FLOG(_L("ProcessChallResponse - iIncoming UserID Extraction FAILED"));
       
   305 					}
       
   306 				}
       
   307 			break;
       
   308 			//don't bother extracting the Nonce as we do not support multiple Nonce replies
       
   309 			//the assumption is the reply received is for the Nonce we sent out
       
   310 			case KObexRespNonceTag:
       
   311 				{
       
   312 				FLOG(_L("ProcessChallResponse: extracting incoming nonce"));
       
   313 				elementsLeft--; //moved passed the tag
       
   314 				TInt nonceSize = iIncomingChallResp[extractionPosn++];
       
   315 				if ( nonceSize > 0 )
       
   316 					{
       
   317 					elementsLeft--; //moved passed size
       
   318 					if ( nonceSize <= elementsLeft )
       
   319 						{
       
   320 						FTRACE(
       
   321 						TPtrC8 incomingNonce(iIncomingChallResp.Ptr() + extractionPosn, nonceSize);
       
   322 						if (incomingNonce != iOutgoingNonce)
       
   323 							{
       
   324 							FLOG(_L("ProcessChallResponse: incoming nonce does not match our challenge. Continuing anyway."));
       
   325 							}
       
   326 						);
       
   327 						
       
   328 						elementsLeft -= nonceSize;
       
   329 						extractionPosn += nonceSize;
       
   330 						}
       
   331 					else
       
   332 						{
       
   333 						FLOG(_L("ProcessChallResponse - iIncoming Request Response extraction, bad nonce size FAILED"));
       
   334 						retValue = EFalse;
       
   335 						}
       
   336 					}
       
   337 				}
       
   338 				break;
       
   339 			default: 
       
   340 				{
       
   341 				FLOG(_L("ProcessChallResponse - iIncoming Request Response extraction,unknown tag type FAILED"));
       
   342 				retValue = EFalse;
       
   343 				}
       
   344 			break;
       
   345 			
       
   346 			}
       
   347 		TRAPD(err, iAuthEngine->ChallengeResponseL(*iChallPassword, iOutgoingNonce, iIncomingRequestDigest));
       
   348 		if ( err != KErrNone)
       
   349 			{
       
   350 			FLOG(_L("ProcessChallResponse - Responsed Denied"));
       
   351 			User::Leave(err);
       
   352 			}
       
   353 		}
       
   354 	if (!retValue )
       
   355 		User::Leave(KErrGeneral);
       
   356 	}
       
   357 
       
   358 /**
       
   359 @internalComponent
       
   360 */
       
   361 void CObex::ProcessChallengeL(const TObexInternalHeader& hdr)
       
   362 	{
       
   363 	FLOG(_L("CObex::ProcessChallenge\n\r"));
       
   364 
       
   365 	//extract all the necessary data
       
   366 	TInt challengeSize = hdr.HVSize();
       
   367 	TInt extractionPosn = 0;
       
   368 	TInt elementsLeft = challengeSize;
       
   369 	TBool nonceExtracted = EFalse;
       
   370 
       
   371 	delete iRxChallenge;
       
   372 	iRxChallenge = NULL;
       
   373 	iRxChallenge = HBufC8::NewL(challengeSize);
       
   374 	iRxChallenge->Des().Copy(hdr.HVByteSeq(), challengeSize);
       
   375 	delete iRemoteRealm;
       
   376 	iRemoteRealm = NULL;
       
   377 
       
   378 
       
   379 
       
   380 	//can't make any assumptions about the order
       
   381 	//in which anything may arrive, so allow any old order
       
   382 	TBool exit = EFalse;
       
   383 	if ( challengeSize < (KObexNonceSize + 2))
       
   384 		{
       
   385 		FLOG(_L("CObex::ProcessChallenge incoming Challenge too small\n\r"));
       
   386 		User::Leave(KErrGeneral);
       
   387 		}
       
   388 
       
   389 	//must be space for Tag and size
       
   390 	while ((elementsLeft > 2) && (!exit))
       
   391 		{
       
   392 		switch (iRxChallenge->Des()[extractionPosn++])
       
   393 			{
       
   394 			case KObexChallNonceTag: //check the Nonce tag has arrived
       
   395 				{
       
   396 				elementsLeft--;  //passed the tag posn
       
   397 				if (( iRxChallenge->Des()[extractionPosn++] == KObexNonceSize )
       
   398 					&& (elementsLeft > KObexNonceSize))
       
   399 					{
       
   400 					FLOG(_L("CObex::ProcessChallenge incoming Nonce Extracted\n\r"));
       
   401 					iIncomingNonce.Zero();
       
   402 					//extract the Nonce data
       
   403 					TPtr8 ptr((TUint8*)iRxChallenge->Ptr() + extractionPosn 
       
   404 						,KObexNonceSize, KObexNonceSize);
       
   405 					iIncomingNonce.Append(ptr);
       
   406 					elementsLeft -= (KObexNonceSize + 1);
       
   407 					nonceExtracted = ETrue;
       
   408 					extractionPosn += KObexNonceSize;
       
   409 					}
       
   410 				else
       
   411 					{
       
   412 					FLOG(_L("CObex::ProcessChallenge Incorrect Nonce size\n\r"));
       
   413 					exit = ETrue;
       
   414 					}
       
   415 				}
       
   416 			break;
       
   417 			case KObexChallOptionsTag:
       
   418 				{
       
   419 				elementsLeft--;  //passed the tag posn
       
   420 				//check the options flag
       
   421 				iUserIDRequested = EFalse; 
       
   422 				if (( iRxChallenge->Des()[extractionPosn++] == KObexChallOptionSize )
       
   423 					&& (elementsLeft > KObexChallOptionSize))
       
   424 					{
       
   425 					//check if the user ID is required in the reply
       
   426 					if ( iRxChallenge->Des()[extractionPosn++] & KObexRequireUID )
       
   427 						{
       
   428 						//the userID has been requested so it MUST be sent back in the chall response
       
   429 						iUserIDRequested = ETrue;
       
   430 						FLOG(_L("CObex::ProcessChallenge User ID Requested\n\r"));
       
   431 						}
       
   432 					elementsLeft -= (KObexChallOptionSize + 1);
       
   433 
       
   434 					}
       
   435 				else
       
   436 					{
       
   437 					FLOG(_L("CObex::ProcessChallenge Incorrect Options size\n\r"));
       
   438 					exit = ETrue;
       
   439 					}
       
   440 				}
       
   441 				break;
       
   442 			case KObexChallRealmTag:
       
   443 				{
       
   444 				elementsLeft--;  //passed the tag posn
       
   445 				TInt size = iRxChallenge->Des()[ extractionPosn++ ];
       
   446 				elementsLeft--;
       
   447 				if ( (size > 0 ) && (size <= elementsLeft ) )
       
   448 					{
       
   449 					elementsLeft -= size;
       
   450 					size--; //remove the first byte
       
   451 					//check which format the data is in
       
   452  					TUint convertType=0;
       
   453  					switch(iRxChallenge->Des()[extractionPosn++])
       
   454  						{
       
   455  					case 0:
       
   456  						convertType=KCharacterSetIdentifierAscii;
       
   457  						break;
       
   458  					case 1:
       
   459  						convertType=KCharacterSetIdentifierIso88591;
       
   460  						break;
       
   461  					case 2:
       
   462  						convertType=KCharacterSetIdentifierIso88592;
       
   463  						break;
       
   464  					case 3:
       
   465  						convertType=KCharacterSetIdentifierIso88593;
       
   466  						break;
       
   467  					case 4:
       
   468  						convertType=KCharacterSetIdentifierIso88594;
       
   469  						break;
       
   470  					case 5:
       
   471  						convertType=KCharacterSetIdentifierIso88595;
       
   472  						break;
       
   473  					case 6:
       
   474  						convertType=KCharacterSetIdentifierIso88596;
       
   475  						break;
       
   476  					case 7:
       
   477  						convertType=KCharacterSetIdentifierIso88597;
       
   478  						break;
       
   479  					case 8:
       
   480  						convertType=KCharacterSetIdentifierIso88598;
       
   481  						break;
       
   482  					case 9:
       
   483  						convertType=KCharacterSetIdentifierIso88599;
       
   484  						break;
       
   485  					case 0xFF:
       
   486  						// Unicode, no conversion needed
       
   487  						break;
       
   488  					default:
       
   489  						User::Leave(KErrGeneral);
       
   490  						}
       
   491  
       
   492  					if(convertType)
       
   493  						{
       
   494  						RFs fs;
       
   495  						LEAVEIFERRORL(fs.Connect());
       
   496  						CleanupClosePushL(fs);
       
   497  						CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewLC();
       
   498  						if (converter->PrepareToConvertToOrFromL(convertType, fs) != CCnvCharacterSetConverter::EAvailable)
       
   499  							User::Leave(KErrGeneral);
       
   500  
       
   501  						iRemoteRealm = HBufC::NewL(size);
       
   502  						TPtr16 dest = iRemoteRealm->Des();
       
   503  						TInt state=CCnvCharacterSetConverter::KStateDefault;
       
   504  						TInt err = converter->ConvertToUnicode(dest, iRxChallenge->Mid(extractionPosn, size), state);
       
   505  						if (err < 0)
       
   506  							User::Leave(err);
       
   507  						CleanupStack::PopAndDestroy(2); // fs, converter
       
   508    						}
       
   509 					else  //can only be unicode
       
   510 						{ //if unicode
       
   511 						FLOG(_L("CObex::ProcessChallenge incoming UNICODE Realm extracted\n\r"));
       
   512 						size = size/2; //if it's UNICODE then should be an even number
       
   513 						iRemoteRealm = HBufC::NewMaxL(size);
       
   514  						TPtr16 dest = iRemoteRealm->Des();
       
   515 						for ( TInt x = 0; x < size; x++ )
       
   516 							dest[x] = LittleEndian::Get16((TUint8*)iRxChallenge->Ptr() + extractionPosn + (2*x));
       
   517 						extractionPosn += size * 2;
       
   518 						}
       
   519 
       
   520 					}
       
   521 				else
       
   522 					{
       
   523 					FLOG(_L("CObex::ProcessChallenge Incorrect Realm size\n\r"));
       
   524 					exit = ETrue;
       
   525 					}
       
   526 				}
       
   527 				break;
       
   528 			default:
       
   529 				{
       
   530 				FLOG(_L("CObex::ProcessChallenge Unknown Tag type\n\r"));
       
   531 				exit = ETrue;
       
   532 				}
       
   533 				break;
       
   534 			}
       
   535 		}
       
   536 	if ( !nonceExtracted) //the nonce is mandatory so must exist
       
   537 		{
       
   538 		FLOG(_L("CObex::ProcessChallenge Nonce was not extracted\n\r"));
       
   539 		exit = ETrue;			
       
   540 		}
       
   541 	if ( exit )	
       
   542 		User::Leave(KErrGeneral);
       
   543 	}
       
   544 
       
   545 
       
   546 /** 
       
   547 Sets the authentication challenge handler.
       
   548 
       
   549 The caller must supply a MObexAuthChallengeHandler implementation to handle 
       
   550 calls from the Server/Client for a request for a password.
       
   551 
       
   552 @param aCallBack Authentication challenge handler  
       
   553 
       
   554 @publishedAll
       
   555 @released
       
   556 */
       
   557 EXPORT_C void CObex::SetCallBack(MObexAuthChallengeHandler& aCallBack)
       
   558 	{
       
   559 	LOG_LINE
       
   560 	LOG_FUNC
       
   561 
       
   562 	iCallBack = &aCallBack;
       
   563 	}
       
   564 
       
   565 /**
       
   566 @internalTechnology
       
   567 
       
   568 This function is retained for backwards compatibility and should not be called.
       
   569 
       
   570 Calling this function has undefined behaviour.
       
   571 */
       
   572 void CObex::Process(CObexPacket& aPacket)
       
   573 	{
       
   574 	NotifyProcess(aPacket);
       
   575 	}
       
   576 
       
   577 /**
       
   578 @internalTechnology
       
   579 
       
   580 This function is retained for backwards compatibility and should not be called.
       
   581 
       
   582 Calling this function has undefined behaviour.
       
   583 */
       
   584 void CObex::Error(TInt aError) 
       
   585 	{
       
   586 	NotifyError(aError);
       
   587 	}
       
   588 
       
   589 /**
       
   590 @internalTechnology
       
   591 
       
   592 This function is retained for backwards compatibility and should not be called.
       
   593 
       
   594 Calling this function has undefined behaviour.
       
   595 */
       
   596 void CObex::TransportUp() 
       
   597 	{
       
   598 	NotifyTransportUp();
       
   599 	}
       
   600 	
       
   601 /**
       
   602 @internalTechnology
       
   603 
       
   604 This function is retained for backwards compatibility and should not be called.
       
   605 Use ControlledTransportDown() or ForcedTransportDown() to disconnect the transport layer.
       
   606 Calling this function will result in an ETransportDownCalled panic.
       
   607 
       
   608 @panic ObexFault ETransportDownCalled
       
   609 @see ControlledTransportDown()
       
   610 @see ForcedTransportDown()
       
   611 */
       
   612 void CObex::TransportDown(TBool)
       
   613 	{
       
   614 	IrOBEXUtil::Fault(ETransportDownCalled);
       
   615 	}
       
   616 
       
   617 
       
   618 void CObex::NotifyProcess(CObexPacket& aPacket)
       
   619 	{
       
   620 	LOG2(_L8("Packet Received, opcode: 0x%2X, Length: %d"), 
       
   621 					aPacket.Opcode(), aPacket.PacketSize());
       
   622 	FTRACE(aPacket.Dump());
       
   623 	OnPacketReceive(aPacket);
       
   624 	// The queuing of the next read packet varies between Server and Client
       
   625 	//     Client is done at the end of CObexClient::OnPacketReceive
       
   626 	//     Server is done once the write packet completes in CObexServer::SignalPacketProcessEvent
       
   627 	// This is because the Server may be mid-way through an asynchronous operation after OnPacketReceive
       
   628 	// so we have to keep the current read packet
       
   629 	if ((GetConnectState() == EWaitForUserInput )&&(iCallBack))
       
   630 		{
       
   631 		TRAPD(err, iCallBack->GetUserPasswordL(iRemoteRealm ? static_cast<TDesC&>(*iRemoteRealm) : KNullDesC()));
       
   632 		if ( err )
       
   633 			{
       
   634 			Error(err);
       
   635 			}
       
   636 		}
       
   637 	}
       
   638 
       
   639 void CObex::NotifyError(TInt aError)
       
   640 	{
       
   641 	LOG1(_L8("Error Called: %d"), aError);
       
   642 
       
   643 	// This call has been moved to before ForcedTransportDown(), because it
       
   644 	// needs to check whether the current operation is "disconnect" or
       
   645 	// not, and ForcedTransportDown() sets it to "idle".
       
   646 	OnError(aError);
       
   647 
       
   648 	if(iConnectState >= EConnTransport)
       
   649 		{
       
   650 		ForcedTransportDown();
       
   651 		}
       
   652 	}
       
   653 
       
   654 void CObex::NotifyTransportUp()
       
   655 	{
       
   656 	FLOG(_L("CObex::NotifyTransportUp\n\r"));
       
   657 	SetConnectState(EConnTransport);
       
   658 	OnTransportUp();
       
   659 	}
       
   660 
       
   661 void CObex::NotifyTransportDown(TBool)
       
   662 	{
       
   663 	IrOBEXUtil::Fault(ETransportDownCalled);
       
   664 	}
       
   665 
       
   666 /**
       
   667 This function forces the transport to be taken down 
       
   668 regardless of whether or not  the underlying transport can recover without 
       
   669 restarting obex applications
       
   670 However if the transport controller fails to bring the transport down, then only
       
   671 the obex connection is cancelled.  
       
   672 This is called in error conditions
       
   673 
       
   674 @see ControlledTransportDown()
       
   675 @internalComponent
       
   676 */
       
   677 void CObex::ForcedTransportDown()
       
   678 	{
       
   679 	// iTransportController must be valid for all the CObex life cycle 
       
   680 	__ASSERT_DEBUG(iTransportController, IrOBEXUtil::Fault(ETransportControllerNotCreated));
       
   681 		
       
   682 	if (iTransportController->BringTransportDown())
       
   683 		{
       
   684 		SetConnectState(EConnIdle);
       
   685 		OnTransportDown();	
       
   686 		}
       
   687 	else 
       
   688 		{
       
   689 		//the transport failed to be taken down 
       
   690 		CancelObexConnection();
       
   691 		}
       
   692 	RemoteInfoCleanup();		
       
   693 	}
       
   694 	
       
   695 /**
       
   696 This function will  tear down the transport if the transport layer supports 
       
   697 transport reconnection on obex reconnection 
       
   698 This is called in conditions other than error conditions
       
   699 
       
   700 @see ForcedTransportDown()
       
   701 @internalComponent
       
   702 */	
       
   703 void CObex::ControlledTransportDown()
       
   704 	{
       
   705 	// iTransportController must be valid for all the CObex life cycle 
       
   706 	__ASSERT_DEBUG(iTransportController, IrOBEXUtil::Fault(ETransportControllerNotCreated));
       
   707 	
       
   708 	TBool canBringTransportDown = iTransportController->IsTransportRestartable();
       
   709 	if  (canBringTransportDown)
       
   710 		{
       
   711 		ForcedTransportDown();
       
   712 		}  	 	
       
   713 	else
       
   714   		{
       
   715   		CancelObexConnection();
       
   716   		RemoteInfoCleanup();
       
   717    		}
       
   718 
       
   719 	}	
       
   720 
       
   721 /**
       
   722 General cleanup of iRemoteInfo
       
   723 @internalComponent
       
   724 */
       
   725 void CObex::RemoteInfoCleanup()
       
   726 	{
       
   727 	// Some general cleanup here.
       
   728 	iRemoteInfo.iTargetHeader.SetLength(0);
       
   729 	iRemoteInfo.iWho.SetLength(0);
       
   730 	}
       
   731 
       
   732 /**
       
   733 Put into  transport connected state but cancel any outstanding transfers and operations
       
   734 @internalComponent
       
   735 */
       
   736 void CObex::CancelObexConnection()
       
   737 	{
       
   738 	// iTransportController must be valid for all the CObex life cycle 
       
   739 	__ASSERT_DEBUG(iTransportController, IrOBEXUtil::Fault(ETransportControllerNotCreated));
       
   740 		
       
   741 	 iTransportController->CancelTransfers();
       
   742    	SetConnectState(EConnTransport);
       
   743    	iCurrentOperation = EOpIdle;
       
   744 	}
       
   745 
       
   746 /**
       
   747 Change the state of the authentication state machine
       
   748 @param aNewState New state
       
   749 @internalComponent
       
   750 */
       
   751 void CObex::SetConnectState(TConnectState aNewState)
       
   752 	{
       
   753 	switch(iConnectState = aNewState)
       
   754 		{
       
   755 	case EConnIdle:
       
   756 		FLOG(_L("### Connection State EConnIdle\r\n"));
       
   757 		break;
       
   758  	case EConnTransport:
       
   759 		FLOG(_L("###### Connection State EConnTransport\r\n"));
       
   760 		break;
       
   761 	case ESimpleConnRequest:
       
   762 		FLOG(_L("######### Connection State ESimpleConnRequest\r\n"));
       
   763 		break;
       
   764 	case EConnObex:
       
   765 		FLOG(_L("######### Connection State EConnObex\r\n"));
       
   766 		break;
       
   767 	case EConnChallRxed:
       
   768 		FLOG(_L("######### Connection State EConnChallRxed\r\n"));
       
   769 		break;
       
   770 	case ESimpleConnChallIssued:
       
   771 		FLOG(_L("######### Connection State ESimpleConnChallIssued\r\n"));
       
   772 		break;
       
   773 	case EChallConnRequested:
       
   774 		FLOG(_L("######### Connection State EChallConnRequested\r\n"));
       
   775 		break;
       
   776 	case EChallConnChallIssued:
       
   777 		FLOG(_L("######### Connection State EChallConnChallIssued\r\n"));
       
   778 		break;
       
   779 	case EWaitForFinalResponse:
       
   780 		FLOG(_L("######### Connection State EWaitForFinalResponse\r\n"));
       
   781 		break;
       
   782 	case EFinalChallRxed:
       
   783 		FLOG(_L("######### Connection State EConnChallReIssued\r\n"));
       
   784 		break;
       
   785 	case EDropLink:
       
   786 		FLOG(_L("######### Connection State EDropLink\r\n"));
       
   787 		break;
       
   788 	default: 
       
   789 		break;
       
   790 		}
       
   791 	}
       
   792 	
       
   793 // CObex::TSetPathInfo
       
   794 /**
       
   795 Constructor. 
       
   796 
       
   797 This is the path information used in the SETPATH command.
       
   798 The variable iFlags is set to zero by default. The variable iConstants is always set to zero as this is a reserved 
       
   799 varaible. The path name is NOT present by default.
       
   800 
       
   801 @publishedAll
       
   802 @released
       
   803 */
       
   804 EXPORT_C CObex::TSetPathInfo::TSetPathInfo() 
       
   805 	{
       
   806 	LOG_LINE
       
   807 	LOG_FUNC
       
   808 
       
   809 	iFlags = 0;
       
   810 	iConstants = 0;
       
   811 	iNamePresent = EFalse;
       
   812 	}
       
   813 
       
   814 /**
       
   815 @internalComponent
       
   816 */
       
   817 CObex::TSetPathInfo::TSetPathInfo(const TObexSetPathData& aData)
       
   818 	: iFlags(aData.iFlags), iConstants(aData.iConstants), iNamePresent(EFalse)
       
   819 	{
       
   820 	}
       
   821 
       
   822 /**
       
   823 Returns true if the flags are set so that the receiver will backup a level before applying the path name
       
   824 
       
   825 @return ETrue if the flags are set so that the receiver will backup a level before applying the path name othewise EFalse.
       
   826 
       
   827 @publishedAll
       
   828 @released
       
   829 */
       
   830 EXPORT_C TBool CObex::TSetPathInfo::Parent() const 
       
   831 	{
       
   832 	LOG_LINE
       
   833 	LOG_FUNC
       
   834 
       
   835 	return(iFlags & KObexSetPathParent);
       
   836 	}
       
   837 
       
   838 // CObex
       
   839 /**
       
   840 Returns ETrue if this CObex is connected at an OBEX level, merely having
       
   841 a transport connected does not satisfy this condition. I.e. the two devices
       
   842 must have completed the OBEX connection request/response . All other states
       
   843 return EFalse. This will be unreliable if either the server blindly 
       
   844 returns the client’s who header (always reporting ETrue), or if neither
       
   845 supply "who" headers (always reporting EFalse).
       
   846 
       
   847 @return ETrue if this CObex is connected at an OBEX level.  EFalse otherwise.
       
   848 @publishedAll
       
   849 @released
       
   850 */
       
   851 EXPORT_C TBool CObex::IsConnected() const 
       
   852 	{
       
   853 	LOG_LINE
       
   854 	LOG_FUNC
       
   855 
       
   856 	return(GetConnectState() == EConnObex);
       
   857 	}
       
   858 
       
   859 /**	
       
   860 @return ETrue if the "who" header specified in the server’s connect response 
       
   861 		matched that of the client’s connect request, and both had a length greater 
       
   862 		than 0 (i.e. both specified a "who" field). Undefined if IsConnected() == EFalse. 
       
   863 
       
   864 @publishedAll
       
   865 @released
       
   866 */
       
   867 EXPORT_C TBool CObex::IsStrictPeer() const 
       
   868 	{
       
   869 	LOG_LINE
       
   870 	LOG_FUNC
       
   871 
       
   872 	return((iLocalInfo.iWho.Length()>0) && (iLocalInfo.iWho==iRemoteInfo.iWho));
       
   873 	}
       
   874 
       
   875 /**
       
   876 Use this member to gain access to (and alter, if necessary) the 
       
   877 CObex::TConnectInfo structure which will be sent to the OBEX peer as part 
       
   878 of the connection process. Only alter the contents of this having read and 
       
   879 understood the purpose of the fields, as defined in the OBEX spec. Altering 
       
   880 this structure after a connection has been made will have no effect on the
       
   881 current session, but will be used for future connection attempts.
       
   882 
       
   883 @return The connect info which will be sent to the OBEX peer.
       
   884 @publishedAll
       
   885 @released
       
   886 */
       
   887 EXPORT_C const TObexConnectInfo& CObex::LocalInfo() const 
       
   888 	{
       
   889 	LOG_LINE
       
   890 	LOG_FUNC
       
   891 
       
   892 	return(iLocalInfo);
       
   893 	}
       
   894 
       
   895 /**
       
   896 Use this member to read the details of the remote machine’s connection 
       
   897 information, as specified by it in during OBEX connection. This data can 
       
   898 not be altered, as this serves no purpose.
       
   899 The content of this structure is undefined when @see IsConnected () ==
       
   900 EFalse. 
       
   901 
       
   902 @return The connect info from the remote machine.
       
   903 @publishedAll
       
   904 @released
       
   905 */
       
   906 EXPORT_C const TObexConnectInfo& CObex::RemoteInfo() const 
       
   907 	{
       
   908 	LOG_LINE
       
   909 	LOG_FUNC
       
   910 
       
   911 	return(iRemoteInfo);
       
   912 	}
       
   913 
       
   914 /**
       
   915 This function is in the protected scope of CObex and so is not externally usable
       
   916 @publishedAll
       
   917 @released
       
   918 */
       
   919 EXPORT_C CObex::TConnectState CObex::ConnectState() const 
       
   920 	{
       
   921 	LOG_LINE
       
   922 	LOG_FUNC
       
   923 
       
   924 	// This function is exported but protected, making it not much use
       
   925 	// Making it public, and exposing more information about the authentication
       
   926 	// state machine is undesirable, but a public function is required for other
       
   927 	// classes in the DLL. Thus another public, unexported function has been defined
       
   928 	// on to which this function chains.
       
   929 	return GetConnectState();
       
   930 	};
       
   931 
       
   932 /**
       
   933 Get the current state of the authentication state machine
       
   934 @internalComponent
       
   935 */
       
   936 CObex::TConnectState CObex::GetConnectState() const 
       
   937 	{
       
   938 	LOG_LINE
       
   939 	LOG_FUNC
       
   940 
       
   941 	return iConnectState;
       
   942 	};
       
   943 	
       
   944 /**
       
   945 Must be called by an application that wishes to suppress the authentication or(not excusive) the realm of the authentication challenge 
       
   946 @param aSuppressedObexAuthElements enum TObexSuppressedAuthElements to indicate which header elements to surpress (if any)
       
   947 @panic KErrArgument if invalid value is passed in for enum
       
   948 @publishedAll
       
   949 @released
       
   950 */
       
   951 EXPORT_C void CObex::SuppressAuthenticationHeaderElements(TObexSuppressedAuthElements aSuppressedObexAuthElements)
       
   952 	{
       
   953 	LOG_LINE
       
   954 	LOG_FUNC
       
   955 		
       
   956 	// If the value passed in is not a valid bitmask then panic
       
   957 	_LIT(panicText, "Invalid bitmask passed to CObex::SuppressAuthenticationHeaderElements");	
       
   958 	__ASSERT_ALWAYS((!(aSuppressedObexAuthElements > EObexSuppressAllAuthElements)), User::Panic(panicText, KErrArgument));
       
   959 		
       
   960 	iSuppressedObexAuthElements = aSuppressedObexAuthElements;
       
   961 	
       
   962 	};