datacommsserver/esockserver/ssock/SS_RSLV.CPP
changeset 0 dfb7c4ff071f
child 12 8b5d60ce1e94
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #define SYMBIAN_NETWORKING_UPS
       
    17 
       
    18 #include <comms-infras/ss_roles.h>
       
    19 #include <comms-infras/ss_log.h>
       
    20 #include <ss_glob.h>
       
    21 #include <ss_std.h>
       
    22 #include <comms-infras/ss_subconnflow.h>
       
    23 #include "ss_flowrequest.h"
       
    24 #include <es_prot.h>
       
    25 #include "SS_rslv.H"
       
    26 #include <comms-infras/nifif.h>
       
    27 #include <comms-infras/ss_sapshim.h>
       
    28 #include <comms-infras/ss_nodemessages_dataclient.h>
       
    29 #include <es_mbuf.h>
       
    30 
       
    31 #include <comms-infras/ss_msgintercept.h>
       
    32 
       
    33 
       
    34 #ifdef _DEBUG
       
    35 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    36 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    37 _LIT(KSpecAssert_ESockSSockS_RSLV, "ESockSSockS_RSLV");
       
    38 #endif
       
    39 
       
    40 #define MSG_PRM(prmIndex)		(prmIndex)
       
    41 
       
    42 using namespace ESock;
       
    43 using namespace Messages;
       
    44 
       
    45 CHostResolver::CHostResolver(CSockSession* aSession, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
    46 : CSockSubSession(aSession, aPlayer, aSubSessionUniqueId),
       
    47   Messages::ASimpleNodeIdBase(),
       
    48   iPtrQryBuf(NULL, 0),
       
    49   iPtrQryResBuf(NULL, 0)
       
    50 
       
    51 /**
       
    52 Constructor - set up default options.
       
    53 
       
    54 */
       
    55 	{
       
    56 	LOG_NODE_CREATE(KESockFlowTag, CHostResolver)
       
    57     }
       
    58 
       
    59 CHostResolver::~CHostResolver()
       
    60 /**
       
    61 Destructor
       
    62 
       
    63 */
       
    64 	{
       
    65    	delete ipQryRespBuf; //-- delete query response buffer
       
    66    	delete ipQryBuf;     //-- delete query buffer
       
    67 	LOG_NODE_DESTROY(KESockFlowTag, CHostResolver)
       
    68 	}
       
    69 
       
    70 void CHostResolver::InitiateDestruction()
       
    71 	{
       
    72 	// Remove the subsession from the session's subsession list.
       
    73     if(iSession)
       
    74 		{
       
    75 		iSession->SubSessions().Lock();
       
    76 
       
    77 		Den::CSubSessionIx::TSubSessionHandle handle;
       
    78 		if(iSession->SubSessions().Find(this, handle) == KErrNone)
       
    79 			{
       
    80 			iSession->PitBoss().RemoveSubSession(handle, iSession);
       
    81 			}
       
    82 
       
    83 		iSession->SubSessions().Unlock();
       
    84 		}
       
    85 
       
    86 	SetClosing();
       
    87 
       
    88     if (iRSP)
       
    89         {
       
    90 //    	ASSERT(iFlowBinderControl);	// in OOM cases may not have been bound
       
    91 		if(iFlowBinderControl)
       
    92 			{
       
    93 	  		iFlowBinderControl->Unbind();
       
    94 			}
       
    95 		delete iRSP;
       
    96         }
       
    97 
       
    98 	if (!FlowRequestPending())
       
    99 		delete this;
       
   100 	}
       
   101 
       
   102 CHostResolver * CHostResolver::NewLC(CProtocolRef* aProtRef, CSockSession *aSession, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
   103 /**
       
   104 Create a new CHostresolver
       
   105 
       
   106 */
       
   107 	{
       
   108 	CHostResolver* h = new(ELeave) CHostResolver(aSession, aPlayer, aSubSessionUniqueId);
       
   109 	CleanupStack::PushL(h);
       
   110 	h->CreateL(aProtRef);
       
   111 	ESOCK_DEBUG_REGISTER_GENERAL_NODE(ESockDebug::KHostResolverNodeUid, h);
       
   112 	return h;
       
   113 	}
       
   114 
       
   115 void CHostResolver::CreateL(CProtocolRef* aProtRef)
       
   116 	{
       
   117 	CSockSubSession::ConstructL(aProtRef->Protocol());
       
   118 	iBusy=EFalse;
       
   119 	iAwaitingConnection=EFalse;
       
   120 	iProtocolInfo = &(aProtRef->Info());
       
   121 	}
       
   122 
       
   123 void CHostResolver::FinalCompleteAllBlockedMessages(TInt aResult)
       
   124 	{
       
   125 	if(iBusy)
       
   126 		{
       
   127 		CompleteMessage(iBlockedReq, aResult);
       
   128 		}
       
   129 	}
       
   130 
       
   131 void CHostResolver::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
       
   132     {
       
   133     (void) aRecipient;
       
   134 	ESOCK_DEBUG_MESSAGE_INTERCEPT(aSender, aMessage, aRecipient);
       
   135 
       
   136     if (aMessage.IsMessage<TEBase::TError>())
       
   137     	{
       
   138     	//The first error would be from the flow request, any other error iIsFlowRequestPending must be false anyway
       
   139 		if (FlowRequestPending())
       
   140 			{
       
   141 			TEBase::TError& errorMsg(static_cast<TEBase::TError&>(aMessage));
       
   142 			CompleteFlowRequestMessage(errorMsg.iValue);
       
   143 			SetFlowRequestPending(EFalse);
       
   144 			}
       
   145 
       
   146 		//We are no longer needed and the client has been completed too, tear us down.
       
   147 		InitiateDestruction();
       
   148 		}
       
   149     else if (aMessage.IsMessage<TCFDataClient::TBindTo>())
       
   150 		{
       
   151 		// An error here is propagated back to the waiting CFlowRequest
       
   152 		TCFDataClient::TBindTo& bindToMsg(static_cast<TCFDataClient::TBindTo&>(aMessage));
       
   153 		SetFlowRequestPending(EFalse);
       
   154 
       
   155 		TInt err;
       
   156 		if (IsClosing())
       
   157 			{
       
   158 			err = KErrAbort;
       
   159 			}
       
   160 		else
       
   161 			{
       
   162 			TRAP(err,BindToL(bindToMsg));
       
   163 			}
       
   164 
       
   165 		TCFDataClient::TBindToComplete bindCompleteMsg(err);
       
   166 		RClientInterface::OpenPostMessageClose(Id(), aSender,
       
   167 			bindCompleteMsg);
       
   168 
       
   169 		CompleteFlowRequestMessage(err);
       
   170 
       
   171 		if (IsClosing())
       
   172 			{
       
   173 			InitiateDestruction();
       
   174 			}
       
   175 		}
       
   176     else
       
   177         {
       
   178   		__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSockS_RSLV, 1));
       
   179         }
       
   180     }
       
   181 
       
   182 void CHostResolver::BindToL(const TCFDataClient::TBindTo& aBindTo)
       
   183     {
       
   184     __ASSERT_DEBUG(iLowerControl==NULL, User::Panic(KSpecAssert_ESockSSockS_RSLV, 2));
       
   185 #if defined(__GCCXML__)
       
   186     CSubConnectionFlowBase* flow = reinterpret_cast<CSubConnectionFlowBase*>(reinterpret_cast<Messages::ANode*>(aBindTo.iNodeId.Ptr()));
       
   187 #else
       
   188     CSubConnectionFlowBase* flow = mcfnode_cast<CSubConnectionFlowBase>(reinterpret_cast<Messages::ANode*>(aBindTo.iNodeId.Ptr()));
       
   189 #endif
       
   190     if (flow==NULL)
       
   191         {
       
   192         User::Leave(KErrArgument);
       
   193         }
       
   194 
       
   195     NM_LOG((KESockServerTag, _L8("CHostResolver %08x:\tSynchronous call: From=%08x To=%08x Func=BindToL"),
       
   196 			this, static_cast<Messages::ANode*>(this), &aBindTo.iNodeId.Node()) )
       
   197 
       
   198 	iFlowBinderControl = flow->GetBinderControlL();
       
   199 	iLowerControl = iFlowBinderControl->GetControlL(KNullDesC8);
       
   200 	iLowerDataSender = iFlowBinderControl->BindL(KNullDesC8, NULL, this);
       
   201 
       
   202 
       
   203 #ifdef SYMBIAN_NETWORKING_UPS
       
   204 	LOG(ESockLog::Printf(KESockConnectionTag, _L8("CHostResolver %08x:\tBindToL(%08x)"), this, &aBindTo.iNodeId.Node()) );
       
   205 	LOG(ESockLogExternal::Printf(KCFNodeTag, KESockFlowTag, _L8("CHostResolver %08x:\tSynchronous call: Sender=%08x, Recipient=%08x, Function=BindToL"), this, static_cast<ANode*>(this), &aBindTo.iNodeId.Node()) );
       
   206 
       
   207 	// UPS support
       
   208 	InitialiseFlow(flow);
       
   209 #endif
       
   210 
       
   211     LockToConnectionInfo();
       
   212     }
       
   213 
       
   214 #ifdef SYMBIAN_NETWORKING_UPS
       
   215 
       
   216 void CHostResolver::InitialiseFlow(CSubConnectionFlowBase* aFlow)
       
   217 /**
       
   218 Initialise the flow for Host Resolver UPS operation
       
   219 
       
   220 @param aFlow Underlying flow to initialise
       
   221 */
       
   222 	{
       
   223 	CTransportFlowShim* shimFlow = Factories::factoryobject_cast<CTransportFlowShim>(aFlow);
       
   224     if (shimFlow)
       
   225     	{
       
   226     	// Pass the MProvdSecurityChecker down to the CTransportFlowShim so that it can perform
       
   227     	// the Platform Security check.
       
   228     	shimFlow->SecurityCheck(Session());
       
   229 
       
   230     	// Pass the thread/process id down to the CTransportFlowShim as these are required
       
   231     	// to perform UPS authorisation.
       
   232 		TSoOwnerInfo info;
       
   233 		GetOwnerInfo(info.iProcessId, info.iUid, info.iThreadId);
       
   234 
       
   235 		shimFlow->SetOption(KSOLProvider, KSoOwnerInfo, TPckgC<TSoOwnerInfo>(info));
       
   236 
       
   237 		//
       
   238 		// In addition to KSoOwnerInfo, communicate an MPlatSecApiExt instance downwards in order
       
   239 		// to allow dynamic retrieval of process and thread id (rather than the process/thread id
       
   240 		// at the time of the subsession open.  It is not certain that our MPlatsecApiExt can
       
   241 		// actually provide a valid process/thread id all the time, so the KSoOwnerInfo gives
       
   242 		// default values for circumstances where MPlatsecApiExt).
       
   243 		//
       
   244 		// @TODO REQ1116 - clean this whole area up - especially the use of two mechanisms
       
   245 		// "one in case the other doesn't always work".  Can we just use the dynamic one?
       
   246 		//
       
   247 		shimFlow->SetOption(KSOLProvider, KSoSetPlatSecApi, TPckgC<const MPlatsecApiExt*>(this));
       
   248     	}
       
   249 	}
       
   250 #endif
       
   251 
       
   252 TBool CHostResolver::GetFlowAndSCPR(Messages::TNodeId& aFlow, Messages::TNodeId& aSCPR) const
       
   253     {
       
   254     if (iFlowBinderControl)
       
   255         {
       
   256     	aFlow = iFlowBinderControl->Flow()->Id();
       
   257     	aSCPR = iFlowBinderControl->Flow()->ControlProvider().RecipientId();
       
   258     	return ETrue;
       
   259         }
       
   260     return EFalse;
       
   261     }
       
   262 
       
   263 HBufC8* CHostResolver::GetBuffer(HBufC8* apBuf, TInt aBufLenRequired)
       
   264 /**
       
   265 Allocate buffer on heap or reallocate it if required size is more than existing
       
   266 
       
   267 @param    apBuf           pointer to the existing buffer. If NULL new bufeer will be allocated.
       
   268 @param    aBufLenRequired reuired buffer length.
       
   269 @return   pointer to the new buffer
       
   270 @return   NULL in case of memory problems or other errors
       
   271 */
       
   272 	{
       
   273     HBufC8* pBufResult = NULL;
       
   274 
       
   275     if(aBufLenRequired <= 0 )
       
   276 		{
       
   277 		PanicClient(KESockClientPanic, EBadDescriptorLength);
       
   278         return NULL; //-- invalid argument
       
   279 		}
       
   280 
       
   281     if(!apBuf)
       
   282 		{//-- the buffer is not allocated at all, try allocate it
       
   283 		pBufResult = HBufC8::New(aBufLenRequired);
       
   284 		}
       
   285     else
       
   286 		{//-- the buffer is already allocated. Check its size and try to reallocate if
       
   287 		//-- required size is bigger than existing. Otherwise do nothing.
       
   288 
       
   289 		if(apBuf->Des().MaxSize() >= aBufLenRequired)
       
   290 			pBufResult = apBuf; //-- do nothing, existing buffer is big enough
       
   291 		else
       
   292 			{  //-- delete and allocate new buffer to avoid data copying
       
   293 			delete apBuf;
       
   294 			pBufResult = HBufC8::New(aBufLenRequired);
       
   295 			}
       
   296 
       
   297 		}
       
   298 
       
   299     return pBufResult;
       
   300 	}
       
   301 
       
   302 
       
   303 TBool CHostResolver::GetQueryRespBuffer(void)
       
   304 /**
       
   305 Allocate or reallocate buffer for CHostResolver::Query() response data.
       
   306 The length of the buffer obtained from Message().Ptr1(), as it is the 2nd parameter in RHostResolver::Query() that
       
   307 shall contain pointer to the client's TPckgBuf query response data.
       
   308 ipQryRespBuf is used for buffer pointer.
       
   309 
       
   310 @return ETrue if the buffer has been successfully allocated (or increased)
       
   311 */
       
   312 	{
       
   313     //-- obtain the length of the client's buffer and allocate the same buffer on our(server) side.
       
   314     //-- data there will be put by the protocol and then copied to the client side in QueryComplete.
       
   315     //-- we need to append sizeof(TDes8) to the buffer lenght because from client point of view the buffer is TPckgBuf<...>
       
   316     TInt len = iBlockedReq.GetDesLength(1) + sizeof(TDes8);
       
   317 
       
   318     ipQryRespBuf = GetBuffer(ipQryRespBuf, len); //-- claim buffer big enough for query response data
       
   319 
       
   320     if(ipQryRespBuf)
       
   321 		{//-- memory allocated, store TPtr8 associated with buffer on the heap, which
       
   322 		//-- can be used later in asynchonous environment by the protocol.
       
   323         iPtrQryResBuf.Set(ipQryRespBuf->Des());
       
   324         return ETrue;
       
   325 		}
       
   326     else
       
   327 		{//-- memory alocation failure
       
   328         iPtrQryResBuf.Set(NULL, 0, 0);
       
   329         return EFalse;
       
   330 		}
       
   331 	}
       
   332 
       
   333 
       
   334 TBool CHostResolver::GetQueryBuffer(void)
       
   335 /**
       
   336 Allocate or reallocate buffer for CHostResolver::Query() data.
       
   337 The length of the buffer obtained from Message().Ptr0(), as it is the 1st parameter in RHostResolver::Query() that
       
   338 shall contain pointer to the client's TPckgBuf query data.
       
   339 
       
   340 @return ETrue if the buffer has been successfully allocated (or increased)
       
   341 */
       
   342 {
       
   343     TInt len = iBlockedReq.GetDesLength(0) + sizeof(TDes8);
       
   344 //    TInt len = iBlockedReq.Client().GetDesLength(Message().Ptr0()) + sizeof(TDes8);
       
   345 
       
   346     ipQryBuf = GetBuffer(ipQryBuf, len); //-- claim buffer big enough for query data
       
   347 
       
   348     if(ipQryBuf)
       
   349     {//-- memory allocated, store TPtr8 associated with buffer on the heap, which
       
   350      //-- can be used later in asynchonous environment by the protocol.
       
   351         iPtrQryBuf.Set(ipQryBuf->Des());
       
   352         return ETrue;
       
   353     }
       
   354     else
       
   355     {//-- memory alocation failure
       
   356         iPtrQryBuf.Set(NULL, 0, 0);
       
   357         return EFalse;
       
   358     }
       
   359 }
       
   360 
       
   361 void CHostResolver::QueryL(void)
       
   362 /**
       
   363 Host Resolver Query implementation
       
   364 Query the current protocol and obtain the result
       
   365 
       
   366 */
       
   367 	{
       
   368 	if (iBusy)
       
   369 		{
       
   370 		PanicClient(KESockClientPanic, ETwice);
       
   371 		SetReturn(KErrInUse);
       
   372 		return;
       
   373 		}
       
   374 
       
   375 	iBlockedReq=Message();
       
   376 
       
   377     //-- allocate or reallocate buffer for query and query  response.
       
   378     if(! GetQueryRespBuffer() || ! GetQueryBuffer())
       
   379 		{//-- buffer hasn't been allocated
       
   380         SetReturn(KErrNoMemory);
       
   381 		return;
       
   382 		}
       
   383 
       
   384 	//-- read query data from client's buffer to the CHostResolver's internal one
       
   385     //-- Ptr0() points to client's Query data buffer, Ptr1() - to the client's query response
       
   386    	SafeMessage().ReadL(0, iPtrQryBuf);
       
   387 
       
   388 	iBusy=ETrue;
       
   389 	iAwaitingConnection = EFalse;
       
   390 	DontCompleteCurrentRequest();
       
   391 
       
   392 	iCurrentOp=EHrQuery;
       
   393 
       
   394 
       
   395 	iCount=0;
       
   396 
       
   397     //-- call CHostResolvProvdBase Query method implemented in appropriate protocol
       
   398     iRSP->Query(iPtrQryBuf, iPtrQryResBuf, iCount);
       
   399 	}
       
   400 
       
   401 void CHostResolver::QueryGetNext(void)
       
   402 /**
       
   403 Host Resolver QueryGetNext implementation.
       
   404 Obtain the next query result.
       
   405 
       
   406 */
       
   407 	{
       
   408 	if (iBusy)
       
   409 		{
       
   410 		PanicClient(KESockClientPanic, ETwice);
       
   411 		SetReturn(KErrInUse);
       
   412 		return;
       
   413 		}
       
   414 
       
   415 	if(iCount<1)
       
   416 		{//-- tried to call QueryGetNext() before Query()
       
   417 		PanicClient(KESockClientPanic, ENoQueryFirst);
       
   418 		SetReturn(KErrNotFound);
       
   419 		return;
       
   420 		}
       
   421 
       
   422 	iBusy=ETrue;
       
   423 	iBlockedReq=Message();
       
   424 	DontCompleteCurrentRequest();
       
   425 
       
   426 	//-- call CHostResolvProvdBase QueryGetNext method implemented in appropriate protocol
       
   427 	if(iCurrentOp == EHrQuery)
       
   428 		{	//-- iCount is incremented in QueryComplete,
       
   429         //-- iQryBuf isn't supposed to be in use here.
       
   430         //-- buffer for response ipQryRespBuf must have been allocated by CHostResolver::Query
       
   431         if(!ipQryRespBuf)
       
   432 			{//-- buffer hasn't been allocated, it means memory problems
       
   433             SetReturn(KErrNoMemory);
       
   434 			return;
       
   435 			}
       
   436 
       
   437         iRSP->Query(iPtrQryBuf, iPtrQryResBuf, iCount);
       
   438 		}
       
   439 
       
   440 	}
       
   441 
       
   442 
       
   443 void CHostResolver::GetByNameL()
       
   444 /**
       
   445 Start a get by name query
       
   446 
       
   447 */
       
   448 	{
       
   449 	if (iBusy)
       
   450 		{
       
   451 		PanicClient(KESockClientPanic, ETwice);
       
   452 		SetReturn(KErrInUse);
       
   453 		return;
       
   454 		}
       
   455 
       
   456 	SafeMessage().ReadL(MSG_PRM(0),iNameRec.iName);
       
   457 
       
   458 	iBusy=ETrue;
       
   459 	iAwaitingConnection = EFalse;
       
   460 	iBlockedReq=Message();
       
   461 	DontCompleteCurrentRequest();
       
   462 
       
   463 	iCurrentOp=EHRGetByName;
       
   464 	iCount=0;
       
   465 	iNameRec.iFlags=iCount;
       
   466 	iRSP->GetByName(iNameRec);
       
   467 	}
       
   468 
       
   469 void CHostResolver::Next()
       
   470 /**
       
   471 Retrieve next record
       
   472 
       
   473 */
       
   474 	{
       
   475 	if (iBusy)
       
   476 		{
       
   477 		PanicClient(KESockClientPanic, ETwice);
       
   478 		SetReturn(KErrInUse);
       
   479 		return;
       
   480 		}
       
   481 
       
   482 	if(iCount<1)
       
   483 		{
       
   484 		PanicClient(KESockClientPanic, ENoResolveFirst);
       
   485 		SetReturn(KErrNotFound);
       
   486 		return;
       
   487 		}
       
   488 
       
   489 	iBusy=ETrue;
       
   490 	iBlockedReq=Message();
       
   491 	DontCompleteCurrentRequest();
       
   492 
       
   493 	iNameRec.iFlags=iCount;
       
   494 	if(iCurrentOp==EHRGetByName)
       
   495 		iRSP->GetByName(iNameRec);
       
   496 	else
       
   497 		iRSP->GetByAddress(iNameRec);
       
   498 	}
       
   499 
       
   500 void CHostResolver::GetByAddressL()
       
   501 /**
       
   502 Start a get by address query
       
   503 
       
   504 */
       
   505 	{
       
   506 	if (iBusy)
       
   507 		{
       
   508 		PanicClient(KESockClientPanic, ETwice);
       
   509 		SetReturn(KErrInUse);
       
   510 		return;
       
   511 		}
       
   512 
       
   513 	SafeMessage().ReadL(MSG_PRM(0),iNameRec.iAddr);
       
   514 
       
   515 	iBusy=ETrue;
       
   516 	iBlockedReq=Message();
       
   517 	DontCompleteCurrentRequest();
       
   518 
       
   519 	iCurrentOp=EHRGetByAddress;
       
   520 
       
   521 	iCount=0;
       
   522 	iNameRec.iFlags=iCount;
       
   523 	iRSP->GetByAddress(iNameRec);
       
   524 	}
       
   525 
       
   526 void CHostResolver::GetHostName()
       
   527 /**
       
   528 Get the name of the local host
       
   529 
       
   530 */
       
   531 	{
       
   532     iCurrentOp = EHRGetHostName;
       
   533 	if (iBusy)
       
   534 		{
       
   535 		PanicClient(KESockClientPanic, ETwice);
       
   536 		SetReturn(KErrInUse);
       
   537 		return;
       
   538 		}
       
   539 
       
   540 	iBusy=ETrue;
       
   541 	iBlockedReq=Message();
       
   542 	DontCompleteCurrentRequest();
       
   543 
       
   544 	iRSP->GetHostName(iNameRec.iName);
       
   545 	}
       
   546 
       
   547 void CHostResolver::SetHostNameL()
       
   548 /**
       
   549 Set the name of the host machine
       
   550 
       
   551 */
       
   552 	{
       
   553    iCurrentOp = EHRSetHostName;
       
   554 	if (iBusy)
       
   555 		{
       
   556 		PanicClient(KESockClientPanic, ETwice);
       
   557 		SetReturn(KErrInUse);
       
   558 		return;
       
   559 		}
       
   560 	THostName n;
       
   561 	SafeMessage().ReadL(MSG_PRM(0),n);
       
   562 
       
   563 	iBusy=ETrue;
       
   564 	iBlockedReq=Message();
       
   565 	DontCompleteCurrentRequest();
       
   566 
       
   567 	iRSP->SetHostName(n);
       
   568 	}
       
   569 
       
   570 void CHostResolver::SetOptionL()
       
   571 	{
       
   572 	iCurrentOp = EHRSetOpt;
       
   573 	if (iBusy)
       
   574 		{
       
   575 		PanicClient(KESockClientPanic, ETwice);
       
   576 		SetReturn(KErrInUse);
       
   577 		return;
       
   578 		}
       
   579 
       
   580 	ReadAndSetOptionL();
       
   581 	
       
   582 	}
       
   583 
       
   584 
       
   585 void CHostResolver::Cancel()
       
   586 /**
       
   587 Cancel any pending request
       
   588 
       
   589 */
       
   590 	{
       
   591 	if (!iBusy)
       
   592 		return;
       
   593 
       
   594 	iBusy=EFalse;
       
   595 	iCount=0;
       
   596 
       
   597 	CompleteMessage(iBlockedReq, KErrCancel);
       
   598 	iRSP->CancelCurrentOperation();
       
   599 	}
       
   600 
       
   601 void CHostResolver::QueryComplete(TInt anError)
       
   602 /**
       
   603 outstanding request has completed
       
   604 
       
   605 */
       
   606 	{
       
   607 	LOG(ESockLog::Printf(KESockConnectionTag, _L8("CHostResolver %08x:\tQueryComplete(TInt anError)\taError %d"), this, anError) );
       
   608 
       
   609 	if(!iBusy)
       
   610 		return;
       
   611 
       
   612 	Den::RSafeMessage& message = static_cast<Den::RSafeMessage&>(const_cast<RMessage2&>(iBlockedReq));
       
   613 	if (anError == KErrCompletion && RequiresConnectionStartup())
       
   614 		{
       
   615 		//
       
   616 		// KErrCompletion from Host Resolvers that require connection startup indicates that
       
   617 		// the name was not found locally, a connection needs to be started, and the
       
   618 		// GetByName() re-issued.   In some ways, this is the equivalent of CSocket::NoBearer().
       
   619 		//
       
   620  		TRAP(anError,HandleConnectionSetupL());
       
   621  		if ( anError == KErrNone )
       
   622  			{
       
   623 			return;
       
   624  			}
       
   625 #ifdef SYMBIAN_NETWORKING_UPS
       
   626  		else
       
   627  		if (anError == KErrPermissionDenied)
       
   628 			{
       
   629 			// This code path supports the UPS "Disabled" configuration.  A KErrPermissionDenied error
       
   630 			// is returned if the platsec capability check failed.  See if the provider has an error
       
   631 			// code that it prefers to complete the request with.  This supports the behaviour in the
       
   632 			// TCP provider whereby the lack of capabilities means that the request is looked up locally
       
   633 			// without using the network and, if not found, a provider specific error code is returned
       
   634 			// rather than KErrPermissionDenied.
       
   635 			TInt err = iRSP->SetOption(KSOLProvider, KSoGetErrorCode, KNullDesC8());
       
   636 			if (err > 0)
       
   637 				{
       
   638 				anError = -err;
       
   639 				}
       
   640 			}
       
   641 #endif //SYMBIAN_NETWORKING_UPS
       
   642 		}
       
   643 	else
       
   644 	if (anError==KErrNone)
       
   645 		{
       
   646 		switch (iBlockedReq.Function())
       
   647 			{
       
   648 		case EHRNext:
       
   649 		case EHRGetByName:
       
   650 		case EHRGetByAddress:
       
   651 			{
       
   652 			TInt ret = message.Write(MSG_PRM(1),TPtr8((TUint8 *)&iNameRec,sizeof(iNameRec),sizeof(iNameRec)));
       
   653 			if(ret!=KErrNone)
       
   654 				{
       
   655 				iBusy=EFalse;
       
   656 				return;
       
   657 				}
       
   658 			++iCount;
       
   659 			break;
       
   660 			}
       
   661 		case EHRGetHostName:
       
   662 			{
       
   663 			TInt ret = message.Write(MSG_PRM(0),iNameRec.iName);
       
   664 			if(ret!=KErrNone)
       
   665 				{
       
   666 				iBusy=EFalse;
       
   667 				return;
       
   668 				}
       
   669 			break;
       
   670 			}
       
   671 		case EHRSetHostName:
       
   672 		case EHRSetOpt:
       
   673 			break;
       
   674 
       
   675         //-- protocol has completed Query or QueryNext write query response data into the client's buffer
       
   676         case EHrQuery:
       
   677             if(ipQryRespBuf)
       
   678             {
       
   679                 TInt ret = message.Write(1, iPtrQryResBuf);
       
   680 				if(ret!=KErrNone)
       
   681 					{
       
   682 					iBusy=EFalse;
       
   683 					return;
       
   684 					}
       
   685 				++iCount;
       
   686 			}
       
   687             else
       
   688               Panic(EBadErrorCall);
       
   689         break;
       
   690 
       
   691         case EHrQueryNext:
       
   692             if(ipQryRespBuf)
       
   693             {
       
   694 				TInt ret = message.Write(0, iPtrQryResBuf);
       
   695 				if(ret!=KErrNone)
       
   696 					{
       
   697 					iBusy=EFalse;
       
   698 					return;
       
   699 					}
       
   700 				++iCount;
       
   701 			}
       
   702             else
       
   703                 Panic(EBadErrorCall);
       
   704         break;
       
   705 
       
   706     	default:
       
   707 			Panic(ENothingToComplete);
       
   708 			}
       
   709 		}
       
   710 	else
       
   711 		iCount=0;
       
   712 
       
   713 	iBusy=EFalse;
       
   714 	iAwaitingConnection = EFalse;
       
   715 	message.Complete(anError);
       
   716 	}
       
   717 
       
   718 //
       
   719 //TBool CHostResolver::FetchOwnerInfo(CConnectionProviderBase::TEnumClients aClientType, TProcessId& aProcessId, TUidType& aUidType, TThreadId& aThreadId)
       
   720 //	{
       
   721 //	TBool b = aClientType == CConnectionProviderBase::EAll || aClientType == CConnectionProviderBase::EHostResolver;
       
   722 //	if ( b )
       
   723 //		{
       
   724 //		GetOwnerInfo( aProcessId, aUidType, aThreadId);
       
   725 //		}
       
   726 //	return b;
       
   727 //	}
       
   728 //
       
   729 
       
   730 void CHostResolver::StartSending()
       
   731 /**
       
   732 Called when we have got a valid connection info that we can set
       
   733 
       
   734 */
       
   735     {
       
   736 	LOG(ESockLog::Printf(KESockConnectionTag, _L8("CHostResolver %08x:\tStartSending() iBusy %d, iAwaitingConnection %d"), this,iBusy,iAwaitingConnection) );
       
   737 	LockToConnectionInfo();
       
   738 	if (iBusy && iAwaitingConnection)
       
   739 		{
       
   740 		switch (iCurrentOp)
       
   741 			{
       
   742 		case EHRGetByName:
       
   743 			iRSP->GetByName(iNameRec);
       
   744 			break;
       
   745 		case EHRGetByAddress:
       
   746 			iRSP->GetByAddress(iNameRec);
       
   747 			break;
       
   748 
       
   749         case EHrQuery:
       
   750 
       
   751             if(! GetQueryRespBuffer())
       
   752 	        {//-- buffer hasn't been allocated
       
   753                 SetReturn(KErrNoMemory);
       
   754 		        break;
       
   755 	        }
       
   756             else
       
   757             {
       
   758                 //-- call CHostResolvProvdBase Query method implemented in appropriate protocol
       
   759                iRSP->Query(iPtrQryBuf, iPtrQryResBuf, iCount);
       
   760             }
       
   761 			break;
       
   762 
       
   763 		case EHRGetHostName:
       
   764 			iRSP->GetHostName(iNameRec.iName);
       
   765 			break;
       
   766 
       
   767 		case EHRSetHostName:
       
   768 			{
       
   769 			THostName n;
       
   770 			SafeMessage().ReadL(MSG_PRM(0),n);
       
   771 			iRSP->SetHostName(n);
       
   772 			}
       
   773 			break;
       
   774 			
       
   775 
       
   776 		case EHRSetOpt:
       
   777 			{
       
   778 			TInt err;
       
   779 			TRAP(err,ReadAndSetOptionL());	
       
   780 			if(err != KErrNone)
       
   781 				{
       
   782 				SetReturn(err);
       
   783 				}
       
   784 			}
       
   785 			break;
       
   786 
       
   787 		default:
       
   788 			Panic(ENothingToComplete);
       
   789 			}
       
   790 		}
       
   791 	iAwaitingConnection = EFalse;
       
   792     }
       
   793 
       
   794 void CHostResolver::Error(TInt aError)
       
   795 	{
       
   796 	LOG(ESockLog::Printf(KESockConnectionTag, _L8("CHostResolver %08x:\tError(aError %d)"), this, aError) );
       
   797 
       
   798 #ifdef SYMBIAN_NETWORKING_UPS
       
   799 	if (aError == KErrPermissionDenied)
       
   800 		{
       
   801 		// UPS support.  We received a TError in response to a TNoBearer sent previously, indicating
       
   802 		// UPS authorisation failure.
       
   803 		//
       
   804 		// ASSERT(incoming message is a TError with iMsgId set to TNoBearer)
       
   805 		//
       
   806 		// See if the provider has an error code that it prefers to complete the request with.
       
   807 		// This supports the behaviour in the TCP provider whereby the lack of capabilities
       
   808 		// (lack of authorisation when using UPS) means that the request is looked up locally
       
   809 		// without using the network and, if not found, a provider specific error code is returned.
       
   810 		//
       
   811 		// The SetOption() interface towards Host Resolver SAPs does not allow for the
       
   812 		// retrieval of a TInt value (being a const interface).  So take a positive return value
       
   813 		// to represent a valid error code to use.
       
   814 
       
   815 		TInt err = iRSP->SetOption(KSOLProvider, KSoGetErrorCode, KNullDesC8());
       
   816 		if (err > 0)
       
   817 			{
       
   818 			aError = -err;
       
   819 			}
       
   820 		}
       
   821 #endif //SYMBIAN_NETWORKING_UPS
       
   822 
       
   823 	QueryComplete(aError);
       
   824 	iAwaitingConnection = EFalse;
       
   825 	TBuf8<sizeof(TConnectionInfo)> buf;
       
   826 	if (aError == KErrBindersInvalid)
       
   827 	    {
       
   828         iLowerControl = NULL;
       
   829     	iFlowBinderControl = NULL;
       
   830 	    iLowerDataSender = NULL;
       
   831 	    }
       
   832 	else if (aError == KErrDisconnected || iLowerControl->Control((TUint)KSOLProvider, (TUint)KSoConnectionInfo, buf)!=KErrNone)
       
   833 	    {
       
   834     	//reset the scope
       
   835     	TConnectionInfo info(0,0);
       
   836     	TPckg<TConnectionInfo> infoBuf(info);
       
   837 
       
   838     	LockToConnectionInfo(infoBuf);
       
   839 	    }
       
   840     }
       
   841 
       
   842 void CHostResolver::HandleConnectionSetupL()
       
   843 /**
       
   844 Handle any implicit connection setup which is required as a result of a Host Resolver request.
       
   845 
       
   846 */
       
   847 	{
       
   848 	LOG(ESockLog::Printf(KESockConnectionTag, _L8("CHostResolver %08x:\tHandleConnectionSetup selecting....."), this) );
       
   849 
       
   850 	iAwaitingConnection = ETrue;
       
   851 
       
   852 	// Workaround to kick off the flow set-up
       
   853 	RMBufChain dummy;
       
   854 #ifdef SYMBIAN_NETWORKING_UPS
       
   855 	User::LeaveIfError(iLowerDataSender->Send(dummy));
       
   856 #else
       
   857 	iLowerDataSender->Send(dummy);
       
   858 #endif
       
   859 	}
       
   860 
       
   861 void CHostResolver::LockToConnectionInfo()
       
   862     {
       
   863     // retrieve default connection info
       
   864     TPckgBuf<TConnectionInfo> info;
       
   865     __ASSERT_DEBUG(iLowerControl!=NULL, User::Panic(KSpecAssert_ESockSSockS_RSLV, 3));
       
   866     iLowerControl->Control((TUint)KSOLProvider, (TUint)KSoConnectionInfo, info);
       
   867 
       
   868     // set host resolver connection info
       
   869 	TPckgBuf<TSoIfConnectionInfo> ifInfo;
       
   870     ifInfo().iIAPId = info().iIapId;
       
   871 	ifInfo().iNetworkId = info().iNetId;
       
   872     LockToConnectionInfo(ifInfo);
       
   873     }
       
   874 
       
   875 void CHostResolver::LockToConnectionInfo(const TDesC8& aConnectionInfo)
       
   876 /**
       
   877 Called when interface selection has completed in order to communicate the connection
       
   878 information to the Host Resolver.
       
   879 
       
   880 @param aConnectionInfo Connection information identifying the interface
       
   881 */
       
   882 	{
       
   883 	if (aConnectionInfo.Length() > 0)
       
   884 		{
       
   885 		LOG( ESockLog::ConnectionInfoPrintf(aConnectionInfo, _L("CHostResolver %08x:\tLockToConnectionInfo()"), this) );
       
   886 		iRSP->SetOption(KSOLProvider, static_cast<TUint>(KSoConnectionInfo), aConnectionInfo);
       
   887 		}
       
   888 	}
       
   889 
       
   890 
       
   891 void CHostResolver::ProcessMessageL()
       
   892 	{
       
   893 	switch(Message().Function())
       
   894 		{
       
   895 	   case EHRGetByName:
       
   896 			GetByNameL();
       
   897 			break;
       
   898 
       
   899 		case EHRNext:
       
   900 			Next();
       
   901 			break;
       
   902 
       
   903 		case EHRGetByAddress:
       
   904 			GetByAddressL();
       
   905 			break;
       
   906 
       
   907 		case EHRGetHostName:
       
   908 			GetHostName();
       
   909 			break;
       
   910 
       
   911 		case EHRSetHostName:
       
   912 			SetHostNameL();
       
   913 			break;
       
   914 
       
   915 		case EHRCancel:
       
   916 			Cancel();
       
   917 			break;
       
   918 
       
   919 		case EHrQuery:
       
   920 			QueryL();
       
   921 			break;
       
   922 
       
   923 		case EHrQueryNext:
       
   924 			QueryGetNext();
       
   925 			break;
       
   926 
       
   927 	    case EHRClose:
       
   928 	    	InitiateDestruction();
       
   929 			break;
       
   930 			
       
   931 	    case EHRSetOpt:
       
   932 	    	SetOptionL();
       
   933 	    	break;
       
   934 			
       
   935 		default:
       
   936 			SetReturn(KErrNotSupported);
       
   937 		}
       
   938 	}
       
   939 
       
   940 #ifdef SYMBIAN_NETWORKING_UPS
       
   941 TInt CHostResolver::GetProcessAndThreadId(TProcessId& aProcessId, TThreadId& aThreadId) const
       
   942 	{
       
   943 	if (iBusy && !iBlockedReq.IsNull())
       
   944 		{
       
   945 		return ASockSubSessionPlatsecApiExt::GetProcessAndThreadIdFromRMessage(iBlockedReq, aProcessId, aThreadId);
       
   946 		}
       
   947 	else
       
   948 		{
       
   949 		return KErrNotFound;
       
   950 		}
       
   951 	}
       
   952 #endif
       
   953 
       
   954 void CHostResolver::ReadAndSetOptionL()
       
   955 	{
       
   956 
       
   957 	TInt optionName=Message().Int0();
       
   958 	TInt optionLevel=Message().Int2();
       
   959 
       
   960 	RBuf8 setOptionBuf;  
       
   961 	setOptionBuf.CreateL(Message().GetDesLengthL(1)); //1 - is the option that is passed 
       
   962 	CleanupClosePushL(setOptionBuf);
       
   963 	SafeMessage().ReadL(MSG_PRM(1),setOptionBuf);
       
   964 
       
   965 	TPtrC8 setOptionPtr(setOptionBuf);
       
   966  	SetReturn(iRSP->SetOption(optionLevel,optionName,setOptionPtr));
       
   967 	
       
   968 	CleanupStack::PopAndDestroy();
       
   969 
       
   970 	}
       
   971 
       
   972 
       
   973 // ============================================================================================
       
   974 
       
   975 CServiceResolver::CServiceResolver(CSockSession* aSession, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
   976 /**
       
   977 Constructor - set up default options.
       
   978 
       
   979 */
       
   980 : CSockSubSession(aSession, aPlayer, aSubSessionUniqueId)
       
   981 	{
       
   982 	}
       
   983 
       
   984 CServiceResolver * CServiceResolver::NewLC(CProtocolRef* aProtRef, CSockSession *aSession, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
   985 /**
       
   986 Create a new CService resolver
       
   987 */
       
   988 	{
       
   989 	CServiceResolver* r = new(ELeave) CServiceResolver(aSession, aPlayer, aSubSessionUniqueId);
       
   990 	CleanupStack::PushL(r);
       
   991 	r->ConstructL(aProtRef->Protocol());
       
   992 	r->iSession=aSession;
       
   993 	return r;
       
   994 	}
       
   995 
       
   996 void CServiceResolver::FinalCompleteAllBlockedMessages(TInt aResult)
       
   997 	{
       
   998 	if(iBusy)
       
   999 		{
       
  1000 		CompleteMessage(iBlockedReq, aResult);
       
  1001 		}
       
  1002 	}
       
  1003 
       
  1004 void CServiceResolver::GetByNameL()
       
  1005 /**
       
  1006 Start a get by name query
       
  1007 
       
  1008 */
       
  1009 	{
       
  1010 	if (iBusy)
       
  1011 		{
       
  1012 		PanicClient(KESockClientPanic, ETwice);
       
  1013 		SetReturn(KErrInUse);
       
  1014 		return;
       
  1015 		}
       
  1016 
       
  1017 	SafeMessage().ReadL(MSG_PRM(0),iNameBuf);
       
  1018 
       
  1019 	iBusy=ETrue;
       
  1020 	iBlockedReq=Message();
       
  1021 	DontCompleteCurrentRequest();
       
  1022 
       
  1023 	iRSP->GetByName(iNameBuf,iPortNum);
       
  1024 	}
       
  1025 
       
  1026 void CServiceResolver::GetByNumber()
       
  1027 /**
       
  1028 Start a get by number query
       
  1029 
       
  1030 */
       
  1031 	{
       
  1032 	if (iBusy)
       
  1033 		{
       
  1034 		PanicClient(KESockClientPanic, ETwice);
       
  1035 		SetReturn(KErrInUse);
       
  1036 		return;
       
  1037 		}
       
  1038 
       
  1039 	iBusy=ETrue;
       
  1040 	iBlockedReq=Message();
       
  1041 	DontCompleteCurrentRequest();
       
  1042 
       
  1043 	iRSP->GetByNumber(iNameBuf,Message().Int1());
       
  1044 	}
       
  1045 
       
  1046 void CServiceResolver::RegisterServiceL()
       
  1047 /**
       
  1048 Register a new service
       
  1049 
       
  1050 */
       
  1051 	{
       
  1052 	if (iBusy)
       
  1053 		{
       
  1054 		PanicClient(KESockClientPanic, ETwice);
       
  1055 		SetReturn(KErrInUse);
       
  1056 		return;
       
  1057 		}
       
  1058 
       
  1059 
       
  1060 	SafeMessage().ReadL(MSG_PRM(0),iNameBuf);
       
  1061 
       
  1062 	iBusy=ETrue;
       
  1063 	iBlockedReq=Message();
       
  1064 	DontCompleteCurrentRequest();
       
  1065 
       
  1066 	iPortNum=Message().Int1();
       
  1067 	iRSP->RegisterService(iNameBuf,iPortNum);
       
  1068 	}
       
  1069 
       
  1070 void CServiceResolver::RemoveServiceL()
       
  1071 /**
       
  1072 delete an entry in the services database
       
  1073 */
       
  1074 	{
       
  1075 	if (iBusy)
       
  1076 		{
       
  1077 		PanicClient(KESockClientPanic, ETwice);
       
  1078 		SetReturn(KErrInUse);
       
  1079 		return;
       
  1080 		}
       
  1081 
       
  1082 	SafeMessage().ReadL(MSG_PRM(0),iNameBuf);
       
  1083 	iBusy=ETrue;
       
  1084 	iBlockedReq=Message();
       
  1085 	DontCompleteCurrentRequest();
       
  1086 
       
  1087 	iPortNum=Message().Int1();
       
  1088 	iRSP->RemoveService(iNameBuf,iPortNum);
       
  1089 	}
       
  1090 
       
  1091 void CServiceResolver::Cancel()
       
  1092 /**
       
  1093 Cancel any pending request
       
  1094 
       
  1095 */
       
  1096 	{
       
  1097 	if (!iBusy)
       
  1098 		return;
       
  1099 
       
  1100 	iBusy=EFalse;
       
  1101 	CompleteMessage(iBlockedReq, KErrCancel);
       
  1102 	iRSP->CancelCurrentOperation();
       
  1103 	}
       
  1104 
       
  1105 
       
  1106 void CServiceResolver::QueryComplete(TInt anError)
       
  1107 /**
       
  1108 a request has completed
       
  1109 */
       
  1110 	{
       
  1111 
       
  1112 	//__ASSERT_DEBUG(iBusy,PanicClient(Message(), EBadQueyComplete));
       
  1113 	if(!iBusy)
       
  1114 		return;
       
  1115 
       
  1116 	Den::RSafeMessage& message = static_cast<Den::RSafeMessage&>(const_cast<RMessage2&>(iBlockedReq));
       
  1117 
       
  1118 	LOG(ESockLog::Printf(KESockConnectionTag, _L8("CServiceResolver %08x:\tQueryComplete(TInt anError)\t aError %d, message %08X"), this, anError, message.Handle()) );
       
  1119 
       
  1120 	TPortNum num;
       
  1121 
       
  1122 	if (anError==KErrNone)
       
  1123 		switch (iBlockedReq.Function())
       
  1124 			{
       
  1125 		case ESRGetByName:
       
  1126 			{
       
  1127 			num=iPortNum;
       
  1128 			TInt ret = message.Write(MSG_PRM(1),num);
       
  1129 			if(ret!=KErrNone)
       
  1130 				{
       
  1131 				iBusy=EFalse;
       
  1132 				return;
       
  1133 				}
       
  1134 			break;
       
  1135 			}
       
  1136 		case ESRGetByNumber:
       
  1137 			{
       
  1138 			TInt ret = message.Write(MSG_PRM(0),iNameBuf);
       
  1139 			if(ret!=KErrNone)
       
  1140 				{
       
  1141 				iBusy=EFalse;
       
  1142 				return;
       
  1143 				}
       
  1144 			break;
       
  1145 			}
       
  1146 		case ESRRegisterService:
       
  1147 		case ESRRemoveService:
       
  1148 			break;
       
  1149 		default:
       
  1150 			Panic(ENothingToComplete);
       
  1151 			}
       
  1152 
       
  1153 	iBusy=EFalse;
       
  1154 	message.Complete(anError);
       
  1155 	}
       
  1156 
       
  1157 CServiceResolver::~CServiceResolver()
       
  1158 	{
       
  1159 	delete iRSP;
       
  1160 	}
       
  1161 
       
  1162 void CServiceResolver::ProcessMessageL()
       
  1163 	{
       
  1164 	switch(Message().Function())
       
  1165 		{
       
  1166 		case ESRGetByName:
       
  1167 			GetByNameL();
       
  1168 			break;
       
  1169 
       
  1170 		case ESRGetByNumber:
       
  1171 			GetByNumber();
       
  1172 			break;
       
  1173 
       
  1174 		case ESRRegisterService:
       
  1175 			RegisterServiceL();
       
  1176 			break;
       
  1177 
       
  1178 		case ESRRemoveService:
       
  1179 			RemoveServiceL();
       
  1180 			break;
       
  1181 
       
  1182 		case ESRCancel:
       
  1183 			Cancel();
       
  1184 			break;
       
  1185 
       
  1186 		case ESRClose:
       
  1187 			delete this;
       
  1188 			break;
       
  1189 
       
  1190 		default:
       
  1191 			SetReturn(KErrNotSupported);
       
  1192 		}
       
  1193 	}
       
  1194 CNetDatabase* CNetDatabase::NewLC(CProtocolRef* aProtRef, CSockSession *aSession, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
  1195 /**
       
  1196 Create a new CNetDatabase
       
  1197 */
       
  1198 	{
       
  1199 	CNetDatabase* n = new(ELeave) CNetDatabase(aSession, aPlayer, aSubSessionUniqueId);
       
  1200 	CleanupStack::PushL(n);
       
  1201 	n->ConstructL(aProtRef->Protocol());
       
  1202 	n->iSession=aSession;
       
  1203 	return n;
       
  1204 	}
       
  1205 
       
  1206 
       
  1207 CNetDatabase::CNetDatabase(CSockSession *aSession, CPlayer* aPlayer, const TSubSessionUniqueId aSubSessionUniqueId)
       
  1208 /**
       
  1209 Constructor - set up default options.
       
  1210 */
       
  1211 : CSockSubSession(aSession, aPlayer, aSubSessionUniqueId)
       
  1212 	{
       
  1213 	}
       
  1214 
       
  1215 void CNetDatabase::FinalCompleteAllBlockedMessages(TInt aResult)
       
  1216 	{
       
  1217 	if(iBusy)
       
  1218 		{
       
  1219 		CompleteMessage(iBlockedReq, aResult);
       
  1220 		}
       
  1221 	}
       
  1222 
       
  1223 void CNetDatabase::RequestL()
       
  1224 /**
       
  1225 Perform a query
       
  1226 */
       
  1227 	{
       
  1228 	if (iBusy)
       
  1229 		{
       
  1230 		PanicClient(KESockClientPanic, ETwice);
       
  1231 		SetReturn(KErrInUse);
       
  1232 		return;
       
  1233 		}
       
  1234 
       
  1235 	delete iBuf;
       
  1236 	iBuf=0;
       
  1237 	iBuf=HBufC8::NewMaxL(Message().Int1());
       
  1238 
       
  1239 	delete iBufPtr;
       
  1240 	iBufPtr=0;
       
  1241 	iBufPtr=new(ELeave) TPtr8(iBuf->Des());
       
  1242 
       
  1243 	SafeMessage().ReadL(MSG_PRM(0),*iBufPtr);
       
  1244 
       
  1245 	iBusy=ETrue;
       
  1246 	iBlockedReq=Message();
       
  1247 	DontCompleteCurrentRequest();
       
  1248 
       
  1249 
       
  1250 	switch (Message().Function())
       
  1251 		{
       
  1252 	case ENDQuery:
       
  1253 		iRSP->Query(*iBufPtr);
       
  1254 		break;
       
  1255 	case ENDAdd:
       
  1256 		iRSP->Add(*iBufPtr);
       
  1257 		break;
       
  1258 	case ENDRemove:
       
  1259 		iRSP->Remove(*iBufPtr);
       
  1260 		break;
       
  1261 		}
       
  1262 	}
       
  1263 
       
  1264 void CNetDatabase::Cancel()
       
  1265 /**
       
  1266 Cancel any pending request
       
  1267 */
       
  1268 	{
       
  1269 	if (!iBusy)
       
  1270 		return;
       
  1271 
       
  1272 	iBusy=EFalse;
       
  1273 	CompleteMessage(iBlockedReq, KErrCancel);
       
  1274 	iRSP->CancelCurrentOperation();
       
  1275 	}
       
  1276 
       
  1277 void CNetDatabase::QueryComplete(TInt anError)
       
  1278 /**
       
  1279 An outstanding query had completed
       
  1280 */
       
  1281 	{
       
  1282 
       
  1283 	if(!iBusy)
       
  1284 		return;
       
  1285 	Den::RSafeMessage& message = static_cast<Den::RSafeMessage&>(const_cast<RMessage2&>(iBlockedReq));
       
  1286 
       
  1287 	if (anError==KErrNone && iBlockedReq.Function()==ENDQuery)
       
  1288 		{
       
  1289 		TInt ret = message.Write(MSG_PRM(2),*iBufPtr);
       
  1290 		if(ret!=KErrNone)
       
  1291 			{
       
  1292 			iBusy=EFalse;
       
  1293 			return;
       
  1294 			}
       
  1295 		}
       
  1296 	iBusy=EFalse;
       
  1297 	message.Complete(anError);
       
  1298 	}
       
  1299 
       
  1300 CNetDatabase::~CNetDatabase()
       
  1301 	{
       
  1302 	delete iRSP;
       
  1303 	delete iBuf;
       
  1304 	delete iBufPtr;
       
  1305 	}
       
  1306 
       
  1307 void CNetDatabase::ProcessMessageL()
       
  1308 	{
       
  1309 	switch(Message().Function())
       
  1310 		{
       
  1311 		case ENDQuery:
       
  1312 		case ENDAdd:
       
  1313 		case ENDRemove:
       
  1314 			RequestL();
       
  1315 			break;
       
  1316 
       
  1317 		case ENDCancel:
       
  1318 			Cancel();
       
  1319 			break;
       
  1320 
       
  1321 		case ENDClose:
       
  1322 			delete this;
       
  1323 			break;
       
  1324 
       
  1325 		default:
       
  1326 			SetReturn(KErrNotSupported);
       
  1327 		}
       
  1328 	}