bluetoothcommsprofiles/btpan/bnep/RBnepFrame.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     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 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19 */
       
    20 
       
    21 #include <bluetooth/logger.h>
       
    22 #include <e32std.h>
       
    23 #include <bttypes.h>
       
    24 #include <es_mbuf.h>
       
    25 
       
    26 #include "RBnepFrame.h"
       
    27 #include "bneputils.h"
       
    28 
       
    29 #ifdef __FLOG_ACTIVE
       
    30 _LIT8(KLogComponent, LOG_COMPONENT_PAN_BNEP);
       
    31 #endif
       
    32 
       
    33 const TUint8  KEBit = 0x80;
       
    34 const TUint16 KQTag = 0x8100;
       
    35 
       
    36 // 'minTypeValue' from section 4.2.7.1 of the 802.3-2002 specification
       
    37 // Subtract one, as the constant in the spec is for the first non-length value.
       
    38 const TUint16 K802_3MaxLength = 1536 - 1;
       
    39 
       
    40 void doResetControl(TAny* aControl)
       
    41     {
       
    42     /**
       
    43        Reset and destroy an RBnepControl object.
       
    44     */
       
    45     LOG_STATIC_FUNC
       
    46     RBnepControl* control = static_cast<RBnepControl*>(aControl);
       
    47     control->Free();
       
    48     delete control;
       
    49     }
       
    50 
       
    51 RBnepFrame::RBnepFrame()
       
    52         : iCommandQueue(_FOFF(RBnepControl, iLink))
       
    53     {
       
    54     /**
       
    55        Construct and initialise (reset) a BNEP frame.
       
    56        @internalComponent
       
    57     */
       
    58     LOG_FUNC
       
    59     Reset(); 
       
    60     }
       
    61 
       
    62 void RBnepFrame::BuildBnepControlFrameL (RMBufChain& aChain)
       
    63     {
       
    64     /**
       
    65        Build a BNEP control frame from the encapsulated data.
       
    66        @param aChain The target to build the frame into.
       
    67        @internalComponent
       
    68     */
       
    69     LOG_FUNC
       
    70     TUint8 frameType = EBnepControl;
       
    71     // There have to be items in the command queue 
       
    72     if(iCommandQueue.IsEmpty())
       
    73         {
       
    74         User::Leave(KErrUnderflow);
       
    75         }
       
    76     else
       
    77         {
       
    78         // If the last item is also the first one, there must be
       
    79         // one and only one item in the queue.
       
    80         // If there is more than one, then the ebit must be set.
       
    81         // Note: there is no checking done here that the queue items are
       
    82         // small enough to fit into an extension header.
       
    83         TUint8 ebit = static_cast<TUint8>(((iCommandQueue.IsLast(iCommandQueue.First())) ? 0 : KEBit));
       
    84         frameType |= ebit;
       
    85 
       
    86         RBnepControl* buffer = iCommandQueue.First();
       
    87         buffer->CopyL(aChain);
       
    88         iCommandQueue.Remove(*buffer);
       
    89         buffer->Free();
       
    90         delete buffer;
       
    91 
       
    92         aChain.PrependL(sizeof(TUint8));
       
    93         TPckgBuf<TUint8> pkgFrameType(frameType);
       
    94         aChain.CopyIn(pkgFrameType,RBnepControl::KControlTypeOffset);
       
    95         if(ebit) // We have at least one extension
       
    96             {
       
    97             TSglQueIter<RBnepControl> iter(iCommandQueue);
       
    98             iter.SetToFirst();
       
    99             RBnepControl* element;
       
   100             while ((element = iter++), element)
       
   101                 {
       
   102                 TPckgBuf<TInt8> aLength(static_cast<TInt8>(element->Length()));
       
   103                 element->PrependL(sizeof(TInt8));
       
   104                 element->CopyIn(aLength);
       
   105 
       
   106                 element->PrependL(sizeof(TUint8));
       
   107                 if(iCommandQueue.IsLast(element))
       
   108                     {
       
   109                     TPckgBuf<TUint8> extFrameType(static_cast<TUint8>(EBnepExtensionControl));
       
   110                     element->CopyIn(extFrameType);
       
   111                     }
       
   112                 else
       
   113                     {
       
   114                     // The extension bit must be set.
       
   115                     TPckgBuf<TUint8> extExtFrameType(static_cast<TUint8>(EBnepExtensionControl | KEBit));
       
   116                     element->CopyIn(extExtFrameType);
       
   117                     }
       
   118 
       
   119                 aChain.Append(*element);
       
   120                 }
       
   121             }
       
   122         LOG1(_L8("Final Chain length = %d"),aChain.Length());
       
   123         Reset();
       
   124         }
       
   125     }
       
   126 
       
   127 void RBnepFrame::BuildBnepDataFrameL(RMBufChain& aChain, 
       
   128                                      const TBTDevAddr& aLocalAddr, 
       
   129                                      const TBTDevAddr& aRemoteAddr,
       
   130                                      TBool aFilterEthernetPayload)
       
   131     {
       
   132     /**
       
   133        Build a BNEP data frame from the encapsulated data.
       
   134        The method deals with compressing off any unnecessary address data based on
       
   135        the parameters supplied.
       
   136        @param aChain The target to build the frame into.
       
   137        @param aLocalAddr The address of the bridge (local side of BNEP link).
       
   138        @param aRemoteAddr The address of the remote end of the BNEP link.
       
   139     */
       
   140     LOG_FUNC
       
   141     // If the command queue has items in it, we need to build extension headers.
       
   142     TUint8 frameType;
       
   143 
       
   144     TBool sendDest = (aRemoteAddr != iDestAddr);
       
   145     TBool sendSrc  = (aLocalAddr  != iSrcAddr);
       
   146     TInt headerLength;
       
   147     if (sendDest && sendSrc)
       
   148         {
       
   149         frameType = EBnepGeneralEthernet;
       
   150         headerLength = KGeneralEthernetHeaderLength;
       
   151         LOG(_L8("frameType = EBnepGeneralEthernet;"));
       
   152         LOG1(_L8("headerLength = %d"),headerLength);
       
   153         }
       
   154     else 
       
   155         {
       
   156         if (sendSrc)
       
   157             {
       
   158             frameType = EBnepCompressedEthernetSourceOnly;
       
   159             headerLength = KCompressedEthernetSourceOnlyHeaderLength;
       
   160             LOG(_L8("frameType = EBnepCompressedEthernetSourceOnly;"));
       
   161             LOG1(_L8("headerLength = %d"),headerLength);
       
   162             }
       
   163         else 
       
   164             {
       
   165             if (sendDest)
       
   166                 {
       
   167                 frameType = EBnepCompressedEthernetDestOnly;
       
   168                 headerLength = KCompressedEthernetDestOnlyHeaderLength;
       
   169                 LOG(_L8("frameType = EBnepCompressedEthernetDestOnly;"));
       
   170                 LOG1(_L8("headerLength = %d"),headerLength);
       
   171                 }
       
   172             else
       
   173                 {
       
   174                 frameType = EBnepCompressedEthernet;
       
   175                 headerLength = KCompressedEthernetHeaderLength;
       
   176                 LOG(_L8("frameType = EBnepCompressedEthernet"));
       
   177                 LOG1(_L8("headerLength = %d"),headerLength);
       
   178                 }
       
   179             }
       
   180         }
       
   181     aChain.AllocL(headerLength);
       
   182 
       
   183 	if(Includes(EExtensionHeaders))
       
   184 		{
       
   185 		frameType |= KEBit;
       
   186 		}
       
   187 		
       
   188     LOG1(_L8("Setting type to %02x"), frameType);
       
   189     TInt offset = 0;
       
   190     TPckgBuf<TUint8> pkgFrameType(frameType);
       
   191     aChain.CopyIn(pkgFrameType, offset++);
       
   192     if (sendDest)
       
   193         {
       
   194         LOG_BT(_L8("Inserting destination address %S"), iDestAddr);
       
   195         aChain.CopyIn(iDestAddr.Des(), offset);
       
   196         offset += KBTDevAddrSize;
       
   197         }
       
   198     if (sendSrc)
       
   199         {
       
   200         LOG_BT(_L8("Inserting source address %S"), iSrcAddr);
       
   201         aChain.CopyIn(iSrcAddr.Des(), offset);
       
   202         offset += KBTDevAddrSize;
       
   203         }
       
   204 
       
   205 	// Set-up the protocol ID to use for this packet.
       
   206 	TUint16 protocol = (aFilterEthernetPayload ? 0x0000 : iProtocol);
       
   207 	
       
   208     aChain.AppendL(KNetworkProtocolTypeFieldLength);
       
   209     TBuf8<KNetworkProtocolTypeFieldLength> protocolBuf;
       
   210     protocolBuf.SetMax();
       
   211 
       
   212     if (Includes(EHas1Q))
       
   213         {
       
   214         BigEndian::Put16(&protocolBuf[0], static_cast<TUint16>(KQTag));
       
   215         }     
       
   216     else
       
   217         {
       
   218         BigEndian::Put16(&protocolBuf[0], static_cast<TUint16>(protocol));
       
   219         }
       
   220     aChain.CopyIn(protocolBuf, offset);
       
   221     offset += KNetworkProtocolTypeFieldLength;
       
   222 
       
   223     // Cannot just append the ethernet payload mbufs, because if this is a 
       
   224     // multicast frame, this will corrupt it for others
       
   225     RMBufChain finalPacket;
       
   226     CleanupStack::PushL(finalPacket); // This will call Free() as its cleanup
       
   227     iFramePayload.CopyL(finalPacket);
       
   228 
       
   229 	// Filter out the ethernet payload if required.
       
   230 	if(aFilterEthernetPayload)
       
   231 		{
       
   232 		TInt payloadOffset = 0;
       
   233 		// Find the start of the ethernet payload.
       
   234 	    TBuf8<KExtensionHeaderHeaderBytes> buf;
       
   235 		buf.SetMax();
       
   236 
       
   237 		TUint8 ebit = ETrue;
       
   238 		while(ebit)
       
   239 			{
       
   240 			// The extension must be long enough for the header.
       
   241 	        if((payloadOffset + KExtensionHeaderHeaderBytes) > finalPacket.Length())
       
   242 	            {	
       
   243 	            User::Leave(KErrCorrupt);
       
   244 	            }
       
   245 
       
   246 			// Move the offset to the next extension header.
       
   247 	    	finalPacket.CopyOut(buf, payloadOffset);
       
   248 			ebit = buf[0] & KEBit;
       
   249 			payloadOffset += (buf[1] + KExtensionHeaderHeaderBytes);
       
   250 			}
       
   251 
       
   252 		// If the packet includes IEEE 802.1Q fields then these should remain.
       
   253 		// The network protocol field should be set to zero. 
       
   254 	    if(Includes(EHas1Q))
       
   255 	        {
       
   256 			if((payloadOffset + KIEEE802_1QTagFieldLength + KNetworkProtocolTypeFieldLength) > finalPacket.Length())
       
   257 				{
       
   258 				User::Leave(KErrCorrupt);
       
   259 				}
       
   260 
       
   261 			protocolBuf[0] = 0;
       
   262 			protocolBuf[1] = 0;
       
   263         	finalPacket.CopyIn(protocolBuf, payloadOffset + KIEEE802_1QTagFieldLength);
       
   264 			payloadOffset += (KIEEE802_1QTagFieldLength + KNetworkProtocolTypeFieldLength);
       
   265 	        }
       
   266 			
       
   267 		// The extension headers are finished.  Remove any remaining data.
       
   268 		finalPacket.TrimEnd(payloadOffset);
       
   269 		}
       
   270 			
       
   271 	// Append will take ownership of finalPacket
       
   272 	CleanupStack::Pop(); // finalPacket
       
   273 	// Add any payload onto the chain.
       
   274     aChain.Append(finalPacket);
       
   275     
       
   276     LOG1(_L8("RBnepFrame::BuildBnepDataFrameL final Chain length = %d"),aChain.Length());
       
   277     }
       
   278 
       
   279 void RBnepFrame::BuildBnepFrameL(RMBufChain& aChain, const TBTDevAddr& aLocalAddr, const TBTDevAddr& aRemoteAddr, TBool aFilterEthernetPayload)
       
   280     {
       
   281     /**
       
   282        Build a BNEP frame from encapsulated data.
       
   283        Processes the data carried by this frame to build a frame which can
       
   284        be sent to a remote PAN device.  This involves compressing off any
       
   285        addresses which are not required for this link and inserting any
       
   286        extension headers.
       
   287        @param aChain The target MBufChain to build into.
       
   288        @param aLocalAddr The address of the local PAN node.
       
   289        @param aRemoteAddr The address of the remote PAN node.
       
   290        @internalComponent
       
   291     */
       
   292     LOG_FUNC
       
   293     if (Includes(EControl))
       
   294         {
       
   295         BuildBnepControlFrameL(aChain);
       
   296         }
       
   297     else
       
   298         {
       
   299         BuildBnepDataFrameL(aChain, aLocalAddr, aRemoteAddr, aFilterEthernetPayload);
       
   300         }
       
   301     }
       
   302 
       
   303 void RBnepFrame::BuildEthernetFrameL(RMBufPacket& aChain)
       
   304     {
       
   305     /**
       
   306        Builds an ethernet frame from the BNEP frame.
       
   307        This function ignores away any control data present and simply inserts all
       
   308        addresses, protocol and 802.1Q data, as well as the data payload.
       
   309        
       
   310        This function always builds an Ethernet II format frame.  This should be
       
   311        accepted by the ethernet NIF, even if it is configured to send in LLC/SNAP
       
   312        format.  This behaviour is unlikely to change as it would be valid for a
       
   313        remote wired station to send a mixture of packet formats.  As the packet
       
   314        driver has no way of knowing which format has been configured, our options
       
   315        here are limited.
       
   316        
       
   317        @param aChain The MBufPacket to build the packet into.
       
   318        @internalComponent
       
   319     */
       
   320     LOG_FUNC
       
   321     // WARNING! Potential for a memory leak follows. 
       
   322     // Remember to free this RMBufChain before you exit.
       
   323     RMBufChain tempFrame;
       
   324 	CleanupStack::PushL(tempFrame);
       
   325 	
       
   326     LOG(_L8("Attempting to copy payload"));
       
   327 	// Check there is a valid payload 
       
   328     if(iFramePayload.IsEmpty())
       
   329         {
       
   330         LOG(_L8("No payload"));
       
   331         User::Leave(KErrUnderflow);
       
   332         }
       
   333 	iFramePayload.CopyL(tempFrame);
       
   334 
       
   335     // Any extensions need to be removed.
       
   336     if(Includes(EExtensionHeaders))
       
   337         {
       
   338 	    TBuf8<KExtensionHeaderHeaderBytes> buf;
       
   339 		buf.SetMax();
       
   340 
       
   341 		TUint8 ebit = ETrue;
       
   342 		while(ebit)
       
   343 			{
       
   344 			// The extension must be long enough for the header.
       
   345 	        if((KExtensionHeaderHeaderBytes) > tempFrame.Length())
       
   346 	            {	
       
   347 	            User::Leave(KErrCorrupt);
       
   348 	            }
       
   349 
       
   350 			// Move the offset to the next extension header.
       
   351 	    	tempFrame.CopyOut(buf, 0);
       
   352 			ebit = buf[0] & KEBit;
       
   353 			tempFrame.TrimStart(buf[1] + KExtensionHeaderHeaderBytes);
       
   354 			}
       
   355         }
       
   356 
       
   357 	// Check there is some data to send.
       
   358 	if(Includes(EHas1Q) && (tempFrame.Length() <= (KIEEE802_1QTagFieldLength + KNetworkProtocolTypeFieldLength)) ||
       
   359 	   tempFrame.IsEmpty())
       
   360 		{
       
   361 		LOG(_L8("No data to send pass up."));
       
   362 		User::Leave(KErrUnderflow);
       
   363 		}
       
   364 		
       
   365 	// Add protocol.
       
   366 	TUint16 protocol = (Includes(EHas1Q) ? KQTag : iProtocol);
       
   367 	
       
   368     TBuf8<KNetworkProtocolTypeFieldLength> protocolBuf;
       
   369     protocolBuf.SetMax();                                                                                                      
       
   370 	tempFrame.PrependL(KNetworkProtocolTypeFieldLength);
       
   371     BigEndian::Put16(&protocolBuf[0], static_cast<TUint16>(protocol));
       
   372     tempFrame.CopyIn(protocolBuf);
       
   373 
       
   374 	// Add addresses
       
   375 	tempFrame.PrependL(KBTDevAddrSize);
       
   376     LOG_BT(_L8("Inserting source address %S"),iSrcAddr);
       
   377     tempFrame.CopyIn(iSrcAddr.Des());
       
   378 
       
   379 	tempFrame.PrependL(KBTDevAddrSize);
       
   380     LOG_BT(_L8("Inserting destination address %S"),iDestAddr);
       
   381     tempFrame.CopyIn(iDestAddr.Des());
       
   382 
       
   383 	// This should be removed when defect DEF066321 is fixed.
       
   384 	TInt alignLength = Min(tempFrame.Length(), KMBufSmallSize);
       
   385 	if(tempFrame.Align(alignLength) != alignLength)
       
   386 		{
       
   387 		User::Leave(KErrCorrupt);
       
   388 		}
       
   389 
       
   390 	RMBufQ tempQueue;
       
   391 	tempQueue.Assign(tempFrame);
       
   392 	CleanupStack::Pop();		// Remove tempFrame from the cleanup stack
       
   393 	CleanupStack::PushL(tempQueue);
       
   394 	
       
   395 	aChain.CreateL(tempQueue); 	
       
   396 	CleanupStack::PopAndDestroy();		// Remove tempQueue from the cleanup stack
       
   397 							// As RMBufQs provide support for normal cleanup stack 
       
   398 							// usage, this will cause the Q to be Free()ed.
       
   399 
       
   400 	// Create the flags field for the packet info header.
       
   401 	// Mark the packet as being from BNEP
       
   402 	TUint flags = KBnep;
       
   403 
       
   404 	// Check if this packet can be forward to DHCP / NAPT
       
   405 	if(iUplinkAccessAllowedForBnepLink)
       
   406 		{
       
   407 		flags |= KBnepForwardingAllowed;
       
   408 		}
       
   409 
       
   410 	aChain.Info()->iFlags = flags;
       
   411     aChain.Pack();
       
   412     }
       
   413 
       
   414 const TBTDevAddr& RBnepFrame::DestAddr () const
       
   415     {
       
   416     LOG_FUNC
       
   417     return iDestAddr; 
       
   418     }
       
   419 
       
   420 RBnepFrame::TDestAddrType RBnepFrame::DestinationType () const
       
   421     {
       
   422     /**
       
   423        Return the type of destination for the frame (local, multicast address,
       
   424        or a specified machine).
       
   425        @internalComponent
       
   426     */
       
   427     LOG_FUNC
       
   428     if (TBTDevAddr(0) == iDestAddr) 
       
   429         {
       
   430         return ELocal;
       
   431         }
       
   432     if (BnepUtils::IsMulticast(iDestAddr)) 
       
   433         {
       
   434         return EMulticast;
       
   435         }
       
   436     return ENormal; 
       
   437     }
       
   438 
       
   439 TBool RBnepFrame::Includes (TPacketContents aContent) const
       
   440     {
       
   441     /**
       
   442        Accessor function for contents of packet.
       
   443        @param aContent The type of content to check for.
       
   444        @internalComponent
       
   445     */
       
   446     LOG_FUNC
       
   447     return (iPacketContents & static_cast<TUint8>(aContent));
       
   448     }
       
   449 
       
   450 void RBnepFrame::InsertControl (RBnepControl* aCommand)
       
   451     {
       
   452     /**
       
   453        Inserts and takes ownership of a BNEP command.
       
   454        @param aCommand The command to insert into the frame.  The method takes
       
   455        ownership of the object, which should be heap based.
       
   456        @internalComponent
       
   457     */
       
   458     LOG_FUNC
       
   459     //iCommandQueue.AddLast(*aCommand);
       
   460     iCommandQueue.AddLast(*aCommand);
       
   461     SetContents(EControl); 
       
   462     }
       
   463 
       
   464 TBnepPacketType RBnepFrame::ParseBnepFrameL (RMBufChain& aInboundChain, const TBTDevAddr& aLocalAddr, const TBTDevAddr& aRemoteAddr)
       
   465     {
       
   466     /**
       
   467        Parse a supplied BNEP frame.
       
   468        Parses the provided BNEP frame, separating data and control messages and
       
   469        resolving any source and destination addresses.
       
   470        @param aInboundChain The frame received from the remote device
       
   471        @param aLocalAddr The address of the bridge (the local PAN node and possible
       
   472        destination of the packet)
       
   473        @param aRemoteAddr The address of the remote PAN node (the possible source
       
   474        of the packet)
       
   475        @internalComponent
       
   476     */
       
   477     LOG_FUNC
       
   478     if(aInboundChain.Length() < 1)
       
   479         {
       
   480         User::Leave(KErrUnderflow);
       
   481         }
       
   482     Reset();
       
   483     // Extract the packet type and the Extension bit.
       
   484     TBnepPacketType type = static_cast<TBnepPacketType>(aInboundChain.First()->Ptr()[0]);
       
   485     aInboundChain.TrimStart(sizeof(TUint8));
       
   486     // Test the extension bit
       
   487     TBool ebit = type & KEBit;
       
   488     // Discard the extension bit
       
   489     type = static_cast<TBnepPacketType>(type & (~KEBit));
       
   490     LOG1(_L8("Type 0x%02x"),type);
       
   491     LOG1(_L8("Ebit 0x%02x"),ebit);
       
   492     // Based on the packet type, determine whether to extract addresses
       
   493     TBool dest = EFalse;
       
   494     TBool src = EFalse;
       
   495     switch (type)
       
   496         {
       
   497         case EBnepGeneralEthernet:
       
   498             // General ethernet -- both source and destination present
       
   499             LOG(_L8("Type = EBnepGeneralEthernet"));
       
   500             SetContents(EDataFrame);
       
   501             dest = ETrue;
       
   502             src = ETrue;
       
   503             break;
       
   504 
       
   505         case EBnepControl:
       
   506             // Control -- no addresses present (or any data)
       
   507             LOG(_L8("Type = EBnepControl"));
       
   508             break;
       
   509 
       
   510         case EBnepCompressedEthernetDestOnly:
       
   511             // Comressed destination only -- only destination present
       
   512             LOG(_L8("Type = EBnepCompressedEthernetDestOnly"));
       
   513             SetContents(EDataFrame);
       
   514             dest = ETrue;
       
   515             break;
       
   516 
       
   517         case EBnepCompressedEthernetSourceOnly:
       
   518             // Compressed source only -- only source present
       
   519             LOG(_L8("Type = EBnepCompressedEthernetSourceOnly"));
       
   520             SetContents(EDataFrame);
       
   521             src = ETrue;
       
   522             break;
       
   523 
       
   524         case EBnepCompressedEthernet:
       
   525             // Compressed -- no addresses present
       
   526             LOG(_L8("Type = EBnepCompressedEthernet"));
       
   527             SetContents(EDataFrame);
       
   528             break;
       
   529 
       
   530         default:
       
   531             // Unknown packet type
       
   532             LOG(_L8("RBnepFrame[%x]: Type = Unknown"));
       
   533             User::Leave(KErrCorrupt);   
       
   534             break;
       
   535         }
       
   536 
       
   537     if (iPacketContents & EDataFrame) // Data present
       
   538         {
       
   539         if (dest)
       
   540             {
       
   541             TrimBTAddrL(aInboundChain, iDestAddr);	// Address in packet, extract
       
   542             LOG_BT(_L8("Extracted destination address %S"), iDestAddr);
       
   543             }
       
   544         else
       
   545             {
       
   546             iDestAddr = aLocalAddr;					// No address in packet, assume.
       
   547             LOG_BT(_L8("Defaulting destination to %S"), iDestAddr);
       
   548             }
       
   549         if (src)
       
   550             {
       
   551             TrimBTAddrL(aInboundChain, iSrcAddr);	// Address in packet, extract
       
   552             LOG_BT(_L8("Extracted source address %S"), iSrcAddr);
       
   553             }
       
   554         else
       
   555             {
       
   556             iSrcAddr = aRemoteAddr;					// No address in packet, assume.
       
   557             LOG_BT(_L8("Defaulting source address to %S"), iSrcAddr);
       
   558             }
       
   559         // Extract protocol
       
   560         TrimUint16L(aInboundChain, iProtocol);
       
   561 		if(iProtocol == KQTag)
       
   562 			{
       
   563 			SetContents(EHas1Q);
       
   564 			}
       
   565         LOG1(_L8("Extracted protocol %04x"), iProtocol);
       
   566         }
       
   567 
       
   568     ParseL(aInboundChain, type, ebit);
       
   569 
       
   570     if(EBnepControl != type)
       
   571         {
       
   572         // Extract data from the incoming frame that might (depending on any filters
       
   573         // need to be forwarded.
       
   574         iFramePayload.Assign(aInboundChain);
       
   575         LOG1(_L8("Extracted %d bytes of payload data"), iFramePayload.Length());
       
   576         }
       
   577     return type;
       
   578     }
       
   579 
       
   580 void RBnepFrame::ParseEthernetFrameL (RMBufChain& aFrame)
       
   581     {
       
   582     /**
       
   583        Parse an ethernet frame.
       
   584        @param aFrame The ethernet frame received from the higher
       
   585        networking layers.
       
   586        @internalComponent
       
   587     */
       
   588     LOG_FUNC
       
   589     Reset();
       
   590     // Extract the source and destination addresses.
       
   591     TrimBTAddrL(aFrame, iDestAddr);
       
   592     TrimBTAddrL(aFrame, iSrcAddr);
       
   593     LOG_BT(_L8("Extracted destination address %S"),iDestAddr);
       
   594     LOG_BT(_L8("Extracted source address %S"),iSrcAddr);
       
   595     
       
   596     // Pull out protocol, and, if present, 802.1Q data
       
   597     TrimUint16L(aFrame, iProtocol);
       
   598     LOG1(_L8("Extracted protocol (or type) %04x"), iProtocol);
       
   599     
       
   600     if (iProtocol <= K802_3MaxLength)
       
   601     	{
       
   602     	// 'Protocol' field is overloaded.  In 802.3, it actually contains the payload
       
   603     	// length.  We can therefore use this field to detect an 802.3 format packet,
       
   604     	// and behave accordingly.  Payload type numbers are guaranteed to be greater
       
   605     	// than available packet lengths (by design, in order to allow this distinction.)
       
   606     	
       
   607     	// 802.3 requires additional headers to carry the required data.  Most of this
       
   608     	// is essentially constant, especially as we only ever parse ethernet frames
       
   609     	// provided by the Symbian NIF.
       
   610     	//
       
   611     	// Expected values:
       
   612     	//  LLC
       
   613     	//  DSAP:    aa
       
   614     	//  SSAP:    aa
       
   615     	//  Control: 03
       
   616     	//
       
   617     	//  SNAP
       
   618     	//  OUI:     00 00 00
       
   619     	//  Type:    varies
       
   620     	//
       
   621     	// We can therefore trim the next six bytes of the supplied data, then extract
       
   622     	// the protocol type.  If we were really keen, we could try to verify that the
       
   623     	// trimmed bytes are as expected.
       
   624     	
       
   625     	aFrame.TrimStart(6);
       
   626 		TrimUint16L(aFrame, iProtocol);
       
   627 		}
       
   628     
       
   629     if (KQTag == iProtocol)
       
   630         {
       
   631         SetContents(EHas1Q);
       
   632 
       
   633 	    TBuf8<KNetworkProtocolTypeFieldLength> protocolBuf;
       
   634 		protocolBuf.SetMax();
       
   635 		if(aFrame.Length() < KIEEE802_1QTagFieldLength + KNetworkProtocolTypeFieldLength)
       
   636 			{
       
   637 			aFrame.Free();
       
   638 			User::Leave(KErrCorrupt);
       
   639 			}
       
   640     	aFrame.CopyOut(protocolBuf, KIEEE802_1QTagFieldLength);
       
   641 		iProtocol = static_cast<TUint16>((protocolBuf[0] << 8) + protocolBuf[1]);
       
   642 
       
   643         LOG1(_L8("Found 802.1Q header, real protocol %04x"), iProtocol);
       
   644         }
       
   645     
       
   646     // Extract frame payload
       
   647     SetContents(EDataFrame);
       
   648     iFramePayload.Assign(aFrame);
       
   649     LOG1(_L8("Extracted %d bytes of payload data"), iFramePayload.Length());
       
   650     aFrame.Free();
       
   651     }
       
   652 
       
   653 void RBnepFrame::Reset ()
       
   654     {
       
   655     /**
       
   656        Reset a BNEP frame.
       
   657        The object can be allowed to go out of scope only after a call to this
       
   658        function.  Note also that some data fields will still contain data after
       
   659        this function returns, so the object should either be destroyed or
       
   660        re-initialised based on another data frame.
       
   661        @internalComponent
       
   662     */
       
   663     LOG_FUNC
       
   664     // Reset contents flag
       
   665     iPacketContents = 0;
       
   666     // Free any payload data
       
   667     iFramePayload.Free();
       
   668     // Remove, free and delete all commands
       
   669     while(!iCommandQueue.IsEmpty())
       
   670         {    
       
   671         RBnepControl* element = iCommandQueue.First();
       
   672         iCommandQueue.Remove(*element);
       
   673         element->Free();
       
   674         delete element;
       
   675         }
       
   676 
       
   677 	// By default remote devices are not permitted to use the uplink
       
   678 	iUplinkAccessAllowedForBnepLink = EFalse;
       
   679     }
       
   680 
       
   681 const TBTDevAddr& RBnepFrame::SrcAddr () const
       
   682     {
       
   683     LOG_FUNC
       
   684     return iSrcAddr; 
       
   685     }
       
   686 
       
   687 void RBnepFrame::TrimBTAddrL (RMBufChain& aChain, TBTDevAddr& aAddr)
       
   688     {
       
   689     /**
       
   690        Populate a Bluetooth address from the front of an MBufChain.
       
   691        Extract the bluetooth address and remove it from the MBufChain.
       
   692        @param aChain The MBufChain starting with a Bluetooth address.
       
   693        @param aAddr The Bluetooth address to populate.
       
   694        @internalComponent
       
   695     */
       
   696     LOG_FUNC
       
   697     TPtr8 ptr = aAddr.Des();
       
   698     if (aChain.Length() < KBTDevAddrSize)
       
   699         {
       
   700         User::Leave(KErrCorrupt);
       
   701         }
       
   702     aChain.CopyOut(ptr);
       
   703     aChain.TrimStart(KBTDevAddrSize);
       
   704     }
       
   705 
       
   706 void RBnepFrame::TrimUint16L (RMBufChain& aChain, TUint16& aInt)
       
   707     {
       
   708     /**
       
   709        Read a TUint16 from an MBufChain.
       
   710        Reads and removes a TUint16 from the front of an MBufChain.
       
   711        @param aChain The MBufChain starting with a TUint16.
       
   712        @param aInt The TUint16 to populate.
       
   713        @internalComponent
       
   714     */
       
   715     LOG_FUNC
       
   716     if (aChain.Length() < static_cast<TInt>(sizeof(TUint16)))
       
   717         {
       
   718         User::Leave(KErrCorrupt);
       
   719         }
       
   720     TBuf8<sizeof(TUint16)> buf;
       
   721 	buf.SetLength(sizeof(TUint16));
       
   722 	aChain.CopyOut(buf);
       
   723     // To handle endian issues, copy int out bytewise
       
   724     aInt = BigEndian::Get16(buf.Ptr());
       
   725     aChain.TrimStart(sizeof(TUint16));
       
   726     }
       
   727 
       
   728 void RBnepFrame::ParseL(RMBufChain& aInboundChain, TBnepPacketType aType, TBool aExt)
       
   729     {
       
   730     /**
       
   731        This method does all the donkey work sorting out the controls and possible extensions on the packet.
       
   732        @param aInboundChain the rest of the packet
       
   733        @param aType the calling method needs to know the packet type when it calls this method
       
   734        @param aExt the calling method needs to know about the existence of extensions when it calls this method.
       
   735        @internalComponent
       
   736     */
       
   737     LOG_FUNC
       
   738     TInt offset = 0;
       
   739     TInt length =0; 	
       
   740 
       
   741     if(aType == EBnepControl)
       
   742         {
       
   743         LOG(_L8("A control"));
       
   744         if(aExt)
       
   745             {
       
   746             LOG(_L8("With extensions"));
       
   747             // This is a control packet with extensions.
       
   748             // We're going to have to apply a little bit of intelligence to this one,
       
   749             // because the spec is a bit unhelpful here (like - how long is the 
       
   750             // control part of the message supposed to be BEFORE we start 
       
   751             // pulling out the extension headers?)
       
   752             TUint8 uuidSize;
       
   753             TUint16 maListLength;
       
   754             TUint16 ntListLength;
       
   755             TBnepControlType type = static_cast<TBnepControlType>(aInboundChain.First()->Ptr()[0]);
       
   756             LOG1(_L8("TBnepControlType = 0x%02x"), type);	
       
   757             switch (type)
       
   758                 {
       
   759                 case EBnepControlCommandNotUnderstood:
       
   760                     LOG(_L8("EBnepControlCommandNotUnderstood"));
       
   761                     length = 2*sizeof(TUint8); // Control type byte + 1 byte response message
       
   762                     ExtractControlL(aInboundChain, length);
       
   763                     break;
       
   764 
       
   765                 case EBnepSetupConnectionRequestMessage: 
       
   766                     LOG(_L8("EBnepSetupConnectionRequestMessage"));
       
   767                     uuidSize = aInboundChain.First()->Ptr()[1];
       
   768                     length = 2*sizeof(TUint8) + 2*uuidSize; // Control type byte + UUIDsize byte + 2 UUIDs
       
   769                     // Note, this NOT where we check that UUIDSize is within bounds. That is done later.
       
   770                     ExtractControlL(aInboundChain, length);
       
   771                     break;
       
   772 
       
   773                 case EBnepSetupConnectionResponseMessage:
       
   774                     LOG(_L8("EBnepSetupConnectionResponseMessage"));
       
   775                     length = sizeof(TUint8) + sizeof(TUint16); // Control type byte + 2 byte response message
       
   776                     ExtractControlL(aInboundChain, length);
       
   777                     break;
       
   778 
       
   779                 case EBnepFilterNetTypeSetMsg:
       
   780                     LOG(_L8("EBnepFilterNetTypeSetMsg"));
       
   781                     ntListLength = BigEndian::Get16(aInboundChain.First()->Ptr() + 1);
       
   782                     length = sizeof(TUint8) + sizeof(TUint16) + ntListLength; // control type byte + length word + list of filters
       
   783                     ExtractControlL(aInboundChain, length);
       
   784                     break;
       
   785 
       
   786                 case EBnepFilterNetTypeResponse:
       
   787                     LOG(_L8("EBnepFilterNetTypeResponse"));
       
   788                     length = sizeof(TUint8) + sizeof(TUint16); // Control type byte + 2 byte response message
       
   789                     ExtractControlL(aInboundChain, length);
       
   790                     break;
       
   791 
       
   792                 case EBnepFilterMultiAddrSetMsg:
       
   793                     LOG(_L8("EBnepFilterMultiAddrSetMsg"));
       
   794                     maListLength = BigEndian::Get16(aInboundChain.First()->Ptr() + 1);
       
   795                     length = sizeof(TUint8) + sizeof(TUint16) + maListLength; // control type byte + length word + list of filters
       
   796                     ExtractControlL(aInboundChain, length);
       
   797                     break;
       
   798 
       
   799                 case EBnepFilterMultiAddrResponseMsg:
       
   800                     LOG(_L8("EBnepFilterMultiAddrResponseMsg"));
       
   801                     length = sizeof(TUint8) + sizeof(TUint16); // Control type byte + 2 byte response message
       
   802                     ExtractControlL(aInboundChain, length);
       
   803                     break;
       
   804 
       
   805                 default: // We don't really want to execute this bit of code ever.
       
   806                     LOG(_L8("Unknown control type - leaving!"));
       
   807                     User::Leave(KErrCorrupt);
       
   808                 }
       
   809             }
       
   810         else
       
   811             {
       
   812             // This one's quite simple because we know that the packet contains a 
       
   813             // control and only a control. So the format is pretty simple to stash 
       
   814             // as a command for future processing.
       
   815             LOG(_L8("Without extensions"));
       
   816             length = aInboundChain.Length();
       
   817             ExtractControlL(aInboundChain, length);
       
   818             }
       
   819         }
       
   820 
       
   821     if(aExt)
       
   822         {
       
   823 		// Extension headers are present.
       
   824         LOG(_L8("Extensions embedded"));
       
   825 
       
   826         offset = ParseExtensionL(aInboundChain);
       
   827         }
       
   828         
       
   829 	// If the packet includes IEEE 802.1Q info then the real protocol field must be
       
   830 	// extracted and stored for filtering purposes.
       
   831     if(Includes(EHas1Q))
       
   832     	{
       
   833 		offset+=KIEEE802_1QTagFieldLength;
       
   834     	// Store the extra protcol information.
       
   835 		if((offset + KNetworkProtocolTypeFieldLength) > aInboundChain.Length())
       
   836 			{
       
   837 			User::Leave(KErrCorrupt);
       
   838 			}
       
   839 			
       
   840 	    TBuf8<KNetworkProtocolTypeFieldLength> protocolBuf;
       
   841 		protocolBuf.SetMax();
       
   842 
       
   843     	aInboundChain.CopyOut(protocolBuf, offset);
       
   844     	
       
   845 		iProtocol = static_cast<TUint16>((protocolBuf[0] << 8) + protocolBuf[1]);
       
   846     	}	
       
   847     }
       
   848 
       
   849 TInt RBnepFrame::ParseExtensionL(RMBufChain& aInboundChain)
       
   850     {
       
   851     /**
       
   852        Helper method to extract control extension headers from a packet.
       
   853        Non-Control extension headers will remain in the inbound chain
       
   854        @param aInboundChain the rest of the packet
       
   855        @internalComponent
       
   856     */
       
   857     LOG_FUNC
       
   858     TUint16 offset = 0;
       
   859     TUint16 lastExtensionHeaderOffset = 0;
       
   860     TBool ebit = ETrue;
       
   861 	TBool removeExtensions = EFalse;
       
   862 	
       
   863     TBuf8<KExtensionHeaderHeaderBytes> buf;
       
   864 	buf.SetMax();
       
   865     
       
   866     // Used to verify that the extensions are in assending order.
       
   867     TBnepExtensionType lastExtensionType = EBnepExtensionControl;
       
   868     
       
   869     while(ebit)
       
   870         {
       
   871         // Extension headers are 2 bytes long.
       
   872         if((offset + KExtensionHeaderHeaderBytes) > aInboundChain.Length())
       
   873             {	
       
   874             User::Leave(KErrCorrupt);
       
   875             }
       
   876 
       
   877     	aInboundChain.CopyOut(buf, offset);
       
   878         
       
   879         // Extract the extension header type and e-bit.
       
   880         TBnepExtensionType type = static_cast<TBnepExtensionType>(buf[0]);
       
   881 		ebit = type & KEBit;
       
   882         type = static_cast<TBnepExtensionType>(type & (~KEBit));
       
   883 
       
   884 		if(type < lastExtensionType)
       
   885 			{
       
   886 			// Extensions are not in assending order.  Remove all subsequent
       
   887 			// extensions from the packet.
       
   888 			if(!removeExtensions)
       
   889 				{
       
   890 				// The previous extension header bit must be set to zero
       
   891 				removeExtensions = ETrue;
       
   892 				TBuf8<KSizeOfBnepExtensionType> exTypeBuf;
       
   893 				exTypeBuf.SetMax();
       
   894 				aInboundChain.CopyOut(exTypeBuf, lastExtensionHeaderOffset);
       
   895 				exTypeBuf[0] &= ~KEBit;
       
   896 				aInboundChain.CopyIn(exTypeBuf, lastExtensionHeaderOffset);
       
   897 				}
       
   898 			}
       
   899 		
       
   900 		lastExtensionType = type;	
       
   901 
       
   902         // Extract the length of this extension header
       
   903         TUint8 length = buf[1];
       
   904 
       
   905         LOG4(_L8("Found extension header, type %02x, ebit %02x, length %d, offset %d"),
       
   906     			      type, ebit, length, offset);
       
   907 
       
   908         if((length + KExtensionHeaderHeaderBytes) > (aInboundChain.Length() - offset))
       
   909             {	
       
   910             User::Leave(KErrCorrupt);
       
   911             }
       
   912 
       
   913 		if(type == EBnepExtensionControl && !removeExtensions)
       
   914 			{
       
   915 			// Remove the BNEP extension control header (i.e., [ebit]0x00, Length). 
       
   916 			aInboundChain.TrimStart(KExtensionHeaderHeaderBytes);
       
   917 			
       
   918 			// Control extention headers need to be extracted.
       
   919 			ExtractControlL(aInboundChain, length);
       
   920 			}
       
   921 		else
       
   922 			{
       
   923 			if(!removeExtensions)
       
   924 				{
       
   925 				// If the extension has not been removed adjust the offset.
       
   926 				lastExtensionHeaderOffset = offset;
       
   927 				offset += (length + KExtensionHeaderHeaderBytes);
       
   928 				
       
   929 				// Note that an extension header is present in the payload.
       
   930 				SetContents(EExtensionHeaders);
       
   931 				}
       
   932 			else
       
   933 				{
       
   934 				// Remove the extension.
       
   935 				RMBufChain tempBuf;
       
   936 				// Split the buffer so that aInboundChain includes everything before
       
   937 				// the extension to be removed and tempBuf includes everything after
       
   938 				// including the extension to be removed.
       
   939 				aInboundChain.SplitL(offset, tempBuf);
       
   940 				
       
   941 				// Remove the extension from tempBuf.
       
   942 				tempBuf.TrimStart(length + KExtensionHeaderHeaderBytes);
       
   943 				
       
   944 				// Re-join the two buffers
       
   945 				aInboundChain.Append(tempBuf);
       
   946 				}
       
   947 			}
       
   948         }
       
   949 
       
   950 	return offset;
       
   951     }
       
   952 
       
   953 void RBnepFrame::ExtractControlL(RMBufChain& aInboundChain, TInt aLength)
       
   954     {
       
   955     /**
       
   956        Helper method to extract the control portion of a packet.
       
   957        @param aInboundChain the rest of the packet.
       
   958        @param aLength the size of the control portion to be extracted.
       
   959        @internalComponent
       
   960     */
       
   961     LOG_FUNC
       
   962     LOG1(_L8("Extraction length = %d bytes"),aLength);
       
   963     if(0 == aLength)	
       
   964         {
       
   965         LOG(_L8("Zero length buffer - leaving!"));
       
   966         User::Leave(KErrArgument);
       
   967         }
       
   968     if(aLength > aInboundChain.Length())
       
   969         {
       
   970         LOG(_L8("Corrupted buffer - leaving!"));
       
   971         User::Leave(KErrCorrupt);
       
   972         }
       
   973     RBnepControl* command = new(ELeave) RBnepControl();
       
   974     CleanupStack::PushL(TCleanupItem(doResetControl, command));
       
   975     // MBuf SplitL is a bit awkward here, as it splits off the end of the chain
       
   976     // into the supplied parameter.  So move the MBuf data to all be with the
       
   977     // command MBufChain, then split back into the original MBufChain.
       
   978     command->Assign(aInboundChain);
       
   979     command->SplitL(aLength,aInboundChain);
       
   980     CleanupStack::Pop(command);
       
   981     LOG1(_L8("Storing new command 0x%08x in queue"),command);
       
   982     iCommandQueue.AddLast(*command);
       
   983     SetContents(EControl);
       
   984     }
       
   985 
       
   986 void RBnepFrame::ExecuteControl (MLinkManager& aController)
       
   987     {
       
   988     /**
       
   989        Helper method that pushes the controls in the queue up to the controller for handling 
       
   990        and response.
       
   991        @param aController The controller object to pass the control messages to.
       
   992        @internalComponent
       
   993     */
       
   994     LOG_FUNC
       
   995     while(!iCommandQueue.IsEmpty() &&
       
   996           !aController.AwaitingResponse())
       
   997         {    
       
   998         RBnepControl* element = iCommandQueue.First();
       
   999         iCommandQueue.Remove(*element);
       
  1000         LOG(_L8("Passing command up to controller"));
       
  1001         // The controller will now own the control and will become responsible for its memory management
       
  1002         aController.Execute(element); 
       
  1003         }
       
  1004 
       
  1005     // If we reached the end, then show that the packet no longer contains control extensions.
       
  1006     if (iCommandQueue.IsEmpty())
       
  1007     	{
       
  1008     	iPacketContents &= ~EControl;
       
  1009     	}
       
  1010     }
       
  1011 
       
  1012     
       
  1013 TInt RBnepFrame::PayloadLength() const
       
  1014 	{
       
  1015 	return iFramePayload.Length();
       
  1016 	}
       
  1017 
       
  1018 void RBnepFrame::SetUplinkAccessAllowedForBnepLink(TBool aUplinkAccessAllowedForBnepLink)
       
  1019 	{
       
  1020 	iUplinkAccessAllowedForBnepLink = aUplinkAccessAllowedForBnepLink;
       
  1021 	}