bluetooth/btsdp/server/protocol/listener.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2000-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 #include <bluetooth/logger.h>
       
    17 #include "listener.h"
       
    18 #include "reqhandler.h"
       
    19 #include "sdpconsts.h"
       
    20 #include "epocsvr.h"
       
    21 #include <bt_sock.h>
       
    22 #include <es_sock.h>
       
    23 
       
    24 #ifdef __FLOG_ACTIVE
       
    25 _LIT8(KLogComponent, LOG_COMPONENT_SDP_SERVER);
       
    26 #endif
       
    27 
       
    28 #ifdef _DEBUG
       
    29 PANICCATEGORY("sdplist");
       
    30 #endif
       
    31 
       
    32 //The size of a the buffer that's used to read a fragment of the incoming data
       
    33 //Typical SDP requests are under 100 bytes. 512 is chosen because it is the 
       
    34 //closest power of 2 to the spec default MTU (672). We expect it is big enough
       
    35 //to handle most requests while not taking too much unnecessary space
       
    36 const TInt KRecvFragmentSize = 512;
       
    37 //The initial size of the buffer used to assemble the fragmented data from multiple 
       
    38 //continuation read. It is initilised to 4 times of the fragment size in the hope 
       
    39 //that on demand growing of the buffer will rarely be necessary.
       
    40 const TInt KRecvInitSize	 = 2048;
       
    41 
       
    42 CSdpConnection* CSdpConnection::NewL(RSocket& aSocket, CSdpDatabase& aDatabase)
       
    43 /**
       
    44 	Spawn of a new connection, using this pre-connected socekt.
       
    45 **/
       
    46 	{
       
    47 	LOG_STATIC_FUNC
       
    48 	CSdpConnection* self = new (ELeave)CSdpConnection(aSocket, aDatabase);
       
    49 	CleanupStack::PushL(self);
       
    50 	self->ConstructL();
       
    51 	CleanupStack::Pop();
       
    52 	return self;
       
    53 	}
       
    54 
       
    55 CSdpConnection::~CSdpConnection()
       
    56 	{
       
    57 	LOG_FUNC
       
    58 	LOG1(_L("CSdpConnection::~CSdpConnection() 0x%08x"), this);
       
    59 	Cancel();
       
    60 
       
    61 	// Delete the active objects that callback on the connection before
       
    62 	// closing the socket so that they don't try and use a bad handle.
       
    63 	delete iSDPClientTimer;
       
    64 	delete iReader;
       
    65 
       
    66 	iSocket.Close();
       
    67 	
       
    68 	// Delete the various buffers used for the connection
       
    69 	delete iReadFragmentHBuf;
       
    70 	delete iReadTotalHBuf;
       
    71 	delete iWriteHBuf;
       
    72 
       
    73 	iLink.Deque();	// Take ourselves off the connection Q.
       
    74 	}
       
    75 
       
    76 /**
       
    77 Handles the completion of asynchronous write and shutdown operations.
       
    78 (reads are handled by the separate CSdpConnectionReader active object).
       
    79 */
       
    80 void CSdpConnection::RunL()
       
    81 	{
       
    82 	LOG_FUNC
       
    83 	LOG2(_L("CSdpConnection::RunL() 0x%08x state=%d"), this, iConnState);
       
    84 	if (iConnState == EShutting)
       
    85 		{
       
    86 		delete this;
       
    87 		}
       
    88 	else
       
    89 		{
       
    90 		// If not in the shutting state, then we must be in the writing state.
       
    91 		__ASSERT_DEBUG(iConnState == EWriting, PanicServer(ESdpBadState));
       
    92 		User::LeaveIfError(iStatus.Int()); // On error go to the error handling routine
       
    93 		// If here then a write successfully completed, so return to
       
    94 		// the reading state.
       
    95 		iConnState = EReading;
       
    96 		}
       
    97 	}
       
    98 
       
    99 void CSdpConnection::HandleReadL()
       
   100 	{
       
   101 	LOG_FUNC
       
   102 	iSDPClientTimer->Cancel();	// client is alive, cancel timer
       
   103 	LOG1(_L("Received %d bytes of request data [contents]"), iReadFragmentBuf.Length());
       
   104 	FTRACE(FHex(iReadFragmentBuf));
       
   105 
       
   106 	// Adjust the fragmented reading buffers as appropriate
       
   107 	TInt remainingDataLength = iRemainingDataLength();
       
   108 	TInt totalDataLength = remainingDataLength + iReadFragmentBuf.Length();
       
   109 	if(iReadTotalBuf.Length() + totalDataLength > iReadTotalBuf.MaxLength())
       
   110 		{
       
   111 		iReadTotalHBuf = iReadTotalHBuf->ReAllocL(iReadTotalBuf.MaxLength() + totalDataLength);
       
   112 		iReadTotalBuf.Set(iReadTotalHBuf->Des()); //in case the buffer has been moved in ReAlloc
       
   113 		}
       
   114 	iReadTotalBuf.Append(iReadFragmentBuf);
       
   115 
       
   116 	// Queue the next read up to always have a read outstanding.
       
   117 	// NOTE: This should be called before the ParseNextPacketL to
       
   118 	// ensure the connection state is correct.
       
   119 	QueRead();
       
   120 
       
   121 	// If we have a complete L2CAP datagram then parse it, otherwise
       
   122 	// continue the fragmented read.
       
   123 	if(remainingDataLength > 0)
       
   124 		{
       
   125         LOG1(_L("Receive Continue...(%d bytes left to read)"), iRemainingDataLength());
       
   126 		}
       
   127 	else
       
   128 		{
       
   129 		ParseNextPacketL();
       
   130 		iReadTotalBuf.Zero();
       
   131 		}
       
   132 	}
       
   133 
       
   134 void CSdpConnection::DoCancel()
       
   135 	{
       
   136 	LOG_FUNC
       
   137    	// There isn't async break in handling state, hence something is wrong if we are here
       
   138 	__ASSERT_DEBUG(iConnState != EHandling, PanicServer(ESdpBadState));
       
   139 
       
   140 	iReader->Cancel();
       
   141 	iSocket.CancelWrite();
       
   142 	// Can't cancel a shutdown request
       
   143 	}
       
   144 
       
   145 TInt CSdpConnection::RunError(TInt __DEBUG_ONLY(aError))
       
   146 	{
       
   147 	LOG_FUNC
       
   148 	// Not a recoverable error, disconnect
       
   149 	LOG1(_L("CSdpConnection::Error(%d). Aborting link!"), aError);
       
   150 	ShutdownConnection();
       
   151 
       
   152 	return KErrNone;
       
   153 	}
       
   154 
       
   155 void CSdpConnection::ClientTimeout()
       
   156 	{
       
   157 	LOG_FUNC
       
   158 	LOG(_L("CSdpListener::ClientTimeout()"));
       
   159 	LOG(_L("Disconnecting Inactive client"));
       
   160 	delete this;
       
   161 	}
       
   162 
       
   163 CSdpConnection::CSdpConnection(RSocket& aSocket, CSdpDatabase& aDatabase)
       
   164 	: CActive(CActive::EPriorityStandard),
       
   165 	iSocket(aSocket),
       
   166 	iDatabase(aDatabase),
       
   167 	iReadFragmentBuf(0,0),
       
   168 	iReadTotalBuf(0,0),
       
   169 	iWriteBuf(0,0)
       
   170 	{
       
   171 	LOG_FUNC
       
   172 	LOG1(_L("CSdpConnection::CSdpConnection 0x%08x"), this);
       
   173 	CActiveScheduler::Add(this);
       
   174 	}
       
   175 
       
   176 void CSdpConnection::ConstructL()
       
   177 	{
       
   178 	LOG_FUNC
       
   179 	TInt outMTU;
       
   180 	User::LeaveIfError(iSocket.GetOpt(KL2CAPOutboundMTUForBestPerformance, KSolBtL2CAP, outMTU));
       
   181 	TInt mru;
       
   182 	User::LeaveIfError(iSocket.GetOpt(KL2CAPInboundMTU, KSolBtL2CAP, mru));
       
   183 
       
   184 	iReadFragmentHBuf = HBufC8::NewL(KRecvFragmentSize);
       
   185 	iReadFragmentBuf.Set(iReadFragmentHBuf->Des());
       
   186 	iReadTotalHBuf = HBufC8::NewL(KRecvInitSize); //will grow on demand
       
   187 	iReadTotalBuf.Set(iReadTotalHBuf->Des());
       
   188 	
       
   189 	iWriteHBuf = HBufC8::NewL(outMTU);
       
   190 	iWriteBuf.Set(iWriteHBuf->Des());
       
   191 	iWriteBuf.SetMax();
       
   192 	iResponse.iParams.Set(&iWriteBuf[KSdpPduHeaderSize], 0, outMTU-KSdpPduHeaderSize);
       
   193 
       
   194 	iSDPClientTimer = CSdpClientTimer::NewL(*this);
       
   195 	iReader = CSdpConnectionReader::NewL(*this);
       
   196 	QueRead();
       
   197 	}
       
   198 
       
   199 void CSdpConnection::ParseNextPacketL()
       
   200 /**
       
   201 	Parse a single SDP PDU out of the L2CAP packet received.
       
   202 **/
       
   203 	{
       
   204 	LOG_FUNC
       
   205 	LOG(_L("CSdpConnection::ParseNextPacketL()"));
       
   206 	iConnState = EHandling;	// So that the RunError will handle leaves correctly
       
   207 	TInt rem = iReadTotalBuf.Length();
       
   208 	if (rem < KSdpPduHeaderSize)
       
   209 		{
       
   210 		// Incomplete header. Let request hadler cope with the error
       
   211 		User::Leave(KErrUnderflow); // Will cause "Invalid Pdu Size" error
       
   212 		}
       
   213 	iRequest.iPduId   = iReadTotalBuf[KSdpPduIdOffset];
       
   214 	iRequest.iTransId = BigEndian::Get16(&iReadTotalBuf[KSdpPduTransIdOffset]);
       
   215 	iResponse.iTransId = iRequest.iTransId; // Response has same TransID as request.
       
   216 
       
   217 	TUint16 paramlen= BigEndian::Get16(&iReadTotalBuf[KSdpPduParamLengthOffset]);
       
   218 	if ((rem != KSdpPduHeaderSize + paramlen) || (paramlen == 0))
       
   219 		{
       
   220 		// Not enough parameter data.
       
   221 		User::Leave(KErrUnderflow); // Will cause "Invalid Pdu Size" error
       
   222 		}
       
   223 	iRequest.iParams.Set(&iReadTotalBuf[KSdpPduHeaderSize], paramlen, paramlen);
       
   224 	iResponse.iParams.Zero();
       
   225 	LOG3(_L("Parsed SDP PDU ID %d, transaction ID %d, paramater length %d, [params]"), iRequest.iPduId, iRequest.iTransId, paramlen);
       
   226 	FTRACE(FHex(iRequest.iParams));
       
   227 
       
   228 	SdpReqHandler::HandleL(iDatabase, iRequest, iResponse);
       
   229 	// No leave occured, so response was formed okay.
       
   230 	// Now write it back to the client
       
   231 	WriteResponse();
       
   232 	}
       
   233 
       
   234 void CSdpConnection::QueRead()
       
   235 	{
       
   236 	LOG_FUNC
       
   237 	__ASSERT_DEBUG(!iReader->IsActive(), PanicServer(ESdpReadAlreadyOutstanding));
       
   238 	iConnState = EReading;
       
   239 	iSocket.Recv(iReadFragmentBuf, KSockReadContinuation, iReader->iStatus, iRemainingDataLength);
       
   240 	iReader->SetActive();
       
   241 	iSDPClientTimer->Start(); // gate the read with a timeout to guard against inactive clients
       
   242 	}
       
   243 
       
   244 void CSdpConnection::WriteResponse()
       
   245 	{
       
   246 	LOG_FUNC
       
   247 	LOG1(_L("Writing %d bytes of response data [contents]"), iWriteBuf.Length());
       
   248 	__ASSERT_DEBUG(!IsActive(), PanicServer(ESdpOutstandingOperation));
       
   249 	TInt paramLen = iResponse.iParams.Length();
       
   250 	ASSERT_DEBUG(paramLen <= static_cast<TInt>(KMaxTUint16));
       
   251 	
       
   252 	iWriteBuf.SetLength(paramLen + KSdpPduHeaderSize);
       
   253 	iWriteBuf[KSdpPduIdOffset] = iResponse.iPduId;
       
   254 	BigEndian::Put16(&iWriteBuf[KSdpPduTransIdOffset], iResponse.iTransId);
       
   255 	BigEndian::Put16(&iWriteBuf[KSdpPduParamLengthOffset], TUint16(paramLen));
       
   256 	
       
   257 	FTRACE(FHex(iWriteBuf));
       
   258 	iConnState = EWriting;
       
   259 	iSocket.Write(iWriteBuf, iStatus);
       
   260 	SetActive();
       
   261 	}
       
   262 
       
   263 void CSdpConnection::ShutdownConnection()
       
   264 	{
       
   265 	LOG_FUNC
       
   266 	__ASSERT_DEBUG(!IsActive(), PanicServer(ESdpOutstandingOperation));
       
   267 	iConnState = EShutting;
       
   268 	iSocket.Shutdown(RSocket::ENormal, iStatus);
       
   269 	SetActive();
       
   270 	}
       
   271 
       
   272 /**
       
   273 Handles the completion of a read operation.
       
   274 */
       
   275 void CSdpConnection::ReadComplete(TInt aStatus)
       
   276 	{
       
   277 	LOG_FUNC
       
   278 	LOG1(_L("CSdpConnection::ReadComplete with %d"), aStatus);
       
   279 	if(aStatus == KErrNone)
       
   280 		{
       
   281 		if(iConnState == EReading)
       
   282 			{
       
   283 			TRAP(aStatus, HandleReadL());
       
   284 
       
   285 			if ((aStatus != KErrNone) && (iConnState == EHandling))
       
   286 				{
       
   287 				// Problem with received pdu, send an error response to the remote
       
   288 				aStatus = SdpReqHandler::RunError(aStatus, iRequest, iResponse);
       
   289 				if (aStatus == KErrNone)
       
   290 					{
       
   291 					LOG(_L("Handled bad SDP request. Sending response..."));
       
   292 					WriteResponse();
       
   293 			        iReadTotalBuf.Zero();
       
   294 					}
       
   295 				}
       
   296 			}
       
   297 		else
       
   298 			{
       
   299 			// If we complete a read while handling an existing request
       
   300 			// the other side is behaving badly.  We deal with this by
       
   301 			// ignoring them and disconnecting the connection.
       
   302 			LOG1(_L("ReadComplete during another operation(%d)!! Disconnecting..."), iConnState);
       
   303 			Cancel();
       
   304 			ShutdownConnection();
       
   305 			}
       
   306 		}
       
   307 
       
   308 	// deal with any unhandled errors by disconnecting
       
   309 	if(aStatus != KErrNone)
       
   310 		{
       
   311 		Cancel();
       
   312 		ShutdownConnection();
       
   313 		}
       
   314 	}
       
   315 
       
   316 void CSdpConnection::CancelRead()
       
   317 	{
       
   318 	LOG_FUNC
       
   319 	iSDPClientTimer->Cancel();
       
   320 	iSocket.CancelRecv();	
       
   321 	}
       
   322 
       
   323 CSdpConnectionReader* CSdpConnectionReader::NewL(CSdpConnection& aConnection)
       
   324 	{
       
   325 	LOG_STATIC_FUNC
       
   326 	CSdpConnectionReader* self = new(ELeave) CSdpConnectionReader(aConnection);
       
   327 	CleanupStack::PushL(self);
       
   328 	self->ConstructL();
       
   329 	CleanupStack::Pop(self);
       
   330 	return self;
       
   331 	}
       
   332 
       
   333 CSdpConnectionReader::CSdpConnectionReader(CSdpConnection& aConnection)
       
   334 	: CActive(EPriorityStandard)
       
   335 	, iConnection(aConnection)
       
   336 	{
       
   337 	LOG_FUNC
       
   338 	}
       
   339 
       
   340 void CSdpConnectionReader::ConstructL()
       
   341 	{
       
   342 	LOG_FUNC
       
   343 	CActiveScheduler::Add(this);
       
   344 	}
       
   345 
       
   346 CSdpConnectionReader::~CSdpConnectionReader()
       
   347 	{
       
   348 	LOG_FUNC
       
   349 	Cancel();
       
   350 	}
       
   351 
       
   352 void CSdpConnectionReader::RunL()
       
   353 	{
       
   354 	LOG_FUNC
       
   355 	iConnection.ReadComplete(iStatus.Int());
       
   356 	}
       
   357 
       
   358 void CSdpConnectionReader::DoCancel()
       
   359 	{
       
   360 	LOG_FUNC
       
   361 	iConnection.CancelRead();
       
   362 	}
       
   363 
       
   364 CSdpClientTimer* CSdpClientTimer::NewL(CSdpConnection& aConnection)
       
   365 	{
       
   366 	LOG_STATIC_FUNC
       
   367 	CSdpClientTimer* t = new (ELeave) CSdpClientTimer(aConnection);
       
   368 	CleanupStack::PushL(t);
       
   369 	t->ConstructL();
       
   370 	CleanupStack::Pop(t);
       
   371 	return t;
       
   372 	}
       
   373 
       
   374 
       
   375 CSdpClientTimer::CSdpClientTimer(CSdpConnection& aConnection)
       
   376 : CTimer(EPriorityStandard), iConnection(aConnection)
       
   377 	{
       
   378 	LOG_FUNC
       
   379 	}
       
   380 
       
   381 void CSdpClientTimer::Start()
       
   382 	{
       
   383 	LOG_FUNC
       
   384 	After(KSDPClientTimeout * 1000000);
       
   385 	}
       
   386 
       
   387 void CSdpClientTimer::ConstructL()
       
   388 	{
       
   389 	LOG_FUNC
       
   390 	CTimer::ConstructL();
       
   391 	CActiveScheduler::Add(this);
       
   392 	}
       
   393 
       
   394 void CSdpClientTimer::RunL()
       
   395 	{
       
   396 	LOG_FUNC
       
   397 	iConnection.ClientTimeout();
       
   398 	}
       
   399 
       
   400 
       
   401 CSdpListener* CSdpListener::NewL(RSocketServ& aSockServ, TInt aQueSize, CSdpDatabase& aDatabase)
       
   402 	{
       
   403 	LOG_STATIC_FUNC
       
   404 	CSdpListener* self = NewLC(aSockServ, aQueSize, aDatabase);
       
   405 	CleanupStack::Pop();
       
   406 	return self;
       
   407 	}
       
   408 
       
   409 CSdpListener* CSdpListener::NewLC(RSocketServ& aSockServ, TInt aQueSize, CSdpDatabase& aDatabase)
       
   410 	{
       
   411 	LOG_STATIC_FUNC
       
   412 	CSdpListener* self = new (ELeave) CSdpListener(aSockServ, aDatabase);
       
   413 	CleanupStack::PushL(self);
       
   414 	self->ConstructL(aQueSize);
       
   415 	return self;
       
   416 	}
       
   417 
       
   418 
       
   419 CSdpListener::~CSdpListener()
       
   420 	{
       
   421 	LOG_FUNC
       
   422 	while (!iConns.IsEmpty())
       
   423 		{
       
   424 		CSdpConnection* conn = iConns.First();
       
   425 		delete conn;
       
   426 		}
       
   427 	
       
   428 	Cancel(); //Ensure this active object is not still active.
       
   429 
       
   430 	iListener.Close();
       
   431 	iAccepter.Close();
       
   432 	iDelayAcceptTimer.Close();
       
   433 	}
       
   434 
       
   435 CSdpListener::CSdpListener(RSocketServ& aSockServ, CSdpDatabase& aDatabase)
       
   436 	: CActive(EPriorityLow), iSockServ(aSockServ), iDatabase(aDatabase),
       
   437 	iIsAcceptDelayed(ETrue), iAcceptDelay(KInitialAcceptDelay),
       
   438 	iConns(_FOFF(CSdpConnection, iLink))
       
   439 	{
       
   440 	LOG_FUNC
       
   441 	CActiveScheduler::Add(this);
       
   442 	}
       
   443 
       
   444 void CSdpListener::ConstructL(TInt aQueSize)
       
   445 	{
       
   446 	LOG_FUNC
       
   447 	User::LeaveIfError(iDelayAcceptTimer.CreateLocal());
       
   448 	iQueSize = aQueSize; //set before calling OpenListeningSocket
       
   449 	QueAcceptL();
       
   450 	}
       
   451 
       
   452 void CSdpListener::OpenListeningSocketL()
       
   453 	{
       
   454 	LOG_FUNC
       
   455 	User::LeaveIfError(iListener.Open(iSockServ, _L("L2CAP")));
       
   456 
       
   457 	TL2CAPSockAddr addr;
       
   458 	addr.SetPort(KSDPPSM);
       
   459 	TBTServiceSecurity sdpSecurity;
       
   460 	sdpSecurity.SetUid(KUidServiceSDP);
       
   461 	sdpSecurity.SetAuthentication(EMitmNotRequired);
       
   462 	sdpSecurity.SetAuthorisation(EFalse);
       
   463 	sdpSecurity.SetEncryption(EFalse);
       
   464 	sdpSecurity.SetDenied(EFalse);
       
   465 
       
   466 	addr.SetSecurity(sdpSecurity);
       
   467 
       
   468 	User::LeaveIfError(iListener.Bind(addr));
       
   469 	User::LeaveIfError(iListener.Listen(iQueSize));
       
   470 	}
       
   471 
       
   472 void CSdpListener::TryRestartL()
       
   473 	{
       
   474 	LOG_FUNC
       
   475 	if (iIsAcceptDelayed)
       
   476 		{
       
   477 		LOG(_L("SDP Server: New session open when accept delayed. Retrying right now"));
       
   478 		Cancel();
       
   479 		QueAcceptL();
       
   480 		}
       
   481 	}
       
   482 
       
   483 void CSdpListener::RunL()
       
   484 	{
       
   485 	LOG_FUNC
       
   486 	if(!iIsAcceptDelayed)
       
   487 		{
       
   488 		User::LeaveIfError(iStatus.Int());
       
   489 		CSdpConnection *conn = CSdpConnection::NewL(iAccepter, iDatabase);
       
   490 		iConns.AddFirst(*conn);
       
   491 		iAcceptDelay = KInitialAcceptDelay;
       
   492 		}
       
   493 	QueAcceptL();
       
   494 	}
       
   495 
       
   496 
       
   497 void CSdpListener::DoCancel()
       
   498 	{
       
   499 	LOG_FUNC
       
   500 	if (iListener.SubSessionHandle())
       
   501 		{
       
   502 		iListener.CancelAccept();
       
   503 		iListener.CancelRecv();
       
   504 		}
       
   505 	if(iIsAcceptDelayed)
       
   506 		{
       
   507 		iDelayAcceptTimer.Cancel();
       
   508 		}
       
   509 	}
       
   510 
       
   511 
       
   512 TInt CSdpListener::RunError(TInt aError)
       
   513 /**
       
   514 	Handle leave from RunL.
       
   515 	If this is called, the accept socket is assumed to be cleaned up already
       
   516 **/
       
   517 	{
       
   518 	LOG_FUNC
       
   519 	LOG1(_L("CSdpListener::Error(%d)"), aError);
       
   520 	// Just try to get an accpet going. If this fails, we'll keep trying using 
       
   521 	// an exponential timeout, as OOM could cause this to keep failing.
       
   522 	iListener.Close();
       
   523 	iAccepter.Close();
       
   524 	iIsAcceptDelayed = ETrue;
       
   525 
       
   526 	if(iAcceptDelay<=(KMaxAcceptDelay/2))
       
   527 		{
       
   528 		//alter ready for next attempt
       
   529 		iAcceptDelay*=2;
       
   530 		}
       
   531 	else if (aError == KErrHardwareNotAvailable)
       
   532 		{
       
   533 /*		the hardware has gone and we've met our retry limit
       
   534 		we'll wait until a new session is created
       
   535 		before attempting to get a connection
       
   536 		this makes sense as the services will have detected hardware off
       
   537 		and typically closed their sockets and handles to SDP.
       
   538 		At some point services will try to re-register and this will trigger
       
   539 		the SDP server to attempt to reaccept connections.
       
   540 */
       
   541 		return KErrNone;
       
   542 		}
       
   543 
       
   544 	iDelayAcceptTimer.After(iStatus, iAcceptDelay); 
       
   545 	SetActive();
       
   546 	
       
   547 	return KErrNone;
       
   548 	}
       
   549 
       
   550 void CSdpListener::QueAcceptL()
       
   551 	{
       
   552 	LOG_FUNC
       
   553 	User::LeaveIfError(iAccepter.Open(iSockServ));
       
   554 	if(iIsAcceptDelayed)
       
   555 		{
       
   556 		OpenListeningSocketL();
       
   557 		iIsAcceptDelayed = EFalse;
       
   558 		}
       
   559 	iListener.Accept(iAccepter, iStatus);
       
   560 	SetActive();
       
   561 	}
       
   562 
       
   563