bluetoothcommsprofiles/btpan/bnep/CBnepLink.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 #include <bluetooth/logger.h>
       
    21 #include "bt_sock.h"
       
    22 #include "CBnepLink.h"
       
    23 #include "CSocketReader.h"
       
    24 #include "CSocketWriter.h"
       
    25 #include "CMultiAddrFilterTable.h"
       
    26 #include "CNetTypeFilterTable.h"
       
    27 
       
    28 #ifdef __FLOG_ACTIVE
       
    29 _LIT8(KLogComponent, LOG_COMPONENT_PAN_BNEP);
       
    30 #endif
       
    31 
       
    32 // Class CBnepLink 
       
    33 
       
    34 /**
       
    35 Construct a link.
       
    36 @param aBridge The CBnepBridge that this link may eventually be attached to to.
       
    37 @param aSocket The socket handed up to the agent from L2CAP which this link will use.
       
    38 @param aParser The CBnepChannelController for this link.
       
    39 @internalComponent
       
    40 */
       
    41 CBnepLink::CBnepLink (MPanDeviceOwner& aBridge, RInternalSocket& aSocket, MLinkManager& aParser)
       
    42     : iLinkManager(aParser), iNegotiating(ETrue)
       
    43     {
       
    44     LOG_FUNC
       
    45     
       
    46     // Take ownership of the socket and acquire the remote end's BT address.                                                                                      	
       
    47     iSocket.Transfer(aSocket);
       
    48     TBTSockAddr btSockAddr;
       
    49     iSocket.RemoteName(btSockAddr);
       
    50     iAddr = btSockAddr.BTAddr();
       
    51     
       
    52     // We tell the link who it's owner is likely to be.
       
    53     // Note that the link is NOT yet attached, though.
       
    54     SetOwner(aBridge); 
       
    55     SetOwnerCountPtr(NULL);    
       
    56     }
       
    57 
       
    58 /**
       
    59 Remove from bridge, delete reader and writer.
       
    60 @internalComponent
       
    61 */
       
    62 CBnepLink::~CBnepLink()
       
    63     {
       
    64     LOG_FUNC
       
    65     
       
    66 #ifndef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
    67     // With 399 we null iOwner if the CBnepBridge is deleted before all the
       
    68     // links go down (see Invalidate())
       
    69     
       
    70     // If we're not actually attached, the bridge will ignore the request.
       
    71     __ASSERT_DEBUG(iOwner,BnepUtils::Panic(Bnep::ENullPointer));
       
    72 #endif
       
    73     if(iOwner)
       
    74         {
       
    75         iOwner->LinkGoingDown(*this);
       
    76         }
       
    77     
       
    78     delete iReader;
       
    79     delete iWriter;
       
    80 
       
    81 	TRequestStatus status;
       
    82 	iSocket.Shutdown(RSocket::ENormal, status);
       
    83 	User::WaitForRequest(status);
       
    84 	iSocket.Close();
       
    85 	
       
    86     delete iMultiAddrFilters;
       
    87     delete iNetTypeFilters;
       
    88     
       
    89     iOutgoing.Reset();
       
    90     iIncoming.Reset();
       
    91     }
       
    92 
       
    93 
       
    94 /**
       
    95 Create the reader and writer objects, and 
       
    96 attempt to attach this device to the bridge.
       
    97 @internalComponent
       
    98 */
       
    99 void CBnepLink::ConstructL ()
       
   100     {
       
   101     LOG_FUNC
       
   102     iReader = CSocketReader::NewL(iSocket, *this);
       
   103     iWriter = CSocketWriter::NewL(iSocket, *this);
       
   104     
       
   105     // If this leaves, we have an unattached link that will be deleted during cleanup. 
       
   106     // This is the scenario in which we don't want to attempt to notify the 
       
   107     // bridge of our demise.
       
   108     User::LeaveIfError(iOwner->AttachDevice(*this));
       
   109     
       
   110     // Start the reader running
       
   111     iReader->Read();
       
   112     }
       
   113 
       
   114 /**
       
   115 Create a BNEP link object.
       
   116 @param aBridge The CBnepBridge that this link may eventually be attached to to.
       
   117 @param aSocket The socket handed up to the agent from L2CAP which this link will use.
       
   118 @param aParser The CBnepChannelController for this link.
       
   119 @internalComponent
       
   120 */
       
   121 CBnepLink* CBnepLink::NewL (MPanDeviceOwner& aBridge, RInternalSocket& aSocket, MLinkManager& aParser)
       
   122     {
       
   123     LOG_STATIC_FUNC
       
   124     CBnepLink* self = new(ELeave) CBnepLink(aBridge, aSocket, aParser);
       
   125     CleanupStack::PushL(self);
       
   126     self->ConstructL();
       
   127     CleanupStack::Pop(self);
       
   128     return(self);
       
   129     }
       
   130 
       
   131 /**
       
   132 Call from the bridge to send a packet.
       
   133 @param aFrame The RBnepFrame from which a packet will be created.
       
   134 @internalComponent
       
   135 */
       
   136 void CBnepLink::Process (RBnepFrame& aFrame)
       
   137     {
       
   138     LOG_FUNC
       
   139     if(iNegotiating)
       
   140         {
       
   141         LOG(_L8("Dropping data frame from bridge during role negotiation"));
       
   142 		return;
       
   143         }
       
   144 
       
   145     TInt err = SendFrame(aFrame);
       
   146         
       
   147     if (err != KErrNone)
       
   148       	{
       
   149       	// Log error but don't send it to the bridge as the IP stack
       
   150        	// should not be flowed off if there is a problem with one link
       
   151         LOG1(_L8("Sending data frame returned error: %d"), err);    	
       
   152        	}
       
   153  	else
       
   154  		{
       
   155  		UpdateOwnerCount(0, aFrame.PayloadLength());
       
   156  		}
       
   157     
       
   158     }
       
   159 
       
   160 /**
       
   161 Call from a control processor to cache a control for 
       
   162 later output processing. This call transfers ownership of the 
       
   163 RBnepControl object down into the RBnepFrame on which it is queued.
       
   164 @param aCommand The control to be cached.
       
   165 @internalComponent
       
   166 */
       
   167 void CBnepLink::QueueOnOutput (RBnepControl* aCommand)
       
   168     {
       
   169     
       
   170     LOG_FUNC
       
   171     iOutgoing.InsertControl(aCommand);
       
   172     }
       
   173 
       
   174 /**
       
   175 This is called from within the RunL of the SocketReader 
       
   176 when new data has been presented to the incoming side of the link.
       
   177 @internalComponent
       
   178 */
       
   179 void CBnepLink::ReadComplete (RMBufChain& aChain)
       
   180     {
       
   181     LOG_FUNC
       
   182     iOutgoing.Reset();  // The output side is set to a known state
       
   183     // The input side of the link attempts to parse the 
       
   184     // input packet into something meaningful.          
       
   185     TRAPD(err, iIncoming.ParseBnepFrameL(aChain, LocalAddr(), iAddr));
       
   186     aChain.Free(); // we're finished with this now, regardless.
       
   187 
       
   188     if (!err)
       
   189         {
       
   190         Proceed(); // Start processing the contents of the input side of the link.
       
   191         }
       
   192     else
       
   193         {
       
   194         iIncoming.Reset(); // Discard the contents of the input side: they are unusuable.
       
   195         }
       
   196     }
       
   197 
       
   198 /**
       
   199 The remote device has disconnected.
       
   200 @internalComponent
       
   201 */
       
   202 void CBnepLink::RemoteDeviceDisconnect (TInt aError)
       
   203     {
       
   204     
       
   205     LOG_FUNC
       
   206     iReader->Cancel();
       
   207     iWriter->Cancel();
       
   208     iLinkManager.RemoteDeviceDisconnect(aError);
       
   209     }
       
   210 
       
   211 /**
       
   212 (Re)start data transfer
       
   213 @internalComponent
       
   214 */
       
   215 void CBnepLink::ResumeDataTransfer ()
       
   216     {
       
   217     LOG_FUNC
       
   218     iNegotiating = EFalse;
       
   219 	}
       
   220 
       
   221 /**
       
   222 Request to send a frame from either the bridge or the channel controller
       
   223 @param aFrame the frame to be sent
       
   224 @internalComponent
       
   225 */
       
   226 TInt CBnepLink::SendFrame (RBnepFrame& aFrame)
       
   227     {
       
   228     LOG_FUNC
       
   229 	TBool filterEthernetPayload = EFalse;
       
   230 	TInt rerr = KErrNone;
       
   231 	
       
   232     if(!aFrame.Includes(RBnepFrame::EControl)) // Don't filter controls
       
   233         {
       
   234         LOG(_L8("Not a control message"));
       
   235         if(iMultiAddrFilters) // If no Multicast Address filters have been set, pass this regardless
       
   236             {
       
   237             LOG(_L8("We have Multicast Address filters set"));
       
   238             if (RBnepFrame::EMulticast == aFrame.DestinationType()) // Is the destination a valid multicast address?
       
   239                 { 
       
   240                 LOG(_L8("We have a Multicast destination type"));   	
       
   241                 TBTDevAddr dest = aFrame.DestAddr();
       
   242                 if(iMultiAddrFilters->FilteredOut(dest)) // // Are we within a permissible range?
       
   243                     {
       
   244 					filterEthernetPayload = ETrue;
       
   245                     }
       
   246                 }
       
   247             }
       
   248 
       
   249         if(iNetTypeFilters) // If no Network Type Protocol filters have been set, pass this regardless.
       
   250             {
       
   251             LOG(_L8("We have Network Protocol Type filters set"));
       
   252             TUint16 protocol = aFrame.Protocol();
       
   253             LOG1(_L8("Frame protocol = %04x"),protocol);
       
   254             if(iNetTypeFilters->FilteredOut(protocol))// Are we within a permissible range?
       
   255                 {
       
   256 				filterEthernetPayload = ETrue;                
       
   257 				}
       
   258             }
       
   259         }
       
   260 
       
   261 	// Check there is something to send.
       
   262 	if(aFrame.Includes(RBnepFrame::EControl) ||
       
   263 	   (aFrame.Includes(RBnepFrame::EDataFrame) && (!filterEthernetPayload || aFrame.Includes(RBnepFrame::EExtensionHeaders))))
       
   264 	   	{
       
   265 		// there is something valid to send.
       
   266 	    RMBufChain chain; // Beware the potential memory leak.
       
   267 	    TRAP(rerr, aFrame.BuildBnepFrameL(chain, LocalAddr(), iAddr, filterEthernetPayload));
       
   268 	    if (!rerr)
       
   269 	        {
       
   270 	        iWriter->Write(chain); // SocketWriter will free the chain for us.
       
   271 	        }
       
   272 	    else
       
   273 	        {
       
   274 	        chain.Free(); // Otherwise we need to plug the potential leak.
       
   275 	        }
       
   276 	   	}
       
   277 	// ELSE: Nothing to send.  Return KErrNone.
       
   278 
       
   279     return rerr;
       
   280     }
       
   281 
       
   282 /**
       
   283 Suspend data transfer whilst new roles are negotiated
       
   284 @internalComponent
       
   285 */
       
   286 void CBnepLink::SuspendDataTransfer ()
       
   287     {
       
   288     LOG_FUNC
       
   289     iNegotiating = ETrue;
       
   290     }
       
   291 
       
   292 void CBnepLink::RemoteDeviceReady()
       
   293 	{
       
   294     iOwner->RemoteDeviceReady();
       
   295 	}
       
   296 
       
   297 /**
       
   298 Install a table of Multicast Address filters on this link. 
       
   299 Any existing table will be deleted.
       
   300 @param aFilterTable The filter table to be installed. Can be NULL, which disables the filter.
       
   301 @internalComponent
       
   302 */
       
   303 void CBnepLink::Install (CMultiAddrFilterTable* aFilterTable)
       
   304     {
       
   305     delete iMultiAddrFilters;
       
   306     iMultiAddrFilters = aFilterTable;
       
   307     }
       
   308 
       
   309 /**
       
   310 Install a table of Network Protocol Type filters on this link.
       
   311 Any existing table will be deleted.
       
   312 @param aFilterTable The filter table to be installed. Can be NULL, which disables the filter.
       
   313 @internalComponent
       
   314 */
       
   315 void CBnepLink::Install (CNetTypeFilterTable* aFilterTable)
       
   316     {
       
   317     delete iNetTypeFilters;
       
   318     iNetTypeFilters = aFilterTable;
       
   319     }
       
   320 
       
   321 /**
       
   322 The control processing method of the link. This method supports re-entrant calls 
       
   323 because of the ambiguity of the interface between BNEP and the PAN Agent.
       
   324 Input side processing has priority over output side. When all input side 
       
   325 processing has finished, the output side will be addressed if there is 
       
   326 anything outstanding.
       
   327 @internalComponent
       
   328 */
       
   329 void CBnepLink::Proceed ()
       
   330     {
       
   331     LOG_FUNC
       
   332     
       
   333     if(iInvalid)
       
   334     	{
       
   335     	// The link is only ever put into an invalid state when the
       
   336     	// CBnepBridge it is attached to is deleted.
       
   337     	// As the CBnepChannelControllers (and therefore CBnepLinks) are owned
       
   338     	// by Pan Agent, the CBnepBridge ignores tidying them up, leaving the
       
   339     	// job upto Pan Agent. The design of Bnep is such that it is assumed
       
   340     	// that Pan Agent will tidy up these links in the same operation that 
       
   341     	// deletes the packet driver (which is our local device bnep
       
   342     	// representation).
       
   343     	// As this behaviour is determined by the NifMan implementation, we get
       
   344     	// Bnep to "invalidate" the links attached to it on deletion, such that
       
   345     	// if we find they are left dangling in debug builds we will be 
       
   346     	// informed by a panic, and otherwise we will handle the strange
       
   347     	// situation as gracefully as possible by dropping packets on this
       
   348     	// rogue link.
       
   349     	__ASSERT_DEBUG(EFalse, BnepUtils::Panic(Bnep::EProceedingOnInvalidLink));
       
   350     	iIncoming.Reset();
       
   351     	return;
       
   352     	}
       
   353 
       
   354     if(iIncoming.Includes(RBnepFrame::EControl))
       
   355         {
       
   356         LOG(_L8("Proceeding with a control message"));
       
   357         iIncoming.ExecuteControl(iLinkManager);
       
   358         }
       
   359 
       
   360 	UpdateOwnerCount(iIncoming.PayloadLength(), 0);
       
   361 	
       
   362     if(iIncoming.Includes(RBnepFrame::EDataFrame))
       
   363         {
       
   364         // Only send if we are enabled for data transfer. 
       
   365         // Otherwise the packet is dropped.
       
   366         if(!iNegotiating)
       
   367             {
       
   368             iIncoming.SetUplinkAccessAllowedForBnepLink(iUplinkAccessAllowed);
       
   369             iOwner->Process(iIncoming, iAddr);
       
   370             }
       
   371         else
       
   372             {
       
   373             LOG(_L8("Negotiating roles: inbound traffic data not allowed: dropping inbound frame."));
       
   374             }
       
   375         }
       
   376     
       
   377     
       
   378     // All input side processing is now 'finished'. 
       
   379     
       
   380 	// If we've finished with the incoming packet...
       
   381     if (iIncoming.IsEmpty())
       
   382     	{
       
   383     	// We can now queue a new read.
       
   384     	iReader->Read();
       
   385     	
       
   386     	// Should we be sending a response yet?
       
   387 		if (!iOutgoing.IsEmpty() && iOutgoing.Includes(RBnepFrame::EControl) &&	// We have controls to respond with
       
   388 			!iLinkManager.AwaitingResponse())									// We're not still waiting for something else
       
   389 	        {
       
   390 	        TInt err = SendFrame(iOutgoing);
       
   391 	        if (err)
       
   392 	            {
       
   393 	            LOG1(_L8("Dropped a packet: SendFrame error %d"),err);
       
   394 	            }
       
   395 			else
       
   396 				{
       
   397 				UpdateOwnerCount(0, iOutgoing.PayloadLength());
       
   398 				}            
       
   399 	        }
       
   400     	}
       
   401     }
       
   402 
       
   403 /**
       
   404 Stops all pending reads on a link..
       
   405 */
       
   406 void CBnepLink::Stop ()
       
   407     {
       
   408     iReader->Cancel();
       
   409     }
       
   410     
       
   411 
       
   412 /**
       
   413 Invalidates the link when it is no longer connected to a bridge.
       
   414 */
       
   415 void CBnepLink::Invalidate ()
       
   416 	{
       
   417 	iInvalid = ETrue;
       
   418 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY	
       
   419     iOwner = NULL; // No longer valid
       
   420 #endif
       
   421 	}
       
   422 
       
   423 void CBnepLink::UpdateOwnerCount(TInt aReceivedCount, TInt aSentCount)
       
   424 	{
       
   425 	if(iOwnerCountPtr && (aReceivedCount>0 || aSentCount>0)) // iOwnerCountPtr will be NULL if CBnepBridge::iBnepPacketNotifier is NULL
       
   426  		{
       
   427   		iOwnerCountPtr->iBytesReceived += aReceivedCount;
       
   428  		iOwnerCountPtr->iBytesSent += aSentCount;
       
   429   		iOwner->DataCountUpdated();
       
   430   		}
       
   431   	}
       
   432 
       
   433 void CBnepLink::SetUplinkAccessAllowedForBnepLink(TBool aAllowed)
       
   434 	{
       
   435 	iUplinkAccessAllowed = aAllowed;
       
   436 	}
       
   437 
       
   438