bluetoothcommsprofiles/btpan/panagt/panagtincoming.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 // panincoming.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @note PAN agent incoming connection listener implementation
       
    21 */
       
    22 
       
    23 #include <bluetooth/logger.h>
       
    24 #include <bt_sock.h>
       
    25 #include <comms-infras/eintsock.h>
       
    26 #include <networking/panuiinterfaces.h>
       
    27 #include "panagtincoming.h"
       
    28 #include "panagtpolicy.h"
       
    29 #include "panagtutils.h"
       
    30 
       
    31 #ifdef __FLOG_ACTIVE
       
    32 _LIT8(KLogComponent, LOG_COMPONENT_PAN_AGENT);
       
    33 #endif
       
    34 
       
    35 using namespace PanAgent;
       
    36 
       
    37 CPanIncomingConnectionListener* CPanIncomingConnectionListener::NewL(MIncomingConnectionAcceptor& aAcceptor)
       
    38 /**
       
    39 Create a new instance of the class
       
    40 @param aAcceptor The class to notify when a new connection is received
       
    41 @return A pointer to the new CPanIncomingConnectionListener, or NULL if it could not be created
       
    42 */
       
    43 	{
       
    44 	CPanIncomingConnectionListener* self = new(ELeave) CPanIncomingConnectionListener(aAcceptor);
       
    45 	CleanupStack::PushL(self);
       
    46 	self->ConstructL();
       
    47 	CleanupStack::Pop(self);
       
    48 	return(self);
       
    49 	}
       
    50 
       
    51 CPanIncomingConnectionListener::CPanIncomingConnectionListener(MIncomingConnectionAcceptor& aAcceptor) :
       
    52 	CActive(KPriorityIncomingListenerAo), iAcceptor(aAcceptor)
       
    53 /**
       
    54 Not much to do here
       
    55 */
       
    56 	{	}
       
    57 
       
    58 CPanIncomingConnectionListener::~CPanIncomingConnectionListener()
       
    59 /**
       
    60 Close all the sockets
       
    61 */
       
    62 	{
       
    63 	Cancel();
       
    64 
       
    65 	iAcceptingSocket.Close();
       
    66 	iListeningSocket.Close();
       
    67 	iListeningSocketIsOpen = EFalse;
       
    68 	
       
    69 	delete iDelayedOpenHelper;
       
    70 	}
       
    71 
       
    72 void CPanIncomingConnectionListener::ConstructL()
       
    73 /**
       
    74 
       
    75 */
       
    76 	{
       
    77 	CActiveScheduler::Add(this);
       
    78 	
       
    79 	iDelayedOpenHelper = CPanIncomingSocketDelayedOpenHelper::NewL(*this);
       
    80 	
       
    81 	OpenListeningSocketL();
       
    82 	User::LeaveIfError(iAcceptingSocket.Open());
       
    83 	iListeningSocket.Accept(iAcceptingSocket, iStatus);
       
    84 
       
    85 	LOG(_L("IncomingConnectionListener: Incoming socket started and ready to accept connections"));
       
    86 
       
    87 	SetActive();
       
    88 	}
       
    89 
       
    90 TBool CPanIncomingConnectionListener::IsAcceptingSocketOpen() const
       
    91 /**
       
    92 Is there an accepting socket open?
       
    93 */
       
    94 	{
       
    95 	return(IsActive());	// if we're active, then we must have an outstanding Accept()
       
    96 	}
       
    97 
       
    98 
       
    99 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   100 /**
       
   101 Notify the main class of the incoming connection
       
   102 */
       
   103 void CPanIncomingConnectionListener::RunL()
       
   104 	{
       
   105 	if(iStatus == KErrNone)
       
   106 		{
       
   107 		LOG(_L("IncomingConnectionListener: ...connection completed successfully, handing connected device off to agent core."));
       
   108 
       
   109 		TRAPD(err, iAcceptor.CreateNewConnectionFromIncomingL(iAcceptingSocket)); // if successful, the socket is transferred away from us here, so a "null" socket is all we have left...
       
   110 		if (err != KErrNone)
       
   111 		    {
       
   112 		    // Something has failed before the message could be sent
       
   113 		    // so we execute the remainder of the RunL logic synchronously
       
   114             RestartIncomingConnectionListener(err);
       
   115 		    }
       
   116 		// else {
       
   117 		//     The rest of the RunL logic is executed asynchonously in
       
   118 		//     RestartIncomingConnectionListener() once BNEP has responded
       
   119 		//     to the TCreateChannelController message
       
   120 		// }
       
   121 		}
       
   122 	else // check what went wrong
       
   123 		{
       
   124 		LOG1(_L("IncomingConnectionListener: ...connection completed with error %d"), iStatus.Int());
       
   125 		iDelayedOpenHelper->SocketOpenFailed();
       
   126 		}
       
   127 	}
       
   128 
       
   129 void CPanIncomingConnectionListener::RestartIncomingConnectionListener(TInt aError)
       
   130     {
       
   131 	// ...otherwise we still have a "live" socket
       
   132 	if(aError) // for some reason the connection could not be completed, so we'll just have to close the socket
       
   133 		{	// it's possible that the device is already connected
       
   134 		LOG(_L("IncomingConnectionListener: ...error - could not hand off socket to agent core, closing socket instead."));
       
   135 		iAcceptingSocket.Close();
       
   136 		}
       
   137 			
       
   138 	// create a new accepting socket...
       
   139 	TInt err = iAcceptingSocket.Open();
       
   140 	if(err) // esp. likely if we've just got KErrNoMemory as the last error		
       
   141 		{
       
   142 		LOG(_L("IncomingConnectionListener: ...could not open new accepting socket. Will try again later."));						
       
   143 		iDelayedOpenHelper->SocketOpenFailed();
       
   144 		}
       
   145 	else
       
   146 		{
       
   147 		LOG(_L("IncomingConnectionListener: ...requeing listening socket..."));
       
   148 
       
   149 		// ...and repeat the cycle
       
   150 		iListeningSocket.Accept(iAcceptingSocket, iStatus);
       
   151 		SetActive();
       
   152 		}
       
   153     }
       
   154 
       
   155 #else
       
   156 // !SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   157 
       
   158 void CPanIncomingConnectionListener::RunL()
       
   159 /**
       
   160 Notify the main class of the incoming connection
       
   161 */
       
   162 	{
       
   163 	if(iStatus==KErrNone)
       
   164 		{
       
   165 		LOG(_L("IncomingConnectionListener: ...connection completed successfully, handing connected device off to agent core."));
       
   166 
       
   167 		TRAPD(err, iAcceptor.CreateNewConnectionFromIncomingL(iAcceptingSocket)); // if successful, the socket is transferred away from us here, so a "null" socket is all we have left...
       
   168 
       
   169 		// ...otherwise we still have a "live" socket
       
   170 		if(err) // for some reason the connection could not be completed, so we'll just have to close the socket
       
   171 			{	// it's possible that the device is already connected
       
   172 			LOG(_L("IncomingConnectionListener: ...error - could not hand off socket to agent core, closing socket instead."));
       
   173 			iAcceptingSocket.Close();
       
   174 			}
       
   175 			
       
   176 		// create a new accepting socket...
       
   177 		err = iAcceptingSocket.Open();
       
   178 		if(err) // esp. likely if we've just got KErrNoMemory as the last error		
       
   179 			{
       
   180 			LOG(_L("IncomingConnectionListener: ...could not open new accepting socket. Will try again later."));						
       
   181 			iDelayedOpenHelper->SocketOpenFailed();
       
   182 			}
       
   183 		else
       
   184 			{
       
   185 			LOG(_L("IncomingConnectionListener: ...requeing listening socket..."));
       
   186 
       
   187 			// ...and repeat the cycle
       
   188 			iListeningSocket.Accept(iAcceptingSocket, iStatus);
       
   189 			SetActive();
       
   190 			}
       
   191 		}
       
   192 	else // check what went wrong
       
   193 		{
       
   194 		LOG1(_L("IncomingConnectionListener: ...connection completed with error %d"), iStatus.Int());
       
   195 		iDelayedOpenHelper->SocketOpenFailed();
       
   196 		}
       
   197 	}
       
   198 #endif
       
   199 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY	
       
   200 
       
   201 void CPanIncomingConnectionListener::DoCancel()
       
   202 /**
       
   203 Cancel the outstanding accept
       
   204 */
       
   205 	{
       
   206 	iListeningSocket.CancelAccept();
       
   207 	}
       
   208 	
       
   209 void CPanIncomingConnectionListener::OpenListeningSocketL()
       
   210 /**
       
   211 Create and initialise the listening socket
       
   212 */
       
   213 	{
       
   214 #if defined(_DEBUG) && defined(SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY)
       
   215     TInt err = iListeningSocket.Open(KBTAddrFamily, KSockSeqPacket, KL2CAP);
       
   216     __ASSERT_DEBUG(err != KErrBadName, PanAgentPanic(EPanAgtMissingBinding));
       
   217     User::LeaveIfError(err);
       
   218 #else
       
   219 	User::LeaveIfError(iListeningSocket.Open(KBTAddrFamily, KSockSeqPacket, KL2CAP));
       
   220 #endif
       
   221 	
       
   222 	// listen on the assigned l2cap port for BNEP
       
   223 	TBTSockAddr incomingConnectionSettings;
       
   224 	incomingConnectionSettings.SetPort(KBnepPsm);
       
   225 
       
   226 	// read the required security settings from commdb, and use them to set up the listening socket
       
   227 	TBTServiceSecurity incomingSecuritySettings;
       
   228 	incomingSecuritySettings.SetAuthentication(KPanIncomingAuthenticationRequired);
       
   229 	incomingSecuritySettings.SetAuthorisation(KPanIncomingAuthorisationRequired);
       
   230 	incomingSecuritySettings.SetEncryption(KPanIncomingEncryptionRequired);
       
   231 	incomingSecuritySettings.SetUid(KBTPanAuthorisationUid);
       
   232 	incomingConnectionSettings.SetSecurity(incomingSecuritySettings);
       
   233 	
       
   234 	User::LeaveIfError(iListeningSocket.Bind(incomingConnectionSettings));
       
   235 
       
   236 	// Set the MTU to the required minimum for BNEP
       
   237 	TUint16 bnepMtu = KBnepMtu;								
       
   238 	TPckg<TUint16> mtuBuf(bnepMtu);
       
   239 	User::LeaveIfError(iListeningSocket.SetOpt(KL2CAPInboundMTU, KSolBtL2CAP, mtuBuf));
       
   240 	User::LeaveIfError(iListeningSocket.SetOpt(KL2CAPNegotiatedOutboundMTU, KSolBtL2CAP, mtuBuf));
       
   241 	// Register the CoD service - Networking bit (especially relevant for WinXP)
       
   242 	User::LeaveIfError(iListeningSocket.SetOpt(KBTRegisterCodService, KSolBtSAPBase, EMajorServiceNetworking));
       
   243 
       
   244 	User::LeaveIfError(iListeningSocket.Listen(KIncomingSockQueueSize));
       
   245 	iListeningSocketIsOpen = ETrue;
       
   246 	}
       
   247 
       
   248 CPanIncomingSocketDelayedOpenHelper* CPanIncomingSocketDelayedOpenHelper::NewL(CPanIncomingConnectionListener& aIncomingConnectionListener)
       
   249 /**
       
   250 
       
   251 */
       
   252 	{
       
   253 	CPanIncomingSocketDelayedOpenHelper* self = new(ELeave) CPanIncomingSocketDelayedOpenHelper(aIncomingConnectionListener);
       
   254 	CleanupStack::PushL(self);
       
   255 	self->ConstructL();
       
   256 	CleanupStack::Pop(self);
       
   257 	return self;
       
   258 	}
       
   259 
       
   260 CPanIncomingSocketDelayedOpenHelper::CPanIncomingSocketDelayedOpenHelper(CPanIncomingConnectionListener& aIncomingConnectionListener) :
       
   261 	CTimer(KPriorityIncomingListenerAo), iCurrentTimerPeriod(KMinSocketReopenAttemptInterval), iIncomingConnectionListener(aIncomingConnectionListener)
       
   262 /**
       
   263 
       
   264 */
       
   265 	{
       
   266 	CActiveScheduler::Add(this);
       
   267 	}
       
   268 	
       
   269 void CPanIncomingSocketDelayedOpenHelper::ConstructL()
       
   270 /**
       
   271 
       
   272 */
       
   273 	{
       
   274 	CTimer::ConstructL();
       
   275 	}
       
   276 	
       
   277 CPanIncomingSocketDelayedOpenHelper::~CPanIncomingSocketDelayedOpenHelper()
       
   278 /**
       
   279 Nothing to do
       
   280 */
       
   281 	{
       
   282 	
       
   283 	}
       
   284 
       
   285 void CPanIncomingSocketDelayedOpenHelper::SocketOpenFailed()
       
   286 /**
       
   287 A socket open has failed, so it's now up to us to keep retrying
       
   288 */
       
   289 	{
       
   290 	After(iCurrentTimerPeriod);
       
   291 	}
       
   292 	
       
   293 void CPanIncomingSocketDelayedOpenHelper::RunL()
       
   294 /**
       
   295 Attempt to open the listening socket (if necessary) and the accepting socket
       
   296 */
       
   297 	{
       
   298 	// check that the accepting (and therefore by inference the listening) sockets aren't open already
       
   299 	__ASSERT_DEBUG(!(iIncomingConnectionListener.IsAcceptingSocketOpen()), PanAgentPanic(EDelayedOpenHelperActiveWhenBothListeningAndAcceptingSocketsAreOpen));
       
   300 	
       
   301 	TInt err;
       
   302 	if(!(iIncomingConnectionListener.IsListeningSocketOpen()))
       
   303 		{
       
   304 		TRAP(err, iIncomingConnectionListener.OpenListeningSocketL());
       
   305 		if(err)	// failed to open listening socket, back off and try again later
       
   306 			{
       
   307 			SetNewTimerPeriod();
       
   308 			After(iCurrentTimerPeriod);	// will set us active
       
   309 			return;
       
   310 			}
       
   311 		}
       
   312 		
       
   313 	if(!(iIncomingConnectionListener.IsAcceptingSocketOpen()))
       
   314 		{
       
   315 		err = iIncomingConnectionListener.iAcceptingSocket.Open();
       
   316 		if(err)	// failed to open accepting socket, back off and try again later
       
   317 			{
       
   318 			SetNewTimerPeriod();
       
   319 			After(iCurrentTimerPeriod);	// will set us active
       
   320 			return;
       
   321 			}
       
   322 		else
       
   323 			{
       
   324 			iIncomingConnectionListener.iListeningSocket.Accept(iIncomingConnectionListener.iAcceptingSocket, iIncomingConnectionListener.iStatus);
       
   325 			iIncomingConnectionListener.SetActive();
       
   326 			return;
       
   327 			}
       
   328 		}
       
   329 	}
       
   330 
       
   331 void CPanIncomingSocketDelayedOpenHelper::SetNewTimerPeriod()
       
   332 /**
       
   333 Set the timer period to a new value - doubles each time up to the limit
       
   334 */
       
   335 	{
       
   336 	iCurrentTimerPeriod = iCurrentTimerPeriod.Int() * 2;
       
   337 	
       
   338 	if(iCurrentTimerPeriod > TTimeIntervalMicroSeconds32(KMaxSocketReopenAttemptInterval))	// this happens rarely enough (once per many secs to minutes) to take the hit of constructing a new object each time
       
   339 		{
       
   340 		iCurrentTimerPeriod = KMaxSocketReopenAttemptInterval;
       
   341 		}
       
   342 	}